Index: /branches/eam_branch_20080223/Ohana/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/.cvsignore	(revision 16632)
@@ -0,0 +1,9 @@
+help
+bin
+lib
+include
+man
+CVS
+ohana-config
+Makefile
+Makefile.System
Index: /branches/eam_branch_20080223/Ohana/Configure.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/Configure.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/Configure.in	(revision 16632)
@@ -0,0 +1,28 @@
+# Configure file for Ohana Package
+# the values of the form @WORD@ are filled in by configure
+
+# location of the package and architecture
+ROOT    = @ROOTDIR@
+ARCH    = @ARCHVAL@
+
+# destination directories:
+DESTBIN	 = @BINDIR@
+DESTINC	 = @INCDIR@
+DESTLIB	 = @LIBDIR@
+DESTMAN	 = @MANDIR@
+DESTDATA = @DATADIR@
+
+# C compiler options
+CC       = @CC@
+CFLAGS   = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS  = @LDFLAGS@
+DLLTYPE  = @DLLTYPE@
+
+# flags for external dependencies
+INCDIRS  = @INCDIRS@
+LIBDIRS  = @LIBDIRS@
+LIBFLAGS = @LIBFLAGS@
+
+# select the appropriate version of ranlib
+RANLIB = @RANLIB@
Index: /branches/eam_branch_20080223/Ohana/Makefile.Common
===================================================================
--- /branches/eam_branch_20080223/Ohana/Makefile.Common	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/Makefile.Common	(revision 16632)
@@ -0,0 +1,113 @@
+# this file must be added to the makefile *after* LIB,BIN, etc are defined
+
+# (INC)     & (LIB)     are the program's local include & lib directories
+# (DESTINC) & (DESTLIB) are the target installation include & lib directories
+# (INCDIRS) & (LIBDIRS) are all of the probed include & lib directories
+# (LIBFLAGS) is the list of -lXXX directives from configure for external libs
+
+BASE_CFLAGS   =	$(CFLAGS)
+BASE_CPPFLAGS =	$(CPPFLAGS) -I$(INC) -I$(DESTINC) $(INCDIRS) -D$(ARCH)
+BASE_LDFLAGS  = $(LDFLAGS) -L$(LIB) -L$(DESTLIB) $(LIBDIRS) $(LIBFLAGS)
+
+DVO_LIBS  = $(DESTLIB)/libdvo.a $(DESTLIB)/libFITS.a $(DESTLIB)/libohana.a
+KAPA_LIBS = $(DVO_LIBS) $(DESTLIB)/libkapa.a 
+
+DVO_INCS  = $(DESTINC)/dvo.h $(DESTINC)/gfitsio.h $(DESTINC)/ohana.h $(DESTINC)/autocode.h 
+KAPA_INCS = $(DVO_INCS) $(DESTINC)/kapa.h 
+
+.PRECIOUS: %.$(ARCH).o
+.PRECIOUS: $(BIN)/%.$(ARCH)
+
+# is this line needed?
+.SUFFIXES: .$(ARCH).o
+
+$(DESTINC)/%: $(INC)/%
+	@if [ ! -d $(DESTINC) ]; then mkdir -p $(DESTINC); fi
+	rm -f $@
+	cp $< $@
+
+%.$(ARCH).o : %.c
+	$(CC) $(FULL_CFLAGS) $(FULL_CPPFLAGS) -c $< -o $@
+
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $(FULL_CFLAGS) -o $@ $^ $(FULL_LDFLAGS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB):
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^
+	$(RANLIB) $@
+	@echo "compiled static library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f $@
+	cp $< $@
+	@echo "installed static library $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).so:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	gcc -shared -Wl,-soname,$*.so -o $@ $^ -lc
+	@echo "compiled shared library $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).dylib:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	gcc -dynamiclib -o $@ $^ -lc $(FULL_LDFLAGS)
+	@echo "compiled shared library $*"
+	@echo ""
+
+# shared objects have a different compilation on solaris:
+# gcc -shared -o $@ $^ -lc
+
+$(DESTLIB)/%.so: $(LIB)/%.$(ARCH).so
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f $@
+	cp $< $@
+	@echo "installed shared library $*"
+	@echo ""
+
+$(DESTLIB)/%.dylib: $(LIB)/%.$(ARCH).dylib
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f $@
+	cp $< $@
+	@echo "installed shared library $*"
+	@echo ""
+
+$(DESTMAN)/%: $(MAN)/%
+	@if [ ! -d $(DESTMAN) ]; then mkdir -p $(DESTMAN); fi
+	rm -f $@
+	cp $< $@
+
+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)
+
+# $@ : target filename
+# $* : matched word (%)
+# $< : first prereq
+# $^ : all prereqs
+
Index: /branches/eam_branch_20080223/Ohana/Makefile.System.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/Makefile.System.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/Makefile.System.in	(revision 16632)
@@ -0,0 +1,28 @@
+# Configure file for Ohana Package
+# the values of the form @WORD@ are filled in by configure
+
+# location of the package and architecture
+ROOT    = @ROOTDIR@
+ARCH    = @ARCHVAL@
+
+# destination directories:
+DESTBIN	 = @BINDIR@
+DESTINC	 = @INCDIR@
+DESTLIB	 = @LIBDIR@
+DESTMAN	 = @MANDIR@
+DESTDATA = @DATADIR@
+
+# C compiler options
+CC       = @CC@
+CFLAGS   = @CFLAGS@
+CPPFLAGS = @CPPFLAGS@
+LDFLAGS  = @LDFLAGS@
+DLLTYPE  = @DLLTYPE@
+
+# flags for external dependencies
+INCDIRS  = @INCDIRS@
+LIBDIRS  = @LIBDIRS@
+LIBFLAGS = @LIBFLAGS@
+
+# select the appropriate version of ranlib
+RANLIB = @RANLIB@
Index: /branches/eam_branch_20080223/Ohana/Makefile.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/Makefile.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/Makefile.in	(revision 16632)
@@ -0,0 +1,149 @@
+# --------------------------------------------------------------------------- #
+# --------------------------------------------------------------------------- #
+#									      #
+#                 OOO    HH   HH    AAA    NN   NN    AAA		      #
+#               OO   OO  HH   HH  AA   AA  NNN  NN  AA   AA		      #
+#               OO   OO  HHHHHHH  AAAAAAA  NN N NN  AAAAAAA		      #
+#               OO   OO  HH   HH  AA   AA  NN  NNN  AA   AA		      #
+#                 OOO    HH   HH  AA   AA  NN   NN  AA   AA		      #
+#      								              #
+# --------------------------------------------------------------------------- #
+# --------------------------------------------------------------------------- #
+
+# This makefile compiles all Ohana package programs in the Elixir
+# system, and their libraries.  Most of the components in this
+# directory were created for Ohana, but there are a few libraries
+# which are from external sources: libjpeg, libpng, zlib, and
+# readline.  Extra care should be taken in compiling those libraries. 
+
+# Edit Configure to reflect the location of your installation 
+# or use the script 'configure'
+
+include Makefile.System
+
+# .SILENT:								       
+default: all
+
+# The collection of Ohana programs.  Other components in the src
+# directory may be compiled by going to those directories. 
+PROGRAM =   \
+addstar     \
+delstar     \
+dvosplit    \
+elixir      \
+gastro      \
+gastro2     \
+getstar     \
+gcompare    \
+imclean     \
+imregister  \
+kapa2       \
+misc        \
+mosastro    \
+nightd      \
+opihi       \
+perl        \
+relphot     \
+relastro    \
+shell       \
+tools       \
+tcl         \
+uniphot
+
+# any of these programs can be built with 'make (name)' 
+EXTRAS =     \
+opihi.v1    \
+fixcat      \
+gophot      \
+getusno     \
+lightcurve  \
+markrock    \
+photdbc     \
+markstar    \
+mosastro.v1 \
+mosastro.v2 \
+skycalc     
+
+OLD = mana status addusno addrefs addspphot
+
+LIBS = libtap libohana libfits libdvo libkapa
+
+# general build targets:
+libs:
+	@if [ "$(ARCH)" = "" ]; then echo ""; echo " *** please define ARCH ***"; echo; exit 1; fi
+	mkdir -p $(DESTINC)
+	mkdir -p $(DESTLIB)
+	mkdir -p $(DESTBIN)
+	for i in $(LIBS); do make $$i.install || exit; done
+	chmod +x ohana-config
+	cp -f ohana-config $(DESTBIN)/
+
+bins: 
+	for i in $(PROGRAM); do make $$i; done
+
+all:
+	make libs || exit
+	for i in $(PROGRAM); do make $$i || exit; done
+
+extras:
+	for i in $(EXTRAS); do make $$i || exit; done
+
+pantasks:
+	make libs || exit
+	cd src/opihi; make pclient.install && exit
+	cd src/opihi; make pcontrol.install && exit
+	cd src/opihi; make pantasks.install && exit
+
+mana:
+	make libs
+	make kapa2.install
+	cd src/opihi; make mana.install && exit
+
+dvoshell:
+	make libs
+	make kapa2.install
+	cd src/opihi; make dvo.install && exit
+
+clean:
+	@if [ "$(ARCH)" = "" ]; then echo ""; echo " *** please define ARCH ***"; echo; exit 1; fi
+	for i in $(LIBS); do make $$i.clean || exit; done
+	for i in $(PROGRAM); do make $$i.clean || exit; done
+	for i in $(EXTRAS); do make $$i.clean || exit; done
+	@rm -f `find . -name .mana`
+	@rm -f `find . -name .dvo`
+	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
+
+dist:
+	@if [ "$(ARCH)" = "" ]; then echo ""; echo " *** please define ARCH ***"; echo; exit 1; fi
+	for i in $(LIBS); do make $$i.dist || exit; done
+	for i in $(PROGRAM); do make $$i.dist || exit; done
+	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
+
+install:
+	@if [ "$(ARCH)" = "" ]; then echo ""; echo " *** please define ARCH ***"; echo; exit 1; fi
+	for i in $(LIBS); do make $$i.install || exit; done
+	for i in $(PROGRAM); do make $$i.install || exit; done
+	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
+
+install.extras:
+	for i in $(EXTRAS); do make $$i.install || exit; done
+	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
+
+# standard rules: targets are foo, foo.clean, foo.install, foo.dist
+$(PROGRAM) $(LIBS) $(EXTRAS): 
+	@if [ -d "src/$@" ]; then \
+	  echo -n -e "\0033]0; *** Ohana: $@ *** \0007"; \
+	  (cd src/$@ && make); \
+	fi
+	@echo -n -e "\0033]0; *** Ohana: done $@ *** \0007" \
+
+%.install:
+	@echo -n -e "\0033]0; *** Ohana: $@ *** \0007" \
+	mkdir -p bin/$(ARCH)
+	if [ -d "src/$*" ]; then (cd src/$* && make install); fi
+
+%.clean:
+	if [ -d "src/$*" ]; then (cd src/$* && make clean); fi
+
+%.dist:
+	(cd src/$* && make dist)
Index: /branches/eam_branch_20080223/Ohana/autogen.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/autogen.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/autogen.sh	(revision 16632)
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+for arg in $*; do
+    case $arg in
+        --no-configure)
+	    exit 0
+            ;;
+        *)
+            ;;
+    esac
+done
+
+./configure.tcsh $*
Index: /branches/eam_branch_20080223/Ohana/config.tools
===================================================================
--- /branches/eam_branch_20080223/Ohana/config.tools	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/config.tools	(revision 16632)
@@ -0,0 +1,47 @@
+#!/bin/csh -f
+
+if ($#argv == 0) then
+  echo "USAGE: config.tools [fixpath | fixconf]"
+  exit 2
+endif
+
+if ("$argv[1]" == "fixpath") goto fixpath
+if ("$argv[1]" == "fixconf") goto fixconf
+
+echo "unknown option $argv[1]"
+exit 1
+
+#######
+fixpath:
+
+if ($#argv != 2) then
+  echo "USAGE: config.tools fixpath (path)"
+  exit 2
+endif
+
+set indir = $argv[2]
+
+# convert // to / in pathnames
+echo $indir | grep "\/\/" > /dev/null
+set success = $status
+while ($success == 0) 
+  set indir = `echo $indir | sed 's|\/\/|\/|g'`
+  echo $indir | grep "\/\/" > /dev/null
+  set success = $status
+end
+
+set indir = `echo $indir | sed 's|\/$||'`
+echo $indir
+exit 0
+
+#######
+fixconf:
+
+if ($#argv != 3) then
+  echo "USAGE: config.tools fixconf (NAME) (value)"
+  exit 2
+endif
+
+cat Makefile.System | sed "s|$argv[2]|$argv[3]|" > Makefile.System.tmp
+mv -f Makefile.System.tmp Makefile.System
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/configure
===================================================================
--- /branches/eam_branch_20080223/Ohana/configure	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/configure	(revision 16632)
@@ -0,0 +1,41 @@
+#!/bin/sh
+
+# strip out CC, CFLAGS, CPPFLAGS, LDFLAGS and set env vars
+while (( $# > 0 )); do
+  skip=0
+
+  # strip out CC, set as env variable
+  echo $1 | grep "^CC=" > /dev/null
+  if (( $? == 0 )) ; then
+    val=`echo $1 | sed "s|^CC=||"`
+    export CC=$val
+    skip=1
+  fi
+  # strip out CFLAGS, set as env variable
+  echo $1 | grep "^CFLAGS=" > /dev/null
+  if (( $? == 0 )) ; then
+    val=`echo $1 | sed "s|^CFLAGS=||"`
+    export CFLAGS=$val
+    skip=1
+  fi
+  # strip out CPPFLAGS, set as env variable
+  echo $1 | grep "^CPPFLAGS=" > /dev/null
+  if (( $? == 0 )) ; then
+    val=`echo $1 | sed "s|^CPPFLAGS=||"`
+    export CPPFLAGS=$val
+    skip=1
+  fi
+  # strip out LDFLAGS, set as env variable
+  echo $1 | grep "^LDFLAGS=" > /dev/null
+  if (( $? == 0 )) ; then
+    val=`echo $1 | sed "s|^LDFLAGS=||"`
+    export LDFLAGS=$val
+    skip=1
+  fi
+  if (( $skip == 0 )) ; then
+    args="$args $1"
+  fi
+  shift
+done
+
+./configure.tcsh $args
Index: /branches/eam_branch_20080223/Ohana/configure.tcsh
===================================================================
--- /branches/eam_branch_20080223/Ohana/configure.tcsh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/configure.tcsh	(revision 16632)
@@ -0,0 +1,640 @@
+#!/bin/csh -f
+
+# this is a very low-tech version of configure, not built by autoconf.
+# we check for the following libraries:
+
+# we need to be able to list the required libraries for a given distribution
+
+# evaluate command-line options
+set vararch = 0
+set optimize = 0
+set pedantic = 0
+set memcheck = 0
+
+set prefix  = ""
+set bindir  = ""
+set libdir  = ""
+set incdir  = ""
+set mandir  = ""
+set datadir  = ""
+set sysconfdir  = ""
+set exec_prefix = ""
+
+set root    = ""
+set args    = ""
+
+while ("$1" != "") 
+ switch ("$1")
+  # options passed by jhbuild or others which we ignore
+  case --enable-maintainer-mode
+  case --no-create
+  case --no-recursion
+  case --sbindir*
+  case --libexecdir*
+  case --sharedstatedir*
+  case --localstatedir*
+  case --oldincludedir*
+  case --infodir*
+   # we need to strip the --opt word and --opt=word versions
+   set word = `echo $1 | tr = ' '`
+   if ($#word == 1) then
+     if ($#argv > 1) then
+      shift
+     endif
+   endif
+   breaksw;
+  case --vararch
+   set vararch = 1
+   breaksw;
+  case --enable-optimize
+   set optimize = 1
+   breaksw;
+  case --enable-memcheck
+   set memcheck = 1
+   breaksw;
+  case --pedantic
+   set pedantic = 1
+   breaksw;
+  case --prefix*
+   if ("$1" == "--prefix") then
+     shift
+     set prefix = $1
+   else
+     set prefix = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --exec-prefix*
+   if ("$1" == "--exec-prefix") then
+     shift
+     set exec_prefix = $1
+   else
+     set exec_prefix = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --bindir*
+   if ("$1" == "--bindir") then
+     shift
+     set bindir = $1
+   else
+     set bindir = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --libdir*
+   if ("$1" == "--libdir") then
+     shift
+     set libdir = $1
+   else
+     set libdir = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --includedir*
+   if ("$1" == "--includedir") then
+     shift
+     set incdir = $1
+   else
+     set incdir = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --sysconfdir*
+   if ("$1" == "--sysconfdir") then
+     shift
+     set sysconfdir = $1
+   else
+     set sysconfdir = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --datadir*
+   if ("$1" == "--datadir") then
+     shift
+     set datadir = $1
+   else
+     set datadir = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --mandir*
+   if ("$1" == "--mandir") then
+     shift
+     set mandir = $1
+   else
+     set mandir = `echo $1 | tr = ' ' | awk '{print $2}'`
+   endif
+   breaksw;
+  case --help:
+   goto usage
+  case -*: 
+   echo ""
+   echo "Unknown option: $1"
+   goto usage
+  default:
+   set args=($args $1);
+   breaksw;
+ endsw
+ shift
+end
+if ($#args != 1) goto usage
+
+if ("$exec_prefix" == "") then
+  set exec_prefix = $prefix
+endif
+
+# replace $exec_prefix in variables
+#echo "setting libdir ($libdir)"
+#set libdir = `echo $libdir | sed 's|\$exec_prefix|$exec_prefix|'`
+
+# set values for CC, CFLAGS, CPPFLAGS, LDFLAGS
+if (! $?CC) then
+  set CC = gcc
+endif  
+
+if (! $?CFLAGS) then
+  set CFLAGS = "-g -O0"
+endif  
+# optimize overrides user-supplied CFLAGS
+if ($optimize) set CFLAGS = "-O2"
+
+if (! $?CPPFLAGS) then
+  set CPPFLAGS = ""
+endif  
+if ($pedantic) set CPPFLAGS = "$CPPFLAGS-Wall -Werror "
+if ($memcheck) set CPPFLAGS = "$CPPFLAGS-DOHANA_MEMORY "
+
+if (! $?LDFLAGS) then
+  set LDFLAGS = 
+endif  
+
+set syslibpath = "/lib /usr/lib /usr/X11R6/lib /usr/local/lib"
+set needlibs   = ""
+set needlibs   = "$needlibs png"
+set needlibs   = "$needlibs z"
+set needlibs   = "$needlibs jpeg"
+set needlibs   = "$needlibs readline"
+set needlibs   = "$needlibs X11"
+set needlibs   = "$needlibs pthread"
+set needlibs   = "$needlibs m"
+
+set optlibs    = ""
+set optlibs    = "$optlibs mysqlclient tcmalloc"
+
+set sysincpath = "/usr/include /usr/local/include /usr/X11R6/include"
+
+set needincs = ""
+set needincs = "$needincs X11/Xatom.h"
+set needincs = "$needincs X11/Xlib.h"
+set needincs = "$needincs X11/Xresource.h"
+set needincs = "$needincs X11/Xutil.h"
+set needincs = "$needincs X11/cursorfont.h"
+set needincs = "$needincs X11/keysym.h"
+set needincs = "$needincs X11/keysymdef.h"
+set needincs = "$needincs arpa/inet.h"
+set needincs = "$needincs ctype.h"
+set needincs = "$needincs errno.h"
+set needincs = "$needincs fcntl.h"
+set needincs = "$needincs glob.h"
+set needincs = "$needincs jpeglib.h"
+set needincs = "$needincs math.h"
+set needincs = "$needincs netdb.h"
+set needincs = "$needincs netinet/ip.h"
+set needincs = "$needincs png.h"
+set needincs = "$needincs pthread.h"
+set needincs = "$needincs readline/history.h"
+set needincs = "$needincs readline/readline.h"
+set needincs = "$needincs signal.h"
+set needincs = "$needincs stdio.h"
+set needincs = "$needincs stdlib.h"
+set needincs = "$needincs string.h"
+set needincs = "$needincs sys/ipc.h"
+set needincs = "$needincs sys/resource.h"
+set needincs = "$needincs sys/sem.h"
+set needincs = "$needincs sys/socket.h"
+set needincs = "$needincs sys/stat.h"
+set needincs = "$needincs sys/time.h"
+set needincs = "$needincs sys/types.h"
+set needincs = "$needincs sys/uio.h"
+set needincs = "$needincs sys/un.h"
+set needincs = "$needincs sys/wait.h"
+set needincs = "$needincs time.h"
+set needincs = "$needincs unistd.h"
+set needincs = "$needincs zlib.h"
+
+set optincs  = ""
+set optincs = "$optincs mysql.h"
+
+# XXX need to have options for non-ANSI includes? (ie, varargs.h)
+# set needincs = "$needincs cfuncs.h" - from non-ANSI option in ohana.h
+# set needincs = "$needincs float.h" - is from missing_proto (CFHT)
+# set needincs = "$needincs floatingpoint.h" - is from missing_proto (CFHT)
+# set needincs = "$needincs stdarg.h" - from std includes (in gcc path)
+# set needincs = "$needincs varargs.h" - from std includes (in gcc path)
+
+# XXX I was probing for these before, but RHL claims we don't need them.
+# I suspect they may be needed on older systems a la CFHT.
+# set needincs = "$needincs malloc.h"
+# set needincs = "$needincs memory.h"
+# set needincs = "$needincs values.h"
+
+# check the hardware architecture:
+set sys=`uname -s` 
+set ranlib = "ranlib"
+set dlltype = "so"
+switch ($sys)
+ case IRIX64:
+   set arch="irix";
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     set arch="sol";
+   else 
+     set arch="sun4";
+   endif
+   # sun (at least) seems to need the socket library (linux does not)
+   set syslibpath = "$syslibpath /usr/openwin/lib"
+   set sysincpath = "$sysincpath /usr/openwin/include"
+   set needlibs = "$needlibs libsocket libnsl"
+   set ranlib = "touch"
+   breaksw;
+ case Linux:
+   set arch="linux";
+   if (-e /etc/sidious.config) set arch="sid";
+   set mach=`uname -m`
+   if ("$mach" == "x86_64") then
+    set arch="lin64";
+    set syslibpath = "/lib64 /usr/lib64 /usr/X11R6/lib64 $syslibpath"
+   endif
+   breaksw;
+ case Darwin:
+   set arch="darwin";
+   set mach=`uname -m`
+   if ("$mach" == "i386") then
+    set arch="darwin_x86";
+   endif
+   set syslibpath = "$syslibpath /sw/lib"
+   set sysincpath = "$sysincpath /sw/include"
+   set dlltype = dylib
+   breaksw;
+ case HP-UX:
+    set arch="hpux";
+    breaksw;
+ default:
+   echo "unknown architecture";
+   exit 1;
+   breaksw;
+endsw
+echo "setting architecture to: $arch" 
+
+# set up the basic directory names:
+set root = `pwd`
+if ($prefix == "") set prefix = $root
+
+# set the install include directory
+if ($incdir == "") then
+  if ($vararch) then
+    set incdir = $prefix/include/$arch
+  else
+    set incdir = $prefix/include
+  endif
+endif
+
+# set the install lib directory
+if ($libdir == "") then
+  if ($vararch) then
+    set libdir = $prefix/lib/$arch
+  else
+    set libdir = $prefix/lib
+  endif
+endif
+
+if ($?LIBRARY_PATH) then 
+  set libpath = `echo $LIBRARY_PATH | tr ':' ' '`
+else
+  set libpath = ""
+endif
+
+# check for basic libraries
+echo ""
+echo "searching for required external libraries..."
+set faillibs = ""
+set libflags = ""
+set libdirs  = ""
+set nonomatch
+foreach f ( $needlibs )
+  foreach g ( $libpath $libdir $syslibpath )
+    set name = $g/lib$f.a
+    if (-e $name[1]) goto got_lib;
+    set name = $g/lib$f.$dlltype
+    if (-e $name[1]) goto got_lib;
+  end
+  echo "missing lib$f"
+  set faillibs = "$faillibs lib$f"
+  continue
+got_lib:
+  echo "found lib$f ($name[1])"
+  set gotlibdir = `dirname $name[1]`
+  echo "$libdirs" | grep -- "-L$gotlibdir " > /dev/null
+  if ($status) then
+    set libdirs  = "$libdirs-L$gotlibdir "
+  endif
+  echo "$libflags" | grep -- "-l$f " > /dev/null
+  if ($status) then
+    set libflags = "$libflags-l$f "
+  endif
+end
+
+# we need a curses library; can choose one of the following:
+# check for termcap, curses, etc
+foreach f ( ncurses curses termcap )
+    foreach g ( $libpath $libdir $syslibpath )
+        set name = $g/lib$f.a
+        if (-e $name[1]) goto got_curses;
+        set name = $g/lib$f.$dlltype
+        if (-e $name[1]) goto got_curses;
+    end
+end
+set faillibs = "$faillibs (ncurses | curses | termcap)"
+echo "missing a valid curses library"
+echo "missing: $faillibs"
+echo "please find one of them and install them in $lib"
+exit 1
+
+got_curses:
+  echo "found $f ($name[$#name])"
+  echo "$libdirs" | grep -- "-L$g " > /dev/null
+  if ($status) then
+    set libdirs  = "$libdirs-L$g "
+  endif
+  echo "$libflags" | grep -- "-l$f " > /dev/null
+  if ($status) then
+    set libflags = "$libflags-l$f "
+  endif
+
+if ("$faillibs" != "") then
+  echo "your installation is missing some important libraries"
+  echo "missing: $faillibs"
+  echo "please find them and install them in $lib"
+  exit 1
+endif    
+
+# check for optional libraries
+echo ""
+echo "searching for optional external libraries..."
+foreach f ( $optlibs )
+  foreach g ( $libpath $libdir $syslibpath )
+    set name = $g/lib$f.a
+    if (-e $name[1]) goto got_optlib;
+    set name = $g/lib$f.$dlltype
+    if (-e $name[1]) goto got_optlib;
+    set name = $g/*/lib$f.a
+    if (-e $name[1]) goto got_optlib;
+    set name = $g/*/lib$f.$dlltype
+    if (-e $name[1]) goto got_optlib;
+  end
+  echo "missing lib$f; skipping"
+  continue
+got_optlib:
+  echo "found lib$f ($name[1])"
+  set gotlibdir = `dirname $name[1]`
+  echo "$libdirs" | grep -- "-L$gotlibdir " > /dev/null
+  if ($status) then
+    set libdirs  = "$libdirs-L$gotlibdir "
+  endif
+  echo "$libflags" | grep -- "-l$f " > /dev/null
+  if ($status) then
+    set libflags = "$libflags-l$f "
+  endif
+end
+
+# add the CPATH
+if ($?CPATH) then 
+  set incpath = `echo $CPATH | tr ':' ' '`
+else
+  set incpath = ""
+endif
+
+# check for required headers (including in subdirectories)
+echo ""
+echo "searching for required external header files..."
+set failincs = ""
+set incdirs = ""
+foreach f ( $needincs )
+  foreach g ( $incdir $incpath $sysincpath )
+    set name = "$g/$f"
+    if (-e $name) goto got_inc;
+    set nonomatch
+    set name = $g/*/$f
+    echo "$name" | grep "*" > /dev/null
+    if (! $status) continue
+    unset nonomatch
+    if (-e $name[1]) goto got_inc;
+  end
+  echo "missing $f"
+  set failincs = "$failincs $f"
+  continue
+got_inc:
+  set gotinc = $name[1]
+  echo "found $f ($gotinc)"
+  set gotincdir = `dirname $name[1]`
+  if (`dirname $f` != ".") then
+    set gotincdir = `dirname $gotincdir`
+  endif
+  echo "$incdirs" | grep -- "-I$gotincdir " > /dev/null
+  if ($status) then
+    set incdirs = "$incdirs-I$gotincdir "
+  endif
+end
+
+if ("$failincs" != "") then
+  echo "your installation is missing some important library headers"
+  echo "please find them and install them in $inc"
+  exit 1
+endif    
+
+# check for optional headers (including in subdirectories)
+echo ""
+echo "searching for optional external header files..."
+foreach f ( $optincs )
+  foreach g ( $incdir $incpath $sysincpath )
+    set name = "$g/$f"
+    if (-e $name) goto got_optinc;
+    set nonomatch
+    set name = $g/*/$f
+    echo "$name" | grep "*" > /dev/null
+    if (! $status) continue
+    unset nonomatch
+    if (-e $name[1]) goto got_optinc;
+  end
+  echo "missing $f; skipping"
+  continue
+got_optinc:
+  set gotinc = $name[1]
+  echo "found $f ($gotinc)"
+  set gotincdir = `dirname $name[1]`
+  if (`dirname $f` != ".") then
+    set gotincdir = `dirname $gotincdir`
+  endif
+  echo "$incdirs" | grep -- "-I$gotincdir " > /dev/null
+  if ($status) then
+    set incdirs = "$incdirs-I$gotincdir "
+  endif
+  set haveflag = `echo $f | tr '[:lower:]' '[:upper:]' | tr '.' '_'`
+  set CPPFLAGS = "$CPPFLAGS-DHAVE_$haveflag "
+end
+
+echo 
+echo "Compiler options:"
+echo "CC: $CC"
+echo "CFLAGS: $CFLAGS"
+echo "CPPFLAGS: $CPPFLAGS"
+echo "LDFLAGS: $LDFLAGS"
+
+echo
+echo "Additional compiler flags:"
+echo "INCDIRS: $incdirs"
+echo "LIBDIRS: $libdirs"
+echo "LIBFLAGS: $libflags"
+
+echo 
+echo "ARCH: $arch"
+echo "ROOT: $root"
+echo "PREFIX: $prefix"
+echo 
+
+# the config.tools fixconf operations below interpolate values in Makefile.System
+if (-e Makefile.System) mv Makefile.System Makefile.System.bak
+cp Makefile.System.in Makefile.System
+
+# we don't currently need to modify the Makefile but since configure
+# should create a new Makefile, we need to do this:
+cp -f Makefile.in Makefile
+
+# the ROOTDIR defines the location of the source tree
+./config.tools fixconf @ROOTDIR@  "$root"
+
+# the following entries define the target installation locations 
+
+# BINDIR (DESTBIN) holds the output binary files
+if ("$bindir" == "") then
+  set subdir = bin
+  set subpath = bin
+  if ($vararch) then 
+    set subdir = 'bin/$(ARCH)'
+    set subpath = "bin/$arch"
+  endif
+  set bindir = $prefix/$subdir
+  set binpath = $prefix/$subpath
+endif
+set bindir = `./config.tools fixpath $bindir`
+./config.tools fixconf @BINDIR@ $bindir
+echo DESTBIN $bindir
+
+# INCDIR (DESTINC) holds the output header files
+if ("$incdir" == "") then
+  set subdir = include
+  if ($vararch) set subdir = 'include/$(ARCH)'
+  set incdir = $prefix/$subdir
+endif
+set incdir = `./config.tools fixpath $incdir`
+./config.tools fixconf @INCDIR@ $incdir
+echo DESTINC $incdir
+
+# LIBDIR (DESTLIB) holds the output library files
+if ("$libdir" == "") then
+  set subdir = lib
+  if ($vararch) set subdir = 'lib/$(ARCH)'
+  set libdir = $prefix/$subdir
+endif
+set libdir = `./config.tools fixpath $libdir`
+./config.tools fixconf @LIBDIR@ $libdir
+echo DESTLIB $libdir
+
+# MANDIR (DESTMAN) holds the output man pages
+if ("$mandir" == "") then
+  set mandir = $prefix/man
+endif
+set mandir = `./config.tools fixpath $mandir`
+./config.tools fixconf @MANDIR@ $mandir
+echo DESTMAN $mandir
+
+# DATADIR (DESTDATA) holds the general non-binary files
+if ("$datadir" == "") then
+  set datadir = $prefix/share
+endif
+set datadir = `./config.tools fixpath $datadir`
+./config.tools fixconf @DATADIR@ $datadir
+echo DESTDATA $datadir
+
+# the vararch option defines an automatic arch-dependent directory 
+# tree for DESTBIN, DESTLIB, DESTINC
+if ($vararch) then
+  ./config.tools fixconf "^\s*ARCH" "# ARCH"
+else 
+  ./config.tools fixconf @ARCHVAL@ $arch
+endif 
+
+# INCDIRS, LIBDIRS, LIBFLAGS define include and library flags needed
+# by the externally-supplied libraries
+./config.tools fixconf @INCDIRS@  "$incdirs"
+./config.tools fixconf @LIBDIRS@  "$libdirs"
+./config.tools fixconf @LIBFLAGS@ "$libflags"
+
+# these are the compiler options
+./config.tools fixconf @CC@ "$CC"
+./config.tools fixconf @CFLAGS@ "$CFLAGS"
+./config.tools fixconf @CPPFLAGS@ "$CPPFLAGS"
+./config.tools fixconf @LDFLAGS@ "$LDFLAGS"
+./config.tools fixconf @DLLTYPE@  "$dlltype"
+
+# other architecture dependent options
+./config.tools fixconf @RANLIB@ "$ranlib"
+
+cat ohana-config.in | sed "s|@INCDIR@|$incdir|" | sed "s|@LIBDIR@|$libdir|" | sed "s|(ARCH)|ARCH|" > ohana-config
+
+echo ""
+echo "include $bindir in your path"
+
+exit 0
+
+usage:
+cat <<EOF
+USAGE: configure [OPTION]
+
+echo remaining args: $args
+
+set the installation directory root with --prefix
+if you define the environment variable ARCH, you can set --vararch
+ 
+Configuration:
+  -h, --help              display this help and exit
+  --enable-optimize       enable compiler optimization (-O2)
+  --pedantic              include -Wall -Werror on compilation
+
+Installation directories:
+  --prefix=PREFIX         install architecture-independent files in PREFIX
+  --vararch               install with ARCH suffixes for variable architectures
+
+Fine tuning of the installation directories:
+  --bindir=DIR           user executables [PREFIX/bin/$ARCH] 
+  --libdir=DIR           object code libraries [PREFIX/lib/$ARCH]
+  --includedir=DIR       C header files [PREFIX/include]
+  --mandir=DIR           man documentation [PREFIX/man]
+  --datadir=DIR          read-only architecture-independent data [PREFIX/share]
+  --sysconfdir=DIR       read-only single-machine data [PREFIX/etc]
+
+Makefile flags:
+  CC=options
+  CFLAGS=options
+  CPPFLAGS=options
+  LDFLAGS=options
+
+The following options are silently ignored for compatibility:
+  --enable-maintainer-mode
+  --no-create
+  --no-recursion
+  --sbindir
+  --libexecdir
+  --sharedstatedir
+  --localstatedir
+  --oldincludedir
+  --infodir
+
+EOF
+ exit 2;
Index: /branches/eam_branch_20080223/Ohana/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,4 @@
+
+2006.08.23:
+  base-1-4 : added doc and test to base
+	     minor updates to configure
Index: /branches/eam_branch_20080223/Ohana/doc/GSCRegion.to.SkyRegions.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/GSCRegion.to.SkyRegions.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/GSCRegion.to.SkyRegions.txt	(revision 16632)
@@ -0,0 +1,12 @@
+
+addstar : all GSCRegion entries removed / moved to old
+delstar : all GSCRegion entries removed / moved to old
+markrock : needs a re-write, keep this program?  (is mini-mops)
+markstar : needs a major re-write.  does this have a future?
+opihi : all dropped / moved to old 
+	(used by some deprecated functions, re-write if these are reserrected)
+relphot : all GSCRegion entries removed / moved to old
+relastro : no real work has been done; take from relphot
+
+photdbc : needs re-write, what is the purpose?
+fixcat : needs re-write, what is the purpose?
Index: /branches/eam_branch_20080223/Ohana/doc/INSTALL
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/INSTALL	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/INSTALL	(revision 16632)
@@ -0,0 +1,74 @@
+
+The Elixir system consists of two main software packages: Ohana (main
+developer Eugene Magnier) and Flips (main developer Jean-Charles
+Cuillandre).  The Elixir system combines these two packages, along
+with other external software products, into a complete system
+providing many utilities and functions for image processing at CFHT
+and elsewhere.  This document describes how to install the Ohana
+portion of the Elixir system.  Ohana may be installed from CVS or from
+a distributed tar ball.  Within the Elixir development community, the
+Ohana source tree may be checked out of the Elixir CVS tree.  Ohana is
+also distributed as a tar ball to users outside of the Elixir
+development community.
+
+1) Installing Ohana from source tar ball:
+
+  un-gzip and untar:  
+
+    > gunzip -c ohana.tgz | tar xvf -
+
+  enter the ohana top-level directory:
+
+    > cd ohana
+
+  construct the input Configure file [1]:
+
+    > configure
+
+  this step will note the binary installation path.  This should be
+  added to your PATH
+
+  compile the software
+
+    > make
+
+  install the software
+
+    > make install
+
+2) Installing Ohana from CVS (Developer's version):
+
+  check out the ohana source tree:
+
+    > setenv CVSROOT poma:/data/elixir2/srcdir/cvs
+    > cvs co ohana
+
+  enter the ohana top-level directory:
+
+    > cd ohana
+
+  construct the input Configure file [1]:
+
+    > configure
+
+  this step will note the binary installation path.  This should be
+  added to your PATH
+
+  compile the software
+
+    > make
+
+  install the software
+
+    > make install
+
+***** Notes *****
+
+[1] Ohana is configured for multiple architecture development, which
+is convenient for end users as well.  The libraries, include files,
+and programs, are all installed in directories with the architecture
+type appended: bin/linux, bin/sol, lib/linux, etc.  To take advantage
+of this multiple architecture organization when compiling, end users
+should arrange for the environment variable ARCH to be set based on
+the machine architecture, and for the PATH to depend on ARCH, rather
+than setting it to a fixed quantity.  
Index: /branches/eam_branch_20080223/Ohana/doc/README
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/README	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/README	(revision 16632)
@@ -0,0 +1,46 @@
+Documenation for Ohana:
+
+ Ohana includes:
+
+   1) fits - FITS I/O library (Eugene Magnier) (V 1.0)
+	These are clean, C-like FITS interaction routines which are
+	meant to be easy to program with and easy to read, etc.
+
+   2) readline - the GNU readline library. (FSF / GNU) (V1.1)
+	This routines allow for easy emacs / vi-like cursor interactions.
+
+   3) opihi - a shell template program (Eugene Magnier) (V1.0)
+      This program provides a tcsh-like interaction with macros
+	and math capabilities.  It is meant to be a template for any
+	program which may require a shell-like interaction, macros, and math.
+
+   4) mana - an image manipulation program. (Eugene Magnier) (V1.0)
+	This program is in someways similar to MIDAS, IRAF, or Vista (the standard
+	astrophysics analysis packages).  However, mana is meant to be more 
+	stripped down (it is not a "do everything in the world" program!).
+	Mana also has three major advantages over the large programs:
+	  a) it is easy to modify (clean, friendly code!)
+	  b) it has a nice macro language with math at the shell input
+	  c) it has a tcsh-like cursor interaction
+
+   5) kii - display program for mana.
+	This is the X window display tool used by mana.  It is not meant to be run
+	by the user, only by mana.
+
+
+
+-----------------------------------------------------------------------------------------
+Notes
+
+Compiled successfully for HP730, gcc & cc
+
+Compiled successfully for Sparc 
+
+
+
+
+-----------------------------------------------------------------------------------------
+Problems / Bugs
+
+mana / kii are rather slow in general - can we do anything about this?
+
Index: /branches/eam_branch_20080223/Ohana/doc/README.include
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/README.include	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/README.include	(revision 16632)
@@ -0,0 +1,23 @@
+
+this top level directory contains the header files associated with
+ohana library packages or basic ohana code snipets not in libraries:
+
+fitsio.h - libFITS.h
+ohana.h, Xohana.h - libohana
+skycalc.h - libskycalc
+loneos.h - FITS database interactions
+
+the architecture-dependent subdirectories allow us to install
+libraries for one architecture which are not needed and would conflict
+on another architecture.  this is mostly a problem for solaris, which
+does not have various libraries installed by default.  we can install
+an older solaris version of these libraries and not cause conflicts
+with the more recent linux versions:
+
+libpng
+libjpeg
+libreadling
+zlib
+
+
+  
Index: /branches/eam_branch_20080223/Ohana/doc/README.mana
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/README.mana	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/README.mana	(revision 16632)
@@ -0,0 +1,133 @@
+
+ April 26, 2000
+
+ I am providing the first release of 'mana' and the supporting
+ packages.  Here I will describe the needed steps to get the program
+ compiled and running. 
+
+Directory organization and Architecture selection:
+
+ Mana is part of a large collection of software called 'ohana'.  This
+ distribution of mana only includes the components of ohana needed for
+ mana.  The ohana collection is contained within a directory tree that
+ eases the use of the package on a multi-system network.  To this end,
+ there are separate bin and lib directories for different architecture
+ machines.  At the top level of 'ohana' there are the src, bin, lib,
+ and include directories.  bin and lib have subdirectories named
+ e.g. bin/linux, bin/sol, or bin/hp.  The Makefiles throughout 'ohana'
+ use an environment variable ARCH to decide which of these directories
+ is the appropriate destination.  Therefore:
+
+ BEFORE compiling any of the ohana programs, please set the ARCH
+ environment variable appropriately for your machine.  To do this
+ automatically, I use the following lines in my .cshrc:
+ 
+     ### automatically setting the ARCH variable:
+     set sys=`uname -s` 
+     switch ($sys)
+      case IRIX64:
+        setenv ARCH irix;
+        breaksw;
+      case SunOS:
+        set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+        if ($ver == 5) then
+          setenv ARCH sol
+        else 
+          setenv ARCH sun4
+        endif
+        breaksw;
+      case Linux:
+        setenv ARCH linux;
+        breaksw;
+      case HP-UX:
+        setenv ARCH hp;
+        breaksw;
+      default:
+        echo "unknown architecture";
+        setenv ARCH unknown;
+        breaksw;
+     endsw
+
+  This mechanism also lets you set your PATH correctly, no matter what
+  architecture you are on.  just include in your PATH
+  /h/fred/src/ohana/bin/{$ARCH} (or whatever the path is to the ohana
+  package!).  
+
+  In order to configure the ohana package for your local installation,
+  edit the file ohana/Configure.  Change the entry for ROOT to point
+  to the correct location of the ohana package.  Also in Configure,
+  you can tell ohana to install things in a different location from
+  the ohana directory structure.
+
+  
+Necessary Libraries:
+
+  I've included in this distribution all of the necessary libraries to
+  compile mana.  Two of these are part of the ohana package: the fits
+  and ohana libraries.  These two should compile trivially when you
+  run make.  There are several other libraries that are typically
+  included in various UNIX installations, but are sometimes missing.
+  I've included them in this distribution in case you need them, but
+  the Makefiles are not well tuned to fit with the ohana layout.  In
+  particular, libjpeg and libpng you will have to compile by hand (ie,
+  by going into those directories and compiling there, not from the
+  top level ohana directory).  Install the resulting libraries and
+  include files in the appropriate locations (either in your system,
+  or just in the appropriate lib and include directores in ohana).
+  The readline library might compile correctly from the ohana
+  Makefile, but I am not sure of this. 
+
+  It is a good idea to try the mana compilation without dealing with
+  these libraries.  You'll find out soon enough which ones your
+  systems doesn't have!
+
+  The other oddity is the situation with libnsl and libsocket.  These
+  are required libraries for Suns, but not available (not even needed)
+  under linux.  To keep the same link lines in the Makefiles, I have
+  made a dummy version of libnsl and libsocket, which should be put in
+  ohana/lib/linux.  see the ohana/src/libdummy/Makefile for details.  
+
+Compiling and installing:
+
+  First of all, move Makefile.mana to Makefile.
+
+  If the libaries are all OK, then you should be able to compile and
+  install mana and the display programs kapa and kii with the command:
+
+  make install
+
+  
+Running Mana:
+
+  Just a couple of notes about running mana.  I'm hoping the commands
+  are generally obvious and the help files helpful...
+
+  When mana starts, it loads a resource file ~/.manarc.  This is just
+  a file with a bunch of mana commands.  They can include common macro
+  definitions, defining variables, or whatever.  I've included an
+  example as mana.rc in ohana/src/mana/doc/
+
+  Mana uses two external programs to display images and vector plots,
+  nominally called 'kii' and 'kapa'.  By default, it assumes those two
+  names, but user may change the names if needed.  Mana looks at the
+  variables (mana variables, not env variables) KAPA and KII to decide
+  the program names.  By default these are set to 'kapa' and 'kii'.
+  Type "echo $KAPA" or "echo $KII" in mana to see the current values.
+  If you need to place these programs outside your path or give them
+  different names, just assign these variables (perhaps in the
+  .manarc) to the correct names and they should work fine.
+
+  In the same way, mana looks for the help files in a preset location,
+  specifically the directory of the mana executable, subdirectory
+  mana.hlp.  So, if you have mana in /usr/local/bin, mana will look
+  for the help files in /usr/local/bin/mana.hlp.  But again, this can
+  be reassigned by the user by changing the mana variable HELPDIR.  
+
+  Two useful mana commands are ? and ??.  The first lists all commands
+  and gives a little helpline.  the second lists are currently defined
+  mana variables.
+
+
+
+  Eugene Magnier
+
Index: /branches/eam_branch_20080223/Ohana/doc/allocate.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/allocate.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/allocate.txt	(revision 16632)
@@ -0,0 +1,40 @@
+
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) ((S)*sizeof(T)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc\n");\
+        exit(0);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) ((S)*sizeof(T))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc\n"); \
+       exit(0); \
+    }
+# endif /* ALLOCATE */
+
+example () {
+
+  float *fred;
+  int Nfred, NFRED, i;
+
+  NFRED = 100;
+  ALLOCATE (fred, float, NFRED);
+
+  for (i = 0; fscanf (stdin, "%f", &fred[i]) != EOF; i++) {
+    if (i == NFRED - 1) {
+      NFRED += 100;
+      REALLOCATE (fred, float, NFRED);
+    }
+  }
+  Nfred = i;
+  REALLOCATE (fred, float, MAX (Nfred, 1));
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/doc/arguments.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/arguments.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/arguments.txt	(revision 16632)
@@ -0,0 +1,63 @@
+# include <stdio.h>
+
+int get_argument (int argc, char **argv, char *arg) {
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int) NULL);
+}
+
+int remove_argument (int N, int *argc, char **argv) {
+
+  int i;
+
+  if ((N != (int) NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+    
+}
+
+main (int argc, char **argv) {
+
+  int VERBOSE;
+  float size;
+
+  /* example of an optional argument */
+  VERBOSE = FALSE;
+  if (N = get_argument (argc, argv, "-v")) {
+    remove_argument (i, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  /* one way to do an required argument */
+  size = -1;
+  if (N = get_argument (argc, argv, "-s")) {
+    remove_argument (i, &argc, argv);
+    size = atof (argv[N]);
+    remove_argument (i, &argc, argv);
+  }
+  if (size < 0) {
+    fprintf (stderr, "USAGE: program (file) -s (size) \n");
+    exit (1);
+  }
+
+  /* another way to demand an argument */
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: program (file) -s (size) \n");
+    exit (1);
+  }
+
+}
+
+
+   
Index: /branches/eam_branch_20080223/Ohana/doc/compiling.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/compiling.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/compiling.txt	(revision 16632)
@@ -0,0 +1,24 @@
+
+There are a few steps needed to compile spicam.  First, untar the
+ohana.tgz file.  Edit the file Configure in the top-level directory.
+ROOT should be the path of the top-level directory.  There are some
+destination directories, places where compiled things will go.  there
+are also two lines for the X library and include directories, though
+spicam does not require this information.  
+
+There are a couple of libraries that need to be compiled to make
+spicam.  first,  type "make install.ohana".  this will compile a set
+of miscellaneous libraries and install the file libohana.a in your
+LDIR (defined in Configure).  Next, type "make install.fits".  this
+will compile the FITS library and install libFITS.a in LDIR (note that
+this is not the Goddard fitsio package...).  Next, you need readline,
+so if you don't have it already, type "make install.readline".  same
+thing.  
+
+finally, you are ready to compile spicam.  type "make install.spicam"
+and it should compile OK.  
+
+good luck!
+
+gene
+ 
Index: /branches/eam_branch_20080223/Ohana/doc/development.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/development.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/development.txt	(revision 16632)
@@ -0,0 +1,95 @@
+
+This document discusses the Elixir / Ohana development environment.
+The Elixir Ohana components are now maintained under CVS for software
+version control.  This document discusses the motivations for this
+migration and the interaction between the developers and the CVS
+system.  It also discusses the use of the Elixir Bugzilla for problem
+reporting and feature requests.
+
+Background
+
+Previously, the Ohana system used RCS as its version control
+method. RCS is simple and easy, but has some disadvantages that make
+it difficult to use as the Elixir development continues forward in a
+wider context.  First, RCS is not network friendly: it is difficult to
+use when developers are located at different sites working on
+different timescales.  Second, it while it does a good job of tracking
+changes to individual files (revisions), it does a poor job of
+connecting those changes together across a larger software
+collection.  In particular, it does not have the ability to define a
+single collection of revisions of a group of files as a single
+software release.  CVS has been widely used for large software
+development projects and solves both of these problems well.
+
+Ohana Organization & Version Control
+
+The Ohana software system consists of many different libraries,
+programs, and scripts in perl, csh, and tcl.  These are all located in
+the Ohana source tree, with different components placed in different
+directories in the src directory.  For example, the Ohana FITS library
+package is located in the directory src/libfits, while the imclean
+program is in the src/imclean directory.  Some additional groups of
+programs are packaged together: The raw image / detrend image database
+tools and related programs are located together in the src/imregister
+directory, while a collection of small programs (consisting of
+individual C files) are located together in the src/misc directory.
+The scripts are grouped together in the src/shell, src/tcl, src/perl
+directories.  Until the introduction of CVS, only the imregister and
+misc collection of programs and the scripts were rigorously tracked
+under RCS.  The other packages were only tracked informally.  CVS
+allows us to use the existing RCS versions of these files, and
+continue the numbering sequence from where they left off.  In
+addition, CVS allows us to tag a snapshot of the revisions for an
+entire software collections with labels which can be used as
+identifiers within the software.  To this end, the software modules
+will be tagged when new releases of those packages are made.
+
+CVS Interactions: Development vs Release
+
+Elixir and Ohana are at a stage of development that it is necessary to
+separate the development and production software.  This has been done
+in the past by designating a developement directory tree
+(/data/elixir2/srcdir) and a binary distribution tree (/apps/elixir).
+Development could proceed within the srcdir tree, with software builds
+going to the local binary directories (srcdir/ohana/bin, etc).  These
+would not impact the production version of the software until the
+developer was ready to push the new version to the development tree.
+This method is sufficient when one or two developers work on the
+software and coordinate the distribution of the new software.  It does
+not allow multiple developers to work on new versions of the software
+without releasing that software until it is ready.  For example,
+consider two developers, jcc & eugene.  jcc is working on improving
+the astrometry tool, gastro, and has made some progres, but does not
+have a tested, working version yet.  Meanwhile, eugene has found and
+repaired a critical bug in the program imsearch.  In order for eugene
+to push the fix to the production version of the software, he would
+need to coordinate carefully with jcc.  jcc would need to remove the
+new version of gastro and replace it with the known working version
+for the moment when eugene pushes the new version of imsearch to the
+production system, then revert back.  
+
+Under the CVS system, each developer maintains their own version of
+the software tree.  So, for example, jcc would have a local copy
+(perhaps in his home directory) of the tree (or even a portion), while
+eugene would have a different version in his own location.  They can
+work and develop the code independently, publishing changes when
+needed to the repository (the details of these commands will be
+discussed later).  When the developer is satisfied with the changes to
+a packages (say, imclean) and feels it is ready for release to the
+public, he then labels the new release with an appropriate tag.  He
+then goes to the production version of the source tree (ie,
+/data/elixir2/srcdir) and checks out the labeled version.  He then
+compiles it and then pushes the changes to the production binary
+tree.  Note that the same is true of the configuration data saved in
+/data/elixir2/srcdir/config as well as the programs.  
+
+User Commands
+
+cvs co ohana (checkout the complete development tree)
+cvs update
+cvs commit
+cvs add
+cvs remove
+
+Bugzilla
+
Index: /branches/eam_branch_20080223/Ohana/doc/dvo2.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/dvo2.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/dvo2.txt	(revision 16632)
@@ -0,0 +1,92 @@
+
+DVO-2 upgrades the DVO concepts to meet the needs of Pan-STARRS.  The
+main constraints that Pan-STARRS has that DVO-1 cannot satisfy are:
+
+- throughput  : upload ~1e6 stars per image, allowing 5 seconds
+- precision   : DVO tables have a restricted number of bits for some
+	        entries which need to be extended for Pan-STARRS
+- flexibility : DVO uses a rigid concept for the sky layout 
+- parallel    : DVO interfaces are poorly designed for parallel I/O
+
+
+Here are the code changes I envision to get from DVO to DVO-2:
+
+- clean the elixir code organization to unify as many DVO things as
+  possible under a single library used by the related programs.
+
+  * this change would be somewhat productive for reducing the number
+    of APIs and generally clarifying the scope of the existing DVO
+    code. 
+
+- add the concept of the mosaic image which groups a set of chips
+  together.  this will include the concept of astrometric information
+  about the focal plane independent of the individual chips
+
+  * this particular change can be a stop gap to get me working with
+    mosaic astrometry within the DVO-1 framework.  Other changes,
+    listed below, will require a variety of fairly fundamental
+    changes.
+
+  * there is no additional cost to adding the mosaic files to the
+    current system, except that 'addstar' requires NSTARS > 0 (or at
+    least NASTRO > 0).  Everything else will work fine with images
+    that have distortion in them (already demonstrated in the past)
+    and the new work on coordops.c makes reverse lookup of RD_to_XY
+    accurate for Npolyterms > 1.
+
+  * chips within a mosaic framework need to have a matched mosaic
+    image.  the coordinates of the mosaic need to be registered
+    somehow with coordops (as a static entry?  not very robust, but an
+    option.  As an implied coords[0], coords[1] passed to the
+    functions?  this can be merged with the existing definitions by
+    only requiring it for entries with one ctype, but not for another
+    cartesian polynomial term (WRP vs PLY? this would make PLY mean
+    Cartesian, not Zenithal).  This is probably safe since only LONEOS
+    data has used the PLY terms in the past.  on the other hand, why
+    break it.  I could use the term PLY for the mosaic term and WRP vs
+    DIS for the two cartesian concepts.  Not very good naming.
+    Another point is that the old LONOES code uses the older style
+    tables, and probably need to be translated anyway.  I could just
+    define a loneos conversion function which converts PLY to DIS and
+    fixes the data format... (this would also let me remove the old
+    table entries from 'loneos.h', or maybe keep them there and move
+    the loneos.h file to a better name.  dvo.h?  elixir.h? 
+
+    - needed functions:
+
+      * int FindMosaicForImage (Image *images, int entry) 
+
+	returns the matching DIS entry for the given WRP entry
+	(matches by time and photcode? would need to define mosaic
+	photcodes that match the chip photcodes.  define an instrument
+	(camera) code in the Image entry?  does not exist at the
+	moment, but would need to be added (space exists in dummy[20],
+	which is surprisingly unused).
+
+- skydb library APIs : we need a collection of functions to define and
+  work with the sky tiling pattern.  These APIs need to specify things
+  like "given RA,DEC, find all overlapping tables"
+
+- convert all tables to FITS tables (currently only average/measure
+  tables are FITS).  this includes migrating the photcode and other
+  external photometry / astrometry tables into the single database
+  repository, rather than having a global table.
+
+- update the average / measure tables to include enough dynamic range.
+
+- place all tables, including average / measure under the FITS db
+  autocoder 
+
+- add proper motion velocity vectors to the average parameters
+
+- add the concept of orphans as a separate table in addition to the
+  measures
+
+- remove any average mag from the average table / place all average
+  magnitudes in their own table (ie, equivalent to secfilt, but with a
+  new name)
+
+- define a client / server interaction.  each server runs on a
+  specific host, associated with specific data tables through the
+  sky.db tables.  servers on a specific host are only responsible for
+  their own data
Index: /branches/eam_branch_20080223/Ohana/doc/dvotools.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/dvotools.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/dvotools.txt	(revision 16632)
@@ -0,0 +1,48 @@
+
+The number of DVO support programs probably needs to expand.  I am
+specifically considering the types of functions I need to perform the
+photometric and astrometric calibrations needed by Pan-STARRS, ie the
+AP Survey.
+
+dvo DB manipulations:
+
+  - create a subset of a database (restrict by magnitude limits, time, 
+    region, etc)
+  - re-organize the table structure using a new SkyTable file
+  - remove the automatic extension of the secfilt table; make a mode to 
+    add a new secondary filter
+
+dvo DB organization mods:
+
+  - drop the primary photcodes and put all primaries in the 'secfilt' table
+  - construct a FITS table for the photcodes
+  - tables for the camera and filter data which is currently in the config
+  - tools to update the photcode table
+
+addstar : need a few additional new variations on the addstar concept
+
+  - load2mass : the raw 2MASS format is so broken, I needed to create
+  a special stand-alone program to load the 2MASS catalog data to a
+  given DVO database.
+
+  - sedstar : this program uses an existing DVO database, and fits the
+    (calibrated) stellar photometry to a set of stellar photometry
+    models.  One goal is to predict magnitudes in other filters from
+    the observed data.  Another goal is to determine the fundamental
+    stellar parameters (eg, Temp, Av, logg, distance).  Another goal
+    is to determine the stellar locus coordinates for use in other
+    fitting functions.
+
+    output magnitudes should be in photcodes of DEP type? or SED type?
+
+    
+relastro : the basic concept of this program is fairly clear, but we
+  need to work out the details a bit.  The program should determine
+  the image astrometry terms, the average stellar coordinates, and
+  things like proper-motion and parallax.  It needs to include both
+  the raw astrometry from the images as well as (high-quality)
+  external reference sources.  Dave Monet thinks the initial
+  conditions (errors and systematics in the external catalogs) drive
+  the solutions too strongly.  He is exploring doing direct
+  (non-iterative) solutions using the psSparse tools.  I'm not totally
+  convinced yet...
Index: /branches/eam_branch_20080223/Ohana/doc/elixir-cvs.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/elixir-cvs.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/elixir-cvs.txt	(revision 16632)
@@ -0,0 +1,181 @@
+
+Proposal for Elixir/Ohana Software Version Control
+
+Current Practice
+
+- RCS on each file
+- source code in /data/elixir2/srcdir/ohana
+- some scripts (mana/status/dimm?) in /data/elixir2/srcdir/config/mana
+- configuration information in /data/elixir2/srcdir/config
+- software compiled in place
+- installed in /apps/elixir/bin, /apps/elixir/config
+
+Proposal
+
+- Use CVS to control software versions
+- Identify software releases, tag with CVS release tags
+- use /data/elixir2/srcdir/ohana as development site (jcc)
+- use /cfht/src/eos/
+
+----
+
+work to be done to finish CFHT elixir conversion to CVS:
+
+- verify perl & shell scripts are current
+- verify config files are current
+- convert to opihi.v2:
+  - test mana scripts under opihi.v2
+  - move 'status' scripts to 'dvo'
+- define a complete set of packages for release
+
+---
+
+In order to convert the operational CFHT version of Elixir / Ohana to
+the CVS-controlled version, we need to do several things:
+
+1) merge the changes between the CFHT and IfA trees.
+
+2) move the CFHT version of Ohana to the new opihi.v2 system from the
+   opihi.v1 system:
+   - move to the name 'dvo' rather than 'status'
+   - use the v2 version of mana
+
+3) define the Elixir / Ohana packages and tag them with a starting
+   release name 
+
+4) define an initial distribution for Elixir / Ohana using the
+   complete set of released packages.
+
+I have been working to unify the CFHT and IfA Elixir / Ohana trees.  I
+have imported all of the CFHT version of the entries in the config
+directories and the CFHT versions of the shell and perl scripts.  
+
+I have checked on the use of the 'status' program within the Elixir /
+Ohana scripts.  I have modified sp_plot and el_plot to use 'dvo'
+instead.  I have also modified elixir.photreport.  
+
+---
+
+Working with Elixir / Ohana and CVS:
+
+The CVS repositories allows the developer to work on a copy of the
+Ohana software, make changes to their copy of the code, test the
+changes within their own version of the Elixir configuration system,
+share the changes with other developers, and freeze a tested, working
+snapshot of portions of the software.
+
+The Ohana software tree is divided into packages, each possibly
+containing a single program, a group of related programs, or a C
+library.  Within the Ohana software version control system, each of
+these packages should be released as a single entity.  Changes may be
+made to any of the elements which make up the package.  The new
+changes should be tested so that the developer is confident that the
+new version of the software may be safely introduced into the
+production system.  At this point, the entire package is tagged with
+an identifying name and the new release of the package may be loaded
+into the production tree.
+
+In the following discussion, we illustrate the process of creating a
+new release of a package within Elixir. 
+
+First, check out the Ohana tree:
+
+set CVSROOT to username@machine:/data/elixir2/srcdir/cvs where
+'username' is your user ID and machine is one of the CFHT linux
+machines which mount /data/elixir2/srcdir.  
+
+check out your copy of the software tree:
+
+ cvs co ohana
+
+you may also check out specific releases of packages with the command:
+ cvs co -r TAG PACKAGE  eg:
+ cvs co -r libfits-1-0 libfits
+
+this version should be executed from the same directory level as the
+cvs co ohana command; each package is placed in the directory
+ohana/src/PACKAGE.
+
+The entire ohana package may be compiled from the ohana directory
+with:
+
+> configure
+> make
+> make install
+
+Make edits, changes, etc to the programs in some package.  For
+example, you might edit the .c files in the directory
+ohana/src/gastro/src.  Occasionally publish your changes to the CVS
+repository:
+
+cvs update (check for changes by other developers)
+cvs commit [filename] (publish the changes)
+
+also:
+
+cvs add (filename)  (add a new file to the repository).  
+
+Once the changes have been made, make sure to compile and test your
+copy of the program.  If you are acting as a developer, you must have
+your version of the ohana/bin/ARCH directory in your path (before the
+production installation path, /apps/elixir/bin).  Once the code has
+been tested, and the package is ready for release, commit all of your
+changes to the repository (cvs commit).  Now you may tag the new
+release of the package.  Within the top-level directory of the
+package, give the command:
+
+cvs tag -c TAG 
+
+where TAG is the name of this release.  Within the Ohana system,
+packages are generally tagged with names of the form PACKAGE-N-M where
+N and M are major and minor version numbers.  For example, libfits has
+tag names starting from libfits-1-0.  If the changes are minor, and
+don't affect interaction with other packages, then it is only
+necessary to change the minor version number.  If the new package
+forces changes on other packages, it is best to change the major
+version as well.  Major version changes should be introduced only with
+discussion among the affected parties!   It is possible to check the
+currenly assigned tags for a package with the command:
+cvs status -v (filename) 
+where (filename) is some file that is part of the package.  A
+convenient file to use is the Makefile for the package.  Assigning the
+tag affects the repository directly (there is no need to run 'commit'
+afterwards).  If you have outstanding changes, the -c option will
+force CVS to complain, so you will not tag different versions of the
+files from what you expect.
+
+Once the tag has been assigned, the new version of the package may be
+introduced to the production system. This is a two step process:
+first the new source tree is placed in the appropriate location and
+compiled.  Then the new binaries are pushed to their final locations.
+There are two options for installing the new package source code.
+First, you may make a new elixir distribution.  To do this, go into
+the ohana/etc directory, and edit the distributions.txt file.  This
+defines the package releases which make up a complete distribution.
+There are entries for the ohana/elixir distributions, mana
+distributions, etc.  Make a new distribution version, update the
+appropriate package, and save the file.  This distribution (or any
+other older distribution) may now be constructed by executing the
+command 'mkdist (distribution) (version)', for example:
+mkdist elixir 1.0
+This command extracts from the CVS repository all of the package
+versions which are specified to be part of the given distribution
+version.  These are placed in a single directory, along with the ohana
+infrastructure pieces, with the directory name matching the package
+name and version number.  This new directory may be moved or copied to
+the official production source code location
+(/data/elixir2/srcdir/ohana).  The entire tree may then be compiled.  
+
+An alternative to the above is to checkout only the new package
+version.  To do this, go to the directory containing the production
+code (ie, /data/elixir2/srcdir).  Perform a checkout of the specific
+tagged release of the package of interest:
+cvs co -r TAG PACKAGE (ie, cvs co -r libfits-1-0 libfits).  This will
+replace the old version of the package with the new version.  Now the
+software may be recompiled from the ohana directory. 
+
+Once a new version of the software has been compiled, it may be pushed
+to the production binary directory.  From the /data/elixir2/srcdir
+directory, issue the command 'make install' (make install-test will
+show what programs are new).
+
Index: /branches/eam_branch_20080223/Ohana/doc/exclude
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/exclude	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/exclude	(revision 16632)
@@ -0,0 +1,4 @@
+find ohana -name "*.o" -print > exclude.files 
+find ohana -name "bin" -print >> exclude.files
+find ohana -name "*.a" -print >> exclude.files
+tar cvfX - exclude.files ohana | gzip > ohana.tgz.8.97 
Index: /branches/eam_branch_20080223/Ohana/doc/exclude.list
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/exclude.list	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/exclude.list	(revision 16632)
@@ -0,0 +1,19 @@
+Configure
+bin
+*.sol*
+*.sid*
+*.linux*
+*.lin64*
+*.o
+*.a
+*.so
+*~
+#*
+.mana
+.status
+.dvo
+RCS
+lib/sol
+lib/sid
+lib/linux
+lib/lin64
Index: /branches/eam_branch_20080223/Ohana/doc/gnu.license
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/gnu.license	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/gnu.license	(revision 16632)
@@ -0,0 +1,344 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                          675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /branches/eam_branch_20080223/Ohana/doc/graphics.info
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/graphics.info	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/graphics.info	(revision 16632)
@@ -0,0 +1,1595 @@
+This is Info file graphics.info, produced by Makeinfo-1.55 from the
+input file graphics.texi.
+
+   This file documents GNU graphics.
+
+   Copyright (C) 1989 Free Software Foundation, Inc.
+
+
+File: graphics.info,  Node: Top,  Up: (dir)
+
+* Menu:
+
+* introduction::         About the GNU graphics utilities
+* graph examples::       Using Graph to create plot files from data
+* graph invocation::     Command line options for Graph.
+* plot2ps examples::     converting plot files to PostScript
+* plot2ps invocation::   Plot2ps Command Line Options
+* xplot::                a plot file previewer for X11
+* xplot invocation::     xplot command line options and X11 resources
+* plot2fig examples::    converting plot files to Fig graphics editor format
+* plot2fig invocation::  command line options for plot2fig
+* plot2tek invocation::  Tektronix 4010 output
+* latex example::        Including a Figure in an Article
+* psfig::                Options to `psfig' for Including Figures
+* atend.pl::             A perl script for use with psfig
+* dvips::                How to Get `dvips'
+* idraw::                How to Get `idraw'
+* ghostscript::          an X11 PostScript interpreter/previewer
+* libps::                The Library of Plot Functions for PostScript Output
+* files::                The Plot File Format
+* Acknowledgements::     The Contributors
+* Function Index::       An Index to the libps Functions
+
+
+File: graphics.info,  Node: introduction,  Next: graph examples,  Up: Top
+
+The GNU Graphics Utilities
+**************************
+
+   The GNU graphics utilities are a set of programs for plotting
+scientific data.  The program `graph' reads data files and writes a
+stream of plotting commands in a device independent format refered to
+below as a GNU plot file.  The remaining programs provide support for
+displaying GNU plot files on tektronix 4010, PostScript (TM)*, and X
+window system compatible output devices.
+
+   `graph' reads both ascii and binary data files and writes a plot
+file with or without axes and labels.  You can specify labels and ranges
+for the axes, and you can set the sizes and position of the plot on the
+page.  Each invocation of graph produces a plot with single set of axes
+and data.  You can place an arbitrary number of plots on the page by
+concatenating the plot output of several invocations.
+
+   `plot2ps' is a utility for converting plot files into PostScript.
+The `plot2ps' utility reads plotting commands from named files or the
+standard input and writes PostScript to the standard output.  You can
+then print the PostScript output on a printer, or edit it using the
+`idraw' graphics editor.  You can also easily include the output in
+LaTeX documents using `dvips' and the LaTeX command `psfig'.
+
+   Why is this useful? The plot file format is a common standard on un*x
+systems.  To produces figures for publication, you might need to take
+data sets, and produce labeled figures from them.  This can be done
+using `graph', `plot2ps' and the `idraw' editor.  You can also include
+these figures in LaTeX documents using the `dvips' utility.  All of
+these utilities, as well as the plot file format and plot library, are
+discussed in the following sections.
+
+   This documentation is under revision.  Any comments, suggestions, or
+additions would greatly benifit GNU users.  Please mail them to either
+`bug-gnu-utils@prep.ai.mit.edu' or `Rich@Rice.edu'.
+
+   * PostScript is a trademark of Adobe Systems Incorporated.
+
+
+File: graphics.info,  Node: graph examples,  Next: graph invocation,  Prev: introduction,  Up: Top
+
+`graph' Examples
+================
+
+   Each invocation of `graph' plots data read from stdin or named files
+togeather in a single plot with or without axes and labels.  The
+following sections show common usage of `graph'.
+
+* Menu:
+
+* Invocation::		Simple examples using graph
+* Input Files::		What the input looks like
+* Overlaying::		Combining several data sets in one plot
+* Multiple Plots::	Multiple plots on one page
+* Binary Data::		Reading other data formats
+
+
+File: graphics.info,  Node: Invocation,  Next: Input Files,  Up: graph examples
+
+Simple examples using graph
+===========================
+
+   By default, `graph' reads ascii data from the standard input or
+files specified on the command line.  `graph' reads pairs of values, x
+and y coordinates:
+
+     0.0  0.0
+     1.0  0.2
+     2.0  0.0
+     3.0  0.4
+     4.0  0.2
+     5.0  0.6
+
+   To plot this data, you might use
+
+     graph < ascii_data_file |plot
+
+   where ascii_data_file could contain data similar to the above
+example.  You can replace the command `plot' with `plot2tek' if you have
+a tektronix 4010 compatible graphics terminal, `plot2ps' if you have a
+postscript compatible printer or previewer, or `xplot' if you have an X
+window system display.
+
+   Note that `graph' is commonly supplied with some operating systems.
+If so, some confusion may arise if the system supplied version is
+executed mistakenly.  On unix systems, you can determine which version
+you invoke by typing the command `which graph', which prints the file
+name of the version you invoke by default.
+
+   To reduce the change the size of the plot and position it in the
+middle of the display, you could use
+
+     graph -h .4 -w .4 -r .2 -u .2 < ascii_data_file |plot
+
+   where `h' and `w' are the height and width of the plot and `r' and
+`u' indicate how far up and to the right the plot is positioned.
+
+   You can put symbols at each data point using
+
+     graph -S 2 .01 < ascii_data_file |plot
+
+   where 2 indicates which symbol to plot, and .01 indicates it's size.
+
+   You can choose the type of line draw on each curve:
+
+     graph -m 2 < ascii_data_file |plot
+
+   where 2 indicates what kind of line connects the data points.
+
+
+File: graphics.info,  Node: Input Files,  Next: Overlaying,  Prev: Invocation,  Up: graph examples
+
+The format of input to `graph'
+==============================
+
+   As mentioned above, by default `graph' reads ascii pairs of values,
+x and y coordinates, from the standard input or files specified on the
+command line.  Optional labels may be placed after each coordinate in
+the data file.  The label ends at the end of the line:
+
+     3.0  0.4 this is a label for point (3.0, 0.4).
+
+   The label must be enclosed in double quotes if it would otherwise be
+appear to be a coordinate:
+
+     3.0  0.4 "5.0 looks like a value."
+
+   You can use the `-b' to break lines after each label in the input.
+Use a pair of empty double quotes if you need to break a line, but do
+not need a label.
+
+     0.0  0.0
+     2.0  0.0
+     1.0  0.2
+     ""
+     0.0  0.1
+     2.0  0.2
+     4.0  0.3
+
+   You can also break cuves using `-M' option to break lines whenever
+the abscissal values between successive pairs of points decrease.  When
+using `-M', each continuous curve has monotonicly increasing abscissal
+values.
+
+     0.0  0.0 first data set
+     2.0  0.0
+     4.0  0.2
+     0.0  0.1 second data set
+     2.0  0.2
+     4.0  0.3
+
+   `graph' will automaticly generate abscissal values for you if you
+specify the `-a' option.  Only ordinate values are given in the data,
+and the data is then assumed to be equally sampled along the abscissa.
+The values following `-a' on the command line specify the sampling
+interval and the abscissal value of the first data point.
+
+     0.0
+     0.1
+     0.2 label for point (2.0, 0.2)
+     0.3
+     0.2
+     0.3
+
+
+File: graphics.info,  Node: Overlaying,  Next: Multiple Plots,  Prev: Input Files,  Up: graph examples
+
+Combining several data sets in one plot
+=======================================
+
+   There are cases where you will want to superimpose several data sets
+or several plots on top of each other.  If for example, the data sets
+are in seperate files, you can specify each by it's name on the command
+line.  Since `graph' reads the standard input only if no files are
+named on the command line, you must add the name `--' if you want
+`graph' to read the standard input as well.
+
+     graph data-file-one data-file-two data-file-three |plot
+
+   For comparison sake, you might wish to distinguish the data in one
+set from another either by using different symbols at each point or by
+distinguishing the type of line draw.  You can do this by preceeding
+each file name with options affecting the synbol or line style used to
+plot that data.
+
+     graph -S 1 data-file-one -S 3 data-file-two -S 4 data-file-three |plot
+     
+     or
+     
+     graph -m 1 data-file-one -m 3 data-file-two -S 4 data-file-three |plot
+
+   If you need to superimpose several data sets, but must invoke graph
+seperately for each, you will have to specify the limits of the axes.
+
+     graph -x 0 100 -y -3 3 -S 3 -m -1 < ascii_data_file_1 >> plot_file
+
+   where `-x 0 100' specifies the limits on the x axis, `-y -3 3'
+specifies the limits on the y axis, `-S 2' specifies a box to be drawn
+at each point, and `-m -1' specifies that no line is to be draw
+connecting the points.  You can overlay a second data set on the first
+by using:
+
+     graph -s -g 0 -x 0 100 -y -3 3 -m 0 < ascii_data_file_1 >> plot_file
+
+   where `-s' avoids erasing the page, `-g 0' avoids drawing the axis,
+tick marks and labels which were drawn previously, and `-m 0' specifies
+that solid lines are draw connecting the points.
+
+
+File: graphics.info,  Node: Multiple Plots,  Next: Binary Data,  Prev: Overlaying,  Up: graph examples
+
+How to put multiple plots on one page
+=====================================
+
+   The command
+     graph -h .4 -w .4 -r .1 -u .1 < ascii_data_file_1 >  plot_file
+
+   will put a single box containing the plot in the lower left hand
+quarter of the page.  You can add another plot to the upper left hand
+corner of the page using the command
+
+     graph -s -h .4 -w .4 -r .1 -u .6 < ascii_data_file_2 >> plot_file
+
+   Be sure you use the `-s' option so the the first plot isn't erased.
+
+   Likewise you can add plots to the right hand side of the page using
+
+     graph -s -h .4 -w .4 -r .6 -u .1 < ascii_data_file_3 >> plot_file
+     graph -s -h .4 -w .4 -r .6 -u .6 < ascii_data_file_4 >> plot_file
+
+   The tick marks can be moved inside the box and labels moved to the
+opposite sides using
+
+     graph -T -.005 < ascii_data_file >> plot_file
+
+
+File: graphics.info,  Node: Binary Data,  Prev: Multiple Plots,  Up: graph examples
+
+Reading other data formats
+==========================
+
+   `graph' will read binary data in integer, short integer, float, and
+double float format when you use the `-d' option followed by `f', or
+`d', respectively.  There are two advantage to using binary data: 1)
+`graph' runs significantly faster because the computational overhead
+for converting data from ascii to binary is eliminated, and 2) the
+input files can be significantly smaller than the ascii format would
+be.  Double float is the fastest format to read, while short integer is
+the most space conservative.  If you have very large data sets, using a
+binary format can reduce storage and runtime costs.
+
+   For example, you can create double float data as output from C
+language programs:
+
+     #include <stdio.h>
+     void write_point (x, y)
+       double x, y;
+     {
+       fwrite(&x, sizeof (double), 1, stdout);
+       fwrite(&y, sizeof (double), 1, stdout);
+     }
+
+   You can then plot data written this way using:
+
+     graph -d d <datafile >plotfile
+
+
+File: graphics.info,  Node: graph invocation,  Next: plot2ps examples,  Prev: graph examples,  Up: Top
+
+Graph Command Line Options
+==========================
+
+   The following table describes each of the command line arguments to
+graph.  Each option which takes an argument is followed by the type and
+default values of the argument in parentheses.
+
+`-a [STEP_SIZE [LOWER_LIMIT]]'
+`+auto-abscissa [STEP_SIZE [LOWER_LIMIT]]'
+     (floats, defaults 1 and 0) Automaticly generate abscissa (x)
+     values.  This option specifies that the data contains only
+     ordinate (y) values.  The difference between successive x values
+     will be STEP_SIZE, and the first x value will be LOWER_LIMIT.  To
+     return to reading abscissal values from the input you can specify
+     `-a 0', which disables automatic generation of the abscissa and
+     returns STEP_SIZE and LOWER_LIMIT to their default values.
+
+`-b'
+`+break-on-labels'
+     Assumes multiple data sets are in the data file, and the data sets
+     are separated by a label.  The default is don't break on labels.
+
+`-M'
+`+break-non-monotone'
+     When successive abscissa (x) values decrease, a separate data set
+     is assumed.  This allows multiple data sets in each file.  Similar
+     to `-b'.
+
+`-f SIZE'
+`+fontsize SIZE'
+     Specify the size of the desired font as SIZE points.  Not all
+     display devices will honor this command.
+
+`-N X|Y'
+`+no-label X|Y'
+     By default, values at each tick mark are labeled beside the axis.
+     This option removes the labeling of the tick marks on the specified
+     axis.
+
+`-R'
+`+dont-round-to-next-tick'
+     By default, the ends of the axes are extended to the next tick
+     mark.  This option prohibits rounding the limits of the axes to
+     the next tick mark.
+
+`-c STRING'
+`+point-label STRING'
+     This option defines STRING as the default label for each point.
+     Any label in the input will override this default.
+
+`-S SYMBOL_NUMBER [SYMBOL_SIZE]'
+`+symbol SYMBOL_NUMBER [SYMBOL_SIZE]'
+     (integer and float, defaults -1 and 0.01) Draw a symbol at each
+     point in the data. SYMBOL_NUMBER specifies the shape of the symbol
+     according to the following table and SYMBOL_SIZE specifies the
+     fractional size of the symbol with respect to the height and width
+     of the plot.  Note that you can specify symbols to be drawn
+     without any line connecting them by specifying the option `-m -1'.
+    -1 no symbol at all
+    0 plus sign (+)
+    1 cross (x)
+    2 star (*)
+    3 box
+    4 diamond
+    5 circle
+`-T TICK_SIZE'
+`+ticksize TICK_SIZE'
+     (float, default .01) TICK_SIZE is the fractional size of the tick
+     marks on each axis.  A value of 1.0 produces tick marks on the x
+     (y) axis whose length is equal to the width (height) of the plot.
+
+`-X X_LABEL'
+`+xtitle X_LABEL'
+     (string, default blank) X_LABEL is a label printed below the x
+     axis.
+
+`-Y Y_LABEL'
+`+ytitle Y_LABEL'
+     (string, default blank) Y_LABEL is a label printed to the right of
+     the y axis.
+
+`-d DATA-FORMAT'
+`+data-format DATA-FORMAT'
+     This specifies what format the input data is in.  Note labels can
+     be used only in ascii format input files.
+    `a'
+    `A'
+          ascii data
+
+    `i'
+    `I'
+          binary integer data
+
+    `s'
+    `S'
+          binary short integer data
+
+    `f'
+    `F'
+          binary float data
+
+    `d'
+    `D'
+          binary double data
+
+`+debug'
+     Debugging information, including the data read in, is sent to the
+     standard error output.
+
+`-g GRID_STYLE'
+`+grid GRID_STYLE'
+     (integer, default 1) GRID_STYLE specifies the type of box framing
+     the plot and whether grid lines are drawn inside the box.
+    0 no box around plot, no axes, no labels.
+    1 box containing a grid and axes with tick marks and labels.
+    2 box around plot, tick marks around the box and labels.
+    3 box around plot, ticks on left and lower sides only and labels.
+    4 axes intersect at the origin without a box or grid.
+`-h HEIGHT'
+`+height-plot HEIGHT'
+     (float, default 0.8) HEIGHT specifies the fractional height of the
+     plot with respect to the height of the plotting area.  A value of
+     1.0 will produce a box which fills the available area.  Note that
+     the tick marks and labels are outside this area so that values
+     less than 1.0 are generally used.
+
+`-L TOP_LABEL'
+`+toptitle TOP_LABEL'
+     (string, default blank) TOP_LABEL is a label placed above the plot.
+
+`-m LINE_MODE'
+`+linestyle LINE_MODE'
+     (integer, default 0) LINE_MODE specifies the mode (or style) of
+     lines drawn between data points.
+    -1 no line at all
+    0 solid
+    1 dotted
+    2 shortdashed
+    3 dotdashed
+    4 longdashed
+    5 disconnected
+`-r RIGHT'
+`+right-margin-posn RIGHT'
+     (float, default 0.1) Move the plot to the right by a fractional
+     amount RIGHT with respect to the width of the plotting area.  This
+     produces a margin on the left hand side of the plot.  A value of
+     0.5 will produce a margin half the width of the available area.
+     Note that the tick marks and labels are drawn in the margin.
+
+`-u UP'
+`+bottom-margin-posn UP'
+     (float, default 0.1) Move the plot up by a fractional amount UP
+     with respect to the height of the plotting area.  This produces a
+     margin below the plot.  A value of 0.5 will produce a margin half
+     the height of the available area.  Note that the tick marks and
+     labels are drawn in the margin.
+
+`-s'
+`+save-screen'
+     Save the screen. This option prevent graph from erasing the
+     previous contents of the graphics window or device.
+
+`-t'
+`+transpose'
+     Transpose the abscissa and ordinate.  This option causes the axes
+     to be interchanged, and the options which apply to each axis to be
+     applied to the opposite axis.  That is, data is read in as (y, x)
+     pairs and `-x', `-X' and `-lx' apply to the y axis.
+
+`-w WIDTH'
+`+width-plot WIDTH'
+     (float, default 0.8) WIDTH specifies the fractional width of the
+     plot with respect to the width of the plotting area.  A value of
+     1.0 will produce a box which fills the available area.  Note that
+     the tick marks and labels are outside this area, so values less
+     than 1.0 are generally used.
+
+`-x LOWER_LIMIT UPPER_LIMIT'
+`+xlimits LOWER_LIMIT UPPER_LIMIT'
+     (floats) The arguments LOWER_LIMIT and UPPER_LIMIT specify the
+     limits of the x axis. By default the upper and lower limits are
+     taken from the data.  If unspecified the limits of the data are
+     used.
+
+`-y LOWER_LIMIT UPPER_LIMIT'
+`+ylimits LOWER_LIMIT UPPER_LIMIT'
+     These arguments specify the scale and limits of the y axis as for
+     the x axis above.
+
+`-l X|Y'
+`+log-axis X|Y'
+     The argument indicates which axis should be a log axis.  Either
+     one or both x- and y-axes can be specified by using the
+     appropriate letter.  Use XY or YX to specify both.
+
+`+high-byte-first'
+`+low-byte-first'
+     These options force graph to use the specified byte order when
+     writing out the plot file.  By default the byte order is host
+     dependent.
+
+
+File: graphics.info,  Node: plot2ps examples,  Next: plot2ps invocation,  Prev: graph invocation,  Up: Top
+
+Examples Using `plot2ps'
+========================
+
+   To produce a plot of data arranged in ordered pairs of x and y
+coordinates in an ASCII file, you can use:
+
+     graph <asciiDataFile | plot2ps | lpr -Plw
+
+   To create a simple PostScript figure you can use:
+
+     echo 0 0 1 1 2 0 | spline | graph | plot2ps > test.ps
+
+   To edit the plot:
+
+     idraw test.ps
+
+   To use the previewer to look at the plot:
+
+     gs test.ps
+
+
+File: graphics.info,  Node: plot2ps invocation,  Next: xplot,  Prev: plot2ps examples,  Up: Top
+
+Plot2ps Command Line Options
+============================
+
+   `plot2ps' is a relatively simple utility in that there are few
+command line options to choose from.  The plot file format does not
+contain methods for specifying font or font size, so you must specify
+these things with options.  There are no other options for controlling
+the picture.
+
+   The plot file format is machine dependent on the byte order of
+unformatted, signed, two byte integer coordinates contained in plot
+commands.  The `-high-byte-first' or `-low-byte-first' option specifies
+this order explicitly.  `plot2ps' attempts to determine the byte order
+from commands early in the plot file, but the method is heuristic and
+is not foolproof.  Several standard plot sizes specified by the `open'
+command are used to recognize byte order by `plot2ps'.  If these sizes
+are recognized in byte reversed order, `plot2ps' adjusts accordingly.
+These sizes include 504x504, 2048x2048 (versatek plotters), 2100x2100,
+3120x3120(tektronix 4010 terminals) and 4096x4096 (gsi 300 terminals).
+
+   The remaining command line options may be used specify an alternate
+PostScript prologue and to print the licensing information.
+
+   Input plot files names may be specified anywhere on the command line.
+If no file names are specified, or the name `-' is specified, the
+standard input is read for plotting instructions.  Only the font or
+font size options which precede a file name will affect the text for
+that file.
+`-H'
+`+help'
+     The help option prints a summary of command line syntax for
+     `plot2ps', a list of the font names (the standard builtin
+     PostScript fonts), and version, copyright and warranty information.
+     Specifying this options causes plot2ps to ignore files on the
+     standard input.  You can specify a file on the standard input
+     explicitly with the option `-' if you want it to read the standard
+     input as well.
+
+`-v'
+`-V'
+`+version'
+     This option prints version, copyright and warranty information.
+
+`-fontsize SIZE'
+`-f SIZE'
+     The fontsize options specifies the default size in printer's points
+     (1/72 inch) of all text appearing in the plot.  If unspecified, the
+     size defaults to 14 points.
+
+     Some sizes are supported better than others under X windows.  The
+     standard sizes distributed with X windows are 8, 10, 12, 14, 18,
+     and 24 points.  Text at these point sizes will display correctly
+     in the `idraw' editor.  Other font sizes will print correctly on a
+     PostScript device such as the laserwriter, but may not appear at
+     the correct size in the `idraw' editor.
+
+`-font NAME'
+`-fo NAME'
+     The font name option specifies the name of the default font for all
+     text appearing in the plot.  `plot2ps -help' prints a listing of
+     the font names on the standard output.  These names include the
+     available builtin fonts on standard PostScript printers.
+
+`-high-byte-first'
+`-h'
+     The high-byte-first option specifies explicitly that the higher
+     order byte of each signed, two byte integer occurs first in the
+     file.  It disables determination of byte order from the file
+     itself.
+
+`-line-width WIDTH'
+     WIDTH is the width of lines drawn in the plot, and defaults to a
+     value of 0.  A value of 0 will produce the thinest line possible
+     in a device dependent fashion, however this is known to cause
+     problems for older versions of idraw.  The line width is device
+     independent for a positive values of WIDTH.
+
+`-low-byte-first'
+`-l'
+     The low-byte-first option specifies explicitly that the lower order
+     byte of each signed, two byte integer occurs first in the file.  It
+     disables determination of byte order from the file itself.
+
+`-prologue FILENAME'
+`-p FILENAME'
+     The prologue option specifies the name of an alternate PostScript
+     prologue FILENAME to be used in place of the default `idraw'
+     prologue.  The prologue declares procedures used to draw each
+     graphic object.  The default prologue was generously provided by
+     John Interante and is a part of the InterViews distribution,
+     version 2.5.
+
+`-copying'
+`-warranty'
+     The copying and warranty options print a copy of the GNU General
+     Public License on the standard error output.  Included is
+     conditions for copying `plot2ps' and information on the lack of any
+     warranty.
+
+     These conditions do not cover the output of `plot2ps'.  The only
+     conditions imposed on the output are those which come from the
+     prologue that you are using.
+
+`-signed'
+`-unsigned'
+     The signed and unsigned options specify whether coordinates in the
+     plot file are signed.  By convention, coordinates are always
+     signed.  Some plot files do not follow this convention, and you
+     can use the unsigned option to convert those files.
+
+`-bbox'
+     The bbox option specifies that a bounding box comment will be
+     written at the end of the output file.  This information is useful
+     for document preparation systems which determine how to size and
+     place the figure using the bounding box.  See also the atend
+     script.
+
+
+File: graphics.info,  Node: xplot,  Next: xplot invocation,  Prev: plot2ps invocation,  Up: Top
+
+A plot file previewer for X11
+=============================
+
+   `xplot' is a plot file previewer for the X window system.  It reads
+GNU plot commands from its standard input and draws the resulting
+graphics in an X window.
+
+   After xplot reaches the end-of-file on the input, it puts itself in
+the background (forks).  Control returns to the calling program, while
+xplot continues, remaining on screen.
+
+   To exit, click the left mouse button in the xplot window.  Note that
+xplot ignores SIGHUP signals, so you must use another signal to kill
+xplot if necessary.
+
+
+File: graphics.info,  Node: xplot invocation,  Next: Plot2fig Examples,  Prev: xplot,  Up: Top
+
+Xplot Options
+=============
+
+   `xplot' accepts all of the standard X toolkit command line options,
+and the initial geometry specification determines the resolution, with a
+default geometry of 500x500 pixels.
+
+   The following standard X Toolkit command line arguments may be used
+with `xplot':
+`-bg COLOR'
+     This specifies the color to use for the background of the window.
+     The default is WHITE.
+
+`-bd COLOR'
+     This specifies the color to use for the border of the window.  The
+     default is BLACK.
+
+`-bw NUMBER'
+     This specifies the width in pixels of the border surrounding the
+     window.
+
+`-fg COLOR'
+     This specifies the color to use for displaying text.  The default
+     is BLACK.
+
+`-fn FONT'
+     This specifies the font to be used for displaying normal text.  The
+     default is 6X10.
+
+`-rv'
+     This indicates that reverse video should be simulated by swapping
+     the foreground and background colors.
+
+`-geometry GEOMETRY'
+     This specifies the preferred size and position of the plot window.
+
+`-display HOST:DISPLAY'
+     This specifies the X server to contact.
+
+`-xrm RESOURCESTRING'
+     This specifies a toolkit resource property.  See the manual page
+     for xrdb.
+
+   `xplot' uses the athena Command widget in the X Toolkit.  So, it
+understands all of the core resource names and classes as well as:
+`reverseVideo'
+     (class ReverseVideo) Specifies that the foreground and background
+     colors should be reversed.
+
+Example
+-------
+
+   The resources:
+
+     Xplot.font: 6x9
+     Xplot.geometry: 300x300
+
+   will set the font used in the plot window to `6x9' and the size of
+the window to 300 by 300 pixels.
+
+
+File: graphics.info,  Node: Plot2fig Examples,  Next: plot2fig invocation,  Prev: xplot invocation,  Up: Top
+
+Using Plot2fig
+==============
+
+   To create a simple plot file one can use:
+
+     echo 0 0 1 1 2 0 | spline | graph | plot2fig > test.fig
+
+   To edit the plot:
+
+     fig test.fig
+
+   To convert the fig file into dvi code, create a latex file containing
+a document which includes the figure:
+
+     \\documentstyle\[\]{article}
+     \\begin{document}
+     \\input{test}
+     \\end{document}
+
+   Then, run transfig on the figure and latex on the document:
+
+     % transfig -L latex test.fig
+     % make test.tex
+     % latex t.tex
+
+   To edit a plot of data arranged in ordered pairs of x and y
+coordinates in an ascii file, one can use:
+
+     % graph <asciiDataFile | plot2fig >file.fig
+     % fig file.fig
+
+
+File: graphics.info,  Node: plot2fig invocation,  Next: plot2tek invocation,  Prev: plot2fig examples,  Up: Top
+
+A plot file to fig file translator
+==================================
+
+   `plot2fig' reads plotting instructions from the specified input
+files and/or the standard input and produces `Fig' compatible code on
+it's standard output.  This output file can be edited with the fig
+(Facility for Interactive Generation of figures) graphics editor.  The
+output can subsequently be converted to pictex, PostScript, latex, epic,
+eepic, and tpic languages using the `transfig' translator.
+
+   Any unrecognized options on the command line are assumed to be input
+files.  The standard input is read by default only if no other files
+specified on the command line are successfully opened.  A single dash
+(-) on the command line indicates the standard input is to be read.
+Each option is set and each file read in the order they are specified on
+the command line.
+
+   For compatibility with pic2fig, plot2fig ignores leading white space
+in labels.  Labels containing all white space are ignored.
+
+`-fn NAME'
+`-fontname NAME'
+     Default: the default font of the transfig output device.  This
+     option sets the font for all subsequent text to NAME.  Recognized
+     font names are typewriter, modern, italic, bold, and times.  In
+     addition, courier is an alias for typewriter and roman is an alias
+     for times.  Note that the fonts are device dependent.
+
+`-fs SIZE'
+`-fontsize SIZE'
+     Default: 12. This option sets the size of subsequent text to SIZE
+     (in printer's points).
+
+`-h'
+`-high-byte-first'
+     This option specifies that the byte ordering of two byte integers
+     in the input plot file is high byte first.
+
+`-l'
+`-low-byte-first'
+     This option specifies that the byte ordering of two byte integers
+     in the input plot file is low byte first.
+
+`-warranty'
+`-copying'
+     This option prints out the copying conditions and warranty
+     information.
+
+`-signed'
+`-unsigned'
+     Default: signed.  This option specifies whether two byte integers
+     in the input plot file are unsigned or signed.
+
+`-'
+     This option specifies explicitly that the standard input should be
+     read for plotting instructions.
+
+
+File: graphics.info,  Node: plot2tek invocation,  Next: latex example,  Prev: plot2fig invocation,  Up: Top
+
+Tektronix 4010 output
+=====================
+
+`-H'
+`+help'
+     The help option prints a summary of command line syntax, a list of
+     the known font names, and version, copyright and warranty
+     information.  Specifying this options causes plot to ignore the
+     standard input, so you must specify the option `-' if you want it
+     to read the standard input as well.
+
+`-v'
+`-V'
+`+version'
+     This option prints version, copyright and warranty information.
+
+`-f SIZE'
+`+fontsize SIZE'
+     The fontsize options specifies the default size in printer's points
+     (1/72 inch) of all text appearing in the plot.  If unspecified, the
+     size defaults to 14 points.
+
+`+high-byte-first'
+`+low-byte-first'
+     These options force graph to use the specified byte order when
+     writing out the plot file.  By default the byte order is host
+     dependent.
+
+`-F NAME'
+`+fontname NAME'
+     The font name option specifies the name of the default font for all
+     text appearing in the plot.  `plot -help' prints a listing of the
+     font names on the standard output.  These names include the
+     available builtin fonts on standard PostScript printers.
+
+`-h'
+`+high-byte-first'
+     The high-byte-first option specifies explicitly that the higher
+     order byte of each signed, two byte integer occurs first in the
+     file.  It disables determination of byte order from the file
+     itself.
+
+`-l'
+`+low-byte-first'
+     The low-byte-first option specifies explicitly that the lower order
+     byte of each signed, two byte integer occurs first in the file.  It
+     disables determination of byte order from the file itself.
+
+`-p FILENAME'
+`+prologue FILENAME'
+     The prologue option specifies the name of an alternate PostScript
+     prologue FILENAME to be used in place of the default `idraw'
+     prologue.  The prologue declares procedures used to draw each
+     graphic object.  The default prologue was generously provided by
+     John Interante and is a part of the InterViews distribution,
+     version 2.5.
+
+`+copying'
+`+C'
+`+warranty'
+`+W'
+     The copying and warranty options print a copy of the GNU General
+     Public License on the standard error output.  Included is
+     conditions for copying `plot' and information on the lack of any
+     warranty.
+
+`-s'
+`+signed-input'
+`-u'
+`+unsigned-input'
+     The signed and unsigned options specify whether coordinates in the
+     plot file are signed.  By convention, coordinates are always
+     signed.  Some plot files do not follow this convention, and you
+     can use the unsigned option to convert those files.
+
+
+File: graphics.info,  Node: latex example,  Next: psfig,  Prev: plot2tek invocation,  Up: Top
+
+Including a Figure in an Article
+================================
+
+   This is an example of LaTeX code which places the figure generated in
+the previous example in a page of text.
+
+     \documentstyle[]{article}
+     \input{psfig}
+     \begin{document}
+     \title{Title of the article.}
+     \author{The Author's name}
+     \maketitle
+     This is an example of how to include PostScript figures in LaTeX documents.
+     \begin{figure}[h]
+     \centerline{\psfig{figure=test.ps,height=3in}}
+     \caption{Here is a description of the figure which will appear below it.}
+     \end{figure}
+     Note that the above figure was included using dvips.
+     \end{document}
+
+   If the above LaTeX code is contained in a file called `mytext.tex'
+you can use the commands
+
+     latex mytext
+     dvips mytext.dvi >mytext.ps
+     lpr -Plw mytext.ps
+
+   to format and print the example text.
+
+
+File: graphics.info,  Node: psfig,  Next: atend.pl,  Prev: latex example,  Up: Top
+
+Options to `psfig' for Including Figures
+========================================
+
+   `psfig' is a LaTeX command used to insert a PostScript figure into a
+document.
+
+   `psfig' can be used to insert `plot2ps' generated PostScript into a
+LaTeX document.  The placement of the `psfig' command tells LaTeX where
+in the document to place the PostScript, and arguments to the command
+give the name of the file containing the PostScript, and the desired
+size of the figure.  Arguments are separated by commas or blanks, and
+are of the form `KEYWORD=VALUE'.  The following is a list of valid
+arguments for the `psfig' command:
+
+`file=NAME'
+     The file name of the PostScript figure.
+
+`height=SIZE'
+     The height of the figure (eg. 3in).  If you specify only a height
+     or only a width, the width and height are scaled equally.  If you
+     specify both a width and a height the aspect ratio will be
+     affected.
+
+`width=SIZE'
+     The width of the figure (eg. 3in).
+
+`bbllx=COORDINATE'
+     The bounding box lower left-hand x coordinate.  Any PostScript file
+     which conforms to the PostScript Document Structuring Conventions
+     version 2.0 should contain a bounding box information at the head
+     of the file.  `plot2ps' output conforms to the version 2.0
+     conventions so that you should not need to use any of the bounding
+     box options.
+
+`bblly=COORDINATE'
+     The bounding box lower left-hand y coordinate.
+
+`bburx=COORDINATE'
+     The bounding box upper right-hand x coordinate.
+
+`bbury=COORDINATE'
+     The bounding box upper right-hand y coordinate.
+
+`rheight=SIZE'
+     Horizontal space to reserve for the figure.
+
+`rwidth=SIZE'
+     Vertical space to reserve for the figure.
+
+`clip='
+     Clip the figure.  `clip=' is a switch and takes no value, but the
+     `=' must be present.  This option is useful for including
+     PostScript figures which use the size of the clipping path to size
+     themselves.
+
+
+File: graphics.info,  Node: atend.pl,  Next: dvips,  Prev: psfig,  Up: Top
+
+A perl script for use with psfig
+================================
+
+   `atend.pl' is a perl script which moves the bounding box comment
+from the trailer to the header.  Although either is legal, most document
+preparation software, such as `psfig', will only accept bounding box
+comments in the header.  If you use `psfig' and the `-bbox' option
+togeather, run `atend.pl' on the output of `plot2ps' before importing
+the graphics using `psfig'.
+
+   `atend.pl' can be used as a filter:
+
+     echo 0 0 1 1 2 0 | spline | graph >spline.pl
+     plot2ps -bbox |atend.pl - >spline.ps
+
+   Or, `atend.pl' can be used to fix the output file in place:
+
+     echo 0 0 1 1 2 0 | spline | graph |plot2ps -bbox >spline.ps
+     atend.pl spline.ps
+
+
+File: graphics.info,  Node: dvips,  Next: idraw,  Prev: atend.pl,  Up: Top
+
+How to Get `dvips'
+==================
+
+   The `dvips' utility mentioned previously is used convert dvi files
+generated by LaTeX into post-script.  It also has support for inclusion
+of PostScript figures into LaTeX documents.  It is available via
+anonymous ftp from `labrea.stanford.edu' (36.8.0.47).  Look for
+`pub/dvips.tar.Z'.
+
+
+File: graphics.info,  Node: idraw,  Next: ghostscript,  Prev: dvips,  Up: Top
+
+How to Get `idraw'
+==================
+
+   The `idraw' utility mentioned previously is an interactive graphics
+editor which is distributed with InterViews.  InterViews is available
+via anonymous ftp from `interviews.stanford.edu' (36.22.0.175) in the
+file `InterViews/2.5.tar.Z'.
+
+
+File: graphics.info,  Node: ghostscript,  Next: libps,  Prev: idraw,  Up: Top
+
+How to Get `ghostscript'
+========================
+
+   Ghostscript is a previewer which is intended to be compatible with
+the PostScript language.  It supports several output devices including
+the X window system and ega displays.  Version 2.0 is suitable for
+previewing LaTeX documents with imbedded encapsulated PostScript
+figures, the type of PostScript figures generated by plot2ps and idraw.
+It is available via anonymous ftp from `prep.ai.mit.edu' (18.71.0.38)
+- Look for `pub/gnu/ghostscript.tar.Z'.
+
+
+File: graphics.info,  Node: libps,  Next: files,  Prev: ghostscript,  Up: Top
+
+`libps', a Library of Plot Functions
+====================================
+
+   Libps is a library of plot functions for drawing graphic object
+using PostScript.  Before drawing any objects or using any of the other
+functions, a program should call `openpl'.  Before exiting and after
+all other libps calls a program should call `closepl'.
+
+* Menu:
+
+The standard plot library includes:
+
+* arc::          draw an arc
+* circle::       draw a circle
+* closepl::      close the device for output
+* cont::	 continue a line
+* erase::        erase the page
+* label::        print a label
+* line::         draw a line
+* linemod::      change the line mode (style)
+* move::         move to a new coordinate
+* openpl::       open the device for output
+* point::        draw a point
+* space::        define the user's plot space (size)
+
+The extensions provided only in libps to take advantage of PostScript
+features include:
+
+* alabel::       print a vertically or horizontally justified label
+* color::        change the color
+* fill::         fill pattern for closed paths
+* fontname::     set the font name
+* fontsize::     set the font size
+* rotate::       rotate subsequent text
+
+
+File: graphics.info,  Node: alabel,  Next: arc,  Up: libps
+
+`alabel'
+--------
+
+   int `alabel' (char X_JUSTIFY, char Y_JUSTIFY, char *LABEL);
+
+   `alabel' takes three arguments X_JUSTIFY, Y_JUSTIFY, and LABEL and
+places the label according to the x and y axis adjustments specified in
+X_JUSTIFY and Y_JUSTIFY respectively.  X_JUSTIFY is a character
+containing either `l', `c', or `r' for left, center or right justified
+with respect to the current x coordinate.  Y_JUSTIFY is a character
+containing either `b', `c', or `t' for placing the bottom center or top
+of the label even with the current y coordinate.  *LABEL is a string
+containing the label.  The current point is moved to follow the end of
+the text.
+
+   *Note fontname:: on how to change the default font.  *Note
+fontsize:: on how to change the font size.
+
+
+File: graphics.info,  Node: arc,  Next: circle,  Prev: alabel,  Up: libps
+
+`arc'
+-----
+
+   int `arc' (int X, int Y, int X0, int Y0, int X1, int Y1)
+
+   `arc' takes six integer arguments specifying the coordinates of the
+center (X, Y), beginning (X0, Y0), and ending (X1, Y1) of a circular
+arc.  The current point becomes (X, Y).
+
+
+File: graphics.info,  Node: circle,  Next: closepl,  Prev: arc,  Up: libps
+
+`circle'
+--------
+
+   int `circle' (int X, int Y, int R)
+
+   `circle' takes three integer arguments specifying the center (X, Y)
+of the circle and its radius (R).  The current point becomes (X, Y).
+
+
+File: graphics.info,  Node: closepl,  Next: color,  Prev: circle,  Up: libps
+
+`closepl'
+---------
+
+   int `closepl' ()
+
+   `closepl' takes no arguments.  It merely outputs the PostScript
+trailer containing a `showpage' command.
+
+
+File: graphics.info,  Node: color,  Next: cont,  Prev: closepl,  Up: libps
+
+`color'
+-------
+
+   int `color' (int RED, int GREEN, int BLUE);
+
+   `color' sets the foreground color of all the following objects.  The
+arguments RED, GREEN and BLUE indicate the intensity of red, green and
+blue components of the foreground color respectively.  Each is a
+unsigned integer specifying an intensity in the range from 0 to 0xFFFF.
+A value of (0, 0, 0) represents black and a value of (0xFFFF, 0xFFFF,
+0xFFFF) indicates white.
+
+
+File: graphics.info,  Node: cont,  Next: erase,  Prev: color,  Up: libps
+
+`cont'
+------
+
+   int `cont' (int X, int Y)
+
+   `cont' takes two integer arguments specifying the coordinate (X, Y)
+for the continuation of a line.  This draws a line segment from the
+current point to the point (X, Y).  The current point then becomes (X,
+Y).
+
+
+File: graphics.info,  Node: erase,  Next: fill,  Prev: cont,  Up: libps
+
+`erase'
+-------
+
+   int `erase' ()
+
+   `erase' normally erases all the graphics from the display before a
+plot is viewed.  Since we start off with a blank page in PostScript and
+`idraw' this function does nothing.
+
+
+File: graphics.info,  Node: fill,  Next: fontname,  Prev: erase,  Up: libps
+
+`fill'
+------
+
+   int `fill' (int LEVEL);
+
+   `fill' sets the intensity of the filler for closed paths.  The
+argument LEVEL indicates the grey level of the fill pattern.  It's
+value ranges from 1 to 0xFFFF.  A value of 1 represents black and a
+value of 0xFFFF indicates white.  A value of 0 represents no fill, or
+transparent.
+
+
+File: graphics.info,  Node: fontname,  Next: fontsize,  Prev: fill,  Up: libps
+
+`fontname'
+----------
+
+   int `fontname' (char *FONT_NAME);
+
+   `fontname' takes a single string argument, FONT_NAME, specifying the
+name of the font to be used for following text.  The laser writer
+builtin fonts are supported:
+
+             courier-bold
+             courier-boldoblique
+             courier-oblique
+             courier
+             helvetica-bold
+             helvetica-boldoblique
+             helvetica-oblique
+             helvetica
+             symbol
+             times-bold
+             times-bolditalic
+             times-italic
+             times-roman
+
+
+File: graphics.info,  Node: fontsize,  Next: label,  Prev: fontname,  Up: libps
+
+`fontsize'
+----------
+
+   int `fontsize' (int SIZE);
+
+   `fontsize' takes a single integer argument SIZE in printer's points
+(1/72 inch) and sets the font size accordingly.
+
+
+File: graphics.info,  Node: label,  Next: line,  Prev: fontsize,  Up: libps
+
+`label'
+-------
+
+   int `label' (char *S)
+
+   `label' takes a single string argument S and draws the text
+contained in S at the most recently used coordinate in the current
+font.  By default the text is left justified and centered vertically
+with respect to the current coordinate.
+
+
+File: graphics.info,  Node: line,  Next: linemod,  Prev: label,  Up: libps
+
+`line'
+------
+
+   int `line' (int X1, int y1, int X2, int Y2)
+
+   `line' takes four integer arguments specifying the beginning (X1,
+Y1) and ending (X2, Y2) points of a line.  The current point becomes
+(X2, Y2).
+
+   *Note linemod:: for how to specify the style or pattern of line.
+
+
+File: graphics.info,  Node: linemod,  Next: move,  Prev: line,  Up: libps
+
+`linemod'
+---------
+
+   int `linemod' (char *S)
+
+   `linemod' takes a single string argument S containing the name of
+the line style desired.  The names supported are longdashed,
+disconnected, dotdashed, dotted, solid and shortdashed.  These
+correspond to the following sixteen bit patterns:
+
+     solid             --------------------------------
+     longdashed        -------         -------
+     disconnected      -               -
+     dotdashed         -----------  -  -----------  -
+     dotted            - - - - - - - - - - - - - - - -
+     shortdashed       --              --
+
+
+File: graphics.info,  Node: move,  Next: openpl,  Prev: linemod,  Up: libps
+
+`move'
+------
+
+   int `move' (int X, int Y)
+
+   `move' takes two integer arguments specifying the coordinate (X, Y)
+for the beginning of a new line.  This is equivalent to lifting the pen
+on a plotter and moving it to a new position without drawing any line.
+The current point becomes (X, Y).
+
+
+File: graphics.info,  Node: openpl,  Next: point,  Prev: move,  Up: libps
+
+`openpl'
+--------
+
+   int `openpl' ()
+
+   `openpl' normally opens the device.  For PostScript we just print
+out the PostScript prologue.  The following global variables defined in
+`openpl' specify what prologue is written to the output.
+
+   USER_HAS_PROLOGUE is a flag.  If it is non-zero then the open
+routine should output the user specified prologue contained in the file
+specified in the string USERS_PROLOGUE.
+
+   USERS_PROLOGUE is a string containing the file name for any user
+specified PostScript prologue.  This file is a substitute for the
+default prologue.
+
+
+File: graphics.info,  Node: point,  Next: rotate,  Prev: openpl,  Up: libps
+
+`point'
+-------
+
+   int `point' (int X, int Y)
+
+   `point' takes a pair of integer arguments specifying the coordinate
+(X, Y) for a single point.  The current point then becomes (X, Y).
+
+
+File: graphics.info,  Node: rotate,  Next: space,  Prev: point,  Up: libps
+
+`rotate'
+--------
+
+   int `rotate' (int ANGLE);
+
+   `rotate' takes three integer arguments.  The last argument, ANGLE,
+specifies the angle in degrees counter-clockwise from the x
+(horizontal) axis following text.
+
+
+File: graphics.info,  Node: space,  Prev: rotate,  Up: libps
+
+`space'
+-------
+
+   int `space' (int X0, int Y0, int X1, int Y1)
+
+   `space' takes two pair of integers arguments specifying the lower,
+left-hand and upper, right-hand limits of the range of plot
+coordinates.  The scaling of input to output coordinate conversion is
+adjusted to fit these ranges into the page.  Note however that if the
+ranges of x and y coordinates are different the smallest scaling of the
+two is used to avoid affecting the aspect ratio of the plot.  This
+means that although the plot is scaled to fit on the page, the axes are
+not stretched with respect to each other.
+
+
+File: graphics.info,  Node: files,  Next: Acknowledgements,  Prev: libps,  Up: Top
+
+The Plot File Format
+====================
+
+   The plot file is a set of plotting commands and data.  Each command
+is a single ascii character indicating which operation is to be
+performed.  The data following a command is either a newline terminated
+ascii string or several signed, two byte integers in binary format.
+For example, the command to move the current point to the coordinate
+(3,5) would be `m\000\003\000\005'.
+
+   Note that the byte order of the binary representation of the signed,
+two byte integers is machine dependent, so on some machines, this
+command might appear as `m\003\000\005\000'.  `plot2ps' tries to guess
+the byte order from the arguments to the `openpl' command and adjust
+the order accordingly.
+
+   The following table lists each single character commands followed by
+the name of the corresponding libps function called to handle the data
+and a description of the command and data.
+
+`Command'
+     Description
+
+`a'
+     The arc command is followed by three pair of signed, two byte
+     integers indicating the center, starting and ending points for a
+     circular arc.  The center becomes the the current point.  This is
+     equivalent to the `arc' function (*note arc::.).
+
+`c'
+     The circle command is followed by three signed, two byte integers.
+     The first two indicate the x and y coordinates of the center of
+     the circle and the third indicates the radius of the circle.  The
+     center becomes the the current point.  This is equivalent to the
+     `circle' function (*note circle::.).
+
+`C'
+     The color command is followed by three unsigned, two byte integer
+     which indicate the intensity of RED, GREEN and BLUE components
+     respectively of the background color.  For each component the
+     range of intensity is from 0 to 65535.  A value of (0, 0, 0)
+     represents black and (65535, 65535, 65535) represents white. This
+     is equivalent to the `color' function (*note color::.).
+
+`e'
+     The erase command is followed by no data.  The erase command is not
+     needed since in `idraw' and PostScript we start off with a blank
+     page.  For this reason the erase command does not actually output
+     any PostScript. This is equivalent to the `erase' function (*note
+     erase::.).
+
+`f'
+     The linemod command is followed by a newline terminated string
+     containing the name of the line mode (or style) for all subsequent
+     lines, circles and arcs. This is equivalent to the `linemod'
+     function (*note linemod::.) which describes the line styles and
+     their names.
+
+`F'
+     The the fontname command is followed by a newline terminated string
+     containing the name of the font to be used for all subsequent
+     text. This is equivalent to the `fontname' function (*note
+     fontname::.).
+
+`l'
+     The line command is followed by two pair of signed, two byte
+     integers which indicate the starting and ending points of the
+     line.  The second pair becomes the the current point. This is
+     equivalent to the `line' function (*note line::.).
+
+`L'
+     The fill command is followed by an unsigned, two byte integer
+     indicating the intensity of the fill for closed paths.  A value of
+     1 represents black and a value of 0xFFFF indicates white.  The
+     value 0 is special in that is indicates that no solid fill should
+     occur, and that the interior of the respective path is
+     transparent. This is equivalent to the `fill' function (*note
+     fill::.).
+
+`m'
+     The move command is followed by a pair of signed, two byte integers
+     containing the location of the new current point.  No line is
+     drawn to this point as opposed to the continue command (`c') which
+     draws a line.  This is equivalent to the `move' function (*note
+     move::.).
+
+`n'
+     The continue command is followed by pair of signed, two byte
+     integers containing the coordinates of the endpoint of a line
+     segment.  A line is drawn from the previous current point if it
+     was set using a command such as move or continue.  This then
+     becomes the the current point. This is equivalent to the `cont'
+     function (*note cont::.).
+
+`p'
+     The point command is followed by pair of signed, two byte integers
+     containing the location of single point to be drawn.  This then
+     becomes the the current point. This is equivalent to the `point'
+     function (*note point::.).
+
+`r'
+     The rotate command is followed by one signed, two byte integer.  It
+     indicates the rotation of all subsequent text.  The rotation is in
+     degrees counter-clockwise from the x (horizontal) axis. This is
+     equivalent to the `rotate' function (*note rotate::.).
+
+`s'
+     The space command is followed by two pair of signed, two byte
+     integers which indicate the the lower right-hand and upper
+     left-hand corners of the range of plot coordinate space.
+     `plot2ps' uses the third signed, two byte integer (the right-hand
+     limit) to try to determine the byte order. This is equivalent to
+     the `space' function (*note space::.) which describes the
+     recognized sizes.
+
+`S'
+     The fontsize command is followed by an signed, two byte integer
+     containing the size in printers points of all subsequent text.
+     This is equivalent to the `fontsize' function (*note fontsize::.).
+
+`t'
+     The label command is followed by a newline terminated string
+     contains a label which is printed at the current point.  It is
+     left justified and centered vertically with respect to the current
+     point.  The current point is then set at the end of the text. This
+     is equivalent to the `label' function (*note label::.).
+
+`T'
+     The adjusted label command is followed by two characters which
+     indicate the horizontal and vertical justification respectively
+     and a newline terminated string containing the label.  The label
+     is drawn with the specified justification and the current point is
+     set at the end of the text.  This is equivalent to the `alabel'
+     function (*note alabel::.) which describes how to specify
+     justification.
+
+
+File: graphics.info,  Node: Acknowledgements,  Next: Function Index,  Prev: files,  Up: Top
+
+Acknowledgements
+================
+
+   Rich Murphey <Rich@Rice.edu> wrote the first version of the graph,
+plot2tek, plot2ps and tek2plot and the documentation.  Richard Stallman
+<Rms@ai.mit.edu> further directed development of the programs and
+editorial support for the documentation.  John Interrante generously
+provided the PostScript prologue and helpful comments on the program.
+
+   Arthur Smith (Lassp, Cornell University)
+<arthur@helios.tn.cornell.edu> has generously provided his code for the
+xplot utility.
+
+   Ray Toy <toy@dino.ecse.rpi.edu> provided code for graph and tek 4011
+and rewrote the tick mark spacing code, incorporated gnu getopt and
+provided the statistics package.
+
+   David B. Rosen <rosen@bu.edu>, jeffrey templon
+<templon@copper.ucs.indiana.edu> and David W. Forslund
+<dwf%hope.ACL@lanl.gov> tested alpha versions.
+
+
+File: graphics.info,  Node: Function Index,  Prev: Acknowledgements,  Up: Top
+
+Function Index
+==============
+
+* Menu:
+
+* alabel (char X_JUSTIFY, char Y_JUSTIFY, char *LABEL): alabel.
+* arc (int X, int Y, int X0, int Y0, int X1, int Y1): arc.
+* circle (int X, int Y, int R):         circle.
+* closepl ():                           closepl.
+* color (int RED, int GREEN, int BLUE): color.
+* cont (int X, int Y):                  cont.
+* erase():                              erase.
+* fill (int LEVEL):                     fill.
+* fontname (char *FONT_NAME):           fontname.
+* fontsize (int SIZE):                  fontsize.
+* label (char *S):                      label.
+* linemod (char *S):                    linemod.
+* line (int X1, int y1, int X2, int Y2): line.
+* move (int X, int Y):                  move.
+* openpl():                             openpl.
+* point (int X, int Y):                 point.
+* rotate (int W, int H, int ANGLE):     rotate.
+* space (int X0, int Y0, int X1, int Y1): space.
+
+
+
+Tag Table:
+Node: Top187
+Node: introduction1407
+Node: graph examples3457
+Node: Invocation4024
+Node: Input Files5739
+Node: Overlaying7374
+Node: Multiple Plots9252
+Node: Binary Data10198
+Node: graph invocation11307
+Node: plot2ps examples18376
+Node: plot2ps invocation18914
+Node: xplot24137
+Node: xplot invocation24803
+Node: Plot2fig Examples26556
+Node: plot2fig invocation27374
+Node: plot2tek invocation29619
+Node: latex example32322
+Node: psfig33301
+Node: atend.pl35322
+Node: dvips36130
+Node: idraw36538
+Node: ghostscript36899
+Node: libps37487
+Node: alabel38741
+Node: arc39560
+Node: circle39892
+Node: closepl40169
+Node: color40400
+Node: cont40919
+Node: erase41255
+Node: fill41545
+Node: fontname41952
+Node: fontsize42615
+Node: label42872
+Node: line43234
+Node: linemod43593
+Node: move44259
+Node: openpl44632
+Node: point45278
+Node: rotate45544
+Node: space45836
+Node: files46490
+Node: Acknowledgements52660
+Node: Function Index53597
+
+End Tag Table
Index: /branches/eam_branch_20080223/Ohana/doc/keywords.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/keywords.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/keywords.txt	(revision 16632)
@@ -0,0 +1,129 @@
+
+here are keywords used in Elixir:
+
+Elixir defined keywords:
+(detrend dB)
+TVSTART
+TVSTOP
+FILTER
+EXPTIME
+OBSTYPE
+NENTRY - values in dB
+
+(phot dB)
+NIMAGES 
+
+(imregister / iminfo)
+EXPTIME-KEYWORD   : ExptimeKeyword   : EXPTIME : Exposure time
+IMAGETYPE-KEYWORD : ImagetypeKeyword : OBSTYPE / EXPTYPE : Image type (DARK, OBJECT, etc)
+CCDNUM-KEYWORD    : CCDnumKeyword    : IMAGEID : CCD number
+FILTER-KEYWORD    : FilterKeyword    : FILTER  : filter name
+AIRMASS-KEYWORD   : AirmassKeyword   : AIRMASS : airmass
+FOCUS-KEYWORD     : FocusKeyword     : TELFOCUS: telescope focus setting
+ROTATION-KEYWORD  : RotationKeyword  : ROTANGLE: rotation angle
+DETTEMP-KEYWORD   : DettempKeyword   : DETTEM  : detector temperature
+TELDATA1-KEYWORD  : Teldata1Keyword  : XPROBE  : bonnette probe x position
+TELDATA2-KEYWORD  : Teldata2Keyword  : YPROBE  : bonnette probe y position
+TELDATA3-KEYWORD  : Teldata3Keyword  : ZPROBE  : bonnette focus
+RA-DDD-KEYWORD    : RADecDegKeyword  : CRVAL1  : RA in dec. degrees
+DEC-DDD-KEYWORD   : DECDecDegKeyword : CRVAL2  : DEC in dec. degrees
+RA-HMS-KEYWORD    : RASexigKeyword   : CRVAL1  : RA in hour,min,sec
+DEC-DMS-KEYWORD   : DECSexigKeyword  : CRVAL2  : DEC in dec,min,sec
+CAMERA-KEYWORD    : CameraKeyword    : INSTRUME: unique name of camera
+
+(time keywords already abstracted)
+DATE-KEYWORD	  : DateKeyword	     : DATE-OBS   : date
+DATE-MODE	  : DateMode	     : yyyy-mm-dd : format for DATE-KEYWORD
+UT-KEYWORD	  : UTKeyword	     : UTC-OBS	  : UT
+JD-KEYWORD	  : JDKeyword	     : NONE	  : JD
+MJD-KEYWORD	  : MJDKeyword	     : NONE	  : MJD
+
+(photcode)
+CAMERA-KEYWORD    : CameraKeyword    : DETECTOR: unique name of camera
+FILTER-KEYWORD    : FilterKeyword    : FILTER  : filter name
+CCDNUM-KEYWORD    : CCDnumKeyword    : IMAGEID : CCD number
+
+
+EXTEND  : extensions present (FITS required keyword for MEF)
+NEXTEND : extension number (not necessarily IMAGEID)
+
+(gophot)
+SATVALUE: saturation value for this image
+GAIN    : gain (e/DN) for this image
+NEWGAIN : a stupid name for an altered gain.
+RDNOISE : read noise (in electrons) ***
+DNNOISE : read noise (in DN)        ***
+
+(gastro / coordops in ohana)
+WCS keywords (these do not need to be abstracted)
+CD1_1
+CD1_2
+CD2_1
+CD2_2
+CDELT1
+CDELT2
+CROTA2
+CRPIX1
+CRPIX2
+CRVAL1
+CRVAL2
+CTYPE2
+NPLYTERM
+PC001001
+PC001002
+PC002001
+PC002002
+PCA1X0Y2
+PCA1X0Y3
+PCA1X1Y1
+PCA1X1Y2
+PCA1X2Y0
+PCA1X2Y1
+PCA1X3Y0
+PCA2X0Y2
+PCA2X0Y3
+PCA2X1Y1
+PCA2X1Y2
+PCA2X2Y0
+PCA2X2Y1
+PCA2X3Y0
+DEC_O
+DEC_X
+DEC_Y
+RA_O
+RA_X
+RA_Y
+EPOCH
+EQUINOX
+
+NAXIS1  : FITS mandatory keyword
+NAXIS2  : FITS mandatory keyword
+RA	: RA in sexigesimal (for rough astrometry)
+DEC	: DEC in sexigesimal (for rough astrometry)
+NSTARS  : elixir-added keyword (number of stars, from imclean)
+
+EXPTIME
+AIRMASS 
+IMAGEID
+
+ZERO_PT : Elixir-added keyword (imclean)
+NASTRO  : Elixir-added keyword (imclean)
+CERROR  : Elixir-added keyword (gastro)
+PHOTCODE: Elixir-added keyword (imclean)
+APMIFIT : Elixir-added keyword (imclean)
+dAPMIFIT: Elixir-added keyword (imclean)
+FLIMIT  : Elixir-added keyword (imclean)
+FSATUR  : Elixir-added keyword (imclean)
+FWHM_X  : Elixir-added keyword (imclean)
+FWHM_Y  : Elixir-added keyword (imclean)
+TZERO   : Elixir-added keyword (imclean)
+TRATE   : Elixir-added keyword (imclean)
+NSTARS  : Elixir-added keyword (imclean)
+
+NIMAGES : (Elixir keyword for phot db)
+
+parse_time.c:    fits_scan (header, JDKeyword, "%lf", 1, &jd);
+parse_time.c:    fits_scan (header, MJDKeyword, "%lf", 1, &jd);
+parse_time.c:  fits_scan (header, UTKeyword, "%s", 1, line);
+parse_time.c:  fits_scan (header, DateKeyword, "%s",  1, line);
+wimage.c:  fits_scan (&header, "NIMAGES", "%d", 1, &Nimages);
Index: /branches/eam_branch_20080223/Ohana/doc/locks.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/locks.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/locks.txt	(revision 16632)
@@ -0,0 +1,70 @@
+
+NFS locks & file locks in ohana / elixir
+
+There are three types of locks in use in the elixir system:
+
+SOFT, XCLD, HARD
+
+SOFT - a soft lock on a file prevents a xcld or hard lock on that
+       file,  but allows other soft locks to be set.  the soft lock
+       uses NFS locking and is ephmeral, vanishing if the holding
+       program ends, whether or not the program explicitly removes the
+       lock. 
+
+XCLD - an xcld lock on a file prevents all other locks: soft, xcld, or
+       hard; only one xcld lock may be active on a file at a time.
+       The xcld lock uses NFS locking is ephemeral, vanisihing when
+       the program exits.
+
+HARD - a hard lock on a file prevents all other locks: soft, xcld, or
+       hard; only one hard lock may be active on a file at a time.
+       The hard lock is sticky and will remain unless the program
+       actively removes the lock.  It is implemented by first setting
+       an XCLD lock in NFS and then creating a lock file (.file.lck)
+       which contains the work BUSY.  until this file is removed or
+       the contents changed, the lock remains.
+
+basic lock APIs:
+
+int setlockfile2 (char *filename, double timeout, int type, int *state)
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state)
+
+setlockfile2 sets a lock of the requested type on the given file,
+  returning an open file descriptor to the file.  If the requested
+  lock is SOFT and the file does not exist, setlockfile2 returns -1
+  and sets the state to  LCK_EMPTY - the lock is not set.  In the case
+  of XCLD or HARD locks, if the file does not exist, it is created.
+  If the lock cannot be set immediately, setlockfile2 will block for
+  up to 'timeout' seconds, at which point it will return -1 and exit
+  with state LCK_TIMEOUT.  
+
+fsetlockfile behaves identically to setlockfile2, but generates and
+returns a stream associated with the open file descriptor.  An error
+will result in the return of (FILE *) NULL.
+
+int clearlockfile2 (char *filename, int fd, int type, int *state)
+int fclearlockfile (char *filename, FILE *f, int type, int *state)
+
+clearlockfile2 clears the lock associated with a file and file
+descriptor.  If the type is HARD, it will clear the associated hard
+lock file before removing the NFS level file lock.  If only the
+filename is passed to clearlockfile2, the NFS-level locks cannot be
+unset, but the hardlock will be unset.  this is useful if a program is
+known to then exit.
+
+fclearlockfile behaves identically to setlockfile2, but requires the
+associated stream, rather than the file descriptor.  
+
+
+-----
+
+
+int lock_catalog (Catalog *catalog, int lockmode)
+
+lock_catalog attempts to set a lock on the specified photometry
+catalog file.  If successful, the catalog file pointer is set to the
+beginning of the catalog and the function returns the value 1.  If the
+file is empty, the return value is 2.  This only indicates an error if
+the file pointer is NULL, which occurs if the requested locktype is
+SOFT. 
+
Index: /branches/eam_branch_20080223/Ohana/doc/ohana-cvs.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/ohana-cvs.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/ohana-cvs.txt	(revision 16632)
@@ -0,0 +1,105 @@
+
+The goal is to have two source trees: a development tree in your own
+private location and an official release tree, which contains the
+production version of the code.  In practice, you never edit the
+production version of the code: it is essentially read-only.  you just
+compile that tree and install it wherever the main-line production
+sources go (eg, /apps/elixir/bin).  New releases of the elixir code
+are done by replacing that tree with a new tree extracted from a
+released tarball.
+
+Start by creating you own CVS checkouts of the elixir ohana and config
+source tree.  this can be in your home directory, if you like, or
+where ever.  now check out the complete ohana and config cvs trees:
+
+- make sure you have CVSROOT set:
+
+setenv CVSROOT jcc@naupaka:/data/elixir2/srcdir/cvs
+
+- check out ohana:
+
+cvs co ohana
+
+- check out config:
+
+cvs co config
+
+now you should compile ohana.  I think you have the ARCH variable
+being setup correctly in your environment.  in this case, you can
+configure ohana to recognize that variable and allow for multiplatform
+compilation:
+
+- go into ohana, run configure, make, make install:
+
+cd ohana
+configure --vararch
+(note the last line of the configure output: it tells you how to set
+your path)
+
+make
+make install
+
+The compilation should run to the end without any trouble.  if you
+have any errors, you should let me know so we can fix them.
+
+You should adjust your path to point at the new installation of
+ohana.  when you ran configure, it told you how to set your path.
+if your path is set correctly, you should see the new versions of the
+elixir programs.
+
+Next, you should setup the elixir config data.  go into the config
+directory which you checked out and copy elixir.site.in to
+elixir.site.  Edit this file to reflect the local (CFHT) elixir data
+locations (the settings in this file are probably already correct for
+CFHT).  
+
+at this point, you should be able to run the elixir programs as jcc
+using this new copy and interacting with the standard CFHT elixir
+data.
+
+Now, let's create a production distribution tarball.  To do this, go
+into ohana/etc and run the distribution creation tool:
+
+- mkdist elixir-ohana 1.1
+
+This will create a new tarball for you containing all of the elixir
+ohana components based on the correct tagged versions of the software
+in the repository.  No matter what code changes you make and commit to
+CVS, when you run this command in the future you will get this
+specific snapshot of the elixir ohana software. 
+
+Install this new tarball in the production location:
+
+- cd /data/elixir2/srcdir
+- mv ohana ohana-preCVS
+- tar xvzf (PATH to tarball elixir-ohana-1.1.tgz)
+- ln -s elixir-ohana-1.1 ohana
+
+Compile the new ohana distribution:
+
+- cd ohana
+- configure --vararch
+- make install
+
+This last step will compile it in the local ohana path. At this point,
+from the viewpoint of the rest of Elixir, everything looks the same as
+it does before we started this process.  You can now go into
+/data/elixir2/srcdir and run the make install-test and make install
+just as you have in the past to install updates to the ohana software.
+
+Same process for the config system.  go back to your checked-out copy
+of ohana.  run 'mkdist elixir-config 1.1'.  go to
+/data/elixir2/srcdir.  save the old version of config
+(config-preCVS).  extract the tarball: ' tar xvzf (PATH to
+elixir-config-1.1.tgz)'.  link the config system to the old name: 'ln
+-s elixir-config-1.1 config'  copy config/elixir.site.in to
+config/elixir.site.  edit to match the existing site.  install in
+/apps/elixir/config (cd /data/elixir2/srcdir; make install).
+
+ 
+--
+
+some useful tricks:
+
+ cvs rdiff -s -r TAG MODULE
+ mkdist -diff GROUP VERSION
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/elixir.fig
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/elixir.fig	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/elixir.fig	(revision 16632)
@@ -0,0 +1,76 @@
+#FIG 3.2
+Portrait
+Center
+Inches
+Letter 
+90.00
+Single
+-2
+1200 2
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 5175 3000 1650 975 5175 3000 6825 3975
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 8400 10575 1350 825 8400 10575 9750 11400
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 2475 10650 1350 825 2475 10650 3825 11475
+2 4 0 1 0 7 0 0 20 0.000 0 0 7 0 0 5
+	 8400 8700 6600 8700 6600 6375 8400 6375 8400 8700
+2 4 0 1 0 7 2 0 20 0.000 0 0 7 0 0 5
+	 9450 8250 7650 8250 7650 5925 9450 5925 9450 8250
+2 4 0 1 0 7 0 0 20 0.000 0 0 7 0 0 5
+	 7425 9150 5625 9150 5625 6825 7425 6825 7425 9150
+2 4 0 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 3300 9150 3300 6825 1500 6825 1500 9150 3300 9150
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 1
+	 5850 3900
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 6225 3750 7950 5925
+2 1 0 1 0 7 20 0 -1 0.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 4275 3900 2400 6825
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 1 2
+	1 0 1.00 60.00 120.00
+	1 0 1.00 60.00 120.00
+	 2475 9150 2475 9825
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 7350 9150 7875 9825
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 9150 8250 8475 9750
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 7950 8700 8175 9750
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 3300 9975 5625 8325
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 7050 10500 3300 8325
+2 2 0 1 7 7 1 0 20 0.000 0 0 -1 0 0 5
+	 2925 4875 4275 4875 4275 5625 2925 5625 2925 4875
+2 1 0 1 0 7 1 0 -1 0.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 5550 3975 6000 6825
+2 1 0 1 0 7 2 0 -1 0.000 0 0 -1 1 0 2
+	1 0 1.00 60.00 120.00
+	 5850 3900 6975 6375
+2 2 0 1 7 7 1 0 20 0.000 0 0 -1 0 0 5
+	 5775 4575 7125 4575 7125 5400 5775 5400 5775 4575
+4 0 0 0 0 0 36 0.0000 4 375 8385 1200 1500 Elixir: Calibration and Data Evaluation\001
+4 0 0 0 0 0 18 0.0000 4 255 915 5850 7425 Ptolemy\001
+4 0 0 0 0 0 18 0.0000 4 195 465 5850 8175 data\001
+4 0 0 0 0 0 18 0.0000 4 195 1155 5850 8550 evaluation\001
+4 0 0 0 0 0 18 0.0000 4 195 720 1650 7425 FLIPS\001
+4 0 0 0 0 0 18 0.0000 4 255 1320 7650 10350 Photometry\001
+4 0 0 0 0 0 18 0.0000 4 255 1320 7725 10875 Astrometry\001
+4 0 0 0 0 0 18 0.0000 4 195 1260 1800 10425 Calibration\001
+4 0 0 0 0 0 18 0.0000 4 255 780 2025 10875 Images\001
+4 0 0 0 0 0 18 0.0000 4 225 720 4800 3075 and/or\001
+4 0 0 0 0 0 18 0.0000 4 255 1110 3975 2625 Telescope\001
+4 0 0 0 0 0 18 0.0000 4 195 930 5325 3525 Archive\001
+4 0 0 0 0 0 18 0.0000 4 195 1185 1650 8550 creation &\001
+4 0 0 0 0 0 18 0.0000 4 195 1155 1650 8865 evaluation\001
+4 0 0 0 0 0 18 0.0000 4 195 1200 1650 8175 calibration\001
+4 0 0 0 0 0 18 0.0000 4 255 765 6225 5250 images\001
+4 0 0 0 0 0 18 0.0000 4 255 765 3225 5475 images\001
+4 0 0 0 0 0 18 0.0000 4 195 1200 3000 5175 calibration\001
+4 0 0 0 0 0 18 0.0000 4 195 870 6000 4875 science \001
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/flags.fig
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/flags.fig	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/flags.fig	(revision 16632)
@@ -0,0 +1,29 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 3
+	 2400 975 4050 975 4050 4125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 3
+	 6525 1425 7650 1425 7650 4200
+4 0 0 0 0 2 14 0.0000 4 195 1695 600 975 Bit 15: ID_Moving\001
+4 0 0 0 0 2 14 0.0000 4 180 1590 600 1425 Bit 14: ID_USNO\001
+4 0 0 0 0 2 14 0.0000 4 195 2085 4275 1425 Bit 14: ID_Bad_Object\001
+4 0 0 0 0 2 14 0.0000 4 195 1695 7875 1875 Lower Byte Values\001
+4 0 0 0 0 2 14 0.0000 4 150 1095 8025 2325 0x01: Ghost\001
+4 0 0 0 0 2 14 0.0000 4 150 1005 8025 2625 0x02: Trail\001
+4 0 0 0 0 2 14 0.0000 4 150 1050 8025 2925 0x03: Bleed\001
+4 0 0 0 0 2 14 0.0000 4 180 1785 600 1875 Bit 13: ID_Variable\001
+4 0 0 0 0 2 14 0.0000 4 180 1875 600 2325 Bit 12: ID_Transient\001
+4 0 0 0 0 2 14 0.0000 4 180 1905 600 2775 Bit 11: ID_Bad_Data\001
+4 0 0 0 0 2 14 0.0000 4 195 1635 600 3225 Bit 10: ID_Proper\001
+4 0 0 0 0 2 14 0.0000 4 150 1620 600 3675 Bit 09: Undefined\001
+4 0 0 0 0 2 14 0.0000 4 150 1620 600 4125 Bit 08: Undefined\001
+4 0 0 0 0 0 12 0.0000 4 180 510 6750 1350 (if yes)\001
+4 0 0 0 0 0 12 0.0000 4 180 510 2925 900 (if yes)\001
+4 0 0 0 0 2 14 0.0000 4 180 1770 4275 1875 Bit 13: ID_Asteroid\001
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/loneos.fig
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/loneos.fig	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/loneos.fig	(revision 16632)
@@ -0,0 +1,174 @@
+#FIG 3.2
+Portrait
+Center
+Inches
+Letter 
+90.00
+Single
+-2
+1200 2
+6 2775 9450 8325 11250
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 5475 10500 825 450 5475 10500 6300 10950
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3675 10500 825 450 3675 10500 4500 10950
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 7275 10500 825 450 7275 10500 8100 10950
+2 4 1 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 8325 11250 8325 9450 2775 9450 2775 11250 8325 11250
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 2
+	 6375 9450 6375 11250
+4 0 0 0 0 0 18 0.0000 4 195 840 5025 10650 Star dB\001
+4 0 0 0 0 0 18 0.0000 4 255 1050 3150 10650 Image dB\001
+4 0 0 0 0 0 18 0.0000 4 195 945 6825 10650 Rock dB\001
+4 0 0 0 0 0 18 0.0000 4 195 1440 3825 9900    Photom dB\001
+-6
+6 3975 8400 5175 8850
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 3975 8400 5175 8400 5175 8850 3975 8850 3975 8400
+4 0 0 0 0 0 18 0.0000 4 195 810 4125 8775 addstar\001
+-6
+6 2100 3150 3075 3525
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2100 3150 3075 3150 3075 3525 2100 3525 2100 3150
+4 0 0 0 0 0 18 0.0000 4 195 735 2175 3450 flatten\001
+-6
+6 375 10050 1725 11250
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1050 10650 675 600 1050 10650 1725 11250
+4 0 0 0 0 0 18 0.0000 4 195 750 750 10725 USNO\001
+-6
+6 375 8625 1725 9825
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1050 9225 675 600 1050 9225 1725 9825
+4 0 0 0 0 0 18 0.0000 4 195 1125 450 9300 HST GSC\001
+-6
+6 3225 6525 4425 6975
+6 3225 6525 4425 6975
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 3225 6525 4425 6525 4425 6975 3225 6975 3225 6525
+4 0 0 0 0 0 18 0.0000 4 195 495 3525 6825 fstat\001
+-6
+-6
+6 2550 4800 3750 5250
+6 2550 4800 3750 5250
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2550 4800 3750 4800 3750 5250 2550 5250 2550 4800
+4 0 0 0 0 0 18 0.0000 4 255 780 2700 5175 dophot\001
+-6
+-6
+6 2925 5475 4125 6225
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3525 5850 600 375 3525 5850 4125 6225
+4 0 0 0 0 0 18 0.0000 4 255 345 3300 5925 obj\001
+-6
+6 2250 3825 3450 4575
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 2850 4200 600 375 2850 4200 3450 4575
+4 0 0 0 0 0 18 0.0000 4 195 255 2700 4275 flt\001
+-6
+6 3600 7275 4800 8025
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 4200 7650 600 375 4200 7650 4800 8025
+4 0 0 0 0 0 18 0.0000 4 195 480 3975 7725 cmp\001
+-6
+6 5925 8325 7125 8775
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 5925 8325 7125 8325 7125 8775 5925 8775 5925 8325
+4 0 0 0 0 0 18 0.0000 4 195 660 6075 8625 filters\001
+-6
+6 6150 6375 7800 7575
+6 6150 6375 7800 7575
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 6975 6975 825 600 6975 6975 7800 7575
+4 0 0 0 0 0 18 0.0000 4 195 510 6750 6900 alert\001
+-6
+4 0 0 0 0 0 18 0.0000 4 195 465 6750 7275 files\001
+-6
+6 1650 7425 2850 7875
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 1650 7425 2850 7425 2850 7875 1650 7875 1650 7425
+4 0 0 0 0 0 18 0.0000 4 225 675 1800 7800 gastro\001
+-6
+6 2775 12600 3975 13050
+6 2925 12750 3825 12975
+4 0 0 0 0 0 18 0.0000 4 195 915 2925 12975 addusno\001
+-6
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2775 12600 3975 12600 3975 13050 2775 13050 2775 12600
+-6
+6 4200 12600 5400 13050
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4200 12600 5400 12600 5400 13050 4200 13050 4200 12600
+4 0 0 0 0 0 18 0.0000 4 195 1005 4350 12975 markstar\001
+-6
+6 5625 12600 6825 13050
+6 5625 12600 6825 13050
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 5625 12600 6825 12600 6825 13050 5625 13050 5625 12600
+-6
+4 0 0 0 0 0 18 0.0000 4 195 1080 5775 12975 markrock\001
+-6
+6 7050 12600 8250 13050
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 7050 12600 8250 12600 8250 13050 7050 13050 7050 12600
+4 0 0 0 0 0 18 0.0000 4 255 765 7200 12975 nrphot\001
+-6
+6 8100 6450 9750 7650
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 8925 7050 825 600 8925 7050 9750 7650
+4 0 0 0 0 0 18 0.0000 4 255 885 8475 7290 pictures\001
+4 0 0 0 0 0 18 0.0000 4 240 795 8475 6975 results,\001
+-6
+6 7725 8250 8925 8700
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 7725 8250 8925 8250 8925 8700 7725 8700 7725 8250
+4 0 0 0 0 0 18 0.0000 4 165 645 7875 8625 status\001
+-6
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1425 1950 750 525 1425 1950 2175 2475
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3750 1950 750 525 3750 1950 4500 2475
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 3525 7650 2850 7650
+2 4 1 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 2025 12375 2025 8550 150 8550 150 12375 2025 12375
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 3375 11250 3375 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 2
+	0 0 1.00 60.00 120.00
+	 2250 3075 1425 2475
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 2
+	0 0 1.00 60.00 120.00
+	 2850 3075 3750 2475
+2 1 1 1 0 7 0 0 -1 4.000 0 0 -1 1 0 2
+	0 0 1.20 100.00 200.00
+	 2550 3525 4875 9450
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 4800 11250 4800 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 6225 11250 6225 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 7575 11250 7575 12600
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 3
+	0 0 1.00 60.00 120.00
+	 2775 12825 1050 12825 1050 12375
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 3
+	0 0 1.00 60.00 120.00
+	 1650 7650 1050 7650 1050 8550
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 6525 8325 6675 7500
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 6225 9450 6361 8772
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 8039 9453 8189 8703
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 8339 8253 8489 7503
+4 0 0 0 0 0 18 0.0000 4 195 1155 525 12075 references\001
+4 0 0 0 0 0 18 0.0000 4 165 840 675 11775 astrom.\001
+4 0 0 0 0 0 18 0.0000 4 195 825 3375 2025 archive\001
+4 0 0 0 0 0 18 0.0000 4 255 1020 900 2025 telescope\001
+4 0 0 0 0 0 36 0.0000 4 495 4200 5250 4425 Variability Pipeline\001
+4 0 0 0 0 0 36 0.0000 4 435 3870 5550 3450 U.W. / LONEOS \001
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/params.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/params.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/params.txt	(revision 16632)
@@ -0,0 +1,125 @@
+# Configuration file for Loneos analysis pipeline 
+
+# important files and directories
+IN_DIR			/pallas
+OUT_DIR			/irene/d11/workspace
+#
+CATDIR			/hebe/d27/database
+IMAGE_CATALOG		/hebe/d27/database/Images.dat
+IMAGE_CATALOG_TEMPLATE	/hebe/d27/database/template.cat
+CATALOG_TEMPLATE	/hebe/d27/database/template.cat
+ROCK_CATALOG		/hebe/d27/database/Rocks.dat
+#
+GSCFILE			/metis/d11/references/GSC/GSCregions.tbl
+GSC_DIR			/metis/d11/references/GSC
+USNO_CDROM		/metis/d11/references/USNO
+DOPHOT_PARAMS		/metis/d11/references/config/default_parameters
+FLATTEN_SCRIPT		/metis/d11/references/config/flatten.pro
+LONEOS_REGIONS		/metis/d11/references/config/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT			24.5
+DOPHOT_CHAR_LINE	129
+DOPHOT_TYPE_FIELD	5
+DOPHOT_AP_FIELD		91
+DOPHOT_PSF_FIELD	52
+MIN_SN_FSTAT		6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR	 0.6
+MIN_PRECISE	 0.12
+CCD_PC1_1	 1
+CCD_PC2_2	 -1    # for loneos
+CCD_PC1_2	 0
+CCD_PC2_1	 0
+ASEC_PIX	 2.82
+NFIELD		 3.0
+MMIN		 6.0
+ROT_ZERO	 0
+dROT		 1.0
+NROT		 2
+POLAR_AXIS_RA	 -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA			3.0
+ALPHA			0.03
+XOVERSCAN		60
+YOVERSCAN		50
+
+# parameters for "controller"
+NEW_IMAGES		images.dat
+USERNAME		gene
+PASSWORD		gene
+
+# here we list all available machines
+NMACHINES		6
+MACHINE0		metis
+MACHINE1		hebe
+MACHINE2		iris
+MACHINE3		irene
+#MACHINE4		juno
+MACHINE4		ceres
+MACHINE5		vesta
+
+# here we define which machines which are always free
+fMACHINE0		1
+fMACHINE1		1
+fMACHINE2		1
+fMACHINE3		1
+fMACHINE4		0
+fMACHINE5		0
+fMACHINE6		0
+
+LOCAL_MACHINE		1  # machine with catalog on local disk
+
+# parameters for "status"
+TIME_REFERENCE		90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU			3.0  		
+SCATTER_LIM		15.0
+MAG_LIM			17.0
+IMAGE_SCATTER		0.075
+NIMAGE_SCATTER		1.5
+STAR_SCATTER		0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS		360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH		5.0   # expected trail width, in arcsec
+NANGLE_BINS		180   # Number of angular bins in 180 degrees
+NPTSINLINE		5     # minimum points needed for trail
+MIN_DENSITY		0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA		10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH	  5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG	  9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE	-80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH	  5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG	 11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG		  8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE	-28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG		7.5
+GHOST_RADIUS		200   # in arcsec
+OPTICAL_AXIS1		2154.0
+OPTICAL_AXIS2		2193.0
+
+# parameters for "addusno"
+USNO_RADIUS		5.0   # in arcsec
+USNO_PROPER		20.0   # in arcsec
+USNO_RED		1000  # code for USNO Red data
+USNO_BLUE		1001  # code for USNO Blue data
+
+# parameters for "markrock"
+ROCK_RADIUS		2.0   # in arcsec
+ROCK_MAX_RADIUS		20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline.c	(revision 16632)
@@ -0,0 +1,22 @@
+\documentstyle[astro]{article]
+\GoodMargins
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+\section{Photometry -- Dophot}
+
+\section{Astrometry -- gastro}
+
+\section{The Photometry Database}
+
+\section{Visualization Tools}
+
+\section{Software Distribution}
+
+\section{Programming Details}
+
+\end{document}
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline.tex	(revision 16632)
@@ -0,0 +1,997 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp, Xm;           /* log(chisq) values in tenths */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[7];          /* extra space for the future?  (seems like a lot!) */
+  float          exptime;           /* exposure time, seconds */
+} Image;  /* 192 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+\section{Programming Details}
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\end{document}
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline2.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline2.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline2.tex	(revision 16632)
@@ -0,0 +1,1284 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp, Xm;           /* log(chisq) values in tenths */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[7];          /* extra space for the future?  (seems like a lot!) */
+  float          exptime;           /* exposure time, seconds */
+} Image;  /* 192 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in apply it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS problem, and others which are more
+general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which decide on a new
+set of data.  At the next level down, these scripts call two main C
+programs which run the images of a given night through the pipeline.  
+A fixed set of files keeps a log of the nights and images that have
+been processed, so the programs may know if a given night has already
+been analysed. 
+
+\subsection{lastnight}
+
+The Perl script {\tt lastnight} looks at the disks used by the
+observers to write the images from a given night.  Images are written
+to a directory called /pallas/d[1-6]/NNNNNN where NNNNNN is an
+abbreviation for the current night's date in the form YYMMDD (ie,
+990223).  All of the images are stored in this directory with names
+yyyyMMDDxxxxb.fits where yyyy is the full year, MM is month, DD is
+date, and xxxx is a sequence number.  The 'b' refers to the 'b' CCD,
+and the .fits extension is required.  The script {\tt lastnight} is
+called by a cron job scheduled for 7am on {\tt hebe.lowell.edu}.  The
+script searches the disks /pallas/d[1-6] for a directory of the right
+form (basically any directory beginning with a number).  By default,
+the program demands that the directory have a name of today's date,
+but with the flag -any, it will accept any directory.  It then checks
+to see if this directory have been already included in the
+'processed.log' file.  If not, it lists all files with the right
+ending (*b.fits) and places these names in a file.  It also writes the
+name of the directory (along with some other data) in a file
+'extracted.log'.  When it has successfully ended and identified some
+data, it calls the next script, {\tt stage1} and then quits.  
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file processed.log.  It tries to
+identify nights listed in the tape.log which have not been included in
+the processed.log.  If it finds any, it tries to download as much of
+the data as will fit on the disk /pallas/d1.  This script is called
+from within the {\tt stage1} script and is invoked if {\tt stage1} is
+run without any data already in extracted.log.  
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} and passes the list to the controller
+program {\tt control1} which performs the parallel analysis.  The
+script has a few features to decide which files have been analysed
+through the pipeline and to what extent.  If {\tt stage1} is called,
+it should be able to figure out 1) if there is data ready to be
+analysed, 2) if the data has been partially analysed, 3) which data
+needs to be run through which part of the pipeline, and so forth.
+These features are most useful if the analysis crashes in the middle
+or needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  The script writes a log file
+called \$scriptdir/stage1.NN.log where NN is a number in sequence
+between all runs of {\tt stage1}.  A file stage1.count keeps track of
+which number NN we are on.  When {\tt stage1} has finished the
+analysis of a night's data, it writes the date in processed.log to
+keep {\tt slurp} and {\tt lastnight} from re-running a night.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the processed.log file.  Once if finds a new name
+in this file, it looks for the appropriate images in the file
+YYMMDD.addlist.  It then submits the list to the second controlling
+program {\tt control2}, which runs the images through {\tt addstar}.
+Images which are successfully run through addstar have their *bf.fits
+(flattened image) and *.obj (dophot output) files deleted.  When the
+entire night is done, the rest of the *.obj and *bf.fits images are
+deleted by {\tt stage2}, the directory with the *.cmp and *.log files
+is tared and gzipped into the file YYMMNN.tgz.  The directory is then
+deleted.  Finally, {\tt stage2} calls the script {\tt cleaning.pl}
+which runs the cleanup programs ({\tt markstar - nrphot}) on the
+database.  After a successful run, {\tt stage2} will automatically
+respawn a new copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it, mostly).  The two programs also run a different set of
+program.  These controller programs start off by executing remote
+shells (using ssh) on a list of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  They maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named YYMMDD.addlist by the {\tt control1} and YYMMDD.outlist
+by {\tt control2}.
+
+\section{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  there is a perl program, locks, which allows the user to
+set or check the state of the different locks. 
+
+\section{File locations}
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+\section{Programming Details}
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline
+
+# important files and directories
+GSCFILE                 /host/pikake/d1/gene/gsc/GSCregions.tbl
+GSC_DIR                 /host/pikake/d1/gene/gsc
+CATDIR                  /host/radon/rad3/gene/photcat2
+IMAGE_CATALOG           /host/radon/rad3/gene/photcat2/Images.dat
+IMAGE_CATALOG_TEMPLATE  /host/radon/rad3/gene/photcat2/template.cat
+CATALOG_TEMPLATE        /host/radon/rad3/gene/photcat2/template.cat
+ROCK_CATALOG            /host/radon/rad3/gene/photcat2/Rocks.dat
+USNO_CDROM              /host/tycho/mnt/md0/kevin/zones
+LONEOS_REGIONS          /host/pikake/h1/gene/loneos3/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.1
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+IN_DIR                  /host/pikake/h1/gene
+OUT_DIR                 /host/pikake/h1/gene/loneos4/
+DOPHOT_PARAMS           /host/pikake/h1/gene/src/ohana/config/default_parameters
+FLATTEN_SCRIPT          /host/pikake/h1/gene/src/ohana/config/test.pro
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               2
+MACHINE0                pikake.astro.washington.edu
+MACHINE1                mildew.astro.washington.edu
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               0
+
+# here we define the machine which runs the database 
+LOCAL_MACHINE           0
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+# /mnt/cdrom
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\end{document}
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline3.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline3.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline3.tex	(revision 16632)
@@ -0,0 +1,1463 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts call two main C programs which run the
+images of a given night through the pipeline.  These C programs are
+more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{data and file organization}
+
+There are a set of standard locations for all of the files used and
+created by the Pipeline.  These locations have both abstract names
+used by the pipeline programs and specific definitions used in the
+LONEOS implementation.  In general, the definitions of the files are
+given in the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of spicam (3.0)).  The C programs all refer to the
+config file for the definitions, but the Perl scripts currently have
+the definitions hardwired as variable names defined in the beginning
+of each file.  This should be changed to a mechanism that looks in
+the config file, perhaps implemented by a standard Perl function.
+
+Here is a list of the main directories and their meanings:
+
+logdir:         /metis/d11/logs - all log files and the files used by
+the Perl scripts to control their actions (except locks) go here.
+
+workspace:      /irene/d11/workspace - the intermediate analysis
+stages go here, and the tar, gzipped directory files stay here.
+
+dumpspace:      /pallad/d1      - used by slurp to store images
+downloaded from the tape archive.
+
+database:       /hebe/d27/database      - the result database, as also
+the locks and the Rocks.dat file.
+
+references:     /metis/d11/references   - a variety of reference data,
+including the HST GSC, the USNO catalog, the config files, and so
+forth.
+
+source:         /metis/d11/src/ohana    - all of the programs source, 
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.  
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\tt lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called
+/pallas/d[1-6]/YYMMDD where 'YYMMDD' is an abbreviation for the current
+night's date (ie, 990223).  Many files use this naming scheme, so we
+will refer to such a name as 'YYMMDD'.  All of the images are stored
+in this directory with names yyyyMMDDxxxxb.fits where yyyy is the full
+year, MM is month, DD is date, and xxxx is a sequence number.  The 'b'
+refers to the 'b' CCD, and the .fits extension is required.  The
+script {\tt lastnight} is called by a cron job scheduled for 7am on
+{\tt hebe.lowell.edu} (note that the clock on hebe is set to PST, not
+local MST - fix this some day!).  The script searches the disks
+{\tt /pallas/d[1-6]} for a directory of the right form (basically any
+directory beginning with a number).  By default, the program demands
+that the directory have the name derived from today's date, but with
+the flag -any, it will accept any directory.  It then checks to see if
+this directory has been already been analysed (ie, it is included in
+the 'processed.log' file).  If not, it lists all files in that
+directory with the right ending (*b.fits) and places these names in a
+file, {\tt /metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file 'extracted.log'.
+When it has successfully ended and identified some data, it calls the
+next script, {\tt stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file 'processed.log'.  It tries
+to identify nights listed in the file 'tape.log' which have not been
+included in the 'processed.log'.  If it finds any, it tries to
+download as much of the data as will fit on the disk {\tt /pallas/d1}.
+This script is called from within the {\tt stage1} script and is
+invoked if {\tt stage1} is run without any data already in
+the file 'extracted.log'.
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} (YYMMDD.inlist) and passes the list to the
+controller program {\tt control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\tt
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+'extracted.log'), 2) if the data has been partially analysed (ie, the
+date reference in 'extracted.log' has not been put in 'processed.log',
+but there are entries in the file YYMMDD.outlist), and 3) which data
+needs to be run through which part of the pipeline (ie, it decides
+which of the images in YYMMDD.outlist have succeeded at which stages
+of the analysis, and starts them at the appropriate spot).  These
+features are most useful if the analysis crashes in the middle or
+needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  Otherwise, when it is done, it
+will restart itself, and since there is no new data in
+'extracted.log', it will start a slurp process to get data from the
+archive.  If there is no data in the archive either, this process will
+sleep for an hour and try again.  After a few attempts (2 days?), {\tt
+stage1} will give up and quit without restarting itself.  The script
+writes a log file called \$scriptdir/stage1.NN.log where NN is a
+number in sequence between all runs of {\tt stage1}.  A file
+stage1.count keeps track of which number NN we are on.  When {\tt
+stage1} has finished the analysis of a night's data, it writes the
+date in 'processed.log' to let other processes know what has been
+analysed.  The bulk of {\tt stage1} is not dependent on details of the
+LONEOS setup, but it does expect the files to have the naming scheme
+described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the 'processed.log file, presumably be {\tt
+stage1}.  Once if finds a new name in this file, it looks for the
+appropriate images in the file 'YYMMDD.addlist'.  It then submits the
+list to the second controlling program {\tt control2}, which runs the
+images through {\tt addstar}.  Images which are successfully run
+through addstar have their *bf.fits (flattened image) and *.obj
+(dophot output) files deleted.  When the entire night is done, the
+rest of the *.obj and *bf.fits images are deleted by {\tt stage2}, the
+directory with the *.cmp and *.log files is tared and gzipped into the
+file YYMMNN.tgz.  The directory is then deleted.  Finally, {\tt
+stage2} calls the scripts {\tt cleaning.pl} and {\tt run.phot} which
+runs the cleanup programs ({\tt markstar - nrphot}) on the database.
+After a successful run, {\tt stage2} will automatically respawn a new
+copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using ssh) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named 'YYMMDD.addlist' by the {\tt control1} and 'YYMMDD.outlist'
+by {\tt control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  There is a perl program, {\tt locks}, which allows the user to
+set or check the state of the different locks. All programs which
+write to the database check for the existence of a lock on the
+database and refuse to run if it exists.  The control1/2 programs and the
+stage1/2 programs check for their own lock files and only run if they
+don't exist.  Finally, the use can set the lock files 'kill' or 'halt'
+for either stage1 or stage2.  The first tells the process to stop
+immediately, taking care of bookkeeping first.  The second tells the
+process to finish the current set of images but not start a new
+version.  
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or are used by the maintainer to check up / work on
+the pipeline.  The two programs 'checkoutlist' and 'checkaddlist' take
+a list of YYMMDD.outlist or YYMMDD.addlist files and list the number
+of images in the file and the number of successes at each analysis
+stage.  There programs 'cleaning.pl' and 'run.phot' deal with the
+cleanup programs and the running of nrphot.  the program
+'backup.stuff' take the first 4 characters of the year/month file
+names and backs up to the jukebox tape all tar files for the given
+month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to hebe.lowell.edu.  This
+device is a set of three 9 GB disks merged into one 27GB raid disk.
+The database is stored mostly on this dist and the RAID disk mounted
+on metis.  It is easy to split the database across multiple file
+systems by using links.  Within the database directory, there are
+directories for each of 24 Declination bands (7.5 degrees tall).  The
+easiest way of splitting up the data is to move some of these
+subdirectories to another device and creating links to them at the
+appropriate place.  This is currently done by having a directory
+/metis/d27/database with the remote directories.  
+
+The current problem with the /hebe/d27 RAID results from the poor way
+it was setup.  It was set up without much knowledge of the (at the
+time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script /root/mdstart
+which lists the step to setup the RAID correctly.  It would be helpful
+if the rc.local or rc.sysinit files were fixed to start, fsck and
+mount the RAID automatically at boot.  The setup on metis is
+substantially more mature and is correctly implemented.  It comes up
+when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at /metis/d11/src/ohana.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form bin/\$ARCH
+and lib/\$ARCH.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+/metis/d11/ohana/bin/\$ARCH.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in ohana/src/perl, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form ohana/src/program.  The exceptions are gastro (stored in
+ohana/src/astro), and control1/2 (stored in ohana/src/astro).  Also, a
+variety of simple, user-level functions are available in
+ohana/src/misc. 
+
+Most of the ohana package of programs use several common libraries.
+These include the readline library (except for dophot, this is the only
+part of ohana that is not written by Eugene Magnier), which is used
+for command-line interface systems.  Other important libraries are the
+fits library for implementing the FITS specifications in a convenient
+C-friendly environment, and the ohana library, consisting of basic
+string and other basic operations.  
+
+For more details on the programming aspects of parts of the pipeline,
+see the associated document, 'A Programmer's Guide to the Loneos
+Pipeline'
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline
+
+# important files and directories
+GSCFILE                 /host/pikake/d1/gene/gsc/GSCregions.tbl
+GSC_DIR                 /host/pikake/d1/gene/gsc
+CATDIR                  /host/radon/rad3/gene/photcat2
+IMAGE_CATALOG           /host/radon/rad3/gene/photcat2/Images.dat
+IMAGE_CATALOG_TEMPLATE  /host/radon/rad3/gene/photcat2/template.cat
+CATALOG_TEMPLATE        /host/radon/rad3/gene/photcat2/template.cat
+ROCK_CATALOG            /host/radon/rad3/gene/photcat2/Rocks.dat
+USNO_CDROM              /host/tycho/mnt/md0/kevin/zones
+LONEOS_REGIONS          /host/pikake/h1/gene/loneos3/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.1
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+IN_DIR                  /host/pikake/h1/gene
+OUT_DIR                 /host/pikake/h1/gene/loneos4/
+DOPHOT_PARAMS           /host/pikake/h1/gene/src/ohana/config/default_parameters
+FLATTEN_SCRIPT          /host/pikake/h1/gene/src/ohana/config/test.pro
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               2
+MACHINE0                pikake.astro.washington.edu
+MACHINE1                mildew.astro.washington.edu
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               0
+
+# here we define the machine which runs the database 
+LOCAL_MACHINE           0
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+# /mnt/cdrom
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\end{document}
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline4.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline4.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline4.tex	(revision 16632)
@@ -0,0 +1,1520 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual image, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} 
+Schematic of the photometry pipeline.  Rectangles represent programs,
+while ovals represent data products.  Arrows show the direction of
+travel of information.  The flatten routine is a filter whose position
+may change as the pipeline matures.
+}
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Flat Fielding -- Mana / Flatten}
+
+Flat fielding is performed on each image after it has been written to
+disk by the acquisition software.  The processing is performed with
+mana (see mana user's guide) using a script written to work with the
+analysis pipeline processing software.  There are several important
+aspects of the script which make it work with the containing programs.
+First, the script is contained within a file, flatten.pro, in the
+references directory.  the script is invoked by calling it on the
+command line wehn mana is started.  If mana is started with a file
+name on the command line, that file is loaded with in 'input'.  The
+file defines a macro 'flatten', and also loads the flat-field file.
+The flattening process is actually done by calling within mana the
+macro flatten, with the input and output file names as arguments.  By
+loading the flat-field at the start of mana, instead of on each
+execution of flatten, we save the load time of each flat-field image
+(which is 2x the size of the basic image, being 4byte floats per
+pixel).  The location of the flat field is currently hard-wired in the
+flatten script - this should probably be changed in the future.  One
+of the aspects of this is that the macro loads a flatfield with a
+specific name and location.  This file is actually a link; The
+higher-level controlling process (stage1) creates a link to the
+correct flatfield.  This allows the analysis process to use different
+flatfields for different situations.  At LONEOS, we currently use a
+flat field generated from a well-understood night.  This is probably
+not the best solution as the flatfield changes with time.  As
+discussed below, the photometry solution program, nrphot, fits a
+high-order polynomial to the relative photometry, allowing for
+differences from the correct flatfield.
+ 
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get a close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+{\footnotesize
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim} }
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The two $\chi^2$ entries ({\tt Xp}
+and {\tt Xm}) are the $\chi^2$ values of the average position and the
+average magnitude.  These are stored as logarthmic quantities because
+high dynamic range is not needed.  For the magnitude, the assumption
+is that the star brightness is constant and the $\chi^2$ incorporates
+the photometric errors on each measurement.  For the postion, the
+a default constant error is used \note{True?} and again the assumption
+is that the postion is constant.  As discussed above, the values of
+{\tt Nm} and {\tt Nn} give the number of measurements and missing
+observations for this star, while the entries {\tt offset} and {\tt
+  missing} point to the first {\bf measure} and {\bf missing} entry
+for this star.  The entry {\tt M} is the current best average
+magnitude solution for this star (see the section on Relative
+Photometry).  Finally, the entry {\tt code} is an ID code for each
+object, which may define a variety of things about the object.  For
+example, if the object is known to be variable, or if the object is
+associated with a USNO star, or if the object is a measurement of an
+asteroid.  See below for details of these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\footnotesize
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim} }
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\footnotesize
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only one bit is used, to define if the image has
+unacceptable photometric scatter.  Seven extra bytes are stored for
+future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (usually dependent on the astrometric for the
+image).  If more than one catalog stars is correlated with a star in
+an image, the new measurement is added to {\em both} catalog stars,
+and a flag is set noting that this observation had a blended IMAGE.
+Conversely, if a single catalog star is matched with more than one
+image star, both new measurements are added to the one catalog star,
+and a different flat is set, noting that this observation had a
+blended CATALOG.   
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad dat are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size is
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is suceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+\section{Relative Photometry -- nrphot}
+
+Once the data has been incorporated in the photometry database and the
+data validation routines have been run, it is possible to determine
+photometric solutions for all of the images.  The program which does
+this is nrphot.  It tries to find a set of solutions for each image
+which reduce both the scatter per image and the scatter per star.  To
+see how this works, we start by defining a measurement of star $j$ on
+image $i$ as $m_{i,j}$.  Every star has an apparent magnitude of
+$M_j$.  Every image has a correction magnitude of $M_i$, defined as
+$m_{i,j}= M_i + M_j$.  (USE SOME OF THE TEXT FROM THE M31 paper).  
+
+The Pipeline implementation of relative photometry includes the
+possibility for up to third order polynomial terms across the field.
+This is needed to account for the different flat fields, particularly
+between images taken with and without the red-block filter.  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} 
+Pictoral representation of the Average.code flags.  The lower byte
+value is used for specific definitions of object types.
+}
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyra may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts call two main C programs which run the
+images of a given night through the pipeline.  These C programs are
+more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{data and file organization}
+
+There are a set of standard locations for all of the files used and
+created by the Pipeline.  These locations have both abstract names
+used by the pipeline programs and specific definitions used in the
+LONEOS implementation.  In general, the definitions of the files are
+given in the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of spicam (3.0)).  The C programs all refer to the
+config file for the definitions, but the Perl scripts currently have
+the definitions hardwired as variable names defined in the beginning
+of each file.  This should be changed to a mechanism that looks in
+the config file, perhaps implemented by a standard Perl function.
+
+Here is a list of the main directories and their meanings:
+
+logdir:         /metis/d11/logs - all log files and the files used by
+the Perl scripts to control their actions (except locks) go here.
+
+workspace:      /irene/d11/workspace - the intermediate analysis
+stages go here, and the tar, gzipped directory files stay here.
+
+dumpspace:      /pallad/d1      - used by slurp to store images
+downloaded from the tape archive.
+
+database:       /hebe/d27/database      - the result database, as also
+the locks and the Rocks.dat file.
+
+references:     /metis/d11/references   - a variety of reference data,
+including the HST GSC, the USNO catalog, the config files, and so
+forth.
+
+source:         /metis/d11/src/ohana    - all of the programs source, 
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.  
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\tt lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called
+/pallas/d[1-6]/YYMMDD where 'YYMMDD' is an abbreviation for the current
+night's date (ie, 990223).  Many files use this naming scheme, so we
+will refer to such a name as 'YYMMDD'.  All of the images are stored
+in this directory with names yyyyMMDDxxxxb.fits where yyyy is the full
+year, MM is month, DD is date, and xxxx is a sequence number.  The 'b'
+refers to the 'b' CCD, and the .fits extension is required.  The
+script {\tt lastnight} is called by a cron job scheduled for 7am on
+{\tt hebe.lowell.edu} (note that the clock on hebe is set to PST, not
+local MST - fix this some day!).  The script searches the disks
+{\tt /pallas/d[1-6]} for a directory of the right form (basically any
+directory beginning with a number).  By default, the program demands
+that the directory have the name derived from today's date, but with
+the flag -any, it will accept any directory.  It then checks to see if
+this directory has been already been analysed (ie, it is included in
+the 'processed.log' file).  If not, it lists all files in that
+directory with the right ending (*b.fits) and places these names in a
+file, {\tt /metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file 'extracted.log'.
+When it has successfully ended and identified some data, it calls the
+next script, {\tt stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file 'processed.log'.  It tries
+to identify nights listed in the file 'tape.log' which have not been
+included in the 'processed.log'.  If it finds any, it tries to
+download as much of the data as will fit on the disk {\tt /pallas/d1}.
+This script is called from within the {\tt stage1} script and is
+invoked if {\tt stage1} is run without any data already in
+the file 'extracted.log'.
+
+A related pair program is the load/unload C programs which are needed
+for loading and unloading the tape jukebox.  The first, load N, takes
+tape number N and loads it into the tape drive.  The second takes the
+tape a returns it to its slot.  It is important to check on the other
+users of the tape drive to be sure it is not occupied.  This is done
+with the llock, lunlock and llockstat programs.  llockstat lists the
+devices which have been allocated.  llock lets you lock a particular
+service, etc.
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} (YYMMDD.inlist) and passes the list to the
+controller program {\tt control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\tt
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+'extracted.log'), 2) if the data has been partially analysed (ie, the
+date reference in 'extracted.log' has not been put in 'processed.log',
+but there are entries in the file YYMMDD.outlist), and 3) which data
+needs to be run through which part of the pipeline (ie, it decides
+which of the images in YYMMDD.outlist have succeeded at which stages
+of the analysis, and starts them at the appropriate spot).  These
+features are most useful if the analysis crashes in the middle or
+needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  Otherwise, when it is done, it
+will restart itself, and since there is no new data in
+'extracted.log', it will start a slurp process to get data from the
+archive.  If there is no data in the archive either, this process will
+sleep for an hour and try again.  After a few attempts (2 days?), {\tt
+stage1} will give up and quit without restarting itself.  The script
+writes a log file called \$scriptdir/stage1.NN.log where NN is a
+number in sequence between all runs of {\tt stage1}.  A file
+stage1.count keeps track of which number NN we are on.  When {\tt
+stage1} has finished the analysis of a night's data, it writes the
+date in 'processed.log' to let other processes know what has been
+analysed.  The bulk of {\tt stage1} is not dependent on details of the
+LONEOS setup, but it does expect the files to have the naming scheme
+described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the 'processed.log file, presumably be {\tt
+stage1}.  Once if finds a new name in this file, it looks for the
+appropriate images in the file 'YYMMDD.addlist'.  It then submits the
+list to the second controlling program {\tt control2}, which runs the
+images through {\tt addstar}.  Images which are successfully run
+through addstar have their *bf.fits (flattened image) and *.obj
+(dophot output) files deleted.  When the entire night is done, the
+rest of the *.obj and *bf.fits images are deleted by {\tt stage2}, the
+directory with the *.cmp and *.log files is tared and gzipped into the
+file YYMMNN.tgz.  The directory is then deleted.  Finally, {\tt
+stage2} calls the scripts {\tt cleaning.pl} and {\tt run.phot} which
+runs the cleanup programs ({\tt markstar - nrphot}) on the database.
+After a successful run, {\tt stage2} will automatically respawn a new
+copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using ssh) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named 'YYMMDD.addlist' by the {\tt control1} and 'YYMMDD.outlist'
+by {\tt control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  There is a perl program, {\tt locks}, which allows the user to
+set or check the state of the different locks. All programs which
+write to the database check for the existence of a lock on the
+database and refuse to run if it exists.  The control1/2 programs and the
+stage1/2 programs check for their own lock files and only run if they
+don't exist.  Finally, the use can set the lock files 'kill' or 'halt'
+for either stage1 or stage2.  The first tells the process to stop
+immediately, taking care of bookkeeping first.  The second tells the
+process to finish the current set of images but not start a new
+version.  
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or are used by the maintainer to check up / work on
+the pipeline.  The two programs 'checkoutlist' and 'checkaddlist' take
+a list of YYMMDD.outlist or YYMMDD.addlist files and list the number
+of images in the file and the number of successes at each analysis
+stage.  There programs 'cleaning.pl' and 'run.phot' deal with the
+cleanup programs and the running of nrphot.  the program
+'backup.stuff' take the first 4 characters of the year/month file
+names and backs up to the jukebox tape all tar files for the given
+month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to hebe.lowell.edu.  This
+device is a set of three 9 GB disks merged into one 27GB raid disk.
+The database is stored mostly on this dist and the RAID disk mounted
+on metis.  It is easy to split the database across multiple file
+systems by using links.  Within the database directory, there are
+directories for each of 24 Declination bands (7.5 degrees tall).  The
+easiest way of splitting up the data is to move some of these
+subdirectories to another device and creating links to them at the
+appropriate place.  This is currently done by having a directory
+/metis/d27/database with the remote directories.  
+
+The current problem with the /hebe/d27 RAID results from the poor way
+it was setup.  It was set up without much knowledge of the (at the
+time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script /root/mdstart
+which lists the step to setup the RAID correctly.  It would be helpful
+if the rc.local or rc.sysinit files were fixed to start, fsck and
+mount the RAID automatically at boot.  The setup on metis is
+substantially more mature and is correctly implemented.  It comes up
+when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, , {\tt gstars (RA) (DEC)
+  (RADIUS)} lists data about the stars within a specified radius of
+the specified location (all numbers above are given in decimal
+degrees).  Similarly, {\tt lcat} lists the catalogs in the region.
+Imstats lists statistics about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} 
+Map of the entire sky, and images added to database.
+}
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} 
+Comparison between HST GSC and photometry database astrometry. 
+}
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} 
+Lightcurve for several image stars.
+}
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following commands (starting
+from the previous image):
+{\footnotesize
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at /metis/d11/src/ohana.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form bin/\$ARCH
+and lib/\$ARCH.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+/metis/d11/ohana/bin/\$ARCH.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in ohana/src/perl, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form ohana/src/program.  The exceptions are gastro (stored in
+ohana/src/astro), and control1/2 (stored in ohana/src/astro).  Also, a
+variety of simple, user-level functions are available in
+ohana/src/misc. 
+
+Most of the ohana package of programs use several common libraries.
+These include the readline library (except for dophot, this is the only
+part of ohana that is not written by Eugene Magnier), which is used
+for command-line interface systems.  Other important libraries are the
+fits library for implementing the FITS specifications in a convenient
+C-friendly environment, and the ohana library, consisting of basic
+string and other basic operations.  
+
+For more details on the programming aspects of parts of the pipeline,
+see the associated document, 'A Programmer's Guide to the Loneos
+Pipeline'
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+{\footnotesize
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline
+
+# important files and directories
+GSCFILE                 /host/pikake/d1/gene/gsc/GSCregions.tbl
+GSC_DIR                 /host/pikake/d1/gene/gsc
+CATDIR                  /host/radon/rad3/gene/photcat2
+IMAGE_CATALOG           /host/radon/rad3/gene/photcat2/Images.dat
+IMAGE_CATALOG_TEMPLATE  /host/radon/rad3/gene/photcat2/template.cat
+CATALOG_TEMPLATE        /host/radon/rad3/gene/photcat2/template.cat
+ROCK_CATALOG            /host/radon/rad3/gene/photcat2/Rocks.dat
+USNO_CDROM              /host/tycho/mnt/md0/kevin/zones
+LONEOS_REGIONS          /host/pikake/h1/gene/loneos3/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.1
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+IN_DIR                  /host/pikake/h1/gene
+OUT_DIR                 /host/pikake/h1/gene/loneos4/
+DOPHOT_PARAMS           /host/pikake/h1/gene/src/ohana/config/default_parameters
+FLATTEN_SCRIPT          /host/pikake/h1/gene/src/ohana/config/test.pro
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               2
+MACHINE0                pikake.astro.washington.edu
+MACHINE1                mildew.astro.washington.edu
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               0
+
+# here we define the machine which runs the database 
+LOCAL_MACHINE           0
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+# /mnt/cdrom
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}}
+
+\end{document}
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline5.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline5.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline5.tex	(revision 16632)
@@ -0,0 +1,1990 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+The Loneos Pipeline provides automated reduction of images, including
+photometry and astrometry, with the final data stored in a photometry
+database organized by star position on the sky.
+
+Fig.~\ref{pipeline} shows a schematic of the analysis pipeline.
+Images are written to the disk from the camera by the software which
+runs it, {\tt astrocam}.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  Images are first analyzed
+by {\tt dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called OBJ files in this
+discussion.  The results from {\tt dophot} are cleaned up by a program
+called {\tt fstat} which merges the header information from the image
+with the most relevant parts of the OBJ file, creating a new file with
+the CMP format.  Astrometry is performed on the CMP file with the
+program {\tt gastro}.  {\tt Gastro} makes a comparison with an
+astrometric reference database and only changes CMP header keywords as
+a result.  Finally, the processed image CMP file is added to the
+photometry database with the program {\tt addstar}.  The photometry
+database is maintained in a large number of files (CPT files), each
+representing a small region of sky.  There is no relationship between
+the image locations and the boundaries of CPT file.  All of these
+processes occur on individual images, and would typically be performed
+while the observations are occuring, or during the day following, but
+may be performed at any time to add new or archived data to the
+database.
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  Typically, these
+routines would be run at the end of a night on all of the CPT files to
+which new data were added.  First, {\tt markstar} identifies bad data
+(the trails of satelites, the bleeding columns from stars, ghost
+images), and flags these data points appropriately.  Second, {\tt
+  addusno} matches the catalog stars with stars from the USNO database
+and adds the USNO magnitudes to the photometry database.  Next, {\tt
+  markrock} searches for likely asteroids in the CPT file, marks them,
+and writes the asteroid observations to an asteroid database.  It also
+notes measurements which are likely to be noise and cosmic rays.
+Finally, {\tt nrphot} determines relative photometric calibrations for
+observations in a set of CPT files.  
+
+With the exception of {\tt dophot}, all of the programs in the
+pipeline refer to a single configuration file to determine the large
+number of parameters necessary in the process.  The default parameter
+file is hardwired into the programs, but an alternate configuration
+file may be specified with the environment variable {\tt
+  PIPE\_CONFIG}.  This option makes independent processing of multiple
+data sources trivial.  For example, if the pipeline is to be used for
+both Loneos and SDSS image analysis and display, there could be two
+configuration files (eg, {\tt loneos.txt} and {\tt sdss.txt}), one for
+each data source.  Several important parameters would be different
+between these two, for example, the initial plate scale guess for the
+astrometry routine, or the parameters which define the rough chip
+orientation.  This scheme allows for analysis of different types of
+images, with a common destination photometry database, or for
+independent photometry databases.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} \small
+  Schematic of the photometry pipeline.  Rectangles represent
+  programs, while ovals represent data products.  Arrows show the
+  direction of travel of information.  The flatten routine is a filter
+  whose position may change as the pipeline matures.  }
+\end{figure}
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+\subsection{Flat Fielding -- Mana / Flatten}
+
+Flat fielding is performed on each image after it has been written to
+disk by the acquisition software.  The processing is performed with
+mana (see mana user's guide) using a script written to work with the
+analysis pipeline processing software.  There are several important
+aspects of the script which make it work with the containing programs.
+First, the script is contained within a file, flatten.pro, in the
+references directory.  The script is invoked by calling it on the
+command line when mana is started.  If mana is started with a file
+name on the command line, that file is loaded with in 'input'.  The
+file defines a macro 'flatten', and also loads the flat-field file.
+The flattening process is actually done by calling within mana the
+macro flatten, with the input and output file names as arguments.  By
+loading the flat-field at the start of mana, instead of on each
+execution of flatten, we save the load time of each flat-field image
+(which is 2x the size of the basic image, being 4byte floats per
+pixel).  \note{The location of the flat field is currently hard-wired in the
+flatten script - this should probably be changed in the future.}  One
+of the aspects of this is that the macro loads a flatfield with a
+specific name and location.  This file is actually a link; The
+higher-level controlling process (stage1) creates a link to the
+correct flatfield.  This allows the analysis process to use different
+flatfields for different situations.  At LONEOS, we currently use a
+flat field generated from a well-understood night.  This is probably
+not the best solution as the flatfield changes with time.  As
+discussed below, the photometry solution program, nrphot, fits a
+high-order polynomial to the relative photometry, allowing for
+differences from the correct flatfield.
+ 
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\tt Dophot}.  The version
+of dophot is based on Dophot 2.0, but it has been adapted to
+streamline processing of many files.  First, with this version of
+dophot, any FITS format data is safely read in.  Instead of compiling
+to a fixed maximum size, only the memory needed to contain the image
+matrix is allocated.  The image is also converted to REAL*32 from
+whatever BITPIX for processing.  Finally, only a single, complete
+parameter file is loaded by dophot.  There is no option for a modified
+and a default parameter file.  The parameter file to be used is
+defined, along with the input image and the output object list on the
+command line when the program is run: \\
+{\tt dophot image.fits image.obj parameter\_file} \\
+To achive this, the code from dophot was wrapped within a C program
+which interprets the command line arguments, allocates the necessary
+memory, and reads in the image.  The rest of the processing is
+performed by dophot in the standad manner.  Notice that we use a
+consistent naming convention through the pipeline reductions.  The
+image is called {\tt foo.fits}, while the resulting dophot-produced
+photometry list is called {\tt foo.obj}.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by dophot, the object file ({\tt foo.obj})
+is converted to a more-compact, more-complete file called a CMP file,
+with a name of the form ({\tt foo.cmp}).  This conversion is done with
+the program {\tt fstat}.  The CMP file consists of the FITS header
+from the original image ({\tt foo.fits}), with some additional
+keywords to be used at later stages in the analysis, followed by an
+ASCII list of the interesting data from ({\tt foo.obj}).  In this
+list, types 6 and 8 are excluded, and only the following values are
+kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\tt MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\tt fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\tt fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\tt ZERO\_PT}), and four numbers
+defining the format of the {\tt dophot} OBJ file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\tt gastro}.
+{\tt gastro} loads a CMP file and determines an initial guess for the
+center coordinates (based on the RA and DEC header keywords).  The
+program also uses the configuration information about the plate scale
+and rough orientation of the image to get close to the final solution.
+Also, the true sky position of the telescope pole may be defined to
+allow astrometry on images taken close to the pole.  The comparison is
+made with the astrometric catalog, which may be the HST Guide Star
+Catalog, or it may be any source if the data is placed in the correct
+format.
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or CPT files (because they have the
+extension {\tt .cpt}).  The photometry files are sorted by Declination
+into different directories, each consisting of a band 7.5\degree\ 
+wide.  These directories have names like n0730, representing the band
+starting at a Declination of +07:30.  The image database (Images.dat)
+is stored in the upper level directory of this directory tree.  In
+fact, the locations of the Images.dat file, the photometry database,
+and such are all flexible and may be changed by altering the
+configuration file.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, GSCregions.tbl, which
+can be used to find the region file appropriate for any location on
+the sky.  A number of routines exist to make such a query.  
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by the RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\tt
+  addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The entry {\tt Xm} is the magnitude
+$\chi^2$ value for the star, under the assumption that the star
+brightness is constant.  This $\chi^2$ incorporates the photometric
+errors on each measurement and is stored as 1000 times the logarithm
+of the $\chi^2$ because high dynamic range is not needed.  The entry
+{\tt Xp} is the scatter about the average postion, in 10
+milli-arcseconds.  As discussed above, the values of {\tt Nm} and {\tt
+  Nn} give the number of measurements and missing observations for
+this star, while the entries {\tt offset} and {\tt missing} point to
+the first {\bf measure} and {\bf missing} entry for this star.  The
+entry {\tt M} is the current best average magnitude solution for this
+star (see the section on Relative Photometry).  Finally, the entry
+{\tt code} is an ID code for each object, which may define a variety
+of things about the object.  For example, if the object is known to be
+variable, or if the object is associated with a USNO star, or if the
+object is a measurement of an asteroid.  See below for details of
+these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only two bits are used, to define if the image has been
+photometrically calibrated and if the calibration is acceptable.
+There are 21 extra bytes are stored for future additions.
+
+\subsection{Data Incorporation -- {\tt addstar}}
+
+Images which are completely processed ({\tt dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\tt 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (dependent on the scatter in the astrometric
+solution for the image).  If more than one catalog stars are correlated
+with a star in an image, the new measurement is added to {\em both}
+catalog stars, and a flag is set noting that this observation had a
+blended IMAGE.  Conversely, if a single catalog star is matched with
+more than one image star, both new measurements are added to the one
+catalog star, and a different flat is set, noting that this
+observation had a blended CATALOG.
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the CPT files.  This may best be done on CPT files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single CPT file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\tt markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current CPT
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\tt markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad data are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size are
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+To run 'markstar' by hand, the syntax is: {\tt markstar (file.cpt)}.
+There are several optional flags, which are listed if you type
+markstar by itself.
+
+\subsection{Addusno}
+
+The program {\tt addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is susceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\tt addusno} stage, no objects
+already flagged as bad by {\tt markstar} will be matched with USNO
+stars.  
+
+To run 'addusno' by hand, the syntax is: {\tt addusno (file.cpt)}.
+There are several optional flags, which are listed if you type
+addusno by itself.
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\tt markrock}
+searches within a specific CPT file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\tt markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\tt markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+To run 'markrock' by hand, the syntax is: {\tt markrock (file.cpt)}.
+There are several optional flags, which are listed if you type
+markrock by itself.
+
+\section{Relative Photometry -- nrphot}
+
+Once the data has been incorporated in the photometry database and the
+data validation routines have been run, it is possible to determine
+photometric solutions for all of the images.  The program which does
+this is nrphot.  It tries to find a set of solutions for each image
+which reduce both the scatter per image and the scatter per star.
+\note{the following section is quoted verbatim from the M31 paper
+  Magnier et al 1992, A\&A Supp 96, 379.  It could use a little
+  editing to fit the reality of the LONEOS implementation.}
+
+In order to convert from instrumental magnitudes reported by DOPHOT
+to a standard photometric system, relative photometry was used, and
+all values converted to one internal magnitude system for the entire
+set of data taken with each filter.  Note that this is not {\em
+  differential}\ photometry on a single image, but rather {\em
+  relative}\ photometry between many images.  This method was
+advantageous for several reasons.  First, since many of our nights
+were not photometric, relative photometry allowed us to use all of our
+data, even that obtained on the cloudy nights.  Second, it allowed us
+to use photometry from several of the recent CCD photometric studies
+(Massey \etal\ 1986; Hodge \& Lee 1988; Freedman 1989; Richer \etal\ 
+1990) in small fields of M31 to calibrate our data to a standard
+system.  Third, relative photometry allowed us to check the agreement
+of the photometry of the calibration data.
+
+        In order to perform relative photometry, we used multiple
+measurements of individual stars on overlapping images to connect
+neighboring images.  A standard method of converting between
+instrumental magnitudes and a standard photometric system is to use a
+photometry equation of the form:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{color}*(color) \\
+\label{M_mag}
+\end{equation}
+where $m$ is the instrumental magnitude,
+\begin{equation}        
+m = -2.5\log(N_{el}) + 2.5\log(t). \\
+\label{inst_mag}
+\end{equation}
+$N_{el}$ is the number of electrons measured in a single star, $t$ is
+the exposure time for the image, $M_{app}$ is the apparent magnitude
+of the star in the standard system, $\zeta$ is the airmass of the
+image, and $color$ is the value of a color index (\ie\ \B\ - \V\ or
+\V\ - \R) for the particular star.  The subscript $\lambda$ refers to
+the filter and the subscript $color$ refers to the color index.  For a
+given filter, several possible color indices could be used (\ie\, for
+calibration of \V\ data, both \B\ - \V\ and \V\ - \R\ could be used to
+measure the response of the detector with the color of the star);
+however the colors of stars are highly correlated, so only one color
+index need be used at a time.  $c_{\lambda}$, $a_{\lambda}$, and
+$\gamma_{color}$ are calibration coefficients dependent on the
+instruments and the site.  $c_{\lambda}$ is a factor to scale the
+response of the detector.  In fact, the value determined for
+$c_{\lambda}$ depends on what color index is used in the calibration,
+so one might in fact write $c_{\lambda}$ as $c_{\lambda, color}$.
+However, for the sake of readability, this second subscript will be
+dropped.  The terms $\gamma_{color}$ and $a_{\lambda}$ give the
+variation of the sensitivity with the color of the star and the
+airmass.  For a detailed discussion of photometric calibrations, see
+Hardie (1962).  Equation (\ref{M_mag}) is only valid for photometric
+conditions.  Under non-photometric conditions, we need to add another
+term to account for clouds:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{color}*(color) + clouds \\
+\label{M_cloud}
+\end{equation}
+Now, we can regroup the terms in (\ref{M_cloud}) as follows:
+\begin{equation}        
+m = [M_{app} - \gamma_{color}*(color)] - [c_{\lambda} + a_{\lambda}*\zeta + clouds]
+\label{M_sep}
+\end{equation}
+Of the two terms on the right side of equation (\ref{M_sep}), the variables
+in the first pair of brackets are dependent on the properties of the
+star, those in the second pair of brackets are dependent on the image parameters,
+except for $c_{\lambda}$ which is independent of both image and star.
+We can now define the ``relative magnitude'' and the ``calibration
+magnitude'' from (\ref{M_sep}) as follows:
+\begin{eqnarray}
+        m       & = & M_{rel} + M_{cal} \label{rel_phot1}\\
+        M_{rel} & = & [M_{app} - \gamma_{color}*(color) + \Delta] \label{color}\\
+        M_{cal} & = & - [c_{\lambda} + a_{\lambda}*\zeta + clouds + \Delta] \label{M_cal}
+\end{eqnarray}
+where $M_{rel}$ is the relative photometric magnitude of the star in
+the internal system and $M_{cal}$ is a correction factor to convert
+instrumental magnitudes to relative magnitudes.  The terms $\Delta$
+are included in eqs. (\ref{color}) and (\ref{M_cal}) to make explicit
+the fact that an arbitrary constant can be added to $M_{rel}$ and
+subtracted from $M_{cal}$, as this fact will be important (see below).
+The goal of relative photometry is to determine $M_{cal}$ for each
+image, then use this $M_{cal}$ to find $M_{rel}$ for all stars from
+eq. (\ref{rel_phot1}).  Once one has $M_{rel}$ for each star, one can
+then convert them to a standard system ($M_{app}$) using equation
+(\ref{color}).
+
+        An equation of the form (\ref{rel_phot1}) exists for each star
+detected on each image.  As described, the value $m$ depends on both
+the particular image and the particular star, the value of $M_{cal}$
+only depends on the image, and the value of $M_{rel}$ only depends on
+the particular star.  Let us label the images with the subscript $i$
+and the stars with the subscript $j$.  Equation (\ref{rel_phot1}) can
+then be written in the form:
+\begin{equation}
+m_{i,j} = M_{rel,j} + M_{cal,i} \label{rel_phot}
+\end{equation}
+Of course, $m_{i,j}$ only exists for certain combinations of images
+and stars: not all stars appear on all images.  In the entire system
+of equations, only one value of $\Delta$ (from eqs. \ref{color} and
+\ref{M_cal}) can be used, but, as noted above, the {\em value}\ of
+$\Delta$ is arbitrary.
+
+        In equation (\ref{rel_phot}), both $M_{rel,j}$ and $M_{cal,i}$
+are unknown quantities.  We can use a method of least squares to find
+these values for the entire set of data.  We try to minimize the chi
+square, defined as:
+\begin{equation}
+\chisq = \sum_{i,j}(m_{i,j} - M_{rel,j} - M_{cal,i})^2 / \sigma_{i,j}^2 \label{chisquare}
+\end{equation}
+where $\sigma_{i,j}$ is the error in the measurement $m_{i,j}$, and
+the index $i$ runs over all images, while the index $j$ runs over all
+stars which are multiply measured, \ie\ those stars which appear on more
+than one image.
+
+        We attempt to minimize \chisq\ analytically by finding the
+derivatives of \chisq\ with respect to $M_{rel,j}$ and $M_{cal,i}$
+and setting them equal to zero:
+\begin{eqnarray}
+\frac{\partial\chisq}{\partial M_{rel,j}} = \sum_{i}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0  \nonumber \\
+\frac{\partial\chisq}{\partial M_{cal,i}} = \sum_{j}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0
+\end{eqnarray}
+In these summations, the index $i$ runs over all images in which star
+$j$ appears, and the index $j$ runs over all stars which appear on
+image $i$ which are multiply measured.  Solving the equality leads to
+the following system of equations:
+\begin{eqnarray}
+R_{j}M_{rel,j} = \sum_{i}(m_{i,j} - M_{cal,i}) / \sigma_{i,j}^2 \label{system1} \\
+R_{i}M_{cal,i} = \sum_{j}(m_{i,j} - M_{rel,j}) / \sigma_{i,j}^2 \label{system2}
+\end{eqnarray}
+where 
+\begin{eqnarray}
+R_{i} = \sum_{j}\frac{1}{\sigma_{i,j}^2} \nonumber \\
+R_{j} = \sum_{i}\frac{1}{\sigma_{i,j}^2} 
+\end{eqnarray}
+Again, the index $i$ runs over all images in which star $j$ appears,
+and the index $j$ runs over all stars which appear on image $i$, with
+the restriction of multiple measurements.  The term $\Delta$ from
+eqs. (\ref{color}) and (\ref{M_cal}) acts as an arbitrary zero point
+between the relative and apparent photometric systems.
+
+        Equations (\ref{system1}) and (\ref{system2}) are a set of
+$N_{images} + N_{stars}$ linear equations with $N_{images} +
+N_{stars}$ unknowns.  The unknown parameters are the terms $M_{rel,j}$
+and $M_{cal,i}$.  Unfortunately, $N_{images} + N_{stars}$ is a number
+on the order of 5000 - 10000, thus an analytical solution is
+impractical and an iteration method must be used.  A simple iteration
+method is as follows:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Guess at values for each $M_{cal,i}$.
+\item Use equation (\ref{system1}) to find values for $M_{rel,j}$.  
+\item Substitute these $M_{rel,j}$ values into (\ref{system2}) to get a new
+set of $M_{cal,i}$ values.  
+\item Return to step 1.
+\end{enumerate}
+%\DoubleSpace
+This process is repeated until some criterion is reached, such as the
+\chisq\ no longer changes or reaches a desired minimum.  Although a
+minimum can be found, error propagation causes severe problems
+since images are only connected to neighboring images.  The end point
+images are connected by \approx 50 intermediate images, and errors
+propagating over such a long distance can cause severe errors.  Also,
+$M_{rel,j}$ and $M_{cal,i}$ are not uniquely defined, because of the
+term $\Delta$.  Therefore, during the iteration process, the values of
+$M_{rel,j}$ and $M_{cal,i}$ tend to wander and do not tend to converge
+($M_{cal,i}$ may be incorrect by typically 0.5 mag).  These problems
+can be overcome if some of the values $M_{cal,i}$ or $M_{rel,j}$ are
+known.  In this situation, the known values can be held fixed,
+providing a reference point for the remaining values.  If enough
+values are known across a large enough portion of the data, no image
+is separated from the fixed values by many images, and errors will not
+build up.
+
+        Although many values $M_{rel,j}$ were known from other CCD
+photometry studies, we chose not to use them.  The reason for this
+decision was threefold: 1) By not using them, we are able to check the
+effectiveness of our method.  2) We are able to check the accuracy of
+the reference data.  3) The known $M_{rel,j}$ values were in a very
+small number of highly concentrated regions (the locations of the CCD
+photometry studies).  This was particularly a problem in \R\ and \I,
+where we only had one or two reference fields.  We therefore chose to
+fix certain values of $M_{cal,i}$
+
+        Images taken under photometric conditions provide a set of
+known $M_{cal,i}$ which can be held fixed.  This is true since, if the
+image is taken under photometric conditions, the term $clouds$ in eq.
+(\ref{M_cal}) is by definition 0.  The other terms in this equation
+are either known ($a_{\lambda}*\zeta$) or are constant for all images
+($c_{\lambda}$) and can thus be assigned to a set value, which can
+later be removed with the zero point calibration.  We used the values
+of $a_{\lambda}$ reported by Pilachowski \etal\ (1991): $a_B$, $a_V$,
+$a_R$, $a_I$ = (0.24, 0.15, 0.11, 0.07).  We used the long-term
+average coefficients, not those measured in October 1991, since the
+observations were performed before the eruption of Mount Pinatubo.
+The task that remains is to determine which images were photometric.
+
+        Since the conditions during observations varied greatly from
+night to night, we decided to determine which images were photometric
+from the images themselves.  To do this, we used a variation on the
+iteration method described above.  Before starting the iterations, we
+assume a value for $c_{\lambda}$.  We can choose this arbitrarily, and
+correct for our choice in the correction to an absolute photometric
+system.  Now, we perform the following iteration:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Assume that all images are photometric and determine $M_{cal,i}$.
+\item Find the corresponding values of $M_{rel,j}$ from equation (\ref{system1}).
+\item Use these $M_{rel,j}$ values to find new values for $M_{cal,i}$.
+\item Find the values of $clouds$ for each image from these $M_{cal,i}$
+\item Assume that any image with a value $clouds$ more than 1 standard
+deviation from the mean value (over images) has a substantial cloud
+layer.  
+\item Return to step 1, but use the iterated $M_{cal,i}$ values for those
+images with substantial clouds.
+\end{enumerate}
+%\DoubleSpace
+This process is continued until \chisq (eq. \ref{chisquare}) does not
+change substantially.  Figure (\ref{fig:Mrel}) shows a histogram of
+the occurrences of different $clouds$ values.  There are a few
+important points to make about this figure.  First, there is a
+concentrated peak at 0.  All of these images have essentially zero
+cloud level.  As one would expect, there are a large number of images
+to the right of this peak.  These are the images which were taken
+through some amount of clouds.  Since the exposures were stopped if
+the clouds got too thick, it is not surprising that these images taper
+off at higher cloud levels.  The most curious and telling part of the
+plot is the area below the 0-cloud peak.  There are many images on the
+``negative cloud'' side of the peak.  Because ``negative clouds'' are
+unphysical, there must be a simple explanation for this.  In fact, 112
+of the 122 images more than 0.02 mag below the peak had exposure times
+of less than 20 seconds.  Since the shutter at MDM is accurate to only
+1 - 2 seconds, it is likely that these images had an exposure time
+which was longer than reported, and therefore have artificially
+enhanced values of $M_{cal,i}$.
+
+        We calculate the error on the relative calibration of each
+image by finding the scatter of the $M_{cal,i}$ values for each image
+and dividing by $\sqrt{N stars}$.  A histogram of this error for all
+images is shown in Figure (\ref{fig:dMrel}).  We also show the
+variation of the formal photometric error reported by \dophot\ with
+magnitude for each filter in Figure (\ref{fig:dm}).  Now that we have
+the values $M_{cal,i}$, we can calculate the values $M_{rel,j}$ for
+every star on every image.
+
+The Pipeline implementation of relative photometry includes the
+possibility for up to third order polynomial terms across the field.
+This is needed to account for the different flat fields, particularly
+between images taken with and without the red-block filter.  
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} \small
+  Pictoral representation of the Average.code flags.  The lower byte
+  value is used for specific definitions of object types.  }
+\end{figure}
+
+To run 'nrphot' by hand, the syntax is: {\tt nrphot (file.cpt)}.
+There are several optional flags, which are listed if you type
+nrphot by itself.
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\tt markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\tt markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\tt markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyrae may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).  It should be noted that the above
+guidelines for variable stars are suggestions only, and to date (July
+7, 1999), no programs currently assign or define these variability flags. 
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\tt addstar} and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts call two main C programs which run the
+images of a given night through the pipeline.  These C programs are
+more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{data and file organization}
+
+There are a set of standard locations for all of the files used and
+created by the Pipeline.  These locations have both abstract names
+used by the pipeline programs and specific definitions used in the
+LONEOS implementation.  In general, the definitions of the files are
+given in the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of spicam (3.0)).  The C programs all refer to the
+config file for the definitions, but the Perl scripts currently have
+the definitions hardwired as variable names defined in the beginning
+of each file.  This should be changed to a mechanism that looks in
+the config file, perhaps implemented by a standard Perl function.
+
+Here is a list of the main directories and their meanings:
+
+logdir:         /metis/d11/logs - all log files and the files used by
+the Perl scripts to control their actions (except locks) go here.
+
+workspace:      /irene/d11/workspace - the intermediate analysis
+stages go here, and the tar, gzipped directory files stay here.
+
+dumpspace:      /pallad/d1      - used by slurp to store images
+downloaded from the tape archive.
+
+database:       /hebe/d27/database      - the result database, as also
+the locks and the Rocks.dat file.
+
+references:     /metis/d11/references   - a variety of reference data,
+including the HST GSC, the USNO catalog, the config files, and so
+forth.
+
+source:         /metis/d11/src/ohana    - all of the programs source, 
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.  
+
+\begin{verbatim}
+database: /hebe/d27/database (also in /metis/d27/database as linked directories).
+ lock files also go in this directory
+workspace: /irene/d11/workspace - temporary storage of result files
+dumpspace: /pallas/d1 - disk to store data dumped from the archive by slurp.
+scriptdir: /metis/d11/logs - all log files
+\end{verbatim}
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\tt lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called
+/pallas/d[1-6]/YYMMDD where 'YYMMDD' is an abbreviation for the current
+night's date (ie, 990223).  Many files use this naming scheme, so we
+will refer to such a name as 'YYMMDD'.  All of the images are stored
+in this directory with names yyyyMMDDxxxxb.fits where yyyy is the full
+year, MM is month, DD is date, and xxxx is a sequence number.  The 'b'
+refers to the 'b' CCD, and the .fits extension is required.  The
+script {\tt lastnight} is called by a cron job scheduled for 7am on
+{\tt hebe.lowell.edu} (note that the clock on hebe is set to PST, not
+local MST - fix this some day!).  The script searches the disks
+{\tt /pallas/d[1-6]} for a directory of the right form (basically any
+directory beginning with a number).  By default, the program demands
+that the directory have the name derived from today's date, but with
+the flag -any, it will accept any directory.  It then checks to see if
+this directory has been already been analysed (ie, it is included in
+the 'processed.log' file).  If not, it lists all files in that
+directory with the right ending (*b.fits) and places these names in a
+file, {\tt /metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file 'extracted.log'.
+When it has successfully ended and identified some data, it calls the
+next script, {\tt stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\tt lastnight} is the Perl script {\tt slurp},
+which looks for data on the tape archive.  This script looks at the
+tape.log file and compares it to the file 'processed.log'.  It tries
+to identify nights listed in the file 'tape.log' which have not been
+included in the 'processed.log'.  If it finds any, it tries to
+download as much of the data as will fit on the disk {\tt /pallas/d1}.
+This script is called from within the {\tt stage1} script and is
+invoked if {\tt stage1} is run without any data already in
+the file 'extracted.log'.
+
+A related pair program is the load/unload C programs which are needed
+for loading and unloading the tape jukebox.  The first, load N, takes
+tape number N and loads it into the tape drive.  The second takes the
+tape a returns it to its slot.  It is important to check on the other
+users of the tape drive to be sure it is not occupied.  This is done
+with the llock, lunlock and llockstat programs.  llockstat lists the
+devices which have been allocated.  llock lets you lock a particular
+service, etc.
+
+\subsection{stage1}
+
+The Perl script {\tt stage1} takes the image list produced by {\tt
+lastnight} or {\tt slurp} (YYMMDD.inlist) and passes the list to the
+controller program {\tt control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\tt
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+'extracted.log'), 2) if the data has been partially analysed (ie, the
+date reference in 'extracted.log' has not been put in 'processed.log',
+but there are entries in the file YYMMDD.outlist), and 3) which data
+needs to be run through which part of the pipeline (ie, it decides
+which of the images in YYMMDD.outlist have succeeded at which stages
+of the analysis, and starts them at the appropriate spot).  These
+features are most useful if the analysis crashes in the middle or
+needs to be restarted.  The {\tt stage1} script is meant to be run
+without any arguments and it will figure out what needs to be done.
+The one possible argument is the -once flag.  This flag tells {\tt
+stage1} to analyse the data it finds and quit when it finishes, and
+not call another instance of itself.  Otherwise, when it is done, it
+will restart itself, and since there is no new data in
+'extracted.log', it will start a slurp process to get data from the
+archive.  If there is no data in the archive either, this process will
+sleep for an hour and try again.  After a few attempts (2 days?), {\tt
+stage1} will give up and quit without restarting itself.  The script
+writes a log file called \$scriptdir/stage1.NN.log where NN is a
+number in sequence between all runs of {\tt stage1}.  A file
+stage1.count keeps track of which number NN we are on.  When {\tt
+stage1} has finished the analysis of a night's data, it writes the
+date in 'processed.log' to let other processes know what has been
+analysed.  The bulk of {\tt stage1} is not dependent on details of the
+LONEOS setup, but it does expect the files to have the naming scheme
+described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\tt stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the 'processed.log file, presumably by {\tt
+stage1}.  Once it finds a new name in this file, it looks for the
+appropriate images in the file 'YYMMDD.addlist'.  It then submits the
+list to the second controlling program {\tt control2}, which runs the
+images through {\tt addstar}.  Images which are successfully run
+through addstar have their *bf.fits (flattened image) and *.obj
+(dophot output) files deleted.  When the entire night is done, the
+rest of the *.obj and *bf.fits images are deleted by {\tt stage2}, the
+directory with the *.cmp and *.log files is tared and gzipped into the
+file YYMMNN.tgz.  The directory is then deleted.  Finally, {\tt
+stage2} calls the scripts {\tt cleaning.pl} and {\tt run.phot} which
+runs the cleanup programs ({\tt markstar - nrphot}) on the database.
+After a successful run, {\tt stage2} will automatically respawn a new
+copy that waits until more data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\tt control1} is allowed to use all machines and {\tt
+control2} can only use one (hebe.lowell.edu, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using ssh) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, flatten,
+astrometry, etc).  Images which successfully run through a queue are
+sent on to the defined 'next' queue, while images which fail are
+instead sent to the defined 'fail' queue.  In most cases, the 'fail'
+queue is a process which marks the image as bad and write the name in
+a file, and then puts the image in the 'done' queue.  However, it is
+possible for the 'fail' queue to be another attempt, such as in the
+case of astrometry.  In this example, images which fail the default
+astrometry are run through a second queue which tries again with the
+-loneos flag set (this flag makes the assumption that the header
+information about the LONEOS region number for the image is correct,
+not the RA/DEC information).
+
+The connections on the remote machines are handled as child processes
+with communication through the stdin and stdout/stderr pipes.
+Messages can be sent back and forth though these pipes, and messages
+which are received from a process associated with an image are written
+to a log file with the name imagename.log (where imagename is the root
+name of the image).  The only required messages from the program are
+messages saying ``SUCCESS'' or ``ERROR''.  The programs therefore all
+end with either of these words.  The programs are started within the
+controller as a command to the shell followed by and echo ``PROCESS
+DONE''.  If the controller sees the message ``PROCESS DONE'' without
+either ``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long
+time), it assumes the program crashed.  Currently, no timeout is
+available for the programs.  The flat-field process is run in mana and
+is a slightly special case.  We avoid re-loading the same flat many
+times by starting a mana process once and running the flatten
+procedures as mana function calls.  The images which are analysed
+(with an indicator of success or failure at each stage) are written to
+a file named 'YYMMDD.addlist' by the {\tt control1} and 'YYMMDD.outlist'
+by {\tt control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling
+programs.  There is a perl program, {\tt locks}, which allows the user to
+set or check the state of the different locks. All programs which
+write to the database check for the existence of a lock on the
+database and refuse to run if it exists.  The control1/2 programs and the
+stage1/2 programs check for their own lock files and only run if they
+don't exist.  Finally, the use can set the lock files 'kill' or 'halt'
+for either stage1 or stage2.  The first tells the process to stop
+immediately, taking care of bookkeeping first.  The second tells the
+process to finish the current set of images but not start a new
+version.  
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or are used by the maintainer to check up or work on
+the pipeline.  The two programs 'checkoutlist' and 'checkaddlist' take
+a list of YYMMDD.outlist or YYMMDD.addlist files and list the number
+of images in the file and the number of successes at each analysis
+stage.  There programs 'cleaning.pl' and 'run.phot' deal with the
+cleanup programs and the running of nrphot.  the program
+'backup.stuff' takes the first 4 characters of the year/month file
+names and backs up to the jukebox tape all tar files for the given
+month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to hebe.lowell.edu.  This
+device is a set of three 9 GB disks merged into one 27GB raid disk.
+The database is stored mostly on this disk and the RAID disk mounted
+on metis.  It is easy to split the database across multiple file
+systems by using links.  Within the database directory, there are
+directories for each of 24 Declination bands (7.5 degrees tall).  The
+easiest way of splitting up the data is to move some of these
+subdirectories to another device and creating links to them at the
+appropriate place.  This is currently done by having a directory
+/metis/d27/database with the remote directories.  
+
+The current problem with the /hebe/d27 RAID results from the poor way
+it was setup.  It was set up without much knowledge of the (at the
+time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script /root/mdstart
+which lists the step to setup the RAID correctly.  It would be helpful
+if the rc.local or rc.sysinit files were fixed to start, fsck and
+mount the RAID automatically at boot.  The setup on metis is
+substantially more mature and is correctly implemented.  It comes up
+when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\tt status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\tt tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\tt status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, {\tt gstars (RA) (DEC) (RADIUS)}
+lists data about the stars within a specified radius of the specified
+location (all numbers above are given in decimal degrees).  Similarly,
+{\tt lcat} lists the catalogs in the region.  Imstats lists statistics
+about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\begin{figure}
+\psfig{file=allsky.ps,width=16cm}
+\caption{\label{allsky} \small
+  Map of the entire sky, and images added to database.  }
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} \small
+  Comparison between HST GSC and photometry database astrometry.  }
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star
+positions.  The crosses are from the photometry database while the
+boxes are from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.5 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: catalog n2230/1951.cpt -m 12 18
+status: style -pt 2
+status: catalog n2230/1951.cpt -m 12 18 -g
+\end{verbatim}
+
+\begin{figure}
+\psfig{file=lightcurve.ps,width=9cm}
+\caption{\label{lightcurve} \small
+  Lightcurve for several image stars.  }
+\end{figure}
+
+Fig.~\ref{lightcurve} shows an example lightcurve from three stars in
+the above field.  The x axis shows the time in seconds, which the y
+axis shows the star magnitudes.  This plot was made with the following
+commands (starting from the previous image): {\small
+\begin{verbatim}
+status: cursor
+1 137.062562 22.791860
+q 137.062562 22.791860
+status: lcurve $R1 $D1 0.01 -l
+status: box
+status: gstar $R1 $D1 0.01
+read 11318 stars from catalog file /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt (22462 total measurements)
+508 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.068619 22.785400 18.438000  1 (2)  1.000000 1.000000
+498 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.062820 22.792747 12.882000  3 (0)  1.000000 1.000000
+501 /host/pikake/d1/gene/loneos/allstars/n2230/1951.cpt 137.064499 22.800817 15.480000  3 (0)  1.000000 1.000000
+\end{verbatim}}
+The last lines show the database information on the three stars.  
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at /metis/d11/src/ohana.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form bin/\$ARCH
+and lib/\$ARCH.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+/metis/d11/ohana/bin/\$ARCH.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in ohana/src/perl, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form ohana/src/program.  The exceptions are gastro (stored in
+ohana/src/astro), and control1/2 (stored in ohana/src/astro).  Also, a
+variety of simple, user-level functions are available in
+ohana/src/misc. 
+
+Most of the ohana package of programs use several common libraries.
+These include the readline library (except for dophot, this is the only
+part of ohana that is not written by Eugene Magnier), which is used
+for command-line interface systems.  Other important libraries are the
+fits library for implementing the FITS specifications in a convenient
+C-friendly environment, and the ohana library, consisting of basic
+string and other basic operations.  
+
+For more details on the programming aspects of parts of the pipeline,
+see the associated document, 'A Programmer's Guide to the Loneos
+Pipeline'
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\tt dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline 
+
+# important files and directories
+IN_DIR                  /pallas
+OUT_DIR                 /irene/d11/workspace
+#
+CATDIR                  /hebe/d27/database
+IMAGE_CATALOG           /hebe/d27/database/Images.dat
+IMAGE_CATALOG_TEMPLATE  /hebe/d27/database/template.cat
+CATALOG_TEMPLATE        /hebe/d27/database/template.cat
+ROCK_CATALOG            /hebe/d27/database/Rocks.dat
+#
+GSCFILE                 /metis/d11/references/GSC/GSCregions.tbl
+GSC_DIR                 /metis/d11/references/GSC
+USNO_CDROM              /metis/d11/references/USNO
+DOPHOT_PARAMS           /metis/d11/references/config/default_parameters
+FLATTEN_SCRIPT          /metis/d11/references/config/flatten.pro
+LONEOS_REGIONS          /metis/d11/references/config/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.03
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               6
+MACHINE0                metis
+MACHINE1                hebe
+MACHINE2                iris
+MACHINE3                irene
+#MACHINE4               juno
+MACHINE4                ceres
+MACHINE5                vesta
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               1
+fMACHINE2               1
+fMACHINE3               1
+fMACHINE4               0
+fMACHINE5               0
+fMACHINE6               0
+
+LOCAL_MACHINE           1  # machine with catalog on local disk
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\section{Creating New Flats}
+
+The LONEOS implementation of the analysis pipeline has a limited
+ability to choose a flatfield image.  There is a mechanism in the
+stage1 script to select a flatfield on the basis of the photcode
+entry.  It works like this:  there is a fixed directory for all
+flatfield files, currently /metis/d11/reference/.  This directory is
+written in the file flatten.pro, and also in the script stage1.  Each
+flatfield has a name like flatcodeN.fits, where N is the relevant
+photcode.  The mana macro 'flatten' in flatten.pro loads the file
+\$flatdir/flatfield.fits (OR SOMETHING LIKE THAT), which is a link to
+the correct flat.  The script stage1 has the job of deciding which is
+the correct photcode and setting the link appropriately.
+
+This then begs the question of how this flatfield file should be
+created and assigned a new photcode.  The flatfield is NOT made
+nightly from the entire set of data, as one might expect.  This is not
+done because of the problems of scattered light in the telescope.  The
+widefield of the LONEOS telescope makes it somewhat succeptible to
+light at relatively large incident angles.  As a result, a median
+image made from images of the night sky will have different amounts of
+scattered light depending on the overall sky brightness.  In our
+experience, the presence of light clouds and just a small moon (as
+little as a quarter) make the resulting median image a very poor
+representation of the chip response.  Our solution to this problem is
+to choose a good night, in which the sky is very dark, and make a
+flatfield from that collection of images.  As a result, there is too
+much decision-making involved to allow the pipeline to make this
+decision.  Instead, we have chosen to only infrequently make a new
+flat from the data, choosing those nights that we are confident will
+not introduce excess scattered light.  
+
+There are a set of scripts and programs to make the flatfield image.
+The process involves first removing the bias and dark from the image,
+by subtracting a dark image, then medianing the resulting images.
+The mana script FRED performs the dark-subtraction and then
+medianfilter performs the medianing.  In fact, instead of medianing,
+medianfilter returns the average of the fraction of pixels with values
+between f1 and f2 percent of the total range of the pixel data. 
+
+\section{Daily Monitoring of the Pipeline}
+
+On a daily basis, the pipeline generally runs by itself without any
+intervention.  There are a few checks that can be made to be sure the
+process is running OK.
+
+First, it is good to see if the disk space is sufficient.  There is a
+component to stage1 which will keep it from running the analysis if
+there is less space on the destination disk (/irene/d11/workspace)
+than 1.1 times the amount of space in the source directory
+(/pallas/d?/YYMMDD).
+
+Second, it is a good idea to see if the nightly cron job is checking
+for new data and if the data is getting analysed.  If data was created
+lastnight, there should be a set of files in the log directory
+(/metis/d11/logs) of the form YYMMDD.inlist, YYMMDD.addlist, and
+YYMMDD.outlist.  If these files do not exist, it may just mean that no
+data was created last night.  In that case, the tail of the file
+/metis/d11/logs/lastnight should say something like 'there is no new
+data to analyse'.
+
+If data was created, and these files exist, it is a good idea then to
+check that the analysis of the images was reasonable and didn't fail
+on most of the images.  There are two Perl scripts to check on this.
+First, 'checkaddlist [filenames]' will take a list of *.addlist files
+and, for each file, list the total number of images, then the number
+that failed for each of the four stage1 processes, flatten, dophot,
+fstat, and gastro.  A typical run might look like this:
+
+\begin{verbatim}
+hebe: checkaddlist 9907??.addlist
+990701: 206 0 0 0 0
+990703: 199 5 0 0 0
+990705: 150 10 1 0 1
+\end{verbatim}
+
+It is actually unusual for any except the flatten process to fail, but
+it might be typical for 1 or 2 to fail, since they will represent
+aborted images or images which failed to write everything to disk.
+The second Perl script is 'checkoutlist' which works just the same
+with the YYMMDD.outlist files, but only give statistics on the
+'addstar' process.  Here, it is more common for several images to fail
+'addstar'.  At the current time, 'gastro' does not return a fail
+status if it finds a bogus solution.   Images which fail 'gastro' are
+mostly those which were taken when the sky was too bright and all that
+is seen is the sky itself, or the focus frames, or the very short
+images taken of bright stars to check the coords.  If the images fail
+'gastro', they are rejected by 'addstar'.  
+
+\section{Restarting the Pipeline}
+
+It is difficult to predict the future, so it is hard to give guidance
+on solving future problems.  Some of the things which might happen
+would include having one of the machines which serve a disk go down or
+having the disks fill up.  If this happens, it is possible that the
+run of a given night will have failed completely, or mostly.  There
+are a variety of things to do to recover from these situations.
+
+\subsection{Deleting data from the archive}
+
+The program 'delstar' lets the user delete a set of data from the
+database.  There are several options for this.  The first example is:
+{\tt delstar 199902040015b.cmp}.  In this form, delstar uses the
+astrometry information in the image header to find the measurements
+and delete them from the database, along with the image from the image
+database.  This form requires the datafile *.cmp to exist in the local
+directory.  The second form, {\tt delstar 911012323 1}, uses the given
+time in standard FORM (NEED TO DISCUSS TIME FORMATS AND GIVE THEM
+NAMES) to identify the image in the image database and delete both the
+image and the measurements.  It is easy to associate time with image
+with the status function 'findimages' or 'gimage' which list images
+covering a specific location.
+
+The third form of delstar is used to clean up the database if an image
+is deleted but not all measurements from that image are removed.  The
+routine 'addstar' uses the astrometric information for an image and
+the X,Y coordinates of each object in the image to locate the object
+in the database.  Several other routines which do the reverse process of
+finding location of objects within the images.  The function which
+performs this association needs to find all database *.cpt files which
+are covered by the image.  The existing implemenation is relatively
+quick, but not the most general possible.  If an image has extreme
+astrometric problems, yet somehow makes it through the pipeline, it
+will introduce stars which are not easily found by the inversion
+process.  This may be because the image has astrometric parameters
+which make it extremely non-rectilinear.  If such an image is deleted,
+which will probably be desired, some of the stars from that image may
+get left behind.  These orphaned stars can be deleted with the command
+{\tt delstar -orphan STUFF}.
+
+\subsection{Deleting a night from the pipeline}
+
+If the analysis for a specific night fails miserably, it is probably
+necessary to delete the entire night and then encourage the system to
+redo that night.  It is easy to delete an entire night with delstar by
+giving a time interval which includes the night in question.  It is
+also easy to find the value of the time in seconds with the status
+function 'ctimes'.  (At some point, delstar should incorporate the
+code from status which does the time format conversion automatically).
+This process will remove the night in question from the database.  But
+before the pipeline can be re-run, the pipeline needs to be forget
+that it ran that night before.  Every night which has been analysed
+gets included in the log files 'processed.log' and 'addstared.log'.
+The appropriate entry from these files needs to be deleted.  It is
+also necessary to delete the files 'YYMMDD.addlist' and
+'YYMMDD.outlist' from the log directory.  If the 'extracted.log' file
+exists, it should be deleted as well.  All of this is predicated on
+the assumption that the user has halted all processing by the pipeline
+before trying to fix anything.  At this point, it is possible to
+restart the database.  This can be done in several possible ways.  If
+the night in question has already been put on tape, it has to be
+extracted.  The program 'slurp' will automatically find data which has
+not been extracted from the tape, download it, and set up the
+appropriate files.  Unfortunately, 'slurp' uses the file 'tape.log'
+which is not automatically generated.  It is therefore necessary to
+add a line to 'tape.log' (in /metis/d11/logs) for the night in
+question.  Instead of actually running 'slurp', however, the user
+should just run 'stage1 -once' which will perform one run of stage1
+and then end.  If there is no pending data (nothing in 'extracted.log'
+that has not been analysed), then stage1 will automatically call
+'slurp' in the correct fashion (ie, on pallas), run through the
+analysis, and then exit without restarting.
+
+If the night's data has not been deleted yet, then it is not necessary
+to run 'slurp' as the script 'lastnight' will do the job.  The
+cronscript for 'lastnight' uses the -today option so that the
+automatic analysis will not reattempt any nights still on pallas.
+Instead, it will be necessary for the user to run 'lastnight' with the
+-any flag, which will also take care of running 'stage1'. This should
+be safe at anytime, as the lock functions keep multiple instances of
+the programs from running, but it is better to do this with enough
+time to allow the process to finish before the next night's data is
+ready for processing.
+
+If the pipeline has been interrupted, it will probably be necessary to
+restart 'stage2' as well.  Since 'stage2' always restarts itself on
+exit, there is no cron job for it to make the initial start.  (This
+probably should be introduced into the /etc/rc.local file, or some
+cron implementation for stage2 worked out).  Note that both 'stage1'
+and 'stage2' take no arguments except the -once flag.  They make their
+own decisions about the correct log file number and so forth.
+
+If the 'lastnight' cron job gets lost, there is a copy of the
+necessary cron script /metis/d11/src/ohana/src/perl/lastnight.cron.
+This can be submitted with 'crontab lastnight.cron'.  
+
+\section{Data backup}
+
+Backups are the still rather primitive in implementation for the
+LONEOS system.  There are two things which should be backed up, but
+only one currently has a good scheme.  The database itself does not
+have a backup process at the moment.  This is a bad situation, but not
+an easy one to solve.  The database is very large, over 30 GB, which
+is larger than the space on a single AIC tape.  At the moment, we are
+satisfied with simply saving the intermediate results directories, all
+of the YYMMDD.tgz files.  If the entire database is destroyed, these
+files can be used to rebuild the database in a relatively short time
+(currently, about a week).  The script 'backup.stuff' will backup a
+group of files.  A good method is to backup a month at a time.  These
+will become a single tar file on the AIC tape, and a month's worth of
+data is a reasonable amount of disk space for future downloads.
+
+\end{document}
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline6.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline6.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/pipeline6.tex	(revision 16632)
@@ -0,0 +1,2047 @@
+%\documentstyle[astro,psfig]{article}
+\documentclass{article}
+\usepackage{psfig}
+\usepackage{astro}
+\usepackage{times}
+\GoodMargins
+\newcommand{\note}[1]{({\bf #1})}
+\newcommand\pr{\em}                   % font for program names
+\newcommand\ff{\bf}                   % font for file names
+\newcommand\cc{\tt}                   % font for program code
+\newcommand\ty{\sc}                   % font for file types
+
+\title{Variability Pipeline}
+\author{Eugene Magnier}
+
+\begin{document}
+\maketitle
+
+\section{Overview}
+
+Ptolemy is a collection of programs which act together to provide
+automated reduction of images, including photometry and astrometry,
+data validation, and incorporation of the resulting measurements in a
+photometry database organized by star position on the sky.  Ptolemy
+was designed to deal with images produced by LONEOS, the Lowell
+Observatory Near Earth Object Search, to study the data stream with
+astronomical goals in mind beyond just the Near-Earth Objects.  The
+document deals with both the generalities of Ptolemy and also the
+specifics of the LONEOS implementation.  Why Ptolemy?  Two reasons:
+First, Ptolemy, the Roman Astronomery (AD 100-170) was the the first
+to make a systematic map of the entire sky visible from Greece, much
+like LONEOS is doing.  Second, Ptolemy I (367-283 BC), as the founder
+of the Library of Alexandria, represents the ideals of collection and
+organization of large quantities of knowledge).
+
+Fig.~\ref{pipeline} shows a schematic of the {\pr Ptolemy} program
+organzation.  Images to be analysed may be provided to Ptolemy either
+from the telescope or from a tape archive.  Images are first analyzed
+by {\pr dophot}, which produces instrumental photometry and pixel
+coordinate positions for stars and other objects in the images,
+writing files with a particular format, called {\ty obj} files in this
+discussion.  The results from {\pr dophot} are cleaned up by a program
+called {\pr fstat} which merges the header information from the image
+with the most relevant parts of the {\ty obj} file, creating a new
+file with the {\ty cmp} format.  Astrometry is performed on the {\ty
+cmp} file with the program {\pr gastro}.  The program {\pr gastro}
+makes a comparison with an astrometric reference database and only
+changes {\ty cmp} header keywords as a result.  Finally, the processed
+image {\ty cmp} file is added to the photometry database with the
+program {\pr addstar}.  The photometry database is maintained in a
+large number of files ({\ty cpt} files), each representing a small
+region of sky.  There is no relationship between the image locations
+and the boundaries of {\ty cpt} file.  All of the preceeding processes
+occur on individual images, and would typically be performed while the
+observations are occuring, or during the day following, but may be
+performed at any time to add new or archived data to the database.
+
+\begin{figure}
+\psfig{file=schematic.eps,width=9cm}
+\caption{\label{pipeline} \small
+  Schematic of the photometry pipeline.  Rectangles represent
+  programs, while ovals represent data products.  Arrows show the
+  direction of travel of information.  The flatten routine is a filter
+  whose position may change as the pipeline matures.  }
+\end{figure}
+
+Once large batches of images have been processed, a series of programs
+should be run to clean up the photometry database.  First, {\pr
+markstar} identifies bad data (the trails of satelites, the bleeding
+columns from stars, ghost images), and flags these data points
+appropriately.  Second, {\pr addusno} matches the catalog stars with
+stars from the USNO database and adds the USNO magnitudes to the
+photometry database.  Next, {\pr markrock} searches for likely
+asteroids in the {\ty cpt} file, marks them, and writes the asteroid
+observations to an asteroid database.  It also notes measurements
+which are likely to be noise and cosmic rays.  Finally, {\pr nrphot}
+determines relative photometric calibrations for observations in a set
+of {\ty cpt} files.
+
+\section{Image Analysis Pipeline}
+\label{parallel}
+
+\subsection{Configuration and Generalization}
+With the exception of {\pr dophot}, all of the Ptolemy programs refer
+to a single configuration file to determine the large number of
+parameters necessary in the process.  The default parameter file is
+hardwired into the programs, but an alternate configuration file may
+be specified with the environment variable {\ff PIPE\_CONFIG}.  This
+option makes independent processing of multiple data sources trivial.
+For example, if the pipeline is to be used for both Loneos and SDSS
+image analysis and display, there could be two configuration files
+(eg, {\ff loneos.txt} and {\ff sdss.txt}), one for each data source.
+Several important parameters would be different between these two, for
+example, the initial plate scale guess for the astrometry routine, or
+the parameters which define the rough chip orientation.  This scheme
+allows for analysis of different types of images, with a common
+destination photometry database, or for independent photometry
+databases.
+
+Data from different sources can be processed by the pipeline and
+stored in the same photometry database, since all photometry is tagged
+with a source ID in the database (as are the images in the image
+database).  This allows us to include, for example, the USNO catalog
+magnitude measurements (or a subset) in the photometry database for a
+quick comparion.  Different sources may be considered different
+filters, so color-color and color-magnitude diagrams could be
+extracted by specifying choices for source catalog.  Currently each
+object has a single primary photometric system, and individual
+observations may be combined to determine that average (eg, if they
+are different photometry sources with roughly the filter bandpass) or
+they may be ignored when calculating relative magnitudes (eg, the USNO
+magnitudes would be ignored).  This may be expanded upon by defining
+multiple average magnitudes and allowing different measurements to
+contribute only to the appropriate average.  The determination of the
+photometry code for a particular image is currently not well defined.
+There are several points in the analysis where the user (or the
+controlling program) may specify the photometry source.  A table
+should be kept in the photometry catalog to define the various
+photometry codes.  
+
+file names: Notice that we use a consistent naming convention through
+the pipeline reductions.  The image is called {\tt foo.fits}, while
+the resulting dophot-produced photometry list is called {\tt foo.obj}.
+
+\subsection{Time representations in Ptolemy}
+
+Every measurement in the Ptolemy database has a time stamp associated
+with it, as do all of the images.  Throughout the software, the time
+is represented consistently using the standard UNIX representation of
+time, which consists of an unsigned integer representing the number of
+seconds since 1970 Jan 01, midnight.  The time used roughly represents
+UT time, though there is some subtlety here.  In reality, the time
+reported at LONEOS is reported by a GPS clock, and therefore uses the
+GPS zero point.  There are small, well defined differences between UT,
+GPS, and WHAT IS THE THIRD ONE?  GPS - UT is a constant NN seconds,
+while UT - OTHER is a function of time, as leap seconds are
+accumulated in one and not the other.  While the programs all refer to
+this seconds representation of GPS time, the user of the programs
+usually has a few more choices.  In {\pr status}, all(?) functions
+which require a time argument expect to see one of three formats. If
+there is a number of the form NNNNNNNNNs, this is assumed to be the
+UNIX seconds form.  If there is a number of the form NNNNNNj, this is
+assumed to be a Julian date.  If there is a number of the form
+YY:MM:DD,hh:mm:ss, this is assumed to be a UT date string.  Note that
+the difference is in the presence of either 's', 'j', or something
+else at the end of the string.  In the case of a date, it is
+acceptable for the separators to be any non-numerical character, and
+there may even be a trailing separator, as long as it is neither 's'
+nor 'j'.  Command arguments which expect a time range may provide one
+of the following units: 's' (seconds), 'm' (minutes), 'h' (hours), 'd'
+(days).  Also, it is only necessary to provide as many significant
+places in the date as desired.  So, if you are interested in the
+images taken on UT 1999 March 03, you could run {\pr images -im
+99:03:03 1d}.  
+
+The validity range of the UNIX seconds representation of time is 143
+years, so this measurement representation will become ambiguous in the
+year 2113.  Note that the Y2K problem is dealt in the date string by
+assuming any date with year smaller that 70 means 21st century, and
+others are 19th century.  Of course, the user may explicitly type the
+full 4 digit year to ensure an unambiguous answer.  Finally, the user
+may refer to the current time as NOW and the current date as TODAY.
+
+\subsection{Flat Fielding -- Mana / Flatten}
+
+Flat fielding is performed on each image with {\pr mana} (see {\pr
+mana} user's guide) using a script which interacts with the Ptolemy
+controlling software.  The script is contained within a file, {\ff
+flatten.pro}, in the references directory.  The script is invoked by
+calling it on the command line when {\pr mana} is started.  If {\pr
+mana} is started with a file name on the command line, that file is
+loaded with in 'input'.  The file defines a macro '{\pr flatten}', and
+also loads the flat-field file.  The flattening process is actually
+done by calling within {\pr mana} the macro {\pr flatten}, with the
+input and output file names as arguments.  By loading the flat-field
+at the start of {\pr mana}, instead of on each execution of {\pr
+flatten}, we save the load time of each flat-field image (which is 2x
+the size of the basic image, being 4byte floats per pixel).  \note{The
+location of the flat field is currently hard-wired in the {\pr
+flatten} script - this should probably be changed in the future.}  The
+macro loads a flatfield with a specific name and location, which is
+actually a link; The higher-level controlling process ({\pr stage1})
+creates a link to the correct flatfield.  This allows the analysis
+process to use different flatfields for different situations.  At
+LONEOS, we currently use a flat field generated from a well-understood
+night.  This is probably not the best solution as the flatfield
+changes with time.  As discussed below, the photometry solution
+program, nrphot, fits a high-order polynomial to the relative
+photometry, allowing for differences from the correct flatfield.
+ 
+\subsection{Photometry -- Dophot}
+
+Photometry is performed using a varient of {\pr dophot}, based on {\pr
+Dophot 2.0} and adapted to streamline processing of many files.  With
+this version of {\pr dophot}, any FITS format data is safely read in.
+Instead of using staticly defined memory blocks for the images, the
+necessary memory is allocated dynamically.  The image is also
+converted to REAL*32 from the given BITPIX for processing.  Finally,
+only a single, complete parameter file is loaded by dophot.  There is
+no option for a modified and a default parameter file.  The parameter
+file to be used is given, along with the input image and the output
+object list on the command line when the program is run: {\cc dophot
+image.fits image.obj parameter\_file}. To achive these changes, the
+code from {\pr dophot} was wrapped within a C program which interprets
+the command line arguments, allocates the necessary memory, and reads
+in the image.  The rest of the processing is performed by {\pr dophot} in
+the standard manner.  
+
+\subsection{Cleanup -- fstat}
+
+After an image is processed by {\pr dophot}, the object file ({\ff
+foo.obj}) is converted to a more-compact, more-complete file called a
+{\ty cmp} file, with a name of the form ({\ff foo.cmp}).  This
+conversion is done with the program {\pr fstat}.  The {\ty cmp} file
+consists of the FITS header from the original image ({\ff foo.fits}),
+with some additional keywords to be used at later stages in the
+analysis, followed by an ASCII list of the interesting data from ({\ff
+foo.obj}).  In this list, types 6 and 8 are excluded, and only the
+following values are kept:
+\begin{verbatim}
+X       Y     Mag   dMag t log(sky) 
+1342.0  106.1 14.166 000 4 3.2
+\end{verbatim}
+Objects with a signal-to-noise ratio lower than a specified cutoff
+({\cc MIN\_SN\_FSTAT}) are also excluded.  Some general information
+about the image is derived by {\pr fstat} (FWHM, saturation and
+completeness limits, number of each dophot type) and stored as
+keywords in the header.  The photometry source must be specified at
+this stage as one of the command line arguments, though the value used
+may be overridden in one of the stages belowe.  The resulting file can
+now stand on its own without reference to the original image.  The
+keywords used by {\pr fstat} include the minimum signal to noise, a
+rough guess at the zero point ({\cc ZERO\_PT}), and four numbers
+defining the format of the {\pr dophot} {\ty obj} file.
+
+\subsection{Astrometry -- gastro}
+
+Astrometry is performed automatically by the program {\pr gastro}.
+{\pr gastro} loads a {\ty cmp} file and determines an initial guess
+for the center coordinates (based on the RA and DEC header keywords).
+The program also uses the configuration information about the plate
+scale and rough orientation of the image to get close to the final
+solution.  Also, the true sky position of the telescope pole may be
+defined to allow astrometry on images taken close to the pole.  The
+comparison is made with the astrometric catalog, which may be the HST
+Guide Star Catalog, or it may be any source if the data is placed in
+the correct format.  \note{the astrometric reference catalog
+is currently stored in an ASCII format with very limited efficiency.
+It would be nice to make a standard format that has a bit of meta-data
+documentation and probably a binary format to save space.}
+
+\section{The Photometry Database}
+
+\subsection{Photometry File Format}
+The photometry database consists of a large number of photometry files
+representing sections of the sky and a file containing information on
+the images incorporated in the database.  These files are called
+alternatively ``region files'' or {\ty cpt} files (because they have
+the extension {\cc .cpt}).  The photometry files are sorted by
+Declination into different directories, each consisting of a band
+7.5\degree\ wide.  These directories have names like n0730,
+representing the band starting at a Declination of +07:30.  The image
+database ({\ff Images.dat}) is stored in the upper level directory of
+this directory tree.  In fact, the locations of the {\ff Images.dat}
+file, the photometry database, and such are all flexible and may be
+changed by altering the configuration file.  
+
+At LONEOS, the database is stored mostly on a RAID disk on {\ff hebe}
+and a RAID disk mounted on {\ff metis}.  It is easy to split the
+database across multiple file systems by using links.  Within the
+database directory, there are directories for each of 24 Declination
+bands (7.5 degrees tall).  The easiest way of splitting up the data is
+to move some of these subdirectories to another device and creating
+links to them at the appropriate place.  This is currently done by
+having a directory{\ff /metis/d27/database} with the remote
+directories.
+
+The name and location of each sky region comes from the Hubble Space
+Telescope Guide Star Catalog.  There is a file, {\ff GSCregions.tbl},
+which can be used to find the region file appropriate for any location
+on the sky.  A number of routines exist to make such a query.
+
+Each photometry file in the photometry database contains all
+observations and all average values for all stars observed within the
+appropriate region on the sky.  The identity of stars is essentially
+determined by their RA and DEC coordinates.  In very crowded regions,
+the end user may need to double check that a neighboring star is not
+contaminating individual detections (see the discusion on {\pr
+addstar} below).
+
+The photometry files are stored in a binary format, both to reduce the
+volume and to speed access.  As a result, the interpretation of the
+data is machine dependent: little endian machines need to swap the
+data intelligently.  Fortunately, this operation is taken care of
+appropriately, if the programs are compiled with the BYTESWAP option
+set as needed, which is automatically set by the Makefile in the case
+of a Linux machine.  For reference, Suns, SGI, and HP are all big
+endian, while PCs and DECs are little endian.  The automatic
+conversion takes place by using the funcions {\tt Fread} and {\tt Fwrite}
+to substitute for the standard C library {\tt fread} and {\tt fwrite}
+functions.  {\tt Fread} and {\tt Fwrite} are told the datatype being read,
+and they know the layout of the bytes for a particular datatype.
+Anytime the definitions of the relevant structures (see below) are
+changed, {\tt Fread} and {\tt Fwrite} must be updated.  Fortunately, there
+is only one file ({\tt Fread.c}), and it has a single byteswapping
+section, making it easy to adjust the code appropriately.
+
+The format of a single photometry database file consists four
+sections:  
+\begin{itemize}
+\item {\bf header} -- this is a standard FITS header with room for comments
+  about the file or whatever.  Since the rest of the file is not a
+  standard FITS file, the SIMPLE keyword is set to False.  The three
+  necessary keywords are NSTARS, NMEAS, and NMISS, which define the
+  sizes of the next three sections.
+\item {\bf average} -- this section contains all average measurement
+  quantities for each star in the file.  There are NSTARS entries, and
+  each entry is the data from a structure of type Average (defined in
+  loneos.h, and discussed in more detail below).  Thus, the total size
+  in bytes of this section can be found by NSTARS*sizeof(Average).
+\item {\bf measure} -- this section contains the individual
+  measurements for each star in the database.  There are NMEAS
+  entries, and like the average section, each entry is a single
+  structure, in this case of type Measure (in loneos.h, see below).
+  All measurements of a single star are consecutive.  The number of
+  measurements for a single star is defined by average.Nm and the
+  starting entry for a single star is given by average.offset.
+  Therefore, the first measurement of a specific star average[500]
+  would be given by measure[average[500].offset], while the second is 
+  measure[average[500].offset + 1], and so forth.  
+\item {\bf missing} -- this section contains references to all missing
+  measurements of a star.  This means all of those occasions when an
+  image enclosed the location of a star in the database, but no star
+  was detected on the image.  Similar to the case of the measure
+  section, each star has a number of missing entries (which may be 0)
+  given by average.Nn, and the first missing entry is given by
+  average.missing.  Each missing entry value is again a structure of
+  type Missing.  Currently, the only data in the structure is the time
+  of the observation, which allows for an unambiguous recovery of the
+  image where the star was missed.
+\end{itemize}
+
+\subsubsection*{Average Structure defined in loneos.h}
+\begin{verbatim}
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm, Nn;  /* number of measurements, missing */
+  short int Xp;               /* scatter in 1/100 arcsec (-327.67 to +327.67 valid range) */
+  short int Xm;               /* 1000*log(chisq) for magnitude measurement */
+  unsigned short int code;    /* an ID code (ie, star, ghost, satelite, etc) */
+  signed int offset;          /* offset to first measurement */
+  signed int missing;         /* offset to first missing obs */
+} Average; /* 28 bytes / Average */
+\end{verbatim}
+The structure above defines the average data stored in the photometry
+database for each star.  Most of the entries are self-explantory, but
+some need a bit of clarification.  The entry {\tt Xm} is the magnitude
+$\chi^2$ value for the star, under the assumption that the star
+brightness is constant.  This $\chi^2$ incorporates the photometric
+errors on each measurement and is stored as 1000 times the logarithm
+of the $\chi^2$ because high dynamic range is not needed.  The entry
+{\tt Xp} is the scatter about the average postion, in 10
+milli-arcseconds.  As discussed above, the values of {\tt Nm} and {\tt
+  Nn} give the number of measurements and missing observations for
+this star, while the entries {\tt offset} and {\tt missing} point to
+the first {\bf measure} and {\bf missing} entry for this star.  The
+entry {\tt M} is the current best average magnitude solution for this
+star (see the section on Relative Photometry).  Finally, the entry
+{\tt code} is an ID code for each object, which may define a variety
+of things about the object.  For example, if the object is known to be
+variable, or if the object is associated with a USNO star, or if the
+object is a measurement of an asteroid.  See below for details of
+these definitions.
+
+\subsubsection*{Measure Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  short int dR, dD;           /* 1/100 of arcsec (-327.67 to +327.67 valid range) */
+  short int M;                /* thousandths of mag (-32.767 to 32.767 valid range) */
+  short int Mcal;             /* image cal mag, thousandths of mag (-32.767 to 32.767 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 to 0.255 valid range) */
+  char dophot;                /* dophot type (1-9) */
+  unsigned short int source;  /* code to identify photometry source */
+  unsigned int   t;           /* time in seconds (0 - 143 years valid range) */
+  unsigned int average;       /* reference to corresponding average entry */
+  /* upper byte of Measure.average stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure; /* 20 bytes / Measure */
+\end{verbatim}
+}
+The structure above defines the individual measurement data stored for
+each observation of each star.  The first two entries, dR and dD, are
+the difference between the average coordinates for this star and the
+coordinates determined for this observation.  Clearly, if this
+residual is too large, the individual measurement will not be
+successfully matched with the average star position.  {\tt M} and {\tt
+  dM} are the instrumental magnitude and error for this measurement,
+after correction for the exposure time and a zero point (defined in
+the configuration file as ZERO\_PT).  The entry {\tt t} determines the
+time of the individual observation.  This is important not only for
+timing purposes, but also to determine the source image for this
+observation.  The time and the entry {\tt source} uniquely determine
+the image in the image database that generated this measurement.
+Furthermore, this correspondence allows for determination of the pixel
+coordinates on the chip, by going throught the image astrometry stored
+in the Image database (see below).  The entry {\tt source} is a code which
+identifies the particular CCD/Telescope/Filter setup.  Each unique
+{\tt source} should be treated as an independent filter set for the
+purposes of accurate relative photometric comparisons.  This entry
+also allows external catalog data, such as the USNO or Sloan
+photometry, to be added to the database, as desired.  The entry {\tt
+  average} is a pointer back to the {\bf average} section to allow
+determination of the star from the measurements, in addition to the
+reverse.  The bits of the upper byte of this value are reserved for
+flags used to define particular situations for this measurement.
+Possible values are:
+\begin{itemize}
+\item 1 = BLEND\_IMAGE - the star on the image matched more than one
+  catalog star
+\item 2 = BLEND\_CATALOG - the star in the catalog matched more than
+  one image star
+\item 4 = UPPER\_LIMIT - \note{not really used?}
+\item 8 = CALIBRATED - relative photometry has been performed at least
+  once.
+\end{itemize}
+The entry {\tt dophot} stores the dophot type for this particular
+measurement (1-9: four extra bits in this field).   
+Finally, the value {\tt Mcal} determines the photometric calibration
+of this specific measurment.  This value is an offset appropriate to
+this image (and if needed, this point in time and this chip position)
+to bring the observations of the stars on multiple images to a common
+system (see the section on relative photometry).
+
+\subsection{Image Database}
+
+All images for which photometry has been included in the photometry
+database also have entries in an image database.  The image database
+is (currently) a single file in the upper directory of the photometry
+database.  The name of the file is determined by the IMAGE\_CATALOG
+entry in the configuration file, and is currently set to Images.dat.
+Like the photometry database files, the image database consists of a
+FITS header followed by binary data.  There is only one type of binary
+data: each image has an entry, which is the data from a structure of
+type Image (loneos.h).  The number of images in the file is determined
+by the {\tt NIMAGES} keyword.  If the number of images becomes too
+large, extrapolation of the system to a set of image database files
+with a reference list is quite straightforeward, and could be modeled
+on the organization of the region files (eg, one image database file
+for each Declination directory).
+
+\subsubsection*{Image Structure defined in loneos.h}
+{\small
+\begin{verbatim}
+typedef struct {
+  Coords         coords;            /* 120 bytes */
+  unsigned int   tzero;             /* readout time row 0 in sec (0 - 142 years valid range) */
+  unsigned int   nstar;             /* number of stars on image */
+  short int      secz;              /* thousanths of airmass (valid range -32.000 -- 32.000) */
+  short int      NX, NY;            /* dimensions of image */
+  short int      apmifit, dapmifit; /* aperture correction and error in thousandths of mag */
+  short int      source;            /* identifier for CCD (each ever used will have a unique letter) */
+  short int      Mcal;              /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      dMcal;             /* thousandths of mag (-32.000 -- 32.000 valid range) */
+  short int      Xm;                /* 10*log(image chi-square) */
+  char           name[32];          /* name of original image */
+  unsigned char  detection_limit;   /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  saturation_limit;  /* tenths of mag (0.0 - 25.6 valid range) */
+  unsigned char  cerror;            /* astrometric error: 1/50 of arcsec (0 -- 5.12 valid range) */
+  unsigned char  fwhm_x, fwhm_y;    /* PSF terms in 25*arcsec (valid range 0.0 -- 10.2" ") */
+  unsigned char  trate;             /* 10000 * scan rate in sec/pix (0 -- 0.0256 valid range, 
+                                       typically 0.0146. this is used only to determine the time
+                                       of the observation, not to find the coordinates.  1 byte
+                                       gives 0.11 sec accuracy */
+  float          exptime;           /* exposure time, seconds */
+  char           code;              /* flag to mark an image as bad or whatever */
+  char           dummy[21];         /* extra space for the future */
+  short int      order;             /* number of terms used for Mrel */
+  short int      Mx, My;
+  short int      Mxx, Mxy, Myy;
+  short int      Mxxx, Mxxy, Mxyy, Myyy;
+  short int      Mxxxx, Mxxxy, Mxxyy, Mxyyy, Myyyy;
+} Image;  /* 240 bytes / Image */
+\end{verbatim}}
+
+The structure above lists all of the data stored for each image.  A
+substantial amount of information is stored for each image.  First,
+the astrometric calibration information is stored in a {\tt Coords}
+structure (see coordinate systems, above).  The upper and lower limits
+of the photometry in the database (in instrumental magnitudes) is
+stored in {\tt detection\_limit} and {\tt saturation\_limit}.  These
+values are useful for comparison for those stars where observations
+are missing.  The relationship between time and pixel coordinates is
+given by {\tt tzero} and {\tt trate}.  Drift images will have a scan
+rate stored in {\tt trate}, while staring images will have a value of
+0.0 for this entry ({\tt tzero} then applies to the whole image).
+Other important parameters are kept: the astrometric error ({\tt
+  cerror}), the airmass ({\tt secz}), the exposure time ({\tt
+  exptime}), the number of stars detected ({\tt nstar}), the FWHM
+values ({\tt fwhm\_x, fwhm\_y}), the image name ({\tt name}), and the
+size of the image ({\tt NX, NY}).  The entry {\tt source} is used as
+above to define the CCD/Telescope/Filter used for this observation.
+The entry {\tt code} is used to flag images in various ways.
+Currently, only two bits are used, to define if the image has been
+photometrically calibrated and if the calibration is acceptable.
+There are 21 extra bytes are stored for future additions.
+
+\subsection{Data Incorporation -- {\pr addstar}}
+
+Images which are completely processed ({\pr dophot, fstat, gastro}) are
+then incorporated into the photometry database with the program {\pr 
+addstar}.  This program decides which region files are appropriate
+for this particular image, then one-by-one adds stars from the image
+to the appropriate region file.  Stars already in the catalog are
+matched with stars in the new image purely by a positional comparison.
+In order to avoid the difficulty of comparisons in the RA and DEC
+coordinate frame, a cartesian projection is performed.  The stars from
+the image being processed and the database stars in the same area are
+projected onto a tangent plane and positional comparisons made in this
+(locally cartesian) coordinate frame.  This avoids the dangerous
+singularities at the pole and also makes the RA 0,360\degree\ boundary
+a trivial problem.  
+
+Several choices must be made in the comparison process.  If a star in
+the catalog is matched with a star in the image, the new measurements
+of that star are added to the database.  If a star in the database
+lies in the field of the image, but is not detected, this information
+is added to the list of missing data.  The only data stored in this
+case is the time and source, which is sufficient to unambiguously
+identify the source image from the image database.  This allows later
+programs to find relevant statistics from the image database, if
+necessary.  If a star is detected in the image, but is not already in
+the database, a new entry is added to the database.  In addition, the
+same ``missing data'' from all previous observations images which have
+covered this location (ie, images already in the image database) are
+included.  This last step is necessary so that the image processing
+order is not important.  
+
+Stars also run the danger of being crowded together.  Since all
+comparisons are performed on the basis of position alone, crowded
+fields may make for ambiguous cross-identifications.  A pair of stars
+are matched if the difference in their positions is less than a
+specified search radius (dependent on the scatter in the astrometric
+solution for the image).  If more than one catalog stars are correlated
+with a star in an image, the new measurement is added to {\em both}
+catalog stars, and a flag is set noting that this observation had a
+blended IMAGE.  Conversely, if a single catalog star is matched with
+more than one image star, both new measurements are added to the one
+catalog star, and a different flat is set, noting that this
+observation had a blended CATALOG.
+
+\section{Catalog Update and Cleaning}
+
+Occasionally, once a large number of images have been added to the
+photometry database, a set of programs should be run to clean and
+update the {\ty cpt} files.  This may best be done on {\ty cpt} files after a
+night's worth of data is incorporated.  These routines define bad
+data, identify the USNO catalog stars, and search for asteroids and
+other junk.  Most of the results from these routines are the addition
+of object flags to the Average data structures (Average.code).  Most
+of these routines process data within a single {\ty cpt} file at a time.
+
+\subsection{Markstar}
+
+The first of the update programs, {\pr markstar}, identifies bad data
+and flags it.  It makes three types of identifications: bright stars,
+ghost stars, and trails.  In the first case, it searches the HST guide
+star catalog for bright stars within the field of the current {\ty cpt}
+file.  Three types of pixels are flagged for bright stars.  Any
+measurements within a circular region centered on the star are suspect
+(the ``halo'' of the bright star).  Second, points along the X axis
+are likely to contain flux from the diffraction spikes.  Finally,
+points along the Y axis are likely to have bleeding in addition to the
+diffraction spikes.  Each of these three regions has a different size
+and range which must be defined in the configuration file.  The
+regions are represented by a representative magnitude and a scale
+parameter.  For example, the diameter $d$ of the halo for a star with
+magnitude $m$ is defined as 
+$d = \mbox{BRIGHT\_HALO\_SLOPE} (m - \mbox{BRIGHT\_HALO\_MAG})$.  The X and
+Y axis points are defined by the length of the diffraction spike, with
+an equivalent formula, and the width of the spike.  Since these are
+each independent, there are 8 parameters to define the exclusion
+regions of bright stars.  One of the current drawbacks of this system
+is the reliance on the HST Guide Star photometry.  In the HST Guide
+Star Catalog, only one photometry band is given, so no color
+information is available.  The parameters currently used were defined
+based on a large number of bright stars, with no adjustment for the
+different effective filter system of the Loneos telescope and the HST
+GSC.  Thus, occasionally very red stars will be several magnitudes
+brighter in the real data than reported in the catalog.  As a result,
+large numbers of bad data points in these halos and spikes may be
+missed.  
+
+The second type of bad data flagged by {\pr markstar} are the trails
+from satelite and other space junk.  This portion of the program
+searches for objects which land along a line and which have a high
+linear density.  Parameters may be adjusted to define the width and
+the necessary density or number of points in the line.  Objects in
+lines are also only identified if all observations come from a common
+image.  If an object only has one measurement and it is in a trail,
+the entire Average is flagged to be bad.  However, if an object has
+many measurements and only one is bad, the object is only flagged as
+having some bad data points.  
+
+The third type of bad data are ghost star images.  The HST GSC is
+searched for stars projected across the telescope optical axis, which
+is defined by the user.  All objects within a region of fixed size are
+marked for ghost stars brighter than a specific cutoff magnitude.
+Similar to the trails, the average is marked as bad only if all
+detections of an object are ghost images.  Otherwise, it is noted that
+some data may be bad.
+
+To run 'markstar' by hand, the syntax is: {\pr markstar (file.cpt)}.
+There are several optional flags, which are listed if you type
+markstar by itself.
+
+\subsection{Addusno}
+
+The program {\pr addusno} makes two types of identifications of stars
+with the USNO catalog.  First, it searches for coincidences within a
+small, specified radius.  The choice of this radius is somewhat
+tricky: it is important to catch the association, but also to avoid
+making too many associations.  Unfortunately, astrometric errors in
+the USNO catalog make it necessary to choose a surprisingly large
+radius of 5\asec.  To avoid making double matches (matching the two
+USNO stars to the same photometry database object), only the USNO
+object closest to the object is associated.  There are also a
+substantial number of stars with significant proper motion between the
+USNO epochs and the current date.  It is not unusual to see 8-15\asec\ 
+discrepancy for specific stars.  To catch these objects, any objects
+which do not match the USNO database, but which have more than a
+minimum number of measurements (2 or 3?) are searched for more distant
+USNO companions.  A large, user-specified radius is used for this
+search.  Of course, only USNO stars which are not already matched to
+the database may be candidates for the proper motion match.  This
+stage is susceptible to errors in that a slow-moving solar-system
+object may be associated with a faint USNO star.  For this reason,
+objects flagged as high proper motion stars should be taken with some
+caution.  Of course, during the {\pr addusno} stage, no objects
+already flagged as bad by {\pr markstar} will be matched with USNO
+stars.  
+
+To run 'addusno' by hand, the syntax is: {\pr addusno (file.cpt)}.
+There are several optional flags, which are listed if you type
+addusno by itself.
+
+\subsection{Markrock}
+
+Once stars have been identified with the USNO database, it is possible
+to search for asteroid detections.  The program {\pr markrock}
+searches within a specific {\ty cpt} file for objects which are moving along
+straight lines in (X,Y,t) space.  In order for an object to be found
+by {\pr markrock}, it must have three points, each with only single
+measurements.  The third point must land within a specified distance
+of the line projected from the first two data points.  These
+comparisons are made in the three dimensional space of image position
+and time.  Also, objects are only accepted if they have a speed less
+than a threshold.  If an object is moving too fast, it will make a
+streak on each individual image and will probably be missed anyway.
+Moving objects detected in this way are flagged in the photometry
+database and are also written to a Rock database.  Currently, the Rock
+database just contains ASCII lists of the RA, DEC, Mag, and time for
+each detection.  In fact, the data are stored in pairs of detections,
+with the middle detection saved twice.  This format makes it easy to
+plot lines connecting the points using the connect-the-dots plotting
+style of status/kapa (see below).
+
+One of the current drawbacks of {\pr markrock} is the insistence on
+three observations with only 1 measurement each.  If an object is
+moving too slowly, two of the dectections of the object may be merged
+together.  Enough data is stored in the database to extract these
+individual measurements, so a more sophisticated search is possible.
+It is also currently the case that USNO proper motion stars are
+ignored, but some of these will be asteroid detections which are
+simply too close to a faint USNO stars (it has to be faint because it
+would otherwise be associated with a star in the photometry
+database).  
+
+To run 'markrock' by hand, the syntax is: {\pr markrock (file.cpt)}.
+There are several optional flags, which are listed if you type
+markrock by itself.
+
+\section{Relative Photometry -- nrphot}
+
+Once the data has been incorporated in the photometry database and the
+data validation routines have been run, it is possible to determine
+photometric solutions for all of the images.  The program which does
+this is nrphot.  It tries to find a set of solutions for each image
+which reduce both the scatter per image and the scatter per star.
+\note{the following section is taken from Magnier et al
+1992, A\&A Supp 96, 379.  It could use a little editing to fit the
+reality of the LONEOS implementation.}
+
+In order bring the different measurements to a common photometric
+system, relative photometry was performed to determine calibrations
+for each image.  We used multiple measurements of individual stars on
+overlapping images to connect neighboring images.  It is useful to
+discuss some of the details of this process.  
+
+A typical photometry equation can be written in a form such as:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{\Delta\lambda}*(\Delta\lambda) \\
+\label{M_mag}
+\end{equation}
+where $m$ is the instrumental magnitude,
+\begin{equation}        
+m = -2.5\log(N_{e}) + 2.5\log(t). \\
+\label{inst_mag}
+\end{equation}
+$N_{e}$ is the number of electrons measured in a single star, $t$ is
+the exposure time for the image, $M_{app}$ is the apparent magnitude
+of the star in the standard system, $\zeta$ is the airmass of the
+image, and $\Delta\lambda$ is the value of a color index (\ie\ $B-V$
+or $V-I$) for the particular star.  The subscript $\lambda$ refers to
+the filter and the subscript $\Delta\lambda$ refers to the color
+index.  Notice that we are ignoring the second-order color-airmass
+crossterm, and any higher order terms in $\Delta\lambda$ or $\zeta$.
+In all situations, $c_{\lambda}$, $a_{\lambda}$, and
+$\gamma_{\Delta\lambda}$ are calibration coefficients dependent on the
+instruments and the site.  The term $c_{\lambda}$ is a factor to scale
+the response of the detector.  The terms $\gamma_{\Delta\lambda}$ and
+$a_{\lambda}$ give the variation of the sensitivity with the color of
+the star and the airmass.  Also, Eqn. (\ref{M_mag}) is only valid for
+photometric conditions.  Under non-photometric conditions, we need to
+add another term to account for clouds:
+\begin{equation}        
+M_{app} = c_{\lambda} + m + a_{\lambda}*\zeta + \gamma_{\Delta\lambda}*(\Delta\lambda) + clouds \\
+\label{M_cloud}
+\end{equation}
+Now, we can regroup the terms in (\ref{M_cloud}) as follows:
+\begin{equation}        
+m = [M_{app} - \gamma_{\Delta\lambda}*(\Delta\lambda)] - [c_{\lambda} + a_{\lambda}*\zeta + clouds]
+\label{M_sep}
+\end{equation}
+Of the two terms on the right side of equation (\ref{M_sep}), the variables
+in the first pair of brackets are dependent on the properties of the
+star, those in the second pair of brackets are dependent on the image parameters,
+except for $c_{\lambda}$ which is independent of both image and star.
+We can now define the ``relative magnitude'' and the ``calibration
+magnitude'' from (\ref{M_sep}) as follows:
+\begin{eqnarray}
+        m       & = & M_{rel} + M_{cal} \label{rel_phot1}\\
+        M_{rel} & = & [M_{app} - \gamma_{\Delta\lambda}*(\Delta\lambda) + \Delta] \label{color}\\
+        M_{cal} & = & - [c_{\lambda} + a_{\lambda}*\zeta + clouds + \Delta] \label{M_cal}
+\end{eqnarray}
+where $M_{rel}$ is the relative photometric magnitude of the star in
+the internal system and $M_{cal}$ is a correction factor to convert
+instrumental magnitudes to relative magnitudes.  The terms $\Delta$
+are included in eqs. (\ref{color}) and (\ref{M_cal}) to make explicit
+the fact that an arbitrary constant can be added to $M_{rel}$ and
+subtracted from $M_{cal}$.  The goal of relative photometry is to
+determine $M_{cal}$ for each image, then use this $M_{cal}$ to find
+$M_{rel}$ for all stars from eq. (\ref{rel_phot1}).  Once one has
+$M_{rel}$ for each star, one can then convert them to a standard
+system ($M_{app}$) using an equation of the form of
+Eqn. (\ref{color}).  In the case of the LONEOS photometry, the absence
+of a filter makes an effective bandpass which is so wide that it may
+be meaningless to force it to a specific, standard filter.  For the
+sake of variability measurements, it is probably more sensible simply
+to refer to the LONEOS system magnitudes and present a set of color
+terms which give the rough relationship between stars of various
+colors and the LONEOS system. 
+
+In fact, the discussion above make a significant simplification which
+assumes that all images will have a single calibration magnitude
+$M_{cal}$.  In fact, it is the case in the LONEOS system that a
+variety of effects introduce systematic variations across the images.
+For this reason, in practice we extrapolate the above discussion to a
+situation where the value of $M_{cal}$ is allowed to be a function of
+position, and is fit with a 2-D polynomial of some degree.  With the
+LONEOS system, we allow the fit to take polynomials of up to 4th
+order, but only accept the minimum order which significantly reduces
+the scatter for the particular image.
+
+        An equation of the form (\ref{rel_phot1}) exists for each star
+detected on each image.  As described, the value $m$ depends on both
+the particular image and the particular star, the value of $M_{cal}$
+only depends on the image, and the value of $M_{rel}$ only depends on
+the particular star.  Let us label the images with the subscript $i$
+and the stars with the subscript $j$.  Equation (\ref{rel_phot1}) can
+then be written in the form:
+\begin{equation}
+m_{i,j} = M_{rel,j} + M_{cal,i} \label{rel_phot}
+\end{equation}
+Of course, $m_{i,j}$ only exists for certain combinations of images
+and stars: not all stars appear on all images.  In the entire system
+of equations, only one value of $\Delta$ (from eqs. \ref{color} and
+\ref{M_cal}) can be used, but, as noted above, the {\em value}\ of
+$\Delta$ is arbitrary.
+
+        In equation (\ref{rel_phot}), both $M_{rel,j}$ and $M_{cal,i}$
+are unknown quantities.  We can use a method of least squares to find
+these values for the entire set of data.  We try to minimize the chi
+square, defined as:
+\begin{equation}
+\chisq = \sum_{i,j}(m_{i,j} - M_{rel,j} - M_{cal,i})^2 / \sigma_{i,j}^2 \label{chisquare}
+\end{equation}
+where $\sigma_{i,j}$ is the error in the measurement $m_{i,j}$, and
+the index $i$ runs over all images, while the index $j$ runs over all
+stars which are multiply measured, \ie\ those stars which appear on more
+than one image.
+
+        We attempt to minimize \chisq\ analytically by finding the
+derivatives of \chisq\ with respect to $M_{rel,j}$ and $M_{cal,i}$
+and setting them equal to zero:
+\begin{eqnarray}
+\frac{\partial\chisq}{\partial M_{rel,j}} = \sum_{i}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0  \nonumber \\
+\frac{\partial\chisq}{\partial M_{cal,i}} = \sum_{j}-2(m_{i,j} -
+M_{rel,j} - M_{cal,i}) / \sigma_{i,j}^2 = 0
+\end{eqnarray}
+In these summations, the index $i$ runs over all images in which star
+$j$ appears, and the index $j$ runs over all stars which appear on
+image $i$ which are multiply measured.  Solving the equality leads to
+the following system of equations:
+\begin{eqnarray}
+R_{j}M_{rel,j} = \sum_{i}(m_{i,j} - M_{cal,i}) / \sigma_{i,j}^2 \label{system1} \\
+R_{i}M_{cal,i} = \sum_{j}(m_{i,j} - M_{rel,j}) / \sigma_{i,j}^2 \label{system2}
+\end{eqnarray}
+where 
+\begin{eqnarray}
+R_{i} = \sum_{j}\frac{1}{\sigma_{i,j}^2} \nonumber \\
+R_{j} = \sum_{i}\frac{1}{\sigma_{i,j}^2} 
+\end{eqnarray}
+Again, the index $i$ runs over all images in which star $j$ appears,
+and the index $j$ runs over all stars which appear on image $i$, with
+the restriction of multiple measurements.  The term $\Delta$ from
+eqs. (\ref{color}) and (\ref{M_cal}) acts as an arbitrary zero point
+between the relative and apparent photometric systems.
+
+        Equations (\ref{system1}) and (\ref{system2}) are a set of
+$N_{images} + N_{stars}$ linear equations with $N_{images} +
+N_{stars}$ unknowns.  The unknown parameters are the terms $M_{rel,j}$
+and $M_{cal,i}$.  Unfortunately, $N_{images} + N_{stars}$ is a number
+on the order of 5000 - 10000, thus an analytical solution is
+impractical and an iteration method must be used.  A simple iteration
+method is as follows:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Guess at values for each $M_{cal,i}$.
+\item Use equation (\ref{system1}) to find values for $M_{rel,j}$.  
+\item Substitute these $M_{rel,j}$ values into (\ref{system2}) to get a new
+set of $M_{cal,i}$ values.  
+\item Return to step 1.
+\end{enumerate}
+%\DoubleSpace
+This process is repeated until some criterion is reached, such as the
+\chisq\ no longer changes or reaches a desired minimum.  Although a
+minimum can be found, error propagation causes severe problems
+since images are only connected to neighboring images.  The end point
+images are connected by \approx 50 intermediate images, and errors
+propagating over such a long distance can cause severe errors.  Also,
+$M_{rel,j}$ and $M_{cal,i}$ are not uniquely defined, because of the
+term $\Delta$.  Therefore, during the iteration process, the values of
+$M_{rel,j}$ and $M_{cal,i}$ tend to wander and do not tend to converge
+($M_{cal,i}$ may be incorrect by typically 0.5 mag).  These problems
+can be overcome if some of the values $M_{cal,i}$ or $M_{rel,j}$ are
+known.  In this situation, the known values can be held fixed,
+providing a reference point for the remaining values.  If enough
+values are known across a large enough portion of the data, no image
+is separated from the fixed values by many images, and errors will not
+build up.
+
+        Images taken under photometric conditions provide a set of
+known $M_{cal,i}$ which can be held fixed.  This is true since, if the
+image is taken under photometric conditions, the term $clouds$ in eq.
+(\ref{M_cal}) is by definition 0.  The other terms in this equation
+are either known ($a_{\lambda}*\zeta$) or are constant for all images
+($c_{\lambda}$) and can thus be assigned to a set value, which can
+later be removed with the zero point calibration.  We make an initial
+assumption of the value of $a_\lambda$, but use the data themselves to
+determine a best fit choice for $a_\lambda$.  The task that remains is
+to determine which images were photometric.
+
+        Since the conditions during observations varied greatly from
+night to night, we decided to determine which images were photometric
+from the images themselves.  To do this, we used a variation on the
+iteration method described above.  Before starting the iterations, we
+assume a value for $c_{\lambda}$.  We can choose this arbitrarily, and
+correct for our choice in the correction to an absolute photometric
+system.  Now, we perform the following iteration:
+
+%\SingleSpace
+\begin{enumerate}
+\setlength{\parskip}{-0.05in}
+\item Assume that all images are photometric and determine $M_{cal,i}$.
+\item Find the corresponding values of $M_{rel,j}$ from equation (\ref{system1}).
+\item Use these $M_{rel,j}$ values to find new values for $M_{cal,i}$.
+\item Find the values of $clouds$ for each image from these $M_{cal,i}$
+\item Assume that any image with a value $clouds$ more than 1 standard
+deviation from the mean value (over images) has a substantial cloud
+layer.  
+\item Return to step 1, but use the iterated $M_{cal,i}$ values for those
+images with substantial clouds.
+\end{enumerate}
+%\DoubleSpace
+This process is continued until \chisq (eq. \ref{chisquare}) does not
+change substantially.  Figure (\ref{fig:Mrel}) shows a histogram of
+the occurrences of different $clouds$ values.  There are a few
+important points to make about this figure.  First, there is a
+concentrated peak at 0.  All of these images have essentially zero
+cloud level.  As one would expect, there are a large number of images
+to the right of this peak.  These are the images which were taken
+through some amount of clouds.  Since the exposures were stopped if
+the clouds got too thick, it is not surprising that these images taper
+off at higher cloud levels.  The most curious and telling part of the
+plot is the area below the 0-cloud peak.  There are many images on the
+``negative cloud'' side of the peak.  Because ``negative clouds'' are
+unphysical, there must be a simple explanation for this.
+
+        We calculate the error on the relative calibration of each
+image by finding the scatter of the $M_{cal,i}$ values for each image
+and dividing by $\sqrt{N stars}$.  A histogram of this error for all
+images is shown in Figure (\ref{fig:dMrel}).  We also show the
+variation of the formal photometric error reported by \dophot\ with
+magnitude for each filter in Figure (\ref{fig:dm}).  Now that we have
+the values $M_{cal,i}$, we can calculate the values $M_{rel,j}$ for
+every star on every image.
+
+To run 'nrphot' by hand, the syntax is: {\pr nrphot (file.cpt)}.
+There are several optional flags, which are listed if you type nrphot
+by itself.  \note{discuss the optional flags in some detail}
+
+\begin{figure}
+\psfig{file=flags.eps,width=9cm}
+\caption{\label{flags} \small
+  Pictoral representation of the Average.code flags.  The lower byte
+  value is used for specific definitions of object types.  }
+\end{figure}
+
+\subsection{Data Flags}
+
+The identifications made by the above routines are noted as a set of
+flags in the Average.code structure entry.  Some of these flags are
+mutually exclusive, so a certain bit may have more than one meaning,
+depending on the value of other bits.  Figure~\ref{flags} shows a
+pictoral representation of the meaning of the different bit fields.
+The uppermost bit (bit 15) determines if the object may be considered
+a ``fixed'' star or something which has no fixed location.  If it is
+not fixed, and this bit is 1, then there are several options.  The
+second uppermost bit (bit 14) will be set if this object is one of the
+three types of bad data flagged by {\pr markstar}.  The lower byte of
+code is used to define the type of bad data: ghost, trail, or bleed.
+Thus, any datapoints determined to be a satelite trail will have a
+code value of 0xc002 (49154 decimal).  If an object is a moving
+object, but not a bad datapoint, it may be identified as a ``rock''
+(an asteroid) by the program {\pr markrock}.  In this case, the flag
+for an asteroid is turned on (bit 13).  Thus anything identified as a
+rock by {\pr markrock} will have a code value of 0xa000.  The lower
+byte of code is not yet defined for asteroids, but could be reserved
+for distinguishing different classes of asteroids (ie, on the basis of
+orbital speeds, and so forth).  Objects which are fixed may have a
+variety of possible flags.  First, an object may be identified with a
+USNO star (bit 14).  It may be found to exhibit variability (bit 13),
+implying that the relative photometry routine should ignore it.  If
+may be a transient object (bit 12).  Note that, while an object
+associated with a USNO object may not be transient, an object which is
+variable may also not be associated with a USNO object.  Thus, we need
+seperate bits for variable vs transient.  Different types of variable
+objects may be represented with different values of the lower byte.
+For example, a Cepheid may have a specific lower byte code of 0x01,
+which an RR Lyrae may have a lower byte code of 0x02.  Thus a Cepheid
+associated with the USNO catalog would have a total code value of
+0x6001. Finally, any of these types of non-moving objects may have
+some bad individual measurements (bit 12) or may be found to have a
+significant proper motion (bit 11).  It should be noted that the above
+guidelines for variable stars are suggestions only, and to date (July
+7, 1999), no programs currently assign or define these variability flags. 
+
+\section{Holding it Together}
+
+The preceeding sections describe the step-by-step analysis and
+incorporation of the data from individual images.  However, the power
+of the Pipeline comes in applying it to large numbers of images.  At
+LONEOS, we are using four Pentinum II computers to analyse the roughly 200
+images that are observed each night.  
+
+It is best to think of the analysis of images occurring on groups of
+images from a given night.  Of the set of processes discussed above,
+those in section \ref{parallel} are performed on individual images
+essentially independently of the other images.  The rest of the steps,
+both the data incorporation ({\pr addstar}) and the database cleaning
+routines occur on the entire batch, one image at a time.  Thus, the
+former routines can easily be run in parallel, but the latter routines
+are run in serial to avoid having two programs writing to same part of
+the database at the same time.  In this model, we would process all of
+the images from a night through the parallel stage of the analysis and
+then run the serial stage only after the entire night is finished in
+the parallel stage.  We thus have a natural division of the pipeline
+into two stages.  
+
+The implementation of the two stages involves several programs, some
+of which are specific to the LONEOS situation, and others which are
+more general.  There are two layers of programs which enable batch
+processing of many images and repeated batch processing over many
+nights.  At the highest level, are Perl scripts which choose what data
+needs to be analysed and when.  These scripts tend to be more
+dependent on the details of the LONEOS implementation. At the next
+level down, these scripts principally call two C programs which run
+the images of a given night through the pipeline.  These C programs
+are more general and do not depend on the details of the LONEOS
+implementation.  A defined set of files holds a log of the nights and
+images that have been processed, both for the information of people
+who might want to monitor the progress, but also used by the programs
+to guide decisions about what to analyse next.
+
+\subsection{Data and File Organization}
+
+There are a set of standard locations for all of the files used and
+created by Ptolemy.  These locations have both abstract names used by
+the pipeline programs and specific definitions used in the LONEOS
+implementation.  In general, the definitions of the files are given in
+the configuration file, 'config.txt' (currently located in a
+hard-wired location, but this may soon change to the mechanism used by
+the lastest version of {\pr spicam} (3.0)).  The C programs all refer
+to the config file for the definitions, but the Perl scripts currently
+have the definitions hardwired as variable names defined in the
+beginning of each file.  This should be changed to a mechanism that
+looks in the config file, perhaps implemented by a standard Perl
+function.
+
+Here is a list of the main directories and their meanings:
+
+{\bf logdir: {\ff /metis/d11/logs} - all log files and the files used
+by the Perl scripts to control their actions (except locks) go here.
+
+{\bf workspace}: {\ff /irene/d11/workspace} - the intermediate
+analysis stages go here, and the tarred, gzipped directory files stay
+here.
+
+{\bf dumpspace}: {\ff /pallas/d1} - used by slurp to store images
+downloaded from the tape archive.
+
+{\bf database}: {\ff /hebe/d27/database} - the result database, and
+also the locks and the {\ff Rocks.dat} file.
+
+{\bf references}: {\ff /metis/d11/references} - a variety of reference
+data, including the HST GSC, the USNO catalog, the config files, and
+so forth.
+
+{\bf source}: {\ff /metis/d11/src/ohana} - all of the programs source,
+binaries, and scripts relevant to running the Pipeline are contained
+in these directories.
+
+\subsection{lastnight}
+
+The first step in the process is the Perl script {\pr lastnight},
+which is highly dependent on the specifics of the LONEOS setup.  It
+looks at the disks used by the observers to write the images from a
+given night.  Images are written to a directory called {\ff
+/pallas/d[1-6]/YYMMDD} where {\ff YYMMDD} is an abbreviation for the
+current night's date (ie, 990223).  Many files use this naming scheme,
+so we will refer to such a name as {\ff YYMMDD}.  All of the images
+are stored in this directory with names {\ff yyyyMMDDxxxxb.fits} where
+{\ff yyyy} is the full year, {\ff MM} is month, {\ff DD} is date, and
+{\ff xxxx} is a sequence number.  The 'b' refers to the 'b' CCD, and
+the '.fits' extension is required.  The script {\pr lastnight} is
+called by a cron job scheduled for 7am on {\ff hebe.lowell.edu} (note
+that the clock on hebe is set to PST, not local MST - fix this some
+day!  see also man crontab for details on setting up a cron job).  The
+script searches the disks {\ff /pallas/d[1-6]} for a directory of the
+right form (basically any directory beginning with a number).  By
+default, the program demands that the directory have the name derived
+from today's date, but with the flag {\pr -any}, it will accept any
+directory.  It then checks to see if this directory has been already
+been analysed (ie, it is included in the {\ff processed.log} file).
+If not, it lists all files in that directory with the right ending
+(\ff b.fits}) and places these names in a file, {\ff
+/metis/d11/logs/YYMMDD.inlist}.  It also writes the name of the
+directory (along with some other data) in a file {\ff extracted.log}.
+When it has successfully ended and identified some data, it calls the
+next script, {\pr stage1} and then quits.
+
+\subsection{slurp}
+
+An alternative to {\pr lastnight} is the Perl script {\pr slurp},
+which looks for data on the tape archive.  This script looks at the
+{\ff tape.log} file and compares it to the file {\ff processed.log}|.
+It tries to identify nights listed in the file {\ff tape.log} which
+have not been included in the {\ff processed.log}.  If it finds any,
+it tries to download as much of the data as will fit on the disk {\ff
+/pallas/d1}.  This script is called from within the {\pr stage1}
+script and is invoked if {\pr stage1} is run without any data already
+in the file {\ff extracted.log.
+
+A related pair program are the {\pr load} \& {\pr unload} C programs
+which are needed for loading and unloading the tape jukebox.  The
+first is called with, {\pr load N}, which takes tape number N and
+loads it into the tape drive.  The second version, called with {\pr
+unload N} takes the tape and returns it to its slot.  Note that the
+jukebox does not know by itself what number tape is in the drive, so
+{\pr unload} needs to be told the correct one.  If it is mis-led, it
+will complain and refuse to return the tape.  It is important to check
+on the other users of the tape drive to be sure it is not occupied.
+This is done with the {\pr llock}, {\pr lunlock} and {\pr llockstat}
+programs.  The first, {\pr llock} lets you lock a particular service,
+etc, while the last {\pr llockstat} lists the devices which have been
+allocated.
+
+\subsection{stage1}
+
+The Perl script {\pr stage1} takes the image list produced by {\pr
+lastnight} or {\pr slurp} ({\ff YYMMDD.inlist}) and passes the list to
+the controller program {\pr control1} which performs the parallel
+analysis.  The script has a few features to decide which files have
+been analysed through the pipeline and to what extent.  If {\pr
+stage1} is called, it should be able to figure out 1) if there is data
+ready to be analysed (ie, there is a new date reference in the file
+{\ff extracted.log}), 2) if the data has been partially analysed (ie,
+the date reference in {\ff extracted.log} has not been put in {\ff
+processed.log}, but there are entries in the file {\ff
+YYMMDD.outlist}), and 3) which data needs to be run through which part
+of the pipeline (ie, it decides which of the images in {\ff
+YYMMDD.outlist} have succeeded at which stages of the analysis, and
+starts them at the appropriate spot).  These features are most useful
+if the analysis crashes in the middle or needs to be restarted.  The
+{\pr stage1} script is meant to be run without any arguments and it
+will figure out what needs to be done.  The only possible argument is
+the -once flag.  This flag tells {\pr stage1} to analyse the data it
+finds and quit when it finishes, and not call another instance of
+itself.  Otherwise, when it is done, it will restart itself, and since
+there is no new data in {\ff extracted.log}, it will start a {\pr
+slurp} process to get data from the archive.  If there is no data in
+the archive either, this process will sleep for an hour and try again.
+After a few attempts (2 days?), {\pr stage1} will give up and quit
+without restarting itself.  The script writes a log file called {\ff
+\$scriptdir/stage1.NN.log} where NN is a number in sequence between
+all runs of {\pr stage1}.  A file {\ff stage1.count} keeps track of
+which number NN we are on.  When {\pr stage1} has finished the
+analysis of a night's data, it writes the date in {\ff processed.log}
+to let other processes know what has been analysed.  The bulk of {\pr
+stage1} is not dependent on details of the LONEOS setup, but it does
+expect the files to have the naming scheme described above.
+
+\subsection{stage2}
+The serial stage processes are run by the Perl scrip {\pr stage2}.
+Normally, this script is always running.  It waits for the name of a
+night to be added to the {\ff processed.log} file, presumably by {\pr
+stage1}.  Once it finds a new name in this file, it looks for the
+appropriate images in the file {\ff YYMMDD.addlist}.  It then submits
+the list to the second controlling program {\pr control2}, which runs
+the images through {\pr addstar}.  Images which are successfully run
+through addstar have their {\ff *bf.fits} (flattened image) and {\ff
+*.obj} (dophot output) files deleted.  When the entire night is done,
+the rest of the {\ff *.obj} and {\ff *bf.fits} images are deleted by
+{\pr stage2}, the directory with the {\ff *.cmp} and {\ff *.log} files
+is tared and gzipped into the file {\ff YYMMNN.tgz}.  The directory is
+then deleted.  Finally, {\pr stage2} calls the scripts {\pr
+cleaning.pl} and {\pr run.phot} which runs the cleanup programs ({\pr
+markstar - nrphot}) on the database.  After a successful run, {\pr
+stage2} will automatically respawn a new copy that waits until more
+data arrives.
+
+\subsection{control1 / control2}
+These two C-programs perform the tasks of farming the images out to
+the different machines for analysis.  The two programs are essentially
+identical, but {\pr control1} is allowed to use all machines and {\pr
+control2} can only use one ({\ff hebe.lowell.edu}, which has the database
+local to it).  These controller programs start off by executing remote
+shells (using {\pr ssh}) on a set of machines.  These shells are then used
+to execute the remote commands and are kept open the entire time the
+process runs.  
+
+Both control programs maintain a list of images in a set of queues.  A
+set of rules defines the order in which each image travels through the
+queues.  Each queue is associated with a single process (ie, {\pr
+flatten}, astrometry, etc).  Images which successfully run through a
+queue are sent on to the defined 'next' queue, while images which fail
+are instead sent to the defined 'fail' queue.  In most cases, the
+'fail' queue is a process which marks the image as bad and write the
+name in a file, and then puts the image in the 'done' queue.  However,
+it is possible for the 'fail' queue to be another attempt, such as in
+the case of astrometry.  In this example, images which fail the
+default astrometry are run through a second queue which tries again
+with the {\pr -loneos} flag set (this flag makes the assumption that
+the header information about the LONEOS region number for the image is
+correct, not the RA/DEC information).
+
+The {\pr ssh} connections on the remote machines are handled as child
+processes with communication through the {\ff stdin} and {\ff
+stdout/stderr} pipes.  Messages can be sent back and forth though
+these pipes, and messages which are received from a process associated
+with an image are written to a log file with the name {\ff
+imagename.log} (where imagename is the root name of the image).  The
+only required messages from the program are messages saying
+``SUCCESS'' or ``ERROR''.  The programs therefore all end with either
+of these words.  The programs are started within the controller as a
+command to the shell followed by an echo of ``PROCESS DONE''.  If the
+controller sees the message ``PROCESS DONE'' without either
+``SUCCESS'' or ``FAILURE'' (after waiting an appropriately long time),
+it assumes the program crashed.  Currently, no timeout is available
+for the programs.  The flat-field process is run in {\pr mana} and is
+a slightly special case.  We avoid re-loading the same flat many times
+by starting a {\pr mana} process once and running the flatten
+procedures as {\pr mana} function calls.  The images which are
+analysed (with an indicator of success or failure at each stage) are
+written to a file named {\ff YYMMDD.addlist} by the {\pr control1} and
+\ff YYMMDD.outlist} by {\pr control2}.
+
+\subsection{Lock files}
+
+A variety of locking mechanisms are used to avoid overwriting the
+database or running more than one version of the controlling programs.
+There is a Perl program, {\pr locks}, which allows the user to set or
+check the state of the different locks. All programs which write to
+the database check for the existence of a lock on the database and
+refuse to run if it exists.  The {\pr control1/2} programs and the
+{\pr stage1/2} programs check for their own lock files and only run if
+they don't exist.  Finally, the user can set the locks 'kill' or
+'halt' for either {\pr stage1} or {\pr stage2}.  The first tells the
+process to stop immediately, taking care of bookkeeping first.  The
+second tells the process to finish the current set of images but not
+start a new version.
+
+\subsection{Other Perl Scripts} 
+
+there are several other scripts which are either used to do some
+simple function or may be used by the maintainer to check on the
+status of the Ptolemy exectution.  The two programs {\pr checkoutlist}
+and {\pr checkaddlist} take a list of {\ff YYMMDD.outlist} or {\ff
+YYMMDD.addlist} files and list the number of images in the file and
+the number of successes at each analysis stage.  There programs {\pr
+cleaning.pl} and {\pr run.phot} deal with the cleanup programs and the
+running of {\pr nrphot}.  The program {\pr backup.stuff} takes the
+first 4 characters of the year/month file names and backs up to the
+jukebox tape all tar files for the given month.
+
+\section{Operational Issues and Subtleties}
+
+The current LONEOS system runs principally on four Intel machines
+under Linux.  The existing system has been generally quite stable over
+the past year of operation, but there are some subtleties.  One
+significant issue is the RAID disk attached to {\ff hebe.lowell.edu}.
+This device is a set of three 9 GB disks merged into one 27GB RAID
+disk.  The current problem with the /hebe/d27 RAID results from the
+poor way it was setup.  It was set up without much knowledge of the
+(at the time) rather rudimentary linux RAID system.  As a result, the
+implementation is such that the disk will not automatically be
+configured and mounted at boot time.  There is a script {\ff
+/root/mdstart} which lists the step to setup the RAID correctly.  It
+would be helpful if the {\ff rc.local} or {\ff rc.sysinit} files were
+fixed to start, fsck and mount the RAID automatically at boot.  The
+setup on {\ff metis} is substantially more mature and is correctly
+implemented.  It comes up when the machine boots.
+
+\section{Visualization -- Status}
+
+Visualization of the data in the photometry database can best be
+performed with the program {\pr status}.  This is a command-line
+driven program with a math and macro language which makes it easy to
+perform complex tasks.  
+
+First, a few notes about the user interface.  The interface has an
+interaction similar to {\pr tcsh}.  The arrows allow editing of
+previous commands.  You can also use emacs-like commands such as
+cntl-a to reach the beginning of the line and cntl-e to reach the end.
+There is command and file completion: if you type part of a command
+(as the first thing on a line) and then type tab, it will fill in as
+much as possible, until the word is not unique.  Typing tab twice at
+that point will list the possible endings.  For any but the first word
+on a line, the same thing will happen for the files in the current
+directory.  It is also possible to type just a fraction of a command,
+as long as it is unique.  An ambiguous command will list the possible
+alternatives.  For example:
+\begin{verbatim}
+status: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+\end{verbatim}
+
+The shell is essentially an interpretive programming language.
+Variables are set as follows:
+\begin{verbatim}
+status: $fred = 10
+\end{verbatim}
+Any expression within curly brackets \{\} is assumed
+to be an arithmetical expression and is evaluated before the line is
+executed.  For example:
+\begin{verbatim}
+echo {$fred*dcos(45)}
+\end{verbatim}
+would give the response 7.07107.  There are math functions cos, sin,
+and tan, which operate on radian expressions, and also dcos, dsin,
+dtan, which operate on degree expressions.  There are also the
+equivalent inverse functions: eg., asin and dasin return radians and
+degrees, respectively.  The help section on Math defines all of the
+available math functions.  
+
+\subsection{Miscellaneous Commands}
+\begin{verbatim}
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+output                    -- redirect output to file
+quit                      -- exit program 
+scan                      -- scan line from keyboard or file to variable 
+wait                      -- wait until return is typed
+which                     -- show command 
+\end{verbatim}
+Most of these are self-explanatory.  The command ?? prints the system
+variables.  The {\tt help} command will provide help on a single
+command or, without any arguments, will list all available help
+files (this includes general help not associated with a specific
+command).  
+
+\subsection{Shell Programing}
+\begin{verbatim}
+break                     -- escape from function 
+for                       -- loops 
+if                        -- logical cases 
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+\end{verbatim}
+
+There are several options for programming in {\pr status}.  First, a
+file which contains a series of commands can be executed with {\tt
+  input (filename)}.  It is also possible to define macros which will
+behave much like regular commands.  A macro is defined by typing {\tt
+  macro name} or {\tt macro create name} followed by the commands.
+Arguments to the macro are assigned to the variables \$1 .. \$N and
+the number of arguments is given by \$0.  Macros may be defined in
+{\tt input} files, and in fact when {\tt status} is started, it loads
+the file {\tt \~/.statusrc} which may contain default macros.  Simple
+loops and if statements can be performed, and are quite useful for
+complex macros.  
+
+``If'' statements are similar in syntax to C if statements, but only
+the following logical operators are available: $>$, $<$, $=$, !, $|$,
+and \&.  Notice that (currently) there is no $>=$ or $<=$ symbol.  The
+operator ! means ``not equal to'', but cannot be used to negate a
+logical value.  The operators $|$ and \& have the meaning of ``or'' and
+``and'' respectively.  Math expresions in the if statement must be
+contained in curly braces, as elsewhere.  Variables with string values
+may use the logical $=$ operator to test if two strings are the same.
+``For'' loops are quite simplistic.  The form is:
+\begin{verbatim}
+for var first last delta
+ (commands)
+end
+\end{verbatim}
+The value of {\tt \$var} will start at the value {\tt first} and increment by
+{\tt delta} after each loop.  The loop will stop after {\tt \$var} is greater
+than {\tt stop}.  The value {\tt delta} is optional, with 1 assumed.
+The value of {\tt \$var} may be changed during the loop, and if set
+beyong the value of {\tt last} will end the loop early.  
+
+\subsection{Vector Plotting}
+
+\begin{verbatim}
+box                       -- draw a box on the plot
+clear                     -- erase plot
+create                    -- create a new vector
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+hist                      -- create histogram from a vector
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+print                     -- write vectors to file
+ps                        -- define labels for plot
+set                       -- vector math
+style                     -- set the style for graph plots
+vectors                   -- list vectors
+zplot                     -- plot scaled points 
+\end{verbatim}
+
+In addition to scalar variables, {\tt status} can manipulate and
+display 1-D vector variables.  Many of the commands which extract data
+from the photometry database place the data in vectors as well as
+plotting them.  A vector can also be created based on a number
+sequence with the command {\tt create name Nelements start delta}.
+The resulting vector has $Nelements$ entries, starting at a value of
+$start$ and running until $start + delta*Nelements$.  If $delta$ is
+0.0, all elements will have the value of $start$.  A histogram of a vector
+may be made with the command {\tt hist}, which creates a new vector
+containing the histogram of the first vector.  The data range and bin
+size of the histogram are defined in same way as with create.  This
+makes it easy to create the index vector that goes with a histogram
+vector:  
+\begin{verbatim}
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+\end{verbatim}
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with {\tt plot dx Ny} will show the histogram.
+
+Vector math is performed with a command of the form {\tt set new =
+  (expression)}.  The expression is some math function employing
+vectors and scalars.  A complete listing of the math operators
+available in {\tt set} can be found in the help for {\tt set}.
+
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to {\tt status}, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option {\tt -n N} is given to specify a different window.  The
+plotting style is determined by the command {\tt style} which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function {\tt limits} lets the user
+set the range of the plot axes, or check the current setting.  The
+command {\tt plot} will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+{\tt zplot} will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The {\tt cursor} command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in {\tt status}
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables {\tt \$R1}
+and {\tt \$D1}.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+{\tt button}, which does the same with the mouse buttons).  
+
+\subsection{Database Functions}
+
+\begin{verbatim}
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+\end{verbatim}
+
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: {\tt gcat (RA) (DEC)} lists
+the catalog at the specified location and places the name in the
+variable {\tt \$CATNAME}, {\tt gimages (RA) (DEC)} lists all images
+which overlap the specified location, {\tt gstars (RA) (DEC) (RADIUS)}
+lists data about the stars within a specified radius of the specified
+location (all numbers above are given in decimal degrees).  Similarly,
+{\tt lcat} lists the catalogs in the region.  Imstats lists statistics
+about each image
+
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First, {\tt
+  extract} will extract average values for each star and place it in a
+vector.  Next, {\tt mextract} will extract measurement values for each
+star and place it in a vector: as a result a single star may have
+multiple entries in the measurement vectors.  Finally, {\tt imextract}
+will extract image statistics into vectors (not yet implemented).
+
+
+\begin{verbatim}
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+\end{verbatim}
+
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command {\tt region} defines the current sky coordinates for plots
+in graphic window 0.  The command {\tt pcat} plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  {\tt images} plots the
+outline of the images in the image database, while {\tt imdense} shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command {\tt cgrid}
+draws a grid in celestial coordinates on the for the current region.
+
+The most complex, but also one of the most useful command is {\tt
+  catalog}, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+Several other commands relate to non-spatial charateristics of images
+and stars.  {\tt lcurve} will plot a light curve for all stars within
+some radius of a point.  {\tt resid} plots the photometry residuals
+for a particular region file.  
+
+\section{Some Examples}
+
+\note{we need some better and more relevant examples}
+
+\begin{figure}
+\psfig{file=fullsky.ps,width=16cm}
+\caption{\label{allsky} \small
+  Map of the entire sky, and images added to database.  }
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) \\
+\begin{verbatim}
+status: region 0 0 90 gls
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=polar.ps,width=16cm}
+\caption{\label{polar} \small
+  Map of the sky in polar project, and images added to database.  }
+\end{figure}
+
+Fig.~\ref{allsky} shows a map of the entire sky, and the location of
+the images currently in the database from a polar project.  This
+picture was made with the following commands: (output is not shown) \\ 
+\begin{verbatim}
+status: region 0 0 90 zea
+status: cgrid
+status: style -lw 2 -c red 
+status: images
+status: ps
+\end{verbatim}
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} \small
+  Comparison between HST GSC and photometry database astrometry.  }
+\end{figure}
+
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star positions.
+The crosses are all objects in the photometry database, while the
+boxes are only the stars identified as USNO stars.  The circles are
+the stars from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+\begin{verbatim}
+status: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+status: region $R1 $D1 0.2 TAN
+status: cgrid
+status: box
+status: style -pt 0 
+status: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+status: style -pt 2; cat -all -m 12 18
+status: style -pt 1; cat -all -m 12 18 -ID $USNO
+status: style -pt 7; cat -all -m 12 18 -g
+\end{verbatim}
+
+\section{Software Distribution}
+
+All of the code, binaries, and scripts for the Pipeline are stored in
+the ohana tree at {\ff /metis/d11/src/ohana}.  The ohana directory contains
+subdirs of bin, lib, include, src, config, and doc.  There is a
+Makefile at the top level which calls lower-level Makefiles to build
+the programs desired.  One of the important concepts in the ohana
+distribution is the design of the directory layout to enable binary
+support for multiple architectures.  The Makefiles use the environment
+variable ARCH to determine the appropriate architecture.  The binary
+and library files are stored in subdirectories of the form {\ff bin/\$ARCH}
+and {\ff lib/\$ARCH}.  It is therefore necessary that users of the ohana
+system architecture define the ARCH variable correctly.  It is also
+necessary to include in the user's PATH the directory
+{\ff /metis/d11/ohana/bin/\$ARCH}.  At LONEOS,
+with the solaris sparc station and the linux machines both in use,
+ARCH can take on the values of 'linux' and 'sol'.  The values 'sun4',
+'irix', and 'hp' have also been used at various sites.  A simple bit
+of csh script in the users .cshrc or equivalent can make this
+assignment transparently:
+
+\begin{verbatim}
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+\end{verbatim}
+
+The Makefiles use the ARCH variable not only for destination
+directories, but also for destination binary names.  All files of the
+form fred.c are compiled to fred.ARCH.o (instead of fred.o), 
+uninstalled libraries get the names libfred.ARCH.a (instead of
+libfred.a), while uninstalled programs are called fred.ARCH.  
+
+The perl scripts are kept in {\ff ohana/src/perl}, with links to the
+appropriate bin directories.  All programs are stored in directories
+of the form {\ff ohana/src/program}.  The exceptions are {\pr gastro}
+(stored in {\ff ohana/src/astro}), and {\pr control1/2} (stored in
+{\ff ohana/src/astro}).  Also, a variety of simple, user-level
+functions are available in {\ff ohana/src/misc}.
+
+Most of the ohana package of programs use several common libraries.
+These include the {\pr readline} library (except for {\pr dophot},
+this is the only part of ohana that is not written by Eugene Magnier),
+which is used for command-line interface systems.  Other important
+libraries are the {\pr fits} library for implementing the FITS
+specifications in a convenient C-friendly environment, and the {\pr
+ohana} library, consisting of basic string and other basic operations.
+
+\section {Comparison with USNO catalog}
+
+I have made several comparisons between the USNO catalog and results
+from running images from Loneos through the photometry pipeline.  In
+general, there is a good agreement between the astrometry of the two
+datasets.  There are specfic areas where the two disagree, however.
+First, as discussed above, the USNO star positions may be
+significantly different from the observed star positions simply
+because of proper motion.  The first picure in the ``Comparisons
+between Loneos + USNO'' pages shows several stars with significant
+proper motion.  These are currently being flagged in the photometry
+database as discussed.  Other differences evident in this first
+picture include the classification of bright stars and the splitting
+of faint and bright stars.  In the upper right of the image, two
+bright stars are visible, one of which is actually a double.  The USNO
+catalog does a good job of detecting both, but it also detects and
+includes as stars several diffraction spike points.  The HST GSC only
+detected a single point and did not split the star at all.  The Loneos
+data in our pipeline did not detect the star at all due to saturation.
+A star in the upper left corner shows the ability of {\pr dophot} in
+the Loneos pipeline to split double stars.  This star is, on close
+inspection, clearly a double.  The USNO catalog only detects one.  The
+Pipeline not only splits the two stars, but it also makes the correct
+cross-identification of the stars.  
+
+The second set of pictures shows the ability of the Loneos pipeline to
+deal with small galaxies.  There are two small galaxies in this field,
+both of which are broken into 4 or 5 objects by the USNO catalog, but
+maintained as single objects in the Loneos pipeline.  In another
+example (not shown) a bright star within the disk of a small galaxies
+was clearly split from the galaxy by the pipeline (and also by USNO).
+
+\appendix
+\section{Parameter file params.txt}
+\note{replace with up-to-date version from Lowell}
+\begin{verbatim}
+# Configuration file for Loneos analysis pipeline 
+
+# important files and directories
+IN_DIR                  /pallas
+OUT_DIR                 /irene/d11/workspace
+#
+CATDIR                  /hebe/d27/database
+IMAGE_CATALOG           /hebe/d27/database/Images.dat
+IMAGE_CATALOG_TEMPLATE  /hebe/d27/database/template.cat
+CATALOG_TEMPLATE        /hebe/d27/database/template.cat
+ROCK_CATALOG            /hebe/d27/database/Rocks.dat
+#
+GSCFILE                 /metis/d11/references/GSC/GSCregions.tbl
+GSC_DIR                 /metis/d11/references/GSC
+USNO_CDROM              /metis/d11/references/USNO
+DOPHOT_PARAMS           /metis/d11/references/config/default_parameters
+FLATTEN_SCRIPT          /metis/d11/references/config/flatten.pro
+LONEOS_REGIONS          /metis/d11/references/config/regions.map
+
+# parameters for "fstat"
+# instrumental mag zero point
+ZERO_PT                 24.5
+DOPHOT_CHAR_LINE        129
+DOPHOT_TYPE_FIELD       5
+DOPHOT_AP_FIELD         91
+DOPHOT_PSF_FIELD        52
+MIN_SN_FSTAT            6.0
+
+# parameters for "gastro"
+DEFAULT_RADIUS   32.0
+MINIMUM_RADIUS   1.5
+MIN_ERROR        0.6
+MIN_PRECISE      0.12
+CCD_PC1_1        1
+CCD_PC2_2        -1    # for loneos
+CCD_PC1_2        0
+CCD_PC2_1        0
+ASEC_PIX         2.82
+NFIELD           3.0
+MMIN             6.0
+ROT_ZERO         0
+dROT             1.0
+NROT             2
+POLAR_AXIS_RA    -90.0
+POLAR_AXIS_DEC   89.88
+RA_OFFSET        -90.0
+DEC_OFFSET        0.0
+
+# parameters for "addstar"
+# airmass extinction coefficient (in mag / airmass)
+NSIGMA                  3.0
+ALPHA                   0.03
+XOVERSCAN               60
+YOVERSCAN               50
+
+# parameters for "controller"
+NEW_IMAGES              images.dat
+USERNAME                gene
+PASSWORD                gene
+
+# here we list all available machines
+NMACHINES               6
+MACHINE0                metis
+MACHINE1                hebe
+MACHINE2                iris
+MACHINE3                irene
+#MACHINE4               juno
+MACHINE4                ceres
+MACHINE5                vesta
+
+# here we define which machines which are always free
+fMACHINE0               1
+fMACHINE1               1
+fMACHINE2               1
+fMACHINE3               1
+fMACHINE4               0
+fMACHINE5               0
+fMACHINE6               0
+
+LOCAL_MACHINE           1  # machine with catalog on local disk
+
+# parameters for "status"
+TIME_REFERENCE          90/01/01 00:00:00
+
+# parameters for "nrphot"
+# make this one small to boost change of getting an early region 
+TAU                     3.0             
+SCATTER_LIM             15.0
+MAG_LIM                 17.0
+IMAGE_SCATTER           0.075
+NIMAGE_SCATTER          1.5
+STAR_SCATTER            0.05
+
+### parameters for "markstar"
+SEARCH_RADIUS           360   # region for initial trail hunt, in arcsec 
+TRAIL_WIDTH             5.0   # expected trail width, in arcsec
+NANGLE_BINS             180   # Number of angular bins in 180 degrees
+NPTSINLINE              5     # minimum points needed for trail
+MIN_DENSITY             0.025 # minimum linear density in star/arcsec
+SPACE_SIGMA             10.0  # how much denser than average for trail?
+# parameters defining bright star exclusion regions
+BRIGHT_XTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_XTRAIL_MAG         9.5 # faintest sat. star
+BRIGHT_XTRAIL_SLOPE     -80.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_YTRAIL_WIDTH       5.0 # faintest sat. star
+BRIGHT_YTRAIL_MAG        11.0 # faintest sat. star
+BRIGHT_YTRAIL_SLOPE    -400.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+BRIGHT_HALO_MAG           8.5 # faintest sat. star
+BRIGHT_HALO_SLOPE       -28.0 # exclusion radius = BRIGHT_SLOPE * (mag - BRIGHT_MAG)
+# parameters which define the ghosts
+GHOST_MAG               7.5
+GHOST_RADIUS            200   # in arcsec
+OPTICAL_AXIS1           2154.0
+OPTICAL_AXIS2           2193.0
+
+# parameters for "addusno"
+USNO_RADIUS             5.0   # in arcsec
+USNO_PROPER             20.0   # in arcsec
+USNO_RED                1000  # code for USNO Red data
+USNO_BLUE               1001  # code for USNO Blue data
+
+# parameters for "markrock"
+ROCK_RADIUS             2.0   # in arcsec
+ROCK_MAX_RADIUS         20.0  # in arcsec
+ROCK_MAX_SPEED          0.1   # in arcsec / sec
+\end{verbatim}
+
+\section{Creating New Flats}
+
+The LONEOS implementation of the analysis pipeline has a limited
+ability to choose a flatfield image.  There is a mechanism in the
+stage1 script to select a flatfield on the basis of the photcode
+entry.  It works like this: there is a fixed directory for all
+flatfield files, currently {\ff /metis/d11/reference}.  This directory
+is written in the file {\ff flatten.pro}, and also in the script {\pr
+stage1}.  Each flatfield has a name like {\ff flatcodeN.fits}, where N
+is the relevant photcode.  The {\pr mana} macro '{\pr flatten}' in
+{\ff flatten.pro} loads the file {\ff \$flatdir/flatfield.fits} (OR
+SOMETHING LIKE THAT), which is a link to the correct flat.  The script
+{\pr stage1} has the job of deciding which is the correct photcode and
+setting the link appropriately.
+
+This then begs the question of how this flatfield file should be
+created and assigned a new photcode.  The flatfield is NOT made
+nightly from the entire set of data, as one might expect.  This is not
+done because of the problems of scattered light in the telescope.  The
+widefield of the LONEOS telescope makes it somewhat succeptible to
+light at relatively large incident angles.  As a result, a median
+image made from images of the night sky will have different amounts of
+scattered light depending on the overall sky brightness.  In our
+experience, the presence of light clouds and just a small moon (as
+little as a quarter) make the resulting median image a very poor
+representation of the chip response.  Our solution to this problem is
+to choose a good night, in which the sky is very dark, and make a
+flatfield from that collection of images.  As a result, there is too
+much decision-making involved to allow the pipeline to make this
+decision.  Instead, we have chosen to only infrequently make a new
+flat from the data, choosing those nights that we are confident will
+not introduce excess scattered light.  
+
+There are a set of scripts and programs to make the flatfield image.
+The process involves first removing the bias and dark from the image,
+by subtracting a dark image, then medianing the resulting images.
+\note{find these scripts...}  In fact, instead of medianing,
+medianfilter returns the average of the fraction of pixels with values
+between f1 and f2 percent of the total range of the pixel data.
+
+\section{Daily Monitoring of the Pipeline}
+
+On a daily basis, the pipeline generally runs by itself without any
+intervention.  There are a few checks that can be made to be sure the
+process is running OK.
+
+First, it is good to see if the disk space is sufficient.  There is a
+component to stage1 which will keep it from running the analysis if
+there is less space on the destination disk ({\ff /irene/d11/workspace})
+than 1.1 times the amount of space in the source directory
+({\ff /pallas/d?/YYMMDD}).
+
+Second, it is a good idea to see if the nightly cron job is checking
+for new data and if the data is getting analysed.  If data was created
+last night, there should be a set of files in the log directory ({\ff
+/metis/d11/logs}) of the form {\ff YYMMDD.inlist}, {\ff
+YYMMDD.addlist}, and {\ff YYMMDD.outlist}.  If these files do not
+exist, it may just mean that no data was created last night.  In that
+case, the tail of the file {\ff /metis/d11/logs/lastnight} should say
+something like 'there is no new data to analyse'.  \note{It would be
+nice to include some notification scripts at the end of {\pr
+lastnight}, {\pr stage1} and {\pr stage2} which sent some mail
+describing what had been accomplished the previous night}.
+
+If data was created, and these files exist, it is a good idea then to
+check that the analysis of the images was reasonable and didn't fail
+on most of the images.  There are two Perl scripts to check on this.
+First, {\pr checkaddlist [filenames]} will take a list of {\ff
+*.addlist} files and, for each file, list the total number of images,
+then the number that failed for each of the four {\pr stage1}
+processes, {\pr flatten}, {\pr dophot}, {\pr fstat}, and {\pr gastro}.
+A typical run might look like this:
+
+\begin{verbatim}
+hebe: checkaddlist 9907??.addlist
+990701: 206 0 0 0 0
+990703: 199 5 0 0 0
+990705: 150 10 1 0 1
+\end{verbatim}
+
+It is actually unusual for any except the {\pr flatten} process to
+fail, and it might be typical for 1 or 2 of those to fail, since they
+will represent aborted images or images which failed to write
+everything to disk.  The second Perl script is {\pr checkoutlist}
+which works just the same with the {\ff YYMMDD.outlist} files, but
+only give statistics on the {\pr addstar} process.  Here, it is more
+common for several images to fail {\pr addstar}.  At the current time,
+{\pr gastro} does not always return a fail status if it finds a bogus
+solution (recent work in late July may have fixed all of those fail
+status messages).  Images which fail {\pr gastro} are mostly those
+which were taken when the sky was too bright and all that is seen is
+the sky itself, or the focus frames, or the very short images taken of
+bright stars to check the coords.  If the images fail {\pr gastro} but
+do not get rejected with an error status, they are rejected by {\pr
+addstar} on the basis of header keywords which will say 0 stars used
+astrometry.  It is also the case that {\pr gastro} should return a
+failure status if the astrometric solution is sufficiently far from
+Cartesian.  In general, the astrometry does not fail with a solution
+close to the correct solution.  I have found several examples of
+images with extremely wrong astrometric solutions, with very large
+non-Cartesian images on the sky.  There are also a number of failures
+near the pole with signficantly off astrometry, but close to an
+accurate solution.  The should now be rejected by {\pr gastro}.
+
+\section{Restarting the Pipeline}
+
+It is difficult to predict the future, so it is hard to give guidance
+on solving future problems.  Some of the things which might happen
+would include having one of the machines which serve a disk go down or
+having the disks fill up.  If this happens, it is possible that the
+run of a given night will have failed completely, or mostly.  There
+are a variety of things to do to recover from these situations.
+
+\subsection{Deleting data from the archive}
+
+The program {\pr delstar} lets the user delete a set of data from the
+database.  There are several options for this.  The first example is:
+{\pr delstar 199902040015b.cmp}.  In this form, delstar uses the
+astrometry information in the image header to find the measurements
+and delete them from the database, along with the image from the image
+database.  This form requires the datafile *.cmp to exist in the local
+directory.  The second form, {\pr delstar 911012323 1}, uses the given
+time in standard UNIX seconds form to identify the image in the image
+database and delete both the image and the measurements.  \note{does
+delstar expect a UNIX seconds date, or can it take any of the
+variations available in 'status'?}  It is easy to associate time with
+image with the status function {\pr findimages} or {\pr gimage} which
+list images covering a specific location.
+
+The third form of {\pr delstar} is used to clean up the database if an
+image is deleted but not all measurements from that image are removed.
+The routine {\pr addstar} uses the astrometric information for an
+image and the X,Y coordinates of each object in the image to locate
+the object in the database.  Several other routines do the reverse
+process of finding the location of objects within the images.  The
+function which performs this association needs to find all database
+*.cpt files which are covered by the image.  The existing
+implemenation is relatively quick, but not the most general possible.
+In some rare cases, parts of an image will not be found.  This is
+normally not an issue since few functions need to find all stars in a
+given image from scratch.  However, if such an image is deleted, some
+of the stars from that image may get left behind.  These orphaned
+stars can be deleted with the command {\pr delstar region.cpt -orphan
+STUFF??}.
+
+\subsection{Deleting a night from the pipeline}
+
+If the analysis for a specific night fails miserably, it is probably
+necessary to delete the entire night and then encourage the system to
+redo that night.  It is easy to delete an entire night with {\pr
+delstar} by giving a time interval which includes (only) the night in
+question.  It is also easy to find the value of the time in seconds
+with the {\pr status} function {\pr ctimes}.  (At some point, {\pr
+delstar} should incorporate the code from {\pr status} which does the
+time format conversion automatically).  This process will remove the
+night in question from the database.  But before the analysis can be
+re-run, Ptolemy needs to forget that it already ran that night before.
+Every night which has been analysed gets included in the log files
+{\ff processed.log} and {\pr addstared.log}.  The appropriate entry
+from these files needs to be deleted.  It is also necessary to delete
+the files {\ff YYMMDD.addlist} and {\ff YYMMDD.outlist} from the log
+directory.  If the {\ff extracted.log} file exists, it should be
+deleted as well.  All of this is predicated on the assumption that the
+user has halted all processing by Ptolemy before trying to fix
+anything.  At this point, it is possible to restart the analysis.
+This can be done in several possible ways.  If the night in question
+has already been put on tape, it has to be extracted.  The program
+{\pr slurp} will automatically find data which has not been extracted
+from the tape, download it, and set up the appropriate files.
+Unfortunately, {\pr slurp} uses the file {\ff tape.log} which is not
+automatically generated.  It is therefore necessary to add a line to
+{\ff tape.log} (in {\ff /metis/d11/logs}) for the night in question,
+which should look just like the entry in the directory {\ff
+pallas:/root/tape.log}.  Instead of actually running {\pr slurp},
+however, the user should just run {\pr stage1 -once} which will
+perform one run of {\pr stage1} and then end.  If there is no pending
+data (nothing in {\ff extracted.log} that has not been analysed), then
+{\pr stage1} will automatically call {\pr slurp} in the correct
+fashion (ie, on {\ff pallas}), run through the analysis, and then exit
+without restarting.
+
+If the night's data has not been deleted yet, then it is not necessary
+to run {\pr slurp} as the script {\pr lastnight} will do the job.  The
+cronscript for {\pr lastnight} uses the -today option so that the
+automatic analysis will not reattempt any nights still on pallas.
+Instead, it will be necessary for the user to run {\pr lastnight
+-any}, which will also take care of running {\pr stage1}. This should be
+safe at anytime, as the lock functions keep multiple instances of the
+programs from running, but it is better to do this with enough time to
+allow the process to finish before the next night's data is ready for
+processing.
+
+If the pipeline has been interrupted, it will probably be necessary to
+restart {\pr stage2} as well.  Since {\pr stage2} always restarts
+itself on exit, there is no cron job for it to make the initial start.
+(This probably should be introduced into the /etc/rc.local file, or
+some cron implementation for {\pr stage2} worked out).  Note that both
+{\pr stage1} and {\pr stage2} take no arguments except the optional
+{\pr -once} flag.  They make their own decisions about the correct log
+file number and so forth.
+
+If the {\pr lastnight} cron job gets lost, there is a copy of the
+necessary cron script {\ff
+/metis/d11/src/ohana/src/perl/lastnight.cron}.  This can be submitted
+with {\pr crontab lastnight.cron}.
+
+\section{Data backup}
+
+Backups are the still rather primitive in implementation for the
+LONEOS system.  There are two things which should be backed up, but
+only one currently has a good scheme.  The database itself does not
+have a backup process at the moment.  This is a bad situation, but not
+an easy one to solve.  The database is very large, over 30 GB, which
+is comparable to the space on a single AIC tape.  At the moment, we
+are satisfied with simply saving the intermediate results directories,
+all of the {\ff YYMMDD.tgz} files.  If the entire database is
+destroyed, these files can be used to rebuild the database in a
+relatively short time (currently, about a week).  The script {\pr
+backup.stuff} will backup a group of files.  A good method is to
+backup a month at a time.  These will become a single tar file on the
+AIC tape, and a month's worth of data is a reasonable amount of disk
+space for future downloads.
+
+\end{document}
+
+At LONEOS, the images are
+written to the disk from the camera by {\pr astrocam}, the camera
+controller user interface.  The resulting images are FITS files (which
+may be arbitrarily sized) and have header keyword parameters RA and
+DEC specifying rough celestial coordinates.  
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/schematic.fig
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/schematic.fig	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/schematic.fig	(revision 16632)
@@ -0,0 +1,214 @@
+#FIG 3.2
+Landscape
+Center
+Inches
+Letter  
+100.00
+Single
+-2
+1200 2
+6 2400 375 3600 825
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2400 375 3600 375 3600 825 2400 825 2400 375
+4 0 0 0 0 0 18 0.0000 4 150 975 2550 750 astrocam\001
+-6
+6 2400 2250 3600 2700
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2400 2250 3600 2250 3600 2700 2400 2700 2400 2250
+4 0 0 0 0 0 18 0.0000 4 240 750 2550 2625 dophot\001
+-6
+6 2400 1125 3600 1875
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3000 1500 600 375 3000 1500 3600 1875
+4 0 0 0 0 0 18 0.0000 4 180 540 2625 1575 *.fits\001
+-6
+6 2475 2925 3675 3675
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3075 3300 600 375 3075 3300 3675 3675
+4 0 0 0 0 0 18 0.0000 4 240 540 2700 3375 *.obj\001
+-6
+6 2475 4650 3675 5400
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 3075 5025 600 375 3075 5025 3675 5400
+4 0 0 0 0 0 18 0.0000 4 240 660 2700 5100 *.cmp\001
+-6
+6 600 4800 1800 5250
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 600 4800 1800 4800 1800 5250 600 5250 600 4800
+4 0 0 0 0 0 18 0.0000 4 210 660 750 5175 gastro\001
+-6
+6 4425 4800 5625 5250
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 4800 5625 4800 5625 5250 4425 5250 4425 4800
+4 0 0 0 0 0 18 0.0000 4 180 780 4575 5175 addstar\001
+-6
+6 8775 4425 9975 4875
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 8775 4425 9975 4425 9975 4875 8775 4875 8775 4425
+4 0 0 0 0 0 18 0.0000 4 150 615 8925 4800 status\001
+-6
+6 525 2850 1875 4050
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 1200 3450 675 600 1200 3450 1875 4050
+4 0 0 0 0 0 18 0.0000 4 210 975 750 3525 Astro dB\001
+4 0 0 0 0 0 18 0.0000 4 225 690 825 3825 (HST)\001
+-6
+6 8475 1725 10125 2925
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 9300 2325 825 600 9300 2325 10125 2925
+4 0 0 0 0 0 18 0.0000 4 240 855 8850 2565 pictures\001
+4 0 0 0 0 0 18 0.0000 4 210 765 8850 2250 results,\001
+-6
+6 6300 1725 7950 2925
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 7125 2325 825 600 7125 2325 7950 2925
+4 0 0 0 0 0 18 0.0000 4 180 480 6900 2250 alert\001
+-6
+6 4200 750 5850 1950
+1 1 0 1 0 7 0 0 -1 4.000 1 0.0000 5025 1350 825 600 5025 1350 5850 1950
+4 0 0 0 0 0 18 0.0000 4 210 885 4575 1275 postage \001
+4 0 0 0 0 0 18 0.0000 4 210 750 4575 1590 stamps\001
+-6
+6 750 1275 1725 1650
+2 2 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 750 1275 1725 1275 1725 1650 750 1650 750 1275
+4 0 0 0 0 0 18 0.0000 4 180 690 825 1575 flatten\001
+-6
+6 2475 3900 3675 4350
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 2475 3900 3675 3900 3675 4350 2475 4350 2475 3900
+4 0 0 0 0 0 18 0.0000 4 180 465 2625 4275 fstat\001
+-6
+6 4425 6225 5625 6675
+6 4575 6375 5475 6600
+4 0 0 0 0 0 18 0.0000 4 180 900 4575 6600 addusno\001
+-6
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 6225 5625 6225 5625 6675 4425 6675 4425 6225
+-6
+6 4425 5550 5625 6000
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 5550 5625 5550 5625 6000 4425 6000 4425 5550
+4 0 0 0 0 0 18 0.0000 4 180 945 4575 5925 markstar\001
+-6
+6 4425 6900 5625 7350
+6 4425 6900 5625 7350
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 6900 5625 6900 5625 7350 4425 7350 4425 6900
+-6
+4 0 0 0 0 0 18 0.0000 4 180 1035 4575 7275 markrock\001
+-6
+6 4425 7575 5625 8025
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4425 7575 5625 7575 5625 8025 4425 8025 4425 7575
+4 0 0 0 0 0 18 0.0000 4 240 705 4575 7950 nrphot\001
+-6
+6 6225 4425 8025 7725
+6 6450 5925 7800 7125
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 7125 6525 675 600 7125 6525 7800 7125
+4 0 0 0 0 0 18 0.0000 4 210 810 6675 6600 Star dB\001
+-6
+6 6450 4650 7800 5850
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 7125 5250 675 600 7125 5250 7800 5850
+4 0 0 0 0 0 18 0.0000 4 240 1050 6675 5325 Image dB\001
+-6
+2 4 1 1 0 7 0 0 -1 4.000 0 0 7 0 0 5
+	 8025 7725 8025 4425 6225 4425 6225 7725 8025 7725
+4 0 0 0 0 0 18 0.0000 4 210 1395 6375 7575    Photom dB\001
+-6
+6 1500 5700 2850 6900
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 2175 6300 675 600 2175 6300 2850 6900
+4 0 0 0 0 0 18 0.0000 4 210 1110 1650 6375 USNO dB\001
+-6
+6 1500 7200 2850 8400
+1 1 0 1 0 7 0 0 -1 0.000 1 0.0000 2175 7800 675 600 2175 7800 2850 8400
+4 0 0 0 0 0 18 0.0000 4 210 945 1725 7875 Rock dB\001
+-6
+2 2 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2775 975 3150 975 3150 1050 2775 1050 2775 975
+2 2 1 1 0 7 0 0 -1 4.000 0 0 -1 0 0 5
+	 2775 2025 3225 2025 3225 2100 2775 2100 2775 2025
+2 1 0 1 0 7 0 0 -1 4.000 0 0 -1 0 0 2
+	 3075 3675 3075 3900
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3075 4350 3075 4650
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3000 2700 3000 2925
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3000 1875 3000 2250
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3000 825 3000 1125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 2475 5025 1800 5025
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3675 5025 4425 5025
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 5625 5025 6225 5025
+2 1 3 1 0 7 0 0 -1 4.000 0 0 -1 0 1 3
+	0 0 1.00 60.00 120.00
+	 2775 975 1350 975 1350 1275
+2 1 3 1 0 7 0 0 -1 4.000 0 0 -1 0 1 4
+	0 0 1.00 60.00 120.00
+	 2775 2025 1425 2025 1350 2025 1350 1650
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 6450 3525 7650 3525 7650 3975 6450 3975 6450 3525
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 5775 6225 5775
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 7050 3975 7050 4425
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 4875 4575 3150
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 3600 1575 4575 2850
+2 2 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 5
+	 4575 2775 5775 2775 5775 3225 4575 3225 4575 2775
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 4950 3225 4950 4800
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 7050 3525 7050 2925
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 4950 2775 4950 1950
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 1 2
+	0 0 1.00 60.00 120.00
+	 8775 4650 8025 4650
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 0 0 1
+	 9375 4425
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 9300 4425 9300 2925
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 6450 6225 6450
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 7125 6225 7125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 5625 7800 6225 7575
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 1 2
+	0 0 1.00 60.00 120.00
+	0 0 1.00 60.00 120.00
+	 2850 7800 4425 7125
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 2850 6300 4425 6450
+2 1 0 1 0 7 0 0 -1 0.000 0 0 -1 1 0 2
+	0 0 1.00 60.00 120.00
+	 1200 4050 1200 4800
+4 0 0 0 0 0 18 0.0000 4 180 465 6900 2625 files\001
+4 0 0 0 0 0 18 0.0000 4 225 810 6675 3825 (filters)\001
+4 0 0 0 0 0 18 0.0000 4 180 675 4800 3075 imdiff\001
Index: /branches/eam_branch_20080223/Ohana/doc/pipeline/survey.fig
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/pipeline/survey.fig	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/pipeline/survey.fig	(revision 16632)
@@ -0,0 +1,16 @@
+#FIG 3.2
+Portrait
+Center
+Inches
+Letter 
+100.00
+Single
+-2
+1200 2
+2 5 0 1 0 -1 0 0 -1 0.000 0 0 -1 0 0 5
+	0 polar.ps
+	 975 823 9127 823 9127 9375 975 9375 975 823
+2 5 0 1 0 -1 0 0 -1 0.000 0 0 -1 0 0 5
+	0 fullsky.ps
+	 975 8273 9127 8273 9127 12225 975 12225 975 8273
+4 0 0 0 0 0 36 0.0000 4 375 6030 2250 1125 LONEOS SURVEY MAPS\001
Index: /branches/eam_branch_20080223/Ohana/doc/projection.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/projection.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/projection.txt	(revision 16632)
@@ -0,0 +1,51 @@
+
+/* 
+here is some C code to project from R,D to x,y (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+project (double *x, double *y, double R, double D, double Ro, double Do) {
+
+  double sdp, cdp, salp, calp, sdel, cdel, stht, sphi, cphi;
+		 
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  salp = sin(RAD_DEG*(ra - Ro));
+  calp = cos(RAD_DEG*(ra - Ro));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+  
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) { return 0; /* projection from the wrong side of the sphere */ }
+  
+  X =  DEG_RAD * sphi;
+  Y = -DEG_RAD * cphi;
+  
+# if (0) 
+  
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+
+  tmp_d = 1.0 / (pc_1_1*pc_2_2 - pc_1_2*pc_2_1); 
+  *x = tmp_d * (pc_2_2*X - pc_1_2*Y) / cdelt1 + Xo;
+  *y = tmp_d * (pc_1_1*Y - pc_2_1*X) / cdelt2 + Yo;
+
+# else
+
+  *x = X;
+  *y = Y;
+  
+# endif
+
+
+  return (1);
+
+}
Index: /branches/eam_branch_20080223/Ohana/doc/solaris.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/solaris.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/solaris.txt	(revision 16632)
@@ -0,0 +1,23 @@
+
+2007.02.12 
+
+I am trying to build ohana on a solaris box:
+
+panstarrs / SunOS panstarrs 5.8 Generic_117350-26 sun4u sparc SUNW,Sun-Fire-V240 Solaris
+
+I have encountered a few issues:
+
+* configure.tcsh
+** I have added /usr/local/lib and /usr/local/include to the library search path
+** configure.tcsh now skips directories it does not find
+** I now list explicitly all of the external include files required
+
+* includes: 
+** netinet/ip.h does not work (though it exists), we need to use:
+
+# include <sys/socket.h>
+# include <netinet/in.h>
+
+* linking:
+** the vscanf family of functions are missing from solaris. 
+
Index: /branches/eam_branch_20080223/Ohana/doc/status.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/status.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/status.txt	(revision 16632)
@@ -0,0 +1,72 @@
+
+hi christian,
+
+The path you need depends on the machine type, either:
+
+/h/eugene/src/ohana/bin/linux  or  /h/eugene/src/ohana/bin/sol
+
+(the linux version is usually a little more up to date, but both
+should work just fine for you). 
+
+you also need to copy the following files to you home directory:
+
+ ~dougados/.ptolemyrc
+ ~eugene/.statusrc
+
+The configuration scheme is much too complex to go into here, but
+basically, the first defines the location of certain data, and in this
+case, by choosing Catherine's .ptolemyrc file, you'll be looking at
+the Taurus data by default, instead of the archive analysis I've been
+running.  
+
+The second file defines various macros for you, in particular
+'ecliptic' and 'galactic', which draw the ecliptic and galactic
+planes.  
+
+start the program by running 'status'.  It is command-line driven, and
+has some limited help files.  type '?' to see a list of commands and
+'help' to get a list of help files.  
+
+I think most things you'd want to do, you can do.  In some cases the
+syntax can be a little cumbersome.  To get you started, here is a
+macro to generate a box from (10,20) to (15,25), with an offset.
+this could be more easily done by loading the reference coordinates
+from a file with the 'data (filename)' and 'read' commands.  I'll try
+to help you figure things out when you have had a chance to play with
+it a bit.
+
+gene
+
+the syntax for somr
+macro skybox
+ create ra 0 2
+ set ra = ra * 0
+ set dec = ra * 0
+ concat {10+$1} ra 
+ concat {15+$1} ra 
+	      
+ concat {15+$1} ra 
+ concat {15+$1} ra 
+	      
+ concat {15+$1} ra 
+ concat {10+$1} ra 
+	      
+ concat {10+$1} ra 
+ concat {10+$1} ra 
+
+ concat {20+$2}  dec
+ concat {20+$2}  dec
+       	       
+ concat {20+$2}  dec
+ concat {25+$2}  dec
+       	       
+ concat {25+$2}  dec
+ concat {25+$2}  dec
+       	       
+ concat {25+$2}  dec
+ concat {20+$2}  dec
+
+ style -x 2 -c red -lw 3 -pt 100
+ cplot ra dec
+end
+
Index: /branches/eam_branch_20080223/Ohana/doc/systest.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/systest.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/systest.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include <stdio.h>
+
+main (argc, argv) 
+int argc;
+char **argv;
+{
+
+  int i;
+  FILE *f;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: %s testfile \n", argv[0]);
+    exit (0);
+  }
+
+  fprintf (stderr, "char:   %d bytes\n", sizeof (char));
+  fprintf (stderr, "short:  %d bytes\n", sizeof (short));
+  fprintf (stderr, "int:    %d bytes\n", sizeof (int));
+  fprintf (stderr, "long:   %d bytes\n", sizeof (long)); 
+  fprintf (stderr, "float:  %d bytes\n", sizeof (float));
+  fprintf (stderr, "double: %d bytes\n", sizeof (double));
+
+  f = fopen (argv[1], "w");
+  
+# define TYPE char
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE short
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE int
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE long
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE float
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+# define TYPE double
+  { 
+    TYPE I[20];
+    
+    I[0] = 1;
+    for (i = 1; i < 20; i++) {
+      I[i] = I[i-1] * 2;
+    }
+    fprintf (f, "20 of type TYPE, %d bytes each\n", sizeof(TYPE));
+    fwrite (I, sizeof(TYPE), 20, f);
+  }
+
+
+}
Index: /branches/eam_branch_20080223/Ohana/doc/thread.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/thread.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/thread.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include <stdio.h>
+# include <pthread.h>
+
+static int loop1, loop2;
+
+void *subloop (void *arg) {
+  
+  char *input;
+  
+  input = (char *) arg;
+  fprintf (stderr, "starting thread %s\n", input);
+
+  while (loop1) {
+    fprintf (stderr, "loop2: %d\n", loop2);
+    usleep (300000);
+  }
+  pthread_exit (0);
+}
+
+main () {
+
+  int var;
+  pthread_t thread1;
+  pthread_attr_t thread_attr;
+
+  loop1 = 1;
+  loop2 = 10;
+  pthread_create (&thread1, NULL, subloop, "test");
+
+  while (fscanf (stdin, "%d", &var) != EOF) {
+    loop2 = var;
+    if (loop2 == 0) loop1 = 0;
+  }
+}
+
+// a comment
Index: /branches/eam_branch_20080223/Ohana/doc/todo.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/todo.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/todo.txt	(revision 16632)
@@ -0,0 +1,32 @@
+
+- KAPA & KII
+  - library functions to access KAPA / KII interfaces
+    - mana uses a text command interface, do the same?
+    - make a text I/F function, and supply a set of basic wrapped functions
+    - see plotstuff.c in various locations
+
+- DVO Images
+  - define a standard I/F to get at the images (dvo-images.c)
+  - include an iterator which loops over blocks?
+  - include the opihi/dvo/LoadImages functions which loads the 
+    images into a static global?
+  - allow for the intenal/external conversions:
+    we need to have internal floats for Mags (just like RA,DEC)
+  - should we keep the 2D Mcal fit structures?
+  - the skyprobe image tables place the 'sky' somewhere odd (Myyyy)
+    - make a conversion to limit the number of formats?
+
+- DVO Catalog tools
+  - unify the USNO, HST-GSC, 2MASS, etc lookup functions
+  - place under libohana
+  - split DVO functions from libohana?
+  - rename the functions for accessing the average/measure tables?
+  - allow for different spatial granularity of average/measure tables?
+
+- Docs
+  - go though */doc directories and cleanup notes, move into doc/www
+  - need more extensive descriptions!
+
+- gastro2
+  - final cleanups and some further testing
+  - translate to psLib & add to IPP!
Index: /branches/eam_branch_20080223/Ohana/doc/wcs.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/wcs.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/wcs.txt	(revision 16632)
@@ -0,0 +1,54 @@
+
+DETSEC - It looks like it is defining the real pixel coordinates of
+each chip relative to the mosaic, including the gaps.  This means it
+is not affected by binning.  For now, let's leave it off from
+subrastering until we can calculate the correct coornates in that
+case.
+
+CRPIX1,2 - these need to be adjusted to the effective coordinate of
+the same pixel in the new coordinate frame:
+
+if you read a subraster (x1 - x2, y1 - y2) [unbinned pixels] with
+binning dx, 
+
+CRPIX1 = (CRPIX1' - x1) / dx
+CRPIX2 = (CRPIX2' - y1) / dy
+
+CD1_1, CD1_2, CD2_1, CD2_2 just need to be rescaled:
+
+CD1_1' = CD1_1 / dx
+CD2_1' = CD2_1 / dx
+
+CD1_2' = CD1_2 / dy
+CD2_2' = CD2_2 / dy
+
+GAIN stays fixed (we are providing the sum of the binned pixels, not
+the average). 
+
+what about the terms PIXSIZEn, PIXSCALn (I don't know whether these
+refer to physical pixels or image pixels.  in the former case, they
+stay constant, in the later case, they get scaled by dx, dy).
+
+As for the issue of the number of valid pixels...  Well, I can see
+arguments both ways.  Perhaps we *should* stick with the old
+definition of the valid data area.  In that case, make it:
+
+X1 = 6
+X2 = (Nx + 1) / dx
+Y1 = 5
+Y2 = (Ny + 4) / dy
+
+for DATASEC, which seems to match what we use now.
+
+you are right about the BIASSEC, we want the vertical region, not the corner.
+
+X1 = Nx / dx + 2
+X2 = Nx / dx + Sx
+Y1 = 5
+Y2 = (Ny + 4) / dy
+
+(currently we don't use the full Y-direction overscan -- BIASSEC is
+[6:2049,5:4100]).
+
+gene
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+Configure
Index: /branches/eam_branch_20080223/Ohana/doc/www/Configure.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/Configure.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/Configure.in	(revision 16632)
@@ -0,0 +1,8 @@
+# place the target location here; last value is used
+# cfht values:
+ROOT = /Instruments/Elixir
+WWW  = /h/www/cfhti/Instruments/Elixir
+
+# kawelu values:
+ROOT = /eugene/idx
+WWW  = /var/www/kiawe/eugene/idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/Makefile	(revision 16632)
@@ -0,0 +1,15 @@
+include Configure
+
+all: idx install
+
+idx: 
+	mkidx html
+
+install:
+	rsync -auvz --delete --delete-excluded --exclude=CVS/ --exclude="*.htm" --exclude="*.idx" html/ $(WWW)
+
+clean:	
+	rm -f `find . -name "index.idx"`
+	rm -f `find . -name "*.html"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/.cvsignore	(revision 16632)
@@ -0,0 +1,3 @@
+*.html
+index.idx
+download
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/DVO-shell.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/DVO-shell.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/DVO-shell.htm	(revision 16632)
@@ -0,0 +1,175 @@
+<meta name=file  content=dvo>
+<meta name=title content=DVO Examples>
+<meta name=page  content=DVO Examples>
+
+<h3> Database Functions </h3>
+
+<pre>
+gcat                        -- get catalog at location
+gimages                     -- get images at location
+gstar                       -- get star statistics
+extract                     -- extract average vectors from catalogs
+mextract                    -- extract measurement vectors from catalogs
+imstats                    -- plot image statistics
+imextract                   -- extract image vectors from database
+lcat                        -- list catalogs in display region
+cmatch                      -- match two catalogs
+</pre>
+
+<p>
+There are a variety of other commands which directly refer to the
+photometry database.  Some of these functions extract data of various
+types from the database, others perform more complex plotting
+operations.  The commands listed above are those which simply extract
+data from the database.  The first three list information relevant to
+a specific RA, DEC location on the sky: <tt>gcat (RA) (DEC)</tt> lists
+the catalog at the specified location and places the name in the
+variable <tt>$CATNAME</tt>, <tt>gimages (RA) (DEC)</tt> lists all images
+which overlap the specified location, <tt>gstars (RA) (DEC) (RADIUS)</tt>
+lists data about the stars within a specified radius of the specified
+location (all numbers above are given in decimal degrees).  Similarly,
+<tt>lcat</tt> lists the catalogs in the region.  Imstats lists statistics
+about each image
+
+<p>
+The next three commands extract a specific piece of information from
+the photometry database and places it in a vector.  First,
+<tt>extract</tt> will extract average values for each star and place
+it in a vector.  Next, <tt>mextract</tt> will extract measurement
+values for each star and place it in a vector: as a result a single
+star may have multiple entries in the measurement vectors.  Finally,
+<tt>imextract</tt> will extract image statistics into vectors (not yet
+implemented).
+
+
+<pre>
+catalog                    -- plot catalog stars
+cgrid                      -- plot sky coordinate grid
+cplot                      -- plot vectors in sky coordinates
+czplot                     -- plot scaled vectors in sky coordinates
+images                     -- plot image boxes
+imdense                    -- image density plot
+lcurve                     -- plot lightcurve for a star
+pcat                       -- plot catalog boundaries
+region                     -- define sky region for plot
+resid                      -- plot residuals
+simage                     -- plot stars in an image
+</pre>
+
+<p>
+There are two types of database plotting functions: those that display
+or refer to the spatial charateristics of the data and those that
+refer to other types of charatersitics, such as the time domain.  The
+graphics window 0 is reserved for all plots of objects on the sky.
+The command <tt>region</tt> defines the current sky coordinates for plots
+in graphic window 0.  The command <tt>pcat</tt> plots the outline of all
+photometry database files which are within the currently defined
+region (and by default, only those with data).  <tt>images</tt> plots the
+outline of the images in the image database, while <tt>imdense</tt> shows
+the number of images at a location by randomly spacing dots within the
+boundary of the images.  The command <tt>cgrid</tt>
+draws a grid in celestial coordinates on the for the current region.
+
+<p>
+The most complex, but also one of the most useful command is
+<tt>catalog</tt>, which plots the positions of stars in the photometry
+database (and others) on the sky.  There are many options to this
+command.  One set allows the user to plot stars from the photometry
+database (the default), from the HST GSC, or from an ASCII text file
+with RA, DEC, and Mag in specified columns.  If the ASCII file has a
+fixed number of bytes per line, the data can be more quickly loaded.
+The size of the points may be scaled by the star magnitude, by the
+number of observations of the star, or by the number of missing
+datapoints for the star.  In addition, points may be plotted only if
+they land in specified magnitude ranges, or with specified numbers of
+measurements, or missed measurements.  Also, objects may be plotted
+only if they have a specified Average.code, so that only asteroids or
+only perfect stars may be plotted.  The plotted vectors may be saved,
+if desired, and the source catalog epoch may be specified as different
+from J2000 (only valid for ASCII data).
+
+<p>
+Several other commands relate to non-spatial charateristics of images
+and stars.  <tt>lcurve</tt> will plot a light curve for all stars within
+some radius of a point.  <tt>resid</tt> plots the photometry residuals
+for a particular region file.  
+
+<h3> Some Examples </h3>
+
+\begin{figure}
+%\psfig{file=fullsky.ps,width=16cm}
+\caption{\label{allsky} \small
+  Map of the entire sky, and images added to database.  }
+\end{figure}
+
+<p>
+Fig.~\ref{allsky} shows a map of the entire sky, and the location
+of the images currently in the database.  This picture was made with
+the following commands: (output is not shown) 
+
+<pre>
+dvo: region 0 0 90 gls
+dvo: cgrid
+dvo: style -lw 2 -c red 
+dvo: images
+dvo: ps
+</pre>
+
+<p>
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+%\psfig{file=polar.ps,width=16cm}
+\caption{\label{polar} \small
+  Map of the sky in polar project, and images added to database.  }
+\end{figure}
+
+<p>
+Fig.~\ref{allsky} shows a map of the entire sky, and the location of
+the images currently in the database from a polar project.  This
+picture was made with the following commands: (output is not shown)
+
+<pre>
+dvo: region 0 0 90 zea
+dvo: cgrid
+dvo: style -lw 2 -c red 
+dvo: images
+dvo: ps
+</pre>
+
+<p>
+In this example, on the graphics window, the image boxes are shown in
+red.  The user now has the possiblitiy of using the cursor command to
+narrow in on a specific region, and so forth.  
+
+\begin{figure}
+%\psfig{file=catalog.ps,width=9cm}
+\caption{\label{catalog} \small
+  Comparison between HST GSC and photometry database astrometry.  }
+\end{figure}
+
+<p>
+Fig.~\ref{catalog} shows an example comparison of the photometry
+database star positions and the HST Guide Star Catalog star positions.
+The crosses are all objects in the photometry database, while the
+boxes are only the stars identified as USNO stars.  The circles are
+the stars from the HST GSC.  The size of both points is a function of
+brightness.  This plot was made with the following commands (starting
+from the previous image):
+
+<pre>
+dvo: cursor  (typed 1 on region of interest)
+1 137.097858 22.698305
+q 137.097858 22.698305
+dvo: region $R1 $D1 0.2 TAN
+dvo: cgrid
+dvo: box
+dvo: style -pt 0 
+dvo: gcat $R1 $D1 
+  0 n2230/1951.cpt *
+dvo: style -pt 2; cat -all -m 12 18
+dvo: style -pt 1; cat -all -m 12 18 -ID $USNO
+dvo: style -pt 7; cat -all -m 12 18 -g
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/addstar.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/addstar.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/addstar.htm	(revision 16632)
@@ -0,0 +1,208 @@
+<meta name=file  content=addstar>
+<meta name=title content=addstar>
+<meta name=page  content=addstar>
+
+<p>
+This program takes a photometry file, with astrometry, provided by
+earlier routines and incorporates the stellar measurements into the
+photometry database.  This routine does NOT try to calibrate or check
+the photometry, nor does it try to improve the coordinate
+determinations or calculate chisquares for position or photometry -
+those tasks are performed by other routines.
+
+<p>
+Addstar starts by loading in the photometry file and converting the
+pixel coordinates to sky coordinates using the astrometry information
+in the header of the file.  It also gets the detection limits and
+stores the image astrometry information.
+
+<p>
+Next, addstar determines which of all the previous images overlaps
+with this image and also which of the catalog regions overlaps with
+this image.
+
+<p>
+Addstar considers each catalog region in turn, and compares the
+positions of stars in the catalog with stars in the image.  If a
+catalog star is detected, a new measurement is added to the catalog.
+If a catalog star is not detected, but is in the field of view of this
+image, the detection limit for this image is added to the list of
+measurements as an upper limit.  If the image contains a star which is
+not already included in the catalog, the star is added to the catalog,
+and all previous images are checked to see if they included this
+location.  If so, upper limits are added to the list of measurements.
+
+<p>
+To deal with blended images, we have taken the philosophy that all
+measurements compatible with the coordinates of a given star should be
+included in the list of measurements.  This assumes that programs or people
+downstream will figure out which is the "correct" measurement.  To
+this end, if a catalog star is consistent with multiple measurements,
+they are all added to the catalog measurement and the measurements are
+given a flag to say that there was blending in the catalog (ie, it is
+probably the catalog star which is a blend).  If multiple catalog
+stars are consistent with the same image star, that measurement is
+added to each catalog star, and given a flag to say that there was
+blending on the image.
+
+<p>
+After all catalogs have been checked, updated, and written to disk,
+the image is added to the database of images.
+
+<p>
+see <a href=database.html> DVO database </a> for discussion of the
+database storage format.   
+
+<hr>
+
+<h2> Usage </h2>
+
+<pre>
+ addstar (filename)
+ addstar -cat (catalog)
+ addstar -ref (filename)
+</pre>
+
+<p>
+In the first form, addstar loads the photometry information for a
+single image into the database.  The file must be in one of the Elixir
+cmp/smp/smf formats, and must have been astrometrized (eg, with
+gastro, gastro2, and/or mosastro).  The file must also be provided
+with a valid photcode in the header (keyword PHOTCODE) or the photcode
+must be supplied as an option to addstar (see below).  The photcode
+must be listed in the photcode table (see config variable
+PHOTCODE_FILE).  In the case that the image has been astrometrized
+with mosastro (two-level mosaic astrometry), the corresponding mosaic
+header unit must be supplied as an option (see below).  
+
+<p>
+In the second form, addstar will load photometry from the specified
+reference catalog, located in a known location, and will load it into
+the database.  Allowed catalog names are: <tt> USNO, GSC, 2MASS,
+2MASS-ALLSKY, 2MASS-DR </tt>.  Note that USNO corresponds to the
+USNO-A catalog, 2MASS corresponds to the 2MASS-ALLSKY catalog.  It is
+necessary to have defined an appropriate photcode for the given
+catalog.  The following photcodes are expected to exist:
+
+<table>
+<tr><th> catalog </th><th> allowed photcodes   	     </th></tr>
+<tr><td> GSC     </td><td> GSC_M               	     </th></tr>
+<tr><td> USNO    </td><td> USNO_RED, USNO_BLUE 	     </th></tr>
+<tr><td> 2MASS*  </td><td> 2MASS_J, 2MASS_H, 2MASS_K </th></tr>
+</table>
+
+When more than one photcode is allowed, one must be selected; there
+are no defaults in that case. <em>It is advised that addstar -cat be
+used with a restricted region of the sky; the default behavior will
+load the reference catalog for the entire sky into the DB!</em>
+
+<p>
+In the third form, addstar will load data from the specified ASCII
+text file with a fixed format.  The file must contain lines with one
+line per star.  The first four columns must contain the values RA,
+DEC, Magnitude, Magnitude error.  The RA and DEC must be in J2000
+decimal degrees.  Blank lines are allowed, and lines may be commented
+with the hash sign (#).  The provided photometry must all be for a
+single photcode, which must be provided as a command-line option.
+
+<h2> Additional Options </h2>
+
+<pre>
+  -region ra ra dec dec           : only add data in specified region (-ref mode only)
+  -p (photcode)                   : specify photcode (override header)
+  -time (YYYY/MM/DD,HH:MM:SS)     : specify date/time (override header)
+  -mosaic (filename)              : identify associated mosaic frame for chip image
+  -fits                           : input file is FITS table, not TEXT table
+  -existing-regions               : only add measurements to existing catalog files
+  -only-match                     : only add measurements to existing objects
+  -missed                         : skipped 'missed' entries
+  -replace                        : replace time/photcode measurements (no duplication)
+  -image                          : only insert image data
+  -cal                            : perform zero-point calibration
+  -skyprobe                       : specify skyprobe mode
+  -2massquality                   : define 2MASS quality flags to keep
+  -accept                         : accept bad astrometry from header
+  -force                          : force read of database with inconsistent info
+  -v                              : verbose mode
+  -dump (mode)                    : output test data
+  -help                           : print this list
+  -h                              : print this list
+</pre>
+
+
+<h2> Elixir Configuration Data </h2>
+
+addstar uses the following Elixir configuration variables:
+
+<ul>
+<li> EXPTIME-KEYWORD  : header keyword defining exposure time
+<li> DATE-KEYWORD  : header keyword defining the date 
+<li> DATE-MODE  : mode for header date information: use a combination
+of Ys, Ms, Ds to specify order.  If only 2 digits are specified for
+the year, numbers greater than 50 are assumed in the 1900s, less than
+in the 2000s.  eg YYYY/MM/DD
+<li> UT-KEYWORD  : header keyword defining UT
+<li> MJD-KEYWORD  : header keyword defining MJD
+<li> JD-KEYWORD  : header keyword defining JD
+<li> AIRMASS-KEYWORD
+<li> CCDNUM-KEYWORD
+<li> ST-KEYWORD
+
+<li> RADIUS : radius for matches; may have the value "header", in which
+case the astrometric error listed in the header, along with
+<tt>NSIGMA</tt> is used to define a match.  Otherwise, defines a
+radius in arcseconds.
+
+<li> NSIGMA : number of astrometric error sigma to use for match
+radius (see <tt>RADIUS</tt>).
+
+<li> XOVERSCAN : used to define valid pixels in the image. subtracted
+from image NAXIS1 value to define image box. 
+
+<li> YOVERSCAN : used to define valid pixels in the image. subtracted
+from image NAXIS2 value to define image box. 
+
+<li> ADDSTAR_XMIN : this value, and the following three, are used to
+define a region on the image where the photometry is considered
+reliable.  Stars outside this region are marked as having poor
+measurements.
+
+<li> ADDSTAR_XMAX : see <tt>ADDSTAR_XMIN</tt>
+<li> ADDSTAR_YMIN : see <tt>ADDSTAR_XMIN</tt>
+<li> ADDSTAR_YMAX : see <tt>ADDSTAR_XMIN</tt>
+
+<li> MIN_SN_FSTAT : only include objects in the DB with S/N greater
+than this value.
+
+<li> GSCDIR        : location of the HST Guide Star Catalog
+<li> USNO_CDROM    : location of the USNO-A data
+<li> 2MASS_DIR_AS  : location of the 2MASS allsky data 
+<li> 2MASS_DIR_DR2 : location of the 2MASS DR2 data 
+
+2MASS, USNO, and GSC are all loaded from their idiosyncratic formats.
+
+<li> GSCFILE  : location of the GSC layout file (for GSC and ptolemy)
+<li> CATDIR  : location of the ptolemy data
+<li> IMAGE_CATALOG : location of the image database table
+
+<li> CATMODE : storage mode for the database.  may be one of RAW,
+MEF, SPLIT, MYSQL.  SPLIT and MYSQL are currently unsupported.  This
+defines the output format for new tables; the input format is auto-detected.
+
+<li> CATFORMAT : data format for the database.  may be one of LONEOS,
+ELIXIR, PANSTARRS.
+
+<li> PHOTCODE_FILE : location of the photcode file describing the
+photometry system of interest.
+
+<li> OBSERVATORY-LATITUDE : hard-wired observatory latitude.  used for
+precision airmass for skyprobe.  <em> should be replaced with a more
+sophisticated approach</em>
+
+<li> SUBPIX_DATAFILE : table for subpixel structure corrections (skyprobe)
+
+<li> IMAGE_CATALOG_TEMPLATE : deprecated, was used to supply a FITS
+header template
+<li> CATALOG_TEMPLATE : deprecated, was used to supply a FITS
+header template
+</ul>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/commands.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/commands.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/commands.htm	(revision 16632)
@@ -0,0 +1,111 @@
+<meta name=file  content=dvo-cmds>
+<meta name=title content=DVO commands>
+<meta name=page  content=DVO commands>
+
+<table>
+ <tr><td> abszero        </td><td> find filter zeropts </td></tr>
+ <tr><td> applyfit       </td><td> apply fit to new vector </td></tr>
+ <tr><td> applyfit2d     </td><td> apply 2-d fit to new vector </td></tr>
+ <tr><td> badimages      </td><td> look for images with anomalous astrometry </td></tr>
+ <tr><td> box            </td><td> draw a box on the plot </td></tr>
+ <tr><td> buffers        </td><td> list the currently allocated buffers </td></tr>
+ <tr><td> calextract  	 </td><td> extract photometry calibration </td></tr>
+ <tr><td> calmextract 	 </td><td> extract photometry calibration </td></tr>
+ <tr><td> cals           </td><td> plot calibration data </td></tr>
+ <tr><td> catalog        </td><td> plot catalog stars </td></tr>
+ <tr><td> ccd         	 </td><td> plot color-color diagram </td></tr>
+ <tr><td> ccdextract     </td><td> extract star coords from color-color diagram </td></tr>
+ <tr><td> center      	 </td><td> center image on coords </td></tr>
+ <tr><td> cgrid          </td><td> plot sky coordinate grid </td></tr>
+ <tr><td> clear          </td><td> erase plot </td></tr>
+ <tr><td> cmatch         </td><td> match two catalogs </td></tr>
+ <tr><td> cmd            </td><td> plot cmd of stars in current region </td></tr>
+ <tr><td> cmdextract     </td><td> extract stars based on cmd regions </td></tr>
+ <tr><td> cmpread        </td><td> read data from cmp format files </td></tr>
+ <tr><td> concat         </td><td> reduce vector dimension </td></tr>
+ <tr><td> contour        </td><td> create contour from image </td></tr>
+ <tr><td> cplot          </td><td> plot vectors in sky coordinates </td></tr>
+ <tr><td> create         </td><td> create a new vector </td></tr>
+ <tr><td> csystem        </td><td> convert between coordinate systems </td></tr>
+ <tr><td> ctimes         </td><td> convert between time formats </td></tr>
+ <tr><td> cursor         </td><td> get coords from cursor </td></tr>
+ <tr><td> czplot         </td><td> plot scaled vectors in sky coordinates </td></tr>
+ <tr><td> datafile       </td><td> define file to read vectors </td></tr>
+ <tr><td> date        	 </td><td> get current date </td></tr>
+ <tr><td> ddmagextr      </td><td> plot magnitude differences </td></tr>
+ <tr><td> ddmags         </td><td> plot magnitude differences </td></tr>
+ <tr><td> delete         </td><td> delete vectors or matrices </td></tr>
+ <tr><td> device         </td><td> set / get current graphics device </td></tr>
+ <tr><td> dmagextract    </td><td> extract stars based on differential magnitudes between filters </td></tr>
+ <tr><td> dmags          </td><td> plot differential magnitudes between filters </td></tr>
+ <tr><td> dmt            </td><td> plot mag scatter </td></tr>
+ <tr><td> dumpmags       </td><td> custom dB dumping thingy </td></tr>
+ <tr><td> elixir         </td><td> get status info from elixir </td></tr>
+ <tr><td> extract        </td><td> extract vectors from catalogs </td></tr>
+ <tr><td> file           </td><td> test for a file </td></tr>
+ <tr><td> fit            </td><td> fit polynomial to vector pair </td></tr>
+ <tr><td> fit2d          </td><td> fit 2-d polynomial to vector triplet </td></tr>
+ <tr><td> gaussj      	 </td><td> solve Ax = B (N-D)\n </td></tr>
+ <tr><td> gcat           </td><td> get catalog at location </td></tr>
+ <tr><td> gimages        </td><td> get images at location </td></tr>
+ <tr><td> grid           </td><td> plot cartesian grid </td></tr>
+ <tr><td> gstar          </td><td> get star statistics </td></tr>
+ <tr><td> gtypes         </td><td> get type fractions </td></tr>
+ <tr><td> histogram      </td><td> generate histogram from vector </td></tr>
+ <tr><td> images         </td><td> plot image boxes </td></tr>
+ <tr><td> imbox          </td><td> plot expected image box </td></tr>
+ <tr><td> imdata         </td><td> extract data for specific images </td></tr>
+ <tr><td> imdense        </td><td> image density plot </td></tr>
+ <tr><td> imextract      </td><td> extract vectors from catalogs </td></tr>
+ <tr><td> imlist         </td><td> list image info </td></tr>
+ <tr><td> imphot         </td><td> image photometry info </td></tr>
+ <tr><td> imrough        </td><td> get info from imruf database </td></tr>
+ <tr><td> imsearch       </td><td> get info from imreg database </td></tr>
+ <tr><td> imstats        </td><td> plot image statistics </td></tr>
+ <tr><td> interpolate    </td><td> interpolate between vector pairs </td></tr>
+ <tr><td> jpeg           </td><td> write text line on graph </td></tr>
+ <tr><td> labels         </td><td> define labels for plot </td></tr>
+ <tr><td> lcat           </td><td> list catalogs in region </td></tr>
+ <tr><td> lcurve         </td><td> plot lightcurve for a star </td></tr>
+ <tr><td> limits         </td><td> define plot limits </td></tr>
+ <tr><td> mcreate     	 </td><td> create a matrix </td></tr>
+ <tr><td> mextract       </td><td> extract vectors from catalogs </td></tr>
+ <tr><td> mget        	 </td><td> extract a vector from a matrix </td></tr>
+ <tr><td> mset        	 </td><td> insert a vector in a matrix </td></tr>
+ <tr><td> pcat           </td><td> plot catalog boundaries </td></tr>
+ <tr><td> photcodes      </td><td> list photometry codes </td></tr>
+ <tr><td> photresid      </td><td> plot photometry residuals </td></tr>
+ <tr><td> plot           </td><td> plot a pair of vectors </td></tr>
+ <tr><td> pmeasure       </td><td> plot individual measurements </td></tr>
+ <tr><td> precess        </td><td> precess coordinates </td></tr>
+ <tr><td> print          </td><td> write vectors to file </td></tr>
+ <tr><td> procks         </td><td> plot rocks </td></tr>
+ <tr><td> ps             </td><td> define labels for plot </td></tr>
+ <tr><td> rd             </td><td> load fits image </td></tr>
+ <tr><td> read           </td><td> read vectors from datafile </td></tr>
+ <tr><td> region         </td><td> define sky region for plot </td></tr>
+ <tr><td> resid          </td><td> plot residuals </td></tr>
+ <tr><td> resize         </td><td> set graphics/image window size </td></tr>
+ <tr><td> section        </td><td> define section of graph </td></tr>
+ <tr><td> set            </td><td> vector math </td></tr>
+ <tr><td> simage         </td><td> plot stars in an image </td></tr>
+ <tr><td> sort           </td><td> sort list of vectors </td></tr>
+ <tr><td> sprintf     	 </td><td> formated print to variable </td></tr>
+ <tr><td> stats          </td><td> give statistics on a portion of a buffer </td></tr>
+ <tr><td> style          </td><td> set the style for graph plots </td></tr>
+ <tr><td> subpix      	 </td><td> get subpixel positions </td></tr>
+ <tr><td> subraster      </td><td> subraster of fits image </td></tr>
+ <tr><td> subset         </td><td> expand vector dimension </td></tr>
+ <tr><td> textline       </td><td> write text line on graph </td></tr>
+ <tr><td> tv         	 </td><td> display an image on the Kii window </td></tr>
+ <tr><td> uniq           </td><td> create a uniq vector subset from a vector </td></tr>
+ <tr><td> vclip       	 </td><td> clip a vector </td></tr>
+ <tr><td> vectobuf       </td><td> convert vector triplet to buffer </td></tr>
+ <tr><td> vectors        </td><td> list vectors </td></tr>
+ <tr><td> vstat          </td><td> get info from imreg database </td></tr>
+ <tr><td> wd         	 </td><td> write an image to a file </td></tr>
+ <tr><td> write          </td><td> write vectors to datafile </td></tr>
+ <tr><td> zap         	 </td><td> delete pixels </td></tr>
+ <tr><td> zeropts        </td><td> show filter zeropts </td></tr>
+ <tr><td> zplot          </td><td> plot x y with size scaled by z </td></tr>
+</table>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/database.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/database.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/database.htm	(revision 16632)
@@ -0,0 +1,121 @@
+
+This discussion is somewhat short, and only valid for the original
+Elixir-RAW style format/mode.  
+
+<pre>
+The format for a catalog region file is as follows:
+
+-- 
+Header
+--
+Averages
+--
+Measurements
+--
+</pre>
+
+<p>
+The Header follows the format of a FITS header but always stored with
+3 blocks to speed up read time: 2880 x 3 bytes.  Two important
+keywords in the header: NSTARS & NMEAS
+
+<p>
+All average values are stored consecutively in a single block.  They
+are written as an array with NSTARS elements of the Average structure
+defined below.  The individual measurements follow the averages as a
+block.  To find a measurement for a given star, you need to get the
+value of the offset for the star.  this is the element number for the
+first measurement of this star, and are followed by next measurements
+for this star, until the value Nm is reached.
+
+Here are the structures being used for the average and measurement
+values:
+
+<pre>
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first Measure-ment */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       /* reference to corresponding Average entry, 
+				 upper byte of value contains flags.
+				 limit of 16,777,215 stars (Naverage) 
+				 in a file (=0xFFFFFF).
+				 flags = average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+</pre>
+
+<p>
+The above two structures define the entries in the photometry
+database.  The database consists of a large number of files
+representing a small patch on the sky (roughly 1.5 degree$^2$ in most
+places).  These files are organized into directories representing
+bands of Declination.  A reference file determines the coordinate
+boundaries for each of the files so that a given point on the sky can
+unambiguously be associated with a specific file in a specific
+directory.  The sky coordinates for each file is the same as those
+used by the HST Guide Star catalog, except for the region around the
+North celestial pole, for which all stars are included in a single
+file.  
+
+<p>
+Within a given file, the data are stored in a binary format, with an
+ASCII FITS-like header.  The header is examply in the format of a
+normal FITS header, but with the exception that all files have a fixed
+number of header blocks (for now 3 blocks = 8640 bytes).  This is done
+to speed loading the header and finding the beginning of the binary
+data.  The number of 3 blocks seems quite generous, as currently only
+a few FITS keywords have been defined for each file, basically
+keywords to define the number of stars and the total number of
+measurements stored in the file, as well as values to define the RA
+and DEC range of the file.  
+
+<p>
+The first section of data following the header blocks consists of
+average measurements for each uniquely observed star.  Each star
+occupies 20 bytes, the size of the Average structure defined above.
+The Average structure contains the average Ra, Dec, and Magnitude for
+the star, as well as the number of measurements, and \chisq\ values
+for the magnitude and position.  Finally, there is a 32 bit integer
+which defines the offset to the first measurement for this star.  This
+offset is defined as the number of Measure records from the start of
+the Measure structure.
+
+<p>
+The second section of data, following the Average data contains all
+measurements for each star listed in Average.  Each measurement
+occupies 13 bytes, the size of the Measure structure.  This structure
+contains the difference of this position from the average RA and DEC,
+and the instrumental magnitude of this measurement (in the units
+defined by the fstat program, which give m = -2.5*log(cts) + Mo, where
+Mo is currently 24.5 [10/15]).  There is also the magnitude error for
+this measurement, the time of the measurement (in seconds relative to
+a to-be-determined zero point), and a reference to the entry in the
+Average structure so we can relate a given measurement with a given star.
+This last entry also includes a byte of flags, of which only 4 have
+currently been defined.  This means the Average offset can only be as
+large as  16,777,215 (0xffffff), limiting the possible number of stars
+allowed in a given file.  This does not seem like a long term problem,
+though:  aside from the fact that this number is very large and we
+only expect in the vicinity of 20,000 stars per file, the file can
+easily be divided into pieces at a later date if needed.  this last
+step is trivial, consisting of splitting the data up into smaller
+RA,DEC regions, and updating the reference catalog.  With the above
+definitions for the Average and Measure structures, we will typically
+expect 20,000 * 15 measurements per year and 20,000 average entries in
+a given file.  This implies a file size of about 4.3 MB at the end of
+a year.  It is also possible that we will choose to split the files up
+in the future if the number of measurements makes their size
+unweildy.  4.3 MB is sufficiently small that this is not a problem,
+but after only 5 years, the files will be over 21 MB each, getting to
+be fairly significant.  
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/dmagoptions.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/dmagoptions.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/dmagoptions.txt	(revision 16632)
@@ -0,0 +1,98 @@
+
+mextract from value [options]
+avextract from value [options]
+
+imextract value [options]
+
+dmags F1 - F2 : F3 [options]
+dmagmeas F1 - F2 : value [options]
+dmagaves F1 - F2 : value [options]
+
+cmd F1 - F2 : F3 [options]
+ccd F1 - F2 : F3 - F4 [options]
+
+calextract F1 - F2 [options]
+calmextract F1 - F2 [options]
+
+options:
+
+ -photcode value
+  for avextract and dmagaves, -photcode defines the which code is used
+  to calculate certain values (mag, dmag, etc).  objects which lack a 
+  photcode return a logical NaN for that value.
+
+ -magrange min max
+
+this can apply to any photcode
+
+ -imaglim min 
+ -flag value
+ -time start stop
+ -fwhm (value)
+ -type (value)
+
+these naturally apply to the REF and DEP photcodes, but cannot apply to 
+to PRI and SEC.  (note that -type is interpretted a bit differently here
+from below. 
+
+ -chisq max
+ -errorlim max
+ -type (value)
+ -typefrac (type) (frac)
+ -nphot (value)
+ -ncode (value)
+ -fwhmfrac (value) (frac)
+
+these naturally apply to PRI and SEC photcodes, but cannot apply to
+REF.  For DEP, they could apply to the equivalent photcode.  eg
+
+  ccd I - 2MASS_J : 2MASS_J - 2MASS_K -chisq 2.0
+
+  this will exclude on chisq for the I value, and ignore the limit
+  for the 2MASS values
+
+  ccd I - CFH12K.R.00 : 2MASS_J - 2MASS_K -chisq 2.0
+
+  this will exclude on chisq for the I value, and ignore the limit
+  for the 2MASS values, and exclude on R (equiv to CFH12K.R.00).
+
+  ccd I - CFH12K.R.00 : 2MASS_J - 2MASS_K -time start stop
+
+  by default, this will filter the CFH12K.R.00 and 2MASS measurements 
+  based on
+
+we need to be able to 
+
+
+measure values:
+  ra
+  dec
+  mag
+  dmag
+  airmass
+  exptime
+  photcode
+  time
+  dR
+  dD
+  fwhm
+  dophot
+  FLAGS
+  XCCD
+  YCCD
+  XMOSAIC
+  YMOSAIC
+
+average values:
+  ra
+  dec
+  dmag
+  Nmeas
+  Nmiss
+  Xp
+  Xm
+  flag
+  type
+  typefrac
+  Nphot
+  Ncode
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/example.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/example.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/example.htm	(revision 16632)
@@ -0,0 +1,82 @@
+
+<p>
+This <a href=../download/dvo.sample.tgz>tarball</a> contains a
+collection of data from 6 Megacam standard star image obtained in
+September, 2003.  There are two sets of three images, taken two weeks
+apart (03 Sep and 21 Sep).  In each set, there is one each of g', r',
+and i' images, all short exposures of 3.0 seconds.  This dataset makes
+a useful demonstration of the DVO system.
+
+<p>
+The tarball contains 6 directories, one for each image.  The images
+have been processed with the Elixir system and the photflat-corrected
+flat-field images for each filter, though no fringe correction has
+been applied.  Sextractor has been run on all of the images, and only
+the sextractor-derived photometry is available in the tarballs.  No
+image pixel data is kept.  The directories are named after the
+exposure odometer numbers, eg 718688o.
+
+<p>
+Within each directory, the data is separated into a number of files
+for each of the 36 detector, with names created by appending the chip
+number to the odometer number of the image, eg 718688o00.  For each
+detector, the directory contains:
+
+<ul>
+<li> the Elixir processing log file: *.log
+<li> the raw sextractor output: *.sx
+<li> the photometry data in Elixir cmp format: *.smp
+<li> the photometry data in FITS table format: *.smf
+<li> the photometry data with mosaic astromtry: *.xmf
+</ul>
+
+<p>
+The raw sextrator output consists of a fixed-format ASCII table with
+columns defined by the Elixir processing system.  The Elixir cmp
+format merges the sextractor photometry table with the image header to
+form a pseudo-FITS table.  The smf format contains essentially the
+same information as the smp format, but the table portion of the data
+is written as a FITS table in the first extension, with appropriate
+table description in the table header unit.  The primary header of
+this file consists of the original image header, with the value of
+NAXIS set to 0.  This has the effect of making the file a valid FITS
+file, while keeping the information of NAXIS1 and NAXIS2 (the original
+image dimensions), while eliminated the data taken by the image array.
+
+<p>
+Both the .smp and .smf files include the astrometric solution in the
+form of WCS header entries.  In the case of these files, the
+astrometry requires a linear solution across the chip.  The linear
+solution provides a robust solution, but results in systematic errors
+which are substantial, roughly 0.5-1.0 arcsec, due to the optical
+system distortion.  A better solution can be obtained by fitting
+higher order polynomials.  We use a two-layer solution, with one set
+of third-order polynomials to represent the warping of each detector,
+and a second third-order polynomial to represent the telescope optical
+distortion.  The .xmf files represent the same data as the .smf files,
+also in the FITS table format, but with the two-layer mosaic
+astrometric solutions in their headers.  In addition, these files
+require the single .phu file which represents the full-mosaic PHU and
+contains the top-level telescope distortion solution.
+
+It is possible to add any of these data to the DVO database using the
+addstar command.  To add any of the .smp files, simply use the
+command:
+
+<pre>
+addstar filename.smp
+</pre>
+
+To add any of the .smf files, it is necessary to specify the
+<tt>-fits</tt> flag:
+
+<pre>
+addstar -fits filename.smf
+</pre>
+
+To add any of the .xmf files, it is necessary to specify the
+<tt>-fits</tt> flag and to identify the mosaic astrometry file:
+
+<pre>
+addstar -mosaic root.phu -fits filename.smf
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/extract.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/extract.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/extract.htm	(revision 16632)
@@ -0,0 +1,147 @@
+<meta name=title content=DVO extractions>
+<meta name=page  content=extractions>
+
+<p>
+DVO provides several ways to access the photometry information stored
+in the database.  Several simple commands allow the user to extract 1
+dimensional information directly from one of the primary database
+tables.  The commands are:
+<ul>
+<li> imextract
+<li> avextract
+<li> mextract
+<li> imsearch
+<li> detsearch
+</ul>
+
+<h3> imextract </h3> 
+
+This command allows the user to extract one of the columns from the
+image table, applying filtering as desired:
+
+<pre>
+  dvo: imextract
+  USAGE: imextract (value) [-region] [-time start range] [-photcode photcode]
+  dvo: imextract help
+  value may be one of the following:
+   ra dec airmass Mcal dMcal Xm photcode time fwhm exptime nstar ncal sky flag
+</pre>
+
+<p>
+The extracted data is saved in a vector with the same name used to
+select the column.  The vector name will have the same case as the
+choice given, but the column selection is case-insensitive (since
+there are no ambiguities in the database columns names by case).  
+
+<h3> avextract </h3>
+
+This command allows the user to extract data from one of the Average
+table columns:
+
+<pre>
+  dvo: avextract
+  USAGE: avextract (from) (value) [options]
+    from: cpt name or 'all'
+    value: average.parameter or photcode
+  dvo: avextract all help
+  value may be one of the following:
+   ra dec dmag Nmeas Nmiss Xm Xp Nphot Ncode flag type
+</pre>
+
+<p>
+This command takes as the first argument the name of one of the
+database regions.  Alternatively, all regions currently displayed may
+be selection with the word 'all'.  The second option specifies which
+column to select from the Average table.  In addition to the basic
+data columns (ra, dec, etc), the magnitude-related average values
+(mag, dmag, Xm, Nphot, Ncode) are coupled to a photcode, which is thus
+required for these selections.  The value 'mag' may also be subsituted
+with a primary or secondary photcode.  Eg:
+
+<pre>
+  avextract all ra : select ra for all objects in displayed region
+  avextract all g  : select g magnitudes
+  avextract all mag -photcode r : select r magnitudes 
+  avextract all Xm -photcode r  : select chisq values for r average mags
+</pre>
+
+<h3> mextract </h3>
+
+This command allows the user to extract data from one of the Measure
+table columns:
+
+<pre>
+  dvo: mextract
+  USAGE: mextract (from) (value) [options]
+    from: cpt name or 'all'
+    value: measure.parameter or photcode
+  dvo: mextract all help
+  value may be one of the following:
+   ra dR dec dD mag dmag Mrel Mcal photcode time fwhm dophot xccd yccd xmosaic ymosaic flags
+</pre>
+
+<p>
+This command takes as the first argument the name of one of the
+database regions.  Alternatively, all regions currently displayed may
+be selection with the word 'all'.  The second option specifies which
+column to select from the Measure table.  In addition to the basic
+data columns (ra, dec, etc), the magnitude-related average values
+(mag, dmag) are coupled to a photcode, which is thus required for
+these selections.  The value 'mag' may also be subsituted with a
+primary or secondary photcode.  Eg:
+
+<pre>
+  mextract all ra : select ra for all objects in displayed region
+  mextract all g  : select g magnitudes
+  mextract all mag -photcode r : select r magnitudes 
+  mextract all Xm -photcode r  : select chisq values for r average mags
+</pre>
+
+<h3> option filtering </h3>
+
+The following extraction options allow the user to restrict the
+selections:
+
+<p>
+<tt> -time (start) (range)<tt><br> 
+
+select data for images within the given time range.  The start date is
+given in the format YYYY/MM/DD,hh:mm:ss (any of these element may be
+dropped, in which case they default to 00 [for hh,mm,ss] or 01 [for
+MM,DD]).  The date may also be written as a number of days followed by
+j (JD) or J (MJD).  The two special date names "now" and "today" are
+also valid.  The range is written as a number followed by a unit, with
+valid units of s (seconds), m (minutes), h (hours), d (days).  Times
+are in UT.  For example:
+
+<pre>
+ -time 2001/1/1 30d : select the range starting at midnight on 2001/1/1
+  and ending 30 days (86400*30 seconds) later.
+
+ -time now -3h : select the time range starting three hours ago and
+  ending now.
+</pre>
+
+<tt> -region<tt><br> 
+
+restrict the selection to the currently display portion of the sky.
+This filter expects a portion of the sky to be plotted, and will only
+select data for images in the part of the sky.  The algorithm for
+selecting the displayed region may not be perfect, so images near the
+boundaries may be unexpected included or excluded (this depends on the
+exact overlap details).  Multiple queries with the same region will
+result in the same subset of images selected.
+
+<tt>-photcode (photcode) </tt><br>
+
+This restricts the selection to the given photcode.  Images may only
+have photcodes of 'Dependent' type (eg, CFH12K.R.00).  This filter
+allows the selection of images by exact match (selected photcode is
+Dependent type) or by equivalence match (selected photcode is Primary
+or Secondary type).  Thus, selecting images based on CFH12K.R.00 will
+ignore images with photcode CFH12K.R.10, while selecting images based
+on photcode 'r' will return all images with CFH12K.R.*, since all are
+equivalent to 'r'.  (NOTE: these details depend on the layout of the
+photcode table).
+
+<em> fill this out with all other restrictions provided by photometry.c</em>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/index.htm	(revision 16632)
@@ -0,0 +1,19 @@
+<meta name=file  content=DVO>
+<meta name=title content=DVO System>
+<meta name=page  content=The DVO System>
+
+<h3> Introduction </h3>
+
+DVO (the Desktop Virtual Observatory) is system for manipulating
+collections of images and measurements related to astronomical
+objects.  The DVO system consists of several programs which insert
+data in the database system, or manipulate data in the database.  One
+of these is the <tt>DVO shell</tt>, which provides a command-line
+driven, programmable user interface to the objects and measurements in
+the database.  The DVO shell is based on the Opihi shell, which
+provides the tools to manipulate and display data in various
+representations.  The DVO shell adds to this basic command set a
+collection of functions which provide direct access to the contents of
+the DVO database tables.
+
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/navigate.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/navigate.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/navigate.htm	(revision 16632)
@@ -0,0 +1,44 @@
+
+<p>
+The <a href=navigate.pro>navigate</a> script provides a convenient
+graphical user interface to the DVO shell and database.  To use it,
+simply load it into the DVO shell with the <tt>input</tt> command.  It
+is useful to always load this script by including the input command in
+your <tt>~/.dvorc</tt> file.  Once you have loaded the script, you
+can start it by typing <tt>navigate</tt>.  You can navigate around the
+sky, then exit the script at any time by typing 'q'.  This allows you
+to issue DVO commands related to your current position.  You can then
+resume navigating by restarting the script.
+
+<p>
+The navigate script lets you move about the sky by placing your cursor
+in the display window and clicking various keys.  Below is a summary
+of the basic key stokes:
+
+<pre>
+1 - zoom in factor of 2
+2 - zoom in factor of 1.2
+3 - recenter at cursor
+4 - zoom out factor of 1.2
+5 - zoom out factor of 2
+6 - zoom out factor of 10
+z - zoom to radius (requires 2nd keystroke)
+f - show full sky
+
+q - quit
+g - toggle skygrid on/off
+r - plot detected asteroids (rocks)
+l - plot HST GSC
+L - plot Landolt stars
+m - list measurements for stars within 1 pixel of cursor
+M - list measurements for stars within 1.8 arcsec of cursor
+i - list info about images touching cursor location 
+I - list info about images, with pixel coords of cursor position
+x - plot stars scaled by magnitude Chisq
+X - plot stars by magnitude scatter
+S - toggle auto-plotting of stars
+t - plot light curve for star within 2 arcsec of cursor position
+T - plot 'galaxy' light curve for star within 2 arcsec of cursor position
+c - plot status catalog boundaries
+C - list catalog at cursor location
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/navigate.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/navigate.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/navigate.pro	(revision 16632)
@@ -0,0 +1,379 @@
+# -*- perl -*-
+
+macro navigate
+  style -n 0
+  limits
+  $DSTARS = -1
+  $ZOOM = 180 / ($YMAX - $YMIN)
+  for i 1 100
+    $REDRAW = 0
+    cursor -g 1
+    # zoom controls
+    if ("$KEY" == "1")
+      $ZOOM = $ZOOM * 2
+      $REDRAW = 1
+      $Rnum = $R$KEY		      
+      $Dnum = $D$KEY
+      $KEY = num
+    end
+    if ("$KEY" == "2")
+      $ZOOM = $ZOOM * 1.2
+      $REDRAW = 1
+      $Rnum = $R$KEY		      
+      $Dnum = $D$KEY
+      $KEY = num
+    end
+    if ("$KEY" == "3")
+      $REDRAW = 1
+      $Rnum = $R$KEY		      
+      $Dnum = $D$KEY
+      $KEY = num
+    end
+    if ("$KEY" == "4")
+      $ZOOM = $ZOOM / 1.2
+      $REDRAW = 1
+      $Rnum = $R$KEY		      
+      $Dnum = $D$KEY
+      $KEY = num
+    end
+    if ("$KEY" == "5")
+      $ZOOM = $ZOOM / 2
+      $REDRAW = 1
+      $Rnum = $R$KEY		      
+      $Dnum = $D$KEY
+      $KEY = num
+    end
+    if ("$KEY" == "6")
+      $ZOOM = $ZOOM / 20
+      $REDRAW = 1
+      $Rnum = $R$KEY		      
+      $Dnum = $D$KEY
+      $KEY = num
+    end
+
+    # help list
+    if ("$KEY" == "h")
+     echo "1 - zoom in factor of 2"
+     echo "2 - zoom in factor of 1.2"
+     echo "3 - recenter at cursor"
+     echo "4 - zoom out factor of 1.2"
+     echo "5 - zoom out factor of 2"
+     echo "6 - zoom out factor of 10"
+     echo "z - zoom to radius (requires 2nd keystroke)"
+     echo "f - show full sky"
+     echo ""
+     echo "q - quit"
+     echo "g - toggle skygrid on/off"
+     echo "r - plot detected asteroids (rocks)"
+     echo "l - plot HST GSC"
+     echo "L - plot Landolt stars"
+     echo "m - list measurements for stars within 1 pixel of cursor"
+     echo "M - list measurements for stars within 1.8 arcsec of cursor"
+     echo "i - list info about images touching cursor location" 
+     echo "I - list info about images, with pixel coords of cursor position"
+     echo "x - plot stars scaled by magnitude Chisq"
+     echo "X - plot stars by magnitude scatter"
+     echo "S - toggle auto-plotting of stars"
+     echo "t - plot light curve for star within 2 arcsec of cursor position"
+     echo "T - plot 'galaxy' light curve for star within 2 arcsec of cursor position"
+     echo "c - plot status catalog boundaries"
+     echo "C - list catalog at cursor location"
+    end
+
+    # quit from navigate
+    if ("$KEY" == "q") 
+      break
+    end
+
+    # measure distance
+    if ("$KEY" == "d")
+      $r0 = $R$KEY
+      $d0 = $D$KEY
+      $ok = $KEY
+      echo "type at radius"
+      cursor -g 1
+      $r1 = $R$KEY
+      $d1 = $D$KEY
+      $dr = 3600*((dcos($d0)*($r0-$r1))^2 + ($d0-$d1)^2)^0.5
+      echo "$dr arcsec"
+    end
+    # show ra, dec
+    if ("$KEY" == "w")
+      $tmp = $R$KEY
+      if ($tmp < 0) 
+        $tmp = $R$KEY + 360.0
+      end
+      echo "$tmp $D$KEY" 
+      exec echo $tmp $D$KEY | radec -hh
+    end
+    # zoom to radius
+    if ("$KEY" == "z")
+      $r0 = $R$KEY
+      $d0 = $D$KEY
+      $ok = $KEY
+      echo "type at radius"
+      cursor -g 1
+      $r1 = $R$KEY
+      $d1 = $D$KEY
+      $dr = (($r0-$r1)^2 + ($d0-$d1)^2)^0.5
+      $ZOOM = $RAD / $dr
+      $REDRAW = 1
+      $KEY = $ok
+      $R$KEY = $r0
+      $D$KEY = $d0
+    end
+
+    # adjust mag scaling
+    if ("$KEY" == "J")
+      $MAG = $MAG - 0.5
+      $REDRAW = 2
+    end
+    if ("$KEY" == "K")
+      $MAG = $MAG + 0.5
+      $REDRAW = 2
+    end
+    if ("$KEY" == "j")
+      $dMAG = $dMAG * 0.8
+      $REDRAW = 2
+    end
+    if ("$KEY" == "k")
+      $dMAG = $dMAG * 1.25
+      $REDRAW = 2
+    end
+    echo "mag, dmag: $MAG, $dMAG"
+
+    # redraw region 
+    if ($REDRAW == 1)
+      region $R$KEY $D$KEY {$RAD/$ZOOM} sin
+      $RMIN = $R$KEY + $XMIN
+      $RMAX = $R$KEY + $XMAX
+      $DMIN = $D$KEY + $YMIN
+      $DMAX = $D$KEY + $YMAX
+      if (($ZOOM < 20) && ($GRID == 1)) 
+        style -c red; cgrid
+      end
+      if (($ZOOM > 20) && ($DSTARS == 1))
+        style -pt 7
+	pmeasure -all -m $MAG {$MAG + $dMAG}
+      end    
+      style -c black
+       images
+#       showtile
+    end
+
+    # redraw region 
+    if ($REDRAW == 2)
+      clear
+      if (($ZOOM < 20) && ($GRID == 1)) 
+        style -c red; cgrid
+      end
+      if (($ZOOM > 20) && ($DSTARS == 1))
+        style -pt 2
+	pmeasure -all -m $MAG {$MAG + $dMAG}
+      end    
+      style -c black
+      images
+    end
+
+    # turn grid on / off
+    if ("$KEY" == "g")
+      if ($GRID == 1) 
+        $GRID = 0
+        style -c white; cgrid
+        style -c black
+      else
+        $GRID = 1 
+        style -c black; cgrid
+      end
+    end
+
+    # plot full sky
+    if ("$KEY" == "f") 
+      echo "full"
+      $ZOOM = 1
+      resize 1150 600		      
+      region 0 0 90 ait
+      $RMIN = 0
+      $RMAX = 360
+      $DMIN = -90
+      $DMAX = +90
+      style -c red; cgrid
+      style -c black
+      images
+    end
+
+    # plot rocks
+    if ("$KEY" == "r") 
+#      plot.rocks
+      style -c blue   -pt 1; procks -speed 0.0041 1
+      style -c red    -pt 1; procks -speed 0.00041 0.0041
+      style -c indigo -pt 1; procks -speed 0 0.00041
+      style -c black -lw 0;
+    end
+    # plot HST-GSC
+    if ("$KEY" == "l") 
+      style -c blue -pt 7; cat -all -g -m 9 16
+      style -c black
+    end
+    # plot Landolt
+    if ("$KEY" == "L") 
+#      style -c red  -lw 2 -pt 3; cat -a 1 2 3 /data/elixir/srcdir/refs/stetson/stetsonBn.txt -m 9 18
+#      style -c blue -lw 2 -pt 3; cat -a 25 26 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.fix -m 9 18
+      style -c red -lw 2 -pt 7; cat -a 1 2 3 /data/elixir/srcdir/refs/sdss/g_SDSS.dat -m 9 14
+#      style -c red -lw 2 -pt 3; cat -a 25 26 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.hq -m 9 18
+#      style -c red -lw 2 -pt 3; cat -a 22 23 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.unfix -m 9 18
+#      style -c blue -lw 2 -pt 7; cat -a 1 2 4 /data/elixir/srcdir/refs/landolt/extreme/extreme.match -m 0 20
+#      style -x 2 -c red -pt 7 ; cplot RA DEC
+      style -c black -lw 0
+    end
+
+    # list star measurements
+    if ("$KEY" == "m") 
+        $dR = $RAD/$ZOOM/300
+        if ($dR < 0.0005)
+	 $dR = 0.0005
+        end
+	gstar $R$KEY $D$KEY $dR -m
+    end
+
+    # plot mag residuals
+    if ("$KEY" == "R") 
+      echo "filter: "
+      cursor 1
+      clear -n 1 -s; lim 10 22 -0.2 0.2; clear; box
+      dmags $KEY\:rel - $KEY : $KEY -type 0
+      plot -x 2 -pt 0 -sz 0.3 -c red yv xv
+      dmags $KEY\:rel - $KEY : $KEY -type 0 -flag 0 -nphot +3 -chisq 2.0
+      plot -x 2 -pt 2 -sz 0.5 -c black yv xv
+      $KEY = R
+      style -n 0
+    end
+
+    if ("$KEY" == "M") 
+	gstar $R$KEY $D$KEY 0.0005 -m
+    end
+    # list images
+    if ("$KEY" == "i") 
+	gimages $R$KEY $D$KEY
+    end
+    if ("$KEY" == "I") 
+	gimages $R$KEY $D$KEY -pix
+    end
+    # turn stars on / off
+    if ("$KEY" == "S")
+      $DSTARS = $DSTARS * -1
+      if (($ZOOM > 20) && ($DSTARS == 1))
+       style -pt 7
+       pmeasure -all -m $MAG {$MAG + $dMAG}
+      end
+    end
+    # plot light-curve interactive
+    if ("$KEY" == "t")
+      style -n 1 -pt 2 -x 2
+      clear
+      if ($R$KEY < 0) 
+       $R$KEY = $R$KEY + 360
+      end
+      lcurve -l $R$KEY $D$KEY {30/3600} -d -v time mag
+      box
+      lcv
+      style -n 0
+    end
+    # plot light-curve 
+    if ("$KEY" == "T")
+      style -n 1 -pt 1 -c red -x 2
+      lcurve $R$KEY $D$KEY {30/3600} -d
+      style -c black
+      style -n 0 
+    end
+    # plot catalogs
+    if ("$KEY" == "c")
+      style -c blue; pcat; style -c black
+    end
+    # list catalogs
+    if ("$KEY" == "C")
+      gcat $R$KEY $D$KEY
+    end
+
+    # plot image chisqs
+    if ("$KEY" == "x") 
+       gcat $R$KEY $D$KEY
+       extract $CATNAME Xm -photcode R
+       extract $CATNAME ra
+       extract $CATNAME dec
+       style -x 2 -pt 7 -c blue
+       czplot ra dec Xm 3 30
+       style -c black -pt 1
+    end
+    # plot meas errors
+    if ("$KEY" == "X") 
+       gcat $R$KEY $D$KEY
+       extract $CATNAME dM -photcode R
+       extract $CATNAME ra
+       extract $CATNAME dec
+       style -x 2 -pt 7 -c red
+       czplot ra dec dM 0 30
+       style -c black -pt 1
+    end
+    # temp plot for skyprobe
+    if ("$KEY" == "u") 
+      imextract -region time
+      imextract -region mcal
+      imextract -region airmass
+      imextract -region nstar
+      vstat time
+      clear -n 1;
+      section a 0 0.00 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3} -0.8 -0.5; box; plot time mcal
+      section b 0 0.33 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3}  0.95 3.0; box; plot time airmass
+      section c 0 0.66 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3} 0 3000; box; plot time nstar
+      style -n 0
+    end
+    if ("$KEY" == "s")
+      $tmp = $R$KEY
+      if ($tmp < 0) 
+        $tmp = $R$KEY + 360.0
+      end
+      $line = `echo $tmp $D$KEY | radec -hh`
+      imextract -region photcode
+      imextract -region time
+     
+      subset t = time if (int(photcode/100) == 1)
+      uniq t T
+      $Bn = t[]
+      $BN = T[]
+      
+      subset t = time if (int(photcode/100) == 2)
+      uniq t T
+      $Vn = t[]
+      $VN = T[]
+      
+      subset t = time if (int(photcode/100) == 3)
+      uniq t T
+      $Rn = t[]
+      $RN = T[]
+      
+      subset t = time if (int(photcode/100) == 4)
+      uniq t T
+      $In = t[]
+      $IN = T[]
+     
+      echo "$line  $Bn $BN  $Vn $VN  $Rn $RN  $In $IN"
+    end
+
+    if ("$KEY" == "p") 
+      echo "P - new coords; p - old coords"
+      cursor -g 1
+      exec echo $Rp $Dp $RP $DP >> fix.coords
+    end
+
+    if ("$KEY" == "y")
+      ccd I - 2MASS_J : 2MASS_J - 2MASS_K
+      lim -n 1 -1 10 -1 3; clear; box; plot -x 2 -pt 2 -sz 0.5 xv yv
+      dev -n 0 -g
+    end
+  end
+end
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/photcodes.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/photcodes.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/photcodes.htm	(revision 16632)
@@ -0,0 +1,30 @@
+<meta name=file  content=photcodes>
+<meta name=title content=photcodes>
+<meta name=page  content=photcodes>
+
+<p>
+The DVO photcodes define a photometric system, consisting of a
+detector, a filter, and a telescope.  
+
+<p>
+Many DVO commands which accept a photcode as an argument allow for
+the photcode name to be appended with a modifier which changes
+slightly the type of magnitude returned to the user.  
+
+<p>
+The type of photcode is
+specified by adding :type to a photcode.  Valid types consist of:
+<ul>
+<li> inst : instrumental magnitude
+<li>  cat : catalog magnitude = inst + nominal ZP
+<li>  sys : system magnitude = color + airmass corrected mag
+<li>  rel : relative magnitude = applies color, airmass, and relative magnitude offset
+corrections
+<li>  cal : calibrated magnitude : applies zero-point and color
+terms from dependent to primary/secondary magnitude system)
+<li>  ref : reference system
+</ul>
+
+<p>
+<em>This page needs serious work to clarify the meaning of a photcode,
+and the selection criteria </em>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/relphot.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/relphot.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/relphot.htm	(revision 16632)
@@ -0,0 +1,224 @@
+
+<h2> relphot outline </h2>
+
+<ul>
+<li> load data
+     <ul>
+     <li> images: match photcode and time range, reset flags
+     <li> measure: select subset matching restritions on:
+          photcode, time, dM, Minst, Mag, dophot == 1
+     </ul>
+<li> iterate to find Mcal, image.flags:
+<li> write out modified Mcal values to image table
+<li> write out modified Mcal values to measure table
+<li> write out modified Mrel values to average table
+</ul>
+
+<h2> relphot overview </h2>
+
+<p> relphot has two primary purposes:<br>
+<ul>
+<li> calculate <b>Mcal</b> for images / measures
+<li> calculate <b>Mrel</b> for stars
+</ul>
+
+<p> relphot can also be used to determine the mosaic grid used to generate
+photometrically corrected flats (-grid option).
+
+<h2> data exclusion </h2>
+
+<p> relphot uses only a subset of the photometry data to calculate
+Mcal and Mrel.  In the first stage, calculation of the Mcal values,
+relphot loads the photometry data from each relevant catalog and
+creates an internal subset catalog with the function
+<em>bcatalog</em>, excluding some of the irrelevant data.  In
+addition, it uses flags to mark some of the data as invalid for the
+processing.
+
+<b> bcatalog exclusions </b>
+<ul>
+<li> measure.photcode not equivalent to requested photcode
+<li> measure.dophot != 1
+<li> measure.Mcat > MAG_LIM
+<li> measure.dM > SIGMA_LIM
+<li> measure.Minst out of range (ImagMin - ImagMax) [optional]
+<li> measure.t out of range (TSTART, TSTOP)
+</ul>
+
+<b> flagged data </b>
+
+<b> flagged image data </b>
+
+images can be flagged by setting bits of <b>image.code</b>
+
+stars can be flagged by setting bits of <b>average.code</b>
+
+measures can be flagged by setting bits of <b>measure.flag</b>
+
+<b>image.code</b>
+
+ID_IMAGE_NOCAL : ignore, irrelevant
+ID_IMAGE_POOR  : image measured bad
+ID_IMAGE_SKIP  : externally known bad
+
+dMcal > VALUE       FLAG_IMAGE_SCATTER <em>clean_images</em>
+fabs(Mcal) > VALUE  FLAG_IMAGE_ZEROPT  <em>clean_images</em>
+
+dMcal > VALUE       FLAG_IMAGE_SCATTER <em>clean_mosaics</em>
+fabs(Mcal) > VALUE  FLAG_IMAGE_ZEROPT  <em>clean_mosaics</em>
+
+<em> mark_images </em> does not seem to do anything useful?
+
+<b>average.code</b>
+
+Ngood < MEAS_TOOFEW                     <em>setMrel</em>
+Ngood < MEAS_TOOFEW                     <em>clean_measures</em>
+ChiSq > STAR_CHISQ                      <em>clean_stars</em>
+dM    > STAR_SCATTER                    <em>clean_stars</em>
+
+average.code (STAR_BAD) is not saved by relphot: it is set by
+clean_stars, clean_measures, and setMrel, but not setMrelOutput.
+STAR_BAD should only be internal since it depends on the photcode, but
+is not associated with a specific photcode in the data.  Just in case,
+it is reset to 0 in setMrelFinal.
+
+<b>measure.flag</b>
+
+X,Y out of range                        <em>setExclusions</em>
+3 sigma clipping                        <em>clean_measures</em>
+
+<h2> setting Mrel final value </h2>
+
+setMrelFinal is used to set the final average.Mrel values.  We do this
+in 4 stages.  In each stage, we set the Mrel values for stars which
+have not already been set, based on the current exclusion settings.
+At successive stages, we relax the exclusions, allowing the more
+spurious objects to have a valid Mrel value to be set.  In this loop,
+we actually run setMrelOutput twice: once to get the approximate Mrel
+value, then we flag the outlier measurements with clean_measure,
+then we redetermine the Mrel values on this basis, and mark the stars
+for exclusion from the next iteration.  
+
+<pre>
+exclude on
+ photcode       0 1 2 3
+ time range     0 1 2 3
+ MEAS_POOR      0 1 2 3
+ MEAS_TOOFEW    0 1 2 3
+ dophot == 10   0 1 2 
+ inst mag       0 1 2 
+ dophot != 1,2  0 1  
+ ID_IMAGE_POOR  0 1
+ ID_IMAGE_SKIP  0 1
+ dophot != 1    0
+ measure.dM     0 
+</pre>
+
+for all relphot runs, Mrel is re-calculated, and measures are marked
+at least if they are outliers in mag or ccd area.
+
+setMrel.output needs to do a few things differently from setMrel:
+<ul>
+<li> set measure.Mcal (skipped in setMrel.basic)
+<li> set average.Mrel if N < TOO_FEW (not STAR_BAD) (optional!)
+<li> use MAX (stats.error, stats.sigma) (optionally)
+<li> allow STAR_BAD?
+</ul>
+
+<h2> imphotset </h2>
+
+imphotset allows you to set certain phot.image table entries.  here
+are the options:
+
+imphotset [-photcode code] [-name foo] [-trange (start) (stop)] -flag and value
+
+
+Here is a complete list of relphot configuration variable names, a
+quick description, and reasonable values to start with:
+
+<pre>
+--- configuration variables used by relphot ---
+MAG_LIM : float
+  ignore measurements fainter than this absolute magnitude
+
+SIGMA_LIM : float
+  ignore measurements with magnitude error larger than this value
+
+STAR_SCATTER : float
+  mark stars as bad if their scatter is larger than this value
+
+IMAGE_SCATTER : float
+  mark images as bad if their scatter is larger than this value
+
+IMAGE_OFFSET : float
+  mark images as bad if the absolute value of thie zero point offset
+  is larger than this number
+
+STAR_CHISQ : float
+  mark stars as variable if their reduced chisq are larger than this value
+
+STAR_TOOFEW : int
+  mark stars as bad if the have fewer than this number of valid measurements
+
+IMAGE_TOOFEW : int
+  mark images as bad if the have fewer than this number of valid measurements
+
+IMAGE_GOOD_FRACTION : float
+  mark images as bad if the have fewer than this fraction of valid measurements  
+
+IMAGE_CATALOG : string
+  name of the image catalog file
+
+IMAGE_CATALOG_TEMPLATE : string
+  name of the template file to create the image catalog file
+
+CATALOG_TEMPLATE : string
+  name of the template file to create the catalog file
+
+GSCFILE : string
+  name of the GSC region table
+
+CATDIR : string
+  directory where the database is stored
+
+PHOTCODE_FILE : string
+  file containing photometry code information
+
+ZERO_PT : float
+  default zero point for random data
+
+RELPHOT_GRID_X : int
+  scale of mosaic correction grid 
+
+RELPHOT_GRID_Y : int
+  scale of mosaic correction grid 
+
+RELPHOT_GRID_BINNING : int
+  deprecated
+
+CAMERA_CONFIG : string
+  name of the file containing descriptive information about the camera
+
+--- sample ConfigFile entries with typical values ---
+
+MAG_LIM                	 24.0
+SIGMA_LIM              	  0.05
+STAR_SCATTER           	  0.05
+IMAGE_SCATTER          	  0.05
+IMAGE_OFFSET           	  0.2
+STAR_CHISQ             	 10.0
+STAR_TOOFEW            	  3
+IMAGE_TOOFEW           	 10
+IMAGE_GOOD_FRACTION    	 
+IMAGE_CATALOG          	 $CATDIR/Images.dat
+IMAGE_CATALOG_TEMPLATE 	 $REFSDIR/elixir/template.cat
+CATALOG_TEMPLATE       	 $REFSDIR/elixir/template.cat
+GSCFILE                	 $REFSDIR/gsc/GSCregions.tbl
+CATDIR                 	 $CATDIR
+PHOTCODE_FILE          	 $CONFDIR/camera/$CAMERA.photcode
+ZERO_PT                	 25.0
+RELPHOT_GRID_X         	 4
+RELPHOT_GRID_Y         	 8
+RELPHOT_GRID_BINNING   	 512
+CAMERA_CONFIG          	 $CONFDIR/camera/$CAMERA.config
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/sequence.idx
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/sequence.idx	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/DVO/sequence.idx	(revision 16632)
@@ -0,0 +1,11 @@
+DVO-shell.htm
+commands.htm
+example.htm
+navigate.htm
+addstar.htm
+delstar.htm
+relphot.htm
+uniphot.htm
+markrock.htm
+markstar.htm
+imphotsearch.htm
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/detrend.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/detrend.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/detrend.htm	(revision 16632)
@@ -0,0 +1,84 @@
+<meta name=file  content=detrend>
+<meta name=title content=detrend.db tools>
+<meta name=page  content=detrend>
+
+<table>
+<tr><td><b><tt> detregister (filename) [elixir options] </tt></b></td></tr>
+
+<tr><td> 
+
+Register a detrend image in the detrend database.  The image
+parameters are automatically loaded from the image header, but can be
+forced with command-line options if needed.  The database consists of
+a database table and a hierarchy of directories.  The registered image
+is copied to the directory structure, assigned an appropriate name
+based on the data type, and an entry added to the database table.
+Below, the command-line options are listed. The matched keyword define
+the header keywords used to automatically identify the values.
+Keywords starting with $ represent the configuration variables which
+provide abstract names to define the real keywords.  The idiosyncratic
+header filter name is converted to the Elixir internal filter name
+based on the filter name table $FILTER_LIST.
+
+<table>
+<tr><th> option               </th><th> equivalent keyword </th><th> description </th></tr>
+<tr><td> -time (start) (stop) </td><td> TV_START, TV_STOP  </td><td>
+<tr><td> -label (label)	      </td><td>	N/A		   </td><td>
+<tr><td> -ID (ID)	      </td><td>	N/A		   </td><td>
+<tr><td> -order (N)	      </td><td>	N/A		   </td><td>
+<tr><td> -type (type)	      </td><td>	$IMAGETYPE-KEYWORD </td><td>
+<tr><td> -ccd (ccdID)	      </td><td>	$CCDNUM-KEYWORD    </td><td>
+<tr><td> -exptime (seconds)   </td><td>	$EXPTIME-KEYWORD   </td><td>
+<tr><td> -filter (name)       </td><td>	$FILTER-KEYWORD	   </td><td>
+</table>
+</tr></td> 
+
+<tr><td><b><tt> detsearch [search options] [elixir options] </tt></b></td></tr>
+
+<tr><td> 
+
+Examine the contents of the detrend database, with options to filter
+the output.  
+
+<table>
+<tr><th colspan=2> options which limit the image selection </th></tr>
+<tr><td> -label (label)	       </td><td> select images by label </td><td>
+<tr><td> -ID (ID)	       </td><td> select images by ID    </td><td>
+<tr><td> -order (N)	       </td><td> select images by order </td><td>
+<tr><td> -type (type)	       </td><td> select images by type (FLAT, etc) </td><td>
+<tr><td> -mode (mode)	       </td><td> select images by mode (MEF, etc)  </td><td>
+<tr><td> -ccd (ccdID)	       </td><td> select images by CCD ID </td><td>
+<tr><td> -exptime (seconds)    </td><td> select images by exposure time </td><td>
+<tr><td> -filter (name)        </td><td> select images by filter </td><td>
+<tr><td> -time (time)          </td><td> select images for given point in time </td><td>
+<tr><td> -trange (start) (stop)</td><td> select images for given time range  </td><td>
+<tr><td> -entry (entry)        </td><td> select images by entry number </td><td>
+<tr><td> -match (number)       </td><td> select images by match number </td><td>
+<tr><td> -name (name)          </td><td> select images by name </td><td>
+<tr><td> -mosaic (filename)    </td><td> select images appropriate to given mosaic </td><td>                
+<tr><td> -image (file) (ccd) (mode)</td><td> select images appropriate to given CCD image </td><td>
+
+<tr><th colspan=2> options which modify the output format </th></tr>
+<tr><td> -tstop                </td><td> print stop time, not start time </td><td>
+<tr><td> -treg                 </td><td> print registration time, not start time </td><td>
+<tr><td> -ve                   </td><td> print SUCCESS / FAILURE on exit </td><td>
+<tr><td> -quiet                </td><td> do not print SUCCESS / FAILURE on exit </td><td>
+<tr><td> -fits (output)        </td><td> write ASCII FITS table (appropriate for CFHT-LS) </td><td>
+<tr><td> -binfits(output)      </td><td> write binary FITS table (can be used as database table) </td><td>
+<tr><td> -chipname             </td><td> provide chip-specific name for MEF entry (ie flat.fits[ccd00]) </td><td>
+
+<tr><th colspan=2> options which modify the behavior </th></tr>
+<tr><td> -select               </td><td> select 'best' detrend image, include complete path </td><td>
+<tr><td> -recipe               </td><td> select all detrend images in recipe for this filter </td><td>
+<tr><td> -h, --help            </td><td> list help information </td><td>
+<tr><td> -criteria             </td><td> list input criteria, not database entries </td><td>
+
+<tr><th colspan=2> options which modify the database table </th></tr>
+<tr><td> -delete, -del         </td><td> delete the selected images </td><td>
+<tr><td> -altpath add          </td><td> add selected images to altpath </td><td>
+<tr><td> -altpath del          </td><td> remove selected images from altpath </td><td>
+<tr><td> -altpath update       </td><td> update altpath value based on file existence </td><td>
+<tr><td> -modify               </td><td> modify selected database fields </td><td>
+</table>
+</tr></td> 
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/imreg.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/imreg.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/imreg.htm	(revision 16632)
@@ -0,0 +1,92 @@
+<meta name=file  content=imreg>
+<meta name=title content=imreg.db tools>
+<meta name=page  content=imreg>
+
+<h3> add information about gconfig variables used </h3>
+
+<table>
+<tr><td><b><tt> imregister (filename) [-split] [-noreg] [-v] [-needtype] [elixir options] </tt></b></td></tr>
+
+<tr><td> 
+
+Register an image in the imreg database.  The -split option tells
+imregister that a single CCD frame is one of multiple frames in a
+split image.  The -noreg option shows the processing information
+without updating the database table.  The -v turns on verbosity.  The
+-needtype requires the image type to be one of the known types to be
+registered.
+
+</tr></td> 
+
+<tr><td><b><tt> imsort (filename) [-split] [-noreg] [-v] [-needtype] [elixir options] </tt></b></td></tr>
+
+<tr><td> identical to 'imregister', but also send entries as
+appropriate to the imstats and ptolemy elixir fifos.  If -noreg is
+selected, the fifo entries are created without the imreg.db
+update. </tr></td>
+
+<tr><td><b><tt> showiminfo (filename) [-split] [-noreg] [-v] [elixir options] </tt></b></td></tr>
+
+<tr><td> list image information extracted from the header, as used to
+update imreg.  </tr></td>
+
+<tr><td><b><tt> imstatreg (fits) (stats) (sdat) [-split] [-noreg] [-v] [-needtype] [elixir options] </tt></b></td></tr>
+
+<tr><td> add image statistics (seeing, bias, sky) to the image entry
+in the imreg table.  The (fits) file need only contain the relevant
+header of the image (used to find the appropriate image in the table).
+The (stats) file consists of the values sky and bias for MEF and SPLIT
+images, while for other modes, there must be an addtional entry
+starting each line: CCD.  The meaning is undefined for SINGLE, and
+usually set to 0.  For CUBE it is the number of slices in the cube,
+while for SLICE, it is the slice entry.  </tr></td>
+
+<tr><td><b><tt> imstatreg -daemon [-v] [-status] [-kill] [-delay Nsec] [elixir options] </tt></b></td></tr>
+
+<tr><td> Start / Stop / Query the imstatreg daemon.  To facility the
+database I/O, imstatreg updates are written to a buffer table
+(imreg.reg.bfr), which is occasionally merged with the master table
+with the imstatreg daemon.The -delay option defines the frequency at
+which imstatreg -daemon updates the database table.  </tr></td>
+
+<tr><td><b><tt> imregtable (filename) [elixir options] </tt></b></td></tr>
+
+<tr><td> 
+merge the given imreg.db table with the current master table.
+</tr></td> 
+
+<tr><td><b><tt> imsearch </tt></b></td></tr>
+
+<tr><td> 
+search the imreg.db table for images, filterd by the options given in the arguments.  
+The table below lists all options to imsearch.
+
+<table>
+<tr><th colspan=2> options which limit the image selection </th></tr>
+<tr><td> [-type type]                 </td><td> limit by image type (BIAS, DARK, OBJECT, etc)         </tr></td> 
+<tr><td> [-mode mode] 		      </td><td> limit by image mode (SINGLE, SPLIT, MEF, CUBE, SLICE)	 </tr></td> 
+<tr><td> [-trange start stop/range]   </td><td> limit by date range (second argument may be an end date or a time range) </tr></td> 
+<tr><td> [-ccd name]		      </td><td> limit by CCD; use CCD ids, not sequence numbers (ccd00 not 00) </tr></td> 
+<tr><td> [-etime exptime] 	      </td><td> limit by exposure time (seconds)	 </tr></td> 
+<tr><td> [-filter name] 	      </td><td> limit by filter name	 </tr></td> 
+<tr><td> [-name string] 	      </td><td> limit by image name (matches substring of full image name) </tr></td> 
+<tr><td> [-proc t/f]		      </td><td> include only processed / unprocessed images (bias != 0)	 </tr></td> 
+<tr><td> [-dist t/f]		      </td><td> include only distributed images (table send to CADC)	 </tr></td> 
+<tr><td> </tr></td>
+				      	 	 	 
+<tr><th colspan=2> options which modify the output format </th></tr>
+<tr><td> [-treg] 		      </td><td> list the registered times, not exposure times </tr></td> 
+<tr><td> [-seq] 		      </td><td> print CCD sequence numbers, not IDs </tr></td> 
+<tr><td> [-pt] 			      </td><td> print the list in ptolemy input format </tr></td> 
+<tr><td> [-table] 		      </td><td> generate a complete ascii FITS table output </tr></td> 
+<tr><td> [-cadctable] 		      </td><td> generate the CADC raw table (one row per mosaic, includes mosaic IQ stats) </tr></td> 
+<tr><td> [-bintable]		      </td><td> generate a complete binary FITS table (can be used as new database) </tr></td> 
+
+<tr><th colspan=2> options which modify the database table </th></tr>
+<tr><td> [-delete] 		      </td><td> delete the selected images </tr></td> 
+<tr><td> [-modify (options)]	      </td><td> modify certain fields of the selected images </tr></td> 
+</table>
+
+</tr></td> 
+</table>
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/index.htm	(revision 16632)
@@ -0,0 +1,18 @@
+<meta name=file  content=Foobar>
+<meta name=title content=Elixir Database Tools>
+<meta name=page  content=Elixir Database Tools>
+
+This section describes Elixir Database interface tools provided by
+Ohana.  The Elixir database consists of the following tables:
+
+<ul>
+<li> imreg : all of the raw images
+<li> detrend : the master detrend images
+<li> photcode : the nominal filter transformation information
+<li> zeropoints : the measured zero-point data values
+<li> transparency : the measured transpareny over long periods (nights or lunations)
+</ul>
+
+In addition, the DVO program is used to maintain a database of the
+photometric measurements of all detected objects.  DVO is described in
+a separate section.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/mkfringetable.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/mkfringetable.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/mkfringetable.txt	(revision 16632)
@@ -0,0 +1,35 @@
+
+mkfringetable (layout) (output)
+
+'mkfringetable' generates a MEF FITS ASCII Table of fringe couples
+based on a simple template file.  The layout file defines the basic
+constraints of the fringe couple lists (filter, time range, ccds,
+etc), and identifies the files used for each CCD.  The output file is
+a MEF FITS file with one extension per CCD.  Each extension consists
+of a table with four columns: X_MIN, Y_MIN, X_MAX, Y_MAX.  An example
+layout file is given below.  The primary header unit of the FITS file
+contains the basic information of the CAMERA, FILTER, etc.  
+
+
+Example layout file:
+
+# layout file for mkfringetable
+
+FILTER   I
+CAMERA   megaprime
+TVSTART  1999/9/1
+TVSTOP   2010/1/1
+NCCD     12
+CCD00    00  CFH12K-I-CCD00-FringeCoord.reg
+CCD01    01  CFH12K-I-CCD01-FringeCoord.reg
+CCD02    02  CFH12K-I-CCD02-FringeCoord.reg
+CCD03    03  CFH12K-I-CCD03-FringeCoord.reg
+CCD04    04  CFH12K-I-CCD04-FringeCoord.reg
+CCD05    05  CFH12K-I-CCD05-FringeCoord.reg
+CCD06    06  CFH12K-I-CCD06-FringeCoord.reg
+CCD07    07  CFH12K-I-CCD07-FringeCoord.reg
+CCD08    08  CFH12K-I-CCD08-FringeCoord.reg
+CCD09    09  CFH12K-I-CCD09-FringeCoord.reg
+CCD10    10  CFH12K-I-CCD10-FringeCoord.reg
+CCD11    11  CFH12K-I-CCD11-FringeCoord.reg
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/photcode.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/photcode.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-DB/photcode.htm	(revision 16632)
@@ -0,0 +1,5 @@
+<meta name=file  content=photcode>
+<meta name=title content=photcode>
+<meta name=page  content=photcode>
+
+Sorry!  The page you requested is not yet available.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/elixir.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/elixir.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/elixir.htm	(revision 16632)
@@ -0,0 +1,437 @@
+<meta name=file  content=gcontrol>
+<meta name=title content=gcontrol: the program-organization program>
+<meta name=page  content=gcontrol>
+
+<b> Overview </b>
+
+<p>
+In a large data analysis project such as Elixir, there are usually
+certain sub-systems which resemble an assembly line: A continuous
+stream of objects, each one very similar to the next, enters a
+factory.  They pass through a series of stages at which some process
+occurs, each step along the way being performed in essentially the
+same way for each object it encounters.  At the end of the assembly
+line, a new object (or objects) appears, fashioned from the original
+that entered at the other end.  
+
+<p>
+Consider, for example, a scientific analysis of images from the
+telescope.  Each image is essentially the same as any other, differing
+only in detail.  A sequence of steps is performed on each image: for
+example, detrending, object detection, and astrometry.  As the
+analysis proceeds, each step performs a transformation on its input
+object, creating a new, slightly modified object.  The result of the
+analysis step may create a new data file, or they may simply alter
+some portion of the file provided.  
+
+<p>
+Because each step in the analysis is identical for every image, there
+is a regularity to the commands which are executed.  For example,
+consider an input science image called <tt> image01.fits </tt>.  The series
+of commands needed to arrive at the final results might consist of:
+
+<pre>
+detrend image01.fits image01.flt
+detect  image01.flt  image01.dat
+astrom  image01.dat  image01.astro
+</pre>
+
+<p>
+Each step in this analysis sequence produces a new file, and each file
+is only different in a portion of the filename.  If the input image
+had been called <tt>image02.fits</tt>, we could easily reconstruct the
+above sequence of commands, replacing <tt>image01</tt> for
+<tt>image02</tt>.
+
+<p>
+We developed the program `elixir' to make it very easy to define a
+sequence of steps which are performed identically for a sequence of
+similar objects in a list.  Elixir is very flexible:  the sequence of
+operations for a given implementation are defined in a simple text
+configuration file, and can consist of essentially any operations
+which fit into the assembly-line model.  Each implementation can be
+drastically different, and need not operated just on images, but any
+anslyis sequence.  We call a specific implementation an `elixir', and
+usually give the elixir a name relevant to its task.
+
+<p>
+Because of the assembly-line nature of the elixir model, it is easy to
+extend the concept from one computer to a network of computers.  Not
+only does `elixir' construct the commands as needed, it also executes
+those commands on any of a collection of computers, keeping track of
+which computers are currently being used and which are currently
+free.  
+
+<p class=figure>
+<img class=figure src=pics/elixir-node.png alt="Elixir node"><br>
+Figure 1: Elixir node
+</p>
+
+<b> List-based command generation </b>
+
+<p>
+To visualize the elixir process, consider each of the analysis steps
+as a node, as shown in Figure 1.  Each node has three queues, an input
+queue of pending objects, a 'success' queue, and a 'failure' queue.
+Each node represents a single command, such as 'detrend' in the
+example above.  The node receives as input a word or a set of words
+which define the object being analysed.  Associated with each node is
+a set of rules to generate the complete command, including possible
+variations on the input words, as necessary.  In the example above,
+the input list might simply consist of the input image names, <tt>
+image01.fits </tt>, <tt> image02.fits </tt>, etc.  The rule for the `detrend'
+node would construct the command <tt> detrend image01.fits
+image01.flt </tt>.
+
+<p>
+Each node in Elixir uses its rule to generate a command, such as <tt>
+detrend image01.fits image01.flt </tt> and start its execution.  When this
+command is finished being executed, the node passes the associated
+words to either the `success' or the `failure' queues, based on the
+command's exit status.  Each success and failure queues are connected
+in turn to the pending queue of another node.  In this way, a
+successful `detrend' command for <tt> image01.fits </tt> would pass the
+word <tt> image01.fits </tt> to its success queue, which is in turn
+connected to the pending queue of the `detect' node.  There is a
+special node called 'global' which represents the entire elixir
+process.  The pending, success, and failure queues of the global node
+represent the global input and output of the elixir analysis.  Thus,
+objects are introduced into the process by placing them in the global
+input queue.  The objects are finished when they reach either the
+global success or failure queues (having a status for the entire
+process of 'success' or 'failure').
+
+<p>
+In order for a node to execute a command, it needs to be given a
+machine on which to run the command.  Elixir maintains a pool of
+available computers.  When a node is ready to execute a command, it
+requests a machine from the pool of free computers.  If none are free,
+it waits for a while then tries again.  If a computer is free, the
+node receives control of the machine, and starts the execution of its
+process.  The node then monitors the output from the machine, saving
+all messages in a log file specific to the current object.
+Eventually, the process finishes, and the node passes the object to
+the appropriate output queue.  At this point, it returns the machine
+to the pool of free machines, and grabs the next object from its
+pending queue, if any.  This process limits the number of executing
+processes to the number of available machines.  This is a very simple,
+but very reliable way of balancing the load on each machine.  As long
+as none of the analysis steps individually overloads the machine
+resources, each machine will be used at an appropriate level.
+
+<p>
+The machines which are available to the Elixir process are simply
+listed in the elixir configuration file.  This makes it easy to change
+the collection of machines used for a given elixir implementation.  In
+practice, if the analysis steps for a particular elixir underload each
+of the machines available to it, multiple entries for each machine can
+be included in the configuration list, increasing the demands on the
+individual machines.
+
+<p class=figure>
+<img class=figure src=pics/elixir-collection.png alt="elixir command example"><br>
+Figure 2: Example elixir command system
+</p>
+
+<b> Elixir configuration </b> 
+
+<p>
+The Elixir configuration file makes if very easy to define a sequence
+of commands and the rules for generating the command line arguments.
+In the configuration file, most lines consist of keyword / value
+pairs.  The keyword can consist of any non-white space.  The value may
+contain any ASCII characters at all, including spaces.  If there are multiple
+entries of the same keyword, the last one provides the value.  
+Keywords defined in the configuration file may be referred to
+elsewhere by appending a dollar sign: $KEYWORD.  The entire
+configuration file is loaded before variables such as this are parsed,
+so order is not important.  
+
+<p>
+In addition to the keyword / value entries, there are a limited number
+of other possible entries.  Lines with a leading hash mark (#) are
+commented out.  A line beginning with the word 'input' is a command to
+load additional configuration information from another file.  In this
+special case, variables used to define the filename must already exist
+in the configuration file loaded so far.  These details about the
+configuration file are relevant to other programs in addition to
+`elixir'.  
+
+<p>
+Finally, we come to the portion of the configuration file which
+defines the components of the specific elixir implementation.  Each
+node in the elixir process is defined by a block which looks like
+this:
+
+<pre>
+process detrend
+detrend.arg      0        detrend
+detrend.arg      5 %s     &0
+detrend.arg      0 %s.flt BASE(&0) 
+detrend.success           detect
+detrend.failure	          global
+</pre>
+
+<p>
+The first line here, <tt> process detrend </tt>, defines the node.  The
+next three lines, beginning with <tt> detrend.arg </tt>, define the syntax
+of the command associated with that node.  The first entry is the
+program, the next two lines generate the first and second argument to
+the program.  The executed command (<tt> detrend </tt>) and the name of the
+node are not required to be the same.  It is particularly important to
+note that the order of these lines in the configuration file matters:
+the order of the command-line arguments is the order of the lines in
+the configuration file.  
+
+<p>
+These lines define how to generate the arguments by providing a
+C-style format statement and a set of arguments to the format
+statement.  Let us first consider the input list.  The input list to
+Elixir describes a set of objects to be analysed.  In our example
+above, these consisted of the names of the raw science images:
+
+<pre>
+image01.fits
+image02.fits
+image03.fits
+</pre>
+
+and so on. In this example, there is only one word on each line to
+describe the objects.  It is possible to have multiple words to
+describe a single object.  For example, to define a specific CCD image
+in both MEF & SPLIT style images, one could use lines like:
+
+<pre>
+image01.fits X SPLIT
+image.fits 00 MEF
+image.fits 01 MEF
+image.fits 02 MEF
+image03.fits X SPLIT
+</pre>
+
+In this example, the first word is a file name, the second defines the
+CCD for MEF images (and is ignored for SPLIT), the third identifies
+the image type, SPLIT vs MEF.  In the elixir configuration file, the
+first word on each line is identified by &0, the second by &1, etc.
+Thus, in the <tt> process detrend </tt> example above, the line which reads
+<tt> detrend.arg 5 %s &0 </tt> constructs an argument which just consists
+of the first word for each line.  
+
+<p>
+The following line shows the use of the filename manipulation
+functions available within the Elixir configuration system.  These
+functions are only available when defining the Elixir node command
+line arguments.  In this example, <tt> detrend.arg 0 %s.flt
+BASE(&0) </tt>, the argument is constructed by taking the first word
+(&0), stripping off the path and extension from the file name (ie,
+taking /path/file.ext and returning 'file'), and appending the string
+'.flt' to that word.  This de-construction of the filename is provided
+by the BASE function.  Other string manipulation functions are
+available, mostly functions relevant to manipulating file names.  Some
+of the available functions are: 
+
+<ul>
+<li> BASE   -  return file basename
+<li> EXT    -  return file extension
+<li> PATH   -  return file pathname
+</ul>
+
+Other functions will be added as they become necessary.
+
+<p>
+These configuration formatting lines are somewhat limited compared
+with standard C formatting commands: There can only be one word
+defined by the format (ie., no white space is allowed).  The only
+formatting command currently allowed is %s.  
+
+<p>
+The only remaining portion of these format lines which has not yet
+been described is the number in the second position.  The number in
+the second space on each line represents part of the flow control
+process.  A positive definite number here says that the word formed by
+this line is a filename which must exist before the process should be
+run.  The number tells how many seconds elixir should wait for the
+object to appear before giving up on this object.  This timeout is
+provided for various possible uses.  One basic use is to avoid NFS
+latency problems.  It is not unusual under NFS for a file created on
+one machine not to appear on a cross-mounted disk on a second machine
+for some tenths of seconds or so.  
+
+<p>
+The final two lines which define this elixir node are used to make the
+connection between the node and other nodes.  The first, <tt>
+detrend.success detect </tt>, tells elixir to connect the success queue of the
+detrend process to the pending queue of the `detect' process.  The
+second line, <tt> detrend.failure global </tt>, tells elixir to connect the
+failure queue of this process to the global failure queue.  Similarly,
+the success queue of the last node should be connected to the global
+success queue.  
+
+<p>
+There is also a set of configuration entries which define global
+concepts for the elixir, including the actions of the global input /
+output queue.  The required entries of this type of listed here:
+<pre>
+global.success	/path/analysis.success
+global.failure	/path/analysis.failure
+global.source	/path/analysis.source
+global.msg	/path/analysis.msg
+global.end	/path/analysis.end
+global.Nargs	3
+global.logfile  0 %s.log  BASE(&0)
+global.pending	detrend
+global.timeout  1200.0
+</pre>
+
+<p>
+The first two entries, <tt> global.success </tt> and <tt>
+global.failure </tt>
+define the output files for the globals success and failure queues.
+When an object lands on either of these queues, the object and the
+exit status are written to the named file, and the object is marked as
+being completed.  The entry <tt> global.pending </tt> defines the first
+node in the process.  <tt> global.timeout </tt> defines a timeout period in
+seconds: if a process provides not output for this much time, elixir
+decides that it has hung and kills it.  The entry <tt> global.logfile </tt>
+defines the rules for generating a log file name for each object,
+using a syntax identical to the command-line argument generation
+lines.  <tt> global.end </tt> is a file to which elixir writes a collection
+of processing statistics after a complete analysis is done.   <tt>
+global.msg </tt> provides a way for elixir to communicate with other
+processes.  Finally, we leave the description of <tt> global.source </tt>
+until after we describe how objects are passed to Elixir.
+
+<b> Elixir Communication Issues </b>
+
+<p>
+The input to an elixir process is a list consisting of lines with
+words which define the specific objects, such as a list of image
+names.  There are two ways in which elixir may be presented such a
+list.  In the simple case, when the program is started, a filename is
+given as a command line argument.  This file contain a complete list
+of names for the elixir run.  The lines from this list are loaded and
+passed to the global.pending queue, which in turn passes them to the
+first node.  Once the elixir process has finished with all of the
+entries in the file, it exits, and the process is complete.
+
+<p>
+The other possibility is to use a mechanism we call an input FIFO.  In
+our implementaton, a FIFO is not a standard UNIX fifo-type special
+file.  We have avoided the use of true fifos for two reasons.  First,
+it would be necessary for a special file to be created for each
+implementation of elixir (by root), which makes it a non-trival task
+to create a new elixir implementation.  Second, the data in a standard
+UNIX fifo is ephemeral.  If the programs on either end of the fifo are
+not running, there is no guarantee that the data will remain (the
+situation with socketed connections is even worse).  Instead, we have
+chosen to implement a type of FIFO by using a normal UNIX file which
+one program writes to and another reads the data from.  To avoid
+conflicts between programs, we simply lock the file each time we are
+accessing it.  Messages are passed to Elixir using this mechanism, and
+so are the lines which define new objects.
+
+<p>
+If elixir is not invoked with a list file on the command line, it
+instead monitors the file defined by <tt> global.source </tt>.  Anytime
+elixir looks for object entries in this file, the file is locked
+first.  Then, when the lines have been loaded, the file is cleared.
+In this way, a second program can add lines to this file at arbitrary
+times without danger of losing any entries, whether or not the
+particular elixir is already running.  When the external program
+writes to the file, it also locks it, so elixir will not load the
+entries before it is ready. Then, when it has written the entries, the
+file is unlocked, ready for elixir to grab the new list of names.  
+
+<p>
+In this mode, elixir runs continuously, waiting for more entries in
+the FIFO file.  A mechanism to end the elixir run is made possible by
+having elixir recognized a special word in the FIFO.  If elixir
+encounters the word EOF, it will no longer accept input from the FIFO,
+and will exit when all of the entries it has already loaded have been
+processed.  The same goal can be accomplished by passing the elixir a
+message saying 'STOP' via the message FIFO.
+
+<p>
+Elixir runs like a daemon, in the background with no output directly
+to the screen (except for serious errors).  It is possible to monitor
+the progress of the elixir run by communicating through the message
+FIFO.  Elixir monitors the message fifo for several specific requests,
+and responds to them as they arrive.  Typically a request will include
+a command, such as STATUS and a filename, where the requested
+information should be placed.  Other messages include 'STOP' (halt
+processing and exit when all objects have been processed), 'KILL'
+(halt all processing immediately), and 'TIME' (provide a set of
+statistics on process times).
+
+<p>
+Elixir uses either the rsh or ssh commands to make the connections to
+the remote machines.  All machines are treated as remote, even the
+machine on which elixir is run.  Elixir forks off a process which logs
+into the remote machine and starts a new shell (csh).  The STDIN,
+STDOUT, and STDERR connections are used for communication between the
+remote shell and elixir.  Programs are started by executing the
+command in the shell. 
+
+<p>
+The configuration file used by Elixir may also contain configuration
+information for a variety of other programs.  Elixir saves a copy of
+the complete configuration and passes this filename to those programs
+which can interpret it with the PTOLEMY environment variable.  This
+name tells the Elixir programs what configuration file to load.  By
+specifying this value as an environment variable, it will override
+other choices so that elixir can guarantee that the programs it
+launches have a consitent, known set of configuration choices.  
+
+<p>
+The other unique feature in the command line aids the process control.
+Every command is followed by an echo of the words "PROCESS DONE".  As
+the programs run, elixir monitors the output stream looking for three
+special phrases.  One is this 'PROCESS DONE' phrase.  Another is the
+word "SUCCESS" and the third is the word "ERROR".  By looking for
+combinations of these words, elixir can determine if the program ended
+successfully, failed, or if the computer crashed.  To interact well
+with Elixir, programs should send the correct word "SUCCESS" or
+"ERROR" on exit.  If necessary, one can wrap the program in a shell
+which monitors the exit status and sends the correct word.  If this is
+not possible, it is always possible to assume the process always ends
+successfully and include these words as an echo on the command line.
+
+<font size=-1>
+
+<p>
+<b> A short note about our use of filelocks </b>.  We have implemented a
+somewhat complex type of file lock mechanism.  We do not want to use a
+standard NFS implemented lock, particularly for the locks on our
+database files.   The problem the standard filelocking mechanism under
+UNIX/NFS is that the lock only exists if the program holding the lock
+is running.  This is insufficient to maintain data integrity.
+Consider a database which consists of several distinct files.  A
+particular write operation to the database may need to manipulate more
+than one file, and it needs to be sure those files are not also
+changed by another program in the meantime.  To avoid this, it should
+set a lock (on the files or on the whole database).  Then it should
+write to the files, then it should clear the lock.  Consider, though,
+what would happen in the program were to crash or be killed after
+writing the first file, but before writing the second.  The data in
+the two would be inconsistent.  At that point, if a second program
+tried to write to the database, it could easily corrupt the data,
+making it rather difficult to correct the problem.  With the standard
+UNIX/NFS locks, the lock is ephemeral - it only exists as long as the
+program is running (and certainly only while the machine is up).  In
+this example, it is easy to imagine that, by the time the second
+program comes along, the files are out of sync but the lock is no
+longer set.  We wanted a lock that would be guaranteed to exist until
+it was actively cleared, either by the program in its usual way, or by
+a person (or program) which has found the problem and fixed it.   
+
+<p>
+To implement such a lock, we create a lock in two stages.  The file
+that is being locked (ie, filename) is associated with the lockfile of
+the form .filename.lck.  The lockfile is locked with NFS style locks.
+Then the word BUSY is written to the lockfile.  At this point the NFS
+lock doesn't matter, and can be cleared or left.  Even if the program
+dies, the word BUSY remains to prevent another program from taking the
+lock.  When it is time to clear the lock, the file is either deleted
+or the word IDLE is written to it.  
+
+</font>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/index.htm	(revision 16632)
@@ -0,0 +1,15 @@
+<meta name=file  content=Foobar>
+<meta name=title content=Elixir System Infrastructure>
+<meta name=page  content=Elixir System Infrastructure Components>
+
+This section describes the Ohana programs used to tie the Elixir
+System together.  These include
+
+<ul>
+<li> elixir : the parallel-processing program organization tool
+<li> mkdetrend : the detrend analysis tool
+<li> mkfringe : the fringe-frame analysis tool
+<li> nightd : the nightly process launching system
+<li> postrun : the end-of-run analysis management tool
+<li> gconfig : the Elixir configuration database interface tool
+</ul>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/mkdetrend.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/mkdetrend.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/mkdetrend.htm	(revision 16632)
@@ -0,0 +1,69 @@
+<meta name=file  content=mkdetrend>
+<meta name=title content=mkdetrend User's Guide>
+<meta name=page  content=mkdetrend>
+
+<p>
+mkdetrend is the interface to the Elixir detrend creation system.  
+
+<p>
+All date/times are in the form YYYY/MM/DD,HH:MM:SS, with HH:MM:SS optional.  
+
+<p>
+By default, commands apply to the currently active camera/run, but
+these may be specified on the command line with the -camera (camera)
+and -run (run) flags.
+
+<h2> primary user commands </h2>
+
+<table>
+<tr><td> create (camera) (run) (start) (stop) </td><td> create a new mkdetrend run for the given camera, normally automatically performed by ert. </td></tr>
+<tr><td> create run (runid)                   </td><td> create a new mkdetrend run based on the mkrun table information. </td></tr>
+<tr><td> config (camera) (run)                </td><td> set the current active config </td></tr>
+<tr><td> state                                </td><td> show the state of the active config </td></tr>
+<tr><td> init                                 </td><td> start the init stage of mkdetrend processing </td></tr>
+<tr><td> run                                  </td><td> start the main processing, or re-processing </td></tr>
+<tr><td> reg                                  </td><td> register the completed images in the detrend database </td></tr>
+<tr><td> clean                                </td><td> clean the camera/run directories; recovery from this command will require a complete reprocessing. </td></tr>
+<tr><td> reset (level)                        </td><td> reset the configs. if level is 'hard', all will be reset.  if level is 'update', configs may be reset to 'init' or 'update', depending on their state.  </td></tr>
+<tr><td> update                               </td><td> perform an update run (identify new images, process residuals, but do not generate master). </td></tr>
+<tr><td> auto (cmd)                           </td><td> automatic processing commands </td></tr>
+</table>
+
+<h2> low-level user comands </h2>
+<table>
+<tr><td> dup (config)                         </td><td> duplicate the given config </td></tr>
+<tr><td> del (config)                         </td><td> delete the given config </td></tr>
+<tr><td> def (config) (start) (stop)          </td><td> set the start & stop times for the given config </td></tr>
+<tr><td> set (config) (state)                 </td><td> manually set the config state </td></tr>
+<tr><td> list.init                            </td><td> run just the list.init stage </td></tr>
+<tr><td> split                                </td><td> run just the split stage </td></tr>
+<tr><td> flips                                </td><td> run just the flips stage </td></tr>
+<tr><td> norm                                 </td><td> run just the norm stage </td></tr>
+<tr><td> scat                                 </td><td> run just the scat stage </td></tr>
+<tr><td> merge                                </td><td> run just the merge stage </td></tr>
+<tr><td> update.list                          </td><td> run just the update.list stage </td></tr>
+<tr><td> update.stats                         </td><td> run just the update.stats stage </td></tr>
+</table>
+
+<h2> HTML cgibin commands </h2>
+<table>
+<tr><td> htmldup </td><td>  </td></tr>
+<tr><td> htmldef </td><td>  </td></tr>
+<tr><td> htmldel </td><td>  </td></tr>
+<tr><td> htmlmod </td><td>  </td></tr>
+<tr><td> htmlkeep </td><td>  </td></tr>
+<tr><td> htmlconfig </td><td>  </td></tr>
+<tr><td> html1 </td><td>  </td></tr>
+<tr><td> html2 </td><td>  </td></tr>
+<tr><td> html3 </td><td>  </td></tr>
+</table>
+
+<h2> other support commands </h2>
+<table>
+<tr><td> dads </td><td>  </td></tr>
+<tr><td> dads.top </td><td>  </td></tr>
+<tr><td> meval </td><td>  </td></tr>
+<tr><td> eval </td><td>  </td></tr>
+<tr><td> fix.masters </td><td>  </td></tr>
+<tr><td> check.splits </td><td>  </td></tr>
+</table>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/mkfringe.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/mkfringe.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/mkfringe.htm	(revision 16632)
@@ -0,0 +1,69 @@
+<meta name=file  content=mkfringe>
+<meta name=title content=mkfringe User's Guide>
+<meta name=page  content=mkfringe>
+
+<p>
+mkfringe is the interface to the Elixir fringe creation system.  
+
+<p>
+All date/times are in the form YYYY/MM/DD,HH:MM:SS, with HH:MM:SS optional.  
+
+<p>
+By default, commands apply to the currently active camera/run, but
+these may be specified on the command line with the -camera (camera)
+and -run (run) flags.
+
+<h2> primary user commands </h2>
+
+<table>
+<tr><td> create (camera) (run) (start) (stop) </td><td> create a new mkfringe run for the given camera, normally automatically performed by ert. </td></tr>
+<tr><td> create run (runid)                   </td><td> create a new mkfringe run based on the mkrun table information. </td></tr>
+<tr><td> mkconfig (camera) (run)              </td><td> create an mkfringe config table based on an existing mkdetrend date range </td></tr>
+<tr><td> config (camera) (run)                </td><td> set the current active config </td></tr>
+<tr><td> state                                </td><td> show the state of the active config </td></tr>
+<tr><td> init                                 </td><td> start the init stage of mkfringe processing </td></tr>
+<tr><td> run                                  </td><td> start the main processing, or re-processing </td></tr>
+<tr><td> reg                                  </td><td> register the completed images in the detrend database </td></tr>
+<tr><td> map                                  </td><td> start the map run (requires manually setting state to map) </td></tr>
+<tr><td> map.reg                              </td><td> register mode maps </td></tr>
+<tr><td> clean                                </td><td> clean the camera/run directories; recovery from this command will require a complete reprocessing. </td></tr>
+</table>
+
+<h2> low-level user comands </h2>
+<table>
+<tr><td> dup (config)                         </td><td> duplicate the given config </td></tr>
+<tr><td> del (config)                         </td><td> delete the given config </td></tr>
+<tr><td> def (config) (start) (stop)          </td><td> set the start & stop times for the given config </td></tr>
+<tr><td> set (config) (state)                 </td><td> manually set the config state </td></tr>
+<tr><td> list.init                            </td><td> run just the list.init stage </td></tr>
+<tr><td> list.reinit                          </td><td> run just the list.reinit stage </td></tr>
+<tr><td> detrend                              </td><td> run just the detrend stage </td></tr>
+<tr><td> merge                                </td><td> run just the merge stage </td></tr>
+<tr><td> mkrough                              </td><td> run just the mkrough stage </td></tr>
+<tr><td> defringe                             </td><td> run just the defringe stage </td></tr>
+<tr><td> mksmooth                             </td><td> run just the mksmooth stage </td></tr>
+<tr><td> regimage                             </td><td> run just the regimage stage </td></tr>
+</table>
+
+<h2> HTML cgibin commands </h2>
+<table>
+<tr><td> htmldup </td><td>  </td></tr>
+<tr><td> htmldef </td><td>  </td></tr>
+<tr><td> htmldel </td><td>  </td></tr>
+<tr><td> htmlmod </td><td>  </td></tr>
+<tr><td> htmlkeep </td><td>  </td></tr>
+<tr><td> htmlconfig </td><td>  </td></tr>
+<tr><td> html1 </td><td>  </td></tr>
+<tr><td> html2 </td><td>  </td></tr>
+<tr><td> html3 </td><td>  </td></tr>
+<tr><td> htmlmodes </td><td>  </td></tr>
+<tr><td> htmlmaps </td><td>  </td></tr>
+<tr><td> htmlmapkeep </td><td>  </td></tr>
+</table>
+
+<h2> other support commands </h2>
+<table>
+<tr><td> dads </td><td>  </td></tr>
+<tr><td> dads.top </td><td>  </td></tr>
+<tr><td> eval </td><td>  </td></tr>
+</table>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/nightd.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/nightd.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/nightd.htm	(revision 16632)
@@ -0,0 +1,94 @@
+<meta name=file  content=nightd>
+<meta name=title content=nightd user's guide>
+<meta name=page  content=nightd>
+
+<p>
+The nightd daemon is a easily-customized daemon which performs a
+defined set of tasks on a nightly basis.  The program behavior is
+defined by the resource file, loaded at the start of execution.  The
+program can have any name, and loads the resource file with the name
+~/.programrc; ie, the implementation used by elixir to control the
+night elixir real-time systems is called 'ert' and it loads the file
+~/.ertrc.  
+
+<pre>
+HOME      /h/skyprobe
+
+DATA_PATH $HOME/data
+PID_FILE  $HOME/.skyprobe.pid
+LOG_FILE  $HOME/sp_daemon.log
+
+CCD_TEMP -20
+EXPTIME   30
+
+INIT_COMMAND sp_command cool $CCD_TEMP
+INIT_COMMAND sp_command init $DATA_PATH/&DATE
+MAIN_COMMAND sp_command expose $EXPTIME $DATA_PATH/&DATE/sp_&DATE_&TIME.fits
+DONE_COMMAND sp_command warm
+
+NIGHT_START 18:00
+NIGHT_STOP  06:00
+
+PERIOD 60
+TIMEOUT 300
+</pre>
+
+<p>
+Above is shown a typical nightd configuration script.  The nightd
+configuration defines commands and execution time scales.  The start
+and end times of the night are defined by the entries NIGHT_START and
+NIGHT_STOP.  The nightd configuration script defines three classes of
+commands: INIT, MAIN, DONE.  The INIT commands are executed in the
+order listed in the configuration script at the start of the night,
+while the DONE commands are executed at the end of the night.  The
+MAIN commands are executed on a regular basis from START to STOP using
+the interval defined by PERIOD (seconds).  The program monitors these
+processes and checks for completion within the TIMEOUT period;
+otherwise, the command is sent the kill signal.  
+
+<p>
+The entries PID_FILE and LOG_FILE are required entries. The PID_FILE
+stores the process id, user and machine for the given nightd
+implementation, and prevents multiple intances of the same process.
+The LOG_FILE is used for all error messages.  The other entries in the
+configuration script define variables to be use elsewhere in the
+script.  There are a few special variables: \&DATE, \&TIME, ???, which
+are expanded by nightd before the execution.
+
+<p>
+The nightd program takes several possible arguments on the command
+line:
+
+<pre>
+nightd start
+nightd stop
+nightd status
+nightd config
+</pre>
+
+<p>
+The 'start' command starts up the nightd program.  Currently, nightd
+does not fork itself into the background, so it is necessary to place
+it in the background manually (nightd start &).  It is not necessary
+to redirect the output; nightd will send all data to LOG_FILE if it
+can be opened and written to.  On start, nightd will check for the
+existence of the PID_FILE and give an error to stdout (not LOG_FILE)
+if it exists; only one implementation may run at a time.  Currently,
+nightd does not check for the existence of the process identified in
+the PID_FILE.  It is necessary for the user to confirm that such a
+process exists on the named machine.
+
+<p>
+The 'stop' command halts execution of the given nightd program.  It
+uses the information in the PID_FILE to remotely log onto the machine
+where the process is being executed and send the STOP signal.  Nightd
+will give an error if there is no PID_FILE, implying no currently
+running nightd.  It is necessary to have rsh access between machines
+for this to work.
+
+<p>
+The status command shows the pid information for the currently running
+nightd, or says that it is not running.
+
+<p>
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/postrun.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/postrun.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/postrun.htm	(revision 16632)
@@ -0,0 +1,58 @@
+<meta name=file  content=postrun>
+<meta name=title content=Elixir Postrun Systems>
+<meta name=page  content=Elixir Postrun Systems>
+
+The Elixir postrun system (<tt>elixir.postrun</tt>) manages the
+end-of-run processing of the calibration and science data.  The
+command <tt>elixir.postrun</tt> manages the stages of the processing.
+The elixir.postrun commands are as follows: <br><br>
+
+<tt>
+<table>
+<tr><td>elixir.postrun state               </td><td> check the current postrun status </td></tr>
+<tr><td>elixir.postrun update              </td><td> update the status, start the next stage </td></tr>
+<tr><td>elixir.postrun set (entry) (value) </td><td> set the state for a specific entry </td></tr>
+<tr><td>elixir.postrun (entry)             </td><td> run a specific entry </td></tr>
+</table>
+</tt>
+
+<p>
+The Elixir postrun system consists of a series of processing stages,
+illustrated by the command <tt> elixir.postrun state </tt>: <br><br>
+
+<tt>
+<table>
+<tr><td> imstats   </td><td> process the unprocessed entries in the imstats database </td></tr>
+<tr><td> mkdetrend </td><td> run the mkdetrend system to generate the detrend data </td></tr>
+<tr><td> mkfringe  </td><td> run the mkfringe system to generate the fringe data </td></tr>
+<tr><td> ptolemy   </td><td> run the science images through the ptolemy system </td></tr>
+<tr><td> standards </td><td> process the standard stars and generate zero-point information </td></tr>
+<tr><td> validate  </td><td> perform the image validation stages </td></tr>
+</table>
+</tt>
+
+<p>
+These stages must be performed in sequence, and the postrun system
+automatically enforces the sequencing.  At the beginning of a run,
+each of these stages are in the state 'init'.  At any stage, the
+command <tt>elixir.postrun update</tt> will attempt to identify the
+state of each of the processing stages, and run the first which is
+ready in the init state.  While stages are running, elixir.postrun
+will set their state to 'running', and as the stages finish, they are
+set to the value 'done'.  
+
+<p> In fact, the description above is an ideal, but in practice, the
+elixir.postrun script does not quite follow these rules.  For example,
+elixir.postrun will not run the mkdetrend or mkfringe systems; these
+must be run manually with the mkdetrend and mkfringe commands.  In
+addition, the mkfringe and ptolemy systems are required to be run in
+sequence by elixir.postrun, but these do not really require this
+sequencing: ptolemy can be run independently of mkfringe since ptolemy
+does not require the fringe frames.  
+
+<p> Furthermore, the error checking in the elixir.postrun system is
+not very well refined, and manual intervention is occasionally needed.
+It is possible, therefore, to set the state to appropriate values as
+needed with the elixir.postrun set (entry) (value) command.  Also, the
+elixir.postrun (entry) command can be used to run the specific stage
+manually.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/sequence.idx
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/sequence.idx	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-System/sequence.idx	(revision 16632)
@@ -0,0 +1,6 @@
+elixir
+mkdetrend
+mkfringe
+nightd
+postrun
+gconfig
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/applyscat.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/applyscat.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/applyscat.htm	(revision 16632)
@@ -0,0 +1,3 @@
+applyscat takes a raw master flat-field image and a scatter correction
+frame and constructs a corrected flat-field image. 
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fhead.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fhead.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fhead.htm	(revision 16632)
@@ -0,0 +1,12 @@
+<pre>
+  fhead (fitsfile) ... [-x N]
+
+  print out the FITS header, adding return chars to the end of each
+  line, stopping at the END (not printed).  By default, the primary
+  header unit is printed.  If the -x is provided the Nth extension's
+  header unit is printed, with 0 being the first extension after the
+  PHU.  Multiple files may be provided, in which case the headers are
+  printed in sequence, with tags between the headers.
+
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fields.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fields.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fields.htm	(revision 16632)
@@ -0,0 +1,10 @@
+<pre>
+  fields (key) ... [-x N]
+
+  Read from stdin a list of file names.  For each file name, print in
+  sequence the value of the given FITS header keywords.  Any number of
+  keys may be present.  By default, the key/values are taken from
+  primary header unit.  If the -x is provided the Nth extension's
+  header unit is used instead, with 0 being the first extension after
+  the PHU.
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fits_insert.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fits_insert.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/fits_insert.htm	(revision 16632)
@@ -0,0 +1,17 @@
+<pre>
+  fields (file) (header) [-X N] [-comment N line]
+
+  Add header entries to the given file.  The header information to be
+  inserted is read from the provided header file, which contains
+  abbreviated FITS header lines:  each line must consist of a keyword
+  and data value, following the FITS conventions, but lines are broken
+  with returns, and there are no required keys or minimum number of
+  lines.  By default, the primary header unit is used, but if the -X
+  flag is used, the Nth extension is used instead, where 0 corresponds
+  to the first extension after the PHU.  If the -comment option is
+  provided, the Nth comment is replaced with the provided line.  By
+  default, this function will search for blank lines and overwrite the
+  data in-situ.  However, if it is necessary to extend the header, a
+  new file will be written.
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/ftable.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/ftable.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/ftable.htm	(revision 16632)
@@ -0,0 +1,24 @@
+<pre>
+  ftable (filename) [options]
+
+  options:
+  -x N:       operate on extension N (0 is default)
+  -n EXTNAME: operate on named extension (incompatible with -x)
+  -row N:     print row number N
+  -column n:  print column named n
+  -ncolumn N: print column number N
+  -list:      print extension names
+  -layout     print the table layout (fields)
+
+  Print out FITS table data, or FITS table header data.  By default,
+  the entire FITS table is printed.  Command-line options may be used
+  to restrict the output to a single column or single row.  Additional
+  options may be used to list all extension names or to print out the
+  complete table fields for the selected extension.  By default, the
+  key/values are taken from the first extension.  If the -x is
+  provided the Nth extension's header unit is used instead, with 0
+  being the first extension after the PHU.  If the -n option is
+  provided, the named extension (matching keyword EXTNAME) is used.  
+
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gastro.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gastro.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gastro.htm	(revision 16632)
@@ -0,0 +1,69 @@
+<meta name=file  content=gastro>
+<meta name=title content=gastro>
+<meta name=page  content=gastro>
+
+<p>
+The gastro program determines the astrometric transformation for an
+image based on the cmp/smp file.  This file contains both the table of
+object data and the complete image FITS header.  Using the header
+astrometric information as a starting point, gastro loads the
+reference astrometry objects appropriate for the region and determines
+the matching objects between the image and the reference.  These
+objects are used, with iteration to improve the sample, to determine
+the astrometric transformation with up to 3rd order polynomials.  
+
+<pre>
+gastro filtname.cmp
+options:
+  -h
+  -help
+  -v
+  -p (photcode)
+  -plot
+  -maglims
+  -nstars
+  -fx
+  -fy
+  -coords (ra) (dec)
+  -dump
+  -mdmp
+  -cdmp
+  -loneos
+
+gastro configuration variables:
+OFFSET_RADIUS     - max allowed offset in gcenter
+MIN_MATCHES       - min number of matched stars for linear fit
+MINIMUM_RADIUS    - target matching radius in gfit iterations
+MAX_ERROR         - maximum allowed error in solution
+MAX_NONLINEAR     - maximum angle between axes
+MAX_PRECISE       - unused?
+DEFAULT_RADIUS    - unused?
+
+ROUGH_ASTROMETRY  - source of initial astrometry terms
+
+CCD_PC1_1         - initial guess pc1_1
+CCD_PC2_2         - initial guess pc2_2
+CCD_PC1_2         - initial guess pc1_2
+CCD_PC2_1         - initial guess pc2_1
+ASEC_PIX          - initial guess arcsec / pix
+
+POLAR_ALIGNMENT   - provide polar alignment of telescope mount?
+POLAR_AXIS_RA     - RA of telescope polar axis
+POLAR_AXIS_DEC    - DEC of telescope polar axis
+RA_OFFSET         - RA offset
+DEC_OFFSET        - DEC offset (degenerate?)
+
+NFIELD            - select stars from region NFIELD x detector size
+NPOLYTERMS	  - number of orders to allow
+MMIN              - minimum magnitude of allowed star 
+ROT_ZERO          - zero of tested rotation range
+dROT              - rotation step size
+NROT              - number of rotation tests = 2NROT + 1
+GSCFILE           - name of HST GSC table file
+GSCDIR            - name of HST GSC data directory
+LONEOS_REGIONS    - table of location coordinates
+USNO_CDROM        - name of USNO data directory
+ASTRO_REFCAT      - reference catalog format to read
+CATDIR            - name of ptolemy database
+PHOTCODE_FILE     - table of photcodes 
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gastro2.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gastro2.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gastro2.htm	(revision 16632)
@@ -0,0 +1,68 @@
+<meta name=file  content=gastro2>
+<meta name=title content=gastro2>
+<meta name=page  content=gastro2>
+
+<p>
+gastro2 is the successor to gastro.  The gastro2 program determines
+the astrometric transformation for an image based on the cmp/smp file.
+This file contains both the table of object data and the complete
+image FITS header.  Using the header astrometric information as a
+starting point, gastro2 loads the reference astrometry objects
+appropriate for the region and determines the matching objects between
+the image and the reference.  These objects are used, with iteration
+to improve the sample, to determine the astrometric transformation
+with up to 3rd order polynomials.
+
+<pre>
+gastro filtname.cmp
+options:
+  -h
+  -help
+  -v
+  -p (photcode)
+  -plot
+  -maglims
+  -nstars
+  -fx
+  -fy
+  -coords (ra) (dec)
+  -dump
+  -mdmp
+  -cdmp
+  -loneos
+
+gastro2 configuration variables:
+OFFSET_RADIUS     - unused
+MIN_MATCHES	  - unused
+DEFAULT_RADIUS	  - unused
+MINIMUM_RADIUS	  -
+MAX_ERROR	  -
+MAX_NONLINEAR	  -
+MAX_PRECISE	  -
+CCD_PC1_1	  -
+CCD_PC2_2	  -
+CCD_PC1_2	  -
+CCD_PC2_1	  -
+ASEC_PIX	  -
+NFIELD		  -
+NPOLYTERMS	  -
+ROT_ZERO	  -
+dROT		  -
+NROT		  -
+POLAR_ALIGNMENT	  -
+GSCFILE		  -
+GSCDIR		  -
+2MASS_DIR         -
+POLAR_AXIS_RA     -
+POLAR_AXIS_DEC    -
+RA_OFFSET         -
+DEC_OFFSET        -
+LONEOS_REGIONS    - 
+USNO_CDROM        -
+ASTRO_REFCAT      - 
+CATDIR            - 
+ROUGH_ASTROMETRY  - 
+PHOTCODE_FILE     -
+GASTRO_MAX_NSTARS -
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gcompare.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gcompare.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/gcompare.htm	(revision 16632)
@@ -0,0 +1,21 @@
+<meta name=file  content=gcompare>
+<meta name=title content=gcompare>
+<meta name=page  content=gcompare>
+
+<p>
+The gcompare program determines compares two lists of objects with X,Y
+coordinates and prints the matched entries.  A radius of matched is
+given, and all pairs of objects between the two lists which lie within
+the given radius are printed.  The delta coordinates may also be
+optionally printer, or the unmatched objects in either the first or
+second list.  An offset for the center can be optionally applied.
+
+<pre>
+gcompare file1 Nx Ny file2 Nx Ny radius [options]
+options:
+ -d
+ -m
+ -n1
+ -n2
+ -c x y
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/glockfile.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/glockfile.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/glockfile.htm	(revision 16632)
@@ -0,0 +1,22 @@
+<pre>
+  glockfile (filename) (type) (duration)
+
+  lock the given file, using the Elixir locking functions, for the
+  specified number of seconds.  The lock type may be SOFT, XCLD, or
+  HARD.  These have the following meanings:
+
+  SOFT : read-only lock; will not block a SOFT lock.  will only last
+         for the duration of the program.
+
+  XCLD : write lock; blocks, and is blocked by, all lock types.  will
+         only last for the duration of the program.
+
+  HARD : write lock; blocks, and is blocked by, all lock types.  If
+  the program is interrupted, the lock will remain until cleared by
+  hand (by deleting the file with the name .filename.lck, where
+  'filename' is replaced the the name of the locked file.
+
+
+  
+  
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/imclean.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/imclean.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/imclean.htm	(revision 16632)
@@ -0,0 +1,24 @@
+<meta name=file  content=imclean>
+<meta name=title content=imclean>
+<meta name=page  content=imclean>
+
+<p>
+The imclean program converts the basic photometry output list from
+dophot, sextractor, or gophot, into a standard format for other Elixir
+subsystems, with both the table of object data and the complete image
+FITS header. 
+
+<pre>
+imclean filename.fits filename.obj filtname.cmp
+imclean -sex filename.fits filename.sx filename.smp
+options:
+  -h
+  -help
+  -v
+  -coords (ra) (dec)
+  -p (photcode)
+  -astrom (file)
+  -sex
+  -chad
+  -key KEYWORD VALUE
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/index.htm	(revision 16632)
@@ -0,0 +1,9 @@
+<meta name=file  content=Foobar>
+<meta name=title content=Elixir Tools>
+<meta name=page  content=Elixir Tools>
+
+This section describes basic Elixir tools provided by Ohana.  These
+include a set of FITS file interaction programs (fields, fhead,
+ftable, fits_insert), a few data analysis tools (gastro, gastro2,
+mosastro, imclean), and a variety of other useful for astronomy and
+data-handling programs.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/list_astro.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/list_astro.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/list_astro.htm	(revision 16632)
@@ -0,0 +1,20 @@
+<pre>
+  list_astro
+
+  read a series of lines consisting of 4 columns.  the columns
+  represent the X,Y coordinate of a series of objects in first one
+  coordinate frame, then in a second coordinate frame.  list_astro
+  will return the linear transformation (and errors) from the first
+  frame to the second frame in the form:
+
+  X0 X1 X2 dX
+  Y0 Y1 Y2 dY
+
+  where
+
+  X = X0 + X1*x + X2*y
+  Y = Y0 + Y1*x + Y2*y
+
+  and dX and dY are the errors in the output coordinate frame.
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/medianfilter.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/medianfilter.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/medianfilter.htm	(revision 16632)
@@ -0,0 +1,13 @@
+<pre>
+  medianfilter output (fmin) (fmax) 
+
+  Read a series of image names from standard input.  The input images
+  must all be the same dimensions, and are expected to correspond to
+  matching pixels.  For each pixel, the data values are sorted.  The
+  data values within the range (fmin) to (fmax) are selected, where
+  (fmin) and (fmax) are fractions between 0 and 1, and represent the
+  fraction of the sorted stack of pixels.  The mean of the selected
+  data within this range is then calculated.  The output file consists
+  of pixels with these output values.  
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/mktemp.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/mktemp.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/mktemp.htm	(revision 16632)
@@ -0,0 +1,12 @@
+<pre>
+  mktemp [template]
+
+  provides the mktemp function for systems which do not provide such a
+  UNIX command tool.  mktemp constructs the name of a unique file and
+  returns it on stdout.  By default, the filename will be
+  /tmp/tmp.XXXXXX where XXXXXX is substituted with a string of
+  characters to enforce uniqueness.  If the template filename is
+  provided, consisting of a valid filename ending in .XXXXXX, then
+  this template is used to construct the temporary file.  
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/mosastro.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/mosastro.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/mosastro.htm	(revision 16632)
@@ -0,0 +1,180 @@
+<meta name=file  content=gastro>
+<meta name=title content=gastro>
+<meta name=page  content=gastro>
+
+<p>
+mosastro takes a collection of data from mosaic CCD images, all
+individually astrometrized, and determines a single global astrometric
+solution for the complete system.  In this process, it determines a
+distortion model for the telescope arising from the optical system, as
+well as mapping solutions relating the coordinate systems of the
+individual chip pixels to the focal plane.  Both of these
+transformations may involve up to 3rd order polynomials.  
+
+<p>
+The suggested operation is to use gastro (or gastro2) to determine
+linear astrometric solutions for the individual chips before running
+mosastro.  Mosastro requires the individual chip astrometry have an
+accuracy of roughly 1 arcsec or better in order to select the match
+between the observed stars and the astrometric reference catalog.   
+This two stage approach allows a more robust linear solution for the
+individual chips, which may have too few reference star matches to
+define reliable high-order solution.  The mosaic analysis determines a
+single distortion model representing the physical contribution of the
+telescope optics.
+
+Mosastro is run assuming the user has a collection of Elixir-style
+astrometry / photometry files in one of the CMP/SMP/SMF set of
+formats.  Mosastro will auto-detect the data format and load the
+stellar astrometric and photometric measurements.  The collection of
+data is assumed to consist of one file per chip, with names which are
+sufficiently consistent that they can be identified with a single
+filename including wild-cards.
+
+<p>
+The user command looks like:
+<pre>
+mosastro (glob) (ext) (phu)
+</pre>
+
+The first argument is an expression containing wild-cards which
+expands into the collection of files containing the astrometric data.
+The mosastro program must receive the wild-card expression
+<em>without</em> expansion by the shell.  The user call needs to
+protect the wild-card against expansion, which can usually be done by
+placing the expression within double-quote marks.  The second argument
+is the new output extension.  The stellar photometry will be written
+out to files using the same names as the input, replacing the final
+filename extension with the provided extension.  The standard input
+extensions are one of the following: 'cmp', 'smp' (used for dophot or
+sextractor output files in raw text format), 'cmf, 'smf' (used for
+dophot or sextractor output files in fits table format).  The
+recommended output extensions replace the 'c' or 's' with 'x': 'xmp'
+for raw text format, or 'xmf' for FITS table format.  The final
+argument is the name of the output 'primary header unit' file.  The
+standard usage here is to use the filename root (without chip
+identifiers) with the extension 'phu'.  The output telescope boresite
+and optical distortion terms are written to this primary header entry,
+which is constructed from the first of the chip files (true?).  
+
+<em> future expansions: allow input list of files from a file, allow
+input MEF collection of chip astrom/photom </em>
+
+<p>
+In the following discussion, we refer to conversions between
+several coordinate frames.  We use the term 'project' to describe the
+projection of the celestial coordinates to the linear (focal plane or
+chip) coordinates; we use the term 'deproject' to describe the
+conversion from the linear chip or focal-plane coordinates to the
+spherical celestial coordinates.
+
+<p>
+mosastro performs the following steps in the analysis.  
+<ul>
+<li> Load the raw stellar astrometry data from the chip files
+<li> Deproject the stars using the approximate chip astrometry
+<li> Determine the RA and DEC range of the observed star measurements
+<li> Define the initial guess telescope boresite / distortion model
+<li> Project the observed star coordinates to the focal plane
+<li> Load the astrometric reference catalog.
+<li> Project the reference catalog to the focal plane
+<li> Match obs and ref on the focal plane
+<li> Measure the local gradient of the matched star coordinate in the
+tangent plane as a function of focal plane coordinate.  
+<li> Fit the local gradient values as a function of focal plane coordinates
+<li> Use the measured gradient model to modify the distortion model
+<li> Fit low-order solution for the chip model
+<li> Clip outlier matches
+<li> Fit high-order solution for the chip model
+<li> Perform several clip / fit iterations
+<li> Write out the new solutions / data to the output file
+</ul>
+
+<h3> options </h3>
+
+The following command-line options are available to the user:
+
+<ul>
+<li> -help or -h : print summary help information
+<li> -v : turn on verbosity
+
+<li> -dump (selection) : write out matched stars data at some
+processing stage.  The selection specifies where in the analysis to
+write out the result.  The following options are available:
+<ul>
+<li> rawstars : write out the raw input observed star positions, after
+the initial projection
+<li> refcat   : write out the reference catalog data (after initial
+projection). 
+
+<li> rawmatch : write out the obs and ref stars after the first match,
+before any fit is performed
+ 
+<li> fitgrads : write out the obs and ref stars after correction for
+the local gradient
+ 
+<li> fitchips_unclip : write out the obs and ref stars after fitting
+the initial chip term
+
+<li> fitchips : write out the obs and ref stars after the clipping
+iterations. 
+</ul>
+
+<li> -save-residuals : save table of obs and ref star matches, with
+coordinates in the multiple frames, as an extension to the PHU file.
+
+<li> -chips : load the initial chip focal-plane mapping (not yet implemented)
+
+<li> -field : load the inital field rotation, boresite, plate-scale
+from reference file
+
+<li> -order : define the polynomial order of the telescope distortion
+model (default is 0).
+
+-chiporder : define the polynomial order of the chip mapping model
+(default is 1).
+</ul>
+
+<h3> Elixir Configuration Data </h3>
+
+Mosastro uses the following Elixir configuration variables:
+
+<ul>
+<li> EXPTIME-KEYWORD  : header keyword defining exposure time
+<li> DATE-KEYWORD  : header keyword defining the date 
+<li> DATE-MODE  : mode for header date information: use a combination
+of Ys, Ms, Ds to specify order.  If only 2 digits are specified for
+the year, numbers greater than 50 are assumed in the 1900s, less than
+in the 2000s.  eg YYYY/MM/DD
+<li> UT-KEYWORD  : header keyword defining UT
+<li> MJD-KEYWORD  : header keyword defining MJD
+<li> JD-KEYWORD  : header keyword defining JD
+
+note that only one of the combination JD, MJD, or DATE/UT needs to be
+defined. 
+
+<li> ASTRO_REFCAT  : desired astrometric reference catalog.  allowed
+values are <tt>GSC, USNO, 2MASS, PTOLEMY, STONE</tt>.  
+
+<li> GSCDIR      : location of the HST Guide Star Catalog
+<li> USNO_CDROM  : location of the USNO-A data
+<li> STONE_DIR   : location of the Stone et al reference data
+<li> 2MASS_DIR   : location of the 2MASS data 
+<li> CATDIR      : location of the ptolemy data
+<li> GSCFILE     : location of the GSC layout file (for GSC and ptolemy)
+
+note that 'ptolemy' refers to data using the DVO format.  2MASS data
+must be in a DVO format database.  USNO and GSC are both loaded from
+their idiosyncratic formats.  
+
+<li> RADIUS  : matching radius in arcsec to select reference stars
+<li> SIGMA_LIM  : exclude stars with formal error larger than this
+
+<li> ZERO_PT  : default zero point, nominally 25.0.  don't set this to
+a 'real' zero point.  it is used only for reference.
+
+<li> INST_MAG_MIN  : exclude stars brighter than this instrumental magnitude
+<li> INST_MAG_MAX  : exclude stars fainter than this instrumental magnitude
+<li> INST_BRIGHT  : use stars brighter than this value to measure
+systematic error limit.
+</ul>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/precess.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/precess.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/precess.htm	(revision 16632)
@@ -0,0 +1,10 @@
+<pre>
+  precess (in) (out)
+
+  read a series of RA,DEC coordinate pairs (in decimal degrees) and
+  precess them from the (in) equinox to the (out) equinox.  Equinoxes
+  are decimal years in the J2000 system, or in the B1950 system if
+  prepended by 'B'.  B and J may be used to substitude for B1950 and
+  J2000 respectively.
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/radec.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/radec.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Elixir-Tools/radec.htm	(revision 16632)
@@ -0,0 +1,11 @@
+<pre>
+  radec [-hh | -hms]
+
+  read a series of coordinate pairs and convert between decimal and
+  sexigesimal representations.  If the option -hh is given, the input
+  is expected to be decimal degrees and the output will be sexigesimal
+  (hours minutes seconds).  If the option -hms is given, the input is
+  expected to be sexigesimal and the output will be decimal degree.
+  Whitespace must be used for all separators.
+
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/index.htm	(revision 16632)
@@ -0,0 +1,17 @@
+<meta name=title content=IPP Subsystems>
+<meta name=page  content=IPP Architectural Subsystems>
+
+The Pan-STARRS IPP is using several programs from the Ohana collection
+for portions of the IPP Infrastructure.  These subsystems include:
+
+<ul> 
+<li> psched: the IPP scheduler program
+<li> pcontrol : the IPP parallel process controller
+<li> pclient : the pcontrol remote client
+</ul>
+
+In addition to these program, the IPP will use DVO for object
+photometry manipulation.  IPP requires the upgraded capability which
+will be provided by DVO after Fall 2005, including enhanced
+throughput. DVO is discussed in its own section.
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pclient/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pclient/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pclient/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pclient/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pclient/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pclient/index.htm	(revision 16632)
@@ -0,0 +1,50 @@
+<meta name=file  content=index>
+<meta name=title content=PCLIENT SUMMARY>
+<meta name=page  content=pclient summary>
+
+<tt>pclient</tt> is the remote process monitor for pcontrol, the parallel
+process controller.
+
+<h3>Overview</h3>
+
+<p>
+The program <tt>pclient</tt> is used to support the remote jobs which are
+run on the remote hosts by <tt>pcontrol</tt>.  The concept of pclient is to
+act as a buffer between the job running on the remote host and
+pcontrol.  The pcontrol design uses (by default) ssh connections
+initiated by pcontrol to the remote hosts.  These connections execute
+the remote program of pclient.  The use of a remote login process lets
+the UNIX system take care of the user authentication issues.  In this
+case, the recommended practice is to set up ssh to allow the
+connection to the remote host without additional authentication using
+the appropriate authorized keys (see <a href=ssh-issues>this
+article<a> on ssh issues).  
+
+<p>
+It is convenient to keep a continuous connection to the remote hosts.
+This avoids incurring the overhead of authentication for each command
+which is executed, while keeping a high-quality user authentication
+process in place.  
+
+<p>
+pclient acts as a buffer between pcontrol and the remote background
+process, allowing the continuous connection to remain viable without
+samping pcontrol with output from the jobs.  
+
+<h3>Command Summary</h3>
+
+<p>
+pclient has a very limited command set, as follows:
+
+<pre>
+job           : start the job (UNIX command) in the background.
+check         : return the current job status
+status        : return the current job status (?)
+stdout        : dump the stdout stream accumulated from the job
+                back to the calling program.
+stderr        : dump the stderr stream accumulated from the job
+                back to the calling program.
+reset         : kill (if needed) the job and reset to accept
+                another job.
+</pre>
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/index.htm	(revision 16632)
@@ -0,0 +1,261 @@
+<meta name=file  content=index>
+<meta name=title content=PCONTROL.SUMMARY>
+<meta name=page  content=pcontrol.summary>
+
+<tt>pcontrol</tt> is the IPP parallel process controller.
+
+<h3>Overview</h3>
+
+<p>
+The IPP uses a group of computers to store and process images and to
+manipulate collections of detections.  These computers perform any of
+a large number of analysis stages or other processing tasks without
+significant interprocess communication.  It is necessary to have a
+mechanism which initiates computing tasks on the different computers,
+which monitors the tasks as they are executed, which handles the
+output and the errors from these tasks, and which reacts to the
+failure of any of the computing nodes.  The system responsible for the
+tasks in the IPP is <tt>pcontrol</tt>.
+
+<h3>Host States</h3>
+
+<p>
+<tt>pcontrol</tt> maintains a table of available processing computers
+(<em>hosts</em>) and tracks their status.  Hosts managed by
+<tt>pcontrol</tt> are allowed to be in one of several states:
+<tt>off</tt>, <tt>down</tt>, <tt>idle</tt>, <tt>busy</tt>, and
+<tt>done</tt>.  These states have the following meanings:
+
+<p>
+If the host is <tt>off</tt>, it is known to pcontrol, but pcontrol
+does not have an active connection to the machine.  Hosts which are
+<tt>off</tt> are not available for jobs, and pcontrol does not attempt
+to initiate a connection to them.
+
+<p>
+When pcontrol is told to consider a machine on, the machine is moved
+from the <tt>off</tt> state to the <tt>down</tt> state.  Pcontrol
+attempts to initiate a connection to the host.  Connections are made
+by running a remote client on the host, using the specified connection
+method.  The connection method may be <tt>ssh</tt>, <tt>rsh</tt>, or
+an equivalent remote shell connection. The choice is specified by the
+COMMAND Opihi variable.  The remote connection starts a dedicated
+remote client which must accept the pcontrol client commands and
+respond appropriately.  The provided remote client is called
+<tt>pclient</tt>, though in principal other equivalent programs could
+be used by setting the Opihi variable SHELL (this feature more
+generally allows a user to specify a path to the remote client, if it
+is not in the user's path).  A pcontrol user may force a host to
+transition to the <tt>off</tt> state with the command <tt>host off
+(hostname)</tt>.  (<em> Note that this command will set only one of
+the connections to the named host to <tt>off</tt>.  If multiple
+connections to a machine have been defined, multiple <tt>off</tt>
+commands must be sent</em>).
+
+<p>
+If the remote connection is successful, the connected host is moved by
+pcontrol from the <tt>down</tt> state to the <tt>idle</tt> state.  If
+the connection is unsuccessful, pcontrol will try again after a
+certain period of time.  If the connection continues to be
+unsuccessful, the retry period is doubled for each successiver
+connection attempt.  If the user wants to force pcontrol to retry the
+connection to a machine (if, for example, the timeout is now very
+long, but the user knows the machine's ethernet cable has been
+re-inserted...), this can be achieved with the command <tt>host retry
+(hostname)</tt>.  A host which is <tt>down</tt> is in the limbo state
+between <tt>off</tt> and <tt>idle</tt>.  
+
+<p>
+Once pcontrol has made a successful connection to the host, the host
+is in the <tt>idle</tt> state.  At this point, it is ready to accept
+jobs from pcontrol for execution.  Pcontrol repeatedly queries the
+hosts to check that they are still alive.  If a host is discovered to
+be unresponsive, and particularly if the remote pipe connection has
+closed, then the machine is moved back to the <tt>down</tt> state.  
+
+<p>
+Hosts which are <tt>idle</tt> may accept a job from pcontrol.  A job simply
+consists of a bare UNIX command, without redirection of standard input
+or standard output.  The host will initiate the job, and pcontrol will
+place the host into the <tt>busy</tt> state.  The remote client, pclient,
+runs the job in the background and will continue to accept input from
+pcontrol.  pcontrol will continue to check the status of the host, and
+now also the status of the specific job.  As before, if the connection
+breaks, pcontrol will migrate the host to the <tt>down</tt> state.  Any job
+already initiated on a host which goes down will be returned for later
+processing, so the job will not be lost. 
+
+<p>
+When the job exits, pclient tells pcontrol that the job is completed,
+and specifies the exit status.  At this point, pcontrol will move the
+host from <tt>busy</tt> to <tt>done</tt> state.  It will stay in this
+state until pcontrol can determine the ending conditions and reset the
+remote client.  pcontrol requests the standard error and standard
+output from the job from pclient.  pcontrol stores this data with its
+information about the completed job, and send a reset command to the
+remote client.  Once these cleanup tasks are successfully completed,
+pcontrol will move the host to the <tt>idle</tt> state, ready for
+further jobs.
+
+<p>
+Each physical computer may have multiple processors.
+<tt>pcontrol</tt> treats each processor independently.  It is up to
+the system configuration if each computer needs to reserve one of its
+CPUs to manage background tasks or if <tt>pcontrol</tt> should attempt
+to send one task per CPU and let the operating system handle the I/O
+load.  <em>some of this behavior will probably be eventually more
+intelligent.  For example, the commands which turn a host on or off
+should be able to do the same operation to all host connections for
+the same machine name.</em>
+
+<p>
+A machine may be completely removed from pcontrol's host tables with
+the command <tt>host delete (hostname)</tt>.  
+
+<h3>Jobs</h3>
+
+<p>
+The <tt>pcontrol</tt> accepts new jobs with the command <tt>job
+...</tt>, in which the ellipsis represents the command and arguments
+of a valid UNIX command.  The commands are run under <tt>sh</tt>, and
+are executed in the user's home directory.  (<em>If it is desired, we
+can easily add a command to tell pclient to perform <tt>cd</tt></em>).
+Users should be wary of the conditions under which the remote jobs are
+run.  If the nodes in question all cross-mount the same home
+directories, multiple jobs which interact with the same named file may
+produce unexpected results.  The controller cannot enforce good
+behavior on the part of the remote jobs; it is the responsibility of
+the user to ensure that conflicts do not arise by, eg, always using
+unique output file names.
+
+<p>
+Other issues may arise from the fact that pcontrol may be choosing any
+of the hosts to run the job.  Typical failures arise if the user does
+not realize that specific jobs do not behave the same on all machines,
+or if a necessary resource (eg, some input data file) is only
+available or accessible from some of the hosts.  It is the
+responsibility of the task to wait for network lags (ie, NFS delays).
+
+<p>
+<tt>pcontrol</tt> gives each task a unique internal identifier (Job
+ID) equivalent to the process ID used in UNIX.  When a job is
+submitted to pcontrol, the command echoes back the Job ID.  This ID
+may be used by other pcontrol commands to obtain information about or
+interact with the job.
+
+<p>
+A job may specify a specific host for the task execution.  The host
+specified for a job may be <b>required</b>, or <b>desired</b>.  In the
+first case, pcontrol, will only run the job on the specified host,
+waiting until it is available before attempting the job.  In the
+second case, pcontrol will attempt to send the job to the specified
+host, but if the host is unavailable (<em>how long? what
+conditions?</em>), pcontrol will allow the job to be sent to an
+alternative host.  <tt>pcontrol</tt> attempts to honor the requests
+for required and desired hosts, giving priority first to required-host
+jobs, then to the desired-host jobs, and finally to all other jobs.
+To specify a host for a job, the following commands are used:
+
+<pre>
+job -host (command and arguments...)
+job +host (command and arguments...)
+</pre>
+
+The first case specifies a desired host, while the second specifies a
+required host.  It is also possible to specify the special host name
+<tt>anyhost</tt>, which is equivalent to not specifying a host at all.
+
+<p>
+<em>Job priority / urgency levels are not implemented at this time.</em>
+
+<p>
+<em>I/O vs CPU tasks are not currently distinguished by pcontrol</em>
+
+<p>
+<tt>pcontrol</tt> stores the stdout and stderr for each completed job.
+To retrieve these data from these streams, the user issues the
+commands <tt>stdout (JobID)</tt> and <tt>stderr (JobID)</tt>.  The
+result is a single line specifying the number of bytes to expect,
+followed by a dump of the buffers, followed by the prompt. It is the
+user's responsibility to relieve pcontrol of this data load by
+deleting jobs once they are no longer needed.  Job deletion is
+performed with the command <tt>delete (JobID)</tt>.
+
+<p>
+Jobs are moved between the following states by pcontrol:
+<ul>
+<li> pending: the job has not yet been executed.
+<li> busy: the job is currently being executed.
+<li> done: the job has completed, but the stdout/stderr has not been processed by
+     pcontrol.
+<li> exit: the job has completed with a valid exit status
+<li>crash: the job has completed with a crash status (exit on signal).
+</ul>
+
+<h3>Miscellaneous Commands</h3>
+
+<p>
+It is possible to check the status of a single host or job with the
+user command <tt>check</tt>.
+
+<p>
+pcontrol continuously examines the stack of jobs, adjusting their
+state as needed and extracting their output when it is ready.  These
+checks are performed in the background, with pcontrol ready to accept
+further commands from the user in the foreground.  These checks are
+performed after every keystroke, and also after an inactivity timeout.
+The interrupt interval defaults to 1 second, but may be adjusted with
+the <tt>pulse</tt> command, which takes as an argument, the number of
+microseconds for the timeout.
+
+<p>
+the pcontrol system status may be examined with the command
+<tt>status</tt>.  This provides a dump of the job stacks and the host
+stacks.  
+
+<p>
+It is possible to list the jobs currently in a specific stack,
+corresponding to the list of jobs with a given state.  This is done
+with the command <tt>jobstack (stackname)</tt>.  The valid stack names are
+pending, busy, exit, crash, and done.  The result is a list of all
+jobs on the specified stack.  This is useful to determine quickly
+which jobs have exited or crashed.  
+
+<p>
+A specific job may be killed with the command <tt>kill (JobID)</tt>.
+This command is only valid for a job in the <tt>busy</tt> state.  Any
+job in the <tt>pending</tt>, <tt>exit</tt>, or <tt>crash</tt> state
+may be deleted with the <tt>delete (JobID)</tt> command.  This is
+necessary to free the memory associated with the job and its output
+streams.
+
+<p>
+The command <tt>verbose (mode)</tt> turns the verbosity of the
+pcontrol operations on or off.
+
+<p>
+The <tt>pcontrol</tt> and the IPP Image Server have related needs for
+information from the combined storage-and-processing nodes regarding
+which nodes are available.  It is not yet clear if this information is
+best stored in a single location (either <tt>pcontrol</tt> or IPP
+Image Server), which provides the information to other systems on
+demand, or if both systems should maintain the information.  Also, it
+may be necessary to distinguish nodes which are available for
+processing from those that are available to serve data as part of the
+IPP Image Server.
+
+<h3>Command Summary</h3>
+
+<pre>
+check                -- get job or host status
+delete               -- delete job
+host                 -- add / delete / modify host
+job                  -- add job
+jobstack             -- list jobs for a single stack
+kill                 -- kill job
+pulse                -- set system pulse
+status               -- get system status
+stderr               -- get stderr buffer for job
+stdout               -- get stdout buffer for job
+verbose              -- set the verbose mode for job
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/speedtest.hts
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/speedtest.hts	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/pcontrol/speedtest.hts	(revision 16632)
@@ -0,0 +1,42 @@
+
+I ran 8 x 32 fake image copies on the 32 po nodes. each one should
+last a minimal amount of time (no real action, no sleep).  The time to
+process the stack is essentially the speed at which pcontrol can cycle
+though the nodes:
+
+-rw-rw-r--  1 eugene users   17 2005-08-11 19:28:50.000000000 -1000 file.00.032.fits
+-rw-rw-r--  1 eugene users   17 2005-08-11 19:29:20.000000000 -1000 file.07.015.fits
+
+that is 30 seconds to run 8 x 32 jobs: 
+
+0.117 sec / job
+3.750 sec / (job / node)
+
+I ran the same 8 x 32 jobs on one node, with the following rate:
+
+-rw-rw-r--  1 eugene users   17 2005-08-11 19:34:39.000000000 -1000 file.00.001.fits
+-rw-rw-r--  1 eugene users   17 2005-08-11 19:35:30.000000000 -1000 file.07.029.fits
+
+or 51 seconds to run 8 x 32 jobs on 1 node.
+
+0.199 sec / job
+0.199 sec / (job / node)
+
+--
+
+I ran the same test getting 56 seconds for 8 x 32 copies on 32 nodes.
+This time, I used one of the machines in the po cluster (po33) for the
+test:
+
+0.219 sec / job
+
+-rw-rw-r--  1 eugene users   17 2005-08-11 19:45:25.000000000 -1000 file.00.030.fits
+-rw-rw-r--  1 eugene users   17 2005-08-11 19:46:21.000000000 -1000 file.07.028.fits
+
+--
+
+running on psched, from kiawe to po01-po32
+-rw-rw-r--  1 eugene users    17 2005-08-11 20:11:25.000000000 -1000 file.00.003.fits
+-rw-rw-r--  1 eugene users    17 2005-08-11 20:12:30.000000000 -1000 file.07.032.fits
+
+55 seconds; roughly equivalent.  
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/chip.host
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/chip.host	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/chip.host	(revision 16632)
@@ -0,0 +1,23 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 1) { die "USAGE: chip.host (chip)\n"; }
+
+$chip = $ARGV[0];
+
+if ($chip eq "ccd00") {
+    print "po04\n";
+    exit 0;
+}
+if ($chip eq "ccd01") {
+    print "po01\n";
+    exit 0;
+}
+if ($chip eq "ccd02") {
+    print "po02\n";
+    exit 0;
+}
+if ($chip eq "ccd03") {
+    print "po03\n";
+    exit 0;
+}
+print "anyhost\n";
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/copy.image
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/copy.image	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/copy.image	(revision 16632)
@@ -0,0 +1,19 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { die "USAGE: copy.image (filename) (chip)\n"; }
+
+$filename = $ARGV[0];
+$chip     = $ARGV[1];
+
+@word = split ("/", $filename);
+$base = $word[-1];
+$output = "/data/alala/swtests/psched/$base";
+
+open (FILE, ">$output");
+$host = `hostname`;
+printf FILE "chip $chip $host\n";
+close (FILE);
+
+printf STDOUT "$filename $chip\n";
+
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/index.htm	(revision 16632)
@@ -0,0 +1,385 @@
+
+This article describes <tt>psched</tt>, the Pan-STARRS IPP task
+scheduler.
+
+<h3>Overview</h3>
+
+<p>
+The purpose of <tt>psched</tt> is to manage the automatic construction
+and execution of inter-related (often repetative) operations.
+<tt>Psched</tt> uses a set of rules to define UNIX commands, and
+their corresponding command-line arguments, to be performed on some
+regular, repeated basis.  The utility of <tt>psched</tt> is that it
+can easily define an analysis system which is completely
+state-based, as opposed to an event-driven system.  
+
+<p>
+Consider, for example, a telescope which obtains a collection of
+images over the course of a night.  Every minute or two, it takes an
+image and writes the image to some disk.  An event-driven analysis
+system would involve having the telescope initiate a process at the
+end of the exposure.  This process would perform an analysis, write
+some output, then send trigger another process.  This type of
+operation works very well for a simple set up with reliable
+hardware.  Such a system becomes more difficult to maintain when
+hardware failures occur or when multiple systems need to interact
+with each other.  When failures occur, the triggering information
+(the events) is easily lost, thus some mechanisms are needed to
+detect these failures and either re-send the trigger or send an
+alternative failure-mode trigger.  Or, if two systems need to
+interact, one or the other system must block for results from the
+first.  Stopping and restarting such an analysis system is very
+delicate since the appropriate triggers must be set up some how, eg
+by noticing which images have not succeeded and restarting them at
+the appropriate stage.  All of these types of methods of handling
+complexity and failures are essentially state-based rules.
+<tt>Psched</tt> allows the easy definition of a totally state-based
+analysis system.
+
+<p>
+In a state-based system, some mechanism examines the state of the
+system and decides which actions to perform based on the current
+state.  In the illustration above, the mechanism could examine the
+images available (either by examining the disk or by examining the
+state of a data table) and decide to perform an operation based on
+what images are available.  This makes it very easy to handle
+complexity and errors.  If an analysis fails, the state either is
+not successfully updated or the error state is recorded, both
+situations being easy to detect and easy to handle.  Restarting the
+system simply involves starting the state-monitoring mechanism.
+Combining results from multiple input sources simply involves
+watching for the multiple inputs to be available.  <tt>Psched</tt>
+provides a mechanism to define state monitors, and to define the
+actions which are performed when those states occur.
+<tt>Psched</tt> action consist of initiating UNIX commands, where
+the arguments of those commands may depend on the results of the
+state tests.
+
+<h3> Tasks vs Jobs </h3>
+
+<p>
+The primary function of <tt>psched</tt> is to repeatedly perform
+<b>tasks</b>, and execute <b>jobs</b> on the basis of those tasks.
+A task consists of a set of rules which describe system state tests
+to perform on a regular time scale.  Based on the results of those
+state tests, the task will then choose whether or not to construct a
+job.  The task also defines actions to perform upon the completion
+of a job, based upon the output and exit status of the job.  A task
+thus defines the repeat period.  It may optionally define valid or
+invalid time ranges (eg, Mon-Fri or 10:00-17:00, etc).  The task may
+also specify that the job be run locally (ie, in the background on
+the same computer as psched) or remotely by the parallel process
+controller (<tt>pcontrol</tt>).  A job may even be restricted to a
+specific computer managed by <tt>pcontrol</tt>.
+
+An example of a simple tasks is given below.  
+
+<pre>
+  task datalist
+    command ls /data/foo
+    periods -exec 5.0
+    periods -timeout 50.0
+    periods -poll 1.0
+
+    task.exit 0
+      queueprint stdout
+      queuedelete stdout
+    end
+ 
+    task.exit 1
+      queuepush failure "task failed"
+    end
+  end
+</pre>
+
+<p>
+This task does not perform any system state tests; it is simply
+constructs a new job every 5.0 seconds.  The job in this case is
+always the same: <tt> ls /data/foo </tt>.  When the job finished,
+if the job exit status is 0 (normal UNIX success status), the
+resulting output is printed to the screen.  If the job returns an
+exit status of 1 (a failure), the failure queue receives a single
+entry.  Although they are not defined in this case, it is also
+possible to specify the action to be taken if the job crashes (does
+not exit normally) or if it times out (runs beyond the specified
+timeout period).
+
+A slightly more complex task which performs a state test and
+constructs a command based on that test is shown below
+
+<pre>
+  task datalist
+    periods -exec 5.0
+    periods -timeout 50.0
+    periods -poll 1.0
+
+    task.exec 
+      $file = `next.file`
+      if ($file == "none")
+        break
+      end
+      command cp /data/foo/$file /data/bar
+    end
+
+    task.exit 0
+      queueprint stdout
+      queuedelete stdout
+      queuepush copied $file
+    end
+ 
+    task.exit 1
+      queuepush failure $file
+    end
+  end
+</pre>
+
+The <tt>task.exec</tt> macro is executed by psched every 5.0
+seconds.  This macro executes a (hypothetical user-defined) UNIX
+command (<tt>next.file</tt>) which examines the system state, return
+either a filename or the word "none".  If the result of this test is
+"none", the task does nothing: no job is constructed.  Otherwise, a
+job is constructed using the name of the file returned by the state
+test.  Successful jobs have the filename added to the 'copied'
+queue, while failed jobs add the filename to the 'failure' queue.
+
+<h3> Parallel vs Local Job Processing </h3>
+
+Job which are generated by psched tasks may either be run locally
+(forked in the background on the same machine as psched) or run on
+the IPP parallel process controller, <tt>pcontrol</tt>.  The default
+is for the job to be run locally.  If a job should be run on the
+parallel controller, this can be specified by including the command
+<tt>host (hostname)</tt> in the definition of a task.  If the value
+of (hostname) is 'anyhost', then pcontrol may select any of its host
+computers to run the job according to its own rules.  If the value
+of (hostname) is one of the computers managed by pcontrol, then that
+machine will be selected for the job, if it is available.  This
+amounts to a preference to use that machine, but pcontrol is allowed
+to substitute a different machine if it chooses.  If the
+<tt>host</tt> command is given the option <tt>-required</tt>, then
+pcontrol is forced to use the named host, even if the machine is
+down, unknown, or otherwise unavailable.  If the machine is not
+available, pcontrol will simply hold onto the job until the machine
+is available or the job is deleted.  Note that psched may delete
+jobs from pcontrol if they remain pending for too long (see
+<tt>period -timeout</tt>).  
+
+<p>
+It is possible to interact directly with the parallel processor to
+examine the current status, halt the parallel processor, etc.
+Commands to the parallel processor are defined under the
+<tt>controller</tt> command.  The following controller commands are
+available:
+
+<ul>
+  <li> <tt>controller host (command) (hostname)</tt>: Manage the
+  parallel controller collection of hosts.  This command can be used
+  to <tt>add</tt> a new host, the <tt>delete</tt> one of the existing
+  hosts, to turn a host <tt>on</tt> or <tt>off</tt>, and to
+  <tt>check</tt> the status of a host
+    <ul>
+      <li> <tt>controller host add (hostname)</tt>: add a new host.
+      <li> <tt>controller host delete (hostname)</tt>: delete a host.
+      <li> <tt>controller host on (hostname)</tt>: tell pcontrol that the host is on.
+      <li> <tt>controller host off (hostname)</tt>: tell pcontrol that the host is off.
+      <li> <tt>controller host retry (hostname)</tt>: tell pcontrol to retry the host connection.
+      <li> <tt>controller host check (hostname)</tt>: check the current status of a host.
+    </ul>
+  <li><tt>controller exit</tt>: stop controller execution.
+  <li><tt>controller status</tt>: report controller current status.
+  <li><tt>controller check</tt>: check job or host status.
+  <li><tt>controller output</tt>: print accumulated messages from the controller.
+</ul>
+
+It is also possible to specify a host for a task which has not been
+identified to the controller.  If such a host is required, the
+controller will simply keep the associated jobs in the pending state
+until such a machine exists.  See the <a href=../pcontrol>pcontrol</a>
+documentation for further discussion of the controller manipuation of
+jobs and hosts.
+
+<h3> Task Restrictions </h3>
+
+Tasks may have restrictions on when they create jobs and how
+frequently they create jobs.  The task command <tt>trange</tt> is
+used to specify a valid or invalid time range for a task.  A valid
+time range limits the task evaluation to that time period.  An
+invalid time range excludes task evaluation from the time period.
+Any number of time range restrictions may be defined, and the union
+of all restrictions will define if a job may be created.  By
+default, the time range is an inclusive time range: the task is
+evaluated only if the current time falls within the specified time
+range.  Alternatively, if the <tt>-exclude</tt> flag is given, the
+time range is exclusive, in which case the task is <em>not</em>
+evaluated if the current time falls within this range.
+
+<p>
+The time range may be given as a range of absolute dates as follows:
+
+<pre>
+trange YYYY/MM/DD,HH:MM:SS YYYY/MM/DD,HH:MM:SS 
+</pre>
+
+where the two dates specify the start and end of the time range.  In
+either of these date representations, the least-significant elements
+of the date and time may be dropped, defaulting to 00 (in the case
+of hours, minutes, and seconds) or 01 (in the case of day and
+months).  Rather than specifying an end date, it is also valid to
+specify a time interval from the starting date.  The time interval
+is specified as a number followed by a unit indicated by a single
+letter: d (days), h (hours), m (minutes), s (seconds).  
+
+<p>
+The time range may also be specified as a repeated period of time,
+either as a time of day or a day and time of week.  In the first
+case, the time range is specified as follows:
+
+<pre> 
+trange HH:MM:SS HH:MM:SS
+</pre>
+
+where again the least-significant elements may be dropped and
+default to 00.  This type of restriction defines a time range which
+is valid every day.  The alternative is to specify a time range
+within the week, in the following form:
+
+<pre>
+trange DAY@HH:MM:SS DAY@HH:MM:SS
+</pre>
+
+where the value of DAY may take on any of the three letter
+day-of-week names (Sun, Mon, Tue, etc).  This restriction specifies
+a start and end time within a week which is evaluated for each
+week. 
+
+<p>
+Below are several examples of valid time range restrictions
+
+<pre>
+trange 2005/01/01 2005/12/31   (only run during 2005!)
+trange 18:00 00:00             (only run from 6pm until midnight)
+trange 00:00 06:00             (only run from midnight until 6am)
+trange Mon@08:00 Fri@17:00     (only run between Mon morning and Fri afternoon)
+trange -exclude 12:00 13:00    (skip 1 hour from noon)
+</pre>
+
+<em>Note that the current definition of trange does not include time
+zone information.  This means that <b>all</b> times are relative to
+UT.  This should be addressed by adding a timezone environment
+variable to psched and by allowing the trange to define a timezone
+offset.</em>
+
+<p>
+It is also possible to restrict the total number of jobs which are
+spawned for a given task.  This is done with the <tt>nmax</tt>
+command, which is given as part of the task definition.  Once a task
+has constructed nmax jobs, it stops task evaluation.  It is possible
+to redefine the value of nmax at any time by redefining the task.
+Any time the task is redefined, the new values for any task concept
+will override the existing values for the task concept.  
+
+<h3> Inter-Task and Inter-Job Communications </h3>
+
+There are several ways in which the results of jobs may be used to
+influence other jobs.  These include:
+<ul>
+<li> external communications
+<li> job exit status
+<li> job stdout parsing
+</ul>
+
+<p>
+It is always possible for the interprocess communication to be
+performed externally: all jobs may simply write results to an
+external data source which is queried as part of the task
+evaluation.  Psched may interact with UNIX programs using Opihi
+system interaction functions.  These interaction methods include:
+the backticks for setting Opihi variables:
+
+<pre>
+$variable = `UNIX Command`
+</pre>
+
+The exec command (which executes a UNIX command) and the backticks
+both receive the UNIX command exit status, setting the variable
+$STATUS.  It is also possible to set a variable list to the output
+of a UNIX command:
+
+<pre>
+list var -x "UNIX Command"
+</pre>
+
+In this last case, the values $var:0 - $var:N-1 are set to the value
+of the stdout lines from the UNIX command, and the value $var:n is
+set to the number of output lines.
+
+<p>
+Fine-grained control over the job exit status is available with the
+<tt>task.exit</tt> macro command.  This allows a task to define an
+exit macro which is performed for different exit status conditions.
+The argument to the <tt>task.exit</tt> command is the exit status
+value which triggers the macro.  This may consist of any valid
+numeric exit status value (0-255).  It may also have the value
+<tt>crash</tt>, in which case the macro is executed if the program
+exited as a result of a signal (ie, segmentation fault, etc).
+Finally, if may have the value <tt>default</tt>, in which case, the
+macro is run if no other macro describes the exit status.
+
+<p>
+Jobs may transmit their results back to psched for further
+evaluation through the standard output and standard error streams.
+Whenever a job exits, the complete stdout and stderr streams from
+the job are pushed onto the psched queues <tt>stdout</tt> and
+<tt>stderr</tt>.  The job exit macros may then parse these queues,
+moving the results into other psched / Opihi data containers
+(queues, variables, vectors, whatever is appropriate).  <em>Note
+that currently, the output data is simply pushed onto these output
+queues.  It is currently the responsibility of the psched programmer
+to use or dispose of the data in these queues.  This may change in
+the future: the queues may be flushed for each job completion.</em>
+
+<h3>Running the scheduler</h3>
+
+Once a set of tasks has been defined, the scheduler can be started.
+The scheduler will run in the background, at regular intervals
+examining the collection of tasks and jobs.  In these periods, the
+scheduler attempts to construct new jobs and checks on the status of
+jobs which may have finished, either locally or on the controller.
+To start the scheduler, give the command <tt>run</tt>.  To stop the
+scheduler, given the command <tt>stop</tt>.  The current status of
+the scheduler, controller, and any jobs which have been spawned are
+listed with the <tt>status</tt> command.
+
+<p>
+It is also possible to kill or delete individual jobs by hand with
+the commands <tt>kill (jobID)</tt> or <tt>delete (jobID)</tt>.
+
+<h3>Other features</h3>
+
+The command <tt>verbose (mode)</tt> turns the verbosity of the
+scheduler operations on or off.
+
+It is possible to change the rate at which the scheduler checks the
+task and job lists with the command <tt>pulse (usec)</tt), which
+takes as an argument, the number of microseconds between timeouts.
+
+<h3>Command Summary</h3>
+
+<pre>
+controller                  -- controller commands
+task                        -- define a schedulable task
+host                        -- define host machine for a task
+nmax                        -- define maximum number of jobs for a task
+trange                      -- define valid/invalid time periods for a task
+task.exit                   -- define exit macros for a task
+task.exec                   -- define pre-exec macro for a task
+command                     -- define executed command for a task
+periods                     -- define time scales for a task
+run                         -- run the scheduler
+stop                        -- stop the scheduler
+pulse                       -- set the scheduler update period
+status                      -- get system status
+kill                        -- kill job
+delete                      -- delete job
+verbose                     -- set/toggle verbose mode
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/new.images
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/new.images	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/new.images	(revision 16632)
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+
+# a dummy script to simulate data arriving from OTIS
+
+# read lines 'new.list', send to 'raw.list'
+
+open (FILE, "new.last");
+@list = <FILE>;
+close (FILE);
+($Nend) = split (" ", $list[0]);
+# print "Nend: $Nend\n";
+
+open (FILE, "new.list");
+@list = <FILE>;
+close (FILE);
+
+$Nend += 5;
+for ($i = 0; $i < $Nend; $i++) {
+    ($name, $chip, $state) = split (" ", $list[$i]);
+    if ($state ne "new") { next; }
+    print "$list[$i]";
+}
+
+open (FILE, ">new.last");
+print FILE "$Nend\n";
+close (FILE);
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/pcopy.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/pcopy.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/pcopy.htm	(revision 16632)
@@ -0,0 +1,138 @@
+
+Below is an example script for psched which demonstrates the
+scheduling system. This parallel-copying script implements the
+Pan-STARRS image copying system, which requests images from the summit
+and copies them to the appropriate computer.  The first task in the
+script queries an external system for new image names with the
+function <tt>new.images</tt>.  In the case of Pan-STARRS, this would
+be a request from OTIS, the observatory controlling system.  The
+second task initiates the individual image copies, with separate CCDs
+being copied to separate computers.  This script uses the concept of
+having specific machines assigned to specific CCDs (as Pan-STARRS
+intends to operate). The association is determined by calling the
+external function <tt>chip.host</tt>, providing the identifier of the
+chip in question.  This returns an appropriate host.  The
+<tt>copy.image</tt> function copies the file and also sends a message
+to the summit system to inform it that the image has been successfully
+copied.
+
+<p>
+You may download just the <a href="pcopy.pro">pcopy.pro</a> script for
+a copy free of HTML code.  Also available are the dummy scripts <a
+href="new.images">new.images</a>, <a href="copy.image">copy.image</a>,
+and <a href="chip.host">chip.host</a>.
+
+<hr>
+
+<pre>
+verbose on
+queueinit newImages
+exec echo 0 > new.last
+exec cp -f raw.list new.list
+
+controller host add po01
+controller host add po02
+controller host add po03
+controller host add po04
+
+# identify the images ready for copy 
+# new entries are added to queue newImages
+# need to compare the new list with the ones already being processed
+task	       new.images
+  command      new.images
+  host         local
+
+  periods      -poll 1
+  periods      -exec 5
+  periods      -timeout 5
+
+  # success
+  task.exit    0
+    local i j Nstdout Nimages
+    # compare output with new.image queue
+    # keep only new entries
+    queuesize stdout -var Nstdout
+    for i 0 $Nstdout
+      queuepop stdout -var line
+      queuepush newImages -uniq -key 0 "$line"
+    end
+  end
+
+  # locked list
+  task.exit    1
+    echo       "new.images: exec failure"
+    $new.image.failure ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "new.images: unknown exit status: $EXIT"
+    $new.image.failure ++
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "new.images: timeout"
+    $new.image.failure ++
+  end
+end
+
+# copy new images, sending job to desired host
+task	       copy.images
+  periods      -poll 0.2
+  periods      -exec 1
+  periods      -timeout 5
+
+  task.exec
+    queuesize  newImages -var N
+    if ($N == 0) break
+    # if ($network == 0) break
+    # if ($filesystem == 1) break
+    
+    queuepop newImages -var line
+    list tmp -split $line
+    $filename   = $tmp:0
+    $chip       = $tmp:1
+    $state      = $tmp:2
+    if ($state == new) 
+      # copy this image
+      queuepush newImages -replace -key 0 "$filename $chip run"
+    else
+      # ignore this image
+      queuepush newImages -replace -key 0 "$filename $chip $state"
+      break
+    end
+    # echo $chip
+    $host = `chip.host $chip`
+    # echo $host
+    host $host
+    # echo "starting copy for $filename on $host..."
+    command copy.image $filename $chip
+  end
+
+  # can I have access to argc,argv?
+
+  # success
+  task.exit    0
+    echo "done copy..."
+    queuepop stdout -var line
+    list tmp -split $line
+    $filename   = $tmp:0
+    $chip       = $tmp:1
+    exec mark.image $filename
+    queuepush newImages -replace -key 0 "$filename $chip copy"
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "new.images: unknown exit status: $EXIT"
+    $new.image.failure ++
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "new.images: timeout"
+    $new.image.failure ++
+  end
+end
+<pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/pcopy.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/pcopy.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/pcopy.pro	(revision 16632)
@@ -0,0 +1,111 @@
+
+verbose on
+queueinit newImages
+exec echo 0 > new.last
+exec cp -f raw.list new.list
+
+controller host add po01
+controller host add po02
+controller host add po03
+controller host add po04
+
+# identify the images ready for copy 
+# new entries are added to queue newImages
+# need to compare the new list with the ones already being processed
+task	       new.images
+  command      new.images
+  host         local
+
+  periods      -poll 1
+  periods      -exec 5
+  periods      -timeout 5
+
+  # success
+  task.exit    0
+    local i j Nstdout Nimages
+    # compare output with new.image queue
+    # keep only new entries
+    queuesize stdout -var Nstdout
+    for i 0 $Nstdout
+      queuepop stdout -var line
+      queuepush newImages -uniq -key 0 "$line"
+    end
+  end
+
+  # locked list
+  task.exit    1
+    echo       "new.images: exec failure"
+    $new.image.failure ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "new.images: unknown exit status: $EXIT"
+    $new.image.failure ++
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "new.images: timeout"
+    $new.image.failure ++
+  end
+end
+
+# copy new images, sending job to desired host
+task	       copy.images
+  periods      -poll 0.2
+  periods      -exec 1
+  periods      -timeout 5
+
+  task.exec
+    queuesize  newImages -var N
+    if ($N == 0) break
+    # if ($network == 0) break
+    # if ($filesystem == 1) break
+    
+    queuepop newImages -var line
+    list tmp -split $line
+    $filename   = $tmp:0
+    $chip       = $tmp:1
+    $state      = $tmp:2
+    if ($state == new) 
+      # copy this image
+      queuepush newImages -replace -key 0 "$filename $chip run"
+    else
+      # ignore this image
+      queuepush newImages -replace -key 0 "$filename $chip $state"
+      break
+    end
+    # echo $chip
+    $host = `chip.host $chip`
+    # echo $host
+    host $host
+    # echo "starting copy for $filename on $host..."
+    command copy.image $filename $chip
+  end
+
+  # can I have access to argc,argv?
+
+  # success
+  task.exit    0
+    echo "done copy..."
+    queuepop stdout -var line
+    list tmp -split $line
+    $filename   = $tmp:0
+    $chip       = $tmp:1
+    exec mark.image $filename
+    queuepush newImages -replace -key 0 "$filename $chip copy"
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "new.images: unknown exit status: $EXIT"
+    $new.image.failure ++
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "new.images: timeout"
+    $new.image.failure ++
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/speedtests.hts
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/speedtests.hts	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/psched/speedtests.hts	(revision 16632)
@@ -0,0 +1,15 @@
+
+CheckController is critical for speed
+
+parse jobs: 1.5 usec per job + 20 usec
+
+check exit stack: 2.7ms average, up to 10ms: this seems to be the
+kernel scheduler putting pcontrol in the background every now and
+again.  
+
+with 1024 jobs and 4 machines, the jobs being sent to machines (should
+take only 1 second, but timeouts add in delays) takes up the first few
+seconds.  initially
+
+
+*write this up, add some tests for timing... *
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/sequence.idx
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/sequence.idx	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/IPP-subsystems/sequence.idx	(revision 16632)
@@ -0,0 +1,3 @@
+psched
+pcontrol
+pclient
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/commands.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/commands.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/commands.htm	(revision 16632)
@@ -0,0 +1,59 @@
+<meta name=file  content=dimm>
+ <meta name=title content=dimm user's guide>
+ <meta name=page  content=dimm>
+ 
+ <table>
+  <tr><td> altaz         </td><td>      altaz / celestial coord conversions </td></tr>
+  <tr><td> box           </td><td>      draw a box on the plot </td></tr>
+  <tr><td> buffers       </td><td>      list the currently allocated buffers </td></tr>
+  <tr><td> camera        </td><td>      camera functions </td></tr>
+  <tr><td> center        </td><td>      center the Kii window at coords </td></tr>
+  <tr><td> clear         </td><td>      erase plot </td></tr>
+  <tr><td> clip          </td><td>      clip values in a buffer to be within a range </td></tr>
+  <tr><td> concat        </td><td>      expand vector dimension </td></tr>
+  <tr><td> coords        </td><td>      load coordinates for buffer from file </td></tr>
+  <tr><td> create        </td><td>      create a new vector </td></tr>
+  <tr><td> cursor        </td><td>      get coordinates from the Kii window </td></tr>
+  <tr><td> cut           </td><td>      extract a cut across an image </td></tr>
+  <tr><td> datafile      </td><td>      define file to read vectors </td></tr>
+  <tr><td> delete        </td><td>      delete a buffer </td></tr>
+  <tr><td> erase         </td><td>      erase objects on an overlay </td></tr>
+  <tr><td> extract       </td><td>      extract a portion of a buffer into another buffer </td></tr>
+  <tr><td> file          </td><td>      test file </td></tr>
+  <tr><td> findstars     </td><td>      find objects on image </td></tr>
+  <tr><td> focus         </td><td>      skyprobe focus </td></tr>
+  <tr><td> gauss         </td><td>      get statistics on a star, assuming gaussian profile </td></tr>
+  <tr><td> getchr        </td><td>      find character in string </td></tr>
+  <tr><td> header        </td><td>      print buffer header </td></tr>
+  <tr><td> histogram     </td><td>      histogram of vector </td></tr>
+  <tr><td> imhist        </td><td>      histogram of an image region </td></tr>
+  <tr><td> jpeg          </td><td>      interpolate between vector pairs </td></tr>
+  <tr><td> keyword       </td><td>      extract a FITS keyword from buffer header </td></tr>
+  <tr><td> labels        </td><td>      define labels for plot </td></tr>
+  <tr><td> limits        </td><td>      define plot limits </td></tr>
+  <tr><td> load          </td><td>      load an SAOimage style overlay </td></tr>
+  <tr><td> mcreate       </td><td>      create a matrix </td></tr>
+  <tr><td> plot          </td><td>      plot a pair of vectors </td></tr>
+  <tr><td> ps            </td><td>      make PS file from Kii </td></tr>
+  <tr><td> rd            </td><td>      read an image from a file </td></tr>
+  <tr><td> read          </td><td>      read vectors from datafile </td></tr>
+  <tr><td> rebin         </td><td>      rebin data by factor of N </td></tr>
+  <tr><td> resize        </td><td>      change Kii window size </td></tr>
+  <tr><td> save          </td><td>      save an SAOimage style overlay </td></tr>
+  <tr><td> set           </td><td>      do image arithmetic </td></tr>
+  <tr><td> sort          </td><td>      sort vectors by key </td></tr>
+  <tr><td> sprintf       </td><td>      formatted print to a variable </td></tr>
+  <tr><td> star          </td><td>      star stats at rough coords </td></tr>
+  <tr><td> stats         </td><td>      give statistics on a portion of a buffer </td></tr>
+  <tr><td> strlen        </td><td>      string length </td></tr>
+  <tr><td> style         </td><td>      set the style for graph plots </td></tr>
+  <tr><td> subset        </td><td>      reduce vector dimension </td></tr>
+  <tr><td> substr        </td><td>      substring </td></tr>
+  <tr><td> telescope     </td><td>      telescope communications </td></tr>
+  <tr><td> textline      </td><td>      write text on Kapa window </td></tr>
+  <tr><td> tv            </td><td>      display an image on the Kii window </td></tr>
+  <tr><td> vectors       </td><td>      list vectors </td></tr>
+  <tr><td> vstat         </td><td>      vector statistics </td></tr>
+  <tr><td> wd            </td><td>      write an image to a file </td></tr>
+  <tr><td> write         </td><td>      write vectors to datafile </td></tr>
+ </table>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/DIMM/index.htm	(revision 16632)
@@ -0,0 +1,20 @@
+<meta name=file  content=DIMM>
+<meta name=title content=DIMM user's guide>
+<meta name=page  content=DIMM>
+
+<h3> Introduction </h3>
+
+DIMM is a control shell for the CFHT DIMM Telescope based on the Opihi
+shell.  See the Opihi documentation for further descriptions of the
+tools provided by the Opihi shell.  In addition to the basic Opihi
+functions and the astronomy functions from Mana, DIMM provides a
+collection of telescope and camera control functions.
+
+<h3> Mana astronomy functions</h3>
+
+<pre>
+altaz                      -- altaz / celestial coord conversions
+camera                     -- camera functions
+findstars                  -- find objects on image
+telescope                  -- telescope communications
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/commands.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/commands.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/commands.htm	(revision 16632)
@@ -0,0 +1,108 @@
+<meta name=file  content=mana>
+ <meta name=title content=mana user's guide>
+ <meta name=page  content=mana>
+ 
+ <table>
+ <tr><td> accum            </td><td> accumulate vector values in another vector                 </td></tr> 
+ <tr><td> applyfit         </td><td> apply fit coeffs to generate vector                        </td></tr> 
+ <tr><td> applyfit2d       </td><td> apply fit coeffs to generate vector                        </td></tr> 
+ <tr><td> biassub          </td><td> subtract medianed overscan row or column                   </td></tr> 
+ <tr><td> box              </td><td> draw a box on the plot                                     </td></tr> 
+ <tr><td> buffers          </td><td> list the currently allocated buffers                       </td></tr> 
+ <tr><td> buftovec         </td><td> convert an image buffer to a single vector                 </td></tr> 
+ <tr><td> center           </td><td> center the Kii window at coords                            </td></tr> 
+ <tr><td> clear            </td><td> erase plot                                                 </td></tr> 
+ <tr><td> clip             </td><td> clip values in a buffer to be within a range               </td></tr> 
+ <tr><td> cmpload          </td><td> load stars from a cmp file on overlay                      </td></tr> 
+ <tr><td> concat           </td><td> expand vector dimension                                    </td></tr> 
+ <tr><td> contour          </td><td> send contour to overlay                                    </td></tr> 
+ <tr><td> coords           </td><td> load coordinates for buffer from file                      </td></tr> 
+ <tr><td> create           </td><td> create a new vector                                        </td></tr> 
+ <tr><td> cursor           </td><td> get coordinates from the Kii window                        </td></tr> 
+ <tr><td> cut              </td><td> extract a cut across an image                              </td></tr> 
+ <tr><td> cval             </td><td> small median image                                         </td></tr> 
+ <tr><td> datafile         </td><td> define file to read vectors                                </td></tr> 
+ <tr><td> delete           </td><td> delete a buffer                                            </td></tr> 
+ <tr><td> demux            </td><td> demux an image pixels interleaved in Nx by Ny sections     </td></tr> 
+ <tr><td> device           </td><td> set / get current graphics device </td><td>                </td></tr> 
+ <tr><td> dimendown        </td><td> convert matrix to vector                                   </td></tr> 
+ <tr><td> dimenup          </td><td> convert vector to matrix                                   </td></tr> 
+ <tr><td> drizzle          </td><td> transform image to image                                   </td></tr> 
+ <tr><td> erase            </td><td> erase objects on an overlay                                </td></tr> 
+ <tr><td> extract          </td><td> extract a portion of a buffer into another buffer          </td></tr> 
+ <tr><td> fft1d            </td><td> fft on the pixel-stream in an image                        </td></tr> 
+ <tr><td> fft2d            </td><td> fft on an image                                            </td></tr> 
+ <tr><td> file             </td><td> test file                                                  </td></tr> 
+ <tr><td> fit              </td><td> least-squares fit to vectors                               </td></tr> 
+ <tr><td> fit2d            </td><td> least-squares fit to vectors                               </td></tr> 
+ <tr><td> flux             </td><td> flux in a convex contour                                   </td></tr> 
+ <tr><td> gauss            </td><td> get statistics on a star, assuming gaussian profile        </td></tr> 
+ <tr><td> gaussj           </td><td> solve Ax = B (N-D)                                         </td></tr> 
+ <tr><td> getchr           </td><td> find character in string                                   </td></tr> 
+ <tr><td> grid             </td><td> wait until return is typed                                 </td></tr> 
+ <tr><td> header           </td><td> print buffer header                                        </td></tr> 
+ <tr><td> histogram        </td><td> histogram of vector                                        </td></tr> 
+ <tr><td> imfit            </td><td> fit function                                               </td></tr> 
+ <tr><td> imhist           </td><td> histogram of an image region                               </td></tr> 
+ <tr><td> integrate        </td><td> integrate a vector                                         </td></tr> 
+ <tr><td> interpolate      </td><td> interpolate between vector pairs                           </td></tr> 
+ <tr><td> jpeg             </td><td> interpolate between vector pairs                           </td></tr> 
+ <tr><td> kern             </td><td> convolve with 3x3 kernel                                   </td></tr> 
+ <tr><td> keyword          </td><td> extract a FITS keyword from buffer header                  </td></tr> 
+ <tr><td> labels           </td><td> define labels for plot                                     </td></tr> 
+ <tr><td> limits           </td><td> define plot limits                                         </td></tr> 
+ <tr><td> load             </td><td> load an SAOimage style overlay                             </td></tr> 
+ <tr><td> mcreate          </td><td> create a matrix                                            </td></tr> 
+ <tr><td> medianmap        </td><td> small median image                                         </td></tr> 
+ <tr><td> memory           </td><td> long listing of the allocated memory                       </td></tr> 
+ <tr><td> mget             </td><td> extract a vector from a matrix                             </td></tr> 
+ <tr><td> minterp          </td><td> interpolate image pixels                                   </td></tr> 
+ <tr><td> mkgauss          </td><td> insert a gaussian in an image                              </td></tr> 
+ <tr><td> mset             </td><td> insert a vector in a matrix                                </td></tr> 
+ <tr><td> multifit         </td><td> solve for overlapping orders in ESI data                   </td></tr> 
+ <tr><td> objload          </td><td> load stars from an obj file on overlay                     </td></tr> 
+ <tr><td> outline          </td><td> vector statistics                                          </td></tr> 
+ <tr><td> peak             </td><td> find vector peak in range                                  </td></tr> 
+ <tr><td> plot             </td><td> plot a pair of vectors                                     </td></tr> 
+ <tr><td> point            </td><td> load overlay with single point                             </td></tr> 
+ <tr><td> profile          </td><td> radial profile at X, Y                                     </td></tr> 
+ <tr><td> ps               </td><td> make PS file from Kii                                      </td></tr> 
+ <tr><td> rd               </td><td> read an image from a file                                  </td></tr> 
+ <tr><td> read             </td><td> read vectors from datafile                                 </td></tr> 
+ <tr><td> rebin            </td><td> rebin data by factor of N                                  </td></tr> 
+ <tr><td> resize           </td><td> change Kii window size                                     </td></tr> 
+ <tr><td> roll             </td><td> roll image to new start point                              </td></tr> 
+ <tr><td> rotate           </td><td> rotate image                                               </td></tr> 
+ <tr><td> save             </td><td> save an SAOimage style overlay                             </td></tr> 
+ <tr><td> scalen           </td><td> get / set real bzero / bscale values                       </td></tr> 
+ <tr><td> section          </td><td> define section of graph                                    </td></tr> 
+ <tr><td> select           </td><td> selective vector assignment                                </td></tr> 
+ <tr><td> set              </td><td> do image arithmetic                                        </td></tr> 
+ <tr><td> sexigesimal      </td><td> convert to/from sexigesimal/decimal                        </td></tr> 
+ <tr><td> shift            </td><td> shift data in an image                                     </td></tr> 
+ <tr><td> simsignal        </td><td> simulate sine-wave with Nbit A/D and given S/N             </td></tr> 
+ <tr><td> sort             </td><td> sort vectors by key                                        </td></tr>                        
+ <tr><td> spline.apply     </td><td> apply spline fit to generate an image                      </td></tr> 
+ <tr><td> spline.construct </td><td> create spline 2nd deriv. terms                             </td></tr> 
+ <tr><td> sprintf          </td><td> formatted print to a variable                              </td></tr> 
+ <tr><td> star             </td><td> star stats at rough coords                                 </td></tr> 
+ <tr><td> stats            </td><td> give statistics on a portion of a buffer                   </td></tr> 
+ <tr><td> strlen           </td><td> string length                                              </td></tr> 
+ <tr><td> style            </td><td> set the style for graph plots                              </td></tr> 
+ <tr><td> subset           </td><td> reduce vector dimension                                    </td></tr> 
+ <tr><td> substr           </td><td> substring                                                  </td></tr> 
+ <tr><td> svd              </td><td> singular value decomposition of a matrix                   </td></tr> 
+ <tr><td> swapbytes        </td><td> byte swap thing                                            </td></tr> 
+ <tr><td> textline         </td><td> write text on Kapa window                                  </td></tr> 
+ <tr><td> tv               </td><td> display an image on the Kii window                         </td></tr> 
+ <tr><td> uniq             </td><td> create a uniq vector subset from a vector                  </td></tr> 
+ <tr><td> unsign           </td><td> toggle the UNSIGN status                                   </td></tr> 
+ <tr><td> vclip            </td><td> clip values in a vector to be within a range               </td></tr> 
+ <tr><td> vcontour         </td><td> create contour vectors                                     </td></tr> 
+ <tr><td> vectors          </td><td> list vectors                                               </td></tr> 
+ <tr><td> vstat            </td><td> vector statistics                                          </td></tr> 
+ <tr><td> wd               </td><td> write an image to a file                                   </td></tr> 
+ <tr><td> write            </td><td> write vectors to datafile                                  </td></tr> 
+ <tr><td> zap              </td><td> delete pixels                                              </td></tr> 
+ <tr><td> zplot            </td><td> plot x y with size scaled by z                             </td></tr> 
+ </table>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/Mana/index.htm	(revision 16632)
@@ -0,0 +1,48 @@
+<meta name=file  content=Mana>
+<meta name=title content=Mana user's guide>
+<meta name=page  content=Mana>
+
+<h3> Introduction </h3>
+
+Mana is a basic image and data analysis program based on the Opihi
+shell.  See the Opihi documentation for further descriptions of the
+tools provided by the Opihi shell.  In addition to these functions,
+Mana provides a collection of astronomical functions.
+
+<h3> Mana astronomy functions</h3>
+
+<pre>
+  findpeaks              -- find image peaks
+  fitcontour             -- fit ellipse contour
+  starcontour            -- object contour
+  rawstars               -- find raw star stats
+  biassub                -- subtract medianed overscan row or column
+  cgrid                  -- plot sky coordinate grid
+  coords                 -- load coordinates for buffer from file
+  cplot                  -- plot vectors in sky coordinates
+  csystem                -- convert between coordinate systems
+  ctimes                 -- convert between time formats
+  cval                   -- cosmic ray flux?
+  czplot                 -- plot scaled vectors in sky coordinates
+  drizzle                -- transform image to image
+  flux                   -- flux in a convex contour
+  gauss                  -- get statistics on a star, assuming gaussian profile
+  getvel                 -- rotcurve to velocities
+  imfit                  -- fit function
+  imsub                  -- subtract function
+  medianmap              -- small median image
+  mkgauss                -- generate a 2-D gaussian centered in image
+  multifit               -- fit multi-order spectrum
+  objload                -- plot obj data on Ximage 
+  outline                -- fit outline region
+  polar                  -- convert polar image to cartesian
+  precess                -- precess coordinates
+  profile                -- radial profile at X, Y
+  region                 -- define sky region for plot
+  rotcurve               -- convert CO images to polar coords
+  scale                  -- get / set real bzero / bscale values
+  sexigesimal            -- convert to/from sexigesimal/decimal
+  spec                   -- extract a spectrum
+  star                   -- star stats at rough coords
+  transform              -- geometric transformation of image
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/Opihi-Programs/index.htm	(revision 16632)
@@ -0,0 +1,563 @@
+<meta name=file  content=opihi>
+<meta name=title content=opihi user's guide>
+<meta name=page  content=opihi>
+
+<h3> Introduction </h3>
+
+<p>
+Opihi is a generic command-line interpreter which has been used as the
+front-end for Mana, DVO, and other high-level programs in the Elixir
+system.  The interpreter has a variety of features of shell-scripting
+languages: if statements, for loops, macros with command-line
+arguments, and so forth.  The shell also allows for variables,
+arithmetic on variables, input from source files, and a variety of
+other useful tools.  Opihi has a simple command-line interaction that
+resembles the UNIX <tt>tcsh</tt>, but with many additional useful
+features.  It can also be used as a scripting language much like
+<tt>sh</tt> or perl.
+
+<p>
+Opihi includes tools to manipulate and display 1-D (vector) and 2-D
+(image) data.  Two external programs are used for graphical display:
+the image display tool (Kii) and the graphing tool (Kapa).  Various
+functions are available to perform math, statistical, and other
+operations on vectors and images.
+
+<h3> User Interface </h3>
+
+<p>
+The command-line interaction is based on the readline libraries and
+behaves like <tt>tcsh</tt>.  Arrows can be used for editing.  There is both
+command and file completion with the TAB key.  You can also use
+emacs-like commands such as ctrl-a to reach the beginning of the line
+and ctrl-e to reach the end.  It is also possible to type just a
+fraction of a command, as long as it is unique.  An ambiguous command
+will list the possible alternatives.  For example:
+
+<pre>
+opihi: c
+ambiguous command: c ( catalog cgrid clear create cursor )
+</pre>
+
+Multiple commands can generally be placed on one line with semi-colons
+as separators.
+
+<h3> Data Representations</h3>
+
+<h4> Simple Scalar Variables </h4>
+
+<p>
+Scalar variables in Opihi are prepended with a dollar sign ($).  A
+variable may be created and the value assigned by a line which looks
+like:
+
+<p class=eq>
+$var = (expression)
+</p>
+
+where (expression) is some math expression.  The math expression may
+consist of the standard math operators (+,-,*,/) as well as any
+already-defined variables and the functions log(), ln(), sqrt(),
+exp(), ten() (10<sup>x</sup>), sin(), cos(), etc.  Other special
+operators are the carret (^) for exponetiation (eg, 2^3 is 8) and the
+@ symbol as a binary arc-tangent (eg, 1@3 is 18.43 degrees).  In
+addition, the operator <tt><<</tt> returns the minimum of the two
+surrounding values, and <tt>>></tt> returns the maximum.  Variables
+can be numeric or character strings.  If the shell does not understand
+the syntax of the line as a math expression, it is assumed to be a
+string.
+
+<em>local variables</em>
+
+<p>
+If there is a pair of curly brackets {} anywhere on a command line,
+whatever is inside is assumed to be a math expression and evaluated
+before the line is executed.  This later feature allows functions of
+variables to be passed as arguments to Opihi functions.  (see also the
+discussion below about temporary vectors and images).
+For example:
+
+<pre>
+echo {$fred*dcos(45)}
+</pre>
+
+would give the response 7.07107 if $fred had the value of 10.0.  There
+are math functions <tt>cos</tt>, <tt>sin</tt>, and <tt>tan</tt>, which operate on radian
+expressions, and also <tt>dcos</tt>, <tt>dsin</tt>, <tt>dtan</tt>, which operate on
+degree expressions.  There are also the equivalent inverse functions:
+eg., <tt>asin</tt> and <tt>dasin</tt> return radians and degrees, respectively.
+The help section on Math defines all of the available math functions.
+
+<h4> Lists </h4>
+
+Opihi lists are grouped sets of scalar variables (which may be
+strings).  A list consists of N variables with names of the form
+<tt>name:i</tt>, where the value of i ranges from 0 to N-1.  In addition,
+the list length is defined as the value <tt>name:n</tt>.  Since these are
+just informally grouped, a list may be defined by hand (ie, by
+defining each element and the length).  There is also the command
+<tt>list</tt> which builds a list from the following lines until reaching
+a line consisting of the single word <tt>end</tt>:
+
+<pre>
+list sample
+ value 0
+ value 1
+ test line
+end
+</pre>
+
+will define the variables <tt>$sample:0 - $sample:2</tt>, and <tt>$sample:n</tt>,
+with value of 3.
+
+<p>
+The list command may also construct a list from the output of a UNIX
+command:
+
+<pre>
+list sample -x "ls /tmp"
+</pre>
+
+will result in a list consisting of one entry for each file in the
+listing.  
+
+<p>
+The list command may also be used to split a string by whitespace:
+
+<pre>
+list sample -split this is a test
+</pre>
+will result in a list with 4 elements, one for each word. 
+
+<h4> queues </h4>
+
+<pre>
+queuelist                 -- list existing queues
+queuesize                 -- return the length of the given queue
+queueinit                 -- create a zero-length queues
+queuedelete               -- delete a queues
+queuepush                 -- add an item to the end of the queue
+queuepop                  -- remove and return the first item in the queue
+</pre>
+
+A queue is a data construct consisting of a sequence of lines from
+which simple selections can be made.  Data items are added and removed
+from the queue with <tt>queuepush</tt> and <tt>queuepop</tt> commands which push
+entries on the end of the queue and pop them off the beginning.  The
+available queues may be obtained with the command <tt>queuelist</tt>, and
+the length of a specific queue may be determined with the <tt>queuesize</tt>
+command.  The contents of a queue may be printed with <tt>queueprint</tt>.
+Pushing data onto a non-existent queue will create the queue.  An
+empty queue may be created with the command <tt>queueinit</tt> and a queue
+may be deleted with <tt>queuedelete</tt>.  
+
+<p>
+The <tt>queuepush</tt> commands allows for additional options which modify
+how the data is pushed on the queue.  The <tt>-uniq</tt> flag specifies that
+the queue should be search for an existing match and not add the new
+data item if a matching item already exists.  The <tt>-replace</tt> flag is
+similar to the <tt>-uniq</tt> flag, but instead the new item will replace
+the existing match, if a match is found.  These two options have
+identical results if the match is made based on the entire line.
+However, they may be more usefully distinguished by specifying a
+restriction on the match with the <tt>-key</tt> flag.  This flag specified
+which whitespace-separated element of the line to use for the match,
+with the first element being element 0.  
+
+<p>
+Numerical vectors and images (matrices) are discussed later in this
+document.
+
+<h3> Opihi Shell Programing and Flow-control</h3>
+
+<pre>
+input                     -- read command lines from a file 
+macro                     -- deal with the macros 
+for                       -- for loop 
+if                        -- logical cases 
+while                     -- while loop
+break                     -- escape from function 
+continue                  -- next loop iteration
+</pre>
+
+<p>
+There are several options for programming in the opihi shell.  First,
+a file which contains a series of commands can be executed with
+<tt>input (filename)</tt>.  When an opihi-based program is started, it
+loads a file from the user's home directory, with a name of the form
+<tt>~/.programrc</tt>.  This resource file may contain any commands,
+and allows a user to customize his or her environment.
+
+<p>
+It is also possible to define macros which will behave much like
+regular commands.  A macro is defined by typing <tt>macro name</tt> or
+<tt>macro create name</tt> followed by the commands.  Arguments to the
+macro are assigned to the variables $1 .. $N and the number of
+arguments is given by $0.  Macros may be defined in <tt>input</tt>
+files.  The following is a sample macro:
+
+<pre>
+macro test
+ echo "this is a macro"
+ echo "number of arguments $0"
+ echo "first argument $1"
+ if ($1 = 10) 
+   echo first argument is 10
+ end
+end
+</pre>
+
+<p>
+Opihi has several types of flow-control features.  These include
+for-loops, while-loops, if-else blocks.  These blocks are defined by
+the corresponding command (<tt>for</tt>, <tt>while</tt>, <tt>if</tt>) and are terminated
+with by a line with the single word <tt>end</tt>.  
+
+<p>
+The for-loop syntax is simplistic.  The <tt>for</tt> command specifies
+the loop variable, the starting value, the ending value, and
+optionally the delta for each loop.  The implicit loop test is always
+to check if the loop variable is still less than the end value (or
+greater than if the delta value is negative).  The definitions of this
+loop syntax and the value of the list length (<tt>$list:n</tt>) and
+the vector length (<tt>vector[]</tt>) make for natural loops over all
+elements of a list or vector.  Below are a few examples:
+
+<pre>
+for i 1 10 0.1
+ echo $i
+end
+</pre>
+This runs the loop with the variable <tt>$i</tt> running from 1.0, 1.1, up to 9.9
+ (inclusive).
+
+<pre>
+for i 0 $list:n
+ echo $list:$i
+end
+</pre>
+This would print all the elements of the list.
+
+<pre>
+for i 0 vector[]
+ echo vector[$i]
+end
+</pre>
+This would print all the elements of the vector.
+
+<p>
+The if-block begins with a line of the form: <tt>if (condition)</tt> and
+ends with a single <tt>end</tt>.  A line with a single <tt>else</tt> specifies the
+optional else portion of the block.  The conditional expression is a
+valid math inequality with approximately C-syntax: 
+
+<pre>
+(($i < 10) && ($i > 4))
+</pre>
+
+The elements of the inequality may also be string comparisons.  The
+only valid string comparisons are <tt>==</tt> and <tt>!=</tt>.  
+
+<p>
+The while loop begins with a line of the form <tt>while (condition)</tt> and
+ends with a single <tt>end</tt>.  The conditions follow the same rules as
+the if conditional statements.
+
+<em>continue, break, auto-break concepts</em>
+
+
+<h3> Miscellaneous Commands </h3>
+
+<pre>
+!                         -- system call
+?                         -- list commands 
+??                        -- list variables 
+echo                      -- type this line 
+exec                      -- system call
+exit                      -- exit program 
+help                      -- get help on a function 
+config                    -- reload configuration information
+exit                      -- exit program 
+quit                      -- exit program 
+wait                      -- wait until return is typed
+sleep                     -- sleep for N seconds
+usleep                    -- sleep for N microseconds
+which                     -- show command 
+cd                        -- change current working directory
+pwd                       -- report current working directory
+date                      -- return the current date
+file                      -- test file existence
+memory                    -- long listing of the allocated memory
+version                   -- list version information
+</pre>
+
+Most of these commands should be clear from the simple descriptions
+above, or from the online help.  The command ?? prints the system
+variables.  The <tt>help</tt> command will provide help on a single
+command or, without any arguments, will list all available help files
+(this includes general help not associated with a specific command).
+
+<h3> String Manipulation and other data commands </h3>
+
+<pre>
+local                     -- define local variables
+output                    -- redirect output to file
+scan                      -- scan line from keyboard or file to variable 
+sprintf                   -- formatted print to a variable
+fprintf                   -- formatted print to standard output
+getchr                    -- find character in string
+strlen                    -- string length
+substr                    -- substring
+</pre>
+
+These commands provide a few tools to manipulate data in opihi
+variables.  The #local/# command specifies that the given variable is
+local to its macro.  The #output/# command changes the default output
+destination for functions which print results to the screen.  This
+function does not zero the file length; new output is appended to the
+file.  The command #scan/# reads specific lines from a file, an
+optionally places them in an opihi variable (EOF is returned at the
+end of a file).  The group of commands #getchr/#, #strlen/#, and
+#substr/# provide the ability to manipulate the elements of a string.
+Finally, #sprintf/# and #fprintf/# perform formatted output to a
+variable and to the screen, respectively.  
+
+<h3> Vectors</h3>
+
+<h4>Vector Manipulation Functions</h4>
+
+<pre>
+create                    -- create a new vector
+hist                      -- create histogram from a vector
+print                     -- write vectors to file
+vectors                   -- list vectors
+accum                     -- accumulate vector values in another vector
+applyfit                  -- apply fit to new vector
+applyfit2d                -- apply 2-d fit to new vector
+circstats                 -- circular statistics
+concat                    -- reduce vector dimension
+datafile                  -- define file to read vectors
+delete                    -- delete vectors or matrices
+fft1d                     -- fft on the pixel-stream in an image
+fit                       -- fit polynomial to vector pair
+gaussdev                  -- generate a gaussian deviate vector
+gaussint                  -- return the integrated gaussian vector
+histogram                 -- generate histogram from vector
+integrate                 -- integrate a vector
+interpolate               -- interpolate between vector pairs
+vectors                   -- list vectors
+medacc                    -- accumulate vector values in another vector
+peak                      -- find vector peak in range
+read                      -- read vectors from datafile
+set                       -- image and vector math
+sort                      -- sort list of vectors
+subset                    -- expand vector dimension
+uniq                      -- create a uniq vector subset from a vector
+vbin                      -- bin values in a vector to be within a range
+vclip                     -- clip values in a vector to be within a range
+select                    -- selective vector assignment
+vgauss         
+vgrid          
+vload                     -- load vectors on Kii
+vstat                     -- get info from imreg database
+vsmooth                   -- gaussian smooth of a vector
+vroll                     -- roll vector elements
+vpop                      -- remove first element
+write                     -- write vectors to datafile
+</pre>
+
+<h4>The Graphing Window (Kapa)</h4>
+
+<pre>
+box                       -- draw a box on the plot
+clear                     -- erase plot
+cursor                    -- get coords from cursor
+grid                      -- plot cartesian grid
+labels                    -- define labels for plot
+limits                    -- define plot limits
+plot                      -- plot a pair of vectors
+ps                        -- define labels for plot
+style                     -- set the style for graph plots
+zplot                     -- plot scaled points 
+device                    -- set / get current graphics device
+jpeg                      -- write text line on graph
+line                      -- plot line
+dot                       -- plot a single point
+resize                    -- set graphics/image window size
+section                   -- define section of graph
+textline                  -- write text line on graph
+zplot                     -- plot x y with size scaled by z
+</pre>
+
+<p>
+Opihi has a variety of commands to manipulate 1-D data (vectors).
+Vectors can be loaded from a data file or created with uniform
+spacing.  New vectors can be defined as the arithmetical combinations
+of other vectors.  For example, we could create a sine wave with the
+following two lines:
+
+<p>
+A vector can be created based on a number sequence with the command
+<tt>create name Nelements start delta</tt>.  The resulting vector has
+#Nelements/# entries, starting at a value of #start/# and running
+until #start + delta*Nelements/#.  If #delta/# is 0.0, all elements
+will have the value of #start/#.  A histogram of a vector may be made
+with the command <tt>hist</tt>, which creates a new vector containing
+the histogram of the first vector.  The data range and bin size of the
+histogram are defined in same way as with create.  This makes it easy
+to create the index vector that goes with a histogram vector:
+
+<pre>
+hist y Ny 1 100 0.1
+create dx 1 100 0.1
+</pre>
+
+<p>
+The above will create a histogram of y in Ny and the index in dx.
+Plotting this with <tt>plot dx Ny</tt> will show the histogram.
+
+<p>
+Vector math is performed with a command of the form <tt>set new =
+  (expression)</tt>.  The expression is some math function employing
+  vectors and scalars.  A complete listing of the math operators
+  available in <tt>set</tt> can be found in the help for <tt>set</tt>.
+
+<p>
+Once vectors are defined, they may be plotted.  A pair of vectors can
+be plotted against each other if they have the same number of entries.
+The plotting is performed on the graphics window, Kapa.  There are
+actually several graphics windows available to <tt>status</tt>, any of
+which may be used to plot at any time.  Some of the more complex
+operations default to either graphics window 0 or 1, depending on the
+context.  Except for those functions with a pre-defined window, all
+plotting functions apply to the current graphics window unless an
+option <tt>-n N</tt> is given to specify a different window.  The
+plotting style is determined by the command <tt>style</tt> which can set
+the line width, the line type (solid, dashed, dotted, etc), the point
+type (box, cross, etc), the point size, the color, and whether a pair
+of vectors is plotted as a sequence of points, a set of connected
+lines, or a histogram.  Some functions which make plots use their own
+styles, as discussed below.  The function <tt>limits</tt> lets the user
+set the range of the plot axes, or check the current setting.  The
+command <tt>plot</tt> will plot a pair of vectors on the current graphics
+window using the current plotting style for that window.  The command
+<tt>zplot</tt> will plot a pair of vectors with the point size scaled by
+a third vector, with maximum and minimum point sizes representing
+specified values.  The <tt>cursor</tt> command goes the other way: this
+command puts the Kapa window in cursor mode and waits for input from
+Kapa.  The user can then type any alphanumeric key on the graphics
+windows and will be told both the pointer location (in the graphics
+coordinates) and will have the coordinates stored in <tt>status</tt>
+variables.  For example, by typing ``1'' in the sky display window,
+the RA and DEC of the pointer are stored in the variables <tt>$R1</tt>
+and <tt>$D1</tt>.  This command can be used to let the user define
+locations or regions of interest on the Kapa window. (Future addition:
+<tt>button</tt>, which does the same with the mouse buttons).  
+
+<pre>
+create x 1 20 0.01
+set y = sin(x)
+</pre>
+
+We can plot this pair of vectors on the Kapa graphing window:
+
+<pre>
+limit x y
+plot x y
+box
+</pre>
+
+The Kapa window has a variety of style options to change the plotting
+type (line, histogram, point), point type, line color, weight and
+style, and the errorbar style (if errorbars are plotted).
+
+<h3> 2D Data and the Image Display Window </h3>
+
+<p>
+Opihi has many commands to manipulate 2-D data (images).  Images can be
+loaded from FITS files and mathematical operations applied to them.
+Various other operations, such as rebinning, shifting, rotating, and
+so forth are also available.  Images can be displayed using the Kii
+image window.  In an 8-bit visual, the image window has a dynamic
+colormap to allow the user to change the relationship between pixel
+value and the displayed color.  There are three colormaps which can be
+selected by pressing the middle three buttons on the bottom row.  The
+PS button produces a PostScript file from the image.  The user can
+change the magnification and the position of the image with the mouse
+(left - recenter at cursor; middle - zoom out; right - zoom in).
+There are four color overlays which the user can draw objects of
+different shapes (circles, boxes, lines) or draw a contour.  The four
+buttons labeled R, G, B, Y turn on or off the display of the red,
+green, blue, and yellow overlays.
+
+<h4>Image Manipulation Functions</h4>
+
+<pre>
+clip                      -- clip values in a buffer to be within a range
+contour                   -- create contour from image
+cut                       -- extract a cut across an image
+extract                   -- extract a portion of a buffer into another buffer
+fft2d                     -- fft on an image
+fit2d                     -- fit 2-d polynomial to vector triplet
+header                    -- print buffer header
+imcut                     -- linear image cut between arbitrary coords
+imhist                    -- histogram of an image region
+imsmooth                  -- circular gaussian smoothing
+kern                      -- convolve with 3x3 kernel
+keyword                   -- extract a FITS keyword from buffer header
+buffers                   -- list the currently allocated buffers
+mcreate                   -- create a matrix
+minterp                   -- interpolate image pixels
+rd                        -- load fits image
+rdseg                     -- read a segment of an image from a file
+rebin                     -- rebin data by factor of N
+roll                      -- roll image to new start point
+rotate                    -- rotate image
+set                       -- image and vector math
+shift                     -- shift data in an image
+spline.apply              -- apply spline fit to generate an image
+spline.const              -- create spline 2nd deriv. terms
+stats                     -- give statistics on a portion of a buffer
+subraster                 -- subraster of fits image
+unsign                    -- toggle the UNSIGN status
+wd                        -- write an image to a file
+zap                       -- delete pixels
+</pre>
+
+<h4>The Image Display Window (Kii)</h4>
+
+<pre>
+ps                        -- define labels for plot
+center                    -- center image on coords
+device                    -- set / get current graphics device
+erase                     -- erase objects on an overlay
+jpeg                      -- write text line on graph
+load                      -- load an SAOimage style overlay
+point                     -- load overlay with single point
+save                      -- save an SAOimage style overlay
+resize                    -- set graphics/image window size
+tv                        -- display an image on the Kii window
+tvcontour                 -- send contour to overlay
+tvgrid                    -- wait until return is typed
+</pre>
+
+
+<h4>Other data functions</h4>
+
+<pre>
+gaussj                    -- solve Ax = B (N-D)
+gridify                   -- convert vector triplet to buffer
+ungridify                 -- convert buffer region to vector triplet
+dimendown                 -- convert matrix to vector
+dimenup                   -- convert vector to matrix
+mget                      -- extract a vector from a matrix
+mset                      -- insert a vector in a matrix
+svd                       -- singular value decomposition of a matrix
+swapbytes                 -- byte swap thing
+</pre>
+
+
+
+<h3> Programming Considerations </h3>
+The programming structure of the Opihi front-end
+makes it very easy to add commands to the package.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/bugzilla.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/bugzilla.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/bugzilla.htm	(revision 16632)
@@ -0,0 +1,11 @@
+<meta name=file  content=bugzilla>
+<meta name=title content=Bugzilla>
+<meta name=page  content=Bugzilla>
+
+<p>
+Ohana bugs and other issues may be reported on the Ohana portion of
+the
+
+<a href="http://kiawe.ifa.hawaii.edu/bugzilla">Elixir Bugzilla</a>
+
+web pages
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/download.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/download.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/download.htm	(revision 16632)
@@ -0,0 +1,31 @@
+<meta name=file  content=download>
+<meta name=title content=Download Ohana>
+<meta name=page  content=download>
+
+<p>
+This page lists Ohana distributions which are available as complete
+tar packages.  There are different distributions representing
+different subsets of the Ohana collection of software.  The Mana
+distribution provides the libraries and components needed to compile
+the <em>mana</em> and <em>dvo</em> programs and their associated
+tools.  The Elixir distribution provides the complete set of Ohana
+tools used by the Elixir system at CFHT.  For <em>dvo</em> or the
+Elixir distribution, you will also need the Elixir configuration
+package.  Other library requirements for the complete Elixir include:
+
+<ul>
+<li> libjpeg 
+<li> libpng
+<li> the readline library
+<li> zlib
+<li> apache
+<li> flips (v.2)
+<li> sextractor
+<li> Xvnc
+</ul>
+
+<ul>
+<li><a href=download/mana-1.0.tgz>mana-1.0.tgz </a>
+<li><a href=download/elixir-ohana-1.2.tgz>elixir-ohana-1.2.tgz </a>
+<li><a href=download/elixir-ohana-head.tgz>elixir-ohana-head.tgz </a>
+<li><a href=download/elixir-config-1.2.tgz>elixir-config-1.2.tgz </a>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/download/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/download/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/download/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+*.html *.tgz
+index.idx
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/install.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/install.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/install.htm	(revision 16632)
@@ -0,0 +1,78 @@
+<meta name=file  content=install>
+<meta name=title content=Installling Ohana>
+<meta name=page  content=install>
+
+<p>
+The Elixir system consists of two main software packages: Ohana (main
+developer Eugene Magnier) and Flips (main developer Jean-Charles
+Cuillandre).  The Elixir system combines these two packages, along
+with other external software products, into a complete system
+providing many utilities and functions for image processing at CFHT
+and elsewhere.  This document describes how to install the Ohana
+portion of the Elixir system.  Ohana may be installed from CVS or from
+a distributed tar ball.  Within the Elixir development community, the
+Ohana source tree may be checked out of the Elixir CVS tree.  Ohana is
+also distributed as a tar ball to users outside of the Elixir
+development community.
+
+<p>
+1) Installing Ohana from source tar ball: <br><br>
+
+  un-gzip and untar:   <br><br>
+
+    <tt> > gunzip -c ohana.tgz | tar xvf - </tt></br></br>
+
+  enter the ohana top-level directory: <br><br>
+
+    <tt> > cd ohana</tt><br><br>
+
+  construct the input Configure file [1]: <br><br>
+
+    <tt> > configure</tt><br><br>
+
+  this step will note the binary installation path.  This should be
+  added to your PATH.  Next, compile the software: <br><br>
+
+    <tt> > make</tt><br><br>
+
+  install the software <br><br>
+
+    <tt> > make install</tt><br><br>
+
+<p>
+2) Installing Ohana from CVS (Developer's version): <br><br>
+
+  check out the ohana source tree: <br><br>
+
+    <tt> > setenv CVSROOT poma:/data/elixir2/srcdir/cvs</tt><br><br>
+    <tt> > cvs co ohana</tt><br><br>
+
+  enter the ohana top-level directory: <br><br>
+
+    <tt> > cd ohana</tt><br><br>
+
+  construct the input Configure file [1]: <br><br>
+
+    <tt> > configure</tt><br><br>
+
+  this step will note the binary installation path.  This should be
+  added to your PATH.  Next, compile the software: <br><br>
+
+    <tt> > make</tt><br><br>
+
+  install the software <br><br>
+
+    <tt> > make install</tt><br><br>
+
+<hr>
+<h3> Notes </h3>
+
+<p>
+[1] Ohana is configured for multiple architecture development, which
+is convenient for end users as well.  The libraries, include files,
+and programs, are all installed in directories with the architecture
+type appended: bin/linux, bin/sol, lib/linux, etc.  To take advantage
+of this multiple architecture organization when compiling, end users
+should arrange for the environment variable ARCH to be set based on
+the machine architecture, and for the PATH to depend on ARCH, rather
+than setting it to a fixed quantity.  
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/kapa.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/kapa.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/kapa.htm	(revision 16632)
@@ -0,0 +1,5 @@
+<meta name=file  content=kapa>
+<meta name=title content=kapa>
+<meta name=page  content=kapa>
+
+Sorry!  The page you requested is not yet available.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/kii.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/kii.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/kii.htm	(revision 16632)
@@ -0,0 +1,5 @@
+<meta name=file  content=kii>
+<meta name=title content=kii>
+<meta name=page  content=kii>
+
+Sorry!  The page you requested is not yet available.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/libfits.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/libfits.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/libfits.htm	(revision 16632)
@@ -0,0 +1,116 @@
+<meta name=file  content=libfits>
+<meta name=title content=libfits>
+<meta name=page  content=libfits>
+
+<h3> FITS-related constants </h3>
+
+<pre>
+# define FT_TEXT_LENGTH          18  /* max length text header field */
+# define FT_MAX_NAXES            10  /* max number of axes */
+# define FT_FIELD_LENGTH          8  /* max length header field */   
+# define FT_COMMENT_LENGTH       47  /* max length comment field */
+# define FT_HISTORY_LENGTH       72  /* max length history / comment */
+# define FT_LINE_LENGTH          80  /* FITS header line length */
+# define FT_RECORD_SIZE        2880  /* FITS block size */
+</pre>
+
+<h3> misc FITS library functions </h3>
+
+<pre>
+char *fits_version ();
+</pre>
+
+<h3> FITS Header Manipulation functions </h3>
+
+<pre>
+int    fits_init_header (Header *header);
+int    fits_create_header (Header *header); 
+int    fits_copy_header (Header *in, Header *out); 
+
+int    fits_read_header (char *filename, Header *header);
+int    fits_write_header (char *filename, Header *header); 
+int    fits_save_header (FILE *f, Header *header);
+int    fits_load_header (FILE *f, Header *header);
+int    fits_fread_header (FILE *f, Header *header);
+void   fits_free_header (Header *header); 
+int    fits_fwrite_header (FILE *f, Header *header); 
+int    fits_read_Xheader (char *filename, Header *header, int N);
+char  *fits_header_field (Header *header, char *field, int N); 
+
+int    fits_modify (Header *header, char *field, char *mode, int N,...); 
+int    fits_print (Header *header, char *field, char *mode, int N,...); 
+int    fits_scan (Header *header, char *field, char *mode, int N,...);
+int    fits_vscan (Header *header, char *field, char *mode, int N, va_list argp);
+int    fits_delete (Header *header, char *field, int N); 
+char  *fits_keyword_end (char *line);
+int    fits_stripwhite (char *string);
+</pre>
+
+<h3> FITS Matrix (Image) Manipulation functions </h3>
+
+<pre>
+int    fits_create_matrix (Header *header, Matrix *); 
+int    fits_copy_matrix (Matrix *in, Matrix *out); 
+
+int    fits_read_matrix (char *filename, Matrix *matrix);      
+int    fits_write_matrix (char *filename, Matrix *matrix); 
+int    fits_fread_matrix (FILE *f, Matrix *matrix, Header *header);
+void   fits_free_matrix (Matrix *matrix); 
+int    fits_fwrite_matrix (FILE *f, Matrix *matrix);      
+int    fits_read_portion (char *filename, Matrix *matrix, int Nskip, int Npix);
+int    fits_read_segment (char *filename, Matrix *matrix, char *region);
+int    fits_load_matrix (FILE *f, Matrix *matrix, Header *header);
+
+int    fits_matrix_size (Header *header);
+int    fits_convert_format (Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int outUnsign);
+void   fits_insert_array (Matrix *matrix, Matrix *array, int x, int y); 
+
+void   fits_set_matrix_value (Matrix *matrix, int x, int y, double); 
+double fits_get_matrix_value (Matrix *, int x, int y); 
+void   fits_add_matrix_value (Matrix *matrix, int x, int y, double value); 
+
+int    fits_divide_matrix (Matrix *numerator, Matrix *denomenator, Matrix *result); 
+int    fits_multiply_matrix (Matrix *matrix1, Matrix *matrix2, Matrix *result); 
+</pre>
+
+<h3> FITS Table Manipulation functions </h3>
+
+<pre>
+int   fits_load_Theader (FILE *f, Header *Theader);
+int   fits_read_Theader (char *filename, Header *header);     
+int   fits_write_Theader (char *filename, Header *header);
+int   fits_read_table (char *filename, FTable *ftable); 
+int   fits_write_table (char *filename, FTable *ftable); 
+int   fits_fwrite_table (FILE *f, FTable *ftable);
+int   fits_fwrite_vtable (FILE *f, VTable *ftable);
+int   fits_fread_ftable (FILE *f, FTable *ftable, char *extname); 
+int   fits_fread_vtable (FILE *f, VTable *ftable, char *extname, int Nrow, int *row);
+int   fits_fread_ftable_data (FILE *f, FTable *ftable);
+int   fits_fwrite_table (FILE *f, FTable *ftable); 
+int   fits_fwrite_vtable (FILE *f, VTable *vtable); 
+int   fits_read_ftable (char *filename, FTable *ftable, char *extname);
+int   fits_create_table_header (Header *header, char *type, char *extname);
+int   fits_create_table (Header *header, FTable *ftable);
+int   fits_free_table (FTable *ftable);
+int   fits_free_vtable (VTable *ftable);
+
+int   fits_bintable_format (char *format, char *type, int *Nval, int *Nbytes);
+int   fits_table_format (char *format, char *type, int *Nval, int *Nbytes);
+int   fits_set_bintable_column (Header *header, FTable *ftable, char *label, void *data, int Nrow);
+int   fits_set_table_column (Header *header, FTable *ftable, char *label, void *data, int Nrow);
+int   fits_define_bintable_column (Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero);
+int   fits_define_table_column (Header *header, char *format, char *label, char *comment, char *unit);
+
+int   fits_vtable_from_ftable (FTable *ftable, VTable *vtable, int *row, int Nrow);
+int   fits_table_to_vtable (FTable *ftable, VTable *vtable, int start, int Nkeep);
+int   fits_vadd_rows (VTable *vtable, char *data, int Nrow, int Nbytes);
+int   fits_add_rows (FTable *ftable, char *data, int Nrow, int Nbytes);
+char *fits_table_print (FTable *ftable,...);
+int   fits_create_Theader (Header *header, char *type);
+int   fits_table_column (FTable *ftable, char *field, char *mode,...); 
+int   fits_table_column (FTable *ftable, char *field, char *mode,...);
+int   fits_get_bintable_column_type (Header *header, char *label, char *type, int *Nval);
+int   fits_get_bintable_column (Header *header, FTable *ftable, char *label, void **data);
+int   fits_get_table_column_type (Header *header, char *label, char *type);
+int   fits_get_table_column (Header *header, FTable *ftable, char *label, void **data);
+</pre>
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/developer/libohana.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/developer/libohana.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/developer/libohana.htm	(revision 16632)
@@ -0,0 +1,278 @@
+<meta name=title content=libohana API reference>
+<meta name=page  content=libohana API reference>
+
+<h2> generic ohana functions </h2>
+
+<h3> basic macros </h3>
+
+<pre>
+TRUE
+FALSE
+SIGN(X)  
+ROUND(X) 
+SQR(X)   
+SQ(X)    
+MIN(X,Y) 
+MAX(X,Y) 
+SWAP(X,Y) 
+whitespace (char c)
+</pre>
+
+<h3> ohana memory management functions </h3>
+
+<pre> 
+ALLOCATE (void *ptr, type, int Nalloc);
+REALLOCATE (void *ptr, type, int Nalloc);
+CHECK_REALLOCATE (void *ptr, type, int Nalloc, int Nused, int Ndelta);
+free (void *ptr); 
+
+void  ohana_memregister (void *ptr);
+void  ohana_memdump (int mode);
+void  ohana_memcheck (int mode);
+</pre>
+
+<h3> string manipulation functions (string.c) </h3>
+
+<pre> 
+int   get_argument (int argc, char **argv, char *arg);
+int   remove_argument (int Narg, int *argc, char **argv);
+char *strcreate (char *string);
+char *strncreate (char *string, int Nbytes);
+int   strnumcmp (char *str1, char *str2);
+int   stripwhite (char *string);
+int   scan_line (FILE *f, char *line);
+int   dparse (double *value, int Nentry, char *line);
+int   fparse (double *value, int Nentry, char *line);
+char *_parse_nextword (char *string);
+</pre>
+
+<pre> int get_argument (int argc, char **argv, char *arg); </pre>
+
+search argv, argc list (starting at argv[1]) for desired argument.
+returns entry number if found, 0 otherwise. 
+<hr>
+
+<pre> int remove_argument (int Narg, int *argc, char **argv); </pre>
+
+remove the given entry Narg from the argv list, adjusting argc
+appropriately. 
+<hr>
+
+<pre> int stripwhite (char *string); </pre>
+
+strip whitespace (space or tab) from start and end of string.
+<hr>
+
+<pre> int strnumcmp (char *str1, char *str2); </pre>
+
+compare str1 and str2 as strings, or as numbers if both are pure
+numeric values (base 10 only).  returns TRUE / FALSE.
+<hr>
+
+<h3> file system functions (findexec.c) </h3>
+
+<pre> 
+char *pathname (char *file);
+char *filerootname (char *file);
+char *fileextname (char *file);
+char *filebasename (char *file);
+char *findexec (int argc, char **argv);
+int   mkdirhier (char *path);
+char *getcwd_cfht (char *path, int size);
+void  make_backup (char *filename);
+int   Fseek (FILE *f, long offset, int whence);
+</pre>
+
+<h3> lockfile functions (glockfile.c) </h3>
+
+<pre> 
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
+int   fclearlockfile (char *filename, FILE *f, int type, int *state);
+</pre>
+
+associated constants:
+
+<pre>
+LCK_SOFT - block writing
+LCK_XCLD - block reading and writing
+LCK_HARD - block reading and writing, persistent
+
+LCK_UNLOCK   - file is unlocked 
+LCK_ACCESS   - can't get access to file 
+LCK_TIMEOUT  - timeout setting lock 
+LCK_HARDLCK  - error setting hard lockfile 
+LCK_HUNLOCK  - error clearing hard lockfile 
+            
+LCK_EMPTY    - locked file is empty 
+LCK_FULL     - locked file is not empty 
+LCK_UNKNOWN  - can't stat file to get size 
+</pre>
+
+<h3> time / radec manipulation functions (time.c) </h3>
+
+<pre>
+int    dms_to_ddd (double *Value, char *string);
+int    str_to_radec (double *ra, double *dec, char *str1, char *str2);
+int    chk_time (char *line);
+int    str_to_time (char *line, time_t *second);
+int    str_to_dtime (char *line, double *second);
+double sec_to_jd (time_t second);
+time_t jd_to_sec (double jd);
+double sec_to_mjd (time_t second);
+time_t mjd_to_sec (double mjd);
+char  *sec_to_date (time_t second);
+time_t date_to_sec (char *date);
+time_t short_date_to_sec (char *date);
+int    hstgsc_hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string);
+</pre>
+
+<h3> functions in config.c </h3>
+
+<pre> 
+char *SelectConfigFile (int *argc, char **argv, char *progname);
+char *LoadConfigFile (char *filename);
+char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...);
+char *expandline (char *line, char *config);
+char *LoadRawConfigFile (char *filename, int options);
+</pre>
+
+<h3> miscellaneous functions </h3>
+
+<pre> char *ohana_version (); </pre>
+
+<h2> DVO data structures and catalog I/O functions </h2>
+
+<h3> read/write (Fread.c) </h3>
+
+<pre> 
+int Fread (char ptr, int size, int nitems, FILE *f, char *type);
+int Fwrite (char ptr, int size, int nitems, FILE *f, char *type);
+int ByteSwap (char *ptr, int size, int nitems, char *type);
+int ConvertStruct (char *buffer, int size, int nitems, char *type);
+</pre>
+
+Several of these functions are used to perform byte-swapping for
+structures in the pre-autocode days.  They should be deprecated and
+dropped, but the autocoding must superceed the hard-wired structure
+first.
+
+<h3> coordinate structure manipulations (coordops.c) </h3>
+
+<pre> 
+int XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
+int RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
+int fXY_to_RD (float *ra, float *dec, float x,  float y,   Coords *coords);
+int fRD_to_XY (float *x,  float *y,   float ra, float dec, Coords *coords);
+int GetCoords (Coords *coords, Header *header);
+int coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
+</pre>
+
+<h3> photcode manipulations (LoadPhotcodes.c) </h3>
+
+<pre>
+int     LoadPhotcodes (char *filename, PhotCodeData *photcodes);
+int     FreePhotcodes (PhotCodeData *photcodes);
+
+PhotCode *GetPhotcodebyName (char *name);
+PhotCode *GetPhotcodeEquivbyName (char *name);
+PhotCode *GetPhotcodebyCode (int code);
+PhotCode *GetPhotcodeEquivbyCode (int code);
+PhotCode *GetPhotcodebyNsec (int Nsec);
+char     *GetPhotcodeNamebyCode (int code);
+
+int     GetPhotcodeCodebyName (char *name);
+int     GetPhotcodeEquivCodebyName (char *name);
+int     GetPhotcodeEquivCodebyCode (int code);
+int     GetPhotcodeNsec (int code);
+int     GetPhotcodeNsecfilt ();
+int      *GetPhotcodeEquivList (int code, int *nlist);
+
+void    SetZeroPoint (double ZP);
+void    ParseColorTerms (char *terms, float *X, int *N);
+
+int       PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);
+short   iPhotColor (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+
+double  PhotInst (Measure *measure);
+double  PhotCat (Measure *measure);
+double  PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+double  PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+double  PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+double  PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+double  PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+double  PhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+double  PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+
+short   iPhotInst (Measure *measure);
+short   iPhotCat (Measure *measure);
+short   iPhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+short   iPhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+short   iPhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+short   iPhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+short   iPhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+short   iPhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+short   iPhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+</pre>
+
+<h3> photometry catalog I/O functions (phot_catalog.c) </h3>
+
+<pre>
+int lock_catalog (Catalog *catalog, int lockmode);
+int unlock_catalog (Catalog *catalog);
+int load_catalog (Catalog *catalog, char mode, int VERBOSE);
+int save_catalog (Catalog *catalog, char VERBOSE);
+</pre>
+
+<h3> DVO format conversions (dvo_convert.c) </h3>
+
+<pre>
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues); 
+Average *FixOldAverage (OldAverage *in, int Nvalues); 
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues); 
+</pre>
+
+<h3> image type / mode lookups (imreg_datatypes.c) </h3>
+
+<pre>
+int   get_image_type (char *name); 
+char *get_type_name (int type); 
+int   get_image_mode (char *name); 
+char *get_mode_name (int mode); 
+</pre>
+
+<h3> mosaic astrometry functions (mosaic_astrom.c) </h3>
+
+<pre>
+int FindMosaicForImage (Image *images, int Nimages, int entry); 
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry); 
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry); 
+int BuildChipMatch (Image *images, int Nimages); 
+</pre>
+
+<h3> FITS DB I/O functions (fits_db.c) </h3>
+
+<pre>
+int fits_db_init (FITS_DB *db); 
+int fits_db_create (FITS_DB *db); 
+int fits_db_lock (FITS_DB *db, char *filename); 
+int fits_db_load (FITS_DB *db); 
+int fits_db_save (FITS_DB *db); 
+int fits_db_update (FITS_DB *db, VTable *vtable); 
+int fits_db_free (FITS_DB *db); 
+int fits_db_close (FITS_DB *db); 
+</pre>
+
+<h3> functions in photfits.c </h3>
+
+<pre>
+short int putMi (double value); 
+double getMi (short int value); 
+void returnMcal (Image *image, double *c); 
+void assignMcal (Image *image, double *c, int order); 
+double applyMcal (Image *image, double x, double y); 
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order); 
+</pre>
+
+These functions manipulate the high-order polynomial fit of magnitude
+offset as a function of image position for the Image structure.
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/download.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/download.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/download.htm	(revision 16632)
@@ -0,0 +1,101 @@
+<meta name=file  content=download>
+<meta name=title content=Download Ohana>
+<meta name=page  content=download>
+
+<p>
+This page lists Ohana packages which are available as complete
+tarballs.  There are different packages representing different subsets
+of the Ohana collection of software.  To install these, simply run
+configure, make, and make install (see <a href="install.html">the
+installation instructions</a> for further details).  Also list on this
+page are the Elixir configuration tarballs, which provide information
+needed by some of the Elixir programs.
+
+<p>
+The following external libraries are needed for Ohana.
+
+<ul>
+<li> libjpeg 
+<li> libpng
+<li> the readline library
+<li> zlib
+</ul>
+
+<h4> Mana Distributions </h4> 
+
+The Mana distribution provides the libraries and components needed to
+compile <tt>mana</tt>, an data and image analysis tool, and the
+associated display tools, <tt>Kapa</tt> and <tt>Kii</tt>.  
+
+<ul>
+<li><a href=download/tarballs/mana-1.1.tgz>mana-1.1.tgz </a>
+<li><a href=download/tarballs/mana-1.0.tgz>mana-1.0.tgz </a>
+</ul>
+
+<h4> Elixir-Ohana Distributions </h4> 
+
+The Elixir-Ohana distribution provides the complete set of Ohana
+software used by the Elixir system at CFHT.  To use the Elixir system,
+you will also need the Elixir configuration package.
+
+<ul>
+<li><a href=download/tarballs/elixir-ohana-head.tgz>elixir-ohana-head.tgz </a>
+<li><a href=download/tarballs/elixir-ohana-1.6.tgz>elixir-ohana-1.6.tgz </a>
+<li><a href=download/tarballs/elixir-ohana-1.5.tgz>elixir-ohana-1.5.tgz </a>
+<li><a href=download/tarballs/elixir-ohana-1.4.tgz>elixir-ohana-1.4.tgz </a>
+<li><a href=download/tarballs/elixir-ohana-1.3.tgz>elixir-ohana-1.3.tgz </a>
+<li><a href=download/tarballs/elixir-ohana-1.2.tgz>elixir-ohana-1.2.tgz </a>
+<li><a href=download/tarballs/elixir-ohana-1.1.tgz>elixir-ohana-1.1.tgz </a>
+<li><a href=download/tarballs/elixir-ohana-1.0.tgz>elixir-ohana-1.0.tgz </a>
+</ul>
+
+<p>
+Other library requirements for the complete Elixir system include:
+<ul>
+<li> apache
+<li> flips (v.2)
+<li> sextractor
+<li> Xvnc
+</ul>
+
+<h4> Opihi Distributions </h4> 
+
+The Opihi distribution provides all of the opihi programs (<tt>mana</tt>,
+<tt>dvo</tt>, <tt>psched</tt>, <tt>pcontrol</tt>, and <tt>pclient</tt>) and the supporting
+programs <tt>Kapa</tt> and <tt>Kii</tt>.
+
+<ul>
+<li><a href=download/tarballs/opihi-2.3.tgz>opihi-2.3.tgz </a>
+</ul>
+
+<h4> Psched Distributions </h4> 
+
+The Psched distribution provides the related programs <tt>psched</tt>,
+<tt>pcontrol</tt>, and <tt>pclient</tt>.  These programs are used for the
+Pan-STARRS IPP scheduling and parallel-processing system.
+
+<ul>
+<li><a href=download/tarballs/psched-0.1.tgz>psched-0.1.tgz </a>
+</ul>
+
+<h4> Ohana Tools Distributions </h4> 
+
+The Ohana Tools distribution provides the various useful tools from
+the Ohana system, including FITS-file manipulation program, precession
+/ coordinate coversions, and the <tt>gcompare</tt> tool.  
+
+<ul>
+<li><a href=download/tarballs/ohana-tools-1.0.tgz>ohana-tools-1.0.tgz </a>
+</ul>
+
+<h4> Elixir Configuration Distributions </h4> 
+
+The Elixir Configuratin distribution provides the configuration files
+needed by several of the Ohana Elixir program.
+
+<ul>
+<li><a href=download/tarballs/elixir-config-1.2.tgz>elixir-config-1.2.tgz </a>
+<li><a href=download/tarballs/elixir-config-1.1.tgz>elixir-config-1.1.tgz </a>
+<li><a href=download/tarballs/elixir-config-1.0.tgz>elixir-config-1.0.tgz </a>
+</ul>
+
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/icons/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/icons/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/icons/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+.xvpics
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/index.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/index.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/index.htm	(revision 16632)
@@ -0,0 +1,60 @@
+<meta name=file  content=home>
+<meta name=title content=Ohana User's Guide>
+<meta name=page  content=Ohana>
+
+<p>
+Ohana is the collection of programs written by Eugene Magnier which
+form a major portion of the Elixir software.  These pages document the
+user interface to the various Ohana programs.
+
+<p>
+Within the Ohana software system, there are several types of programs
+and program groups.  There are basic, independent C programs, groups
+of related C programs which address a common Elixir system, C programs
+which run as daemons, and C programs which provide an interactive
+command language environment.  There are also a number of perl, csh,
+and tcl scripts.  
+
+<h4> Software Organization</h4>
+
+The top-level of the Ohana software tree includes the Makefile, a
+system-dependent configuration file, and the directories src, bin,
+lib, and include.  Within the bin, lib, and include directories, there
+are subdirectories by computer architecture.  These allow a
+segregation of the architecture dependent binary files, and provide
+some flexibility for working will various types of hardware.  The
+Makefiles require the environment variable ARCH to be set to make
+complilation choices and to place the binaries in their appropriate
+locations.  The ohana user may choose to include this directory in
+their path, in which case they should define the variable in their
+resource files (.cshrc / .bashrc / etc) using the sample given in
+getarch, and set the pathname to the value ohana/bin/$ARCH, which will
+then correctly expand depending on what machine the user is one. An
+alternative is to treat the ohana tree as the program development
+tree, and to export the binaries to an architecture-dependent external
+location. 
+
+<p>
+The src directory contains all of the program and library source-code
+subdirectories.  Many of the programs are contained within their own
+unique src subdirectory, but there are a few execeptions.  First, the
+perl, csh, and tcl scripts are collected together in perl, csh, and
+tcl subdirectories.  Second, there are a variety of simple, small
+C-programs in the directory misc.  Third, there is a collection of
+related C programs which provide user interfaces to the Elixir
+databases.  These are collected together in the imregister-3.0
+subdirectory.
+
+<p>
+Each of the program and library subdirectories contain their own src,
+bin, and include directories.  When the programs are compiled, the C
+files in src are compiled to .o files with names which include the
+$ARCH value: src/foo.c -> src/foo.linux.o.  The output executable is
+written to the bin directory with a name which also includes the
+binary: bin/foo.linux.  These are then installed in the appropriate
+ohana/bin/ARCH directories with 'make install'.  In the case of the
+program directories which include multiple C programs, the make file
+takes commands of the form 'make program', 'make program.install',
+'make program.clean', etc, which perform the requested operation on
+the specific program.  The generic commands 'make' and 'make install'
+will operate on the complete collection of programs.
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/install.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/install.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/install.txt	(revision 16632)
@@ -0,0 +1,74 @@
+
+The Elixir system consists of two main software packages: Ohana (main
+developer Eugene Magnier) and Flips (main developer Jean-Charles
+Cuillandre).  The Elixir system combines these two packages, along
+with other external software products, into a complete system
+providing many utilities and functions for image processing at CFHT
+and elsewhere.  This document describes how to install the Ohana
+portion of the Elixir system.  Ohana may be installed from CVS or from
+a distributed tar ball.  Within the Elixir development community, the
+Ohana source tree may be checked out of the Elixir CVS tree.  Ohana is
+also distributed as a tar ball to users outside of the Elixir
+development community.
+
+1) Installing Ohana from source tar ball:
+
+  un-gzip and untar:  
+
+    > gunzip -c ohana.tgz | tar xvf -
+
+  enter the ohana top-level directory:
+
+    > cd ohana
+
+  construct the input Configure file [1]:
+
+    > configure
+
+  this step will note the binary installation path.  This should be
+  added to your PATH
+
+  compile the software
+
+    > make
+
+  install the software
+
+    > make install
+
+2) Installing Ohana from CVS (Developer's version):
+
+  check out the ohana source tree:
+
+    > setenv CVSROOT poma:/data/elixir2/srcdir/cvs
+    > cvs co ohana
+
+  enter the ohana top-level directory:
+
+    > cd ohana
+
+  construct the input Configure file [1]:
+
+    > configure
+
+  this step will note the binary installation path.  This should be
+  added to your PATH
+
+  compile the software
+
+    > make
+
+  install the software
+
+    > make install
+
+***** Notes *****
+
+[1] Ohana is configured for multiple architecture development, which
+is convenient for end users as well.  The libraries, include files,
+and programs, are all installed in directories with the architecture
+type appended: bin/linux, bin/sol, lib/linux, etc.  To take advantage
+of this multiple architecture organization when compiling, end users
+should arrange for the environment variable ARCH to be set based on
+the machine architecture, and for the PATH to depend on ARCH, rather
+than setting it to a fixed quantity.  
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/sequence.idx
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/sequence.idx	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/sequence.idx	(revision 16632)
@@ -0,0 +1,10 @@
+Elixir-System
+Elixir-Tools
+Elixir-DB
+Opihi-Programs
+IPP-subsystems
+DVO
+developer
+download.htm
+bugzilla.htm
+install.txt
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/template.css
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/template.css	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/template.css	(revision 16632)
@@ -0,0 +1,75 @@
+
+/* heading styles */
+H1   		{ color: #000000; font-size: xx-large; }
+H2		{ color: #000000; font-size: x-large;  }
+H3		{ color: #000000; font-size: large;    }
+H4		{ color: #000000; font-size: normal;   }
+H5		{ color: #000000; font-size: small;    }
+
+span.title      { font-size: 200% }
+span.line       { color: #ff0000 }
+
+/* document-specific styles come next */
+
+a:link, a:visited, a:active { text-decoration: underline; font-weight: bold; color: #000080 }
+
+body  { bgcolor: #e0d8f0; background-color: #e0d8f0; padding: 0px; margin: 0px }
+table.outline { 
+	text-align: left; 
+	font-size: small; 
+	font-weight: normal; 
+	background: #5c0ca8; 
+	border: 2px solid #5c0ca8; 
+	padding: 0px; 
+}
+
+table.toparea { border-width: 0px}
+
+a.menutop  { text-decoration: none; color: #ffffff; font-weight: bold }
+a.menulink { text-decoration: none; font-weight: normal; color: #000000}
+a.menusele { text-decoration: none; font-weight: normal; color: #ff0000}
+
+td.menutop  { text-align: left; background: #000000; font-size: small; color: #ffffff; padding: 2px; }
+td.menulink { text-align: left; background: #ffffff; font-size: small; color: #000000; padding: 2px; font-weight: normal; text-indent: 8px; }
+td.menumiss { text-align: left; background: #e0e0e0; font-size: small; color: #000000; padding: 2px; text-indent: 8px; }
+td.menusel  { text-align: left; background: #00ffff; font-size: small; color: #ff0000; padding: 2px; font-weight: normal; text-indent: 8px; }
+
+a.ln { text-decoration: none; font-weight: normal; color: #000000}
+a.dl { text-decoration: none; font-weight: normal; color: #000000}
+a.sl { text-decoration: none; font-weight: normal; color: #ff0000}
+
+td.dir0 { background: #c0b0b0; color: #000000; padding: 2px; text-indent: 0px;  }
+td.dir1 { background: #d0c0c0; color: #000000; padding: 2px; text-indent: 8px;  }
+td.dir2 { background: #e0d0d0; color: #000000; padding: 2px; text-indent: 16px; }
+td.dir3 { background: #f0e0e0; color: #000000; padding: 2px; text-indent: 24px; }
+
+td.dsl0 { background: #c0b0b0; color: #ff0000; padding: 2px; text-indent: 0px;  }
+td.dsl1 { background: #d0c0c0; color: #ff0000; padding: 2px; text-indent: 8px;  }
+td.dsl2 { background: #e0d0d0; color: #ff0000; padding: 2px; text-indent: 16px; }
+td.dsl3 { background: #f0e0e0; color: #ff0000; padding: 2px; text-indent: 24px; }
+
+td.doc0 { background: #a090f0; color: #000000; padding: 2px; text-indent: 0px;  }
+td.doc1 { background: #b0a0f0; color: #000000; padding: 2px; text-indent: 8px;  }
+td.doc2 { background: #c0b0f0; color: #000000; padding: 2px; text-indent: 16px; }
+td.doc3 { background: #d0c0f0; color: #000000; padding: 2px; text-indent: 24px; }
+
+td.sel0 { background: #a090f0; color: #ff0000; padding: 2px; text-indent: 0px;  }
+td.sel1 { background: #b0a0f0; color: #ff0000; padding: 2px; text-indent: 8px;  }
+td.sel2 { background: #c0b0f0; color: #ff0000; padding: 2px; text-indent: 16px; }
+td.sel3 { background: #d0c0f0; color: #ff0000; padding: 2px; text-indent: 24px; }
+
+td.title { background-color: #ffffff; padding: 5px; font-size: x-large; text-align: left; vertical-align: top}
+td.body  { background-color: #ffffff; padding: 5px; font-size: normal;  text-align: left; vertical-align: top }
+
+a.submenu { text-decoration: underline; font-weight: bold; color: #ffffff}
+a.sublist { text-decoration: none; font-weight: bold; color: #0000ff}
+a.subplot { text-decoration: underline; font-weight: bold; color: #000000}
+
+td.subtitle  { background: #a02020; font-size: large; font-weight: bold; color: #ffffff; padding: 2px }
+td.submenu   { background: #000000; text-align: center; font-size: small; font-weight: bold; color: #ffffff; padding: 2px }
+td.subsel    { background: #b0b0b0; text-align: center; font-size: small; font-weight: bold; color: #000000; padding: 2px }
+
+table.pretty    { background: #ffffff; border: 1px solid #000000; padding: 0px; cellspacing: 0px; }
+table.pretty td { border: 1px solid #000000; padding: 3px; text-align: left}
+table.pretty th { border: 1px solid #000000; padding: 3px; text-align: left}
+table.pretty caption { font-weight: bold; }
Index: /branches/eam_branch_20080223/Ohana/doc/www/html/template.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/html/template.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/html/template.htm	(revision 16632)
@@ -0,0 +1,42 @@
+<html>
+<head>
+<title>
+<meta name=page>
+</title>
+</head>
+
+<link rel="STYLESHEET" HREF="ROOT/template.css">
+<!-- link rel="STYLESHEET" HREF="template.css" -->
+
+<body>
+
+<table class=toparea cellspacing=10><tr><td valign=top>
+<!-- Index -->
+<table width=188px class=outline cellspacing=0>
+<tr><td><a href=ROOT>
+<IMG border=0 width=188px SRC="ROOT/icons/logo-pw.png"></a></td></tr>
+<tr><td class=menutop>  <a class=menutop href=ROOT> Ohana Home </a></td></tr>
+<tr><td class=menutop>  <a class=menutop href=ROOT/..> Elixir Home </a></td></tr>
+<tr><td class=menutop>  <a class=menutop href=/> CFHT Home </a></td></tr>
+
+<meta name=index file=index.idx>
+
+</table> <br>
+
+</td><td width=100% valign=top> 
+
+<!-- Main Content -->
+<table width=100% class=outline>
+<tr><td class=title>
+<meta name=title>
+</td></tr>
+
+<!-- Body of Content -->
+<tr><td class=body>
+<meta name=body>
+</td></tr>
+</table>
+
+</td></tr></table>
+</body>
+</html>
Index: /branches/eam_branch_20080223/Ohana/doc/www/ohana.css
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/ohana.css	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/ohana.css	(revision 16632)
@@ -0,0 +1,44 @@
+
+/* heading styles */
+H1   		{ color: #000000; font-size: xx-large; }
+H2		{ color: #000000; font-size: x-large;  }
+H3		{ color: #000000; font-size: large;    }
+H4		{ color: #000000; font-size: normal;   }
+H5		{ color: #000000; font-size: small;    }
+
+span.title      { font-size: 200% }
+span.line       { color: #ff0000 }
+
+/* document-specific styles come next */
+
+a:link, a:visited, a:active { text-decoration: underline; font-weight: bold; color: #000080 }
+
+body  { bgcolor: #20d0e0; background-color: #20d0e0; padding: 0px; margin: 0px }
+table.outline { background: #ffffff; border: 5px solid #0850c0; padding: 0px; }
+
+table.toparea { border-width: 0px}
+
+a.menutop  { text-decoration: none; color: #ffffff; font-weight: bold }
+a.menulink { text-decoration: none; font-weight: normal; color: #000000}
+
+td.menutop  { text-align: left; background: #000000; font-size: small; color: #ffffff; padding: 2px; }
+td.menuhead { text-align: left; background: #b0b0b0; font-size: small; color: #000080; padding: 2px; font-weight: bold; }
+td.menulink { text-align: left; background: #ffffff; font-size: small; color: #000000; padding: 2px; font-weight: normal; text-indent: 8px; }
+td.menumiss { text-align: left; background: #e0e0e0; font-size: small; color: #000000; padding: 2px; text-indent: 8px; }
+td.menusel  { text-align: left; background: #ffffff; font-size: small; color: #ff0000; padding: 2px; font-weight: normal; text-indent: 8px; }
+
+td.title { background-color: #ffffff; padding: 5px; font-size: x-large; text-align: left; vertical-align: top}
+td.body  { background-color: #ffffff; padding: 5px; font-size: normal;  text-align: left; vertical-align: top }
+
+a.submenu { text-decoration: underline; font-weight: bold; color: #ffffff}
+a.sublist { text-decoration: none; font-weight: bold; color: #0000ff}
+a.subplot { text-decoration: underline; font-weight: bold; color: #000000}
+
+td.subtitle  { background: #0754ba; font-size: large; font-weight: bold; color: #ffffff; padding: 2px }
+td.submenu   { background: #000000; text-align: center; font-size: small; font-weight: bold; color: #ffffff; padding: 2px }
+td.subsel    { background: #b0b0b0; text-align: center; font-size: small; font-weight: bold; color: #000000; padding: 2px }
+
+table.pretty    { background: #ffffff; border: 1px solid #0000ff; padding: 0px; cellspacing: 0px; }
+table.pretty td { border: 1px solid #0000ff; padding: 3px; text-align: left}
+table.pretty th { border: 1px solid #0000ff; padding: 3px; text-align: left}
+table.pretty caption { font-weight: bold; }
Index: /branches/eam_branch_20080223/Ohana/doc/www/ohana.src
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/ohana.src	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/ohana.src	(revision 16632)
@@ -0,0 +1,72 @@
+<html>
+<head> 
+<!-- Page Title -->
+</head>
+<link rel="STYLESHEET" HREF="$HREF/ohana.css">
+<body>
+
+<table class=toparea cellspacing=10><tr><td valign=top>
+
+<!-- Elixir Selection Menu Begin -->
+<table width=188px class=outline cellspacing=0>
+<tr><td><a href=$HREF/home.html><IMG border=0 width=188px SRC="$HREF/icons/logo.png"></a></td></tr>
+<tr><td class=menutop>  <a class=menutop href=$HREF/home.html> Ohana Home                                         </a></td></tr>
+<tr><td class=menutop>  <a class=menutop href=$HREF/..> Elixir Home                                               </a></td></tr>
+<tr><td class=menutop>  <a class=menutop href=/> CFHT Home                                                        </a></td></tr>
+
+<tr><td class=menuhead> User's Guides                                                                                 </td></tr>
+<tr><td class=menuhead> Top-Level Systems                                                                             </td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/opihi.html>                        Opihi shell               </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/dvo.html>                          DVO examples              </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/mana.html>                         Mana command              </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/dvo-cmds.html>                     DVO commands              </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/dimm.html>                         DIMM commands             </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/mkdetrend.html>                    mkdetrend                 </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/mkfringe.html>                     mkfringe                  </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/gcontrol.html>                     gcontrol (elixir)         </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/nightd.html>                       nightd                    </a></td></tr>
+
+<tr><td class=menuhead> Components                                                                                    </td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/imreg.html>                        imreg                     </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/detrend.html>                      detrend                   </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/imclean.html>                      imclean                   </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/gastro.html>                       gastro                    </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/gcompare.html>                     gcompare                  </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/photcode.html>                     photcode                  </a></td></tr>
+
+<tr><td class=menuhead> Perl Scripts                                                                                  </td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/mkdetrend.html>                    mkdetrend components      </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/mkfringe.html>                     mkfringe components       </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/postrun.html>                      elixir.postrun            </a></td></tr>
+
+<tr><td class=menuhead> Programmer's Reference                                                                        </td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/install.html>                      installing                </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/download.html>                     download                  </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/kapa.html>                         kapa                      </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/kii.html>                          kii                       </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/includes.html>                     include                   </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/libfits.html>                      libfits                   </a></td></tr>
+<tr><td class=menulink> <a class=menulink href=$HREF/libohana.html>                     libohana                  </a></td></tr>
+
+<tr><td></td></tr>
+</table>
+<!-- Elixir Selection Menu End -->
+
+</td><td width=100% valign=top> 
+
+<!-- Main Content -->
+<table width=100% class=outline>
+<tr><td class=title>
+<!-- Title --> 
+</td></tr>
+
+<tr><td class=body>
+<!-- Body Begin -->
+
+<!-- Body End -->
+</td></tr>
+</table>
+
+</td></tr></table>
+</body>
+</html>
Index: /branches/eam_branch_20080223/Ohana/doc/www/sample.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/doc/www/sample.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/doc/www/sample.htm	(revision 16632)
@@ -0,0 +1,18 @@
+<meta name=file  content=home>
+<meta name=title content=The Elixir System>
+<meta name=page  content=Elixir>
+
+<p>
+The Elixir Project at CFHT has the goal of enabling the optimal use of
+data by our observers.  The current target of the Elixir project is
+data from large mosaic cameras.  We call the project `Elixir' after
+the fabled goal of the ancient alchemists: the Elixir which could
+restore youth or turn lead into gold.  The Elixir project seeks to
+restore youth to archived data and turn weighty mass of unmined data
+collected at CFHT into nuggets of gold.
+
+<p>
+Elixir is not a single program or package; rather it is a collection
+of programs, databases, and other tools related to the processing and
+evaluation of the telescope data.  This document provides a starting
+point for a variety of documentation related to the Elixir project.
Index: /branches/eam_branch_20080223/Ohana/ohana-config.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/ohana-config.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/ohana-config.in	(revision 16632)
@@ -0,0 +1,25 @@
+#!/bin/csh -f
+
+if ($#argv != 1) then
+  echo "USAGE: ohana-config [option]"
+  echo "valid options:"
+  echo " --libs"
+  echo " --cflags"
+  echo " --prefix"
+  exit 2
+endif
+
+switch ($1) 
+  case "--libs":
+    echo "-L@LIBDIR@ -lkapa -ldvo -lFITS -lohana"
+    shift
+    breaksw
+  case "--cflags":
+    echo "-I@INCDIR@"
+    shift
+    breaksw
+  default:
+    echo "unknown option $1"
+    exit 2
+endsw
+ 
Index: /branches/eam_branch_20080223/Ohana/src/absphot/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/absphot/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/absphot/doc/notes.txt	(revision 16632)
@@ -0,0 +1,17 @@
+
+absphot
+
+  we have relphot to determine the relative photometry on small spatial scales
+  we have uniphot to determine the zero point trend with time.
+  the result of these two should be a single, consistent photometry system in the internal filter system
+
+  the goal of absphot is to determine the relationships between the
+  internal magnitude system and an external reference
+
+usage:
+
+  absphot -target (photcode) -ref (photcode) [-region RA RA DEC DEC]
+
+  - determine the fit M_ref = M_target + \Sum_i A_i * color^i
+
+    
Index: /branches/eam_branch_20080223/Ohana/src/absphot/src/absphot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/absphot/src/absphot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/absphot/src/absphot.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "relphot.h"
+
+int main (int argc, char **argv) {
+
+  // select the list of database region files, based on region
+  // loop over the catalogs, load the magnitudes in the selected bands
+  // determine the fit
+
+  int i, status, Ncatalog;
+  Catalog *catalog;
+  FITS_DB db;
+
+  SkyList *skylist = NULL;
+
+  /* get configuration info, args */
+  initialize (argc, argv);
+
+  /* register database handle with shutdown procedure */
+  set_db (&db);
+  db.mode   = dvo_catalog_catmode (CATMODE);
+  db.format = dvo_catalog_catformat (CATFORMAT);
+
+  /* load regions based on specified sky patch */
+  skylist = load_regions (&db, &UserPatch, UserPatchSelect);
+
+  /* load catalog data from region files */
+  catalog = load_catalogs (skylist, &Ncatalog);
+  
+  fitTrends (catalog);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+bin
Index: /branches/eam_branch_20080223/Ohana/src/addstar/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/Makefile	(revision 16632)
@@ -0,0 +1,244 @@
+default: addstar
+help:
+	@echo "make options: addstar (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/addstar
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+addstar     : $(BIN)/addstar.$(ARCH)
+addstard    : $(BIN)/addstard.$(ARCH)
+addstart    : $(BIN)/addstart.$(ARCH)
+addstarc    : $(BIN)/addstarc.$(ARCH)
+mkacc-2mass : $(BIN)/mkacc-2mass.$(ARCH)
+sedstar     : $(BIN)/sedstar.$(ARCH)
+load2mass   : $(BIN)/load2mass.$(ARCH)
+gztest      : $(BIN)/gztest.$(ARCH)
+
+all: addstar addstarc addstard addstart sedstar load2mass skycells
+
+ADDSTAR = \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SkyListForStars.$(ARCH).o \
+$(SRC)/SkyRegionUtils.$(ARCH).o \
+$(SRC)/SkyTableFromTychoIndex.$(ARCH).o \
+$(SRC)/addstar.$(ARCH).o \
+$(SRC)/airmass.$(ARCH).o \
+$(SRC)/args.$(ARCH).o \
+$(SRC)/build_links.$(ARCH).o \
+$(SRC)/calibrate.$(ARCH).o \
+$(SRC)/dump.$(ARCH).o \
+$(SRC)/edge_check.$(ARCH).o \
+$(SRC)/fakeimage.$(ARCH).o \
+$(SRC)/find_matches.$(ARCH).o \
+$(SRC)/find_matches_closest.$(ARCH).o \
+$(SRC)/find_matches_refstars.$(ARCH).o \
+$(SRC)/find_subset.$(ARCH).o \
+$(SRC)/get2mass.$(ARCH).o \
+$(SRC)/get2mass_as.$(ARCH).o \
+$(SRC)/get2mass_as_raw.$(ARCH).o \
+$(SRC)/get2mass_dr2.$(ARCH).o \
+$(SRC)/get2mass_ops.$(ARCH).o \
+$(SRC)/getgsc.$(ARCH).o \
+$(SRC)/gettycho.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/getusnob.$(ARCH).o \
+$(SRC)/greference.$(ARCH).o \
+$(SRC)/grefstars.$(ARCH).o \
+$(SRC)/LoadStars.$(ARCH).o \
+$(SRC)/in_image.$(ARCH).o \
+$(SRC)/load_subpix.$(ARCH).o \
+$(SRC)/opening_angle.$(ARCH).o \
+$(SRC)/parse_time.$(ARCH).o \
+$(SRC)/replace_match.$(ARCH).o \
+$(SRC)/resort_catalog.$(ARCH).o \
+$(SRC)/ReadStarsFITS.$(ARCH).o \
+$(SRC)/ReadStarsTEXT.$(ARCH).o \
+$(SRC)/FilterStars.$(ARCH).o \
+$(SRC)/ImageOptions.$(ARCH).o \
+$(SRC)/GetFileMode.$(ARCH).o \
+$(SRC)/ReadImageHeader.$(ARCH).o \
+$(SRC)/update_coords.$(ARCH).o
+
+ADDSTARD = \
+$(SRC)/CheckPassword.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/NewImage.$(ARCH).o \
+$(SRC)/NewRefcat.$(ARCH).o \
+$(SRC)/NewReflist.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SkyListForStars.$(ARCH).o \
+$(SRC)/SkyRegionUtils.$(ARCH).o \
+$(SRC)/SkyTableFromTychoIndex.$(ARCH).o \
+$(SRC)/SocketOps.$(ARCH).o \
+$(SRC)/UpdateDatabase_Image.$(ARCH).o \
+$(SRC)/UpdateDatabase_Refcat.$(ARCH).o \
+$(SRC)/UpdateDatabase_Reflist.$(ARCH).o \
+$(SRC)/addstard.$(ARCH).o \
+$(SRC)/airmass.$(ARCH).o \
+$(SRC)/args_server.$(ARCH).o \
+$(SRC)/build_links.$(ARCH).o \
+$(SRC)/calibrate.$(ARCH).o \
+$(SRC)/edge_check.$(ARCH).o \
+$(SRC)/find_matches.$(ARCH).o \
+$(SRC)/find_matches_closest.$(ARCH).o \
+$(SRC)/find_matches_refstars.$(ARCH).o \
+$(SRC)/find_subset.$(ARCH).o \
+$(SRC)/get2mass.$(ARCH).o \
+$(SRC)/get2mass_as.$(ARCH).o \
+$(SRC)/get2mass_as_raw.$(ARCH).o \
+$(SRC)/get2mass_dr2.$(ARCH).o \
+$(SRC)/get2mass_ops.$(ARCH).o \
+$(SRC)/getgsc.$(ARCH).o \
+$(SRC)/gettycho.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/getusnob.$(ARCH).o \
+$(SRC)/ImageOptions.$(ARCH).o \
+$(SRC)/greference.$(ARCH).o \
+$(SRC)/in_image.$(ARCH).o \
+$(SRC)/load_subpix.$(ARCH).o \
+$(SRC)/opening_angle.$(ARCH).o \
+$(SRC)/replace_match.$(ARCH).o \
+$(SRC)/update_coords.$(ARCH).o
+
+ADDSTART = \
+$(SRC)/addstart.$(ARCH).o \
+$(SRC)/ImageOptions.$(ARCH).o \
+$(SRC)/DatasetOps.$(ARCH).o \
+$(SRC)/SocketOps.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/args_server.$(ARCH).o \
+$(SRC)/CheckPassword.$(ARCH).o \
+$(SRC)/UpdateDatabase_Image.$(ARCH).o \
+$(SRC)/UpdateDatabase_Reflist.$(ARCH).o \
+$(SRC)/UpdateDatabase_Refcat.$(ARCH).o \
+$(SRC)/airmass.$(ARCH).o \
+$(SRC)/build_links.$(ARCH).o \
+$(SRC)/calibrate.$(ARCH).o \
+$(SRC)/find_matches.$(ARCH).o \
+$(SRC)/find_matches_closest.$(ARCH).o \
+$(SRC)/find_matches_refstars.$(ARCH).o \
+$(SRC)/find_subset.$(ARCH).o \
+$(SRC)/get2mass.$(ARCH).o \
+$(SRC)/get2mass_as.$(ARCH).o \
+$(SRC)/get2mass_as_raw.$(ARCH).o \
+$(SRC)/get2mass_dr2.$(ARCH).o \
+$(SRC)/get2mass_ops.$(ARCH).o \
+$(SRC)/getgsc.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/getusnob.$(ARCH).o \
+$(SRC)/gettycho.$(ARCH).o \
+$(SRC)/greference.$(ARCH).o \
+$(SRC)/in_image.$(ARCH).o \
+$(SRC)/load_subpix.$(ARCH).o \
+$(SRC)/replace_match.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/SkyRegionUtils.$(ARCH).o \
+$(SRC)/SkyListForStars.$(ARCH).o \
+$(SRC)/update_coords.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/edge_check.$(ARCH).o \
+$(SRC)/opening_angle.$(ARCH).o \
+$(SRC)/SkyTableFromTychoIndex.$(ARCH).o \
+$(SRC)/ListenClients_Thread.$(ARCH).o \
+$(SRC)/NewImage_Thread.$(ARCH).o \
+$(SRC)/NewReflist_Thread.$(ARCH).o \
+$(SRC)/NewRefcat_Thread.$(ARCH).o 
+
+ADDSTARC = \
+$(SRC)/addstarc.$(ARCH).o \
+$(SRC)/airmass.$(ARCH).o \
+$(SRC)/SocketOps.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/LoadStars.$(ARCH).o \
+$(SRC)/grefstars.$(ARCH).o \
+$(SRC)/load_subpix.$(ARCH).o \
+$(SRC)/parse_time.$(ARCH).o \
+$(SRC)/ReadStarsFITS.$(ARCH).o \
+$(SRC)/GetFileMode.$(ARCH).o \
+$(SRC)/ReadImageHeader.$(ARCH).o \
+$(SRC)/ReadStarsTEXT.$(ARCH).o \
+$(SRC)/FilterStars.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/args_client.$(ARCH).o
+
+### this program may need to be repaired (EAM 2006.08)
+MKACC-2MASS = \
+$(SRC)/mkacc-2mass.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/get2mass_as.$(ARCH).o
+
+LOAD-2MASS = \
+$(SRC)/load2mass.$(ARCH).o \
+$(SRC)/load2mass_as_rawdata.$(ARCH).o \
+$(SRC)/load2mass_catalog.$(ARCH).o \
+$(SRC)/get2mass_ops.$(ARCH).o \
+$(SRC)/find_matches_refstars.$(ARCH).o \
+$(SRC)/args_load2mass.$(ARCH).o \
+$(SRC)/replace_match.$(ARCH).o \
+$(SRC)/update_coords.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o
+
+SEDSTAR = \
+$(SRC)/sedstar.$(ARCH).o \
+$(SRC)/SEDtableLoad.$(ARCH).o \
+$(SRC)/SEDfit.$(ARCH).o \
+$(SRC)/SEDops.$(ARCH).o \
+$(SRC)/args_sedstar.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o
+
+SKYCELLS = \
+$(SRC)/skycells.$(ARCH).o \
+$(SRC)/args_skycells.$(ARCH).o \
+$(SRC)/ConfigInit_skycells.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/sky_tessalation.$(ARCH).o
+
+$(ADDSTARC) : $(INC)/addstar.h
+$(ADDSTARD) : $(INC)/addstar.h
+$(ADDSTART) : $(INC)/addstar.h
+$(ADDSTAR)  : $(INC)/addstar.h
+$(SKYCELLS) : $(INC)/addstar.h
+
+$(BIN)/addstar.$(ARCH) : $(ADDSTAR)
+$(BIN)/addstard.$(ARCH) : $(ADDSTARD)
+$(BIN)/addstart.$(ARCH) : $(ADDSTART)
+$(BIN)/addstarc.$(ARCH) : $(ADDSTARC)
+$(BIN)/mkacc-2mass.$(ARCH) : $(MKACC-2MASS)
+$(BIN)/sedstar.$(ARCH)   : $(SEDSTAR)
+$(BIN)/load2mass.$(ARCH) : $(LOAD-2MASS)
+$(BIN)/skycells.$(ARCH) : $(SKYCELLS)
+
+INSTALL = addstar addstarc addstard addstart sedstar load2mass skycells
+
+# dependancy rules for binary code #########################
+$(INSTALL): % : $(BIN)/%.$(ARCH)
+
+%.clean :
+	rm -f $(BIN)/$*.$(ARCH)
+
+%.install:
+	make $(DESTBIN)/$*
+
+install:
+	for i in $(INSTALL); do make $$i.install || exit; done
Index: /branches/eam_branch_20080223/Ohana/src/addstar/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,5 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/addstar/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,77 @@
+
+- addstar 1.7 (2006.10.04)
+  * converted to gfits APIs (forces libfits 1.6)
+  * added the -resort option
+  * added timeout for large operations
+  * dropped old versions now not needed
+  * converted to the new DVO APIs (forces libdvo 1.3)
+  * added 'sedstar'
+  * added 'load2mass'
+  * more error checks on config
+  * converted to 'check_dir_access' 
+  * check that catalog stars fall in image (or skip catalog)
+  * fixed memory leak issues in find_matches
+  * changed match projection to ZEA
+  * fixed some 0,360 boundary errors
+
+- addstar 1.6
+  * added the 'fakeimage' mode
+
+- addstar 1.5
+  * fixed up skyregion errors
+  * added untested threaded server version
+  * added Tycho catalog
+  * added USNO-B catalog
+  * added proper motion and parallax
+  * fixed 2MASS to work with skyregions correctly
+  * dropped IMAGE_CATALOG from config
+  * changed to used dvo_image_lock,unlock
+  * cleaned up excess verbosity for timing tests
+  * added -photcode (supplement -p)
+  * added PMTEST format
+
+- addstar 1.4
+  * major work to support SkyRegions
+  * cleaned up signed/unsigned inconsistencies
+  * fixed 2MASS time to use JD 
+
+2005.10.20 : addstar-1.3
+
+	This release incorportates many substantial improvements
+	needed to handle the panstarrs data problems:
+	- internal data representation now high precision
+	- multiple data storage formats (LONEOS, ELIXIR, PANSTARRS)
+	- multiple data storage modes (RAW, MEF, SPLIT)
+	- alternative matching scheme (-closest)
+	- sorted output tables now optional
+	- incremental updates possible for inserts
+	- client / server set now defined
+
+2005.08.15 : addstar-1.2
+
+        This is a snapshot release before I begin serious work on the
+	code to handle alternate formats and so forth needed for the
+	panstarrs support.  Minor updates since v1.1, mostly to fix
+	2MASS issues and to stay in sync with the libs.  
+
+2005.07.06 : addstar-1.1
+
+	I have made a variety of fairly substantial changes since
+        v1.0.  I have added autocode for the basic DVO data types.  I
+        have merged the functionality of addspphot, addrefs, and
+        addusno into the single addstar function.  There are now
+        options to add an ascii text table or stars from known
+        external reference catalogs (HST GSC, USNO, 2MASS).  Also, the
+        functions added for skyprobe (in-flight Mcal calculation,
+        color terms) are also incorporated.  I also substantially
+        re-organized the basic code to make the different modes more
+        sensible.  There are still a few changes needed for addstar
+        v2.0 (which will be able to handle the pan-starrs bandwidth).
+        specifically, addstar needs to handle the catalog files using
+        the TBD sky.db interfaces, it needs to interact with a DVO
+        server in a client/server way (to divide up the sky), it needs
+        to handle multiple versions of the table formats, and it might
+        need to know about the mysql backend interface.  
+
+2005.02.24 : I am adding the mosaic two-level astrometry information to the Image table.
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/doc/camera-sample.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/doc/camera-sample.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/doc/camera-sample.txt	(revision 16632)
@@ -0,0 +1,81 @@
+# example camera layout file
+
+# arcsec per mm
+PLATE_SCALE  25.0
+
+DPLATE_X     1.0e-5
+DPLATE_Y     1.0e-5
+
+NCHIPS        64
+NAXIS1      4800
+NAXIS2      4800
+
+# mm per pixel
+PIXEL_SCALE   0.010
+
+# for now, we force the chip rotation to be 0 and parity to be 1,1
+# ref      name  dX      dY
+CHIP.000   x0y0 -19200  -19200
+CHIP.001   x1y0 -14400  -19200
+CHIP.002   x2y0  -9600  -19200
+CHIP.003   x3y0  -4800  -19200
+CHIP.004   x4y0      0  -19200
+CHIP.005   x5y0   4800  -19200
+CHIP.006   x6y0   9600  -19200
+CHIP.007   x7y0  14400  -19200
+CHIP.008   x0y1 -19200  -14400
+CHIP.009   x1y1 -14400  -14400
+CHIP.010   x2y1  -9600  -14400
+CHIP.011   x3y1  -4800  -14400
+CHIP.012   x4y1      0  -14400
+CHIP.013   x5y1   4800  -14400
+CHIP.014   x6y1   9600  -14400
+CHIP.015   x7y1  14400  -14400
+CHIP.016   x0y2 -19200   -9600
+CHIP.017   x1y2 -14400   -9600
+CHIP.018   x2y2  -9600   -9600
+CHIP.019   x3y2  -4800   -9600
+CHIP.020   x4y2      0   -9600
+CHIP.021   x5y2   4800   -9600
+CHIP.022   x6y2   9600   -9600
+CHIP.023   x7y2  14400   -9600
+CHIP.024   x0y3 -19200   -4800
+CHIP.025   x1y3 -14400   -4800
+CHIP.026   x2y3  -9600   -4800
+CHIP.027   x3y3  -4800   -4800
+CHIP.028   x4y3      0   -4800
+CHIP.029   x5y3   4800   -4800
+CHIP.030   x6y3   9600   -4800
+CHIP.031   x7y3  14400   -4800
+CHIP.032   x0y4 -19200       0
+CHIP.033   x1y4 -14400       0
+CHIP.034   x2y4  -9600       0
+CHIP.035   x3y4  -4800       0
+CHIP.036   x4y4      0       0
+CHIP.037   x5y4   4800       0
+CHIP.038   x6y4   9600       0
+CHIP.039   x7y4  14400       0
+CHIP.040   x0y5 -19200    4800
+CHIP.041   x1y5 -14400    4800
+CHIP.042   x2y5  -9600    4800
+CHIP.043   x3y5  -4800    4800
+CHIP.044   x4y5      0    4800
+CHIP.045   x5y5   4800    4800
+CHIP.046   x6y5   9600    4800
+CHIP.047   x7y5  14400    4800
+CHIP.048   x0y6 -19200    9600
+CHIP.049   x1y6 -14400    9600
+CHIP.050   x2y6  -9600    9600
+CHIP.051   x3y6  -4800    9600
+CHIP.052   x4y6      0    9600
+CHIP.053   x5y6   4800    9600
+CHIP.054   x6y6   9600    9600
+CHIP.055   x7y6  14400    9600
+CHIP.056   x0y7 -19200   14400
+CHIP.057   x1y7 -14400   14400
+CHIP.058   x2y7  -9600   14400
+CHIP.059   x3y7  -4800   14400
+CHIP.060   x4y7      0   14400
+CHIP.061   x5y7   4800   14400
+CHIP.062   x6y7   9600   14400
+CHIP.063   x7y7  14400   14400
Index: /branches/eam_branch_20080223/Ohana/src/addstar/doc/config.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/doc/config.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/doc/config.txt	(revision 16632)
@@ -0,0 +1,68 @@
+
+addstar is expecting to get the following information from the header.
+
+Required keywords:
+
+NAXIS1, NAXIS2
+NASTRO (non-zero for valid astrometry solution)
+NSTARS 
+CERROR (astrometric error)
+
+a valid WCS:
+
+CTYPE1,2
+CRVAL1,2
+CRPIX1,2
+CDELT1,2
+PC001001
+PC001002
+PC002001
+PC002002
+
+PHOTCODE
+
+optional keywords:
+
+APMIFIT, dAPMIFIT
+FLIMIT, FSATUR
+FWHM_X, FWHM_Y, 
+TRATE (for driftscanning)
+ZERO_PT 
+
+Note that these entries are used to define the actual keywords:
+
+(eg, in the dvo.config file, DATE-KEYWORD tells addstar what keyword
+to use for the DATE).
+
+For Date/Time, one of the following three sets is needed:
+
+ * DATE-KEYWORD (date in format specified below)
+ * DATE-MODE (YYYY/MM/DD, MM/DD/YYYY, DD/MM/YYYY)
+ * UT-KEYWORD (HH:MM:SS for UT)
+
+ or:
+
+ * MJD-KEYWORD (MJD)
+
+ or: 
+
+ * JD-KEYWORD (JD)
+
+For Exposure time:
+
+ * EXPTIME-KEYWORD (seconds)
+
+For Airmass:
+
+ * AIRMASS-KEYWORD
+
+CCDNUM-KEYWORD??
+
+For sidereal time (optional):
+
+ * ST-KEYWORD
+
+For alternate EXTNAME:
+
+ * EXTNAME-KEYWORD
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/doc/notes.txt	(revision 16632)
@@ -0,0 +1,502 @@
+
+2008.01.31
+
+  Adding extended sources:
+
+  * create a libautocode extended source table description (DONE)
+  * load the extended source measurements:
+    this could be done within LoadStars or as a separate pass over the file, loading the extended source tables
+    * we can call this function only optionally
+    * need to make the association between the psf and ext measurements via det ID
+  * in find_matches, we could/should record the reference from Stars to the matched average entry
+    that would let us use the PSF position to get the average object match:
+
+  * find_matches_extended
+    * loop over extended sources
+    * use ID to find the corresponding Stars entry
+    * use the averef to find the corresponding Average entry
+    * update the extended source table
+
+  * Write out ext sources with the rest of the data
+
+  where do we put the table? require split?
+
+  (160 byte per detection; PS1 will have 5e8 => 400 GB)
+
+2007.01.04
+
+  Use of options.photcode:
+    - M_REFLIST: used to assign a photcode value to the loaded data
+    - M_REFCAT: used to select data from the reference of the given photcode
+    - M_FAKEIMAGE: used to assign a photcode value to the generated data
+    - M_RESORT: unused
+    - M_IMAGE: is used to override or supply the image header photcode
+	       * only valid for single chip runs
+
+  Re: MOSAIC_PHU
+      - the mosaic phu needs to have the time to enable the image/mosaic match
+
+      - NX,NY are used for plotting the mosaic outline.  the center of
+        the mosaic is 0,0, and the mosaic outline is drawn from
+        -NX/2,-NY/2 to NX/2,NY/2.  A problem: NX,NY in Image is using
+        a short int.  If the units of the FPA/TPA coords are microns, this overflows.
+	* change NX,NY to int?
+	* require the use of mm not microns?
+	* for GPC, NX,NY ~ 384000 um excluding gaps
+
+      - only the astrometry, time, and NX,NY are loaded for MOSAIC_PHU headers.
+
+2007.01.03
+
+  I am working on adding the ability to read MEF files containing
+  multiple tables and multiple image headers.  Here are the details:
+
+  SIMPLE CMP:
+    PHU:
+      NAXIS = 2 or
+      SIMPLE = FALSE or
+      TEXTMODE = TRUE (use option; global variable)
+
+  SIMPLE CMF:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 exists, > 0
+      NAXIS2 exists, > 0
+    EXT:
+      EXTNAME = SMPDATA, PS1DATA, etc (defines layout)
+
+  SIMPLE MEF:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 does not exist
+      NAXIS2 does not exist
+      &CTYPE[4] is not "-DIS"
+      EXTEND is true
+    EXT HEAD:
+      EXTTYPE = IMAGE
+      EXTNAME = image.name
+      EXTDATA = table.name
+    EXT DATA:
+      EXTTYPE = SMPDATA, PS1DATA, etc (defines layout)
+      EXTNAME = table.name
+      EXTHEAD = image.name
+
+  MOSAIC MEF:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 does not exist
+      NAXIS2 does not exist
+      &CTYPE[4] is "-DIS"
+      EXTEND is true
+    EXT HEAD:
+      EXTTYPE = IMAGE
+      EXTNAME = image.name
+      EXTDATA = table.name
+    EXT DATA:
+      EXTTYPE = SMPDATA, PS1DATA, etc (defines layout)
+      EXTNAME = table.name
+      EXTHEAD = image.name
+
+  MOSAIC PHU:
+    PHU: 
+      NAXIS = 0
+      NAXIS1 does not exist
+      NAXIS2 does not exist
+      &CTYPE[4] is "-DIS"
+      NEXTEND = 0 or  
+      EXTEND is false
+
+    
+
+2006.04.02
+
+  I am considering an option to insert fake camera images into the
+  database.  The camera would be described with a file specifying the
+  dimensions of each chip (Nx,Ny,pixel scale), the location of each
+  chip in the focal plane, and the optical parameters of the camera
+  (plate scale at center, x,y distortion terms).  Each call to addstar
+  would specify the boresite center:
+
+  addstar -fakeimage ra dec theta
+
+  the camera parameters should be loaded via the config information.
+
+2005.10.24
+
+  I have changed addstar to use the new, more flexible, SkyRegion
+  concept to define the sky layout rather than just the GSCRegion
+  files.  This includes the ability to subdivide the existing
+  GSCRegion concept, and to have a more flexible sky table
+  arrangement.  
+
+  Names of catalog files are a bit tricky.  The SkyRegion functions
+  return base names without fullpath or extensions (ie, n0000/0012).
+  There are a few places in addstar which need the fullname:
+
+  SkyListExitingSubset () requires the path and adds .cpt
+
+  load_pt_catalog () takes the path and adds .cpt.  it also allocates
+  a filename entry for catalog, which is freed later in the loop in
+  addstars
+
+  mkcatalog uses the name in the catalog structure and replaces .cpt
+  with .cpm, .cpn, .cps as needed.
+
+  *** I need to fix the name method: common function to set it once 
+  in the dvo functions.  perhaps a pointer in the SkyRegion structure.
+  This needs some 32/64 bit care, though.  use a long long (or other 
+  type guaranteed to be 64 bit), and case to the appropriate type (size_t) 
+  when it is used?  also needs to be freed.
+
+todo:
+
+  * sky db tools 
+  * parallel servers
+  * threaded addstard
+  * dvo_load daemon
+  * getstar (program and c-client)
+  * parallal / proper-motion data
+  * other additional Average / Measure columns
+  * deal with Myyyy as sky value
+  * better way to interpret flips header info for sky?
+  * fix unlink empty file problem
+  * programs like relphot and dvo need to be provided 
+    with sorted measure tables; add this as a feature 
+    of the load_catalog API?
+
+done:
+
+  o move addstar/gstars to AddstarClientOptions
+  o add thiscode to AddstarClientOptions
+  o address MOSAIC somehow
+  o replace skyprobe mode
+  o complete server db interactions
+  o address the cat & ref modes in client/server
+  o add airmass quality to options
+
+2005.10.19
+
+	I have added the client / server mode, and tested it out to a
+	fair degree.  It handles all of the available addstar modes,
+	including -ref and -cat.  A handful of things still need to be
+	done, including pushing some of the logic to enforce sorting
+	into the dvo load_catalog functions.  Also, I need to correct
+	the idiosyncratic problem with sky vs Myyyy for the skyprobe
+	data.  There are a handful of other improvements that are
+	needed before addstar / DVO is ready for IPP release.
+	However, at this point, it is ready for internal use by the
+	grad students, but not yet ready for CFHT use with Elixir.
+
+2005.10.14
+
+  the current db interactions are somewhat in efficient wrt the image
+  table.  the basic outline is as follows:
+
+  - load image overlaps (needs entire image table)
+  - find detection matches (uses overlap information for missed)
+  - save new image (needs calculated calibration value from detection
+    matches)
+  
+  currently, I access the image table twice, and both times I load the
+  entire thing.  I really only need to append in the second case.  To
+  get to that point, I need to:
+
+  - split image overlaps from image db load
+  - define image partial load (analogous with catalog LOAD_MEAS_META)
+  
+  for the moment, I'm being wasteful so I can defer this issue.
+
+2005.10.13
+
+  I am working to minimize usage of globals and cleanup addstar
+  functions to make them more appropriate for the client / server
+  model.  
+
+  I have dropped save_pt_catalog, and modified load_pt_catalog, as
+  well as the load_catalog functions.  Now, the choice of elements to
+  load is made by setting flags in the catalog structure itself
+  (catalog.catflags).  Thus this information is carried around by the
+  catalog variable.  the load_pt_catalog function now only returns
+  true.  it is now necessary to check the state of the disk file by
+  examining Nave_disk to decide if the file is empty or not.  This is
+  perhaps too limiting: it prevents us from using only one of the
+  catalog tables (say measure without average).  The concern I have is
+  to manage the process of cleaning up the catalogs if no data is
+  added to them:  I don't want addstar to leave behind empty files
+  (plus, I think this breaks the lock/load state logic).  Thus,
+  whenever addstar unlocks / closes a file, if the Nave_disk +
+  Naverage is 0, the file should be unlinked.
+
+2005.10.12
+
+  By friday (2005.10.07), I managed to get the update process
+  working well, and tested it with some example data to demonstrate
+  that the partial update improved speed hugely.  Saturday, I started
+  to work on the client/server separation of addstar.  The first step
+  was to test out socket communication issues.  I set up a simple
+  client/server pair, in which one program listens on a socket while
+  the client connects to the socket and sends some command.  I set up
+  two autocode functions to send and receive complete structures
+  (Send_*, Recv_*) and added these to libautocode.  I have been able
+  to demonstrate sending Stars, Image, and Options to the server.
+
+  The next difficulty is in pulling out the command-line and
+  configuration options.  My original, somewhat lazy, design over-used
+  global variables to pass information between program sections.  This
+  needs to be cleaned up, especially if the server needs to have
+  multiple threads interacting with the db tables.  
+
+  Of the global variables that get set, some simply carry options on
+  how gstars should behave when it loads the data (including the
+  header interpretation information).  This can probably stay in the
+  globals for now.  Another group are configuration information used
+  only by the server-related functions, such as defining the location
+  of the database files and their format, etc.  These can also stay as
+  global, at least for now.  Another set of variables basically pass
+  information from the client to the server on how to behave *this
+  time*.  I have defined the AddstarClientOptions structure to carry
+  these, and will pass them from the client to the server along with
+  the stars and the image data.
+
+  Some outstanding issues:
+
+  sidereal time / latitude
+
+  I am carrying these as globals simply because the image structure
+  did not have them.  This is silly: I can define them as part of the
+  internal image structure without breaking any of the I/O issues.  
+
+  thiscode
+
+  I have been using this as a static photcode structure.  The
+  Send_*/Recv_* mechanisms are better suited to simple structures.  I
+  probably need to change this to just the code, and use the lookup
+  functions to the full structures where needed.  It can be part of
+  the options, and I should re-write functions which use it to accept
+  the options as an argument rather than rely on it as a global.
+
+  mosaic
+
+  this stores the coords structure for a needed mosaic.  this should
+  be kept, filled as needed by the client, and sent to the server with
+  the image.  perhaps it can be moved out of global.
+
+2005.10.06
+
+  I am getting seg faults from find_matches_closest, apparently
+  related to the partial Measure load.  They occur when trying to
+  realloc secfilt.  I tried to debug using the ohana_allocate stuff,
+  but it causes problems because fitsio does not fall under the ohana
+  memory system.  This is fairly bad; I should probably deal with that
+  issue before pursuing the other stuff.  Do I have to make libfits
+  depend on libohana, in which case I should probably split off libdvo
+  from libohana.  That is probably not a bad plan in any case...
+
+2005.10.07
+
+	I have finished the basic implementation of the update mode.
+	I have been able to demonstrate substantial improvements in
+	speed when the number of existing measurements dominates the
+	total number of measurements and the number of averages is
+	typically small compared to the number of measurements (ie,
+	most objects are real, detected in most images, and each new
+	image supplies many new measurements of objects which exist
+	and not many of objects which don't exist already).  The speed
+	gain is significant in this context because the average table
+	is small compared to the measure table; since both update and
+	full-load methods require the complete average table, there is
+	no difference in the load time for the average table.  
+
+	I was having some memory collision problems, and attempting to
+	use the ohana_allocate functions reminded me that the libFITS
+	functions were not supported under ohana_allocate.  This was
+	unhelpful.  I bit the bullet and split libohana into libohana
+	(base functions only, including ohana_allocate) and libdvo
+	(functions based on the libautocode structures).  Doing this
+	allowed me to make libFITS depend on libohana (including
+	ohana_allocate).  BUT, this forced me to change all LDFLAGS
+	entries in ohana to swap -lohana -lFITS for -lFITS -lohana,
+	and to add include <fitsio.h> in some cases.
+
+2005.10.06
+	split / nosort / update
+	I have added a few new concepts to addstar recently: split
+	catalog files, nosort for the measurement table, and
+	update-only.
+
+	split mode
+
+	The split mode is quite straightforeward.  In this mode, each
+	catalog is represented by a set of four files: *.cpt, *.cpm,
+	*.cpn, *.cps.  Each file contains only one FITS table of the
+	data, along with basic header and empty matrix.  Having
+	individual tables for each component of the database lets me
+	add entries without re-writing the entire table.  This should
+	save on I/O operations in the long run.  
+
+	The first file contains the table of averages, and is the file
+	normally identified in the table lookup functions.  The header
+	of this file contains the names of the other table files
+	(paths relative to the directory containing the cpt file).
+	The names and extensions are specified in 'mkcatalog.c'; all
+	other functions use the defined filename references, rather
+	than expecting a naming convention.
+
+	The additional files contain the measures (cpm), missings
+	(cpn), and secfilt (cps) elements of the catalog tables.  
+
+	To facilitate the handling of the additional filenames, file
+	pointers, and headers, Catalog was extended to include
+	pointers to the measure, missing, and secfilt files as
+	additional catalogs.  When the data are loaded into memory,
+	these catalogs are locked (as usual), and file information is
+	stored in the individual Catalog entries; the data segements
+	are all loaded into the main catalog pointers (eg, measures
+	are loaded into catalog[0].measure, rather than
+	catalog[0].measure_catalog[0].measure).
+	
+	The function 'load_catalog' auto-recognizes the SPLIT format
+	by looking for the header keyword MEASURE, identifying the
+	file containing the measures.  The identification of the RAW
+	format and the SPLIT format are not cross-checked: if the
+	NAXIS keyword is set to 2, the file is assumed to be RAW, even
+	if the MEASURE keyword is present.  Careful with this (though
+	there is no reason the main matrix should be used in a basic
+	database table).
+
+	nosort 
+
+	the nosort option by itself provides a minor processing
+	speed-up by deferring the re-sorting of the measurement table
+	until after multiple addstar processes are run.  addstar
+	should not require the measurements to be sorted, so this step
+	can be safetly deferred if only addstars are being performed.
+	the other DVO operations require the sorted table, so the sort
+	must be performed before they are run (either as part of the
+	catalog load, not implemented yet, or with a call to addstar
+	without the -nosort option set.  the real goal of the nosort
+	option is to enable the -update concept in addstar, in which
+	only the new rows are written out; this will only work if
+	addstar can handle unsorted measures. 
+
+	the nosort option required the addition of a 'sorted' element
+	in the Catalog structure to track if the data are sorted or
+	not.  On load, this flag is set based on the value of the
+	header keyword SORTED; if the data is sorted during addstar,
+	the flag is appropriately set, otherwise it is set FALSE be
+	default.  
+
+	The nosort option requires a function which can generate the
+	'next_meas' link sequence based on the measure table.  there
+	is now a function called 'build_meas_link' which generates a
+	correct link list; there is also the pair of functions
+	'init_meas_links' and'init_miss_links' to generate the links
+	in the event that the table is sorted (should be must
+	quicker).
+
+	The 'missing' table is problematic: the LONEOS and ELIXIR
+	formats do not carry an averef entry, thus they do not have
+	enough information to define the links based only on the
+	missing table.  This means we are forced to write out a sorted
+	missing table; the nosort option is invalid for the missing
+	table.  One future upgrade path is to add the averef entry to
+	the PANSTARRS format and then only require the missing table
+	to be sorted if the format is old and does not support
+	-nosort.  (Note also that, for the moment, the missing table
+	has only a single valid format).
+
+	In the process of defining the nosort option, I also cleaned
+	up a bit the find_matches functions to use clearer functions
+	for the links.  
+	
+	update
+
+	The 'update' process in principle allows addstar to
+	substantially reduce the amount of I/O it needs to perform by
+	only requiring addstar to write out new measures and new
+	average/secfilt entries.
+
+	The 'missing' table is problematic: since the format does not
+	support the 'nosort' option, it is not possible to use update
+	with the missing table.  This means we are forced to write out
+	a complete, sorted missing table.  This is currently
+	implemented in update_catalog_split by simply writing out the
+	complete missing table.  In fact, this choice is still flawed
+	because the average table, since it is not written out in full
+	each time, is inconsistent with the missing table: the Nn
+	entries for each average, which identifies the number of
+	missing entries, are not updated.  In practice, this means
+	that the -update option forces the use of the -missed option,
+	though at the moment, this is not forced or checked in any
+	way.
+
+	Note that the 'missed' table contains duplicate information
+	and can, in principle, be completely regenerated at any time.
+	This should be an addstar option: to re-construct the missing
+	table, potentially with constraints on the images which are
+	searched for matches.  
+
+2005.10.04
+	- moved measure/missing list manipulation to separate functions
+	- added concept of sorted / unsorted measure catalog
+	- defined build_meas_links and reorder_measure,missing
+	- some cleanup of both find_matches.c and find_matches_closest.c
+
+2005.10.03:
+	- dropping GSCRegion *region entry from find_matches (unused!)
+	- adding function find_matches_closest (alternate matches)
+
+2005.08.19:
+	changed load_photcode to handle CATMODE and CATFORMAT variations
+	- addstar.h: added CATMODE and CATFORMAT globals
+	- ConfigInit: read CATMODE and CATFORMAT from config
+	- gcatalog: set catalog.catmode from CATMODE
+	- mkcatalog: set CATFORMAT and CATMODE for new catalog
+	- wcatalog: set CATFORMAT for new catalog
+	
+	using full photometry conversions in find_matches
+	added SetZeroPoint to gstars to enable phot conversions
+	
+2005.08.15:
+	cleanup of the minor Wall,Werror messages
+
+2005.03.07 : notes related to new version of addstar
+
+- USNO seems to work fine now:
+
+  addstar -region 9.0 12.0 9.0 12.0 -cat usno -p USNO_RED
+  addstar -region 9.0 12.0 9.0 12.0 -cat usno -p USNO_BLUE
+
+- 2MASS seems to work as well:
+
+  addstar -region 3.0 12.0 12.0 14.0 -cat 2mass -p 2MASS_J
+  addstar -region 3.0 12.0 12.0 14.0 -cat 2mass -p 2MASS_H
+  addstar -region 3.0 12.0 12.0 14.0 -cat 2mass -p 2MASS_K
+
+- both of these are somewhat inefficient since they need to search
+  through the (larger) USNO/2MASS data files for each output ptolemy
+  region file.
+
+- GSC seems to work fine now:
+
+  addstar -region 3.0 12.0 12.0 14.0 -cat gsc 
+  (photcode is not needed here since there is only one)
+
+- images seems to work fine now
+
+- general concerns:
+
+  - RA 0,360 boundary is likely to have problems, especially with
+    region selection
+  - mosaic astrometry concepts still need to be added.
+
+  - average magnitudes are being set incorrectly in addstar (not
+    taking account of the zero-points).  I don't really want to apply
+    the colors here, but I need to do something, perhaps?
+
+    one option is to only apply the correction for the first
+    measurement of an object, unlike the way astrometry works
+    currently.  both of these should be updated based on
+    relphot/uniphot and eqiuvalent relastro/uniastro independently
+    from the addstar step.
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/etc/phottemp.cat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/etc/phottemp.cat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/etc/phottemp.cat	(revision 16632)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /branches/eam_branch_20080223/Ohana/src/addstar/etc/template.cat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/etc/template.cat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/etc/template.cat	(revision 16632)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /branches/eam_branch_20080223/Ohana/src/addstar/include/2mass.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/include/2mass.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/include/2mass.h	(revision 16632)
@@ -0,0 +1,43 @@
+
+/* structure for data on a catalog region */
+typedef struct {
+  char filename[256];
+  double RA[2];
+  int Nrec;
+} TM_Region;
+
+typedef struct {
+  double Rmin, Rmax, Dmin, Dmax;
+  int index[20];
+  int Nindex;
+} TMBands;
+
+typedef struct {
+  double R, D;
+  int offset;
+  int flag;
+} TMStars;
+
+short TM_J, TM_H, TM_K;
+
+SkyTable *get2mass_acc (SkyRegion *patch, char *path, char *accel);
+Stars    *get2mass_2DR_data (SkyRegion *region, char *filename, SkyRegion *patch, int photcode, int *nstars);
+Stars    *get2mass_AS_data (SkyRegion *region, char *filename, SkyRegion *patch, int phocode, int *nstars);
+Stars    *get2mass_AS_rawdata (SkyRegion *region, char *filename, SkyRegion *patch, int phocode, int *nstars);
+
+SkyTable *scan2mass_acc (char *path, char *accel);
+int       scan2mass_as_data (char *filename);
+
+char     *skipNbounds (char *line, char bound, int Nbound, int Nbyte);
+e_time    get2mass_time (char *ptr, int Nbound, int Nbyte);
+e_time    get2mass_date (char *ptr, int Nbound, int Nmax);
+
+int       load2mass_as_rawdata (SkyTable *skytable, char *filename, AddstarClientOptions options);
+SkyTable *load2mass_acc (char *path, char *accel);
+int       get2mass_3star (Stars *star, char *line, int Nmax);
+int       load2mass_catalog (Catalog *catalog, Stars *stars, int Nstars);
+
+int       get2mass_setup (int photcode);
+int       get2mass_coords (char *line, double *R, double *D, int Nmax);
+int       get2mass_star (Stars *star, char *line, int Nmax);
+int       get2mass_3star (Stars *star, char *line, int Nmax);
Index: /branches/eam_branch_20080223/Ohana/src/addstar/include/addstar.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/include/addstar.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/include/addstar.h	(revision 16632)
@@ -0,0 +1,262 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+# include <sys/time.h>
+# include <time.h>
+# include <zlib.h>
+
+/* solaris requires both of these instead of ip.h:
+   # include <sys/socket.h>
+   # include <netinet/in.h>
+*/
+
+/* linux is happy with this, not solaris */
+# include <netinet/ip.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+# include <glob.h>
+
+/* used in find_matches, find_matches_refstars */
+# define IN_REGION(R,D) ( \
+((D) >= region[0].Dmin) && ((D) < region[0].Dmax) && \
+((R) >= region[0].Rmin)  && ((R) < region[0].Rmax))
+
+/* grab named photcode */
+# define NAMED_PHOTCODE(CODE,NAME) \
+  CODE = GetPhotcodeCodebyName (NAME); \
+  if (!CODE) { \
+    fprintf (stderr, "ERROR:  photcode %s not found in photcode table\n", NAME); \
+    exit (0); }
+
+typedef struct {
+  int Nstars;
+  Stars *stars;
+  int Nimages;
+  Image *images;
+  Coords *mosaic;
+  SkyRegion *patch;
+  AddstarClientOptions *options;
+  char *refcat;
+} DVO_DATA;
+
+typedef struct {
+  char *exthead;
+  char *extdata;
+  char *exttype;
+  int extnum_head;
+  int extnum_data;
+} HeaderSet;
+
+typedef struct sockaddr_in SockAddress;
+
+enum {M_IMAGE, M_REFLIST, M_REFCAT, M_FAKEIMAGE, M_RESORT};
+enum {NONE, SIMPLE_CMP, SIMPLE_CMF, SIMPLE_MEF, MOSAIC_CMP, MOSAIC_CMF, MOSAIC_MEF, MOSAIC_PHU};
+/* note: MEF implies CMF */
+
+/* globals which define database info / data sources (KEEP) */
+char   ImageCat[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char   TWO_MASS_DIR_AS[256];
+char   TWO_MASS_DIR_DR2[256];
+char   GSCDIR[256];
+char   USNO_A_DIR[256];
+char   USNO_B_DIR[256];
+char   TYCHO_DIR[256];
+char   SubpixDatafile[256];
+char   PASSWORD[80];
+char   HOSTNAME[80];
+int    NVALID, *VALID_IP;
+char   SKY_TABLE[256];
+int    SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
+char   CameraLayout[256];
+SkyTable *ServerSky;
+
+/* used to select entries from header (gstars or parse_time) (KEEP) */
+char   DateKeyword[64];
+char   DateMode[64];
+char   UTKeyword[64];
+char   MJDKeyword[64];
+char   JDKeyword[64];
+char   ExptimeKeyword[64];
+char   AirmassKeyword[64];
+char   CCDNumKeyword[64];
+char   STKeyword[64];
+char   ExtnameKeyword[64];
+
+/* these globals modify the behavior of gstars (KEEP) */
+double 	SNLIMIT;
+int    	ACCEPT_ASTROM;  // accept even bad astrometry solutions (NASTRO == 0)
+int    	ACCEPT_MOTION;  // accept reference proper motion measurements
+int    	ACCEPT_TIME;    // accept time stamp (or 0)
+int    	NO_STARS;       // ignore the stars
+int    	TEXTMODE;       // force input file to be loaded as RAW
+int     SUBPIX;         // apply a subpix correction
+char   *DUMP;           // dump out intermediate results
+int    	XOVERSCAN;      // used to modify stored image dimensions 
+int    	YOVERSCAN;      // used to modify stored image dimensions 
+int    	XMIN;           // used to filter loaded star list 
+int    	XMAX;           // used to filter loaded star list 
+int    	YMIN;           // used to filter loaded star list 
+int    	YMAX;           // used to filter loaded star list 
+double 	Latitude;       // carried into image structure from config
+double 	Longitude;      // carried into image structure from config
+Coords *MOSAIC;         // carries the mosaic into gstars
+double  FAKE_RA;        // boresite coords for fake images
+double  FAKE_DEC;       // boresite coords for fake images
+double  FAKE_THETA;     // boresite angle for fake images
+
+/* these globals are used separately by both client and server (KEEP) */
+double CAL_INSTMAG_MAX;
+double CAL_INSTMAG_MIN;
+int    VERBOSE;
+int    PLOT;
+double MAX_CERROR;
+
+/* modify server behavior (make this an addstar cleanup mode?) */
+int    FORCE_READ;
+
+// XXX this should be replaced with 
+// 1) an airmass accuracy option
+// 2) an alternative CATFORMAT with the sky element correctly defined.
+
+/* these depend on HOW we implement the client/server interaction for CAT/REF modes */
+time_t    TIMEREF;    // used by MODE REF
+SkyRegion UserPatch;  // used by MODE CAT
+char     *SELECT_2MASS_QUALITY;  // used only by get2mass_as
+
+/*** addstar prototypes ***/
+
+void       AddToCalibration       PROTO((Average *average, SecFilt *secfilt, Measure *measure, Measure *new, int *next, int Nstar));
+AddstarClientOptions ConfigInit   PROTO((int *argc, char **argv));
+void       FindCalibration        PROTO((Image *image));
+FILE      *GetDB                  PROTO((int *state));
+void       InitCalibration        PROTO(());
+void       SaveCalibration        PROTO((float Mo, float dMo, float Mr, float dMr, float Mi, int N));
+void       SetProtect             PROTO((int mode));
+int        SetSignals             PROTO(());
+int        Shutdown               PROTO((char *message, ...); ) 
+void       TrapSignal             PROTO((int sig));
+float      airmass                PROTO((float secz_image, double ra, double dec, double st, double latitude));
+void       SetAirmassQuality      PROTO((int quality));
+SkyTable  *SkyTableFromTychoIndex PROTO((char *filename, int VERBOSE));
+AddstarClientOptions args         PROTO((int argc, char **argv, AddstarClientOptions options));
+void       check_permissions      PROTO((char *basefile));
+int        dump_rawstars          PROTO((Stars *stars, int Nstars));
+int        edge_check             PROTO((double *x1, double *y1, double *x2, double *y2));
+Image     *fakeimage              PROTO((char *rootname, int *Nimage, int photcode));
+int        find_matches           PROTO((SkyRegion *region, Stars *stars, int Nstars, Catalog *catalog, AddstarClientOptions options));
+int        find_matches_closest   PROTO((SkyRegion *region, Stars *stars, int Nstars, Catalog *catalog, AddstarClientOptions options));
+int        find_matches_refstars  PROTO((SkyRegion *region, Stars **stars, int Nstars, Catalog *catalog, AddstarClientOptions options));
+Stars    **find_subset            PROTO((SkyRegion *region, Stars *stars, int Nstars, int *NSTARS));
+int        gcatalog               PROTO((Catalog *catalog));
+Stars     *get2mass               PROTO((SkyRegion *patch, int photcode, int mode, int *NSTARS));
+double     get_subpix             PROTO((double x, double y));
+Stars     *getgsc                 PROTO((SkyRegion *patch, int *NSTARS));
+Stars     *gettycho               PROTO((SkyRegion *catstats, int photcode, int *Nstars));
+Stars     *getusno                PROTO((SkyRegion *catstats, int photcode, int *Nstars));
+Stars     *getusnob               PROTO((SkyRegion *catstats, int photcode, int *Nstars));
+Image     *gimages                PROTO((FITS_DB *db, Image *image, Coords *mosaic, int *Npimage));
+Stars     *grefcat                PROTO((char *Refcat, SkyRegion *catstats, int photcode, int *nstars));
+Stars     *grefstars              PROTO((char *file, int photcode, int *Nstars));
+
+Stars     *LoadStars              PROTO((char *file, int *Nstars, Image **images, int *Nimages, int photcode));
+Header   **LoadHeaders            PROTO((FILE *f, int *mode, int *Nheader));
+HeaderSet *MatchHeaders           PROTO((int **extsize, int *nimage, int mode, Header **headers, int Nheaders));
+int        LoadData               PROTO((FILE *f, char *file, Image **images, int *nvalid, Stars **stars, int *Nstars, Header **headers, int *extsize, HeaderSet *headerSets, int NheaderSets));
+
+int        in_image               PROTO((double r, double d, Image *image));
+int        load_pt_catalog        PROTO((Catalog *catalog, SkyRegion *region));  /*** choose new name ***/
+void       load_subpix            PROTO(());
+void       lock_image_db          PROTO((FITS_DB *db, char *filename));
+int        main                   PROTO((int argc, char **argv));
+void       make_backup            PROTO((char *filename));
+int        match_refstars         PROTO((Stars *stars, int Nstars));
+void       mkcatalog              PROTO((SkyRegion *region, Catalog *catalog));
+double     opening_angle          PROTO((double x1, double y1, double x2, double y2, double x3, double y3));
+int        parse_time             PROTO((Header *header));
+Stars     *rd_gsc                 PROTO((char *filename, int *nstars));
+int        replace_match          PROTO((Average *average, Measure *measure, Stars *star));
+void       resort_catalog         PROTO((Catalog *catalog));
+Stars     *rfits                  PROTO((FILE *f, unsigned int *nstars));
+Stars     *rtext                  PROTO((FILE *f, unsigned int *nstars));
+Stars     *ReadStarsFITS          PROTO((FILE *f, Header *header, Header *in_theader, unsigned int *nstars));
+Stars     *ReadStarsTEXT          PROTO((FILE *f, unsigned int *nstars));
+int        ReadImageHeader        PROTO((Header *header, Image *image, int photcode));
+Stars     *FilterStars            PROTO((Stars *instars, Image *image));
+Stars     *MergeStars             PROTO((Stars *stars, int *Nstars, Stars *instars, int Ninstars));
+void       save_pt_catalog        PROTO((Catalog *catalog));  /*** choose new name ***/
+double     scat_subpix            PROTO((double x, double y));
+time_t     short_date_to_sec      PROTO((char *date));
+void       sort_lists             PROTO((float *X, float *Y, int *S, int N));
+void       sort_stars             PROTO((Stars *stars, int N));
+int        str_to_radec           PROTO((double *ra, double *dec, char *str1, char *str2));
+void       unlock_image_db        PROTO((FITS_DB *db));
+void       update_coords          PROTO((Average *average, Measure *measure, int *next));
+void       wcatalog               PROTO((Catalog *catalog));
+void       free_catalog           PROTO((Catalog *catalog));
+void       wimage                 PROTO((FITS_DB *db, Image *image));
+void       create_image_db        PROTO((FITS_DB *db));
+void       set_db                 PROTO((FITS_DB *in));
+void       uppercase              PROTO((char *string));
+void       fsort                  PROTO((float *X, int N));
+void       fsort2                 PROTO((float *X, float *Y, int N));
+int 	  *init_measure_links     PROTO((Average *average, int Naverage, Measure *measure, int Nmeasure));
+int 	  *init_missing_links     PROTO((Average *average, int Naverage, Missing *missing, int Nmissing));
+int 	   add_meas_link     	  PROTO((Average *average, int *next, int Nmeasure, int NMEASURE));
+int 	   add_miss_link     	  PROTO((Average *average, int *next, int Nmissing));
+int 	  *build_measure_links    PROTO((Average *average, int Naverage, Measure *measure, int Nmeasure));
+Measure   *sort_measure     	  PROTO((Average *average, int Naverage, Measure *measure, int Nmeasure, int *next));
+Missing   *sort_missing     	  PROTO((Average *average, int Naverage, Missing *missing, int Nmissing, int *next_miss));
+int        ImageOptions		  PROTO((AddstarClientOptions *options, Image *images, int Nimages));
+int        GetFileMode		  PROTO((Header *header));
+AddstarClientOptions args_client  PROTO((int argc, char **argv, AddstarClientOptions options));
+AddstarClientOptions args_load2mass PROTO((int argc, char **argv, AddstarClientOptions options));
+AddstarClientOptions args_sedstar PROTO((int argc, char **argv, AddstarClientOptions options));
+void	   args_server		  PROTO((int argc, char **argv));
+int 	   CheckPassword	  PROTO((int BindSocket));
+int 	   NewImage		  PROTO((int BindSocket));
+int 	   NewReflist		  PROTO((int BindSocket));
+int 	   NewRefcat		  PROTO((int BindSocket));
+int 	   InitServerSocket	  PROTO((SockAddress *Address));
+int 	   WaitServerSocket	  PROTO((int InitSocket, SockAddress *Address, int *validIP, int Nvalid));
+int 	   GetClientSocket	  PROTO((char *hostname));
+int 	   UpdateDatabase_Image	  PROTO((AddstarClientOptions *options, Image *images, int Nimages, Coords *mosaic, Stars *stars, int Nstars));
+int 	   UpdateDatabase_Reflist PROTO((AddstarClientOptions *options, Stars *stars, int Nstars));
+int 	   UpdateDatabase_Refcat  PROTO((AddstarClientOptions *options, SkyRegion *UserPatch, char *refcat));
+SkyList   *SkyListForStars	  PROTO((SkyTable *table, int depth, Stars *stars, int Nstars));
+SkyList   *SkyListExistingSubset  PROTO((SkyList *input, char *path));
+int        SkyListSetPath	  PROTO((SkyList *list, char *path));
+SkyTable  *SkyTableLoadOptimal	  PROTO(());
+int 	   InitDataset		  PROTO(());
+int 	   PushDataset		  PROTO((DVO_DATA *data));
+DVO_DATA  *PopDataset		  PROTO((void));
+void	  *ListenClients_Thread	  PROTO((void *data));
+int 	   NewImage_Thread	  PROTO((int BindSocket));
+int 	   NewRefcat_Thread	  PROTO((int BindSocket));
+int 	   NewReflist_Thread	  PROTO((int BindSocket));
+
+Stars     *Convert_SMPDATA	  PROTO((FTable *table, int *nstars));
+Stars     *Convert_PS1_DEV_0	  PROTO((FTable *table, int *nstars));
+Stars     *Convert_PS1_DEV_1	  PROTO((FTable *table, int *nstars));
+
+int args_skycells (int argc, char **argv);
+int ConfigInit_skycells (int *argc, char **argv);
+
+// this is a gnu extension?? caution!
+void *memrchr(const void *s, int c, size_t n);
+
+/** 
+    there is an inconsistency to be resolved: fixed structures (like Image)
+    need a fixed bit-length time (e_time), but these functions all use the
+    UNIX time_t types, which may be 32 or 64 bits, depending on the machine.
+    This can be resolved by using time_t with these functions, but casting 
+    between e_time and time_t when necessary (ie, cannot return data to an
+    e_time pointer from one of these functions)
+**/
+
+
+/** function for client / server **/ 
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/include/sedstar.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/include/sedstar.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/include/sedstar.h	(revision 16632)
@@ -0,0 +1,45 @@
+# include "addstar.h"
+# include "kapa.h"
+
+typedef enum {
+  SED_FIT,
+  SED_REQ,
+  SED_MODEL,
+  SED_SAMPLE,
+} SEDtableModes;
+
+typedef struct {
+  float *mags;
+  float color;
+  float Temp;
+  float Av;
+} SEDtableRow;
+
+typedef struct {
+  float chisq;
+  float Md;
+  int row;
+} SEDfit;
+
+typedef struct {
+  int Nfilter;
+  float *wavecode;
+  float *vegaToAB;
+  int *mode;
+  int *hashcode;
+  int *code;
+  int codeP;
+  int codeM;
+  SEDtableRow **row;
+  int Nrow;
+} SEDtable;
+
+SEDtableRow **sort_SEDtable (SEDtableRow *raw, int N);
+SEDfit SEDchisq (SEDtableRow *ref, SEDtableRow *data, SEDtableRow *error, int Nfilter);
+SEDtable *SEDtableLoad (char *filename);
+int SEDcolorBracket (SEDtable *table, float color, float delta);
+int SEDfitInit (SEDtable *table);
+int SEDfitPlot (SEDtable *table, double R, double D, SEDfit *minFit, SEDtableRow *sourceValue, SEDtableRow *sourceError);
+int SEDfitClear ();
+int SEDfitCatalog (Catalog *outcat, Catalog *incat, SEDtable *table);
+void SetLimitsRaw (float *xvec, float *yvec, int Nelements, Graphdata *graphmode);
Index: /branches/eam_branch_20080223/Ohana/src/addstar/include/skycells.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/include/skycells.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/include/skycells.h	(revision 16632)
@@ -0,0 +1,92 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+# include <sys/time.h>
+# include <time.h>
+# include <zlib.h>
+
+/* linux is happy with this, not solaris */
+# include <netinet/ip.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+# include <glob.h>
+
+enum {SQUARES, TRIANGLES};
+
+typedef struct {
+  double x, y, z;
+} Point;
+
+typedef struct {
+  Point vertex[3];	      // triangle vertices (3d)
+  Point center;		      // triangle center (3d)
+  double r, d;		      // triangle center (2d)
+  double rv[3], dv[3];	      // triangle center (2d)
+} SkyTriangle;
+
+typedef struct {
+  Coords coords;
+  int NX;
+  int NY;
+  int code;
+  char name[64];
+} SkyRectangle;
+
+/* globals which define database info / data sources (KEEP) */
+char   ImageCat[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char   PASSWORD[80];
+char   HOSTNAME[80];
+int    NVALID, *VALID_IP;
+char   SKY_TABLE[256];
+int    SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
+char   CameraLayout[256];
+SkyTable *ServerSky;
+
+/* used to select entries from header (gstars or parse_time) (KEEP) */
+char   DateKeyword[64];
+char   DateMode[64];
+char   UTKeyword[64];
+char   MJDKeyword[64];
+char   JDKeyword[64];
+char   ExptimeKeyword[64];
+char   AirmassKeyword[64];
+char   CCDNumKeyword[64];
+char   STKeyword[64];
+
+int    VERBOSE;
+int    MODE;
+int    FIX_NS;
+int    NMAX;
+int    NX_SUB, NY_SUB;
+double SCALE;
+double PADDING;
+
+double EULER_A;
+double EULER_B;
+
+void         SetProtect                PROTO((int mode));
+int          SetSignals                PROTO(());
+int          Shutdown                  PROTO((char *message, ...); ) 
+void         TrapSignal                PROTO((int sig));
+
+int 	     args_skycells 	       PROTO((int argc, char **argv));
+int 	     ConfigInit_skycells       PROTO((int *argc, char **argv));
+int 	     sky_tessalation 	       PROTO((FITS_DB *db, int level, int Nmax, int mode, double scale));
+int          sky_tessalation_init      PROTO((double scale));
+int 	     sky_tessalation_triangles PROTO((FITS_DB *db, int level, int Nmax));
+int 	     sky_tessalation_squares   PROTO((FITS_DB *db, int level, int Nmax));
+int 	     sky_triangle_to_image     PROTO((Image *image, SkyTriangle *triangle));
+int 	     sky_triangle_to_rectangle PROTO((SkyRectangle *image, SkyTriangle *triangle));
+int 	     sky_subdivide_image       PROTO((Image *output, SkyRectangle *input, int Nx, int Ny));
+int 	     sky_triangle_coords       PROTO((SkyTriangle *triangle));
+SkyTriangle *sky_divide_triangles      PROTO((SkyTriangle *in, int *ntriangles));
+SkyTriangle *sky_base_triangles        PROTO((int *ntriangles));
+int          sky_base_rotation         PROTO((SkyTriangle *base, int Nbase));
+Point        sky_divide_edge           PROTO((Point v1, Point v2));
+
+// XXX migrate to libdvo eventually
+int dvo_image_clear_vtable             PROTO((FITS_DB *db));
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/CheckPassword.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/CheckPassword.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/CheckPassword.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "addstar.h"
+
+int CheckPassword (int BindSocket) {
+
+  IOBuffer message;
+  int status;
+
+  status = ExpectCommand (BindSocket, strlen(PASSWORD), 0.1, &message);
+  if (status != 0) {
+    if (VERBOSE) fprintf (stderr, "failed connection\n");
+    FreeIOBuffer (&message);
+    close (BindSocket);
+    return (FALSE);
+  }
+  if (strncmp (message.buffer, PASSWORD, strlen(PASSWORD))) {
+    if (VERBOSE) fprintf (stderr, "invalid password\n");
+    close (BindSocket);
+    return (FALSE);
+  }
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,185 @@
+# include "addstar.h"
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+
+AddstarClientOptions ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char *config, *file;
+  char RadiusWord[80];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+  AddstarClientOptions options;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+
+  /* exclude overscan region from the dB image boundaries */
+  XOVERSCAN = YOVERSCAN = 0;
+  ScanConfig (config, "XOVERSCAN",              "%d",  0, &XOVERSCAN);
+  ScanConfig (config, "YOVERSCAN",              "%d",  0, &YOVERSCAN);
+
+  /* only upload stars within region; a value of 0 means ignore the limit */
+  XMIN = XMAX = YMIN = YMAX = 0;
+  ScanConfig (config, "ADDSTAR_XMIN",           "%d",  0, &XMIN);
+  ScanConfig (config, "ADDSTAR_XMAX",           "%d",  0, &XMAX);
+  ScanConfig (config, "ADDSTAR_YMIN",           "%d",  0, &YMIN);
+  ScanConfig (config, "ADDSTAR_YMAX",           "%d",  0, &YMAX);
+
+  /* exclude stars with SN > SNLIMIT (ADDSTAR_SNLIMIT overrides old name MIN_SN_FSTAT) */
+  SNLIMIT = 0;
+  ScanConfig (config, "MIN_SN_FSTAT",           "%lf", 0, &SNLIMIT);
+  ScanConfig (config, "ADDSTAR_SNLIMIT",        "%lf", 0, &SNLIMIT);
+
+  MAX_CERROR = 0.5; // arcseconds
+  ScanConfig (config, "ADDSTAR_MAX_CERROR",     "%lf", 0, &MAX_CERROR);
+
+  /* used by parse_time to find time-related keywords */
+  strcpy (DateKeyword, "NONE");
+  strcpy (DateMode, "NONE");
+  strcpy (UTKeyword, "NONE");
+  strcpy (JDKeyword, "NONE");
+  strcpy (MJDKeyword, "NONE");
+  ScanConfig (config, "DATE-KEYWORD",           "%s",  0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",              "%s",  0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",             "%s",  0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",            "%s",  0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",             "%s",  0, JDKeyword);
+
+  ScanConfig (config, "EXPTIME-KEYWORD",        "%s",  0, ExptimeKeyword);
+  ScanConfig (config, "AIRMASS-KEYWORD",        "%s",  0, AirmassKeyword);
+  ScanConfig (config, "CCDNUM-KEYWORD",         "%s",  0, CCDNumKeyword);
+  ScanConfig (config, "ST-KEYWORD",             "%s",  0, STKeyword);
+  ScanConfig (config, "OBSERVATORY-LATITUDE",   "%lf", 0, &Latitude);
+  ScanConfig (config, "OBSERVATORY-LONGITUDE",  "%lf", 0, &Longitude);
+  ScanConfig (config, "SUBPIX_DATAFILE",        "%s",  0, SubpixDatafile);
+
+  if (!ScanConfig (config, "EXTNAME-KEYWORD",        "%s",  0, ExtnameKeyword)) {
+      strcpy (ExtnameKeyword, "EXTNAME"); 
+  }
+
+  /* instrumental magnitude range for calibration mode */
+  CAL_INSTMAG_MAX =  -9.0;
+  CAL_INSTMAG_MIN = -13.0;
+  ScanConfig (config, "CAL_INSTMAG_MAX",        "%lf", 0, &CAL_INSTMAG_MAX);
+  ScanConfig (config, "CAL_INSTMAG_MIN",        "%lf", 0, &CAL_INSTMAG_MIN);
+
+  /* location of needed data sources */
+  ScanConfig (config, "2MASS_DIR_AS",           "%s",  0, TWO_MASS_DIR_AS);
+  ScanConfig (config, "2MASS_DIR_DR2",          "%s",  0, TWO_MASS_DIR_DR2);
+  ScanConfig (config, "GSCDIR",                 "%s",  0, GSCDIR);
+
+  if (!ScanConfig (config, "USNO_A_DIR",        "%s",  0, USNO_A_DIR)) {
+    ScanConfig (config, "USNO_CDROM",           "%s",  0, USNO_A_DIR);
+  }
+  ScanConfig (config, "USNO_B_DIR",             "%s",  0, USNO_B_DIR);
+
+  ScanConfig (config, "TYCHO_DIR",             	"%s",  0, TYCHO_DIR);
+
+  GetConfig (config, "GSCFILE",                	"%s",  0, GSCFILE);
+  GetConfig (config, "CATDIR",                 	"%s",  0, CATDIR);
+  GetConfig (config, "PHOTCODE_FILE",          	"%s",  0, MasterPhotcodeFile);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = SKY_DEPTH_HST;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+  GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  if (!ScanConfig (config, "IMAGE_TABLE",       "%s",  0, ImageCat)) {
+    if (!ScanConfig (config, "IMAGE_CATALOG",   "%s",  0, ImageCat)) {
+      sprintf (ImageCat, "%s/Images.dat", CATDIR);
+    }
+  }
+
+  ScanConfig (config, "CAMERA_LAYOUT",          "%s",  0, CameraLayout);
+
+  /* used by client/server setup */
+  ScanConfig (config, "PASSWORD",               "%s",  0, PASSWORD);
+  ScanConfig (config, "HOSTNAME",               "%s",  0, HOSTNAME);
+  
+  /* load valid ip list */
+  {
+    int i, Nvalid, ip1, ip2, ip3, ip4, test, status;
+    char string[80];
+
+    Nvalid = 0;
+    NVALID = 10;
+    ALLOCATE (VALID_IP, int, NVALID);
+    for (i = 0; ScanConfig (config, "VALID_IP", "%s", i, string) != NULL; i++) {
+      status = sscanf (string, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+      test = TRUE;
+      test &= (status == 4);
+      test &= ((ip1 > 0) && (ip1 < 256)); 
+      test &= ((ip2 > 0) && (ip2 < 256)); 
+      test &= ((ip3 > 0) && (ip3 < 256)); 
+      test &= ((ip4 >=0) && (ip4 < 256)); 
+      if (!test) {
+	fprintf (stderr, "invalid IP address %s\n", string);
+	exit (2);
+      }
+      VALID_IP[Nvalid] = ip1 | (ip2 << 8) | (ip3 << 16) | (ip4 << 24);
+      Nvalid ++;
+      CHECK_REALLOCATE (VALID_IP, int, NVALID, Nvalid, 10);
+    }
+    NVALID = Nvalid;
+    REALLOCATE (VALID_IP, int, NVALID);
+    if (NVALID == 0) {
+      free (VALID_IP);
+      VALID_IP = NULL;
+    }
+  }
+
+  /* set the default search radius */
+  if (!ScanConfig (config, "ADDSTAR_RADIUS", "%s", 0, RadiusWord)) {
+    GetConfig (config, "RADIUS", "%s", 0, RadiusWord);
+  }
+  /* XXX this does not work for refcat and reflist modes... */
+  if (!strcasecmp (RadiusWord, "header")) {
+    options.radius = 0;
+    if (!ScanConfig (config, "ADDSTAR_NSIGMA", "%lf", 0, &options.Nsigma)) {
+      GetConfig (config, "NSIGMA", "%lf", 0, &options.Nsigma);
+    }
+  } else {
+    options.radius = atof (RadiusWord);
+  }
+
+  /* default mode, format, if not specified */
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+  return (options);
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/ConfigInit_skycells.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/ConfigInit_skycells.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/ConfigInit_skycells.c	(revision 16632)
@@ -0,0 +1,77 @@
+# include "skycells.h"
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+
+int ConfigInit_skycells (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* used by parse_time to find time-related keywords */
+  strcpy (DateKeyword, "NONE");
+  strcpy (DateMode, "NONE");
+  strcpy (UTKeyword, "NONE");
+  strcpy (JDKeyword, "NONE");
+  strcpy (MJDKeyword, "NONE");
+  ScanConfig (config, "DATE-KEYWORD",           "%s",  0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",              "%s",  0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",             "%s",  0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",            "%s",  0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",             "%s",  0, JDKeyword);
+
+  ScanConfig (config, "EXPTIME-KEYWORD",        "%s",  0, ExptimeKeyword);
+  ScanConfig (config, "AIRMASS-KEYWORD",        "%s",  0, AirmassKeyword);
+  ScanConfig (config, "CCDNUM-KEYWORD",         "%s",  0, CCDNumKeyword);
+  ScanConfig (config, "ST-KEYWORD",             "%s",  0, STKeyword);
+
+  GetConfig (config, "GSCFILE",                	"%s",  0, GSCFILE);
+  GetConfig (config, "CATDIR",                 	"%s",  0, CATDIR);
+  GetConfig (config, "PHOTCODE_FILE",          	"%s",  0, MasterPhotcodeFile);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = SKY_DEPTH_HST;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  /* default mode, format, if not specified */
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+  return (TRUE);
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/DatasetOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/DatasetOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/DatasetOps.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "addstar.h"
+# include <pthread.h>
+
+/* the init function is an alternative */
+/* pthread_mutex_init(&mutex, const pthread_mutexattr_t *mutexattr); */
+pthread_mutex_t fastmutex = PTHREAD_MUTEX_INITIALIZER;
+
+static int Ndataset = 0;
+static int NDATASET = 0;
+static DVO_DATA **dataset = NULL;
+
+int InitDataset () {
+
+  int i;
+
+
+  Ndataset = 0;
+  NDATASET = 100;
+  ALLOCATE (dataset, DVO_DATA *, NDATASET);
+  for (i = 0; i < NDATASET; i++) {
+    dataset[i] = NULL;
+  }
+  return (TRUE);
+}
+
+/* data a set dataset to the end of the stack */
+int PushDataset (DVO_DATA *data) {
+
+  int N;
+
+  pthread_mutex_lock(&fastmutex);
+
+  N = Ndataset;
+  Ndataset ++;
+  CHECK_REALLOCATE (dataset, DVO_DATA *, NDATASET, Ndataset, 100);
+
+  dataset[N] = data;
+
+  pthread_mutex_unlock(&fastmutex);
+  return (TRUE);
+}
+
+/* remove and return first dataset */
+DVO_DATA *PopDataset (void) {
+
+  int i;
+  DVO_DATA *data;
+
+  pthread_mutex_lock(&fastmutex);
+
+  if (Ndataset == 0) {
+    pthread_mutex_unlock(&fastmutex);
+    return (NULL);
+  }
+
+  data = dataset[0];
+  
+  for (i = 0; i < Ndataset - 1; i++) {
+    dataset[i] = dataset[i+1];
+  }
+  Ndataset --;
+  if ((Ndataset < NDATASET / 2) && (Ndataset > 50)) {
+    NDATASET = Ndataset / 2;
+    REALLOCATE (dataset, DVO_DATA *, NDATASET);
+  }
+
+  pthread_mutex_unlock(&fastmutex);
+  return (data);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/FilterStars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/FilterStars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/FilterStars.c	(revision 16632)
@@ -0,0 +1,101 @@
+# include "addstar.h"
+
+Stars *FilterStars (Stars *instars, Image *image) {
+
+  int j, N;
+  float MTIME, dMs, dMx;
+  Stars *stars;
+  float RMIN, RMAX, DMIN, DMAX;
+
+  /* correct instrumental mags for exposure time */
+  MTIME = (image[0].exptime > 0) ? 2.500*log10(image[0].exptime) : 0.0;
+
+  RMIN = 360.0;
+  RMAX =   0.0;
+  DMIN = +90.0;
+  DMAX = -90.0;
+
+  /* modify resulting star list */
+  ALLOCATE (stars, Stars, image[0].nstar);
+  for (N = j = 0; j < image[0].nstar; j++) {
+    /* allow for some dynamic filtering of star list */
+    if (SNLIMIT && instars[j].dM > SNLIMIT) continue;
+    if (XMAX && (instars[j].X > XMAX)) continue;
+    if (XMIN && (instars[j].X < XMIN)) continue;
+    if (YMAX && (instars[j].Y > YMAX)) continue;
+    if (YMIN && (instars[j].Y < YMIN)) continue;
+    stars[N] = instars[j];
+
+    XY_to_RD (&stars[N].R, &stars[N].D, stars[N].X, stars[N].Y, &image[0].coords);
+    while (stars[N].R <    0.0) stars[N].R += 360.0;
+    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+    stars[N].found = -1;
+    stars[N].code = image[0].photcode;
+
+    RMIN = MIN (RMIN, stars[N].R);
+    RMAX = MAX (RMAX, stars[N].R);
+    DMIN = MIN (DMIN, stars[N].D);
+    DMAX = MAX (DMAX, stars[N].D);
+    /** additional quantities to supply to Stars based on the image data **/
+
+    /* calculate accurate per-star airmass */
+    stars[N].airmass = airmass (image[0].secz, stars[N].R, stars[N].D, image[0].sidtime, image[0].latitude);
+    stars[N].Mcal    = image[0].Mcal;
+    stars[N].t       = image[0].tzero + 1e-4*stars[N].Y*image[0].trate;  /* trate is in 0.1 msec / row */
+    stars[N].dt      = MTIME;
+
+    if ((stars[N].M > 25.0) && (stars[N].M < 32.0)) {
+      fprintf (stderr, "*");
+    }
+
+    // stars->M is either NAN or a valid inst magnitude
+    // stars->dM is either NAN or a valid error
+
+    dMs  = 0.0;
+    dMx = 0.0;
+    if (SUBPIX) {
+      dMs = get_subpix (stars[N].X, stars[N].Y);
+      dMx = scat_subpix (stars[N].X, stars[N].Y);
+      if (!isnan(stars[N].dM)) {
+	stars[N].dM = hypot (stars[N].dM, dMx);
+      }
+    }
+
+    if (!isnan(stars[N].M)) {
+      stars[N].M += MTIME - dMs;
+    }
+    if (!isnan(stars[N].Mgal)) {
+      stars[N].Mgal += MTIME - dMs;
+    }
+    if (!isnan(stars[N].Map)) {
+      stars[N].Map += MTIME - dMs;
+    }
+    
+    N ++;
+  }
+  image[0].nstar = N;
+  REALLOCATE (stars, Stars, image[0].nstar);
+  free (instars);
+
+  if (VERBOSE) fprintf (stderr, "read %d stars from target file\n", image[0].nstar);
+  if (VERBOSE) fprintf (stderr, "stars cover region %f,%f - %f,%f\n", RMIN, DMIN, RMAX, DMAX);
+  return (stars);
+}
+
+Stars *MergeStars (Stars *stars, int *Nstars, Stars *instars, int Ninstars) {
+
+  int i, j;
+
+  if (stars == NULL) {
+    ALLOCATE (stars, Stars, Ninstars);
+  } else {
+    REALLOCATE (stars, Stars, *Nstars + Ninstars);
+  }
+
+  for (j = 0, i = *Nstars; i < *Nstars + Ninstars; i++, j++) {
+    stars[i] = instars[j];
+  }
+  
+  *Nstars += Ninstars;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/GetFileMode.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/GetFileMode.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/GetFileMode.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "addstar.h"
+
+// examine the PHU of this file and determine the file mode
+int GetFileMode (Header *header) {
+
+  char ctype[80];
+  int Naxis, Nx, Ny;
+  int simple, extend, haveNaxis, haveNx, haveNy, haveCTYPE;
+
+  gfits_scan (header, "SIMPLE", "%t", 1, &simple);
+  haveNaxis = gfits_scan (header, "NAXIS",  "%d", 1, &Naxis);
+  haveNx    = gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  haveNy    = gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  haveCTYPE = gfits_scan (header, "CTYPE1", "%s", 1, ctype);
+
+  gfits_scan (header, "EXTEND", "%t", 1, &extend);
+    
+  if ((Naxis == 2) || TEXTMODE || !simple) {
+    if (!strcmp (&ctype[4], "-WRP")) {
+      return MOSAIC_CMP;
+    }
+    return SIMPLE_CMP;
+  }
+
+  if (!extend && strcmp (&ctype[4], "-DIS")) {
+    if (!strcmp (&ctype[4], "-WRP")) {
+      return MOSAIC_CMF;
+    }
+    return SIMPLE_CMF;
+  }
+
+  if (!extend && !strcmp (&ctype[4], "-DIS")) {
+    return MOSAIC_PHU;
+  }
+
+  if (extend && strcmp (&ctype[4], "-DIS")) {
+    return SIMPLE_MEF;
+  }
+
+  if (extend && !strcmp (&ctype[4], "-DIS")) {
+    return MOSAIC_MEF;
+  }
+
+  return (NONE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/ImageOptions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/ImageOptions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/ImageOptions.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "addstar.h"
+
+/* set specific options based on the image collection */
+int ImageOptions (AddstarClientOptions *options, Image *images, int Nimages) {
+
+  int i, equivPhotcode;
+  float maxError;
+  PhotCode *photcode;
+
+  // set the radius to the maximum error circle
+  if (options[0].radius == 0) {
+    maxError = 0;
+    for (i = 0; i < Nimages; i++) {
+      maxError = MAX (maxError, 0.02 * images[i].cerror);
+    }
+    options[0].radius = options[0].Nsigma * maxError;
+  }     
+
+  // check that all images have the same equiv photcode and save it
+  equivPhotcode = 0;
+
+  for (i = 0; i < Nimages; i++) {
+    /* MOSAIC_PHU images do not have a photcode */
+    if (!strcmp (&images[0].coords.ctype[4], "-DIS")) continue;
+
+    photcode = GetPhotcodebyCode (images[i].photcode);
+
+    if (equivPhotcode) {
+      if (equivPhotcode != photcode[0].equiv) {
+	fprintf (stderr, "ERROR: mismatch in equiv photcode values\n");
+	exit (2);
+      }
+    } else {
+      equivPhotcode = photcode[0].equiv;
+    }
+  }
+  options[0].photcode = equivPhotcode;
+
+  options[0].imageID = 0;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/ListenClients_Thread.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/ListenClients_Thread.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/ListenClients_Thread.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "addstar.h"
+
+/* wait for incoming messages from clients */
+void *ListenClients_Thread (void *data) {
+
+  int status, InitSocket, BindSocket;
+  SockAddress Address;
+  IOBuffer message;
+  
+  /* if we have multiple threads, each one creates its own socket? */
+  InitSocket = InitServerSocket (&Address);
+  
+  while (1) {
+
+    /* wait for clients to make connection */
+    BindSocket = WaitServerSocket (InitSocket, &Address, VALID_IP, NVALID);
+    if (BindSocket == -1) continue;
+
+    /* validate : wait for password */
+    if (!CheckPassword (BindSocket)) continue;
+    
+    /* accept command : XXX EAM : long-enough timeout? */
+    status = ExpectCommand (BindSocket, 5, 0.1, &message);
+    if (status != 0) {
+      if (VERBOSE) fprintf (stderr, "failed connection\n");
+      FreeIOBuffer (&message);
+      close (BindSocket);
+      continue;
+    }
+
+    /* message options */
+    if (!strcmp (message.buffer, "IMAGE")) {
+      fprintf (stderr, "Image\n");
+      NewImage_Thread (BindSocket);
+      continue;
+    }
+    if (!strcmp (message.buffer, "REFLS")) {
+      fprintf (stderr, "Reflist\n");
+      NewReflist_Thread (BindSocket);
+      continue;
+    }
+    if (!strcmp (message.buffer, "REFCT")) {
+      fprintf (stderr, "Refcat\n");
+      NewRefcat_Thread (BindSocket);
+      continue;
+    }
+    if (!strcmp (message.buffer, "EXIT")) {
+      /* need to send this signal to the main thread */
+      fprintf (stderr, "Exit\n");
+      exit (2);
+    }
+  }    
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/LoadStars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/LoadStars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/LoadStars.c	(revision 16632)
@@ -0,0 +1,264 @@
+# include "addstar.h"
+
+Stars *LoadStars (char *filename, int *Nstars, Image **images, int *Nimages, int photcode) {
+
+  int i, Nfile, Nheaders, NheaderSets, mode, *extsize;
+  char **file;
+  FILE *f;
+  glob_t globList;
+  Header **headers;
+  Stars *stars;
+  HeaderSet *headerSets;
+
+  // parse the filename as a glob
+  globList.gl_offs = 0;
+  glob (filename, 0, NULL, &globList);
+
+  // if the glob does not match, save the literal word:
+  // otherwise save all glob matches
+  if (globList.gl_pathc == 0) {
+    Nfile = 1;
+    ALLOCATE (file, char *, Nfile);
+    file[0] = strcreate (filename);
+  } else {
+    Nfile = globList.gl_pathc;
+    ALLOCATE (file, char *, Nfile);
+    for (i = 0; i < Nfile; i++) {
+      file[i] = strcreate (globList.gl_pathv[i]);
+    }
+  }
+
+  *Nimages = 0;
+  *Nstars = 0;
+  *images = NULL;
+  stars = NULL;
+
+  for (i = 0; i < Nfile; i++) {
+    f = fopen (file[i], "r");
+    if (f == NULL) {
+      fprintf (stderr, "can't read file %s, skipping\n", file[i]);
+      continue;
+    }
+
+    headers = LoadHeaders (f, &mode, &Nheaders);
+    headerSets = MatchHeaders (&extsize, &NheaderSets, mode, headers, Nheaders);
+    if (headerSets == NULL) {
+      fprintf (stderr, "ERROR: can't read headers for %s\n", file[i]);
+      continue;
+    }
+    if (NheaderSets == 0) {
+      fprintf (stderr, "no object data in file %s, skipping\n", file[i]);
+      continue;
+    }
+    if (VERBOSE) fprintf (stderr, "file %s has %d headers, including %d images\n", file[i], Nheaders, NheaderSets);
+
+    /* supplied photcode is incompatible with multi-chip images */
+    if ((NheaderSets > 1) && photcode) {
+      fprintf (stderr, "ERROR: photcode cannot be supplied to multi-chip images -- manually adjust the headers\n");
+      exit (1);
+    }
+
+    LoadData (f, file[i], images, Nimages, &stars, Nstars, headers, extsize, headerSets, NheaderSets);
+  }
+
+  if (*Nimages == 0) {
+    if (Nfile == 1) 
+      fprintf (stderr, "no valid image data in any of these files, giving up\n");
+    else 
+      fprintf (stderr, "no valid image data in this file, giving up\n");
+    exit (0);
+  }
+
+  return stars;
+}
+
+// load all of the headers, jump in file to skip data segments
+Header **LoadHeaders (FILE *f, int *mode, int *Nheaders) {
+
+  int i, status, Nskip, NHEADERS;
+  Header **headers;
+
+  /* we need to examine the extensions to determine the headers and the data */
+  NHEADERS = 10;
+  ALLOCATE (headers, Header *, NHEADERS);
+
+  // load all headers into memory
+  for (i = 0;; i++) {
+    ALLOCATE (headers[i], Header, 1);
+    status = gfits_fread_header (f, headers[i]);
+    if (!status) { 
+      *Nheaders = i;
+      return (headers);
+    }
+
+    // check the mode for this file
+    if (i == 0) {
+      *mode = GetFileMode (headers[0]);
+      if ((*mode == SIMPLE_CMP) || (*mode == MOSAIC_CMP)) {
+	*Nheaders = i;
+	return (headers);
+      }
+    }
+
+    // advance to the next header
+    Nskip = gfits_data_size (headers[i]);
+    fseek (f, Nskip, SEEK_CUR); 
+    if (i == NHEADERS - 1) {
+      NHEADERS += 10;
+      REALLOCATE (headers, Header *, NHEADERS);
+    }
+  }
+}
+
+HeaderSet *MatchHeaders (int **extsize, int *nimage, int mode, Header **headers, int Nheaders) {
+
+  int i, j, Nimage, NIMAGE;
+  char extname[80], exttype[80], exthead[80];
+  HeaderSet *headerSets;
+
+  ALLOCATE (extsize[0], int, Nheaders);
+
+  Nimage = 0;
+  NIMAGE = 10;
+  ALLOCATE (headerSets, HeaderSet, NIMAGE);
+
+  // what is the mode of the first header (ie, do we have a PHU DIS image?)
+  mode = GetFileMode (headers[0]);
+
+  if (mode == MOSAIC_MEF) {
+    headerSets[Nimage].exthead     = strcreate ("PHU");
+    headerSets[Nimage].extdata     = strcreate ("NONE");
+    headerSets[Nimage].extnum_data = -1;
+    headerSets[Nimage].extnum_head =  0;
+    Nimage ++;
+  }
+
+  // now examine the headers, count the table entries, find corresponding headers
+  for (i = 0; i < Nheaders; i++) {
+    if (mode == SIMPLE_CMP) {
+      extsize[0][i] = headers[i][0].size;
+    } else {
+      extsize[0][i] = headers[i][0].size + gfits_data_size (headers[i]);
+    }
+    gfits_scan (headers[i], "EXTTYPE", "%s", 1, exttype);
+
+    if (!strcmp (exttype, "SMPDATA")) goto keep;
+    if (!strcmp (exttype, "PS1_DEV_0")) goto keep;
+    if (!strcmp (exttype, "PS1_DEV_1")) goto keep;
+    continue;
+
+  keep:
+    headerSets[Nimage].exttype = strcreate (exttype);
+
+    gfits_scan (headers[i], ExtnameKeyword, "%s", 1, extname);
+    gfits_scan (headers[i], "EXTHEAD", "%s", 1, exthead);
+
+    headerSets[Nimage].extdata     = strcreate (extname);
+    headerSets[Nimage].exthead     = strcreate (exthead);
+    headerSets[Nimage].extnum_data = i;
+    headerSets[Nimage].extnum_head = -1;
+
+    // find the matching exthead entry
+    for (j = 0; j < Nheaders; j++) {
+      if (!gfits_scan (headers[j], ExtnameKeyword, "%s", 1, extname)) continue;
+      if (strcmp (extname, headerSets[Nimage].exthead)) continue;
+      headerSets[Nimage].extnum_head = j;
+      break;
+    }
+
+    // skip or crash on table with missing matching header?
+    if (headerSets[Nimage].extnum_head == -1) {
+      return NULL;
+    }
+    Nimage ++;
+    if (Nimage == NIMAGE) {
+      NIMAGE += 10;
+      REALLOCATE (headerSets, HeaderSet, NIMAGE);
+    }
+  }
+
+  // some old format files did not write EXTTYPE.  they have a single table in the first
+  // extension matched to the header in the PHU
+  if (Nimage == 0) {
+    extsize[0][0] = headers[0][0].size + gfits_data_size (headers[0]);
+    extsize[0][1] = headers[1][0].size + gfits_data_size (headers[1]);
+    gfits_scan (headers[1], ExtnameKeyword, "%s", 1, extname);
+    if (!strcmp (extname, "SMPFILE")) {
+      headerSets[Nimage].extdata     = strcreate (extname);
+      headerSets[Nimage].exttype     = strcreate ("SMPDATA");
+      headerSets[Nimage].exthead     = strcreate ("PHU");
+      headerSets[Nimage].extnum_head = 0;
+      headerSets[Nimage].extnum_data = 1;
+      Nimage = 1;
+    }
+  }
+  
+  *nimage = Nimage;
+  return (headerSets);
+}
+
+// examine the header sets and set the Image entries for the the valid images
+int LoadData (FILE *f, char *file, Image **images, int *nvalid, Stars **stars, int *Nstars, Header **headers, int *extsize, HeaderSet *headerSets, int Nimages) {
+
+  char *name;
+  int i, j, Nvalid, Nhead, Ndata, Nskip;
+  Stars *inStars;
+
+  if (images[0] == NULL) {
+    Nvalid = 0;
+    NVALID = 10;
+    ALLOCATE (images[0], Image, NVALID);
+  } else {
+    Nvalid = *nvalid;
+    NVALID = Nvalid + 10;
+    REALLOCATE (images[0], Image, NVALID);
+  }    
+
+  // find image rootname
+  name = filebasename (file);
+
+  // now run through the images, interpret the headers and read the stars
+  for (i = 0; i < Nimages; i++) {
+    Nhead = headerSets[i].extnum_head;
+
+    if (VERBOSE) fprintf (stderr, "reading header for %s (%s)\n", headerSets[i].exthead, headerSets[i].extdata);
+    if (!ReadImageHeader (headers[Nhead], &images[0][Nvalid], 0)) {
+      fprintf (stderr, "skipping %s\n", headerSets[i].exthead);
+      continue;
+    }
+
+    // XXX use something to set the chip name? EXTNAME?
+    if (!strcmp(headerSets[i].exthead, "PHU") && (Nimages == 1)) {
+      snprintf (images[0][Nvalid].name, 64, "%s", name);
+    } else {
+      snprintf (images[0][Nvalid].name, 64, "%s[%s]", name, headerSets[i].exthead);
+    }
+
+    // skip the table if there is no data segment (eg, mosaic WRP image)
+    if (!strcmp(headerSets[i].extdata, "NONE")) {
+      Nvalid++;
+      if (Nvalid == NVALID) {
+	NVALID += 10;
+	REALLOCATE (images[0], Image, NVALID);
+      }
+      continue;
+    }
+
+    // advance the pointer to the start of the corresponding table block
+    Ndata = headerSets[i].extnum_data;
+    Nskip = 0;
+    for (j = 0; j < Ndata; j++) {
+      Nskip += extsize[j];
+    }
+    fseek (f, Nskip, SEEK_SET); 
+	 
+    inStars = ReadStarsFITS (f, headers[Nhead], headers[Ndata], &images[0][Nvalid].nstar);
+    inStars = FilterStars (inStars, &images[0][Nvalid]);
+    *stars = MergeStars (*stars, Nstars, inStars, images[0][Nvalid].nstar);
+    Nvalid++;
+  }
+  free (name);
+  *nvalid = Nvalid;
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/NewImage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/NewImage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/NewImage.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "addstar.h"
+
+int NewImage (int BindSocket) {
+
+  int N, Nstars, Nimages;
+  Stars *stars;
+  Image *images;
+  Coords *mosaic;
+  AddstarClientOptions *options;
+
+  /* accept incoming data set */
+  if (!Recv_AddstarClientOptions (BindSocket, &options, &N)) {
+    fprintf (stderr, "error: problem receiving options\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many option sets (%d)\n", N);
+    goto reject;
+  }
+
+  if (!Recv_Image (BindSocket, &images, &Nimages)) {
+    fprintf (stderr, "error: problem receiving image data\n");
+    goto reject;
+  }
+
+  if (options[0].mosaic) {
+    if (!Recv_Coords (BindSocket, &mosaic, &N)) {
+      fprintf (stderr, "error: problem receiving mosaic coordinates\n");
+      goto reject;
+    }
+    if (N != 1) {
+      fprintf (stderr, "error: invalid number of mosaic coords (%d)\n", N);
+      goto reject;
+    }
+  }    
+
+  if (!Recv_Stars (BindSocket, &stars, &Nstars)) {
+    fprintf (stderr, "error: problem receiving star data\n");
+    goto reject;
+  }
+  fprintf (stderr, "accepted %d images, %d stars\n", Nimages, Nstars);
+
+  /* add to db */
+  UpdateDatabase_Image (options, images, Nimages, mosaic, stars, Nstars);
+
+  close (BindSocket);
+  return (TRUE);
+
+reject:
+  close (BindSocket);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/NewImage_Thread.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/NewImage_Thread.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/NewImage_Thread.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "addstar.h"
+
+int NewImage_Thread (int BindSocket) {
+
+  int N, Nstars, Nimages;
+  Stars *stars;
+  Image *images;
+  Coords *mosaic;
+  AddstarClientOptions *options;
+  DVO_DATA *dataset;
+
+  /* accept incoming data set */
+  if (!Recv_AddstarClientOptions (BindSocket, &options, &N)) {
+    fprintf (stderr, "error: problem receiving options\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many option sets (%d)\n", N);
+    goto reject;
+  }
+
+  if (!Recv_Image (BindSocket, &images, &Nimages)) {
+    fprintf (stderr, "error: problem receiving image data\n");
+    goto reject;
+  }
+
+  if (options[0].mosaic) {
+    if (!Recv_Coords (BindSocket, &mosaic, &N)) {
+      fprintf (stderr, "error: problem receiving mosaic coordinates\n");
+      goto reject;
+    }
+    if (N != 1) {
+      fprintf (stderr, "error: invalid number of mosaic coords (%d)\n", N);
+      goto reject;
+    }
+  }    
+
+  if (!Recv_Stars (BindSocket, &stars, &Nstars)) {
+    fprintf (stderr, "error: problem receiving star data\n");
+    goto reject;
+  }
+  fprintf (stderr, "accepted %d, %d stars\n", Nimages, Nstars);
+
+  /* create new dataset to store the incoming data */
+  ALLOCATE (dataset, DVO_DATA, 1);
+  dataset[0].options = options;
+  dataset[0].patch   = NULL;
+  dataset[0].refcat  = NULL;
+  dataset[0].images  = images;
+  dataset[0].Nimages = Nimages;
+  dataset[0].mosaic  = mosaic;
+  dataset[0].stars   = stars;
+  dataset[0].Nstars  = Nstars;
+
+  /* place on dataset stack */
+  PushDataset (dataset);
+
+  /* close connection, return */
+  close (BindSocket);
+  return (TRUE);
+
+reject:
+  close (BindSocket);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/NewRefcat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/NewRefcat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/NewRefcat.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "addstar.h"
+
+int NewRefcat (int BindSocket) {
+
+  int N, status;
+  AddstarClientOptions *options;
+  IOBuffer message;
+  SkyRegion *patch;
+
+  /* accept incoming data set */
+  if (!Recv_AddstarClientOptions (BindSocket, &options, &N)) {
+    fprintf (stderr, "error: problem receiving options\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many option sets (%d)\n", N);
+    goto reject;
+  }
+
+  if (!Recv_SkyRegion (BindSocket, &patch, &N)) {
+    fprintf (stderr, "error: problem receiving patch\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many patches (%d)\n", N);
+    goto reject;
+  }
+
+  status = ExpectMessage (BindSocket, 0.25, &message);
+  if (status != 0) {
+    if (VERBOSE) fprintf (stderr, "failed connection\n");
+    FreeIOBuffer (&message);
+    goto reject;
+  }
+
+  /* add to db */
+  UpdateDatabase_Refcat (options, patch, message.buffer);
+
+  close (BindSocket);
+  return (TRUE);
+
+reject:
+  close (BindSocket);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/NewRefcat_Thread.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/NewRefcat_Thread.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/NewRefcat_Thread.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "addstar.h"
+
+int NewRefcat_Thread (int BindSocket) {
+
+  int N, status;
+  AddstarClientOptions *options;
+  IOBuffer message;
+  SkyRegion *patch;
+  DVO_DATA *dataset;
+
+  /* accept incoming data set */
+  if (!Recv_AddstarClientOptions (BindSocket, &options, &N)) {
+    fprintf (stderr, "error: problem receiving options\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many option sets (%d)\n", N);
+    goto reject;
+  }
+
+  if (!Recv_SkyRegion (BindSocket, &patch, &N)) {
+    fprintf (stderr, "error: problem receiving patch\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many patches (%d)\n", N);
+    goto reject;
+  }
+
+  status = ExpectMessage (BindSocket, 0.25, &message);
+  if (status != 0) {
+    if (VERBOSE) fprintf (stderr, "failed connection\n");
+    FreeIOBuffer (&message);
+    goto reject;
+  }
+
+  /* add to db */
+  UpdateDatabase_Refcat (options, patch, message.buffer);
+
+  /* create new dataset to store the incoming data */
+  ALLOCATE (dataset, DVO_DATA, 1);
+  dataset[0].options = options;
+  dataset[0].patch   = patch;
+  dataset[0].refcat  = message.buffer;
+  dataset[0].images  = NULL;
+  dataset[0].mosaic  = NULL;
+  dataset[0].stars   = NULL;
+  dataset[0].Nstars  = 0;
+
+  /* place on dataset stack */
+  PushDataset (dataset);
+
+  close (BindSocket);
+  return (TRUE);
+
+reject:
+  close (BindSocket);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/NewReflist.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/NewReflist.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/NewReflist.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "addstar.h"
+
+int NewReflist (int BindSocket) {
+
+  int N, Nstars;
+  Stars *stars;
+  AddstarClientOptions *options;
+
+  /* accept incoming data set */
+  if (!Recv_AddstarClientOptions (BindSocket, &options, &N)) {
+    fprintf (stderr, "error: problem receiving options\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many option sets (%d)\n", N);
+    goto reject;
+  }
+
+  if (!Recv_Stars (BindSocket, &stars, &Nstars)) {
+    fprintf (stderr, "error: problem receiving star data\n");
+    goto reject;
+  }
+  fprintf (stderr, "accepted %d stars\n", Nstars);
+
+  /* add to db */
+  UpdateDatabase_Reflist (options, stars, Nstars);
+
+  close (BindSocket);
+  return (TRUE);
+
+reject:
+  close (BindSocket);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/NewReflist_Thread.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/NewReflist_Thread.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/NewReflist_Thread.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "addstar.h"
+
+int NewReflist_Thread (int BindSocket) {
+
+  int N, Nstars;
+  Stars *stars;
+  AddstarClientOptions *options;
+  DVO_DATA *dataset;
+
+  /* accept incoming data set */
+  if (!Recv_AddstarClientOptions (BindSocket, &options, &N)) {
+    fprintf (stderr, "error: problem receiving options\n");
+    goto reject;
+  }
+  if (N != 1) {
+    fprintf (stderr, "error: too many option sets (%d)\n", N);
+    goto reject;
+  }
+
+  if (!Recv_Stars (BindSocket, &stars, &Nstars)) {
+    fprintf (stderr, "error: problem receiving star data\n");
+    goto reject;
+  }
+  fprintf (stderr, "accepted %d stars\n", Nstars);
+
+  /* create new dataset to store the incoming data */
+  ALLOCATE (dataset, DVO_DATA, 1);
+  dataset[0].options = options;
+  dataset[0].patch   = NULL;
+  dataset[0].refcat  = NULL;
+  dataset[0].images  = NULL;
+  dataset[0].mosaic  = NULL;
+  dataset[0].stars   = stars;
+  dataset[0].Nstars  = Nstars;
+
+  /* place on dataset stack */
+  PushDataset (dataset);
+
+  close (BindSocket);
+  return (TRUE);
+
+reject:
+  close (BindSocket);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadImageHeader.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadImageHeader.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadImageHeader.c	(revision 16632)
@@ -0,0 +1,167 @@
+# include "addstar.h"
+
+/* read an image header corresponding to a CMF / CMP data block */
+// XXX need to pass AddstarClientOptions?
+int ReadImageHeader (Header *header, Image *image, int photcode) {
+
+  int Nastro, ccdnum, hour, min, Nx, Ny;
+  double tmp, sec, Cerror, ZeroPt;
+  char *c, photname[64], line[80];
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, header)) {
+    fprintf (stderr, "no astrometric solution in header\n");
+    return (FALSE);
+  }
+  // XXX currently, image uses an unsigned short for NX,XY. this is rather restrictive
+  // and needs to be at least checked.
+  gfits_scan (header, "NAXIS1",   "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",   "%d", 1, &Ny);
+  if ((Nx < 0) || (Nx > 0xffff)) {
+    fprintf (stderr, "WARNING: NX, NY out of range : image boundary will be wrong\n");
+  }
+  image[0].NX = Nx;
+  image[0].NY = Ny;
+
+  if (!gfits_scan (header, "TZERO",   "%d",  1, &image[0].tzero) && !ACCEPT_TIME) {
+    image[0].tzero = parse_time (header);
+  }
+
+  /* only load astrometry, NAXIS1,2, and time if this is a MOSAIC_PHU (ctype is ....-DIS) */
+  if (!strcmp (&image[0].coords.ctype[4], "-DIS")) {
+    MOSAIC = &image[0].coords;
+    return (TRUE);
+  }
+
+  /* require Nastro > 0 unless or ACCEPT_ASTROM */
+  Nastro = 0;
+  gfits_scan (header, "NASTRO", "%d", 1, &Nastro);
+  Cerror = 0;
+  gfits_scan (header, "CERROR", "%lf", 1, &Cerror);
+  if (((Nastro == 0) || (Cerror > MAX_CERROR)) && !ACCEPT_ASTROM) {
+    fprintf (stderr, "bad astrometric solution in header\n");
+    return (FALSE);
+  }
+  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) {
+    if (MOSAIC == NULL) {
+      fprintf (stderr, "no mosaic for WRP image (use -mosaic)\n");
+      return (FALSE);
+    }
+    RegisterMosaic (MOSAIC);
+  } else {
+    /* force image to lie in 0-360 range */
+    while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+    while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+  }
+
+  { 
+    double R, D;
+    /* sanity check on the image coordinates */
+    XY_to_RD (&R, &D, 0.5*Nx, 0.5*Ny, &image[0].coords);
+    if (!finite(R) || !finite(D)) {
+      fprintf (stderr, "corrupted header coordinates, skipping\n");
+      return (FALSE);
+    }
+  }
+    
+  /* CERROR in data file is in arcsec */
+  if (!gfits_scan (header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
+  image[0].cerror = tmp * 50.0;
+ 
+  /* get photcode from header */
+  if (photcode == 0) {
+    if (!gfits_scan (header, "PHOTCODE", "%s", 1, photname)) {
+      fprintf (stderr, "photcode not supplied in header\n");
+      return (FALSE);
+    }
+    photcode = GetPhotcodeCodebyName (photname);
+    if (photcode == 0) {
+      fprintf (stderr, "photcode %s not found in photcode table\n", photname);
+      return (FALSE);
+    }
+  }
+  if (photcode == 0) { 
+    fprintf (stderr, "no valid photcode is supplied\n");
+    return (FALSE);
+  }
+  image[0].photcode = photcode;
+
+  image[0].NX -= XOVERSCAN;
+  image[0].NY -= YOVERSCAN;
+  gfits_scan (header, ExptimeKeyword,  "%lf", 1, &tmp);
+  image[0].exptime = tmp;
+  
+  /*** why are we no longer using APMIFIT?? ***/
+  tmp = 0;
+  /* gfits_scan (header, "APMIFIT",  "%lf", 1, &tmp); */
+  image[0].apmifit = tmp;
+
+  tmp = 0;
+  /* gfits_scan (header, "dAPMIFIT", "%lf", 1, &tmp); */
+  image[0].dapmifit = tmp;
+
+  tmp = 0;
+  gfits_scan (header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  gfits_scan (header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  tmp = 0;
+  gfits_scan (header, "FWHM_X",   "%lf", 1, &tmp);
+  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  tmp = 0;
+  gfits_scan (header, "FWHM_Y",   "%lf", 1, &tmp);
+  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  if (STKeyword[0]) {
+    /* get ST (used for airmass calculation) */
+    gfits_scan (header, STKeyword, "%s", 1, line);
+    /* remove ':' characters */
+    for (c = strchr (line, ':'); c != (char *) NULL; c = strchr (line, ':')) { *c = ' '; }
+    sscanf (line, "%d %d %lf", &hour, &min, &sec);
+    image[0].sidtime = hour + min/60.0 + sec/3600.0;
+  } else {
+    double jd;
+    jd = ohana_sec_to_jd (image[0].tzero);
+    image[0].sidtime  = ohana_lst (jd, Longitude);
+  }
+  image[0].latitude = Latitude;
+
+  tmp = 0;
+  gfits_scan (header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  image[0].secz = NAN;
+  if (gfits_scan (header, AirmassKeyword, "%lf", 1, &tmp)) {
+    image[0].secz = tmp;
+  } 
+
+  if (!gfits_scan (header, CCDNumKeyword, "%d", 1, &ccdnum)) {
+    image[0].ccdnum = 0xff;
+  } else {
+    image[0].ccdnum = ccdnum;
+  }
+
+  gfits_scan (header, "ZERO_PT", "%lf", 1, &ZeroPt);
+  if (ZeroPt != GetZeroPoint()) {
+      fprintf (stderr, "inconsistent zero point values: image: %f, config: %f\n", ZeroPt, GetZeroPoint()); 
+      return (FALSE);
+  }
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal = 0.0;
+  image[0].Xm   = NAN_S_SHORT;
+  image[0].code = 0;
+  memset (image[0].dummy, 0, sizeof(image[0].dummy));
+
+  /* find expected number of stars */
+  if (!gfits_scan (header, "NSTARS", "%d", 1, &image[0].nstar) && !NO_STARS) {
+    fprintf (stderr, "can't get NSTARS from header\n");
+    return (FALSE);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadStarsFITS.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadStarsFITS.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadStarsFITS.c	(revision 16632)
@@ -0,0 +1,232 @@
+# include "addstar.h"
+
+// given a file with the pointer at the start of the table block and the 
+// corresponding image header, load the stars from the table
+Stars *ReadStarsFITS (FILE *f, Header *header, Header *in_theader, unsigned int *nstars) {
+
+  int Nskip, Nstars;
+  char type[80];
+  Header theader;
+  FTable table;
+  Stars *stars;
+  
+  if (in_theader == NULL) {
+    table.header = &theader;
+    if (!gfits_fread_header (f, table.header)) Shutdown ("ERROR: can't read table header");
+  } else {
+    table.header = in_theader;
+    Nskip = in_theader[0].size;
+    fseek (f, Nskip, SEEK_CUR); 
+  }
+
+  /* load the table data */
+  if (!gfits_fread_ftable_data (f, &table)) {
+    fprintf (stderr, "ERROR: can't read table header\n");
+    exit (1);
+  }
+
+  if (!gfits_scan (table.header, "EXTTYPE", "%s", 1, type)) {
+    strcpy (type, "SMPDATA");
+  }
+
+  stars = NULL;
+  if (!strcmp (type, "SMPDATA")) {
+    stars = Convert_SMPDATA (&table, &Nstars);
+  }
+  if (!strcmp (type, "PS1_DEV_0")) {
+    stars = Convert_PS1_DEV_0 (&table, &Nstars);
+  }
+  if (!strcmp (type, "PS1_DEV_1")) {
+    stars = Convert_PS1_DEV_1 (&table, &Nstars);
+  }
+  if (stars == NULL) {
+    fprintf (stderr, "ERROR: invalid table type %s\n", type);
+    exit (1);
+  }
+  if (*nstars != Nstars) {
+    fprintf (stderr, "WARNING: inconsistent number of stars? %d vs %d\n", *nstars, Nstars);
+  }
+  *nstars = Nstars;
+  return stars;
+}
+
+Stars *Convert_SMPDATA (FTable *table, int *nstars) {
+
+  int i, Nstars, swapped;
+  double ZeroPt;
+  Stars *stars = NULL;
+  SMPData *smpdata = NULL;
+
+  swapped = FALSE;
+  smpdata = gfits_table_get_SMPData (table, &Nstars, &swapped);
+  ZeroPt = GetZeroPoint();
+
+  /* XXX we need to check at least the size of the loaded table */
+  // XXX use memset to zero-out the elements before setting
+
+  ALLOCATE (stars, Stars, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    stars[i].X      = smpdata[i].X;
+    stars[i].Y      = smpdata[i].Y;
+
+    if ((smpdata[i].M >= ZeroPt) || isnan(smpdata[i].M)) {
+      stars[i].M    = NAN;
+      stars[i].Mgal = NAN;
+      stars[i].Map  = NAN;
+    } else {
+      stars[i].M    = smpdata[i].M;
+      stars[i].Mgal = smpdata[i].M;
+      stars[i].Map  = smpdata[i].M;
+    }
+
+    stars[i].dM     = smpdata[i].dM*0.001;
+    stars[i].dophot = smpdata[i].dophot;
+
+    stars[i].fx     = smpdata[i].fx;
+    stars[i].fy     = smpdata[i].fy;
+    stars[i].df     = smpdata[i].df;
+  }    
+  *nstars = Nstars;
+  return (stars);
+}
+
+Stars *Convert_PS1_DEV_0 (FTable *table, int *nstars) {
+
+  int i, Nstars;
+  double ZeroPt;
+  Stars *stars;
+  PS1_DEV_0 *ps1data;
+
+  ps1data = gfits_table_get_PS1_DEV_0 (table, &Nstars, NULL);
+  ZeroPt = GetZeroPoint();
+
+  ALLOCATE (stars, Stars, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    stars[i].X       = ps1data[i].X;
+    stars[i].Y       = ps1data[i].Y;
+    stars[i].dX      = ps1data[i].dX;
+    stars[i].dY      = ps1data[i].dY;
+    if ((ps1data[i].M >= 0.0) || isnan(ps1data[i].M)) {
+      stars[i].M     = NAN;
+    } else {
+      stars[i].M     = ps1data[i].M + ZeroPt;
+    }
+    stars[i].dM      = ps1data[i].dM;
+    stars[i].Mpeak   = ps1data[i].Mpeak;
+
+    stars[i].sky     = ps1data[i].sky;
+    stars[i].dsky    = ps1data[i].dSky;
+
+    stars[i].fx      = ps1data[i].fx;
+    stars[i].fy      = ps1data[i].fy;
+    stars[i].df      = ps1data[i].df;
+
+    stars[i].psfProb = ps1data[i].psfProb;
+    stars[i].psfQual = ps1data[i].psfQual;
+
+    stars[i].detID   = ps1data[i].detID;
+
+    /* these are set elsewhere */
+    stars[i].R       = 0.0;
+    stars[i].D       = 0.0;
+    stars[i].dR      = 0.0;
+    stars[i].dD      = 0.0;
+
+    stars[i].uR      = 0.0;
+    stars[i].uD      = 0.0;
+    stars[i].duR     = 0.0;
+    stars[i].duD     = 0.0;
+
+    stars[i].P       = 0.0;
+    stars[i].dP      = 0.0;
+
+    stars[i].Mcal    = 0;
+    stars[i].t       = 0;
+    stars[i].dt      = 0;
+    stars[i].airmass = 0;
+    stars[i].code    = 0;
+    stars[i].found   = 0;
+
+    /* these are not used */
+    stars[i].Map     = NAN;
+    stars[i].Mgal    = NAN;
+    stars[i].dophot  = 0;
+  }    
+  *nstars = Nstars;
+  return (stars);
+}
+
+// XXX I need to make the IPP I/O functions and these functions
+// consistent wrt ZERO_POINT....
+Stars *Convert_PS1_DEV_1 (FTable *table, int *nstars) {
+
+  int i, Nstars;
+  double ZeroPt;
+  Stars *stars;
+  PS1_DEV_1 *ps1data;
+
+  ps1data = gfits_table_get_PS1_DEV_1 (table, &Nstars, NULL);
+  ZeroPt = GetZeroPoint();
+
+  ALLOCATE (stars, Stars, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    stars[i].X       = ps1data[i].X;
+    stars[i].Y       = ps1data[i].Y;
+    stars[i].dX      = ps1data[i].dX;
+    stars[i].dY      = ps1data[i].dY;
+    if ((ps1data[i].M >= 0.0) || isnan(ps1data[i].M)) {
+	stars[i].M   = NAN;
+    } else {
+	stars[i].M   = ps1data[i].M + ZeroPt;
+    }
+    stars[i].dM      = ps1data[i].dM;
+    stars[i].Mpeak   = ps1data[i].Mpeak;
+
+    stars[i].sky     = ps1data[i].sky;
+    stars[i].dsky    = ps1data[i].dSky;
+
+    stars[i].fx      = ps1data[i].fx;
+    stars[i].fy      = ps1data[i].fy;
+    stars[i].df      = ps1data[i].df;
+
+    stars[i].psfProb   = ps1data[i].psfProb;
+    stars[i].psfQual   = ps1data[i].psfQual;
+    stars[i].crNsigma  = ps1data[i].crNsigma;
+    stars[i].extNsigma = ps1data[i].extNsigma;
+
+    stars[i].detID     = ps1data[i].detID;
+    stars[i].flags     = ps1data[i].flags;
+
+    // XXX not defined anyway
+    // stars[i].stargal   = ps1data[i].stargal;
+
+    /* these are set elsewhere */
+    stars[i].R       = 0.0;
+    stars[i].D       = 0.0;
+    stars[i].dR      = 0.0;
+    stars[i].dD      = 0.0;
+
+    stars[i].uR      = 0.0;
+    stars[i].uD      = 0.0;
+    stars[i].duR     = 0.0;
+    stars[i].duD     = 0.0;
+
+    stars[i].P       = 0.0;
+    stars[i].dP      = 0.0;
+
+    stars[i].Mcal    = 0;
+    stars[i].t       = 0;
+    stars[i].dt      = 0;
+    stars[i].airmass = 0;
+    stars[i].az      = 0;
+    stars[i].code    = 0;
+    stars[i].found   = 0;
+
+    /* these are not used */
+    stars[i].Map     = NAN;
+    stars[i].Mgal    = NAN;
+    stars[i].dophot  = 0;
+  }    
+  *nstars = Nstars;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadStarsTEXT.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadStarsTEXT.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/ReadStarsTEXT.c	(revision 16632)
@@ -0,0 +1,91 @@
+# include "addstar.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+Stars *ReadStarsTEXT (FILE *f, unsigned int *nstars) {
+
+  int j, N, Nextra, Ninstar, Nskip, Nbytes, nbytes;
+  int done;
+  char *buffer, *c, *c2;
+  double tmp;
+  double ZeroPt;
+  Stars *stars;
+  
+  ZeroPt = GetZeroPoint();
+
+  /* load in stars by blocks of 1000 */
+  N = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+
+  ALLOCATE (stars, Stars, *nstars);
+
+  while (N < *nstars) {
+    /* load next data block */
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = fread (&buffer[Nextra], 1, Nbytes, f);
+    if (nbytes == 0) {
+      *nstars = N;
+      return (stars);
+    }
+    nbytes += Nextra;
+
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	memset (buffer + nbytes, 0, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted %d extra return chars\n", Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	memset (buffer + nbytes, 0, Nskip);
+	if (VERBOSE) fprintf (stderr, "deleted line, %d extra chars\n", Nskip);
+      } else {
+	c = c2;
+      }
+    }
+
+    /* extract data for stars */
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (j = 0; (j < Ninstar) && (N < *nstars); j++, N++) {
+      dparse (&stars[N].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].M,  3, &buffer[j*BYTES_STAR]);
+      if ((stars[N].M > ZeroPt) || isnan(stars[N].M)) {
+	stars[N].M = NAN;
+      }
+
+      /* cmp files carry dM in millimags */
+      dparse (&tmp, 4, &buffer[j*BYTES_STAR]);
+      stars[N].dM = 0.001*tmp;
+
+      dparse (&tmp,         5, &buffer[j*BYTES_STAR]);
+      stars[N].dophot = tmp;
+
+      dparse (&stars[N].Mgal, 7, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Map,  8, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fx,   9, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fy,  10, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].df,  11, &buffer[j*BYTES_STAR]);
+    }
+  }
+  *nstars = N;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDfit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDfit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDfit.c	(revision 16632)
@@ -0,0 +1,222 @@
+# include "sedstar.h"
+
+// XXX a couple of fixes should speed this up a bit: test
+
+int SEDfitCatalog (Catalog *outcat, Catalog *incat, SEDtable *table) {
+  
+  int i, j, m, n, idx, start, done, row, Nsec, Nfit, Nphot;
+  int Nave, Nmeas, NAVE, NMEAS, Nmodel, Nreq;
+  unsigned short USNOred, USNOblu;
+  float color;
+  int *found, valid, *modelRow, *reqRow;
+
+  SEDtableRow sourceValue, sourceError;
+  SEDfit minFit, testFit;
+
+  Nmodel = Nreq = 0;
+  for (i = 0; i < table[0].Nfilter; i++) {
+    if (table[0].mode[i] == SED_REQ) Nreq ++;
+    if (table[0].mode[i] == SED_MODEL) Nmodel ++;
+  }
+  if (Nmodel < 1) {
+    fprintf (stderr, "no model filter defined\n!");
+    exit (2);
+  }
+  if (Nreq < 1) {
+    fprintf (stderr, "no required filter defined\n!");
+    exit (2);
+  }
+
+  ALLOCATE (modelRow, int, Nmodel);
+  for (j = i = 0; i < table[0].Nfilter; i++) {
+    if (table[0].mode[i] == SED_MODEL) { 
+      modelRow[j] = i;
+      j++;
+    }
+  }
+  ALLOCATE (reqRow, int, Nreq);
+  for (j = i = 0; i < table[0].Nfilter; i++) {
+    if (table[0].mode[i] == SED_REQ) { 
+      reqRow[j] = i;
+      j++;
+    }
+  }
+
+  sourceValue.mags = NULL;
+  sourceError.mags = NULL;
+
+  Nsec = GetPhotcodeNsecfilt ();
+  Nave = outcat[0].Naverage;
+  Nmeas = outcat[0].Nmeasure;
+
+  NAVE = 100;
+  NMEAS = 100;
+  REALLOCATE (outcat[0].average, Average, NAVE);
+  REALLOCATE (outcat[0].secfilt, SecFilt, NAVE*Nsec);
+  REALLOCATE (outcat[0].measure, Measure, NMEAS);
+
+  // artificially set USNOred and blu errors to 0.3
+  USNOred = GetPhotcodeCodebyName ("USNO_RED");
+  USNOblu = GetPhotcodeCodebyName ("USNO_BLUE");
+
+  // create holder for the source data
+  ALLOCATE (sourceValue.mags, float, table[0].Nfilter);
+  ALLOCATE (sourceError.mags, float, table[0].Nfilter);
+  ALLOCATE (found, int, table[0].Nfilter);
+
+  if (PLOT) SEDfitInit (table);
+
+  // perform the fit to all sources
+  for (i = 0; i < incat[0].Naverage; i++) {
+
+    // blank out the source array
+    for (j = 0; j < table[0].Nfilter; j++) {
+      sourceValue.mags[j] = 100;
+      found[j] = FALSE;
+    }	
+
+    // load the measurements for this source
+    m = incat[0].average[i].offset;
+    Nphot = 0;
+    for (j = 0; j < incat[0].average[i].Nm; j++) {
+      idx = table[0].hashcode[incat[0].measure[m+j].photcode];
+      if (idx == -1) continue;
+      // only fit the selected photcodes (mode == "fit")
+      if (table[0].mode[idx] == SED_MODEL) continue; 
+      if (table[0].mode[idx] == SED_SAMPLE) continue; 
+      // XXX do something more clever if more than one value exists per photcode
+      sourceValue.mags[idx] = incat[0].measure[m+j].M + table[0].vegaToAB[idx];
+      sourceError.mags[idx] = incat[0].measure[m+j].dM;
+      if (incat[0].measure[m+j].photcode == USNOred) sourceError.mags[idx] = 0.3;
+      if (incat[0].measure[m+j].photcode == USNOblu) sourceError.mags[idx] = 0.3;
+      found[idx] = TRUE;
+      Nphot ++;
+    }
+    if (Nphot < 3) continue;
+
+    // XXX pre-select list of REQ entries; loop over only those?
+    valid = TRUE;
+    for (j = 0; valid && (j < Nreq); j++) {
+      if ((table[0].mode[reqRow[j]] == SED_REQ) && !found[reqRow[j]]) valid = FALSE;
+    }
+    if (!valid) continue;
+
+    // skip sources without ref color
+    if (sourceValue.mags[table[0].codeP] > 50) continue;
+    if (sourceValue.mags[table[0].codeM] > 50) continue;
+    color = sourceValue.mags[table[0].codeP] - sourceValue.mags[table[0].codeM];
+
+    // find tableRow within 0.1 mag of color 
+    // XXX : check on the delta value
+    start = SEDcolorBracket (table, color, 0.05);
+    minFit = SEDchisq (table[0].row[start], &sourceValue, &sourceError, table[0].Nfilter);
+    minFit.row = start;
+
+    // search for min chisq backwards
+    // XXX : check on the delta value
+    done = FALSE;
+    row = start - 1;
+    while (!done && (row > 0)) {
+      testFit = SEDchisq (table[0].row[row], &sourceValue, &sourceError, table[0].Nfilter);
+      if (testFit.chisq < minFit.chisq) {
+	minFit = testFit;
+	minFit.row = row;
+      }
+      if (fabs(table[0].row[row][0].color - color) > 0.25) done = TRUE;
+      row --;
+    }
+
+    // search for min chisq forwards
+    // XXX : check on the delta value
+    done = FALSE;
+    row = start + 1;
+    while (!done && (row < table[0].Nrow)) {
+      testFit = SEDchisq (table[0].row[row], &sourceValue, &sourceError, table[0].Nfilter);
+      if (testFit.chisq < minFit.chisq) {
+	minFit = testFit;
+	minFit.row = row;
+      }
+      if (fabs(table[0].row[row][0].color - color) > 0.25) done = TRUE;
+      row ++;
+    }
+
+    Nfit ++;
+    // create the vectors for the example plots
+    if (PLOT) SEDfitPlot (table, incat[0].average[i].R, incat[0].average[i].D, &minFit, &sourceValue, &sourceError);
+
+    // construct an average object for this object
+    // XXX for now, the output objects will have limited astrometric interpretation...
+    outcat[0].average[Nave].R         = incat[0].average[i].R;
+    outcat[0].average[Nave].D         = incat[0].average[i].D;
+    outcat[0].average[Nave].dR    = 0;
+    outcat[0].average[Nave].dD    = 0;
+    outcat[0].average[Nave].uR    = 0;
+    outcat[0].average[Nave].uD    = 0;
+    outcat[0].average[Nave].duR   = 0;
+    outcat[0].average[Nave].duD   = 0;
+    outcat[0].average[Nave].P     = 0;
+    outcat[0].average[Nave].dP    = 0;
+
+    // XXX for now, set the average mag data to NULL
+    outcat[0].average[Nave].Nm        = 0;
+    outcat[0].average[Nave].Nn        = 0;
+    outcat[0].average[Nave].Xp        = NAN_S_SHORT;
+    outcat[0].average[Nave].offset    = Nmeas;
+    outcat[0].average[Nave].missing   = -1;
+    outcat[0].average[Nave].code      = 0;
+
+    for (j = 0; j < Nsec; j++) {
+      outcat[0].secfilt[Nave*Nsec+j].M  = NAN;
+      outcat[0].secfilt[Nave*Nsec+j].dM = NAN;
+      outcat[0].secfilt[Nave*Nsec+j].Xm = NAN_S_SHORT;
+    }
+
+    // we now have the min chisq row. use this to supply the other filter values....
+    // XXX pre-select the SED_MODEL rows...
+    if (Nmeas + table[0].Nfilter >= NMEAS) {
+	NMEAS += 100 + table[0].Nfilter;
+	REALLOCATE (outcat[0].measure, Measure, NMEAS);
+    }
+
+    for (j = 0; valid && (j < Nmodel); j++) {
+      n = modelRow[j];
+      outcat[0].measure[Nmeas].dR       = 0.0;
+      outcat[0].measure[Nmeas].dD       = 0.0;
+      outcat[0].measure[Nmeas].M        = table[0].row[minFit.row][0].mags[n] + minFit.Md;
+      outcat[0].measure[Nmeas].dM       = 0.0;
+      outcat[0].measure[Nmeas].Mcal     = 0;
+      outcat[0].measure[Nmeas].t        = TIMEREF;
+      outcat[0].measure[Nmeas].averef   = Nave;
+      outcat[0].measure[Nmeas].photcode = table[0].code[n];
+      outcat[0].measure[Nmeas].dophot   = 0;
+      outcat[0].measure[Nmeas].dbFlags  = 0;
+      outcat[0].measure[Nmeas].dt       = 0xffff;
+
+      outcat[0].measure[Nmeas].Mgal     = NAN;
+      outcat[0].measure[Nmeas].airmass  = 0;
+      outcat[0].measure[Nmeas].FWx      = NAN_S_SHORT;
+      outcat[0].measure[Nmeas].FWy      = NAN_S_SHORT;
+      outcat[0].measure[Nmeas].theta    = NAN_S_SHORT;
+
+      outcat[0].average[Nave].Nm++;
+      Nmeas ++;
+    }
+
+    Nave ++;
+    if (Nave >= NAVE) {
+      NAVE += 100;
+      REALLOCATE (outcat[0].average, Average, NAVE);
+      REALLOCATE (outcat[0].secfilt, SecFilt, NAVE*Nsec);
+    }
+  }
+  outcat[0].Naverage  = Nave;
+  outcat[0].Nmeasure  = Nmeas;
+  outcat[0].Nsecf_mem = Nave*Nsec;
+  
+  free (sourceValue.mags);
+  free (sourceError.mags);
+  free (found);
+
+  SEDfitClear ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDops.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDops.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDops.c	(revision 16632)
@@ -0,0 +1,249 @@
+# include "sedstar.h"
+
+// fit the data (with errors) to the given table row
+SEDfit SEDchisq (SEDtableRow *ref, SEDtableRow *data, SEDtableRow *error, int Nfilter) {
+
+  int i;
+  double Sm, Sd, S2, wt, dM;
+  SEDfit fit;
+
+  Sm = Sd = S2 = 0.0;
+
+  for (i = 0; i < Nfilter; i++) {
+    if (data[0].mags[i] > 50.0) continue;
+
+    if (error[0].mags[i] == 0.0) {
+      wt = 1.0;
+    } else {
+      wt = 1.0 / SQ(error[0].mags[i]);
+    }
+
+    dM = data[0].mags[i] - ref[0].mags[i];
+    S2 += SQ(dM) * wt;
+    Sm += dM * wt;
+    Sd += wt;
+  }
+    
+  // row is assigned after fit
+  fit.row = -1;
+  fit.Md = Sm / Sd;
+  fit.chisq = S2 + SQ(fit.Md) * Sd - 2*fit.Md*Sm;
+
+  return (fit);
+}
+
+// find the first table row within 0.1 mag of the requested color (or within 10)
+int SEDcolorBracket (SEDtable *table, float color, float delta) {
+
+  int Nlo, Nhi, N;
+  float tcolor;
+
+  N = Nlo = 0; Nhi = table[0].Nrow;
+  tcolor = table[0].row[Nlo][0].color;
+  while ((Nhi - Nlo > 10) && (fabs(tcolor-color) > delta)) {
+    N = 0.5*(Nlo + Nhi);
+    N = MAX (N, 0);
+    N = MIN (N, table[0].Nrow - 1);
+    tcolor = table[0].row[N][0].color;
+    if (tcolor < color) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  return (N);
+}
+
+SEDtableRow **sort_SEDtable (SEDtableRow *raw, int N) {
+
+  int i;
+
+  SEDtableRow **value;
+  
+  if (N <= 0) return (NULL);
+
+  ALLOCATE (value, SEDtableRow *, N);
+  for (i = 0; i < N; i++) {
+    value[i] = &raw[i];
+  }
+
+# define SWAPFUNC(A,B){ SEDtableRow *temp = value[A]; value[A] = value[B]; value[B] = temp; }
+# define COMPARE(A,B)(value[A][0].color < value[B][0].color)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+  return (value);
+}
+
+static Graphdata graphdata;
+static KapaSection magSection, resSection;
+static int Xgraph;
+static float *fitmags, *fiterrs;
+
+int SEDfitInit (SEDtable *table) {
+
+  Xgraph = KiiOpen ("kapa", "sedstar");
+  KapaInitGraph (&graphdata);
+  SetLimitsRaw (table[0].wavecode, NULL, table[0].Nfilter, &graphdata);
+  graphdata.style = 2;
+  graphdata.ptype = 2;
+  KapaClearSections (Xgraph);
+  magSection.name = strcreate ("mag");
+  magSection.x  = 0;
+  magSection.dx = 1;
+  magSection.y  = 0.5;
+  magSection.dy = 0.5;
+  resSection.name = strcreate ("res");
+  resSection.x  = 0.0;
+  resSection.dx = 1.0;
+  resSection.y  = 0.0;
+  resSection.dy = 0.5;
+    
+  KiiResize (Xgraph, 900, 500);
+  KapaSetFont (Xgraph, "helvetica", 14);
+  ALLOCATE (fitmags, float, table[0].Nfilter);
+  ALLOCATE (fiterrs, float, table[0].Nfilter);
+  return (TRUE);
+}
+
+int SEDfitClear () {
+
+  free (fitmags);
+  free (fiterrs);
+  KiiClose (Xgraph);
+  return (TRUE);
+}
+
+int SEDfitPlot (SEDtable *table, double R, double D, SEDfit *minFit, SEDtableRow *sourceValue, SEDtableRow *sourceError) {
+
+  int j, minRow, Nfilter;
+  double X, Y, Z, RA, DEC;
+  char line[1024], key[20];
+
+  minRow = minFit[0].row;
+  Nfilter = table[0].Nfilter;
+
+  // we want to plot the OBSERVED magnitudes
+  for (j = 0; j < Nfilter; j++) {
+    fitmags[j] = table[0].row[minRow][0].mags[j] + minFit[0].Md;
+  }
+
+  // find plot range
+  SetLimitsRaw (NULL, fitmags, Nfilter, &graphdata);
+  SWAP (graphdata.ymin, graphdata.ymax);
+
+  KapaClearSections (Xgraph);
+  KapaSetSection (Xgraph, &magSection);
+  KapaSetLimits (Xgraph, &graphdata);
+  KapaBox (Xgraph, &graphdata);
+  graphdata.color = KapaColorByName ("blue");
+  graphdata.etype = 0;
+  graphdata.ptype = 7;
+  KapaPrepPlot (Xgraph, Nfilter, &graphdata);
+  KapaPlotVector (Xgraph, Nfilter, table[0].wavecode, "x");
+  KapaPlotVector (Xgraph, Nfilter, fitmags, "y");
+
+  graphdata.color = KapaColorByName ("red");
+  graphdata.etype = 1;
+  graphdata.ptype = 2;
+  for (j = 0; j < Nfilter; j++) {
+    fitmags[j] = 100;
+    fiterrs[j] = 0;
+    if (sourceValue[0].mags[j] > 50) continue;
+    fitmags[j] = sourceValue[0].mags[j];
+    fiterrs[j] = sourceError[0].mags[j];
+  }
+  KapaPrepPlot (Xgraph, Nfilter, &graphdata);
+  KapaPlotVector (Xgraph, Nfilter, table[0].wavecode, "x");
+  KapaPlotVector (Xgraph, Nfilter, fitmags, "x");
+  KapaPlotVector (Xgraph, Nfilter, fiterrs, "dym");
+  KapaPlotVector (Xgraph, Nfilter, fiterrs, "dyp");
+  KapaSendLabel (Xgraph, "model,fit (mags)", 1);
+
+  sprintf (line, "star: %10.6f %10.6f  T: %5.0fK  A_V|: %4.2f  M_D|: %5.2f  &sc&h^2|: %5.2f", 
+	   R, D, 
+	   table[0].row[minRow][0].Temp, 
+	   table[0].row[minRow][0].Av, 
+	   minFit[0].Md, minFit[0].chisq);
+  KapaSendLabel (Xgraph, line, 2);
+  KapaSendLabel (Xgraph, "model,fit (mags)", 1);
+
+  KapaSetSection (Xgraph, &resSection);
+  graphdata.ymin = -1.0;
+  graphdata.ymax = +1.0;
+  KapaSetLimits (Xgraph, &graphdata);
+  KapaBox (Xgraph, &graphdata);
+  graphdata.color = KapaColorByName ("red");
+  graphdata.etype = 1;
+
+  for (j = 0; j < Nfilter; j++) {
+    fitmags[j] = 100;
+    fiterrs[j] = 0;
+    if (sourceValue[0].mags[j] > 50) continue;
+    fitmags[j] = sourceValue[0].mags[j] - minFit[0].Md - table[0].row[minRow][0].mags[j];
+    fiterrs[j] = sourceError[0].mags[j];
+  }
+  KapaPrepPlot (Xgraph, Nfilter, &graphdata);
+  KapaPlotVector (Xgraph, Nfilter, table[0].wavecode, "x");
+  KapaPlotVector (Xgraph, Nfilter, fitmags, "y");
+  KapaPlotVector (Xgraph, Nfilter, fiterrs, "dym");
+  KapaPlotVector (Xgraph, Nfilter, fiterrs, "dyp");
+  KapaSendLabel (Xgraph, "wavelength (nm)", 0);
+  KapaSendLabel (Xgraph, "resid (mags)", 1);
+
+  KiiCursorOn (Xgraph);
+  while (KiiCursorRead (Xgraph, &X, &Y, &Z, &RA, &DEC, key)) {
+    // fprintf (stderr, "window: %f %f (%s)\n", X, Y, key);
+    if (!strcasecmp (key, "Q")) {
+      KiiCursorOff (Xgraph);
+      break;
+    }
+    if (!strcasecmp (key, "ESCAPE")) {
+      KiiCursorOff (Xgraph);
+      PLOT = FALSE;
+      return (TRUE);
+    }
+    if (!strcasecmp (key, "X")) {
+      KiiCursorOff (Xgraph);
+      Shutdown ("quitting sedstar");
+    }
+  }
+  return (TRUE);
+}
+
+void SetLimitsRaw (float *xvec, float *yvec, int Nelements, Graphdata *graphmode) {
+
+  double maxX, minX, maxY, minY, range;
+  int i;
+
+  if (xvec != NULL) {
+    maxX = minX = xvec[0];
+    for (i = 1; i < Nelements; i++) {
+      if (!finite(xvec[i])) continue;
+      maxX = MAX (maxX, xvec[i]);
+      minX = MIN (minX, xvec[i]);
+    }
+    range = maxX - minX;
+    if (range == 0) range = 0.001 * maxX;
+    if (range == 0) range = 0.001;
+    graphmode[0].xmin = minX - 0.05*range;
+    graphmode[0].xmax = maxX + 0.05*range;
+  }
+
+  if (yvec != NULL) {
+    maxY = minY = yvec[0];
+    for (i = 1; i < Nelements; i++) {
+      if (!finite(yvec[i])) continue;
+      maxY = MAX (maxY, yvec[i]);
+      minY = MIN (minY, yvec[i]);
+    }
+    range = maxY - minY;
+    if (range == 0) range = 0.0011 * maxY;
+    if (range == 0) range = 0.0011;
+    graphmode[0].ymin = minY - 0.05*range;
+    graphmode[0].ymax = maxY + 0.05*range;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDtableLoad.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDtableLoad.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SEDtableLoad.c	(revision 16632)
@@ -0,0 +1,83 @@
+# include "sedstar.h"
+
+// XXX where do the colorP and colorM codes come from?
+SEDtable *SEDtableLoad (char *filename) {
+
+  FILE *f;
+  char line[1024], name[64], mode[64];
+  char colornameP[64], colornameM[64];
+  int colorP, colorM, code;
+  int i, Nrow, NROW;
+  SEDtable *table;
+  SEDtableRow *raw;
+
+  ALLOCATE (table, SEDtable, 1);
+
+  // load SED table
+  f = fopen (filename, "r");
+  if (f == NULL) Shutdown ("failure to open SED table");
+
+
+  // XXX add error checks for header data
+  scan_line (f, line);
+  sscanf (line, "%*s %*s %d", &table[0].Nfilter);
+
+  // load SED table photcodes, generate the photcode hashtable
+  ALLOCATE (table[0].hashcode, int, 0x10000);
+  ALLOCATE (table[0].wavecode, float, table[0].Nfilter);
+  ALLOCATE (table[0].vegaToAB, float, table[0].Nfilter);
+  ALLOCATE (table[0].mode,     int,   table[0].Nfilter);
+  ALLOCATE (table[0].code,     int,   table[0].Nfilter);
+
+  for (i = 0; i < 0x10000; i++) table[0].hashcode[i] = -1;
+  for (i = 0; i < table[0].Nfilter; i++) {
+    scan_line (f, line);
+    sscanf (line, "%*s %s %f %f %s", name, &table[0].wavecode[i], &table[0].vegaToAB[i], mode);
+    code = GetPhotcodeCodebyName (name);
+    table[0].code[i] = code;
+    if (code == 0) Shutdown ("undefined photcode in SED table");
+    table[0].hashcode[code] = i;
+
+    table[0].mode[i] = -1;     
+    if (!strcasecmp(mode, "fit")) table[0].mode[i] = SED_FIT; 
+    if (!strcasecmp(mode, "req")) table[0].mode[i] = SED_REQ; 
+    if (!strcasecmp(mode, "model")) table[0].mode[i] = SED_MODEL; 
+    if (!strcasecmp(mode, "sample")) table[0].mode[i] = SED_SAMPLE; 
+    if (table[0].mode[i] == -1) Shutdown ("invalid photcode mode in SED table");
+  }
+
+  // load color key
+  scan_line (f, line);
+
+  // define the selection color codes
+  sscanf (line, "# %s - %s", colornameP, colornameM);
+  colorP = GetPhotcodeCodebyName (colornameP);
+  colorM = GetPhotcodeCodebyName (colornameM);
+  table[0].codeP = table[0].hashcode[colorP];
+  table[0].codeM = table[0].hashcode[colorM];
+  if (table[0].codeP == -1) Shutdown ("missing positive color filter");
+  if (table[0].codeM == -1) Shutdown ("missing positive color filter");
+    
+  // load the SED raw table rows
+  Nrow = 0;
+  NROW = 100;
+  ALLOCATE (raw, SEDtableRow, NROW);
+  while (scan_line(f, line) != EOF) {
+    stripwhite (line);
+    if (line[0] == '#') continue;
+    fparse (&raw[Nrow].Temp, 1, line);
+    fparse (&raw[Nrow].Av, 2, line);
+    ALLOCATE (raw[Nrow].mags, float, table[0].Nfilter);
+    for (i = 0; i < table[0].Nfilter; i++) {
+      fparse (&raw[Nrow].mags[i], i + 3, line);
+    }
+    raw[Nrow].color = raw[Nrow].mags[table[0].codeP] - raw[Nrow].mags[table[0].codeM];
+    Nrow ++;
+    CHECK_REALLOCATE (raw, SEDtableRow, NROW, Nrow, 100);
+  }      
+
+  // sort the SEDtable by the reference colors
+  table[0].row = sort_SEDtable (raw, Nrow);
+  table[0].Nrow = Nrow;
+  return (table);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "addstar.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect these signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored (POSIX.1-1990) */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored (POSIX.1-1990) */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore (POSIX.1-1990) */
+    case SIGCONT:    /* continue - maintain this action (POSIX.1-1990) */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? (POSIX.1-1990) */
+    case SIGURG:     /* socket signal, ignore this (POSIX.1-2001) */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "addstar.h"
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format) + 2);
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyListForStars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyListForStars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyListForStars.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "addstar.h"
+
+SkyList *SkyListForStars (SkyTable *table, int depth, Stars *stars, int Nstars) {
+  
+  int i, j, Nr, NR;
+  SkyList *here;
+  SkyList *list;
+  
+  Nr = 0;
+  NR = 10;
+  ALLOCATE (list, SkyList, 1);
+  ALLOCATE (list[0].regions,  SkyRegion *, NR);
+  ALLOCATE (list[0].filename, char *, NR);
+  list[0].Nregions = Nr;
+  list[0].ownElements = FALSE; // free these elements when freeing the list
+
+  sort_stars_ra (stars, Nstars); /* sort by RA */
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].found) continue;
+    here = SkyRegionByPoint (table, depth, stars[i].R, stars[i].D);
+    stars[i].found = TRUE;
+    /* search forward for all contained stars */
+    for (j = i; j < Nstars; j++) {
+      if (stars[j].R >= here[0].regions[0][0].Rmax) break;
+      if (stars[j].R <  here[0].regions[0][0].Rmin) break;
+      if (stars[j].D <  here[0].regions[0][0].Dmin) continue;
+      if (stars[j].D >= here[0].regions[0][0].Dmax) continue;
+      stars[j].found = TRUE;
+    }
+    list[0].regions[Nr] = here[0].regions[0];
+    list[0].filename[Nr] = here[0].filename[0];
+    SkyListFree (here); 
+    Nr ++;
+    if (Nr >= NR) {
+	NR += 32;
+	REALLOCATE (list[0].regions, SkyRegion *, NR);
+	REALLOCATE (list[0].filename, char *, NR);
+    }
+    list[0].Nregions = Nr;
+  }
+
+  /* reset to -1 for all stars: required start for find_match_refstars */
+  for (i = 0; i < Nstars; i++) stars[i].found = -1; 
+  return (list);
+}
+
+/* given a list of stars, find all region files which contain them 
+
+   - sort by ra
+   - loop over stars
+     - find region file which contains star
+     - go forwards until ra > Rmax
+       - mark all stars in this region file
+     
+   - use DEC band information?
+   - would like to minimize the number of disk reads
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyRegionUtils.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyRegionUtils.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyRegionUtils.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "addstar.h"
+
+SkyList *SkyListExistingSubset (SkyList *input, char *path) {
+  
+  int i, status, Nsubset, NSUBSET;
+  SkyList *subset;
+  struct stat filestats;
+  
+  Nsubset = 0;
+  NSUBSET = 100;
+  ALLOCATE (subset, SkyList, 1);
+  ALLOCATE (subset[0].regions, SkyRegion *, NSUBSET);
+  subset[0].ownElements = FALSE; // free these elements when freeing the list
+
+  /* match the basename against the GSCRegion file names */
+  for (i = 0; i < input[0].Nregions; i++) {
+    status = stat (input[0].filename[i], &filestats);
+    if ((status == -1) && (errno == ENOENT)) continue;
+    /* give an error for other conditions? */
+
+    subset[0].regions[Nsubset] = input[0].regions[i];
+    Nsubset ++;
+    CHECK_REALLOCATE (subset[0].regions, SkyRegion *, NSUBSET, Nsubset, 100);
+    subset[0].Nregions = Nsubset;
+  }
+  return (subset);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyTableFromTychoIndex.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyTableFromTychoIndex.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SkyTableFromTychoIndex.c	(revision 16632)
@@ -0,0 +1,152 @@
+# include "dvo.h"
+# define NBANDS 24
+# define NDIV 4
+
+static double DecBands[] = {0.0, +7.5, +15.0, +22.5, +30.0, +37.5, +45.0, +52.5, +60.0, +67.5, +75.0, +82.5, +90.0,
+			    0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+
+static char *DecNames[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", "n5230", "n6000", "n6730", "n7500", "n8230", "none",
+			   "s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", "s5230", "s6000", "s6730", "s7500", "s8230", "none"};
+
+SkyTable *SkyTableFromTychoIndex (char *filename, int VERBOSE) {
+
+  int i, No, Nr, NR, Ntycho;
+  double Dmin, Dmax;
+  char line[256];
+  FILE *f;
+  SkyTable *skytable;
+  SkyRegion *regions;
+  SkyRegion *tycho;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    if (VERBOSE) fprintf (stderr, "can't find Tycho Index file %s\n", filename);
+    return (NULL);
+  }
+
+  /* load in table data */
+  ALLOCATE (tycho, SkyRegion, 10000);
+  for (i = 0; i < 10000; i++) {
+    if (scan_line (f, line) == EOF) break;
+    tycho[i].Rmin = atof (&line[15]);
+    tycho[i].Rmax = atof (&line[22]);
+    tycho[i].Dmin = atof (&line[29]);
+    tycho[i].Dmax = atof (&line[36]);
+
+    memset (tycho[i].name, 0, 21);
+    strncpy (tycho[i].name, line, 7);
+    tycho[i].name[7] = 0;
+  }
+  Ntycho = i;
+  fclose (f);
+
+  /* build supporting level 0 and 1 regions */
+  Nr = 0;
+  NR = 100;
+  ALLOCATE (regions, SkyRegion, 100);
+  
+  /* level 0 : full sky */
+  regions[Nr].Rmin 	=   0;
+  regions[Nr].Rmax 	= 360;
+  regions[Nr].Dmin 	= -90;
+  regions[Nr].Dmax 	= +90;
+  regions[Nr].index  	=  0;
+  regions[Nr].depth  	=  0;
+  regions[Nr].parent 	= -1;
+  regions[Nr].child  	=  TRUE;
+  regions[Nr].table  	=  FALSE;
+  memset (regions[Nr].name, 0, 21);
+  strcpy (regions[Nr].name, "fullsky");
+  
+  No = Nr;
+  Nr ++;
+
+  /* level 1 : add the dec bands */
+  regions[No].childS = Nr;
+  /* first north */
+  for (i = 0; i < 12; i++, Nr++) {
+    regions[Nr].Rmin   	  =   0;
+    regions[Nr].Rmax   	  = 360;
+    regions[Nr].Dmin   	  = DecBands[i];
+    regions[Nr].Dmax   	  = DecBands[i+1];
+    regions[Nr].index  	  =  i+1;
+    regions[Nr].depth  	  =  1;
+    regions[Nr].parent 	  =  0;
+    regions[Nr].child  	  =  TRUE;
+    regions[Nr].table  	  =  FALSE;
+    memset (regions[Nr].name, 0, 21);
+    strcpy (regions[Nr].name, DecNames[i]);
+  }
+  /* now south */
+  for (i = 0; i < 12; i++, Nr++) {
+    regions[Nr].Rmin   	  =   0;
+    regions[Nr].Rmax   	  = 360;
+    regions[Nr].Dmin   	  = DecBands[i+14];
+    regions[Nr].Dmax   	  = DecBands[i+13];
+    regions[Nr].index  	  =  i+1;
+    regions[Nr].depth  	  =  1;
+    regions[Nr].parent 	  =  0;
+    regions[Nr].child  	  =  TRUE;
+    regions[Nr].table  	  =  FALSE;
+    memset (regions[Nr].name, 0, 21);
+    strcpy (regions[Nr].name, DecNames[i+13]);
+  }
+  regions[No].childE = Nr;
+
+  CHECK_REALLOCATE (regions, SkyRegion, NR, Nr, 100);
+
+  /* level 2 : copy the data from the GSC Region files */
+  No = 1;
+  Dmin = regions[No].Dmin - 0.2;
+  Dmax = regions[No].Dmax + 0.2;
+  regions[No].childS = Nr;
+
+  for (i = 0; i < Ntycho; i++) {
+    /* if we are outside of current region, go to the next one */
+    if ((tycho[i].Dmin < Dmin) || (tycho[i].Dmax > Dmax)) {
+      regions[No].childE = Nr;
+
+      No++;
+      Dmin = regions[No].Dmin - 0.2;
+      Dmax = regions[No].Dmax + 0.2;
+      regions[No].childS = Nr;
+
+      if ((tycho[i].Dmin < Dmin) || (tycho[i].Dmax > Dmax)) {
+	fprintf (stderr, "ERROR: tycho index is not in order!\n");
+	exit (1);
+      }
+    }
+
+    /* set the values for this region */
+    regions[Nr].Rmin = tycho[i].Rmin;
+    regions[Nr].Rmax = tycho[i].Rmax;
+    regions[Nr].Dmin = tycho[i].Dmin;
+    regions[Nr].Dmax = tycho[i].Dmax;
+    strcpy (regions[Nr].name, tycho[i].name);
+
+    regions[Nr].index    =  Nr;
+    regions[Nr].depth    =  2;
+    regions[Nr].parent   =  No;
+    regions[Nr].child    =  FALSE;
+    regions[Nr].table    =  FALSE;
+    regions[Nr].childS   =  0;
+    regions[Nr].childE   =  0;
+
+    Nr ++;
+    CHECK_REALLOCATE (regions, SkyRegion, NR, Nr, 100);
+  }
+
+  free (tycho);
+
+  ALLOCATE (skytable, SkyTable, 1);
+  skytable[0].regions = regions;
+  skytable[0].Nregions = Nr;
+
+  ALLOCATE (skytable[0].filename, char *, skytable[0].Nregions);
+  for (i = 0; i < skytable[0].Nregions; i++) {
+    skytable[0].filename[i] = NULL;
+  }
+  if (VERBOSE) fprintf (stderr, "loaded %d tables from tycho index\n", skytable[0].Nregions);
+
+  return (skytable);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/SocketOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/SocketOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/SocketOps.c	(revision 16632)
@@ -0,0 +1,211 @@
+# include "addstar.h"
+
+# define MY_PORT 2000
+# define MY_WAIT 500
+
+int InitServerSocket (SockAddress *Address) {
+
+  int status, InitSocket, length;
+
+# if (0)
+  struct hostent  *host;
+  char tmpline[80], hostip[80];
+
+  host = gethostbyname (hostname);
+  memset (hostip, 0, 80);
+  for (i = 0; i < host[0].h_length; i++) {
+    sprintf (tmpline, "%u", (0xff & host[0].h_addr[i]));
+    strcat (hostip, tmpline);
+    if (i < host[0].h_length - 1) strcat (hostip, ".");
+  }
+# endif
+  
+  Address[0].sin_family = AF_INET;
+  Address[0].sin_port   = MY_PORT;
+  Address[0].sin_addr.s_addr = INADDR_ANY; // use this line to bind any address / port?
+
+# if (0)  
+  status = inet_aton (hostip, &Address[0].sin_addr);
+  if (!status) {
+    fprintf (stderr, "invalid address\n");
+    exit (2);
+  }
+# endif
+
+  length = sizeof(Address[0]);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (2);
+  }
+
+  fprintf (stderr, "init sock: %d, len: %d\n", InitSocket, length);
+  status = bind (InitSocket, (struct sockaddr *) Address, length);
+  if (status == -1) {
+    perror ("bind: ");
+    exit (2);
+  }
+
+  status = listen (InitSocket, 10);
+  if (status == -1) {
+    perror ("listen: ");
+    exit (2);
+  }
+
+  // if (VERBOSE) fprintf (stderr, "socket listening on %s (%s:%d)\n", host[0].h_name, hostip, MY_PORT);
+  return (InitSocket);
+}
+
+int WaitServerSocket (int InitSocket, SockAddress *Address, int *validIP, int Nvalid) {
+
+  int i, BindSocket;
+  socklen_t length;
+  SockAddress Address_in;
+  u_int32_t addr;
+
+  Address_in = Address[0];
+
+  length = sizeof(Address_in);
+
+  /* this is a blocking wait; use in a separate thread */
+  fcntl (InitSocket, F_SETFL, !O_NONBLOCK); 
+
+  fprintf (stderr, "init sock: %d, len: %d\n", InitSocket, length);
+  BindSocket = accept (InitSocket, (struct sockaddr *) &Address_in, &length);
+  fprintf (stderr, "bind sock: %d\n", BindSocket);
+  if (BindSocket == -1) {
+    perror ("accept: ");
+    exit (2);
+  }
+
+  addr = Address_in.sin_addr.s_addr;
+  if (VERBOSE) {
+    fprintf (stderr, "incoming connection from: ");
+    fprintf (stderr, " %u", (0xff & (addr >>  0)));
+    fprintf (stderr, ".%u", (0xff & (addr >>  8)));
+    fprintf (stderr, ".%u", (0xff & (addr >> 16)));
+    fprintf (stderr, ".%u", (0xff & (addr >> 24)));
+    fprintf (stderr, "\n");
+  }
+
+  if (Nvalid == 0) goto accepted;
+
+  for (i = 0; i < Nvalid; i++) {
+    /* valid IP addresses may be machines (120.90.121.142) or 
+       class C networks (120.90.121.0) */
+       
+    /* for machine, address must match */
+    if ((0xff & (validIP[i] >> 24)) != 0) {
+      if (addr == validIP[i]) goto accepted;
+    }
+
+    /* for network, lower three bytes of address must match */
+    if ((0xff & (validIP[i] >> 24)) == 0) {
+      if ((0x00ffffff & addr) == validIP[i]) goto accepted;
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "connection rejected\n");
+  close (BindSocket);
+  return (-1);
+
+accepted:
+  if (VERBOSE) fprintf (stderr, "connection accepted\n");
+  fcntl (BindSocket, F_SETFL, O_NONBLOCK); 
+  return (BindSocket);
+}
+
+int GetClientSocket (char *hostname) {
+
+  int i, status, InitSocket, length;
+  SockAddress Address;
+  struct hostent  *host;
+  char tmpline[80], hostip[80];
+
+  host = gethostbyname (hostname);
+  memset (hostip, 0, 80);
+  for (i = 0; i < host[0].h_length; i++) {
+    sprintf (tmpline, "%u", (0xff & host[0].h_addr[i]));
+    strcat (hostip, tmpline);
+    if (i < host[0].h_length - 1) strcat (hostip, ".");
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "trying %s (%s:%d)...", host[0].h_name, hostip, MY_PORT);
+  }
+
+  Address.sin_family = AF_INET;
+  Address.sin_port   = MY_PORT;
+  status = inet_aton (hostip, &Address.sin_addr);
+  if (!status) {
+    fprintf (stderr, "invalid address\n");
+    exit (2);
+  }
+
+  length = sizeof(Address);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (2);
+  }
+
+  status = connect (InitSocket, (struct sockaddr *) &Address, length);
+  if (status == -1) {
+    perror ("connect: ");
+    exit (2);
+  }
+
+  if (VERBOSE) fprintf (stderr, "connected\n");
+  fcntl (InitSocket, F_SETFL, O_NONBLOCK); 
+  return (InitSocket);
+}
+
+int InitServerSocket_Named (char *hostname, SockAddress *Address) {
+
+  int i, status, InitSocket, length;
+  struct hostent  *host;
+  char tmpline[80], hostip[80];
+
+  host = gethostbyname (hostname);
+  memset (hostip, 0, 80);
+  for (i = 0; i < host[0].h_length; i++) {
+    sprintf (tmpline, "%u", (0xff & host[0].h_addr[i]));
+    strcat (hostip, tmpline);
+    if (i < host[0].h_length - 1) strcat (hostip, ".");
+  }
+  
+  Address[0].sin_family = AF_INET;
+  Address[0].sin_port   = MY_PORT;
+  status = inet_aton (hostip, &Address[0].sin_addr);
+  if (!status) {
+    fprintf (stderr, "invalid address\n");
+    exit (2);
+  }
+
+  length = sizeof(Address[0]);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (2);
+  }
+
+  fprintf (stderr, "init sock: %d, len: %d\n", InitSocket, length);
+  status = bind (InitSocket, (struct sockaddr *) Address, length);
+  if (status == -1) {
+    perror ("bind: ");
+    exit (2);
+  }
+
+  status = listen (InitSocket, 10);
+  if (status == -1) {
+    perror ("listen: ");
+    exit (2);
+  }
+
+  if (VERBOSE) fprintf (stderr, "socket listening on %s (%s:%d)\n", host[0].h_name, hostip, MY_PORT);
+  return (InitSocket);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Image.c	(revision 16632)
@@ -0,0 +1,121 @@
+# include "addstar.h"
+
+int UpdateDatabase_Image (AddstarClientOptions *options, Image *images, int Nimages, Coords *mosaic, Stars *stars, int Nstars) {
+
+  int i, status;
+  Catalog catalog;
+  SkyList *skylist, *newlist;
+
+  if (options[0].mode != M_IMAGE) {
+    fprintf (stderr, "error: expecting only IMAGE mode\n");
+    return (FALSE);
+  }
+
+  catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+  if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
+  
+  // XXX this is probably not needed anymore
+  SetAirmassQuality (options[0].quality_airmass);
+
+  /*** update catalog: average, measure, etc ***/
+
+  /* find correpsonding regions for image */
+  RegisterMosaic (mosaic);
+  skylist = NULL;
+  newlist = NULL;
+  for (i = 0; i < Nimages; i++) {
+      newlist = SkyListByImage (ServerSky, -1, &images[i]);
+      SkyListMerge (&skylist, newlist);
+      SkyListFree (newlist);
+  }
+
+  ImageOptions (options, images, Nimages);
+
+  /* reduce regions to existing subset, if necessary */
+  if (options[0].only_match || options[0].existing_regions) {
+    SkyList *tmp;
+    tmp = SkyListExistingSubset (skylist, CATDIR);
+    SkyListFree (skylist);
+    skylist = tmp;
+  }
+  if (VERBOSE) fprintf (stderr, "writing to %d regions\n", skylist[0].Nregions);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // set the parameters which guide catalog open/load/create
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+    catalog.filename  = skylist[0].filename[i];
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+
+    // Naves_disk == 0 implies an empty catalog file
+    // for only_match, skip empty catalogs 
+    if ((catalog.Naves_disk == 0) && options[0].only_match) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    if (options[0].closest) {
+      find_matches_closest (skylist[0].regions[i], stars, Nstars, &catalog, options[0]);
+    } else {
+      find_matches (skylist[0].regions[i], stars, Nstars, &catalog, options[0]);
+    }
+
+    if (!options[0].only_images) {
+      SetProtect (TRUE);
+      if (options[0].update) {
+	catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
+      SetProtect (FALSE);
+    }
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+
+  if (options[0].calibrate) { FindCalibration (&images[0]); }
+  
+  /*** load image db, save new image ***/
+  { 
+    FITS_DB db;
+
+    /*** update the image table ***/
+    /* setup image table format and lock */
+    db.mode   = dvo_catalog_catmode (CATMODE);
+    db.format = dvo_catalog_catformat (CATFORMAT);
+    status = dvo_image_lock (&db, ImageCat, 60.0, LCK_XCLD);
+    if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+
+    /* load or create the image table */
+    if (db.dbstate == LCK_EMPTY) {
+      if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+      dvo_image_create (&db, GetZeroPoint());
+    } else {
+      if (!dvo_image_load (&db, VERBOSE, FORCE_READ)) {
+	Shutdown ("can't read image catalog %s", db.filename);
+      }
+    }
+
+    /* write out new image */
+    dvo_image_addrows (&db, images, Nimages);
+    SetProtect (TRUE);
+    dvo_image_update (&db, VERBOSE);
+    SetProtect (FALSE);
+    dvo_image_unlock (&db);
+  }
+  free (mosaic);
+  free (images);
+  free (stars);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Refcat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Refcat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Refcat.c	(revision 16632)
@@ -0,0 +1,77 @@
+# include "addstar.h"
+
+int UpdateDatabase_Refcat (AddstarClientOptions *options, SkyRegion *patch, char *refcat) {
+
+  int i, Nstars, Nsubset;
+  Catalog catalog;
+  Stars *stars, **subset;
+  SkyList *skylist;
+
+  if (options[0].mode != M_REFCAT) {
+    fprintf (stderr, "error: expecting only REFCAT mode\n");
+    return (FALSE);
+  }
+
+  if (!check_dir_access (CATDIR, VERBOSE)) exit (1);
+
+  /*** update catalog: average, measure, etc ***/
+  
+  /* find correpsonding regions for image */
+  skylist = SkyListByPatch (ServerSky, -1, patch);
+
+  /* reduce regions to existing subset, if necessary */
+  if (options[0].only_match || options[0].existing_regions) {
+    SkyList *tmp;
+    tmp = SkyListExistingSubset (skylist, CATDIR);
+    SkyListFree (skylist);
+    skylist = tmp;
+  }
+  if (VERBOSE) fprintf (stderr, "writing to %d regions\n", skylist[0].Nregions);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // set the parameters which guide catalog open/load/create
+    catalog.filename  = skylist[0].filename[i];
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
+  
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+
+    // Naves_disk == 0 implies an empty catalog file
+    // for only_match, skip empty catalogs
+    if ((catalog.Naves_disk == 0) && options[0].only_match) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    // load stars from corresponding catalog 
+    stars = grefcat (refcat, skylist[0].regions[i], options[0].photcode, &Nstars);
+
+    subset = find_subset (skylist[0].regions[i], stars, Nstars, &Nsubset);
+    find_matches_refstars (skylist[0].regions[i], subset, Nsubset, &catalog, options[0]);
+    if (Nsubset) free (subset);
+
+    if (!options[0].only_images) {
+      SetProtect (TRUE);
+      if (options[0].update) {
+	catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
+      SetProtect (FALSE);
+    }
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+    free (stars);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Reflist.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Reflist.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/UpdateDatabase_Reflist.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "addstar.h"
+
+int UpdateDatabase_Reflist (AddstarClientOptions *options, Stars *stars, int Nstars) {
+
+  int i, Nsubset;
+  Catalog catalog;
+  Stars **subset;
+  SkyList *skylist;
+
+  if (options[0].mode != M_REFLIST) {
+    fprintf (stderr, "error: expecting only REFLIST mode\n");
+    return (FALSE);
+  }
+
+  if (!check_dir_access (CATDIR, VERBOSE)) exit (1);
+
+  /*** update catalog: average, measure, etc ***/
+  
+  /* find correpsonding regions for image */
+  skylist = SkyListForStars (ServerSky, -1, stars, Nstars);
+
+  /* reduce regions to existing subset, if necessary */
+  if (options[0].only_match || options[0].existing_regions) {
+    SkyList *tmp;
+    tmp = SkyListExistingSubset (skylist, CATDIR);
+    SkyListFree (skylist);
+    skylist = tmp;
+  }
+  if (VERBOSE) fprintf (stderr, "writing to %d regions\n", skylist[0].Nregions);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // set the parameters which guide catalog open/load/create
+    catalog.filename  = skylist[0].filename[i];
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    if (options[0].update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+
+    /* for only_match, skip empty catalogs XXX EAM : this leaves behind empty files */
+    if ((catalog.Naves_disk == 0) && options[0].only_match) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    subset = find_subset (skylist[0].regions[i], stars, Nstars, &Nsubset);
+    find_matches_refstars (skylist[0].regions[i], subset, Nsubset, &catalog, options[0]);
+    if (Nsubset) free (subset);
+
+    if (!options[0].only_images) {
+      SetProtect (TRUE);
+      if (options[0].update) {
+	catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
+      SetProtect (FALSE);
+    }
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+
+  free (stars);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/addstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/addstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/addstar.c	(revision 16632)
@@ -0,0 +1,201 @@
+# include "addstar.h"
+
+int main (int argc, char **argv) {
+
+  int Nmatch, status, loadObjects;
+  int i, Nstars, Nimages, Nsubset;
+  unsigned long long Naverage, Nmeasure;
+  Stars *stars, **subset;
+  Image *images;
+  Catalog catalog;
+  FITS_DB db;
+  AddstarClientOptions options;
+
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+  SkyList *newlist = NULL;
+
+  double dtime;
+  struct timeval start, stop;
+
+  gettimeofday (&start, NULL);
+
+  SetSignals ();
+  options = ConfigInit (&argc, argv);
+  options = args (argc, argv, options);
+
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  if (sky == NULL) {
+      fprintf (stderr, "ERROR: unable to load sky table data\n");
+      exit (2);
+  }
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  stars = NULL;
+
+  /*** load in the new data (images, stars) ***/
+  switch (options.mode) {
+    case M_IMAGE:
+      stars = LoadStars (argv[1], &Nstars, &images, &Nimages, options.photcode);
+      if ((DUMP != NULL) && !strcmp (DUMP, "rawstars")) dump_rawstars (stars, Nstars);
+      for (i = 0; i < Nimages; i++) {
+	newlist = SkyListByImage (sky, -1, &images[i]);
+	SkyListMerge (&skylist, newlist);
+	if (VERBOSE) fprintf (stderr, "added %d regions to yield %d total\n", newlist[0].Nregions, skylist[0].Nregions);
+	SkyListFree (newlist);
+      }
+      ImageOptions (&options, images, Nimages);
+      break;
+    case M_REFLIST:
+      stars = grefstars (argv[1], options.photcode, &Nstars);
+      skylist = SkyListForStars (sky, -1, stars, Nstars);
+      break;
+    case M_RESORT:
+    case M_REFCAT:
+      skylist = SkyListByPatch (sky, -1, &UserPatch);
+      break;
+    case M_FAKEIMAGE:
+      images = fakeimage (argv[1], &Nimages, options.photcode);
+      RegisterMosaic (MOSAIC);
+      ALLOCATE (skylist, SkyList, 1);
+      skylist[0].Nregions = 0;
+      skylist[0].ownElements = FALSE;
+      break;
+
+    default:
+      fprintf (stderr, "ERROR: invalid mode\n");
+      exit (2);
+  }
+
+  // in these cases, limit the sky catalogs to an existing subset
+  if (options.only_match || options.existing_regions) {
+    SkyList *tmp;
+    tmp = SkyListExistingSubset (skylist, CATDIR);
+    SkyListFree (skylist);
+    skylist = tmp;
+  }
+  if (VERBOSE) fprintf (stderr, "writing to %d regions\n", skylist[0].Nregions);
+
+  /* don't load the object tables for only_images, unless we are getting the calibration. */
+  loadObjects = !options.only_images || options.calibrate;
+
+  /* match stars to existing catalog data (or otherwise manipulate catalog data) */
+  Nmatch = Naverage = Nmeasure = 0;
+  for (i = 0; loadObjects && (i < skylist[0].Nregions); i++) {
+
+    // set the parameters which guide catalog open/load/create
+    catalog.filename  = skylist[0].filename[i];
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    if (options.update) catalog.catflags = LOAD_AVES | LOAD_MISS | LOAD_SECF;
+
+    // open as read or write, depending on desire
+    if (options.only_images && options.calibrate) {
+      if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "r")) {
+	continue;
+      }
+    } else {
+      // an error exit status here is a significant error (disk I/O or file access)
+      if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+	fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+	exit (2);
+      }
+    }
+
+    // Naves_disk == 0 implies an empty catalog file
+    // for only_match, skip empty catalogs
+    if ((catalog.Naves_disk == 0) && options.only_match) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    switch (options.mode) {
+      case M_IMAGE:
+	Nsubset = Nstars;
+	if (options.closest) {
+	  Nmatch += find_matches_closest (skylist[0].regions[i], stars, Nstars, &catalog, options);
+	} else {
+	  Nmatch += find_matches (skylist[0].regions[i], stars, Nstars, &catalog, options);
+	}
+	break;
+      case M_REFCAT:
+	stars = grefcat (argv[1], skylist[0].regions[i], options.photcode, &Nstars);
+      case M_REFLIST:
+	subset = find_subset (skylist[0].regions[i], stars, Nstars, &Nsubset);
+	Nmatch += find_matches_refstars (skylist[0].regions[i], subset, Nsubset, &catalog, options);
+	if (Nsubset) free (subset);
+	break;
+      case M_RESORT:
+	if (options.nosort == 3) catalog.sorted = FALSE;
+	resort_catalog (&catalog);
+	Nsubset = 1;
+	break;
+    }
+    /* report total updated values */
+    Naverage += catalog.Naverage;
+    Nmeasure += catalog.Nmeasure;
+
+    // write out catalog, if appropriate
+    if (Nsubset && !options.only_images) {
+      SetProtect (TRUE);
+      if (options.update) {
+	catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	dvo_catalog_update (&catalog, VERBOSE);
+      } else {
+	dvo_catalog_save (&catalog, VERBOSE);
+      }
+      SetProtect (FALSE);
+    }
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+
+    if (options.mode == M_REFCAT) free (stars);
+  }
+
+  // We only measure a single value for the entire mosaic (add all images to this function)
+  if (options.calibrate) { FindCalibration (&images[0]); }
+
+  /*** update the image table ***/
+  /* setup image table format and lock */
+  db.mode   = dvo_catalog_catmode (CATMODE);
+  db.format = dvo_catalog_catformat (CATFORMAT);
+  status    = dvo_image_lock (&db, ImageCat, 3600.0, LCK_XCLD);  // shorter timeout?
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+
+  /* load or create the image table */
+  if (db.dbstate == LCK_EMPTY) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    dvo_image_create (&db, GetZeroPoint());
+  } else {
+    if (!dvo_image_load (&db, VERBOSE, FORCE_READ)) {
+      Shutdown ("can't read image catalog %s", db.filename);
+    }
+  }
+
+  /* add the new images and save */
+  if (options.mode == M_IMAGE) {
+    dvo_image_addrows (&db, images, Nimages);
+    SetProtect (TRUE);
+    dvo_image_update (&db, VERBOSE);
+    SetProtect (FALSE);
+  }
+  dvo_image_unlock (&db); /* unlock? */
+
+  gettimeofday (&stop, NULL);
+  dtime = DTIME (stop, start);
+  fprintf (stderr, "SUCCESS: elapsed time %9.4f sec for %5d stars (%5d matches), %6lld average, %7lld measure\n", dtime, Nstars, Nmatch, Naverage, Nmeasure);
+
+  exit (0);
+}
+
+/* names:
+   catalog - existing object db table
+   regions - sky area which may or may not contain data
+   patch   - RA,DEC bounded portion of sky
+*/
+
+// add in case of failures:
+// ohana_memcheck (FALSE);
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/addstarc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/addstarc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/addstarc.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "addstar.h"
+
+int main (int argc, char **argv) {
+
+  int Nstars, Nimages;
+  int BindSocket;
+  AddstarClientOptions options;
+  Stars *stars;
+  Image *images;
+
+  /* load config and options */
+  options = ConfigInit (&argc, argv);
+  options = args_client (argc, argv, options);
+
+  /* set up server connection */
+  BindSocket = GetClientSocket (HOSTNAME);
+  SendCommand (BindSocket, strlen(PASSWORD), PASSWORD);
+
+  /* send new data to server */
+  switch (options.mode) {
+    case M_IMAGE:
+      /* load data */
+      stars = LoadStars (argv[1], &Nstars, &images, &Nimages, options.photcode);
+
+      /* send data to server */
+      SendCommand (BindSocket, 5, "IMAGE");
+      Send_AddstarClientOptions (BindSocket, &options, 1, TRUE);
+      Send_Image (BindSocket, images, Nimages, FALSE);
+      if (options.mosaic) {
+	Send_Coords (BindSocket, MOSAIC, 1, FALSE);
+      }
+      Send_Stars (BindSocket, stars, Nstars, FALSE);
+      break;
+
+    case M_REFLIST:
+      /* load data */
+      stars = grefstars (argv[1], options.photcode, &Nstars);
+      
+      /* send data to server */
+      SendCommand (BindSocket, 5, "REFLS");
+      Send_AddstarClientOptions (BindSocket, &options, 1, TRUE);
+      Send_Stars (BindSocket, stars, Nstars, FALSE);
+      break;
+
+    case M_REFCAT:
+      /* send data to server */
+      SendCommand (BindSocket, 5, "REFCT");
+      Send_AddstarClientOptions (BindSocket, &options, 1, TRUE);
+      Send_SkyRegion (BindSocket, &UserPatch, 1, TRUE);
+      SendMessage (BindSocket, argv[1]);
+      break;
+
+    default:
+      fprintf (stderr, "unknown addstar mode\n");
+      exit (1);
+  }
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/addstard.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/addstard.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/addstard.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "addstar.h"
+
+int main (int argc, char **argv) {
+
+  int status, InitSocket, BindSocket;
+  SockAddress Address;
+  IOBuffer message;
+  AddstarClientOptions options;
+
+  options = ConfigInit (&argc, argv);
+  args_server (argc, argv);
+
+  /* store the sky table in a global for internal use */
+  ServerSky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (ServerSky, CATDIR, "cpt");
+
+  /* if we separate the incoming data from db update, spawn db thread here */
+
+  VERBOSE = TRUE;
+  InitSocket = InitServerSocket (&Address);
+  
+  while (1) {
+
+    /* wait for clients to make connection */
+    BindSocket = WaitServerSocket (InitSocket, &Address, VALID_IP, NVALID);
+    if (BindSocket == -1) continue;
+
+    /* validate : wait for password */
+    if (!CheckPassword (BindSocket)) continue;
+    
+    /* accept command : XXX EAM : long-enough timeout? */
+    status = ExpectCommand (BindSocket, 5, 0.1, &message);
+    if (status != 0) {
+      if (VERBOSE) fprintf (stderr, "failed connection\n");
+      FreeIOBuffer (&message);
+      close (BindSocket);
+      continue;
+    }
+
+    /* message options */
+    if (!strcmp (message.buffer, "IMAGE")) {
+      fprintf (stderr, "Image\n");
+      NewImage (BindSocket);
+      continue;
+    }
+    if (!strcmp (message.buffer, "REFLS")) {
+      fprintf (stderr, "Reflist\n");
+      NewReflist (BindSocket);
+      continue;
+    }
+    if (!strcmp (message.buffer, "REFCT")) {
+      fprintf (stderr, "Refcat\n");
+      NewRefcat (BindSocket);
+      continue;
+    }
+    if (!strcmp (message.buffer, "EXIT")) {
+      fprintf (stderr, "Exit\n");
+      exit (2);
+    }
+  }    
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/addstart.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/addstart.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/addstart.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "addstar.h"
+# include <pthread.h>
+
+int main (int argc, char **argv) {
+
+  AddstarClientOptions options;
+  pthread_t thread;
+  DVO_DATA *dataset;
+
+  options = ConfigInit (&argc, argv);
+  args_server (argc, argv);
+
+  /* store the sky table in a global for internal use */
+  ServerSky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (ServerSky, CATDIR, "cpt");
+
+  VERBOSE = TRUE;
+
+  InitDataset ();
+
+  // launch thread to listen for client data
+  pthread_create (&thread, NULL, &ListenClients_Thread, NULL);
+
+  // XXX need to watch for shutdown message
+  while (1) {
+
+    dataset = PopDataset ();
+    if (dataset == NULL) {
+      usleep (50000);
+    }
+
+    switch (dataset[0].options[0].mode) {
+      case M_IMAGE:
+	UpdateDatabase_Image (dataset[0].options, dataset[0].images, dataset[0].Nimages, dataset[0].mosaic, dataset[0].stars, dataset[0].Nstars);
+	continue;
+
+      case M_REFLIST:
+	UpdateDatabase_Reflist (dataset[0].options, dataset[0].stars, dataset[0].Nstars);
+	continue;
+
+      case M_REFCAT:
+	UpdateDatabase_Refcat (dataset[0].options, dataset[0].patch, dataset[0].refcat);
+	continue;
+
+      default:
+	fprintf (stderr, "error: unexpected dataset\n");
+    }
+  }    
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/airmass.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/airmass.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/airmass.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "addstar.h"
+
+static int AirmassQuality = FALSE;
+
+void SetAirmassQuality (int quality) {
+  AirmassQuality = quality;
+}
+
+float airmass (float secz_image, double ra, double dec, double st, double latitude) {
+
+  double hour, cosz, secz;
+  double rdec, rlat;
+
+  if (!AirmassQuality) return (secz_image);
+
+  /*** make this optional? we may not have ST... ***/
+  /* ra, dec, latitude in dec deg; st in dec hours */
+
+  /* hour : hour angle in degrees */
+  rdec = RAD_DEG*dec;
+  rlat = RAD_DEG*latitude;
+  hour = 15.0*st - ra;
+  cosz = sin (rdec) * sin (rlat) + cos (rdec) * cos (RAD_DEG*hour) * cos (rlat);
+  secz = 1.000 / cosz;
+  return (secz);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/args.c	(revision 16632)
@@ -0,0 +1,354 @@
+# include "addstar.h"
+static void help (void);
+
+AddstarClientOptions args (int argc, char **argv, AddstarClientOptions options) {
+  
+  int i, N;
+  int QUALITY_AIRMASS;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /*** check for command line options ***/
+
+  /* basic mode: image, list, refcat */
+  options.mode = M_IMAGE;
+  if ((N = get_argument (argc, argv, "-ref"))) {
+    options.mode = M_REFLIST;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-cat"))) {
+    options.mode = M_REFCAT;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-fakeimage"))) {
+    options.mode = M_FAKEIMAGE;
+    remove_argument (N, &argc, argv);
+    FAKE_RA = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    FAKE_DEC = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    FAKE_THETA = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-resort"))) {
+    options.mode = M_RESORT;
+    remove_argument (N, &argc, argv);
+  }
+
+  /*** provide additional data ***/ 
+  /* restrict to a portion of the sky? (REFCAT only) */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else {
+      if (options.mode == M_IMAGE) goto allow;
+      if (options.mode == M_FAKEIMAGE) goto allow;
+      if (options.mode == M_REFLIST) goto allow;
+      if (options.mode == M_REFCAT) {
+	  fprintf (stderr, "you have requested uploading from a catalog to the entire sky in one pass\n");
+      }
+      if (options.mode == M_RESORT) {
+	  fprintf (stderr, "you have requested resorting the entire sky in one pass\n");
+      }
+      fprintf (stderr, "this could be a time consuming operation.  type Ctrl-C within 5 seconds to cancel\n");
+      for (i = 5; i > 0; i--) {
+	  fprintf (stderr, "%d.. ", i);
+	  usleep (1000000);
+      }
+      fprintf (stderr, "\n");
+  }
+allow:
+  /* override any header PHOTCODE values */
+  options.photcode = 0;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    remove_argument (N, &argc, argv);
+    options.photcode = GetPhotcodeCodebyName (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    options.photcode = GetPhotcodeCodebyName (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* provide a time for dataset */
+  TIMEREF = 0; 
+  if ((N = get_argument (argc, argv, "-time"))) {
+    time_t tmp;
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tmp)) { 
+      fprintf (stderr, "syntax error in time\n");
+      exit (1);
+    }
+    TIMEREF = tmp;
+    remove_argument (N, &argc, argv);
+  }
+  /* provide a mosaic for distortion */
+  MOSAIC = NULL;
+  options.mosaic = FALSE;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    Header header;
+    ALLOCATE (MOSAIC, Coords, 1);
+
+    remove_argument (N, &argc, argv);
+    if (!gfits_read_header (argv[N], &header)) {
+      fprintf (stderr, "ERROR: can't read header for mosaic %s\n", argv[N]);
+      exit (1);
+    }
+    if (!GetCoords (MOSAIC, &header)) {
+      fprintf (stderr, "ERROR: no astrometric solution in header\n");
+      exit (1);
+    }
+    if (strcmp(&MOSAIC[0].ctype[4], "-DIS")) {
+      fprintf (stderr, "ERROR: not a mosaic distortion header\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    gfits_free_header (&header);
+    options.mosaic = TRUE;
+  }
+  
+  /*** modify behavior ***/
+  /* only add to existing objects */
+  options.existing_regions = FALSE;
+  if ((N = get_argument (argc, argv, "-existing-regions"))) {
+    options.existing_regions = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* only add to existing objects */
+  options.only_match = FALSE;
+  if ((N = get_argument (argc, argv, "-only-match"))) {
+    options.only_match = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* don't add missed pts to Missed table (image only) */
+  options.skip_missed = TRUE;
+  if ((N = get_argument (argc, argv, "-missed"))) {
+    options.skip_missed = TRUE;
+    remove_argument (N, &argc, argv);
+    fprintf (stderr, "ERROR: addstar no longer supports -missed\n");
+    exit (2);
+  }
+  /* replace measurement, don't duplicate (ref/cat only) */
+  options.replace = FALSE;
+  if ((N = get_argument (argc, argv, "-replace"))) {
+    options.replace = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* use 'closest star' matching, rather than traditional method */
+  options.closest = FALSE;
+  if ((N = get_argument (argc, argv, "-closest"))) {
+    options.closest = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* don't re-sort the measure sequence */
+  options.nosort = FALSE;
+  if ((N = get_argument (argc, argv, "-nosort"))) {
+    options.nosort = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* only add new rows (-update) or re-write complete measure table (forces -nosort) */
+  options.update = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    options.update = TRUE;
+    options.nosort = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-force-sort"))) {
+    options.nosort = 3;  // temporary mode to mean 'force-sort'
+    remove_argument (N, &argc, argv);
+  }
+
+  /* only add image potion to image table */
+  options.only_images = FALSE;
+  if ((N = get_argument (argc, argv, "-image"))) {
+    options.only_images = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* apply average zpt offset calibration (image only) */
+  options.calibrate = FALSE;
+  if ((N = get_argument (argc, argv, "-cal"))) {
+    options.calibrate = TRUE;
+    remove_argument (N, &argc, argv);
+    InitCalibration (FALSE);
+  }
+  if ((N = get_argument (argc, argv, "-excal"))) {
+    options.calibrate = TRUE;
+    remove_argument (N, &argc, argv);
+    InitCalibration (FALSE);
+  }
+  if ((N = get_argument (argc, argv, "-incal"))) {
+    options.calibrate = TRUE;
+    remove_argument (N, &argc, argv);
+    InitCalibration (TRUE);
+  }
+
+  /*** optional situations ***/
+  /* choose high quality airmass vs low quality airmass (per-star vs per-image) */
+  QUALITY_AIRMASS = FALSE;
+  if ((N = get_argument (argc, argv, "-quality-airmass"))) {
+    remove_argument (N, &argc, argv);
+    QUALITY_AIRMASS = TRUE;
+  }
+  /* choose high quality airmass vs low quality airmass (per-star vs per-image) */
+  SUBPIX = FALSE;
+  if ((N = get_argument (argc, argv, "-subpix"))) {
+    remove_argument (N, &argc, argv);
+    SUBPIX = TRUE;
+  }
+  /* skyprobe means: subpix correction and quality airmass */ 
+  if ((N = get_argument (argc, argv, "-skyprobe"))) {
+    remove_argument (N, &argc, argv);
+    QUALITY_AIRMASS = TRUE;
+    SUBPIX = TRUE;
+  }
+  SetAirmassQuality (QUALITY_AIRMASS);
+  if (SUBPIX) load_subpix ();
+
+  /* define 2MASS quality flags to keep */
+  SELECT_2MASS_QUALITY = NULL;
+  if ((N = get_argument (argc, argv, "-2massquality"))) {
+    remove_argument (N, &argc, argv);
+    SELECT_2MASS_QUALITY = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* accept bad header astrometry */
+  ACCEPT_ASTROM = FALSE;
+  if ((N = get_argument (argc, argv, "-accept"))) {
+    ACCEPT_ASTROM = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-accept-astrom"))) {
+    ACCEPT_ASTROM = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* accept proper-motion data from reference */
+  ACCEPT_MOTION = FALSE;
+  if ((N = get_argument (argc, argv, "-accept-motion"))) {
+    ACCEPT_MOTION = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* accept bad header astrometry */
+  ACCEPT_TIME = FALSE;
+  if ((N = get_argument (argc, argv, "-accept-time"))) {
+    ACCEPT_TIME = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* skip the stars */
+  NO_STARS = FALSE;
+  if ((N = get_argument (argc, argv, "-no-stars"))) {
+    NO_STARS = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* force read of image database with mismatched NSTARS & size */ 
+  FORCE_READ = FALSE;
+  if ((N = get_argument (argc, argv, "-force"))) {
+    FORCE_READ = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* force read of image database with mismatched NSTARS & size */ 
+  TEXTMODE = FALSE;
+  if ((N = get_argument (argc, argv, "-textmode"))) {
+    TEXTMODE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  DUMP = NULL;
+  if ((N = get_argument (argc, argv, "-dump"))) {
+    remove_argument (N, &argc, argv);
+    DUMP = strcreate(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((options.mode == M_RESORT) && (argc == 1)) return (options);
+  if (argc == 2) return (options);
+
+  if ((options.mode == M_REFLIST) && (options.photcode == 0)) {
+    fprintf (stderr, "photcode must be specified for -ref\n");
+    exit (2);
+  }
+
+  fprintf (stderr, "USAGE: addstar (filename)\n");
+  fprintf (stderr, "USAGE: addstar -cat (catalog)\n");
+  fprintf (stderr, "USAGE: addstar -ref (filename)\n");
+  fprintf (stderr, "USAGE: addstar -fakeimage (ra) (dec) (theta) (name)\n");
+  fprintf (stderr, "USAGE: addstar -resort (SkyRegion)\n");
+  exit (2);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  addstar (filename)\n");
+  fprintf (stderr, "     add specified image (cmp format) to database\n\n");
+  fprintf (stderr, "  addstar -ref (filename)");
+  fprintf (stderr, "     add ASCII data (ra dec mag dmag) to database\n\n");
+  fprintf (stderr, "  addstar -cat (catalog)");
+  fprintf (stderr, "     add data from catalog (USNO/2MASS/GSC) to database\n\n");
+  fprintf (stderr, "  addstar -resort (SkyRegion)");
+  fprintf (stderr, "     perform measure sorting for the specified catalog\n\n");
+
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -region ra ra dec dec 	  : only add data in specified region (-ref mode only)\n");
+  fprintf (stderr, "  -p (photcode)         	  : specify photcode (-ref / -cat / or override header)\n");
+  fprintf (stderr, "  -photcode (photcode)    	  : specify photcode (-ref / -cat / or override header)\n");
+  fprintf (stderr, "  -time (YYYY/MM/DD,HH:MM:SS) : specify date/time (override header)\n");
+  fprintf (stderr, "  -mosaic (filename)    	  : identify associated mosaic frame for chip image\n");
+  fprintf (stderr, "  -textmode                	  : input file is RAW TEXT table, not FITS table\n");
+  fprintf (stderr, "  -existing-regions           : only add measurements to existing catalog files\n");
+  fprintf (stderr, "  -only-match           	  : only add measurements to existing objects\n");
+  fprintf (stderr, "  -missed               	  : skipped 'missed' entries\n");
+  fprintf (stderr, "  -replace              	  : replace time/photcode measurements (no duplication)\n");
+  fprintf (stderr, "  -closest             	  : use closest-star algorith\n");
+  fprintf (stderr, "  -nosort             	  : don't re-sort the measure entries (improves speed)\n");
+  fprintf (stderr, "  -update             	  : only update the new rows (forces -nosort)\n");
+  fprintf (stderr, "  -image                	  : only insert image data\n");
+  fprintf (stderr, "  -cal                  	  : perform zero-point calibration\n");
+  fprintf (stderr, "  -skyprobe             	  : specify skyprobe mode\n");
+  fprintf (stderr, "  -accept               	  : accept bad astrometry from header\n");
+  fprintf (stderr, "  -accept-astrom          	  : accept bad astrometry from header\n");
+  fprintf (stderr, "  -accept-motion           	  : accept proper-motion data from reference\n");
+  fprintf (stderr, "  -force                	  : force read of database with inconsistent info\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -dump (mode)          	  : output test data\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
+
+/** addstar modes:
+ 
+    addstar (image.smp)  - add cmp/smp image data to db
+    addstar -ref (file.dat) (photcode) 
+    addstar -cat (USNO/2MASS/GSC) -region (ra dec - ra dec)
+
+    -replace : ref/cat - replace existing match (photcode/time)
+    -match   : ref/cat - only add measures to existing averages
+
+    ref types: 
+    ASCII - RA,DEC,M,dM in a table
+
+    addstar 
+
+**/
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/args_client.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/args_client.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/args_client.c	(revision 16632)
@@ -0,0 +1,264 @@
+# include "addstar.h"
+static void help (void);
+
+AddstarClientOptions args_client (int argc, char **argv, AddstarClientOptions options) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /*** check for command line options ***/
+
+  /* basic mode: image, list, refcat */
+  options.mode = M_IMAGE;
+  if ((N = get_argument (argc, argv, "-ref"))) {
+    options.mode = M_REFLIST;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-cat"))) {
+    options.mode = M_REFCAT;
+    remove_argument (N, &argc, argv);
+  }
+
+  /*** provide additional data ***/ 
+  /* restrict to a portion of the sky? (REFCAT only) */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax= 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* override any header PHOTCODE values */
+  options.photcode = 0;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    remove_argument (N, &argc, argv);
+    options.photcode = GetPhotcodeCodebyName (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* provide a time for dataset */
+  options.timeref = 0; 
+  if ((N = get_argument (argc, argv, "-time"))) {
+    time_t tmp;
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tmp)) { 
+      fprintf (stderr, "syntax error in time\n");
+      exit (1);
+    }
+    options.timeref = tmp;
+    remove_argument (N, &argc, argv);
+  }
+  /* provide a mosaic for distortion */
+  MOSAIC = NULL;
+  options.mosaic = FALSE;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    Header header;
+    ALLOCATE (MOSAIC, Coords, 1);
+
+    remove_argument (N, &argc, argv);
+    if (!gfits_read_header (argv[N], &header)) {
+      fprintf (stderr, "ERROR: can't read header for mosaic %s\n", argv[N]);
+      exit (1);
+    }
+    if (!GetCoords (MOSAIC, &header)) {
+      fprintf (stderr, "ERROR: no astrometric solution in header\n");
+      exit (1);
+    }
+    if (strcmp(&MOSAIC[0].ctype[4], "-DIS")) {
+      fprintf (stderr, "ERROR: not a mosaic distortion header\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    gfits_free_header (&header);
+    options.mosaic = TRUE;
+  }
+  
+  /*** modify behavior ***/
+  /* only add to existing objects */
+  options.existing_regions = FALSE;
+  if ((N = get_argument (argc, argv, "-existing-regions"))) {
+    options.existing_regions = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* only add to existing objects */
+  options.only_match = FALSE;
+  if ((N = get_argument (argc, argv, "-only-match"))) {
+    options.only_match = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* don't add missed pts to Missed table (image only) */
+  options.skip_missed = FALSE;
+  if ((N = get_argument (argc, argv, "-missed"))) {
+    options.skip_missed = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* replace measurement, don't duplicate (ref/cat only) */
+  options.replace = FALSE;
+  if ((N = get_argument (argc, argv, "-replace"))) {
+    options.replace = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* use 'closest star' matching, rather than traditional method */
+  options.closest = FALSE;
+  if ((N = get_argument (argc, argv, "-closest"))) {
+    options.closest = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* don't re-sort the measure sequence */
+  options.nosort = FALSE;
+  if ((N = get_argument (argc, argv, "-nosort"))) {
+    options.nosort = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* only add new rows (-update) or re-write complete measure table (forces -nosort) */
+  options.update = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    options.update = TRUE;
+    options.nosort = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* only add image potion to image table */
+  options.only_images = FALSE;
+  if ((N = get_argument (argc, argv, "-image"))) {
+    options.only_images = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* apply average zpt offset calibration (image only) */
+  options.calibrate = FALSE;
+  if ((N = get_argument (argc, argv, "-cal"))) {
+    options.calibrate = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /*** optional situations ***/
+  /* choose high quality airmass vs low quality airmass (per-star vs per-image) */
+  options.quality_airmass = FALSE;
+  if ((N = get_argument (argc, argv, "-quality-airmass"))) {
+    remove_argument (N, &argc, argv);
+    options.quality_airmass = TRUE;
+  }
+  /* choose high quality airmass vs low quality airmass (per-star vs per-image) */
+  SUBPIX = FALSE;
+  if ((N = get_argument (argc, argv, "-subpix"))) {
+    remove_argument (N, &argc, argv);
+    SUBPIX = TRUE;
+  }
+  /* skyprobe means: subpix correction and quality airmass */ 
+  if ((N = get_argument (argc, argv, "-skyprobe"))) {
+    remove_argument (N, &argc, argv);
+    options.quality_airmass = TRUE;
+    SUBPIX = TRUE;
+  }
+  if (SUBPIX) load_subpix ();
+
+  /* define 2MASS quality flags to keep */
+  SELECT_2MASS_QUALITY = NULL;
+  if ((N = get_argument (argc, argv, "-2massquality"))) {
+    remove_argument (N, &argc, argv);
+    SELECT_2MASS_QUALITY = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* accept bad header astrometry */
+  ACCEPT_ASTROM = FALSE;
+  if ((N = get_argument (argc, argv, "-accept"))) {
+    ACCEPT_ASTROM = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* force read of image database with mismatched NSTARS & size */ 
+  FORCE_READ = FALSE;
+  if ((N = get_argument (argc, argv, "-force"))) {
+    FORCE_READ = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* over-ride autointerpretation of input data format */ 
+  TEXTMODE = FALSE;
+  if ((N = get_argument (argc, argv, "-textmode"))) {
+    TEXTMODE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  DUMP = NULL;
+  if ((N = get_argument (argc, argv, "-dump"))) {
+    remove_argument (N, &argc, argv);
+    DUMP = strcreate(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: addstarc (filename)\n");
+    exit (2);
+  }
+  return (options);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  addstar (filename)\n");
+  fprintf (stderr, "     add specified image (cmp format) to database\n\n");
+  fprintf (stderr, "  addstar -ref (filename)");
+  fprintf (stderr, "     add ASCII data (ra dec mag dmag) to database\n\n");
+  fprintf (stderr, "  addstar -cat (catalog)");
+  fprintf (stderr, "     add data from catalog (USNO/2MASS/GSC) to database\n\n");
+
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -region ra ra dec dec 	  : only add data in specified region (-ref mode only)\n");
+  fprintf (stderr, "  -p (photcode)         	  : specify photcode (override header)\n");
+  fprintf (stderr, "  -time (YYYY/MM/DD,HH:MM:SS) : specify date/time (override header)\n");
+  fprintf (stderr, "  -mosaic (filename)    	  : identify associated mosaic frame for chip image\n");
+  fprintf (stderr, "  -fits                 	  : input file is FITS table, not TEXT table\n");
+  fprintf (stderr, "  -existing-regions           : only add measurements to existing catalog files\n");
+  fprintf (stderr, "  -only-match           	  : only add measurements to existing objects\n");
+  fprintf (stderr, "  -missed               	  : skipped 'missed' entries\n");
+  fprintf (stderr, "  -replace              	  : replace time/photcode measurements (no duplication)\n");
+  fprintf (stderr, "  -closest             	  : use closest-star algorith\n");
+  fprintf (stderr, "  -nosort             	  : don't re-sort the measure entries (improves speed)\n");
+  fprintf (stderr, "  -update             	  : only update the new rows (foreces -nosort)\n");
+  fprintf (stderr, "  -image                	  : only insert image data\n");
+  fprintf (stderr, "  -cal                  	  : perform zero-point calibration\n");
+  fprintf (stderr, "  -skyprobe             	  : specify skyprobe mode\n");
+  fprintf (stderr, "  -accept               	  : accept bad astrometry from header\n");
+  fprintf (stderr, "  -force                	  : force read of database with inconsistent info\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -dump (mode)          	  : output test data\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
+
+/** addstar modes:
+ 
+    addstar (image.smp)  - add cmp/smp image data to db
+    addstar -ref (file.dat) (photcode) 
+    addstar -cat (USNO/2MASS/GSC) -region (ra dec - ra dec)
+
+    -replace : ref/cat - replace existing match (photcode/time)
+    -match   : ref/cat - only add measures to existing averages
+
+    ref types: 
+    ASCII - RA,DEC,M,dM in a table
+
+    addstar 
+
+**/
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/args_load2mass.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/args_load2mass.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/args_load2mass.c	(revision 16632)
@@ -0,0 +1,110 @@
+# include "addstar.h"
+static void help (void);
+
+AddstarClientOptions args_load2mass (int argc, char **argv, AddstarClientOptions options) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /*** check for command line options ***/
+
+  /* basic mode: image, list, refcat */
+  options.mode = M_REFCAT;
+
+  /*** provide additional data ***/ 
+  /* restrict to a portion of the sky? (UNUSED) */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax= 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* override any header PHOTCODE values */
+  options.photcode = 0;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    remove_argument (N, &argc, argv);
+    options.photcode = GetPhotcodeCodebyName (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  options.timeref = 0; 
+  options.mosaic = FALSE;
+  options.existing_regions = FALSE;
+  options.skip_missed = FALSE;
+  options.closest = FALSE;
+
+  /* only add to existing objects */
+  options.only_match = FALSE;
+  if ((N = get_argument (argc, argv, "-only-match"))) {
+    options.only_match = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* replace measurement, don't duplicate (ref/cat only) */
+  options.replace = FALSE;
+  if ((N = get_argument (argc, argv, "-replace"))) {
+    options.replace = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* select quality flags */
+  SELECT_2MASS_QUALITY = NULL;
+  if ((N = get_argument (argc, argv, "-2massquality"))) {
+    remove_argument (N, &argc, argv);
+    SELECT_2MASS_QUALITY = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* other defaults */
+  options.nosort = FALSE;
+  options.update = FALSE;
+  options.only_images = FALSE;
+  options.calibrate = FALSE;
+  options.quality_airmass = FALSE;
+  ACCEPT_ASTROM = FALSE;
+  FORCE_READ = FALSE;
+  TEXTMODE = FALSE;
+  SUBPIX = FALSE;
+  DUMP = NULL;
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: load2mass\n");
+    exit (2);
+  }
+  return (options);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  load2mass");
+  fprintf (stderr, "     add data from 2MASS catalog to fullsky\n\n");
+
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -p (photcode)         	  : specify photcode (override header)\n");
+  fprintf (stderr, "  -only-match           	  : only add measurements to existing objects\n");
+  fprintf (stderr, "  -replace              	  : replace time/photcode measurements (no duplication)\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/args_sedstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/args_sedstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/args_sedstar.c	(revision 16632)
@@ -0,0 +1,89 @@
+# include "addstar.h"
+static void help (void);
+
+AddstarClientOptions args_sedstar (int argc, char **argv, AddstarClientOptions options) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /*** check for command line options ***/
+
+  /* basic mode: image, list, refcat */
+  options.mode = M_REFCAT;
+
+  /*** provide additional data ***/ 
+  /* restrict to a portion of the sky? (UNUSED) */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax= 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* extra error messages */
+  PLOT = FALSE;
+  if ((N = get_argument (argc, argv, "-plot"))) {
+    PLOT = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* other defaults */
+  options.timeref = 0; 
+  options.mosaic = FALSE;
+  options.existing_regions = FALSE;
+  options.skip_missed = FALSE;
+  options.closest = FALSE;
+  options.only_match = FALSE;
+  options.replace = FALSE;
+  options.nosort = FALSE;
+  options.update = FALSE;
+  options.only_images = FALSE;
+  options.calibrate = FALSE;
+  options.quality_airmass = FALSE;
+  ACCEPT_ASTROM = FALSE;
+  FORCE_READ = FALSE;
+  TEXTMODE = FALSE;
+  SUBPIX = FALSE;
+  DUMP = NULL;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: sedstar (sedtable) (outcatalog) [-region Rmin Rmax Dmin Dmax]\n");
+    exit (2);
+  }
+  return (options);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  sedstar (SEDtable)");
+  fprintf (stderr, "     fit objects to stellar SEDs\n\n");
+
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -region Rmin Rmax Dmin Dmax : sky region for analysis\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/args_server.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/args_server.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/args_server.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "addstar.h"
+static void help (void);
+
+void args_server (int argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* restrict to a portion of the sky? (REFCAT only) */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  /* define 2MASS quality flags to keep */
+  SELECT_2MASS_QUALITY = NULL;
+  if ((N = get_argument (argc, argv, "-2massquality"))) {
+    remove_argument (N, &argc, argv);
+    SELECT_2MASS_QUALITY = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* force read of image database with mismatched NSTARS & size */ 
+  FORCE_READ = FALSE;
+  if ((N = get_argument (argc, argv, "-force"))) {
+    FORCE_READ = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: addstard\n");
+    exit (2);
+  }
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  addstard\n");
+  fprintf (stderr, "  -force                	  : force read of database with inconsistent info\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/args_skycells.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/args_skycells.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/args_skycells.c	(revision 16632)
@@ -0,0 +1,109 @@
+# include "skycells.h"
+static void help (void);
+
+int args_skycells (int argc, char **argv) {
+  
+  int N;
+  char *ptr;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* what type of output files? */
+  MODE = SQUARES;
+  if ((N = get_argument (argc, argv, "-triangles"))) {
+    MODE = TRIANGLES;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* what type of output files? */
+  FIX_NS = FALSE;
+  if ((N = get_argument (argc, argv, "-fix-ns"))) {
+    FIX_NS = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* pixel scale (arcsec/pixel) */
+  SCALE = 1.0;
+  if ((N = get_argument (argc, argv, "-scale"))) {
+    remove_argument (N, &argc, argv);
+    SCALE = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* pixel scale (arcsec/pixel) */
+  EULER_A = EULER_B = 0.0;
+  if ((N = get_argument (argc, argv, "-euler"))) {
+    remove_argument (N, &argc, argv);
+    EULER_A = RAD_DEG*atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    EULER_B = RAD_DEG*atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* pixel scale (arcsec/pixel) */
+  PADDING = 0.0;
+  if ((N = get_argument (argc, argv, "-padding"))) {
+    remove_argument (N, &argc, argv);
+    PADDING = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* max number of skycells kept in memory */
+  NMAX = 200000;
+  if ((N = get_argument (argc, argv, "-nmax"))) {
+    remove_argument (N, &argc, argv);
+    NMAX = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* max number of skycells kept in memory */
+  NX_SUB = NY_SUB = 1;
+  if ((N = get_argument (argc, argv, "-nx"))) {
+    remove_argument (N, &argc, argv);
+    NX_SUB = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-ny"))) {
+    remove_argument (N, &argc, argv);
+    NY_SUB = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc == 2) {
+    strtol (argv[1], &ptr, 10);
+    if (*ptr == 0) return (TRUE);
+  }
+
+  fprintf (stderr, "USAGE: skycells (level) [-scale arcsec/pix] [-nx (Nx cells)] [-ny (Ny cells)]\n");
+  fprintf (stderr, "  [-h for details and other options]\n");
+  exit (2);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  skycells\n\n");
+
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -triangles                  : save base triangles instead of skycells\n");
+  fprintf (stderr, "  -fix-ns                     : orient skycells with y-axis aligned with Dec\n");
+  fprintf (stderr, "  -scale                      : set pixel scale (default 1.0 arcsec / pixel)\n");
+  fprintf (stderr, "  -padding                    : pad skycells by this fraction in each dimension\n");
+  fprintf (stderr, "  -nmax                    	  : only keep nmax skycells in memory\n");
+  fprintf (stderr, "  -nx                    	  : subdivide skycell projection in x\n");
+  fprintf (stderr, "  -ny                    	  : subdivide skycell projection in y\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/build_links.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/build_links.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/build_links.c	(revision 16632)
@@ -0,0 +1,200 @@
+# include "addstar.h"
+
+/* build the initial links assuming the table is sorted, 
+   not partial, and has a correct set of average[].offset,Nm values */
+int *init_measure_links (Average *average, int Naverage, Measure *measure, int Nmeasure) {
+
+  int i, j, N;
+  int *next;
+
+  N = 0;
+
+  ALLOCATE (next, int, Nmeasure);
+  for (i = 0; i < Naverage; i++, N++) {
+    for (j = 0; j < average[i].Nm - 1; j++, N++) {
+      next[N] = N + 1;
+      if (N >= Nmeasure) {
+	fprintf (stderr, "WARNING: N out of bounds (1)\n");
+      }
+    }
+    next[N] = -1;
+    if (N >= Nmeasure) {
+      fprintf (stderr, "WARNING: N out of bounds (2)\n");
+    }
+
+    if (N >= Nmeasure) {
+      fprintf (stderr, "overflow in init_measure_links\n");
+      abort ();
+    }
+  }
+  return (next);
+}
+
+/* build the initial links assuming the table is sorted */
+int *init_missing_links (Average *average, int Naverage, Missing *missing, int Nmissing) {
+
+  int i, j, N;
+  int *next;
+
+  N = 0;
+
+  ALLOCATE (next, int, Nmissing);
+  for (i = 0; i < Naverage; i++) {
+    for (j = 0; j < average[i].Nn - 1; j++, N++) {
+      next[N] = N + 1;
+    }
+    if (average[i].Nn > 0) {
+      next[N] = -1;
+      if (N >= Nmissing) {
+	fprintf (stderr, "overflow in init_missing_links");
+	abort ();
+      }
+      N++;
+    }
+
+  }
+  return (next);
+}
+
+/* average[].offset, average[].Nm are valid within an addstar run */
+int add_meas_link (Average *average, int *next, int Nmeasure, int NMEASURE) {
+
+  int k, m;
+
+  /* if we have trouble, check validity of next[m] : m < Nmeasure */
+  m = average[0].offset;  
+
+  for (k = 0; k < average[0].Nm - 1; k++)  {
+    m = next[m];
+    if (m >= NMEASURE) {
+      fprintf (stderr, "WARNING: m out of bounds (3)\n");
+    }
+  }
+
+  /* set up references */
+  next[Nmeasure] = -1;
+  if (Nmeasure >= NMEASURE) {
+    fprintf (stderr, "WARNING: Nmeasure out of bounds (1)\n");
+  }
+
+  if (m == -1) {
+    average[0].offset = Nmeasure;
+  } else {
+    next[m] = Nmeasure;
+    if (m >= NMEASURE) {
+      fprintf (stderr, "WARNING: m out of bounds (4)\n");
+    }
+  }
+
+  return (TRUE);
+}
+
+int add_miss_link (Average *average, int *next, int Nmissing) {
+
+  int k, m;
+
+  /* there may be 0 Nmiss; this is not true for Nmeas */
+  if (average[0].Nn < 1) {
+    average[0].missing = Nmissing;
+    next[Nmissing] = -1;
+    return (TRUE);
+  }
+
+  m = average[0].missing;  
+  for (k = 0; k < average[0].Nn - 1; k++) m = next[m];
+  /* set up references */
+  next[Nmissing] = -1;
+  next[m] = Nmissing;
+  return (TRUE);
+}
+
+/* construct measure links which are valid FOR THIS LOAD
+ * - if we have a full load, we will get links which can
+ *   be used by other programs (eg, relphot, etc)
+ * - if we have a partial load, the links are only valid
+ *   for that partial load
+ */ 
+
+int *build_measure_links (Average *average, int Naverage, Measure *measure, int Nmeasure) {
+
+  int i, m, k, Nm, averef;
+  int *next;
+
+  ALLOCATE (next, int, Nmeasure);
+
+  /* reset the Nm, offset values for average */
+  for (i = 0; i < Naverage; i++) {
+    average[i].offset = -1;
+    average[i].Nm     =  0;
+  }
+
+  for (Nm = 0; Nm < Nmeasure; Nm++) {
+    averef = measure[Nm].averef;
+    m = average[averef].offset;  
+    next[Nm] = -1;
+
+    if (m == -1) { /* no links yet for source */
+      average[averef].offset = Nm;
+      average[averef].Nm     = 1;
+      continue;
+    }
+
+    for (k = 0; next[m] != -1; k++) {
+      m = next[m];
+      if (m >= Nmeasure) {
+	fprintf (stderr, "WARNING: m out of bounds (1)\n");
+      }
+    }
+
+    average[averef].Nm = k + 2;
+    next[m] = Nm;
+    if (m >= Nmeasure) {
+      fprintf (stderr, "WARNING: m out of bounds (2)\n");
+    }
+  }
+  return (next);
+}
+
+/* Missing does not carry enough information to reconstruct the links
+   we must always save the missing table, if it exists */
+
+Measure *sort_measure (Average *average, int Naverage, Measure *measure, int Nmeasure, int *next) {
+
+  int i, k, n, N;
+  Measure *tmpmeasure;
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeasure);
+  for (i = 0; i < Naverage; i++) {
+    n = average[i].offset;
+    average[i].offset = N;
+    for (k = 0; k < average[i].Nm; k++, N++) {
+      tmpmeasure[N] = measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  free (measure);
+  return (tmpmeasure);
+}
+
+Missing *sort_missing (Average *average, int Naverage, Missing *missing, int Nmissing, int *next) {
+
+  int i, k, n, N;
+  Missing *tmpmissing;
+
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmissing);
+  for (i = 0; i < Naverage; i++) {
+    n = average[i].missing;
+    average[i].missing = N;
+    for (k = 0; k < average[i].Nn; k++, N++) {
+      tmpmissing[N] = missing[n]; 
+      n = next[n];
+    }
+  }
+  free (missing);
+  return (tmpmissing);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/calibrate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/calibrate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/calibrate.c	(revision 16632)
@@ -0,0 +1,233 @@
+# include "addstar.h"
+
+static int InternalCal;
+static int Ncal, NCAL, *Nstar;
+static float *Mobs, *dMobs, *Mref, *dMref, *Minst;
+
+void InitCalibration (int mode) {
+
+  InternalCal = mode;
+
+  fprintf (stderr, "calibrating the image...\n");
+  Ncal = 0;
+  NCAL = 1000;
+  ALLOCATE (Mobs,  float,  NCAL);
+  ALLOCATE (dMobs, float, NCAL);
+  ALLOCATE (Mref,  float,  NCAL);
+  ALLOCATE (dMref, float,  NCAL);
+  ALLOCATE (Minst, float,  NCAL);
+  ALLOCATE (Nstar, int, NCAL);
+}
+  
+void SaveCalibration (float Mo, float dMo, float Mr, float dMr, float Mi, int N) {
+
+  Mobs[Ncal]  = Mo;
+  dMobs[Ncal] = dMo;
+  Mref[Ncal]  = Mr;
+  dMref[Ncal] = dMr;
+  Minst[Ncal] = Mi;
+  Nstar[Ncal] = N;
+  Ncal ++;
+
+  if (Ncal == NCAL) {
+    NCAL += 1000;
+    REALLOCATE (Mobs,  float, NCAL);
+    REALLOCATE (dMobs, float, NCAL);
+    REALLOCATE (Mref,  float, NCAL);
+    REALLOCATE (dMref, float, NCAL);
+    REALLOCATE (Minst, float, NCAL);
+    REALLOCATE (Nstar, int,   NCAL);
+  }
+}
+
+/* use the linked list to navigate the measures; safe for unsorted measures */
+void AddToCalibration (Average *average, SecFilt *secfilt, Measure *measure, Measure *new, int *next, int Nstar) {
+
+  int i, j, m, Nsec, found0, found1, found2;
+  float CalM0, CalM1, CalM2, dCalM;
+  float Mcal, color, factor, Minst;
+  short CalC0, CalC1, CalC2;
+
+  PhotCode *mycode;  // photcode of this measurement
+  PhotCode *incode;  // mycode.equiv (internal reference)
+  PhotCode *excode;  // incode.equiv (external reference)
+
+  found0 = found1 = found2 = FALSE;
+  CalM0 = CalM1 = CalM2 = dCalM = NAN;
+
+  // we have two options here: 
+  //  - calibrate to internal system (Mcal)
+  //  - calibrate to external system (Mref)
+
+  mycode = GetPhotcodebyCode (new[0].photcode);
+  incode = GetPhotcodebyCode (mycode[0].equiv);
+  excode = GetPhotcodebyCode (incode[0].equiv);
+
+  if (InternalCal) {
+    CalC0 = incode[0].code;
+    Nsec  = GetPhotcodeNsec (CalC0);
+  } else {
+    CalC0 = excode[0].code;
+    Nsec  = GetPhotcodeNsec (CalC0);
+  }
+  /* check if this reference code is an average magnitude */
+  if (Nsec != -1) {
+    CalM0 = secfilt[Nsec].M;
+    dCalM = secfilt[Nsec].dM;
+    found0 = TRUE;
+  }
+
+  CalC1 = mycode[0].c1;
+  Nsec  = GetPhotcodeNsec (CalC1);
+  if (Nsec != -1) {
+    CalM1 = secfilt[Nsec].M;
+    found1 = TRUE;
+  }
+
+  CalC2 = mycode[0].c2;
+  Nsec  = GetPhotcodeNsec (CalC2);
+  if (Nsec != -1) {
+    CalM2 = secfilt[Nsec].M;
+    found2 = TRUE;
+  }
+
+  if (!CalC1 && !CalC2) {
+    found1 = found2 = TRUE;
+    CalM1 = CalM2 = 0.0;
+  }
+
+  m = average[0].offset;
+  for (i = 0; i < average[0].Nm; i++) {
+    if (measure[m].photcode == CalC0) { 
+      found0 = TRUE; 
+      CalM0  = measure[m].M; 
+      dCalM  = measure[m].dM; 
+    }
+    if (measure[m].photcode == CalC1) { 
+      found1 = TRUE; 
+      CalM1  = measure[m].M; 
+    }
+    if (measure[m].photcode == CalC2) { 
+      found2 = TRUE; 
+      CalM2  = measure[m].M; 
+    }
+    if (found0 && found1 && found2) {
+      Mcal   = new[0].M + 0.001*mycode[0].C + mycode[0].K*(new[0].airmass - 1.0) - GetZeroPoint();
+      color  = CalM1 - CalM2 - 0.001*mycode[0].dX;
+      factor = color;
+      for (j = 0; j < mycode[0].Nc; j++) {
+	Mcal += mycode[0].X[j]*factor;
+	factor *= color;
+      }
+      if (!InternalCal) {
+	Mcal += 0.001*incode[0].C;
+      }
+      // if we want to apply a Mcal -> Mref color correction, we need the additional color term
+      Minst = new[0].M - GetZeroPoint() - new[0].dt;
+      SaveCalibration (Mcal, new[0].dM, CalM0, dCalM, Minst, Nstar);
+      if ((DUMP != NULL) && !strcmp (DUMP, "cal")) {
+	fprintf (stdout, "cal-match : %10.6f %10.6f : %7.4f %6.4f  %7.4f %6.4f   %7.4f : %7.4f %7.4f\n", average[0].R, average[0].D, Mcal, new[0].dM, CalM0, dCalM, Minst, new[0].airmass, color);
+      }
+      return;
+    }
+    m = next[m];
+  }
+  return;
+}
+
+void FindCalibration (Image *image) {
+
+  int i, MaxN, *Nlist, Nkeep;
+  float N, M1, M2, *Dmag, *dDmag;
+  float dMo, dMr, Mw, Dmed, W1, W2, NSigma;
+
+  /* reject multiple matched-stars */
+  /* find maximum value of Nstar[] */
+  MaxN = -1;
+  for (i = 0; i < Ncal; i++) {
+    MaxN = MAX (Nstar[i], MaxN);
+  }
+  if (MaxN == -1) {
+    fprintf (stderr, "no clean stars\n");
+    image[0].Mcal = 10.000;
+    image[0].dMcal = 10.000;
+    return;
+  }
+  /* create a hash array from Nstar[] entries */
+  ALLOCATE (Nlist, int, MaxN + 1);
+  memset (Nlist, 0, MAX (0, MaxN*sizeof(int)));
+  for (i = 0; i < Ncal; i++) {
+    Nlist[Nstar[i]] ++;
+  }
+  
+  /* accumulate delta mags */
+  ALLOCATE (Dmag, float, Ncal);
+  ALLOCATE (dDmag, float, Ncal);
+  Nkeep = 0;
+  for (i = 0; i < Ncal; i++) {
+    /* if this entry has too many (or two few?) matches, skip it */
+    if (Nlist[Nstar[i]] != 1) continue;
+
+    /* clip by instrumental magnitude */
+    if (Minst[i] > CAL_INSTMAG_MAX) continue;
+    if (Minst[i] < CAL_INSTMAG_MIN) continue;
+    
+    /* XXX EAM: note the artificial 0.005 dmag here */
+    dMr = MAX (0.005, dMref[i]);
+    dMo = MAX (0.005, dMobs[i]);
+
+    Dmag[Nkeep] = (Mobs[i] - Mref[i]);
+    dDmag[Nkeep] = (dMr*dMr + dMo*dMo);
+    Nkeep ++;
+  }
+
+  if (Nkeep < 5) {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10.000;
+    image[0].dMcal = 10.000;
+    return;
+  }
+  fsortpair (Dmag, dDmag, Nkeep);
+
+  /* take sort list of Dmag, find median */
+  Dmed = Dmag[(int)(0.5*Nkeep)];
+
+  /* exclude points with abs(Dmag - Dmed) / dDmag > 2.5 */
+
+  /* accumulate delta mags (25% - 75% of clipped range) */
+  W1 = 0.0;
+  W2 = 0.0;
+  M1 = 0.0;
+  M2 = 0.0;
+  N  = 0.0;
+  for (i = 0; i < Nkeep; i++) {
+    NSigma = fabs (Dmag[i] - Dmed) / sqrt (dDmag[i]);
+    if (NSigma > 2.5) continue;
+    W1 += Dmag[i] / dDmag[i];
+    W2 += 1 / dDmag[i];
+    M1 += Dmag[i];
+    M2 += SQ (Dmag[i]);
+    N  += 1.0; 
+  }
+
+  if (N > 1) {
+    M1 = M1 / N;
+    M2 = sqrt (fabs(M2/N - M1*M1));
+    Mw = W1 / W2;
+    fprintf (stdout, "STATUS: SUCCESS\n");
+    fprintf (stdout, "ZERO_POINT_MEAN      = %7.4f\n", M1);
+    fprintf (stdout, "ZERO_POINT_WTMEAN    = %7.4f\n", Mw);
+    fprintf (stdout, "ZERO_POINT_STDEV     = %7.4f\n", M2);
+    fprintf (stdout, "ZERO_POINT_PRECISION = %7.4f\n", M2 / sqrt (N));
+    fprintf (stdout, "ZERO_POINT_NSTARS    =    %4.0f\n", N);
+    // fprintf (stderr, "N: %.0f, mean: %f, wt mean: %f, stdev: %f, precision: %f\n", N, M1, Mw, M2, M2 / sqrt (N));
+    image[0].Mcal = M1;
+    image[0].dMcal = M2 / sqrt (N);
+    image[0].Mxxxx = N;
+  } else {
+    fprintf (stderr, "too few stars\n");
+    image[0].Mcal = 10.000;
+    image[0].dMcal = 10.000;
+    image[0].Mxxxx = 0;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/dump.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/dump.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/dump.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "addstar.h"
+
+int dump_rawstars (Stars *stars, int Nstars) {
+
+  int i;
+  FILE *f;
+
+  f = fopen ("stars.dat", "w");
+
+  for (i = 0; i < Nstars; i++) {
+    fprintf (f, "%4d  %10.6f %10.6f  %8.2f %8.2f  %7.2f %7.2f\n", 
+	     i, 
+	     stars[i].R, stars[i].D,
+	     stars[i].X, stars[i].Y,
+	     stars[i].M, stars[i].dM);
+  }
+
+  fclose (f);
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/edge_check.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/edge_check.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/edge_check.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "addstar.h"
+
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/fakeimage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/fakeimage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/fakeimage.c	(revision 16632)
@@ -0,0 +1,197 @@
+# include "addstar.h"
+
+Image *fakeimage (char *rootname, int *Nimage, int photcode) {
+
+  int i, j, Nx, Ny, Nchips;
+  double pltscale, pixscale;
+  double Rmin, Rmax, Dmin, Dmax;
+  // double Xmin, Xmax, Ymin, Ymax;
+  double dX, dY, r, d;
+  char chipname[80], chipdata[256], name[80];
+  char *config;
+  Image *image;
+  e_time MosaicTime;
+
+  /* this is a somewhat bogus method to set a time for the exposure */
+  struct timeval now;
+  long int seedval;
+
+  gettimeofday (&now, NULL);
+  seedval = now.tv_sec + now.tv_usec;
+  srand48(seedval);
+
+  MosaicTime = 0xffffffff * drand48();
+  fprintf (stderr, "time: %x\n", MosaicTime);
+
+  /* load in the camera layout file */
+  config = LoadConfigFile (CameraLayout);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find camera layout file %s\n", CameraLayout);
+    exit (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded camera layout file: %s\n", CameraLayout);
+
+  /* create a mosaic distortion structure */
+  ALLOCATE (MOSAIC, Coords, 1);
+  strcpy (MOSAIC[0].ctype, "RA---DIS");
+  MOSAIC[0].crval1 = FAKE_RA;
+  MOSAIC[0].crval2 = FAKE_DEC;
+  
+  MOSAIC[0].crpix1 = MOSAIC[0].crpix2 = 0.0;
+  
+  /* mosaic 'pixels' are millimeters */
+  ScanConfig (config, "PLATE_SCALE",   "%lf", 0, &pltscale);
+  MOSAIC[0].cdelt1 = MOSAIC[0].cdelt2 = pltscale / 3600.0;
+
+  MOSAIC[0].pc1_1 =  cos(FAKE_THETA*RAD_DEG);
+  MOSAIC[0].pc1_2 = -sin(FAKE_THETA*RAD_DEG);
+  MOSAIC[0].pc2_1 =  sin(FAKE_THETA*RAD_DEG);
+  MOSAIC[0].pc2_2 =  cos(FAKE_THETA*RAD_DEG);
+
+  MOSAIC[0].Npolyterms = 3;
+  for (i = 0; i < 7; i++) {
+    MOSAIC[0].polyterms[i][0] = 0;
+    MOSAIC[0].polyterms[i][1] = 0;
+  }
+  ScanConfig (config, "DPLATE_X",   "%lf", 0, &pltscale);
+  MOSAIC[0].polyterms[3][0] = pltscale;  // L : X^3 Y^0
+  MOSAIC[0].polyterms[5][0] = pltscale;  // L : X^1 Y^2
+  ScanConfig (config, "DPLATE_Y",   "%lf", 0, &pltscale);
+  MOSAIC[0].polyterms[4][1] = pltscale;  // M : X^0 Y^0
+  MOSAIC[0].polyterms[6][1] = pltscale;  // M : X^2 Y^0
+
+  /* some basic data about the chisp */
+  ScanConfig (config, "NCHIPS", "%d", 0, &Nchips);
+  ScanConfig (config, "NAXIS1", "%d", 0, &Nx);
+  ScanConfig (config, "NAXIS2", "%d", 0, &Ny);
+  ScanConfig (config, "PIXEL_SCALE", "%lf", 0, &pixscale);
+
+  ALLOCATE (image, Image, Nchips + 1);
+  
+  Rmin = Rmax = Dmin = Dmax = 0;
+
+  /* define the chip images (1 - Nchips) */
+  for (i = 0; i < Nchips; i++) {
+    /* this is the addstar name for the chip in the camera */
+    sprintf (chipname, "CHIP.%03d", i);
+    ScanConfig (config, chipname, "%s", 0, chipdata);
+
+    sscanf (chipdata, "%s %lf %lf", chipname, &dX, &dY);
+    // if (VERBOSE) fprintf (stderr, "chip %s (%f,%f)\n", chipname, dX, dY);
+
+    /* this is the camera-specific name of a chip */
+    sprintf (name, "%s.%s", rootname, chipname);
+    strcpy (image[i+1].name, name);
+
+    strcpy (image[i+1].coords.ctype, "RA---WRP");
+    
+    image[i+1].coords.crval1 = dX*pixscale;
+    image[i+1].coords.crval2 = dY*pixscale;
+    
+    image[i+1].coords.crpix1 = image[i+1].coords.crpix2 = 0.0;
+    image[i+1].coords.cdelt1 = image[i+1].coords.cdelt2 = pixscale;
+
+    image[i+1].coords.pc1_1 = 1.0;
+    image[i+1].coords.pc1_2 = 0.0;
+    image[i+1].coords.pc2_1 = 0.0;
+    image[i+1].coords.pc2_2 = 1.0;
+
+    image[i+1].coords.Npolyterms = 0;
+    for (j = 0; j < 7; j++) {
+      image[i+1].coords.polyterms[j][0] = 0;
+      image[i+1].coords.polyterms[j][1] = 0;
+    }
+
+    image[i+1].sidtime  = 0.0;
+    image[i+1].latitude = 0.0;
+
+    image[i+1].cerror = 0.0;
+    
+    image[i+1].NX = Nx;
+    image[i+1].NY = Ny;
+
+    image[i+1].photcode = photcode;
+
+    image[i+1].exptime = 0.0;
+  
+    image[i+1].apmifit = 0.0;
+    image[i+1].dapmifit = 0.0;
+
+    image[i+1].detection_limit = 0.0;
+    image[i+1].saturation_limit = 0.0;
+    image[i+1].fwhm_x = 0.0;
+    image[i+1].fwhm_y = 0.0;
+    image[i+1].tzero = MosaicTime;
+    image[i+1].trate = 0;
+    image[i+1].secz = 1.0;
+    image[i+1].ccdnum = 0xff;
+
+    image[i+1].Mcal = 0.0;
+    image[i+1].Xm   = NAN_S_SHORT;
+    image[i+1].code = 0;
+    memset (image[i+1].dummy, 0, sizeof(image[i+1].dummy));
+
+    image[i+1].nstar = 0;
+    image[i+1].Myyyy = 0;
+
+    /* check if chip hits outer bounds of mosaic */
+    XY_to_RD (&r, &d, 0, 0, &image[i+1].coords);
+    Rmin = MIN (Rmin, r);
+    Rmax = MAX (Rmax, r);
+    Dmin = MIN (Dmin, d);
+    Dmax = MAX (Dmax, d);
+    XY_to_RD (&r, &d, Nx, 0, &image[i+1].coords);
+    Rmin = MIN (Rmin, r);
+    Rmax = MAX (Rmax, r);
+    Dmin = MIN (Dmin, d);
+    Dmax = MAX (Dmax, d);
+    XY_to_RD (&r, &d, 0, Ny, &image[i+1].coords);
+    Rmin = MIN (Rmin, r);
+    Rmax = MAX (Rmax, r);
+    Dmin = MIN (Dmin, d);
+    Dmax = MAX (Dmax, d);
+    XY_to_RD (&r, &d, Nx, Ny, &image[i+1].coords);
+    Rmin = MIN (Rmin, r);
+    Rmax = MAX (Rmax, r);
+    Dmin = MIN (Dmin, d);
+    Dmax = MAX (Dmax, d);
+  }
+
+  /* define the mosaic image */
+  strcpy (image[0].name, rootname);
+
+  image[0].coords = MOSAIC[0];
+  strcpy (image[0].coords.ctype, MOSAIC[0].ctype);
+
+  image[0].sidtime  = 0.0;
+  image[0].latitude = 0.0;
+  image[0].cerror = 0.0;
+    
+  // RD_to_XY (&Xmax, &Ymax, Rmax, Dmax, MOSAIC);
+  // RD_to_XY (&Xmin, &Ymin, Rmin, Dmin, MOSAIC);
+  image[0].NX = Rmax - Rmin;
+  image[0].NY = Dmax - Dmin;
+
+  image[0].photcode = photcode;
+
+  image[0].exptime = 0.0;
+  image[0].apmifit = 0.0;
+  image[0].dapmifit = 0.0;
+  image[0].detection_limit = 0.0;
+  image[0].saturation_limit = 0.0;
+  image[0].fwhm_x = 0.0;
+  image[0].fwhm_y = 0.0;
+  image[0].tzero = MosaicTime;
+  image[0].trate = 0;
+  image[0].secz = 1.0;
+  image[0].ccdnum = 0xff;
+  image[0].Mcal = 0.0;
+  image[0].Xm   = NAN_S_SHORT;
+  image[0].code = 0;
+  memset (image[0].dummy, 0, sizeof(image[0].dummy));
+  image[0].nstar = 0;
+  image[0].Myyyy = 0;
+
+  *Nimage = Nchips + 1;
+  return (image);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches.c	(revision 16632)
@@ -0,0 +1,386 @@
+# include "addstar.h"
+
+int find_matches (SkyRegion *region, Stars *stars, int NstarsIn, Catalog *catalog, AddstarClientOptions options) {
+
+  int i, j, n, N, J, status, Nstars;
+  double RADIUS, RADIUS2;
+  double *X1, *Y1, *X2, *Y2;
+  double dX, dY, dR;
+  int *N1, *N2,  *next_meas;
+  int Nave, NAVE, Nmeas, NMEAS, Nmatch;
+  int Nsecfilt, Nsec;
+  Coords tcoords;
+
+  /* photcode data - must by of type DEP; options.photcode is equiv photcode for all input
+     images this function requires incoming stars to have the same photcode.equiv value.  if
+     this value is not a valid photcode (ie, 0), then no modification is made to the average 
+     magnitudes (Nsec will be -1) */
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  Nsec     = GetPhotcodeNsec (options.photcode);
+
+  /** allocate local arrays (stars) **/
+  ALLOCATE (X1, double, NstarsIn);
+  ALLOCATE (Y1, double, NstarsIn);
+  ALLOCATE (N1, int,   NstarsIn);
+
+  /** allocate local arrays (catalog) **/
+  NAVE = Nave = catalog[0].Naverage;
+  ALLOCATE (X2, double, NAVE);
+  ALLOCATE (Y2, double, NAVE);
+  ALLOCATE (N2, int,   NAVE);
+  ALLOCATE (catalog[0].found, int, NAVE);
+  /* for secfilt j and star i, secfilt[i*Nsecfilt+j] */
+
+  /* internal counters */
+  Nmatch = 0;
+  NMEAS = Nmeas = catalog[0].Nmeasure;
+  
+  /* project onto rectilinear grid with 1 arcsec pixels. the choice of ZEA projection has the
+   * advantage that every point in R,D has a mapping to a unique X,Y.  However, note that not all
+   * possible X,Y points map back to R,D and the local plate scale changes substantially far from
+   * the projection pole.  a better mapping might be ARC, not yet implemented (see
+   * coordops.update.c).  We use the center of the region (catalog) for crval1,2. 
+   */
+  tcoords.crval1 = 0.5*(region[0].Rmin + region[0].Rmax);
+  if (region[0].Dmax < 90) {
+    tcoords.crval2 = 0.5*(region[0].Dmin + region[0].Dmax);
+  } else {
+    tcoords.crval2 = 90.0;
+  }
+  tcoords.crpix1 = 0;
+  tcoords.crpix2 = 0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  tcoords.Npolyterms = 1;
+  strcpy (tcoords.ctype, "RA---ARC");
+
+  /* build spatial index (RA sort) */
+  Nstars = 0;
+  for (i = 0; i < NstarsIn; i++) {
+    status = RD_to_XY (&X1[Nstars], &Y1[Nstars], stars[i].R, stars[i].D, &tcoords);
+    if (!status) continue;
+    N1[Nstars] = i;
+    Nstars ++;
+  }
+  if (Nstars < 1) {
+    if (VERBOSE) fprintf (stderr, "skipping %s, no overlapping stars\n", catalog[0].filename);
+    free (catalog[0].found);
+    free (X1);
+    free (Y1);
+    free (N1);
+    free (X2);
+    free (Y2);
+    free (N2);
+    return (0);
+  }
+  if (Nstars > 1) sort_coords_index (X1, Y1, N1, Nstars);
+  
+  /* build spatial index (RA sort) */
+  for (i = 0; i < Nave; i++) {
+    RD_to_XY (&X2[i], &Y2[i], catalog[0].average[i].R, catalog[0].average[i].D, &tcoords);
+    N2[i] = i;
+    catalog[0].found[N2[i]] = -1;
+  }
+  if (Nave > 1) sort_coords_index (X2, Y2, N2, Nave);
+
+  /* set up pointers for linked list of measure */
+  if (catalog[0].sorted) {
+    next_meas = init_measure_links (catalog[0].average, Nave, catalog[0].measure, Nmeas);
+  } else {
+    next_meas = build_measure_links (catalog[0].average, Nave, catalog[0].measure, Nmeas);
+  }    
+
+  /* choose a radius for matches (defined in args.c or ImageOptions.c) */
+  RADIUS = options.radius;
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nstars) && (j < Nave); ) {
+        if (!finite(X1[i]) || !finite(Y1[i])) { 
+      i++; 
+      continue;
+    }
+    if (!finite(X2[j]) || !finite(Y2[j])) { 
+      j++; 
+      continue;
+    }
+
+    /* negative dX: j is too large */
+    dX = X1[i] - X2[j];
+    if (dX <= -2*RADIUS) {
+      i++;
+      continue;
+    }
+    /* positive dX, i is too large */
+    if (dX >= 2*RADIUS) {
+      j++;
+      continue;
+    }
+
+    /* within match range; look for matches */
+    for (J = j; (dX > -2*RADIUS) && (J < Nave); J++) {
+      dX = X1[i] - X2[J];
+      dY = Y1[i] - Y2[J];
+      dR = dX*dX + dY*dY;
+      if (dR > RADIUS2) continue;
+
+      /* make sure there is space for next entry */
+      if (Nmeas >= NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next_meas, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+
+      Nmatch ++;
+      n = N2[J];
+      N = N1[i];
+
+      /* add to end of measurement list */
+      add_meas_link (&catalog[0].average[n], next_meas, Nmeas, NMEAS);
+
+      /** add measurements for this star **/
+      /** dR,dD now represent arcsec **/
+      catalog[0].measure[Nmeas].dR       = 3600.0*(catalog[0].average[n].R - stars[N].R);
+      if (catalog[0].measure[Nmeas].dR > +180.0*3600.0) {
+	  // average on high end of boundary, move star up
+	  stars[N].R += 360.0;
+	  catalog[0].measure[Nmeas].dR = 3600.0*(catalog[0].average[n].R - stars[N].R);
+      }
+      if (catalog[0].measure[Nmeas].dR < -180.0*3600.0) {
+	  // average on low end of boundary, move star down
+	  stars[N].R -= 360.0;
+	  catalog[0].measure[Nmeas].dR = 3600.0*(catalog[0].average[n].R - stars[N].R);
+      }
+      if (fabs(catalog[0].measure[Nmeas].dR) > 10*RADIUS) {
+	  fprintf (stderr, "error: %10.6f,%10.6f vs %10.6f,%10.6f (%f,%f vs %f,%f)\n", 
+		   catalog[0].average[n].R, catalog[0].average[n].D, 
+		   stars[N].R, stars[N].D,
+		   X1[i], X2[J], 
+		   Y1[i], Y2[J]);
+      }
+      catalog[0].measure[Nmeas].dD       = 3600.0*(catalog[0].average[n].D - stars[N].D);
+
+      catalog[0].measure[Nmeas].Xccd     = stars[N].X;
+      catalog[0].measure[Nmeas].Yccd     = stars[N].Y;
+
+      catalog[0].measure[Nmeas].M        = stars[N].M;
+      catalog[0].measure[Nmeas].dM       = stars[N].dM;  /* error in input files stored in thousandths of mag */
+      catalog[0].measure[Nmeas].Mcal     = stars[N].Mcal;
+      catalog[0].measure[Nmeas].t        = stars[N].t;
+      catalog[0].measure[Nmeas].averef   = n;              /* this must be an absolute sequence number, if partial average is loaded */
+      catalog[0].measure[Nmeas].photcode = stars[N].code;  /* photcode */
+      catalog[0].measure[Nmeas].dophot   = stars[N].dophot;  
+      catalog[0].measure[Nmeas].dbFlags  = 0;
+      catalog[0].measure[Nmeas].dt       = stars[N].dt;
+      catalog[0].measure[Nmeas].airmass  = stars[N].airmass;
+
+      catalog[0].measure[Nmeas].photFlags = stars[N].flags;
+      catalog[0].measure[Nmeas].qPSF      = stars[N].psfQual;
+      catalog[0].measure[Nmeas].psfProb   = stars[N].psfProb;
+      catalog[0].measure[Nmeas].crNsigma  = stars[N].crNsigma;
+      catalog[0].measure[Nmeas].extNsigma = stars[N].extNsigma;
+      catalog[0].measure[Nmeas].Sky       = stars[N].sky;
+      catalog[0].measure[Nmeas].dSky      = stars[N].dsky;
+
+      catalog[0].measure[Nmeas].stargal   = 0; // XXX not yet set
+
+      catalog[0].measure[Nmeas].detID     = stars[N].detID;
+      catalog[0].measure[Nmeas].imageID   = options.imageID;
+
+      catalog[0].measure[Nmeas].dXccd     = stars[N].dX;
+      catalog[0].measure[Nmeas].dYccd     = stars[N].dY;
+
+      catalog[0].measure[Nmeas].Mgal     = stars[N].Mgal;
+      catalog[0].measure[Nmeas].FWx      = 100*stars[N].fx;
+      catalog[0].measure[Nmeas].FWy      = 100*stars[N].fy;
+      catalog[0].measure[Nmeas].theta    = (0xffff/360.0)*stars[N].df;
+	
+      /* adds the measurement to the calibration if appropriate color terms are found */
+      /* we call this before (optionally) setting the average magnitude to avoid auto-correlations */
+      if (options.calibrate) {
+	AddToCalibration (&catalog[0].average[n], &catalog[0].secfilt[n*Nsecfilt], catalog[0].measure, &catalog[0].measure[Nmeas], next_meas, N);
+      }
+
+      /* set the average magnitude if not already set and if photcode.equiv is not 0 */
+      /* in UPDATE mode, this value is not saved; use relphot to recalculate */
+      if (Nsec > -1) { 
+	if (isnan(catalog[0].secfilt[n*Nsecfilt+Nsec].M)) {
+	  catalog[0].secfilt[n*Nsecfilt+Nsec].M = PhotCat (&catalog[0].measure[Nmeas]);
+	}
+      }
+
+      /*** flag multiple stars */
+      /* this image star matches more than one catalog star */
+      if (stars[N].found > -1) {
+	catalog[0].measure[stars[N].found].dbFlags |= BLEND_IMAGE;
+	catalog[0].measure[Nmeas].dbFlags |= BLEND_IMAGE;
+      } 
+      if (stars[N].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+	catalog[0].measure[Nmeas].dbFlags |= BLEND_IMAGE_NEIGHBOR;
+      } 
+      if (stars[N].found == -1) { /* this image star matches only this catalog star */
+	stars[N].found = Nmeas;  /* save first match, in case coincidences are found */
+      }
+      /* this catalog star matches more than one image star */
+      if (catalog[0].found[n] > -1) {
+	catalog[0].measure[catalog[0].found[n]].dbFlags |= BLEND_CATALOG;
+	catalog[0].measure[Nmeas].dbFlags |= BLEND_CATALOG;
+      } else {
+	catalog[0].found[n] = Nmeas;
+      }
+      /* Nm is updated, but not written out in -update mode (for existing entries)
+	 Nm is recalculated in build_meas_links if loaded table is not sorted */
+      catalog[0].average[n].Nm ++;
+      Nmeas ++;
+
+      if (!options.update) {
+	/* in UPDATE mode, newly calculated coordinates are not saved */
+	update_coords (&catalog[0].average[n], &catalog[0].measure[0], next_meas);
+      }
+    }
+    i++;
+  }
+
+  /* incorporate unmatched image stars, if this star is in field of this catalog */
+  /* these new entries are all written out in UPDATE mode */ 
+  for (i = 0; (i < Nstars) && !options.only_match; i++) {
+    /* make sure there is space for next entry */
+    if (Nmeas >= NMEAS) {
+      NMEAS = Nmeas + 1000;
+      REALLOCATE (next_meas, int, NMEAS);
+      REALLOCATE (catalog[0].measure, Measure, NMEAS);
+    }
+    if (Nave >= NAVE) {
+      NAVE = Nave + 1000;
+      REALLOCATE (catalog[0].average, Average, NAVE);
+      REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+    }
+
+    N = N1[i];
+    if (stars[N].found >= 0) continue;
+    if (!IN_REGION (stars[N].R, stars[N].D)) continue;
+
+    catalog[0].average[Nave].R         = stars[N].R;
+    catalog[0].average[Nave].D         = stars[N].D;
+    catalog[0].average[Nave].Xp        = 0;
+    catalog[0].average[Nave].Nm        = 1;
+    catalog[0].average[Nave].Nn        = 0;
+    catalog[0].average[Nave].offset    = Nmeas;
+    catalog[0].average[Nave].missing   = -1;
+    catalog[0].average[Nave].code      = 0;
+
+    catalog[0].average[Nave].dR        = 0;
+    catalog[0].average[Nave].dD        = 0;
+    catalog[0].average[Nave].uR        = 0;
+    catalog[0].average[Nave].uD        = 0;
+    catalog[0].average[Nave].duR       = 0;
+    catalog[0].average[Nave].duD       = 0;
+    catalog[0].average[Nave].P         = 0;
+    catalog[0].average[Nave].dP        = 0;
+
+    for (j = 0; j < Nsecfilt; j++) {
+      catalog[0].secfilt[Nave*Nsecfilt+j].M  = NAN;
+      catalog[0].secfilt[Nave*Nsecfilt+j].dM = NAN;
+      catalog[0].secfilt[Nave*Nsecfilt+j].Xm = NAN_S_SHORT;
+    }
+
+    catalog[0].measure[Nmeas].Xccd     = stars[N].X;
+    catalog[0].measure[Nmeas].Yccd     = stars[N].Y;
+
+    catalog[0].measure[Nmeas].dR       	= 0.0;
+    catalog[0].measure[Nmeas].dD       	= 0.0;
+    catalog[0].measure[Nmeas].M        	= stars[N].M;
+    catalog[0].measure[Nmeas].dM       	= stars[N].dM;
+    catalog[0].measure[Nmeas].Mcal  	= stars[N].Mcal;
+    catalog[0].measure[Nmeas].t        	= stars[N].t;
+    catalog[0].measure[Nmeas].averef   	= Nave;           /* XXX EAM : must be absolute Nave if partial read */
+    catalog[0].measure[Nmeas].photcode  = stars[N].code;  /* photcode */
+    catalog[0].measure[Nmeas].dophot   	= stars[N].dophot;  
+    catalog[0].measure[Nmeas].dbFlags 	= 0;
+    catalog[0].measure[Nmeas].dt    	= stars[N].dt;
+    catalog[0].measure[Nmeas].airmass   = stars[N].airmass;
+
+    catalog[0].measure[Nmeas].photFlags = stars[N].flags;
+    catalog[0].measure[Nmeas].qPSF      = stars[N].psfQual;
+    catalog[0].measure[Nmeas].psfProb   = stars[N].psfProb;
+    catalog[0].measure[Nmeas].crNsigma  = stars[N].crNsigma;
+    catalog[0].measure[Nmeas].extNsigma = stars[N].extNsigma;
+    catalog[0].measure[Nmeas].Sky       = stars[N].sky;
+    catalog[0].measure[Nmeas].dSky      = stars[N].dsky;
+
+    catalog[0].measure[Nmeas].stargal   = 0; // XXX not yet set
+
+    catalog[0].measure[Nmeas].detID     = stars[N].detID;
+    catalog[0].measure[Nmeas].imageID   = options.imageID;
+
+    catalog[0].measure[Nmeas].dXccd     = stars[N].dX;
+    catalog[0].measure[Nmeas].dYccd     = stars[N].dY;
+
+    catalog[0].measure[Nmeas].Mgal  	= stars[N].Mgal;
+    catalog[0].measure[Nmeas].FWx      	= 100*stars[N].fx;
+    catalog[0].measure[Nmeas].FWy      	= 100*stars[N].fy;
+    catalog[0].measure[Nmeas].theta    	= (0xffff/360.0)*stars[N].df;
+    /* XXX replace df here with theta, right? */
+
+    /* set the average magnitude if not already set and the photcode.equiv is not 0 */
+    /* in UPDATE mode, this value is not saved; use relphot to recalculate */
+    if (Nsec > -1) { 
+	catalog[0].secfilt[Nave*Nsecfilt+Nsec].M = PhotCat (&catalog[0].measure[Nmeas]);
+    }
+
+    /* next[Nmeas] should always be -1 in this context (it is always the only
+       measurement for the star) */
+    stars[N].found = Nmeas;
+    next_meas[Nmeas] = -1;
+    Nmeas ++;
+    Nave ++;
+  }
+      
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+ 
+  if (options.nosort) {
+    catalog[0].sorted = FALSE;
+  } else {
+    catalog[0].sorted = TRUE;
+    catalog[0].measure = sort_measure (catalog[0].average, Nave, catalog[0].measure, Nmeas, next_meas);
+  }
+
+  /* note stars which have been found in this catalog */
+  for (i = 0; i < NstarsIn; i++) {
+    if (stars[i].found > -1) {
+      stars[i].found = -2;
+    } else {
+      stars[i].found = -3;
+    }
+  }
+
+  /* check if the catalog has changed?  if no change, no need to write */
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas: %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmatch);
+
+  free (catalog[0].found);
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (X2);
+  free (Y2);
+  free (N2);
+  return (Nmatch);
+}
+
+/* 
+   notes:
+   
+   for finding if a catalog star is in an image or an image star is in the catalog:
+   
+   catalogs have boundaries defined by RA and DEC, but they may curve in projection
+   images have boundaries which are lines in pixels coords, but curve in RA and DEC
+   
+   catalog[0].found[Ncat] but stars[Nstar].found
+   
+*/
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches_closest.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches_closest.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches_closest.c	(revision 16632)
@@ -0,0 +1,387 @@
+# include "addstar.h"
+
+int find_matches_closest (SkyRegion *region, Stars *stars, int NstarsIn, Catalog *catalog, AddstarClientOptions options) {
+
+  int i, j, n, N, J, Jmin, status, Nstars;
+  double RADIUS, RADIUS2, Rmin;
+  double *X1, *Y1, *X2, *Y2;
+  double dX, dY, dR;
+  int *N1, *N2,  *next_meas, *next_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  Coords tcoords;
+  int Nsecfilt, Nsec;
+
+  /* photcode data - must by of type DEP; options.photcode is equiv photcode for all input
+     images this function requires incoming stars to have the same photcode.equiv value.  if
+     this value is not a valid photcode (ie, 0), then no modification is made to the average 
+     magnitudes (Nsec will be -1) */
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  Nsec     = GetPhotcodeNsec (options.photcode);
+
+  /** allocate local arrays (stars) **/
+  ALLOCATE (X1, double, NstarsIn);
+  ALLOCATE (Y1, double, NstarsIn);
+  ALLOCATE (N1, int,   NstarsIn);
+
+  /** allocate local arrays (catalog) **/
+  NAVE = Nave = catalog[0].Naverage;
+  ALLOCATE (X2, double, NAVE);
+  ALLOCATE (Y2, double, NAVE);
+  ALLOCATE (N2, int,   NAVE);
+  ALLOCATE (catalog[0].found, int, NAVE);
+  /* for secfilt j and star i, secfilt[i*Nsecfilt+j] */
+
+  /* internal counters */
+  Nmatch = 0;
+  NMEAS = Nmeas = catalog[0].Nmeasure;
+  NMISS = Nmiss = catalog[0].Nmissing;
+
+  /* project onto rectilinear grid with 1 arcsec pixels. the choice of ZEA projection has the
+   * advantage that every point in R,D has a mapping to a unique X,Y.  However, note that not all
+   * possible X,Y points map back to R,D and the local plate scale changes substantially far from
+   * the projection pole.  a better mapping might be ARC, not yet implemented (see
+   * coordops.update.c).  We use the center of the region (catalog) for crval1,2. 
+   */
+  tcoords.crval1 = 0.5*(region[0].Rmin + region[0].Rmax);
+  if (region[0].Dmax < 90) {
+    tcoords.crval2 = 0.5*(region[0].Dmin + region[0].Dmax);
+  } else {
+    tcoords.crval2 = 90.0;
+  }
+  tcoords.crpix1 = 0;
+  tcoords.crpix2 = 0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  tcoords.Npolyterms = 1;
+  strcpy (tcoords.ctype, "RA---ARC");
+
+  /* build spatial index (RA sort) referencing input array sequence */
+  Nstars = 0;
+  for (i = 0; i < NstarsIn; i++) {
+    status = RD_to_XY (&X1[Nstars], &Y1[Nstars], stars[i].R, stars[i].D, &tcoords);
+    if (!status) continue;
+    N1[Nstars] = i;
+    Nstars ++;
+  }
+  if (Nstars < 1) {
+    if (VERBOSE) fprintf (stderr, "skipping %s, no overlapping stars\n", catalog[0].filename);
+    free (catalog[0].found);
+    free (X1);
+    free (Y1);
+    free (N1);
+    free (X2);
+    free (Y2);
+    free (N2);
+    return (0);
+  }
+  if (Nstars > 1) sort_coords_index (X1, Y1, N1, Nstars);
+
+  /* build spatial index (RA sort) */
+  for (i = 0; i < Nave; i++) {
+    RD_to_XY (&X2[i], &Y2[i], catalog[0].average[i].R, catalog[0].average[i].D, &tcoords);
+    N2[i] = i;
+    catalog[0].found[N2[i]] = -1;
+  }
+  if (Nave > 1) sort_coords_index (X2, Y2, N2, Nave);
+
+  /* set up pointers for linked list of measure, missing */
+  if (catalog[0].sorted) {
+    next_meas = init_measure_links (catalog[0].average, Nave, catalog[0].measure, Nmeas);
+  } else {
+    next_meas = build_measure_links (catalog[0].average, Nave, catalog[0].measure, Nmeas);
+  }    
+  next_miss = init_missing_links (catalog[0].average, Nave, catalog[0].missing, Nmiss);
+  /* missing MUST be written 'sorted', or not at all */
+
+  /* choose a radius for matches */
+  RADIUS = options.radius; /* provided by config */
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nstars) && (j < Nave); ) {
+    if (!finite(X1[i]) || !finite(Y1[i])) { 
+      i++; 
+      continue;
+    }
+    if (!finite(X2[j]) || !finite(Y2[j])) { 
+      j++; 
+      continue;
+    }
+    
+    /* negative dX: j is too large */
+    dX = X1[i] - X2[j];
+    if (dX <= -2*RADIUS) {
+      i++;
+      continue;
+    }
+    /* positive dX, i is too large */
+    if (dX >= 2*RADIUS) {
+      j++;
+      continue;
+    }
+
+    Jmin = -1;
+    Rmin = RADIUS2;
+    for (J = j; (dX > -2*RADIUS) && (J < Nave); J++) {
+      /* find closest match for this detection */
+      dX = X1[i] - X2[J];
+      dY = Y1[i] - Y2[J];
+      dR = dX*dX + dY*dY;
+      if (dR > RADIUS2) continue;
+      if (dR < Rmin) {
+	Rmin = dR;
+	Jmin  = J;
+      }
+    }
+
+    /* no match, try next detection */ 
+    if (Jmin == -1) {
+      i++;
+      continue;
+    }
+
+    /*** a match is found, add to average, measure ***/
+
+    /* make sure there is space for next entry */
+    if (Nmeas >= NMEAS) {
+      NMEAS = Nmeas + 1000;
+      REALLOCATE (next_meas, int, NMEAS);
+      REALLOCATE (catalog[0].measure, Measure, NMEAS);
+    }
+
+    Nmatch ++;
+    n = N2[Jmin];
+    N = N1[i];
+
+    /* add to end of measurement list */
+    add_meas_link (&catalog[0].average[n], next_meas, Nmeas, NMEAS);
+	
+    /** add measurements for this star **/
+    /** dR,dD now represent arcsec **/
+    catalog[0].measure[Nmeas].dR       = 3600.0*(catalog[0].average[n].R - stars[N].R);
+    if (catalog[0].measure[Nmeas].dR > +180.0*3600.0) {
+      // average on high end of boundary, move star up
+      stars[N].R += 360.0;
+      catalog[0].measure[Nmeas].dR = 3600.0*(catalog[0].average[n].R - stars[N].R);
+    }
+    if (catalog[0].measure[Nmeas].dR < -180.0*3600.0) {
+      // average on low end of boundary, move star down
+      stars[N].R -= 360.0;
+      catalog[0].measure[Nmeas].dR = 3600.0*(catalog[0].average[n].R - stars[N].R);
+    }
+    if (fabs(catalog[0].measure[Nmeas].dR) > 10*RADIUS) {
+      fprintf (stderr, "error: %10.6f,%10.6f vs %10.6f,%10.6f (%f,%f vs %f,%f)\n", 
+	       catalog[0].average[n].R, catalog[0].average[n].D, 
+	       stars[N].R, stars[N].D,
+	       X1[i], X2[Jmin], 
+	       Y1[i], Y2[Jmin]);
+    }
+    catalog[0].measure[Nmeas].dD       = 3600.0*(catalog[0].average[n].D - stars[N].D);
+
+    /* XXX need to add dX, dY : need to load into stars[N].dX,dY */
+    /* XXX need to add stargal, Sky, dSky, qPSF, detID, imageID */
+    catalog[0].measure[Nmeas].Xccd     = stars[N].X;
+    catalog[0].measure[Nmeas].Yccd     = stars[N].Y;
+
+    catalog[0].measure[Nmeas].M        = stars[N].M;
+    catalog[0].measure[Nmeas].dM       = stars[N].dM;  /* error in input files stored in thousandths of mag */
+    catalog[0].measure[Nmeas].Mcal     = stars[N].Mcal;
+    catalog[0].measure[Nmeas].t        = stars[N].t;
+    catalog[0].measure[Nmeas].averef   = n;
+    catalog[0].measure[Nmeas].photcode = stars[N].code;  /* photcode */
+    catalog[0].measure[Nmeas].dophot   = stars[N].dophot;  
+    catalog[0].measure[Nmeas].dbFlags  = 0;
+    catalog[0].measure[Nmeas].dt       = stars[N].dt;
+    catalog[0].measure[Nmeas].airmass  = stars[N].airmass;
+
+    catalog[0].measure[Nmeas].photFlags = stars[N].flags;
+    catalog[0].measure[Nmeas].qPSF      = stars[N].psfQual;
+    catalog[0].measure[Nmeas].psfProb   = stars[N].psfProb;
+    catalog[0].measure[Nmeas].crNsigma  = stars[N].crNsigma;
+    catalog[0].measure[Nmeas].extNsigma = stars[N].extNsigma;
+    catalog[0].measure[Nmeas].Sky       = stars[N].sky;
+    catalog[0].measure[Nmeas].dSky      = stars[N].dsky;
+
+    catalog[0].measure[Nmeas].stargal   = 0;
+
+    catalog[0].measure[Nmeas].detID     = stars[N].detID;
+    catalog[0].measure[Nmeas].imageID   = options.imageID;
+
+    catalog[0].measure[Nmeas].dXccd     = stars[N].dX;
+    catalog[0].measure[Nmeas].dYccd     = stars[N].dY;
+
+    catalog[0].measure[Nmeas].Mgal     = stars[N].Mgal;
+
+    // XXX saturate range for FWx, FWy, theta
+    // XXX convert to unsigned int for these...
+    catalog[0].measure[Nmeas].FWx      = 100*stars[N].fx;
+    catalog[0].measure[Nmeas].FWy      = 100*stars[N].fy;
+    catalog[0].measure[Nmeas].theta    = (0xffff/360.0)*stars[N].df;
+	
+    /* set the average magnitude if not already set and the photcode.equiv is not 0 */
+    /* in UPDATE mode, this value is not saved; use relphot to recalculate */
+    if (Nsec > -1) { 
+      if (isnan(catalog[0].secfilt[n*Nsecfilt+Nsec].M)) {
+	catalog[0].secfilt[n*Nsecfilt+Nsec].M = PhotCat (&catalog[0].measure[Nmeas]);
+      }
+    }
+
+    /* adds the measurement to the calibration if appropriate color terms are found */
+    if (options.calibrate) {
+      AddToCalibration (&catalog[0].average[n], &catalog[0].secfilt[n*Nsecfilt], catalog[0].measure, &catalog[0].measure[Nmeas], next_meas, N);
+    }
+
+    /* if we choose to flag close encounters, see find_matches.c */
+    /* if we choose to calculate RA,DEC averages, see update_coords.c */
+
+    /* Nm is updated, but not written out in -update mode (for existing entries)
+       Nm is recalculated in build_meas_links if loaded table is not sorted */
+    stars[N].found = Nmeas;
+    catalog[0].found[n] = Nmeas;
+    catalog[0].average[n].Nm ++;
+    Nmeas ++;
+    i++;
+  }
+
+  /** incorporate unmatched image stars, if this star is in field of this catalog **/
+  /* these new entries are all written out in UPDATE mode */ 
+  for (i = 0; (i < Nstars) && !options.only_match; i++) {
+    /* make sure there is space for next entry */
+    if (Nmeas >= NMEAS) {
+      NMEAS = Nmeas + 1000;
+      REALLOCATE (next_meas, int, NMEAS);
+      REALLOCATE (catalog[0].measure, Measure, NMEAS);
+    }
+    if (Nave >= NAVE) {
+      NAVE = Nave + 1000;
+      REALLOCATE (catalog[0].average, Average, NAVE);
+      REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+    }
+
+    N = N1[i];
+    if (stars[N].found >= 0) continue;
+    if (!IN_REGION (stars[N].R, stars[N].D)) continue;
+
+    catalog[0].average[Nave].R         = stars[N].R;
+    catalog[0].average[Nave].D         = stars[N].D;
+    catalog[0].average[Nave].Xp        = 0;
+    catalog[0].average[Nave].Nm        = 1;
+    catalog[0].average[Nave].Nn        = 0;
+    catalog[0].average[Nave].offset    = Nmeas;
+    catalog[0].average[Nave].missing   = -1;
+    catalog[0].average[Nave].code      = 0;
+
+    catalog[0].average[Nave].dR        = 0;
+    catalog[0].average[Nave].dD        = 0;
+    catalog[0].average[Nave].uR        = 0;
+    catalog[0].average[Nave].uD        = 0;
+    catalog[0].average[Nave].duR       = 0;
+    catalog[0].average[Nave].duD       = 0;
+    catalog[0].average[Nave].P         = 0;
+    catalog[0].average[Nave].dP        = 0;
+
+    for (j = 0; j < Nsecfilt; j++) {
+      catalog[0].secfilt[Nave*Nsecfilt+j].M  = NAN;
+      catalog[0].secfilt[Nave*Nsecfilt+j].dM = NAN;
+      catalog[0].secfilt[Nave*Nsecfilt+j].Xm = NAN_S_SHORT;
+    }
+
+    catalog[0].measure[Nmeas].Xccd     = stars[N].X;
+    catalog[0].measure[Nmeas].Yccd     = stars[N].Y;
+
+    catalog[0].measure[Nmeas].dR       = 0.0;
+    catalog[0].measure[Nmeas].dD       = 0.0;
+    catalog[0].measure[Nmeas].M        = stars[N].M;
+    catalog[0].measure[Nmeas].dM       = stars[N].dM;
+    catalog[0].measure[Nmeas].Mcal     = stars[N].Mcal;
+    catalog[0].measure[Nmeas].t        = stars[N].t;
+    catalog[0].measure[Nmeas].averef   = Nave;
+    catalog[0].measure[Nmeas].photcode = stars[N].code;  /* photcode */
+    catalog[0].measure[Nmeas].dophot   = stars[N].dophot;  
+    catalog[0].measure[Nmeas].dbFlags  = 0;
+    catalog[0].measure[Nmeas].dt       = stars[N].dt;
+    catalog[0].measure[Nmeas].airmass  = stars[N].airmass;
+
+    catalog[0].measure[Nmeas].photFlags = stars[N].flags;
+    catalog[0].measure[Nmeas].qPSF      = stars[N].psfQual;
+    catalog[0].measure[Nmeas].psfProb   = stars[N].psfProb;
+    catalog[0].measure[Nmeas].crNsigma  = stars[N].crNsigma;
+    catalog[0].measure[Nmeas].extNsigma = stars[N].extNsigma;
+    catalog[0].measure[Nmeas].Sky       = stars[N].sky;
+    catalog[0].measure[Nmeas].dSky      = stars[N].dsky;
+
+    catalog[0].measure[Nmeas].stargal   = 0;
+
+    catalog[0].measure[Nmeas].detID     = stars[N].detID;
+    catalog[0].measure[Nmeas].imageID   = options.imageID;
+
+    catalog[0].measure[Nmeas].dXccd     = stars[N].dX;
+    catalog[0].measure[Nmeas].dYccd     = stars[N].dY;
+
+    catalog[0].measure[Nmeas].Mgal     = stars[N].Mgal;
+    catalog[0].measure[Nmeas].FWx      = 100*stars[N].fx;
+    catalog[0].measure[Nmeas].FWy      = 100*stars[N].fy;
+    catalog[0].measure[Nmeas].theta    = (0xffff/360.0)*stars[N].df;
+
+    /* set the average magnitude if not already set and the photcode.equiv is not 0 */
+    /* in UPDATE mode, this value is not saved; use relphot to recalculate */
+    if (Nsec > -1) { 
+	catalog[0].secfilt[Nave*Nsecfilt+Nsec].M = PhotCat (&catalog[0].measure[Nmeas]);
+    }
+
+    /* next[Nmeas] should always be -1 in this context (it is always the only
+       measurement for the star) */
+    stars[N].found = Nmeas;
+    next_meas[Nmeas] = -1;
+    Nmeas ++;
+    Nave ++;
+  }
+      
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+ 
+  if (options.nosort) {
+    catalog[0].sorted = FALSE;
+  } else {
+    catalog[0].sorted = TRUE;
+    catalog[0].measure = sort_measure (catalog[0].average, Nave, catalog[0].measure, Nmeas, next_meas);
+  }
+
+  /* note stars which have been found in this catalog */
+  for (i = 0; i < NstarsIn; i++) {
+    if (stars[i].found > -1) {
+      stars[i].found = -2;
+    } else {
+      stars[i].found = -3;
+    }
+  }
+
+  /* check if the catalog has changed?  if no change, no need to write */
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas: %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmatch);
+
+  free (catalog[0].found);
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (X2);
+  free (Y2);
+  free (N2);
+  return (Nmatch);
+}
+
+/* 
+   notes:
+   
+   for finding if a catalog star is in an image or an image star is in the catalog:
+   
+   catalogs have boundaries defined by RA and DEC, but they may curve in projection
+   images have boundaries which are lines in pixels coords, but curve in RA and DEC
+   
+   catalog[0].found[Ncat] but stars[Nstar].found
+   
+*/
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches_refstars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches_refstars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/find_matches_refstars.c	(revision 16632)
@@ -0,0 +1,377 @@
+# include "addstar.h"
+
+int find_matches_refstars (SkyRegion *region, Stars **stars, int Nstars, Catalog *catalog, AddstarClientOptions options) {
+
+  int i, j, k, n, m, N, J;
+  double RADIUS, RADIUS2;
+  double *X1, *Y1, *X2, *Y2;
+  double dX, dY, dR;
+  int *N1, *N2,  *next, *next_miss, last, last_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+  Coords tcoords;
+  int Nsecfilt;
+
+  /* photcode data -- should not have to modify secfilt / average */
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /** allocate local arrays (stars) **/
+  ALLOCATE (X1, double, Nstars);
+  ALLOCATE (Y1, double, Nstars);
+  ALLOCATE (N1, int,   Nstars);
+
+  /** allocate local arrays (catalog) **/
+  Nave = catalog[0].Naverage;
+  NAVE = Nave + 1000;
+  ALLOCATE (X2, double, NAVE);
+  ALLOCATE (Y2, double, NAVE);
+  ALLOCATE (N2, int, NAVE);
+  ALLOCATE (catalog[0].found, int, NAVE);
+  REALLOCATE (catalog[0].average, Average, NAVE);
+  REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+  /* for secfilt j and star i, secfilt[i*Nsecfilt+j] */
+
+  Nmatch = 0;
+  Nmeas = catalog[0].Nmeasure;
+  NMEAS = Nmeas + 1000;
+  ALLOCATE (next, int, NMEAS);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+  
+  Nmiss = catalog[0].Nmissing;
+  NMISS = Nmiss + 1000;
+  if ((NMISS < 1) || (NMISS > 1e10)) {
+      fprintf (stderr, "weird value for NMISS: %d\n", NMISS);
+  }
+  ALLOCATE (next_miss, int, NMISS);
+  REALLOCATE (catalog[0].missing, Missing, NMISS);
+  
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is catalog center */
+  tcoords.crval1 = 0.5*(region[0].Rmin + region[0].Rmax);
+  tcoords.crval2 = 0.5*(region[0].Dmin + region[0].Dmax);
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---ZEA");
+  tcoords.Npolyterms = 0;
+  
+  for (i = 0; i < Nstars; i++) {
+    RD_to_XY (&X1[i], &Y1[i], stars[i][0].R, stars[i][0].D, &tcoords);
+    N1[i] = i;
+  }
+  if (Nstars > 1) sort_coords_index (X1, Y1, N1, Nstars);
+  
+  for (i = 0; i < Nave; i++) {
+    RD_to_XY (&X2[i], &Y2[i], catalog[0].average[i].R, catalog[0].average[i].D, &tcoords);
+    N2[i] = i;
+    catalog[0].found[N2[i]] = -1;
+  }
+  if (Nave > 1) sort_coords_index (X2, Y2, N2, Nave);
+
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+
+  /* choose a radius for matches */
+  if (options.radius == 0) {
+    RADIUS = 2.0; /* hardwired default for refstars */
+  } else {
+    RADIUS = options.radius; /* provided by config */
+  }
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nstars) && (j < Nave); ) {
+    
+    dX = X1[i] - X2[j];
+    if (dX <= -2*RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*RADIUS) {
+      j++;
+      continue;
+    }
+
+    /* negative dX: j is too large, positive dX, i is too large */
+    for (J = j; (dX > -2*RADIUS) && (J < Nave); J++) {
+      dX = X1[i] - X2[J];
+      dY = Y1[i] - Y2[J];
+      dR = dX*dX + dY*dY;
+      if (dR > RADIUS2) continue;
+
+      Nmatch ++;
+      n = N2[J];
+      N = N1[i];
+      m = catalog[0].average[n].offset;  
+
+      /** in replace mode, search for entry and replace values M, dM, R, D */
+      if (options.replace && replace_match (&catalog[0].average[n], &catalog[0].measure[m], stars[N])) continue;
+
+      /** insert star in measurement list */
+      /* find last measurement of this star */
+      for (k = 0; k < catalog[0].average[n].Nm - 1; k++) m = next[m];
+      /* set up references */
+      next[Nmeas] = next[m];
+      next[m] = Nmeas;
+      /* last just was moved */
+      if (next[Nmeas] == -1) last = Nmeas;
+	
+      /** add measurements for this star **/
+      /** *** dR,dD now in arcsec *** **/
+      catalog[0].measure[Nmeas].dR       = 3600.0*(catalog[0].average[n].R - stars[N][0].R);
+      catalog[0].measure[Nmeas].dD       = 3600.0*(catalog[0].average[n].D - stars[N][0].D);
+      catalog[0].measure[Nmeas].M        = stars[N][0].M;
+      catalog[0].measure[Nmeas].dM       = stars[N][0].dM;
+      catalog[0].measure[Nmeas].Mcal     = 0;
+      catalog[0].measure[Nmeas].t        = (TIMEREF == 0) ? stars[N][0].t : TIMEREF; /** careful : time_t vs e_time **/
+      catalog[0].measure[Nmeas].averef   = n;
+      catalog[0].measure[Nmeas].photcode = stars[N][0].code;
+      catalog[0].measure[Nmeas].dophot   = 0;
+      catalog[0].measure[Nmeas].dbFlags  = 0;
+      catalog[0].measure[Nmeas].dt       = 0xffff;
+
+      catalog[0].measure[Nmeas].Mgal     = NAN;
+      catalog[0].measure[Nmeas].airmass  = 0;
+      catalog[0].measure[Nmeas].FWx      = NAN_S_SHORT;
+      catalog[0].measure[Nmeas].FWy      = NAN_S_SHORT;
+      catalog[0].measure[Nmeas].theta    = NAN_S_SHORT;
+	
+      catalog[0].measure[Nmeas].photFlags = 0;
+      catalog[0].measure[Nmeas].qPSF      = 0;
+      catalog[0].measure[Nmeas].psfProb   = 0;
+      catalog[0].measure[Nmeas].crNsigma  = 0;
+      catalog[0].measure[Nmeas].extNsigma = 0;
+      catalog[0].measure[Nmeas].Sky       = 0;
+      catalog[0].measure[Nmeas].dSky      = 0;
+
+      catalog[0].measure[Nmeas].stargal   = 0; // XXX not yet set
+
+      catalog[0].measure[Nmeas].detID     = 0;
+      catalog[0].measure[Nmeas].imageID   = 0;
+
+      catalog[0].measure[Nmeas].dXccd     = 0;
+      catalog[0].measure[Nmeas].dYccd     = 0;
+
+      catalog[0].measure[Nmeas].Xccd     = 0.0;
+      catalog[0].measure[Nmeas].Yccd     = 0.0;
+
+      if (ACCEPT_MOTION) {
+	catalog[0].average[n].uR         = stars[N][0].uR;
+	catalog[0].average[n].uD         = stars[N][0].uD;
+	catalog[0].average[n].duR        = stars[N][0].duR;
+	catalog[0].average[n].duD        = stars[N][0].duD;
+	catalog[0].average[n].P          = stars[N][0].P;
+	catalog[0].average[n].dP         = stars[N][0].dP;
+      }
+
+      /** don't update average / secfilt values for REF photcodes **/
+
+      /*** handle multiple stars */
+      /* this image star matches more than one catalog star */
+      if (stars[N][0].found > -1) {
+	catalog[0].measure[stars[N][0].found].dbFlags |= BLEND_IMAGE;
+	catalog[0].measure[Nmeas].dbFlags |= BLEND_IMAGE;
+      } 
+      if (stars[N][0].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+	catalog[0].measure[Nmeas].dbFlags |= BLEND_IMAGE_NEIGHBOR;
+      } 
+      if (stars[N][0].found == -1) { /* this image star matches only this catalog star */
+	stars[N][0].found = Nmeas;  /* save first match, in case coincidences are found */
+      }
+      /* this catalog star matches more than one image star */
+      if (catalog[0].found[n] > -1) {
+	catalog[0].measure[catalog[0].found[n]].dbFlags |= BLEND_CATALOG;
+	catalog[0].measure[Nmeas].dbFlags |= BLEND_CATALOG;
+      } else {
+	catalog[0].found[n] = Nmeas;
+      }
+
+      catalog[0].average[n].Nm ++;
+      Nmeas ++;
+      if (Nmeas == NMEAS) {
+	NMEAS = Nmeas + 1000;
+	REALLOCATE (next, int, NMEAS);
+	REALLOCATE (catalog[0].measure, Measure, NMEAS);
+      }
+
+      update_coords (&catalog[0].average[n], &catalog[0].measure[0], next);
+    }
+    i++;
+  }
+
+  /* we don't add missed entries for refcat
+     (already in database, not refcat) */
+
+  /* incorporate unmatched refcat stars */
+  /* skip if we want to require matches
+     combined with -replace, this lets us keep 
+     the reference up-to-date with known stars only */
+
+  for (i = 0; (i < Nstars) && !options.only_match; i++) {
+    N = N1[i];
+    if (stars[N][0].found >= 0) continue;
+
+    catalog[0].average[Nave].R         = stars[N][0].R;
+    catalog[0].average[Nave].D         = stars[N][0].D;
+    catalog[0].average[Nave].Xp        = 0;
+    catalog[0].average[Nave].Nm        = 1;
+    catalog[0].average[Nave].Nn        = 0;
+    catalog[0].average[Nave].offset    = Nmeas;
+    catalog[0].average[Nave].missing   = -1;
+    catalog[0].average[Nave].code      = 0;
+
+    if (ACCEPT_MOTION) {
+      catalog[0].average[Nave].dR    = stars[N][0].dR;
+      catalog[0].average[Nave].dD    = stars[N][0].dD;
+      catalog[0].average[Nave].uR    = stars[N][0].uR;
+      catalog[0].average[Nave].uD    = stars[N][0].uD;
+      catalog[0].average[Nave].duR   = stars[N][0].duR;
+      catalog[0].average[Nave].duD   = stars[N][0].duD;
+      catalog[0].average[Nave].P     = stars[N][0].P;
+      catalog[0].average[Nave].dP    = stars[N][0].dP;
+    } else {
+      catalog[0].average[Nave].dR    = 0;
+      catalog[0].average[Nave].dD    = 0;
+      catalog[0].average[Nave].uR    = 0;
+      catalog[0].average[Nave].uD    = 0;
+      catalog[0].average[Nave].duR   = 0;
+      catalog[0].average[Nave].duD   = 0;
+      catalog[0].average[Nave].P     = 0;
+      catalog[0].average[Nave].dP    = 0;
+    }
+
+    for (j = 0; j < Nsecfilt; j++) {
+      catalog[0].secfilt[Nave*Nsecfilt+j].M  = NAN;
+      catalog[0].secfilt[Nave*Nsecfilt+j].dM = NAN;
+      catalog[0].secfilt[Nave*Nsecfilt+j].Xm = NAN_S_SHORT;
+    }
+
+    catalog[0].measure[Nmeas].dR       = 0.0;
+    catalog[0].measure[Nmeas].dD       = 0.0;
+    catalog[0].measure[Nmeas].M        = stars[N][0].M;
+    catalog[0].measure[Nmeas].dM       = stars[N][0].dM;
+    catalog[0].measure[Nmeas].Mcal     = 0;
+    catalog[0].measure[Nmeas].t        = (stars[N][0].t == 0) ? TIMEREF : stars[N][0].t; /** careful : time_t vs e_time **/
+    catalog[0].measure[Nmeas].averef   = Nave;
+    catalog[0].measure[Nmeas].photcode = stars[N][0].code;
+    catalog[0].measure[Nmeas].dophot   = 0;
+    catalog[0].measure[Nmeas].dbFlags  = 0;
+    catalog[0].measure[Nmeas].dt       = 0xffff;
+
+    catalog[0].measure[Nmeas].photFlags = 0;
+    catalog[0].measure[Nmeas].qPSF      = 0;
+    catalog[0].measure[Nmeas].psfProb   = 0;
+    catalog[0].measure[Nmeas].crNsigma  = 0;
+    catalog[0].measure[Nmeas].extNsigma = 0;
+    catalog[0].measure[Nmeas].Sky       = 0;
+    catalog[0].measure[Nmeas].dSky      = 0;
+
+    catalog[0].measure[Nmeas].stargal   = 0; // XXX not yet set
+
+    catalog[0].measure[Nmeas].detID     = 0;
+    catalog[0].measure[Nmeas].imageID   = 0;
+
+    catalog[0].measure[Nmeas].dXccd     = 0;
+    catalog[0].measure[Nmeas].dYccd     = 0;
+
+    catalog[0].measure[Nmeas].Xccd     = 0.0;
+    catalog[0].measure[Nmeas].Yccd     = 0.0;
+
+    catalog[0].measure[Nmeas].airmass  = 0;
+    catalog[0].measure[Nmeas].Mgal     = NAN;
+    catalog[0].measure[Nmeas].FWx      = NAN_S_SHORT;
+    catalog[0].measure[Nmeas].FWy      = NAN_S_SHORT;
+    catalog[0].measure[Nmeas].theta    = NAN_S_SHORT;
+
+    catalog[0].measure[Nmeas].Xccd     = 0.0;
+    catalog[0].measure[Nmeas].Yccd     = 0.0;
+
+    stars[N][0].found = Nmeas;
+    next[last] = Nmeas;
+    next[Nmeas] = -1;
+    last = Nmeas;
+    Nmeas ++;
+    if (Nmeas == NMEAS) {
+      NMEAS = Nmeas + 1000;
+      REALLOCATE (next, int, NMEAS);
+      REALLOCATE (catalog[0].measure, Measure, NMEAS);
+    }
+    Nave ++;
+    if (Nave == NAVE) {
+      NAVE = Nave + 1000;
+      REALLOCATE (catalog[0].average, Average, NAVE);
+      REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*catalog[0].Nsecfilt);
+    }
+  }
+      
+  free (catalog[0].found);
+  REALLOCATE (catalog[0].average, Average, Nave);
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog[0].average[i].Nn > 0) {
+      n = catalog[0].average[i].missing;
+      catalog[0].average[i].missing = N;
+      for (k = 0; k < catalog[0].average[i].Nn; k++, N++) {
+	tmpmissing[N] = catalog[0].missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  free (catalog[0].missing);
+  catalog[0].missing = tmpmissing;
+
+  /* note stars which have been found in this catalog */
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i][0].found > -1) {
+      stars[i][0].found = -2;
+    } else {
+      stars[i][0].found = -3;
+    }
+  }
+
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (X2);
+  free (Y2);
+  free (N2);
+  free (next);
+  free (next_miss);
+
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nmissing = Nmiss;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
+  if (VERBOSE) fprintf (stderr, "Nstars, Nave, Nmeas, Nmiss: %d %d %d %d, (%d matches)\n", Nstars, Nave, Nmeas, Nmiss, Nmatch);
+  return (Nmatch);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/find_missing.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/find_missing.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/find_missing.c	(revision 16632)
@@ -0,0 +1,52 @@
+
+/* XXX I have dropped the -missed capability of addstar. This is an expensive operation which
+ * is only rarely needed.  It is more efficient to perform this operation as a crawler like
+ * relphot.  I am saving in this file the code which was used in find_matches to perform the
+ * missing matches.
+ */
+
+/** code to add references from all previous non-detection observations of this spot on the sky */
+for (j = 0; (j < Noverlap) && !options.skip_missed; j++) {
+  /* make sure there is space for next entry */
+  if (Nmiss >= NMISS) {
+    NMISS = Nmiss + 1000;
+    REALLOCATE (next_miss, int, NMISS);
+    REALLOCATE (catalog[0].missing, Missing, NMISS);
+  }
+  if (!FindMosaicForImage (overlap, Noverlap, j)) continue;
+  if (!in_image (catalog[0].average[Nave].R, catalog[0].average[Nave].D, &overlap[j])) continue;
+  add_miss_link (&catalog[0].average[Nave], next_miss, Nmiss);
+
+  /* get time of exposure of this portion of the image */
+  RD_to_XY (&X, &Y, catalog[0].average[Nave].R, catalog[0].average[Nave].D, &overlap[j].coords);	  
+  catalog[0].missing[Nmiss].t  = overlap[j].tzero + 1e-4*Y*overlap[j].trate;  /* rough guess at time */
+  catalog[0].average[Nave].Nn ++;
+  Nmiss ++;
+}
+
+/* add reference for undetected catalog stars */
+/* XXX allow this option only for single images? */
+if (!strcmp (&image[0].coords.ctype[4], "-WRP")) RegisterMosaic (mosaic);
+for (j = 0; (j < Nave) && !options.skip_missed; j++) {
+  n = N2[j];
+  if (catalog[0].found[n] < 0) { 
+    /* make sure there is space for next entry */
+    if (Nmiss >= NMISS) {
+      NMISS = Nmiss + 1000;
+      REALLOCATE (next_miss, int, NMISS);
+      REALLOCATE (catalog[0].missing, Missing, NMISS);
+    }
+
+    /* should the catalog star be on this image? project into image coords */
+    if (!in_image (catalog[0].average[n].R, catalog[0].average[n].D, image)) continue;
+    add_miss_link (&catalog[0].average[n], next_miss, Nmiss);
+
+    /* calculate time of exposure for this coordinate in the image */
+    RD_to_XY (&X, &Y, catalog[0].average[n].R, catalog[0].average[n].D, &image[0].coords);	  
+    catalog[0].missing[Nmiss].t  = image[0].tzero + 1e-4*Y*image[0].trate;  /* trate is in 0.1 msec / row */
+    catalog[0].average[n].Nn ++;
+    Nmiss ++;
+  }
+}
+  catalog[0].missing = sort_missing (catalog[0].average, Nave, catalog[0].missing, Nmiss, next_miss);
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/find_proper.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/find_proper.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/find_proper.c	(revision 16632)
@@ -0,0 +1,158 @@
+# include "addusno.h"
+
+find_proper (catstats, catalog, usnostats, usno, Nusno)
+CatStats catstats[];
+Catalog catalog[];
+USNOstats usnostats[];
+USNOdata usno[];
+int Nusno;
+{
+
+  int i, j, k, n, m, N, first_j;
+  double RADIUS2, PROPER2;
+  float *X1, *Y1, *X2, *Y2, *usnodist;
+  float dX, dY, dR, dR2;
+  int *N1, *N2,  *next, last;
+  int Nave, Nmeas, NMEAS, Nmatch;
+  unsigned int flags;
+  Measure *tmpmeasure;
+  Coords *tcoords;
+  int already_matched, far_enough;
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  N1 = catstats[0].N;
+  Nave = catalog[0].Naverage;
+
+  /* no need to do this twice!! */
+  ALLOCATE (usnodist, float, Nave);
+  memset (usnodist, 0, Nave*sizeof(float));
+
+  X2 = usnostats[0].X;
+  Y2 = usnostats[0].Y;
+  N2 = usnostats[0].N;
+
+ /* set up link listed pointers for new measurements */
+  Nmatch = 0;
+  Nmeas = catalog[0].Nmeasure;
+  NMEAS = Nmeas + 1000;
+  ALLOCATE (next, int, NMEAS);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+  /* set up pointers for linked list of measurements */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+  
+  /* choose a radius for matches */
+  PROPER2 = PROPER*PROPER;
+  RADIUS2 = RADIUS*RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nave) && (j < Nusno); ) {
+    if (catalog[0].average[N1[i]].code & ID_MOVING) { 
+      /* this is not a star, skip */
+      i++;
+      continue;
+    }
+    if (catalog[0].average[N1[i]].Nm < 3) { 
+      /* may just be a noise spike, skip */
+      i++;
+      continue;
+    }
+    if (catalog[0].average[N1[i]].code & ID_USNO) {
+      /* already matched with USNO, skip this one */
+      i++;
+      continue;
+    }
+    dX = X1[i] - X2[j];
+    if (dX <= -2*PROPER) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*PROPER) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*PROPER) && (j < Nusno); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < PROPER2) {  
+	n = N1[i];  /* N1 refers to the average[] list */
+	N = N2[j];  /* N2 refers to the usno[] list */
+	if (usnostats[0].match[N] > -1) 
+	  continue;
+	if ((catalog[0].average[n].code & ID_USNO) && (usnodist[i] < dR)) {
+	  /* existing USNO match is closer than this new one, skip this one */
+	  continue;
+	}
+	usnodist[i] = dR;
+	m = catalog[0].average[n].offset;  /* first measurement of this star */
+	for (k = 0; k < catalog[0].average[n].Nm - 1; k++)
+	  m = next[m];
+	next[Nmeas+1] = next[m]; /* insert 2 measurements in linked list */
+	next[Nmeas] = Nmeas + 1;
+	next[m] = Nmeas;
+	if (next[Nmeas+1] == -1) { /* last just was moved */
+	  last = Nmeas+1;
+	}
+	Nmatch ++;
+	
+	/** add measurements for this star **/
+	catalog[0].measure[Nmeas].dR  = 360000.0*(catalog[0].average[n].R - usno[N].R);
+	catalog[0].measure[Nmeas].dD  = 360000.0*(catalog[0].average[n].D - usno[N].D);
+	catalog[0].measure[Nmeas].M   = 1000.0*fabs(usno[N].r);
+	catalog[0].measure[Nmeas].Mcal= 0;    /* above measurement is exact */
+	catalog[0].measure[Nmeas].dM  = 100;  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas].t   = 0;    /* a flag: if 0, image is not in database */
+	catalog[0].measure[Nmeas].averef  = n;
+	catalog[0].measure[Nmeas].photcode = USNO_RED; 
+	catalog[0].measure[Nmeas+1].dR  = catalog[0].measure[Nmeas].dR;
+	catalog[0].measure[Nmeas+1].dD  = catalog[0].measure[Nmeas].dD;
+	catalog[0].measure[Nmeas+1].M   = 1000.0*fabs(usno[N].b);
+	catalog[0].measure[Nmeas+1].Mcal= 0;    /* above measurement is exact */
+	catalog[0].measure[Nmeas+1].dM  = 100;  /* error in input files stored in thousandths of mag */
+	catalog[0].measure[Nmeas+1].t   = 0;    /* a flag: if 0, image is not in database */
+	catalog[0].measure[Nmeas+1].averef  = n;
+	catalog[0].measure[Nmeas+1].photcode = USNO_BLUE; 
+	/* add flag in average to mark as matched with the USNO catalog */
+	catalog[0].average[n].code |= (ID_PROPER | ID_USNO);
+	
+	/* we add two measurement for each star: 1 in r, 1 in b */
+	catalog[0].average[n].Nm +=2;
+	Nmeas +=2;  
+	if (Nmeas == NMEAS - 2) {  /* just to be safe... */
+	  NMEAS = Nmeas + 1000;
+	  REALLOCATE (next, int, NMEAS);
+	  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      n = next[n];
+    }
+  }
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+    
+  catalog[0].Nmeasure = Nmeas;
+  if (VERBOSE) fprintf (stderr, "Nusno, Nave, Nmeas: %d %d %d, (%d matches)\n", Nusno, Nave, Nmeas, Nmatch);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/find_subset.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/find_subset.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/find_subset.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "addstar.h"
+
+/* find stars within this region */
+Stars **find_subset (SkyRegion *region, Stars *stars, int Nstars, int *Nsubset) {
+
+  int i, N, NSUBSET;
+  Stars **subset;
+  double RA0, RA1, DEC0, DEC1;
+
+  NSUBSET = 1000;
+  ALLOCATE (subset, Stars *, NSUBSET);
+
+  RA0  = region[0].Rmin;
+  RA1  = region[0].Rmax;
+  DEC0 = region[0].Dmin;
+  DEC1 = region[0].Dmax;
+
+  if (VERBOSE) fprintf (stderr, "subset for %f - %f, %f - %f\n", RA0, RA1, DEC0, DEC1);
+
+  /* find stars within ra,dec region */
+  for (i = N = 0; i < Nstars; i++) {
+    if (stars[i].R <  RA0)  continue;
+    if (stars[i].R >= RA1)  continue;
+    if (stars[i].D <  DEC0) continue;
+    if (stars[i].D >= DEC1) continue;
+
+    subset[N] = &stars[i];
+    N++;
+    if (N == NSUBSET - 1) {
+      NSUBSET += 1000;
+      REALLOCATE (subset, Stars *, NSUBSET);
+    }
+  }
+  *Nsubset = N;
+  return (subset);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass.c	(revision 16632)
@@ -0,0 +1,121 @@
+# include "addstar.h"
+# include "2mass.h"
+
+Stars *get2mass (SkyRegion *patch, int photcode, int mode, int *NSTARS) {
+  
+  char *path;
+  char gzname[1024];
+  int i, status, Nstars, Nrefcat; 
+  Stars    *stars;
+  Stars    *refcat;
+  SkyTable *sky;
+  struct stat filestat;
+
+  NAMED_PHOTCODE (TM_J, "2MASS_J");
+  NAMED_PHOTCODE (TM_H, "2MASS_H");
+  NAMED_PHOTCODE (TM_K, "2MASS_K");
+  if (photcode == TM_J) goto good_code;
+  if (photcode == TM_H) goto good_code;
+  if (photcode == TM_K) goto good_code;
+  Shutdown ("2MASS photcode not specified");
+
+good_code:
+  path = TWO_MASS_DIR_AS;
+  if (mode == 1) path = TWO_MASS_DIR_DR2;
+
+  // the accel.dat file has the raw filenames
+  // test if the file exists, or else try the .gz version
+  sky = get2mass_acc (patch, path, "accel.dat");
+  
+  Nstars = 0;
+  ALLOCATE (stars, Stars, 1);
+
+  for (i = 0; i < sky[0].Nregions; i++) {
+    refcat = NULL;
+    switch (mode) {
+      case 0:
+	// XXX put filename from table here
+	status = stat (sky[0].filename[i], &filestat);
+	if ((status == -1) && (errno == ENOENT)) {
+	  sprintf (gzname, "%s.gz", sky[0].filename[i]);
+	  refcat = get2mass_AS_data (&sky[0].regions[i], gzname, patch, photcode, &Nrefcat);
+	} else {
+	  refcat = get2mass_AS_rawdata (&sky[0].regions[i], sky[0].filename[i], patch, photcode, &Nrefcat);
+	}
+	if (VERBOSE) fprintf (stderr, "loaded %d stars from 2MASS (allsky) : %s\n", Nrefcat, sky[0].filename[i]);
+	break;
+      case 1:
+	refcat = get2mass_2DR_data (&sky[0].regions[i], sky[0].filename[i], patch, photcode, &Nrefcat);
+	if (VERBOSE) fprintf (stderr, "loaded %d stars from 2MASS (dr2)\n", Nrefcat);
+	break;
+    }
+
+    REALLOCATE (stars, Stars, MAX (1, Nstars + Nrefcat));
+    memcpy (&stars[Nstars], refcat, Nrefcat*sizeof(Stars));
+    Nstars += Nrefcat;
+
+    free (refcat);
+  }
+  
+  if (VERBOSE) fprintf (stderr, "loaded total %d stars from 2MASS\n", Nstars);
+  *NSTARS = Nstars;
+  return (stars);
+}  
+
+/* watch for patches which cross 0,360 boundary */
+SkyTable *get2mass_acc (SkyRegion *patch, char *path, char *accel) {
+
+  int Nregions, NREGIONS, Nrec;
+  char accelfile[1024], line[256], filename[128], datafile[256], **filenames;
+  FILE *f;
+  double Rs, Re, Ds, De;
+
+  SkyTable *sky;
+  SkyRegion *regions;
+
+  sprintf (accelfile, "%s/%s", path, accel);
+  f = fopen (accelfile, "r");
+  if (f == NULL) Shutdown ("can't read data from accelerator %s", accelfile);
+
+  Nregions = 0;
+  NREGIONS = 200;
+  ALLOCATE (regions, SkyRegion, NREGIONS);
+  ALLOCATE (filenames, char *, NREGIONS);
+
+  /* read in stars line-by-line */
+  while (scan_line (f, line) != EOF) {
+    stripwhite (line);
+    if (line[0] == 0) continue;
+    if (line[0] == '#') continue;
+    sscanf (line, "%s %lf %lf %lf %lf %d", filename, &Rs, &Re, &Ds, &De, &Nrec);
+    Rs *= 15.0;
+    Re *= 15.0;
+    if (Rs > patch[0].Rmax) continue;
+    if (Re < patch[0].Rmin) continue;
+    if (Ds > patch[0].Dmax) continue;
+    if (De < patch[0].Dmin) continue;
+    regions[Nregions].Rmin = Rs;
+    regions[Nregions].Rmax = Re;
+    regions[Nregions].Dmin = Ds;
+    regions[Nregions].Dmax = De;
+    regions[Nregions].childE = Nrec; // a cheat since 2MASS only has one depth
+    fprintf (stderr, "choosing: %10.6f - %10.6f, %10.6f - %10.6f\n", Rs, Re, Ds, De);
+
+    sprintf (datafile, "%s/%s", path, filename);
+    filenames[Nregions] = strcreate (datafile);
+
+    Nregions ++;
+    if (Nregions >= NREGIONS) {
+	NREGIONS += 20;
+	REALLOCATE (regions, SkyRegion, NREGIONS);
+	REALLOCATE (filenames, char *, NREGIONS);
+    }
+  }    
+  fclose (f);
+
+  ALLOCATE (sky, SkyTable, 1);
+  sky[0].regions = regions;
+  sky[0].filename = filenames;
+  sky[0].Nregions = Nregions;
+  return (sky);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_as.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_as.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_as.c	(revision 16632)
@@ -0,0 +1,128 @@
+# include "addstar.h"
+# include "2mass.h"
+
+/* unlike the DR2 data, the AS data is NOT fixed bytes/row 
+ * we need to handle fractional lines at the end of each read block
+ */
+
+/* read in chunks of ~16MB */
+# define NBYTE 0x1000000
+
+Stars *get2mass_AS_data (SkyRegion *region, char *filename, SkyRegion *patch, int photcode, int *nstars) {
+  
+  int Nstars, NSTARS, Nbyte, Nextra;
+  Stars *stars;
+  gzFile gf;
+  char *buffer;
+  char *p, *q, *tmp;
+  double RA, DEC;
+  double RA0, RA1, DEC0, DEC1;
+
+  ALLOCATE (buffer, char, NBYTE);
+
+  RA0  = MAX (patch[0].Rmin, UserPatch.Rmin);
+  RA1  = MIN (patch[0].Rmax, UserPatch.Rmax);
+  DEC0 = MAX (patch[0].Dmin, UserPatch.Dmin);
+  DEC1 = MIN (patch[0].Dmax, UserPatch.Dmax);
+
+  get2mass_setup (photcode);
+
+  gf = gzopen (filename, "rb");
+  if (gf == NULL) Shutdown ("can't read 2mass data file: %s", filename);
+
+  Nstars = 0;
+  NSTARS = 10000;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  /* I want to add a seek-ahead test to find a good starting position in the file
+     this is very expensive using gzseek / gzread.  */
+
+  Nextra = 0;
+  while ((Nbyte = gzread (gf, &buffer[Nextra], NBYTE-Nextra)) != 0) {
+    if (Nbyte == -1) Shutdown ("error reading from gzipped file %s", filename);
+    Nbyte += Nextra;
+
+    if (VERBOSE) fprintf (stderr, ".");
+
+    /* find bounds on first complete line */
+    p = buffer;
+    q = memchr (p, '\n', Nbyte);
+    if (q == NULL) Shutdown ("incomplete line at end of file\n");
+
+    while (1) {
+
+      get2mass_coords (p, &RA, &DEC, Nbyte - (p - buffer));
+
+      /* skip stars which are outside desired region */
+      if (DEC > DEC1) goto skip_star;
+      if (DEC < DEC0) goto skip_star;
+      if (RA <  RA0)  goto skip_star;
+      if (RA >  RA1)  goto skip_star;
+
+      get2mass_star (&stars[Nstars], p, Nbyte - (p - buffer));
+
+      Nstars ++;
+      CHECK_REALLOCATE (stars, Stars, NSTARS, Nstars, 5000);
+
+    skip_star:
+      /* start of the next line */
+      tmp = p;
+      p = q + 1;
+      if (p - buffer == Nbyte) {
+	Nextra = 0;
+	break;
+      }
+      /* end of the next line */
+      q = memchr (p, '\n', Nbyte - (p - buffer));
+      if (q == NULL) {
+	Nextra = Nbyte - (p - buffer);
+	memmove (buffer, p, Nextra);
+	break;
+      } 
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "\n");
+  
+  gzclose (gf);
+  free (buffer);
+  *nstars = Nstars;
+  return (stars);
+}
+
+/* this just scans along in the file.  file is sorted by dec, so we 
+   should be skipping large chunks - but we would need to have
+   the size from the accel file (won't fit in SkyRegion) and need
+   to use gzseek, if it exists.
+*/
+/* don't bother to seek ahead : position is not sufficiently predictable 
+   and gzseek is as expensive as gzread */
+/* 
+   Noffset = region[0].Nrec * (patch[0].DEC[0] + 90) / 180.0;
+   gzseek (gf, Noffset * NBYTE, SEEK_SET);
+   Nbyte = gzread (gf, buffer, NLINE*NBYTE);
+*/
+
+# if (0)
+    /** need to re-think this test **/
+    if (0) {
+      /* search for end of last complete line */
+      p = memrchr (buffer, '\n', Nbyte);
+      if (p == NULL) Shutdown ("incomplete line in at end of file\n");
+
+      /* search for start of last complete line */
+      /* last block may be only one line */
+      q = memrchr (buffer, '\n', (p - buffer - 1));
+      if (q == NULL) {
+	q = buffer;
+      } else {
+	q ++;
+      }
+
+      /* skip past block not yet in range */
+      RA = strtod (q, NULL);
+      ptr = skipNbounds (q, '|', 1, Nbyte - (q - buffer));
+      DEC = strtod (ptr, NULL);
+      if (DEC < DEC0) continue;
+    }
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_as_raw.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_as_raw.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_as_raw.c	(revision 16632)
@@ -0,0 +1,89 @@
+# include "addstar.h"
+# include "2mass.h"
+
+/* unlike the DR2 data, the AS data is NOT fixed bytes/row 
+ * we need to handle fractional lines at the end of each read block
+ */
+
+/* read in chunks of ~16MB */
+# define NBYTE 0x1000000
+# define NBREC 330
+
+Stars *get2mass_AS_rawdata (SkyRegion *region, char *filename, SkyRegion *patch, int photcode, int *nstars) {
+  
+  int Nstars, NSTARS, Nbyte, Nextra;
+  Stars *stars;
+  FILE *f;
+  char *buffer;
+  char *p, *q, *tmp;
+  double RA, DEC;
+  double RA0, RA1, DEC0, DEC1;
+
+  ALLOCATE (buffer, char, NBYTE);
+
+  RA0  = MAX (patch[0].Rmin, UserPatch.Rmin);
+  RA1  = MIN (patch[0].Rmax, UserPatch.Rmax);
+  DEC0 = MAX (patch[0].Dmin, UserPatch.Dmin);
+  DEC1 = MIN (patch[0].Dmax, UserPatch.Dmax);
+
+  get2mass_setup (photcode);
+
+  f = fopen (filename, "r");
+  if (f == NULL) Shutdown ("can't read 2mass data file: %s", filename);
+  // test if this is a raw datafile or gzipped...
+
+  Nstars = 0;
+  NSTARS = 10000;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  Nextra = 0;
+  while ((Nbyte = fread (&buffer[Nextra], 1, NBYTE-Nextra, f)) != 0) {
+    if (Nbyte == -1) Shutdown ("error reading from raw file %s", filename);
+    Nbyte += Nextra;
+
+    if (VERBOSE) fprintf (stderr, ".");
+
+    /* find bounds on first complete line */
+    p = buffer;
+    q = memchr (p, '\n', Nbyte);
+    if (q == NULL) Shutdown ("incomplete line at end of file\n");
+
+    while (1) {
+
+      get2mass_coords (p, &RA, &DEC, Nbyte - (p - buffer));
+
+      /* skip stars which are outside desired region */
+      if (DEC > DEC1) goto skip_star;
+      if (DEC < DEC0) goto skip_star;
+      if (RA <  RA0)  goto skip_star;
+      if (RA >  RA1)  goto skip_star;
+
+      get2mass_star (&stars[Nstars], p, Nbyte - (p - buffer));
+
+      Nstars ++;
+      CHECK_REALLOCATE (stars, Stars, NSTARS, Nstars, 5000);
+
+    skip_star:
+      /* start of the next line */
+      tmp = p;
+      p = q + 1;
+      if (p - buffer == Nbyte) {
+	Nextra = 0;
+	break;
+      }
+      /* end of the next line */
+      q = memchr (p, '\n', Nbyte - (p - buffer));
+      if (q == NULL) {
+	Nextra = Nbyte - (p - buffer);
+	memmove (buffer, p, Nextra);
+	break;
+      } 
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "\n");
+  
+  fclose (f);
+  free (buffer);
+  *nstars = Nstars;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_dr2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_dr2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_dr2.c	(revision 16632)
@@ -0,0 +1,109 @@
+# include "addstar.h"
+# include "2mass.h"
+
+# define NBYTE 302
+# define NLINE 30000
+
+Stars *get2mass_2DR_data (SkyRegion *region, char *filename, SkyRegion *patch, int photcode, int *nstars) {
+  
+  int i, Nstars, NSTARS, Nbyte, Nline;
+  Stars *stars;
+  gzFile gf;
+  char *buffer;
+  char line[303];
+  double RA, DEC, J, H, K, dJ, dH, dK;
+  double RA0, RA1, DEC0, DEC1;
+
+  ALLOCATE (buffer, char, (NBYTE*NLINE));
+
+  if (region == NULL) exit (2);
+  if (patch == NULL) exit (3);
+
+  RA0  = MAX (patch[0].Rmin, UserPatch.Rmin);
+  RA1  = MIN (patch[0].Rmax, UserPatch.Rmax);
+  DEC0 = MAX (patch[0].Dmin, UserPatch.Dmin);
+  DEC1 = MIN (patch[0].Dmax, UserPatch.Dmax);
+
+  fprintf (stderr, "overlap: %f - %f, %f - %f\n", RA0, RA1, DEC0, DEC1);
+
+  gf = gzopen (filename, "rb");
+  if (gf == NULL) Shutdown ("can't read 2mass data file: %s", filename);
+
+  Nstars = 0;
+  NSTARS = 10000;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  while ((Nbyte = gzread (gf, buffer, NLINE*NBYTE)) != 0) {
+    if (Nbyte ==  0) Shutdown ("error reading from gzipped file %s", filename);
+    if (Nbyte == -1) Shutdown ("error reading from gzipped file %s", filename);
+    if (Nbyte % NBYTE) Shutdown ("error reading complete line from gzipped file %s", filename);
+    Nline = Nbyte / NBYTE;
+
+    /* skip past block not yet in range */
+    sscanf (&buffer[NBYTE*(Nline - 1)], "%lf %lf", &RA, &DEC);
+    if (DEC < DEC0) continue;
+
+    memcpy (line, &buffer[NBYTE*(Nline-1)], NBYTE);
+    line[302] = 0;
+
+    for (i = 0; i < Nline; i++) {
+      
+      dparse (&RA,  1, &buffer[NBYTE*i+  0]);
+      dparse (&DEC, 2, &buffer[NBYTE*i+  0]);
+
+      /* dr2 is nicely sorted in dec order */
+      if (DEC > DEC1) goto finished;
+      if (DEC < DEC0) continue;
+      if (RA <  RA0) continue;
+      if (RA >  RA1) continue;
+
+      stars[Nstars].R  	  = RA;
+      stars[Nstars].D  	  = DEC;
+      stars[Nstars].t  	  = short_date_to_sec (&buffer[NBYTE*i + 164]);
+      stars[Nstars].found = -1;
+
+      if (photcode == TM_J) {
+	dparse (&J,  1, &buffer[NBYTE*i + 53]);
+	dparse (&dJ, 2, &buffer[NBYTE*i + 53]);
+	stars[Nstars].M    = J;
+	stars[Nstars].dM   = dJ;
+	stars[Nstars].code = TM_J;
+      }
+      if (photcode == TM_H) {
+	dparse (&H,  1, &buffer[NBYTE*i + 72]);
+	dparse (&dH, 2, &buffer[NBYTE*i + 72]);
+	stars[Nstars].M    = H;
+	stars[Nstars].dM   = dH;
+	stars[Nstars].code = TM_H;
+      }
+      if (photcode == TM_K) {
+	dparse (&K,  1, &buffer[NBYTE*i + 91]);
+	dparse (&dK, 2, &buffer[NBYTE*i + 91]);
+	stars[Nstars].M    = K;
+	stars[Nstars].dM   = dK;
+	stars[Nstars].code = TM_K;
+      }
+      Nstars ++;
+      CHECK_REALLOCATE (stars, Stars, NSTARS, Nstars, 5000);
+    }
+  }  
+finished:
+  gzclose (gf);
+  free (buffer);
+
+  *nstars = Nstars;
+  return (stars);
+}
+
+/* this just scans along in the file.  file is sorted by dec, so we should be
+   skipping large chunks - but we would need to have the size from the accel
+   file in (and need to use gzseek, if the data is compressed)
+*/
+/* don't bother to seek ahead : position is not sufficiently predictable 
+   and gzseek is as expensive as gzread */
+/* 
+   Noffset = region[0].Nrec * (patch[0].Dmin + 90) / 180.0;
+   gzseek (gf, Noffset * NBYTE, SEEK_SET);
+   Nbyte = gzread (gf, buffer, NLINE*NBYTE);
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_ops.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_ops.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/get2mass_ops.c	(revision 16632)
@@ -0,0 +1,247 @@
+# include "addstar.h"
+# include "2mass.h"
+
+static int FilterSkip;
+static int TimeSkip;
+static int Qentry;
+static int Photcode;
+
+int get2mass_setup (int photcode) {
+
+  NAMED_PHOTCODE (TM_J, "2MASS_J");
+  NAMED_PHOTCODE (TM_H, "2MASS_H");
+  NAMED_PHOTCODE (TM_K, "2MASS_K");
+
+  FilterSkip = TimeSkip = Qentry = 0;
+  Photcode = photcode;
+  if (photcode == -1) return TRUE;
+
+  if (photcode == TM_J) {
+      FilterSkip = 6;
+      TimeSkip = 28;
+      Qentry   = 0;
+  }
+  if (photcode == TM_H) {
+      FilterSkip = 10;
+      TimeSkip = 24;
+      Qentry   = 1;
+  }
+  if (photcode == TM_K) {
+      FilterSkip = 14;
+      TimeSkip = 20;
+      Qentry   = 2;
+  }
+  if (!FilterSkip) Shutdown ("invalid photcode %s", GetPhotcodeNamebyCode(photcode));
+  return TRUE;
+}
+
+// fill in the data for a single star.  takes a pointer to the start of the line
+int get2mass_star (Stars *star, char *line, int Nmax) {
+
+  char *ptr, qc;
+  double M, dM;
+  e_time time;
+
+  ptr = skipNbounds (line, '|', FilterSkip, Nmax);
+  if (ptr == NULL) Shutdown ("format error in 2mass");
+  M  = strtod (ptr, NULL);
+  ptr = skipNbounds (ptr, '|', 1, Nmax - (ptr - line));
+  dM = strtod (ptr, NULL);
+  time = get2mass_time (ptr, TimeSkip, Nmax - (ptr - line));
+
+  /* filter on the ph_qual flag for this filter (field 19) */
+  if (SELECT_2MASS_QUALITY != NULL) {
+    ptr = skipNbounds (line, '|', 18, Nmax);
+    qc  = ptr[Qentry];
+    if (strchr (SELECT_2MASS_QUALITY, qc) == NULL) return (FALSE);
+  }
+
+  star[0].M     = M;
+  star[0].dM    = dM;
+  star[0].code  = Photcode;
+  star[0].t     = time;
+  star[0].found = -1;
+
+  return TRUE;
+}
+
+// fill in the data for a JHK triplet star.  takes a pointer to the start of the line
+int get2mass_3star (Stars *star, char *line, int Nmax) {
+
+  char *ptr;
+  char Jquality, Hquality, Kquality;
+  double J, dJ, H, dH, K, dK;
+  e_time time;
+
+  ptr = line;
+  if (ptr == NULL) Shutdown ("format error in 2mass");
+
+  ptr = skipNbounds (ptr, '|', 6, Nmax - (ptr - line));
+  J  = strtod (ptr, NULL);
+  ptr = skipNbounds (ptr, '|', 1, Nmax - (ptr - line));
+  dJ = strtod (ptr, NULL);
+
+  ptr = skipNbounds (ptr, '|', 3, Nmax - (ptr - line));
+  H  = strtod (ptr, NULL);
+  ptr = skipNbounds (ptr, '|', 1, Nmax - (ptr - line));
+  dH = strtod (ptr, NULL);
+
+  ptr = skipNbounds (ptr, '|', 3, Nmax - (ptr - line));
+  K  = strtod (ptr, NULL);
+  ptr = skipNbounds (ptr, '|', 1, Nmax - (ptr - line));
+  dK = strtod (ptr, NULL);
+
+  /* filter on the ph_qual flag for this filter (field 19) */
+  if (SELECT_2MASS_QUALITY != NULL) {
+    ptr = skipNbounds (ptr, '|', 3, Nmax - (ptr - line));
+    Jquality = (strchr (SELECT_2MASS_QUALITY, ptr[0]) != NULL);
+    Hquality = (strchr (SELECT_2MASS_QUALITY, ptr[1]) != NULL);
+    Kquality = (strchr (SELECT_2MASS_QUALITY, ptr[2]) != NULL);
+    time = get2mass_time (ptr, 18, Nmax - (ptr - line));
+  } else {
+    time = get2mass_time (ptr, 20, Nmax - (ptr - line));
+  }
+
+  star[0].M     = J;
+  star[0].dM    = dJ;
+  star[0].code  = TM_J;
+  star[0].t     = time;
+  star[0].found = -1;
+
+  star[1].M     = H;
+  star[1].dM    = dH;
+  star[1].code  = TM_H;
+  star[1].t     = time;
+  star[1].found = -1;
+
+  star[2].M     = K;
+  star[2].dM    = dK;
+  star[2].code  = TM_K;
+  star[2].t     = time;
+  star[2].found = -1;
+
+  return TRUE;
+}
+
+// fill in the coords for a single star.  takes a pointer to the start of the line
+int get2mass_coords (char *line, double *R, double *D, int Nmax) {
+
+  char *ptr;
+
+  *R = strtod (line, NULL);
+  ptr = skipNbounds (line, '|', 1, Nmax);
+  *D = strtod (ptr, NULL);
+  if (*D > 90) Shutdown ("weird DEC value: something is wrong");
+
+  return TRUE;
+}
+
+// this function retrieves the time from the DATE field
+e_time get2mass_date (char *ptr, int Nbound, int Nmax) {
+
+  e_time time;
+  char *p, *end;
+
+  p = skipNbounds (ptr, '|', Nbound, Nmax);
+  if (p == NULL) Shutdown ("format error in 2mass");
+  end = memchr (p, '|', Nmax - (p - ptr));
+  if (end == NULL) Shutdown ("format error in 2mass");
+  *end = 0;
+  time = ohana_date_to_sec (ptr);
+  *end = '|';
+
+  return (time);
+}
+
+// this function retrieves the time from the JDATE field (%12.4f)
+e_time get2mass_time (char *ptr, int Nbound, int Nmax) {
+
+  e_time time;
+  double jd;
+  char *p, *end;
+
+  p = skipNbounds (ptr, '|', Nbound, Nmax);
+  if (p == NULL) Shutdown ("format error in 2mass");
+  end = memchr (p, '|', Nmax - (p - ptr));
+  if (end == NULL) Shutdown ("format error in 2mass");
+  *end = 0;
+  jd = strtod (p, NULL);
+  time = ohana_jd_to_sec (jd);
+  *end = '|';
+
+  return (time);
+}
+
+/* return a pointer to the first char after Nbound of value bound */
+char *skipNbounds (char *line, char bound, int Nbound, int Nbyte) {
+
+  int i;
+  char *p, *q;
+
+  p = line;
+  for (i = 0; i < Nbound; i++) {
+    q = memchr (p, bound, Nbyte - (p - line));
+    if (q == NULL) return (NULL);
+    p = q + 1;
+    if (p - line == Nbyte) return (NULL);
+  }
+  return (p);
+}
+  
+/* watch for patches which cross 0,360 boundary */
+SkyTable *load2mass_acc (char *path, char *accel) {
+
+  int Nregions, NREGIONS, Nrec;
+  char accelfile[1024], line[256], filename[128], datafile[256], **filenames;
+  FILE *f;
+  double Rs, Re, Ds, De;
+
+  SkyTable *sky;
+  SkyRegion *regions;
+
+  sprintf (accelfile, "%s/%s", path, accel);
+  f = fopen (accelfile, "r");
+  if (f == NULL) Shutdown ("can't read data from accelerator %s", accelfile);
+
+  Nregions = 0;
+  NREGIONS = 200;
+  ALLOCATE (regions, SkyRegion, NREGIONS);
+  ALLOCATE (filenames, char *, NREGIONS);
+
+  /* read in stars line-by-line */
+  while (scan_line (f, line) != EOF) {
+    stripwhite (line);
+    if (line[0] == 0) continue;
+    if (line[0] == '#') continue;
+    sscanf (line, "%s %lf %lf %lf %lf %d", filename, &Rs, &Re, &Ds, &De, &Nrec);
+    Rs *= 15.0;
+    Re *= 15.0;
+
+    // don't restrict by RA, but limit by DEC
+    if (De < UserPatch.Dmin) continue;
+    if (Ds > UserPatch.Dmax) continue;
+
+    regions[Nregions].Rmin = Rs;
+    regions[Nregions].Rmax = Re;
+    regions[Nregions].Dmin = Ds;
+    regions[Nregions].Dmax = De;
+    regions[Nregions].childE = Nrec; // a cheat since 2MASS only has one depth
+
+    sprintf (datafile, "%s/%s", path, filename);
+    filenames[Nregions] = strcreate (datafile);
+
+    Nregions ++;
+    if (Nregions >= NREGIONS) {
+	NREGIONS += 20;
+	REALLOCATE (regions, SkyRegion, NREGIONS);
+	REALLOCATE (filenames, char *, NREGIONS);
+    }
+  }    
+  fclose (f);
+
+  ALLOCATE (sky, SkyTable, 1);
+  sky[0].regions = regions;
+  sky[0].filename = filenames;
+  sky[0].Nregions = Nregions;
+  return (sky);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/getgsc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/getgsc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/getgsc.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "addstar.h"
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+static short GSC_M;
+
+Stars *getgsc (SkyRegion *patch, int *NSTARS) {
+  
+  int i, Ngsc, Nstars; 
+  Stars *gsc;
+  Stars *stars;
+  SkyList *skylist;
+  SkyTable *sky;
+
+  NAMED_PHOTCODE (GSC_M, "GSC_M");
+
+  /* load regions from GSC table, restrict to patch */
+  sky = SkyTableFromGSC (GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, GSCDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, patch);
+  
+  Nstars = 0;
+  ALLOCATE (stars, Stars, 1);
+  
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    gsc = rd_gsc (skylist[0].filename[i], &Ngsc);
+
+    REALLOCATE (stars, Stars, MAX (1, Nstars + Ngsc));
+    memcpy (&stars[Nstars], gsc, Ngsc*sizeof(Stars));
+    Nstars += Ngsc;
+
+    free (gsc);
+  }
+  SkyTableFree (sky);
+
+  if (VERBOSE) fprintf (stderr, "%d stars from HST GSC\n", Nstars);
+  *NSTARS = Nstars;
+  return (stars);
+}  
+
+Stars *rd_gsc (char *filename, int *nstars) {
+  
+  int i, NSTARS, Nstars, Nbytes, nbytes, Nline, Nbyte;
+  char *buffer;
+  FILE *f;
+  Stars *stars;
+
+  Nstars = 0;
+  NSTARS = 1000;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find catalog file %s\n", filename);
+    exit (2);
+  }
+  
+  Nbytes = BLOCK*BYTES_STAR;
+  ALLOCATE (buffer, char, Nbytes);
+  while ((nbytes = fread (buffer, 1, Nbytes, f)) > 0) {
+    Nline = nbytes / BYTES_STAR;
+    for (i = 0; i < Nline; i++) {
+      Nbyte = i*BYTES_STAR;
+      dparse (&stars[Nstars].R, 1, &buffer[Nbyte]);
+      dparse (&stars[Nstars].D, 2, &buffer[Nbyte]);
+      if (stars[Nstars].R < UserPatch.Rmin) continue;
+      if (stars[Nstars].R > UserPatch.Rmax) continue;
+      if (stars[Nstars].D < UserPatch.Dmin) continue;
+      if (stars[Nstars].D > UserPatch.Dmax) continue;
+
+      dparse (&stars[Nstars].M, 3, &buffer[Nbyte]);
+      stars[Nstars].dM 	  = NAN;
+      stars[Nstars].t  	  = 0;
+      stars[Nstars].code  = GSC_M;
+      stars[Nstars].found = -1;
+      Nstars ++;
+      CHECK_REALLOCATE (stars, Stars, NSTARS, Nstars, 1000);
+    }
+  }
+  free (buffer);
+  REALLOCATE (stars, Stars, Nstars);
+  *nstars = Nstars;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/gettycho.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/gettycho.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/gettycho.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include "addstar.h"
+# define NZONE 180
+# define NBYTE 207
+# define NITEM 100
+
+static SkyTable *tychoTable = NULL;
+
+Stars *gettycho (SkyRegion *catstats, int photcode, int *nstars) {
+
+  int i, j, nitems;
+  char *buffer;
+  char filename[128], *line;
+  FILE *f;
+  int NTYCHO, Ntycho;
+  int firstRow, firstByte;
+  short int TYCHO_B, TYCHO_V;
+  e_time TychoEpoch;
+  SkyRegion *region;
+  SkyList  *skylist;
+  Stars *stars;
+
+  /* require photcode */
+  NAMED_PHOTCODE (TYCHO_B, "TYCHO_B");
+  NAMED_PHOTCODE (TYCHO_V, "TYCHO_V");
+  if (photcode == TYCHO_B) goto good_code;
+  if (photcode == TYCHO_V) goto good_code;
+  Shutdown ("TYCHO photcode not specified");
+good_code:
+
+  fprintf (stderr, "loading TYCHO catalog\n");
+
+  /* load tycho index file into sky table */
+  if (tychoTable == NULL) {
+    sprintf (filename, "%s/index.dat", TYCHO_DIR);
+    tychoTable = SkyTableFromTychoIndex (filename, VERBOSE);
+    if (tychoTable == NULL) {
+      fprintf (stderr, "ERROR: problem loading tycho data\n");
+      exit (2);
+    }
+  }
+
+  /* identify tycho region files overlapping the requested region */
+  skylist = SkyListByPatch (tychoTable, 2, catstats);
+
+  /* open the Tycho catalog file */
+  sprintf (filename, "%s/tycho.dat", TYCHO_DIR);
+  f = fopen (filename, "r");
+
+  Ntycho = 0;
+  NTYCHO = 5000;
+  ALLOCATE (stars, Stars, NTYCHO);
+
+  ALLOCATE (buffer, char, NITEM*NBYTE);
+
+  TychoEpoch = ohana_date_to_sec ("1991/04/02,07:30:00");
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    region = skylist[0].regions[i];
+    if (VERBOSE) fprintf (stderr, "section %d (%f - %f, %f - %f)...", i, 
+			  region[0].Rmin, region[0].Rmax, region[0].Dmin, region[0].Dmax);
+
+    firstRow  = atoi (region[0].name);
+    firstByte = firstRow * NBYTE;
+    fseek (f, firstByte, SEEK_SET);
+
+    while (1) {
+      nitems = fread (buffer, NBYTE, NITEM, f);
+      if (nitems == 0) break;
+
+      for (j = 0; j < nitems; j++) {
+	line = &buffer[j*NBYTE];
+	stars[Ntycho].R = atof (&line[15]);
+	stars[Ntycho].D = atof (&line[28]);
+
+	if (stars[Ntycho].R < region[0].Rmin) goto next_section;
+	if (stars[Ntycho].R > region[0].Rmax) goto next_section;
+	if (stars[Ntycho].D < region[0].Dmin) goto next_section;
+	if (stars[Ntycho].D > region[0].Dmax) goto next_section;
+
+	if (stars[Ntycho].R < UserPatch.Rmin) continue;
+	if (stars[Ntycho].R > UserPatch.Rmax) continue;
+	if (stars[Ntycho].D < UserPatch.Dmin) continue;
+	if (stars[Ntycho].D > UserPatch.Dmax) continue;
+
+	stars[Ntycho].dR  = 1000 * atof (&line[57]);
+	stars[Ntycho].dD  = 1000 * atof (&line[64]);
+
+	/* XXX : we need to apply uR,uD to R,D to advance to 2000.0 */
+	stars[Ntycho].uR  = atof (&line[41]);
+	stars[Ntycho].uD  = atof (&line[49]);
+
+	stars[Ntycho].duR = atof (&line[69]);
+	stars[Ntycho].duD = atof (&line[75]);
+	
+	stars[Ntycho].P   = 0;
+	stars[Ntycho].dP  = 0;
+
+	/* Tycho uses J2000 equinox and 1991.25 epoch for coordinates */
+	/* the magnitudes have no temporal information */ 
+	stars[Ntycho].t   = TychoEpoch;
+	stars[Ntycho].found = -1;
+      
+	/* one pass of addstar does either r or b */
+	if (photcode == TYCHO_B) {
+	  stars[Ntycho].M     = atof (&line[110]);
+	  stars[Ntycho].dM    = atof (&line[117]);
+	  stars[Ntycho].code  = TYCHO_B;
+	} else {
+	  stars[Ntycho].M     = atof (&line[123]);
+	  stars[Ntycho].dM    = atof (&line[130]);
+	  stars[Ntycho].code  = TYCHO_V;
+	}	
+      
+	Ntycho ++;
+	CHECK_REALLOCATE (stars, Stars, NTYCHO, Ntycho, 5000);
+      }
+
+      if (nitems != NITEM) break;
+    }
+  next_section:
+    if (VERBOSE) fprintf (stderr, "%d stars\n", Ntycho);
+  }
+  fclose (f);
+
+  SkyListFree (skylist);
+
+  free (buffer);
+  REALLOCATE (stars, Stars, MAX (1, Ntycho));
+
+  *nstars = Ntycho;
+  if (VERBOSE) fprintf (stderr, "%d stars from Tycho\n", Ntycho);
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/getusno.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/getusno.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/getusno.c	(revision 16632)
@@ -0,0 +1,159 @@
+# include "addstar.h"
+# define NZONE 24
+# define NBYTE  4
+# define NELEM  3
+
+Stars *getusno (SkyRegion *catstats, int photcode, int *nstars) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins, Nstars;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128];
+  FILE *f;
+  int iRA0, iRA1, iDEC0, iDEC1;
+  double dec;
+  int spd, spd_start, spd_end;
+  int NUSNO, Nusno;
+  Stars *stars;
+  short int USNO_RED, USNO_BLUE;
+
+  /* require photcode */
+  NAMED_PHOTCODE (USNO_RED, "USNO_RED");
+  NAMED_PHOTCODE (USNO_BLUE, "USNO_BLUE");
+  if (photcode == USNO_RED) goto good_code;
+  if (photcode == USNO_BLUE) goto good_code;
+  Shutdown ("USNO photcode not specified");
+good_code:
+
+  /* identify ra & dec range of interest */
+  /* note: the use of UserPatch to restrict here limits general utility of function */
+  iRA0  =  MAX (catstats[0].Rmin, UserPatch.Rmin) * 360000.0;
+  iRA1  =  MIN (catstats[0].Rmax, UserPatch.Rmax) * 360000.0;
+  iDEC0 = (MAX (catstats[0].Dmin, UserPatch.Dmin) + 90.0) * 360000.0;
+  iDEC1 = (MIN (catstats[0].Dmax, UserPatch.Dmax) + 90.0) * 360000.0;
+  
+  /* data is organized in south-pole distance zones */
+  spd_start = (int)((catstats[0].Dmin + 90) / 7.5) * 75.0;
+  dec = (catstats[0].Dmax + 90) / 7.5;
+  if (dec > (int)(dec)) {
+    spd_end =   (int)(1 + (catstats[0].Dmax + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (catstats[0].Dmax + 90) / 7.5) * 75.0;
+  }
+
+  Nusno = 0;
+  NUSNO = 5000;
+  ALLOCATE (stars, Stars, NUSNO);
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc", USNO_A_DIR, spd); 
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open accelerator file %s\n", filename);
+      exit (1);  
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].Rmin / 3.75;
+    if ((catstats[0].Rmax / 3.75) == (int) (catstats[0].Rmax / 3.75)) 
+      last  = catstats[0].Rmax / 3.75;
+    else 
+      last  = 1 + catstats[0].Rmax / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "ERROR: RA out of range\n");
+      exit (1);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat", USNO_A_DIR, spd);
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s\n", filename);
+      exit (1);
+    }
+
+    /** USNO-A consists of 3 x 4byte (int) records **/
+    /* advance file pointer to first slice */
+    offset = NELEM*NBYTE*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+
+    /* sum the number of stars in data segment of interest */
+    Nstars = 0;
+    for (bin = first; bin < last; bin++) {
+      Nstars += number[bin];
+    }
+    Nitems = NELEM*Nstars;  
+    /* number of blocks to read -- we need to use Fread for byte-swapping read */
+
+    /* read stars from catalog */
+    ALLOCATE (buffer, int, Nitems);
+    nitems = Fread (buffer, NBYTE, Nitems, f, "int");
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failure reading data from file %s\n", filename);
+      exit (1);
+    }
+
+    /* extract the data of interest from segment (in RA and DEC range) */
+    buf = buffer;
+    for (i = 0; i < Nstars; i++, buf += NELEM) {
+      if (buf[0] < iRA0) continue;
+      if (buf[0] > iRA1) continue;
+      if (buf[1] < iDEC0) continue;
+      if (buf[1] > iDEC1) continue;
+
+      memset (&stars[Nusno], 0, sizeof(Stars));
+      stars[Nusno].R     = buf[0]/360000.0;
+      stars[Nusno].D     = buf[1]/360000.0 - 90.0;
+      stars[Nusno].dM    = NAN;
+      stars[Nusno].t     = 0;
+      stars[Nusno].found = -1;
+
+      /* one pass of addstar does either r or b */
+      if (photcode == USNO_RED) {
+	stars[Nusno].code  = USNO_RED;
+	stars[Nusno].M     = fabs (0.1*(buf[2] - 1000*((int)(buf[2]/1000))));
+      } 
+      if (photcode == USNO_BLUE) {	
+	stars[Nusno].code  = USNO_BLUE;
+	stars[Nusno].M     = fabs (0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000));
+      }
+      Nusno ++;
+      CHECK_REALLOCATE (stars, Stars, NUSNO, Nusno, 5000);
+    }
+    free (buffer);
+    fclose (f);
+  }
+  REALLOCATE (stars, Stars, Nusno);
+
+  *nstars = Nusno;
+  if (VERBOSE) fprintf (stderr, "%d stars from USNO 1.0\n", Nusno);
+  return (stars);
+}
+
+
+
+
+/* these entries are legacy code incase you want to read from one of the USNO CDRoms
+int SPDzone[]  = {0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+int USNOdisk[] = {1,  1,   1,   2,    2,    2,   3,    3,    3,   4,    4,   5,   5,   6,   6,    6,   7,   7,   8,    8,    9,    9,  10,   10};
+
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find cdrom for spd %d\n",  spd);
+      exit (1);
+    }
+
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/getusnob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/getusnob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/getusnob.c	(revision 16632)
@@ -0,0 +1,178 @@
+# include "addstar.h"
+# define NBYTE   4
+# define NELEM  20
+
+Stars *getusnob (SkyRegion *catstats, int photcode, int *nstars) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128];
+  FILE *f;
+  double dec;
+  float m1, m2, mag;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end;
+  int NUSNO, Nusno, Nstars;
+  short int USNO_RED, USNO_BLUE;
+  e_time USNOepoch;
+  Stars *stars;
+
+  /* require photcode */
+  NAMED_PHOTCODE (USNO_RED, "USNO_RED");
+  NAMED_PHOTCODE (USNO_BLUE, "USNO_BLUE");
+  if (photcode == USNO_RED) goto good_code;
+  if (photcode == USNO_BLUE) goto good_code;
+  Shutdown ("USNO photcode not specified");
+good_code:
+
+  fprintf (stderr, "loading USNO-B 1.0\n");
+
+  /* identify ra & dec range of interest */
+  /* note: the use of UserPatch to restrict here limits general utility of function */
+  iRA0  =  MAX (catstats[0].Rmin, UserPatch.Rmin) * 360000.0;
+  iRA1  =  MIN (catstats[0].Rmax, UserPatch.Rmax) * 360000.0;
+  iDEC0 = (MAX (catstats[0].Dmin, UserPatch.Dmin) + 90.0) * 360000.0;
+  iDEC1 = (MIN (catstats[0].Dmax, UserPatch.Dmax) + 90.0) * 360000.0;
+  /* note that iDECn is in SPD, while both have units of 0.01 degrees */
+  
+  /* data is organized in south-pole distance zones, 1 deg per direction, 0.1 deg per file */
+  spd_start = (int)(10*(catstats[0].Dmin + 90));
+  dec = 10*(catstats[0].Dmax + 90);
+  if (dec > (int)(dec)) {
+    spd_end =   (int)(1 + 10*(catstats[0].Dmax + 90));
+  } else {
+    spd_end =   (int)(0 + 10*(catstats[0].Dmax + 90));
+  }
+
+  Nusno = 0;
+  NUSNO = 5000;
+  ALLOCATE (stars, Stars, NUSNO);
+
+  for (spd = spd_start; spd < spd_end; spd ++) {
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/%03d/b%04d.acc", USNO_B_DIR, (int)(spd/10), spd); 
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open accelerator file %s\n", filename);
+      exit (1);  
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].Rmin / 3.75;
+    if ((catstats[0].Rmax / 3.75) == (int) (catstats[0].Rmax / 3.75)) 
+      last  = catstats[0].Rmax / 3.75;
+    else 
+      last  = 1 + catstats[0].Rmax / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "ERROR: RA out of range\n");
+      exit (1);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/%03d/b%04d.cat", USNO_B_DIR, (int)(spd/10), spd); 
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s\n", filename);
+      exit (1);
+    }
+
+    /** USNO-B consists of 20 x 4byte (int) records **/
+    /* advance file pointer to first slice */
+    offset = NELEM*NBYTE*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+
+    /* sum the number of stars in data segment of interest */
+    Nstars = 0;
+    for (bin = first; bin < last; bin++) {
+      Nstars += number[bin];
+    }
+    Nitems = NELEM*Nstars;  
+    /* number of blocks to read -- we need to use Fread for byte-swapping read */
+
+    /* allocate space for stars in segment and read */
+    ALLOCATE (buffer, int, Nitems);
+    // data has the WRONG byte order?
+    // nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+    nitems = fread (buffer, NBYTE, Nitems, f);
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failure reading data from file %s\n", filename);
+      exit (1);
+    }
+
+    USNOepoch = ohana_date_to_sec ("2000/01/01,00:00:00");
+
+    buf = buffer;
+    /* print out data from slice within RA and DEC range */
+    for (i = 0; i < Nstars; i++, buf += NELEM) {
+      if (buf[0] < iRA0) continue;
+      if (buf[0] > iRA1) continue;
+      if (buf[1] < iDEC0) continue;
+      if (buf[1] > iDEC1) continue;
+      
+      /* USNO coords are reported for J2000 / epoch 2000.0 */
+      /* extract the basic stellar data */
+      memset (&stars[Nusno], 0, sizeof(Stars));
+      stars[Nusno].R   = buf[0]/360000.0;
+      stars[Nusno].D   = buf[1]/360000.0 - 90.0;
+
+      /* XXX uR cos(D) or just uR ??? */
+      stars[Nusno].uR  = 2.0 * ((buf[2]       % 10000) - 5000);
+      stars[Nusno].uD  = 2.0 * ((buf[2]/10000 % 10000) - 5000);
+
+      stars[Nusno].duR = (buf[3]      % 1000);
+      stars[Nusno].duD = (buf[3]/1000 % 1000);
+
+      stars[Nusno].dR  = 0.001 * (buf[4]      % 1000);
+      stars[Nusno].dD  = 0.001 * (buf[4]/1000 % 1000);
+
+      stars[Nusno].P   = 0;
+      stars[Nusno].dP  = 0;
+
+      /* USNO magnitude errors are reported as a fixed 0.3 mag */
+      stars[Nusno].dM    = 0.3;
+      stars[Nusno].found = -1;
+      
+      /* USNO-B uses J2000 equinox and 2000.0 epoch for coordinates */
+      /* the magnitudes have no temporal information */ 
+      stars[Nusno].t     = USNOepoch;
+
+      /* one pass of addstar does either r or b */
+      if (photcode == USNO_BLUE) {
+	m1 = fabs(0.01 * (buf[5] % 10000)); /* 1st blue mag */
+	m2 = fabs(0.01 * (buf[7] % 10000)); /* 1st blue mag */
+	stars[Nusno].code  = USNO_BLUE;
+      } else {
+	m1 = fabs(0.01 * (buf[6] % 10000)); /* 1st red mag */
+	m2 = fabs(0.01 * (buf[8] % 10000)); /* 2nd red mag */
+	stars[Nusno].code  = USNO_RED;
+      }	
+
+      /* if two mags are available, get an average */
+      if (m1 && m2) {
+	mag = 0.5*(m1 + m2);
+      } else {
+	mag = (m1) ? m1 : m2;
+      }
+      stars[Nusno].M = (mag == 0.0) ? 32.0 : mag;
+
+      Nusno ++;
+      CHECK_REALLOCATE (stars, Stars, NUSNO, Nusno, 5000);
+    }
+    free (buffer);
+    fclose (f);
+  }
+
+  REALLOCATE (stars, Stars, MAX (1, Nusno));
+
+  *nstars = Nusno;
+  if (VERBOSE) fprintf (stderr, "%d stars from USNO-B 1.0\n", Nusno);
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/greference.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/greference.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/greference.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "addstar.h"
+# define LOAD_ALLSKY 0
+# define LOAD_DR2    1
+
+Stars *grefcat (char *Refcat, SkyRegion *region, int photcode, int *nstars) {
+
+  int Nstars;
+  Stars *stars;
+
+  if (VERBOSE) fprintf (stderr, "loading reference catalog data from %s\n", Refcat); 
+  if (VERBOSE) fprintf (stderr, "full region: %f - %f, %f - %f\n", region[0].Rmin, region[0].Rmax, region[0].Dmin, region[0].Dmax);
+
+  Nstars = 0;
+  stars = NULL;
+
+  /* get stars from USNO for the given region */
+  if (!strcasecmp (Refcat, "USNO")) {
+    stars = getusno (region, photcode, &Nstars);
+  }
+
+  /* get stars from the USNO B catalog for the given region */
+  if (!strcasecmp (Refcat, "USNOB")) {
+    stars = getusnob (region, photcode, &Nstars);
+  }
+
+  /* get stars from the USNO B catalog for the given region */
+  if (!strcasecmp (Refcat, "TYCHO")) {
+    stars = gettycho (region, photcode, &Nstars);
+  }
+
+  /* get stars from HST GSC for the given region */
+  if (!strcasecmp (Refcat, "GSC")) {
+    stars = getgsc (region, &Nstars);
+  }
+  
+  /* get stars from 2MASS for the given region */
+  if (!strcasecmp (Refcat, "2MASS")) {
+    stars = get2mass (region, photcode, LOAD_ALLSKY, &Nstars);
+  }
+  
+  /* get stars from 2MASS for the given region */
+  if (!strcasecmp (Refcat, "2MASS-ALLSKY")) {
+    stars = get2mass (region, photcode, LOAD_ALLSKY, &Nstars);
+  }
+  
+  /* get stars from 2MASS for the given region */
+  if (!strcasecmp (Refcat, "2MASS-DR2")) {
+    stars = get2mass (region, photcode, LOAD_DR2, &Nstars);
+  }
+  
+  if (VERBOSE && (Nstars == 0)) fprintf (stderr, "no ref objects in region %s\n", region[0].name);
+
+  *nstars = Nstars;
+  return (stars);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/grefstars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/grefstars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/grefstars.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "addstar.h"
+
+/* read ASCII file with ref star data */
+Stars *grefstars (char *file, int photcode, int *Nstars) {
+
+  FILE *f;
+  int N, NSTARS;
+  Stars *stars;
+  char line[256];
+
+  /* open file */
+  f = fopen (file, "r");
+  if (f == NULL) Shutdown ("can't read data from %s", file);
+
+  NSTARS = 100;
+  ALLOCATE (stars, Stars, NSTARS);
+
+  /* read in stars line-by-line */
+  for (N = 0; scan_line (f, line) != EOF; N++) {
+    stripwhite (line);
+    if (line[0] == 0) continue;
+    if (line[0] == '#') continue;
+    dparse (&stars[N].R,  1, line);
+    dparse (&stars[N].D,  2, line);
+    dparse (&stars[N].M,  3, line);
+    dparse (&stars[N].dM, 4, line);
+    while (stars[N].R < 0.0) stars[N].R += 360.0;
+    while (stars[N].R >= 360.0) stars[N].R -= 360.0;
+    stars[N].t = 0;
+    stars[N].code = photcode;
+    stars[N].found = FALSE;
+    CHECK_REALLOCATE (stars, Stars, NSTARS, N+1, 100);
+  }
+  *Nstars = N;
+  return (stars);
+}
+
+/* stars.found is set here to FALSE.
+   find_match_refstars uses stars.found to identify the seq number of the
+   star which is found.  it requires an initial value of -1 XXX
+*/
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/gztest.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/gztest.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/gztest.c	(revision 16632)
@@ -0,0 +1,99 @@
+# include "ohana.h"
+# include "zlib.h"
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+main (int argc, char **argv) {
+
+  int N, Nread, Nseek, Nback;
+  char *filename, *buffer;
+  gzFile gf;
+  FILE *f;
+  struct timeval start, stop;
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: gztest (mode) (file) (Nseek) (Nread) (Nback)\n");
+    exit (2);
+  }
+
+  filename = argv[2];
+  Nseek = atoi (argv[3]);
+  Nread = atoi (argv[4]);
+  Nback = -1 * atoi (argv[5]);
+  ALLOCATE (buffer, char, Nread);
+
+  if (!strcmp (argv[1], "gz")) {
+    gf = gzopen (filename, "rb");
+    if (gf == NULL) {
+      fprintf (stderr, "can't read data file: %s", filename);
+      exit (1);
+    }
+
+    gettimeofday (&start, NULL);
+    N = gzseek (gf, Nseek, SEEK_SET);
+    gettimeofday (&stop, NULL);
+    if (N != Nseek) {
+      fprintf (stderr, "error seeking\n");
+      exit (1);
+    }
+    fprintf (stdout, "seek: %f\n", DTIME (stop, start));
+
+    gettimeofday (&start, NULL);
+    N = gzread (gf, buffer, Nread);
+    if (N != Nread) {
+      fprintf (stderr, "error reading\n");
+      exit (1);
+    }
+    gettimeofday (&stop, NULL);
+    fprintf (stdout, "read: %f\n", DTIME (stop, start));
+
+    gettimeofday (&start, NULL);
+    N = gzseek (gf, Nback, SEEK_CUR);
+    gettimeofday (&stop, NULL);
+    if (N == -1) {
+      fprintf (stderr, "error seeking\n");
+      exit (1);
+    }
+    fprintf (stdout, "back: %f\n", DTIME (stop, start));
+    exit (0);
+  } 
+
+  if (!strcmp (argv[1], "raw")) {
+    f = fopen (filename, "r");
+    if (f == NULL) {
+      fprintf (stderr, "can't read data file: %s", filename);
+      exit (1);
+    }
+
+    gettimeofday (&start, NULL);
+    N = fseek (f, Nseek, SEEK_SET);
+    gettimeofday (&stop, NULL);
+    if (N) {
+      fprintf (stderr, "error seeking\n");
+      exit (1);
+    }
+    fprintf (stdout, "seek: %f\n", DTIME (stop, start));
+
+    gettimeofday (&start, NULL);
+    N = fread (buffer, 1, Nread, f);
+    gettimeofday (&stop, NULL);
+    if (N != Nread) {
+      fprintf (stderr, "error reading\n");
+      exit (1);
+    }
+    fprintf (stdout, "read: %f\n", DTIME (stop, start));
+
+    gettimeofday (&start, NULL);
+    N = fseek (f, Nback, SEEK_CUR);
+    gettimeofday (&stop, NULL);
+    if (N) {
+      fprintf (stderr, "error seeking\n");
+      exit (1);
+    }
+    fprintf (stdout, "back: %f\n", DTIME (stop, start));
+    exit (0);
+  }
+    
+  
+  fprintf (stderr, "unknown mode\n");
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/in_image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/in_image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/in_image.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "addstar.h"
+
+int in_image (double r, double d, Image *image) {
+
+  double X, Y;
+
+  RD_to_XY (&X, &Y, r, d, &image[0].coords);
+  if (X < 0) return (FALSE);
+  if (Y < 0) return (FALSE);
+  if (X >= image[0].NX) return (FALSE);
+  if (Y >= image[0].NY) return (FALSE);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "addstar.h"
+# include "2mass.h"
+
+int main (int argc, char **argv) {
+
+  char *path;
+  int i;
+  SkyTable *sky, *sky2mass;
+  AddstarClientOptions options;
+
+  // need to construct these options with args_load2mass...
+  options = ConfigInit (&argc, argv);
+  options = args_load2mass (argc, argv, options);
+
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  path = TWO_MASS_DIR_AS;
+
+  // the accel.dat file has the raw filenames
+  // test if the file exists, or else try the .gz version
+  sky2mass = load2mass_acc (path, "accel.dat");
+  
+  for (i = 0; i < sky2mass[0].Nregions; i++) {
+    fprintf (stderr, "loading %s\n", sky2mass[0].filename[i]);
+    load2mass_as_rawdata (sky, sky2mass[0].filename[i], options);
+  }
+  exit (0);
+}  
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass_as_rawdata.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass_as_rawdata.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass_as_rawdata.c	(revision 16632)
@@ -0,0 +1,212 @@
+# include "addstar.h"
+# include "2mass.h"
+
+/* unlike the DR2 data, the AS data is NOT fixed bytes/row 
+ * we need to handle fractional lines at the end of each read block
+ */
+
+/* read in chunks of ~64MB */
+# define NBYTE 0x4000000
+# define NBREC 330
+# define DEBUG 0
+
+int load2mass_as_rawdata (SkyTable *skytable, char *filename, AddstarClientOptions options) {
+  
+  int i, j, verbose;
+  int Nstars, NSTARS, Ntstars, NTSTARS;
+  int Nbyte, Nextra, Ntotal, offset;
+
+  double Rmin, Rmax, Dmin, Dmax;
+
+  FILE *f;
+  char *buffer, *p, *q;
+
+  Stars *stars;
+  TMStars *tstars;
+  SkyList *skylist;
+  SkyRegion *region;
+  Catalog catalog;
+
+  get2mass_setup (-1);
+
+  ALLOCATE (buffer, char, NBYTE);
+
+  // scan through the entire 2MASS file
+  f = fopen (filename, "r");
+  if (f == NULL) Shutdown ("can't read 2mass data file: %s", filename);
+  // test if this is a raw datafile or gzipped...
+
+  Nextra = 0;  // number excess bytes from lsat partial row
+  Ntotal = 0;  // track the total number of bytes read 
+  while ((Nbyte = fread (&buffer[Nextra], 1, NBYTE-Nextra, f)) != 0) {
+    if (Nbyte == -1) Shutdown ("error reading from raw file %s", filename);
+    if (DEBUG) fprintf (stderr, "read %d bytes", Nbyte);
+
+    Nbyte += Nextra;
+
+    if (VERBOSE) fprintf (stderr, ".");
+
+    /* find bounds on first complete line */
+    p = buffer;
+    q = memchr (p, '\n', Nbyte);
+    if (q == NULL) Shutdown ("incomplete line at end of file\n");
+    offset = p - buffer; // offset within this scan
+
+    Ntstars = 0;
+    NTSTARS = 10000;
+    ALLOCATE (tstars, TMStars, NTSTARS);
+
+    Rmin = 360.0;
+    Rmax =   0.0;
+    Dmin = +90.0;
+    Dmax = -90.0;
+
+    // scan through entire buffer for star coords
+    while (1) {
+      get2mass_coords (p, &tstars[Ntstars].R, &tstars[Ntstars].D, Nbyte - offset);
+      tstars[Ntstars].offset = offset; // offset within scan
+      tstars[Ntstars].flag = FALSE;
+
+      if (VERBOSE) {
+	Rmin = MIN (Rmin, tstars[Ntstars].R);
+	Rmax = MAX (Rmax, tstars[Ntstars].R);
+	Dmin = MIN (Dmin, tstars[Ntstars].D);
+	Dmax = MAX (Dmax, tstars[Ntstars].D);
+      }
+
+      Ntstars ++;
+      CHECK_REALLOCATE (tstars, TMStars, NTSTARS, Ntstars, 10000);
+
+      /* start of the next line */
+      p = q + 1;
+      offset = p - buffer; // offset within this scan
+      if (offset == Nbyte) {
+	// last line in buffer is a complete line
+	Nextra = 0;
+	break;
+      }
+      /* end of the next line */
+      q = memchr (p, '\n', Nbyte - offset);
+      if (q == NULL) {
+	// last, incomplete line in buffer
+	Nextra = Nbyte - offset;
+	break;
+      } 
+    }
+    if (VERBOSE) fprintf (stderr, "read %d stars (%10.6f - %10.6f, %10.6f - %10.6f)\n", Ntstars, Rmin, Rmax, Dmin, Dmax);
+
+
+    // scan through the stars, loading the containing catalogs
+    // skip through table for unsaved stars
+    for (i = 0; i < Ntstars; i++) {
+      if (tstars[i].flag) continue;
+
+      // collect stars in a new output catalog
+      Nstars = 0;
+      NSTARS = 3000;
+      ALLOCATE (stars, Stars, NSTARS);
+	
+      // identify the relevant catalog
+      skylist = SkyRegionByPoint (skytable, -1, tstars[i].R, tstars[i].D);
+      region = skylist[0].regions[0];
+      if (DEBUG) fprintf (stderr, "writing to %s\n", skylist[0].filename[0]);
+
+      for (j = i; j < Ntstars; j++) {
+	if (tstars[j].flag) continue;
+
+	// check if in skyregion
+	if (tstars[j].R < region[0].Rmin) continue;
+	if (tstars[j].R > region[0].Rmax) continue;
+	if (tstars[j].D < region[0].Dmin) continue;
+	if (tstars[j].D > region[0].Dmax) continue;
+	  
+	// check if in UserPatch
+	if (tstars[j].R < UserPatch.Rmin) continue;
+	if (tstars[j].R > UserPatch.Rmax) continue;
+	if (tstars[j].D < UserPatch.Dmin) continue;
+	if (tstars[j].D > UserPatch.Dmax) continue;
+	  
+	offset = tstars[j].offset;
+
+	stars[Nstars+0].R = tstars[j].R;
+	stars[Nstars+0].D = tstars[j].D;
+	stars[Nstars+1].R = tstars[j].R;
+	stars[Nstars+1].D = tstars[j].D;
+	stars[Nstars+2].R = tstars[j].R;
+	stars[Nstars+2].D = tstars[j].D;
+	get2mass_3star (&stars[Nstars], &buffer[offset], Nbyte - offset);
+	// get2mass_star (&stars[Nstars], &buffer[offset], Nbyte - offset);
+
+	tstars[j].flag = TRUE;
+
+	Nstars += 3;
+	if (Nstars >= NSTARS - 3) {
+	  NSTARS += 3000;
+	  REALLOCATE (stars, Stars, NSTARS);
+	}
+      }
+      if (!Nstars) {
+	free (stars);
+	continue;
+      }
+      if (DEBUG) fprintf (stderr, "selected %d stars (%10.6f - %10.6f, %10.6f - %10.6f\n", Nstars, 
+			  region[0].Rmin, region[0].Rmax, region[0].Dmin, region[0].Dmax);
+
+      if (1) {
+	verbose = VERBOSE;
+	VERBOSE = FALSE;
+
+	// now we have all of the loaded stars in this catalog
+	catalog.filename = skylist[0].filename[0];
+	catalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+	catalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+	catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+	catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+	// an error exit status here is a significant error
+	if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+	  fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+	  exit (2);
+	}
+
+	// assume no input star matches an existing star 
+	// simply add to the existing table
+	load2mass_catalog (&catalog, stars, Nstars);
+
+	dvo_catalog_save (&catalog, VERBOSE);
+	dvo_catalog_unlock (&catalog);
+	dvo_catalog_free (&catalog);
+	// free (catalog.filename);
+	// XXX don't free this! it points to an element of the skytable
+      }
+
+      SkyListFree (skylist);
+      free (stars);
+      VERBOSE = verbose;
+    }
+    free (tstars);
+
+    // at end, p points at the start of last, partial line
+    if (Nextra) memmove (buffer, p, Nextra);
+  }
+
+  if (VERBOSE) fprintf (stderr, "\n");
+  
+  fclose (f);
+  free (buffer);
+  return (TRUE);
+}
+
+/*
+  for each 2mass file:
+  for each data block
+  generate a table of: R, D, byte, flag
+  for each unsaved star
+  find containing catalog
+  load catalog
+  find all contained stars
+  add to catalog
+  save catalog 
+  mark all contained stars
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass_catalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass_catalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/load2mass_catalog.c	(revision 16632)
@@ -0,0 +1,83 @@
+# include "addstar.h"
+
+int load2mass_catalog (Catalog *catalog, Stars *stars, int Nstars) {
+
+  int i, j, Nsec, Nmeas, Nave, NMEAS, NAVE;
+
+  Nsec = GetPhotcodeNsecfilt ();
+  Nave = catalog[0].Naverage;
+  Nmeas = catalog[0].Nmeasure;
+   
+  NAVE = Nave + 100;
+  NMEAS = Nmeas + 100;
+  REALLOCATE (catalog[0].average, Average, NAVE);
+  REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*Nsec);
+  REALLOCATE (catalog[0].measure, Measure, NMEAS);
+
+  for (i = 0; i < Nstars; i+=3) {
+
+    // construct an average object for this object
+    // XXX for now, the output objects will have limited astrometric interpretation...
+    // XXX every 3 stars represents 3 measurements and 1 average
+    catalog[0].average[Nave].R     = stars[i].R;
+    catalog[0].average[Nave].D     = stars[i].D;
+    catalog[0].average[Nave].dR    = 0;
+    catalog[0].average[Nave].dD    = 0;
+    catalog[0].average[Nave].uR    = 0;
+    catalog[0].average[Nave].uD    = 0;
+    catalog[0].average[Nave].duR   = 0;
+    catalog[0].average[Nave].duD   = 0;
+    catalog[0].average[Nave].P     = 0;
+    catalog[0].average[Nave].dP    = 0;
+
+    // XXX for now, set the average mag data to NULL
+    catalog[0].average[Nave].Nm        = 0;
+    catalog[0].average[Nave].Nn        = 0;
+    catalog[0].average[Nave].Xp        = NAN_S_SHORT;
+    catalog[0].average[Nave].offset    = Nmeas;
+    catalog[0].average[Nave].missing   = -1;
+    catalog[0].average[Nave].code      = 0;
+
+    for (j = 0; j < Nsec; j++) {
+      catalog[0].secfilt[Nave*Nsec+j].M  = NAN;
+      catalog[0].secfilt[Nave*Nsec+j].dM = NAN;
+      catalog[0].secfilt[Nave*Nsec+j].Xm = NAN_S_SHORT;
+    }
+
+    // we now have the min chisq row. use this to supply the other filter values....
+    for (j = 0; j < 3; j++) {
+      catalog[0].measure[Nmeas].dR       = 0.0;
+      catalog[0].measure[Nmeas].dD       = 0.0;
+      catalog[0].measure[Nmeas].M        = stars[i+j].M;
+      catalog[0].measure[Nmeas].dM       = stars[i+j].dM;
+      catalog[0].measure[Nmeas].Mcal     = 0;
+      catalog[0].measure[Nmeas].t        = stars[i+j].t;
+      catalog[0].measure[Nmeas].averef   = Nave;
+      catalog[0].measure[Nmeas].photcode = stars[i+j].code;
+      catalog[0].measure[Nmeas].dophot   = 0;
+      catalog[0].measure[Nmeas].dbFlags  = 0;
+      catalog[0].measure[Nmeas].dt       = 0xffff;
+
+      catalog[0].measure[Nmeas].Mgal     = NAN;
+      catalog[0].measure[Nmeas].airmass  = 0;
+      catalog[0].measure[Nmeas].FWx      = NAN_S_SHORT;
+      catalog[0].measure[Nmeas].FWy      = NAN_S_SHORT;
+      catalog[0].measure[Nmeas].theta    = NAN_S_SHORT;
+
+      catalog[0].average[Nave].Nm++;
+      Nmeas ++;
+      CHECK_REALLOCATE (catalog[0].measure, Measure, NMEAS, Nmeas, 100);
+    }
+
+    Nave ++;
+    if (Nave >= NAVE) {
+      NAVE += 100;
+      REALLOCATE (catalog[0].average, Average, NAVE);
+      REALLOCATE (catalog[0].secfilt, SecFilt, NAVE*Nsec);
+    }
+  }
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nsecf_mem = Nave*Nsec;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/load_subpix.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/load_subpix.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/load_subpix.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "addstar.h"
+
+typedef struct {
+  double Amp;
+  double Phase;
+  double dM;
+} SubPixFix;
+
+static int Nsubpix;
+static SubPixFix *Subpix;
+
+void load_subpix () {
+
+  int i;
+  FILE *f;
+
+  Nsubpix = 40;
+  ALLOCATE (Subpix, SubPixFix, Nsubpix);
+
+  f = fopen (SubpixDatafile, "r");
+  if (f == NULL) Shutdown ("can't load subpix datafile %s", SubpixDatafile);
+
+  for (i = 0; i < Nsubpix; i++) {
+    fscanf (f, "%*s %*s %lf %lf %lf %*s\n", 
+	    &Subpix[i].Amp, &Subpix[i].Phase, &Subpix[i].dM);
+  }
+  fclose (f);
+
+}
+
+double get_subpix (double x, double y) {
+
+  int bin;
+  double dy, dM;
+
+  dy = y - (int)(y);
+  bin = 5 * (int)(x/100) + (int)(y/100);
+  dM = Subpix[bin].Amp*sin(2*3.14159*dy + Subpix[bin].Phase);
+  return (dM);
+}
+
+double scat_subpix (double x, double y) {
+
+  int bin;
+  double dy, dM;
+
+  dy = y - (int)(y);
+  bin = 5 * (int)(x/100) + (int)(y/100);
+  dM = Subpix[bin].dM;
+  return (dM);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/mkacc-2mass.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/mkacc-2mass.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/mkacc-2mass.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "addstar.h"
+# include "2mass.h"
+
+int main (int argc, char **argv) {
+
+  int i, N, Nrefcat;
+  Stars *refcat;
+  SkyRegion *regions, accregion;
+
+  ConfigInit (&argc, argv);
+
+  /* override any header PHOTCODE values */
+  thiscode = NULL;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    remove_argument (N, &argc, argv);
+    thiscode = GetPhotcodebyName (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: mkacc.2mass (file)\n");
+    exit (2);
+  }
+
+  NAMED_PHOTCODE (TM_J, "2MASS_J");
+  NAMED_PHOTCODE (TM_H, "2MASS_H");
+  NAMED_PHOTCODE (TM_K, "2MASS_K");
+  if (thiscode == NULL) Shutdown ("photcode not specified");
+  if (thiscode[0].code == TM_J) goto good_code;
+  if (thiscode[0].code == TM_H) goto good_code;
+  if (thiscode[0].code == TM_K) goto good_code;
+  Shutdown ("2MASS photcode not specified");
+
+good_code:
+  UserPatch.RAmin = 0;
+  UserPatch.RAmax = 360;
+  UserPatch.DECmin = -90;
+  UserPatch.DECmax = +90;
+
+  ALLOCATE (regions, SkyRegion, 1);
+  strcpy (regions[0].filename, argv[1]);
+  regions[0].RAmin = 0;
+  regions[0].RAmax = 360;
+  regions[0].DECmin = -90;
+  regions[0].DECmax = +90;
+
+  refcat = get2mass_AS_data (regions, &UserPatch, &Nrefcat);
+
+  /* find upper and lower file limits in RA and DEC */
+
+  strcpy (accregion.filename, regions[0].filename);
+  accregion.RAmin  = 360;
+  accregion.RAmax  =   0;
+  accregion.DECmin = +90;
+  accregion.DECmax = -90;
+
+  for (i = 0; i < Nrefcat; i++) {
+    accregion.RAmin  = MIN (refcat[i].R, accregion.RAmin);
+    accregion.RAmax  = MAX (refcat[i].R, accregion.RAmax);
+    accregion.DECmin = MIN (refcat[i].D, accregion.DECmin);
+    accregion.DECmax = MAX (refcat[i].D, accregion.DECmax);
+  }
+
+  fprintf (stderr, "%s %10.6f %10.6f  %10.6f %10.6f  %d\n", 
+	   accregion.filename, accregion.RAmin/15.0, accregion.RAmax/15.0, accregion.DECmin, accregion.DECmax, Nrefcat);
+
+  exit (0);
+}
+
+/* XXX update this function to create an additional accelerator file for each 2mass file
+   each file: one row per DEC band
+   each row: Rmin, Rmax, Dmin, Dmax, Nbyte(i)
+   where Nbyte(i) = byte for each Rmin + i*30 deg transition
+*/
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/opening_angle.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/opening_angle.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/opening_angle.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "addstar.h"
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/parse_time.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/parse_time.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/parse_time.c	(revision 16632)
@@ -0,0 +1,146 @@
+# include "addstar.h"
+
+int parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    if (!gfits_scan (header, JDKeyword, "%lf", 1, &jd)) {
+      fprintf (stderr, "ERROR: missing JD Keyword %s\n", JDKeyword);
+      exit (1);
+    }
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    if (!gfits_scan (header, MJDKeyword, "%lf", 1, &jd)) {
+      fprintf (stderr, "ERROR: missing MJD Keyword %s\n", MJDKeyword);
+      exit (1);
+    }
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  if (!strcasecmp (UTKeyword, "NONE")) {
+      fprintf (stderr, "ERROR: no valid Date/Time keywords\n");
+      exit (1);
+  }
+  if (!strcasecmp (DateKeyword, "NONE")) {
+      fprintf (stderr, "ERROR: no valid Date/Time keywords\n");
+      exit (1);
+  }
+  if (!strcasecmp (DateMode, "NONE")) {
+      fprintf (stderr, "ERROR: no valid Date/Time keywords\n");
+      exit (1);
+  }
+
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  if (!gfits_scan (header, UTKeyword, "%s", 1, line)) {
+      fprintf (stderr, "ERROR: missing UT Keyword %s\n", UTKeyword);
+      exit (1);
+    }
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  if (!gfits_scan (header, DateKeyword, "%s",  1, line)) {
+    fprintf (stderr, "ERROR: missing DATE Keyword %s\n", DateKeyword);
+    exit (1);
+  }
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  Nf = 0;
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    exit (1);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* this should probably use localtime */
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/replace_match.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/replace_match.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/replace_match.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "addstar.h"
+
+int replace_match (Average *average, Measure *measure, Stars *star) {
+
+  int i;
+
+  /* search for entry and replace values M, dM, R, D */
+  for (i = 0; i < average[0].Nm; i++) {
+    if (measure[i].photcode != star[0].code) continue;
+    measure[i].dR = 3600.0*(average[0].R - star[0].R);
+    measure[i].dD = 3600.0*(average[0].D - star[0].D);
+    measure[i].M  = star[0].M;
+    measure[i].dM = star[0].dM;
+    star[0].found = average[0].offset + i;
+    return (TRUE);
+  }
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/resort_catalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/resort_catalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/resort_catalog.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "addstar.h"
+
+void resort_catalog (Catalog *catalog) {
+
+  int *next_meas;
+  int Naves, Nmeas;
+  double dtime;
+  struct timeval start, stop;
+
+  if (catalog[0].sorted == TRUE) return;
+
+  gettimeofday (&start, NULL);
+
+  /* internal counters */
+  Nmeas = catalog[0].Nmeasure;
+  Naves = catalog[0].Naverage;
+  
+  /* set up pointers for linked list of measure, missing */
+  next_meas = build_measure_links (catalog[0].average, Naves, catalog[0].measure, Nmeas);
+
+  catalog[0].sorted = TRUE;
+  catalog[0].measure = sort_measure (catalog[0].average, Naves, catalog[0].measure, Nmeas, next_meas);
+
+  gettimeofday (&stop, NULL);
+  dtime = DTIME (stop, start);
+  fprintf (stderr, "  match time %9.4f sec for %7d measures, %6d average\n", dtime, Nmeas, Naves);
+
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/sedstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/sedstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/sedstar.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "sedstar.h"
+
+int main (int argc, char **argv) {
+
+  char *root, *ext, tmp;
+  int i, Nbytes;
+  SkyList *skylist;
+  SkyTable *sky;
+  AddstarClientOptions options;
+  Catalog incatalog, outcatalog;
+  SEDtable *sedtable;
+
+  // need to construct these options with args_load2mass...
+  options = ConfigInit (&argc, argv);
+  options = args_sedstar (argc, argv, options);
+
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  // select regions of interest
+  skylist = SkyListByPatch (sky, -1, &UserPatch);
+
+  // load the SED data table
+  sedtable = SEDtableLoad (argv[1]);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    incatalog.filename = skylist[0].filename[i];
+    incatalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&incatalog, skylist[0].regions[i], VERBOSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", incatalog.filename);
+      exit (2);
+    }
+
+    // Naves_disk == 0 implies an empty catalog file
+    if ((incatalog.Naves_disk == 0) && options.only_match) {
+      if (VERBOSE) fprintf (stderr, "skipping empty region\n");
+      dvo_catalog_unlock (&incatalog);
+      dvo_catalog_free (&incatalog);
+      continue;
+    }
+
+    // create output catalog filename
+    root = strstr (incatalog.filename, CATDIR);
+    if (root == NULL) Shutdown ("error with input catalog name");
+    ext = incatalog.filename + strlen(CATDIR);
+    while (*ext == '/') ext++;
+    Nbytes = snprintf (&tmp, 0, "%s/%s", argv[2], ext);
+    ALLOCATE (outcatalog.filename, char, Nbytes + 1);
+    snprintf (outcatalog.filename, Nbytes + 1, "%s/%s", argv[2], ext);
+
+    outcatalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    outcatalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+    outcatalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    outcatalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&outcatalog, skylist[0].regions[i], VERBOSE, "w")) {
+      Shutdown ("ERROR: failure to open/create catalog file %s\n", outcatalog.filename);
+    }
+
+    SEDfitCatalog (&outcatalog, &incatalog, sedtable);
+    
+    dvo_catalog_save (&outcatalog, VERBOSE);
+    dvo_catalog_unlock (&outcatalog);
+    dvo_catalog_free (&outcatalog);
+
+    dvo_catalog_unlock (&incatalog);
+    dvo_catalog_free (&incatalog);
+    // XXX free filename or not?
+  }
+  exit (0);
+}  
+
+/**  sedstar: 
+
+* load in the SED data table
+* load in the catalog file (by region)
+* fit stars in the catalog file
+* load output catalog file?
+* construct output catalog file (optional)
+* save output catalog file
+
+**/
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/sky_tessalation.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/sky_tessalation.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/sky_tessalation.c	(revision 16632)
@@ -0,0 +1,675 @@
+# include "skycells.h"
+# include "assert.h"
+# define iSWAP(X,Y) {int tmp=(X); (X) = (Y); (Y) = tmp;}
+
+// we use a static refcoords structure to avoid multiple alloc / init steps
+static Coords *refcoords = NULL;
+
+int sky_tessalation (FITS_DB *db, int level, int Nmax, int mode, double scale) {
+
+  sky_tessalation_init (scale);
+
+  if (mode == SQUARES) {
+    sky_tessalation_squares (db, level, Nmax);
+    return TRUE;
+  }
+
+  if (mode == TRIANGLES) {
+    sky_tessalation_triangles (db, level, Nmax);
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+int sky_tessalation_triangles (FITS_DB *db, int level, int Nmax) {
+
+  int i, j, Ndigit, Ntriangles, Nbase, Ntotal, Ltop, Nout, Nimages;
+  double Ntop, fLtop;
+  SkyTriangle *base, *tri, *new;
+  Image *image;
+  char format[16];
+
+  // generate the initial base set
+  base = sky_base_triangles (&Nbase);
+
+  sky_base_rotation (base, Nbase);
+
+  // how many triangles total for this level?
+  Ntotal = Nbase*pow(4.0, level);
+  Ndigit = (int)(log10(Ntotal)) + 1 ;
+  snprintf (format, 16, "skytri.%%0%dd", Ndigit);
+
+  // to what depth do we need to go to have only Nmax foreach subcell?
+  Ntop = Ntotal / Nmax;
+  if (Ntop > Nbase) {
+    fLtop = log10(Ntop / Nbase) / log10(4.0);
+    if (fLtop > (int)(fLtop)) {
+      Ltop = fLtop + 1;
+    } else {
+      Ltop = fLtop;
+    }
+  } else {
+    Ltop = 0;
+  }
+
+  // subdivide the base set to Ltop level
+  for (i = 0; i < Ltop; i++) {
+    new = sky_divide_triangles (base, &Nbase);
+    free (base);
+    base = new;
+  }
+
+  // for each base triangle, subdivide the rest of the way and save
+  Nout = 0;
+  for (i = 0; i < Nbase; i++) {
+    ALLOCATE (tri, SkyTriangle, 1);
+    tri[0] = base[i];
+    Ntriangles = 1;
+    for (j = Ltop; j < level; j++) {
+      new = sky_divide_triangles (tri, &Ntriangles);
+      free (tri);
+      tri = new;
+    }
+
+    // convert the SkyTriangles to Image
+    ALLOCATE (image, Image, Ntriangles);
+    for (j = 0; j < Ntriangles; j++) {
+      sky_triangle_to_image (&image[j], &tri[j]);
+      snprintf (image[j].name, 64, format, Nout);
+      Nout++;
+    }  
+    Nimages = Ntriangles;
+
+    /* add the new images and save */
+    dvo_image_addrows (db, image, Nimages);
+    SetProtect (TRUE);
+    dvo_image_update (db, VERBOSE);
+    SetProtect (FALSE);
+    dvo_image_clear_vtable (db);
+
+    free (image);
+    free (tri);
+  }
+  return (TRUE);
+}
+
+int sky_tessalation_squares (FITS_DB *db, int level, int Nmax) {
+
+  int i, j, Nname, Ndigit, Ntriangles, Nbase, Nimage, Ntotal, Ntop, Ltop, Nsubset, Nx, Ny;
+  double fLtop;
+  SkyTriangle *base, *tri, *new;
+  SkyRectangle *rectangle, *subset;
+  Image *image;
+  char format[16];
+
+  Nx = NX_SUB;
+  Ny = NY_SUB;
+
+  // generate the initial base set
+  base = sky_base_triangles (&Nbase);
+
+  sky_base_rotation (base, Nbase);
+
+  // how many total cells for this level (multiply by subdivisions, if used)?
+  Ntotal = Nbase*pow(4.0, level);
+  Ndigit = (int)(log10(Ntotal)) + 1 ;
+  snprintf (format, 16, "skycell.%%0%dd", Ndigit);
+
+  // to what depth do we need to go to have only Nmax foreach subcell?
+  Ntop = Ntotal / (Nmax*Nx*Ny) ;
+  if (Ntop > Nbase) {
+    fLtop = log10(Ntotal / (double)(Ntop * Nbase)) / log10(4.0);
+    if (fLtop > (int)(fLtop)) {
+      Ltop = fLtop + 1;
+    } else {
+      Ltop = fLtop;
+    }
+  } else {
+    Ltop = 0;
+  }
+
+  // subdivide the base set to Ltop level
+  for (i = 0; i < Ltop; i++) {
+    new = sky_divide_triangles (base, &Nbase);
+    free (base);
+    base = new;
+  }
+
+  // for each base triangle, subdivide the rest of the way and save
+  Nname = 0;
+  for (i = 0; i < Nbase; i++) {
+    ALLOCATE (tri, SkyTriangle, 1);
+    tri[0] = base[i];
+    Ntriangles = 1;
+    for (j = Ltop; j < level; j++) {
+      new = sky_divide_triangles (tri, &Ntriangles);
+      free (tri);
+      tri = new;
+    }
+
+    // convert the SkyTriangles to SkyRectangles
+    ALLOCATE (rectangle, SkyRectangle, Ntriangles);
+    for (j = 0; j < Ntriangles; j++) {
+      sky_triangle_to_rectangle (&rectangle[j], &tri[j]);
+    }  
+
+    // drop the appropriate subset
+    ALLOCATE (subset, SkyRectangle, Ntriangles);
+    for (j = Nsubset = 0; j < Ntriangles; j++) {
+      if (!strcmp(rectangle[j].coords.ctype, "DROP")) continue;
+      memcpy (&subset[Nsubset], &rectangle[j], sizeof(SkyRectangle));
+      snprintf (subset[Nsubset].name, 64, format, Nname);
+      Nname++;
+      Nsubset++;
+    }  
+    free (rectangle);
+
+    // subdivide each image (Nx x Ny subcells)
+    Nimage = Nx*Ny*Nsubset;
+    ALLOCATE (image, Image, Nimage);
+    for (j = 0; j < Nsubset; j++) {
+      // convert the SkyRectangles to Images for output
+      sky_subdivide_image (&image[j*Nx*Ny], &subset[j], Nx, Ny);
+    }
+
+    /* add the new images and save */
+    dvo_image_addrows (db, image, Nimage);
+    SetProtect (TRUE);
+    dvo_image_update (db, VERBOSE);
+    SetProtect (FALSE);
+    dvo_image_clear_vtable (db);
+
+    free (subset);
+    free (image);
+    free (tri);
+  }
+  return (TRUE);
+}
+
+// an allocated image is supplied, we fill in the values
+int sky_triangle_to_image (Image *image, SkyTriangle *triangle) {
+
+  int i, NX, NY;
+  double xv[3], yv[3];	      // coordinates of the vertex in the reference projection 
+  double scale;
+  double Xmin, Xmax, Ymin, Ymax;
+
+  // calculate the triangle coordinates in r,d
+  sky_triangle_coords (triangle);
+
+  // we will project to the triangle center position
+  refcoords[0].crval1 = triangle[0].r;
+  refcoords[0].crval2 = triangle[0].d;
+
+  // project the vertices to this projection, find bounds
+  Xmin = Xmax = Ymin = Ymax = 0.0; // 0,0 is center of triangle
+  for (i = 0; i < 3; i++) {
+    RD_to_XY (&xv[i], &yv[i], triangle[0].rv[i], triangle[0].dv[i], refcoords);
+    Xmin = MIN (xv[i], Xmin);
+    Xmax = MAX (xv[i], Xmax);
+    Ymin = MIN (yv[i], Ymin);
+    Ymax = MAX (yv[i], Ymax);
+  }
+
+  // set NX, NY to the roughly full-width box (centered at 0,0)
+  NX = Xmax - Xmin;
+  NY = Ymax - Ymin;
+
+  memset (image, 0, sizeof(Image));
+  image[0].coords = *refcoords;
+  image[0].coords.pc1_1 = image[0].coords.pc2_2 = 1.0;
+  image[0].coords.pc1_2 = image[0].coords.pc2_1 = 0.0;
+
+  // We cannot use the correction below if we want to set cdelt1,2 to our desired pixel scale
+  // use this test to raise an error (60000 x 60000 is a very large image...)
+  strcpy (image[0].coords.ctype, "TRI--TAN");
+  scale = 0;
+  for (i = 0; i < 3; i++) {
+    scale = MAX (abs(xv[i]), scale);
+    scale = MAX (abs(yv[i]), scale);
+  }
+  if (scale > 32000) {
+    scale /= 30000.0;
+    NX /= scale;
+    NY /= scale;
+    image[0].coords.cdelt1 *= scale;
+    image[0].coords.cdelt2 *= scale;
+    for (i = 0; i < 3; i++) {
+      xv[i] /= scale;
+      yv[i] /= scale;
+    }
+  }
+  image[0].NX = NX;
+  image[0].NY = NY;
+
+  image[0].code = 1; // this needs to be set more sensibly
+
+  image[0].Mx   = xv[0];  image[0].My   = yv[0];
+  image[0].Mxxx = xv[1];  image[0].Mxyy = yv[1];
+  image[0].Mxxy = xv[2];  image[0].Myyy = yv[2];
+
+  return (TRUE);
+}
+
+// an allocated image is supplied, we fill in the values
+// we are only keeping ~half of the images
+int sky_triangle_to_rectangle (SkyRectangle *rectangle, SkyTriangle *triangle) {
+
+  int i, parity, peak, b1, b2, NX, NY, right;
+  double xv[3], yv[3];	      // coordinates of the vertex in the reference projection 
+  double xo, yo, xc, yc, xcr, ycr, angle;
+  double dB, dP, s1, s2, r1, r2, dr, dx, dy;
+  double angle_b1, angle_b2, slope;
+
+  // calculate the triangle coordinates in r,d
+  sky_triangle_coords (triangle);
+
+  // we will project to the triangle center position
+  refcoords[0].crval1 = triangle[0].r;
+  refcoords[0].crval2 = triangle[0].d;
+
+  // find the size, rotation, and parity of the image
+  // project the vertices and find the image parity
+  parity = 1;
+  for (i = 0; i < 3; i++) {
+    RD_to_XY (&xv[i], &yv[i], triangle[0].rv[i], triangle[0].dv[i], refcoords);
+    parity *= SIGN(yv[i]);
+  }
+
+  // choose the peak vertex
+  peak = -1;
+  for (i = 0; (peak == -1) && (i < 3); i++) {
+    if (parity == SIGN(yv[i])) {
+      peak = i;
+    }
+  }
+  assert (peak != -1);
+
+  // angle is from the center to the peak corner
+  angle = atan2(parity*xv[peak], parity*yv[peak]); // note that this is x/y not y/x (and in radians)
+
+  // find the base and height
+  b1 = (peak + 1) % 3;
+  b2 = (peak + 2) % 3;
+
+  // angle is from the center to the peak corner
+  angle_b1 = DEG_RAD*atan(yv[b1] / xv[b1]);
+  angle_b2 = DEG_RAD*atan(yv[b2] / xv[b2]);
+
+  // if one of the base-center angles is very small, the parity is marginal.  Use additional
+  // information to choose the parity.  note that both angle_b1 and angle_b2 cannot be close to
+  // zero.
+  if (fabs(angle_b1) < 10.0) {
+    right = (xv[b1] > 0);     // pointing left or right?
+    slope = (xv[peak] -  xv[b2]) / (yv[peak] - yv[b2]);
+    if ( right && (slope >= 0.0)) parity = +1;
+    if ( right && (slope <  0.0)) parity = -1;
+    if (!right && (slope <= 0.0)) parity = +1;
+    if (!right && (slope >  0.0)) parity = -1;
+    if (parity > 0) {
+      if (yv[peak] < yv[b2]) iSWAP(peak, b2); // require peak to be top (bottom) point
+    } else {
+      if (yv[peak] > yv[b2]) iSWAP(peak, b2); // require peak to be top (bottom) point
+    }
+    angle = atan2(parity*xv[peak], parity*yv[peak]); // note that this is x/y not y/x (and in radians)
+  }
+  if (fabs(angle_b2) < 10.0) {
+    right = (xv[b2] > 0);     // pointing left or right?
+    slope = (xv[peak] - xv[b1]) / (yv[peak] - yv[b1]); // tilt of opposite line
+    if ( right && (slope >= 0.0)) parity = +1;
+    if ( right && (slope <  0.0)) parity = -1;
+    if (!right && (slope <= 0.0)) parity = +1;
+    if (!right && (slope >  0.0)) parity = -1;
+    if (parity > 0) {
+      if (yv[peak] < yv[b1]) iSWAP(peak, b1); // require peak to be top (bottom) point
+    } else {
+      if (yv[peak] > yv[b1]) iSWAP(peak, b1); // require peak to be top (bottom) point
+    }
+    angle = atan2(parity*xv[peak], parity*yv[peak]); // note that this is x/y not y/x (and in radians)
+  }
+
+  // xo, yo is the center of the baseline
+  xo = 0.5*(xv[b2] + xv[b1]);
+  yo = 0.5*(yv[b2] + yv[b1]);
+
+  // find the max perpendicular distance from the peak
+
+  // dB[b1] == dB[b2] (since xo,yo is the midpoint of [b1] to [b2]
+  dB = hypot(xo      -xv[b1], yo      -yv[b1]);
+  dP = hypot(xv[peak]-xo,     yv[peak] -yo);
+	     
+  // XXX we could just choose the point based on s1 vs s2...
+  s1 = hypot(xv[peak]-xv[b1], yv[peak]-yv[b1]);
+  s2 = hypot(xv[peak]-xv[b2], yv[peak]-yv[b2]);
+
+  r1 = (SQ(s1) - SQ(dB) - SQ(dP)) / (2*dP);
+  r2 = (SQ(s2) - SQ(dB) - SQ(dP)) / (2*dP);
+
+  // dr >= 0
+  dr = MAX (r1, r2);
+
+  dx = -parity*dr*sin(angle);
+  dy = -parity*dr*cos(angle);
+
+  xo += dx;
+  yo += dy;
+
+  // xc, yc is the true image center
+  xc = 0.5*(xv[peak] + xo);
+  yc = 0.5*(yv[peak] + yo);
+
+  // NX,NY are the size of the circumscribed square, expanded by PADDING
+  NX = hypot((xv[b2]-xv[b1]),(yv[b2]-yv[b1])) * (1 + PADDING);
+  NY = hypot((xv[peak]-xo),(yv[peak]-yo)) * (1 + PADDING);
+
+  memset (rectangle, 0, sizeof(SkyRectangle));
+  rectangle[0].coords = *refcoords;
+
+  if (FIX_NS) {
+    rectangle[0].coords.pc1_1 = +1.0;
+    rectangle[0].coords.pc1_2 = +0.0;
+    rectangle[0].coords.pc2_1 = -0.0;
+    rectangle[0].coords.pc2_2 = +1.0;
+    xcr = xc*cos(angle) - yc*sin(angle); 
+    ycr = yc*cos(angle) + xc*sin(angle); 
+  } else {
+    rectangle[0].coords.pc1_1 = +cos(angle);
+    rectangle[0].coords.pc1_2 = +sin(angle);
+    rectangle[0].coords.pc2_1 = -sin(angle);
+    rectangle[0].coords.pc2_2 = +cos(angle);
+    xcr = xc;
+    ycr = yc;
+  }
+  
+  // crpix1,crpix2 is the projection center
+  rectangle[0].coords.crpix1 = 0.5*NX - xcr;
+  rectangle[0].coords.crpix2 = 0.5*NY - ycr;
+
+  // only keep one of the parity rectangles
+  if (((triangle[0].d >= 0) && (parity == +1)) || ((triangle[0].d < 0) && (parity == -1))) {
+    strcpy (rectangle[0].coords.ctype, "DEC--TAN");
+  } else {
+    strcpy (rectangle[0].coords.ctype, "DROP");
+  }
+
+  rectangle[0].NX = NX;
+  rectangle[0].NY = NY;
+  rectangle[0].code = 1; // this needs to be set more sensibly
+
+  return (TRUE);
+}
+
+// an allocated image set is supplied, we fill in the values
+int sky_subdivide_image (Image *output, SkyRectangle *input, int Nx, int Ny) {
+
+  int i, j, N, NX, NY, Ndigit;
+  char format[24];
+
+  NX = input[0].NX/(double)Nx + 0.5;
+  NY = input[0].NY/(double)Ny + 0.5;
+
+  // image[0].NX,NY are unsigned short: abort is we overflow
+  if ((NX > 0xffff) || (NY > 0xffff)) {
+    fprintf (stderr, "error: NX,NY too big for DVO limits; modify pixel scale\n");
+    fprintf (stderr, "NX: %d, NY: %d\n", NX, NY);
+    exit (1);
+  }
+
+  Ndigit = (int)(log10(Nx*Ny)) + 1 ;
+  snprintf (format, 24, "%s.%%0%dd", input[0].name, Ndigit);
+
+  N = 0;
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+
+      memset (&output[N], 0, sizeof(Image));
+      memcpy (&output[N].coords, &input[0].coords, sizeof(Coords));
+
+      snprintf (output[N].name, 64, format, N);
+      output[N].NX = NX;
+      output[N].NY = NY;
+      output[N].code = input[0].code;
+
+      output[N].coords.crpix1 = input[0].coords.crpix1 - i*NX;
+      output[N].coords.crpix2 = input[0].coords.crpix2 - j*NY;
+      N++;
+    }
+  }
+  return (TRUE);
+}
+
+int sky_triangle_coords (SkyTriangle *triangle) {
+
+  int i;
+  double r;
+
+  // calculate the triangle center
+  triangle[0].center.x = (triangle[0].vertex[0].x + triangle[0].vertex[1].x + triangle[0].vertex[2].x)/3.0;
+  triangle[0].center.y = (triangle[0].vertex[0].y + triangle[0].vertex[1].y + triangle[0].vertex[2].y)/3.0;
+  triangle[0].center.z = (triangle[0].vertex[0].z + triangle[0].vertex[1].z + triangle[0].vertex[2].z)/3.0;
+
+  // renormalize
+  r = 1.0 / sqrt (SQ(triangle[0].center.x) + SQ(triangle[0].center.y) + SQ(triangle[0].center.z));
+
+  triangle[0].center.x *= r;
+  triangle[0].center.y *= r;
+  triangle[0].center.z *= r;
+
+  triangle[0].d = DEG_RAD * asin(triangle[0].center.z);
+  triangle[0].r = DEG_RAD * atan2(triangle[0].center.y, triangle[0].center.x);
+
+  for (i = 0; i < 3; i++) {
+    triangle[0].dv[i] = DEG_RAD * asin(triangle[0].vertex[i].z);
+    triangle[0].rv[i] = DEG_RAD * atan2(triangle[0].vertex[i].y, triangle[0].vertex[i].x);
+  }
+
+  return TRUE;
+}
+
+// take a list of triangles from one level and return a list of triangles in the next level
+// we are doing basic edge division, always yielding 4x as many new triangles as old;
+SkyTriangle *sky_divide_triangles (SkyTriangle *in, int *ntriangles) {
+
+  int i, j, Ntriangles, Nt;
+  SkyTriangle *out;
+
+  Ntriangles = *ntriangles * 4;
+  ALLOCATE (out, SkyTriangle, Ntriangles);
+
+  Nt = 0;
+  for (i = 0; i < *ntriangles; i++) {
+    for (j = 0; j < 3; j++) {
+      out[4*i + j].vertex[0] = in[i].vertex[j];
+      out[4*i + j].vertex[1] = sky_divide_edge (in[i].vertex[j], in[i].vertex[(j+1)%3]);
+    }
+    for (j = 0; j < 3; j++) {
+      out[4*i + j].vertex[2] = out[4*i + (j+2)%3].vertex[1];
+    }
+    for (j = 0; j < 3; j++) {
+      out[4*i + 3].vertex[j] = out[4*i + j].vertex[1];
+    }
+    Nt += 4;
+  }
+  *ntriangles = Nt;
+  return (out);
+}
+
+// take a list of triangles from one level and return a list of triangles in the next level
+// we are doing basic edge division, always yielding 4x as many new triangles as old;
+Point sky_divide_edge (Point v1, Point v2) {
+
+  double r;
+  Point out;
+
+  out.x = v1.x + v2.x;
+  out.y = v1.y + v2.y;
+  out.z = v1.z + v2.z;
+
+  r = 1.0 / sqrt (SQ(out.x) + SQ(out.y) + SQ(out.z));
+
+  out.x *= r;
+  out.y *= r;
+  out.z *= r;
+
+  return (out);
+}
+
+# define THETA RAD_DEG*26.565
+# define D_PSI RAD_DEG*360.0/5.0
+
+SkyTriangle *sky_base_triangles (int *ntriangles) {
+
+  int i;
+  double ctht, stht, psi;
+  SkyTriangle *tri;
+
+  // generate 0-level triangles
+  ALLOCATE (tri, SkyTriangle, 20);
+
+  for (i = 0; i < 20; i++) {
+    memset (&tri[i], 0, sizeof(SkyTriangle));
+  }
+
+  ctht = cos(THETA);
+  stht = sin(THETA);
+
+  for (i = 0; i < 5; i++) {
+    tri[i].vertex[0].x = +0;
+    tri[i].vertex[0].y = +0;
+    tri[i].vertex[0].z = +1;
+
+    psi = (i + 0.0)*D_PSI;
+    tri[i].vertex[1].x = +ctht*cos(psi);
+    tri[i].vertex[1].y = +ctht*sin(psi);
+    tri[i].vertex[1].z = +stht;
+    
+    psi = (i + 1.0)*D_PSI;
+    tri[i].vertex[2].x = +ctht*cos(psi);
+    tri[i].vertex[2].y = +ctht*sin(psi);
+    tri[i].vertex[2].z = +stht;
+  }    
+  
+  for (i = 5; i < 10; i++) {
+    psi = (i + 0.0)*D_PSI;
+    tri[i].vertex[0].x = +ctht*cos(psi);
+    tri[i].vertex[0].y = +ctht*sin(psi);
+    tri[i].vertex[0].z = +stht;
+    
+    psi = (i + 0.5)*D_PSI;
+    tri[i].vertex[1].x = +ctht*cos(psi);
+    tri[i].vertex[1].y = +ctht*sin(psi);
+    tri[i].vertex[1].z = -stht;
+
+    psi = (i + 1.0)*D_PSI;
+    tri[i].vertex[2].x = +ctht*cos(psi);
+    tri[i].vertex[2].y = +ctht*sin(psi);
+    tri[i].vertex[2].z = +stht;
+  }    
+  
+  for (i = 10; i < 15; i++) {
+    psi = (i + 0.5)*D_PSI;
+    tri[i].vertex[0].x = +ctht*cos(psi);
+    tri[i].vertex[0].y = +ctht*sin(psi);
+    tri[i].vertex[0].z = -stht;
+
+    psi = (i + 1.0)*D_PSI;
+    tri[i].vertex[1].x = +ctht*cos(psi);
+    tri[i].vertex[1].y = +ctht*sin(psi);
+    tri[i].vertex[1].z = +stht;
+    
+    psi = (i + 1.5)*D_PSI;
+    tri[i].vertex[2].x = +ctht*cos(psi);
+    tri[i].vertex[2].y = +ctht*sin(psi);
+    tri[i].vertex[2].z = -stht;
+  }    
+  
+  for (i = 15; i < 20; i++) {
+    psi = (i + 0.5)*D_PSI;
+    tri[i].vertex[1].x = +ctht*cos(psi);
+    tri[i].vertex[1].y = +ctht*sin(psi);
+    tri[i].vertex[1].z = -stht;
+    
+    psi = (i + 1.5)*D_PSI;
+    tri[i].vertex[2].x = +ctht*cos(psi);
+    tri[i].vertex[2].y = +ctht*sin(psi);
+    tri[i].vertex[2].z = -stht;
+
+    tri[i].vertex[0].x = +0;
+    tri[i].vertex[0].y = +0;
+    tri[i].vertex[0].z = -1;
+  }    
+  
+  *ntriangles = 20;
+  return tri;
+}
+
+int sky_base_rotation (SkyTriangle *base, int Nbase) {
+
+  // apply the three euler angles (A, B, C)
+  // XXX for now, just apply A and B
+
+  int i, j, ix;
+  float rot[3][3], v[3];
+
+  rot[0][0] = +cos(EULER_A)*cos(EULER_B);
+  rot[1][0] = +sin(EULER_A)*cos(EULER_B);
+  rot[2][0] = +sin(EULER_B);
+
+  rot[0][1] = -sin(EULER_A);
+  rot[1][1] = +cos(EULER_A);
+  rot[2][1] = +0.0;
+
+  rot[0][2] = -cos(EULER_A)*sin(EULER_B);
+  rot[1][2] = -sin(EULER_A)*sin(EULER_B);
+  rot[2][2] = +cos(EULER_B);
+
+  for (i = 0; i < Nbase; i++) {
+    for (j = 0; j < 3; j++) {
+      for (ix = 0; ix < 3; ix++) {
+	v[ix] = 0.0;
+	v[ix] += base[i].vertex[j].x * rot[0][ix];
+	v[ix] += base[i].vertex[j].y * rot[1][ix];
+	v[ix] += base[i].vertex[j].z * rot[2][ix];
+      }
+      base[i].vertex[j].x = v[0];
+      base[i].vertex[j].y = v[1];
+      base[i].vertex[j].z = v[2];
+    }
+  }
+  return (TRUE);
+}
+
+int sky_tessalation_init (double scale) {
+
+  ALLOCATE (refcoords, Coords, 1);
+  refcoords[0].crval1 = refcoords[0].crval2 = 0.0;
+  refcoords[0].crpix1 = refcoords[0].crpix2 = 0.0;
+  refcoords[0].cdelt1 = refcoords[0].cdelt2 = scale / 3600;
+  refcoords[0].pc1_1 = refcoords[0].pc2_2 = 1.0;
+  refcoords[0].pc1_2 = refcoords[0].pc2_1 = 0.0;
+  refcoords[0].Npolyterms = 0;
+  memset (refcoords[0].polyterms, 0, 14*sizeof(float));
+  strcpy (refcoords[0].ctype, "RA---TAN");
+  return (TRUE);
+}
+
+// free the space used by the current vtable entries
+int dvo_image_clear_vtable (FITS_DB *db) {
+
+  int i;
+
+  // free memory used by the current vtable rows
+  for (i = 0; i < db[0].vtable.Nrow; i++) {
+    free (db[0].vtable.buffer[i]);
+  }
+  REALLOCATE (db[0].vtable.buffer, char *, 1);
+  REALLOCATE (db[0].vtable.row, int, 1);
+  db[0].vtable.Nrow   = 0;
+
+  // reset db[0].theader(NAXIS1) to match Image
+  gfits_modify (&db[0].theader, "NAXIS1", "%d", 1, sizeof(Image));
+  db[0].theader.Naxis[0] = sizeof(Image);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/skycells.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/skycells.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/skycells.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "skycells.h"
+
+int main (int argc, char **argv) {
+
+  int status, level;
+  FITS_DB db;
+
+  SetSignals ();
+  ConfigInit_skycells (&argc, argv);
+  args_skycells (argc, argv);
+  level = atoi (argv[1]);
+  
+  /*** update the image table ***/
+  /* setup image table format and lock */
+  db.mode   = dvo_catalog_catmode (CATMODE);
+  db.format = dvo_catalog_catformat (CATFORMAT);
+  status    = dvo_image_lock (&db, ImageCat, 3600.0, LCK_XCLD);  // shorter timeout?
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+
+  /* load or create the image table */
+  if (db.dbstate == LCK_EMPTY) {
+    if (VERBOSE) fprintf (stderr, "can't find %s, creating a new one\n", ImageCat);
+    dvo_image_create (&db, 25.0);
+  } else {
+    if (!dvo_image_load (&db, VERBOSE, FALSE)) {
+      Shutdown ("can't read image catalog %s", db.filename);
+    }
+  }
+
+  // we have to put the database update calls deep down in the sky_tessalation code so we
+  // can write out the skycells in limited-sized chunks.
+  sky_tessalation (&db, level, NMAX, MODE, SCALE);
+
+  dvo_image_unlock (&db);
+  exit (0);
+}
+
+/*
+ * - we start with the image database loaded into memory (db)
+ * - we convert this to an empty vtable 
+ * - add groups of images to the vtable
+ * - we write out the vtable data
+ * - zero-out the saved entries, 
+ */
+
Index: /branches/eam_branch_20080223/Ohana/src/addstar/src/update_coords.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/addstar/src/update_coords.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/addstar/src/update_coords.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "addstar.h"
+
+/* find the average and scatter for R and D - no outlier rejection */
+void update_coords (Average *average, Measure *measure, int *next) {
+
+  int i, m, Npt;
+  double R, D, r, d;
+  double r2, d2, dR2, dD2;
+
+  Npt = r = d = r2 = d2 = 0;
+
+  if (average[0].Nm < 2) return;
+
+  /* find the average & sum-square (does not use reference coordinates) */
+  m = average[0].offset;  /* first measurement of this star */
+  for (i = 0; i < average[0].Nm; i++) {
+    if (measure[m].t == 0) {
+      m = next[m];
+      continue;
+    }
+    R = measure[m].dR;
+    D = measure[m].dD;
+    r += R;
+    d += D;
+    r2 += R*R;
+    d2 += D*D;
+    m = next[m];
+    Npt ++;
+  }
+  if (Npt < 1) return;
+
+  /* apply average offset */
+  r = r / Npt;  /* these are corrections in 1/100 arcsec to RA and DEC */
+  d = d / Npt;
+  average[0].R -= r / 3600.0;
+  average[0].D -= d / 3600.0;
+  m = average[0].offset;  /* first measurement of this star */
+  for (i = 0; i < average[0].Nm; i++) {
+    measure[m].dR -= r;
+    measure[m].dD -= d;
+    m = next[m];
+  }
+  
+  /* measure scatter, if possible */
+  if (Npt < 2) return;
+
+  dR2 = r2 / Npt - r*r;
+  dD2 = d2 / Npt - d*d;
+  average[0].Xp = sqrt (dD2 + dR2 / SQ(cos(d*RAD_DEG)));
+  /* Xp is scatter in position in hundredths of arcsec */
+
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/Makefile	(revision 16632)
@@ -0,0 +1,43 @@
+default: delstar
+help:
+	@echo "make options: addstar (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/delstar
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+INC	= 	$(HOME)/include
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+delstar: $(BIN)/delstar.$(ARCH)
+install: $(DESTBIN)/delstar
+
+DELSTAR = \
+$(SRC)/delstar.$(ARCH).o          \
+$(SRC)/SetSignals.$(ARCH).o       \
+$(SRC)/ConfigInit.$(ARCH).o 	  \
+$(SRC)/args.$(ARCH).o	          \
+$(SRC)/delete_imagename.$(ARCH).o \
+$(SRC)/delete_imagefile.$(ARCH).o \
+$(SRC)/delete_times.$(ARCH).o 	  \
+$(SRC)/gimages.$(ARCH).o   	  \
+$(SRC)/find_image_db.$(ARCH).o    \
+$(SRC)/find_matches.$(ARCH).o 	  \
+$(SRC)/parse_time.$(ARCH).o       \
+$(SRC)/check_permissions.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o          
+
+OLD = \
+$(SRC)/gregion_image.$(ARCH).o    \
+$(SRC)/gregion_patch.$(ARCH).o    \
+$(SRC)/RegionOps.$(ARCH).o   	  
+
+$(DELSTAR): $(INC)/delstar.h
+$(BIN)/delstar.$(ARCH) : $(DELSTAR)
Index: /branches/eam_branch_20080223/Ohana/src/delstar/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/delstar/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,20 @@
+
+- delstar 1.6 : 
+  * converted to gfits APIs (forces libfits 1.6)
+  * converted to new DVO APIs (forces libdvo 1.3)
+  * removed unused code
+
+- delstar 1.5 : 2006.03.26
+  * dropped IMAGE_CATALOG from config
+  * convert to dvo_image_lock,unlock
+
+- delstar 1.4 : 2006.01.06
+  * major work to support SkyRegions
+  * cleaned up signed/unsigned inconsistencies
+
+2005.10.20 : delstar.1-3
+
+    This release keeps delstar in sync with addstar v1.3.  Support is
+    added for the different modes and formats, and for the new
+    internal data types (eg, mags, not millimags).
+
Index: /branches/eam_branch_20080223/Ohana/src/delstar/include/addstar.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/include/addstar.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/include/addstar.h	(revision 16632)
@@ -0,0 +1,13 @@
+# include <ohana.h>
+# include <dvo.h>
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+double NSIGMA;
+double ALPHA;
+int    VERBOSE;
+
Index: /branches/eam_branch_20080223/Ohana/src/delstar/include/delstar.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/include/delstar.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/include/delstar.h	(revision 16632)
@@ -0,0 +1,73 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+double NSIGMA;
+double ALPHA;
+int    VERBOSE;
+int    ORPHAN;
+int    MISSED;
+char   SKY_TABLE[256];
+int    SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
+
+time_t    START;
+time_t    END;
+PhotCode *PHOTCODE;
+
+int    MODE;
+enum {MODE_IMAGENAME, MODE_IMAGEFILE, MODE_TIME, MODE_ORPHAN, MODE_MISSED};
+
+char DateKeyword[64], DateMode[64], UTKeyword[64], MJDKeyword[64], JDKeyword[64];
+
+/*** delstar prototypes ***/
+void       ConfigInit             PROTO((int *argc, char **argv));
+int        FindDecBand            PROTO((double dec, double *DEC0, double *DEC1));
+FILE      *GetDB                  PROTO((int *state));
+Image     *GetImages              PROTO((int *nimage));
+int        SetImages              PROTO((Image *new, int Nnew));
+void       SetProtect             PROTO((int mode));
+int        SetSignals             PROTO(());
+int        Shutdown               PROTO((char *format, ...));
+void       TrapSignal             PROTO((int sig));
+int        args                   PROTO((int *argc, char **argv));
+void       check_permissions      PROTO((char *basefile));
+void       delete_imagefile       PROTO((FITS_DB *db, char *filename));
+void       delete_imagename       PROTO((FITS_DB *db, char *name));
+void       delete_times           PROTO((FITS_DB *db));
+int        edge_check             PROTO((double *x1, double *y1, double *x2, double *y2));
+int       *find_images_data       PROTO((FITS_DB *db, Image *timage, int *nlist));
+int       *find_images_name       PROTO((FITS_DB *db, char *filename, int *nlist));
+int       *find_images_time       PROTO((FITS_DB *db, time_t start, time_t end, PhotCode *code, int *nlist));
+void       find_matches           PROTO((Catalog *catalog, int photcode, int start, int end));
+int        gcatalog               PROTO((Catalog *catalog));
+Image     *gimages                PROTO((char *filename));
+Image     *gtimes                 PROTO((int *NIMAGE));
+void       help                   PROTO(());
+int        load_image_db          PROTO((FITS_DB *db));
+void       lock_image_db          PROTO((FITS_DB *db, char *filename));
+void       match_images           PROTO((Catalog *catalog, Image *image, int Nimage));
+double     opening_angle          PROTO((double x1, double y1, double x2, double y2, double x3, double y3));
+int        parse_time             PROTO((Header *header));
+int        save_image_db          PROTO(());
+void       sort_lists             PROTO((float *X, float *Y, int *S, int N));
+void       unlock_image_db        PROTO((FITS_DB *db));
+void       usage                  PROTO(());
+int        wcatalog               PROTO((Catalog *catalog));
+
+void set_db (FITS_DB *in);
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "delstar.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "NSIGMA",                 "%lf", 0, &NSIGMA);
+  ScanConfig (config, "ALPHA",                  "%lf", 0, &ALPHA);
+  ScanConfig (config, "GSCFILE",                "%s", 0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s", 0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  ScanConfig (config, "DATE-KEYWORD",           "%s", 0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",              "%s", 0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",             "%s", 0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",            "%s", 0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",             "%s", 0, JDKeyword);
+
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = 2;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "delstar.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect these signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored (POSIX.1-1990) */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored (POSIX.1-1990) */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore (POSIX.1-1990) */
+    case SIGCONT:    /* continue - maintain this action (POSIX.1-1990) */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? (POSIX.1-1990) */
+    case SIGURG:     /* socket signal, ignore this (POSIX.1-2001) */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "delstar.h"
+
+static FITS_DB *db;
+
+void set_db (FITS_DB *in) {
+  db = in;
+}
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format));
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  SetProtect (TRUE);
+  gfits_db_close (db);
+  fprintf (stderr, "ERROR: delstar halted\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/args.c	(revision 16632)
@@ -0,0 +1,101 @@
+# include "delstar.h"
+
+void help () {
+
+  fprintf (stderr, "USAGE:\n");
+  fprintf (stderr, "  delstar (filename)\n");
+  fprintf (stderr, "  delstar -name (filename)\n");
+  fprintf (stderr, "  delstar -time (start) (stop/range)\n");
+  fprintf (stderr, "  delstar -orphan (region)\n");
+  fprintf (stderr, "  delstar -missed (region)\n\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v               : verbose mode\n");
+  fprintf (stderr, "  -photcode (code) : restrict by photcode\n");
+  fprintf (stderr, "\n"); 
+  exit (2);
+
+}
+
+void usage () {
+  fprintf (stderr, "USAGE: delstar (filename) / [optional mode] : -h for help\n");
+  exit (2);
+}
+
+int args (int *argc, char **argv) {
+  
+  int N;
+  double trange;
+  time_t tmp;
+
+  /* check for help request */
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    help ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MODE = MODE_IMAGEFILE;
+  if ((N = get_argument (*argc, argv, "-name"))) {
+    if (MODE != MODE_IMAGEFILE) usage();
+    MODE = MODE_IMAGENAME;
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-orphan"))) {
+    if (MODE != MODE_IMAGEFILE) usage();
+    MODE = MODE_ORPHAN;
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-missed"))) {
+    if (MODE != MODE_IMAGEFILE) usage();
+    MODE = MODE_MISSED;
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-time"))) {
+    if (MODE != MODE_IMAGEFILE) usage();
+    MODE = MODE_TIME;
+    remove_argument (N, argc, argv);
+
+    if (!ohana_str_to_time (argv[N], &START)) usage ();
+    remove_argument (N, argc, argv);
+
+    /* interpret second value */
+    if (ohana_str_to_dtime (argv[N], &trange)) { 
+      if (trange < 0) {
+	END = START;
+	START = END + trange;
+      } else {
+	END = START + trange;
+      }
+      remove_argument (N, argc, argv);
+      goto goodtime;
+    }
+    if (ohana_str_to_time (argv[N], &END)) { 
+      if (START > END) {
+	tmp   = START;
+	START = END;
+	END   = START;
+      }
+      remove_argument (N, argc, argv);
+      goto goodtime;
+    }
+    usage ();
+  }
+goodtime:
+
+  /* restrict to a single photcode (not compatible with -image) */
+  PHOTCODE = NULL;
+  if ((N = get_argument (*argc, argv, "-photcode"))) {
+    remove_argument (N, argc, argv);
+    PHOTCODE = GetPhotcodebyName (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  if ((MODE == MODE_TIME) && (*argc != 1)) usage ();
+  if ((MODE != MODE_TIME) && (*argc != 2)) usage ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/check_permissions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/check_permissions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/check_permissions.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include "addstar.h"
+
+void check_permissions (char *basefile) {
+  
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "directory %s does not exist, creating...\n", dir);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdir (dir, cmode);
+    if (status == -1) {
+      fprintf (stderr, "ERROR: can't create %s\n", dir);
+      exit (1);
+    }
+  } 
+  status = stat (dir, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (1);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s", basefile);
+  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_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~", basefile);
+  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_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (1);
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_imagefile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_imagefile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_imagefile.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "delstar.h"
+
+void delete_imagefile (FITS_DB *db, char *filename) {
+
+  int i, Nimlist;
+  int *imlist;
+  double trange;
+  time_t start, stop;
+  Image *image;
+  Catalog catalog;
+  SkyTable *sky;
+
+  /* load sky from correct table */
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+
+  /* load information about file - time/photcode */
+  image = gimages (filename);
+  
+  /* need to define method to get the mosaic (look up from table) */
+  if (VERBOSE) fprintf (stderr, "deleting %s\n", image[0].name);
+
+  for (i = 0; i < sky[0].Nregions; i++) {
+
+    if (VERBOSE) fprintf (stderr, "deleting from %s\n", sky[0].filename[i]);
+    catalog.filename = sky[0].filename[i];  /* don't free region before catalog! */
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, &sky[0].regions[i], VERBOSE, "a")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    if (!catalog.Naves_disk) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    /* pad exposure time by 1 sec to require a valid time */
+    /* trate is in 0.1 msec / row  - stop is the latest exposure end time */
+    trange = 1e-4*image[0].NY*image[0].trate + image[0].exptime + 1;  
+    start = image[0].tzero;
+    stop  = image[0].tzero + trange;
+    find_matches (&catalog, image[0].photcode, start, stop);
+
+    dvo_catalog_save (&catalog, VERBOSE);
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+
+  /* find and delete matching images */
+  // XXX EAM : load image data above, find mosaic?
+  imlist = find_images_data (db, image, &Nimlist);
+  if (!Nimlist) Shutdown ("image %s not found in db", filename);
+
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, imlist, Nimlist);
+  dvo_image_update (db, VERBOSE);
+  dvo_image_unlock (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_imagename.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_imagename.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_imagename.c	(revision 16632)
@@ -0,0 +1,92 @@
+# include "delstar.h"
+
+void delete_imagename (FITS_DB *db, char *name) {
+
+  int i, j, k;
+  int Nimlist, Nimage, Noutimage;
+  int *imlist;
+  double trange;
+  time_t start, stop;
+  Image *image;
+  Image *outimage;
+  Catalog catalog;
+  SkyList *skylist;
+  SkyTable *sky;
+
+  /* load sky from correct table */
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  /* find image in db by name */
+  imlist = find_images_name (db, name, &Nimlist);
+  if (!Nimlist) Shutdown ("image %s not found in db", name);
+  
+  for (k = 0; k < Nimlist; k++) {
+
+    j = imlist[k];
+    if (VERBOSE) fprintf (stderr, "deleting %s\n", image[j].name);
+    
+    // XXX EAM : need to handle failure
+    FindMosaicForImage (image, Nimage, j);
+    skylist = SkyListByImage (sky, -1, &image[j]);
+
+    for (i = 0; i < skylist[0].Nregions; i++) {
+      if (VERBOSE) fprintf (stderr, "deleting from %s\n", skylist[0].filename[i]);
+      catalog.filename = skylist[0].filename[i];  /* don't free region before catalog! */
+      catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+      catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+      // an error exit status here is a significant error
+      if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "a")) {
+	fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+	exit (2);
+      }
+      if (!catalog.Naves_disk) {
+	dvo_catalog_unlock (&catalog);
+	dvo_catalog_free (&catalog);
+	continue;
+      }
+
+      /* trate is in 0.1 msec / row  - stop is the latest exposure end time */
+      /* pad exposure time by 1 sec to require a valid time */
+      trange = 1e-4*image[j].NY*image[j].trate + image[j].exptime + 1;  
+      start = image[j].tzero;
+      stop  = image[j].tzero + trange;
+      find_matches (&catalog, image[j].photcode, start, stop);
+
+      dvo_catalog_save (&catalog, VERBOSE);
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+    }
+  }
+
+  /* delete the identified images */
+  ALLOCATE (outimage, Image, Nimage - Nimlist);
+  for (i = 0, k = 0; i < Nimage; i++) {
+      for (j = 0; j < Nimlist; j++) {
+	  if (imlist[j] == i) goto skip;
+      }
+      outimage[k] = image[i];
+      k++;
+  skip:
+      continue;
+  }
+  free (image);
+  Noutimage = Nimage - Nimlist;
+  
+  if (VERBOSE) fprintf (stderr, "removing %d images (leaving %d of %d)\n", Nimlist, Noutimage, Nimage);
+  // gfits_table_set_Image (&db[0].ftable, outimage, Noutimage);
+
+  gfits_modify (&db[0].theader, "NAXIS2", "%d", 1, Noutimage);
+  gfits_modify (&db[0].header, "NIMAGES", "%d", 1, Noutimage);
+  db[0].theader.Naxis[1] = Noutimage;
+  db[0].ftable.buffer = (char *) outimage;
+
+  dvo_image_save (db, VERBOSE);
+  dvo_image_unlock (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_missed.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_missed.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_missed.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "delstar.h"
+
+/* drop all MISSED values for the given catalog */
+
+delete_missed (Catalog *catalog) {
+
+  int i;
+  int Nave, Nmeas, Nmiss;
+
+  Nave = catalog[0].Naverage;
+  Nmeas = catalog[0].Nmeasure;
+  Nmiss = catalog[0].Nmissing;
+  
+  if (VERBOSE) fprintf (stderr, "starting with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  /* set up references for missing to average */
+  for (i = 0; i < Nave; i++) {
+    catalog[0].average[i].Nn = 0;
+  }
+  REALLOCATE (catalog[0].missing, Missing, 1);
+  catalog[0].Nmissing = 0;
+  if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_orphans.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_orphans.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_orphans.c	(revision 16632)
@@ -0,0 +1,258 @@
+# include "delstar.h"
+
+delete_orphans (char *name) {
+
+  int i, j, k, n, m, N, M, found;
+  int *N1, *N2,  *next, *next_miss, *ave_miss, last, last_miss;
+  int Nave, NAVE, Nmeas, NMEAS, Nmiss, NMISS, Nmatch;
+  int start, end, Nmeasfound, Nsecfilt;
+  unsigned int flags;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+  Coords tcoords;
+  Catalog catalog;
+
+  /* find and load catalog file */
+  catalog.filename = name;
+  dvo_catalog_load (&catalog);
+  gcatstats (&catalog, &catstats);
+
+  /* find images overlapping catalog */
+  image = find_images_region (&catstats, &Nimage);
+  match_images (&catalog, image, Nimage);
+
+  /** allocate local arrays **/
+  Nave = catalog.Naverage;
+
+  Nmeas = catalog.Nmeasure;
+  ALLOCATE (next, int, Nmeas);
+  
+  Nmiss = catalog.Nmissing;
+  ALLOCATE (next_miss, int, Nmiss);
+  ALLOCATE (ave_miss, int, Nmiss);
+  
+  if (VERBOSE) fprintf (stderr, "starting with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  /* set up pointers for linked list of measure */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+  /* set up pointers for linked list of missing */
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+  /* set up references for missing to average */
+  for (i = 0; i < Nave; i++) {
+    for (j = 0; j < catalog.average[i].Nn; j++) {
+      ave_miss[catalog.average[i].missing + j] = i;
+    }
+  }
+  Nmeasfound = 0;
+  Nsecfilt = catalog.Nsecfilt;
+
+  /* fprintf (stderr, "fixing the measures...\n"); */
+  for (i = 0; (i < Nmeas); i++) {
+    if ((catalog.measure[i].t != 0) && (catalog.image[i] == -1)) { 
+      /* this star is an orphan */
+      Nmeasfound ++;
+      next[i] = -2; /* we delete this one */
+      /* fix the list links: connect the previous valid link to the next valid link */
+      for (j = i; (j >= 0) && (next[j] == -2); j--); /* find previous entry to fix link */
+      if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	if (next[j] != i) {
+	  fprintf (stderr, "error?  this link seems to have been lost\n");
+	  exit (1);
+	}
+	/* find next valid entry to fix link */
+	for (k = i; (k < Nmeas) && (next[k] == -2); k++);
+	if (k < Nmeas)
+	  next[j] = k;
+	else 
+	  next[j] = -1;  /* last link in list gets a -1 */
+      }
+      
+      /*** fix the corresponding average entry ***/
+      n = catalog.measure[i].averef;
+      if (catalog.average[n].Nm == 0) { /* this should never happen */
+	fprintf (stderr, "error? we deleted one too many objects?\n");
+	exit (1);
+      }
+      catalog.average[n].Nm --;
+      /* this was only entry in list: will be deleted below.  meanwhile, delete all missing entries*/
+      if ((catalog.average[n].Nm < 1) && (catalog.average[n].Nn > 0)) { 
+	m = catalog.average[n].missing;
+	for (j = 0; j < catalog.average[n].Nn; j++) {
+	  M = next_miss[m];
+	  next_miss[m] = -2;
+	  m = M;
+	}
+	m = catalog.average[n].missing;
+	/* fix the list links: connect the previous valid link to the next valid link */
+	for (j = m; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+	if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	  if (next_miss[j] != m) {
+	    fprintf (stderr, "error?  this link seems to have been lost\n");
+	    exit (1);
+	  }
+	  /* find next valid entry to fix link */
+	  for (k = m; (k < Nmiss) && (next_miss[k] == -2); k++);
+	  if (k < Nmiss)
+	    next_miss[j] = k;
+	  else 
+	    next_miss[j] = -1;  /* last link in list gets a -1 */
+	}
+      }
+      /* this was first entry in list */
+      if ((catalog.average[n].offset == i) && (catalog.average[n].Nm > 0)) { 
+	m = catalog.average[n].offset;
+	/* find next valid entry -- notice lack of error checking... */
+	for (j = 0; (j < Nmeas) && (next[m+j] == -2); j++);
+	catalog.average[n].offset = m + j;
+      }
+
+    }
+  }
+  fprintf (stderr, "found %d meas to remove\n", Nmeasfound);
+
+  /* fprintf (stderr, "fixing the missing...\n"); */
+  /** find missing in time range of image **/
+  for (i = 0; (i < Nmiss); i++) {
+    if ((next_miss[i] != -2) && (catalog.missing[i].t >= start) && (catalog.missing[i].t <= end)) { 
+      /* this star is in this image */
+
+      next_miss[i] = -2; /* we delete this one */
+      /* fix the list links: connect the previous valid link to the next valid link */
+      for (j = i; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+      if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	if (next_miss[j] != i) {
+	  fprintf (stderr, "error?  this link seems to have been lost\n");
+	  exit (1);
+	}
+	/* find next valid entry to fix link */
+	for (k = i; (k < Nmiss) && (next_miss[k] == -2); k++);
+	if (k < Nmiss)
+	  next_miss[j] = k;
+	else 
+	  next_miss[j] = -1;  /* last link in list gets a -1 */
+      }
+      
+      /* find the corresponding avearge entry 
+      found = FALSE;
+      for (n = 0; !found && (n < Nave); n++) {
+	if ((catalog.average[n].missing > 0) && (catalog.average[n].missing <= i) && (catalog.average[n].missing + catalog.average[n].Nn > i)) 
+	  found = TRUE;
+      }
+      n--; */
+      /*** fix the corresponding average entry ***/
+      n = ave_miss[i];
+      if (catalog.average[n].Nn == 0) { /* this should never happen */
+	fprintf (stderr, "error? we deleted one too many missing?\n");
+	exit (1);
+      }
+      catalog.average[n].Nn --;
+      /* this was first entry in list */
+      if ((catalog.average[n].missing == i) && (catalog.average[n].Nn > 0)) { 
+	m = catalog.average[n].missing;
+	for (j = 0; (j < Nmiss) && (next_miss[m+j] == -2); j++);
+	catalog.average[n].missing = m + j;
+      }
+
+    }
+  }
+
+  /* currently not worked out, but we will need to delete the references to blended image and cat stars */
+# if 0
+  /*** handle multiple stars */
+  /* this image star matches more than one catalog star */
+  if (stars[N].found > -1) {
+    catalog.measure[stars[N].found].flags |= BLEND_IMAGE;
+    catalog.measure[Nmeas].flags |= BLEND_IMAGE;
+  } 
+  if (stars[N].found == -2) { /* this image star matches a catalog star on a neighboring catalog */
+    catalog.measure[Nmeas].flags |= BLEND_IMAGE_NEIGHBOR;
+  } 
+  if (stars[N].found == -1) { /* this image star matches only this star */
+    stars[N].found = Nmeas;  /* save first match, in case coincidences are found */
+  }
+  /* this catalog star matches more than one image star */
+  if (catalog.found[n] > -1) {
+    catalog.measure[catalog.found[n]].flags |= BLEND_CATALOG;
+    catalog.measure[Nmeas].flags |= BLEND_CATALOG;
+  } else {
+    catalog.found[n] = Nmeas;
+  }
+# endif  
+
+  /* fprintf (stderr, "fixing the averages...\n"); */
+  /* fix Average list: delete entries with Nm == 0 */
+  for (i = j = 0; (i < Nave) && (j < Nave); i++, j++) {
+    for (; (j < Nave) && (catalog.average[j].Nm == 0); j++);
+    if ((i != j) && (j < Nave)) {
+      catalog.average[i] = catalog.average[j];
+      for (k = 0; k < catalog.Nsecfilt; k++) {
+	catalog.secfilt[i*Nsecfilt + k] = catalog.secfilt[j*Nsecfilt + k];
+      }
+    }
+    if (j == Nave) i--;
+  }
+  Nave = i;
+  REALLOCATE (catalog.average, Average, Nave);
+  REALLOCATE (catalog.secfilt, SecFilt, MAX (1, Nave*Nsecfilt));
+  
+  /* fprintf (stderr, "fixing the measure order...\n"); */
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog.average[i].offset;
+    catalog.average[i].offset = N;
+    for (k = 0; k < catalog.average[i].Nm; k++, N++) {
+      if ((n == -1) || (n == -2)) {
+	fprintf (stderr, "error: linked list is confused\n");
+	exit (1);
+      }
+      tmpmeasure[N] = catalog.measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  Nmeas = N;
+  free (catalog.measure);
+  catalog.measure = tmpmeasure;
+  REALLOCATE (catalog.measure, Measure, Nmeas);
+    
+  /* fprintf (stderr, "fixing the mising order...\n"); */
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog.average[i].Nn > 0) {
+      n = catalog.average[i].missing;
+      catalog.average[i].missing = N;
+      for (k = 0; k < catalog.average[i].Nn; k++, N++) {
+	if ((n == -1) || (n == -2)) {
+	  fprintf (stderr, "error: linked list is confused\n");
+	  exit (1);
+	}
+	tmpmissing[N] = catalog.missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  Nmiss = N;
+  free (catalog.missing);
+  catalog.missing = tmpmissing;
+  REALLOCATE (catalog.missing, Missing, Nmiss);
+
+  catalog.Naverage = Nave;
+  catalog.Nmeasure = Nmeas;
+  catalog.Nmissing = Nmiss;
+  catalog.Nsecf_mem = Nave*Nsecfilt;
+
+  if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_times.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_times.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/delete_times.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "delstar.h"
+
+void delete_times (FITS_DB *db) {
+
+  int i, j, k, n;
+  int Nimage, Nimlist, found, code;
+  int Nregions, NREGIONS;
+  int *imlist;
+  SkyList *skylist, *skyset;
+  SkyTable *sky;
+  Image *image;
+  Catalog catalog;
+
+  code = (PHOTCODE == NULL) ? -1 : PHOTCODE[0].code;
+
+  /* load sky from correct table */
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+
+  Nregions = 0;
+  NREGIONS = 10;
+  ALLOCATE (skylist, SkyList, 1);
+  ALLOCATE (skylist[0].regions, SkyRegion *, NREGIONS);
+  skylist[0].ownElements = FALSE; // free these elements when freeing the list
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  /* find images for time range, delete each image */ 
+  imlist = find_images_time (db, START, END, PHOTCODE, &Nimlist);
+
+  /* find all overlapping regions */
+  for (n = 0; n < Nimlist; n++) {
+    j = imlist[n];
+    if (VERBOSE) fprintf (stderr, "finding regions for %s\n", image[j].name);
+
+    // XXX EAM : need to handle failure
+    FindMosaicForImage (image, Nimage, j);
+    skyset = SkyListByImage (sky, -1, &image[j]);
+
+    // tregion = gregion_image (&image[j], &Ntregions);
+    for (i = 0; i < skyset[0].Nregions; i++) {
+      found = FALSE;
+      for (k = 0; (k < skylist[0].Nregions) && !found; k++) {
+	found = !strcmp (skylist[0].regions[k][0].name, skyset[0].regions[i][0].name);
+      }
+      if (found) continue;
+      skylist[0].regions[Nregions] = skyset[0].regions[i];
+      Nregions ++;
+      CHECK_REALLOCATE (skylist[0].regions, SkyRegion *, NREGIONS, Nregions, 10);
+    }
+    SkyListFree (skyset);
+  }
+
+  /* delete from all identified regions */
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    if (VERBOSE) fprintf (stderr, "deleting from %s\n", skylist[0].filename[i]);
+    catalog.filename = skylist[0].filename[i];  /* don't free region before catalog! */
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "a")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    if (!catalog.Naves_disk) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    find_matches (&catalog, code, START, END);
+    dvo_catalog_save (&catalog, VERBOSE);
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+
+  /* delete the identified images */
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, imlist, Nimlist);
+  dvo_image_update (db, VERBOSE);
+  dvo_image_unlock (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/delstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/delstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/delstar.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include "delstar.h"
+
+int main (int argc, char **argv) {
+
+  FITS_DB db;
+
+  int status;
+  SetSignals ();
+  ConfigInit (&argc, argv);
+  args (&argc, argv);
+
+  set_db (&db);
+  status = dvo_image_lock (&db, ImageCat, 60.0, LCK_XCLD); /* XCLD */
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+  if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+
+  status = dvo_image_load (&db, VERBOSE, FALSE);
+  if (!status) Shutdown ("can't read image catalog %s", db.filename);
+
+  switch (MODE) {
+    case MODE_IMAGEFILE:
+      delete_imagefile (&db, argv[1]);
+      break;
+    case MODE_IMAGENAME:
+      delete_imagename (&db, argv[1]);
+      break;
+    case MODE_TIME:
+      delete_times (&db);
+      break;
+    case MODE_ORPHAN:
+      fprintf (stderr, "delete orphans not available\n");
+      // delete_orphans (argv[1]);
+      break;
+    case MODE_MISSED:
+      fprintf (stderr, "delete missed not available\n");
+      // delete_missed (argv[1]);
+      break;
+    default:
+      usage ();
+  }
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/find_image_db.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/find_image_db.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/find_image_db.c	(revision 16632)
@@ -0,0 +1,94 @@
+# include "delstar.h"
+
+int *find_images_name (FITS_DB *db, char *filename, int *nlist) {
+
+  int i, Nimage, Nlist, NLIST;
+  int *list;
+  char *p, *name;
+  Image *image;
+
+  /* strip off all but the filename */
+  p = strrchr (filename, '/');
+  if (p == NULL) {
+    name = filename;
+  } else {
+    name = p + 1;
+  }
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  Nlist = 0;
+  NLIST = 100;
+  ALLOCATE (list, int, NLIST);
+
+  for (i = 0; i < Nimage; i++) {
+    if (strcmp (image[i].name, name)) continue;
+    list[Nlist] = i;
+    Nlist ++;
+    CHECK_REALLOCATE (list, int, NLIST, Nlist, 100);
+  }
+
+  *nlist = Nlist;
+  return (list);
+}
+
+/* find images in db by image data (time/photcode) */
+int *find_images_data (FITS_DB *db, Image *timage, int *nlist) {
+
+  int i, Nimage, Nlist, NLIST; 
+  int *list;
+  Image *image;
+  time_t start, stop;
+  int code;
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  start = timage[0].tzero - MAX(0.05*timage[0].trate*timage[0].NY, 1);
+  stop  = timage[0].tzero + MAX(1.05*timage[0].trate*timage[0].NY, 1);
+  code  = timage[0].photcode;
+
+  Nlist = 0;
+  NLIST = 100;
+  ALLOCATE (list, int, NLIST);
+
+  for (i = 0; i < Nimage; i++) {
+    if (image[i].tzero < start) continue;
+    if (image[i].tzero > stop) continue;
+    if (image[i].photcode != code) continue;
+    list[Nlist] = i;
+    Nlist ++;
+    CHECK_REALLOCATE (list, int, NLIST, Nlist, 100);
+  }
+
+  *nlist = Nlist;
+  return (list);
+}
+
+/* find images in db by image data (time/photcode) */
+int *find_images_time (FITS_DB *db, time_t start, time_t end, PhotCode *code, int *nlist) {
+
+  int i, Nimage, Nlist, NLIST;
+  int *list;
+  Image *image;
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  Nlist = 0;
+  NLIST = 100;
+  ALLOCATE (list, int, NLIST);
+
+  for (i = 0; i < Nimage; i++) {
+    if (image[i].tzero < START) continue;
+    if (image[i].tzero > END) continue;
+    if (code != NULL) {
+      if (image[i].photcode != code[0].code) continue;
+    }
+    list[Nlist] = i;
+    Nlist ++;
+    CHECK_REALLOCATE (list, int, NLIST, Nlist, 100);
+  }
+
+  *nlist = Nlist;
+  return (list);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/find_matches.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/find_matches.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/find_matches.c	(revision 16632)
@@ -0,0 +1,245 @@
+# include "delstar.h"
+
+void find_matches (Catalog *catalog, int photcode, int start, int end) {
+
+  int i, j, k, n, m, N, M, drop;
+  int *next, *next_miss, *ave_miss, last, last_miss;
+  int Nave, Nmeas, Nmiss;
+  int Nmeasfound, Nsecfilt;
+  int this, prev;
+  Measure *tmpmeasure;
+  Missing *tmpmissing;
+
+  /** allocate local arrays **/
+  Nave = catalog[0].Naverage;
+
+  Nmeas = catalog[0].Nmeasure;
+  ALLOCATE (next, int, MAX(Nmeas,1));
+  
+  Nmiss = catalog[0].Nmissing;
+  ALLOCATE (next_miss, int, MAX(Nmiss,1));
+  ALLOCATE (ave_miss, int, MAX(Nmiss,1));
+  
+  if (VERBOSE) fprintf (stderr, "starting with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  /* set up pointers for linked list of measure */
+  for (i = 0; i < Nmeas - 1; i++) {
+    next[i] = i+1;
+  }
+  next[i] = -1;
+  last = i;
+  /* set up pointers for linked list of missing */
+  for (i = 0; i < Nmiss - 1; i++) {
+    next_miss[i] = i+1;
+  }
+  next_miss[i] = -1;
+  last_miss = i;
+  /* set up references for missing to average */
+  for (i = 0; i < Nave; i++) {
+    for (j = 0; j < catalog[0].average[i].Nn; j++) {
+      ave_miss[catalog[0].average[i].missing + j] = i;
+    }
+  }
+
+  if (VERBOSE) fprintf (stderr, "deleting for range %d to %d, photcode %d\n", start, end, photcode);
+  Nmeasfound = 0;
+  Nsecfilt = catalog[0].Nsecfilt;
+
+  if (VERBOSE) fprintf (stderr, "fixing measure...\n"); 
+
+  /** find measure in time range **/
+  this = prev = -1;
+  for (i = 0; (i < Nmeas); i++) {
+    if (VERBOSE && !(i % 10000)) fprintf (stderr, ". ");
+    drop = TRUE;
+    drop &= (catalog[0].measure[i].t >= start);
+    drop &= (catalog[0].measure[i].t <= end);
+    drop &= ((photcode == -1) || (photcode == catalog[0].measure[i].photcode));
+    if (!drop) {
+      prev = i;
+      continue;
+    }
+    Nmeasfound ++;
+
+    /* this star is in this image */
+    this = next[i];
+    next[i] = -2; /* we delete this one */
+    if (prev != -1) { next[prev] = this; }
+
+# if (0) 
+    /* why is this section disabled? */
+    /* fix the list links: connect the previous valid link to the next valid link */
+    for (j = i; (j >= 0) && (next[j] == -2); j--); /* find previous entry to fix link */
+    if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+      if (next[j] != i) {
+	fprintf (stderr, "error? (1)  this link seems to have been lost\n");
+	fprintf (stderr, "j: %d, next[j]: %d, i: %d\n", j, next[j], i);
+	exit (1);
+      }
+      /* find next valid entry to fix link */
+      for (k = i; (k < Nmeas) && (next[k] == -2); k++);
+      if (k < Nmeas)
+	next[j] = k;
+      else 
+	next[j] = -1;  /* last link in list gets a -1 */
+    }
+# endif      
+
+    /*** fix the corresponding average entry ***/
+    n = catalog[0].measure[i].averef;
+    if (catalog[0].average[n].Nm == 0) { /* this should never happen */
+      fprintf (stderr, "error? we deleted one too many objects?\n");
+      exit (1);
+    }
+    catalog[0].average[n].Nm --;
+    /* this was only entry in list: will be deleted below.  meanwhile, delete all missing entries*/
+    if ((catalog[0].average[n].Nm < 1) && (catalog[0].average[n].Nn > 0)) { 
+      m = catalog[0].average[n].missing;
+      for (j = 0; j < catalog[0].average[n].Nn; j++) {
+	M = next_miss[m];
+	next_miss[m] = -2;
+	m = M;
+      }
+      m = catalog[0].average[n].missing;
+      /* fix the list links: connect the previous valid link to the next valid link */
+      for (j = m; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+      if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+	if (next_miss[j] != m) {
+	  fprintf (stderr, "error? (2) this link seems to have been lost\n");
+	  fprintf (stderr, "j: %d, next_miss[j]: %d, i: %d\n", j, next_miss[j], i);
+	  exit (1);
+	}
+	/* find next valid entry to fix link */
+	for (k = m; (k < Nmiss) && (next_miss[k] == -2); k++);
+	if (k < Nmiss)
+	  next_miss[j] = k;
+	else 
+	  next_miss[j] = -1;  /* last link in list gets a -1 */
+      }
+    }
+    /* this was first entry in list */
+    if ((catalog[0].average[n].offset == i) && (catalog[0].average[n].Nm > 0)) { 
+      m = catalog[0].average[n].offset;
+      /* find next valid entry -- notice lack of error checking... */
+      for (j = 0; (j < Nmeas) && (next[m+j] == -2); j++);
+      catalog[0].average[n].offset = m + j;
+    }
+  } 
+  fprintf (stderr, "found %d meas to remove\n", Nmeasfound);
+
+  if (VERBOSE) fprintf (stderr, "fixing missing..."); 
+  /** find missing in time range of image **/
+  for (i = 0; (i < Nmiss); i++) {
+    if (next_miss[i] == -2) continue;
+    if (catalog[0].missing[i].t < start) continue;
+    if (catalog[0].missing[i].t > end) continue;
+
+    next_miss[i] = -2; /* we delete this one */
+    /* fix the list links: connect the previous valid link to the next valid link */
+    for (j = i; (j >= 0) && (next_miss[j] == -2); j--); /* find previous entry to fix link */
+    if (j >= 0) { /* if j < 0, there is no previous valid link, ignore this step */
+      if (next_miss[j] != i) {
+	fprintf (stderr, "error? (3) this link seems to have been lost\n");
+	fprintf (stderr, "j: %d, next_miss[j]: %d, i: %d\n", j, next_miss[j], i);
+	exit (1);
+      }
+      /* find next valid entry to fix link */
+      for (k = i; (k < Nmiss) && (next_miss[k] == -2); k++);
+      if (k < Nmiss)
+	next_miss[j] = k;
+      else 
+	next_miss[j] = -1;  /* last link in list gets a -1 */
+    }
+      
+    /*** fix the corresponding average entry ***/
+    n = ave_miss[i];
+    if (catalog[0].average[n].Nn == 0) { /* this should never happen */
+      fprintf (stderr, "error? we deleted one too many missing?\n");
+      exit (1);
+    }
+    catalog[0].average[n].Nn --;
+    /* this was first entry in list */
+    if ((catalog[0].average[n].missing == i) && (catalog[0].average[n].Nn > 0)) { 
+      m = catalog[0].average[n].missing;
+      for (j = 0; (j < Nmiss) && (next_miss[m+j] == -2); j++);
+      catalog[0].average[n].missing = m + j;
+    }
+  }
+
+  /* we should delete the references to blended image and cat stars ?? */
+  /* or drop since we are changing this concept ?? */
+
+  /* fix Average list: delete entries with Nm == 0 */
+  for (i = j = 0; (i < Nave) && (j < Nave); i++, j++) {
+    for (; (j < Nave) && (catalog[0].average[j].Nm == 0); j++);
+    if ((i != j) && (j < Nave)) {
+      catalog[0].average[i] = catalog[0].average[j];
+      for (k = 0; k < catalog[0].Nsecfilt; k++) {
+	catalog[0].secfilt[i*Nsecfilt + k] = catalog[0].secfilt[j*Nsecfilt + k];
+      }
+    }    
+    if (j == Nave) i--;
+  }
+  Nave = i;
+  REALLOCATE (catalog[0].average, Average, Nave);
+  REALLOCATE (catalog[0].secfilt, SecFilt, MAX (1, Nave*Nsecfilt));
+
+  /* fix order of Measure (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmeasure, Measure, Nmeas);
+  for (i = 0; i < Nave; i++) {
+    n = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = N;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, N++) {
+      if ((n == -1) || (n == -2)) {
+	fprintf (stderr, "error: linked list is confused\n");
+	exit (1);
+      }
+      tmpmeasure[N] = catalog[0].measure[n]; 
+      tmpmeasure[N].averef = i;
+      n = next[n];
+    }
+  }
+  Nmeas = N;
+  free (catalog[0].measure);
+  catalog[0].measure = tmpmeasure;
+  REALLOCATE (catalog[0].measure, Measure, Nmeas);
+    
+  /* fprintf (stderr, "fixing the mising order...\n"); */
+  /* fix order of Missing (memory intensive, but fast) */
+  N = 0; 
+  ALLOCATE (tmpmissing, Missing, Nmiss);
+  for (i = 0; i < Nave; i++) {
+    if (catalog[0].average[i].Nn > 0) {
+      n = catalog[0].average[i].missing;
+      catalog[0].average[i].missing = N;
+      for (k = 0; k < catalog[0].average[i].Nn; k++, N++) {
+	if ((n == -1) || (n == -2)) {
+	  fprintf (stderr, "error: linked list is confused\n");
+	  exit (1);
+	}
+	tmpmissing[N] = catalog[0].missing[n]; 
+	n = next_miss[n];
+      }
+    }
+  }
+  Nmiss = N;
+  free (catalog[0].missing);
+  catalog[0].missing = tmpmissing;
+  REALLOCATE (catalog[0].missing, Missing, Nmiss);
+
+  fprintf (stderr, "\n");
+
+  catalog[0].Naverage = Nave;
+  catalog[0].Nmeasure = Nmeas;
+  catalog[0].Nmissing = Nmiss;
+  catalog[0].Nsecf_mem = Nave*Nsecfilt;
+
+  if (VERBOSE) fprintf (stderr, "  ending with Nave, Nmeas, Nmiss: %d %d %d\n", Nave, Nmeas, Nmiss);
+
+  free (next);
+  free (next_miss);
+  free (ave_miss);
+  return;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/gimages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/gimages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/gimages.c	(revision 16632)
@@ -0,0 +1,87 @@
+# include "delstar.h"
+
+/* load information about image from image header
+ * this should be the same as addstar/gstars, but it is not...
+ */
+
+Image *gimages (char *filename) {
+ 
+  FILE *f;
+  Header header;
+  char photcode[64], *c;
+  double tmp;
+  Image *image;
+  int Nc;
+
+  ALLOCATE (image, Image, 1);
+  /* load header */
+  if (!gfits_read_header (filename, &header)) {
+    Shutdown ("ERROR: can't find image file %s", filename);
+  }
+
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    Shutdown ("ERROR: can't find data file %s", filename);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* add file name to image structure */
+  c = strrchr (filename, 0x2f);
+  if (c == (char *) NULL) {
+    strcpy (image[0].name, filename);
+  } else { 
+    strcpy (image[0].name, (c+1));
+  }
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, &header)) {
+    Shutdown ("ERROR: no astrometric solution in header");
+  }
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+
+  /* CERROR in data file is in pixels, convert to 20*arcsec */
+  image[0].cerror = tmp * 50.0 * image[0].coords.cdelt1 * 3600.0;
+  while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+  while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+ 
+  /* get other header info */
+  gfits_scan (&header, "NAXIS1",   "%hd", 1, &image[0].NX); 
+  gfits_scan (&header, "NAXIS2",   "%hd", 1, &image[0].NY);
+
+  gfits_scan (&header, "PHOTCODE", "%s", 1, photcode);
+  Nc = GetPhotcodeCodebyName (photcode);
+  if (!Nc) {
+    Shutdown ("ERROR: photcode %s not found in photcode table", photcode);
+  }
+  image[0].photcode = Nc;
+
+  tmp = 0;
+  gfits_scan (&header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  gfits_scan (&header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  if (!gfits_scan (&header, "TZERO",   "%d",  1, &image[0].tzero)) {
+    image[0].tzero = parse_time (&header);
+  }
+
+  tmp = 0;
+  gfits_scan (&header, "TRATE",   "%lf", 1, &tmp);
+  image[0].trate = 10000 * tmp;
+
+  tmp = 0;
+  gfits_scan (&header, "AIRMASS", "%lf", 1, &tmp);
+  image[0].secz = tmp;
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal = ALPHA*(image[0].secz - 1.000);
+  image[0].Xm   = NAN_S_SHORT;
+
+  free (header.buffer);
+ 
+  return (image);
+}
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/match_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/match_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/match_images.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "delstar.h"
+
+void match_images (Catalog *catalog, Image *image, int Nimage) {
+  
+  int j, k, found;
+  unsigned int *start, *stop;
+
+  /* this must be allocated so future free will not fail */
+  ALLOCATE (catalog[0].image, int, MAX (catalog[0].Nmeasure, 1));
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (start, unsigned int, Nimage);
+  ALLOCATE (stop,  unsigned int, Nimage);
+  for (j = 0; j < Nimage; j++) {
+    start[j] = image[j].tzero - MAX(0.05*image[j].trate*image[j].NY, 1);
+    stop[j]  = image[j].tzero + MAX(1.05*image[j].trate*image[j].NY, 1);
+  }
+
+  for (j = 0; j < catalog[0].Nmeasure; j++) {
+    found = FALSE;
+    if (catalog[0].measure[j].t == 0) {
+      catalog[0].image[j] = -1;
+      found = TRUE;
+    }
+    for (k = 0; (k < Nimage) && !found; k++) {
+      if ((catalog[0].measure[j].t >= start[k]) && 
+	  (catalog[0].measure[j].t <= stop[k])) {
+	catalog[0].image[j] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      catalog[0].image[j] = -1;
+      /* fprintf (stderr, "missing: %d %d\n", catalog[0].image[j], catalog[0].measure[j].t); */
+    }
+  }
+  free (start);
+  free (stop);
+}
+
+  /* this routine uses the time of each measurement to match the
+measurement with an image.  Since the measurement is only store to 1
+sec accuracy, which corresponds to roughly 30 rows at nominal speed,
+we can't tell exactly which image the star come from.  However, this
+doesn't matter, and in fact this helps a bit: a measurement from the
+top of one image is the same as from the bottom of the next.
+Therefore, we intentionally blur the edges of the images by 5%, which
+will help to tie together neighboring images... */
+
Index: /branches/eam_branch_20080223/Ohana/src/delstar/src/parse_time.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/delstar/src/parse_time.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/delstar/src/parse_time.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "delstar.h"
+
+int parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    gfits_scan (header, JDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    gfits_scan (header, MJDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  gfits_scan (header, UTKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    Shutdown ("error in DATE-MODE format: %s", DateMode);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    Shutdown ("error in DATE-MODE format: %s", DateMode);
+  }
+  if ((py > pm) && (py < pd)) {
+    Shutdown ("error in DATE-MODE format: %s", DateMode);
+  }
+  if ((py > pd) && (py < pm)) {
+    Shutdown ("error in DATE-MODE format: %s", DateMode);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    Shutdown ("error in DATE-MODE format: %s", DateMode);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  gfits_scan (header, DateKeyword, "%s",  1, line);
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  Nf = 0;
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    Shutdown ("error in date entry (%s) or DATE-MODE format (%s)", line, DateMode);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+bin
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/Makefile	(revision 16632)
@@ -0,0 +1,48 @@
+default: dvosplit
+help:
+	@echo "make options: dvosplit (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/dvosplit
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+dvosplit     : $(BIN)/dvosplit.$(ARCH)
+all: dvosplit
+
+DVOSPLIT = \
+$(SRC)/dvosplit.$(ARCH).o \
+$(SRC)/SetSignals.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/Shutdown.$(ARCH).o \
+$(SRC)/args.$(ARCH).o \
+$(SRC)/split_averages.$(ARCH).o \
+$(SRC)/split_measures.$(ARCH).o \
+$(SRC)/open_output_catalogs.$(ARCH).o
+
+$(DVOSPLIT)  : $(INC)/dvosplit.h
+
+$(BIN)/dvosplit.$(ARCH) : $(DVOSPLIT)
+
+INSTALL = dvosplit
+
+# dependancy rules for binary code #########################
+$(INSTALL): % : $(BIN)/%.$(ARCH)
+
+%.clean :
+	rm -f $(BIN)/$*.$(ARCH)
+
+%.install:
+	make $(DESTBIN)/$*
+
+install:
+	for i in $(INSTALL); do make $$i.install || exit; done
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/include/dvosplit.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/include/dvosplit.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/include/dvosplit.h	(revision 16632)
@@ -0,0 +1,42 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+# include <sys/time.h>
+# include <time.h>
+# include <zlib.h>
+
+/* solaris requires both of these instead of ip.h:
+   # include <sys/socket.h>
+   # include <netinet/in.h>
+*/
+
+/* linux is happy with this, not solaris */
+# include <netinet/ip.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+# include <glob.h>
+
+typedef struct {
+  int *outref;
+  int *outcat;
+} AveLinks;
+
+int    VERBOSE;
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+
+SkyRegion UserPatch;  // used by MODE CAT
+
+int        main                   PROTO((int argc, char **argv));
+
+int        ConfigInit             PROTO((int *argc, char **argv));
+int        SetSignals             PROTO(());
+void       SetProtect             PROTO((int mode));
+void       TrapSignal             PROTO((int sig));
+int        Shutdown               PROTO((char *format, ...));
+int        args                   PROTO((int argc, char **argv));
+
+Catalog   *open_output_catalogs   PROTO((SkyList *outlist));
+AveLinks  *split_averages         PROTO((Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs));
+int        split_measures         PROTO((Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs, AveLinks *avelinks));
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "dvosplit.h"
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+
+int ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  GetConfig (config, "CATDIR",                 	"%s",  0, CATDIR);
+  GetConfig (config, "PHOTCODE_FILE",          	"%s",  0, MasterPhotcodeFile);
+
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+
+  /* default mode, format, if not specified */
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+  return (TRUE);
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "dvosplit.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect these signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored (POSIX.1-1990) */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored (POSIX.1-1990) */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore (POSIX.1-1990) */
+    case SIGCONT:    /* continue - maintain this action (POSIX.1-1990) */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? (POSIX.1-1990) */
+    case SIGURG:     /* socket signal, ignore this (POSIX.1-2001) */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "dvosplit.h"
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format) + 2);
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/args.c	(revision 16632)
@@ -0,0 +1,87 @@
+# include "dvosplit.h"
+static void help (void);
+
+int args (int argc, char **argv) {
+  
+  int i, N, CONFIRM;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /*** check for command line options ***/
+
+  /*** provide additional data ***/ 
+  /* restrict to a portion of the sky? (REFCAT only) */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  CONFIRM = TRUE;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    CONFIRM = FALSE;
+  }
+
+  /* extra error messages */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc == 2) {
+    if (CONFIRM) {
+      fprintf (stderr, "you are splitting the entire sky in one pass\n");
+      fprintf (stderr, "this could be a time consuming operation.  type Ctrl-C within 5 seconds to cancel\n");
+      for (i = 5; i > 0; i--) {
+	fprintf (stderr, "%d.. ", i);
+	usleep (1000000);
+      }
+      fprintf (stderr, "\n");
+    }    
+    return (TRUE);
+  }
+
+  fprintf (stderr, "USAGE: dvosplit (newlevel) [-region (Rmin) (Rmax) (Dmin) (Dmax)]\n");
+  exit (2);
+}
+
+static void help () {
+
+  fprintf (stderr, "USAGE\n");
+  fprintf (stderr, "  dvosplit (newlevel)\n\n");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -region ra ra dec dec 	  : migrate catalogs in specified region\n");
+  fprintf (stderr, "  -v                    	  : verbose mode\n");
+  fprintf (stderr, "  -help                 	  : this list\n");
+  fprintf (stderr, "  -h                    	  : this list\n\n");
+  exit (2);
+}
+
+/** addstar modes:
+ 
+    addstar (image.smp)  - add cmp/smp image data to db
+    addstar -ref (file.dat) (photcode) 
+    addstar -cat (USNO/2MASS/GSC) -region (ra dec - ra dec)
+
+    -replace : ref/cat - replace existing match (photcode/time)
+    -match   : ref/cat - only add measures to existing averages
+
+    ref types: 
+    ASCII - RA,DEC,M,dM in a table
+
+    addstar 
+
+**/
+
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/dvosplit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/dvosplit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/dvosplit.c	(revision 16632)
@@ -0,0 +1,88 @@
+# include "dvosplit.h"
+
+// dvosplit (outlevel) [-region Rmin Rmax Dmin Dmax]
+int main (int argc, char **argv) {
+
+  int i, j, OUT_DEPTH;
+  SkyTable *sky;
+  SkyList *skylist, *outlist;
+  Catalog incatalog, *outcatalogs;
+  AveLinks *avelinks;
+  char filename[256];
+
+  SetSignals ();
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  OUT_DEPTH = atoi (argv[1]);
+
+  // load the sky table for the existing database
+  sky = SkyTableLoadOptimal (CATDIR, NULL, NULL, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+
+  // get the list of populated regions
+  skylist  = SkyListByPatch (sky, -1, &UserPatch);
+  
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    fprintf (stderr, "%s\n", skylist[0].regions[i][0].name);
+
+    // if (current level >  out level) skip: cannot currently merge catalogs
+    // if (current level == out level) skip: no action is needed
+    if (skylist[0].regions[i][0].depth >= OUT_DEPTH) continue;
+
+    // set the parameters which guide catalog open/load/create
+    incatalog.filename = skylist[0].filename[i];
+    incatalog.Nsecfilt = GetPhotcodeNsecfilt ();
+    incatalog.catflags = LOAD_NONE;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&incatalog, skylist[0].regions[i], VERBOSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", incatalog.filename);
+      exit (2);
+    }
+
+    // skip empty input catalogs
+    if (!incatalog.Naves_disk) {
+      dvo_catalog_unlock (&incatalog);
+      dvo_catalog_free (&incatalog);
+      continue;
+    }
+
+    // change sky.regions[i].depth for these regions
+    outlist = SkyListByPatch (sky, OUT_DEPTH, skylist[0].regions[i]);
+
+    outcatalogs = open_output_catalogs (outlist);
+
+    avelinks = split_averages (&incatalog, outlist, outcatalogs); 
+
+    split_measures (&incatalog, outlist, outcatalogs, avelinks); 
+
+    // XXX missing entries have to be reconstructed if they are desired
+    // split_missings (&incatalog, outlist, outcatalogs, avelinks); 
+
+    free (avelinks[0].outref);
+    free (avelinks[0].outcat);
+
+    dvo_catalog_unlock (&incatalog);
+
+    for (j = 0; j < outlist[0].Nregions; j++) {
+      dvo_catalog_unlock (&outcatalogs[j]);
+    }
+
+    // adjust depth
+    skylist[0].regions[i][0].table = FALSE;
+    for (j = 0; j < outlist[0].Nregions; j++) {
+      outlist[0].regions[j][0].table = TRUE;
+    }
+  }
+
+  // save sky table copy
+  sprintf (filename, "%s/SkyTable.fits", CATDIR);
+  check_file_access (filename, TRUE, VERBOSE);
+  if (!SkyTableSave (sky, filename)) {
+    fprintf (stderr, "ERROR: failed to save sky table for %s\n", CATDIR);
+    exit (1);
+  }
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/open_output_catalogs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/open_output_catalogs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/open_output_catalogs.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "dvosplit.h"
+
+Catalog *open_output_catalogs (SkyList *outlist) {
+
+  int i;
+  Catalog *outcatalogs;
+
+  ALLOCATE (outcatalogs, Catalog, outlist[0].Nregions);
+
+  // an error exit status here is a significant error
+  for (i = 0; i < outlist[0].Nregions; i++) {
+    
+    // set the parameters which guide catalog open/load/create
+    outcatalogs[i].filename  = outlist[0].filename[i];
+    outcatalogs[i].Nsecfilt  = GetPhotcodeNsecfilt ();
+    outcatalogs[i].catflags  = LOAD_NONE;
+    outcatalogs[i].catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    outcatalogs[i].catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+
+    if (!dvo_catalog_open (&outcatalogs[i], outlist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", outcatalogs[i].filename);
+      exit (2);
+    }
+  }
+  
+  return (outcatalogs);
+}
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_averages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_averages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_averages.c	(revision 16632)
@@ -0,0 +1,118 @@
+# include "dvosplit.h"
+# define NROWS 100000 /* ~10MB per block for measures */
+# define DNOUT 1000
+
+AveLinks *split_averages (Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs) {
+
+  double inR, inD;
+  int n, block, ave, cat, averef, Nblocks, Ncat, Nout, Nsecfilt;
+  int *outref, *outcat, *outmem;
+  AveLinks *avelinks;
+
+  ALLOCATE (outref, int, incatalog[0].Naves_disk);
+  ALLOCATE (outcat, int, incatalog[0].Naves_disk);
+  ALLOCATE (outmem, int, outlist[0].Nregions);
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  // allocate enough space for these output buffers: use Nsecfilt + 1 incase the file
+  // contains primary photcodes, which will increase Nsecfilt by one.
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    outmem[cat] = DNOUT;
+    REALLOCATE (outcatalogs[cat].average, Average, outmem[cat]);
+    REALLOCATE (outcatalogs[cat].secfilt, SecFilt, outmem[cat]*(Nsecfilt + 1));
+  }
+
+  // split out the average & secfilt entries:
+  incatalog[0].catflags = LOAD_AVES | LOAD_SECF;
+  Nblocks = incatalog[0].Naves_disk / NROWS;
+  if (incatalog[0].Naves_disk % NROWS) Nblocks ++;
+  for (block = 0; block < Nblocks; block++) {
+
+    // read up to NROWS at a time
+    dvo_catalog_load_segment (incatalog, VERBOSE, block*NROWS, NROWS);
+    fprintf (stderr, "splitting %s (averages) .. %d of %d\n", incatalog[0].filename, block, Nblocks);
+
+    assert (block*NROWS == incatalog[0].Naves_off);
+
+    // distribute data to the output catalogs
+    for (ave = 0; ave < incatalog[0].Naverage; ave++) {
+      averef = ave + incatalog[0].Naves_off;
+	
+      inR = incatalog[0].average[ave].R;
+      inD = incatalog[0].average[ave].D;
+
+      // which of the outcatalogs contains this coordinate?
+
+      Ncat = -1;
+      for (cat = 0; cat < outlist[0].Nregions; cat++) {
+	if (inR < outlist[0].regions[cat][0].Rmin) continue;
+	if (inR > outlist[0].regions[cat][0].Rmax) continue;
+	if (inD < outlist[0].regions[cat][0].Dmin) continue;
+	if (inD > outlist[0].regions[cat][0].Dmax) continue;
+	Ncat = cat;
+	break;
+      }
+
+      if (Ncat == -1) {
+	fprintf (stderr, "WARNING: missed %d (%f, %f)\n", averef, inR, inD);
+	continue;
+      }
+
+      Nout = outcatalogs[Ncat].Naverage;
+      outref[averef] = Nout + outcatalogs[Ncat].Naves_off;
+      outcat[averef] = Ncat;
+
+      // assign the value to the next element of the output catalog
+      outcatalogs[Ncat].average[Nout] = incatalog[0].average[ave];
+      outcatalogs[Ncat].Naverage ++;
+
+      // update secfilt at the same time
+      for (n = 0; n < Nsecfilt; n++) {
+	outcatalogs[Ncat].secfilt[Nout*Nsecfilt + n] = incatalog[0].secfilt[ave*Nsecfilt + n];
+	outcatalogs[Ncat].Nsecf_mem++;
+      }
+
+      if (outcatalogs[Ncat].Naverage >= outmem[Ncat]) {
+	outmem[Ncat] += DNOUT;
+	REALLOCATE (outcatalogs[Ncat].average, Average, outmem[Ncat]);
+	REALLOCATE (outcatalogs[Ncat].secfilt, SecFilt, outmem[Ncat]*(Nsecfilt + 1));
+      }
+    }
+    dvo_catalog_free_data (incatalog);
+
+    // double check the values of Naverage, Nsecf_mem?
+
+    // write out the new values
+    for (cat = 0; cat < outlist[0].Nregions; cat++) {
+      outcatalogs[cat].catflags = LOAD_AVES | LOAD_SECF;
+
+      dvo_catalog_save (&outcatalogs[cat], VERBOSE);
+      // fprintf (stderr, "secfilt: %d %d %d %d\n", outcatalogs[cat].Nsecf_mem, outcatalogs[cat].Nsecf_disk, outcatalogs[cat].Nsecf_off, outcatalogs[cat].Naverage, outcatalogs[cat].Nsecfilt);
+
+      // advance the pointers and free the current data
+      // XXX these should be done within save segment:
+      outcatalogs[cat].Naves_disk += outcatalogs[cat].Naverage;
+      outcatalogs[cat].Naves_off  += outcatalogs[cat].Naverage;
+      outcatalogs[cat].Nsecf_disk += outcatalogs[cat].Nsecfilt * outcatalogs[cat].Naverage;
+      outcatalogs[cat].Nsecf_off  += outcatalogs[cat].Nsecfilt * outcatalogs[cat].Naverage;
+      outcatalogs[cat].Nsecfilt    = Nsecfilt;
+
+      outcatalogs[cat].Naverage    = 0;
+      outcatalogs[cat].Nsecf_mem   = 0;
+    }
+  }
+
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    dvo_catalog_free_data (&outcatalogs[cat]);
+  }
+
+  free (outmem);
+
+  ALLOCATE (avelinks, AveLinks, 1);
+  avelinks[0].outref = outref;
+  avelinks[0].outcat = outcat;
+
+
+  return (avelinks);
+}
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_measures.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_measures.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_measures.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include "dvosplit.h"
+# define NROWS 100000 /* ~10MB per row for measures */
+# define DNOUT 1000
+
+int split_measures (Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs, AveLinks *avelinks) {
+
+  int block, meas, cat, Nblocks, Ncat, Nout, averef;
+  int *outref, *outcat, *outmem;
+
+  outref = avelinks->outref;
+  outcat = avelinks->outcat;
+  ALLOCATE (outmem, int, outlist[0].Nregions);
+
+  // allocate enough space for the output buffer
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    outmem[cat] = DNOUT;
+    REALLOCATE (outcatalogs[cat].measure, Measure, outmem[cat]);
+  }
+
+  // split out the measure entries:
+  incatalog[0].catflags = LOAD_MEAS;
+  Nblocks = incatalog[0].Nmeas_disk / NROWS;
+  if (incatalog[0].Nmeas_disk % NROWS) Nblocks ++;
+  for (block = 0; block < Nblocks; block++) {
+
+    // read up to NROWS at a time
+    dvo_catalog_load_segment (incatalog, VERBOSE, block*NROWS, NROWS);
+    fprintf (stderr, "splitting %s (measures) .. %d of %d\n", incatalog[0].filename, block, Nblocks);
+
+    assert (block*NROWS == incatalog[0].Nmeas_off);
+
+    for (meas = 0; meas < incatalog[0].Nmeasure; meas++) {
+
+      averef = incatalog[0].measure[meas].averef;
+      Ncat = outcat[averef];
+
+      Nout = outcatalogs[Ncat].Nmeasure;
+      outcatalogs[Ncat].measure[Nout] = incatalog[0].measure[meas];
+      outcatalogs[Ncat].measure[Nout].averef = outref[averef];
+      outcatalogs[Ncat].Nmeasure++;
+
+      if (outcatalogs[Ncat].Nmeasure >= outmem[Ncat]) {
+	outmem[Ncat] += DNOUT;
+	REALLOCATE (outcatalogs[Ncat].measure, Measure, outmem[Ncat]);
+      }
+    }
+    dvo_catalog_free_data (incatalog);
+
+    for (cat = 0; cat < outlist[0].Nregions; cat++) {
+      outcatalogs[cat].catflags = LOAD_MEAS;
+      dvo_catalog_save (&outcatalogs[cat], VERBOSE);
+
+      outcatalogs[cat].Nmeas_disk += outcatalogs[cat].Nmeasure;
+      outcatalogs[cat].Nmeas_off  += outcatalogs[cat].Nmeasure;
+      outcatalogs[cat].Nmeasure    = 0;
+
+    }
+  }
+
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    dvo_catalog_free_data (&outcatalogs[cat]);
+  }
+
+  free (outmem);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_missings.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_missings.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/dvosplit/src/split_missings.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "dvosplit.h"
+# define NROWS 100000 /* ~10MB per row for missings */
+
+int split_missings (Catalog *incatalog, SkyList *outlist, Catalog *outcatalogs, AveLinks *avelinks) {
+
+  int *outref, *outcat;
+
+  outref = avelinks->outref;
+  outcat = avelinks->outcat;
+
+  // allocate enough space for the output buffer
+  for (cat = 0; cat < outlist[0].Nregions; cat++) {
+    REALLOCATE (outcatalog[cat].missing, Missing, NROWS);
+  }
+
+  // split out the missing entries:
+  incatalog[0].catflags = LOAD_MISS;
+  Nblocks = incatalog[0].Nmiss_disk / NROWS;
+  if (incatalog[0].Nmiss_disk % NROWS) Nblocks ++;
+  for (block = 0; block < Nblocks; block++) {
+
+    // read up to NROWS at a time
+    dvo_catalog_load_segment (incatalog, VERBOSE, block*NROWS, NROWS);
+
+    for (miss = 0; miss < incatalog[0].Nmissing; miss++) {
+
+      averef = incatalog[0].missing[miss].averef;
+      Ncat = outcat[averef];
+
+      Nout = outcatalog[Ncat].Nmissing;
+      outcatalog[Ncat].missing[Nout] = incatalog[0].missing[miss];
+      outcatalog[Ncat].missing[Nout].averef = outref[averef];
+      outcatalog[Ncat].Nmissing++;
+    }
+
+    for (cat = 0; cat < outlist[0].Nregions; cat++) {
+      outcatalogs[cat].catflags = LOAD_MISS;
+      dvo_catalog_save_segment (&outcatalog[cat], VERBOSE);
+
+      outcatalog[cat].Nmiss_disk += outcatalog[cat].Nmissing;
+      outcatalog[cat].Nmiss_off  += outcatalog[cat].Nmissing;
+      outcatalog[cat].Nmissing    = 0;
+
+    }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/Makefile	(revision 16632)
@@ -0,0 +1,37 @@
+default: elixir
+help:
+	@echo "make options: elixir (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/elixir
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+elixir: $(BIN)/elixir.$(ARCH)
+install: $(DESTBIN)/elixir
+
+ELIXIR = \
+$(SRC)/elixir.$(ARCH).o			$(SRC)/ConfigInit.$(ARCH).o		\
+$(SRC)/MachineOps.$(ARCH).o		$(SRC)/FifoOps.$(ARCH).o		\
+$(SRC)/QueueOps.$(ARCH).o		$(SRC)/CheckCluster.$(ARCH).o		\
+$(SRC)/CheckDepend.$(ARCH).o		$(SRC)/CheckEndingState.$(ARCH).o	\
+$(SRC)/CheckMachineStatus.$(ARCH).o	$(SRC)/CheckProcess.$(ARCH).o		\
+$(SRC)/InitProcess.$(ARCH).o		$(SRC)/StartMachine.$(ARCH).o		\
+$(SRC)/SockScan.$(ARCH).o		$(SRC)/LoadPending.$(ARCH).o		\
+$(SRC)/Photcodes.$(ARCH).o		$(SRC)/rconnect.$(ARCH).o		\
+$(SRC)/DefineProcesses.$(ARCH).o        $(SRC)/ProcessOps.$(ARCH).o		\
+$(SRC)/DumpStatus.$(ARCH).o		$(SRC)/CheckMessages.$(ARCH).o		\
+$(SRC)/MsgOps.$(ARCH).o			$(SRC)/LogOpen.$(ARCH).o		\
+$(SRC)/ConfigPID.$(ARCH).o		$(SRC)/RemoteOps.$(ARCH).o
+
+$(ELIXIR): $(INC)/elixir.h
+$(BIN)/elixir.$(ARCH): $(ELIXIR)
Index: /branches/eam_branch_20080223/Ohana/src/elixir/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/elixir/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,24 @@
+
+- elixir-1-5 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+
+elixir-1-4:
+  changed printing formats for pointers to %p
+  using updated version of mkdirhier (libohana 1.7)
+
+elixir-1-3:
+  libohana / libfits were modified, forcing the 
+  addition of fitsio.h to controller.h
+
+elixir-1-2:
+ - changing setlockfile2 to fsetlockfile
+   (dropping use of fd version of APIs)
+   elixir should eventually be superceeded by sched/pcontrol,
+   but perhaps not at CFHT.
+
+elixir-1-1:
+ - minor cleanup of rconnect process
+ - ignore SIG_CHLD now 
+
+elixir-1-0:
+ - created tag for first elixir distribution
Index: /branches/eam_branch_20080223/Ohana/src/elixir/doc/README
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/doc/README	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/doc/README	(revision 16632)
@@ -0,0 +1,13 @@
+
+There are two parts to elixir which are a bit dangerous (and limit the
+possibilities).  
+
+First, the number of arguments which describe an object is limited to
+7.  This is limited in LoadPending.c and is due to the dumb way I
+parse these input lines.
+
+Second, in a similar way, the number of arguments to a command line
+argument (the 'process.arg' entries) is limited to 5, again for about
+the same reason.  this is in 'ParseLine' in ProcessOps.c
+
+
Index: /branches/eam_branch_20080223/Ohana/src/elixir/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/doc/notes.txt	(revision 16632)
@@ -0,0 +1,40 @@
+
+
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nmaxread;
+  int   Nextra;
+  int   Nlast;
+  int   Nbuffer;
+} Fifo;
+
+typedef struct {
+  int argc; char **argv; /* a list of words that define this object */
+  struct timeval start, accum, timer;
+  int   status;
+  char *logfile;
+  char *lastproc;
+} Object;
+
+typedef struct {
+  Object **object;
+  int    Nobject;
+  int    NOBJECT;
+} Queue;
+
+typedef struct {
+  char   *hostname;
+  int     rsock, wsock;
+  int     status; /* idle, busy, etc... */
+  struct  timeval start, accum, timer;
+  Fifo    fifo;
+  int     code;
+  Object *object;
+} Machine;
+
+
+currently, the transport is /usr/bin/rsh, defined in InitMachines.c 
+
+the shell on the remote machines is /bin/tcsh, defined by rconnect.c
+
Index: /branches/eam_branch_20080223/Ohana/src/elixir/include/elixir.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/include/elixir.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/include/elixir.h	(revision 16632)
@@ -0,0 +1,173 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <signal.h>
+# include <errno.h>
+
+# define CR 0x0D
+# define LF 0x0A
+
+# define IDLE     0x00
+# define BUSY     0x01
+# define DOWN     0x02
+# define DONE     0x04
+# define MESSAGE  0x08
+# define SUCCESS  0x10
+# define FAILURE  0x20
+# define JOBDONE  0x40
+# define WAITING  0x80
+# define ERROR    0x100
+# define CRASH    0x200
+# define TIMEOUT  0x400
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+/* represents a socketed connection to a remote host
+   which may or may not be currently running a process */
+
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nmaxread;
+  int   Nextra;
+  int   Nlast;
+  int   Nbuffer;
+} Fifo;
+
+typedef struct {
+  int argc; char **argv; /* a list of words that define this object */
+  struct timeval start, accum, timer;
+  int   status;
+  char *logfile;
+  char *lastproc;
+} Object;
+
+typedef struct {
+  Object **object;
+  int    Nobject;
+  int    NOBJECT;
+} Queue;
+
+typedef struct {
+  char   *hostname;
+  int     rsock, wsock, pid;
+  int     status; /* idle, busy, etc... */
+  struct  timeval start, accum, timer, quiet;
+  Fifo    fifo;
+  int     code;
+  Object *object;
+} Machine;
+
+typedef struct {
+  Machine **machine;
+  int     Nmachine;
+  int     NMACHINE;
+} Cluster;
+
+typedef struct {
+  char    *name;
+  Queue   *pending;
+  Queue   *success;
+  Queue   *failure;
+  Cluster *cluster;
+  int     argc;
+  char    **argv;
+} Process;
+
+/* we have one ProcessTimer for each existing machine
+   each ProcessTimer has one element for each process */
+typedef struct {
+  struct timeval *timer;
+  double       *timesum;
+  int          *Njobs;
+  int          *active;
+  Machine      *machine;
+  Process     **process;
+} ProcessTimers;
+
+int   VERBOSE;
+char  CONNECT[128];
+
+/* prototypes */
+
+Process **DefineProcesses (Process *global, int *nprocess, char *config);
+Process **GetProcessInfo (Process **gb, int *np, int *no);
+char 	 *BaseFilename (char *file);
+char 	 *BuildCode (char *line);
+char 	 *BuildName (char *line);
+char 	 *ConfigInit (int *argc, char **argv);
+Process  *ConfigProcess (char *config, char *procname);
+char 	 *ExpandEntry (char *entry, int argc, char **argv);
+Machine  *GetMachine (Cluster *cluster);
+Object   *GetObject (Queue *queue);
+char 	 *GetPhotcode (char *file);
+char 	 *GetPhotcodeExt (char *file);
+char 	 *GetPhotcodeMef (char *file);
+Machine  *GrabMachine ();
+Cluster  *InitCluster ();
+Process  *InitProcess (char *name, Queue *pending, Queue *failure, int (*mkargs)());
+Queue    *InitQueue ();
+FILE     *LogOpen (char *filename);
+char 	 *PathFilename (char *file);
+char 	 *RootFilename (char *file);
+int 	  CheckCluster (Cluster *cluster, Queue *success, Queue *failure, Queue *pending);
+int 	  CheckDepend (Object *object, int argc, char **argv, int *argd);
+int 	  CheckEndingState (Process *global, int Nobjects, int Dynamic);
+int 	  CheckMachineStatus (Machine *machine);
+int 	  CheckMessages ();
+int 	  CheckProcess (Process *process);
+void 	  CloseMachine (Machine *machine);
+void 	  ConfigPID (char *PIDFile);
+int 	  ConnectMachine (Machine *machine);
+void 	  DownMachine (Machine *machine);
+void 	  DumpFinished (Queue *queue, int Nstart, char *filename);
+void 	  DumpMachineStatus (FILE *f);
+int 	  DumpProcessTimes (char *filename);
+int 	  DumpStatus (char *filename);
+void 	  ElixirStop ();
+int 	  FlushFifo (Fifo *fifo);
+void 	  FreeArgs (int argc, char **argv, int *argd);
+void 	  FreeFifo (Fifo *fifo);
+int 	  GetDynamicState ();
+double    GetTimeout ();
+void 	  HaltElixir (char *pidfile);
+int 	  HalttoRestart (char *pidfile);
+void 	  IdleMachine (Machine *machine);
+int 	  InitFifo (Fifo *fifo, int Nalloc, int Nextra);
+void 	  InitMachines (char *config);
+int 	  InitMsgFile (char *file);
+void 	  InitProcessTimers (Process **process, int Nprocess);
+void 	  KillElixir (char *pidfile);
+int 	  LoadPID (char *file, pid_t *pid, char *username, char *machine);
+int 	  LoadPending (Process *global, char *inlist, int *state, int *dynamic);
+int 	  MakeArgs (Process *process, Object *object, int *cargc, char ***cargv, int **cargd);
+void 	  ParseLine (char *testline, int argc, char **argv, int *depend, char **outline);
+void 	  PushMachine (Machine *machine, Cluster *cluster);
+void 	  PushObject (Queue *queue, Object *object);
+void 	  PutMachine (Machine *machine, Cluster *cluster);
+void 	  PutObject (Queue *queue, Object *object);
+int 	  ReadMsg (char *fifo, char **message);
+int 	  ReadtoFifo (Fifo *fifo, int sock);
+void 	  RegisterTimeout (double value);
+void 	  RemovePID ();
+void 	  Restart (char **argv);
+void 	  RestartMachines ();
+void 	  SIG_DIE (int sig);
+void 	  SIG_MESSAGE (int sig);
+void 	  SIG_PIPE (int sig);
+void 	  SIG_RELOAD (int sig);
+void 	  SIG_STOP (int sig);
+int 	  SetExitTimer ();
+void 	  SetMessageFile (char *filename);
+int 	  ShiftFifo (Fifo *fifo);
+void 	  Shutdown (int status);
+int 	  SockScan (char *string, Fifo *fifo, int sock);
+int 	  StartMachine (Machine *machine, Object *object, int argc, char **argv);
+void 	  StartProcessTimer (Process *process, Machine *machine);
+void 	  StatusElixir (char *pidfile, char *msgfile);
+void 	  StopProcessTimer (Machine *machine);
+int 	  TestMachine (Machine *machine);
+int 	  WaitMsg (char *fifo, char **message, double maxdelay);
+int 	  WriteMsg (char *fifo, char *message);
+int 	  memstr (char *m1, char *m2, int n);
+int 	  rconnect (char *hostname, char *command, int *rsock, int *wsock);
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckCluster.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckCluster.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckCluster.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "elixir.h"
+
+int CheckCluster (Cluster *cluster, Queue *success, Queue *failure, Queue *pending) {
+
+  int i, j, status;
+  Machine *machine, **tmachine;
+  Object *object;
+  FILE *logfile;
+
+  /* check current status of all machines in cluster, idle those finished */
+  for (i = 0; i < cluster[0].Nmachine; i++) {
+    
+    machine = cluster[0].machine[i];
+    status = CheckMachineStatus (machine);
+
+    object = machine[0].object;
+    logfile = LogOpen (object[0].logfile);
+
+    if (status & MESSAGE) {
+      fprintf (logfile, "%s @ %s:", object[0].argv[0], machine[0].hostname);
+      fwrite (&machine[0].fifo.buffer[machine[0].fifo.Nlast], 1, machine[0].fifo.Nbuffer - machine[0].fifo.Nlast, logfile);
+    }      
+
+    if (status & DOWN) {
+      fprintf (stderr, "%s @ %s is down\n", object[0].argv[0], machine[0].hostname);
+      fprintf (logfile, "%s @ %s is down\n", object[0].argv[0], machine[0].hostname);
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      /* PutObject (failure, object); */
+      /* if machine crashes, retry object later */
+      PutObject (pending, object);
+      DownMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & DONE) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      fprintf (logfile, "%s @ %s is done\n", object[0].argv[0], machine[0].hostname);
+      if (status & SUCCESS) {
+	PutObject (success, object);
+      } 
+      if (status & FAILURE) {
+	PutObject (failure, object);
+      } 
+      IdleMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & CRASH) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      fprintf (logfile, "%s @ %s had process crash\n", object[0].argv[0], machine[0].hostname);
+      PutObject (failure, object);
+      IdleMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & ERROR) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      StopProcessTimer (machine);
+      fprintf (logfile, "%s @ %s has an odd status\n", object[0].argv[0], machine[0].hostname);
+      PutObject (failure, object);
+      DownMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+    if (status & TIMEOUT) {
+      object[0].timer.tv_sec = 0; /* reset timer */
+      /* don't include TIMEOUT in timer stats StopProcessTimer (machine); */
+      fprintf (logfile, "%s @ %s timed out, retrying\n", object[0].argv[0], machine[0].hostname);
+      PutObject (pending, object);
+      IdleMachine (machine);
+      cluster[0].machine[i] = (Machine *) NULL;
+      goto escape;
+    }
+
+  escape:
+    if (logfile != stderr) fclose (logfile);
+  }
+
+  /* remove idle machines from this cluster's list */
+  ALLOCATE (tmachine, Machine *, cluster[0].NMACHINE);
+  for (j = i = 0; i < cluster[0].Nmachine; i++) {
+    if (cluster[0].machine[i] != (Machine *) NULL) {
+      tmachine[j] = cluster[0].machine[i];
+      j++;
+    }
+  }
+  free (cluster[0].machine);
+  cluster[0].machine = tmachine;
+  cluster[0].Nmachine = j;
+
+  return (TRUE);
+}
+
+
+/*
+
+  possible ending states:
+
+  DONE & SUCCESS = process finished normally & succeeded
+  DONE & FAILURE = process finished normally & failed
+
+  CRASH = process crashed
+  DOWN  = machine crashed
+  IDLE  = no process (should never show up here!)
+  ERROR = unexpected state!
+
+  whenever an object is done, in any of the possible states, the
+  arg dependency timer must be reset 
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckDepend.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckDepend.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckDepend.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "elixir.h"
+
+int CheckDepend (Object *object, int argc, char **argv, int *argd) {
+
+  int i;
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status;
+  struct timeval now;
+  FILE *logfile;
+  double dtime;
+
+  uid = getuid();
+  gid = getgid();
+
+  for (i = 0; i < argc; i++) {
+    if (argd[i]) {
+      /* check permission to read file */
+      status = stat (argv[i], &filestat);
+      
+      /* continue if file exists and is accessible */
+      if (!status) {
+	if ((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) continue;
+	if ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) continue;
+	if (filestat.st_mode & S_IROTH) continue;
+      }
+
+      /* if the file doesn't exist or is inaccessible, check the timer on this object */
+      if (object[0].timer.tv_sec == 0) {
+	gettimeofday (&object[0].timer, (void *) NULL);
+	return (0);
+      } 
+      
+      gettimeofday (&now, (void *) NULL);
+      dtime = DTIME (now, object[0].timer);
+      if (dtime > argd[i]) {
+	logfile = LogOpen (object[0].logfile);
+	fprintf (logfile, "timeout on %s: %f > %d\n", argv[i], dtime, argd[i]);
+	if (logfile != stderr) fclose (logfile);
+	object[0].status &= TIMEOUT;
+	return (2);
+      } else {
+	return (0);
+      }
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckEndingState.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckEndingState.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckEndingState.c	(revision 16632)
@@ -0,0 +1,80 @@
+# include "elixir.h"
+
+static int Nsuccess = 0;
+static int Nfailure = 0;
+static double timeout;
+struct timeval start;
+static int Reload = FALSE;
+
+int CheckEndingState (Process *global, int Nobjects, int Dynamic) {
+  
+  int Ndone;
+  struct timeval now;
+  double dtime;
+  
+  /* check the success and failure queues for newly added objects */
+  
+  if (global[0].success[0].Nobject > Nsuccess) {
+    DumpFinished (global[0].success, Nsuccess, global[0].argv[0]);
+    Nsuccess = global[0].success[0].Nobject;
+  }
+  if (global[0].failure[0].Nobject > Nfailure) {
+    DumpFinished (global[0].failure, Nfailure, global[0].argv[1]);
+    Nfailure = global[0].failure[0].Nobject;
+  }
+
+  if (Dynamic) return  (TRUE);
+  
+  Ndone = 0;
+  Ndone += global[0].success[0].Nobject;
+  Ndone += global[0].failure[0].Nobject;
+
+  if (Reload) {
+    gettimeofday (&now, (void *) NULL);
+    dtime = DTIME (now, start);
+    if (dtime > timeout) return (FALSE);
+  }
+  
+  if (Ndone == Nobjects)  
+    return (FALSE);
+  else
+    return (TRUE);
+}
+
+void DumpFinished (Queue *queue, int Nstart, char *filename) {
+  
+  int i, j;
+  FILE *f;
+  
+  f = fopen (filename, "a");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't output status of finished objects to %s\n", filename);
+    f = stderr;
+  }
+  
+  for (i = Nstart; i < queue[0].Nobject; i++) {
+    
+    for (j = 0; j < queue[0].object[i][0].argc; j++) {
+      fprintf (f, "%s ", queue[0].object[i][0].argv[j]);
+    }
+    fprintf (f, "%08x %s\n", queue[0].object[i][0].status, queue[0].object[i][0].lastproc);
+  }
+  
+  if (f != stderr) fclose (f);
+  
+}
+
+int SetExitTimer () {
+
+  timeout = GetTimeout ();
+  gettimeofday (&start, (void *) NULL);
+  Reload = TRUE;
+  return (TRUE);
+}
+
+/* 
+   
+   global.success = global[0].argv[0]
+   global.failure = global[0].argv[1]
+   
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckMachineStatus.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckMachineStatus.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckMachineStatus.c	(revision 16632)
@@ -0,0 +1,131 @@
+# include "elixir.h"
+# define MAXTIME 120
+
+static double timeout;
+
+void RegisterTimeout (double value) {
+ timeout = value;
+}
+
+double GetTimeout () {
+  return (timeout);
+}
+
+int CheckMachineStatus (Machine *machine) {
+
+  unsigned int status;
+  int Nread;
+  struct timeval now;
+  FILE *logfile;
+  float dtime;
+
+  status = machine[0].status;
+
+  if (status == IDLE) return (status);
+  if (status == DONE) return (status);
+  if (status == DOWN) return (status);
+
+  status &= ~MESSAGE; /* clear MESSAGE status */
+  
+  /* read from socket into fifo */
+  ShiftFifo (&machine[0].fifo);
+
+  Nread = ReadtoFifo (&machine[0].fifo, machine[0].rsock);
+  
+  /* evaluate data in message */
+  switch (Nread) {
+  case 0:
+    status = DOWN;
+    break;
+  case -1:
+    status |= BUSY;
+    gettimeofday (&now, (void *) NULL);
+    dtime = DTIME (now, machine[0].quiet);
+    if (dtime > timeout) {
+      logfile = LogOpen (machine[0].object[0].logfile);
+      fprintf (logfile, "%s: process is taking too long, giving up\n", machine[0].hostname);
+      if (logfile != stderr) fclose (logfile);
+      fprintf (stderr, "process on %s hung?  killing and retrying...\n", machine[0].hostname);
+      /* interrupt process which is running */
+      kill (machine[0].pid, SIGINT);
+      status = TIMEOUT;
+      /* status = (JOBDONE | FAILURE); */
+    }
+    break;
+  default:
+    status |= MESSAGE;
+    gettimeofday (&machine[0].quiet, (void *) NULL);
+    if (memstr (machine[0].fifo.buffer, "ERROR",        machine[0].fifo.Nbuffer))
+      status |= FAILURE;
+    if (memstr (machine[0].fifo.buffer, "SUCCESS",      machine[0].fifo.Nbuffer))
+      status |= SUCCESS;
+    if (memstr (machine[0].fifo.buffer, "PROCESS DONE", machine[0].fifo.Nbuffer))
+      status |= JOBDONE;
+    break;
+  }
+
+  /* evaluate status completion-type status signals */
+  switch (status & (JOBDONE | SUCCESS | FAILURE)) {
+  case FAILURE:
+  case SUCCESS:
+  case JOBDONE:
+    if (status & WAITING) break;
+    status |= WAITING;
+    gettimeofday (&machine[0].timer, (void *) NULL);
+    break;
+  case (JOBDONE | SUCCESS):
+  case (JOBDONE | FAILURE):
+    status |= DONE;
+    break;
+  case (FAILURE | SUCCESS):
+  case (JOBDONE | FAILURE | SUCCESS):
+    status |= ERROR;
+    break;
+  default:
+    break;
+  }
+
+  /* check for completion timeout */
+  if (status & WAITING) {
+    gettimeofday (&now, (void *) NULL);
+    if (DTIME (now, machine[0].timer) > MAXTIME) {
+      switch (status & (JOBDONE | SUCCESS | FAILURE)) {
+      case JOBDONE:
+	status |= CRASH;
+	break;
+      case SUCCESS:
+      case FAILURE:
+      default:
+	status |= ERROR;
+	break;
+      }
+    }
+  }
+
+  machine[0].object[0].status = status;
+  machine[0].status = status;
+
+  return (status);
+
+}
+
+
+/* machine status:
+
+   the machine can have several possible statuss, made up of specific bits
+   in the status variable:
+
+   IDLE 0x00 - no process running on host
+   DOWN 0x01 - no connection to host
+   BUSY 0x02 - no message on socket
+   DONE 0x04 - process completed
+
+   MESSAGE 0x08 - message on socket
+   FAILURE 0x10 - process reported 'failure'
+   SUCCESS 0x20 - process reported 'success'
+   JOBDONE 0x40 - process reported 'jobdone'
+   WAITING 0x80 - process reported 'jobdone'
+
+   ERROR   0x010 - unexpected return values
+   CRASH   0x020 - process crashed
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckMessages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckMessages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckMessages.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "elixir.h"
+
+static struct timeval then = {0,0};
+static char *MessageFile = (char *) NULL;
+
+void SetMessageFile (char *filename) {
+  MessageFile = filename;
+}
+
+int CheckMessages () {
+  
+  int status, Message;
+  struct timeval now;
+  char *message, *p, *p2;
+  char file[256], cmd[64];
+
+  /* we should only do this check every 200ms or so */
+  gettimeofday (&now, (void *) NULL);
+  if (DTIME (now, then) < 0.2) return (1);
+
+  if (MessageFile == (char *) NULL) {
+    fprintf (stderr, "not ready for messages\n");
+    return (FALSE);
+  }
+
+  status = WaitMsg (MessageFile, &message, 0.1);
+  then = now;
+  if (!status) return (FALSE);
+
+  Message = 0;
+
+  /* loop over all lines in message */
+  p = message;
+  while (strlen (p) > 0) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL) {
+      p2 = p + strlen (p) - 1;
+    } else {
+      *p2 = 0;
+    }
+
+    sscanf (p, "%s %s", cmd, file);
+
+    if (!strcasecmp (cmd, "ALIVE"))  {
+      WriteMsg (file, "BUSY");
+    }
+    if (!strcasecmp (cmd, "TIMES")) {
+      DumpProcessTimes (file);
+    }
+    if (!strcasecmp (cmd, "STATUS")) {
+      DumpStatus (file); 
+    }
+    if (!strcasecmp (cmd, "STOP"))   {
+      WriteMsg (file, "Elixir will end when processes are done");
+      ElixirStop ();
+    }
+    if (!strcasecmp (cmd, "ABORT"))  {
+      WriteMsg (file, "Elixir is exiting without finishing");
+      Shutdown (1);
+    }
+
+    p = p2 + 1;
+
+  }
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckProcess.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckProcess.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/CheckProcess.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "elixir.h"
+
+int CheckProcess (Process *process) {
+
+  Machine *machine;
+  int cargc, *cargd;
+  char **cargv;
+  Object *object;
+
+  CheckCluster (process[0].cluster, process[0].success, process[0].failure, process[0].pending);
+  if (drand48() > 0.5) return (FALSE);
+
+
+  if ((object = GetObject (process[0].pending)) == (Object *) NULL) return (FALSE);
+  object[0].lastproc = process[0].name;
+
+  /* can't create arguments, some dependencies might not be ready */
+  if (!MakeArgs (process, object, &cargc, &cargv, &cargd)) {
+    FreeArgs (cargc, cargv, cargd);
+    PutObject (process[0].pending, object);
+    return (FALSE);
+  }
+
+  /* dependencies not ready */
+  switch (CheckDepend (object, cargc, cargv, cargd)) {
+  case 0:
+    FreeArgs (cargc, cargv, cargd);
+    PutObject (process[0].pending, object);
+    return (FALSE);
+  case 2:
+    FreeArgs (cargc, cargv, cargd);
+    PutObject (process[0].failure, object);
+    return (FALSE);
+  case 1:
+  default:
+    break;
+  }
+    
+  /* no machine ready */
+  if ((machine = GrabMachine ()) == (Machine *) NULL) {
+    /* need to free appropriate items from above */
+    FreeArgs (cargc, cargv, cargd);
+    PushObject (process[0].pending, object);
+    return (FALSE);
+  }
+
+  StartMachine (machine, object, cargc, cargv);
+  FreeArgs (cargc, cargv, cargd);
+  StartProcessTimer (process, machine);
+
+  PutMachine (machine, process[0].cluster);
+  return (TRUE);
+}
+
+/* objects that are not ready go to the bottom of the stack (PutObject)
+   objects that are ready, but have no machine free, go to top of stack (PushObject) 
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,193 @@
+# include "elixir.h"
+
+void SIG_STOP (int sig) {
+  fprintf (stderr, "trapped signal %d, exiting when jobs are done\n", sig);
+  ElixirStop ();
+}
+
+void SIG_MESSAGE (int sig) {
+  fprintf (stderr, "trapped signal %d, reading message\n", sig);
+  CheckMessages ();
+}
+
+void SIG_DIE (int sig) {
+  fprintf (stderr, "trapped signal %d, exiting\n", sig);
+  Shutdown (1);
+}
+
+void SIG_PIPE (int sig) {
+  fprintf (stderr, "pipe signal %d\n", sig);
+}
+
+char *ConfigInit (int *argc, char **argv) {
+
+  int N;
+  char *config, *file;
+
+  /* use default settings */
+  signal (SIGKILL,   SIG_DFL);    
+  signal (SIGCONT,   SIG_DFL);    
+  signal (SIGSTOP,   SIG_DFL);    
+  signal (SIGCHLD,   SIG_DFL);    
+
+  /* exit on these signals */
+  signal (SIGILL,    SIG_DIE);     
+  signal (SIGABRT,   SIG_DIE);    
+  signal (SIGFPE,    SIG_DIE);     
+  signal (SIGSEGV,   SIG_DIE);    
+  signal (SIGTERM,   SIG_DIE);    
+  signal (SIGBUS,    SIG_DIE);     
+  signal (SIGTRAP,   SIG_DIE);    
+  signal (SIGXCPU,   SIG_DIE);    
+  signal (SIGXFSZ,   SIG_DIE);    
+  signal (SIGIOT,    SIG_DIE);     
+  signal (SIGHUP,    SIG_IGN);
+  signal (SIGINT,    SIG_DIE);
+  signal (SIGQUIT,   SIG_IGN);
+  signal (SIGPIPE,   SIG_PIPE);    
+  signal (SIGALRM,   SIG_IGN);    
+  signal (SIGUSR1,   SIG_STOP);    
+  signal (SIGUSR2,   SIG_MESSAGE);    
+  signal (SIGTSTP,   SIG_IGN);    
+  signal (SIGTTIN,   SIG_IGN);    
+  signal (SIGTTOU,   SIG_IGN);    
+  signal (SIGPROF,   SIG_IGN);    
+  signal (SIGURG,    SIG_IGN);     
+  signal (SIGVTALRM, SIG_IGN);  
+  signal (SIGIO,     SIG_IGN);      
+
+  /* signals which are not always defined */
+# ifdef SIGPOLL
+  signal (SIGPOLL,   SIG_IGN);    
+# endif
+# ifdef SIGPWR
+  signal (SIGPWR, SIG_DIE);     /* power failure (Sys V) */
+# endif
+# ifdef SIGWINCH
+  signal (SIGWINCH, SIG_IGN);   /* window resized (4.3BSD) */
+# endif
+# ifdef SIGSYS
+  signal (SIGSYS,    SIG_DIE);     
+# endif
+# ifdef SIGEMT
+ signal (SIGEMT,     SIG_DIE); 
+# endif
+# ifdef SIGSTKFLT
+  signal (SIGSTKFLT, SIG_DIE);  
+# endif
+# ifdef SIGINFO
+ signal (SIGINFO,    SIG_DIE); 
+# endif
+# ifdef SIGCLD
+  signal (SIGCLD,    SIG_DFL);     
+# endif
+# ifdef SIGLOST
+  signal (SIGLOST,   SIG_IGN); 
+# endif
+# ifdef SIGUNUSED
+  signal (SIGUNUSED, SIG_IGN); 
+# endif
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  if (file == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't choose configuration file\n");
+    Shutdown (1);
+  }    
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    if (file != (char *) NULL) free (file);
+    Shutdown (1);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+  free (file);
+
+  if ((N = get_argument (*argc, argv, "-restart"))) {
+    char pidfile[128];
+
+    remove_argument (N, argc, argv);
+    if (!ScanConfig (config, "global.pid", "%s",  0, pidfile)) {
+      fprintf (stderr, "pid file not defined: global.pid\n");
+      exit (1);
+    }
+    HalttoRestart (pidfile);
+  }
+
+  if ((*argc != 2) && (*argc != 1)) {
+    fprintf (stderr, "USAGE: elixir [list]\n");
+    fprintf (stderr, "       elixir [-kill]\n");
+    fprintf (stderr, "       elixir [-stop]\n");
+    fprintf (stderr, "       elixir [-status]\n");
+    Shutdown (1);
+  }
+  
+  /* special command-line options */
+  { 
+    char pidfile[128], msgfile[128];
+
+    if (!ScanConfig (config, "global.pid", "%s",  0, pidfile)) {
+      fprintf (stderr, "pid file not defined: global.pid\n");
+      exit (1);
+    }
+    
+    if (!ScanConfig (config, "global.msg", "%s",  0, msgfile)) {
+      fprintf (stderr, "msg file not defined: global.msg\n");
+      exit (1);
+    }
+    
+    if (!ScanConfig (config, "CONNECT", "%s",  0, CONNECT)) {
+      sprintf (CONNECT, "/usr/bin/rsh");
+    }
+    
+    if (get_argument (*argc, argv, "-kill"))   KillElixir (pidfile);
+    if (get_argument (*argc, argv, "-stop"))   HaltElixir (pidfile);
+    if (get_argument (*argc, argv, "-status")) StatusElixir (pidfile, msgfile);
+  }
+
+  return (config);
+
+}
+
+/*
+
+  SIGHUP             1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+  SIGINT             2        A      Interrupt from keyboard
+  SIGQUIT            3        C      Quit from keyboard
+  SIGILL             4        C      Illegal Instruction
+  SIGABRT            6        C      Abort signal from abort(3)
+  SIGFPE             8        C      Floating point exception
+  SIGKILL            9       AEF     Kill signal
+  SIGSEGV           11        C      Invalid memory reference
+  SIGPIPE           13        A      Broken pipe: write to pipe with no readers
+  SIGALRM           14        A      Timer signal from alarm(2)
+  SIGTERM           15        A      Termination signal
+  SIGUSR1        30,10,16     A      User-defined signal 1
+  SIGUSR2        31,12,17     A      User-defined signal 2
+  SIGCHLD        20,17,18     B      Child stopped or terminated
+  SIGCONT        19,18,25            Continue if stopped
+  SIGSTOP        17,19,23    DEF     Stop process
+  SIGTSTP        18,20,24     D      Stop typed at tty
+  SIGTTIN        21,21,26     D      tty input for background process
+  SIGTTOU        22,22,27     D      tty output for background process
+  SIGBUS         10,7,10      C      Bus error (bad memory access)
+  SIGPOLL                     A      Pollable event (Sys V). Synonym of SIGIO
+  SIGPROF        27,27,29     A      Profiling timer expired
+  SIGSYS         12,-,12      C      Bad argument to routine (SVID)
+  SIGTRAP           5         C      Trace/breakpoint trap
+  SIGURG         16,23,21     B      Urgent condition on socket (4.2 BSD)
+  SIGVTALRM      26,26,28     A      Virtual alarm clock (4.2 BSD)
+  SIGXCPU        24,24,30     C      CPU time limit exceeded (4.2 BSD)
+  SIGXFSZ        25,25,31     C      File size limit exceeded (4.2 BSD)
+  SIGIOT            6         C      IOT trap. A synonym for SIGABRT
+  SIGEMT          7,-,7
+  SIGSTKFLT       -,16,-      A      Stack fault on coprocessor
+  SIGIO          23,29,22     A      I/O now possible (4.2 BSD)
+  SIGCLD          -,-,18             A synonym for SIGCHLD
+  SIGPWR         29,30,19     A      Power failure (System V)
+  SIGINFO         29,-,-             A synonym for SIGPWR
+  SIGLOST         -,-,-       A      File lock lost
+  SIGWINCH       28,28,20     B      Window resize signal (4.3 BSD, Sun)
+  SIGUNUSED       -,31,-      A      Unused signal (will be SIGSYS)
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/ConfigPID.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/ConfigPID.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/ConfigPID.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "elixir.h"
+
+static char *PIDMaster = (char *) NULL;
+
+void ConfigPID (char *PIDFile) {
+
+  pid_t pid;
+  char *username, machine[256];
+  FILE *f;
+
+  f = fopen (PIDFile, "r");
+  if (f == (FILE *) NULL) { 
+
+    pid = getpid ();
+    username = getenv ("USER");
+    if (username == (char *) NULL) {
+      fprintf (stderr, "error getting username\n");
+      exit (2);
+    }
+    bzero (machine, 256);
+    if (gethostname (machine, 256)) {
+      fprintf (stderr, "error getting hostname\n");
+      exit (2);
+    }
+
+    f = fopen (PIDFile, "w");
+    if (f == (FILE *) NULL) { 
+      fprintf (stderr, "can't write to PID file %s\n", PIDFile);
+      exit (2);
+    }
+
+    fprintf (f, "PID:     %d\n", pid);
+    fprintf (f, "USER:    %-s\n", username);
+    fprintf (f, "MACHINE: %-s\n", machine);
+    fclose (f);
+
+    PIDMaster = PIDFile;
+    return; 
+  }
+
+  ALLOCATE (username, char, 256);
+  fscanf (f, "%*s %d", &pid);
+  fscanf (f, "%*s %s", username);
+  fscanf (f, "%*s %s", machine);
+  fclose (f);
+
+  fprintf (stderr, "elixir is apparently running:\n\n");
+  fprintf (stderr, "  machine: %s\n", machine);
+  fprintf (stderr, "  user: %s\n", username);
+  fprintf (stderr, "  PID: %d\n", pid);
+  fprintf (stderr, "  remove %s if elixir has died unexpectedly\n", PIDFile);
+  Shutdown (1);
+}
+
+void RemovePID () {
+  
+  if (PIDMaster == (char *) NULL) 
+    return;
+  
+  if (unlink (PIDMaster)) {
+    fprintf (stderr, "error deleting PID File %s\n", PIDMaster);
+  }   
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/DefineProcesses.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/DefineProcesses.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/DefineProcesses.c	(revision 16632)
@@ -0,0 +1,135 @@
+# include "elixir.h"
+
+Process **DefineProcesses (Process *global, int *nprocess, char *config) {
+
+  int i, j;
+  char procname[256], entry[256], field[256];
+  Process **process;
+  int Nprocess, NPROCESS;
+  double timeout;
+
+  global[0].success = InitQueue ();
+  global[0].failure = InitQueue ();
+  
+  ALLOCATE (global[0].argv, char *, 8);
+  ALLOCATE (global[0].argv[0], char, 256);
+  ALLOCATE (global[0].argv[1], char, 256);
+  ALLOCATE (global[0].argv[2], char, 256);
+  ALLOCATE (global[0].argv[3], char, 256);
+  ALLOCATE (global[0].argv[4], char, 256);
+  ALLOCATE (global[0].argv[5], char, 256);
+  ALLOCATE (global[0].argv[6], char, 256);
+  ALLOCATE (global[0].argv[7], char, 256);
+  
+  GetConfig (config, "global.Nargs",   "%d",  0, &global[0].argc);
+  GetConfig (config, "global.success", "%s",  0, global[0].argv[0]);
+  GetConfig (config, "global.failure", "%s",  0, global[0].argv[1]);
+  GetConfig (config, "global.pending", "%s",  0, global[0].argv[2]);
+  GetConfig (config, "global.logfile", "%s",  0, global[0].argv[3]);
+  GetConfig (config, "global.photcode",  "%s",  0, global[0].argv[4]);
+  GetConfig (config, "global.msg",     "%s",  0, global[0].argv[5]);
+  GetConfig (config, "global.end",     "%s",  0, global[0].argv[6]);
+  GetConfig (config, "global.pid",     "%s",  0, global[0].argv[7]);
+
+  ScanConfig (config, "global.timeout", "%lf", 0, &timeout);
+  if (timeout < 1) {
+    fprintf (stderr, "global.timeout is absurd: %f\n", timeout);
+    Shutdown (1);
+  }
+  if (timeout < 100) {
+    fprintf (stderr, "**** global.timeout is very short (%f) ****\n", timeout);
+  }
+  RegisterTimeout (timeout);
+  
+  Nprocess = 0;
+  NPROCESS = 5;
+  ALLOCATE (process, Process *, NPROCESS);
+
+  /* find all entries in config file labeled 'process' */
+  for (i = 1; ScanConfig (config, "process", "%s", i, procname); i++) {
+    process[Nprocess] = ConfigProcess (config, procname);
+    Nprocess ++;
+    if (Nprocess == NPROCESS) {
+      NPROCESS += 5;
+      REALLOCATE (process, Process *, NPROCESS);
+    }
+  }
+  if (Nprocess == 0) {
+    fprintf (stderr, "no processes defined in config file\n");
+    Shutdown (1);
+  }
+
+  /* make links between processes */
+  for (i = 0; i < Nprocess; i++) {
+    /* connect this process success queue */
+    sprintf (field, "%s.success", process[i][0].name);
+    GetConfig (config, field, "%s", 0, entry);
+    if (!strcasecmp (entry, "global")) {
+      process[i][0].success = global[0].success;
+      goto stage1;
+    }
+    for (j = 0; j < Nprocess; j++) {
+      if (!strcasecmp (entry, process[j][0].name)) {
+	if (i == j) {
+	  fprintf (stderr, "ERROR: can't connect a process to itself: %s\n", process[i][0].name);
+	  Shutdown (1);
+	}
+	process[i][0].success = process[j][0].pending;
+	goto stage1;
+      }
+    }
+    fprintf (stderr, "ERROR: can't connect process %s to target %s\n", process[i][0].name, entry);
+    Shutdown (1);
+    
+  stage1:
+    /* connect this process failure queue */
+    sprintf (field, "%s.failure", process[i][0].name);
+    GetConfig (config, field, "%s", 0, entry);
+    if (!strcasecmp (entry, "global")) {
+      process[i][0].failure = global[0].failure;
+      goto stage2;
+    }
+    for (j = 0; j < Nprocess; j++) {
+      if (!strcasecmp (entry, process[j][0].name)) {
+	if (i == j) {
+	  fprintf (stderr, "ERROR: can't connect a process to itself: %s\n", process[i][0].name);
+	  Shutdown (1);
+	}
+	process[i][0].failure = process[j][0].pending;
+	goto stage2;
+      }
+    }
+    fprintf (stderr, "ERROR: can't connect process %s to target %s\n", process[i][0].name, entry);
+    Shutdown (1);
+    
+  stage2:
+    continue;
+  }
+
+  /* link global process to first process */
+  for (j = 0; j < Nprocess; j++) {
+    if (!strcasecmp (global[0].argv[2], process[j][0].name)) {
+      global[0].pending = process[j][0].pending;
+      goto stage3;
+    }
+  }
+  fprintf (stderr, "ERROR: can't connect global process to target %s\n", global[0].argv[2]);
+  Shutdown (1);
+ 
+stage3:
+  *nprocess = Nprocess;
+  return (process);
+
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find required field %s\n", field);
+    Shutdown (1);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/DumpStatus.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/DumpStatus.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/DumpStatus.c	(revision 16632)
@@ -0,0 +1,78 @@
+# include "elixir.h"
+
+int DumpStatus (char *filename) {
+
+  FILE *f;
+  int i, state, total, mode;
+  Process *global, **process;
+  int Nprocess, Nobject, Dynamic;
+
+  process = GetProcessInfo (&global, &Nprocess, &Nobject);
+  Dynamic = GetDynamicState ();
+
+  if (filename == (char *) NULL) {
+    system ("tput clear");
+    f = stderr;
+  } else {
+    /* lock file */
+    f = fsetlockfile (filename, 0.1, LCK_XCLD, &state);
+    if (f == NULL) return (2);
+    fseek (f, 0, SEEK_END);
+  }  
+  
+  fprintf (f, "processes status:\n");
+  fprintf (f, "            name   pending  success  failure  total\n");
+  fprintf (f, "----------------------------------------------------------------\n");
+  total = global[0].pending[0].Nobject + global[0].success[0].Nobject + global[0].failure[0].Nobject;
+  fprintf (f, "%16s    %6d   %6d   %6d   %4d\n", "global", 
+	   global[0].pending[0].Nobject, global[0].success[0].Nobject, global[0].failure[0].Nobject, total); 
+  for (i = 0; i < Nprocess; i++) {
+    fprintf (f, "%16s    %6d\n", process[i][0].name, process[i][0].pending[0].Nobject); 
+  }
+  fprintf (f, "\n");
+
+  DumpMachineStatus (f);
+
+  fprintf (f, "\n");
+  fprintf (f, "objects loaded so far: %d\n\n", Nobject);
+  if (Dynamic) {
+    fprintf (f, "accepting input from FIFO\n");
+  } else {
+    fprintf (f, "NOT accepting input from FIFO\n");
+  }    
+  
+  if (f != stderr) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    chmod (filename, mode);
+    fclearlockfile (filename, f, LCK_XCLD, &state);
+  }
+  return (TRUE);
+}
+
+/*
+
+processes status:
+            name  pending  success  failure  total
+----------------------------------------------------------------
+          global        1        0        4      5
+           mkdir        1
+         flatten        0
+          dophot        0
+         imclean        0
+          gastro        0
+         addstar        0
+          rmfile        5
+
+machine status:
+          name  process  status
+----------------------------------------------------------------
+         kiawe  rmfile   1
+         kiawe  addstar  9
+          milo  addstar  1
+
+objects loaded so far: 13
+
+accepting input from FIFO
+
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/FifoOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/FifoOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/FifoOps.c	(revision 16632)
@@ -0,0 +1,96 @@
+# include "elixir.h"
+
+int InitFifo (Fifo *fifo, int Nalloc, int Nextra) {
+
+  if (Nextra >= Nalloc) {
+    fprintf (stderr, "absurd fifo definition\n");
+    return (FALSE);
+  }
+
+  fifo[0].Nalloc = Nalloc;
+  fifo[0].Nextra = Nextra;
+  fifo[0].Nmaxread = Nalloc - Nextra;
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  ALLOCATE (fifo[0].buffer, char, fifo[0].Nalloc);
+
+  return (TRUE);
+
+}
+
+int FlushFifo (Fifo *fifo) {
+
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  return (TRUE);
+
+}
+
+/* after a shift, we can always read 
+   fifo[0].Nmaxread 
+   bytes into 
+   &fifo[0].buffer[Nbuffer] 
+   which is the byte after then end of existing data */
+
+int ShiftFifo (Fifo *fifo) {
+
+  int Nextra, Nshift;
+
+  Nextra = fifo[0].Nextra;
+  Nshift = fifo[0].Nbuffer - fifo[0].Nextra;
+  if (Nshift <= 0) return (TRUE);
+
+  memcpy (fifo[0].buffer, &fifo[0].buffer[Nshift], Nextra);
+  fifo[0].Nbuffer = Nextra;
+  fifo[0].Nlast = Nextra;
+
+  return (TRUE);
+}
+
+/* like a standard read, ReadtoFifo returns Nbytes read,
+   -1 for sock busy, or 0 for sock closed */
+
+int ReadtoFifo (Fifo *fifo, int sock) {
+
+  int Nread;
+  int Nbuffer, Nmaxread;
+
+  if (sock == 0) {
+    fprintf (stderr, "error with socket?\n");
+    return (0);
+  }
+
+  fifo[0].Nlast = fifo[0].Nbuffer;
+
+  Nbuffer = fifo[0].Nbuffer;
+  Nmaxread = fifo[0].Nmaxread;
+  Nread = read (sock, &fifo[0].buffer[Nbuffer], Nmaxread);
+
+  if (Nread > 0) fifo[0].Nbuffer += Nread;
+
+  if (Nread == -1) {
+    /* check for possible errors.  anything other than EAGAIN
+       is bad and should indicate the connection is down */
+    switch (errno) {
+    case EAGAIN:
+    case EIO:
+      Nread = -1;
+      break;
+    default:
+      fprintf (stderr, "read error: %d\n", errno);
+      Nread = 0;
+      break;
+    }
+  }
+
+  return (Nread);
+}
+
+void FreeFifo (Fifo *fifo) {
+
+  if (fifo[0].buffer != (char *) NULL) {
+    free (fifo[0].buffer);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/InitProcess.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/InitProcess.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/InitProcess.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "elixir.h"
+
+Process *InitProcess (char *name, Queue *pending, Queue *failure, int (*mkargs)()) {
+
+  Process *process;
+
+  ALLOCATE (process, Process, 1);
+
+  process[0].success = InitQueue ();
+  process[0].failure = failure;
+  process[0].pending = pending;
+
+  process[0].name    = strcreate (name);
+  /* process[0].mkarg   = mkargs; */
+
+  process[0].cluster = InitCluster ();
+
+  return (process);
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/LoadPending.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/LoadPending.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/LoadPending.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include "elixir.h"
+
+static struct timeval then = {0.0, 0.0};
+
+/* LoadPending returns the number of objects loaded from inlist
+   
+   state can be: 
+   0 - success
+   1 - file locked
+   2 - file has EOF flag
+   3 - error in input 
+*/
+
+int LoadPending (Process *global, char *filename, int *state, int *dynamic) {
+
+  int i, status, depend, Nobjects;
+  int lockstate, mode;
+  FILE *f;
+  char name[7][256], line[1024];
+  struct timeval now;
+  Object *object;
+
+  *state = 0;
+  Nobjects = 0;
+
+  /* we should only do this check every 1sec or so */
+  gettimeofday (&now, (void *) NULL);
+  if (DTIME (now, then) < 1.0) return (Nobjects);
+  then = now;
+
+  /* if dynamic, we must lock the file first, but not if not dynamic */
+  if (*dynamic) {
+    
+    /* check lockfile - don't remove list if locked */
+    f = fsetlockfile (filename, 1.0, LCK_XCLD, &lockstate);
+    if (f == NULL) { 
+      *state = 1;
+      return (Nobjects);
+    }
+  } else {
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      *state = 1;
+      return (Nobjects);
+    }
+  }
+
+  /* read lines, parse each line */
+  while (1) {
+    if (scan_line (f, line) == EOF) goto escape;
+
+    switch (global[0].argc) {
+    case 1:
+      status = sscanf (line, "%s", name[0]);
+      break;
+    case 2:
+      status = sscanf (line, "%s%s", name[0], name[1]);
+      break;
+    case 3:
+      status = sscanf (line, "%s%s%s", name[0], name[1], name[2]);
+      break;
+    case 4:
+      status = sscanf (line, "%s%s%s%s", name[0], name[1], name[2], name[3]);
+      break;
+    case 5:
+      status = sscanf (line, "%s%s%s%s%s", name[0], name[1], name[2], name[3], name[4]);
+      break;
+    case 6:
+      status = sscanf (line, "%s%s%s%s%s%s", name[0], name[1], name[2], name[3], name[4], name[5]);
+      break;
+    case 7:
+      status = sscanf (line, "%s%s%s%s%s%s%s", name[0], name[1], name[2], name[3], name[4], name[5], name[6]);
+      break;
+    default:
+      fprintf (stderr, "ERROR: unexpected number of entries per line in input file\n");
+      *state = 3;
+      goto escape;
+    }
+
+    if (status == 0) continue;  /* an empty or blank line */
+
+    if (!strcasecmp (name[0], "EOF")) {
+      /* dynamic -> static */
+      *state = 2;
+      goto escape;
+    }
+
+    /* silently ignore lines with the wrong number of args */
+    if (status != global[0].argc) continue;
+
+    ALLOCATE (object, Object, 1);
+    object[0].argc = status;
+    ALLOCATE (object[0].argv, char *, status);
+    for (i = 0; i < status; i++) {
+      object[0].argv[i] = strcreate (name[i]);
+    }
+    
+    /* convert the global.logfile description to a specific logfile for this object */
+    ParseLine (global[0].argv[3], object[0].argc, object[0].argv, &depend, &object[0].logfile);
+    object[0].status = 0;
+    object[0].timer.tv_sec = 0;
+    object[0].lastproc = (char *) NULL;
+    PutObject (global[0].pending, object);
+    Nobjects ++;
+  }
+
+  escape:
+  if (*dynamic) {
+    if (truncate (filename, 0)) {
+      fprintf (stderr, "failed to clear source %s (errno %d)\n", filename, errno);
+      Shutdown (1);
+    }
+
+    /* clean up fifo - set mode to 666, unlock */
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    chmod (filename, mode);
+    fclearlockfile (filename, f, LCK_XCLD, &lockstate);
+  } else {
+    fclose (f);
+  }
+
+  if ((*state == 2) && *dynamic) {
+    *dynamic = FALSE;
+  }
+  return (Nobjects);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/LogOpen.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/LogOpen.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/LogOpen.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "elixir.h"
+
+FILE *LogOpen (char *filename) {
+
+  FILE *f;
+  char *path;
+
+  f = fopen (filename, "a");
+
+  /* probably don't have needed directory */
+  if ((f == (FILE *) NULL) && (errno == ENOENT)) {
+    path = pathname (filename);
+    if (!mkdirhier (path, S_IRWXU | S_IRWXG | S_IRWXO)) {
+      f = fopen (filename, "a");
+    }
+  }
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "LogOpen could not open the log file %s, errno: %d\n", filename, errno);
+    f = stderr;
+  }
+
+  return (f);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/MachineOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/MachineOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/MachineOps.c	(revision 16632)
@@ -0,0 +1,484 @@
+# include "elixir.h"
+
+/* this is in libohana -> should be in ohana.h */
+char *getcwd_cfht (char *path, int size);
+
+static Cluster *fullpool = (Cluster *) NULL;
+static Cluster *idlepool = (Cluster *) NULL;
+static Cluster *downpool = (Cluster *) NULL;
+static char *ConfigFilename;
+
+/* put machine on top of cluster */
+void PushMachine (Machine *machine, Cluster *cluster) {
+
+  int i;
+
+  if (cluster[0].Nmachine == cluster[0].NMACHINE) {
+    cluster[0].NMACHINE += 5;
+    REALLOCATE (cluster[0].machine, Machine *, cluster[0].NMACHINE);
+  }
+  for (i = cluster[0].Nmachine; i > 0; i--) {
+    cluster[0].machine[i] = cluster[0].machine[i-1];
+  }
+  cluster[0].machine[0] = machine;
+  cluster[0].Nmachine ++;
+}
+
+/* put machine on bottom of cluster */
+void PutMachine (Machine *machine, Cluster *cluster) {
+
+  if (cluster[0].Nmachine == cluster[0].NMACHINE) {
+    cluster[0].NMACHINE += 5;
+    REALLOCATE (cluster[0].machine, Machine *, cluster[0].NMACHINE);
+  }
+  cluster[0].machine[cluster[0].Nmachine] = machine;
+  cluster[0].Nmachine ++;
+}
+
+/* Get a machine from top of cluster */
+Machine *GetMachine (Cluster *cluster) {
+
+  int i;
+  Machine *machine;
+
+  if (cluster[0].Nmachine == 0) return ((Machine *) NULL);
+
+  machine = cluster[0].machine[0];
+  cluster[0].Nmachine --;
+  for (i = 0; i < cluster[0].Nmachine; i++) {
+    cluster[0].machine[i] = cluster[0].machine[i+1];
+  }
+  return (machine);
+}
+
+void IdleMachine (Machine *machine) {
+
+  machine[0].status = IDLE;
+  machine[0].object = (Object *) NULL;
+  PutMachine (machine, idlepool);
+ 
+}
+
+void DownMachine (Machine *machine) {
+
+  machine[0].status = DOWN;
+  machine[0].object = (Object *) NULL;
+  gettimeofday (&machine[0].start, (void *) NULL);
+  gettimeofday (&machine[0].timer, (void *) NULL);
+  machine[0].timer.tv_sec += 5;
+  PutMachine (machine, downpool);
+ 
+}
+
+# define NRETRIES 50
+int TestMachine (Machine *machine) {
+
+  int i, status;
+  char buffer[64];
+
+  FlushFifo (&machine[0].fifo);
+
+  if ((machine[0].wsock == 0) || (machine[0].rsock == 0)) return (FALSE);
+
+  /* writes are non-blocking.  check for EPIPE in case pipe is closed */
+  sprintf (buffer, "echo CONNECTION TEST\n");
+  status = write (machine[0].wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket unexpectedly closed in test\n");
+    CloseMachine (machine);
+    return (FALSE);
+  }
+
+  status = -1;
+  for (i = 0; (i < NRETRIES) && (status == -1); i++) {
+    status = SockScan ("CONNECTION TEST", &machine[0].fifo, machine[0].rsock);
+    if (status == 0) {
+      fprintf (stderr, "socket unexpectedly closed in test\n");
+      CloseMachine (machine);
+      return (FALSE);
+    }
+  }
+  if (i == NRETRIES) {
+    fprintf (stderr, "no response from machine, shutting it down\n");
+    CloseMachine (machine);
+    return (FALSE);
+  }
+  FlushFifo (&machine[0].fifo);
+  return (TRUE);
+}
+
+Machine *GrabMachine () {
+
+  Machine *machine;
+
+  machine = GetMachine (idlepool);
+  if (machine == (Machine *) NULL) return (machine);
+
+  if (!TestMachine (machine)) {
+    DownMachine (machine);
+    return ((Machine *) NULL);
+  }
+  return (machine);
+}
+
+Cluster *InitCluster () {
+
+  Cluster *cluster;
+
+  ALLOCATE (cluster, Cluster, 1);
+  cluster[0].NMACHINE = 5;
+  cluster[0].Nmachine = 0;
+  ALLOCATE (cluster[0].machine, Machine *, cluster[0].NMACHINE);
+  
+  return (cluster);
+
+}
+
+void InitMachines (char *config) {
+
+  int i, Nm, fd, Nout, status;
+  char name[256];
+  Machine *machine;
+  char *cwd;
+
+  fullpool = InitCluster ();
+  idlepool = InitCluster ();
+  downpool = InitCluster ();
+
+  /* processes run on these machines need to have access to the
+     exact config file used by elixir.  Therefore, we write the 
+     config file to a unique filename in this directory and pass 
+     that name to the processes which start machines.  it is 
+     crucial that the cwd be visible on the other machines, and have
+     the same path name.  when we exit (Shutdown(n)), we will delete
+     this file (but not before!). */
+  
+  /* get cwd and create config file here */
+  if ((cwd = getcwd_cfht (NULL, 1024)) == NULL) {
+    fprintf (stderr, "error getting cwd\n");
+    Shutdown (1);
+  }
+  sprintf (name, "%s/elixir.XXXXXX", cwd);
+  if ((fd = mkstemp (name)) == -1) {
+    fprintf (stderr, "can't store current config in cwd\n");
+    Shutdown (1);
+  }
+  Nout = write (fd, config, strlen (config));
+  if (Nout != strlen (config)) {
+    fprintf (stderr, "can't store current config in cwd\n");
+    Shutdown (1);
+  }
+  status = close (fd);
+  if (status == -1) {
+    fprintf (stderr, "can't store current config in cwd\n");
+    Shutdown (1);
+  }
+  ConfigFilename = strcreate (name);
+
+  /* create connection to each of the machines */
+  Nm = 0;
+  for (i = 1; ScanConfig (config, "MACHINE", "%s", i, name); i++) {
+    ALLOCATE (machine, Machine, 1);
+    machine[0].hostname = strcreate (name);
+    InitFifo (&machine[0].fifo, 0x4000, 0x1000);
+    if (ConnectMachine (machine)) {
+      IdleMachine (machine);
+    } else {
+      DownMachine (machine);
+    }
+    PutMachine (machine, fullpool);
+    Nm ++;
+  }
+  if (Nm == 0) {
+    fprintf (stderr, "no available machines, exiting\n");
+    Shutdown (1);
+  }
+      
+}
+
+int ConnectMachine (Machine *machine) {
+
+  int rsock, wsock, pid;
+  char line[256];
+
+  pid = rconnect (machine[0].hostname, CONNECT, &rsock, &wsock);
+  if (pid) {
+    machine[0].rsock = rsock;
+    machine[0].wsock = wsock;
+    machine[0].pid   = pid;
+    /* we can set up the shell here */
+    sprintf (line, "setenv PTOLEMY %s\n", ConfigFilename);
+    write (wsock, line, strlen (line));
+    sprintf (line, "umask 002\n");
+    write (wsock, line, strlen (line));
+    return (TRUE);
+  } else {
+    fprintf (stderr, "can't make connection to %s, skipping for now\n", machine[0].hostname);
+    machine[0].rsock = 0;
+    machine[0].wsock = 0;
+    machine[0].pid   = 0;
+    return (FALSE);
+  }
+}
+
+/* machine which are claimed as down need to be restarted.  
+   first, check that they really are down, then restart as needed */
+void RestartMachines () {
+  
+  int i;
+  Machine *machine;
+  double dtime;
+  struct timeval now;
+
+  for (i = 0; i < downpool[0].Nmachine; i++) {
+    machine = GetMachine (downpool);
+    if (machine == (Machine *) NULL) return;
+
+    /* we only try to reconnect if timer is expired */
+    gettimeofday (&now, (void *) NULL);
+    dtime = DTIME (machine[0].timer, now);
+    if (dtime > 0) {
+      PutMachine (machine, downpool);
+      continue;
+    }
+
+    fprintf (stderr, "restarting machine %s\n", machine[0].hostname);
+    if (TestMachine (machine)) {
+      /* machine is still alive, return to idlepool */
+      fprintf (stderr, "%s is alive\n", machine[0].hostname);
+      IdleMachine (machine);
+      continue;
+    }
+
+    if (ConnectMachine (machine)) {
+      fprintf (stderr, "connection to %s successfully restarted\n", machine[0].hostname);
+      IdleMachine (machine);
+    } else {
+      /* advance dtime so restarts happen later and later */
+      dtime = DTIME (machine[0].timer, machine[0].start);
+      dtime = dtime * 2;
+      dtime = MIN (600, dtime);
+      gettimeofday (&machine[0].start, (void *) NULL);
+      gettimeofday (&machine[0].timer, (void *) NULL);
+      machine[0].timer.tv_sec += dtime;
+      PutMachine (machine, downpool);
+    }
+  }
+
+}
+
+void Shutdown (int status) {
+
+  int i;
+
+  if (unlink (ConfigFilename) == -1) {
+    fprintf (stderr, "trouble deleting config file: %s\n", ConfigFilename);
+  }
+
+  RemovePID ();
+
+  if (fullpool == (Cluster *) NULL) exit (status);
+    
+  for (i = 0; i < fullpool[0].Nmachine; i++) {
+    CloseMachine (fullpool[0].machine[i]);
+  }
+
+  exit (status);
+
+}
+
+void Restart (char **argv) {
+
+  int i;
+
+  if (unlink (ConfigFilename) == -1) {
+    fprintf (stderr, "trouble deleting config file: %s\n", ConfigFilename);
+  }
+
+  RemovePID ();
+
+  if (fullpool == (Cluster *) NULL) execvp (argv[0], argv);
+    
+  for (i = 0; i < fullpool[0].Nmachine; i++) {
+    CloseMachine (fullpool[0].machine[i]);
+  }
+
+  execvp (argv[0], argv);
+}
+
+
+int InitMsgFile (char *file) {
+  
+  char line[256];
+  int status;
+  struct stat filestat;
+
+  if (stat (file, &filestat) == -1) return (TRUE);
+  sprintf (line, "mv -f %s %s~", file, file);
+  status = system (line);
+  return (status);
+}
+
+void CloseMachine (Machine *machine) {
+
+  char buffer[128];
+
+  sprintf (buffer, "exit\n");
+  write (machine[0].wsock, buffer, strlen(buffer));
+  close (machine[0].wsock);
+  close (machine[0].rsock);
+  fprintf (stderr, "shutdown machine %s, pid %d\n", machine[0].hostname, machine[0].pid); 
+
+}
+
+void DumpMachineStatus (FILE *f) {
+  
+  int i;
+
+  if (fullpool == (Cluster *) NULL) return;
+
+  fprintf (f, "machine status:\n");
+  fprintf (f, "          name  process  status\n");
+  fprintf (f, "----------------------------------------------------------------\n");
+  for (i = 0; i < fullpool[0].Nmachine; i++) {
+    if (fullpool[0].machine[i][0].object == (Object *) NULL) {
+      fprintf (f, "%14s %8s      %2d\n", 
+	       fullpool[0].machine[i][0].hostname,
+	       "(none)",
+	       fullpool[0].machine[i][0].status);
+      
+    } else {      
+      fprintf (f, "%14s %8s      %2d\n", 
+	       fullpool[0].machine[i][0].hostname,
+	       fullpool[0].machine[i][0].object[0].lastproc,
+	       fullpool[0].machine[i][0].status);
+    }
+
+  }
+
+}
+
+static int Nprocs, Nmachine;
+static ProcessTimers *proctimers;
+
+/* this must be called after machines have been loaded, registered */
+void InitProcessTimers (Process **process, int Nprocess) {
+  int i, j;
+
+  Nmachine = fullpool[0].Nmachine;
+  Nprocs = Nprocess;
+  ALLOCATE (proctimers, ProcessTimers, Nmachine);
+
+  for (i = 0; i < Nmachine; i++) {
+    ALLOCATE (proctimers[i].timer,   struct timeval, Nprocs);
+    ALLOCATE (proctimers[i].timesum, double,         Nprocs);
+    ALLOCATE (proctimers[i].Njobs,   int,            Nprocs);
+    ALLOCATE (proctimers[i].active,  int,            Nprocs);
+    ALLOCATE (proctimers[i].process, Process *,      Nprocs);
+    
+    for (j = 0; j < Nprocess; j++) {
+      proctimers[i].timer[j].tv_sec = 0;
+      proctimers[i].timer[j].tv_usec = 0;
+      proctimers[i].timesum[j] = 0;
+      proctimers[i].Njobs[j] = 0;
+      proctimers[i].active[j] = FALSE;
+      proctimers[i].process[j] = process[j];
+    }
+
+    proctimers[i].machine = fullpool[0].machine[i];
+
+  }
+  
+}
+
+void StartProcessTimer (Process *process, Machine *machine) {
+  
+  int i, j;
+
+  /* identify the machine */
+  for (i = 0; i < Nmachine; i++) {
+    if (proctimers[i].machine == machine) {
+      for (j = 0; j < Nprocs; j++) {
+	if (proctimers[i].process[j] == process) {
+	  gettimeofday (&proctimers[i].timer[j], (void *) NULL);
+	  proctimers[i].active[j] = TRUE;
+	  return;
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "can't find this machine, process combination!\n");
+  fprintf (stderr, "machine: %p process: %p\n", machine, process);
+  return;
+}
+
+void StopProcessTimer (Machine *machine) {
+  
+  int i, j;
+  struct timeval stop;
+  double dtime;
+
+  /* identify the machine */
+  for (i = 0; i < Nmachine; i++) {
+    if (proctimers[i].machine == machine) {
+      for (j = 0; j < Nprocs; j++) {
+	if (proctimers[i].active[j]) {
+ 	  gettimeofday (&stop, (void *) NULL);
+	  dtime = DTIME (stop, proctimers[i].timer[j]);
+	  proctimers[i].timesum[j] += dtime;
+	  proctimers[i].active[j] = FALSE;
+	  proctimers[i].Njobs[j] ++;
+	  return;
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "can't find an active process for this machine!\n");
+  fprintf (stderr, "machine: %p\n", machine);
+
+}
+
+int DumpProcessTimes (char *filename) {
+  
+  int i, j, state, mode;
+  FILE *f;
+  double dt;
+
+  if (filename == (char *) NULL) {
+    system ("tput clear");
+    f = stderr;
+  } else {
+    /* check lockfile */
+    f = fsetlockfile (filename, 0.1, LCK_XCLD, &state);
+    if (f == NULL) return (2);
+    fseek (f, 0, SEEK_END);
+  }  
+
+  fprintf (f, "               .");
+  for (j = 0; j < Nprocs; j++) {
+    fprintf (f, "   %-14s", proctimers[0].process[j][0].name);
+  }
+  fprintf (f, "\n");
+  for (i = 0; i < Nmachine; i++) {
+    fprintf (f, "%16s ", proctimers[i].machine[0].hostname);
+    for (j = 0; j < Nprocs; j++) {
+      if (proctimers[i].Njobs[j] > 0) {
+	dt = proctimers[i].timesum[j] / proctimers[i].Njobs[j];
+      } else {
+	dt = 0;
+      }
+      fprintf (f, "%7.3f %-6d   ", dt, proctimers[i].Njobs[j]);
+    }
+    fprintf (f, "\n");
+  }
+
+  if (f != stderr) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    chmod (filename, mode);
+    fclearlockfile (filename, f, LCK_XCLD, &state);
+  }
+  return (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/MsgOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/MsgOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/MsgOps.c	(revision 16632)
@@ -0,0 +1,114 @@
+# include "elixir.h"
+
+int WaitMsg (char *fifo, char **message, double maxdelay) {
+
+  int status, Nsleep;
+  struct timeval now, then;
+  double dtime;
+  struct stat filestats;
+
+  /* maxdelay is the longest we will wait if the file is locked.  
+     if the file doesn't exist, or is empty, skip it */
+  /* limit our reads to only 10 tries, waiting for a little while in between */
+  Nsleep = 100000 * maxdelay;
+
+  status = stat (fifo, &filestats);
+  if (status == -1) return (0);
+  if (filestats.st_size == 0) return (0);
+
+  gettimeofday (&then, (void *) NULL);
+  while (TRUE) {
+    status = ReadMsg (fifo, message);
+    switch (status) {
+    case 1:
+      return (1);
+    default:
+      gettimeofday (&now, (void *) NULL);
+      dtime = DTIME (now, then);
+      if (dtime > maxdelay) return (0);
+    }
+    usleep (Nsleep);
+  }
+}
+
+int ReadMsg (char *fifo, char **message) {
+
+  int nbytes, Nbytes, NBYTES;
+  char *buffer;
+  int state, mode;
+  FILE *f;
+
+  /* check lockfile */
+  f = fsetlockfile (fifo, 0.1, LCK_XCLD, &state);
+  if (f == NULL) return (2);
+  
+  /* if file is empty, return 0 */
+  if (state == LCK_EMPTY) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    chmod (fifo, mode);
+    fclearlockfile (fifo, f, LCK_XCLD, &state);
+    return (0);
+  }  
+  
+  /* read data from file */
+  Nbytes = 0;
+  NBYTES = 0x1000;
+  ALLOCATE (buffer, char, NBYTES);
+  while (TRUE) {
+    nbytes = fread (&buffer[Nbytes], 1, 0x1000, f);
+    if (nbytes < 0) { 
+      fprintf (stderr, "error in ReadMsg -- got -1 bytes\n");
+      exit (0);
+    }
+    if (nbytes == 0) break;
+    Nbytes += nbytes;
+    NBYTES += 0x1000;
+    REALLOCATE (buffer, char, NBYTES);
+  }
+  buffer[Nbytes] = 0;
+  
+  /* file will remain until unlocked and fclosed below, 
+     but cannot be written to because it is locked */
+  if (truncate (fifo, 0)) {
+    fprintf (stderr, "failed to clear fifo file %s (errno: %d)\n", fifo, errno);
+    Shutdown (1);
+  }
+  
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (fifo, mode);
+  fclearlockfile (fifo, f, LCK_XCLD, &state);
+  
+  if (Nbytes == 0) {
+    free (buffer);
+    return (0);
+  }
+
+  *message = buffer;
+  return (1);
+
+}
+
+int WriteMsg (char *fifo, char *message) {
+
+  int state, mode;
+  FILE *f;
+
+  /* check lockfile */
+  f = fsetlockfile (fifo, 0.1, LCK_XCLD, &state);
+  if (f == NULL) return (2);
+
+  /* write message to end of file */
+  fseek (f, 0, SEEK_END);
+  fprintf (f, "%s\n", message);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (fifo, mode);
+  fclearlockfile (fifo, f, LCK_XCLD, &state);
+  return (1);
+}
+
+/*  possible return states:
+    0 - no message (fifo file empty or non-existent) 
+    1 - message received
+    2 - busy (fifo file locked)
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/Photcodes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/Photcodes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/Photcodes.c	(revision 16632)
@@ -0,0 +1,256 @@
+# include "elixir.h"
+
+char *GetPhotcode (char *file) {
+
+  char *code;
+  Header header;
+  char detector[80], filter[80];
+  int i, imageid;
+
+  /* read in image header, open image data region */
+  if (!gfits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+
+  /** WARNING: this should use the abstracted keyword names **/
+  gfits_scan (&header, "DETECTOR", "%s", 1, detector);
+  gfits_scan (&header, "FILTER",   "%s", 1, filter);
+  gfits_scan (&header, "IMAGEID",  "%d", 1, &imageid);
+
+  gfits_free_header (&header);
+
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);
+  sprintf (code, "%s.%s.%02d", detector, filter, imageid);
+  return (code);
+
+}
+
+/** WARNING: this is pretty weak **/
+char *GetPhotcodeMef (char *file) {
+
+  char *code;
+  Header header;
+  char detector[80], filter[80];
+  int i, imageid;
+  char *filename, *p;
+
+  /* file contains file and extend number */
+  ALLOCATE (filename, char, strlen(file) + 1);
+  
+  p = file;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (file, "%s %d", filename, &imageid);
+
+  /* read in image header, open image data region */
+  if (!gfits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+  free (filename);
+
+  gfits_scan (&header, "DETECTOR", "%s", 1, detector);
+  gfits_scan (&header, "FILTER",   "%s", 1, filter);
+  gfits_free_header (&header);
+
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);  sprintf (code, "%s.%s.%02d", detector, filter, imageid);
+  return (code);
+
+}
+
+char *BuildCode (char *line) {
+
+  char *code, *p;
+  Header header;
+  char fullname[256], detector[80], filter[80];
+  char name[256], path[256], ccd[80], mode[80];
+  int i;
+
+  p = line;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (line, "%s %s %s %s", path, name, ccd, mode);
+
+  if (!strcasecmp (mode, "MEF")) {
+    sprintf (fullname, "%s/%s.fits", path, name);
+  } else {
+    sprintf (fullname, "%s/%s/%s%s.fits", path, name, name, ccd);
+  }
+
+  if (!gfits_read_header (fullname, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", fullname);
+    exit(0);
+  }
+  gfits_scan (&header, "DETECTOR", "%s", 1, detector);
+  gfits_scan (&header, "FILTER",   "%s", 1, filter);
+  gfits_free_header (&header);
+  
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);
+  sprintf (code, "%s.%s.%s", detector, filter, ccd);
+  return (code);
+
+}
+
+char *BuildName (char *line) {
+
+  char *fullname;
+  char name[256], path[256], ccd[80], mode[80];
+  char *p;
+
+  ALLOCATE (fullname, char, 256);
+
+  p = line;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (line, "%s %s %s %s", path, name, ccd, mode);
+
+  if (!strcasecmp (mode, "MEF")) {
+    sprintf (fullname, "%s/%s.fits", path, name);
+  } else {
+    sprintf (fullname, "%s/%s/%s%s.fits", path, name, name, ccd);
+  }
+
+  return (fullname);
+
+}
+
+char *GetPhotcodeExt (char *file) {
+
+  char *code;
+  Header header;
+  char detector[80], filter[80];
+  int i, imageid, extend;
+  char *filename, *p;
+
+  /* file contains file and extend number */
+  ALLOCATE (filename, char, strlen(file) + 1);
+  
+  p = file;
+  while ((p = strchr (p, ',')) != (char *) NULL) { *p = ' '; }
+  sscanf (file, "%s %d", filename, &extend);
+
+  /* read in image header, open image data region */
+  if (!gfits_read_Xheader (filename, &header, extend)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+  free (filename);
+
+  gfits_scan (&header, "DETECTOR", "%s", 1, detector);
+  gfits_scan (&header, "FILTER",   "%s", 1, filter);
+  gfits_scan (&header, "IMAGEID",  "%d", 1, &imageid);
+  gfits_free_header (&header);
+
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(filter); i++) { filter[i] = toupper (filter[i]); }
+
+  ALLOCATE (code, char, 256);
+  sprintf (code, "%s.%s.%02d", detector, filter, imageid);
+  return (code);
+
+}
+
+/* given path/filename.ext return filename */
+char *RootFilename (char *file) {
+
+  int Nbyte;
+  char *root, *p1, *p2;
+
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) p1 = file;
+
+  p2 = strrchr (file, '.');
+  if (p2 == (char *) NULL) p2 = p1 + strlen(p1);
+  Nbyte = p2-p1;
+
+  ALLOCATE (root, char, Nbyte + 1);
+  strncpy (root, p1, Nbyte);
+  root[Nbyte] = 0;
+  
+  return (root);
+
+}  
+
+/* given: path/filename
+   return: path or ./ if none */
+char *PathFilename (char *file) {
+
+  int Nbyte;
+  char *path, *p1;
+
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) {
+    ALLOCATE (p1, char, 2);
+    strcpy (p1, ".");
+    return (p1);
+  }
+
+  Nbyte = p1-file;
+  ALLOCATE (path, char, Nbyte + 1);
+  strncpy (path, file, Nbyte);
+  path[Nbyte] = 0;
+  
+  return (path);
+
+}  
+
+/* given: A/B/D/filename
+   return: D or ./ if none 
+   if /filename, return '/' 
+   if filename, return ./
+*/
+char *BaseFilename (char *file) {
+
+  int Nbyte;
+  char *path, *p1, *p2;
+
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) {
+    ALLOCATE (p1, char, 2);
+    strcpy (p1, ".");
+    return (p1);
+  }
+  if (p1 == file) {
+    ALLOCATE (p1, char, 2);
+    strcpy (p1, "/");
+    return (p1);
+  }
+
+  p2 = p1 - 1;
+  while ((p2 > file) && (*p2 != '/')) p2--;
+  if (p2 != file) {
+    p2 ++;
+  }
+
+  Nbyte = (p1 - p2);
+  ALLOCATE (path, char, Nbyte + 1);
+  strncpy (path, p2, Nbyte);
+  path[Nbyte] = 0;
+  
+  return (path);
+
+}  
+
+
+/*
+
+There are two methods to implement the Photcode determination for MEF files. 
+The difference is in whether the IMAGEID is used to refer to the ccd, or the EXTNUM.
+Originally, EXTNUM was used, which meant we needed to determine the IMAGEID for a given EXTNUM.
+The old implementation of PhotCodeMef returned the photcode based on the input MEF filename
+and the EXTNUM.  This is now maintained as PhotCodeExt, but not used in elixir.
+
+As of 13/2/00, we've converted to only using the IMAGEID.  this means that PhotCodeMef returns 
+the photcode, based on the MEF filename and the IMAGEID.  To go along with this change, the 
+function flatten.mef operates on the given IMAGEID not EXTNUM as well.                             
+
+*/
+
+
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/ProcessOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/ProcessOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/ProcessOps.c	(revision 16632)
@@ -0,0 +1,240 @@
+# include "elixir.h"
+
+/* take entry and return char with filled out value,
+   perform recursively */
+
+char *ExpandEntry (char *entry, int argc, char **argv) {
+
+  char *p1, *p2, *p3;
+  int Nbyte, N;
+  char *function, *operand, *value;
+  int Nout, Ncpy;
+
+  if (entry[0] == '!') {
+    p1 = strchr (entry, '!'); p1++;
+    p2 = strchr (entry, '(');
+    p3 = strchr (entry, ')');
+    if ((p2 == (char *) NULL) || (p3 == (char *) NULL)) {
+      fprintf (stderr, "syntax error in process defs\n");
+      Shutdown (1);
+    }
+    Nbyte = p2 - p1;
+    function = strncreate (p1, Nbyte);
+
+    p2 ++;
+    Nbyte = p3 - p2;
+    operand = strncreate (p2, Nbyte);
+    value = ExpandEntry (operand, argc, argv); 
+    free (operand);
+    operand = value; 
+    
+    value = (char *) NULL;
+    if (!strcasecmp (function, "buildname")) {
+      value = BuildName (operand);
+    }
+    if (!strcasecmp (function, "buildcode")) {
+      value = BuildCode (operand);
+    }
+    if (!strcasecmp (function, "photcode")) {
+      value = GetPhotcode (operand);
+    }
+    if (!strcasecmp (function, "photcodemef")) {
+      value = GetPhotcodeMef (operand);
+    }
+    if (!strcasecmp (function, "root")) {
+      value = RootFilename (operand);
+    }
+    if (!strcasecmp (function, "path")) {
+      value = PathFilename (operand);
+    }
+    if (!strcasecmp (function, "base")) {
+      value = BaseFilename (operand);
+    }
+    if (value == (char *) NULL) {
+      fprintf (stderr, "unknown process command %s\n", function);
+      Shutdown (1);
+    }
+    free (function); 
+    free (operand); 
+  } else {
+    Nbyte = strlen (entry) + 50;
+    ALLOCATE (value, char, Nbyte);
+
+    Nout = 0;
+    p1 = entry;
+    while ((p2 = strchr (p1, '&')) != (char *) NULL) {
+      Ncpy = p2 - p1;
+      if (Nout + Ncpy >= Nbyte - 1) {
+	Nbyte = Nout + Ncpy + 50;
+	REALLOCATE (value, char, Nbyte);
+      }    
+      strncpy (&value[Nout], p1, Ncpy);
+      Nout += Ncpy;
+      p2 ++;
+      N = strtod (p2, &p1);
+      if ((N > argc - 1) || (N < 0)) {
+	fprintf (stderr, "ERROR: command expects too many object arguments\n");
+	Shutdown (1);
+      }
+      Ncpy = strlen (argv[N]);
+      if (Nout + Ncpy >= Nbyte - 1) {
+	Nbyte = Nout + Ncpy + 50;
+	REALLOCATE (value, char, Nbyte);
+      }    
+      strcpy (&value[Nout], argv[N]);
+      Nout += Ncpy;
+    }
+    Ncpy = strlen (p1);
+    if (Nout + Ncpy >= Nbyte - 1) {
+      Nbyte = Nout + Ncpy + 50;
+      REALLOCATE (value, char, Nbyte);
+    }    
+    strncpy (&value[Nout], p1, Ncpy);
+    Nout += Ncpy;
+    value[Nout] = 0;
+  }
+
+  return (value);
+
+}
+
+Process *ConfigProcess (char *config, char *procname) {
+  
+  int j, NPAR;
+  char argname[256], argline[256];
+  Process *process;
+
+  NPAR = 10;
+  ALLOCATE (process, Process, 1);
+  ALLOCATE (process[0].argv, char *, NPAR);
+
+  process[0].name = strcreate (procname);
+
+  /* find all lines of form procname.arg - the argument lines */
+  sprintf (argname, "%s.arg", procname);
+  for (j = 0; ScanConfig (config, argname, "%s", j+1, argline); j++) {
+    process[0].argv[j] = strcreate (argline);
+    if (j == NPAR) {
+      NPAR += 10;
+      REALLOCATE (process[0].argv, char *, NPAR);
+    }
+  }
+  process[0].argc = j;
+  REALLOCATE (process[0].argv, char *, MAX (j,1));
+  if (j == 0) {
+    fprintf (stderr, "ERROR: process %s has no arguments defined\n", procname);
+    Shutdown (1);
+  }
+    
+  process[0].pending = InitQueue ();
+  process[0].failure = (Queue *) NULL;
+  process[0].success = (Queue *) NULL;
+  process[0].cluster = InitCluster ();
+
+  return (process);
+  
+}
+
+/* need a return value */
+int MakeArgs (Process *process, Object *object, int *cargc, char ***cargv, int **cargd) {
+
+  int i;
+  int Cargc, *Cargd;
+  char **Cargv;
+
+  Cargc = process[0].argc;
+  ALLOCATE (Cargv, char *, Cargc);
+  ALLOCATE (Cargd, int, Cargc);
+  
+  /* convert par to entry */
+  for (i = 0; i < Cargc; i++) {
+    ParseLine (process[0].argv[i], object[0].argc, object[0].argv, &Cargd[i], &Cargv[i]);
+  }
+  *cargc = Cargc;
+  *cargv = Cargv;
+  *cargd = Cargd;
+
+  return (TRUE);
+
+}
+
+/* 'process' carries around a list of strings which MakeArgs uses to create the command line
+   arguments and the dependencies (cargc, cargv, cargd) */
+
+void FreeArgs (int argc, char **argv, int *argd) {
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    free (argv[i]);
+  }
+
+  free (argv);
+  free (argd);
+
+}
+
+
+void ParseLine (char *testline, int argc, char **argv, int *depend, char **outline) {
+
+  int i, k;
+  char format[256], *line, *value;
+  int NTERMS, Nterms;
+  char **terms;
+  
+
+  NTERMS = 8;
+  ALLOCATE (terms, char *, NTERMS);
+  for (i = 0; i < NTERMS; i++) {
+    ALLOCATE (terms[i], char, 256);
+  }
+
+  Nterms = sscanf (testline, "%d%s%s%s%s%s%s%s%s%s", depend, format, 
+		   terms[0], terms[1], terms[2], terms[3], terms[4], terms[5], terms[6], terms[7]);
+  Nterms -= 2;
+      
+  for (k = 0; k < Nterms; k++) {
+    value = ExpandEntry (terms[k], argc, argv);
+    strcpy (terms[k], value);
+    free (value);
+  }
+      
+  ALLOCATE (line, char, 256);
+  switch (Nterms) {
+  case 0:
+    sprintf (line, format); 
+    break;
+  case 1:
+    sprintf (line, format, terms[0]); 
+    break;
+  case 2:
+    sprintf (line, format, terms[0], terms[1]); 
+    break;
+  case 3:
+    sprintf (line, format, terms[0], terms[1], terms[2]); 
+    break;
+  case 4:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3]); 
+    break;
+  case 5:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4]); 
+    break;
+  case 6:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4], terms[5]); 
+    break;
+  case 7:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4], terms[5], terms[6]); 
+    break;
+  case 8:
+    sprintf (line, format, terms[0], terms[1], terms[2], terms[3], terms[4], terms[5], terms[6], terms[7]); 
+    break;
+  default: 
+    fprintf (stderr, "too many terms for command line argument (lim = 5)\n");
+    Shutdown (1);
+  }
+  *outline = line;
+
+  for (i = 0; i < NTERMS; i++) { free (terms[i]); }
+  free (terms);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/QueueOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/QueueOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/QueueOps.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "elixir.h"
+
+/* get object from top of stack */
+Object *GetObject (Queue *queue) {
+
+  int i;
+  Object *object;
+  
+  if (queue[0].Nobject == 0) return ((Object *) NULL);
+
+  object = queue[0].object[0];
+  queue[0].Nobject --;
+  for (i = 0; i < queue[0].Nobject; i++) {
+    queue[0].object[i] = queue[0].object[i+1];
+  }
+  return (object);
+}
+
+/* put object on bottom of stack */
+void PutObject (Queue *queue, Object *object) {
+
+  if (queue[0].Nobject == queue[0].NOBJECT) {
+    queue[0].NOBJECT += 100;
+    REALLOCATE (queue[0].object, Object *, queue[0].NOBJECT);
+  }
+  queue[0].object[queue[0].Nobject] = object;
+  queue[0].Nobject ++;
+
+}
+
+/* push object on top of stack */
+void PushObject (Queue *queue, Object *object) {
+
+  int i;
+
+  if (queue[0].Nobject == queue[0].NOBJECT) {
+    queue[0].NOBJECT += 100;
+    REALLOCATE (queue[0].object, Object *, queue[0].NOBJECT);
+  }
+  for (i = queue[0].Nobject; i > 0; i--) {
+    queue[0].object[i] = queue[0].object[i-1];
+  }
+  queue[0].object[0] = object;
+  queue[0].Nobject ++;
+
+}
+
+/* allocate queue, setup with default values, allocate data */
+Queue *InitQueue () {
+
+  Queue *queue;
+
+  ALLOCATE (queue, Queue, 1);
+
+  queue[0].Nobject = 0;
+  queue[0].NOBJECT = 50;
+  ALLOCATE (queue[0].object, Object *, queue[0].NOBJECT);
+  return (queue);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/RemoteOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/RemoteOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/RemoteOps.c	(revision 16632)
@@ -0,0 +1,189 @@
+# include "elixir.h"
+
+void HaltElixir (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+  char line[512];
+  int i, wsock, rsock;
+  struct stat filestat;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "elixir is not running\n");
+    exit (0);
+  }
+
+  /* set signal to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to kill process\n", machine);
+    exit (1);
+  }
+  sprintf (line, "kill -USR1 %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  for (i = 0; i < 100; i++) {
+    if (stat (pidfile, &filestat) == -1) exit (0);
+    usleep (100000);
+  }
+  fprintf (stderr, "elixir is still running\n");
+  exit (2);
+}
+
+void KillElixir (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+  char line[512];
+  int i, wsock, rsock;
+  struct stat filestat;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "elixir is not running\n");
+    exit (0);
+  }
+
+  /* send signal to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to kill process\n", machine);
+    exit (1);
+  }
+  sprintf (line, "kill -TERM %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  for (i = 0; i < 100; i++) {
+    if (stat (pidfile, &filestat) == -1) exit (0);
+    usleep (100000);
+  }
+  fprintf (stderr, "elixir is still running\n");
+  exit (2);
+}
+
+void StatusElixir (char *pidfile, char *msgfile) {
+  
+  pid_t pid;
+  char username[256], machine[256], response[256], message[512];
+  char *answer;
+  char line[512];
+  int i, done, status, wsock, rsock;
+  struct stat filestat;
+  struct timeval now, then;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "elixir is not running\n");
+    exit (0);
+  }
+
+  sprintf (response, "%s.XXXXXX", msgfile);
+  mkstemp (response);
+  sprintf (message, "STATUS %s", response);
+  if (VERBOSE) fprintf (stderr, "sending message: %s\n", message);
+  WriteMsg (msgfile, message);
+
+  /* send signal to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to signal process\n", machine);
+    exit (1);
+  }
+  sprintf (line, "kill -USR2 %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  /* wait (2 sec) for file to exist, then try to read it */
+  for (i = 0; ((status = stat (response, &filestat)) == -1) && (i < 20); i++) {
+    if (VERBOSE) fprintf (stderr, "waiting for response: %d\n", status);
+    usleep (100000);
+  }
+  if (i >= 20) {
+    fprintf (stderr, "no response\n");
+    exit (2);
+  }
+
+  done = FALSE;
+  gettimeofday (&then, (void *) NULL);
+  if (VERBOSE) fprintf (stderr, "reading message: %s\n", message);
+  while (!done) {
+    status = ReadMsg (response, &answer);
+    switch (status) {
+    case 1:
+      done = TRUE;
+      break;
+    default:
+      gettimeofday (&now, (void *) NULL);
+      if (DTIME (now, then) > 5.0) {
+	fprintf (stderr, "no response from elixir\n");
+	exit (2);
+      }
+    }
+    usleep (10000);
+  }
+  fprintf (stderr, "%s\n", answer);
+  gettimeofday (&now, (void *) NULL);
+  if (VERBOSE) fprintf (stderr, "response in %f\n", DTIME (now, then));
+
+  unlink (response);
+  exit (0);
+}
+
+int HalttoRestart (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+  char line[512];
+  int i, wsock, rsock;
+  struct stat filestat;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "previous elixir not running\n");
+    return (TRUE);
+  }
+  /* check username matches: can only send signals to own process */
+
+  /* make connection to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to kill process\n", machine);
+    exit (1);
+  }
+	     
+  /* send TERM signal */
+  sprintf (line, "kill -TERM %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  /* wait for cleanup to finish */
+  for (i = 0; i < 100; i++) {
+    if (stat (pidfile, &filestat) == -1) {
+      fprintf (stderr, "previous elixir halted\n");
+      goto success;
+    }
+    usleep (100000);
+  }
+
+  /* kill meanly */
+  sprintf (line, "kill -KILL %d", pid);
+  write (wsock, line, strlen (line));
+  unlink (pidfile);
+
+  /* test if process is still alive? */
+ success:
+  sprintf (line, "exit\n");
+  write (wsock, line, strlen(line));
+  close (wsock);
+  close (rsock);
+  return (TRUE);
+  
+}
+
+int LoadPID (char *file, pid_t *pid, char *username, char *machine) {
+
+  FILE *f;
+
+  f = fopen (file, "r");
+  if (f == (FILE *) NULL) { 
+    return (FALSE);
+  }
+
+  fscanf (f, "%*s %d", pid);
+  fscanf (f, "%*s %s", username);
+  fscanf (f, "%*s %s", machine);
+  fclose (f);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/SockScan.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/SockScan.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/SockScan.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "elixir.h"
+# include <errno.h>
+# define MAXTIME 10
+
+int SockScan (char *string, Fifo *fifo, int sock) {
+  
+  int i, done, status;
+
+  done = 0;
+  for (i = 0; (i < MAXTIME) && !done; i++) {
+    ShiftFifo (fifo);
+    status = ReadtoFifo (fifo, sock);
+    switch (status) {
+    case 0:
+      break;
+    case -1:
+      usleep (1000);
+      break;
+    default:
+      done = memstr (fifo[0].buffer, string, fifo[0].Nbuffer);
+      break;
+    }
+  }
+  return (status);
+}
+
+/* returns (offset to m2) + 1, or 0 if failure */ 
+int memstr (char *m1, char *m2, int n) {
+
+  int i, N;
+
+  N = strlen (m2);
+  for (i = 0; (i < n - N + 1) && memcmp (m1, m2, N); i++, m1++);
+  if (memcmp (m1, m2, N)) {
+    return (0);
+  }
+  else {
+    return (i+1);
+  }
+
+}
+ 
+/* SockScan reads from the given socket looking for the given string
+   SockScan stores data read from socket in the fifo buffer to ensure 
+   it catches the given string.  a single invocation of SockScan will 
+   wait for up to 10 msec for data to come down the pipe before giving up.
+   SockScan can only search for one string in the output stream.
+   */
+
+
+/* need a way of signalling that the socket has closed...
+   maybe change the sock entry to 0?
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/StartMachine.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/StartMachine.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/StartMachine.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "elixir.h"
+
+int StartMachine (Machine *machine, Object *object, int argc, char **argv) {
+
+  int i, Nbyte, Nout;
+  char command[1024];
+  FILE *logfile;
+
+  logfile = LogOpen (object[0].logfile);
+  machine[0].object = object;
+
+  Nbyte = Nout = 0;
+  for (i = 0; i < argc; i++) {
+    Nout = sprintf (&command[Nbyte], "%s ", argv[i]);
+    Nbyte += Nout;
+  }
+    
+  fprintf (logfile, "%s @ %s: %s\n", object[0].argv[0], machine[0].hostname, command);
+  if (logfile != stderr) {
+    fflush (logfile);
+    fclose (logfile);
+  }
+
+  Nout = sprintf (&command[Nbyte], "\n echo PROCESS DONE\n");
+  write (machine[0].wsock, command, strlen(command));
+
+  gettimeofday (&machine[0].object[0].start, (void *) NULL);
+  gettimeofday (&machine[0].quiet, (void *) NULL);
+
+  machine[0].status = BUSY;
+  return (TRUE);
+}
+
+/* machine[0].quiet times since last message received from process. 
+   if process is too quiet for too long, we assume it died */
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/elixir.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/elixir.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/elixir.c	(revision 16632)
@@ -0,0 +1,126 @@
+# include "elixir.h"
+
+static int Dynamic;
+static int Reload;
+
+static int      Nobjects;
+static int      Nprocess;
+static Process **process;
+static Process   global;
+
+int main (int argc, char **argv) {
+  
+  int i, Nnew, state;
+  char *config;
+  int nloop;
+  char **targv;
+
+  /* save complete arglist incase we reload */
+  ALLOCATE (targv, char *, argc + 1);
+  for (i = 0; i < argc; i++) {
+    targv[i] = strcreate (argv[i]);
+  }
+  targv[i] = (char *) NULL;
+
+  config = ConfigInit (&argc, argv);
+
+  process = DefineProcesses (&global, &Nprocess, config);
+
+  /* PID filename stored in global.argv[7] */
+  ConfigPID (global.argv[7]);
+
+  InitMsgFile (global.argv[0]); /* success */
+  InitMsgFile (global.argv[1]); /* failure */
+  InitMsgFile (global.argv[5]); /* message */
+  InitMsgFile (global.argv[6]); /* end stat */
+  InitMachines (config);
+  free (config);
+
+  SetMessageFile (global.argv[5]);
+
+  InitProcessTimers (process, Nprocess);
+
+  Nobjects = 0;
+  Reload = FALSE;
+  Dynamic = TRUE;
+  nloop = 0;
+
+  /* any remaining entry is a file to load in static mode */
+  if (argc == 2) {
+    Dynamic = FALSE;
+    Nobjects = LoadPending (&global, argv[1], &state, &Dynamic);
+    if (state) {
+      fprintf (stderr, "error with input file %s (state %d)\n", argv[1], state);
+      Shutdown (1);
+    }
+  }
+
+  while (CheckEndingState (&global, Nobjects, Dynamic)) {
+
+    if (Dynamic) { 
+      Nnew = LoadPending (&global, global.argv[4], &state, &Dynamic);
+      Nobjects += Nnew;
+    }
+
+    for (i = 0; i < Nprocess; i++) {
+      CheckProcess (process[i]);
+    }
+
+    for (i = Nprocess - 1; i >= 0; i--) {
+      CheckProcess (process[i]);
+    }
+
+    CheckMessages ();
+    /* CheckMessages (&global, process, Nprocess, &Dynamic, Nobjects); */
+    RestartMachines ();
+
+    usleep (1000000);
+    if (nloop > 3000) {
+      fprintf (stderr, ".");
+      nloop = 0;
+    }
+    nloop ++;
+  }
+
+  DumpProcessTimes (global.argv[6]);
+ 
+  /* DumpStatus (global.argv[6], &global, process, Nprocess, Dynamic, Nobjects);  */
+  DumpStatus (global.argv[6]);
+
+  WriteMsg (global.argv[6], "DONE");
+
+  if (Reload) Restart (targv);
+
+  Shutdown (0);
+  exit (0);
+}
+
+void SIG_RELOAD (int sig) {
+  fprintf (stderr, "got signal RELOAD\n");
+  SetExitTimer ();
+  Dynamic = FALSE;
+  Reload = TRUE;
+}
+
+void ElixirStop () {
+  Dynamic = FALSE;
+}
+
+int GetDynamicState () {
+  return (Dynamic);
+}
+
+Process **GetProcessInfo (Process **gb, int *np, int *no) {
+  *np = Nprocess;
+  *no = Nobjects;
+  *gb = &global;
+  return (process);
+}
+
+/* create 'reload' mode:
+   0 - Reload = TRUE;
+   1 - Dynamic = FALSE;
+   2 - start timer (in CheckEndingState.c)
+   3 - if timer expires, set exit state
+   4 - if (Reload) exec (argc, arg)
+*/
Index: /branches/eam_branch_20080223/Ohana/src/elixir/src/rconnect.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/src/rconnect.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/src/rconnect.c	(revision 16632)
@@ -0,0 +1,100 @@
+# include "elixir.h"
+
+/* rconnect opens a remote shell on hostname and returns two file descriptors:
+   one for read, one for write */
+
+int rconnect (char *hostname, char *command, int *rsock, int *wsock) {
+
+  int i, rfd[2], wfd[2], status;
+  pid_t pid;
+  char buffer[0x4000];
+  char *file;
+  Fifo fifo;
+
+  InitFifo (&fifo, 0x4000, 0x1000);
+
+  status = pipe (rfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+  status = pipe (wfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+
+  file = filebasename (command);
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    fprintf (stderr, "starting remote connection to %s...", hostname);
+    /* close the excess sockets */
+    close (wfd[1]);
+    close (rfd[0]);
+    dup2 (wfd[0], STDIN_FILENO);
+    dup2 (rfd[1], STDOUT_FILENO);
+    dup2 (rfd[1], STDERR_FILENO);
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+    fprintf (stderr, "child is spawned\n");
+
+    status = execl (command, file, hostname, "/bin/csh", NULL); 
+    fprintf (stderr, "error starting remote shell process\n");
+    Shutdown (1);
+  }
+  *wsock = wfd[1];
+  *rsock = rfd[0];
+  close (wfd[0]);
+  close (rfd[1]);
+   
+  fcntl (*rsock, F_SETFL, O_NONBLOCK);
+  fcntl (*wsock, F_SETFL, O_NONBLOCK);
+
+  sprintf (buffer, "echo PTOLEMY STARTED\n");
+  status = write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  /* try to get evidence connection is alive - wait upto a few seconds */
+  status = -1;
+  for (i = 0; (i < 300) && (status == -1); i++) {
+    fcntl (*rsock, F_SETFL, O_NONBLOCK);
+    status = SockScan ("PTOLEMY STARTED", &fifo, *rsock);
+    if (!(i % 30)) fprintf (stderr, ".");
+    if (status == 0) {
+      fprintf (stderr, "socket closed unexpectedly\n");
+      close (*wsock);
+      close (*rsock);
+      return (FALSE);
+    }
+  }
+  if (status == -1) {
+    fprintf (stderr, "timeout while connecting\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+  fprintf (stderr, "Connected\n");
+
+  /* the onintr command works with csh/tcsh type shells to
+     prevent trapping of SIGTERM, used to kill hung jobs.
+     for bash/sh type shells, you can use SIGQUIT instead
+     without setting onintr */
+  sprintf (buffer, "onintr\n");
+  write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  FreeFifo (&fifo);
+  return (pid);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/elixir/test/README
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/test/README	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/test/README	(revision 16632)
@@ -0,0 +1,149 @@
+
+This directory includes a very simple elixir script, test.pro, to test
+that elixir is working correctly.  
+
+To run it, create an input list with one element per line.  The
+elements can be any word; an example is provided in test.list.
+
+Make sure the machines listed above represent valid machine names in
+your cluster.  Also, be certain that you can rsh to these machines
+without a password.
+
+Run the test by exectuting:
+
+elixir -c test.pro test.list
+
+the result of this test will be several files in your home directory:
+
+elixir-test.log
+elixir-test.end
+elixir-test.success
+
+elixir-test.log:
+
+The first file, elixir-test.log, shows the output from all of the
+processing steps.  In this test example, the log file is defined to be
+a single file, but it is also possible to use the &0 style
+command-line arguments to create a different file for each input line.
+All output from each of the processes goes into this file in the order
+received by the elixir program.  The resulting lines may look a bit
+confusing sometime as a result.  In addition, elixir adds some extra
+information to aid in debugging.  Here are a few example lines:
+
+foo @ kiawe: ls foo ; echo SUCCESS 
+bar @ milo: ls bar ; echo SUCCESS 
+foo @ kiawe:ls: foo: No such file or directory
+SUCCESS
+PROCESS DONE
+foo @ kiawe is done
+bar @ milo:ls: bar: No such file or directory
+SUCCESS
+PROCESS DONE
+bar @ milo is done
+
+Every output line from the processes are prepended with:
+
+(&0) @ (machine): 
+
+In this example, I used the two machines, kiawe & milo.  The first two
+lines show the first two commands being executed: 
+
+ls foo ; echo SUCCESS
+
+The next three lines show the output from the process executing on foo:
+
+ls: foo: No such file or directory 
+SUCCESS
+PROCESS DONE
+
+The 'ls' command did not find a file 'foo' in the home directory -
+note that all commands, since they are run remotely, execute in the
+user's home directory.  The word "SUCCESS" comes from the 'echo
+SUCCESS' portion of the command.  Currently, elixir uses the words
+SUCCESS, ERROR, and PROCESS DONE for process monitoring.  Ideally, the
+program called by elixir should check its output state and echo either
+SUCCESS or ERROR as appropriate.  In this test example, we simply
+force all processes to claim they succeeded with the 'echo SUCCESS'
+command.  The PROCESS DONE is added by elixir when it creates the
+command.  This lets elixir detect programs which crash and thereby
+fail to send either SUCCESS or ERROR.
+
+Side Note: this SUCCESS / ERROR flow control construct will soon be
+replaced by tests of the actual process exit status.  This will make
+elixir able to more cleanly support unix commnands.  
+
+The 6th line in the example above is the output from elixir noting
+that the process for 'foo' ended.  The next few lines show the output
+for the process on 'bar'.
+
+elixir-test.end:
+
+This file is created at the end of the elixir run and provides
+information about the run.  This same status information can be
+retrieved from elixir while it is running by using the 'status'
+program.  Here is the output from the above example:
+
+##################################################################
+               .   test1            test2            test3         
+           kiawe   0.120 3          5.056 2          0.130 1        
+            milo   0.110 1          5.062 2          0.109 3        
+processes status:
+            name   pending  success  failure  total
+----------------------------------------------------------------
+          global         0        4        0      4
+           test1         0
+           test2         0
+           test3         0
+
+machine status:
+          name  process  status
+----------------------------------------------------------------
+         kiawe   (none)       0
+          milo   (none)       0
+
+objects loaded so far: 4
+
+NOT accepting input from FIFO
+DONE
+##################################################################
+
+The first section shows a grid with processes across the top and
+machines in the left column.  The entries for each pair of machine &
+process are the average execution time and the number of instances of
+the given process which was run on the given machine.  So, in this
+example, the process 'test1' (which is the 'ls') was run on 'kiawe' 3
+times for an average of 0.120 sec and on 'milo' for an average of
+0.110 sec.  
+
+The second section shows the state of the different queues when the
+elixir process ended.  The left hand column shows the possible queues
+(global, test1, test2, test3).  For all nodes except the global node,
+the success and failure queues are always linked to a queue of another
+node.  Jobs which land in the success or failure queue of a node are
+instantly moved to the pending queue of another job.  Therefore, we
+only show the pending queue for the nodes except for 'global'.  Each
+number represents the number of jobs waiting in the given queue.
+(note: the global.pending queue is identical to one of the other
+pending queues and therefore represents a duplication).  The 'total'
+entry is the sum of jobs in each of the global queues.  Note that this
+table does not show the processes which are actually being executed,
+as these are considered to be 'in' a node, not on the queue of a node.
+They are represented in the next section.  
+
+The third section lists the status of all machines available.  The
+first column is the machine name; the second is the name of the
+process being executed, or '(none)' if the machine is idle; the third
+is a numerical status indication (which is generally ignored).  
+
+The next line shows the number of objects loaded by elixir.  Since
+elixir has the capability of loading new objects dynamically, this
+value on this line may increment as time goes by.  The next line shows
+whether elixir is accepting input during runtime or not.
+
+elixir-test.success:
+
+This file lists the processes which elixir successfully finished.  (An
+equivalent file, elixir-test.failure, would include jobs which did not
+succeed).  Entries are added to this file as the jobs complete.  In
+this way, it can be used to monitor the process of an elixir run.  
+
Index: /branches/eam_branch_20080223/Ohana/src/elixir/test/save.source
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/test/save.source	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/test/save.source	(revision 16632)
@@ -0,0 +1,4 @@
+msg1
+msg2
+msg3
+msg4
Index: /branches/eam_branch_20080223/Ohana/src/elixir/test/test.end
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/test/test.end	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/test/test.end	(revision 16632)
@@ -0,0 +1,21 @@
+               .   test1            test2            test3         
+       localhost   1.565 2          5.180 2          1.030 2        
+       localhost   1.575 2          5.180 2          1.030 2        
+processes status:
+            name   pending  success  failure  total
+----------------------------------------------------------------
+          global         0        4        0      4
+           test1         0
+           test2         0
+           test3         0
+
+machine status:
+          name  process  status
+----------------------------------------------------------------
+     localhost   (none)       0
+     localhost   (none)       0
+
+objects loaded so far: 4
+
+NOT accepting input from FIFO
+DONE
Index: /branches/eam_branch_20080223/Ohana/src/elixir/test/test.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/test/test.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/test/test.pro	(revision 16632)
@@ -0,0 +1,54 @@
+# Elixir test config file
+
+CONNECT         /usr/bin/ssh
+MACHINE		localhost
+MACHINE		localhost
+elixir		test
+
+# FIFO files
+global.success	$elixir.success
+global.failure	$elixir.failure
+global.source	$elixir.source
+global.msg	$elixir.msg
+global.end	$elixir.end
+global.pid	$elixir.pid
+
+# process definition
+global.Nargs	1
+global.logfile  0 %s $elixir.log
+global.pending	test1
+global.timeout	100
+
+# test1: ls (will ls &0 user home dir)
+process	test1 
+test1.arg 0 ls
+test1.arg 0 %s  &0
+test1.arg 0 ;
+test1.arg 0 echo
+test1.arg 0 SUCCESS
+test1.success test2
+test1.failure global
+
+# test2 sleep 5
+process	test2 
+test2.arg 0 sleep
+test2.arg 0 5
+test2.arg 0 ;
+test2.arg 0 echo
+test2.arg 0 SUCCESS
+test2.success test3
+test2.failure global
+
+# test3 echo &0
+process	test3 
+test3.arg 0 echo 
+test3.arg 0 %s  &0
+test3.arg 0 ;
+test3.arg 0 echo
+test3.arg 0 SUCCESS
+test3.success global
+test3.failure global
+
+# this is a very simple elixir script to test that elixir is working
+# correctly.  See the README file for instructions.
+ 
Index: /branches/eam_branch_20080223/Ohana/src/elixir/test/test.success
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/elixir/test/test.success	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/elixir/test/test.success	(revision 16632)
@@ -0,0 +1,4 @@
+msg1 0000005d test3
+msg2 0000005d test3
+msg3 0000005d test3
+msg4 0000005d test3
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/Makefile	(revision 16632)
@@ -0,0 +1,33 @@
+default: uniphot
+help:
+	@echo "make options: uniphot (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/fixcat
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+uniphot: $(BIN)/uniphot.$(ARCH)
+install: $(DESTBIN)/uniphot
+
+FIXCAT = \
+$(SRC)/fixcat.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   \
+$(SRC)/coordops.$(ARCH).o	$(SRC)/sorts.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o 	$(SRC)/config.$(ARCH).o     \
+$(SRC)/Fread.$(ARCH).o		$(SRC)/check_lockfile.$(ARCH).o \
+$(SRC)/find_images.$(ARCH).o	$(SRC)/match_images.$(ARCH).o	\
+$(SRC)/gregions.$(ARCH).o	$(SRC)/aregion.$(ARCH).o	\
+$(SRC)/find_funnymags.$(ARCH).o	$(SRC)/gcatstats.$(ARCH).o\
+$(SRC)/find_matches.$(ARCH).o	$(SRC)/check_permissions.$(ARCH).o
+
+$(UNIPHOT): $(INC)/uniphot.h
+$(BIN)/uniphot.$(ARCH): $(UNIPHOT)
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/doc/example.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/doc/example.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/doc/example.txt	(revision 16632)
@@ -0,0 +1,13 @@
+
+rats: foreach f ( */*.cpt )
+foreach? echo $f
+foreach? echo $f >> bright.log
+foreach? (markstar -v $f >> bright.dat) >>& bright.log
+foreach? end
+
+
+
+ echo $f
+ echo $f >> bright.log
+ (markstar -v $f >> bright.dat) >>& bright.log
+ end
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/include/markstar.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/include/markstar.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/include/markstar.h	(revision 16632)
@@ -0,0 +1,42 @@
+# include <ohana.h>
+# include <dvo.h>
+
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+
+/* global variables set in parameter file */
+char   CATDIR[256];
+char   GSCDIR[256];
+char   ImageCat[256];
+char   GSCFILE[256];
+
+double RADIUS;
+double TRAIL_WIDTH;
+int    NBINS;
+int    NPTSINLINE;
+double MIN_DENSITY;
+double NSIGMA;
+
+double BRIGHT_HALO_MAG;
+double BRIGHT_HALO_SLOPE;
+double BRIGHT_XTRAIL_WIDTH;
+double BRIGHT_XTRAIL_MAG;
+double BRIGHT_XTRAIL_SLOPE;
+double BRIGHT_YTRAIL_WIDTH;
+double BRIGHT_YTRAIL_MAG;
+double BRIGHT_YTRAIL_SLOPE;
+
+double GHOST_MAG;
+double GHOST_RADIUS;
+double OPTICAL_AXIS1;
+double OPTICAL_AXIS2;
+
+typedef struct {
+  Coords coords;
+  double *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "markstar.h"
+
+ConfigInit (int argc, char **argv) {
+
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* used in other pipeline functions */
+  ScanConfig (config, "CATDIR",          "%s",  0, CATDIR);
+  ScanConfig (config, "GSCDIR",          "%s",  0, GSCDIR);
+  ScanConfig (config, "GSCFILE",         "%s",  0, GSCFILE);
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  /* unique to markstar */
+  ScanConfig (config, "SEARCH_RADIUS",   "%lf", 0, &RADIUS);
+  ScanConfig (config, "TRAIL_WIDTH",     "%lf", 0, &TRAIL_WIDTH);
+  ScanConfig (config, "NANGLE_BINS",     "%d",  0, &NBINS);
+  ScanConfig (config, "NPTSINLINE",      "%d",  0, &NPTSINLINE);
+  ScanConfig (config, "MIN_DENSITY",     "%lf", 0, &MIN_DENSITY);
+  ScanConfig (config, "SPACE_SIGMA",     "%lf", 0, &NSIGMA); 
+
+  ScanConfig (config, "BRIGHT_HALO_MAG",     "%lf", 0, &BRIGHT_HALO_MAG);
+  ScanConfig (config, "BRIGHT_HALO_SLOPE",   "%lf", 0, &BRIGHT_HALO_SLOPE);
+  ScanConfig (config, "BRIGHT_XTRAIL_WIDTH", "%lf", 0, &BRIGHT_XTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_XTRAIL_MAG",   "%lf", 0, &BRIGHT_XTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_XTRAIL_SLOPE", "%lf", 0, &BRIGHT_XTRAIL_SLOPE);
+  ScanConfig (config, "BRIGHT_YTRAIL_WIDTH", "%lf", 0, &BRIGHT_YTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_YTRAIL_MAG",   "%lf", 0, &BRIGHT_YTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_YTRAIL_SLOPE", "%lf", 0, &BRIGHT_YTRAIL_SLOPE);
+
+  ScanConfig (config, "GHOST_MAG",       "%lf", 0, &GHOST_MAG);
+  ScanConfig (config, "GHOST_RADIUS",    "%lf", 0, &GHOST_RADIUS);
+  ScanConfig (config, "OPTICAL_AXIS1",   "%lf", 0, &OPTICAL_AXIS1);
+  ScanConfig (config, "OPTICAL_AXIS2",   "%lf", 0, &OPTICAL_AXIS2);
+ 
+  free (config);
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/aregion.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/aregion.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/aregion.c	(revision 16632)
@@ -0,0 +1,118 @@
+# include "markstar.h"
+
+double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+			 52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+			 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+			 -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+		       "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+		       "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+		       "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			"n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			"s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			"s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		"disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		"disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+                   0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/* find region file which contains ra, dec */
+aregion (region, f, ra, dec) 
+GSCRegion region[];
+FILE *f;
+double ra, dec;
+{
+  
+  
+  char buffer[28800], temp[50], file[50];
+  double dr, dd;
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done, nregion;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+    
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt\0", GSCDIR);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] = -180.0;
+    region[0].RA[1] =  540.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+# ifdef DEBUG
+    fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+# ifdef DEBUG
+      fprintf (stderr, "%d %f %f %f\n", i, dec, BigDecBounds[i], BigDecBounds[i+1]);
+# endif
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    fprintf (stderr, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  Fread (buffer, 1, 48*NDecLines[NBigDec], f, "char");
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hstgsc_hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+# ifdef DEBUG
+    fprintf (stderr, "%f %f %f  %f %f %f  %s\n", DEC0, dec, DEC1, RA0, ra, RA1, temp);
+# endif
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+  if (!done) {
+    fprintf (stderr, "error in search: %f %f\n", ra, dec);
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt\0", GSCDIR, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/check_lockfile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/check_lockfile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/check_lockfile.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "markstar.h"
+
+check_lockfile ()
+{
+  
+  FILE *f;
+  char filename[128];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    fprintf (stderr, "ERROR: catalog %s is locked, try again later\n", CATDIR);
+    exit (0);
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock file %s\n", filename);
+    exit (0);
+  }
+  fclose (f);
+
+}
+
+clear_lockfile ()
+{
+  
+  char filename[128], line[256];
+  struct stat filestat;
+
+  sprintf (filename, "%s/lock\0", CATDIR);
+  if (stat (filename, &filestat) != -1) {
+    sprintf (line, "rm %s\0", filename);
+    system (line);
+  } else {
+    fprintf (stderr, "can't remove lockfile, why not?\n");
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/check_permissions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/check_permissions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/check_permissions.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "markstar.h"
+
+check_permissions (char *basefile) {
+  
+  FILE *f;
+  char *c, dir[256], filename[256];
+  struct stat filestat;
+  uid_t fuid, uid;
+  gid_t fgid, gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  sprintf (filename, "%s\0", basefile);
+  c = strrchr (filename, '/');
+  if (c == (char *) NULL) {
+    strcpy (dir, ".");
+  } else {
+    *c = 0;
+    strcpy (dir, filename);
+  }
+  status = stat (dir, &filestat);
+  if (status == -1) {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  } 
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    fprintf (stderr, "ERROR: can't write to %s\n", dir);
+    exit (0);
+  }
+  
+  /* check permission to write to file */
+  sprintf (filename, "%s\0", basefile);
+  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_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  sprintf (filename, "%s~\0", basefile);
+  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_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      fprintf (stderr, "ERROR: can't write to %s\n", filename);
+      exit (0);
+    }
+  }
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/config.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/config.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/config.c	(revision 16632)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NBYTES 4096
+
+char *LoadConfigFile (filename) 
+char *filename; 
+{
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, size;
+  char *config;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find %s\n", filename);
+    return ((char *) NULL);
+  }
+ 
+  NBYTES = D_NBYTES;
+  ALLOCATE (config, char, NBYTES);
+ 
+  size = 0;
+  done = FALSE;
+  for (i = 0; !done; i++) {
+    Nbytes = Fread (&config[i*D_NBYTES], sizeof(char), D_NBYTES, f, "char");
+    size += Nbytes;
+    if (Nbytes < D_NBYTES) 
+      done = TRUE;
+    else {
+      NBYTES += D_NBYTES;
+      REALLOCATE (config, char, NBYTES);
+    }
+  }
+  
+  config[size] = '\n';
+  config[size+1] = 0;
+  REALLOCATE (config, char, size + 2);
+ 
+  fclose (f);
+
+  return (config);
+}
+
+int ScanConfig /* we expect one more field: the pointer to the value requested */
+# ifndef ANSI
+(config, field, mode, va_alist) 
+ char *config; char *field, *mode; va_dcl
+# else
+(char       config[],
+ char       field[],
+ char       mode[],...)
+# endif
+{
+ 
+  int i, j;
+  char *p, *p2, tmp[256];
+  va_list argp;
+  double value;
+  
+# ifndef ANSI
+  va_start (argp);
+# else
+  va_start (argp, N);
+# endif
+  
+  /* find the correct line with field */
+  p2 = config;
+  for (i = 0; ; i++) {
+    if (!strncmp (field, p2, strlen(field))) {
+      p = p2 + strlen (field);
+      break;
+    }
+    else {
+      p2 = strchr (p2, '\n');
+      if (p2 == (char *) NULL) {
+	fprintf (stderr, "entry %s not found in config file\n", field);
+	return (FALSE);
+      }
+      else p2++;
+    }
+  }
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL)
+      p2 = config + strlen(config);
+    bcopy (p, tmp, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+  }
+  else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_bright_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_bright_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_bright_stars.c	(revision 16632)
@@ -0,0 +1,142 @@
+# include "markstar.h"
+
+find_bright_stars (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, n, m, first_j, Nave, Ngsc;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  double *X1, *Y1, *X2, *Y2;
+  int *N1, *N2;
+  char *mark;
+  double dX, dY, dR, MaxDist, MaxDist1, MaxRadius, radius, radius2;
+
+  load_gsc_data (&GSCdata, catstats);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  /* in the function below, it is better to have the catalog with
+     more stars associated with index 2 (j) */ 
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+  ALLOCATE (X1, double, Ngsc);
+  ALLOCATE (Y1, double, Ngsc);
+  ALLOCATE (N1, int, Ngsc);
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    RD_to_XY (&X1[i], &Y1[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Ngsc > 1) sort_coords_index (X1, Y1, N1, Ngsc);
+  
+  /* first find stellar halos */
+  /* max radius (mag = -1) */
+  /** the j index moves quickly and is better associated with the catalog with more stars */
+  MaxRadius = BRIGHT_HALO_SLOPE * (-1.0 - BRIGHT_HALO_MAG); 
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*MaxRadius) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*MaxRadius) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    radius = MAX (BRIGHT_HALO_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_HALO_MAG), 0.0);
+    if (radius == 0) {
+      i++; 
+      continue;
+    }
+    radius2 = radius*radius;
+    for (; (dX > -2*radius) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < radius2) {  /* new measurement of this star */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find y spikes */
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -BRIGHT_YTRAIL_WIDTH) {
+      i++;
+      continue;
+    }
+    if (dX >= BRIGHT_YTRAIL_WIDTH) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist = MAX (BRIGHT_YTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_YTRAIL_MAG), 0.0);
+    for (; (dX > -BRIGHT_YTRAIL_WIDTH) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dX) < BRIGHT_YTRAIL_WIDTH) && (fabs(dY) < MaxDist)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find x spikes */
+  /** find catalog stars near GSC stars **/
+  MaxDist = MAX (BRIGHT_XTRAIL_SLOPE * (-1.0 - BRIGHT_XTRAIL_MAG), 0.0);
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -MaxDist) {
+      i++;
+      continue;
+    }
+    if (dX >= MaxDist) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist1 = MAX (BRIGHT_XTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_XTRAIL_MAG), 0.0);
+    for (; (dX > -MaxDist1) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dY) < BRIGHT_XTRAIL_WIDTH) && (fabs(dX) < MaxDist1)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* done with search, mark selected stars */
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      catalog[0].average[N2[i]].code = ID_BLEED;
+    }
+  } 
+  
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (mark);
+  free (GSCdata.average);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_funnymags.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_funnymags.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_funnymags.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "markstar.h"
+
+find_funnymags (catalog, images, Nimage)
+Catalog catalog[];
+Image images[];
+int Nimage;
+{
+
+  int i;
+  int *bad;
+
+  ALLOCATE (bad, int, Nimage);
+  bzero (bad, Nimage*sizeof(int));
+
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    if (catalog[0].measure[i].M < 9000) {
+      bad[catalog[0].image[i]] ++;
+    }
+  }
+
+  for (i = 0; i < Nimage; i++) {
+    if (bad[i] > 0) {
+      fprintf (stdout, "%s %d %d\n", images[i].name, images[i].tzero, bad[i]);
+    }
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_ghosts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_ghosts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_ghosts.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "markstar.h"
+
+find_ghosts (catalog, catstats, filename, image, Nimage)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+Image image[];
+int Nimage;
+{
+
+  int i, j, first_j, Nave, Ngsc, Nregions;
+  Catalog GSCdata, Ghostdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius, X, Y, R, D;
+  Image timage;
+  GSCRegion *region, *gregions2();
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* coords structure for ghost image */
+    timage = image[i];
+    timage.coords.cdelt1 = -1*image[i].coords.cdelt1;
+    timage.coords.cdelt2 = -1*image[i].coords.cdelt2;
+    timage.coords.crpix1 = 2*OPTICAL_AXIS1 - image[i].coords.crpix1;
+    timage.coords.crpix2 = 2*OPTICAL_AXIS2 - image[i].coords.crpix2;
+
+    region = gregions2 (&timage, &Nregions);
+    
+    /* find ghost stars */
+    load_gsc_data_ghost (&GSCdata, region, Nregions, &timage);
+
+    /* refect ghost stars to find locations of ghosts */
+    ALLOCATE (Ghostdata.average, Average, MAX (GSCdata.Naverage, 1));
+    for (j = 0; j < GSCdata.Naverage; j++) {
+      RD_to_XY (&X, &Y, GSCdata.average[j].R, GSCdata.average[j].D, &timage);
+      fXY_to_RD (&Ghostdata.average[j].R, &Ghostdata.average[j].D, X, Y, &image[i]);
+      Ghostdata.average[j].M = GSCdata.average[j].M;
+    }    
+    Ghostdata.Naverage = GSCdata.Naverage;
+
+    /* match ghosts and image stars, mark ghosts */
+    find_matches (catalog, catstats, &Ghostdata, i);
+
+    free (Ghostdata.average);
+    free (GSCdata.average);
+  }
+
+}
+
+/* 
+
+   just to be clear on some of the terms:
+
+   the "ghost" is the fuzzy patch of light on an image caused by
+     a reflected star
+
+   the "ghost star" is the star in the sky which causes a ghost
+
+   the "ghost image" is the image location on the sky 
+     where ghost stars may come from.
+
+   the "image stars" are observed stars at the location of the
+     ghost - these are detections of the ghost
+
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_group.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_group.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_group.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "markstar.h"
+
+find_group (catstats, mark, Npts, i, ANGLE)
+     CatStats catstats[];
+     double *ANGLE;
+     int i, Npts;
+     char *mark;
+{
+ 
+  float *R, *D;
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Ra, De, dR, dD, angle, limit;
+
+   /* assign some parameter values */
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  limit = 10.0*sqrt((double)(M_PI*RADIUS*RADIUS*catstats[0].density)/(double)(NBINS));
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS)
+  bzero (A, NBINS*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  if (mark[i]) return (FALSE);
+  Ra = R[i];
+  De = D[i];
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  return (FALSE);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_images.c	(revision 16632)
@@ -0,0 +1,261 @@
+# include "markstar.h"
+# define OLDSTYLE 1
+# if (OLDSTYLE)
+double opening_angle ();
+# endif
+
+Image *find_images (catstats, Nimages)
+CatStats catstats[];
+int *Nimages;
+{
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status;
+  FILE *f;
+  double Xc[6], Yc[6], Xi[6], Yi[6], r, d, x, y, dx, dy;
+  Coords *tcoords;
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords = &catstats[0].coords;
+  /* define catalog corners */
+  Xc[0] = catstats[0].RA[0]; Yc[0] = catstats[0].DEC[0];
+  Xc[1] = catstats[0].RA[1]; Yc[1] = catstats[0].DEC[0];
+  Xc[2] = catstats[0].RA[1]; Yc[2] = catstats[0].DEC[1];
+  Xc[3] = catstats[0].RA[0]; Yc[3] = catstats[0].DEC[1];
+  Xc[4] = catstats[0].RA[0]; Yc[4] = catstats[0].DEC[0];
+  Xc[5] = catstats[0].RA[1]; Yc[5] = catstats[0].DEC[1];
+  for (j = 0; j < 6; j++) {
+    r = Xc[j]; d = Yc[j];
+    RD_to_XY (&Xc[j], &Yc[j], r, d, tcoords);
+  }
+  /* find Y positions of RA center */
+  r = 0.5*(catstats[0].RA[0] + catstats[0].RA[1]);
+  d = catstats[0].DEC[0];
+  RD_to_XY (&x, &y, r, d, tcoords);
+  Yc[0] = MIN (y, Yc[0]);
+  Yc[1] = MIN (y, Yc[1]);
+  Yc[4] = MIN (y, Yc[4]);
+  /* find Y positions of RA center */
+  r = 0.5*(catstats[0].RA[0] + catstats[0].RA[1]);
+  d = catstats[0].DEC[1];
+  RD_to_XY (&x, &y, r, d, tcoords);
+  Yc[2] = MAX (y, Yc[2]);
+  Yc[3] = MAX (y, Yc[3]);
+  Yc[5] = MAX (y, Yc[5]);
+
+  dx = 0.02*(Xc[2] - Xc[0]);
+  dy = 0.02*(Yc[2] - Yc[0]);
+  Xc[0] -= dx; Yc[0] -= dy;
+  Xc[1] += dx; Yc[1] -= dy;
+  Xc[2] += dx; Yc[2] += dy;
+  Xc[3] -= dx; Yc[3] += dy;
+  Xc[4] -= dx; Yc[4] -= dy;
+  Xc[5] -= dx; Yc[5] -= dy;
+
+  /* check if image datafile exists, get header, number of images */
+  if (!gfits_read_header (ImageCat, &header)) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+  Nimage = 0;
+  gfits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  if (Nimage == 0) {
+    fprintf (stderr, "ERROR: No images in catalog %s (1)\n", ImageCat);
+    exit (0);
+  }
+
+  /* get ready to read data on images */ 
+  f = fopen (ImageCat, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: trouble opening Image catalog: %s (2)\n", ImageCat);
+    exit (0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* set up buffers for images, temporary storage */
+  NTIMAGE = 100;
+  ALLOCATE (timage, Image, NTIMAGE);
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  nimage = 0;
+  Nloop = Nimage / NTIMAGE + 1;
+  Nlast = Nimage % NTIMAGE;
+  
+  /* read in images in groups of NTIMAGE (100) */
+  for (n = 0; n < Nloop; n++) {
+    Nim = (n == Nloop - 1) ? Nlast : NTIMAGE;
+    status = Fread (timage, sizeof(Image), Nim, f, "image");
+    if (status != Nim) {
+      fprintf (stderr, "ERROR: couldn't read images from image catalog: %s\n", ImageCat);
+      exit (0);
+    }
+    /* test each image in block */
+    for (i = 0; i < Nim; i++) {
+      /* define image corners */
+      Xi[0] = 0;            Yi[0] = 0;
+      Xi[1] = timage[i].NX; Yi[1] = 0;
+      Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+      Xi[3] = 0;            Yi[3] = timage[i].NY;
+      Xi[4] = 0;            Yi[4] = 0;
+      Xi[5] = timage[i].NX; Yi[5] = timage[i].NY;
+      found = FALSE;
+      /* transform to tcoords */
+      if (catstats[0].DEC[1] > 86.25) { /* pole */
+	for (j = 0; j < 6; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  if (d > catstats[0].DEC[0] - 0.5) found = TRUE;
+	}
+      } else {
+	for (j = 0; j < 6; j++) {
+	  XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	  RD_to_XY (&Xi[j], &Yi[j], r, d, tcoords);
+	}
+	/* check if edges cross */
+	for (j = 0; (j < 5) && !found; j++) {
+	  for (k = 0; (k < 5) && !found; k++) {
+	    found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	  }
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	image[nimage].code = 0;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	}
+      }
+    }
+  }
+      
+  if (VERBOSE) { 
+    for (i = 0; i < nimage; i++) {
+      XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+      fprintf (stderr, "associated images: %d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	       i, r, d, image[i].tzero, image[i].nstar, 0.001*image[i].secz, 
+	       0.001*image[i].Mcal, 0.001*image[i].dMcal);
+    }
+  }
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  free (timage);
+  *Nimages = nimage;
+  fclose (f);
+  return (image);
+}
+
+# if (OLDSTYLE)
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+#else 
+
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double dot;
+  double dx1, dx2, dy1, dy2, dx3, dy3, x, y;
+  double cross, L1, L3, d1, d2;
+
+  dx1 = x1[1] - x1[0]; dy1 = y1[1] - y1[0];
+  dx2 = x2[1] - x2[0]; dy2 = y2[1] - y2[0];
+
+  cross = dx2*dy1 - dx1*dy2;
+  
+  if (cross == 0) {  /* lines are parallel, are they inline? */
+    dx3 = x2[1] - x1[0]; dy2 = y2[1] - y1[0];
+    L1 = hypot (dx1,dy1);
+    L3 = hypot (dx3,dy3);
+
+    dot = fabs (dx1*dx3 + dy1*dy3) / (L1*L3);
+    if (dot == 1.0) { /* lines are inline, do they overlap? */
+      d1 = (x1[1]-x2[1])*(x1[1]-x2[0]) + (y1[1]-y2[1])*(y1[1]-y2[0]);
+      d2 = (x1[0]-x2[1])*(x1[0]-x2[0]) + (y1[0]-y2[1])*(y1[0]-y2[0]);
+      if (d1*d2 < 0) { /* lines overlap */
+	return (TRUE);
+      } else {
+	return (FALSE);
+      }
+    } else {
+      return (FALSE);
+    }
+  }
+
+  x = (dx1*dx2*(y2[0] - y1[0]) + (x1[0]*dy1*dx2 - x2[0]*dy2*dx1)) / cross;
+
+  if (dx1 != 0) {
+    y = y1[0] + (x - x1[0])*dy1/dx1;
+  } else {
+    y = y2[0] + (x - x2[0])*dy2/dx2;
+  }
+
+  d1 = (x - x1[0])*(x - x1[1]) + (y - y1[0])*(y - y1[1]);
+  d2 = (x - x2[0])*(x - x2[1]) + (y - y2[0])*(y - y2[1]);
+  if ((d1 > 0) || (d2 > 0)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+      
+
+#endif
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_line.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_line.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_line.c	(revision 16632)
@@ -0,0 +1,161 @@
+# include "markstar.h"
+
+find_line (catstats, mark, Npts, i, M, B, Angle)
+     CatStats catstats[];
+     double *M, *B, Angle;
+     int i, Npts;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, angle;
+  char Flipped;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Ra;
+  Y = De;
+  X2 = Ra*Ra;
+  Y2 = De*De;
+  XY = Ra*De;
+  N = 1;
+  /* points to the east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; !mark[i] && (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  Flipped = 0;
+  det = 1.0 / (X2*N - X*X);
+  m = det * (XY*N - X*Y);
+  b = det * (X2*Y - XY*X);
+  if (fabs(m) > 1.1) { /* use a line of R = m*D + b instead */
+    /* fprintf (stderr, "high slope object: %f %f  -> ", m, b); */
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+    Flipped = 1;
+    /* fprintf (stderr, "%f %f\n", m, b); */
+  }
+
+  *M = m;
+  *B = b;
+  return (Flipped);
+
+}
+
+
+find_better_line (catstats, mark, Npts, i, M, B, axis)
+     CatStats catstats[];
+     double *M, *B;
+     int i, Npts, axis;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, delta;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Y = X2 = Y2 = XY = N = 0;
+  m = *M;  b = *B;
+
+  /* points to the east */
+  for (j = i; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  if (axis == 0) {
+    det = 1.0 / (X2*N - X*X);
+    m = det * (XY*N - X*Y);
+    b = det * (X2*Y - XY*X);
+  } else {
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+  }
+
+  /* fprintf (stderr, "%f %f %d\n", m, b, N); */
+
+  *M = m;
+  *B = b;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_matches.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_matches.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_matches.c	(revision 16632)
@@ -0,0 +1,87 @@
+# include "markstar.h"
+
+find_matches (catalog, catstats, Ghostdata, Nimage)
+CatStats catstats[];
+Catalog catalog[], Ghostdata[];
+int Nimage;
+{
+
+  int i, j, k, n, m, N, M, first_j;
+  double X, Y, RADIUS, RADIUS2;
+  double *X1, *Y1, *X2, *Y2;
+  double dX, dY, dR;
+  int *N1, *N2;
+  int Nstar, Nghost, Ng;
+  unsigned int flags;
+  Coords *tcoords;
+
+  Nstar = catalog[0].Naverage;
+  Nghost = Ghostdata[0].Naverage;
+
+  if (Nghost < 1) return (0);
+
+  /* it is better to have the catalog with fewer stars
+     assigned to the X1 set */
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+
+  ALLOCATE (X1, double, Nghost);
+  ALLOCATE (Y1, double, Nghost);
+  ALLOCATE (N1, int, Nghost);
+
+  /* project ghosts to the frame of the catalog */
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Nghost; i++) {
+    RD_to_XY (&X1[i], &Y1[i], Ghostdata[0].average[i].R, Ghostdata[0].average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Nghost > 1) sort_coords_index (X1, Y1, N1, Nghost);
+
+  /* choose a radius for matches */
+  RADIUS2 = GHOST_RADIUS*GHOST_RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nghost) && (j < Nstar); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*GHOST_RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*GHOST_RADIUS) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*GHOST_RADIUS) && (j < Nstar); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  
+	/* this object may be a ghost star, 
+	   but only mark those measurements on the correct image */
+	M = N2[j];
+	m = catalog[0].average[M].offset;
+	Ng = 0;
+	for (k = 0; k < catalog[0].average[M].Nm; k++) {
+	  if (catalog[0].image[m+k] == Nimage) {
+	    catalog[0].measure[m+k].average |= GHOST_DATA;
+	    Ng ++;
+	  }
+	}
+	/* all measurements are ghosts */
+	if (catalog[0].average[M].Nm == Ng) {
+	  catalog[0].average[M].code = ID_GHOST;
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  free (X1);
+  free (Y1);
+  free (N1);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_trails.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_trails.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/find_trails.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "markstar.h"
+
+find_trails (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, N, Nave, axis, marked;
+  double density, spacing, Area, Angle, m, b, RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  char *mark;
+  int *N1;
+  Coords tcoords;
+  
+  Nave = catalog[0].Naverage;
+  N1 = catstats[0].N;
+
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  for (i = 0; i < Nave; i++) {
+    /* already marked, ignore */
+    if ((mark[i]) || 
+	(catalog[0].average[N1[i]].code == ID_BLEED) || 
+	(catalog[0].average[N1[i]].code == ID_GHOST))
+      continue;
+    /* a good star, ignore */
+    if ((catalog[0].average[N1[i]].Nm > 3) && 
+	(catalog[0].average[N1[i]].Nm > 4*catalog[0].average[N1[i]].Nn)) {
+      continue;
+    }
+    if (find_group (catstats, mark, Nave, i, &Angle)) {
+      /* this point has an excess nearby concentration, find the line */
+      axis = find_line (catstats, mark, Nave, i, &m, &b, Angle);
+      find_better_line (catstats, mark, Nave, i, &m, &b, axis);
+      mark_trail (catstats, mark, Nave, i, m, b, axis, catalog);
+    }
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/fixcat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/fixcat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/fixcat.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "markstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nimages;
+  Image *image, *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  struct timeval now, then;  
+  
+  fprintf (stderr, "this function is not well-defined: review and recode\n");
+  exit (1);
+
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: fixcat (catalog)\n");
+    exit (0);
+  }
+
+  /* replace with addstar/gcatalog as example */
+  gcatalog (argv[1], &catalog);
+
+  gcatstats (&catalog, &catstats);
+
+  image = find_images (&catstats, &Nimages);
+
+  match_images (&catalog, image, Nimages);
+    
+  find_funnymags (&catalog, image, Nimages);  
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/gcatalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/gcatalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/gcatalog.c	(revision 16632)
@@ -0,0 +1,108 @@
+# include "markstar.h"
+
+gcatalog (catname, catalog)
+char *catname;
+Catalog catalog[];
+{
+  
+  char filename[128], line[64];
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, done;
+  FILE *f;
+  struct tm *local;
+  struct timeval now;
+  unsigned int NotTrail;
+  unsigned short NotBad;
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+
+  /* read catalog header */
+  if (!gfits_read_header (filename, &catalog[0].header)) {
+    fprintf (stderr, "ERROR: file doesn't exist %s\n", filename);
+    exit (0);
+  }
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open catalog file: %s\n", filename);
+    exit (0);
+  }
+  fseek (f, catalog[0].header.size, SEEK_SET); 
+
+  /** find number of stars, measurements **/
+  catalog[0].Nmissing = catalog[0].Naverage = catalog[0].Nmeasure = 0;
+  gfits_scan (&catalog[0].header, "NSTARS", "%d", 1, &catalog[0].Naverage);
+  gfits_scan (&catalog[0].header, "NMEAS", "%d", 1, &catalog[0].Nmeasure);
+  gfits_scan (&catalog[0].header, "NMISS", "%d", 1, &catalog[0].Nmissing);
+
+  ALLOCATE (catalog[0].average, Average, MAX (catalog[0].Naverage, 1));
+  ALLOCATE (catalog[0].measure, Measure, MAX (catalog[0].Nmeasure, 1));
+  ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+  if (catalog[0].Naverage == 0) {
+    /* this is a valid ending state: no stars */
+    if (VERBOSE) fprintf (stderr, "SUCCESS: no stars yet in catalog %s\n", filename);
+    fclose (f);
+    clear_lockfile ();
+    exit (0);
+  }
+
+  /* read average values */
+  Nitems = catalog[0].Naverage;
+  nitems = Fread (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (1)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  /* read measurements */
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fread (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (2)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  /* read missing */
+  Nitems = catalog[0].Nmissing;
+  nitems = Fread (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to read data from catalog file %s (3)\n", filename);
+    fclose (f);
+    exit (0);
+  }
+  
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing)\n", 
+	   catalog[0].Naverage, filename, catalog[0].Nmeasure, catalog[0].Nmissing);
+
+  for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+    Nmeas += catalog[0].average[i].Nm; 
+    Nmiss += catalog[0].average[i].Nn; 
+  }
+  if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+    fprintf (stderr, "ERROR: data in catalog %s is corrupt, sums don't check\n");
+    fprintf (stderr, "ERROR: Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+    fprintf (stderr, "ERROR: Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+    exit (0);
+  }
+
+  if (RESET) {
+    NotBad = (0xffff ^ 0xc003);
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      if ((catalog[0].average[i].code & ID_MOVING) &&
+	  (catalog[0].average[i].code & ID_BAD_OBJECT) &&
+	  (catalog[0].average[i].code & 0x0003)) {
+	/* this will set the correct bit for each to 0 */ 
+	catalog[0].average[i].code &= NotBad;
+      }
+    }
+    for (i = 0; i < catalog[0].Nmeasure; i++) {
+      catalog[0].measure[i].average &= ~PART_OF_TRAIL;
+    }
+  }
+
+
+  fclose (f);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/gcatstats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/gcatstats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/gcatstats.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "markstar.h"
+
+gcatstats (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  double *X1, *Y1;
+  int *N1;
+  Coords tcoords;
+  
+  gfits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  gfits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  gfits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  gfits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+  /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    DecCenter = 90.0;
+    RaCenter = 0.0;
+  }
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+  catstats[0].Area = (MaxDEC - MinDEC)*(MaxRA - MinRA) / cos (RAD_DEG*DecCenter);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    catstats[0].Area = 44.2;
+  }
+  catstats[0].density = catalog[0].Naverage / (3600*3600*catstats[0].Area);
+  catstats[0].spacing = 1.0 / (NSIGMA * catstats[0].density * 2*TRAIL_WIDTH);
+  fprintf (stderr, "Area, density, spacing: %f %f %f\n", catstats[0].Area, 
+	   catstats[0].density, catstats[0].spacing);
+  /* number of stars per square arcsec */
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, double, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, double, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    RD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, &catstats[0].coords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_coords_index (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/gregions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/gregions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/gregions.c	(revision 16632)
@@ -0,0 +1,134 @@
+# include "markstar.h"
+
+GSCRegion *gregions1 (catstats, Nregions)
+CatStats catstats[];
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  int i, j, k, x, y, done, nregion, nregion2, NREGION;
+  double ra, dec, dx, dy, Xo[4], Yo[4];
+  FILE *f;
+
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: could not open GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  nregion = 0;
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+
+  if (catstats[0].DEC[0] == 86.25) { /* pole region */
+    dec = 86.0;
+    for (ra = 0.1; ra < 370; ra+= 30.0) {
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion - 1) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  } else {
+    for (x = 0; x < 2; x++) {
+      for (y = 0; y < 2; y++) {
+	for (dx = -0.1; dx <= 0.1; dx += 0.2) {
+	  for (dy = -0.1; dy <= 0.1; dy += 0.2) {
+	    ra  = catstats[0].RA[x] + dx;
+	    dec = catstats[0].DEC[y] + dy;
+	    aregion (&region[nregion], f, ra, dec);
+	    done = FALSE;
+	    for (j = 0; (j < nregion) && !done; j++) {
+	      if (!strcmp (region[nregion].filename, region[j].filename)) {
+		done = TRUE;
+	      }
+	    }
+	    if (!done) {
+	      nregion ++;
+	    } 
+	    if (nregion == NREGION) {
+	      NREGION += 10;
+	      REALLOCATE (region, GSCRegion, NREGION);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "using %d regions\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "region %d: %f %f  %f %f\n", i, region[i].RA[0], region[i].RA[1], region[i].DEC[0], region[i].DEC[1]);
+    } 
+  }
+
+  REALLOCATE (region, GSCRegion, MAX (nregion, 1));
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
+
+GSCRegion *gregions2 (image, Nregions)
+Image *image;
+int *Nregions;
+{
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dr, dd, dec, ra;
+  int i, j, done, nregion, NREGION;
+  
+  f = fopen (GSCFILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find GSC region file %s\n", GSCFILE);
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "found %d region files:\n", nregion);
+    for (i = 0; i < nregion; i++) {
+      fprintf (stderr, "  %d %s\n", i, region[i].filename);
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/load_gsc_data.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/load_gsc_data.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/load_gsc_data.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+load_gsc_data (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes, Nregions;
+  double R, D, M, MagLimit;
+  FILE *f;
+  GSCRegion *region, *gregions1(), *gregions2();
+  
+  region = gregions1 (catstats, &Nregions);
+
+  MagLimit = MAX (MAX (BRIGHT_HALO_MAG, BRIGHT_XTRAIL_MAG), BRIGHT_YTRAIL_MAG); 
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  Nbytes = BLOCK*BYTES_STAR;
+  
+  for (j = 0; j < Nregions; j++) {
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "GSC file for region %s missing\n", region[j].filename);
+      exit (0);
+    }
+    
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > MagLimit) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, nstar);
+  catalog[0].Naverage = nstar;
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/load_gsc_data_ghost.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/load_gsc_data_ghost.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/load_gsc_data_ghost.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "markstar.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+/* this routine is basically identical to load_gsc_data, but
+   it is not limited to a single region file, and it merges the 
+   results */
+
+load_gsc_data_ghost (catalog, region, Nregion, image)
+Catalog catalog[];
+GSCRegion *region;
+int Nregion;
+Image image[];
+{
+
+  /* load data from the GSC files */
+  char filename[128];
+  char *tbuffer;
+  int nstar, NSTARS;
+  int i, j, Nbytes, nbytes;
+  double R, D, M, X, Y;
+  FILE *f;
+  Coords *tcoords;
+  int MinX, MinY, MaxX, MaxY;
+  
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog[0].average, Average, NSTARS);
+  tcoords = &image[0].coords;
+  MinX = 0;
+  MinY = 0;
+  MaxX = image[0].NX;
+  MaxY = image[0].NY;
+  
+  for (j = 0; j < Nregion; j++) {
+    
+    f = fopen (region[j].filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "no GSC file for region %s (2)\n", region[j].filename);
+      exit (0);
+    }
+    
+    Nbytes = BLOCK*BYTES_STAR;
+    while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+      for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	if (M > GHOST_MAG) continue;
+	dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	RD_to_XY (&X, &Y, R, D, tcoords);
+	if ((X < MinX) || (X > MaxX) || (Y < MinY) || (Y > MaxY)) continue;
+	catalog[0].average[nstar].R = R;
+	catalog[0].average[nstar].D = D;
+	catalog[0].average[nstar].M = M * 1000.0;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog[0].average, Average, NSTARS);
+	}
+      }
+    }
+    fclose (f);
+
+  }
+
+  free (tbuffer);
+  REALLOCATE (catalog[0].average, Average, MAX (nstar, 1));
+  catalog[0].Naverage = nstar;
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/mark_trail.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/mark_trail.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/mark_trail.c	(revision 16632)
@@ -0,0 +1,272 @@
+# include "markstar.h"
+int *make_common_list ();
+int *check_common_list ();
+
+mark_trail (catstats, mark, Nave, i, m, b, axis, catalog)
+     CatStats catstats[];
+     char *mark;
+     int i, Nave, axis;
+     double m, b;
+     Catalog catalog[];
+{
+
+  double *R, *D;
+  int j, k, jj, kk, N, NPTS, marked, start, end, Nm;
+  int *good, *seq, *N1;
+  double *dist, *dist2;
+  double d2, di, Di, dD, n, Dist, scale, norm;
+  double spacing;
+  int *list, Nlist;
+  int M, Nmeas, thisimage;
+
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  N1 = catstats[0].N;
+  spacing = catstats[0].spacing;
+
+  NPTS = 200;
+  ALLOCATE (good, int, NPTS);
+  ALLOCATE (dist, double, NPTS);
+  ALLOCATE (dist2, double, NPTS);
+  ALLOCATE (seq, int, NPTS);
+
+  /* Find all points which lie near line */
+  /* save the entry number and distance along line */
+  N = 0;
+  scale = sqrt (1.0 + m*m);
+
+  if (axis == 1) {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(R[j] - m*D[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (D[j] - D[i] + m*(R[j] - R[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  } else {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(D[j] - m*R[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (R[j] - R[i] + m*(D[j] - D[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  }
+  
+  if (N < NPTSINLINE) 
+    return (0);
+
+  sort_seq (dist, seq, N);
+  
+  start = -1; end = -1;
+  for (j = 0; j < N-1; j++) {
+    /* if we have part of a line, and next point is in the line, check for common images */
+    if ((start != -1) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      list = check_common_list (list, N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, dump list and continue */
+	end = j + 1;
+	if (end - start > NPTSINLINE) {
+	  if (axis == 0)
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	  else
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	  for (k = start; k < end; k++) {
+	    M = N1[good[seq[k]]];
+	    mark[good[seq[k]]] = TRUE;
+	    /* we need to mark measurements from all images in common on the line */
+	    Nm = 0;
+	    for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	      Nmeas = catalog[0].average[M].offset + jj;
+	      thisimage = catalog[0].image[Nmeas];
+	      for (kk = 0; kk < Nlist; kk++) {
+		if (thisimage == list[kk]) {
+		  catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		  Nm ++;
+		}
+	      }
+	    }
+	    /* if there is only 1 measurement, mark object as bad */
+	    if (catalog[0].average[M].Nm == Nm) {
+	      catalog[0].average[M].code = ID_TRAIL;
+	    }
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	}
+	start = -1;
+	end = -1;
+      }
+    }
+    /* if we haven't yet found a line segment, check for the beginning */
+    if ((start < 0) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      start = j;
+      list = make_common_list (N1[good[seq[j]]], N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, move on */
+	start = -1;
+	free (list);
+      }
+    }
+    /* if we have a complete line, check for validity.  if it has enough members,
+	 mark them and continue searching for lines */
+    if ((start != -1) && ((fabs(dist[j] - dist[j+1]) >= spacing) || (j == N-2))) {
+      end = j + 1;
+      if (end - start > NPTSINLINE) {
+	if (axis == 0)
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	else
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	for (k = start; k < end; k++) {
+	  M = N1[good[seq[k]]];
+	  mark[good[seq[k]]] = TRUE;
+	  if (catalog[0].average[M].code == ID_BLEED) continue;
+	  /* we need to mark measurements from all images in common on the line */
+	  Nm = 0;
+	  for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	    Nmeas = catalog[0].average[M].offset + jj;
+	    thisimage = catalog[0].image[Nmeas];
+	    for (kk = 0; kk < Nlist; kk++) {
+	      if (thisimage == list[kk]) {
+		catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		Nm ++;
+	      }
+	    }
+	  }
+	  /* if there is only 1 measurement, mark object as bad */
+	  if (catalog[0].average[M].Nm == Nm) {
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	  catalog[0].average[M].code = ID_TRAIL;
+	}
+      }
+      free (list);
+      start = -1;
+      end = -1;
+    }
+  }
+}
+
+
+/* I is Average seq number for star 1, J for star 2 */
+/* make a list of images in common between two measurements */
+int *make_common_list (I, J, Nlist, catalog)
+int I, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N1, N2, nlist, NLIST;
+  int *list;
+  int k, already;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+
+  for (i = 0; i < catalog[0].average[I].Nm; i++) {
+    N1 = catalog[0].average[I].offset + i;
+    if (catalog[0].image[N1] == -1)
+      continue; /* not a real measurement */
+    for (j = 0; j < catalog[0].average[J].Nm; j++) {
+      N2 = catalog[0].average[J].offset + j;
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (catalog[0].image[N1] == catalog[0].image[N2]) {
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (catalog[0].image[N1] == list[k]) { 
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = catalog[0].image[N1];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  REALLOCATE (list, int, MAX(nlist, 1));
+  *Nlist = nlist;
+  return (list);
+
+}
+
+
+
+/* J is Average seq number for star */
+
+int *check_common_list (inlist, J, Nlist, catalog)
+int *inlist, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N2, Ninlist;
+  int *list, NLIST, nlist;
+  int already, found, k;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+  Ninlist = *Nlist;
+
+  for (j = 0; j < catalog[0].average[J].Nm; j++) {
+    N2 = catalog[0].average[J].offset + j;
+    found = FALSE;
+    for (i = 0; !found && (i < Ninlist); i++) {
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (inlist[i] == catalog[0].image[N2]) {
+	found = TRUE;
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (inlist[i] == list[k]) {
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = inlist[i];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  /* if there are no common images, return the input list */
+  if (nlist != 0) {
+    free (inlist);
+    REALLOCATE (list, int, MAX(nlist, 1));
+    *Nlist = nlist;
+    return (list);
+  } else {
+    return (inlist);
+  }
+
+}
+
+
+/* measurements associated with image number -1 are not 
+   measurements we made, but are added, like USNO */
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/markstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/markstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/markstar.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "markstar.h"
+
+main (argc, argv)
+int argc;
+char **argv;
+{
+
+  FILE *f;
+  int i, Nstars, Nimage, Nregions, Nmissed;
+  Image *image, *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  FORCE_RUN = FALSE;
+  if ((i = get_argument (argc, argv, "-f"))) {
+    FORCE_RUN = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: markstar (catalog)\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  check_lockfile (); 
+  check_permissions (argv[1]);
+
+  gcatalog (argv[1], &catalog);
+
+  gcatstats (&catalog, &catstats);
+
+  image = find_images (&catstats, &Nimage);
+
+  match_images (&catalog, image, Nimage);
+    
+  find_bright_stars (&catalog, &catstats); 
+
+  find_ghosts (&catalog, &catstats, argv[1], image, Nimage);  
+
+  find_trails (&catalog, &catstats);  
+
+  wcatalog (argv[1], &catalog);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  clear_lockfile (); 
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/match_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/match_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/match_images.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "markstar.h"
+
+match_images (catalog, image, Nimage)
+Catalog catalog[];
+Image   image[];
+int Nimage;
+{
+  
+  int j, k, found;
+  unsigned int *start, *stop;
+
+  /* this must be allocated so future free will not fail */
+  ALLOCATE (catalog[0].image, int, MAX (catalog[0].Nmeasure, 1));
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (start, unsigned int, Nimage);
+  ALLOCATE (stop,  unsigned int, Nimage);
+  for (j = 0; j < Nimage; j++) {
+    start[j] = image[j].tzero - MAX(0.05*image[j].trate*image[j].NY, 1);
+    stop[j]  = image[j].tzero + MAX(1.05*image[j].trate*image[j].NY, 1);
+  }
+
+  for (j = 0; j < catalog[0].Nmeasure; j++) {
+    found = FALSE;
+    if (catalog[0].measure[j].t == 0) {
+      catalog[0].image[j] = -1;
+      found = TRUE;
+    }
+    for (k = 0; (k < Nimage) && !found; k++) {
+      if ((catalog[0].measure[j].t >= start[k]) && 
+	  (catalog[0].measure[j].t <= stop[k])) {
+	catalog[0].image[j] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      fprintf (stderr, "ERROR: can't find source image for this measurement: %d\n",
+	       catalog[0].measure[j].t);
+      exit (0);
+    }
+  }
+  free (start);
+  free (stop);
+}
+
+  /* this routine uses the time of each measurement to match the
+measurement with an image.  Since the measurement is only store to 1
+sec accuracy, which corresponds to roughly 30 rows at nominal speed,
+we can't tell exactly which image the star come from.  However, this
+doesn't matter, and in fact this helps a bit: a measurement from the
+top of one image is the same as from the bottom of the next.
+Therefore, we intentionally blur the edges of the images by 5%, which
+will help to tie together neighboring images... */
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/sorts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/sorts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/sorts.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "markstar.h"
+
+void sort_seq (double *X, int *S, int N) {
+
+# define SWAPFUNC(A,B){ \
+  double dtmp = X[A]; X[A] = X[B]; X[B] = dtmp; \
+  int    itmp = Y[A]; Y[A] = Y[B]; Y[B] = itmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/fixcat/src/wcatalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/fixcat/src/wcatalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/fixcat/src/wcatalog.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "markstar.h"
+
+wcatalog (catname, catalog)
+char *catname;
+Catalog catalog[];
+{
+  
+  int i, Nitems, nitems, status, mode;
+  char filename[128], line[256];
+  FILE *f;
+  struct stat filestat;
+
+  sprintf (filename, "%s/%s\0", CATDIR, catname);
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "mv %s %s~\0", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (0);
+    }
+  }
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create new catalog file: %s\n", filename);
+    exit (0);
+  }
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (filename, mode);
+  
+  gfits_modify (&catalog[0].header, "NSTARS", "%d", 1, catalog[0].Naverage);
+  gfits_modify (&catalog[0].header, "NMEAS", "%d", 1, catalog[0].Nmeasure);
+  gfits_modify (&catalog[0].header, "NMISS", "%d", 1, catalog[0].Nmissing);
+
+  gfits_modify (&catalog[0].header, "MARKSTAR", "%t", 1, TRUE);
+
+  nitems = Fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f, "char");
+  if (nitems != catalog[0].header.size) {
+    fprintf (stderr, "ERROR: failed to write header\n");
+    exit (0);
+  }
+
+  Nitems = catalog[0].Naverage;
+  nitems = Fwrite (catalog[0].average, sizeof(Average), Nitems, f, "average");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file aves %s\n", filename);
+    exit (0);
+  }
+  
+  Nitems = catalog[0].Nmeasure;
+  nitems = Fwrite (catalog[0].measure, sizeof(Measure), Nitems, f, "measure");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file meas %s\n", filename);
+    exit (0);
+  }
+
+  Nitems = catalog[0].Nmissing;
+  nitems = Fwrite (catalog[0].missing, sizeof(Missing), Nitems, f, "missing");
+  if (nitems != Nitems) {
+    fprintf (stderr, "ERROR: failed to write catalog file miss %s\n", filename);
+    exit (0);
+  }
+
+  fclose (f);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/Makefile	(revision 16632)
@@ -0,0 +1,44 @@
+default: gastro
+help:
+	@echo "make options: gastro (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/gastro
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+gastro: $(BIN)/gastro.$(ARCH)
+install: $(DESTBIN)/gastro
+
+GASTRO	= \
+$(SRC)/gastro.$(ARCH).o \
+$(SRC)/gstars.$(ARCH).o \
+$(SRC)/gargs.$(ARCH).o \
+$(SRC)/gcenter.$(ARCH).o \
+$(SRC)/granges.$(ARCH).o \
+$(SRC)/gfit.$(ARCH).o \
+$(SRC)/rotate.$(ARCH).o \
+$(SRC)/gproject.$(ARCH).o \
+$(SRC)/gheader.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/gfitpoly.$(ARCH).o \
+$(SRC)/get_region_coords.$(ARCH).o \
+$(SRC)/greference.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/getgsc.$(ARCH).o \
+$(SRC)/getptolemy.$(ARCH).o \
+$(SRC)/plotstuff.$(ARCH).o \
+$(SRC)/misc.$(ARCH).o
+
+$(GASTRO): $(INC)/gastro.h
+$(BIN)/gastro.$(ARCH): $(GASTRO)
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/gastro/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,13 @@
+
+ gastro-1-4:
+  * converted to gfits APIs (forces libfits 1.6)
+  * converted to new DVO APIs (forces libdvo 1.3)
+  * removed unused code
+  * better error-checking for ConfigInit
+
+ gastro-1-3:
+    minor fixes to use updates to average.d
+
+ gastro-1-2:
+    added support for dvo table modes / formats (libdvo v1.0)
+    minor changes to sync with libfits modes (libfits v1.4)
Index: /branches/eam_branch_20080223/Ohana/src/gastro/include/gastro.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/include/gastro.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/include/gastro.h	(revision 16632)
@@ -0,0 +1,115 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <kapa.h>
+
+double DEFAULT_RADIUS;
+double MINIMUM_RADIUS;
+double MAX_ERROR, MAX_NONLINEAR;
+double MIN_PRECISE;
+double CCD_PC1_1;
+double CCD_PC2_2;
+double CCD_PC1_2;
+double CCD_PC2_1;
+double NFIELD;
+double SEARCH_RADIUS;
+double MMIN;
+double ROT_ZERO;
+double dROT;
+double RA_OFFSET, DEC_OFFSET;
+double POLE_RA, POLE_DEC;
+int POLAR_ALIGNMENT;
+int NROT;
+int VERBOSE;
+int LONEOS_COORDS;
+int CATDUMP;
+int MATCHDUMP;
+int NOMATCHDUMP;
+int NEWPHOTCODE;
+int MIN_MATCHES;
+char *PHOTCODE;
+int FLIPX, FLIPY;
+int NPOLYTERMS;
+char CDROM[256];
+char CATDIR[256];
+char CATMODE[16];    /* raw, mef, split, mysql */
+char CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char REFCAT[256];
+char HEADER[256];
+int PLOTSTUFF;
+int MAGLIMS;
+int NMAX_STARS;
+char PhotCodeFile[256];
+
+int    FORCE;
+double F_RA;
+double F_DEC;
+
+char GSCFILE[256], GSCDIR[256], LONEOS_REGION_FILE[256];
+double ASEC_PIX;
+char ROUGH_ASTROMETRY[64];
+
+/* simple structure to carry around data on an array of stars */
+typedef struct {
+  double X;
+  double Y;
+  double mag;
+} SStars;
+
+typedef struct {
+  Coords coords;
+  float *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+typedef struct {
+  double R, D;
+  double r, b;
+} USNOdata;
+
+typedef struct {
+  int *match;
+  float *X, *Y;
+  int *N;
+} USNOstats;
+
+/*  this seems to be a problem: is not included from math.h with the -ansi flag */
+extern double hypot PROTO((double, double));
+
+SStars   *getptolemy          PROTO((CatStats *catstats, int *NSTARS));
+SStars   *getgsc              PROTO((CatStats *catstats, int *NSTARS));
+USNOdata *getusno	      PROTO((USNOstats *usnostats, CatStats *catstats, int *Nusno));
+SStars   *gstars	      PROTO((char *file, int *NSTARS, Coords *coords, int *NX, int *NY, double *dNdM));
+void 	  ConfigInit	      PROTO((int *argc, char **argv));
+void 	  DonePlotting	      PROTO((Graphdata *graphmode, int N));
+void 	  PlotReset	      PROTO((int N));
+void 	  PlotVector	      PROTO((int Npts, float *vect, int mode, int N));
+void 	  PrepPlotting	      PROTO((int Npts, Graphdata *graphmode, int N));
+void 	  XDead		      PROTO(());
+void   	  alter_header        PROTO((char *, char **, int, double, double, double, double, double, double, double, double, int));
+void 	  area_of_region      PROTO((CatStats *region));
+void 	  define_region	      PROTO((CatStats *catstats, Coords *coords, int NX, int NY));
+void   	  find_shift          PROTO((SStars *, SStars *, int, int, double, double, int *, double *, double *, double *));
+void 	  gargs		      PROTO((int *argc, char **argv, Coords *coords));
+int 	  gaussj	      PROTO((double **a, int n, double **b, int m));
+int 	  gcenter	      PROTO((SStars *stars1in, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *dR));
+int 	  get_region_coords   PROTO((double *ra, double *dec, int rnumber, char *side));
+int 	  gfit		      PROTO((SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *Radius, double *DR, int *Nmatch, int mode));
+void 	  gfitpoly	      PROTO((SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, double *Radius, double *DR, int *Nmatch));
+void 	  gheader	      PROTO((char *file, Coords coords, double dR, int Nmatch));
+void 	  gproject	      PROTO((SStars *catalog, SStars **stars, int Ncat, int *Nstars, Coords *coords, int NX, int NY, double dNdM, int N1));
+void 	  granges	      PROTO((SStars *stars1, SStars *stars2, int N1, int N2, int NPIX, double *gx, double *gy, double *gx0, double *gy0));
+int 	  greference	      PROTO((SStars **cat, int *Ncat, Coords *coords, int NX, int NY));
+void 	  hh_hms	      PROTO((double hh, int *hr, int *mn, double *sc));
+void 	  hms_format	      PROTO((char *line, double value));
+int       line_fit            PROTO((SStars *, SStars *, int, int, double, double, double, double, double *, double *, double *, double *, double *, double *, double *, double *));
+int 	  mk_polyterm	      PROTO((int n, int m, int norder));
+int 	  mk_vector	      PROTO((int n, int m, int norder));
+int 	  open_graph	      PROTO((int N));
+void   	  precess             PROTO((double *, double *, double, double));
+void   	  ranges              PROTO((SStars *, SStars *, int, int, double *, double *, double *, double *, double, double));
+void 	  rotate	      PROTO((SStars *stars, int Nstars, double angle, int Xo, int Yo));
+void 	  sort_stars	      PROTO((SStars *stars, int N));
+void      sort_lists          PROTO((double *X, double *Y, int *S, int N));
+void   	  stats               PROTO((char *, double *, double *, double *, double *, double));
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "gastro.h"
+
+void ConfigInit (int *argc, char **argv) {
+  
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "OFFSET_RADIUS",     "%lf", 0, &SEARCH_RADIUS);   // max allowed offset in gcenter
+  ScanConfig (config, "MIN_MATCHES",       "%d",  0, &MIN_MATCHES);     // min allowed fitted stars 
+  ScanConfig (config, "DEFAULT_RADIUS",    "%lf", 0, &DEFAULT_RADIUS);  // starting radius for matched fit
+  ScanConfig (config, "MINIMUM_RADIUS",    "%lf", 0, &MINIMUM_RADIUS);  // min allowed radius for matched fit
+  ScanConfig (config, "MAX_ERROR",         "%lf", 0, &MAX_ERROR);       // max allowed error for valid solution
+  ScanConfig (config, "MAX_NONLINEAR",     "%lf", 0, &MAX_NONLINEAR);   // max allowed shear |(11*22 - 12*21) / (L1*L2)|
+  ScanConfig (config, "CCD_PC1_1",         "%lf", 0, &CCD_PC1_1);       // guess if WCS is missing
+  ScanConfig (config, "CCD_PC2_2",         "%lf", 0, &CCD_PC2_2);       // guess if WCS is missing
+  ScanConfig (config, "CCD_PC1_2",         "%lf", 0, &CCD_PC1_2);       // guess if WCS is missing
+  ScanConfig (config, "CCD_PC2_1",         "%lf", 0, &CCD_PC2_1);       // guess if WCS is missing
+  ScanConfig (config, "ASEC_PIX",          "%lf", 0, &ASEC_PIX);        // guess if WCS is missing
+  ScanConfig (config, "NFIELD",            "%lf", 0, &NFIELD);          // search region in field units
+  ScanConfig (config, "NPOLYTERMS",        "%d",  0, &NPOLYTERMS);      // fit order
+  ScanConfig (config, "ROT_ZERO",          "%lf", 0, &ROT_ZERO);        // rotation search region
+  ScanConfig (config, "dROT",              "%lf", 0, &dROT);            // rotation search region
+  ScanConfig (config, "NROT",              "%d",  0, &NROT);            // rotation search region
+  ScanConfig (config, "POLAR_ALIGNMENT",   "%d",  0, &POLAR_ALIGNMENT); // apply polar alignment correction
+  ScanConfig (config, "POLAR_AXIS_RA",     "%lf", 0, &POLE_RA);         // true coords of pole (should be HA, not RA)
+  ScanConfig (config, "POLAR_AXIS_DEC",    "%lf", 0, &POLE_DEC);        // true coords of pole
+  ScanConfig (config, "RA_OFFSET",         "%lf", 0, &RA_OFFSET);       // ?? not well defined (should be euler angle)
+  ScanConfig (config, "DEC_OFFSET",        "%lf", 0, &DEC_OFFSET);      // ?? not well defined (should be euler angle)
+  ScanConfig (config, "LONEOS_REGIONS",    "%s",  0, LONEOS_REGION_FILE); // table of LONEOS regions to fix guess astrometry
+
+  ScanConfig (config, "GSCFILE",           "%s",  0, GSCFILE);          // location of sky table
+  ScanConfig (config, "GSCDIR",            "%s",  0, GSCDIR);           // location of HST GSC data 
+  ScanConfig (config, "USNO_CDROM",        "%s",  0, CDROM);            // location of USNO A data (USNO_A_DIR in gastro2)
+  ScanConfig (config, "ASTRO_REFCAT",      "%s",  0, REFCAT);           // which astrometry catalog to use
+  ScanConfig (config, "CATDIR",            "%s",  0, CATDIR);           // location of ptolemy-format ref data
+  ScanConfig (config, "ROUGH_ASTROMETRY",  "%s",  0, ROUGH_ASTROMETRY); // where to get initial guess (header, config)
+
+  if (strcasecmp (ROUGH_ASTROMETRY, "header") && 
+      strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    fprintf (stderr, "ROUGH_ASTROMETRY must be one of: header, config\n");
+    exit (0);
+  }
+  free (config);
+  free (file);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gargs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gargs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gargs.c	(revision 16632)
@@ -0,0 +1,125 @@
+# include "gastro.h"
+# define NARGS 2  /* minimum is:  gastro catalog */
+
+void ahelp () {
+
+  fprintf (stderr, "gastro -- astrometry for LONEOS\n");
+
+  fprintf (stderr, "  USAGE: gastro pixscale filename");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "  -dump (dump catalog stars, don't complete astrometry)\n");
+  fprintf (stderr, "  -mdmp (dump matched catalog stars)\n");
+  fprintf (stderr, "\n"); 
+  exit (0);
+
+}
+
+void gargs (int *argc, char **argv, Coords *coords) {
+  
+  int N;
+
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    ahelp ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  LONEOS_COORDS = FALSE;
+  if ((N = get_argument (*argc, argv, "-loneos"))) {
+    LONEOS_COORDS = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  NEWPHOTCODE = FALSE;
+  if ((N = get_argument (*argc, argv, "-p"))) {
+    NEWPHOTCODE = TRUE;
+    remove_argument (N, argc, argv);
+    PHOTCODE = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  PLOTSTUFF = FALSE;
+  if ((N = get_argument (*argc, argv, "-plot"))) {
+    PLOTSTUFF = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MAGLIMS = TRUE;
+  if ((N = get_argument (*argc, argv, "-maglims"))) {
+    MAGLIMS = FALSE;
+    remove_argument (N, argc, argv);
+  }
+
+  NMAX_STARS = 300;
+  if ((N = get_argument (*argc, argv, "-nstars"))) {
+    remove_argument (N, argc, argv);
+    NMAX_STARS = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-header"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-head"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPX = FALSE;
+  if ((N = get_argument (*argc, argv, "-fx"))) {
+    FLIPX = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPY = FALSE;
+  if ((N = get_argument (*argc, argv, "-fy"))) {
+    FLIPY = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FORCE = FALSE;
+  if ((N = get_argument (*argc, argv, "-coords"))) {
+    FORCE = TRUE;
+    remove_argument (N, argc, argv);
+    F_RA = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    F_DEC = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  CATDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-dump"))) {
+    CATDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-mdmp"))) {
+    MATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  NOMATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-cdmp"))) {
+    NOMATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != NARGS) {
+    fprintf (stderr, "USAGE: gastro filename\n");
+    exit (0);
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gastro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gastro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gastro.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "gastro.h"
+# define ABORT \
+{ Nmatch = 1; dR = 0; \
+  gheader (argv[1], coords, dR, Nmatch); \
+  exit (0); }
+
+int main (int argc, char **argv) {
+
+  int N1, N2, Ncat, NX, NY, Nmatch, Nminterms;
+  SStars *catalog, *stars1, *stars2;
+  struct timeval now, then;  
+  Coords coords;
+  double dNdM, dR, Radius;
+  
+  gettimeofday (&then, (void *) NULL);
+
+  ConfigInit (&argc, argv);
+  gargs (&argc, argv, &coords); 
+
+  /* load stars from image (*.cmp file) */
+  N1 = NMAX_STARS;  /* we only want a small number of stars */
+  stars1 = gstars (argv[1], &N1, &coords, &NX, &NY, &dNdM);
+
+  /* load stars from reference catalogs */
+  greference (&catalog, &Ncat, &coords, NX, NY);
+
+  /* get rough alignment with reference stars */
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  gcenter (stars1, stars2, N1, N2, &coords, NX, NY, &Radius);
+  free (stars2);
+
+  /* reload reference, get good astrometry */
+  if (!greference (&catalog, &Ncat, &coords, NX, NY)) ABORT;
+  /* NFIELD = 1.2; */
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  if (!gfit (stars1, stars2, N1, N2, &coords, NX, NY, &Radius, &dR, &Nmatch, 1)) ABORT;
+  free (stars2);
+ 
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  gfitpoly (stars1, stars2, N1, N2, &coords, &Radius, &dR, &Nmatch);
+
+  if (dR > MAX_ERROR) {
+    fprintf (stderr, "ERROR: bad solution! %f %f (%d stars)\n", dR, (dR / sqrt(1.0*Nmatch)), Nmatch);
+    ABORT;
+  }
+  fprintf (stderr, "good solution: %f %f (%d stars)\n", dR, (dR / sqrt(1.0*Nmatch)), Nmatch);
+
+  Nminterms = MIN_MATCHES;
+  switch (NPOLYTERMS) {
+  case 0:
+  case 1:
+    /* we don't really allow zero order fits */
+    Nminterms = MIN_MATCHES;
+    break;
+  case 2:
+    Nminterms = 20;
+    break;
+  case 3:
+    Nminterms = 40;
+    break;
+  }
+    
+  if (Nmatch <= Nminterms) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n", Nmatch);
+    ABORT;
+  }
+
+  gheader (argv[1], coords, dR, Nmatch);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+/*
+  free (stars2);
+
+  DEFAULT_RADIUS = DEFAULT_RADIUS / 4;
+  gproject (catalog, &stars2, Ncat, &N2, &coords, NX, NY, dNdM, N1);
+  if (!gfit (stars1, stars2, N1, N2, &coords, NX, NY, &Radius, &dR, &Nmatch, 0)) ABORT;
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gcenter.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gcenter.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gcenter.c	(revision 16632)
@@ -0,0 +1,255 @@
+# include "gastro.h"
+# define NSIGMA 2.0
+
+/* stars1.X,Y and stars2.X,Y are in image pixels 
+   stars2 (ref catalog) is approx, based on guess for scale */
+
+int gcenter (SStars *stars1in, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *dR) {
+
+  double mean, sigma, gx, gy, gx0, gy0, n, SearchRadius;
+  int NPIX, minN, Nmin, Nmin0;
+  int i, j, k;
+  double *N, *DX, *DY, *D2, *tX1, *tY1, *tX2, *tY2;
+  double rot, Rot, Smin, Smin0, s, Fmin, Fmin0, f;
+  double Xmin, Xmin0, Ymin, Ymin0;
+  double RA, DEC, RAo, DECo;
+  double dX, dY, refX, refY;
+  double cs, sn;
+  double dR1, dD1, dR2, dD2, d1, d2;
+  double *sx1, *sy1, *sx2, *sy2;
+  SStars *stars1;  
+  char c;
+  Graphdata graphdata;
+  float *xvect, *yvect;
+  int Nvect, NVECT;
+  
+  SearchRadius = NX * SEARCH_RADIUS;
+  xvect = yvect = NULL;
+  Nvect = 0;
+
+  if (PLOTSTUFF) {
+    NVECT = N1*N2;
+    ALLOCATE (xvect, float, NVECT);
+    ALLOCATE (yvect, float, NVECT);
+    graphdata.xmin = 0;
+    graphdata.xmax = 2000;
+    graphdata.ymin = 0;
+    graphdata.ymax =  4000;
+    graphdata.style = 2;
+    graphdata.ptype = 2;
+    graphdata.ltype = 0;
+    graphdata.etype = 0;
+    graphdata.color = 0;
+    graphdata.lweight = 0;
+    graphdata.size = 0.5;
+  }
+ 
+  /*  NPIX = MAX (300, sqrt (20*(N1*N2) / MIN (N1, N2))); */
+  /* NPIX = 10 * sqrt (N2); */
+  NPIX = 300;
+  mean = 2 * N1*N2 / (NPIX*NPIX);
+  sigma = sqrt (mean);
+  minN =  MAX (6, mean + NSIGMA*sigma);
+  fprintf (stderr, "N1: %d, N2: %d, minN: %d\n", N1, N2, minN);
+
+  ALLOCATE (N,    double, NPIX*NPIX);
+  ALLOCATE (DX,   double, NPIX*NPIX);
+  ALLOCATE (DY,   double, NPIX*NPIX);
+  ALLOCATE (D2,   double, NPIX*NPIX);
+
+  ALLOCATE (stars1, SStars, N1);
+  for (i = 0; i < N1; i++) {
+    stars1[i] = stars1in[i];
+  }
+  
+  if (PLOTSTUFF) {
+    for (i = 0; i < N1; i++) {
+      xvect[Nvect] = stars1in[i].X;
+      yvect[Nvect] = stars1in[i].Y;
+      Nvect ++;
+    }
+  }
+  if (PLOTSTUFF) {
+    PlotReset (0);
+    PrepPlotting (Nvect, &graphdata, 0);
+    PlotVector (Nvect, xvect, 0, 0);
+    PlotVector (Nvect, yvect, 1, 0);
+    DonePlotting (&graphdata, 0);
+    usleep (300000);
+    fprintf (stderr, "plotting %d points\n", Nvect);
+    fprintf (stderr, "type return to continue");
+    fscanf (stdin, "%c", &c);
+    Nvect = 0;
+  }
+
+  Xmin = Ymin = 0;
+  Fmin = Smin = 1000000.0;
+  rot = Rot = ROT_ZERO-dROT*NROT;
+  rotate (stars1, N1, Rot, (int)coords[0].crpix1, (int)coords[0].crpix2); 
+
+  graphdata.xmin = -200;
+  graphdata.xmax =  200;
+  graphdata.ymin = -200;
+  graphdata.ymax =  200;
+
+  ALLOCATE (tX1, double, N1);
+  ALLOCATE (tY1, double, N1);
+  ALLOCATE (tX2, double, N2);
+  ALLOCATE (tY2, double, N2);
+  for (i = 0; i < N2; i++) {
+    tX2[i] = stars2[i].X;
+    tY2[i] = stars2[i].Y;
+  }
+  for (Rot = ROT_ZERO-dROT*NROT; Rot <= ROT_ZERO+dROT*NROT; Rot += dROT) {
+    granges (stars1, stars2, N1, N2, NPIX, &gx, &gy, &gx0, &gy0);
+    bzero (N,   NPIX*NPIX*sizeof(double));
+    bzero (DX,  NPIX*NPIX*sizeof(double));
+    bzero (DY,  NPIX*NPIX*sizeof(double));
+    bzero (D2,  NPIX*NPIX*sizeof(double));
+    for (i = 0; i < N1; i++) {
+      tX1[i] = stars1[i].X;
+      tY1[i] = stars1[i].Y;
+    }
+    sx1 = tX1; sy1 = tY1;
+    for (i = 0; i < N1; i++, sx1++, sy1++) {
+      sx2 = tX2; sy2 = tY2;
+      for (j = 0; j < N2; j++, sx2++, sy2++) {
+	dX = *sx1 - *sx2;
+	dY = *sy1 - *sy2;
+	if (hypot (dX, dY) > SearchRadius) continue;
+	if (PLOTSTUFF) {
+	  xvect[Nvect] = stars1[i].X - stars2[j].X;
+	  yvect[Nvect] = stars1[i].Y - stars2[j].Y;
+	  Nvect ++;
+	}
+	k = NPIX*(int)(gx*dX+gx0) + (int)(gy*dY+gy0);
+	N[k]   += 1.0;
+	DX[k]  += dX;
+	DY[k]  += dY;
+	D2[k]  += dX*dX + dY*dY;
+      }
+    }
+
+    Fmin0 = 1000.0;
+    Smin0 = Nmin0 = Xmin0 = Ymin0 = 0;
+    for (k = 0; k < NPIX*NPIX; k++) {
+      n = N[k]; /* 1*/ 
+      if (n < minN)
+	continue;
+      s = D2[k] - (SQ(DX[k]) + SQ(DY[k])) / n; 
+      f = s / (pow(n,4.0)); /* = 12 ops */
+      
+      if (f < Fmin0) { 
+	Fmin0 = f;
+	Smin0 = s;
+	Nmin0 = n;
+	Xmin0 = DX[k] / n;
+	Ymin0 = DY[k] / n;
+      }
+    }
+    if (VERBOSE) fprintf (stderr, "best offset: %7.1f %7.1f at %.1f deg  (%f %f %d)\n", Xmin0, Ymin0, Rot, Fmin0, sqrt(Smin0), Nmin0);
+    if (Fmin0 < Fmin) {
+      Fmin = Fmin0;
+      Smin = Smin0;
+      Nmin = Nmin0;
+      Xmin = Xmin0;
+      Ymin = Ymin0;
+      rot  = Rot;
+    }
+    if (PLOTSTUFF) {
+      PlotReset (0);
+      PrepPlotting (Nvect, &graphdata, 0);
+      PlotVector (Nvect, xvect, 0, 0);
+      PlotVector (Nvect, yvect, 1, 0);
+      DonePlotting (&graphdata, 0);
+      usleep (300000);
+      fprintf (stderr, "plotting %d points\n", Nvect);
+      fprintf (stderr, "type return to continue");
+      fscanf (stdin, "%c", &c);
+      Nvect = 0;
+    }
+    
+    rotate (stars1, N1, dROT, (int)coords[0].crpix1, (int)coords[0].crpix2);
+  }
+  rotate (stars1, N1, -ROT_ZERO-dROT*NROT, (int)coords[0].crpix1, (int)coords[0].crpix2);
+
+  free (N);
+  free (DX);
+  free (DY);
+  free (D2);
+
+  /* dx = dy = 10 pix */
+  refX = coords[0].crpix1 - Xmin;
+  refY = coords[0].crpix2 - Ymin;
+  XY_to_RD (&RA, &DEC, refX, refY, coords);
+  XY_to_RD (&RAo, &DECo, (refX + 10), refY, coords);
+  dR1 = (RAo - RA)*cos(DEC*RAD_DEG);
+  dD1 = (DECo - DEC);
+  XY_to_RD (&RAo, &DECo, refX, (refY + 10), coords);
+  dR2 = (RAo - RA)*cos(DEC*RAD_DEG);
+  dD2 = (DECo - DEC);
+  d1 = coords[0].cdelt1;  d2 = coords[0].cdelt2;
+  cs = cos(RAD_DEG*rot);  sn = sin(RAD_DEG*rot);
+
+  coords[0].pc1_1 =  cs*dR1 / (10*d1) + sn*dR2 / (10*d1);    coords[0].pc1_2 = cs*dR2 / (10*d1) - sn*dR1 / (10*d1);
+  coords[0].pc2_1 =  cs*dD1 / (10*d2) + sn*dD2 / (10*d2);    coords[0].pc2_2 = cs*dD2 / (10*d2) - sn*dD1 / (10*d2);
+  coords[0].crval1 = RA;
+  coords[0].crval2 = DEC;
+
+  /* diameter of 1 pixel box */
+  *dR = 1*sqrt(Smin);
+
+  fprintf (stderr, "%f x %f, %f\n", 1/gx, 1/gy, *dR);
+  if (VERBOSE) fprintf (stderr, "using: %7.1f %7.1f at %.1f deg\n", Xmin, Ymin, rot);
+
+# if (0)
+  if (VERBOSE) {
+    fprintf (stderr, "%s\n", coords[0].ctype);
+    fprintf (stderr, "%f %f\n", coords[0].crval1, coords[0].crval2);
+    fprintf (stderr, "%f %f\n", coords[0].crpix1, coords[0].crpix2);
+    fprintf (stderr, "%f %f\n", coords[0].pc1_1, coords[0].pc1_2);
+    fprintf (stderr, "%f %f\n", coords[0].pc2_1, coords[0].pc2_2);
+    fprintf (stderr, "%f %f\n", coords[0].cdelt1, coords[0].cdelt2);
+  }
+# endif
+
+  DEFAULT_RADIUS = MAX ((5*NX / NPIX), DEFAULT_RADIUS);
+  return (TRUE);
+}
+
+  /* we now have Xmin, Ymin, rot, get coords in unrotate stars1 frame of correct crref 
+  RAo = coords[0].crval1;
+  DECo = coords[0].crval2;
+
+  cs = cos(RAD_DEG*rot);  sn = sin(RAD_DEG*rot);
+  refX = coords[0].crpix1;
+  refY = coords[0].crpix2;
+
+  coords[0].crpix1 =  Xmin*cs + Ymin*sn + refX;
+  coords[0].crpix2 = -Xmin*sn + Ymin*cs + refY;
+
+  xx = coords[0].pc1_1; xy = coords[0].pc1_2; 
+  yx = coords[0].pc2_1; yy = coords[0].pc2_2; 
+  coords[0].pc1_1 =  cs*xx + sn*xy;    coords[0].pc1_2 = cs*xy - sn*xx;
+  coords[0].pc2_1 =  cs*yx + sn*yy;    coords[0].pc2_2 = cs*yy - sn*yx;
+
+  XY_to_RD (&RA, &DEC, refX, refY, coords);
+  if (fabs(RAo - RA) > 90) {
+    RA = (RA > 180.0) ? (RA - 180) : (RA + 180);
+    DEC = (DEC > 0.0) ? (180.0 - DEC) : (-180.0 - DEC);
+  }
+  coords[0].crval1 = RA;
+  coords[0].crval2 = DEC;
+  coords[0].crpix1 = refX;
+  coords[0].crpix2 = refY;
+
+  Rot = RAo - RA;
+  cs = cos(RAD_DEG*rot);  sn = sin(RAD_DEG*rot);
+  xx = coords[0].pc1_1; xy = coords[0].pc1_2; 
+  yx = coords[0].pc2_1; yy = coords[0].pc2_2; 
+  coords[0].pc1_1 =  cs*xx + sn*xy;    coords[0].pc1_2 = cs*xy - sn*xx;
+  coords[0].pc2_1 =  cs*yx + sn*yy;    coords[0].pc2_2 = cs*yy - sn*yx;
+
+  
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/get_region_coords.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/get_region_coords.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/get_region_coords.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "gastro.h"
+# define NBYTE_LINE 53
+# define NLINES 100
+
+int get_region_coords (double *ra, double *dec, int rnumber, char *side) {
+  
+  FILE *f;
+  int i, j, done, found, Nbytes, Nline, num, NBYTES;
+  char *buffer;
+  double R, D;
+  
+  f = fopen (LONEOS_REGION_FILE, "r");
+  if (f == NULL) {
+    fprintf (stderr, "couldn't find region map %s\n", LONEOS_REGION_FILE);
+    return (FALSE);
+  }
+ 
+  NBYTES = NBYTE_LINE * NLINES;
+  ALLOCATE (buffer, char, NBYTES);
+ 
+  found = done = FALSE;
+  for (i = 0; !done && !found; i++) {
+    Nbytes = fread (buffer, sizeof(char), NBYTES, f);
+    if (Nbytes < 1) done = TRUE;
+    Nline = Nbytes / NBYTE_LINE;
+    for (j = 0; !found && (j < Nline); j++) {
+      num = atof (&buffer[j*NBYTE_LINE]);
+      if (num == rnumber) {
+	found = TRUE;
+	sscanf (&buffer[j*NBYTE_LINE], "%*d %lf %lf", &R, &D);
+	fwrite (&buffer[j*NBYTE_LINE], 1, 106, stderr);
+	fprintf (stderr, "\n\n%f %f\n", R, D);
+	if (!strncasecmp (side, "east", 4)) {
+	  R += 0.026 / cos (D);  
+	  /* if the word says "east", we need to offset by 1 chip width,
+	     R and D are in radians here, so 0.026 is 1.5 deg in radians */
+	}
+	R *= (180.0 / M_PI);
+	D *= (180.0 / M_PI);
+      }
+    }
+  }
+
+  free (buffer);
+  fclose (f);
+
+  if (!found) {
+    fprintf (stderr, "error: can't find desired region number %d\n", rnumber);
+    *ra = *dec = 0;
+    return (FALSE);
+  }
+
+  *ra = R;
+  *dec = D;
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/getgsc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/getgsc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/getgsc.c	(revision 16632)
@@ -0,0 +1,86 @@
+# include "gastro.h"
+# define BYTES_STAR 23
+# define BLOCK 1000
+
+SStars *rd_gsc (char *filename, int *Nstars);
+
+SStars *getgsc (CatStats *catstats, int *NSTARS) {
+  
+  int i, j, k, Ns, Ngsc, Nstars; 
+  SStars *gsc;
+  SStars *stars;
+  SkyList *skylist;
+  SkyTable *sky;
+  SkyRegion patch;
+
+  patch.Rmin = catstats[0].RA[0];
+  patch.Rmax = catstats[0].RA[1];
+  patch.Dmin = catstats[0].DEC[0];
+  patch.Dmax = catstats[0].DEC[1];
+
+  /* load regions from GSC table, restrict to patch */
+  sky = SkyTableFromGSC (GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, GSCDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, &patch);
+  
+  Nstars = 0;
+  ALLOCATE (stars, SStars, 1);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    gsc = rd_gsc (skylist[0].filename[i], &Ngsc);
+
+    Ns = Nstars;
+    Nstars += Ngsc;
+
+    REALLOCATE (stars, SStars, MAX (1, Nstars));
+    for (k = Ns, j = 0; j < Ngsc; k++, j++) {
+      stars[k].X   = gsc[j].X;
+      stars[k].Y   = gsc[j].Y;
+      stars[k].mag = gsc[j].mag;
+    }      
+    free (gsc);
+  }
+  SkyTableFree (sky);
+
+  *NSTARS = Nstars;
+  return (stars);
+}  
+
+SStars *rd_gsc (char *filename, int *Nstars) {
+  
+  SStars *stars;
+  int i, NSTAR, nstar, Nbytes, nbytes;
+  char *buffer;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find catalog file %s\n", filename);
+    exit (1);
+  }
+  
+  nstar = 0;
+  NSTAR = 1000;
+  ALLOCATE (stars, SStars, NSTAR);
+
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  Nbytes = BLOCK*BYTES_STAR;
+
+  while ((nbytes = fread (buffer, 1, Nbytes, f)) > 0) {
+    for (i = 0; i < nbytes / BYTES_STAR; i++) {
+      dparse (&stars[nstar].X, 1, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].Y, 2, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].mag, 3, &buffer[i*BYTES_STAR]);
+      nstar++;
+      if (nstar == NSTAR) {
+	NSTAR += 1000;
+	REALLOCATE (stars, SStars, NSTAR);
+      }
+    }
+  }
+
+  free (buffer);
+
+  *Nstars = nstar;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/getptolemy.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/getptolemy.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/getptolemy.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "gastro.h"
+
+SStars *getptolemy (CatStats *catstats, int *NSTARS) {
+  
+  int i, j, k, Ns, Nstars; 
+  Catalog catalog;
+  SStars *stars;
+  SkyList *skylist;
+  SkyTable *sky;
+  SkyRegion patch;
+
+  patch.Rmin = catstats[0].RA[0];
+  patch.Rmax = catstats[0].RA[1];
+  patch.Dmin = catstats[0].DEC[0];
+  patch.Dmax = catstats[0].DEC[1];
+
+  Nstars = 0;
+  ALLOCATE (stars, SStars, 1);
+
+  /* load regions from GSC table, restrict to patch */
+  sky = SkyTableLoadOptimal (CATDIR, NULL, GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, &patch);
+  
+  for (i = 0; i <skylist[0].Nregions; i++) {
+    // set the parameters which guide catalog open/load/create
+    catalog.filename  = skylist[0].filename[i];
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS;
+    catalog.Nsecfilt  = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    // Naves_disk == 0 implies an empty catalog file
+    // for only_match, skip empty catalogs
+    if (!catalog.Naves_disk) {
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    Ns = Nstars;
+    Nstars += catalog.Naverage;
+
+    REALLOCATE (stars, SStars, MAX (1, Nstars));
+    for (k = Ns, j = 0; j < catalog.Naverage; k++, j++) {
+      stars[k].X = catalog.average[j].R;
+      stars[k].Y = catalog.average[j].D;
+      stars[k].mag = catalog.measure[catalog.average[j].offset].M;
+    }      
+    dvo_catalog_free (&catalog);
+  }
+
+  if (VERBOSE) fprintf (stderr, "%d stars from PTOLEMY\n", Nstars);
+  *NSTARS = Nstars;
+  return (stars);
+}  
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/getusno.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/getusno.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/getusno.c	(revision 16632)
@@ -0,0 +1,131 @@
+# include "gastro.h"
+# define NZONE 24
+
+int SPDzone[] = {
+  0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 
+  675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+
+int USNOdisk[] = {
+  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10};
+
+USNOdata *getusno (USNOstats *usnostats, CatStats *catstats, int *Nusno) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128], c;
+  FILE *f;
+  double DEC1;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end, disk;
+  int NUSNO, nusno;
+  USNOdata *usno;
+
+  iRA0 = catstats[0].RA[0] * 360000.0;
+  iRA1 = catstats[0].RA[1] * 360000.0;
+  iDEC0 = (catstats[0].DEC[0] + 90.0) * 360000.0;
+  iDEC1 = (catstats[0].DEC[1] + 90.0) * 360000.0;
+  
+  spd_start = (int)(    (catstats[0].DEC[0] + 90) / 7.5) * 75.0;
+  DEC1 = (catstats[0].DEC[1] + 90) / 7.5;
+  if (DEC1 > (int)(DEC1)) {
+    spd_end =   (int)(1 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  }
+
+  NUSNO = 5000;
+  ALLOCATE (usno, USNOdata, NUSNO);
+  nusno = 0;
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find cdrom for spd %d\n",  spd);
+      exit (0);
+    }
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc", CDROM, spd); 
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s, is cdrom %d in drive?\n", filename, disk);
+      fprintf (stderr, "press return when ready to continue: ");
+      fscanf (stdin, "%c", &c);
+      fprintf (stderr, "trying again...\n");
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "still can't open file %s, is cdrom %d in drive?\n", filename, disk);
+	exit (0);  
+      }
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].RA[0] / 3.75;
+    if ((catstats[0].RA[1] / 3.75) == (int) (catstats[0].RA[1] / 3.75)) 
+      last  = catstats[0].RA[1] / 3.75;
+    else 
+      last  = 1 + catstats[0].RA[1] / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "RA out of range\n");
+      exit (0);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat", CDROM, spd);
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open file %s\n", filename);
+      exit (0);
+    }
+    /* advance file pointer to first slice */
+    offset = 3*sizeof(int)*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+    /* on each loop, load data from an RA slice of the catalog */
+    for (bin = first; bin < last; bin++) {
+      Nitems = 3*number[bin];
+      ALLOCATE (buffer, int, Nitems);
+      nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+      if (nitems != Nitems) {
+	fprintf (stderr, "error reading data from file %s (%d, %d, %d)\n", 
+		 filename, start[bin], number[bin], nitems);
+	exit (0);
+      }
+      buf = buffer;
+      /* print out data from slice within RA and DEC range */
+      for (i = 0; i < number[bin]; i++, buf+=3) {
+	if ((buf[0] > iRA0) && (buf[0] < iRA1) &&
+	    (buf[1] > iDEC0) && (buf[1] < iDEC1)) {
+	  usno[nusno].R = buf[0]/360000.0;
+	  usno[nusno].D = buf[1]/360000.0 - 90.0;
+	  usno[nusno].r = 0.1*(buf[2] - 1000*((int)(buf[2]/1000)));
+	  usno[nusno].b = 0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000);
+	  nusno ++;
+	  if (nusno == NUSNO - 1) {
+	    NUSNO += 5000;
+	    REALLOCATE (usno, USNOdata, NUSNO);
+	  }	  
+	}
+      }
+      free (buffer);
+    }
+    fclose (f);
+  }
+
+  REALLOCATE (usno, USNOdata, MAX (nusno, 1));
+  *Nusno = nusno;
+  return (usno);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gfit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gfit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gfit.c	(revision 16632)
@@ -0,0 +1,460 @@
+# include "gastro.h"
+
+/* stars1.X,Y and stars2.X,Y are both in image pixels. 
+   The conversion terms (X_O, X_X, etc) make linear 
+   corrections in pixel coordinates */
+
+int gfit (SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, int NX, int NY, double *Radius, double *DR, int *Nmatch, int mode) {
+  
+  int i, j, iteration, Niter, last, halt, first_j, *Nextra, extras;
+  int *tmpN1, *tmpN2;
+  double X_O, X_X, X_Y, dX;
+  double Y_O, Y_X, Y_Y, dY;
+  double x, y, x2, y2, xy, N, R, wt;
+  double X, Y, Xx, Yy, Xy, Yx;
+  double Dx, Dy, DD, d2X, d2Y;
+  double RA, DEC, radius, radius2, fratio;
+  double *tmpX1, *tmpX2, *tmpY1, *tmpY2;
+  double tX1, tX2, tY1, tY2;
+  double dS;
+
+  char c;
+  Graphdata graphdata;
+  float *xvect, *yvect;
+  float *xvect2, *yvect2;
+  int Nvect, NVECT;
+  int Nvect2, NVECT2;
+  
+  Nvect = NVECT = Nvect2 = NVECT2 = 0;
+  xvect = yvect = xvect2 = yvect2 = NULL;
+
+  if (PLOTSTUFF) {
+    NVECT2 = MAX(N1, N2);
+    NVECT = MAX(N1, N2);
+    ALLOCATE (xvect, float, NVECT);
+    ALLOCATE (yvect, float, NVECT);
+    ALLOCATE (xvect2, float, NVECT2);
+    ALLOCATE (yvect2, float, NVECT2);
+  }
+    
+
+  /* allocate space for star coords */
+  ALLOCATE (tmpX1, double, N1);
+  ALLOCATE (tmpY1, double, N1);
+  ALLOCATE (tmpN1, int, N1);
+  
+  ALLOCATE (tmpX2, double, N2);
+  ALLOCATE (tmpY2, double, N2);
+  ALLOCATE (tmpN2, int, N2);
+  ALLOCATE (Nextra, int, N2);
+  bzero (Nextra, sizeof(int) * N2);
+
+  dX = dY = N = 0;
+
+  /* assign and sort list */
+  for (i = 0; i < N1; i++) {
+    tmpX1[i] = stars1[i].X;
+    tmpY1[i] = stars1[i].Y;
+    tmpN1[i] = i;
+  }
+  if (N1 > 1) sort_coords_index (tmpX1, tmpY1, tmpN1, N1);
+
+   
+  /* choose iteration ranges */
+  fratio = 1.41421;
+  extras = halt = last = FALSE;
+  radius = *Radius;
+  Niter = 2 + log (radius/MINIMUM_RADIUS) / log (fratio);
+  
+  /* initial values for fit coeffs */
+  X_X = 1; X_Y = 0; X_O = 0;
+  Y_X = 0; Y_Y = 1; Y_O = 0;
+  
+  for (iteration = 0; iteration < Niter; iteration ++) {
+
+    if (iteration >= Niter - 1) { /* next loop is the last one */
+      radius *= fratio;
+      last = TRUE;
+    }
+
+    /* setup and define */
+    radius2 = radius*radius;
+    dX = dY = d2X = d2Y = x = y = x2 = y2 = xy = X = Y = Xx = Xy = Yx = Yy = N = R = 0;
+    for (i = 0; i < N2; i++) {
+      tmpX2[i] = (X_O) + (X_X)*stars2[i].X + (X_Y)*stars2[i].Y;
+      tmpY2[i] = (Y_O) + (Y_X)*stars2[i].X + (Y_Y)*stars2[i].Y;
+      tmpN2[i] = i;
+    }
+    
+    if (PLOTSTUFF) {
+      for (i = 0; i < N1; i++) {
+	xvect2[i] = tmpX1[i];
+	yvect2[i] = tmpY1[i];
+      }
+      Nvect2 = N1;
+
+      graphdata.xmin = 0;
+      graphdata.xmax = 2000;
+      graphdata.ymin = 4000;
+      graphdata.ymax =  0;
+      graphdata.style = 2;
+      graphdata.ptype = 3;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+    
+      PlotReset (1);
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+      Nvect2 = 0;
+
+      for (i = 0; i < N2; i++) {
+	xvect2[i] = tmpX2[i];
+	yvect2[i] = tmpY2[i];
+      }
+      Nvect2 = N2;
+
+      graphdata.ptype = 1;
+
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+      Nvect2 = 0;
+    }
+
+    if (N2 > 1) sort_coords_index (tmpX2, tmpY2, tmpN2, N2);
+    
+    /* find matched stars */
+    for (i = j = 0; (i < N1) && (j < N2); ) {  
+      tX1 = tmpX1[i];
+      tX2 = tmpX2[j];
+      Dx = tX1 - tX2;
+      if (Dx <= -2.0*radius) {
+	i++;
+	continue;
+      }
+      if (Dx >= 2.0*radius) {
+	j++;
+	continue;
+      }
+
+      /**** possible improvement: find only the closest match 
+	    for stars that have more than one (save DD and i for each
+            cat star j */
+      /* in the right range */
+      first_j = j;
+      for (; (Dx > -2.0*radius) && (j < N2); j++) {
+	tY1 = tmpY1[i];
+	tX2 = tmpX2[j];
+	tY2 = tmpY2[j];
+	Dx = tX1 - tX2;
+	Dy = tY1 - tY2;
+	DD = Dx*Dx + Dy*Dy;
+	/* stars matched */
+	if (DD < radius2) {
+	  if (PLOTSTUFF) {
+	    xvect[Nvect] = Dx;
+	    yvect[Nvect] = tmpY1[i];
+	    Nvect ++;
+	    if (Nvect == NVECT) {
+	      NVECT += 100;
+	      REALLOCATE (xvect, float, NVECT);
+	      REALLOCATE (yvect, float, NVECT);
+	    }
+	    xvect2[Nvect2] = tmpX1[i];
+	    yvect2[Nvect2] = tmpY1[i];
+	    Nvect2 ++;
+	    if (Nvect2 == NVECT2 - 1) {
+	      NVECT2 += 100;
+	      REALLOCATE (xvect2, float, NVECT2);
+	    REALLOCATE (yvect2, float, NVECT2);
+	    }
+	  }
+	  /* wt = sqrt(sqrt(DD)); */
+	  wt = DD + 1;
+	  dX += Dx;
+	  dY += Dy;
+	  d2X += Dx*Dx;
+	  d2Y += Dy*Dy;
+	  x  += tX2/wt;
+	  y  += tY2/wt;
+	  x2 += tX2*tX2/wt;
+	  y2 += tY2*tY2/wt;
+	  xy += tX2*tY2/wt;
+	  X  += tX1/wt;
+	  Y  += tY1/wt;
+	  Xx += tX1*tX2/wt;
+	  Xy += tX1*tY2/wt;
+	  Yx += tY1*tX2/wt;
+	  Yy += tY1*tY2/wt;
+	  N  += 1.0;
+	  R  += 1.0/wt;
+	  if (last && MATCHDUMP && mode) {
+	    XY_to_RD (&RA, &DEC, stars2[tmpN2[j]].X, stars2[tmpN2[j]].Y, coords);
+	    fprintf (stdout, "%f %f %f %f %f\n", RA, DEC, stars2[tmpN2[j]].X, stars2[tmpN2[j]].Y, stars2[tmpN2[j]].mag);
+	  } 
+	}
+      }
+      j = first_j;
+      i++;
+    }
+    
+    if (PLOTSTUFF) {
+      
+      graphdata.xmin = 0;
+      graphdata.xmax = 2000;
+      graphdata.ymin = 4000;
+      graphdata.ymax =  0;
+      graphdata.style = 2;
+      graphdata.ptype = 2;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+
+      PrepPlotting (Nvect2, &graphdata, 1);
+      PlotVector (Nvect2, xvect2, 0, 1);
+      PlotVector (Nvect2, yvect2, 1, 1);
+      DonePlotting (&graphdata, 1);
+
+      graphdata.xmin = -150;
+      graphdata.xmax = 150;
+      graphdata.ymin = 0;
+      graphdata.ymax =  4000;
+      graphdata.style = 2;
+      graphdata.ptype = 2;
+      graphdata.ltype = 0;
+      graphdata.etype = 0;
+      graphdata.color = 0;
+      graphdata.lweight = 0;
+      graphdata.size = 1.5;
+    
+      PlotReset (0);
+      PrepPlotting (Nvect, &graphdata, 0);
+      PlotVector (Nvect, xvect, 0, 0);
+      PlotVector (Nvect, yvect, 1, 0);
+      DonePlotting (&graphdata, 0);
+      usleep (300000);
+      fprintf (stderr, "plotting %d points\n", Nvect);
+      fprintf (stderr, "type return to continue");
+      fscanf (stdin, "%c", &c);
+      Nvect = 0;
+    }
+
+    /* 
+    if (extras == 1) {
+      extras = 2;
+      halt = last = FALSE;
+      iteration -= 2;
+      radius *= fratio*fratio;
+    }
+    */
+
+    if (MATCHDUMP && mode && last) exit (0);
+    
+    if (NOMATCHDUMP && mode && last) {
+      for (i = 0; i < N2; i++) {
+	XY_to_RD (&RA, &DEC, stars2[i].X, stars2[i].Y, coords);
+	fprintf (stdout, "%f %f %f %f %f\n", RA, DEC, stars2[i].X, stars2[i].Y, stars2[i].mag);
+      }
+      exit (0);
+    }
+    
+    /* calculate the fit parameters */
+    if (!last) { 
+      double XX1, XY1, YX1, YY1, XO1, YO1;
+      double XX0, XY0, YX0, YY0, XO0, YO0;
+      double **matrix, **vector;
+      int NR, NC;
+      
+      if (VERBOSE) fprintf (stderr, "radius: %f, No. of matched stars: %d\n", radius, (int) N);
+      
+      if (N < 3) {
+	fprintf (stderr, "ERROR: too few stars\n");
+	X_O = X_X = X_Y = Y_O = Y_X = Y_Y = 0;
+	return (FALSE);
+      }
+      
+      NR = 3; NC = 2;
+      ALLOCATE (matrix, double *, NR);
+      ALLOCATE (vector, double *, NR);
+      for (i = 0; i < NR; i++) {
+	ALLOCATE (matrix[i], double, NR);
+	ALLOCATE (vector[i], double, NC);
+	bzero (vector[i], NC*sizeof(double));
+	bzero (matrix[i], NR*sizeof(double));
+      }
+
+      matrix[0][0] = R;
+      matrix[0][1] = matrix[1][0] = x;
+      matrix[0][2] = matrix[2][0] = y;
+      matrix[1][2] = matrix[2][1] = xy;
+      matrix[1][1] = x2;
+      matrix[2][2] = y2;
+
+      vector[0][0] = X;
+      vector[1][0] = Xx;
+      vector[2][0] = Xy;
+
+      vector[0][1] = Y;
+      vector[1][1] = Yx;
+      vector[2][1] = Yy;
+
+      dgaussjordan (matrix, vector, NR, NC); 
+      
+      /* 
+      Sx2 = x2 - x*x/N;
+      Sy2 = y2 - y*y/N;
+      Sxy = xy - x*y/N;
+      SXx = Xx - X*x/N;
+      SXy = Xy - X*y/N;
+      SYx = Yx - Y*x/N;
+      SYy = Yy - Y*y/N;
+      */
+
+      XX0 = X_X; XY0 = X_Y; XO0 = X_O;
+      YX0 = Y_X; YY0 = Y_Y; YO0 = Y_O;
+      
+      /* fit parameters relative to rotated frame */
+      /* 
+      XX1 = (SXx*Sy2 - SXy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      XY1 = (SXy*Sx2 - SXx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      XO1 = X/N - (XX1)*x/N - (XY1)*y/N;
+      
+      YX1 = (SYx*Sy2 - SYy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      YY1 = (SYy*Sx2 - SYx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+      YO1 = Y/N - (YX1)*x/N - (YY1)*y/N;
+      */
+
+      XO1 = vector[0][0];
+      XX1 = vector[1][0];
+      XY1 = vector[2][0];
+			
+      YO1 = vector[0][1];
+      YX1 = vector[1][1];
+      YY1 = vector[2][1];
+
+      fprintf (stderr, "%f %f %f\n", vector[0][0], vector[1][0], vector[2][0]);
+      fprintf (stderr, "%f %f %f\n", vector[0][1], vector[1][1], vector[2][1]);
+
+      /* fit parameters relative to original frame */
+      X_X = XX1*XX0 + XY1*YX0;
+      X_Y = XX1*XY0 + XY1*YY0;
+      X_O = XX1*XO0 + XY1*YO0 + XO1;
+      
+      Y_X = YX1*XX0 + YY1*YX0;
+      Y_Y = YX1*XY0 + YY1*YY0;
+      Y_O = YX1*XO0 + YY1*YO0 + YO1;
+      
+    }
+    dX = sqrt(d2X/N - dX*dX/(N*N));  /* scatter in pixels in the X direction */
+    dY = sqrt(d2Y/N - dY*dY/(N*N));  /* scatter in pixels in the Y direction */
+    dS = hypot (dX, dY) / sqrt(N);
+    if (VERBOSE) {
+      fprintf (stderr, "scatter in pixels: %5.2f x %5.2f -- %5.2f %d %d %d %d\n", dX, dY, dS, halt, last, extras, iteration);
+    }
+# if (0)
+    if (!halt && !extras) {
+      if (iteration > 0) {
+	dSS = (Sprev - dS) / Sprev;
+      } else {
+	dSS = 1.0;
+      }
+      if (dSS < 0.05) { /* no fractional improvement, stop at last value */
+	radius = Rprev * fratio;
+	halt = TRUE;
+	/* recalculate fit parameters on first, get scatter on second, exit on third */
+      }
+      Rprev = radius;
+      Sprev = dS;
+    }
+# endif
+    radius /= fratio;
+  }
+  radius *= fratio;
+  
+  /* convert X_X, etc to coords */ 
+  { 
+    double X0, Y0, S1, S2, p11, p21, p12, p22;
+    double delt, A, B, C, D, dRot;
+    
+    *Nmatch = N;
+    
+    delt = 1.0 / (X_X*Y_Y - X_Y*Y_X);
+    X = (coords[0].crpix1 - X_O);
+    Y = (coords[0].crpix2 - Y_O);
+    X0 = delt * (X*Y_Y - Y*X_Y);
+    Y0 = delt * (Y*X_X - X*Y_X);
+    XY_to_RD (&RA, &DEC, X0, Y0, coords);
+    
+    S1 = coords[0].cdelt1;
+    S2 = coords[0].cdelt2;
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    A =  S1*p11*Y_Y - S2*p12*Y_X;   B = S2*p12*X_X - S1*p11*X_Y;
+    C =  S1*p21*Y_Y - S2*p22*Y_X;   D = S2*p22*X_X - S2*p21*X_Y;
+    
+    coords[0].cdelt1 = sqrt (A*A + C*C);
+    coords[0].cdelt2 = sqrt (B*B + D*D);
+    
+    coords[0].pc1_1 = A / coords[0].cdelt1; 
+    coords[0].pc1_2 = B / coords[0].cdelt2; 
+    coords[0].pc2_1 = C / coords[0].cdelt1; 
+    coords[0].pc2_2 = D / coords[0].cdelt2; 
+    
+    coords[0].cdelt1 = coords[0].cdelt1 * delt;
+    coords[0].cdelt2 = coords[0].cdelt2 * delt;
+    if ((fabs(coords[0].cdelt1) > 2.0*ASEC_PIX/3600.0) || 
+	(fabs(coords[0].cdelt1) < 0.5*ASEC_PIX/3600.0) ||
+	(fabs(coords[0].cdelt2) > 2.0*ASEC_PIX/3600.0) || 
+	(fabs(coords[0].cdelt2) < 0.5*ASEC_PIX/3600.0)) {
+      fprintf (stderr, "ERROR: absurd solution\n");
+      return (FALSE);
+    }
+    
+    dRot = coords[0].crval1 - RA ;
+    coords[0].crval1 = RA;
+    coords[0].crval2 = DEC;
+    
+    A = cos (dRot*RAD_DEG);
+    B = sin (dRot*RAD_DEG);
+
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    coords[0].pc1_1 = p11*A - p12*B;
+    coords[0].pc1_2 = p11*B + p12*A;
+    coords[0].pc2_1 = p21*A - p22*B;
+    coords[0].pc2_2 = p21*B + p22*A;
+
+  }
+
+  while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+  while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+
+  *DR = sqrt (SQ(dX*coords[0].cdelt1*3600.0) + SQ(dY*coords[0].cdelt1*3600.0));
+  *Radius = radius;
+
+  if ((mode == 1) && VERBOSE) {
+    fprintf (stderr, "linear astrometric solution:\n");
+    fprintf (stderr, "mode: %s\n", coords[0].ctype);
+    fprintf (stderr, "ref value: %f %f\n", coords[0].crval1, coords[0].crval2);
+    fprintf (stderr, "ref pixel: %f %f\n", coords[0].crpix1, coords[0].crpix2);
+    fprintf (stderr, "ra  terms: %f %f\n", coords[0].pc1_1, coords[0].pc1_2);
+    fprintf (stderr, "dec terms: %f %f\n", coords[0].pc2_1, coords[0].pc2_2);
+    fprintf (stderr, "plt scale: %f %f\n", coords[0].cdelt1, coords[0].cdelt2);
+    fprintf (stderr, "accuracy:  %f %f\n", *DR, *DR / sqrt ((double)(*Nmatch)));
+  }
+
+  return (TRUE);
+
+  
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gfitpoly.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gfitpoly.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gfitpoly.c	(revision 16632)
@@ -0,0 +1,389 @@
+# include "gastro.h"
+
+void gfitpoly (SStars *stars1, SStars *stars2, int N1, int N2, Coords *coords, double *Radius, double *DR, int *Nmatch) {
+  
+  int i, j, m, n, M, N;
+  int first_j, last;
+  int *tmpN1, *tmpN2;
+  int NORDER, NTERM, NPARS, NPOWR;
+  double **sum, **xsum, **ysum;
+  double **matrix, **vector;
+  double Dx, Dy, DD, dX, dY, d2X, d2Y;
+  double radius, radius2;
+  double *tmpX1, *tmpX2, *tmpY1, *tmpY2;
+  double tX1, tX2, tY1, tY2;
+  double xterm, yterm, term, max;
+
+  NORDER = NPOLYTERMS;
+  NPOWR = NORDER + 1;
+  NTERM = 2*NORDER + 1;
+  NPARS = (NORDER + 1)*(NORDER + 2) / 2;
+  if (NPOLYTERMS < 2) {
+    coords[0].Npolyterms = 0;
+    {
+      double nominal_det, measure_det, min_det, max_det, d1, d2, diffangle, tmp;
+      
+      nominal_det = CCD_PC1_1 * CCD_PC2_2 - CCD_PC1_2 * CCD_PC2_1;
+      min_det = nominal_det / 1.05;
+      max_det = nominal_det * 1.05;
+      if (min_det > max_det) {
+	tmp = max_det; max_det = min_det; min_det = tmp;
+      }
+      
+      measure_det = coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1;
+      if ((measure_det > max_det) || (measure_det < min_det)) {
+	fprintf (stderr, "absurd solution, not cartesian\n");
+	*DR = 1e9;
+      }
+      d1 = hypot (coords[0].pc1_2, coords[0].pc1_1);
+      d2 = hypot (coords[0].pc2_2, coords[0].pc2_1);
+      diffangle = fabs (coords[0].pc2_1*coords[0].pc1_1 + coords[0].pc1_2*coords[0].pc2_2) / (d1*d2);
+      if (diffangle > MAX_NONLINEAR) {
+	fprintf (stderr, "absurd solution, not cartesian\n");
+	*DR = 1e9;
+      }
+    }
+    return;
+  }
+
+  fprintf (stderr, "\nattempting higher order fit\n");
+
+  /* allocate space for star coords */
+  ALLOCATE (tmpX1, double, N1);
+  ALLOCATE (tmpY1, double, N1);
+  ALLOCATE (tmpN1, int, N1);
+
+  ALLOCATE (tmpX2, double, N2);
+  ALLOCATE (tmpY2, double, N2);
+  ALLOCATE (tmpN2, int, N2);
+
+  /* assign and sort list */
+  for (i = 0; i < N1; i++) {
+    tmpX1[i] = stars1[i].X;
+    tmpY1[i] = stars1[i].Y;
+    tmpN1[i] = i;
+  }
+  if (N1 > 1) sort_coords_index (tmpX1, tmpY1, tmpN1, N1);
+  for (i = 0; i < N2; i++) {
+    tmpX2[i] = stars2[i].X;
+    tmpY2[i] = stars2[i].Y;
+    tmpN2[i] = i;
+  }
+  if (N2 > 1) sort_coords_index (tmpX2, tmpY2, tmpN2, N2);
+  
+  /* choose iteration ranges */
+  radius = MINIMUM_RADIUS;
+  radius2 = radius*radius;
+
+  /* allocate arrays for fit solution */
+  ALLOCATE (sum, double *, NTERM);
+  ALLOCATE (xsum, double *, NTERM);
+  ALLOCATE (ysum, double *, NTERM);
+  for (i = 0; i < NTERM; i++) {
+    ALLOCATE (sum[i], double, NTERM);
+    bzero (sum[i], NTERM*sizeof(double));
+    ALLOCATE (xsum[i], double, NTERM);
+    bzero (xsum[i], NTERM*sizeof(double));
+    ALLOCATE (ysum[i], double, NTERM);
+    bzero (ysum[i], NTERM*sizeof(double));
+  }
+  ALLOCATE (matrix, double *, NPARS);
+  ALLOCATE (vector, double *, NPARS);
+  for (i = 0; i < NPARS; i++) {
+    ALLOCATE (matrix[i], double, NPARS);
+    ALLOCATE (vector[i], double, 2);
+    bzero (vector[i], 2*sizeof(double));
+    bzero (matrix[i], NPARS*sizeof(double));
+  }
+  
+  /* do the following loop twice.  
+     on first pass, find the coeffs.
+     on next pass, find just the residuals */
+
+  dX = dY = d2X = d2Y = N = 0;
+  for (last = 0; last < 2; last++) {
+    if (last) {
+      /* assign values based on determined coeffs */
+      for (i = 0; i < N1; i++) {
+	tmpX1[i] = tmpY1[i] = 0;
+	yterm = 1;
+	for (m = 0; m < NPOWR; m++) { 
+	  xterm = 1;
+	  for (n = 0; n < NPOWR - m; n++) {
+	    tmpX1[i] += xterm*yterm*xsum[n][m];
+	    tmpY1[i] += xterm*yterm*ysum[n][m];
+	    xterm *= stars1[i].X;
+	  }	
+	  yterm *= stars1[i].Y;
+	}
+	tmpN1[i] = i;
+      }
+      if (N1 > 1) sort_coords_index (tmpX1, tmpY1, tmpN1, N1);
+      dX = dY = d2X = d2Y = N = 0;
+    }
+    /* find matched stars */
+    for (i = j = 0; (i < N1) && (j < N2); ) {  
+      tX1 = tmpX1[i];
+      tX2 = tmpX2[j];
+      Dx = tX1 - tX2;
+      if (Dx <= -2.0*radius) {
+	i++;
+	continue;
+      }
+      if (Dx >= 2.0*radius) {
+	j++;
+	continue;
+      }
+      /* in the right range */
+      first_j = j;
+      for (; (Dx > -2.0*radius) && (j < N2); j++) {
+	tY1 = tmpY1[i];
+	tX2 = tmpX2[j];
+	tY2 = tmpY2[j];
+	Dx = tX1 - tX2;
+	Dy = tY1 - tY2;
+	DD = Dx*Dx + Dy*Dy;
+	/* stars matched */
+	if (DD < radius2) {
+	  if (last) {  /* calculate residuals */
+	    dX += Dx;
+	    dY += Dy;
+	    d2X += Dx*Dx;
+	    d2Y += Dy*Dy;
+	    N  += 1.0; 
+	  } else {    /* accumulate data for coeffs */
+	    xterm = 1;
+	    for (n = 0; n < NTERM; n++) {
+	      yterm = 1;
+	      for (m = 0; m < NTERM; m++) {
+		term = xterm*yterm;
+		if (n+m < NTERM) {
+		  sum[n][m] += term;
+		}
+		if (n+m < NPOWR) {
+		  xsum[n][m] += tX2*term;
+		  ysum[n][m] += tY2*term;
+		}
+		yterm *= tY1;
+	      }
+	      xterm *= tX1;
+	    }
+	  }
+	}
+      }
+      j = first_j;
+      i++;
+    }
+    
+    if (!last) { /* calculate polyterm coeffs */
+      fprintf (stderr, "matched %.0f stars for polyterms\n", sum[0][0]);
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  vector[i][0] = xsum[n][m];
+	  vector[i][1] = ysum[n][m];
+	}	
+      }
+      j = 0;
+      for (M = 0; M < NPOWR; M++) {
+	for (N = 0; N < NPOWR - M; N++, j++) {
+	  i = 0;
+	  for (m = 0; m < NPOWR; m++) {
+	    for (n = 0; n < NPOWR - m; n++, i++) {
+	      matrix[i][j] = sum[n+N][m+M];
+	    }	
+	  }
+	}
+      }       
+      max = 0.0;
+      for (i = 0; i < NPARS; i++) {
+	for (j = 0; j < NPARS; j++) {
+	  max = MAX (max, fabs(matrix[i][j]));
+	}
+	max = MAX (max, fabs(vector[i][0]));
+	max = MAX (max, fabs(vector[i][1]));
+      }
+      for (i = 0; i < NPARS; i++) {
+	for (j = 0; j < NPARS; j++) {
+	  matrix[i][j] /= max;
+	}
+	vector[i][0] /= max;
+	vector[i][1] /= max;
+      }
+      /* svd (matrix, NPARS, vector, 2);  */
+      dgaussjordan (matrix, vector, NPARS, 2); 
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  xsum[n][m] = vector[i][0];
+	  ysum[n][m] = vector[i][1];
+	}	
+      }
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  fprintf (stderr, "RA x^%dy^%d: %10.4g    DEC x^%dy^%d: %10.4g \n", 
+		   n, m, vector[i][0], n, m, vector[i][1]);
+	}	
+      }
+    } else {
+      fprintf (stderr, "%d stars matched for residuals\n", N);
+      
+      dX = sqrt(d2X/N - dX*dX/(N*N));  /* scatter in pixels in the X direction */
+      dY = sqrt(d2Y/N - dY*dY/(N*N));  /* scatter in pixels in the Y direction */
+      if (VERBOSE) fprintf (stderr, "scatter in pixels: %5.2f x %5.2f -- %5.2f\n", dX, dY, hypot(dX,dY) / sqrt(N));
+      *DR = sqrt (SQ(dX*coords[0].cdelt1*3600.0) + SQ(dY*coords[0].cdelt1*3600.0));
+      *Nmatch = N;
+
+    }
+  } 
+
+  /* convert new terms to adjustments in coords and to polyterms */
+  {
+    double S1, S2, p11, p12, p21, p22;
+    double a0, a1, a2, b0, b1, b2, det;
+    double X, Y;
+    int Np, Nv;
+    
+    S1 = coords[0].cdelt1;
+    S2 = coords[0].cdelt2;
+    p11 = coords[0].pc1_1;    p12 = coords[0].pc1_2;
+    p21 = coords[0].pc2_1;    p22 = coords[0].pc2_2;
+    
+    /* get the correct vector entries for the linear terms */
+    N = mk_vector (0, 0, NORDER);
+    a0 = vector[N][0];  b0 = vector[N][1];
+    N = mk_vector (1, 0, NORDER);
+    a1 = vector[N][0];  b1 = vector[N][1];
+    N = mk_vector (0, 1, NORDER);
+    a2 = vector[N][0];  b2 = vector[N][1];
+
+    det = 1.0 / (a1*b2 - a2*b1);
+
+    coords[0].pc1_1 = p11*a1 + p12*b1*(S2/S1);
+    coords[0].pc2_1 = p21*a1 + p22*b1*(S2/S1);
+    
+    coords[0].pc1_2 = p12*b2 + p11*a2*(S1/S2);
+    coords[0].pc2_2 = p22*b2 + p21*a2*(S1/S2);
+    
+    X = (coords[0].crpix1 - a0);
+    Y = (coords[0].crpix2 - b0);
+    coords[0].crpix1 = det*(X*b2 - Y*a2);
+    coords[0].crpix2 = det*(Y*a1 - X*b1);
+
+    coords[0].Npolyterms = NORDER;
+    strcpy (coords[0].ctype, "DEC--PLY");
+
+    /* generate higher order terms from vector */
+
+    for (i = 0; i < NORDER + 1; i++) {
+      for (j = 0; j < (NORDER - i + 1); j++) {
+	if (i + j < 2) continue;
+	Np = mk_polyterm (i, j, NORDER);
+	Nv = mk_vector (i, j, NORDER);
+	coords[0].polyterms[Np][0] = det*(vector[Nv][0]*b2  - vector[Nv][1]*a2);  /* x2 y0 */
+	coords[0].polyterms[Np][1] = det*(vector[Nv][1]*a1  - vector[Nv][0]*b1);  /* x2 y0 */
+      }
+    }
+  }
+
+  while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+  while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+
+  {
+    double nominal_det, measure_det, min_det, max_det, tmp;
+    
+    nominal_det = CCD_PC1_1 * CCD_PC2_2 - CCD_PC1_2 * CCD_PC2_1;
+    min_det = nominal_det / 1.05;
+    max_det = nominal_det * 1.05;
+    if (min_det > max_det) {
+      tmp = max_det; max_det = min_det; min_det = tmp;
+    }
+    
+    measure_det = coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1;
+    if ((measure_det > max_det) || (measure_det < min_det)) {
+      fprintf (stderr, "absurd solution, not cartesian: %f (%f - %f)\n", measure_det, max_det, min_det);
+      *DR = 1e9;
+    }
+  }
+}
+
+int mk_polyterm (int n, int m, int norder) {
+  
+  int i, nt, N;
+  
+  N = 0;
+  nt = n + m;
+  for (i = 2; i < nt; i++) {
+    N += i + 1;
+  }
+  N += m;
+  return (N);
+}
+
+int mk_vector (int n, int m, int norder) {
+  
+  int i, N;
+  
+  N = 0;
+  for (i = 0; i < m; i++) {
+    N += (norder - i + 1);
+  }
+  N += n;
+  return (N);
+}
+
+
+
+/**********************
+
+  vector vs polyterms:
+
+  the variable 'vector' is similar to, but not exactly like polyterms. 
+  vector[i][j] provides coeffs for all of the x,y terms, 
+    polyterms[i][j] only provides coeffs for the terms or order > 2.
+
+  vector[i][j] and polyterms[i][j] also use a slightly different order:
+
+  vector[i][j] runs in this order:
+
+                   n     m  norder = 3
+  vector[0][0] * x^0 * y^0
+  vector[1][0] * x^1 * y^0
+  vector[2][0] * x^2 * y^0
+  vector[3][0] * x^3 * y^0
+  vector[4][0] * x^0 * y^1
+  vector[5][0] * x^1 * y^1
+  vector[6][0] * x^2 * y^1
+  vector[7][0] * x^0 * y^2
+  vector[8][0] * x^1 * y^2
+  vector[9][0] * x^0 * y^3
+
+  to generate the vector entry from n, m, norder:
+  N = 0;
+  for (i = 0; i < m; i++) {
+    N += (norder - i + 1);
+  }
+  N += n;
+
+  polyterms[i][j] runs in this order:
+
+                      n     m
+  polyterms[0][0] * x^2 * y^0 = vector[2][0]
+  polyterms[1][0] * x^1 * y^1 = vector[5][0]
+  polyterms[2][0] * x^0 * y^2 = vector[7][0]
+  polyterms[3][0] * x^3 * y^0 = vector[3][0]
+  polyterms[4][0] * x^2 * y^1 = vector[6][0]
+  polyterms[5][0] * x^1 * y^2 = vector[8][0]
+  polyterms[6][0] * x^0 * y^3 = vector[9][0]
+  
+  to generate the polyterms entry from n, m, norder:
+
+  N = 0;
+  nt = n + m;
+  for (i = 2; i < nt; i++) {
+    N += i + 1;
+  }
+  N += m;
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gheader.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gheader.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gheader.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include "gastro.h"
+
+void gheader (char *file, Coords coords, double dR, int Nmatch) {
+
+  Header header;
+  FILE *f, *g;
+  int i, oldsize, nbytes, status;
+  char line[1024];
+
+  if (!gfits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (3)\n", file);
+    exit(0);
+  }
+  oldsize = header.size;
+
+  /* validating the photcode name should be the job of DVO/addstar */
+  /* here we are only writing the selected photcode name to the header */
+  if (NEWPHOTCODE) {
+    gfits_modify (&header, "PHOTCODE", "%s", 1, PHOTCODE);
+  }    
+  
+  if (Nmatch < 2) {
+    gfits_modify (&header, "NASTRO", "%d", 1, 0);
+    gfits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+    goto skipstuff;
+  }
+  
+  gfits_modify (&header, "NASTRO", "%d", 1, Nmatch);
+  gfits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+
+  /*** use PutCoords to update header ***/
+  if (coords.Npolyterms > 1) {
+    gfits_modify (&header, "CTYPE1",   "%s",  1, "RA---PLY");
+    gfits_modify (&header, "CTYPE2",   "%s",  1, "DEC--PLY");
+  } else {
+    gfits_modify (&header, "CTYPE1",   "%s",  1, "RA---TAN");
+    gfits_modify (&header, "CTYPE2",   "%s",  1, "DEC--TAN");
+  }    
+  gfits_modify (&header, "CDELT1",   "%le", 1, coords.cdelt1); 
+  gfits_modify (&header, "CDELT2",   "%le", 1, coords.cdelt2);
+  gfits_modify (&header, "CRVAL1",   "%lf", 1, coords.crval1);
+  gfits_modify (&header, "CRVAL2",   "%lf", 1, coords.crval2);  
+  gfits_modify (&header, "CRPIX1",   "%lf", 1, coords.crpix1);
+  gfits_modify (&header, "CRPIX2",   "%lf", 1, coords.crpix2);
+  gfits_modify (&header, "PC001001", "%le", 1, coords.pc1_1);
+  gfits_modify (&header, "PC001002", "%le", 1, coords.pc1_2);
+  gfits_modify (&header, "PC002001", "%le", 1, coords.pc2_1);
+  gfits_modify (&header, "PC002002", "%le", 1, coords.pc2_2);
+  gfits_modify (&header, "NPLYTERM", "%d", 1, coords.Npolyterms);
+  if (coords.Npolyterms > 1) {
+    /* RA Terms */
+    gfits_modify (&header, "PCA1X2Y0", "%le", 1, coords.polyterms[0][0]);   /* polyterms[0]); */
+    gfits_modify (&header, "PCA1X1Y1", "%le", 1, coords.polyterms[1][0]);   /* polyterms[1]); */
+    gfits_modify (&header, "PCA1X0Y2", "%le", 1, coords.polyterms[2][0]);   /* polyterms[2]); */
+
+    if (coords.Npolyterms > 2) {
+      gfits_modify (&header, "PCA1X3Y0", "%le", 1, coords.polyterms[3][0]);   /* polyterms[3]); */
+      gfits_modify (&header, "PCA1X2Y1", "%le", 1, coords.polyterms[4][0]);   /* polyterms[4]); */
+      gfits_modify (&header, "PCA1X1Y2", "%le", 1, coords.polyterms[5][0]);   /* polyterms[5]); */
+      gfits_modify (&header, "PCA1X0Y3", "%le", 1, coords.polyterms[6][0]);   /* polyterms[6]); */
+    }
+    /* Dec Terms */
+    gfits_modify (&header, "PCA2X2Y0", "%le", 1, coords.polyterms[0][1]);   /* polyterms[7]); */
+    gfits_modify (&header, "PCA2X1Y1", "%le", 1, coords.polyterms[1][1]);   /* polyterms[8]); */
+    gfits_modify (&header, "PCA2X0Y2", "%le", 1, coords.polyterms[2][1]);   /* polyterms[9]); */
+
+    if (coords.Npolyterms > 2) {
+      gfits_modify (&header, "PCA2X3Y0", "%le", 1, coords.polyterms[3][1]);   /* polyterms[10]); */
+      gfits_modify (&header, "PCA2X2Y1", "%le", 1, coords.polyterms[4][1]);   /* polyterms[11]); */
+      gfits_modify (&header, "PCA2X1Y2", "%le", 1, coords.polyterms[5][1]);   /* polyterms[12]); */
+      gfits_modify (&header, "PCA2X0Y3", "%le", 1, coords.polyterms[6][1]);   /* polyterms[13]); */
+    }
+  }
+  gfits_modify (&header, "CERROR", "%lf", 1, dR);
+  gfits_modify (&header, "CERROR", "%C", 1, "scatter in astrometry soln (arcsec)");
+  gfits_modify (&header, "CPRECISE", "%lf", 1, dR / sqrt(1.0*Nmatch));
+  gfits_modify (&header, "CPRECISE", "%C", 1, "precision of astrometry soln (arcsec)");
+  gfits_modify (&header, "EQUINOX", "%lf", 1, 2000.0);
+  /* we force equinox to be 2000.0 for all images */
+
+skipstuff:
+  if (header.size > oldsize) {
+    if (VERBOSE) fprintf (stderr, "header expanded, creating new copy\n");
+    sprintf (line, "mv %s %s~", file, file);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", file);
+      exit (0);
+    }
+    sprintf (line, "%s~", file);
+    f = fopen (line, "r");
+    g = fopen (file, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", line);
+      exit(0);
+    }
+    if (g == NULL) {
+      fprintf (stderr, "ERROR: can't open output image file %s (4)\n", file);
+      exit(0);
+    }
+    nbytes = fwrite (header.buffer, 1, header.size, g);
+    fseek (f, oldsize, SEEK_SET);
+    for (i = 0; (nbytes = fread (header.buffer, 1, header.size, f)) > 0; i++) {
+      if (nbytes != fwrite (header.buffer, 1, nbytes, g)) {
+	fprintf (stderr, "ERROR: failure writing output data file\n");
+	exit (0);
+      }
+    }
+    fclose (f);
+    fclose (g);
+  } else {
+    f = fopen (file, "r+");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", file);
+      exit(0);
+    }
+    
+    fseek (f, 0, SEEK_SET);
+    nbytes = fwrite (header.buffer, 1, header.size, f);
+    
+    fclose (f);
+  }
+  free (header.buffer);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gproject.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gproject.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gproject.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "gastro.h"
+# define MMIN 2
+# define dM 0.5
+# define NMBIN 64
+
+void gproject (SStars *catalog, SStars **stars, int Ncat, int *Nstars, Coords *coords, int NX, int NY, double dNdM, int N1) {
+  
+  double mbin[NMBIN], ratio;
+  int i, j, NSTARS, nstar, nstar2;
+  double X, Y, m0, Mmin, Mmax;
+  int XMIN, XMAX, YMIN, YMAX;
+  SStars *tstars, *t2stars;
+
+  NSTARS = Ncat;
+  ALLOCATE (tstars, SStars, NSTARS);
+
+  XMIN = 0.5*(1.0 - NFIELD)*NX;
+  XMAX = 0.5*(1.0 + NFIELD)*NX;
+  YMIN = 0.5*(1.0 - NFIELD)*NY;
+  YMAX = 0.5*(1.0 + NFIELD)*NY;
+  
+  /* project to local coords, select stars within region */
+  for (nstar = i = 0; i < Ncat; i++) {
+    RD_to_XY (&X, &Y, catalog[i].X, catalog[i].Y, coords);
+    if ((X > XMIN) && (X < XMAX) && (Y > YMIN) && (Y < YMAX)) {
+      tstars[nstar].X = X;
+      tstars[nstar].Y = Y;
+      tstars[nstar].mag = catalog[i].mag;
+      nstar++;
+      if (CATDUMP) {
+	fprintf (stdout, "%f %f %f %f %f\n", catalog[i].X, catalog[i].Y, X, Y, catalog[i].mag);
+      }
+    }
+  }
+  if (CATDUMP) {
+    exit (0);
+  }
+
+  REALLOCATE (tstars, SStars, nstar);
+  if (VERBOSE) fprintf (stderr, "%d total reference stars\n", nstar);
+  
+  /* find appropriate magnitude range */ 
+  ratio = NFIELD * NFIELD;
+  m0 = 0;
+  bzero (mbin, NMBIN * sizeof (double));
+  for (i = 0; i < nstar; i++) {
+    if (tstars[i].mag < MMIN) {
+      fprintf (stderr, "%d %f %f %f\n", i, tstars[i].X, tstars[i].Y, tstars[i].mag);
+    }
+    j = (tstars[i].mag - MMIN) / dM;
+    j = MIN (MAX (j, 0), (NMBIN - 1));
+    mbin[j] ++;
+  }
+  for (i = 0; i < NMBIN; i++) {
+    if (ratio * dNdM < mbin[i] / dM) {
+      m0 = (i - 1) * dM + MMIN;
+      break;
+    }
+  }
+  
+  Mmin = m0 - 1.0;
+  Mmax = m0 + MAX (N1/dNdM, 1) + 1.0;
+  if (m0 == 0) {
+    Mmin = 0;
+    Mmax = 32;
+  }
+  if (VERBOSE) fprintf (stderr, "choosing magnitude range for reference stars: ");
+  if (VERBOSE) fprintf (stderr, " %5.2f to %5.2f mags\n", Mmin, Mmax);
+
+
+  ALLOCATE (t2stars, SStars, nstar);
+  if (MAGLIMS) {
+    /* make cut on mags */
+    for (nstar2 = i = 0; i < nstar; i++) {
+      if ((tstars[i].mag > Mmin) && (tstars[i].mag < Mmax)) { 
+	t2stars[nstar2] = tstars[i];
+	nstar2 ++;
+      }
+    }
+  } else {
+    bcopy (tstars, t2stars, nstar*sizeof(SStars));
+    nstar2 = nstar;
+  }
+    
+
+  free (tstars);
+  *stars = t2stars;
+  *Nstars = nstar2;
+  if (VERBOSE) fprintf (stderr, "%d reference stars in mag range\n\n", nstar2);
+
+}
+
+
+/* in this routine, 
+   catalog[i].X,Y are RA,DEC in dec degrees
+   stars[i].X.Y   are projected coords in approx pixels on image
+   */
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/granges.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/granges.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/granges.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "gastro.h"
+
+void granges (SStars *stars1, SStars *stars2, int N1, int N2, int NPIX, double *gx, double *gy, double *gx0, double *gy0) {
+
+  int i;
+  double maxX1, minX1, maxY1, minY1;
+  double maxX2, minX2, maxY2, minY2;
+  double Xzero, Xrange, Yzero, Yrange;
+
+  maxX1 = minX1 = stars1[0].X;
+  maxY1 = minY1 = stars1[0].Y;
+  for (i = 0; i < N1; i++) {
+    maxX1 = MAX (maxX1, stars1[i].X);    
+    minX1 = MIN (minX1, stars1[i].X);    
+    maxY1 = MAX (maxY1, stars1[i].Y);    
+    minY1 = MIN (minY1, stars1[i].Y);    
+  }
+
+  maxX2 = minX2 = stars2[0].X;
+  maxY2 = minY2 = stars2[0].Y;
+  for (i = 0; i < N2; i++) {
+    maxX2 = MAX (maxX2, (stars2[i].X));    
+    minX2 = MIN (minX2, (stars2[i].X));    
+    maxY2 = MAX (maxY2, (stars2[i].Y));    
+    minY2 = MIN (minY2, (stars2[i].Y));    
+  }
+
+  Xzero = minX1 - maxX2;
+  Yzero = minY1 - maxY2;
+  Xrange = ((maxX1 - minX1) + (maxX2 - minX2));
+  Yrange = ((maxY1 - minY1) + (maxY2 - minY2));
+  
+  *gx = (NPIX - 1.0) / Xrange;
+  *gy = (NPIX - 1.0) / Yrange;
+  *gx0  = (1.0 - NPIX)*Xzero/Xrange;
+  *gy0  = (1.0 - NPIX)*Yzero/Yrange;
+
+  fprintf (stderr, "gx, gy: %f %f\n", *gx, *gy);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/greference.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/greference.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/greference.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include "gastro.h"
+
+# define USNO 1
+# define GSC  0
+
+int greference (SStars **cat, int *Ncat, Coords *coords, int NX, int NY) {
+
+  int  i;
+  CatStats catstats;
+
+  if (VERBOSE) fprintf (stderr, "\nloading astrometric reference data from %s\n", REFCAT); 
+
+  *Ncat = 0;
+
+  define_region (&catstats, coords, NX, NY);
+  ALLOCATE (*cat, SStars, 1);
+
+  /* get stars from the USNO catalog for the given region */
+  if (!strcmp (REFCAT, "USNO") || !strcmp (REFCAT, "BOTH")) {
+    while (catstats.RA[0] > 360.0) catstats.RA[0] -= 360.0;
+    while (catstats.RA[0] <   0.0) catstats.RA[0] += 360.0;
+    while (catstats.RA[1] > 360.0) catstats.RA[1] -= 360.0;
+    while (catstats.RA[1] <   0.0) catstats.RA[1] += 360.0;
+
+    /* if RA crosses 0,360 boundary, do 2 passes */
+    if (catstats.RA[0] > catstats.RA[1]) {
+      int Nusno1, Nusno2;
+      USNOdata *usno1, *usno2;
+      USNOstats usnostats;
+      CatStats substats;
+
+      substats = catstats;
+      substats.RA[0] = 0.0;
+      usno1 = getusno (&usnostats, &substats, &Nusno1);
+
+      substats = catstats;
+      substats.RA[1] = 360.0;
+      usno2 = getusno (&usnostats, &substats, &Nusno2);
+
+      REALLOCATE (*cat, SStars, MAX (Nusno1 + Nusno2, 1));
+      for (i = 0; i < Nusno1; i++) {
+	cat[0][i].X = usno1[i].R;
+	cat[0][i].Y = usno1[i].D;
+	cat[0][i].mag = fabs(usno1[i].r);
+      }      
+      for (i = Nusno1; i < Nusno2; i++) {
+	cat[0][i].X = usno2[i].R;
+	cat[0][i].Y = usno2[i].D;
+	cat[0][i].mag = fabs(usno2[i].r);
+      }      
+      *Ncat = Nusno1 + Nusno2;
+      free (usno1);
+      free (usno2);
+    } else {
+      int Nusno;
+      USNOdata *usno;
+      USNOstats usnostats;
+
+      usno = getusno (&usnostats, &catstats, &Nusno);
+
+      REALLOCATE (*cat, SStars, MAX (Nusno, 1));
+      for (i = 0; i < Nusno; i++) {
+	cat[0][i].X = usno[i].R;
+	cat[0][i].Y = usno[i].D;
+	cat[0][i].mag = fabs(usno[i].r);
+      }      
+      *Ncat = Nusno;
+      free (usno);
+    }
+    if (VERBOSE) fprintf (stderr, "%d stars from USNO 1.0\n", *Ncat);
+  }
+
+  if (!strcmp (REFCAT, "GSC") || !strcmp (REFCAT, "BOTH")) {
+    int j, Ngsc;
+    SStars *gsc;
+
+    gsc = getgsc (&catstats, &Ngsc);
+    REALLOCATE (*cat, SStars, MAX (Ngsc + *Ncat, 1));
+    for (j = *Ncat, i = 0; i < Ngsc; i++) {
+      cat[0][j] = gsc[i];
+    }
+    if (VERBOSE) fprintf (stderr, "%d stars from HST GSC\n", Ngsc);
+    *Ncat += Ngsc;
+  }
+
+  if (!strcmp (REFCAT, "PTOLEMY")) {
+    free (*cat);
+    *cat = getptolemy (&catstats, Ncat);
+    if (VERBOSE) fprintf (stderr, "%d stars from PTOLEMY\n", *Ncat);
+  }
+  return (TRUE);
+}
+
+void define_region (CatStats *catstats, Coords *coords, int NX, int NY) {
+   
+  int i, j;
+  double X, Y, R, D;
+
+  catstats[0].RA[0] = catstats[0].DEC[0] =  360.0;
+  catstats[0].RA[1] = catstats[0].DEC[1] = -360.0;
+
+  for (i = -1; i < 2; i++) {
+    for (j = -1; j < 2; j++) {
+      X = 0.5*(1.0 + i*NFIELD)*NX;
+      Y = 0.5*(1.0 + j*NFIELD)*NY;
+      XY_to_RD (&R, &D, X, Y, coords);
+      /* coords returns a region all in same phase 
+	 while (R < 0.0)    R += 360.0;
+	 while (R >= 360.0) R -= 360.0;
+      */
+      catstats[0].RA[0]  = MIN (catstats[0].RA[0], R);
+      catstats[0].RA[1]  = MAX (catstats[0].RA[1], R);
+      catstats[0].DEC[0] = MIN (catstats[0].DEC[0], D);
+      catstats[0].DEC[1] = MAX (catstats[0].DEC[1], D);
+    }
+  }
+  fprintf (stderr, "full region: %f - %f, %f - %f\n", 
+	   catstats[0].RA[0], catstats[0].RA[1], catstats[0].DEC[0], catstats[0].DEC[1]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/gstars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/gstars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/gstars.c	(revision 16632)
@@ -0,0 +1,232 @@
+# include "gastro.h"
+# define dcos(a) (cos((double)((a)*(RAD_DEG))))
+# define dsin(a) (sin((double)((a)*(RAD_DEG))))
+
+/* by necesity hard wired */
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+# include <sys/time.h>
+# include <time.h>
+
+void sort_stars_mag (SStars *stars, int N) {
+
+# define SWAPFUNC(A,B){ SStars tmp; tmp = stars[A]; stars[A] = stars[B]; stars[B] = tmp; }
+# define COMPARE(A,B)(stars[A].mag < stars[B].mag)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+SStars *gstars (char *file, int *NSTARS, Coords *coords, int *NX, int *NY, double *dNdM) {
+
+  char line[64], side[64];
+  Header header, theader;
+  FILE *f;
+  int j, Ninstar, nstar, rnumber, N, Nstars, nbytes, Nbytes;
+  SStars *stars;
+  char *buffer;
+  double X, Y, T1, T2, T3, type, csign;
+  double PD, PR, DE, RE;
+  double ra, dec, dmag;
+
+  /* read in image header, open image data region */
+  if (!gfits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (1)\n", file);
+    exit(0);
+  }
+  /* get complete info from header */
+  gfits_scan (&header, "NAXIS1", "%d", 1, NX);
+  gfits_scan (&header, "NAXIS2", "%d", 1, NY);
+
+  /* attempt to get detailed astrometric information from header */
+  if (!strcasecmp (ROUGH_ASTROMETRY, "header")) {
+    if (!HEADER[0]) {
+      GetCoords (coords, &header);
+    } else {
+      gfits_read_header (HEADER, &theader);
+      GetCoords (coords, &theader);
+    }
+    if (!strcmp (coords[0].ctype, "NONE") || (coords[0].cdelt1 == 0) ||  (coords[0].cdelt2 == 0)) {
+      fprintf (stderr, "header coordinates incomplete, trying for rough coordinates\n");
+      strcpy (ROUGH_ASTROMETRY, "config");
+    } else {
+      if (FLIPX) {
+	coords[0].pc1_1 *= -1;
+	coords[0].crpix1 = *NX - coords[0].crpix1;
+      }
+      if (FLIPY) {
+	coords[0].pc2_2 *= -1;
+	coords[0].crpix2 = *NY - coords[0].crpix2;
+      }
+      ASEC_PIX = fabs (coords[0].cdelt1 * 3600.0);
+      csign = coords[0].cdelt1 / fabs (coords[0].cdelt1);
+      CCD_PC1_1 = coords[0].pc1_1 * csign;
+      CCD_PC2_1 = coords[0].pc2_1 * csign;
+      csign = coords[0].cdelt2 / fabs (coords[0].cdelt2);
+      CCD_PC1_2 = coords[0].pc1_2 * csign;
+      CCD_PC2_2 = coords[0].pc2_2 * csign;
+      if (!strcmp (&coords[0].ctype[4], "-PLY")) {
+	strcpy (coords[0].ctype, "DEC--TAN");
+      }
+    }
+  }
+  
+  /* get just RA & DEC from header, other terms from config file */
+  if (!strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    /* default values for coords */
+    strcpy (coords[0].ctype, "RA---TAN");
+    coords[0].pc1_1 = CCD_PC1_1; coords[0].pc1_2 = CCD_PC1_2;
+    coords[0].pc2_1 = CCD_PC2_1; coords[0].pc2_2 = CCD_PC2_2;
+    coords[0].cdelt1 = coords[0].cdelt2 = ASEC_PIX / 3600.0;
+    coords[0].Npolyterms = 0;
+    coords[0].crpix1 = 0.5*(*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+
+    /* get RA & DEC from header, unless FORCE is ste */
+    if (!FORCE) {
+      /* RA (in hours, not degrees) */
+      if (!gfits_scan (&header, "RA", "%s", 1, line)) {
+	fprintf (stderr, "ERROR: no astrometry in header\n");
+	exit (1);
+      }
+      ohana_dms_to_ddd (&coords[0].crval1, line);
+      coords[0].crval1 = coords[0].crval1 * 15.0;
+
+      /* DEC */
+      if (!gfits_scan (&header, "DEC", "%s", 1, line)) {
+	fprintf (stderr, "ERROR: no astrometry in header\n");
+	exit (1);
+      } 
+      ohana_dms_to_ddd (&coords[0].crval2, line);
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "coordinates from header: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+
+  /* use RA & DEC from command line arguments */
+  if (FORCE) {
+    coords[0].crval1 = F_RA;
+    coords[0].crval2 = F_DEC;
+    if (VERBOSE) fprintf (stderr, " forcing coordinates to: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+  }    
+
+  /* the following two sections are LONEOS derived and may not be needed elsewhere */
+  if (LONEOS_COORDS) {
+    gfits_scan (&header, "COMMENT", "%s", 1, line);
+    sscanf (line, "%*s%d%s", &rnumber, side);
+    if (get_region_coords (&ra, &dec, rnumber, side)) {
+      if (fabs(ra - coords[0].crval1) > 0.1) {
+	fprintf (stderr, "large offset from claimed position, using region coords %f %f -> %f %f (%d %s)\n", 
+		 coords[0].crval1, coords[0].crval2, ra, dec, rnumber, side);
+	coords[0].crval1 = ra;
+	coords[0].crval2 = dec;
+      }
+    }
+  }
+
+  /* at this point, we need to correct the crval1, crval2, and ROT_ZERO values
+     based on the pole axis angle and the ra, dec offsets */
+  if (POLAR_ALIGNMENT) {
+    X = coords[0].crval1;
+    Y = coords[0].crval2;
+    PD = POLE_DEC;  PR = POLE_RA;
+    DE = DEC_OFFSET; RE = RA_OFFSET;
+    
+    T1 = dcos(Y-DE) * dcos(X-RE) * dsin(PD) + dsin(Y-DE) * dcos(PD);
+    T2 = dcos(Y-DE) * dsin(X-RE);
+    T3 = dsin(Y-DE) * dsin(PD) - dcos(Y-DE) * dcos(X-RE) * dcos(PD);
+    
+    coords[0].crval1 = (DEG_RAD * atan2 (T2, T1)) + PR;
+    coords[0].crval2 = (DEG_RAD * asin (T3));
+    while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+    while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+    
+    if (VERBOSE) fprintf (stderr, "  after polar alignment: %9.4f %9.4f\n", coords[0].crval1, coords[0].crval2);
+  }
+
+  Nstars = 0;
+  gfits_scan (&header, "NSTARS", "%d", 1, &Nstars);
+  if (Nstars == -1) {
+    fprintf (stderr, "ERROR: failed to find NSTARS\n");
+    exit (0);
+  }
+  ALLOCATE (stars, SStars, Nstars);
+  Nbytes = Nstars*BYTES_STAR;
+
+  /* re-open file for stars */
+  f = fopen (file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find image file %s (2)\n", file);
+    exit(0);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  N = nstar = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  
+  while ((nbytes = fread (buffer, 1, (BLOCK*BYTES_STAR), f)) != 0) {
+    Ninstar = nbytes / BYTES_STAR;
+    for (j = 0; j < Ninstar; j++, nstar++) {
+      dparse (&stars[N].X,   1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,   2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].mag, 3, &buffer[j*BYTES_STAR]);
+      dparse (&dmag, 4, &buffer[j*BYTES_STAR]);
+      dparse (&type,         5, &buffer[j*BYTES_STAR]);
+      if ((type == 4) || (type == 6) || (type == 5) || (type == 9)) continue;
+      if (dmag > 100) continue;
+      N++;
+    }
+  }
+  free (header.buffer);
+  free (buffer);
+  fclose (f);
+ 
+  if (nstar != Nstars) {
+    fprintf (stderr, "WARNING: only read %d of %d stars\n", nstar, Nstars);
+  }
+  if (N < 5) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n",
+	     N);
+    exit (0);
+  }
+
+  sort_stars_mag (stars, N);  /* sorting by magnitude */
+  Nstars = N;
+
+  if (VERBOSE) fprintf (stderr, "\nread %d stars from data file", Nstars);
+  if (*NSTARS < Nstars) {
+    REALLOCATE (stars, SStars, *NSTARS);
+    if (VERBOSE) fprintf (stderr, ", using %d\n", *NSTARS);
+  } else {
+    *NSTARS = Nstars;
+    if (VERBOSE) fprintf (stderr, "\n");
+  }
+
+  *dNdM = *NSTARS / (stars[(*NSTARS-1)].mag - stars[0].mag) ;
+  if (VERBOSE) fprintf (stderr, "brightest star in datafile: %f mag\n", stars[0].mag);
+  
+  return (stars);
+}
+
+# if (0)
+
+  /***  this is tailored for LONEOS ***/
+  Nccd = -1;
+  gfits_scan (&header, "NCCD", "%d", 1, &Nccd);
+  if (Nccd == -1) {  /* no ccd info in header, not loneos */
+    coords[0].crpix1 = 0.5*(*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+  if (Nccd == 0) {  /* chip 0 (a) *** might be wrong *** */
+    coords[0].crpix1 = 0;
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+  if (Nccd == 1) {  /* chip 1 (b) */
+    coords[0].crpix1 = (*NX);
+    coords[0].crpix2 = 0.5*(*NY);
+  }
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/misc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/misc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/misc.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "gastro.h"
+
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+
+void hh_hms (double hh, int *hr, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh *= flag;
+  hh = 24.0*(hh/24.0 - (int)(hh/24.0));
+  *sc = 60.0*(60.0*hh - (int)(60.0*hh));
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+
+}
+ 
+void hms_format (char *line, double value) {
+
+  int hr, mn;
+  double sc;
+
+  hh_hms (value, &hr, &mn, &sc);
+  hr = (int) value;
+  if (isnan (value))
+    sprintf (line, "xx:xx:xx.xx");
+  else {
+    if (value < 0) {
+      sprintf (line, "-%02d:%02d:%05.2f", abs(hr), mn, sc);
+    } else {
+      sprintf (line, "%02d:%02d:%05.2f", hr, mn, sc);
+    }
+  }      
+}
+
+void area_of_region (CatStats *region) {
+  
+  double area;
+
+  area = DEG_RAD*(region[0].RA[1] - region[0].RA[0])*(sin(region[0].DEC[1]*RAD_DEG) - sin(region[0].DEC[0]*RAD_DEG));
+  region[0].Area = area;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/plotstuff.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/plotstuff.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/plotstuff.c	(revision 16632)
@@ -0,0 +1,104 @@
+# include "gastro.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+  char name[100];
+  
+  active = N;
+
+  sprintf (name, "gastro [%d]", N);
+  Xgraph[N] = KapaOpen ("kapa", name);
+
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+
+  if (Xgraph[N] == 0) return;
+  KapaBox (Xgraph[N], graphmode);
+  return;
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  if (Xgraph[N] == 0) return;
+
+  active = N;
+  if (Npts < 1) return;
+
+  KapaPrepPlot (Xgraph[N], Npts, graphmode);
+}
+
+void PlotVector (int Npts, float *vect, int mode, int N) {
+
+  if (Npts < 1) return;
+  active = N;
+
+  switch (mode) {
+    case 0:
+      KapaPlotVector (Xgraph[N], Npts, vect, "x");
+      break;
+    case 1:
+      KapaPlotVector (Xgraph[N], Npts, vect, "y");
+      break;
+    default:
+      abort();
+  }
+}
+
+void PlotReset (int N) {
+
+  char buffer[128];
+  int i;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+  KapaClearSections (Xgraph[N]);
+}
+
+/* include these lines to plot a pair of vectors: 
+
+   typedef struct {
+   double xmin, xmax, ymin, ymax;
+   int style, ptype, ltype, etype, color;
+   double lweight, size;
+   } Graphdata;
+   Graphdata graphdata;
+   
+   graphdata.xmin = -200;
+   graphdata.xmax = 4200;
+   graphdata.ymin = -500;
+   graphdata.ymax = 500;
+   graphdata.style = 2;
+   graphdata.ptype = 2;
+   graphdata.ltype = 0;
+   graphdata.etype = 0;
+   graphdata.color = 0;
+   graphdata.lweight = 0;
+   graphdata.size = 0.5;
+   
+   PrepPlotting (N, &graphdata, n);
+   PlotVector (N, Y, 0, n);
+   PlotVector (N, dM, 1, n);
+   DonePlotting (&graphdata, n);
+   
+ */
Index: /branches/eam_branch_20080223/Ohana/src/gastro/src/rotate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro/src/rotate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro/src/rotate.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "gastro.h"
+
+void rotate (SStars *stars, int Nstars, double angle, int Xo, int Yo) {
+  
+  int i;
+  double dX, dY, DX, DY, CS, SN;
+  double theta, theta2;
+
+  if (angle == 0.0) {
+    return;
+  }
+
+  theta = (angle*RAD_DEG);
+
+  if (fabs (angle) < 10) {
+    theta2 = 0.5*theta*theta;
+    for (i = 0; i < Nstars; i++) {
+      dX = (stars[i].X - Xo);
+      dY = (stars[i].Y - Yo);
+      stars[i].X += -theta*dY - theta2*dX;
+      stars[i].Y +=  theta*dX - theta2*dY;
+    }
+  } else {
+
+    CS = cos (theta);
+    SN = sin (theta);
+
+    for (i = 0; i < Nstars; i++) {
+      dX = (stars[i].X - Xo);
+      dY = (stars[i].Y - Yo);
+
+      DX = dX * CS - dY * SN;
+      DY = dX * SN + dY * CS;
+
+      stars[i].X = DX + Xo;
+      stars[i].Y = DY + Yo;
+    }
+  }
+    
+}
+
+
+  /* rotate the list 'stars' by an angle ccw from x axis */
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/Makefile	(revision 16632)
@@ -0,0 +1,67 @@
+default: gastro2
+help:
+	@echo "make options: gastro2 (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/gastro2
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+gastro2: $(BIN)/gastro2.$(ARCH)
+coordtest: $(BIN)/coordtest.$(ARCH)
+extr2mass: $(BIN)/extr2mass.$(ARCH)
+install: $(DESTBIN)/gastro2
+
+EXTR2MASS = \
+$(SRC)/extr2mass.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/gregions2.$(ARCH).o
+
+COORDTEST = \
+$(SRC)/coordtest.$(ARCH).o \
+$(SRC)/gpairs.$(ARCH).o \
+$(SRC)/polyfit.$(ARCH).o
+
+GASTRO2 = \
+$(SRC)/plots.$(ARCH).o \
+$(SRC)/gheader2.$(ARCH).o \
+$(SRC)/gfit2.$(ARCH).o \
+$(SRC)/gpairs.$(ARCH).o \
+$(SRC)/polyfit.$(ARCH).o \
+$(SRC)/plotstuff.$(ARCH).o \
+$(SRC)/rotate2.$(ARCH).o \
+$(SRC)/gcenter2.$(ARCH).o \
+$(SRC)/gproject2.$(ARCH).o \
+$(SRC)/grid.$(ARCH).o \
+$(SRC)/lumfunc.$(ARCH).o \
+$(SRC)/sort.$(ARCH).o \
+$(SRC)/misc.$(ARCH).o \
+$(SRC)/gargs.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/gastro2.$(ARCH).o \
+$(SRC)/gstars2.$(ARCH).o \
+$(SRC)/greference2.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/getusnob.$(ARCH).o \
+$(SRC)/getptolemy.$(ARCH).o \
+$(SRC)/getgsc.$(ARCH).o \
+$(SRC)/remove_clumps.$(ARCH).o \
+$(SRC)/rfits.$(ARCH).o \
+$(SRC)/rtext.$(ARCH).o
+
+$(GASTRO2): $(INC)/gastro2.h
+$(COORDTEST): $(INC)/gastro2.h
+$(EXTR2MASS): $(INC)/gastro2.h
+
+$(BIN)/gastro2.$(ARCH): $(GASTRO2)
+$(BIN)/coordtest.$(ARCH): $(COORDTEST)
+$(BIN)/extr2mass.$(ARCH): $(EXTR2MASS)
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,20 @@
+
+ gastro-2-3 2006.10.04
+  * converted to gfits APIs (forces libfits 1.6)
+  * converted to new DVO APIs (forces libdvo 1.3)
+  * removed unused code
+  * better error checks in ConfigInit
+  * fixed luminosity function matching
+  * added ASCA mode
+  * added mode to measure ptolemy fill-factor
+  * cleaned up polynomial fitting / header conversions
+  * cleaned up fitting code
+  * added error test for two few / nan fits
+
+ gastro-2-2:
+    added USNO-B
+
+ gastro-2-1:
+    added support for dvo table modes / formats (libdvo v1.0)
+    minor changes to sync with libfits modes (libfits v1.4)
+    added support for both fits and text input data files
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/include/gastro2.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/include/gastro2.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/include/gastro2.h	(revision 16632)
@@ -0,0 +1,202 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <kapa.h>
+
+typedef struct {
+  double R, D;
+  double P, Q;
+  double X, Y;
+  double M, dM;
+  int type;
+} StarData;
+
+typedef struct {
+  double dNdM;
+  double Mo;
+  double Mmin;
+  double Mmax;
+  double Mz;
+} LumStats;
+
+typedef struct {
+  double angle;
+  double Xoff;
+  double Yoff;
+  double Chi;
+  double dR;
+  int    N;
+} Answer;
+
+typedef struct {
+  Header header;   /* cmp file header */
+  LumStats lum;
+  Coords coords;   /* current best guess for astrometry */
+  Answer answer;
+
+  double Area;
+  StarData *stars; /* array with all star data */
+  int N;           /* number of stars */
+} CmpCatalog;
+
+typedef struct {
+  LumStats lum;
+
+  double Area;
+  double Moff;
+  double R0, R1;
+  double D0, D1;
+  int N;           /* number of stars */
+  
+  StarData *stars; /* array with all star data */
+} RefCatalog;
+
+typedef struct {
+  double RA[2], DEC[2];
+  double Area;
+  char *name;
+} CatStats;
+
+typedef struct {
+  double R, D;
+  double r, b;
+} USNOdata;
+
+/* global variables, from ConfigInit or args */
+double DEFAULT_RADIUS;
+double MINIMUM_RADIUS;
+double MAX_ERROR, MAX_NONLINEAR;
+double MIN_PRECISE;
+double CCD_PC1_1;
+double CCD_PC2_2;
+double CCD_PC1_2;
+double CCD_PC2_1;
+double NFIELD;
+double SEARCH_RADIUS;
+double ROT_ZERO;
+double dROT;
+double RA_OFFSET, DEC_OFFSET;
+double POLE_RA, POLE_DEC;
+int POLAR_ALIGNMENT;
+int NROT;
+int VERBOSE;
+int LONEOS_COORDS;
+int CATDUMP;
+int MATCHDUMP;
+int NOMATCHDUMP;
+int NEWPHOTCODE;
+int MIN_MATCHES;
+char *PHOTCODE;
+int FLIPX, FLIPY;
+int NPOLYTERMS;
+char CATDIR[256];
+char CATMODE[16];    /* raw, mef, split, mysql */
+char CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char REFCAT[256];
+char HEADER[256];
+int PLOTSTUFF;
+int MAGLIMS;
+int NMAX_STARS;
+char PhotCodeFile[256];
+int GASTRO_MAX_NSTARS;
+int TEXTMODE;
+int PTOLEMY_FILL_FACTOR;
+int MAGMANUAL;
+double MAGLIM_MIN;
+double MAGLIM_MAX;
+int NGRID_PIX;
+
+int    ASCA;
+int    FORCE;
+double F_RA;
+double F_DEC;
+
+double ASEC_PIX;
+char ROUGH_ASTROMETRY[64];
+
+/* locations for reference data */
+char GSCFILE[256];
+char GSCDIR[256];
+char CATDIR[256];
+char USNO_A_DIR[256];
+char USNO_B_DIR[256];
+char TWO_MASS_DIR[256];
+char ASTROM_CATDIR[256];
+char LONEOS_REGION_FILE[256];
+
+StarData *rtext (FILE *f, int *nstars);
+StarData *rfits (FILE *f, int *nstars);
+
+StarData *remove_clumps (StarData *instars, int *nstars, int NX, int NY);
+void 	  ConfigInit (int *argc, char **argv);
+void 	  DonePlotting (Graphdata *graphmode, int N);
+void 	  PlotReset (int N);
+void 	  PlotVector (int Npts, float *vect, int mode, int N);
+void 	  PrepPlotting (int Npts, Graphdata *graphmode, int N);
+void 	  XDead ();
+void 	  add_to_regions (CatStats *area);
+void 	  ahelp ();
+void 	  area_of_region (CatStats *region);
+double    area_of_skyregion (SkyRegion *region);
+void 	  args (int *argc, char **argv, Coords *coords);
+void 	  define_region (CatStats *catstats, CmpCatalog *Target);
+int 	  dms_to_ddd (double *Value, char *string);
+void 	  dump_coords (CmpCatalog *Target);
+void 	  fill_lumfunc (StarData *stars, int N, float *lbin, float *bin, int *nb);
+int 	  find_dec_bands (CatStats *area);
+void 	  fit_add (double x1, double y1, double x2, double y2, double wt);
+int 	  fit_adjust (Coords *coords);
+void 	  fit_apply (double *x, double *y, double X, double Y);
+void 	  fit_eval ();
+void 	  fit_init (int order);
+void 	  fit_lum_bin (double *x, double *y, int N, double *C0, double *C1);
+void 	  fit_norm (); 
+double    fit_scat (StarData *st, StarData *sr, Coords *coords);
+int 	  gaussj (double **a, int n, double **b, int m);
+void 	  gcenter (CmpCatalog *Target, RefCatalog *Ref);
+int 	  get_luminosity_func (StarData *stars, int N, LumStats *lum);
+int 	  getptolemy (CatStats *catstats, RefCatalog *Ref);
+int 	  getusno (CatStats *catstats, RefCatalog *Ref);
+int 	  getusnob (CatStats *catstats, RefCatalog *Ref, double epoch);
+int       getgsc (CatStats *catstats, RefCatalog *Ref);
+
+void 	  gfit (CmpCatalog *Target, RefCatalog *Ref, int order);
+void 	  gheader (char *file, CmpCatalog *Target);
+void 	  gproject (CmpCatalog *Target, RefCatalog *Ref, RefCatalog *Subset);
+void 	  greference (CmpCatalog *Target, RefCatalog *Ref);
+void 	  grid (CmpCatalog *Target, RefCatalog *Subset, Answer *answer);
+int 	  gridbin (double dX, double dY);
+void 	  gridfree ();
+void 	  gridinit (double XMIN, double XMAX, double YMIN, double YMAX, int Nr, int Nt);
+void 	  gstars (char *filename, CmpCatalog *Target);
+void 	  hh_hms (double hh, int *hr, int *mn, double *sc);
+void 	  hms_format (char *line, double value);
+void 	  init_regions ();
+int 	  load_ra_blocks (int Ndec, CatStats *area);
+int 	  mk_polyterm (int n, int m, int norder);
+int 	  mk_vector (int n, int m, int norder);
+int 	  open_graph (int N);
+
+void 	  pair_add (int i1, int i2);
+void 	  pair_init ();
+int       pair_lists (int **index1, int **index2);
+
+int 	  parse_GSC_line (CatStats *tregion, char *line);
+int 	  plot_addpt_gridplot (double x, double y);
+void 	  plot_done_gridplot ();
+void 	  plot_fullfield (CmpCatalog *Target, RefCatalog *Ref);
+void 	  plot_fullfield_pairs (float *x, float *y, int n);
+void 	  plot_gridpts (double *pts, int Npts);
+void 	  plot_init_gridplot ();
+void 	  plot_lumfunc (CmpCatalog *Target, RefCatalog *Ref);
+void 	  plot_resid (StarData *st, StarData *sr, Coords *coords);
+void 	  plot_resid_init (int version, double xmax);
+void 	  plot_resid_plot (int version, float *xvect, float *yvect, int Nvect);
+
+void 	  rotate (RefCatalog *Subset, RefCatalog *Ref, double angle);
+void 	  set_catalog (char *catdir);
+void 	  sort (double *X, int N);
+void 	  sort_lists (double *X, double *Y, int *S, int N);
+void 	  sort_lum (double *R, double *X, double *Y, int N);
+void 	  sort_stars_X (StarData *stars, int N);
+void 	  sort_stars_mag (StarData *stars, int N);
+int 	  str_to_radec (double *ra, double *dec, char *str1, char *str2);
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "gastro2.h"
+
+void ConfigInit (int *argc, char **argv) {
+  
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* default values for config variables: used if key is missing from the config file */
+  strcpy (ROUGH_ASTROMETRY, "header");
+
+  ScanConfig (config, "CCD_PC1_1",         "%lf", 0, &CCD_PC1_1);       // guess if WCS is missing
+  ScanConfig (config, "CCD_PC2_2",         "%lf", 0, &CCD_PC2_2);       // guess if WCS is missing
+  ScanConfig (config, "CCD_PC1_2",         "%lf", 0, &CCD_PC1_2);       // guess if WCS is missing
+  ScanConfig (config, "CCD_PC2_1",         "%lf", 0, &CCD_PC2_1);       // guess if WCS is missing
+  ScanConfig (config, "ASEC_PIX",          "%lf", 0, &ASEC_PIX);        // guess if WCS is missing
+  ScanConfig (config, "NFIELD",            "%lf", 0, &NFIELD);          // search region *padding* in field units
+  ScanConfig (config, "NGRID_PIX",         "%d",  0, &NGRID_PIX);       // resolution of grid search (pixels)
+  ScanConfig (config, "NPOLYTERMS",        "%d",  0, &NPOLYTERMS);      // high-order fit terms (2 or 3)
+  ScanConfig (config, "ROT_ZERO",          "%lf", 0, &ROT_ZERO);        // rotation search region
+  ScanConfig (config, "dROT",              "%lf", 0, &dROT);            // rotation search region
+  ScanConfig (config, "NROT",              "%d",  0, &NROT);            // rotation search region
+  ScanConfig (config, "POLAR_ALIGNMENT",   "%d",  0, &POLAR_ALIGNMENT); // apply polar alignment correction
+  ScanConfig (config, "POLAR_AXIS_RA",     "%lf", 0, &POLE_RA);         // true coords of pole (should be HA, not RA)
+  ScanConfig (config, "POLAR_AXIS_DEC",    "%lf", 0, &POLE_DEC);        // true coords of pole
+  ScanConfig (config, "RA_OFFSET",         "%lf", 0, &RA_OFFSET);       // ?? not well defined (should be euler angle)
+  ScanConfig (config, "DEC_OFFSET",        "%lf", 0, &DEC_OFFSET);      // ?? not well defined (should be euler angle)
+
+  /* possible sources of astrometric reference data */
+  if (!ScanConfig (config, "USNO_A_DIR",             "%s",  0, USNO_A_DIR)) {  // location of USNO A data (USNO_CDROM in gastro)
+    ScanConfig (config, "USNO_CDROM",             "%s",  0, USNO_A_DIR);  // alternate location of USNO A data
+  }
+  ScanConfig (config, "USNO_B_DIR",        "%s",  0, USNO_B_DIR);       // location of USNO B ref data
+  ScanConfig (config, "GSCDIR",            "%s",  0, GSCDIR);           // location of HST GSC ref data 
+  ScanConfig (config, "2MASS_DIR",         "%s",  0, TWO_MASS_DIR);  	// location of 2MASS ref data 
+  ScanConfig (config, "ASTROM_CATDIR",     "%s",  0, ASTROM_CATDIR); 	// location of ptolemy-format ref data
+
+  ScanConfig (config, "GSCFILE",           "%s",  0, GSCFILE);          // location of sky table
+  ScanConfig (config, "ASTRO_REFCAT",      "%s",  0, REFCAT);           // which astrometry catalog to use
+  ScanConfig (config, "ROUGH_ASTROMETRY",  "%s",  0, ROUGH_ASTROMETRY); // where to get initial guess (header, config)
+  ScanConfig (config, "GASTRO_MAX_NSTARS", "%d",  0, &GASTRO_MAX_NSTARS); // max number of stars from image to fit
+  ScanConfig (config, "GASTRO_MAX_MAG_ERROR", "%lf", 0, &MAX_ERROR);    // S/N limit on image stars used in fit
+
+  ScanConfig (config, "PHOTCODE_FILE",     "%s",  0, PhotCodeFile);  // not used
+
+  if (NFIELD <= 0.0) {
+      fprintf (stderr, "NFIELD is not sensible: choose a non-zero number\n");
+      exit (1);
+  }
+
+  if (!GASTRO_MAX_NSTARS) GASTRO_MAX_NSTARS = 300;
+  if (!MAX_ERROR) MAX_ERROR = 0.2;
+  if (!NGRID_PIX) NGRID_PIX = 50.0;
+  if (!NFIELD) NFIELD = 0.1;
+  
+  if (strcasecmp (ROUGH_ASTROMETRY, "header") && 
+      strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    fprintf (stderr, "ROUGH_ASTROMETRY must be one of: header, config\n");
+    exit (1);
+  }
+  free (config);
+  free (file);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/coordtest.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/coordtest.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/coordtest.c	(revision 16632)
@@ -0,0 +1,142 @@
+# include "gastro2.h"
+
+# define A00 +500.00
+# define A10 +4.00
+# define A01 +1.00
+# define A20 -0.001
+# define A11 +0.000
+# define A02 -0.001
+# define A30 +0.00002
+# define A21 +0.00001
+# define A12 -0.00001
+# define A03 -0.00002
+
+# define B00 400.00
+# define B10  -1.00
+# define B01  4.00
+# define B20 -0.001
+# define B11  0.000
+# define B02 -0.001
+# define B30 -0.00002
+# define B21 -0.00001
+# define B12 +0.00001
+# define B03 +0.00002
+
+int main (int argc, char **argv) {
+
+  /* generate a set of fake data and send to fitter */
+  int i, N, order;
+  double x, y, z;
+  double L[50000], M[50000], X[50000], Y[50000];
+  Coords coords;
+  FILE *f;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: coordtest (order)\n");
+    exit (2);
+  }
+
+  order = atoi (argv[1]);
+  fit_init (order);
+  N = 0;
+
+  switch (order) {
+    case 1:
+      for (x = -10.0; x < 10.1; x += 0.1) {
+	for (y = -10.0; y < 10.1; y += 0.1) {
+      
+	  L[N] = A00 + A10*x + A01*y;
+	  M[N] = B00 + B10*x + B01*y;
+	  X[N] = x;
+	  Y[N] = y;
+	  fit_add (x, y, L[N], M[N], 1.0);
+	  N++;
+	}
+      }
+      break;
+    case 2:
+      for (x = -10.0; x < 10.1; x += 0.1) {
+	for (y = -10.0; y < 10.1; y += 0.1) {
+      
+	  L[N] = A00 + A10*x + A01*y + A20*x*x + A11*x*y + A02*y*y;
+	  M[N] = B00 + B10*x + B01*y + B20*x*x + B11*x*y + B02*y*y;
+	  X[N] = x;
+	  Y[N] = y;
+	  fit_add (x, y, L[N], M[N], 1.0);
+	  N++;
+	}
+      }
+      break;
+    case 3:
+      for (x = -10.0; x < 10.1; x += 0.1) {
+	for (y = -10.0; y < 10.1; y += 0.1) {
+      
+	  L[N] = A00 + A10*x + A01*y + A20*x*x + A11*x*y + A02*y*y + A30*x*x*x + A21*x*x*y + A12*x*y*y + A03*y*y*y;
+	  M[N] = B00 + B10*x + B01*y + B20*x*x + B11*x*y + B02*y*y + B30*x*x*x + B21*x*x*y + B12*x*y*y + B03*y*y*y;
+	  X[N] = x;
+	  Y[N] = y;
+	  fit_add (x, y, L[N], M[N], 1.0);
+	  N++;
+	}
+      }
+      break;
+  }
+
+  fit_eval ();
+
+  strcpy (coords.ctype, "RA---PLY");
+  coords.crval1 = 0.0;
+  coords.crval2 = 0.0;
+
+  fit_adjust (&coords);
+
+  fprintf (stderr, "CTYPE: %s\n", coords.ctype);
+  fprintf (stderr, "CRVAL: %f %f\n", coords.crval1, coords.crval2);
+  fprintf (stderr, "CRPIX: %f %f\n", coords.crpix1, coords.crpix2);
+  fprintf (stderr, "CDELT: %f %f\n", coords.cdelt1, coords.cdelt2);
+  fprintf (stderr, "PC1_j: %f %f\n", coords.pc1_1,  coords.pc1_2);
+  fprintf (stderr, "PC2_j: %f %f\n", coords.pc2_1,  coords.pc2_2);
+
+  fprintf (stderr, "Npolyterms: %d\n", coords.Npolyterms);
+  for (i = 0; i < 7; i++) {
+    fprintf (stderr, "%f %f\n", coords.polyterms[i][0], coords.polyterms[i][1]);
+  }
+
+  f = fopen ("test.dat", "w");
+  {
+    double Lo, Mo, dL, dL2, dM, dM2;
+    double Xo, Yo, dX, dX2, dY, dY2;
+    double Lx, Mx;
+
+    dL = dL2 = dM = dM2 = 0.0;
+    dX = dX2 = dY = dY2 = 0.0;
+    for (i = 0; i < N; i++) {
+      XY_to_RD (&Lo, &Mo, X[i], Y[i], &coords);
+      dL  += (L[i] - Lo);
+      dM  += (M[i] - Mo);
+      dL2 += SQ(L[i] - Lo);
+      dM2 += SQ(M[i] - Mo);
+
+      RD_to_XY (&Xo, &Yo, L[i], M[i], &coords);
+      dX  += (X[i] - Xo);
+      dY  += (Y[i] - Yo);
+      dX2 += SQ(X[i] - Xo);
+      dY2 += SQ(Y[i] - Yo);
+
+      // fit_apply (&Lx, &Mx, X[i], Y[i]);
+      // fprintf (stderr, "%f,%f -> %f,%f | %f,%f : %f, %f\n", X[i], Y[i], Lx, Mx, L[i], M[i], Lo, Mo);
+
+      fprintf (f, "%f %f : %f %f :: %f %f : %f %f\n",
+	       X[i], Y[i], L[i], M[i], Lo, Mo, Xo, Yo);
+    }
+    fclose (f);
+
+    fprintf (stderr, "dL: %f\n", sqrt(fabs(dL2/N - SQ(dL/N))));
+    fprintf (stderr, "dM: %f\n", sqrt(fabs(dM2/N - SQ(dM/N))));
+    fprintf (stderr, "dX: %f\n", sqrt(fabs(dX2/N - SQ(dX/N))));
+    fprintf (stderr, "dY: %f\n", sqrt(fabs(dY2/N - SQ(dY/N))));
+  }
+
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gargs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gargs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gargs.c	(revision 16632)
@@ -0,0 +1,156 @@
+# include "gastro2.h"
+# define NARGS 2  /* minimum is:  gastro catalog */
+
+void ahelp () {
+
+  fprintf (stderr, "gastro -- astrometry for LONEOS\n");
+
+  fprintf (stderr, "  USAGE: gastro pixscale filename");
+  fprintf (stderr, "  optional flags:\n");
+  fprintf (stderr, "  -v (verbose mode)\n");
+  fprintf (stderr, "  -dump (dump catalog stars, don't complete astrometry)\n");
+  fprintf (stderr, "  -mdmp (dump matched catalog stars)\n");
+  fprintf (stderr, "\n"); 
+  exit (0);
+
+}
+
+void args (int *argc, char **argv, Coords *coords) {
+  
+  int N;
+
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    ahelp ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  /* force read of image database with mismatched NSTARS & size */ 
+  TEXTMODE = FALSE;
+  if ((N = get_argument (*argc, argv, "-textmode"))) {
+    TEXTMODE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  /* force read of image database with mismatched NSTARS & size */ 
+  PTOLEMY_FILL_FACTOR = FALSE;
+  if ((N = get_argument (*argc, argv, "-ptolemy-fill-factor"))) {
+    PTOLEMY_FILL_FACTOR = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  PLOTSTUFF = FALSE;
+  if ((N = get_argument (*argc, argv, "-plot"))) {
+    PLOTSTUFF = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MAGLIMS = TRUE;
+  if ((N = get_argument (*argc, argv, "-maglims"))) {
+    MAGLIMS = FALSE;
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-magrange"))) {
+    MAGLIMS = TRUE;
+    MAGMANUAL = TRUE;
+    remove_argument (N, argc, argv);
+    MAGLIM_MIN = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    MAGLIM_MAX = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  NMAX_STARS = 300;
+  if ((N = get_argument (*argc, argv, "-nstars"))) {
+    remove_argument (N, argc, argv);
+    NMAX_STARS = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-header"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  HEADER[0] = 0;
+  if ((N = get_argument (*argc, argv, "-head"))) {
+    remove_argument (N, argc, argv);
+    strcpy (HEADER, argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPX = FALSE;
+  if ((N = get_argument (*argc, argv, "-fx"))) {
+    FLIPX = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FLIPY = FALSE;
+  if ((N = get_argument (*argc, argv, "-fy"))) {
+    FLIPY = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  FORCE = FALSE;
+  if ((N = get_argument (*argc, argv, "-coords"))) {
+    FORCE = TRUE;
+    remove_argument (N, argc, argv);
+    F_RA = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    F_DEC = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /** XXX temporary trick to deal with the very wide-field ASCA images 
+      this alters the definition of the reference field boundaries */
+  ASCA = FALSE;
+  if ((N = get_argument (*argc, argv, "-asca"))) {
+    ASCA = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  CATDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-dump"))) {
+    CATDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  MATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-mdmp"))) {
+    MATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  NOMATCHDUMP = FALSE;
+  if ((N = get_argument (*argc, argv, "-cdmp"))) {
+    NOMATCHDUMP = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  // XXX these options are being ignored
+  NEWPHOTCODE = FALSE;
+  if ((N = get_argument (*argc, argv, "-p"))) {
+    NEWPHOTCODE = TRUE;
+    remove_argument (N, argc, argv);
+    PHOTCODE = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  LONEOS_COORDS = FALSE;
+  if ((N = get_argument (*argc, argv, "-loneos"))) {
+    LONEOS_COORDS = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  if (*argc != NARGS) {
+    fprintf (stderr, "USAGE: gastro filename\n");
+    exit (0);
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gastro2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gastro2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gastro2.c	(revision 16632)
@@ -0,0 +1,99 @@
+# include "gastro2.h"
+
+int main (int argc, char **argv) {
+
+  int i;
+  RefCatalog Ref;
+  CmpCatalog Target;
+
+  /* start_timer (); */
+
+  ConfigInit (&argc, argv);
+  args (&argc, argv, &Target.coords); 
+
+  gstars (argv[1], &Target);
+  greference (&Target, &Ref);
+  gcenter (&Target, &Ref);
+
+  for (i = 0; i < 3; i++) {
+    gfit (&Target, &Ref, 1);
+    fprintf (stderr, "precision: %f\n", Target.answer.dR / sqrt(Target.answer.N));
+    if ((Target.answer.N < 2) || isnan(Target.answer.dR)) {
+	fprintf (stderr, "ERROR: bad fit\n");
+	exit (1);
+    }
+    if (VERBOSE) {
+      fprintf (stderr, "%s\n", Target.coords.ctype);
+      fprintf (stderr, "%f %f\n", Target.coords.crval1, Target.coords.crval2);
+      fprintf (stderr, "%f %f\n", Target.coords.crpix1, Target.coords.crpix2);
+      fprintf (stderr, "%f %f\n", Target.coords.pc1_1,  Target.coords.pc1_2);
+      fprintf (stderr, "%f %f\n", Target.coords.pc2_1,  Target.coords.pc2_2);
+      fprintf (stderr, "%f %f\n", Target.coords.cdelt1, Target.coords.cdelt2);
+    }
+
+  }
+
+  for (i = 0; i < 5; i++) {
+    gfit (&Target, &Ref, MIN (MAX (1, NPOLYTERMS), 3));
+    fprintf (stderr, "precision: %f\n", Target.answer.dR / sqrt(Target.answer.N));
+    if ((Target.answer.N < 2) || isnan(Target.answer.dR)) {
+	fprintf (stderr, "ERROR: bad fit\n");
+	exit (1);
+    }
+  }
+
+  if (VERBOSE) {
+    fprintf (stderr, "%s\n", Target.coords.ctype);
+    fprintf (stderr, "%f %f\n", Target.coords.crval1, Target.coords.crval2);
+    fprintf (stderr, "%f %f\n", Target.coords.crpix1, Target.coords.crpix2);
+    fprintf (stderr, "%f %f\n", Target.coords.pc1_1,  Target.coords.pc1_2);
+    fprintf (stderr, "%f %f\n", Target.coords.pc2_1,  Target.coords.pc2_2);
+    fprintf (stderr, "%f %f\n", Target.coords.cdelt1, Target.coords.cdelt2);
+  }
+
+  gheader (argv[1], &Target);
+
+  /* print_timer (); */
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+  /* 
+     load config & args 
+
+     load stars & header from cmp file
+     (this should include filtering based on CONFIG data:
+     limit number of stars, limit types, etc) 
+
+     identify and load reference catalog(s)
+     - load all catalogs available?
+     - keep ra, dec, mag
+
+     project catalog to initial guess
+
+     find simple x, y offset in limited number of rotations
+   
+     reload reference catalog if dx, dy large 
+
+     project to new guess
+
+     fit on star-by-star basis
+     - include weighting by dmag
+     - downweight by Nmatch to each star
+     - iterate a few times?
+
+     project to new guess (why is this not part of the routines?)
+
+     try a higher order fit
+
+     adjust header, re-write file
+
+     TODO:
+
+     1) downweight points by Nmatch
+     2) better criterion for success
+     3) better criterion for failure
+     4) polyterms are broken
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gcenter2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gcenter2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gcenter2.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include "gastro2.h"
+
+void gcenter (CmpCatalog *Target, RefCatalog *Ref) {
+
+  int i, N, Imin;
+  double angle, ChiMin;
+  Answer *answer;
+  RefCatalog Subset;
+
+  gproject (Target, Ref, &Subset);
+  if (PLOTSTUFF) plot_fullfield (Target, &Subset);
+
+  fprintf (stderr, "Target: %d, Ref: %d\n", Target[0].N, Subset.N);
+  dump_coords (Target);
+
+  ALLOCATE (answer, Answer, 2*NROT + 1);
+
+  N = 0;
+  for (angle = ROT_ZERO-dROT*NROT; angle <= ROT_ZERO+dROT*NROT; angle += dROT, N++) {
+
+    if (N == 2*NROT + 1) {
+      fprintf (stderr, "ERROR in logic: Nanswer > 2*NROT+1 (%d, %d)\n", N, 2*NROT+1);
+      exit (1);
+    }
+    answer[N].angle = angle;
+    grid (Target, &Subset, &answer[N]);
+  }
+
+  Imin = 0;
+  ChiMin = answer[0].Chi;
+  for (i = 0; i < N; i++) {
+    if (answer[i].Chi < ChiMin) {
+      Imin = i;
+      ChiMin = answer[i].Chi;
+    }
+  }
+      
+  fprintf (stderr, "best solution: angle: %6.1f, (%6.1f,%6.1f) - %10.8f for %d pairs\n", 
+	   answer[Imin].angle, answer[Imin].Xoff, answer[Imin].Yoff, answer[Imin].Chi, answer[Imin].N);
+
+  Target[0].answer = answer[Imin];
+
+  /* adjust original coordinates for new center */
+  { 
+
+    double cs, sn;
+    double pc11, pc12, pc21, pc22;
+    double Xo, Yo;
+
+    cs = cos(RAD_DEG*answer[Imin].angle);  sn = sin(RAD_DEG*answer[Imin].angle);
+    
+    pc11 = Target[0].coords.pc1_1;
+    pc12 = Target[0].coords.pc1_2;
+    pc21 = Target[0].coords.pc2_1;
+    pc22 = Target[0].coords.pc2_2;
+
+    Target[0].coords.pc1_1 =  pc11*cs - pc21*sn;
+    Target[0].coords.pc1_2 =  pc11*sn + pc12*cs;
+    Target[0].coords.pc2_1 =  pc21*cs - pc22*sn;
+    Target[0].coords.pc2_2 =  pc21*sn + pc22*cs;
+    
+    Xo = Target[0].coords.crpix1;
+    Yo = Target[0].coords.crpix2;
+    Target[0].coords.crpix1 = answer[Imin].Xoff + cs*Xo - sn*Yo;
+    Target[0].coords.crpix2 = answer[Imin].Yoff + sn*Xo + cs*Yo;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/getgsc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/getgsc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/getgsc.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include "gastro2.h"
+
+StarData *rd_gsc (char *filename, int *Nstars);
+
+int getgsc (CatStats *catstats, RefCatalog *Ref) {
+  
+  int i, j, k, Ns, Ngsc; 
+  StarData *gsc;
+  SkyList *skylist;
+  SkyTable *sky;
+  SkyRegion patch;
+
+  Ref[0].N = 0;
+  Ref[0].Area = 0;
+  ALLOCATE (Ref[0].stars, StarData, 1);
+
+  patch.Rmin = catstats[0].RA[0];
+  patch.Rmax = catstats[0].RA[1];
+  patch.Dmin = catstats[0].DEC[0];
+  patch.Dmax = catstats[0].DEC[1];
+
+  /* load regions from GSC table, restrict to patch */
+  sky = SkyTableFromGSC (GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, GSCDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, &patch);
+  
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    gsc = rd_gsc (skylist[0].filename[i], &Ngsc);
+
+    Ns = Ref[0].N;
+    Ref[0].N += Ngsc;
+    Ref[0].Area += area_of_skyregion (skylist[0].regions[i]);
+
+    REALLOCATE (Ref[0].stars, StarData, MAX (1, Ref[0].N));
+    for (k = Ns, j = 0; j < Ngsc; k++, j++) {
+      Ref[0].stars[k].R = gsc[j].R;
+      Ref[0].stars[k].D = gsc[j].D;
+      Ref[0].stars[k].M = gsc[j].M;
+    }      
+    free (gsc);
+  }
+  SkyTableFree (sky);
+  
+  Ref[0].R0    = catstats[0].RA[0];
+  Ref[0].R1    = catstats[0].RA[1];
+  Ref[0].D0    = catstats[0].DEC[0];
+  Ref[0].D1    = catstats[0].DEC[1];
+
+  /* calculate luminosity function of stars */
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+
+  if (VERBOSE) fprintf (stderr, "%d stars from HST GSC\n", Ref[0].N);
+  return (TRUE);
+}  
+
+# define BYTES_STAR 23
+# define BLOCK 1000
+StarData *rd_gsc (char *filename, int *Nstars) {
+  
+  StarData *stars;
+  int i, NSTAR, nstar, Nbytes, nbytes;
+  char *buffer;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find catalog file %s\n", filename);
+    exit (1);
+  }
+  
+  nstar = 0;
+  NSTAR = 1000;
+  ALLOCATE (stars, StarData, NSTAR);
+
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  Nbytes = BLOCK*BYTES_STAR;
+
+  while ((nbytes = fread (buffer, 1, Nbytes, f)) > 0) {
+    for (i = 0; i < nbytes / BYTES_STAR; i++) {
+      dparse (&stars[nstar].R, 1, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].D, 2, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].M, 3, &buffer[i*BYTES_STAR]);
+      nstar++;
+      if (nstar == NSTAR) {
+	NSTAR += 1000;
+	REALLOCATE (stars, StarData, NSTAR);
+      }
+    }
+  }
+
+  free (buffer);
+
+  *Nstars = nstar;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/getptolemy.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/getptolemy.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/getptolemy.c	(revision 16632)
@@ -0,0 +1,115 @@
+# include "gastro2.h"
+double catalog_area (Average *average, int Naverage, SkyRegion *region);
+
+int getptolemy (CatStats *catstats, RefCatalog *Ref) {
+  
+  int i, j, k, Ns; 
+  double FracArea;
+  Catalog catalog;
+  SkyList *skylist;
+  SkyTable *sky;
+  SkyRegion patch;
+
+  Ref[0].N = 0;
+  Ref[0].Area = 0;
+  ALLOCATE (Ref[0].stars, StarData, 1);
+
+  patch.Rmin = catstats[0].RA[0];
+  patch.Rmax = catstats[0].RA[1];
+  patch.Dmin = catstats[0].DEC[0];
+  patch.Dmax = catstats[0].DEC[1];
+
+  /* load regions from GSC table, restrict to patch */
+  sky = SkyTableLoadOptimal (CATDIR, NULL, GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, &patch);
+  
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    // set the parameters which guide catalog open/load/create
+    catalog.filename  = skylist[0].filename[i];
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS;
+    catalog.Nsecfilt  = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    // Naves_disk == 0 implies an empty catalog file
+    // for only_match, skip empty catalogs
+    if (!catalog.Naves_disk) {
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    // this measurement adjusts a DVO database for partial coverage
+    // XXX the correction is bogus if the sky density of the catalog 
+    // is too low (<< 100 stars per field)
+    FracArea = 1.0;
+    if (PTOLEMY_FILL_FACTOR) {
+      FracArea = catalog_area (catalog.average, catalog.Naverage, skylist[0].regions[i]);
+    } 
+
+    Ns = Ref[0].N;
+    Ref[0].N += catalog.Naverage;
+    Ref[0].Area += FracArea * area_of_skyregion (skylist[0].regions[i]);
+
+    REALLOCATE (Ref[0].stars, StarData, MAX (1, Ref[0].N));
+    for (k = Ns, j = 0; j < catalog.Naverage; k++, j++) {
+      Ref[0].stars[k].R = catalog.average[j].R;
+      Ref[0].stars[k].D = catalog.average[j].D;
+      Ref[0].stars[k].M = catalog.measure[catalog.average[j].offset].M;
+    }      
+    dvo_catalog_free (&catalog);
+  }
+  
+  Ref[0].R0 = catstats[0].RA[0];
+  Ref[0].R1 = catstats[0].RA[1];
+  Ref[0].D0 = catstats[0].DEC[0];
+  Ref[0].D1 = catstats[0].DEC[1];
+
+  /* calculate luminosity function of stars */
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+
+  if (VERBOSE) fprintf (stderr, "%d stars from PTOLEMY\n", Ref[0].N);
+  return (TRUE);
+}  
+
+double catalog_area (Average *average, int Naverage, SkyRegion *region) {
+
+  int i, xb, yb, Nb;
+  int bin[10][10];
+  double frac, Rmin, Rmax, Dmin, Dmax, dR, dD;
+
+  Rmin = region[0].Rmin;
+  Rmax = region[0].Rmax;
+  Dmin = region[0].Dmin;
+  Dmax = region[0].Dmax;
+  dR = Rmax - Rmin;
+  dD = Dmax - Dmin;
+
+  for (xb = 0; xb < 10; xb++) {
+    for (yb = 0; yb < 10; yb++) {
+      bin[xb][yb] = 0;
+    }
+  }
+
+  for (i = 0; i < Naverage; i++) {
+    xb = MAX (MIN (0, 10 * (average[i].R - Rmin) / dR), 9);
+    yb = MAX (MIN (0, 10 * (average[i].D - Dmin) / dD), 9);
+    bin[xb][yb] ++;
+  }
+
+  Nb = 0;
+  for (xb = 0; xb < 10; xb++) {
+    for (yb = 0; yb < 10; yb++) {
+      if (bin[xb][yb]) Nb ++;
+    }
+  }
+
+  frac = Nb / 100.0;
+
+  return (frac);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/getusno.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/getusno.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/getusno.c	(revision 16632)
@@ -0,0 +1,138 @@
+# include "gastro2.h"
+# define NZONE 24
+
+int SPDzone[] = {
+  0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 
+  675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+
+int USNOdisk[] = {
+  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10};
+
+int getusno (CatStats *catstats, RefCatalog *Ref) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128];
+  FILE *f;
+  double DEC1;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end, disk;
+  int NUSNO, Nusno;
+  StarData *stars;
+
+  /* identify ra & dec range of interest */
+  iRA0 = catstats[0].RA[0] * 360000.0;
+  iRA1 = catstats[0].RA[1] * 360000.0;
+  iDEC0 = (catstats[0].DEC[0] + 90.0) * 360000.0;
+  iDEC1 = (catstats[0].DEC[1] + 90.0) * 360000.0;
+  
+  /* data is organized in south-pole distance zones */
+  spd_start = (int)((catstats[0].DEC[0] + 90) / 7.5) * 75.0;
+  DEC1 = (catstats[0].DEC[1] + 90) / 7.5;
+  if (DEC1 > (int)(DEC1)) {
+    spd_end =   (int)(1 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (catstats[0].DEC[1] + 90) / 7.5) * 75.0;
+  }
+
+  Nusno = 0;
+  NUSNO = 5000;
+  ALLOCATE (stars, StarData, NUSNO);
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find USNO zone for spd %d\n",  spd);
+      exit (0);
+    }
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc", USNO_A_DIR, spd); 
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open accelerator file %s\n", filename);
+      exit (1);  
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].RA[0] / 3.75;
+    if ((catstats[0].RA[1] / 3.75) == (int) (catstats[0].RA[1] / 3.75)) 
+      last  = catstats[0].RA[1] / 3.75;
+    else 
+      last  = 1 + catstats[0].RA[1] / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "ERROR: RA out of range\n");
+      exit (1);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat", USNO_A_DIR, spd);
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s\n", filename);
+      exit (1);
+    }
+    /* advance file pointer to first slice */
+    offset = 3*sizeof(int)*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+    /* on each loop, load data from an RA slice of the catalog */
+    for (bin = first; bin < last; bin++) {
+      Nitems = 3*number[bin];
+      ALLOCATE (buffer, int, Nitems);
+      nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+      if (nitems != Nitems) {
+	fprintf (stderr, "ERROR: failure reading data from file %s\n", filename);
+	exit (1);
+      }
+      buf = buffer;
+      /* print out data from slice within RA and DEC range */
+      for (i = 0; i < number[bin]; i++, buf+=3) {
+	if ((buf[0] > iRA0) && (buf[0] < iRA1) &&
+	    (buf[1] > iDEC0) && (buf[1] < iDEC1)) {
+	  stars[Nusno].R = buf[0]/360000.0;
+	  stars[Nusno].D = buf[1]/360000.0 - 90.0;
+	  /* note that this is the RED mag */
+	  stars[Nusno].M = fabs (0.1*(buf[2] - 1000*((int)(buf[2]/1000))));
+	  /* b = 0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000); */
+	  Nusno ++;
+	  if (Nusno == NUSNO) {
+	    NUSNO += 5000;
+	    REALLOCATE (stars, StarData, NUSNO);
+	  }	  
+	}
+      }
+      free (buffer);
+    }
+    fclose (f);
+  }
+
+  area_of_region (catstats);
+
+  REALLOCATE (stars, StarData, MAX (1, Nusno));
+
+  Ref[0].stars = stars;
+  Ref[0].N     = Nusno;
+  Ref[0].R0    = catstats[0].RA[0];
+  Ref[0].R1    = catstats[0].RA[1];
+  Ref[0].D0    = catstats[0].DEC[0];
+  Ref[0].D1    = catstats[0].DEC[1];
+  Ref[0].Area  = catstats[0].Area;
+
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+  
+  if (VERBOSE) fprintf (stderr, "%d stars from USNO 1.0\n", Nusno);
+  return (TRUE);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/getusnob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/getusnob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/getusnob.c	(revision 16632)
@@ -0,0 +1,163 @@
+# include "gastro2.h"
+# define NBYTE   4
+# define NELEM  20
+
+int getusnob (CatStats *catstats, RefCatalog *Ref, double epoch) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128];
+  FILE *f;
+  double DEC1;
+  double uR, uD;
+  float mB1, mB2, mR1, mR2, mB, mR;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end;
+  int NUSNO, Nusno, Nstars;
+  StarData *stars;
+
+  /* identify ra & dec range of interest */
+  iRA0 = catstats[0].RA[0] * 360000.0;
+  iRA1 = catstats[0].RA[1] * 360000.0;
+  iDEC0 = (catstats[0].DEC[0] + 90.0) * 360000.0;
+  iDEC1 = (catstats[0].DEC[1] + 90.0) * 360000.0;
+  /* note that DEC is in SPD, while both have units to 0.01 degrees */
+  
+  /* data is organized in south-pole distance zones, 1 deg per direction, 0.1 deg per file */
+  spd_start = (int)(10*(catstats[0].DEC[0] + 90));
+  DEC1 = 10*(catstats[0].DEC[1] + 90);
+  if (DEC1 > (int)(DEC1)) {
+    spd_end =   (int)(1 + 10*(catstats[0].DEC[1] + 90));
+  } else {
+    spd_end =   (int)(0 + 10*(catstats[0].DEC[1] + 90));
+  }
+
+  Nusno = 0;
+  NUSNO = 5000;
+  ALLOCATE (stars, StarData, NUSNO);
+
+  for (spd = spd_start; spd < spd_end; spd ++) {
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/%03d/b%04d.acc", USNO_B_DIR, (int)(spd/10), spd); 
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open accelerator file %s\n", filename);
+      exit (1);  
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].RA[0] / 3.75;
+    if ((catstats[0].RA[1] / 3.75) == (int) (catstats[0].RA[1] / 3.75)) 
+      last  = catstats[0].RA[1] / 3.75;
+    else 
+      last  = 1 + catstats[0].RA[1] / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "ERROR: RA out of range\n");
+      exit (1);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/%03d/b%04d.cat", USNO_B_DIR, (int)(spd/10), spd); 
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s\n", filename);
+      exit (1);
+    }
+
+    /** USNO-B consists of 20 x 4byte (int) records **/
+    /* advance file pointer to first slice */
+    offset = NELEM*NBYTE*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+
+    /* sum the number of stars in data segment of interest */
+    Nstars = 0;
+    for (bin = first; bin < last; bin++) {
+      Nstars += number[bin];
+    }
+    Nitems = NELEM*Nstars;  /* number of integer blocks; need to use Fread for byte-swapping read */
+
+    /* allocate space for stars in segment */
+    ALLOCATE (buffer, int, Nitems);
+    // data has the WRONG byte order?
+    // nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+    nitems = fread (buffer, sizeof(int), Nitems, f);
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failure reading data from file %s\n", filename);
+      exit (1);
+    }
+
+    buf = buffer;
+    /* print out data from slice within RA and DEC range */
+    for (i = 0; i < Nstars; i++, buf += NELEM) {
+      if (buf[0] < iRA0) continue;
+      if (buf[0] > iRA1) continue;
+      if (buf[1] < iDEC0) continue;
+      if (buf[1] > iDEC1) continue;
+      
+      bzero (&stars[Nusno], sizeof(StarData));
+      stars[Nusno].R = buf[0]/360000.0;
+      stars[Nusno].D = buf[1]/360000.0 - 90.0;
+      
+      uR = (buf[2] % 10000);
+      uR = (uR - 5000.0) * 0.002 / 3600.0;
+      uD = ((buf[2] / 10000) % 10000);
+      uD = (uD - 5000.0) * 0.002 / 3600.0;
+
+      /* 1st blue mag */
+      mB1 = 0.01 * (buf[5] % 10000);
+      /* 1st blue mag */
+      mB2 = 0.01 * (buf[6] % 10000);
+      /* 1st blue mag */
+      mR1 = 0.01 * (buf[7] % 10000);
+      /* 1st blue mag */
+      mR2 = 0.01 * (buf[8] % 10000);
+
+      if (mB1 && mB2) {
+	mB = 0.5*(mB1 + mB2);
+      } else {
+	mB = (mB1) ? mB1 : mB2;
+      }
+
+      if (mR1 && mR2) {
+	mR = 0.5*(mR1 + mR2);
+      } else {
+	mR = (mR1) ? mR1 : mR2;
+      }
+      
+      stars[Nusno].M = mB;
+      stars[Nusno].R += uR*(epoch - 2000.0);
+      stars[Nusno].D += uD*(epoch - 2000.0);
+      Nusno ++;
+      CHECK_REALLOCATE (stars, StarData, NUSNO, Nusno, 5000);
+    }
+    free (buffer);
+    fclose (f);
+  }
+
+  area_of_region (catstats);
+
+  REALLOCATE (stars, StarData, MAX (1, Nusno));
+
+  Ref[0].stars = stars;
+  Ref[0].N     = Nusno;
+  Ref[0].R0    = catstats[0].RA[0];
+  Ref[0].R1    = catstats[0].RA[1];
+  Ref[0].D0    = catstats[0].DEC[0];
+  Ref[0].D1    = catstats[0].DEC[1];
+  Ref[0].Area  = catstats[0].Area;
+
+  get_luminosity_func (Ref[0].stars, Ref[0].N, &Ref[0].lum);
+  
+  if (VERBOSE) fprintf (stderr, "%d stars from USNO 1.0\n", Nusno);
+  return (TRUE);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gfit2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gfit2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gfit2.c	(revision 16632)
@@ -0,0 +1,83 @@
+# include "gastro2.h"
+
+void gfit (CmpCatalog *Target, RefCatalog *Ref, int order) {
+
+  int i, j, j0;
+  int Npair, *idx1, *idx2;
+  double Radius, Radius2;
+  double dX, dY, dR;
+  RefCatalog Subset;
+  StarData *st, *sr;
+
+  /* XXX why is this hardwired here? */
+  NFIELD = 0.1;
+  gproject (Target, Ref, &Subset);
+  if (PLOTSTUFF) plot_fullfield (Target, &Subset);
+
+  if (Subset.N < 3) {
+    fprintf (stderr, "ERROR: solution off target\n");
+    exit (1);
+  }
+
+  /* need the stars sorted in X */
+  sort_stars_X (Target[0].stars, Target[0].N);
+  sort_stars_X (Subset.stars, Subset.N);
+
+  Radius = MAX (2.5 * Target[0].answer.dR, 0.5);
+  Radius2 = Radius*Radius;
+
+  st = Target[0].stars;
+  sr = Subset.stars;
+
+  /* find the matched pairs of stars within the radius */
+  pair_init ();
+  for (i = j = 0; (i < Target[0].N) && (j < Subset.N);) {
+    /* get in right X range */
+    dX = st[i].X - sr[j].X;
+    if (dX < -Radius) {
+      i++;
+      continue;
+    }
+    if (dX > Radius) {
+      j++;
+      continue;
+    }
+
+    /* check for pairs in this X range */
+    j0 = j;
+    for (; (dX > -Radius) && (j < Subset.N); j++) {
+    
+      dX = st[i].X - sr[j].X;
+      dY = st[i].Y - sr[j].Y;
+
+      dR = dX*dX + dY*dY;
+      if (dR > Radius2) {
+	j++;
+	continue;
+      }
+      pair_add (i, j);
+    }
+    j = j0;
+    i ++;
+  }
+  
+  Npair = pair_lists (&idx1, &idx2);
+  /* find fit for matched pairs */
+  fit_init (order);
+  for (i = 0; i < Npair; i++) {
+    fit_add (st[idx1[i]].X, st[idx1[i]].Y, sr[idx2[i]].P, sr[idx2[i]].Q, 1.0);
+  }
+  fit_eval ();
+
+  /* XXX this is weak: the fit_scat call requires the coords from the fit_adjust call */
+  Target[0].answer.N  = fit_adjust (&Target[0].coords);
+  Target[0].answer.dR = fit_scat (st, sr, &Target[0].coords);
+
+  if (PLOTSTUFF) fprintf (stderr, "ploting resid (2)\n");
+  plot_resid_init (0, (double) Target[0].header.Naxis[0]);
+  // XXX test: plotting fit_apply and RD_to_XY results plot_resid_init (1, (double) Target[0].header.Naxis[1]);
+  plot_resid_init (1, (double) Target[0].header.Naxis[0]);
+  if (PLOTSTUFF) plot_resid (st, sr, &Target[0].coords);
+  free (idx1);
+  free (idx2);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gheader2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gheader2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gheader2.c	(revision 16632)
@@ -0,0 +1,106 @@
+# include "gastro2.h"
+
+void gheader (char *file, CmpCatalog *Target) {
+
+  double dR;
+  Header header;
+  FILE *f, *g;
+  int i, oldsize, nbytes, status;
+  char line[1024];
+
+  if (!gfits_read_header (file, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s (3)\n", file);
+    exit(0);
+  }
+  oldsize = header.size;
+
+  /* check for insufficient number of stars */
+  switch (Target[0].coords.Npolyterms) {
+    case 0:
+    case 1:
+      if (Target[0].answer.N < 6) {
+	gfits_modify (&header, "NASTRO", "%d", 1, 0);
+	gfits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+	goto skipstuff;
+      }
+      break;
+    case 2:
+      if (Target[0].answer.N < 12) {
+	gfits_modify (&header, "NASTRO", "%d", 1, 0);
+	gfits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+	goto skipstuff;
+      }
+      break;
+    case 3:
+      if (Target[0].answer.N < 20) {
+	gfits_modify (&header, "NASTRO", "%d", 1, 0);
+	gfits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+	goto skipstuff;
+      }
+      break;
+    default:
+      fprintf (stderr, "invalid order\n");
+      exit (2);
+  }
+  
+  gfits_modify (&header, "NASTRO", "%d", 1, Target[0].answer.N);
+  gfits_modify (&header, "NASTRO", "%C", 1, "number of stars used for astrometry");
+
+  /*** use PutCoords to update header ***/
+  PutCoords (&Target[0].coords, &header);
+
+  dR = fabs (Target[0].answer.dR*Target[0].coords.cdelt1*3600.0);
+  gfits_modify (&header, "CERROR", "%lf", 1, dR);
+  gfits_modify (&header, "CERROR", "%C", 1, "scatter in astrometry soln (arcsec)");
+  gfits_modify (&header, "CPRECISE", "%lf", 1, dR / sqrt(1.0*Target[0].answer.N));
+  gfits_modify (&header, "CPRECISE", "%C", 1, "precision of astrometry soln (arcsec)");
+  gfits_modify (&header, "EQUINOX", "%lf", 1, 2000.0);
+  /* we force equinox to be 2000.0 for all images */
+
+skipstuff:
+  if (header.size > oldsize) {
+    if (VERBOSE) fprintf (stderr, "header expanded, creating new copy\n");
+    sprintf (line, "mv %s %s~", file, file);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", file);
+      exit (0);
+    }
+    sprintf (line, "%s~", file);
+    f = fopen (line, "r");
+    g = fopen (file, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", line);
+      exit(0);
+    }
+    if (g == NULL) {
+      fprintf (stderr, "ERROR: can't open output image file %s (4)\n", file);
+      exit(0);
+    }
+    nbytes = fwrite (header.buffer, 1, header.size, g);
+    fseek (f, oldsize, SEEK_SET);
+    for (i = 0; (nbytes = fread (header.buffer, 1, header.size, f)) > 0; i++) {
+      if (nbytes != fwrite (header.buffer, 1, nbytes, g)) {
+	fprintf (stderr, "ERROR: failure writing output data file\n");
+	exit (0);
+      }
+    }
+    fclose (f);
+    fclose (g);
+  } else {
+    f = fopen (file, "r+");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't find image file %s (4)\n", file);
+      exit(0);
+    }
+    
+    fseek (f, 0, SEEK_SET);
+    nbytes = fwrite (header.buffer, 1, header.size, f);
+    
+    fclose (f);
+  }
+  free (header.buffer);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gpairs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gpairs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gpairs.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "gastro2.h"
+
+static int NPAIR, Npair;
+static int *idx1, *idx2;
+
+void pair_init () {
+
+  Npair = 0;
+  NPAIR = 100;
+  ALLOCATE (idx1, int, NPAIR);
+  ALLOCATE (idx2, int, NPAIR);
+
+}
+
+void pair_add (int i1, int i2) {
+
+  idx1[Npair] = i1;
+  idx2[Npair] = i2;
+
+  Npair ++;
+
+  if (Npair == NPAIR) {
+    NPAIR += 100;
+    REALLOCATE (idx1, int, NPAIR);
+    REALLOCATE (idx2, int, NPAIR);
+  }
+
+}
+
+int pair_lists (int **index1, int **index2) {
+
+  *index1 = idx1;
+  *index2 = idx2;
+  return (Npair);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gproject2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gproject2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gproject2.c	(revision 16632)
@@ -0,0 +1,135 @@
+# include "gastro2.h"
+
+void gproject (CmpCatalog *Target, RefCatalog *Ref, RefCatalog *Subset) {
+
+  int i, N;
+  double X, Y, P, Q, M, Moff;
+  double XMIN, XMAX, YMIN, YMAX, MMIN, MMAX;
+  Coords TPtoSky, FPtoTP, *coords;
+  StarData *in, *out;
+
+  Subset[0] = Ref[0];
+
+  ALLOCATE (Subset[0].stars, StarData, MAX (1, Ref[0].N));
+
+  in     = Ref[0].stars;
+  out    = Subset[0].stars;
+
+  coords = &Target[0].coords;
+
+  /* create Tangent Plane to Sky transformation from input coords */
+  strcpy (TPtoSky.ctype, coords[0].ctype);
+  TPtoSky.crval1 = coords[0].crval1;
+  TPtoSky.crval2 = coords[0].crval2;
+
+  TPtoSky.cdelt1 = TPtoSky.cdelt2 = 1;
+  TPtoSky.crpix1 = TPtoSky.crpix2 = 0;
+  TPtoSky.pc1_1 = TPtoSky.pc2_2 = 1;
+  TPtoSky.pc1_2 = TPtoSky.pc2_1 = 0;
+  TPtoSky.Npolyterms = 0;
+  for (i = 0; i < 7; i++) {
+    TPtoSky.polyterms[i][0] = 0;
+    TPtoSky.polyterms[i][1] = 0;
+  }
+
+  /* create Focal Plane to Tangent Plane transformation from input coords */
+  strcpy (FPtoTP.ctype, "FP---PLY");
+  FPtoTP.crval1 = FPtoTP.crval2 = 0;
+
+  FPtoTP.cdelt1 = coords[0].cdelt1;
+  FPtoTP.cdelt2 = coords[0].cdelt2;
+  FPtoTP.crpix1 = coords[0].crpix1;
+  FPtoTP.crpix2 = coords[0].crpix2;
+  FPtoTP.pc1_1  = coords[0].pc1_1;
+  FPtoTP.pc1_2  = coords[0].pc1_2;
+  FPtoTP.pc2_1  = coords[0].pc2_1;
+  FPtoTP.pc2_2  = coords[0].pc2_2;
+
+  FPtoTP.Npolyterms = coords[0].Npolyterms;
+  for (i = 0; i < 7; i++) {
+    FPtoTP.polyterms[i][0] = coords[0].polyterms[i][0];
+    FPtoTP.polyterms[i][1] = coords[0].polyterms[i][1];
+  }
+
+  Moff = Ref[0].Moff;
+
+  XMIN = -0.5*NFIELD*Target[0].header.Naxis[0];
+  XMAX =  0.5*NFIELD*Target[0].header.Naxis[0] + Target[0].header.Naxis[0];
+  YMIN = -0.5*NFIELD*Target[0].header.Naxis[1];
+  YMAX =  0.5*NFIELD*Target[0].header.Naxis[1] + Target[0].header.Naxis[1];
+ 
+  /* need to allow some leeway? use a fixed +/- 0.5 mag for now */
+  MMIN = MMAX = 0;
+  if (MAGLIMS && !MAGMANUAL) {
+      MMAX = Target[0].lum.Mmax + 1.0;
+      MMIN = Target[0].lum.Mmin - 1.0;
+
+      if (MMAX < Ref[0].lum.Mmin + Moff) 
+	  fprintf (stderr, "warning: reference catalog probably too faint:  %5.3f < %5.3f\n", Target[0].lum.Mmax, Ref[0].lum.Mmin + Moff);
+
+      if (MMIN > Ref[0].lum.Mmax + Moff) 
+	  fprintf (stderr, "warning: reference catalog probably too bright: %5.3f > %5.3f\n", Target[0].lum.Mmin, Ref[0].lum.Mmax + Moff);
+  }
+  if (MAGMANUAL) {
+      MMIN = MAGLIM_MIN;
+      MMAX = MAGLIM_MAX;
+      Moff = 0;
+  }
+
+  if (VERBOSE) fprintf (stderr, "limited reference stars to mag range %f - %f\n", MMIN - Moff, MMAX - Moff);
+
+  for (N = i = 0; i < Ref[0].N; i++) {
+    RD_to_XY (&X, &Y, in[i].R, in[i].D, coords);
+    M = in[i].M + Moff;
+
+    if (X < XMIN) continue;
+    if (X > XMAX) continue;
+    if (Y < YMIN) continue;
+    if (Y > YMAX) continue;
+
+    if (MAGLIMS) {
+      if (M < MMIN) continue;
+      if (M > MMAX) continue;
+    }
+
+    /* get tangent-plane coordinates as well */
+    RD_to_XY (&P, &Q, in[i].R, in[i].D, &TPtoSky);
+
+    out[N] = in[i];
+    out[N].X = X;
+    out[N].Y = Y;
+    out[N].P = P;
+    out[N].Q = Q;
+    out[N].M = M;
+    N++;
+  }
+
+  if (N < 3) {
+    fprintf (stderr, "ERROR: too few reference stars accepted\n");
+    exit (1);
+  }
+    
+  Subset[0].N = N;
+  sort_stars_mag (Subset[0].stars, N);
+  if (GASTRO_MAX_NSTARS && (GASTRO_MAX_NSTARS < Subset[0].N)) {
+    Subset[0].N = GASTRO_MAX_NSTARS;
+    REALLOCATE (Subset[0].stars, StarData, Subset[0].N);
+  }
+  if (VERBOSE) fprintf (stderr, "using %d stars from ref catalog\n", Subset[0].N);
+
+  REALLOCATE (Subset[0].stars, StarData, MAX (1, Subset[0].N));
+
+  /* get tangent-plane coords for target as well */
+  for (i = 0; i < Target[0].N; i++) {
+    XY_to_RD (&P, &Q, Target[0].stars[i].X, Target[0].stars[i].Y, &FPtoTP);
+    Target[0].stars[i].P = P;
+    Target[0].stars[i].Q = Q;
+  }
+
+}
+
+/* in this function, we convert the Ra & Dec coords to the rough X, Y coords
+   we also convert the magnitudes to the approximate system with Ref[0].Moff 
+   also, reduce the domain to those within X, Y, M limits 
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/greference2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/greference2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/greference2.c	(revision 16632)
@@ -0,0 +1,131 @@
+# include "gastro2.h"
+
+void greference (CmpCatalog *Target, RefCatalog *Ref) {
+
+  CatStats catstats;
+
+  if (VERBOSE) fprintf (stderr, "loading astrometric reference data from %s\n", REFCAT); 
+
+  define_region (&catstats, Target);
+
+  Ref[0].N = 0;
+  /* get stars from the USNO A catalog for the given region */
+  if (!strcasecmp (REFCAT, "USNO")) {
+    getusno (&catstats, Ref);
+    /* calculate Ref[0].Moff from Target & Ref dMdN, Mo */
+  }
+
+  /* get stars from the USNO B catalog for the given region */
+  if (!strcasecmp (REFCAT, "USNOB")) {
+    getusnob (&catstats, Ref, 2000.0);
+    /* calculate Ref[0].Moff from Target & Ref dMdN, Mo */
+  }
+
+  /* get stars from the HST GSC catalog for the given region */
+  if (!strcasecmp (REFCAT, "GSC")) {
+    getgsc (&catstats, Ref);
+  }
+  
+  /* get stars from 2MASS for the given region -- add PHOTCODE check? */
+  if (!strcasecmp (REFCAT, "2MASS")) {
+    strcpy (CATDIR, TWO_MASS_DIR);
+    getptolemy (&catstats, Ref);
+  }
+  
+  /* get stars from the DVO CATDIR for the given region */
+  if (!strcasecmp (REFCAT, "PTOLEMY")) {
+    strcpy (CATDIR, ASTROM_CATDIR);
+    getptolemy (&catstats, Ref);
+  }
+  
+  if (Ref[0].N == 0) {
+    fprintf (stderr, "no ref objs: %s\n", REFCAT);
+    exit (1);
+  }
+
+  {
+    double Mref, Mtar, logRho;
+
+    /* what is the offset between the two lines at the average magnitude? */
+    Mref = 0.5*(Ref[0].lum.Mmin + Ref[0].lum.Mmax);
+    logRho = Mref * Ref[0].lum.dNdM + Ref[0].lum.Mo - log10(Ref[0].Area);
+    Mtar = (logRho + log10(Target[0].Area) - Target[0].lum.Mo) / Target[0].lum.dNdM;
+
+    Ref[0].lum.Mz = Mref;
+    Target[0].lum.Mz = Mtar;
+    Ref[0].Moff = Target[0].lum.Mz - Ref[0].lum.Mz;
+    fprintf (stderr, "mag offset: %f (Areas: %f vs %f; log(Rho): %f @ %f mags)\n", Ref[0].Moff, Target[0].Area, Ref[0].Area, logRho, Mref);
+  }
+
+  if (PLOTSTUFF) plot_lumfunc (Target, Ref);
+
+}
+
+/* return RA, DEC bounds of the reigon of interest */  
+void define_region (CatStats *catstats, CmpCatalog *Target) {
+   
+  int NX, NY, status;
+  double x, y, X, Y, R, D, dX, dY, Xo, Yo;
+
+  NX = Target[0].header.Naxis[0];
+  NY = Target[0].header.Naxis[1];
+
+  dX = NX + NFIELD*NX;
+  dY = NY + NFIELD*NY;
+
+  Xo = -0.5*NFIELD*NX;
+  Yo = -0.5*NFIELD*NY;
+
+  if (ASCA) {
+      XY_to_RD (&R, &D, 0.5*NX, 0.5*NY, &Target[0].coords);
+      catstats[0].RA[0]  = R - 90.0;
+      catstats[0].RA[1]  = R + 90.0;
+      catstats[0].DEC[0] = MAX (-90.0, D - 90.0);
+      catstats[0].DEC[1] = MIN (+90.0, D + 90.0);
+      if (VERBOSE) fprintf (stderr, "asca region: %f - %f, %f - %f\n", 
+			    catstats[0].RA[0], catstats[0].RA[1], catstats[0].DEC[0], catstats[0].DEC[1]);
+      return;
+  }
+
+  catstats[0].RA[0] =  360.0;
+  catstats[0].RA[1] =    0.0;
+  catstats[0].DEC[0] = +90.0;
+  catstats[0].DEC[1] = -90.0;
+
+  for (x = 0; x <= 1.0; x += 0.5) {
+    for (y = 0; y <= 1.0; y += 0.5) {
+
+      X = x*dX + Xo;
+      Y = y*dY + Yo;
+      status = XY_to_RD (&R, &D, X, Y, &Target[0].coords);
+      if (!status) continue;
+      if (isinf(R) || isnan(R)) continue;
+      if (isinf(D) || isnan(D)) continue;
+
+      catstats[0].RA[0]  = MIN (catstats[0].RA[0], R);
+      catstats[0].RA[1]  = MAX (catstats[0].RA[1], R);
+      catstats[0].DEC[0] = MIN (catstats[0].DEC[0], D);
+      catstats[0].DEC[1] = MAX (catstats[0].DEC[1], D);
+    }
+  }
+
+  /* is a pole in the image?  if so, include it... */
+  status = RD_to_XY (&X, &Y, 0.0, 90.0, &Target[0].coords);
+  if (status) {
+      if (fabs(X - NX*0.5) > (NFIELD + 0.5)*NX) goto not_north;
+      if (fabs(Y - NY*0.5) > (NFIELD + 0.5)*NY) goto not_north;
+      catstats[0].DEC[1] = 90.0;
+  }
+not_north:
+  
+  status = RD_to_XY (&X, &Y, 0.0, -90.0, &Target[0].coords);
+  if (status) {
+      if (fabs(X - NX*0.5) > (NFIELD + 0.5)*NX) goto not_south;
+      if (fabs(Y - NY*0.5) > (NFIELD + 0.5)*NY) goto not_south;
+      catstats[0].DEC[0] = -90.0;
+  }
+not_south:
+
+  if (VERBOSE) fprintf (stderr, "full region: %f - %f, %f - %f\n", 
+	   catstats[0].RA[0], catstats[0].RA[1], catstats[0].DEC[0], catstats[0].DEC[1]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/grid.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/grid.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/grid.c	(revision 16632)
@@ -0,0 +1,219 @@
+# include "gastro2.h"
+
+/* this needs to be user-configured */
+static int NX, NY, Nbin;
+static double C0x, C1x, C0y, C1y;
+static double *N, *DX, *DY, *D2;
+
+void grid (CmpCatalog *Target, RefCatalog *Subset, Answer *answer) {
+
+  int i, j, n, Imin, Nmin, Nval;
+  double XMIN, XMAX, YMIN, YMAX;
+  double dX, dY;
+  double s, f, Fmin, Smin, *ntmp;
+
+  RefCatalog Ref;
+  StarData *st, *sr;
+
+  /* Ref is temporary in this function.  Free Ref.stars before exiting */
+  rotate (Subset, &Ref, answer[0].angle);
+
+  st = Target[0].stars;
+  sr = Ref.stars;
+  
+  /* NFIELD represents the search box; it is also the extra padding used 
+     to select the reference stars */
+  XMIN = -0.5*NFIELD*Target[0].header.Naxis[0];
+  XMAX = +0.5*NFIELD*Target[0].header.Naxis[0];
+  YMIN = -0.5*NFIELD*Target[0].header.Naxis[1];
+  YMAX = +0.5*NFIELD*Target[0].header.Naxis[1];
+
+  dX = dY = 0;
+  /* make two passes, with grids offset by 0.5 box for the second */
+  for (n = 0; n < 2; n++) {
+    gridinit (XMIN, XMAX, YMIN, YMAX, Ref.N, Target[0].N);
+    
+    if (PLOTSTUFF) plot_init_gridplot ();
+    /* fill in grid points */
+    for (i = 0; i < Target[0].N; i++) {
+      for (j = 0; j < Ref.N; j++) {
+	
+	dX = st[i].X - sr[j].X;
+	if (dX < XMIN) continue;
+	if (dX > XMAX) continue;
+	
+	dY = st[i].Y - sr[j].Y;
+	if (dY < YMIN) continue;
+	if (dY > YMAX) continue;
+	
+	gridbin (dX, dY);
+	if (PLOTSTUFF) plot_addpt_gridplot (dX, dY);
+      }
+    }
+
+    /* use sorted N list to define Nmin cut */
+    ALLOCATE (ntmp, double, Nbin);
+    bcopy (N, ntmp, Nbin*sizeof(double));
+    dsort (ntmp, Nbin);
+    for (i = 0; (ntmp[i] == 0) && (i < Nbin); i++);
+    Nval = MIN (Nbin - 1, (int)(0.75*(Nbin - i)) + i);
+    Nmin = ntmp[Nval];
+    free (ntmp);
+    
+    /* select 'best' grid point - is this statistic good enough? */
+    Fmin = 1e10;
+    Imin = -1;
+    for (i = 0; i < Nbin; i++) {
+      
+      if (N[i] < Nmin) continue;
+      
+      /* s is the variance, f is varience overweighted by number */
+      s = fabs ((D2[i]/N[i]) - SQ(DX[i]/N[i]) - SQ(DY[i]/N[i]));
+      f = s / SQ(SQ(N[i]));
+      
+      if (f < Fmin) {
+	Smin = s;
+	Fmin = f;
+	Imin = i;
+      }
+    }
+    if (Imin == -1) { 
+      fprintf (stderr, "ERROR: odd min value\n");
+      exit (1);
+    }
+    
+    if ((n == 0) || (Fmin < answer[0].Chi)) {
+      Smin = fabs ((D2[Imin]/N[Imin]) - SQ(DX[Imin]/N[Imin]) - SQ(DY[Imin]/N[Imin]));
+      answer[0].Xoff = DX[Imin] / N[Imin];
+      answer[0].Yoff = DY[Imin] / N[Imin];
+      answer[0].dR   = sqrt (Smin);
+      answer[0].Chi  = Fmin;
+      answer[0].N    = N[Imin];
+    }
+    
+    fprintf (stderr, "angle: %6.1f, (%6.1f,%6.1f) - %6.2f : %10.8f for %d pairs\n", 
+	     answer[0].angle, answer[0].Xoff, answer[0].Yoff, answer[0].dR, answer[0].Chi, answer[0].N);
+
+    if (PLOTSTUFF) plot_gridpts (N, Nbin);
+    if (PLOTSTUFF) plot_done_gridplot (dX, dY);
+
+    XMIN -= 0.5*NGRID_PIX;
+    XMAX -= 0.5*NGRID_PIX;
+    YMIN -= 0.5*NGRID_PIX;
+    YMAX -= 0.5*NGRID_PIX;
+    gridfree ();
+  }
+
+  free (Ref.stars);
+
+}
+
+void gridinit (double XMIN, double XMAX, double YMIN, double YMAX, int Nr, int Nt) {
+
+  NX = (XMAX - XMIN) / NGRID_PIX;
+  NY = (YMAX - YMIN) / NGRID_PIX;
+
+  C1x =          NX / (XMAX - XMIN); 
+  C0x = - XMIN * NX / (XMAX - XMIN);
+
+  C1y =          NY / (YMAX - YMIN); 
+  C0y = - YMIN * NY / (YMAX - YMIN);
+
+  Nbin = NX*NY;
+
+  ALLOCATE (N, double, Nbin);
+  ALLOCATE (DX, double, Nbin);
+  ALLOCATE (DY, double, Nbin);
+  ALLOCATE (D2, double, Nbin);
+
+  bzero (N,  Nbin*sizeof(double));
+  bzero (DX, Nbin*sizeof(double));
+  bzero (DY, Nbin*sizeof(double));
+  bzero (D2, Nbin*sizeof(double));
+
+}
+
+int gridbin (double dX, double dY) {
+
+  int bin, xbin, ybin;
+
+  xbin = (int) (C0x + dX * C1x);
+  ybin = (int) (C0y + dY * C1y);
+
+  bin =  xbin + NX * ybin;
+
+  if (bin < 0)     return (0);
+  if (bin >= Nbin) return (0);
+
+  N[bin]   += 1.0;
+  DX[bin]  += dX;
+  DY[bin]  += dY;
+  D2[bin]  += dX*dX + dY*dY;
+  
+  return (bin);
+
+}
+  
+void gridfree () {
+
+  free (N);
+  free (DX);
+  free (DY);
+  free (D2);
+
+}
+
+# if (0) 
+  /* use sorted N list to define Nmin cut */
+  ALLOCATE (ntmp, double, Nbin);
+  bcopy (N, ntmp, Nbin*sizeof(double));
+  dsort (ntmp, Nbin);
+  for (i = 0; (ntmp[i] == 0) && (i < Nbin); i++);
+  Nval = MIN (Nbin - 1, (int)(0.75*(Nbin - i)) + i);
+  Nmin = ntmp[Nval];
+  free (ntmp);
+
+  /* select 'best' grid point - is this statistic good enough? */
+  Fmin = 1e10;
+  Imin = -1;
+  for (i = 0; i < Nbin; i++) {
+
+    if (N[i] < Nmin) continue;
+
+    /* s is the variance, f is varience overweighted by number */
+    s = fabs ((D2[i]/N[i]) - SQ(DX[i]/N[i]) - SQ(DY[i]/N[i]));
+    f = s / SQ(SQ(N[i]));
+
+    if (f < Fmin) {
+      Smin = s;
+      Fmin = f;
+      Imin = i;
+    }
+  }
+  if (Imin == -1) { 
+    fprintf (stderr, "ERROR: odd min value\n");
+    exit (1);
+  }
+# endif
+
+# if (0)
+    /* find N sigma */
+    Ns = Ns2 = 0;
+    for (i = 0; i < Nbin; i++) {
+      Ns += N[i];
+      Ns2 += N[i]*N[i];
+    }
+    Ns = Ns / Nbin;
+    Ns2 = sqrt (Ns2 / Nbin - Ns*Ns);
+    fprintf (stderr, "N sigma: %f\n", Ns2);
+    
+    Imin = 0;
+    Fmin = N[0] / Ns2;
+    for (i = 0; i < Nbin; i++) {
+      f = N[i] / Ns2;
+      if (f > Fmin) {
+	Fmin = f;
+	Imin = i;
+      }
+    }
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/gstars2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/gstars2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/gstars2.c	(revision 16632)
@@ -0,0 +1,177 @@
+# include "gastro2.h"
+
+void gstars (char *filename, CmpCatalog *Target) {
+
+  int Nstars;
+  char line[80];
+  double det;
+  int NX, NY, Nskip, FoundAstrom, extend, naxis;
+  StarData *stars;
+  FILE *f;
+
+  /* open file for stars */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open file to load stars\n");
+    exit (1);
+  }
+  if (!gfits_fread_header (f, &Target[0].header)) {
+    fprintf (stderr, "ERROR: can't read image header\n");
+    exit (1);
+  }
+  /* this line should not be needed */
+  fseek (f, Target[0].header.size, SEEK_SET); 
+
+  NX = Target[0].header.Naxis[0];
+  NY = Target[0].header.Naxis[1];
+
+  /* default values for coords */
+  strcpy (Target[0].coords.ctype, "RA---TAN");
+  Target[0].coords.pc1_1 = CCD_PC1_1; Target[0].coords.pc1_2 = CCD_PC1_2;
+  Target[0].coords.pc2_1 = CCD_PC2_1; Target[0].coords.pc2_2 = CCD_PC2_2;
+  Target[0].coords.cdelt1 = Target[0].coords.cdelt2 = ASEC_PIX / 3600.0;
+  Target[0].coords.Npolyterms = 0;
+  Target[0].coords.crpix1 = 0.5*NX;
+  Target[0].coords.crpix2 = 0.5*NY;
+  
+  /* attempt to get detailed astrometric information from header */
+  FoundAstrom = FALSE;
+  if (!strcasecmp (ROUGH_ASTROMETRY, "header")) {
+    if (!HEADER[0]) {
+      FoundAstrom = GetCoords (&Target[0].coords, &Target[0].header);
+    } else {
+      Header header;
+
+      if (!gfits_read_header (HEADER, &header)) {
+	fprintf (stderr, "ERROR: can't load external header\n");
+	exit (1);
+      }
+      FoundAstrom = GetCoords (&Target[0].coords, &header);
+      gfits_free_header (&header);
+    }
+    if (!FoundAstrom) {
+      fprintf (stderr, "header coordinates incomplete, trying for rough coordinates\n");
+      strcpy (ROUGH_ASTROMETRY, "config");
+    } else {
+      /* make optional adustments to header values (standard problems) */
+      if (FLIPX) {
+	Target[0].coords.pc1_1 *= -1;
+	Target[0].coords.crpix1 = NX - Target[0].coords.crpix1;
+      }
+      if (FLIPY) {
+	Target[0].coords.pc2_2 *= -1;
+	Target[0].coords.crpix2 = NY - Target[0].coords.crpix2;
+      }
+    }
+  }
+  
+  /*** abstract RA & DEC keywords, formats */
+  /* get just RA & DEC from header, other terms from config file */
+  if (!strcasecmp (ROUGH_ASTROMETRY, "config")) {
+    /* get RA & DEC from header */
+    FoundAstrom = TRUE;
+    FoundAstrom &= gfits_scan (&Target[0].header, "RA", "%s", 1, line);
+    ohana_dms_to_ddd (&Target[0].coords.crval1, line);
+    Target[0].coords.crval1 = Target[0].coords.crval1 * 15.0;
+    FoundAstrom &= gfits_scan (&Target[0].header, "DEC", "%s", 1, line);
+    ohana_dms_to_ddd (&Target[0].coords.crval2, line);
+  }
+
+  /* use RA & DEC from command line arguments */
+  if (FORCE) {
+    Target[0].coords.crval1 = F_RA;
+    Target[0].coords.crval2 = F_DEC;
+    if (VERBOSE) fprintf (stderr, " forcing coordinates to: %9.4f %9.4f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+    FoundAstrom = TRUE;
+  }    
+
+  if (VERBOSE) fprintf (stderr, "using coordinates: %9.4f %9.4f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+  if (!FoundAstrom) {
+    fprintf (stderr, "ERROR: can't get any valid coordinates, fix config file?\n");
+    exit (1);
+  }
+
+  /* at this point, we need to correct the crval1, crval2, and ROT_ZERO values
+     based on the pole axis angle and the ra, dec offsets */
+
+# define dcos(a) (cos((double)((a)*(RAD_DEG))))
+# define dsin(a) (sin((double)((a)*(RAD_DEG))))
+
+  if (POLAR_ALIGNMENT) {
+
+    double X, Y, PD, PR, DE, RE, T1, T2, T3;
+
+    X = Target[0].coords.crval1;
+    Y = Target[0].coords.crval2;
+    PD = POLE_DEC;   PR = POLE_RA;
+    DE = DEC_OFFSET; RE = RA_OFFSET;
+    
+    T1 = dcos(Y-DE) * dcos(X-RE) * dsin(PD) + dsin(Y-DE) * dcos(PD);
+    T2 = dcos(Y-DE) * dsin(X-RE);
+    T3 = dsin(Y-DE) * dsin(PD) - dcos(Y-DE) * dcos(X-RE) * dcos(PD);
+    
+    Target[0].coords.crval1 = (DEG_RAD * atan2 (T2, T1)) + PR;
+    Target[0].coords.crval2 = (DEG_RAD * asin (T3));
+    while (Target[0].coords.crval1 < 0) Target[0].coords.crval1 += 360.0;
+    while (Target[0].coords.crval1 > 360.0) Target[0].coords.crval1 -= 360.0;
+    
+    if (VERBOSE) fprintf (stderr, "  after polar alignment: %9.4f %9.4f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+  }
+
+  /* get image area in deg^2 */
+  det = Target[0].coords.pc1_1 * Target[0].coords.pc2_2 - Target[0].coords.pc1_2 * Target[0].coords.pc2_1;
+  Target[0].Area = fabs (NX*NY*Target[0].coords.cdelt1*Target[0].coords.cdelt2*det);
+
+  /* read from FITS table or from text table */
+  /* Is NAXIS == 0 a better test?? */
+  extend = FALSE;
+  gfits_scan (&Target[0].header, "NAXIS",  "%t", 1, &naxis);
+  if ((naxis == 0) && !TEXTMODE) {
+    Nskip = gfits_data_size (&Target[0].header);
+    fseek (f, Nskip, SEEK_CUR); 
+    stars = rfits (f, &Nstars);
+  } else {
+    /* allocate space for stars */
+    if (!gfits_scan (&Target[0].header, "NSTARS", "%d", 1, &Nstars)) {
+      fprintf (stderr, "ERROR: failed to find NSTARS\n");
+      exit (1);
+    }
+    stars = rtext (f, &Nstars);
+  }
+  fclose (f);
+
+  stars = remove_clumps (stars, &Nstars, NX, NY);
+
+  sort_stars_mag (stars, Nstars);  /* sorting by magnitude */
+  Target[0].stars = stars;
+  Target[0].N = Nstars;
+
+  /* limit number of stars */
+  if (GASTRO_MAX_NSTARS && (GASTRO_MAX_NSTARS < Target[0].N)) {
+    Target[0].N = GASTRO_MAX_NSTARS;
+    REALLOCATE (Target[0].stars, StarData, Target[0].N);
+  }
+  if (VERBOSE) fprintf (stderr, "using %d stars from data file\n", Target[0].N);
+
+  /* calculate luminosity function of stars */
+  get_luminosity_func (stars, Target[0].N, &Target[0].lum);
+
+}
+
+/* 
+
+load cmp file FITS header 
+
+extract needed data from header:
+- NX, NY?
+- coords
+   
+load stellar photometry
+
+sort stars by mag
+
+filter & limit numbers
+
+find luminosity function slope, area?
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/lumfunc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/lumfunc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/lumfunc.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "gastro2.h"
+
+/* mag range -5 - 35, dmag = 0.25, Nbin = 160 */
+# define MMIN -5
+# define MMAX 35
+# define dM 0.5
+# define NMBIN 90
+
+int get_luminosity_func (StarData *stars, int N, LumStats *lum) {
+
+  int i, j, Nb, peaki, peakn;
+  double mbin[NMBIN];
+  double bin[NMBIN], lbin[NMBIN], rbin[NMBIN];
+  double C0, C1;
+
+  lum[0].dNdM = lum[0].Mo = 0;
+
+  bzero (mbin, NMBIN * sizeof (double));
+
+  /* sum histogram */
+  for (i = 0; i < N; i++) {
+    if (stars[i].M < MMIN) continue;
+    if (stars[i].M > MMAX) continue;
+
+    j = (stars[i].M - MMIN) / dM;
+    j = MIN (MAX (j, 0), (NMBIN - 1));
+    mbin[j] ++;
+  }
+
+  /* find peak bin */
+  peaki = 0;
+  peakn = mbin[0];
+  for (i = 0; i < NMBIN; i++) {
+    if (mbin[i] > peakn) {
+      peaki = i;
+      peakn = mbin[i];
+    }
+  }
+
+  /* select filled bins */
+  for (Nb = i = 0; i < peaki; i++) {
+    if (mbin[i] > 0) {
+      bin[Nb]  = i * dM + MMIN;
+      lbin[Nb] = log10 (mbin[i]);
+      Nb++;
+    }
+  }
+
+  /* find max & min mag bins */
+  lum[0].Mmin = bin[0];
+  lum[0].Mmax = bin[Nb-1];
+
+  if (Nb < 4) { return (FALSE); }
+  fit_lum_bin (bin, lbin, Nb, &C0, &C1);
+  
+  /* find residuals */
+  for (i = 0; i < Nb; i++) {
+    rbin[i] = C0 + C1*bin[i] - lbin[i];
+  }
+
+  /* keep inner 80% */
+  dsortthree (rbin, bin, lbin, Nb);
+  for (j = 0, i = 0.1*Nb; i < 0.9*Nb; i++, j++) {
+    bin[j]  = bin[i];
+    lbin[j] = lbin[i];
+  }    
+  Nb = j;
+
+  if (Nb < 4) { return (FALSE); }
+  fit_lum_bin (bin, lbin, Nb, &C0, &C1);
+
+  lum[0].dNdM = C1;
+  lum[0].Mo   = C0;
+  
+  if (VERBOSE) fprintf (stderr, "lum stats: dNdM = %f, Mo = %f, Mmin = %f, Mmax = %f\n", 
+	   lum[0].dNdM, lum[0].Mo, lum[0].Mmin, lum[0].Mmax);
+
+  return (TRUE);
+
+}
+
+
+void fit_lum_bin (double *x, double *y, int N, double *C0, double *C1) {
+
+  int i;
+  double **c, **b;
+
+  ALLOCATE (c, double *, 2);
+  ALLOCATE (b, double *, 2);
+  ALLOCATE (c[0], double, 2);
+  ALLOCATE (c[1], double, 2);
+  ALLOCATE (b[0], double, 1);
+  ALLOCATE (b[1], double, 1);
+
+  /* fit x, y to line */
+  c[0][0] = 0; c[0][1] = 0;
+  c[1][0] = 0; c[1][1] = 0;
+  b[0][0] = 0; b[1][0] = 0;
+
+  for (i = 0; i < N; i++) {
+    c[0][0] += 1;
+    c[0][1] += x[i];
+    c[1][0] += x[i];
+    c[1][1] += x[i]*x[i];
+    
+    b[0][0] += y[i];
+    b[1][0] += y[i]*x[i];
+  }
+  dgaussjordan (c, b, 2, 1);
+  *C0 = b[0][0];
+  *C1 = b[1][0];
+
+  free (b[0]);
+  free (b[1]);
+  free (c[0]);
+  free (c[1]);
+  free (c);
+  free (b);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/misc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/misc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/misc.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "gastro2.h"
+
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+
+void hh_hms (double hh, int *hr, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh *= flag;
+  hh = 24.0*(hh/24.0 - (int)(hh/24.0));
+  *sc = 60.0*(60.0*hh - (int)(60.0*hh));
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+
+}
+ 
+void hms_format (char *line, double value) {
+
+  int hr, mn;
+  double sc;
+
+  hh_hms (value, &hr, &mn, &sc);
+  hr = (int) value;
+  if (isnan (value))
+    sprintf (line, "xx:xx:xx.xx");
+  else {
+    if (value < 0) {
+      sprintf (line, "-%02d:%02d:%05.2f", abs(hr), mn, sc);
+    } else {
+      sprintf (line, "%02d:%02d:%05.2f", hr, mn, sc);
+    }
+  }      
+}
+
+void area_of_region (CatStats *region) {
+  
+  double area;
+
+  area = DEG_RAD*(region[0].RA[1] - region[0].RA[0])*(sin(region[0].DEC[1]*RAD_DEG) - sin(region[0].DEC[0]*RAD_DEG));
+  region[0].Area = area;
+}
+
+double area_of_skyregion (SkyRegion *region) {
+  
+  double area;
+
+  area = DEG_RAD*(region[0].Rmax - region[0].Rmin)*(sin(region[0].Dmax*RAD_DEG) - sin(region[0].Dmin*RAD_DEG));
+  return (area);
+}
+
+void dump_coords (CmpCatalog *Target) {
+  if (VERBOSE) {
+    fprintf (stderr, "%s\n", Target[0].coords.ctype);
+    fprintf (stderr, "%f %f\n", Target[0].coords.crval1, Target[0].coords.crval2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.crpix1, Target[0].coords.crpix2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.pc1_1,  Target[0].coords.pc1_2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.pc2_1,  Target[0].coords.pc2_2);
+    fprintf (stderr, "%f %f\n", Target[0].coords.cdelt1, Target[0].coords.cdelt2);
+    fprintf (stderr, "\n");
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/plots.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/plots.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/plots.c	(revision 16632)
@@ -0,0 +1,440 @@
+# include "gastro2.h"
+
+int Nv, NV;
+float *xv, *yv;
+Graphdata gv;
+
+void plot_init_gridplot () {
+  
+  NV = 1000;
+  Nv = 0;
+
+  ALLOCATE (xv, float, NV);
+  ALLOCATE (yv, float, NV);
+
+  PlotReset (2);
+
+  gv.xmin = -400;
+  gv.xmax = +400;
+  gv.ymin = -400;
+  gv.ymax = +400;
+
+  gv.style = 2;
+  gv.ltype = 0;
+  gv.etype = 0;
+  gv.ebar  = 0;
+  gv.size = 0.3;
+  gv.lweight = 0;
+  gv.color = 0;
+  gv.ptype = 2;
+
+}
+
+int plot_addpt_gridplot (double x, double y) {
+
+  if (x < gv.xmin) return (0);
+  if (x > gv.xmax) return (0);
+  if (y < gv.ymin) return (0);
+  if (y > gv.ymax) return (0);
+
+  xv[Nv] = x;
+  yv[Nv] = y;
+  Nv ++;
+  
+  if (Nv == NV) {
+    NV += 1000;
+    REALLOCATE (xv, float, NV);
+    REALLOCATE (yv, float, NV);
+  }
+  return (1);
+}
+
+void plot_done_gridplot () {
+
+  char c;
+
+  /* send to Kapa */
+  PrepPlotting (Nv, &gv, 2);
+  PlotVector (Nv, xv, 0, 2);
+  PlotVector (Nv, yv, 1, 2);
+
+  DonePlotting (&gv, 2);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+  free (xv);
+  free (yv);
+}
+  
+static double Xm[2];
+static int Xg[2] = {0, 2};
+
+void plot_resid_init (int version, double xmax) {
+
+  if (version > 1) return;
+  if (version < 0) return;
+  
+  Xm[version] = xmax;
+}
+
+
+void plot_resid_plot (int version, float *xvect, float *yvect, int Nvect) {
+ 
+  int i;
+  char c;
+  float xmin, xmax, ymin, ymax;
+  Graphdata graphdata;
+  
+  xmin = xmax = xvect[0];
+  ymin = ymax = yvect[0];
+  for (i = 0; i < Nvect; i++) {
+    xmax = MAX (xvect[i], xmax);
+    xmin = MIN (xvect[i], xmin);
+    ymax = MAX (yvect[i], ymax);
+    ymin = MIN (yvect[i], ymin);
+  }
+    
+  PlotReset (Xg[version]);
+
+  graphdata.xmin = MIN (xmin,   0);
+  graphdata.xmax = MAX (xmax, Xm[version]);
+  graphdata.ymin = MIN (ymin, -10);
+  graphdata.ymax = MAX (ymax, +10);
+
+  graphdata.style = 2;
+  graphdata.ltype = 0;
+  graphdata.etype = 0;
+  graphdata.ebar  = 0;
+  graphdata.size = 0.5;
+  graphdata.lweight = 0;
+  graphdata.color = 0;
+  graphdata.ptype = 2;
+
+  /* send to Kapa */
+  PrepPlotting (Nvect, &graphdata, Xg[version]);
+  PlotVector (Nvect, xvect, 0, Xg[version]);
+  PlotVector (Nvect, yvect, 1, Xg[version]);
+
+  DonePlotting (&graphdata, Xg[version]);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}
+
+void plot_gridpts (double *pts, int Npts) {
+
+  char c;
+  int i;
+  float *xvect, *yvect, ymax;
+  Graphdata graphdata;
+  
+  ymax = 0;
+  ALLOCATE (xvect, float, Npts);
+  ALLOCATE (yvect, float, Npts);
+  for (i = 0; i < Npts; i++) {
+    xvect[i] = i;
+    yvect[i] = pts[i];
+    ymax = MAX (yvect[i], ymax);
+  }
+    
+  PlotReset (0);
+
+  graphdata.xmin = -10;
+  graphdata.xmax = Npts + 10;
+  graphdata.ymin = -1;
+  graphdata.ymax = ymax + 1;
+
+  graphdata.style = 1;
+  graphdata.ltype = 0;
+  graphdata.etype = 0;
+  graphdata.ebar  = 0;
+  graphdata.size = 0.5;
+  graphdata.lweight = 0;
+  graphdata.color = 0;
+  graphdata.ptype = 0;
+
+  /* send to Kapa */
+  PrepPlotting (Npts, &graphdata, 0);
+  PlotVector (Npts, xvect, 0, 0);
+  PlotVector (Npts, yvect, 1, 0);
+  free (xvect);
+  free (yvect);
+
+  DonePlotting (&graphdata, 0);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}
+
+static Graphdata gf;
+
+void plot_fullfield (CmpCatalog *Target, RefCatalog *Ref) {
+
+  int i, Nvect;
+  float *xvect, *yvect, *zvect, M, dM, mRefMin, mRefMax;
+  char c;
+  
+  dM = Target[0].lum.Mmax - Target[0].lum.Mmin;
+
+  PlotReset (1);
+
+  gf.xmin = -100;
+  gf.xmax = Target[0].header.Naxis[0] + 100;
+  gf.ymin = -100;
+  gf.ymax = Target[0].header.Naxis[1] + 100;
+
+  gf.style = 2;
+  gf.ltype = 0;
+  gf.etype = 0;
+  gf.ebar  = 0;
+  gf.size = -1;
+  gf.lweight = 0;
+
+  /* fill in vectors */
+  Nvect = Target[0].N;
+  ALLOCATE (xvect, float, Nvect);
+  ALLOCATE (yvect, float, Nvect);
+  ALLOCATE (zvect, float, Nvect);
+  for (i = 0; i < Nvect; i++) {
+    xvect[i] = Target[0].stars[i].X;
+    yvect[i] = Target[0].stars[i].Y;
+    M = (Target[0].lum.Mmax - Target[0].stars[i].M) / dM;
+    zvect[i] = MIN (1.0, MAX (0.01, M));
+  }
+
+  /* send to Kapa */
+  gf.ptype = 1;
+  gf.color = 0;
+  PrepPlotting (Nvect, &gf, 1);
+  PlotVector (Nvect, xvect, 0, 1);
+  PlotVector (Nvect, yvect, 1, 1);
+  PlotVector (Nvect, zvect, 1, 1);
+  free (xvect);
+  free (yvect);
+  free (zvect);
+
+  /* fill in vectors */
+  Nvect = Ref[0].N;
+  ALLOCATE (xvect, float, Nvect);
+  ALLOCATE (yvect, float, Nvect);
+  ALLOCATE (zvect, float, Nvect);
+
+  mRefMin = 30.0;
+  mRefMax = -5.0;
+  for (i = 0; i < Nvect; i++) {
+      mRefMin = MIN (mRefMin, Ref[0].stars[i].M);
+      mRefMax = MAX (mRefMax, Ref[0].stars[i].M);
+  }
+  dM = mRefMax - mRefMin;
+
+  for (i = 0; i < Nvect; i++) {
+    xvect[i] = Ref[0].stars[i].X;
+    yvect[i] = Ref[0].stars[i].Y;
+    M = (mRefMax - Ref[0].stars[i].M) / dM;
+    zvect[i] = MIN (1.0, MAX (0.01, M));
+  }
+
+  /* send to Kapa */
+  gf.color = 2;
+  gf.ptype = 2;
+  PrepPlotting (Nvect, &gf, 1);
+  PlotVector (Nvect, xvect, 0, 1);
+  PlotVector (Nvect, yvect, 1, 1);
+  PlotVector (Nvect, zvect, 2, 1);
+  free (xvect);
+  free (yvect);
+  free (zvect);
+
+  DonePlotting (&gf, 1);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}
+
+void plot_fullfield_pairs (float *x, float *y, int n) {
+
+  char c;
+
+  /* send to Kapa */
+  gf.color = 6;
+  gf.ptype = 100;
+  gf.size =  1.0;
+  
+  PrepPlotting (n, &gf, 1);
+  PlotVector (n, x, 0, 1);
+  PlotVector (n, y, 1, 1);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+}  
+
+/* mag range -5 - 35, dmag = 0.25, Nbin = 160 */
+# define MMIN -5
+# define MMAX 35
+# define dM 0.5
+# define NMBIN 90
+
+void plot_lumfunc (CmpCatalog *Target, RefCatalog *Ref) {
+
+  int i, Nr, Nt;
+  float tbin[NMBIN], tval[NMBIN], rbin[NMBIN], rval[NMBIN];
+  double ymin, ymax;
+  char c;
+  Graphdata graphdata;
+
+  fill_lumfunc (Target[0].stars, Target[0].N, tval, tbin, &Nt);
+  fill_lumfunc (Ref[0].stars, Ref[0].N, rval, rbin, &Nr);
+
+  /* construct plots of log(stars / degree square) */
+  ymin = 5; ymax = -5;
+  for (i = 0; i < Nt; i++) {
+    tval[i] = tval[i] - log10 (Target[0].Area);
+    ymin = MIN (tval[i], ymin);
+    ymax = MAX (tval[i], ymax);
+  }
+
+  for (i = 0; i < Nr; i++) {
+    rval[i] = rval[i] - log10 (Ref[0].Area);
+    rbin[i] = rbin[i] + Ref[0].Moff;
+    ymin = MIN (rval[i], ymin);
+    ymax = MAX (rval[i], ymax);
+  }
+
+  graphdata.xmin = MMIN;
+  graphdata.xmax = MMAX;
+  graphdata.ymin = ymin - 0.1;
+  graphdata.ymax = ymax + 0.1;
+
+  graphdata.style = 1;
+  graphdata.ptype = 2;
+  graphdata.ltype = 0;
+  graphdata.etype = 0;
+  graphdata.ebar  = 0;
+  graphdata.color = 0;
+
+  graphdata.lweight = 0;
+  graphdata.size = 0.5;
+
+  PlotReset (0);
+
+  PrepPlotting (Nt, &graphdata, 0);
+  PlotVector (Nt, tbin, 0, 0);
+  PlotVector (Nt, tval, 1, 0);
+
+  graphdata.color = 2;
+  graphdata.style = 1;
+  graphdata.lweight = 0;
+  PrepPlotting (Nr, &graphdata, 0);
+  PlotVector (Nr, rbin, 0, 0);
+  PlotVector (Nr, rval, 1, 0);
+
+  /* plot truncated lum func */
+  for (i = 0; i < Nr; i++) {
+    if (rbin[i] < Target[0].lum.Mmin - 0.5) rval[i] = -1;
+    if (rbin[i] > Target[0].lum.Mmax + 0.5) rval[i] = -1;
+  }
+  graphdata.ltype = 1;
+  PrepPlotting (Nr, &graphdata, 0);
+  PlotVector (Nr, rbin, 0, 0);
+  PlotVector (Nr, rval, 1, 0);
+
+  DonePlotting (&graphdata, 0);
+  fprintf (stderr, "type return to continue");
+  fscanf (stdin, "%c", &c);
+
+}
+
+
+void plot_resid (StarData *st, StarData *sr, Coords *coords) {
+
+  int i;
+  double x, y, dx, dy;
+  float *xvect0, *yvect0, *xvect1, *yvect1, *xvect2, *yvect2;
+  int Npair, *idx1, *idx2;
+
+  Npair = pair_lists (&idx1, &idx2);
+  ALLOCATE (xvect0, float, Npair);
+  ALLOCATE (yvect0, float, Npair);
+  ALLOCATE (xvect1, float, Npair);
+  ALLOCATE (yvect1, float, Npair);
+
+  ALLOCATE (xvect2, float, 2*Npair);
+  ALLOCATE (yvect2, float, 2*Npair);
+  
+  for (i = 0; i < Npair; i++) {
+    RD_to_XY (&x, &y, sr[idx2[i]].R, sr[idx2[i]].D, coords);
+    
+    dx = st[idx1[i]].X - x;
+    dy = st[idx1[i]].Y - y;
+    
+    xvect0[i] = st[idx1[i]].X;
+    xvect1[i] = st[idx1[i]].Y;
+    yvect0[i] = dx;
+    yvect1[i] = dy;
+
+    xvect2[2*i+0] = st[idx1[i]].X;
+    yvect2[2*i+0] = st[idx1[i]].Y;
+    xvect2[2*i+1] = x;
+    yvect2[2*i+1] = y;
+  }
+
+  fprintf (stderr, "residuals using RD_to_XY\n");
+  plot_resid_plot (0, xvect0, yvect0, Npair);
+  // plot_resid_plot (1, xvect1, yvect1, Npair);
+  plot_fullfield_pairs (xvect2, yvect2, 2*Npair);
+
+  for (i = 0; i < Npair; i++) {
+    fit_apply (&x, &y, st[idx1[i]].X, st[idx1[i]].Y);
+    
+    dx = (x - sr[idx2[i]].P)/coords[0].cdelt1;
+    dy = (y - sr[idx2[i]].Q)/coords[0].cdelt2;
+    
+    xvect0[i] = st[idx1[i]].X;
+    xvect1[i] = st[idx1[i]].Y;
+    yvect0[i] = dx;
+    yvect1[i] = dy;
+
+    xvect2[2*i+0] = sr[idx2[i]].P;
+    yvect2[2*i+0] = sr[idx2[i]].Q;
+    xvect2[2*i+1] = x;
+    yvect2[2*i+1] = y;
+  }
+
+  fprintf (stderr, "residuals using fit_apply\n");
+  plot_resid_plot (1, xvect0, yvect0, Npair);
+  // plot_resid_plot (1, xvect1, yvect1, Npair);
+  // plot_fullfield_pairs (xvect2, yvect2, 2*Npair);
+
+  free (xvect2);
+  free (yvect2);
+  free (xvect0);
+  free (yvect0);
+  free (xvect1);
+  free (yvect1);
+
+}
+
+void fill_lumfunc (StarData *stars, int N, float *lbin, float *bin, int *nb) {
+
+  int i, j, Nb;
+  double mbin[NMBIN];
+
+  bzero (mbin, NMBIN * sizeof (double));
+
+  /* sum histogram */
+  for (i = 0; i < N; i++) {
+    if (stars[i].M < MMIN) continue;
+    if (stars[i].M > MMAX) continue;
+
+    j = (stars[i].M - MMIN) / dM;
+    j = MIN (MAX (j, 0), (NMBIN - 1));
+    mbin[j] ++;
+  }
+
+  /* select filled bins */
+  for (Nb = i = 0; i < NMBIN; i++) {
+    if (mbin[i] > 0) {
+      bin[Nb]  = i * dM + MMIN;
+      lbin[Nb] = log (mbin[i]) / log (10.0);
+      Nb++;
+    }
+  }
+
+  *nb = Nb;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/plotstuff.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/plotstuff.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/plotstuff.c	(revision 16632)
@@ -0,0 +1,104 @@
+# include "gastro2.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+  char name[100];
+  
+  active = N;
+
+  sprintf (name, "gastro [%d]", N);
+  Xgraph[N] = KapaOpen ("kapa", name);
+
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+
+  if (Xgraph[N] == 0) return;
+  KapaBox (Xgraph[N], graphmode);
+  return;
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  if (Xgraph[N] == 0) return;
+
+  active = N;
+  if (Npts < 1) return;
+
+  KapaPrepPlot (Xgraph[N], Npts, graphmode);
+}
+
+void PlotVector (int Npts, float *vect, int mode, int N) {
+
+  if (Npts < 1) return;
+  active = N;
+
+  switch (mode) {
+    case 0:
+      KapaPlotVector (Xgraph[N], Npts, vect, "x");
+      break;
+    case 1:
+      KapaPlotVector (Xgraph[N], Npts, vect, "y");
+      break;
+    default:
+      abort();
+  }
+}
+
+void PlotReset (int N) {
+
+  char buffer[128];
+  int i;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+  KapaClearSections (Xgraph[N]);
+}
+
+/* include these lines to plot a pair of vectors: 
+
+   typedef struct {
+   double xmin, xmax, ymin, ymax;
+   int style, ptype, ltype, etype, color;
+   double lweight, size;
+   } Graphdata;
+   Graphdata graphdata;
+   
+   graphdata.xmin = -200;
+   graphdata.xmax = 4200;
+   graphdata.ymin = -500;
+   graphdata.ymax = 500;
+   graphdata.style = 2;
+   graphdata.ptype = 2;
+   graphdata.ltype = 0;
+   graphdata.etype = 0;
+   graphdata.color = 0;
+   graphdata.lweight = 0;
+   graphdata.size = 0.5;
+   
+   PrepPlotting (N, &graphdata, n);
+   PlotVector (N, Y, 0, n);
+   PlotVector (N, dM, 1, n);
+   DonePlotting (&graphdata, n);
+   
+ */
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/polyfit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/polyfit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/polyfit.c	(revision 16632)
@@ -0,0 +1,408 @@
+# include "gastro2.h"
+
+static int NTERM, NPOWR, NPARS, NORDER, Npts;
+static double **sum, **xsum, **ysum;
+static double **matrix, **vector;
+
+void fit_init (int order) {
+
+  int i;
+
+  NORDER = order;
+  NPOWR = NORDER + 1;
+  NTERM = 2*NORDER + 1;
+  NPARS = (NORDER + 1)*(NORDER + 2) / 2;
+  Npts  = 0;
+
+  /* allocate arrays for fit solution */
+  ALLOCATE (sum, double *, NTERM);
+  ALLOCATE (xsum, double *, NTERM);
+  ALLOCATE (ysum, double *, NTERM);
+  for (i = 0; i < NTERM; i++) {
+    ALLOCATE (sum[i], double, NTERM);
+    bzero (sum[i], NTERM*sizeof(double));
+    ALLOCATE (xsum[i], double, NTERM);
+    bzero (xsum[i], NTERM*sizeof(double));
+    ALLOCATE (ysum[i], double, NTERM);
+    bzero (ysum[i], NTERM*sizeof(double));
+  }
+  ALLOCATE (matrix, double *, NPARS);
+  ALLOCATE (vector, double *, NPARS);
+  for (i = 0; i < NPARS; i++) {
+    ALLOCATE (matrix[i], double, NPARS);
+    ALLOCATE (vector[i], double, 2);
+    bzero (vector[i], 2*sizeof(double));
+    bzero (matrix[i], NPARS*sizeof(double));
+  }
+}
+
+/* */
+void fit_add (double x1, double y1, double x2, double y2, double wt) {
+
+  int n, m;
+  double xterm, yterm, term;
+
+  xterm = 1;
+  for (n = 0; n < NTERM; n++) {
+    yterm = 1;
+    for (m = 0; m < NTERM; m++) {
+      term = xterm*yterm;
+      if (n+m < NTERM) {
+	sum[n][m] += term;
+      }
+      if (n+m < NPOWR) {
+	xsum[n][m] += x2*term;
+	ysum[n][m] += y2*term;
+      }
+      yterm *= y1;
+    }
+    xterm *= x1;
+  }
+  Npts ++;
+
+}
+
+void fit_eval () {
+
+  int i, j, n, m, M, N;
+  double max;
+
+  i = 0;
+  for (m = 0; m < NPOWR; m++) {
+    for (n = 0; n < NPOWR - m; n++, i++) {
+      vector[i][0] = xsum[n][m];
+      vector[i][1] = ysum[n][m];
+    }	
+  }
+  j = 0;
+  for (M = 0; M < NPOWR; M++) {
+    for (N = 0; N < NPOWR - M; N++, j++) {
+      i = 0;
+      for (m = 0; m < NPOWR; m++) {
+	for (n = 0; n < NPOWR - m; n++, i++) {
+	  matrix[i][j] = sum[n+N][m+M];
+	}	
+      }
+    }
+  }       
+  max = 0.0;
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      max = MAX (max, fabs(matrix[i][j]));
+    }
+    max = MAX (max, fabs(vector[i][0]));
+    max = MAX (max, fabs(vector[i][1]));
+  }
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      matrix[i][j] /= max;
+    }
+    vector[i][0] /= max;
+    vector[i][1] /= max;
+  }
+  dgaussjordan (matrix, vector, NPARS, 2); 
+  i = 0;
+  for (m = 0; m < NPOWR; m++) {
+    for (n = 0; n < NPOWR - m; n++, i++) {
+      xsum[n][m] = vector[i][0];
+      ysum[n][m] = vector[i][1];
+    }	
+  }
+  i = 0;
+  for (m = 0; m < NPOWR; m++) {
+    for (n = 0; n < NPOWR - m; n++, i++) {
+      if (VERBOSE) fprintf (stderr, "RA x^%dy^%d: %10.4g    DEC x^%dy^%d: %10.4g \n", n, m, vector[i][0], n, m, vector[i][1]);
+    }	
+  }
+}
+
+void fit_norm () { 
+
+  xsum[0][0] = 0;
+  xsum[1][0] = 1;
+  xsum[0][1] = 0;
+
+  ysum[0][0] = 0;
+  ysum[1][0] = 0;
+  ysum[0][1] = 1;
+}
+
+/* evaluate the fit at (X,Y) to yield (x,y) */
+void fit_apply (double *x, double *y, double X, double Y) {
+
+  int m, n;
+  double xterm, yterm;
+  double Xo, Yo;
+
+  Xo = Yo = 0;
+  yterm = 1;
+  for (m = 0; m < NPOWR; m++) { 
+    xterm = 1;
+    for (n = 0; n < NPOWR - m; n++) {
+      Xo += xterm*yterm*xsum[n][m];
+      Yo += xterm*yterm*ysum[n][m];
+      xterm *= X;
+    }	
+    yterm *= Y;
+  }
+  
+  *x = Xo;
+  *y = Yo;
+}
+
+/* evaluate the x-derivative of the fit at (X,Y) to yield (x,y) */
+void fit_apply_dx (double *x, double *y, double X, double Y) {
+
+  int m, n;
+  double xterm, yterm;
+  double Xo, Yo;
+
+  Xo = Yo = 0;
+  yterm = 1;
+  for (m = 0; m < NPOWR; m++) { 
+    xterm = 1;
+    for (n = 1; n < NPOWR - m; n++) {
+      Xo += n*xterm*yterm*xsum[n][m];
+      Yo += n*xterm*yterm*ysum[n][m];
+      xterm *= X;
+    }	
+    yterm *= Y;
+  }
+  
+  *x = Xo;
+  *y = Yo;
+}
+
+/* evaluate the y-derivative of the fit at (X,Y) to yield (x,y) */
+void fit_apply_dy (double *x, double *y, double X, double Y) {
+
+  int m, n;
+  double xterm, yterm;
+  double Xo, Yo;
+
+  Xo = Yo = 0;
+  yterm = 1;
+  for (m = 1; m < NPOWR; m++) { 
+    xterm = 1;
+    for (n = 0; n < NPOWR - m; n++) {
+      Xo += m*xterm*yterm*xsum[n][m];
+      Yo += m*xterm*yterm*ysum[n][m];
+      xterm *= X;
+    }	
+    yterm *= Y;
+  }
+  
+  *x = Xo;
+  *y = Yo;
+}
+
+/* measure the residual scatter in the fit */
+double fit_scat (StarData *st, StarData *sr, Coords *coords) {
+
+  int i;
+  int Npair, *idx1, *idx2;
+  double x, y, dx, dy, dX, dY, dX2, dY2, dR;
+  
+  Npair = pair_lists (&idx1, &idx2);
+
+  dX = dY = dX2 = dY2 = 0;
+  for (i = 0; i < Npair; i++) {
+
+    /* projection this direction includes the error introduced by
+       the interation on the nonlinear solution */
+    RD_to_XY (&x, &y, sr[idx2[i]].R, sr[idx2[i]].D, coords);
+    
+    dx = x - st[idx1[i]].X;
+    dy = y - st[idx1[i]].Y;
+    
+    dX += dx;
+    dY += dy;
+    dX2 += dx*dx;
+    dY2 += dy*dy;
+  }
+
+  /* scatter is measured on the tangent plane in degrees */
+  dX = dX / Npair;
+  dY = dY / Npair;
+  fprintf (stderr, "scatter: %f, %f\n", sqrt(dX2/Npair - dX*dX), sqrt(dY2/Npair - dY*dY));
+  fprintf (stderr, "Npts: %d\n", Npair);
+
+  dR = 0.5 * sqrt(fabs(dX2/Npair - dX*dX)) + 0.5 * sqrt (fabs(dY2/Npair - dY*dY));
+  return (dR);
+}
+
+/* convert fit terms to coords and polyterms */
+/**** what do we do with the value of ctype??? 
+      can we leave it alone? ****/
+int fit_adjust (Coords *coords) {
+
+  int i;
+  double a10, a01, a20, a11, a02, a30, a21, a12, a03;
+  double b10, b01, b20, b11, b02, b30, b21, b12, b03;
+  double Xo, Yo, det;
+  double **A, **B, Fx, Fy;
+    
+  /* start with the linear solution for Xo,Yo */
+  coords[0].cdelt1 = hypot (xsum[1][0], ysum[1][0]);
+  coords[0].cdelt2 = hypot (xsum[0][1], ysum[0][1]);
+  // coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+
+  det = 1.0 / (xsum[1][0]*ysum[0][1] - xsum[0][1]*ysum[1][0]);
+  Xo = det*(ysum[0][0]*xsum[0][1] - xsum[0][0]*ysum[0][1]);
+  Yo = det*(xsum[0][0]*ysum[1][0] - ysum[0][0]*xsum[1][0]);
+
+  coords[0].Npolyterms = NORDER;
+
+  if (coords[0].Npolyterms > 1) {
+    /* use the linear solution as a starting guess */
+    /* solve for L(Xo,Yo) = 0, M(Xo,Yo) = 0 */
+    /* this is the Newton-Raphson method - it needs the high order terms to be small */
+    ALLOCATE (A, double *, 2);
+    ALLOCATE (B, double *, 2);
+    ALLOCATE (A[0], double, 2);
+    ALLOCATE (A[1], double, 2);
+    ALLOCATE (B[0], double, 1);
+    ALLOCATE (B[1], double, 1);
+
+    for (i = 0; i < 10; i++) {
+      fit_apply (&Fx, &Fy, Xo, Yo);
+      fit_apply_dx (&A[0][0], &A[0][1], Xo, Yo);
+      fit_apply_dy (&A[1][0], &A[1][1], Xo, Yo);
+      B[0][0] = -Fx;
+      B[1][0] = -Fy;
+      dgaussjordan (A, B, 2, 1);
+      Xo += B[0][0]; 
+      Yo += B[1][0];
+    }
+    free (A[0]); free (B[0]);
+    free (A[1]); free (B[1]);
+    free (A); free (B);
+  }
+  coords[0].crpix1 = Xo;
+  coords[0].crpix2 = Yo;
+
+  switch (coords[0].Npolyterms) {
+    case 0:
+    case 1:
+      /* the linear solution can be analytically inverted */
+      coords[0].pc1_1 = xsum[1][0] / coords[0].cdelt1;
+      coords[0].pc1_2 = xsum[0][1] / coords[0].cdelt2;
+      coords[0].pc2_1 = ysum[1][0] / coords[0].cdelt1;
+      coords[0].pc2_2 = ysum[0][1] / coords[0].cdelt2;
+      for (i = 0; i < 7; i++) {
+	coords[0].polyterms[i][0] = coords[0].polyterms[i][1] = 0.0;
+      }
+      break;
+
+    case 2:
+      a10 = xsum[1][0] + 2.0*xsum[2][0]*Xo + xsum[1][1]*Yo;
+      a01 = xsum[0][1] + 2.0*xsum[0][2]*Yo + xsum[1][1]*Xo;
+      a20 = xsum[2][0];
+      a11 = xsum[1][1];
+      a02 = xsum[0][2];
+
+      b10 = ysum[1][0] + 2.0*ysum[2][0]*Xo + ysum[1][1]*Yo;
+      b01 = ysum[0][1] + 2.0*ysum[0][2]*Yo + ysum[1][1]*Xo;
+      b20 = ysum[2][0];
+      b11 = ysum[1][1];
+      b02 = ysum[0][2];
+
+      coords[0].pc1_1 = a10 / coords[0].cdelt1;
+      coords[0].pc1_2 = a01 / coords[0].cdelt2;
+      coords[0].pc2_1 = b10 / coords[0].cdelt1;
+      coords[0].pc2_2 = b01 / coords[0].cdelt2;
+
+      coords[0].polyterms[0][0] = a20 / SQ(coords[0].cdelt1);
+      coords[0].polyterms[1][0] = a11 / (coords[0].cdelt1*coords[0].cdelt2);
+      coords[0].polyterms[2][0] = a02 / SQ(coords[0].cdelt2);
+
+      coords[0].polyterms[0][1] = b20 / SQ(coords[0].cdelt1);
+      coords[0].polyterms[1][1] = b11 / (coords[0].cdelt1*coords[0].cdelt2);
+      coords[0].polyterms[2][1] = b02 / SQ(coords[0].cdelt2);
+      for (i = 3; i < 7; i++) {
+	coords[0].polyterms[i][0] = coords[0].polyterms[i][1] = 0.0;
+      }
+      break;
+      
+    case 3:
+      a10 = xsum[1][0] + 2*xsum[2][0]*Xo +   xsum[1][1]*Yo + 3*xsum[3][0]*Xo*Xo + 2*xsum[2][1]*Xo*Yo + xsum[1][2]*Yo*Yo;
+      a01 = xsum[0][1] + 2*xsum[0][2]*Yo +   xsum[1][1]*Xo + 3*xsum[0][3]*Yo*Yo + 2*xsum[1][2]*Xo*Yo + xsum[2][1]*Xo*Xo;
+      a20 = xsum[2][0] + 3*xsum[3][0]*Xo +   xsum[2][1]*Yo;
+      a11 = xsum[1][1] + 2*xsum[2][1]*Xo + 2*xsum[1][2]*Yo;
+      a02 = xsum[0][2] + 3*xsum[0][3]*Yo +   xsum[1][2]*Xo;
+      a30 = xsum[3][0];
+      a21 = xsum[2][1];
+      a12 = xsum[1][2];
+      a03 = xsum[0][3];
+
+      b10 = ysum[1][0] + 2*ysum[2][0]*Xo +   ysum[1][1]*Yo + 3*ysum[3][0]*Xo*Xo + 2*ysum[2][1]*Xo*Yo + ysum[1][2]*Yo*Yo;
+      b01 = ysum[0][1] + 2*ysum[0][2]*Yo +   ysum[1][1]*Xo + 3*ysum[0][3]*Yo*Yo + 2*ysum[1][2]*Xo*Yo + ysum[2][1]*Xo*Xo;
+      b20 = ysum[2][0] + 3*ysum[3][0]*Xo +   ysum[2][1]*Yo;
+      b11 = ysum[1][1] + 2*ysum[2][1]*Xo + 2*ysum[1][2]*Yo;
+      b02 = ysum[0][2] + 3*ysum[0][3]*Yo +   ysum[1][2]*Xo;
+      b30 = ysum[3][0];
+      b21 = ysum[2][1];
+      b12 = ysum[1][2];
+      b03 = ysum[0][3];
+
+      coords[0].pc1_1 = a10 / coords[0].cdelt1;
+      coords[0].pc1_2 = a01 / coords[0].cdelt2;
+      coords[0].pc2_1 = b10 / coords[0].cdelt1;
+      coords[0].pc2_2 = b01 / coords[0].cdelt2;
+
+      coords[0].polyterms[0][0] = a20 / SQ(coords[0].cdelt1);
+      coords[0].polyterms[1][0] = a11 / (coords[0].cdelt1*coords[0].cdelt2);
+      coords[0].polyterms[2][0] = a02 / SQ(coords[0].cdelt2);
+
+      coords[0].polyterms[3][0] = a30 / (SQ(coords[0].cdelt1)*coords[0].cdelt1);
+      coords[0].polyterms[4][0] = a21 / (SQ(coords[0].cdelt1)*coords[0].cdelt2);
+      coords[0].polyterms[5][0] = a12 / (SQ(coords[0].cdelt2)*coords[0].cdelt1);
+      coords[0].polyterms[6][0] = a03 / (SQ(coords[0].cdelt2)*coords[0].cdelt2);
+
+      coords[0].polyterms[0][1] = b20 / SQ(coords[0].cdelt1);
+      coords[0].polyterms[1][1] = b11 / (coords[0].cdelt1*coords[0].cdelt2);
+      coords[0].polyterms[2][1] = b02 / SQ(coords[0].cdelt2);
+
+      coords[0].polyterms[3][1] = b30 / (SQ(coords[0].cdelt1)*coords[0].cdelt1);
+      coords[0].polyterms[4][1] = b21 / (SQ(coords[0].cdelt1)*coords[0].cdelt2);
+      coords[0].polyterms[5][1] = b12 / (SQ(coords[0].cdelt2)*coords[0].cdelt1);
+      coords[0].polyterms[6][1] = b03 / (SQ(coords[0].cdelt2)*coords[0].cdelt2);
+      break;
+
+    default:
+      fprintf (stderr, "error: invalid order %d\n", coords[0].Npolyterms);
+      exit (2);
+  }
+
+  while (coords[0].crval1 < 0) coords[0].crval1 += 360.0;
+  while (coords[0].crval1 > 360.0) coords[0].crval1 -= 360.0;
+
+  /* test for valid solution */
+  return (Npts);
+}
+
+int mk_polyterm (int n, int m, int norder) {
+  
+  int i, nt, N;
+  
+  N = 0;
+  nt = n + m;
+  for (i = 2; i < nt; i++) {
+    N += i + 1;
+  }
+  N += m;
+  return (N);
+}
+
+int mk_vector (int n, int m, int norder) {
+  
+  int i, N;
+  
+  N = 0;
+  for (i = 0; i < m; i++) {
+    N += (norder - i + 1);
+  }
+  N += n;
+  return (N);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/remove_clumps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/remove_clumps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/remove_clumps.c	(revision 16632)
@@ -0,0 +1,94 @@
+# include "gastro2.h"
+
+StarData *remove_clumps (StarData *instars, int *nstars, int NX, int NY) {
+
+  int i, j, nx, ny, Npix, nn, x, y, pix, Nstars;
+  double s1, s2, mean, sigma, cutoff;
+  int *hist, *xcld;
+  int nxcld, Nxcld, Nout;
+  
+  StarData *outstars;
+
+  /* create histogram of pixels using coords */
+
+  Nstars = *nstars;
+
+  Npix = 100;
+  nx = (int) (NX / Npix) + 1;
+  ny = (int) (NY / Npix) + 1;
+  nn = nx * ny;
+
+  ALLOCATE (hist, int, nn);
+  ALLOCATE (xcld, int, nn);
+  bzero (hist, nn*sizeof(int));
+
+  for (i = 0; i < Nstars; i++) {
+    
+    x = (int) (instars[i].X / Npix);
+    y = (int) (instars[i].Y / Npix);
+    pix = x + nx * y;
+
+    if ((pix < 0) || (pix >= nn)) { 
+      fprintf (stderr, "! %f %f  %d %d  %d %d\n", instars[i].X, instars[i].Y, x, y, pix, nn);
+      continue;
+    }
+    
+    hist[pix] ++;
+
+  }
+
+  /* find stats on histogram */
+  s1 = s2 = 0;
+  for (i = 0; i < nn; i++) {
+    s1 += hist[i];
+    s2 += hist[i]*hist[i];
+  }
+  mean  = s1 / nn;
+  sigma = 2 + sqrt (s2 / nn - mean*mean);
+  cutoff = mean + 5*sigma;
+
+  /* identify clumps to exclude */
+  Nxcld = 0;
+  for (i = 0; i < nn; i++) {
+    if (hist[i] > cutoff) {
+      y = (int) (i / nx);
+      x = i - y*nx;
+      fprintf (stderr, "cut: %d  %d %d  %d\n", i, x, y, hist[i]);
+      xcld[Nxcld] = i;
+      Nxcld ++;
+    }
+  }
+
+  /* identify stars to exclude (type = -1) */
+  for (i = 0; i < Nxcld; i++) {
+
+    nxcld = 0;
+    for (j = 0; j < Nstars; j++) {
+      
+      x = (int) (instars[j].X / Npix);
+      y = (int) (instars[j].Y / Npix);
+      pix = x + nx * y;
+      if (pix != xcld[i]) continue;
+      nxcld ++;      
+      instars[j].type = -1;
+    }
+    fprintf (stderr, "exclude %d in clump %d\n", nxcld, i);
+  }
+
+  ALLOCATE (outstars, StarData, Nstars);
+  Nout = 0;
+
+  for (i = 0; i < Nstars; i++) {
+    if (instars[i].type == -1) continue;
+    outstars[Nout] = instars[i];
+    Nout ++;
+  } 
+
+  REALLOCATE (outstars, StarData, Nout);
+  *nstars = Nout;
+  fprintf (stderr, "keeping %d of %d stars\n", Nout, Nstars);
+  return (outstars);
+
+}
+  
+     
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/rfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/rfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/rfits.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "gastro2.h"
+
+StarData *rfits (FILE *f, int *nstars) {
+
+  int i, N, Nstars;
+  Header theader;
+  FTable table;
+  SMPData  *stars;
+  StarData *stardata;
+
+  /* init & load in table data */
+  table.header   = &theader;
+  if (!gfits_fread_ftable (f, &table, "SMPFILE")) goto escape;
+
+  stars = gfits_table_get_SMPData (&table, &Nstars, NULL);
+
+  ALLOCATE (stardata, StarData, Nstars);
+  for (i = N = 0; i < Nstars; i++) {
+    /* hardwired dophot exclusions should eventually be encapsulated elsewhere */
+    if (stars[i].dophot == 4) continue;
+    if (stars[i].dophot == 5) continue;
+    if (stars[i].dophot == 6) continue;
+    if (stars[i].dophot == 9) continue;
+    if ((MAX_ERROR > 0) && (stars[i].dM > MAX_ERROR)) continue;
+    stardata[N].X    = stars[i].X;
+    stardata[N].Y    = stars[i].Y;
+    stardata[N].M    = stars[i].M;
+    stardata[N].dM   = 1000*stars[i].dM;
+    stardata[N].type = stars[i].dophot;
+    stardata[N].R    = 0;
+    stardata[N].D    = 0;
+    N++;
+  }    
+  if (N < 5) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n", N);
+    exit (1);
+  }
+
+  REALLOCATE (stardata, StarData, MAX(N,1));
+  *nstars = N;
+  return (stardata);
+
+escape:
+  fprintf (stderr, "error reading file\n");
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/rotate2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/rotate2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/rotate2.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "gastro2.h"
+
+void rotate (RefCatalog *Subset, RefCatalog *Ref, double angle) {
+  
+  int i;
+  double dX, dY, DX, DY, CS, SN;
+  double theta;
+  StarData *in, *out;
+
+  Ref[0] = Subset[0];
+
+  ALLOCATE (Ref[0].stars, StarData, MAX (1, Ref[0].N));
+  bcopy (Subset[0].stars, Ref[0].stars, Ref[0].N*sizeof(StarData));
+
+  if (angle == 0.0) return;
+
+  theta = (angle*RAD_DEG);
+  CS = cos (theta);
+  SN = sin (theta);
+
+  in  = Subset[0].stars;
+  out = Ref[0].stars;
+
+  for (i = 0; i < Ref[0].N; i++) {
+    dX = in[i].X;
+    dY = in[i].Y;
+    
+    DX = dX * CS - dY * SN;
+    DY = dX * SN + dY * CS;
+    
+    out[i].X = DX;
+    out[i].Y = DY;
+  }
+    
+}
+
+/* rotate the star list by an angle ccw from x axis */
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/rtext.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/rtext.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/rtext.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "gastro2.h"
+/* by necesity hard wired */
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+StarData *rtext (FILE *f, int *nstars) {
+
+  char *buffer;
+  int i, N, Nbytes, nbytes, Ninstar, Nstars, NSTARS;
+  double dmag, type;
+  StarData *stars;
+
+  NSTARS = *nstars;
+  ALLOCATE (stars, StarData, MAX (NSTARS, 1));
+  Nbytes = NSTARS*BYTES_STAR;
+
+  N = Nstars = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  
+  while ((nbytes = fread (buffer, 1, (BLOCK*BYTES_STAR), f)) != 0) {
+    Ninstar = nbytes / BYTES_STAR;
+    for (i = 0; i < Ninstar; i++, Nstars++) {
+      dparse (&stars[N].X, 1, &buffer[i*BYTES_STAR]);
+      dparse (&stars[N].Y, 2, &buffer[i*BYTES_STAR]);
+      dparse (&stars[N].M, 3, &buffer[i*BYTES_STAR]);
+      dparse (&dmag,       4, &buffer[i*BYTES_STAR]);
+      dparse (&type,       5, &buffer[i*BYTES_STAR]);
+
+      /* hardwired dophot exclusions should eventually be encapsulated elsewhere */
+      if ((type == 4) || (type == 6) || (type == 5) || (type == 9)) continue;
+      if ((MAX_ERROR > 0) && (dmag > 1000*MAX_ERROR)) continue;
+      stars[N].dM   = 0.001 * dmag;
+      stars[N].type = type;
+      N++;
+    }
+  }
+  free (buffer);
+ 
+  if (Nstars != NSTARS) {
+    fprintf (stderr, "WARNING: only read %d of %d stars\n", Nstars, NSTARS);
+  }
+  if (N < 5) { 
+    fprintf (stderr, "ERROR: too few stars for reliable solution, only %d\n", N);
+    exit (1);
+  }
+  *nstars = N;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gastro2/src/sort.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gastro2/src/sort.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gastro2/src/sort.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "gastro2.h"
+
+void sort_stars_mag (StarData *stars, int N) {
+
+# define SWAPFUNC(A,B){ StarData tmp; tmp = stars[A]; stars[A] = stars[B]; stars[B] = tmp; }
+# define COMPARE(A,B)(stars[A].M < stars[B].M)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void sort_stars_X (StarData *stars, int N) {
+
+# define SWAPFUNC(A,B){ StarData tmp; tmp = stars[A]; stars[A] = stars[B]; stars[B] = tmp; }
+# define COMPARE(A,B)(stars[A].X < stars[B].X)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/Makefile	(revision 16632)
@@ -0,0 +1,29 @@
+default: gcompare
+help:
+	@echo "make options: gcompare (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/gcompare
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+MAN	=	$(HOME)/doc
+SRC	=	$(HOME)/src
+INC	=	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+gcompare: $(BIN)/gcompare.$(ARCH)
+install: $(DESTBIN)/gcompare
+
+GCOMPARE 	= \
+$(SRC)/input.$(ARCH).o 				$(SRC)/output.$(ARCH).o    		\
+$(SRC)/compare.$(ARCH).o 			$(SRC)/sort.$(ARCH).o      		\
+$(SRC)/count_neighbors.$(ARCH).o                $(SRC)/nextline.$(ARCH).o		\
+$(SRC)/nextword.$(ARCH).o			$(SRC)/gcompare.$(ARCH).o
+
+$(GCOMPARE): $(INC)/gcompare.h
+$(BIN)/gcompare.$(ARCH): $(GCOMPARE)
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/doc/gcompare.1
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/doc/gcompare.1	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/doc/gcompare.1	(revision 16632)
@@ -0,0 +1,52 @@
+.ad l
+.nh
+.TH gcompare 1.0 "Sept 18, 1992" "Version 1.0"
+.SH NAME
+\fIgcompare:\fP  2-D intercomparison between 2 files
+
+.SH SYNOPSIS
+.B gcompare [-d -m -n1 -n2 -s1 N -s2 N -c X Y] file1 X1 Y1 file2 X2 Y2 radius
+
+.SH DESCRIPTION
+\fIgcompare\fP takes two files and compares the entries with one with
+the entries in the second.  Two columns (X and Y) which contain the
+coordinates are given.  Lines in the second file with coordinates
+within the given radius of the first file are selected.  Depending on
+the optional flags, any of the following are printed:  
+1) the coordinate difference for these matched lines,
+2) both matched lines (concatenated into a single line)
+3) \fIunmatched\fP lines from file 1 
+4) \fIunmatched\fP lines from file 2 
+
+.SS OPTIONS
+.TP
+.I "-d"
+Include in the output the coordinate differences for the two files
+.TP
+.I "-m"
+Include in the output the matched lines from the two files
+.TP
+.I "-n1"
+Include in the output the unmatched lines from file 1
+.TP
+.I "-n2"
+Include in the output the unmatched lines from file 2
+.TP
+.I "-s1 N"
+skip the first N lines of file 1
+.TP
+.I "-s2 N"
+skip the first N lines of file 2
+.TP
+.I "-c X Y"
+offset the coordinates of file 2 by (X,Y)
+.TP
+.I "-h, -help"
+print a short help summary
+
+
+.SH COPYRIGHT
+Copyright 1993 Eugene Magnier
+.PP                                                
+.SH AUTHOR
+Eugene Magnier.  MIT - CSR, UvA
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/include/gcompare.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/include/gcompare.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/include/gcompare.h	(revision 16632)
@@ -0,0 +1,38 @@
+# include <math.h>
+# include <ohana.h>
+
+typedef struct {
+  double  X, Y;
+  char   *line;
+  int     match;
+} value_type;
+
+typedef struct {
+  value_type *values;
+  char       *buffer;
+  int        Nvalues;
+} data_type;
+
+
+typedef struct {
+  char *line1;
+  char *line2;
+  double dX, dY;
+} match_type;
+
+/******* PROTOTYPES ***********/
+
+void               help              PROTO(());
+data_type          input             PROTO((char *, int, int, int));
+match_type        *compare           PROTO((data_type, data_type, int *, double, double, double, double));
+int                get_argument      PROTO((int, char **, char *));
+int                remove_argument   PROTO((int, int *, char **));
+void               data_sort         PROTO((data_type));
+void               output            PROTO((data_type, data_type, match_type *, int, int, int, int, int));
+char              *nextword          PROTO((char *));
+int                parse             PROTO((double *, int, char *));
+char              *nextline          PROTO((char *));
+int                scan_line         PROTO((FILE *, char *));
+
+extern double hypot PROTO((double, double));
+/*  this seems to be a problem: is not included from math.h with the -ansi flag */
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/compare.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/compare.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/compare.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "gcompare.h"
+# define D_NMATCH 500;
+
+match_type *compare (data_type data1, data_type data2, int *Nmatches, double radius, double DX, double DY, double noauto) {
+
+  int i, j, first_j, Nmatch, NMATCH;
+  double dX, dY, dR;
+  match_type *match;
+
+  fprintf (stderr, "%f  %f\n", DX, DY);
+  Nmatch = 0;
+  NMATCH = D_NMATCH;
+  ALLOCATE (match, match_type, NMATCH);
+
+  for (i = j = 0;(i < data1.Nvalues) && (j < data2.Nvalues);) {
+    
+    dX = data1.values[i].X - data2.values[j].X - DX;
+
+    if (!(i % 100))
+      fprintf (stderr, ".");
+    
+    if (dX <= -radius)
+      i++;
+    if (dX >= radius)
+      j++;
+
+    if (fabs (dX) < radius) {
+      first_j = j;
+      for (j = first_j; (fabs (dX) < radius) && (j < data2.Nvalues); j++) {
+	dX = data1.values[i].X - data2.values[j].X - DX;
+	dY = data1.values[i].Y - data2.values[j].Y - DY;
+	dR = hypot (dX, dY);
+	if ((dR < radius) && ((noauto == 0) || (dR > noauto))) {
+	  match [Nmatch].line1 = data1.values[i].line;
+	  match [Nmatch].line2 = data2.values[j].line;
+	  match [Nmatch].dX = data1.values[i].X - data2.values[j].X - DX;
+	  match [Nmatch].dY = data1.values[i].Y - data2.values[j].Y - DY;
+	  data1.values[i].match = TRUE;
+	  data2.values[j].match = TRUE;
+	  Nmatch ++;
+	  if (Nmatch == NMATCH - 1) {
+	    NMATCH += D_NMATCH;
+	    REALLOCATE (match, match_type, NMATCH);
+	  }
+	}
+      }
+      j = first_j;
+      i++;
+    }
+
+  }
+  *Nmatches = Nmatch;
+  return (match);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/count_neighbors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/count_neighbors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/count_neighbors.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "gcompare.h"
+# define D_NMATCH 500;
+
+int count_neighbors (data, radius, DX, DY)
+data_type  data;
+double     radius;
+double     DX;
+double     DY;
+{
+
+  int i, j, first_j, Nfriends;
+  double dX, dY, dR;
+
+  fprintf (stderr, "%f  %f\n", DX, DY);
+
+  for (i = j = 0; (i < data.Nvalues) && (j < data.Nvalues);) {
+    
+    dX = data.values[i].X - data.values[j].X - DX;
+
+    if (!(i % 100))
+      fprintf (stderr, ".");
+    
+    Nfriends = 0;
+
+    if (dX <= -radius) {
+      fprintf (stdout, "%f %f %d\n", data.values[i].X, data.values[i].Y, Nfriends);
+      i++;
+    }
+    if (dX >= radius)
+      j++;
+
+    if (fabs (dX) < radius) {
+      first_j = j;
+      for (j = first_j; (fabs (dX) < radius) && (j < data.Nvalues); j++) {
+	if (i == j) continue;
+	dX = data.values[i].X - data.values[j].X - DX;
+	dY = data.values[i].Y - data.values[j].Y - DY;
+	dR = hypot (dX, dY);
+	if (dR < radius) {
+	  Nfriends ++;
+	}
+      }
+      j = first_j;
+      fprintf (stdout, "%f %f %d\n", data.values[i].X, data.values[i].Y, Nfriends);
+      i++;
+    }
+
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/find_matches.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/find_matches.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/find_matches.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include "gcompare.h"
+
+table_type *find_matches (table, values, Nvalues, catalog, Ncatalog, noauto)
+table_type   table[];
+value_type   values[];
+int          Nvalues;
+catalog_type catalog[];
+int          Ncatalog;
+int          noauto;
+{
+
+  int i, j, start, done;
+  double delta_Dec, dRA, dDec, radius;
+
+  delta_Dec = (catalog[Ncatalog - 1].Dec - catalog[0].Dec);
+  for (i = 0; i < Nvalues; i++) {
+    if ((values[i].Dec > catalog[Ncatalog - 1].Dec) || (values[i].Dec < catalog[0].Dec))
+      continue;
+    start = Ncatalog * (values[i].Dec - catalog[0].Dec) / delta_Dec;
+    done = FALSE;
+    while (!done) {
+      if ((catalog[start].Dec > values[i].Dec - values[i].radius) && (start != 0)) {
+	start -= 100;
+	if (start < 0)
+	  start = 0;
+      }
+      else
+	done = TRUE;
+    }
+    for (j = start; ((j < Ncatalog) && 
+		     (catalog[j].Dec < values[i].Dec + values[i].radius)); j++) {
+      dRA = (values[i].RA - catalog[j].RA) / cos (DEG_RAD*values[i].Dec);
+      dDec = values[i].Dec - catalog[j].Dec;
+      
+      radius = hypot (dRA, dDec);
+      if ((radius <= values[i].radius) && (!noauto || (radius > 0))) {
+	ALLOCATE (table[i].match[table[i].Nmatches], char, NBYTES_LINE + 1);
+	bzero (table[i].match[table[i].Nmatches], NBYTES_LINE + 1);
+	strcpy (table[i].match[table[i].Nmatches], catalog[j].line);
+	table[i].Nmatches ++;
+	if (table[i].Nmatches > 500)
+	  fprintf (stderr, "too many objects! \n");
+      }
+    }
+  }
+
+  return (table);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/gcompare.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/gcompare.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/gcompare.c	(revision 16632)
@@ -0,0 +1,101 @@
+# include "gcompare.h"
+
+int main (int argc, char **argv) {
+  
+  /* USAGE:  gcompare file1 X1 Y1 file2 X2 Y2 radius */
+  
+  int Nskip1, Nskip2, Nmatches, N;
+  int X1, X2, Y1, Y2, deltas, match, nomatch1, nomatch2;
+  data_type data1, data2;
+  match_type *matches;
+  double radius, DX, DY, noauto;
+
+  DX = DY = Nskip1 = Nskip2 = 0;
+  noauto = match = nomatch1 = nomatch2 = deltas = FALSE;
+
+  if (remove_argument(get_argument (argc, argv, "-d"), &argc, argv))
+    deltas = TRUE;
+  if (remove_argument(get_argument (argc, argv, "-h"), &argc, argv))
+    help();
+  if (remove_argument(get_argument (argc, argv, "-help"), &argc, argv))
+    help();
+  if (remove_argument(get_argument (argc, argv, "-m"), &argc, argv))
+    match = TRUE;
+  if (remove_argument(get_argument (argc, argv, "-n1"), &argc, argv))
+    nomatch1 = TRUE;
+  if (remove_argument(get_argument (argc, argv, "-n2"), &argc, argv))
+    nomatch2 = TRUE;
+  if (!(match || deltas || nomatch1 || nomatch2)) {
+    fprintf (stderr, "no output mode, use at least one of -d, -m, -n1, or -n2\n");
+    exit (2);
+  }
+  if ((N = get_argument (argc, argv, "-na"))) {
+    remove_argument(N, &argc, argv);
+    noauto = atof(argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+    
+  if ((N = get_argument (argc, argv, "-c")) && (N + 2 < argc)) {
+    DX = atof(argv[N + 1]);
+    DY = atof(argv[N + 2]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-s1"))) {
+    Nskip1 = atof(argv[N + 1]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-s2")) && (N + 1 < argc)) {
+    Nskip2 = atof(argv[N + 1]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  
+  if (argc != 8) {
+    fprintf (stderr, "gcompare [mode] file1 X1 Y1 file2 X2 Y2 radius\n");
+    exit (2);
+  }
+
+  X1 = atof (argv[2]);
+  Y1 = atof (argv[3]);
+  X2 = atof (argv[5]);
+  Y2 = atof (argv[6]);
+  radius = atof(argv[7]);
+  fprintf (stderr, "radius = %f %s\n", radius, argv[7]);
+
+  data1 = input (argv[1], X1, Y1, Nskip1);
+  fprintf (stderr, "list 1: %d values %d %d\n", data1.Nvalues, X1, Y1);
+  data2 = input (argv[4], X2, Y2, Nskip2);
+  fprintf (stderr, "list 2: %d values %d %d\n", data2.Nvalues, X2, Y2);
+
+  data_sort (data1); fprintf (stderr, "sorted 1\n");
+  data_sort (data2); fprintf (stderr, "sorted 2\n");
+
+  fprintf (stderr, "noauto: %e\n", noauto);
+  matches = compare (data1, data2, &Nmatches, radius, DX, DY, noauto);
+
+  output (data1, data2, matches, Nmatches, match, deltas, nomatch1, nomatch2);
+  exit (0);
+}
+
+
+
+void
+help() {
+
+  fprintf (stderr, "gcompare [mode] file1 X1 Y1 file2 X2 Y2 radius\n");
+  fprintf (stderr, " modes:\n");
+  fprintf (stderr, "  -d      return delta coords\n");
+  fprintf (stderr, "  -m      return matched lines\n");
+  fprintf (stderr, "  -n1     return unmatched lines, file 1\n");
+  fprintf (stderr, "  -n2     return unmatched lines, file 2\n");
+  fprintf (stderr, " additional options:\n");
+  fprintf (stderr, "  -c X Y    set offset (file1 - file2)\n");
+  fprintf (stderr, "  -s1 N     skip N lines from file 1\n");
+  fprintf (stderr, "  -s2 N     skip N lines from file 2\n");
+  fprintf (stderr, "  -na X     eliminate auto-matches (radius < X)\n");
+  exit (2);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/input.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/input.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/input.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "gcompare.h"
+# define D_NVALUES 1000
+# define D_NBYTES  10000
+
+data_type input (filename, X, Y, Nskip)
+char *filename;
+int   X;
+int   Y;
+int   Nskip;
+{
+  
+  data_type data;
+  int i, status, n, NVALUES, NBYTES, nbytes;
+  FILE *f;
+  char dummy_line[1000], *next;
+  
+  n = 0;
+
+  if (!strcmp (filename, "-")) {
+    f = stdin;
+  }
+  else {
+    f = fopen (filename, "r");
+    if (f == NULL) {
+      fprintf (stderr, "error opening file %s\n", filename);
+      exit (0);
+    }
+  }
+
+  for (i = 0; i < Nskip; i++) 
+    scan_line (f, dummy_line);
+ 
+  /* read in entire file */
+  NBYTES = D_NBYTES + 1;
+  ALLOCATE (data.buffer, char, NBYTES);
+  for (i = 0, nbytes = D_NBYTES; nbytes == D_NBYTES; i++) {
+    nbytes = fread (&data.buffer[i*D_NBYTES], 1, D_NBYTES, f);
+    NBYTES += D_NBYTES;
+    REALLOCATE (data.buffer, char, NBYTES);
+  }
+  NBYTES -= 2*D_NBYTES - nbytes;
+  data.buffer[NBYTES] = 0;
+  fprintf (stderr, "got %d bytes\n", NBYTES);
+
+  NVALUES = D_NVALUES;
+  ALLOCATE (data.values, value_type, NVALUES);
+  next = data.buffer;
+  for (i = 0; next != (char *) NULL; ) {
+    data.values[i].line  = next;
+    data.values[i].match = FALSE;
+    status  = dparse (&data.values[i].X, X, data.values[i].line);
+    status &= dparse (&data.values[i].Y, Y, data.values[i].line);
+    next = nextline (data.values[i].line);
+    if (status && (data.values[i].line[0] != '#')) {
+      i++;
+    }
+    if (i == NVALUES - 3) {
+      NVALUES += D_NVALUES;
+      REALLOCATE (data.values, value_type, NVALUES);
+    }
+  }
+  data.Nvalues = i;
+  return (data);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/neighbors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/neighbors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/neighbors.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "gcompare.h"
+
+void main (argc, argv)
+int    argc;
+char **argv;
+{
+  
+  /* USAGE:  gcompare file1 X1 Y1 file2 X2 Y2 radius */
+  
+  int i, Nskip1, Nskip2, Nmatches, N;
+  int X1, X2, Y1, Y2, deltas, match, nomatch1, nomatch2, noauto;
+  data_type data1, data2;
+  match_type *matches;
+  double radius, DX, DY;
+
+  DX = DY = Nskip1 = Nskip2 = 0;
+
+  if (remove_argument(get_argument (argc, argv, "-h"), &argc, argv))
+    help();
+  if (remove_argument(get_argument (argc, argv, "-help"), &argc, argv))
+    help();
+    
+  if ((N = get_argument (argc, argv, "-c")) && (N + 2 < argc)) {
+    DX = atof(argv[N + 1]);
+    DY = atof(argv[N + 2]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-s1")) {
+    Nskip1 = atof(argv[N + 1]);
+    remove_argument(N, &argc, argv);
+    remove_argument(N, &argc, argv);
+  }
+  
+  if (argc != 5) {
+    fprintf (stderr, "neighbors [mode] file X Y radius\n");
+    exit (0);
+  }
+
+  X1 = atof (argv[2]);
+  Y1 = atof (argv[3]);
+  radius = atof(argv[4]);
+
+  data1 = input (argv[1], X1, Y1, Nskip1);
+  fprintf (stderr, "list 1: %d values %d %d\n", data1.Nvalues, X1, Y1);
+
+  data_sort (data1); fprintf (stderr, "sorted 1\n");
+
+  count_neighbors (data1, radius, DX, DY);
+
+}
+
+
+
+void
+help() {
+
+  fprintf (stderr, "gcompare [mode] file1 X1 Y1 file2 X2 Y2 radius\n");
+  fprintf (stderr, " modes:\n");
+  fprintf (stderr, "  -d      return delta coords\n");
+  fprintf (stderr, "  -m      return matched lines\n");
+  fprintf (stderr, "  -n1     return unmatched lines, file 1\n");
+  fprintf (stderr, "  -n2     return unmatched lines, file 2\n");
+  fprintf (stderr, " additional options:\n");
+  fprintf (stderr, "  -c X Y    set offset (file1 - file2)\n");
+  fprintf (stderr, "  -s1 N     skip N lines from file 1\n");
+  fprintf (stderr, "  -s2 N     skip N lines from file 2\n");
+  fprintf (stderr, "  -na X     eliminate auto-matches (radius < X)\n");
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/nextline.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/nextline.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/nextline.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "gcompare.h"
+
+char *nextline (line)
+char line[];
+{
+
+  char *ret;
+  
+  ret = strchr (line, '\n');
+  if (ret != NULL) { 
+    *ret = 0;
+    ret += 1;
+  }
+
+  return (ret);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/nextword.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/nextword.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/nextword.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "gcompare.h"
+
+char *nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/output.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "gcompare.h"
+
+void output (data1, data2, matches, Nmatches, match, deltas, nomatch1, nomatch2)
+data_type  data1;
+data_type  data2;
+match_type matches[];
+int        Nmatches;
+int        match;
+int        deltas; 
+int        nomatch1;
+int        nomatch2;
+{
+
+  int i, Nmatch1, Nmatch2;
+
+  fprintf (stderr, "This is a Gcompare output list\n");
+  fprintf (stderr, "There are %d matches\n\n", Nmatches);
+  Nmatch1 = Nmatch2 = 0.0;
+
+  if (match || deltas) {
+    for (i = 0; i < Nmatches; i++) {
+      if (deltas)
+	fprintf (stdout, "%15.9f  %15.9f  ", matches[i].dX, matches[i].dY);
+      if (match)
+	fprintf (stdout, "%s  %s", matches[i].line1, matches[i].line2);
+      fprintf (stdout, "\n");
+    }
+  }
+
+  if (match && nomatch1) 
+    fprintf (stdout, "\n non-matces from file 1:\n");
+  
+  if (nomatch1) {
+    for (i = 0; i < data1.Nvalues; i++) {
+      if (!data1.values[i].match) {
+	fprintf (stdout, "%s\n", data1.values[i].line);
+	Nmatch1 ++;
+      }
+    }
+    fprintf (stderr, "no matches in file 1: %d\n", Nmatch1);
+  }
+
+  if ((match || nomatch1) && nomatch2)
+    fprintf (stdout, "\n non-matces from file 2:\n");
+
+  if (nomatch2) {
+    for (i = 0; i < data2.Nvalues; i++) {
+      if (!data2.values[i].match) {
+	fprintf (stdout, "%s\n", data2.values[i].line);
+	Nmatch2++;
+      }
+    }
+    fprintf (stderr, "no matches in file 2: %d\n", Nmatch2);
+  }
+
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gcompare/src/sort.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gcompare/src/sort.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gcompare/src/sort.c	(revision 16632)
@@ -0,0 +1,13 @@
+# include "gcompare.h"
+
+void data_sort (data_type data) {
+
+# define SWAPFUNC(A,B){ value_type tmp; tmp = data.values[A]; data.values[A] = data.values[B]; data.values[B] = tmp; }
+# define COMPARE(A,B)(data.values[A].X < data.values[B].X)
+
+  OHANA_SORT (data.Nvalues, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+bin
Index: /branches/eam_branch_20080223/Ohana/src/getstar/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/Makefile	(revision 16632)
@@ -0,0 +1,74 @@
+default: all
+help:
+	@echo "make options: getstar (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/getstar
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+getstar: $(BIN)/getstar.$(ARCH)
+getstar.install: $(DESTBIN)/getstar
+
+dvoImageOverlaps: $(BIN)/dvoImageOverlaps.$(ARCH)
+dvoImageOverlaps.install: $(DESTBIN)/dvoImageOverlaps
+
+dvoImageExtract: $(BIN)/dvoImageExtract.$(ARCH)
+dvoImageExtract.install: $(DESTBIN)/dvoImageExtract
+
+all: getstar dvoImageOverlaps dvoImageExtract
+install: getstar.install dvoImageOverlaps.install dvoImageExtract.install
+
+GETSTAR = \
+$(SRC)/getstar.$(ARCH).o 	  \
+$(SRC)/args.$(ARCH).o		  \
+$(SRC)/ConfigInit.$(ARCH).o 	  \
+$(SRC)/Shutdown.$(ARCH).o	  \
+$(SRC)/SetSignals.$(ARCH).o	  \
+$(SRC)/select_by_region.$(ARCH).o \
+$(SRC)/write_catalog.$(ARCH).o    \
+$(SRC)/write_getstar_ps1_dev_0.$(ARCH).o \
+$(SRC)/write_getstar_ps1_dev_1.$(ARCH).o \
+$(SRC)/write_getstar_ps1_dev_2.$(ARCH).o 
+
+$(GETSTAR): $(INC)/getstar.h $(DVO_INCS)
+$(BIN)/getstar.$(ARCH): $(GETSTAR) $(DVO_LIBS)
+
+OVERLAPS = \
+$(SRC)/dvoImageOverlaps.$(ARCH).o 	 \
+$(SRC)/args_overlaps.$(ARCH).o		 \
+$(SRC)/ConfigInit_overlaps.$(ARCH).o 	 \
+$(SRC)/Shutdown.$(ARCH).o	         \
+$(SRC)/SetSignals.$(ARCH).o	         \
+$(SRC)/ReadImageFiles.$(ARCH).o          \
+$(SRC)/ReadImageHeader.$(ARCH).o         \
+$(SRC)/ListImageOverlaps.$(ARCH).o       \
+$(SRC)/GetFileMode.$(ARCH).o             \
+$(SRC)/edge_check.$(ARCH).o              \
+$(SRC)/opening_angle.$(ARCH).o           \
+$(SRC)/MatchImages.$(ARCH).o
+
+$(OVERLAPS): $(INC)/dvoImageOverlaps.h $(DVO_INCS)
+$(BIN)/dvoImageOverlaps.$(ARCH): $(OVERLAPS) $(DVO_LIBS)
+
+EXTRACT = \
+$(SRC)/dvoImageExtract.$(ARCH).o 	 \
+$(SRC)/ConfigInit_extract.$(ARCH).o 	 \
+$(SRC)/args_extract.$(ARCH).o		 \
+$(SRC)/Shutdown.$(ARCH).o	         \
+$(SRC)/SetSignals.$(ARCH).o	         \
+$(SRC)/WriteImages.$(ARCH).o             \
+$(SRC)/WriteImageFITS.$(ARCH).o          \
+$(SRC)/SelectImages.$(ARCH).o       
+
+$(EXTRACT): $(INC)/dvoImageExtract.h $(DVO_INCS)
+$(BIN)/dvoImageExtract.$(ARCH): $(EXTRACT) $(DVO_LIBS)
Index: /branches/eam_branch_20080223/Ohana/src/getstar/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/getstar/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,8 @@
+ getstar-1-2
+  * added maximum magnitude selection
+
+ getstar-1-1
+  * converted to gfits APIs (forces libfits 1.6)
+
+ getstar-1-0
+    basic program, not really tested (not sure why this is tagged)
Index: /branches/eam_branch_20080223/Ohana/src/getstar/doc/database.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/doc/database.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/doc/database.txt	(revision 16632)
@@ -0,0 +1,91 @@
+
+\begin{verbatim}
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first Measure-ment */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       /* reference to corresponding Average entry, 
+				 upper byte of value contains flags.
+				 limit of 16,777,215 stars (Naverage) 
+				 in a file (=0xFFFFFF).
+				 flags = average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
+
+\end{verbatim}
+
+The above two structures define the entries in the photometry
+database.  The database consists of a large number of files
+representing a small patch on the sky (roughly 1.5 degree$^2$ in most
+places).  These files are organized into directories representing
+bands of Declination.  A reference file determines the coordinate
+boundaries for each of the files so that a given point on the sky can
+unambiguously be associated with a specific file in a specific
+directory.  The sky coordinates for each file is the same as those
+used by the HST Guide Star catalog, except for the region around the
+North celestial pole, for which all stars are included in a single
+file.  
+
+Within a given file, the data are stored in a binary format, with an
+ASCII FITS-like header.  The header is examply in the format of a
+normal FITS header, but with the exception that all files have a fixed
+number of header blocks (for now 3 blocks = 8640 bytes).  This is done
+to speed loading the header and finding the beginning of the binary
+data.  The number of 3 blocks seems quite generous, as currently only
+a few FITS keywords have been defined for each file, basically
+keywords to define the number of stars and the total number of
+measurements stored in the file, as well as values to define the RA
+and DEC range of the file.  
+
+The first section of data following the header blocks consists of
+average measurements for each uniquely observed star.  Each star
+occupies 20 bytes, the size of the Average structure defined above.
+The Average structure contains the average Ra, Dec, and Magnitude for
+the star, as well as the number of measurements, and \chisq\ values
+for the magnitude and position.  Finally, there is a 32 bit integer
+which defines the offset to the first measurement for this star.  This
+offset is defined as the number of Measure records from the start of
+the Measure structure.
+
+The second section of data, following the Average data contains all
+measurements for each star listed in Average.  Each measurement
+occupies 13 bytes, the size of the Measure structure.  This structure
+contains the difference of this position from the average RA and DEC,
+and the instrumental magnitude of this measurement (in the units
+defined by the fstat program, which give m = -2.5*log(cts) + Mo, where
+Mo is currently 24.5 [10/15]).  There is also the magnitude error for
+this measurement, the time of the measurement (in seconds relative to
+a to-be-determined zero point), and a reference to the entry in the
+Average structure so we can relate a given measurement with a given star.
+This last entry also includes a byte of flags, of which only 4 have
+currently been defined.  This means the Average offset can only be as
+large as  16,777,215 (0xffffff), limiting the possible number of stars
+allowed in a given file.  This does not seem like a long term problem,
+though:  aside from the fact that this number is very large and we
+only expect in the vicinity of 20,000 stars per file, the file can
+easily be divided into pieces at a later date if needed.  this last
+step is trivial, consisting of splitting the data up into smaller
+RA,DEC regions, and updating the reference catalog.  With the above
+definitions for the Average and Measure structures, we will typically
+expect 20,000 * 15 measurements per year and 20,000 average entries in
+a given file.  This implies a file size of about 4.3 MB at the end of
+a year.  It is also possible that we will choose to split the files up
+in the future if the number of measurements makes their size
+unweildy.  4.3 MB is sufficiently small that this is not a problem,
+but after only 5 years, the files will be over 21 MB each, getting to
+be fairly significant.  
Index: /branches/eam_branch_20080223/Ohana/src/getstar/doc/description.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/doc/description.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/doc/description.txt	(revision 16632)
@@ -0,0 +1,94 @@
+
+ADDSTAR:
+
+This program takes a photometry file, with astrometry, provided by
+earlier routines and incorporates the stellar measurements into the
+photometry database.  This routine does NOT try to calibrate or check
+the photometry, nor does it try to improve the coordinate
+determinations or calculate chisquares for position or photometry -
+those tasks are performed by other routines.
+
+Addstar starts by loading in the photometry file and converting the
+pixel coordinates to sky coordinates using the astrometry information
+in the header of the file.  It also gets the detection limits and
+stores the image astrometry information.
+
+Next, addstar determines which of all the previous images overlaps
+with this image and also which of the catalog regions overlaps with
+this image.
+
+Addstar considers each catalog region in turn, and compares the
+positions of stars in the catalog with stars in the image.  If a
+catalog star is detected, a new measurement is added to the catalog.
+If a catalog star is not detected, but is in the field of view of this
+image, the detection limit for this image is added to the list of
+measurements as an upper limit.  If the image contains a star which is
+not already included in the catalog, the star is added to the catalog,
+and all previous images are checked to see if they included this
+location.  If so, upper limits are added to the list of measurements.
+
+To deal with blended images, we have taken the philosophy that all
+measurements compatible with the coordinates of a given star should be
+included in the list of measurements.  This assumes that programs or people
+downstream will figure out which is the "correct" measurement.  To
+this end, if a catalog star is consistent with multiple measurements,
+they are all added to the catalog measurement and the measurements are
+given a flag to say that there was blending in the catalog (ie, it is
+probably the catalog star which is a blend).  If multiple catalog
+stars are consistent with the same image star, that measurement is
+added to each catalog star, and given a flag to say that there was
+blending on the image.
+
+After all catalogs have been checked, updated, and written to disk,
+the image is added to the database of images.
+
+The format for a catalog region file is as follows:
+
+-- 
+Header
+--
+Averages
+--
+Measurements
+--
+
+The Header follows the format of a FITS header but always stored with
+3 blocks to speed up read time: 2880 x 3 bytes.  Two important
+keywords in the header: NSTARS & NMEAS
+
+All average values are stored consecutively in a single block.  They
+are written as an array with NSTARS elements of the Average structure
+defined below.  The individual measurements follow the averages as a
+block.  To find a measurement for a given star, you need to get the
+value of the offset for the star.  this is the element number for the
+first measurement of this star, and are followed by next measurements
+for this star, until the value Nm is reached.
+
+Here are the structures being used for the average and measurement
+values:
+
+typedef struct {
+  float R;                    /* RA  in decimal degrees */
+  float D;                    /* DEC in decimal degrees */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned short int Nm;      /* number of measurements */
+  unsigned short int Xp, Xm;  /* chisq values in tenths */
+  unsigned int offset;        /* offset to first measurement */
+} Average;                    /* = 20 bytes / average */
+
+typedef struct {
+  char dR, dD;                /* tenths of arcsec (-12.7 to +12.7 valid range) */
+  short int M;                /* thousandths of mag (-32.000 to 32.000 valid range) */
+  unsigned char dM;           /* thousandths of mag (0.000 -- 0.255 valid range) */
+  float t;                    /* time in seconds (what is reference?) */
+  unsigned int average;       
+  /* reference to corresponding average entry, upper byte stores flags:
+   limit of 16,777,215 stars (Naverage) in a file (=0xFFFFFF) 
+   flags: average & 0x1000000 */
+} Measure;                    /* = 13 bytes / measure */
+
+/* flags for measurements: */
+# define BLEND_IMAGE   0X01000000
+# define BLEND_CATALOG 0X02000000
+# define UPPER_LIMIT   0X04000000
+# define CALIBRATED    0X08000000
Index: /branches/eam_branch_20080223/Ohana/src/getstar/etc/phottemp.cat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/etc/phottemp.cat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/etc/phottemp.cat	(revision 16632)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /branches/eam_branch_20080223/Ohana/src/getstar/etc/template.cat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/etc/template.cat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/etc/template.cat	(revision 16632)
@@ -0,0 +1,296 @@
+SIMPLE  =                    F  / ASTROCAM PHOTOMETRY FILE                    \
+BITPIX  =                   16 /                                              \
+NAXIS   =                    2  / NUMBER OF AXES                              \
+NAXIS1  =                 1106  / NUMBER OF COLUMNS                           \
+NAXIS2  =                 1024  / NUMBER OF ROWS                              \
+BSCALE  =             1.000000 /                                              \
+BZERO   =             0.000000 /                                              \
+DATE    = '19/12/94'            / UT Date of file creation (DD/MM/YY)         \
+ORIGIN  = 'MDM Observatory'     / Michigan-Dartmouth-MIT                      \
+LATITUDE=              31.9500  / Latitude (degrees N)                        \
+LONGITUD=            -111.6150  / Longitude (degrees E)                       \
+OBSERVER= 'Metzger '            / Name of observer                            \
+TELESCOP= '1.3m McGraw-Hill'    / Telescope used for observation              \
+INSTRUME= 'Charlotte Direct'    / Instrument used for observation             \
+DETECTOR= 'Charlotte/Tek 1024^2 CCD'  / Detector used for observation         \
+FRAME   =                   32  / Frame number of observation                 \
+CCDPICNO=                   32  / Frame number of observation                 \
+OBJECT  = 'ocl0327 '            / Name of object                              \
+IMAGETYP= 'OBJECT  '            / Type of observation                         \
+EXPTIME =              250.000  / Integration time (seconds)                  \
+DARKTIME=              250.067  / Dark current time (seconds)                 \
+DATE-OBS= '19/12/94'            / UT Date of observation (DD/MM/YY)           \
+UT      = ' 05:25:44.00'        / Universal time (UTC) at exposure start      \
+JD      =       2449705.726204                                                \
+RA      =           50.700      / Right Ascension                             \
+DEC     =           89.000      / Declination                                 \
+DIRECTN =                 -1    / Moving South                                \
+EQUINOX =             1950.000  / Equinox of RA and DEC                       \
+HA      = ' 02:14:06.72'        / Hour angle at start                         \
+ST      = ' 03:49:36.85'        / Sidereal time at start                      \
+ZD      = ' 36:26:07.17'        / Zenith distance (degrees)                   \
+AIRMASS =                1.243  / Airmass at start                            \
+FILTER  = 'I KP    '            / Filter description                          \
+GAIN    =                3.350  / Nominal gain (e-/ADU)                       \
+SECPIX1 =                0.508  / Arcseconds per pixel in fast dir            \
+SECPIX2 =                0.508  / Arcseconds per pixel in slow dir            \
+CCDBIN1 =                    1  / On-chip column binning (fast dir)           \
+CCDBIN2 =                    1  / On-chip row binning (slow dir)              \
+GPROBE  = '  5000.00   7000.00'  / Guide probe X Y                            \
+DATASEC = '[51:1074,1:1024]'    / Image area of frame                         \
+CCDSEC  = '[1:1074,1:1024]'     / Image area relative to full chip            \
+BIASSEC = '[1080:1106,1:1023]'  / Overscan area of frame                      \
+UNSIGN  =                    T /                                              \
+NSTARS  =                    0  / NUMBER OF stars                             \
+CTYPE1  = 'RA---SIN          ' /                                               
+CTYPE2  = 'DEC--SIN          ' /                                               
+CDELT1  =             0.000733 /                                               
+CDELT2  =             0.000733 /                                               
+CRVAL1  =            50.191418 /                                               
+CRVAL2  =            88.998663 /                                               
+CRPIX1  =          1028.644173 /                                               
+CRPIX2  =           503.129830 /                                               
+PC001001=             0.999906 /                                               
+PC001002=             0.012081 /                                               
+PC002001=            -0.011936 /                                               
+PC002002=             0.999950 /                                               
+END                                                                           \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+                                                                              \
+ 246.5  352.1 13.000 020 1 3.2
+ 246.5  352.1 14.100 020 1 3.2
+ 279.4  328.9 13.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 187.3  238.8  9.800 020 1 3.2
+ 436.6  413.5 14.300 020 1 3.2
+   9.3  856.5 13.000 020 1 3.2
+   9.3  856.2 13.600 020 1 3.2
+ 319.7  697.9 12.000 020 1 3.2
+ 319.7  697.7 12.100 020 1 3.2
+ 244.3    9.5 14.100 020 1 3.2
+ 284.7  334.4 14.000 020 1 3.2
+ 127.1  122.8 14.200 020 1 3.2
+ 140.2  791.1 13.700 020 1 3.2
+ 140.2  790.8 14.400 020 1 3.2
+ 131.7  636.3 13.800 020 1 3.2
+ 423.8  700.6 13.800 020 1 3.2
+ 423.7  700.7 12.500 020 1 3.2
+ 266.2  290.7 13.800 020 1 3.2
+ 266.0  290.7 13.100 020 1 3.2
+ 570.7  721.6 13.600 020 1 3.2
+ 570.7  721.6 13.100 020 1 3.2
+ 548.7  673.0 13.700 020 1 3.2
+ 264.2  219.7 12.800 020 1 3.2
+ 264.0  219.7 12.100 020 1 3.2
+ 161.9  797.4 11.900 020 1 3.2
+ 162.0  797.2 12.200 020 1 3.2
+ 505.8  851.8 13.700 020 1 3.2
+  88.2  419.0 11.400 020 1 3.2
+  88.2  419.0 11.800 020 1 3.2
+ 426.9  613.2  9.400 020 1 3.2
+ 427.4  613.5  7.600 020 1 3.2
+ 326.1  595.2 12.100 020 1 3.2
+ 326.2  595.1 12.600 020 1 3.2
+ 444.4  845.2 14.200 020 1 3.2
+ 254.1  916.8 14.500 020 1 3.2
+ 502.6  882.4 14.200 020 1 3.2
+ 128.3  275.7 12.300 020 1 3.2
+ 128.3  275.7 12.900 020 1 3.2
+ 230.9  554.8 13.300 020 1 3.2
+ 230.9  554.7 14.200 020 1 3.2
+  47.5  685.2 13.500 020 1 3.2
+  47.5  684.9 14.200 020 1 3.2
+ 382.6  658.7 14.000 020 1 3.2
+ 182.2  330.3 14.200 020 1 3.2
+ 245.1  548.3 12.600 020 1 3.2
+ 245.3  548.0 13.200 020 1 3.2
+  50.3  849.0 13.700 020 1 3.2
+  50.5  848.8 14.300 020 1 3.2
+  17.9  772.7 14.200 020 1 3.2
+ 499.8  712.8 13.500 020 1 3.2
+ 499.8  712.6 14.400 020 1 3.2
+ 294.5  349.4 14.000 020 1 3.2
+ 497.7  747.8 11.000 020 1 3.2
+ 497.5  747.8 10.900 020 1 3.2
+ 109.7  323.5 14.000 020 1 3.2
+  59.5  917.6 14.300 020 1 3.2
+  59.4  917.8 13.700 020 1 3.2
+  82.2  880.5 13.800 020 1 3.2
+ 145.1  341.2 14.500 020 1 3.2
+ 452.7  592.4 14.400 020 1 3.2
+ 623.4  820.0 13.700 020 1 3.2
+ 609.7  829.3 13.500 020 1 3.2
+ 481.8  938.3 14.400 020 1 3.2
+ 617.0  792.7 13.500 020 1 3.2
+ 183.2  539.7 14.400 020 1 3.2
+ 133.9  679.6 14.400 020 1 3.2
+ 423.7  667.8  6.500 020 1 3.2
+ 434.7  111.9 13.200 020 1 3.2
+ 434.5  111.9 13.200 020 1 3.2
+ 434.6  111.9 14.200 020 1 3.2
+1222.3  684.2 13.900 020 1 3.2
+1077.6  282.5 14.000 020 1 3.2
+1077.8  282.5 13.400 020 1 3.2
+ 720.8  562.1 14.100 020 1 3.2
+ 721.1  561.9 14.400 020 1 3.2
+1182.1  944.4 12.100 020 1 3.2
+1181.9  944.4 11.800 020 1 3.2
+1181.9  944.4 12.300 020 1 3.2
+ 761.2  423.1 14.300 020 1 3.2
+ 761.0  423.1 14.100 020 1 3.2
+ 926.7  436.8 13.400 020 1 3.2
+ 926.6  436.8 14.200 020 1 3.2
+1209.1   45.0 13.200 020 1 3.2
+1209.2   43.6 12.800 020 1 3.2
+1135.2  653.1  8.100 020 1 3.2
+1135.6  653.4  8.200 020 1 3.2
+1123.5  735.8 12.000 020 1 3.2
+1123.6  735.8 11.800 020 1 3.2
+1123.7  735.7 11.600 020 1 3.2
+ 730.7   28.6 12.100 020 1 3.2
+ 730.7   28.6 12.200 020 1 3.2
+ 783.1  267.5 14.200 020 1 3.2
+ 783.2  267.5 13.400 020 1 3.2
+ 876.2  462.7 13.800 020 1 3.2
+ 876.4  462.7 14.200 020 1 3.2
+ 917.2  399.9 13.700 020 1 3.2
+ 917.3  399.9 13.200 020 1 3.2
+1227.5  218.4 10.400 020 1 3.2
+1227.7  218.4 10.500 020 1 3.2
+1022.7  146.0 13.300 020 1 3.2
+1022.5  146.0 14.100 020 1 3.2
+1324.7   72.3 12.900 020 1 3.2
+1324.6   72.3 13.200 020 1 3.2
+ 743.2  379.4 14.300 020 1 3.2
+ 742.9  379.4 13.900 020 1 3.2
+1255.9  544.0 12.600 020 1 3.2
+1256.0  543.9 12.300 020 1 3.2
+ 848.9  251.1 13.200 020 1 3.2
+ 849.0  251.1 12.700 020 1 3.2
+ 495.6  147.4 11.400 020 1 3.2
+ 495.6  147.4 11.300 020 1 3.2
+ 495.5  147.4 11.000 020 1 3.2
+1016.4  735.5 14.200 020 1 3.2
+1016.3  735.7 13.900 020 1 3.2
+ 795.2  675.9 14.400 020 1 3.2
+ 887.2  968.8 10.800 020 1 3.2
+ 626.8  726.9 14.400 020 1 3.2
+ 718.6  800.1  9.700 020 1 3.2
+ 675.4  301.6 14.400 020 1 3.2
+ 801.6  436.8 14.200 020 1 3.2
+1066.4  870.0 13.700 020 1 3.2
+1066.5  869.9 13.800 020 1 3.2
+ 644.5  662.9  9.900 020 1 3.2
+ 639.1  760.4 13.000 020 1 3.2
+ 822.7  663.1 12.800 020 1 3.2
+ 822.7  663.1 13.100 020 1 3.2
+ 677.2  716.2 12.900 020 1 3.2
+ 765.6  641.5 13.200 020 1 3.2
+ 765.7  641.4 13.500 020 1 3.2
+ 998.3  425.8 14.400 020 1 3.2
+ 713.7  716.2 13.800 020 1 3.2
+ 814.7  887.6  2.000 020 1 3.2
+ 808.7  884.1  8.200 020 1 3.2
+1812.3  259.3 14.500 020 1 3.2
+1655.9  655.4 12.200 020 1 3.2
+1655.9  655.4 12.100 020 1 3.2
+1577.2  839.6 11.500 020 1 3.2
+1577.2  839.6 11.400 020 1 3.2
+1643.7  597.0 14.100 020 1 3.2
+1552.8  251.1 10.100 020 1 3.2
+1552.8  251.1 10.300 020 1 3.2
+1410.0  999.9 13.900 020 1 3.2
+1335.6  687.0 13.000 020 1 3.2
+1335.8  686.8 12.700 020 1 3.2
+1471.4  262.0 14.200 020 1 3.2
+1479.6  608.3 14.200 020 1 3.2
+1478.1  211.5 12.000 020 1 3.2
+1478.3  211.5 12.000 020 1 3.2
+1552.5   46.4 14.500 020 1 3.2
+2042.4  548.3 10.800 020 1 3.2
+2042.6  548.3 11.000 020 1 3.2
+1448.0  915.7 14.100 020 1 3.2
+1462.3  989.2 13.000 020 1 3.2
+1462.3  989.0 12.700 020 1 3.2
+1316.9  787.3 14.100 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1787.6  883.5 12.200 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1979.1  300.3 12.900 020 1 3.2
+1677.2  106.4 13.100 020 1 3.2
+1677.0  106.4 13.300 020 1 3.2
+1324.2  429.9  9.200 020 1 3.2
+1324.2  429.9  9.000 020 1 3.2
+1462.8  214.3 13.700 020 1 3.2
+1462.8  214.3 14.200 020 1 3.2
+1405.4   95.5 11.700 020 1 3.2
+1405.2   95.5 11.600 020 1 3.2
+1604.8   90.0 11.200 020 1 3.2
+1604.8   90.0 11.300 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1921.5  738.1 13.500 020 1 3.2
+1459.8  473.6 13.400 020 1 3.2
+1459.7  473.6 13.800 020 1 3.2
+1438.7   77.8 12.200 020 1 3.2
+1438.6   77.8 12.200 020 1 3.2
+1355.0  114.6 13.000 020 1 3.2
+1354.9  114.6 13.200 020 1 3.2
+1941.4  940.7 13.000 020 1 3.2
+1941.6  940.7 12.900 020 1 3.2
+1994.0  800.8 13.900 020 1 3.2
+1993.8  800.8 14.000 020 1 3.2
+2024.4  907.0 13.700 020 1 3.2
+2024.4  907.0 13.800 020 1 3.2
+2035.7  881.6 13.900 020 1 3.2
+2035.9  881.6 13.800 020 1 3.2
+1994.0  924.2 12.100 020 1 3.2
+1994.0  924.2 12.000 020 1 3.2
Index: /branches/eam_branch_20080223/Ohana/src/getstar/include/dvoImageExtract.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/include/dvoImageExtract.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/include/dvoImageExtract.h	(revision 16632)
@@ -0,0 +1,33 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+# include <glob.h>
+
+enum {NONE, SIMPLE_CMP, SIMPLE_CMF, SIMPLE_MEF, MOSAIC_CMP, MOSAIC_CMF, MOSAIC_MEF, MOSAIC_PHU};
+
+int       VERBOSE;
+
+char OUTPUT[256];
+char GSCFILE[256];
+char CATDIR[256];
+char CATMODE[16];    /* raw, mef, split, mysql */
+char CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char SKY_TABLE[256];
+int  SKY_DEPTH;
+char   ImageCat[256];
+char *OUTFILE;
+Coords *MOSAIC;         // carries the mosaic into ReadImageHeader
+
+int  args_extract    	 PROTO((int argc, char **argv));
+int  ConfigInit_extract  PROTO((int *argc, char **argv));
+int  Shutdown         	 PROTO((char *format, ...));
+void TrapSignal       	 PROTO((int sig));
+void SetProtect       	 PROTO((int mode));
+int  SetSignals       	 PROTO(());
+
+int GetFileMode (Header *header);
+int edge_check (double *x1, double *y1, double *x2, double *y2);
+
+int  WriteImageFITS (FILE *f, Image *image);
+int  WriteImages (char *filename, Image *images, int Nimages, int *matches, int Nmatches);
+int *SelectImages (char *filename, Image *dbImages, int NdbImages, int *Nmatch);
Index: /branches/eam_branch_20080223/Ohana/src/getstar/include/dvoImageOverlaps.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/include/dvoImageOverlaps.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/include/dvoImageOverlaps.h	(revision 16632)
@@ -0,0 +1,38 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+# include <glob.h>
+
+enum {NONE, SIMPLE_CMP, SIMPLE_CMF, SIMPLE_MEF, MOSAIC_CMP, MOSAIC_CMF, MOSAIC_MEF, MOSAIC_PHU};
+
+int       VERBOSE;
+
+char OUTPUT[256];
+char GSCFILE[256];
+char CATDIR[256];
+char CATMODE[16];    /* raw, mef, split, mysql */
+char CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char SKY_TABLE[256];
+int  SKY_DEPTH;
+char   ImageCat[256];
+Coords *MOSAIC;         // carries the mosaic into ReadImageHeader
+
+int WITH_PHU;
+int SOLO_PHU;
+int ACCEPT_ASTROM;
+
+int  args_overlaps    	 PROTO((int argc, char **argv));
+int  ConfigInit_overlaps PROTO((int *argc, char **argv));
+int  Shutdown         PROTO((char *format, ...));
+void TrapSignal       PROTO((int sig));
+void SetProtect       PROTO((int mode));
+int  SetSignals       PROTO(());
+
+Image *ReadImageFiles (char *filename, int *Nimages);
+int ReadImageHeader (Header *header, Image *image);
+int *MatchImage (Image *dbImages, int NdbImages, Image *image, int *Nmatch);
+int ListImageOverlaps (Image *dbImages, Image *image, int *matches, int Nmatches);
+
+int GetFileMode (Header *header);
+int edge_check (double *x1, double *y1, double *x2, double *y2);
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3);
Index: /branches/eam_branch_20080223/Ohana/src/getstar/include/getstar.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/include/getstar.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/include/getstar.h	(revision 16632)
@@ -0,0 +1,49 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+
+enum {
+  BY_NOTHING,
+  BY_REGION,
+  BY_RADIUS,
+  BY_CATALOG,
+  BY_IMAGE,
+  BY_IMMATCH,
+  BY_IMLIST,
+};
+
+int       VERBOSE;
+int       MODE;
+SkyRegion REGION;
+char     *IMAGENAME;
+
+char OUTPUT[256];
+char OUTFORMAT[256];
+char GSCFILE[256];
+char CATDIR[256];
+char CATMODE[16];    /* raw, mef, split, mysql */
+char CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char SKY_TABLE[256];
+int  SKY_DEPTH;
+
+int  MagLimitUse;
+float MagLimitValue;
+PhotCode *photcode;
+
+int  args             	     PROTO((int argc, char **argv));
+int  ConfigInit       	     PROTO((int *argc, char **argv));
+int  Shutdown         	     PROTO((char *format, ...));
+int  load_pt_catalog  	     PROTO((Catalog *catalog, SkyRegion *region));
+int  select_by_region 	     PROTO((Catalog *output, Catalog *catalog, SkyRegion *region, int start, int end));
+void set_db           	     PROTO((FITS_DB *in));
+void wcatalog         	     PROTO((char *filename, Catalog *catalog));
+void mkcatalog        	     PROTO((Catalog *catalog));
+void init_catalog     	     PROTO((Catalog *catalog));
+void TrapSignal       	     PROTO((int sig));
+void SetProtect       	     PROTO((int mode));
+int  SetSignals       	     PROTO(());
+int  gcatalog         	     PROTO((Catalog *catalog));
+int  write_catalog           PROTO((Catalog *catalog));
+int  write_getstar_PS1_DEV_0 PROTO((Catalog *catalog));
+int  write_getstar_PS1_DEV_1 PROTO((Catalog *catalog));
+int  write_getstar_PS1_DEV_2 PROTO((Catalog *catalog));
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "getstar.h"
+
+int ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "GSCFILE",                "%s", 0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s", 0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = 2;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+  SetZeroPoint (25.0);
+
+  free (config);
+  free (file);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit_extract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit_extract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit_extract.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "dvoImageExtract.h"
+
+int ConfigInit_extract (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "GSCFILE",                "%s", 0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s", 0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = 2;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit_overlaps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit_overlaps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/ConfigInit_overlaps.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "dvoImageOverlaps.h"
+
+int ConfigInit_overlaps (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "GSCFILE",                "%s", 0, GSCFILE);
+  ScanConfig (config, "CATDIR",                 "%s", 0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = 2;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/GetFileMode.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/GetFileMode.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/GetFileMode.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "dvoImageOverlaps.h"
+
+// examine the PHU of this file and determine the file mode
+int GetFileMode (Header *header) {
+
+  char ctype[80];
+  int Naxis, Nx, Ny;
+  int simple, extend, haveNaxis, haveNx, haveNy, haveCTYPE;
+
+  gfits_scan (header, "SIMPLE", "%t", 1, &simple);
+  haveNaxis = gfits_scan (header, "NAXIS",  "%d", 1, &Naxis);
+  haveNx    = gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  haveNy    = gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  haveCTYPE = gfits_scan (header, "CTYPE1", "%s", 1, ctype);
+
+  gfits_scan (header, "EXTEND", "%t", 1, &extend);
+    
+  if ((Naxis == 2) || !simple) {
+    if (!strcmp (&ctype[4], "-WRP")) {
+      return MOSAIC_CMP;
+    }
+    return SIMPLE_CMP;
+  }
+
+  if (!extend && strcmp (&ctype[4], "-DIS")) {
+    if (!strcmp (&ctype[4], "-WRP")) {
+      return MOSAIC_CMF;
+    }
+    return SIMPLE_CMF;
+  }
+
+  if (!extend && !strcmp (&ctype[4], "-DIS")) {
+    return MOSAIC_PHU;
+  }
+
+  if (extend && strcmp (&ctype[4], "-DIS")) {
+    return SIMPLE_MEF;
+  }
+
+  if (extend && !strcmp (&ctype[4], "-DIS")) {
+    return MOSAIC_MEF;
+  }
+
+  return (NONE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/ListImageOverlaps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/ListImageOverlaps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/ListImageOverlaps.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "dvoImageOverlaps.h"
+
+/* given image, find catalog images which overlap it */
+int ListImageOverlaps (Image *dbImages, Image *image, int *matches, int Nmatches) {
+  
+  int i, N;
+
+  for (i = 0; i < Nmatches; i++) {
+    N = matches[i];
+    fprintf (stdout, "%s  :  %s\n", image[0].name, dbImages[N].name);
+  }
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/MatchImages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/MatchImages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/MatchImages.c	(revision 16632)
@@ -0,0 +1,153 @@
+# include "dvoImageOverlaps.h"
+# ifndef FLT_MAX
+# define FLT_MAX 1e32
+# endif
+
+/* given image, find catalog images which overlap it */
+int *MatchImage (Image *dbImages, int NdbImages, Image *image, int *Nmatch) {
+  
+  int i, j, N, addtolist, status;
+  int NMATCH, nmatch, *match;
+  Coords tcoords;
+  double r, d;
+  double Xi[4], Yi[4], Xo[4], Yo[4];  /* image and original corners */
+  double Xmin, Xmax, Ymin, Ymax;
+  double xmin, xmax, ymin, ymax;
+
+  *Nmatch = 0;
+
+  if (!WITH_PHU && !strcmp (&image[0].coords.ctype[4], "-DIS")) return NULL;
+  if ( SOLO_PHU &&  strcmp (&image[0].coords.ctype[4], "-DIS")) return NULL;
+
+  /* project onto rectilinear grid with 1 arcsec pixels */
+  /* we keep the original crpix1,2 and crref1,2 */
+  /* for mosaic astrometry, the grid should be w.r.t. the tangent-plane, not chip coords */
+  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) {
+    // if the input image is a mosaic, we need to register that mosaic for the calculations below
+    if (MOSAIC == NULL) {
+      fprintf (stderr, "no mosaic for WRP image (use -mosaic)\n");
+      return NULL;
+    }
+    RegisterMosaic (MOSAIC);
+
+    tcoords = MOSAIC[0];
+    tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+    tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+    tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+    tcoords.Npolyterms = 1;
+    strcpy (tcoords.ctype, "RA---TAN");
+    /* register so image->sky conversions below have correct mosaic */
+  } else {
+    tcoords = image[0].coords;
+    tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+    tcoords.pc1_1 = tcoords.pc2_2 = 1.0;
+    tcoords.pc1_2 = tcoords.pc2_1 = 0.0;
+    strcpy (tcoords.ctype, "RA---TAN");
+  }
+
+  /* define original corners */
+  SetImageCorners (Xo, Yo, &image[0]);
+  
+  Ymin = Xmin = +FLT_MAX;
+  Ymax = Xmax = -FLT_MAX;
+  for (j = 0; j < 4; j++) {
+    /* XY-to_RD is two-level if ctype == WRP */
+    XY_to_RD (&r, &d, Xo[j], Yo[j], &image[0].coords);
+    RD_to_XY (&Xo[j], &Yo[j], r, d, &tcoords);
+    Xmin = MIN (Xmin, Xo[j]);
+    Xmax = MAX (Xmax, Xo[j]);
+    Ymin = MIN (Ymin, Yo[j]);
+    Ymax = MAX (Ymax, Yo[j]);
+  }
+
+  /* match represents the subset of overlapping images */
+  nmatch = 0;
+  NMATCH = 20;
+  ALLOCATE (match, int, NMATCH);
+
+  /* setup links for mosaic WRP and DIS entries */
+  BuildChipMatch (dbImages, NdbImages);
+
+  /* run through image table and search for overlaps
+     also define the vtable entries for the images we keep  */
+
+  for (i = 0; i < NdbImages; i++) {
+
+    if (!WITH_PHU && !strcmp (&dbImages[i].coords.ctype[4], "-DIS")) continue;
+    if ( SOLO_PHU &&  strcmp (&dbImages[i].coords.ctype[4], "-DIS")) continue;
+
+    /* if any of these images are WRP images, need to find matching DIS */
+    if (!FindMosaicForImage (dbImages, NdbImages, i)) continue;
+
+    /* define image corners */
+    SetImageCorners (Xi, Yi, &dbImages[i]);
+    // Xi[4] = Xi[0]; Yi[4] = Yi[0];
+
+    /* transform to tcoords, skip corners off image */
+    /*** XXX this will fail for very large images which extend beyond 180deg */
+    ymin = xmin = +FLT_MAX;
+    ymax = xmax = -FLT_MAX;
+    for (j = N = 0; j < 4; j++) {
+      status = XY_to_RD (&r, &d, Xi[j], Yi[j], &dbImages[i].coords);
+      if (!status) continue;
+      status = RD_to_XY (&Xi[N], &Yi[N], r, d, &tcoords);
+      if (!status) continue;
+      xmin = MIN (xmin, Xi[N]);
+      xmax = MAX (xmax, Xi[N]);
+      ymin = MIN (ymin, Yi[N]);
+      ymax = MAX (ymax, Yi[N]);
+      N++;
+    }
+
+    /* check if one corner of dbImages[i] is inside image[0] */
+    for (j = 0; j < N; j++) {
+      addtolist = TRUE;
+      addtolist &= (Xi[j] >= Xmin);
+      addtolist &= (Xi[j] <= Xmax);
+      addtolist &= (Yi[j] >= Ymin);
+      addtolist &= (Yi[j] <= Ymax);
+      if (addtolist) goto addtolist;
+    }
+
+    /* or else, check if one corner of image[0] is inside dbImages[i] */
+    for (j = 0; j < 4; j++) {
+      addtolist = TRUE;
+      addtolist &= (Xo[j] >= xmin);
+      addtolist &= (Xo[j] <= xmax);
+      addtolist &= (Yo[j] >= ymin);
+      addtolist &= (Yo[j] <= ymax);
+      if (addtolist) goto addtolist;
+    }
+
+    // no match, skip this dbImage
+    continue;
+
+  addtolist:
+    match[nmatch] = i;
+    nmatch ++;
+    if (nmatch == NMATCH) {
+      NMATCH += 20;
+      REALLOCATE (match, int, NMATCH);
+    }
+  }
+  
+  if (VERBOSE) fprintf (stderr, "found %d overlapping images\n", nmatch);
+
+  *Nmatch = nmatch;
+  return (match);
+}
+  
+void SetImageCorners (double *X, double *Y, Image *image) {
+
+  if (!strcmp(&image[0].coords.ctype[4], "-DIS")) {
+    X[0] = -0.5*image[0].NX; Y[0] = -0.5*image[0].NY;
+    X[1] = +0.5*image[0].NX; Y[1] = -0.5*image[0].NY;
+    X[2] = +0.5*image[0].NX; Y[2] = +0.5*image[0].NY;
+    X[3] = -0.5*image[0].NX; Y[3] = +0.5*image[0].NY;
+  } else {
+    X[0] = 0;           Y[0] = 0;
+    X[1] = image[0].NX; Y[1] = 0;
+    X[2] = image[0].NX; Y[2] = image[0].NY;
+    X[3] = 0;           Y[3] = image[0].NY;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/ReadImageFiles.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/ReadImageFiles.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/ReadImageFiles.c	(revision 16632)
@@ -0,0 +1,226 @@
+# include "dvoImageOverlaps.h"
+
+Image *ReadImageFiles (char *filename, int *Nimages) {
+
+  int i, j, N, Nfile, Nheader, NHEADER, Nimage, NIMAGE;
+  int Nskip, Nhead, Ndata, done, status, mode;
+  char **file, *name;
+  FILE *f;
+  glob_t globList;
+  char **exthead, **extdata, **exttype, tmpword[80];
+  int *extnum_head, *extnum_data, *extsize;
+  Header *header, **headers;
+  Image *image;
+
+  // parse the filename as a glob
+  globList.gl_offs = 0;
+  glob (filename, 0, NULL, &globList);
+
+  // if the glob does not match, save the literal word:
+  // otherwise save all glob matches
+  if (globList.gl_pathc == 0) {
+    Nfile = 1;
+    ALLOCATE (file, char *, Nfile);
+    file[0] = strcreate (filename);
+  } else {
+    Nfile = globList.gl_pathc;
+    ALLOCATE (file, char *, Nfile);
+    for (i = 0; i < Nfile; i++) {
+      file[i] = strcreate (globList.gl_pathv[i]);
+    }
+  }
+
+  // open the first file, read the PHU header
+  f = fopen (file[0], "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", file[0]);
+    exit (1);
+  }
+  ALLOCATE (header, Header, 1);
+  gfits_fread_header (f, header);
+
+  mode = GetFileMode (header);
+
+  /*** load data from a single PHU or a collection of PHU files ***/
+  if ((mode != SIMPLE_MEF) && (mode != MOSAIC_MEF)) {
+    Nimage = Nfile;
+    ALLOCATE (image, Image, Nimage);
+    for (i = N = 0; i < Nfile; i++) {
+      if (i > 0) {
+	f = fopen (file[i], "r");
+	if (f == NULL) {
+	  fprintf (stderr, "can't read header for %s, skipping\n", file[i]);
+	  continue;
+	}
+	gfits_fread_header (f, header);
+      }
+
+      if (!ReadImageHeader (header, &image[N])) {
+	fprintf (stderr, "skipping %s\n", file[i]);
+	continue;
+      }
+      
+      /* find image rootname */
+      name = filebasename (file[i]);
+      snprintf (image[N].name, 64, name);
+      free (name);
+
+      fclose (f);
+      gfits_free_header (header);
+      N++;
+    }
+    *Nimages = N;
+    
+    if (N == 0) {
+      fprintf (stderr, "ERROR: no valid image data in %s, giving up\n", filename);
+      exit (1);
+    }
+    return image;
+  }
+    
+  /* we have a multi-chip image */
+
+  /* we need to examine the extensions to determine the headers and the data */
+  NHEADER = 10;
+  ALLOCATE (headers, Header *, NHEADER);
+
+  // the first header is already loaded
+  headers[0] = header;
+  Nskip = gfits_data_size (header);
+  fseek (f, Nskip, SEEK_CUR); 
+
+  // load all headers into memory
+  done = FALSE;
+  for (i = 1; !done; i++) {
+      ALLOCATE (headers[i], Header, 1);
+      status = gfits_fread_header (f, headers[i]);
+      if (!status) { 
+	  done = TRUE;
+      } else {
+	  Nskip = gfits_data_size (headers[i]);
+	  fseek (f, Nskip, SEEK_CUR); 
+      }
+      if (i == NHEADER - 1) {
+	  NHEADER += 10;
+	  REALLOCATE (headers, Header *, NHEADER);
+      }
+  }
+  Nheader = i - 1; /* we failed on the last loop */
+    
+  // space to store the images, indexes to the matching headers
+  Nimage = 0;
+  NIMAGE = Nheader;
+  ALLOCATE (image, Image, NIMAGE);
+  ALLOCATE (exthead, char *, NIMAGE);
+  ALLOCATE (extdata, char *, NIMAGE);
+  ALLOCATE (exttype, char *, NIMAGE);
+  ALLOCATE (extnum_head, int, NIMAGE);
+  ALLOCATE (extnum_data, int, NIMAGE);
+  ALLOCATE (extsize, int, Nheader);
+
+  if (mode == MOSAIC_MEF) {
+      exthead[Nimage] = strcreate ("PHU");
+      extdata[Nimage] = strcreate ("NONE");
+      extnum_data[Nimage] = -1;
+      extnum_head[Nimage] = 0;
+      Nimage ++;
+  }
+
+  // now examine the headers, count the table entries, find corresponding headers
+  for (i = 0; i < Nheader; i++) {
+      extsize[i] = headers[i][0].size + gfits_data_size (headers[i]);
+      gfits_scan (headers[i], "EXTTYPE", "%s", 1, tmpword);
+
+      if (!strcmp (tmpword, "SMPDATA")   ||  
+	  !strcmp (tmpword, "PS1_DEV_0") ||  
+	  !strcmp (tmpword, "PS1_DEV_1")) {
+
+	  exttype[Nimage] = strcreate (tmpword);
+	  gfits_scan (headers[i], "EXTNAME", "%s", 1, tmpword);
+	  extdata[Nimage] = strcreate (tmpword);
+	  gfits_scan (headers[i], "EXTHEAD", "%s", 1, tmpword);
+	  exthead[Nimage] = strcreate (tmpword);
+	  extnum_data[Nimage] = i;
+	  extnum_head[Nimage] = -1;
+	  // find the matching exthead entry
+	  for (j = 0; j < Nheader; j++) {
+	    if (gfits_scan (headers[j], "EXTNAME", "%s", 1, tmpword)) {
+	      if (!strcmp (tmpword, exthead[Nimage])) {
+		extnum_head[Nimage] = j;
+	      }
+	    }
+	  }
+	  // skip or crash on table with missing matching header?
+	  if (extnum_head[Nimage] == -1) {
+	      fprintf (stderr, "ERROR: can't read header for %s\n", file[0]);
+	      exit (1);
+	  }
+	  Nimage ++;
+      }
+  }
+
+  // some old format files did not write EXTTYPE.  they have a single table in the first
+  // extension matched to the header in the PHU
+  if (Nimage == 0) {
+      extsize[0] = headers[0][0].size + gfits_data_size (headers[0]);
+      extsize[1] = headers[1][0].size + gfits_data_size (headers[1]);
+      gfits_scan (headers[1], "EXTNAME", "%s", 1, tmpword);
+      if (!strcmp (tmpword, "SMPFILE")) {
+	  extdata[Nimage] = strcreate (tmpword);
+	  exttype[Nimage] = strcreate ("SMPDATA");
+	  exthead[Nimage] = strcreate ("PHU");
+	  extnum_head[Nimage] = 0;
+	  extnum_data[Nimage] = 1;
+	  Nimage = 1;
+      }
+  }
+  if (Nimage == 0) Shutdown ("no object data in file");
+    
+  if (VERBOSE) fprintf (stderr, "file %s has %d headers, including %d images\n", file[0], Nheader, Nimage);
+
+  /* find image rootname */
+  name = filebasename (file[0]);
+
+  // now run through the images, interpret the headers and read the stars
+  for (i = N = 0; i < Nimage; i++) {
+      Nhead = extnum_head[i];
+
+      // XXX do I need to advance the file pointer, or does ReadImageHeader do this?
+      if (VERBOSE) fprintf (stderr, "reading header for %s (%s)\n", exthead[i], extdata[i]);
+      if (!ReadImageHeader (headers[Nhead], &image[N])) {
+	  fprintf (stderr, "skipping %s\n", exthead[i]);
+	  continue;
+      }
+
+      // XXX use something to set the chip name? EXTNAME?
+      if (!strcmp(exthead[i], "PHU") && (Nimage == 1)) {
+	snprintf (image[N].name, 64, "%s", name);
+      } else {
+	snprintf (image[N].name, 64, "%s[%s]", name, exthead[i]);
+      }
+
+      // skip the table if there is not data segment (eg, mosaic WRP image)
+      if (!strcmp(extdata[i], "NONE")) {
+	  N++;
+	  continue;
+      }
+
+      // advance the pointer to the start of the corresponding table block
+      Ndata = extnum_data[i];
+      Nskip = 0;
+      for (j = 0; j < Ndata; j++) {
+	  Nskip += extsize[j];
+      }
+      fseek (f, Nskip, SEEK_SET); 
+      N++;
+  }
+  free (name);
+  *Nimages = N;
+
+  if (N == 0) {
+    fprintf (stderr, "ERROR: no valid image data in %s, giving up\n", filename);
+    exit (1);
+  }
+
+  return image;
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/ReadImageHeader.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/ReadImageHeader.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/ReadImageHeader.c	(revision 16632)
@@ -0,0 +1,103 @@
+# include "dvoImageOverlaps.h"
+
+/* read an image header corresponding to a CMF / CMP data block */
+int ReadImageHeader (Header *header, Image *image) {
+
+  int Nastro, Nx, Ny;
+  double tmp;
+
+  /* get astrometry information */
+  if (!GetCoords (&image[0].coords, header)) {
+    fprintf (stderr, "no astrometric solution in header\n");
+    return (FALSE);
+  }
+  // XXX currently, image uses an unsigned short for NX,XY. this is rather restrictive
+  // and needs to be at least checked.
+  gfits_scan (header, "NAXIS1",   "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",   "%d", 1, &Ny);
+  if ((Nx < 0) || (Nx > 0xffff)) {
+    fprintf (stderr, "WARNING: NX, NY out of range : image boundary will be wrong\n");
+  }
+  image[0].NX = Nx;
+  image[0].NY = Ny;
+
+  // if (!gfits_scan (header, "TZERO",   "%d",  1, &image[0].tzero)) {
+  // image[0].tzero = parse_time (header);
+  // }
+
+  /* only load astrometry, NAXIS1,2, and time if this is a MOSAIC_PHU (ctype is ....-DIS) */
+  if (!strcmp (&image[0].coords.ctype[4], "-DIS")) {
+    MOSAIC = &image[0].coords;
+    return (TRUE);
+  }
+
+  /* require Nastro > 0 unless or ACCEPT_ASTROM */
+  Nastro = 0;
+  gfits_scan (header, "NASTRO", "%d", 1, &Nastro);
+  if ((Nastro == 0) && !ACCEPT_ASTROM) {
+    fprintf (stderr, "bad astrometric solution in header\n");
+    return (FALSE);
+  }
+  if (!strcmp (&image[0].coords.ctype[4], "-WRP")) {
+    if (MOSAIC == NULL) {
+      fprintf (stderr, "no mosaic for WRP image (use -mosaic)\n");
+      return (FALSE);
+    }
+    RegisterMosaic (MOSAIC);
+  } else {
+    /* force image to lie in 0-360 range */
+    while (image[0].coords.crval1 < 0) image[0].coords.crval1 += 360.0;
+    while (image[0].coords.crval1 > 360.0) image[0].coords.crval1 -= 360.0;
+  }
+
+  { 
+    double R, D;
+    /* sanity check on the image coordinates */
+    XY_to_RD (&R, &D, 0.5*Nx, 0.5*Ny, &image[0].coords);
+    if (!finite(R) || !finite(D)) {
+      fprintf (stderr, "corrupted header coordinates, skipping\n");
+      return (FALSE);
+    }
+  }
+    
+  /* CERROR in data file is in arcsec */
+  if (!gfits_scan (header, "CERROR",   "%lf", 1, &tmp)) tmp = 1.0;
+  image[0].cerror = tmp * 50.0;
+ 
+  /*** why are we no longer using APMIFIT?? ***/
+  tmp = 0;
+  /* gfits_scan (header, "APMIFIT",  "%lf", 1, &tmp); */
+  image[0].apmifit = tmp;
+
+  tmp = 0;
+  /* gfits_scan (header, "dAPMIFIT", "%lf", 1, &tmp); */
+  image[0].dapmifit = tmp;
+
+  tmp = 0;
+  gfits_scan (header, "FLIMIT",   "%lf", 1, &tmp);
+  image[0].detection_limit = tmp * 10.0;
+
+  tmp = 0;
+  gfits_scan (header, "FSATUR",   "%lf", 1, &tmp);
+  image[0].saturation_limit = tmp * 10.0;
+
+  tmp = 0;
+  gfits_scan (header, "FWHM_X",   "%lf", 1, &tmp);
+  image[0].fwhm_x = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  tmp = 0;
+  gfits_scan (header, "FWHM_Y",   "%lf", 1, &tmp);
+  image[0].fwhm_y = tmp * 25.0 * image[0].coords.cdelt1 * 3600.0;
+
+  image[0].trate  = 0.0;
+  image[0].secz   = NAN;
+  image[0].ccdnum = 0;
+
+  /* secz is in units milli-airmass */
+  image[0].Mcal = 0.0;
+  image[0].Xm   = NAN_S_SHORT;
+  image[0].code = 0;
+  bzero (image[0].dummy, sizeof(image[0].dummy));
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/SelectImages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/SelectImages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/SelectImages.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "dvoImageExtract.h"
+
+/* given image, find catalog images which overlap it */
+int *SelectImages (char *filename, Image *images, int Nimages, int *Nmatch) {
+  
+  int i, Nchar;
+  int NMATCH, nmatch, *match;
+
+  /* matches here are only based on string comparisons */
+
+  /* match represents the subset of matched images */
+  nmatch = 0;
+  NMATCH = 20;
+  ALLOCATE (match, int, NMATCH);
+
+  /* setup links for mosaic WRP and DIS entries */
+  BuildChipMatch (images, Nimages);
+
+  Nchar = strlen (filename);
+
+  for (i = 0; i < Nimages; i++) {
+
+    if (strncmp (images[i].name, filename, Nchar)) continue;
+
+    match[nmatch] = i;
+    nmatch ++;
+    if (nmatch == NMATCH) {
+      NMATCH += 20;
+      REALLOCATE (match, int, NMATCH);
+    }
+  }  
+
+  if (VERBOSE) fprintf (stderr, "found %d matching images\n", nmatch);
+
+  *Nmatch = nmatch;
+  return (match);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "getstar.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect these signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored (POSIX.1-1990) */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored (POSIX.1-1990) */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore (POSIX.1-1990) */
+    case SIGCONT:    /* continue - maintain this action (POSIX.1-1990) */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? (POSIX.1-1990) */
+    case SIGURG:     /* socket signal, ignore this (POSIX.1-2001) */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "getstar.h"
+
+static FITS_DB *db;
+
+void set_db (FITS_DB *in) {
+  db = in;
+}
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format));
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  SetProtect (TRUE);
+  gfits_db_close (db);
+  fprintf (stderr, "ERROR: getstar halted\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/WriteImageFITS.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/WriteImageFITS.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/WriteImageFITS.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "dvoImageExtract.h"
+
+/* given image, find catalog images which overlap it.  this function actually creates an
+ * image-less file, filling in the header, but not the pixels.
+ */
+int WriteImageFITS (FILE *f, Image *image) {
+  
+  int Nstars;
+  Header header;
+  Header theader;
+  FTable table;
+
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  header.Naxes = 2;
+  if (image) {
+    header.Naxis[0] = image[0].NX;
+    header.Naxis[1] = image[0].NY;
+  }
+  gfits_create_header (&header);
+  gfits_modify (&header, "NAXIS", "%d", 1, 0);
+
+  if (image) {
+    PutCoords (&image[0].coords, &header);
+  }
+  /* do not create data matrix - the matrix is defined to be empty (NAXIS=0)
+     gfits_create_matrix (&header, &matrix);
+  */
+  gfits_fwrite_header  (f, &header);
+
+  // gfits_fwrite_matrix  (f, &matrix);
+  return (TRUE);
+
+  Nstars = 0;
+  if (image) Nstars = image[0].nstar;
+
+  table.header = &theader;
+  gfits_table_set_SMPData (&table, NULL, Nstars);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &table);
+
+  return TRUE;
+}
+
+// XXX this is a temporary hack to get skycell output working
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/WriteImages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/WriteImages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/WriteImages.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "dvoImageExtract.h"
+
+/* given image, find catalog images which overlap it */
+int WriteImages (char *filename, Image *images, int Nimages, int *matches, int Nmatches) {
+  
+  int i, N;
+  int nWRP, newWRP, isWRP;
+  FILE *f;
+
+  /* matches here are only based on string comparisons */
+
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "failed to open output file %s\n", filename);
+    exit (1);
+  }
+
+  nWRP = -1;
+  isWRP = FALSE;
+  for (i = 0; i < Nmatches; i++) {
+    if (!strcmp (&images[0].coords.ctype[4], "-WRP")) {
+      if (!FindMosaicForImage (images, Nimages, i)) {
+	fprintf (stderr, "failed to find matching mosaic\n");
+	exit (1);
+      }
+      if (isWRP) {
+	newWRP = GetRegisteredMosaic();
+	if (newWRP != nWRP) {
+	  fprintf (stderr, "only one mosaic allowed in an output file\n");
+	  exit (1);
+	}
+      } else {
+	nWRP = GetRegisteredMosaic();
+	isWRP = TRUE;
+      }
+    }      
+  }
+
+  if (isWRP) {
+    WriteImageFITS (f, &images[nWRP]);
+  } else {
+    // write a blank
+    if (Nmatches > 1) {
+      WriteImageFITS (f, NULL);
+    }
+  }
+
+  for (i = 0; i < Nmatches; i++) {
+    N = matches[i];
+    WriteImageFITS (f, &images[N]);
+  }  
+
+  fclose (f);
+  return TRUE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/args.c	(revision 16632)
@@ -0,0 +1,159 @@
+# include "getstar.h"
+
+void help () {
+  fprintf (stderr, "USAGE: \n"
+	   "getstar -region ra dec ra dec\n"
+	   "getstar -radius ra dec radius\n"
+	   "getstar -catalog n0000/0000.cpt\n"
+	   "getstar -image name\n"
+	   "getstar -immatch partial-name\n\n"
+	   " options: \n"
+	   " -maglim (mag)    : maximum magnitude returned\n"
+	   " -format (format) : output formats (CATALOG, PS1_DEV_0, PS1_DEV_1, PS1_DEV_2)\n"
+	   " -photcode (code) : desired photcode for output magnitudes\n"
+	   " -o output        : defaults to stdout\n"
+	   " -v               : verbose mode\n"
+	   " -h / -help       : this list\n"
+    );
+  exit (2);
+}
+
+int args (int argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* configuration info */
+  ConfigInit (&argc, argv);
+
+  /* check for command line options */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  MagLimitUse = FALSE;
+  if ((N = get_argument (argc, argv, "-maglim"))) {
+    MagLimitUse = TRUE;
+    remove_argument (N, &argc, argv);
+    MagLimitValue = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for command line options */
+  strcpy (OUTPUT, "stdout");
+  if ((N = get_argument (argc, argv, "-o"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (OUTPUT, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for command line options */
+  strcpy (OUTFORMAT, "CATALOG");
+  if ((N = get_argument (argc, argv, "-format"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (OUTFORMAT, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  // in some cases, we need a photcode
+  photcode = GetPhotcodebyNsec (0); // default to first average photcode
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    photcode = GetPhotcodebyName (argv[N]);
+    if (photcode == NULL) {
+      fprintf (stderr, "photcode %s not found in photcode table\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  /* parse optional entries above. one of the options below is required */
+  MODE = BY_NOTHING;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    double R, D;
+    MODE = BY_REGION;
+    remove_argument (N, &argc, argv);
+    if (argc != 5) help();
+    ohana_str_to_radec (&R, &D, argv[N+0], argv[N+1]);
+    REGION.Rmin = R;
+    REGION.Dmin = D;
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+
+    ohana_str_to_radec (&R, &D, argv[N+0], argv[N+1]);
+    REGION.Rmax = R;
+    REGION.Dmax = D;
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+
+    // XXX we will have issues at 0,360 boundary...
+    // see code in dvo/pmeasure for fixes
+    while (REGION.Rmin > 360) REGION.Rmin -= 360.0;
+    while (REGION.Rmin <   0) REGION.Rmin += 360.0;
+    while (REGION.Rmax > 360) REGION.Rmax -= 360.0;
+    while (REGION.Rmax <   0) REGION.Rmax += 360.0;
+    if (REGION.Dmax < REGION.Dmin) {
+	SWAP (REGION.Dmax, REGION.Dmin);
+    }
+  }
+  if ((N = get_argument (argc, argv, "-radius"))) {
+    double R, D, radius;
+    fprintf (stderr, "-radius is not recommended\n");
+    MODE = BY_RADIUS;
+    remove_argument (N, &argc, argv);
+    if (argc != 4) help();
+    ohana_str_to_radec (&R, &D, argv[N+0], argv[N+1]);
+    radius = atof(argv[N+2]);
+    REGION.Rmin = R - radius / cos(D*RAD_DEG);
+    REGION.Dmin = D - radius;
+    REGION.Rmax = R + radius / cos(D*RAD_DEG);
+    REGION.Dmax = D + radius;
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-catalog"))) {
+    fprintf (stderr, "-catalog is not implemented\n");
+    exit (2);
+    MODE = BY_CATALOG;
+    remove_argument (N, &argc, argv);
+    if (argc != 2) help();
+  }
+  if ((N = get_argument (argc, argv, "-image"))) {
+    MODE = BY_IMAGE;
+    remove_argument (N, &argc, argv);
+    IMAGENAME = strcreate (argv[N]);
+    if (argc != 2) help();
+  }
+  if ((N = get_argument (argc, argv, "-immatch"))) {
+    MODE = BY_IMMATCH;
+    remove_argument (N, &argc, argv);
+    IMAGENAME = strcreate (argv[N]);
+    if (argc != 2) help();
+  }
+  if (MODE == BY_NOTHING) help ();
+
+  return (TRUE);
+}
+
+
+/* USAGE
+
+getstar -region ra dec ra dec
+getstar -radius ra dec radius
+getstar -catalog n0000/0000.cpt
+getstar -image name [-smp | -smf]
+getstar -immatch partial-name [-smp | -smf]
+   
+* return measurements 
+* return average / secfilt table
+* return a single image (smf/smp format)
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/args_extract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/args_extract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/args_extract.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "dvoImageExtract.h"
+
+void help () {
+  fprintf (stderr, "USAGE: \n"
+	   "dvoExtractImages (imageID) [-o output]\n"
+    );
+  exit (2);
+}
+
+int args_extract (int argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* check for command line options */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for command line options */
+  OUTFILE = NULL;
+  if ((N = get_argument (argc, argv, "-o"))) {
+    remove_argument (N, &argc, argv);
+    OUTFILE = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) help();
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/args_overlaps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/args_overlaps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/args_overlaps.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "dvoImageOverlaps.h"
+
+void help () {
+  fprintf (stderr, "USAGE: \n"
+	   "dvoImageOverlaps (image)\n"
+    );
+  exit (2);
+}
+
+int args_overlaps (int argc, char **argv) {
+  
+  int N;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  /* check for command line options */
+  WITH_PHU = FALSE;
+  if ((N = get_argument (argc, argv, "+phu"))) {
+    WITH_PHU = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  SOLO_PHU = FALSE;
+  if ((N = get_argument (argc, argv, "-phu"))) {
+    WITH_PHU = TRUE;
+    SOLO_PHU = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for command line options */
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* accept bad header astrometry */
+  ACCEPT_ASTROM = FALSE;
+  if ((N = get_argument (argc, argv, "-accept"))) {
+    ACCEPT_ASTROM = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-accept-astrom"))) {
+    ACCEPT_ASTROM = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  /* provide a mosaic for distortion */
+  MOSAIC = NULL;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    Header header;
+    ALLOCATE (MOSAIC, Coords, 1);
+
+    remove_argument (N, &argc, argv);
+    if (!gfits_read_header (argv[N], &header)) {
+      fprintf (stderr, "ERROR: can't read header for mosaic %s\n", argv[N]);
+      exit (1);
+    }
+    if (!GetCoords (MOSAIC, &header)) {
+      fprintf (stderr, "ERROR: no astrometric solution in header\n");
+      exit (1);
+    }
+    if (strcmp(&MOSAIC[0].ctype[4], "-DIS")) {
+      fprintf (stderr, "ERROR: not a mosaic distortion header\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    gfits_free_header (&header);
+  }
+
+  if (argc != 2) help();
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/dvoImageExtract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/dvoImageExtract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/dvoImageExtract.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "dvoImageExtract.h"
+
+int main (int argc, char **argv) {
+
+  int Nimages, status;
+  int Nmatches, *matches;
+  Image *images;
+  FITS_DB db;
+
+  SetSignals ();
+  ConfigInit_extract (&argc, argv);
+  args_extract (argc, argv);
+
+  /*** update the image table ***/
+  /* setup image table format and lock */
+  db.mode   = dvo_catalog_catmode (CATMODE);
+  db.format = dvo_catalog_catformat (CATFORMAT);
+  status    = dvo_image_lock (&db, ImageCat, 3600.0, LCK_SOFT);  // shorter timeout?
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+
+  /* load or create the image table */
+  if (db.dbstate == LCK_EMPTY) {
+    fprintf (stderr, "no images in database (%s)\n", ImageCat);
+    exit (1);
+  } else {
+    if (!dvo_image_load (&db, VERBOSE, FALSE)) {
+      Shutdown ("can't read image catalog %s", db.filename);
+    }
+  }
+  dvo_image_unlock (&db);
+
+  // convert database table to internal structure
+  images = gfits_table_get_Image (&db.ftable, &Nimages, &db.swapped);
+  
+  matches = SelectImages (argv[1], images, Nimages, &Nmatches);
+  WriteImages (OUTFILE, images, Nimages, matches, Nmatches);
+
+  exit (0);
+}
+
+/* This program extracts images headers from a DVO database and writes them 
+   in cmf format (headers + object tables).
+
+   If multiple images are selected, they must be from the same exposures (how?).
+
+   If images are selected with WRP astrometry, the associated DIS image header is first written to
+   the output file.
+ 
+   USAGE: dvoExtractImages (imageID[s]) -o output.cmf
+*/
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/dvoImageOverlaps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/dvoImageOverlaps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/dvoImageOverlaps.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "dvoImageOverlaps.h"
+
+int main (int argc, char **argv) {
+
+  int i, Nimages, NdbImages, status;
+  int Nmatches, *matches;
+  Image *images, *dbImages;
+  FITS_DB db;
+
+  SetSignals ();
+  ConfigInit_overlaps (&argc, argv);
+  args_overlaps (argc, argv);
+  
+  images = ReadImageFiles (argv[1], &Nimages); 
+
+  /*** update the image table ***/
+  /* setup image table format and lock */
+  db.mode   = dvo_catalog_catmode (CATMODE);
+  db.format = dvo_catalog_catformat (CATFORMAT);
+  status    = dvo_image_lock (&db, ImageCat, 3600.0, LCK_SOFT);  // shorter timeout?
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+
+  /* load or create the image table */
+  if (db.dbstate == LCK_EMPTY) {
+    fprintf (stderr, "no images in database (%s)\n", ImageCat);
+    exit (1);
+  } else {
+    if (!dvo_image_load (&db, VERBOSE, FALSE)) {
+      Shutdown ("can't read image catalog %s", db.filename);
+    }
+  }
+  dvo_image_unlock (&db);
+
+  // convert database table to internal structure
+  dbImages = gfits_table_get_Image (&db.ftable, &NdbImages, &db.swapped);
+  
+  // for (i = 1; i < 2; i++) {
+  for (i = 0; i < Nimages; i++) {
+    matches = MatchImage (dbImages, NdbImages, &images[i], &Nmatches);
+    ListImageOverlaps (dbImages, &images[i], matches, Nmatches);
+  }
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/edge_check.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/edge_check.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/edge_check.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "dvoImageOverlaps.h"
+
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/getstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/getstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/getstar.c	(revision 16632)
@@ -0,0 +1,114 @@
+# include "getstar.h"
+
+int main (int argc, char **argv) {
+
+  int i;
+  SkyTable *sky;
+  SkyList *skylist;
+  Catalog catalog;
+  Catalog output;
+  FITS_DB db;
+
+  args (argc, argv);
+  set_db (&db);
+
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+
+  // create an output catalog with the desired name and format options
+  dvo_catalog_init (&output, TRUE);
+  output.filename  = OUTPUT;
+  output.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+  output.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+  output.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+  output.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+  // this has to be here because the 'open' inits the catalog (perhaps not ideal)
+  if (!strcmp (OUTFORMAT, "CATALOG")) {
+    unlink (OUTPUT);
+    dvo_catalog_open   (&output, NULL, VERBOSE, "w");
+  }
+
+  switch (MODE) {
+
+    case BY_REGION:
+    case BY_RADIUS:
+
+      /* load corresponding sky regions */
+      skylist = SkyListByPatch (sky, -1, &REGION);
+      for (i = 0; i < skylist[0].Nregions; i++) {
+	// set the parameters which guide catalog open/load/create
+	catalog.filename = skylist[0].filename[i];
+	catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+	catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+
+	// an error exit status here is a significant error
+	if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "r")) {
+	  fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+	  exit (2);
+	}
+	if (!catalog.Naves_disk) {
+	  dvo_catalog_unlock (&catalog);
+	  dvo_catalog_free (&catalog);
+	  continue;
+	}
+	dvo_catalog_unlock (&catalog);
+
+	/* skip empty catalogs */
+	select_by_region (&output, &catalog, &REGION, 0, 0);
+      }
+      break;
+
+    case BY_IMLIST:
+      /* load image list */
+    case BY_IMAGE:
+
+      # if (0)
+      /* load corresponding sky regions */
+      skylist = SkyListByImage (sky, -1, &image, &Nimage);
+      for (i = 0; i < skylist[0].Nregions; i++) {
+	// set the parameters which guide catalog open/load/create
+	catalog.filename = skylist[0].filename[i];
+	catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+	catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+
+	// an error exit status here is a significant error
+	if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "r")) {
+	  fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+	  exit (2);
+	}
+	/* skip empty catalogs */
+	if (!catalog.Naves_disk) continue;
+	stars = select_by_image (&catalog, &image, 0, 0, stars, &Nstars);
+      }
+      # endif
+      fprintf (stderr, "error: BY_IMAGE not implemented\n");
+      exit (1);
+      break;
+
+    case BY_CATALOG:
+      fprintf (stderr, "error: BY_CATALOG not implemented\n");
+      exit (1);
+      break;
+      
+    default:
+      fprintf (stderr, "error: invalid options\n");
+      exit (1);
+  }
+
+  if (!strcmp (OUTFORMAT, "CATALOG")) {
+    write_catalog (&output);
+  }
+  if (!strcmp (OUTFORMAT, "PS1_DEV_0")) {
+    write_getstar_PS1_DEV_0 (&output);
+  }
+  if (!strcmp (OUTFORMAT, "PS1_DEV_1")) {
+    write_getstar_PS1_DEV_1 (&output);
+  }
+  if (!strcmp (OUTFORMAT, "PS1_DEV_2")) {
+    write_getstar_PS1_DEV_2 (&output);
+  }
+
+  fprintf (stderr, "error: invalid output format %s\n", OUTFORMAT);
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/opening_angle.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/opening_angle.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/opening_angle.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "dvoImageOverlaps.h"
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/parse_time.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/parse_time.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/parse_time.c	(revision 16632)
@@ -0,0 +1,146 @@
+# include "addstar.h"
+
+int parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    if (!gfits_scan (header, JDKeyword, "%lf", 1, &jd)) {
+      fprintf (stderr, "ERROR: missing JD Keyword %s\n", JDKeyword);
+      exit (1);
+    }
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    if (!gfits_scan (header, MJDKeyword, "%lf", 1, &jd)) {
+      fprintf (stderr, "ERROR: missing MJD Keyword %s\n", MJDKeyword);
+      exit (1);
+    }
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  if (!strcasecmp (UTKeyword, "NONE")) {
+      fprintf (stderr, "ERROR: no valid Date/Time keywords\n");
+      exit (1);
+  }
+  if (!strcasecmp (DateKeyword, "NONE")) {
+      fprintf (stderr, "ERROR: no valid Date/Time keywords\n");
+      exit (1);
+  }
+  if (!strcasecmp (DateMode, "NONE")) {
+      fprintf (stderr, "ERROR: no valid Date/Time keywords\n");
+      exit (1);
+  }
+
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  if (!gfits_scan (header, UTKeyword, "%s", 1, line)) {
+      fprintf (stderr, "ERROR: missing UT Keyword %s\n", UTKeyword);
+      exit (1);
+    }
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  if (!gfits_scan (header, DateKeyword, "%s",  1, line)) {
+    fprintf (stderr, "ERROR: missing DATE Keyword %s\n", DateKeyword);
+    exit (1);
+  }
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  Nf = 0;
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    exit (1);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* this should probably use localtime */
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/select_by_image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/select_by_image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/select_by_image.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "getstar.h"
+
+Stars *select_by_image (Catalog *catalog, Image *image, int start, int end, Stars *stars, int *Nstar) {
+
+  int i, n, N, NSTARS;
+  int photcode;
+
+  if (stars == (Stars *) NULL) {
+    N = 0;
+    NSTARS = 1000;
+    ALLOCATE (stars, Stars, NSTARS);
+  } else {
+    N = *Nstar;
+    NSTARS = N + 1000;
+    REALLOCATE (stars, Stars, NSTARS);
+  }    
+
+  /* identify selection criteria */
+  photcode = -1;
+  if ((start == 0) && (end == 0)) {
+    start = image[0].tzero;
+    end   = image[0].tzero + 1e-4*image[0].NY*image[0].trate;  /* trate is in 0.1 msec / row */
+    photcode = image[0].photcode;
+  }
+  if (VERBOSE) fprintf (stderr, "extracting for range %d to %d (photcode %s)\n", start, end, photcode);
+
+  for (i = 0; (i < catalog[0].Nmeasure); i++) {
+    if ((i % 10000) == 0) fprintf (stderr, ". ");
+    if ((catalog[0].measure[i].t >= start) && (catalog[0].measure[i].t <= end) && (photcode == catalog[0].measure[i].photcode)) { 
+      n = catalog[0].measure[i].averef;
+      stars[N].R      = catalog[0].average[n].R - catalog[0].measure[i].dR / 360000.0;
+      stars[N].D      = catalog[0].average[n].D - catalog[0].measure[i].dD / 360000.0;
+
+      stars[N].M      = 0.001*(catalog[0].measure[i].M - catalog[0].measure[i].dt);
+      stars[N].dM     = catalog[0].measure[i].dM;
+      stars[N].dophot = catalog[0].measure[i].dophot;  
+
+      stars[N].Mgal   = 0.001*(catalog[0].measure[i].Mgal - catalog[0].measure[i].dt);
+
+      stars[N].fx     = 0.01*catalog[0].measure[i].FWx;
+      stars[N].fy     = stars[N].fx * 0.01*catalog[0].measure[i].fwy;
+      stars[N].df     = (360.0/255.0)*catalog[0].measure[i].theta;
+      stars[N].found  = catalog[0].measure[i].flags;
+
+      N ++;
+      if (N == NSTARS) {
+	NSTARS += 1000;
+	REALLOCATE (stars, Stars, NSTARS);
+      }    
+
+    } 
+  }
+  fprintf (stderr, "found %d meas\n", N);
+  *Nstar = N;
+  return (stars);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/select_by_region.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/select_by_region.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/select_by_region.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "getstar.h"
+
+/* add selected catalog objects to the output catalog */
+int select_by_region (Catalog *output, Catalog *catalog, SkyRegion *region, int start, int end) {
+
+  int i, j, n, Nm, offset, m, Nsecfilt, code, Nsec;
+  int Nave, NAVE, Nmeas, NMEAS;
+  double R, D;
+  float mag;
+
+  Nsecfilt = output[0].Nsecfilt;
+
+  if (output == NULL) Shutdown ("output not defined");
+
+  /* identify selection criteria */
+  if (VERBOSE) fprintf (stderr, "extracting for time range %d to %d\n", start, end);
+  if (VERBOSE) fprintf (stderr, "extracting for region %f,%f to %f,%f\n", 
+			region[0].Rmin, region[0].Dmin, region[0].Rmax, region[0].Dmax);
+
+  if (output[0].header.buffer != NULL) {
+    gfits_modify (&output[0].header, "RA0",  "%lf", 1, region[0].Rmin);
+    gfits_modify (&output[0].header, "DEC0", "%lf", 1, region[0].Dmin);
+    gfits_modify (&output[0].header, "RA1",  "%lf", 1, region[0].Rmax);
+    gfits_modify (&output[0].header, "DEC1", "%lf", 1, region[0].Dmax);
+  }
+
+  code = photcode[0].code;
+  Nsec = GetPhotcodeNsec (code);
+
+  /* select the average objects in this region */
+  Nave = output[0].Naverage;
+  NAVE = output[0].Naverage + 1000;
+  REALLOCATE (output[0].average, Average, NAVE);
+  REALLOCATE (output[0].secfilt, SecFilt, NAVE*Nsecfilt);
+
+  Nmeas = output[0].Nmeasure;
+  NMEAS = output[0].Nmeasure + 1000;
+  REALLOCATE (output[0].measure, Measure, NMEAS);
+
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    n = catalog[0].measure[i].averef;
+
+    R = catalog[0].average[i].R;
+    D = catalog[0].average[i].D;
+    
+    if (R < region[0].Rmin) continue;
+    if (R > region[0].Rmax) continue;
+    if (D < region[0].Dmin) continue;
+    if (D > region[0].Dmax) continue;
+
+    if (MagLimitUse) {
+      mag = NAN;
+      if (Nsec != -1) {
+	mag = catalog[0].secfilt[i*Nsecfilt + Nsec].M;
+      } else {
+	offset = catalog[0].average[i].offset;
+	for (m = 0; m < catalog[0].average[i].Nm; m++) {
+	  if (catalog[0].measure[offset + m].photcode == code) {
+	    mag = PhotRel (&catalog[0].measure[offset + m], &catalog[0].average[i], &catalog[0].secfilt[i*Nsecfilt]);
+	    break;
+	  }
+	}
+      }
+      if (isnan(mag) || (mag > MagLimitValue)) continue;
+    }
+
+    output[0].average[Nave] = catalog[0].average[i];
+    output[0].average[Nave].offset = Nmeas;
+    for (j = 0; j < Nsecfilt; j++) {
+      output[0].secfilt[Nsecfilt*Nave + j] = catalog[0].secfilt[Nsecfilt*i + j];
+    }
+
+    Nm = 0;
+    offset = catalog[0].average[i].offset;
+
+    for (j = 0; j < catalog[0].average[i].Nm; j++) {
+      output[0].measure[Nmeas] = catalog[0].measure[offset + j];
+      output[0].measure[Nmeas].averef = Nave;
+      Nmeas ++;
+      
+      CHECK_REALLOCATE (output[0].measure, Measure, NMEAS, Nmeas, 1000);
+    }      
+
+    Nave ++;
+    if (Nave == NAVE) {
+      NAVE += 1000;
+      REALLOCATE (output[0].average, Average, NAVE);
+      REALLOCATE (output[0].secfilt, SecFilt, NAVE*Nsecfilt);
+    }
+  }
+  output[0].Naverage = Nave;
+  output[0].Nmeasure = Nmeas;
+  output[0].Nsecf_mem = Nave*Nsecfilt;
+
+  fprintf (stderr, "output catalog has %d stars (%d measures, %d secfilt)\n",
+	   output[0].Naverage, output[0].Nmeasure, output[0].Nsecfilt);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/write_catalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/write_catalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/write_catalog.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "getstar.h"
+
+int write_catalog (Catalog *catalog) {    
+
+  /* write out the selected stars */
+  // XXX need to set the catalog boundaries by hand? RA0-RA1, DEC0-DEC1
+  dvo_catalog_save   (catalog, VERBOSE);
+  dvo_catalog_unlock (catalog);
+  dvo_catalog_free   (catalog);
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_0.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_0.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_0.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "getstar.h"
+
+// convert the average/secfilt values to getstar format 
+// PS1_DEV_0 has no errors or motions, only positions and magnitudes
+int write_getstar_PS1_DEV_0 (Catalog *catalog) {    
+
+  int i, m, offset;
+  int Nsec_c0, Nsec_c1, Nsec_c2, Nsecfilt;
+  int code_c0, code_c1, code_c2;
+  Average *average;
+  Measure *measure;
+  SecFilt *secfilt;
+  Getstar_PS1_DEV_0 *output;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  FILE *f;
+  int Noutput;
+
+  Noutput = catalog[0].Naverage;
+  ALLOCATE (output, Getstar_PS1_DEV_0, Noutput);
+
+  // photcode is a global
+  if (photcode == NULL) {
+    fprintf (stderr, "undefined photcode\n");
+    exit (2);
+  }
+
+  Nsec_c0 = GetPhotcodeNsec (photcode[0].code);
+  Nsec_c1 = GetPhotcodeNsec (photcode[0].c1);
+  Nsec_c2 = GetPhotcodeNsec (photcode[0].c2);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  code_c0 = photcode[0].code;
+  code_c1 = photcode[0].c1;
+  code_c2 = photcode[0].c2;
+  measure = catalog[0].measure;
+  average = catalog[0].average;
+  secfilt = catalog[0].secfilt;
+
+  // do we skip any of catalog entries? (probably not)
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    
+    output[i].R        = average[i].R;
+    output[i].D        = average[i].D;
+
+    output[i].code     = average[i].code;
+    output[i].photcode = code_c0;
+
+    // It is not necessary for the output magnitude or color terms to be average values.
+    // If they are, we grab them quickly & easily from the secfilt table.  If not, then we
+    // need to scan the list of measures to find the value of interest
+
+    // find primary magnitude
+    if (Nsec_c0 != -1) {
+      output[i].mag = secfilt[i*Nsecfilt + Nsec_c0].M;
+    } else {
+      output[i].mag = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c0) {
+          output[i].mag = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+
+    // find color term 1
+    if (Nsec_c1 != -1) {
+      output[i].c1 = secfilt[i*Nsecfilt + Nsec_c1].M;
+    } else {
+      output[i].c1 = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c1) {
+          output[i].c1 = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+
+    // find color term 2
+    if (Nsec_c2 != -1) {
+      output[i].c2 = secfilt[i*Nsecfilt + Nsec_c2].M;
+    } else {
+      output[i].c2 = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c2) {
+          output[i].c2 = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+  }
+
+  // open file for output
+  f = fopen (OUTPUT, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", OUTPUT);
+    exit (1);
+  }
+
+  // create primary header
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_Getstar_PS1_DEV_0 (&ftable, output, Noutput);
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_1.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_1.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_1.c	(revision 16632)
@@ -0,0 +1,125 @@
+# include "getstar.h"
+
+// convert the average/secfilt values to getstar format 
+// PS1_DEV_1 has no errors, only positions, motions and magnitudes
+int write_getstar_PS1_DEV_1 (Catalog *catalog) {    
+
+  int i, m, offset;
+  int Nsec_c0, Nsec_c1, Nsec_c2, Nsecfilt;
+  int code_c0, code_c1, code_c2;
+  Average *average;
+  Measure *measure;
+  SecFilt *secfilt;
+  Getstar_PS1_DEV_1 *output;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  FILE *f;
+  int Noutput;
+
+  Noutput = catalog[0].Naverage;
+  ALLOCATE (output, Getstar_PS1_DEV_1, Noutput);
+
+  // photcode is a global
+  if (photcode == NULL) {
+    fprintf (stderr, "undefined photcode\n");
+    exit (2);
+  }
+
+  Nsec_c0 = GetPhotcodeNsec (photcode[0].code);
+  Nsec_c1 = GetPhotcodeNsec (photcode[0].c1);
+  Nsec_c2 = GetPhotcodeNsec (photcode[0].c2);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  code_c0 = photcode[0].code;
+  code_c1 = photcode[0].c1;
+  code_c2 = photcode[0].c2;
+  measure = catalog[0].measure;
+  average = catalog[0].average;
+  secfilt = catalog[0].secfilt;
+
+  // do we skip any of catalog entries? (probably not)
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    
+    output[i].R        = average[i].R;
+    output[i].D        = average[i].D;
+    output[i].uR       = average[i].uR;
+    output[i].uD       = average[i].uD;
+    output[i].P        = average[i].P;
+
+    output[i].code     = average[i].code;
+    output[i].photcode = code_c0;
+
+    // It is not necessary for the output color terms to be average values.  If they are,
+    // we grab them quickly & easily from the secfilt table.  If not, then we need to scan
+    // the list of measures to find the value of interest
+
+    // find primary magnitude
+    if (Nsec_c0 != -1) {
+      output[i].mag = secfilt[i*Nsecfilt + Nsec_c0].M;
+    } else {
+      output[i].mag = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c0) {
+          output[i].mag = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+
+    // find color term 1
+    if (Nsec_c1 != -1) {
+      output[i].c1 = secfilt[i*Nsecfilt + Nsec_c1].M;
+    } else {
+      output[i].c1 = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c1) {
+          output[i].c1 = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+
+    // find color term 2
+    if (Nsec_c2 != -1) {
+      output[i].c2 = secfilt[i*Nsecfilt + Nsec_c2].M;
+    } else {
+      output[i].c2 = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c2) {
+          output[i].c2 = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+  }
+
+  // open file for output
+  f = fopen (OUTPUT, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", OUTPUT);
+    exit (1);
+  }
+
+  // create primary header
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_Getstar_PS1_DEV_1 (&ftable, output, Noutput);
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/getstar/src/write_getstar_ps1_dev_2.c	(revision 16632)
@@ -0,0 +1,131 @@
+# include "getstar.h"
+
+// convert the average/secfilt values to getstar format 
+int write_getstar_PS1_DEV_2 (Catalog *catalog) {    
+
+  int i, m, offset;
+  int Nsec_c0, Nsec_c1, Nsec_c2, Nsecfilt;
+  int code_c0, code_c1, code_c2;
+  Average *average;
+  Measure *measure;
+  SecFilt *secfilt;
+  Getstar_PS1_DEV_2 *output;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  FILE *f;
+  int Noutput;
+
+  Noutput = catalog[0].Naverage;
+  ALLOCATE (output, Getstar_PS1_DEV_2, Noutput);
+
+  // photcode is a global
+  if (photcode == NULL) {
+    fprintf (stderr, "undefined photcode\n");
+    exit (2);
+  }
+
+  Nsec_c0 = GetPhotcodeNsec (photcode[0].code);
+  Nsec_c1 = GetPhotcodeNsec (photcode[0].c1);
+  Nsec_c2 = GetPhotcodeNsec (photcode[0].c2);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  code_c0 = photcode[0].code;
+  code_c1 = photcode[0].c1;
+  code_c2 = photcode[0].c2;
+  measure = catalog[0].measure;
+  average = catalog[0].average;
+  secfilt = catalog[0].secfilt;
+
+  // do we skip any of catalog entries? (probably not)
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    
+    output[i].R        = average[i].R;
+    output[i].D        = average[i].D;
+    output[i].dR       = average[i].dR;
+    output[i].dD       = average[i].dD;
+
+    output[i].uR       = average[i].uR;
+    output[i].uD       = average[i].uD;
+    output[i].duR      = average[i].duR;
+    output[i].duD      = average[i].duD;
+
+    output[i].P        = average[i].P;
+    output[i].dP       = average[i].dP;
+
+    output[i].code     = average[i].code;
+    output[i].photcode = code_c0;
+
+    // It is not necessary for the output color terms to be average values.  If they are,
+    // we grab them quickly & easily from the secfilt table.  If not, then we need to scan
+    // the list of measures to find the value of interest
+
+    // find primary magnitude
+    if (Nsec_c0 != -1) {
+      output[i].mag = secfilt[i*Nsecfilt + Nsec_c0].M;
+    } else {
+      output[i].mag = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c0) {
+          output[i].mag = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+
+    // find color term 1
+    if (Nsec_c1 != -1) {
+      output[i].c1 = secfilt[i*Nsecfilt + Nsec_c1].M;
+    } else {
+      output[i].c1 = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c1) {
+          output[i].c1 = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+
+    // find color term 2
+    if (Nsec_c2 != -1) {
+      output[i].c2 = secfilt[i*Nsecfilt + Nsec_c2].M;
+    } else {
+      output[i].c2 = NAN;
+      offset = average[i].offset;
+      for (m = 0; m < average[i].Nm; m++) {
+        if (measure[offset + m].photcode == code_c2) {
+          output[i].c2 = PhotRel (&measure[offset + m], &average[i], &secfilt[i*Nsecfilt]);
+	  break;
+        }
+      }
+    }
+  }
+
+  // open file for output
+  f = fopen (OUTPUT, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", OUTPUT);
+    exit (1);
+  }
+
+  // create primary header
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_Getstar_PS1_DEV_2 (&ftable, output, Noutput);
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/Makefile	(revision 16632)
@@ -0,0 +1,46 @@
+default: gophot
+help:
+	@echo "make options: gophot (default)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/gophot
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+gophot: $(BIN)/gophot.$(ARCH)
+install: $(DESTBIN)/gophot
+
+GOPHOT = \
+$(SRC)/gophot.$(ARCH).o 	$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/message.$(ARCH).o	$(SRC)/dophot.$(ARCH).o \
+$(SRC)/makenoise.$(ARCH).o      $(SRC)/findsky.$(ARCH).o \
+$(SRC)/makemask.$(ARCH).o       $(SRC)/paravg.$(ARCH).o \
+$(SRC)/objout.$(ARCH).o         $(SRC)/addstar.$(ARCH).o \
+$(SRC)/ellipse.$(ARCH).o        $(SRC)/improve.$(ARCH).o \
+$(SRC)/fillerup.$(ARCH).o       $(SRC)/parinterp.$(ARCH).o \
+$(SRC)/guess.$(ARCH).o          $(SRC)/offpic.$(ARCH).o \
+$(SRC)/addlims.$(ARCH).o        $(SRC)/parupd.$(ARCH).o \
+$(SRC)/toofaint.$(ARCH).o       $(SRC)/isearch.$(ARCH).o \
+$(SRC)/shape.$(ARCH).o          $(SRC)/galaxy.$(ARCH).o \
+$(SRC)/transmask.$(ARCH).o      $(SRC)/cosmic.$(ARCH).o \
+$(SRC)/impaper2.$(ARCH).o       \
+$(SRC)/oblit.$(ARCH).o          $(SRC)/toobright.$(ARCH).o \
+$(SRC)/Chisq.$(ARCH).o          $(SRC)/oblims.$(ARCH).o \
+$(SRC)/ludcmp.$(ARCH).o         $(SRC)/lubksb.$(ARCH).o \
+$(SRC)/pseud2d.$(ARCH).o        $(SRC)/twofit.$(ARCH).o \
+$(SRC)/skyfun_plane.$(ARCH).o   $(SRC)/pseud4d.$(ARCH).o \
+$(SRC)/large_features.$(ARCH).o $(SRC)/set_thresholds.$(ARCH).o \
+$(SRC)/outline.$(ARCH).o        $(SRC)/delete_ellipse.$(ARCH).o \
+$(SRC)/feature_fluxes.$(ARCH).o $(SRC)/mediansky.$(ARCH).o
+
+$(GOPHOT): $(INC)/gophot.h $(INC)/prototypes.h
+$(BIN)/gophot.$(ARCH): $(GOPHOT)
Index: /branches/eam_branch_20080223/Ohana/src/gophot/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/gophot/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,4 @@
+
+- gophot-1-2 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+  * cleaned up Makefile, -Wall compilation errors
Index: /branches/eam_branch_20080223/Ohana/src/gophot/doc/Notes
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/doc/Notes	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/doc/Notes	(revision 16632)
@@ -0,0 +1,150 @@
+
+2005.10.20 : gophot v1.1
+
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+Old Notes
+
+Converting dophot to C: (I use dophot.f and dophot.c to refer to the
+fortran and C versions of dophot).
+
+some rules and goals for the first pass:
+
+1) I am maintaining the fortran dophot variable names as much as
+   possible, at least for now. 
+
+2) I am avoiding making proceedural changes / method changes, but I am
+willing to make minor modifications of things like looping strategies
+and if-statement order to clean the code a bit.
+
+3) I have placed all of the common-block variables in a single include
+file, gophot.h, with some attempt to define the names.  I've also placed the
+image data and noise matricies in gophot.h, along with nfast, nslow,
+so these are not passed endlessly back and forth among functions.
+
+4) My (sort-of) working fortran f2c dophot used an external loop,
+getfits.c which enclosed dophot.f and performed the image loading,
+big matrix allocation stuff.  I have renamed that gophot.c and cleaned
+it somewhat.  
+
+5) The biggest structural change so far is the infamous tuneup.f.  I
+have replaced it with my own ConfigInit function, based on my ohana
+config functions.  These have a much cleaner syntax for reading
+configuration values.  I have also placed the ConfigInit function much
+earlier, in gophot.c at the very beginning.  this means that config
+values can be overridden by image header values, if the fits_scan
+lines are coded.  currently, itop is read from the header (SATVALUE).
+
+For the moment, I am only making those changes needed to get a working
+dophot version, not a complete version.  Thus, I am skipping:
+warmstart, autothresh, median sky, hubble sky. 
+
+some function with significant adjustments, other than getfits.c and
+tuneup.f:
+
+message.c: actually this didn't exist in dophot.f - I have created a
+function mprint, which conditionally prints a message based on the
+verbosity level and an associated threshold.  the verbosity is
+registered with set_verbosity (level) and is stored static in
+message.c (not visible to the rest of dophot.c).  the prototype is:
+mprint (int level, char format, ...), with a format and argument
+syntax identical to printf.  all messages go to stderr, for now.
+
+makenoise.c: I am using pointers to do the loops. this should speed
+life alot.
+
+findsky.c: a new addition of mine to determine skyvalue from median of
+image.  this is implemented in the most recent dophot.f, but only
+since March 2000.
+
+There are some typical coding structures in the fortran that I am
+changing to make more legible:
+
+1) a = a + 1, a = a + b --> I'm using C inc args: a++, a+=b
+
+2) nested logic:
+
+{ /* some block */
+
+ code, code, code;
+
+ if (condition) then 
+
+   big block;
+
+ endif
+
+} /* end block */  
+
+there are many of these structures which conditionally perform a large
+operation, and otherwise do nothing or almost nothing.  I'm inverting
+these like this:
+
+{ /* some block */
+
+ code, code, code;
+
+ if (!condition) continue
+
+ big block;
+
+} /* end block */  
+
+data hard.soft.mat 
+read m1 4 m2 15
+set dm = m1 - m2
+lim -17 -7 -1 1; clear; box; plot m1 dm
+
+I have been making some significant changes to the dophot strategy for
+finding stars.  The goal is to handle saturated stars more
+effectively.  The strategy should not really change for faint stars.
+There are a few problems with the old strategy.  
+
+First, we were using an image array and a noise array.  To inhibit
+finding fake stars in the wings of bright stars, the noise array was
+enhanced when the stars were subtracted.  But for each loop, we were
+fitting and re-fitting each star several times.  As a result, we were
+adding, subtracting, adding, and subtracting the noise, which was of
+the order Nstar^2, many times.  Round off errors eventually made the
+noise array useless in the vicinity of bright stars.  Second, bright
+stars likely have many bad pixels, either low from sagging counts at
+or near saturation or high from bleeding.  Since these all have quite
+high flux, they highly discrepant points drive the fits
+significantly.  Finally, the initial guess location used the peak of
+the flux in a box around the trigger pixel.  This was problematic for
+bright stars because bleeding and saturation meant the peak was
+frequently far from the centroid.  I am addressing each of these
+problems separately.
+
+First, for the fits, we are now softening the errors by the residual
+from the initial guess fit.  This is a fitting method called 'robust
+fitting', and it allows significantly discrepant points to be part of
+the data without dominating or driving the fit to funny places.  This
+means the saturated stars are less biased by the few pixels in the
+core which are saturated and discrepant from the fit for the other
+pixels.
+
+Second, for the noise problem, I have made several related changes.
+First, I am now converting the image from DN to electrons (and
+re-scaling all relevant parameters to match).  This means the Poisson
+noise in the original image is now simply sqrt(Ncts).  I am putting
+only the square of the read noise in the noise array.  When I subtract
+a star, I move the counts from the image array to the noise array.
+Thus, the noise per pixel is always (Icts + Ncts) [where Icts = image
+array counts and Ncts = noise array counts] before or after the star
+subtraction.  I now have two tests for bump significance:  1) the
+signal-to-noise must be above a threshold: 
+
+sq(sum[image-sky]) > sum[noise + image] * ratio
+
+and the image counts must be significant:
+
+sub[image-sky] > sum[noise - readnoise^2] * ratio
+
+Finally, the initial guess will use a centroid in fillerup if the flux
+is high enough.
+
+
+
+
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/include/fit.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/include/fit.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/include/fit.h	(revision 16632)
@@ -0,0 +1,27 @@
+
+# ifndef ALLOCATE
+# define ALLOCATE(X,T,S)  \
+  X=(T *)malloc((unsigned) (MAX(((S)*sizeof(T)),1)));\
+  if(X==NULL) \
+    { \
+      fprintf(stderr,"failed to malloc X\n");\
+        exit (10);\
+    } 
+# define REALLOCATE(X,T,S) \
+  X=(T *)realloc(X,(unsigned) (MAX(((S)*sizeof(T)),1))); \
+  if(X==NULL) \
+    { \
+       fprintf(stderr,"failed to realloc X\n"); \
+       exit (10); \
+    }
+# endif /* ALLOCATE */
+
+float mrq2dinit (int *, int *, float *, float *, int, float *, int, float (funcs)(int *, int *, float *, float *)); 
+float mrq2dmin (int *, int *, float *, float *, int, float *, int, float (funcs)(int *, int *, float *, float *)); 
+float **mrq2dcovar (int);
+
+# define NPARS 8
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/include/gophot.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/include/gophot.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/include/gophot.h	(revision 16632)
@@ -0,0 +1,129 @@
+/* includes */
+
+# include <ohana.h>
+# include <gfitsio.h>
+
+typedef char bool;
+
+# define TRUE (1)
+# define FALSE (0)
+# define SIGN(X)  (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+# define ROUND(X) ((int) ((X) + 0.5*SIGN(X)))
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
+
+/* constants */
+
+# define NRMAX 1024 /* max Ny, deprecated */
+# define NCMAX 1024 /* max Nx, deprecated */
+
+# define CHIPAR 0.9 /* used by chisq.f */
+# define NSMAX 100000 /* max number of stars */
+# define NPMAX 8    /* max number of parameters */
+# define NPAR  8    /* max number of parameters used */
+# define NPSKY 8    /* max sky fit parameters */
+# define NSKYFIT 3  /* max sky fit parameters used */
+# define NFF   20   /* max number of files / flags */
+# define NAPPLE 5   /* number of aper data somethings? */
+# define NAPMAX 30  /* number of correction apertures in file? */
+# define NFIT0  2   /* N par in fit 0 */
+# define NFIT1  4   /* N par in fit 1 */
+# define NFIT2  7   /* N par in fit 2 */
+# define NFIT3  8   /* N par in fit 3 */
+
+# define MAXFIL 5000 /* max size of subraster vector */
+# define NMASK 17    /* max mask size */
+# define MAGIC HUGE_VAL  /* sentinel for bad pixels */
+/* # define MAGICSET 2e30 old value for sentinel */
+
+# define ADD +1
+# define SUB -1
+
+/* global variables */
+
+/* int   lverb;     * verbosity - no longer global */
+float chipar;       /* unknown chisq scale factor */
+float ufactor;      /* star scaling factor */
+
+/* float b[2*NPMAX];   * two-star fit array */
+/* float fb[2*NPMAX];  * two-star fit error array */
+
+bool test7; 
+bool needit;        /* deprecated? */
+
+int xs[MAXFIL], ys[MAXFIL], nrect[3];        /* subraster vectors */
+float zs[MAXFIL], dzs[MAXFIL];   /* subraster vectors */
+float ts[MAXFIL];
+
+float starmask[NMASK][NMASK];
+float parms[NPMAX];
+
+/* float a[NPMAX], fa[NPMAX], c[NPMAX][NPMAX];  fit param arrays */
+float chiimp, apertime, filltime, addtime;   /* deprecated? */
+
+float sum0, sum1, sum2, maxval, xmax, ymax, xmax2, ymax2;  /* crude star statistics */
+int   npt;
+
+float chi[5]; /* almost deprecated, but still in galaxy & shape */
+
+/* tuneup parameters */
+
+enum {NONE1, PGAUSS};
+enum {NONE2, PLANE, HUBBLE, MEDIAN};
+enum {NONE3, COMPLETE, INCOMPLETE, INTERNAL, OLDSTYLE};
+
+char flags[NFF];
+char files[64][NFF];
+bool fixpos;
+
+float  skyguess, tmin, tmax, tfac;
+float  fac, xpnd, ctpersat, widobl, cmax;
+float  stograt, discrim, sig[4], arect[3];
+float  chicrit, xtra, crit7, snlim, bumpcrit, sn2cos;
+float  enuff4, enuff7;
+float  eperdn, rnoise;
+float  acc[NPMAX], parlim[NPMAX], ava[NPMAX];
+float  beta4, beta64;
+float  pixthresh;
+float  apmagmaxerr;
+float  nphsub, nphob, apmax, apskymin, apskymax, aperrmax;
+
+int irect[3], krect[3], ibot, itop, nit, grect[3];
+int icrit, ixby2, iyby2;
+int n0left, n0right, nthpix, nbadleft, nbadright, nbadtop, nbadbot;
+int jhxwid, jhywid, mprec, napertures;
+      
+/* image data */
+float *big, *noise;
+int nfast, nslow;   /* NAXIS1, NAXIS2 of image */
+
+/* star data */
+float starpar[NSMAX][NPMAX];
+float galpar[NSMAX][NPMAX];
+float shadow[NSMAX][NPMAX];
+float shaderr[NSMAX][NPMAX];
+float apple[NSMAX][NAPPLE];
+int   imtype[NSMAX];
+int   nstot;
+float thresh;
+float probgal[NSMAX]; /* deprecated */
+float rchisq[NSMAX]; /* deprecated */
+bool  fixxy;
+
+int nregion;
+float region[100][8];
+
+/* sky data */
+float skypar[NPSKY];
+
+/* image data */
+Header header;
+Matrix matrix;
+
+float (*onestar)(int, int, float *, float *);
+float (*twostar)(int, int, float *, float *);
+float (*skyfun)(int, int, float *, float *);
+
+# include "prototypes.h"
Index: /branches/eam_branch_20080223/Ohana/src/gophot/include/prototypes.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/include/prototypes.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/include/prototypes.h	(revision 16632)
@@ -0,0 +1,46 @@
+float pseud2d (int ix, int iy, float *a, float *fa);
+float pseud4d (int ix, int iy, float *a, float *fa);
+float skyfun_plane (int ix, int iy, float *a, float *fa);
+float chisq (float (function)(int, int, float *, float *), int *, int *, float *, float *, int, float *, float*, int, float *, float *, int);
+int ConfigInit (int *argc, char **argv);
+int addlims (float *star, int *jrect);
+int addstar (float *instar, int iadd, int type);
+char *SelectConfigFile (int *argc, char **argv, char *progname);
+char *LoadConfigFile (char *filename);
+char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...);
+char *expandline (char *line, char *config);
+bool cosmic (float *star);
+int dophot ();
+int ellipse (float, float, float, float *, float *, float *, float *);
+int errupd (float *, int);
+int fillerup (int, int, int);
+float findsky ();
+bool galaxy (float *, float *, float *);
+float guess1 (float *, float *, int, int);
+float guess2 (float *, float *, int *, int *);
+float guess3 (float *, float *, int *, int *);
+int impaper2 (int);
+int improve (int);
+int isearch ();
+void lubksb (float **, int, int *, float *);
+void ludcmp (float **, int, int *, float *);
+int makemask ();
+int makenoise ();
+int mprint (int, char *, ...);
+int set_verbosity (int);
+int completeout ();
+int oblims (float *, int *);
+bool oblit (float *);
+bool oblit (float *);
+int paravg ();
+float parinterp (float, float, float *);
+int parupd (float *, float *, int, int);
+int shape ();
+int sort (float *, int);
+bool toobright (float *);
+bool toofaint (float *, float *);
+bool transmask (int, int, float);
+float twofit (float *, float *, float *, float *);
+int variparplane ();
+bool offpic (float *, int, int, float *, float *);
+float newguess (float *, float *, int, int);
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/Chisq.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/Chisq.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/Chisq.c	(revision 16632)
@@ -0,0 +1,202 @@
+# include "gophot.h"
+
+float chisq (function, ix, iy, z, dz, npts, pars, dpars, npars, Acc, Parlim, niter) 
+     float (function)(int, int, float *, float *);
+     int *ix;
+     int *iy;
+     float *z, *dz;
+     float *pars, *dpars, *Acc, *Parlim;
+     int npts, npars, niter;
+{
+
+  float **covmatr, **tmpmatr;
+  float *v, *tmpvec, *fpars;
+  int *indx;
+  bool conv, marq, limit, islimit;
+  int i, j, k, jj, kk;
+  float ifact, fact, chinew, chiold, f, dz1, fakk, d, tmpval, value;
+  float perdeg, save;
+
+  if (npars >= NPMAX) return (MAGIC);
+
+  ALLOCATE (v, float, npars);
+  ALLOCATE (indx, int, npars);
+  ALLOCATE (fpars, float, NPMAX);
+  ALLOCATE (tmpvec, float, npars);
+  ALLOCATE (covmatr, float *, npars);
+  ALLOCATE (tmpmatr, float *, npars);
+  for (i = 0; i < npars; i++) {
+    ALLOCATE (covmatr[i], float, npars);
+    ALLOCATE (tmpmatr[i], float, npars + 1);
+  }
+
+  conv = FALSE;
+  limit = FALSE;
+
+  /* check if parameters exceeds limits at the start. */
+  for (j = 0; j < npars; j++) {
+    if (Parlim[j] < 0.0) {
+      limit = fabs(pars[j]) > fabs(Parlim[j]);
+      if (limit) mprint (4, "self-deception has occured: initial limits\n");
+    }
+  }
+
+  /*
+  for (j = 0; j < npars; j++) {
+    mprint (3, "%d %f %f\n", j, pars[j], fpars[j]);
+  }
+  */
+
+  ifact = 0;
+
+  for (i = 0; (i < niter) && !conv && !limit; i++) {
+    chinew = 0.0;
+    for (j = 0; j < npars; j++) {
+      for (kk = 0; kk < npars + 1; kk++) {
+	tmpmatr[j][kk] = 0;
+      }
+    }
+
+    for (j = 0; j < npts; j++) {
+      f = function (ix[j], iy[j], pars, fpars) - z[j];
+      /* fprintf (stderr, "%d  %d %d  %f %f %f\n", j, ix[j], iy[j], f, z[j], dz[j]); */
+      dz1 = 1.0 / dz[j];
+      chinew += SQ(f)*dz1;
+      for (kk = 0; kk < npars; kk++) {
+	if (fabs(fpars[kk]) > 1e-12) {
+	  fakk = fpars[kk]*dz1;
+	  tmpmatr[kk][npars] += fakk*f;
+	  for (jj = 0; jj <= kk; jj++) {
+	    if (fabs(fpars[kk]) > 1e-12) tmpmatr[kk][jj] += fakk*fpars[jj];	
+	  }
+	}
+      }
+    } 
+
+    chiold = chinew;
+    marq = FALSE;
+    for (k = 1; (k <= 10) && !marq && !limit; k++) {
+      conv = (k == 1);
+      fact = (k == 1) ? 0.0 : pow (2.0, ifact);
+      for (j = 0; j < npars; j++) {
+	for (jj = 0; jj < j; jj++) {
+	  covmatr[j][jj] = tmpmatr[j][jj];
+	  covmatr[jj][j] = tmpmatr[j][jj];
+	}
+	covmatr[j][j] = (1+fact)*tmpmatr[j][j];
+	v[j] = tmpmatr[j][npars];
+      }
+      ludcmp (covmatr, npars, indx, &d);
+
+      /* if d = 0, the matrix was singular; no convergence. */
+      if (d == 0) {
+	mprint (4, "singular matrix!\n");
+	/* need to free arrays */
+	return (MAGIC);
+      }
+      lubksb (covmatr, npars, indx, v);
+
+      /* 
+	 check if change in parameters exceeds limits.  if Parlim(j) > 0, then
+	 consider fractional changes.  if Parlim(j) < 0, consider absolute
+	 changes.  if Parlim(j) = 0, ignore this test.
+      */
+      for (j = 0; j < npars; j++) {
+	pars[j] -= chipar*v[j];
+	if (Parlim[j] > 0.0) {
+	  tmpval = fabs (v[j]/pars[j]);
+	  islimit = (tmpval > Parlim[j]);
+	  limit = limit || islimit;
+	  if (islimit) mprint (4, "self-deception has occured: frac limits: %d  %f %f %f\n", j, pars[j], v[j], Parlim[j]);
+	}
+	if (Parlim[j] < 0.0) {
+	  islimit = (fabs (pars[j]) > fabs (Parlim[j]));
+	  limit = limit || islimit;
+	  if (islimit) mprint (4, "self-deception has occured: abs limits: %d  %f %f %f\n", j, pars[j], v[j], Parlim[j]);
+	}
+	/* check convergence */
+	if (Acc[j] > 0) {
+	  tmpval = fabs (v[j]/pars[j]);
+	  conv = conv && (tmpval <= Acc[j]);
+	} else {
+	  conv = conv && (fabs (v[j]) <= fabs (Acc[j]));
+	}
+      }
+
+      if (conv) {
+	marq = TRUE;
+      } else {
+	if (!limit) {
+	  chinew = 0.0;
+	  for (j = 0; j < npts; j++) {
+	    f = function(ix[j], iy[j], pars, (float *) NULL) - z[j];
+	    chinew += SQ(f)/dz[j];
+	  }
+	  if (k == 2) ifact --;
+	  if (chinew < 1.0001*chiold) {
+	    marq = TRUE;
+	  } else {
+	    if (k == 2) ifact += 2;
+	    if (k > 2)  ifact ++;
+	    if (ifact > 10) goto escape;
+	    for (j = 0; j < npars; j++) pars[j] += chipar*v[j];
+	  }
+	}
+      }
+
+      mprint (4, "%d, %d, ", i, k);
+      for (kk = 0; kk < npars; kk++) mprint (4, "%f ", pars[kk]);
+      mprint (4, "  %f\n", chinew);
+
+    }
+  }
+  escape:
+      
+  if (!limit) {
+    for (j = 0; j < npars; j++) {
+      for (i = 0; i < npars; i++) tmpvec[i] = 0;
+      tmpvec[j] = 1;
+      lubksb (covmatr, npars, indx, tmpvec);
+      for (i = 0; i < npars; i++) tmpmatr[i][j] = tmpvec[i];
+    }
+  }
+      
+  if (conv && !limit) {
+    perdeg = sqrt (chinew / MAX (npts - npars, 1));
+    for (i = 0; i < npars; i++) {
+      if (tmpmatr[i][i] > 0) {
+	save = sqrt (tmpmatr[i][i]);
+      } else {
+	mprint (4, "trouble: negative autovariance for tmpmatr[%d][%d] = %f\n", i, i, tmpmatr[i][i]);
+	save = 1e10;
+      }
+      for (j = 0; j < npars; j++) {
+	covmatr[i][j] = tmpmatr[i][j]/save;
+	covmatr[j][i] = tmpmatr[j][i]/save;
+      }
+      covmatr[i][i] = save*perdeg;
+    }
+    value = chiold;
+  } else {
+    value = MAGIC;
+  }
+  
+  for (i = 0; i < npars; i++) dpars[i] = SQ(covmatr[i][i]);
+
+  for (kk = 0; kk < npars; kk++) mprint (4, "%f ", pars[kk]);
+  mprint (4, "     %f\n", chiold);
+  
+  for (i = 0; i < npars; i++) {
+    free (covmatr[i]);
+    free (tmpmatr[i]);
+  }
+  free (v);
+  free (indx);
+  free (fpars);
+  free (tmpvec);
+  free (covmatr);
+  free (tmpmatr);
+
+  return (value);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,265 @@
+# include "gophot.h"
+
+# define TestConfig(A,B,C,D,E) { if (!ScanConfig (A,B,C,D,E)) { fprintf (stderr, B); exit (1); }}
+
+int ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  float fwhm, ar, tilt;
+  char line[128];
+  int level;
+  float gmajwid, gxwid, gywid, fwhmx, fwhmy;
+  float scalefb, fbmin, scaleab, abmin, scalemb, ambmin;
+
+  /*** load configuration info ***/
+  file = argv[3];
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find configuration file %s\n", file);
+    exit (0);
+  }
+
+  set_verbosity (0);  /* initializes function data */
+
+  /* flags -- OK for now, not really used much */
+  flags[1] =  PGAUSS;  /* psf type */
+  flags[2] =  NONE2;   /* sky type */
+  flags[3] =  NONE3;   /* objtype_out */
+  flags[4] =  FALSE;   /* output shadow file? */
+  flags[5] =  FALSE;   /* image out? */
+  flags[6] =  FALSE;   /* warmstart? */
+  flags[7] =  FALSE;   /* load input shadow file? */
+  flags[8] =  FALSE;   /* objtype_in */
+  flags[10] = FALSE;   /* aperture correction file? */
+
+  onestar = pseud2d;
+  twostar = pseud4d;
+  skyfun  = skyfun_plane;
+
+  /* files:
+     files[2] - image_out 
+     files[3] - objects_in      - UNUSED
+     files[5] - shadowfile_out  - UNUSED
+     files[7] - shadowfile_in   - UNUSED
+     files[6] - logfile         - UNUSED
+     files[8] - apcorrfile      - UNUSED
+  */
+  
+  /** legacy - delete? */
+  n0left = 0;
+  n0right = 0;
+  nthpix = 0;
+
+  TestConfig (config, "FWHM",                   "%f", 0,    &fwhm);               /* Approx FWHM of objects (pixels) along major axis. */
+  TestConfig (config, "AXIS_RATIO",             "%f", 0,    &ar);                 /* For star objects.  AR=b/a; b=minor axis. */
+  TestConfig (config, "TILT",                   "%f", 0,    &tilt);               /* Angle of major axis in degrees; +x=0; +y=90. */
+  TestConfig (config, "SKY",                    "%f", 0,    &skyguess);           /* Approximate mean sky value in data numbers. */
+
+  /* convert to internal values */
+  fwhm *= 1.2; /* is this really necessary? */
+  tilt = tilt/57.29578;
+  gmajwid = SQ(fwhm/2.3548);
+  gxwid = gmajwid*(SQ(cos(tilt)) + SQ(ar*sin(tilt)));
+  gywid = gmajwid*(SQ(ar*cos(tilt)) + SQ(sin(tilt)));
+  fwhmx = 2.3548*sqrt(gxwid);
+  fwhmy = 2.3548*sqrt(gywid);
+  mprint (1, "fwhm x & y: %f, %f\n", fwhmx, fwhmy);
+
+  /* no longer use ava[0-3] */
+  ava[4] = gxwid;
+  ava[6] = gywid;
+  ava[5] = 0.01/sqrt(gxwid*gywid);
+  
+  TestConfig (config, "NFITBOX_X",              "%d", 0,    &irect[1]);           /* Size of fit box in the x-direction. */
+  TestConfig (config, "NFITBOX_Y",              "%d", 0,    &irect[2]);           /* Size of fit box in the y-direction. */
+  TestConfig (config, "MASKBOX_X",              "%d", 0,    &ixby2);              /* Size of mask box size in x. */
+  TestConfig (config, "MASKBOX_Y",              "%d", 0,    &iyby2);              /* Size of mask box size in y. */
+  TestConfig (config, "APBOX_X",                "%f", 0,    &arect[1]);           /* Size of aperture photometry box in x. */
+  TestConfig (config, "APBOX_Y",                "%f", 0,    &arect[2]);           /* Size of aperture photometry box in y. */
+  TestConfig (config, "NGALBOX_X",              "%d", 0,    &grect[1]);           /* Size of fit box in the x-direction. */
+  TestConfig (config, "NGALBOX_Y",              "%d", 0,    &grect[2]);           /* Size of fit box in the y-direction. */
+
+  TestConfig (config, "IBOTTOM",                "%d", 0,    &ibot);               /* Lowest allowed data value in data numbers. */
+  TestConfig (config, "ITOP",                   "%d", 0,    &itop);               /* Level where Saturation begins. */
+  TestConfig (config, "THRESHMIN",              "%f", 0,    &tmin);               /* Sigmas above sky for min threshold */
+  TestConfig (config, "THRESHMAX",              "%f", 0,    &tmax);               /* Value of maximum threshold. */
+  TestConfig (config, "THRESHDEC",              "%f", 0,    &tfac);               /* Threshold decrement in powers-of-2. */
+  TestConfig (config, "EPERDN",                 "%f", 0,    &eperdn);             /* Electrons per data number. */
+  TestConfig (config, "RDNOISE",                "%f", 0,    &rnoise);             /* Readout noise in electrons. */
+  rnoise = SQ (rnoise);  /* we will store SQ(rnoise) since this is always needed */
+
+  /* I don't like AUTOSCALE because it is not dynamic - 
+     it sets the values once here for the run, so FWHM better be right */
+  TestConfig (config, "AUTOSCALE",              "%s", 0,    line);                /* Auto-scaling of sizes by FWHM. */
+  if (!strncasecmp (line, "y", 1)) {
+    ScanConfig (config, "SCALEFITBOX",          "%f", 0,    &scalefb);          /* Size of fit box in units of FWHM. */
+    ScanConfig (config, "FITBOXMIN",            "%f", 0,    &fbmin);            /* Smallest allowed fit box size. */
+    ScanConfig (config, "SCALEAPBOX",           "%f", 0,    &scaleab);          /* Size of aperture phot box in units of FWHM. */
+    ScanConfig (config, "APBOXMIN",             "%f", 0,    &abmin);            /* Smallest allowed aperture phot box size. */
+    ScanConfig (config, "SCALEMASKBOX",         "%f", 0,    &scalemb);          /* Size of mask box in units of FWHM. */
+    ScanConfig (config, "AMASKBOXMIN",          "%f", 0,    &ambmin);           /* Smallest allowed mask box size. */
+    irect[1] = MAX (fwhmx*scalefb, fbmin);
+    irect[2] = MAX (fwhmy*scalefb, fbmin);
+    arect[1] = MAX (fwhmx*scaleab, abmin);
+    arect[2] = MAX (fwhmy*scaleab, abmin);
+    ixby2 = MAX(fwhmx*scalemb, ambmin);
+    ixby2 = MAX(fwhmy*scalemb, ambmin);
+  }
+  /* force boxes to have odd sizes */
+  if (((int)arect[1]) % 2 == 0) arect[1]++;
+  if (((int)arect[2]) % 2 == 0) arect[2]++;
+  if (irect[1] % 2 == 0) irect[1]++;
+  if (irect[2] % 2 == 0) irect[2]++;
+  if (ixby2 % 2 == 0) ixby2 ++;
+  if (iyby2 % 2 == 0) iyby2 ++;
+  ixby2 = (ixby2 - 1)/2;
+  iyby2 = (iyby2 - 1)/2;
+
+  fixpos = FALSE;
+  TestConfig (config, "FIXPOS", "%s", 0, line);                 /* Fix star positions? */
+  if (!strncasecmp (line, "y", 1)) fixpos = TRUE;
+
+  if (ScanConfig (config, "IMAGE_OUT", "%s", 0, files[2])) flags[5] = TRUE;    /* Output image name. */
+
+  TestConfig (config, "OBJTYPE_OUT", "%s", 0, &line);                /* Output format: (COMPLETE, INCOMPLETE, INTERNAL) */
+  if (!strcasecmp (line, "complete"))   flags[3] = COMPLETE;
+  if (!strcasecmp (line, "incomplete")) flags[3] = INCOMPLETE;
+  if (!strcasecmp (line, "internal"))   flags[3] = INTERNAL;
+  if (!strcasecmp (line, "oldstyle"))   flags[3] = OLDSTYLE;
+  if (flags[3] == NONE3) {
+    fprintf (stderr, "invalid OBJTYPE_OUT: %s\n", line);
+    exit (1);
+  }
+  
+  TestConfig (config, "LOGVERBOSITY",           "%d", 0,    &level);               /* Verbosity of log file; (0-4). */
+  set_verbosity (level);
+  TestConfig (config, "RESIDNOISE",             "%f", 0,    &fac);                 /* Fraction of noise to ADD to noise file. */
+  TestConfig (config, "FOOTPRINT_NOISE",        "%f", 0,    &xpnd);                /* Expand stars in noise file by this amount. */
+  TestConfig (config, "NPHSUB",                 "%f", 0,    &nphsub);              /* Limiting surface brightness for subtractions. */
+  TestConfig (config, "NPHOB",                  "%f", 0,    &nphob);               /* Limiting surface brightness for obliterations. */
+  TestConfig (config, "ICRIT",                  "%d", 0,    &icrit);               /* Obliterate if # of pixels > ITOP exceeds this. */
+  TestConfig (config, "CENTINTMAX",             "%f", 0,    &cmax);                /* Obliterate if central intensity exceeds this. */
+  TestConfig (config, "CTPERSAT",               "%f", 0,    &ctpersat);            /* Assumed intensity for saturated pixels. */
+
+  TestConfig (config, "STARGALKNOB",            "%f", 0,    &stograt);             /* Star/galaxy discriminator: bigger number, more stars */
+  TestConfig (config, "STARCOSKNOB",            "%f", 0,    &discrim);             /* Object/cosmic-ray discriminator: bigger number, more cosmics */
+  TestConfig (config, "SNLIM7",                 "%f", 0,    &crit7);               /* Minimum S/N for 7-parameter fit. */
+  crit7 = SQ(crit7);
+  TestConfig (config, "SNLIM",                  "%f", 0,    &snlim);               /* Minimum S/N for a pixel to be in fit subraster. */
+  TestConfig (config, "SNLIMMASK",              "%f", 0,    &bumpcrit);            /* Minimum S/N through mask to identify an object. */
+  TestConfig (config, "SNLIMCOS",               "%f", 0,    &sn2cos);              /* Minimum S/N to be called a cosmic ray. */
+  sn2cos = SQ(sn2cos);
+  TestConfig (config, "NBADLEFT",               "%d", 0,    &nbadleft);            /* Ignore pixels closer to the left edge than this. */
+  TestConfig (config, "NBADRIGHT",              "%d", 0,    &nbadright);           /* Ignore pixels closer to the right edge than this. */
+  TestConfig (config, "NBADTOP",                "%d", 0,    &nbadtop);             /* Ignore pixels closer to the top edge than this. */
+  TestConfig (config, "NBADBOT",                "%d", 0,    &nbadbot);             /* Ignore pixels closer to the bottom edge than this. */
+
+  TestConfig (config, "SKYTYPE",                "%s", 0,    line);                 /* SKY type: (PLANE, HUBBLE, MEDIAN) */
+  if (!strcasecmp (line, "plane")) flags[2] =  PLANE;
+  /* if (!strcasecmp (line, "hubble")) flags[2] = HUBBLE; */
+  /* if (!strcasecmp (line, "median")) flags[2] = MEDIAN; */
+  if (flags[2] == NONE2) {
+    fprintf (stderr, "invalid SKYTYPE: %s\n", line);
+    exit (1);
+  }
+
+  TestConfig (config, "NFITITER",               "%d", 0,    &nit);                 /* Maximum number of iterations. */
+  TestConfig (config, "NFITBOXFIRST_X",         "%d", 0,    &krect[1]);            /* Size of fit box in x for first pass. */
+  TestConfig (config, "NFITBOXFIRST_Y",         "%d", 0,    &krect[2]);            /* Size of fit box in y for first pass. */
+  TestConfig (config, "CHI2MINBIG",             "%f", 0,    &chicrit);             /* Critical CHI-squared for a large object. */
+  TestConfig (config, "XTRA",                   "%f", 0,    &xtra);                /* We need more S/N if some pixels are missing. */
+  TestConfig (config, "SIGMA1",                 "%f", 0,    &sig[1]);              /* Max. frac. scatter in sigma_x for stars. */
+  TestConfig (config, "SIGMA2",                 "%f", 0,    &sig[2]);              /* Max. scatter in xy cross term for stars. */
+  TestConfig (config, "SIGMA3",                 "%f", 0,    &sig[3]);              /* Max. frac. scatter in sigma_y for stars. */
+  TestConfig (config, "ENUFF4",                 "%f", 0,    &enuff4);              /* Fraction of pixels needed for 4-param fit. */
+  TestConfig (config, "ENUFF7",                 "%f", 0,    &enuff7);              /* Fraction of pixels needed for 7-param fit. */
+  TestConfig (config, "COSOBLSIZE",             "%f", 0,    &widobl);              /* Size of obliteration box for a cosmic ray. */
+  TestConfig (config, "APMAG_MAXERR",           "%f", 0,    &apmagmaxerr);         /* Max anticipated error for aperture phot report. */
+  TestConfig (config, "PIXTHRESH",              "%f", 0,    &pixthresh);           /* Trigger on pixels higher than noise*PIXTHRESH. */
+  TestConfig (config, "BETA4",                  "%f", 0,    &beta4);               /* R**4 coefficient modifier. */
+  TestConfig (config, "BETA6",                  "%f", 0,    &beta64);              /* R**6 coefficient modifier. */
+  beta4 = 1.0;
+  beta64 = 1.0;
+
+  TestConfig (config, "RELACC1",                "%f", 0,    &acc[0]);              /* Convergence criterion for sky. */
+  TestConfig (config, "RELACC2",                "%f", 0,    &acc[1]);              /* Convergence criterion for for central intensity. */
+  TestConfig (config, "RELACC3",                "%f", 0,    &acc[2]);              /* Convergence criterion for x-position. */
+  TestConfig (config, "RELACC4",                "%f", 0,    &acc[3]);              /* Convergence criterion for y-position. */
+  TestConfig (config, "RELACC5",                "%f", 0,    &acc[4]);              /* Convergence criterion for sigma-x. */
+  TestConfig (config, "RELACC6",                "%f", 0,    &acc[5]);              /* Convergence criterion for sigma-xy. */
+  TestConfig (config, "RELACC7",                "%f", 0,    &acc[6]);              /* Convergence criterion for sigma-y. */
+  TestConfig (config, "PARLIM1",                "%f", 0,    &parlim[0]);           /* Allowed change for sky value. */
+  TestConfig (config, "PARLIM2",                "%f", 0,    &parlim[1]);           /* Allowed change for central intensity. */
+  TestConfig (config, "PARLIM3",                "%f", 0,    &parlim[2]);           /* Allowed change for x-position. */
+  TestConfig (config, "PARLIM4",                "%f", 0,    &parlim[3]);           /* Allowed change for y-position. */
+  TestConfig (config, "PARLIM5",                "%f", 0,    &parlim[4]);           /* Allowed change for sigma-x. */
+  TestConfig (config, "PARLIM6",                "%f", 0,    &parlim[5]);           /* Allowed change for sigma-xy. */
+  TestConfig (config, "PARLIM7",                "%f", 0,    &parlim[6]);           /* Allowed change for sigma-y. */
+
+  /* other initial values for parameters */
+  needit = TRUE;
+  fixxy = FALSE;
+  test7 = FALSE;
+  ufactor = 100;
+  chipar = 0.9;
+
+  free (config);
+  /* free (file); */
+
+  return 1;
+}
+
+
+# if (0) /* things used by MEDIAN sky, disabled */
+  /* only if 'median' */
+  ScanConfig (config, "JHXWID",                 "%f", 0,    &jhxwid);                 /* X Half-size of median box (.le. 0 -> autoscale) */
+  ScanConfig (config, "JHYWID",                 "%f", 0,    &jhywid);                 /* Y (same as above) */
+  ScanConfig (config, "MPREC",                  "%f", 0,    &mprec);                 /* Median precision in DN (use .le. 0 for autocalc) */
+  ScanConfig (config, "NTHPIX",                 "%f", 0,    &nthpix);                 /* Frequency of sky updates in pixels for 1st pass */
+
+  /* log is now going to stderr, up to user to redirect */
+  ScanConfig (config, "LOGFILE",                "%s", 0,    &A);                 /* Log file name.  TERM for screen. */
+  ScanConfig (config, "IMAGE_IN",               "%s", 0,    &A);                 /* Input image name.  */
+  ScanConfig (config, "OBJECTS_OUT",            "%s", 0,    &A);                 /* Output object list file name. */
+  ScanConfig (config, "PARAMS_DEFAULT",         "%s", 0,    &A);                 /* Default parameters file name. */
+  ScanConfig (config, "PARAMS_OUT",             "%s", 0,    &A);                 /* Output parameters file name. */
+  ScanConfig (config, "SHADOWFILE_OUT",         "%s", 0,    &A);                 /* Output shadow file name. */
+  ScanConfig (config, "SHADOWFILE_IN",          "%s", 0,    &A);                 /* Input shadow file name. */
+  
+  ScanConfig (config, "ABSLIM1",                "%f", 0,    &A);                 /* Allowed range for sky value. */
+  ScanConfig (config, "ABSLIM2",                "%f", 0,    &A);                 /* Allowed range for central intensity. */
+  ScanConfig (config, "ABSLIM3",                "%f", 0,    &A);                 /* Allowed range for x-position. */
+  ScanConfig (config, "ABSLIM4",                "%f", 0,    &A);                 /* Allowed range for y-position. */
+  ScanConfig (config, "ABSLIM5",                "%f", 0,    &A);                 /* Allowed range for sigma-x. */
+  ScanConfig (config, "ABSLIM6",                "%f", 0,    &A);                 /* Allowed range for sigma-xy. */
+  ScanConfig (config, "ABSLIM7",                "%f", 0,    &A);                 /* Allowed range for sigma-y. */
+  ScanConfig (config, "ABSLIM8",                "%f", 0,    &A);                 /* Allowed range for sigma-y. */
+  
+  ScanConfig (config, "NPARAM",                 "%f", 0,    &A);                 /* Maximum number of PSF fit parameters. */
+  ScanConfig (config, "NFITMAG",                "%f", 0,    &A);                 /* No. of PSF parameters to get magnitudes. */
+  ScanConfig (config, "NFITSHAPE",              "%f", 0,    &A);                 /* No. of PSF parameters to get shape and mags. */
+  
+  ScanConfig (config, "MAXSTARS",               "%f", 0,    &A);                 /* Ignore pixels closer to the bottom edge than this. */
+  ScanConfig (config, "PSFTYPE",                "%s", 0,    &A);                 /* PSF type: (PGAUSS) */
+# endif
+
+# if (0) /* autothresh eliminated: we are using threshmin = Nsigma above sky always */
+  Autothresh = FALSE;
+  ScanConfig (config, "AUTOTHRESH",             "%s", 0,    line);                 /* Auto-scaling of thresholds. */
+  if (!strncasecmp (line, "y")) Autothresh = TRUE;
+  /* only if 'autothresh' */
+  ScanConfig (config, "SIGMAIBOTTOM",           "%f", 0,    &sigbot);                 /* Level of IBOTTOM below sky in units of noise. */
+  ScanConfig (config, "SIGMATHRESHMIN",         "%f", 0,    &sigthresh);                 /* Level of THRESHMIN above sky in units of noise. */
+# endif
+
+# if (0) /* warmstart code */  
+  status = ScanConfig (config, "OBJECTS_IN",             "%s", 0,    &A);                 /* Input object list file name. */
+  if (status) {
+    flags[6] = TRUE;
+    ScanConfig (config, "OBJTYPE_IN",             "%s", 0,    &A);                 /* Input format: (COMPLETE, INTERNAL) */
+  }
+# endif
+
+# if (0) /* aperture correction file - there are several other parameters, see tuneup.f */ 
+    ScanConfig (config, "APCORRFILE",             "%s", 0,    &A);                 /* Aperture correction file name. */
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/addlims.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/addlims.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/addlims.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "gophot.h"
+
+addlims (float *star, int *jrect) {
+
+  float temp, fudgex, fudgey;
+	
+  if (star[1] > 0) {
+    if (beta4 < 0.1) {
+      temp = star[1]/nphsub - 1.0;
+    } else {
+      temp = pow (6*star[1]/nphsub, 0.33333);
+    }
+    if (star[4] > 0) {
+      fudgex = sqrt(temp*star[4]*2);
+    } else {
+      fudgex = 1.5*irect[1]/2;
+    }
+    if (star[6] > 0) {
+      fudgey = sqrt(temp*star[6]*2);
+    } else {
+      fudgey = 1.5*irect[2]/2;
+    }
+  } else {
+    fudgex = 1.5*irect[1]/2;
+    fudgey = 1.5*irect[2]/2;
+  }
+  /* don't extrapolate beyond 2*fit box */
+  fudgex = MIN (irect[1], fudgex);
+  fudgey = MIN (irect[2], fudgex);
+  jrect[1] = star[2] - fudgex;
+  jrect[2] = star[2] + fudgex;
+  jrect[3] = star[3] - fudgey;
+  jrect[4] = star[3] + fudgey;
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/addstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/addstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/addstar.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "gophot.h"
+
+addstar (float *instar, int iadd, int type) {
+
+  float star0[NPMAX], star1[NPMAX], *bigval, *noiseval;
+  float sky, bfactor, bsky, cfactor, csky, val;
+  int ix, iy, jrect[5];
+  int i, j, ihi, ilo, jhi, jlo, ixin, iyin;
+	
+  if (type == 12) beta4 = 0.01;
+
+  needit = FALSE;
+	
+  sky = guess2 (star0, instar, &ixin, &iyin);
+  sky = guess2 (star1, instar, &ixin, &iyin) / ufactor;
+	
+  addlims (instar, jrect);
+  star1[4] = star0[4]*SQ(xpnd);
+  star1[5] = star0[5]/SQ(xpnd);			
+  star1[6] = star0[6]*SQ(xpnd);
+	
+  bfactor = ufactor*iadd;
+  bsky = iadd*(0.5 - sky);  /* why the 0.5? */
+  cfactor = fac*ufactor;
+  csky = 0.5 - fac*sky;
+
+  ilo = MAX (jrect[1], 0);
+  ihi = MIN (jrect[2], nfast-1);
+  jlo = MAX (jrect[3], 0);
+  jhi = MIN (jrect[4], nslow-1);
+	
+  for (j = jlo; j <= jhi; j++) {
+    iy = j - iyin;
+    bigval = &big[ilo + j*nfast];
+    noiseval = &noise[ilo + j*nfast];
+    for (i = ilo; i <= ihi; i++, bigval++, noiseval++) {
+      if (!finite (*noiseval)) continue;
+      ix = i - ixin;
+      /* shouldn't bfactor multiply both onestar and bsky? */
+      val = ufactor*(onestar (ix, iy, star0, (float *) NULL) - sky);
+      *bigval += iadd*val;
+
+      val = fac*ufactor*fabs(onestar (ix, iy, star1, (float *) NULL) - sky);
+      *noiseval -= iadd*val;
+
+      if (*noiseval <= -1000) {
+	mprint (2, "i,j,noise = %d, %d, %f, %f %f %f %d, negative noise! obliterating\n", i, j, *noiseval, val, *bigval, cfactor, iadd);
+	/*
+	*bigval = MAGIC;
+	*noiseval = MAGIC;
+	*/
+      }
+    }
+  }
+  needit = TRUE;
+  beta4 = 1.0;
+}
+
+/* star0 is the nominial star region, star1 is the expanded are for the noise array */
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/cosmic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/cosmic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/cosmic.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "gophot.h"
+
+bool cosmic (float *star) {
+
+  float dummy[NPMAX];
+  float obs, maxob, sky, chistar, chicos, pred, temp;
+  float sn2, tnoise, *Bval, *Nval;
+  int ix, iy, I, J, ii, jj, npix, imax, jmax;
+  bool pointy;
+
+  pointy = FALSE;
+
+  sky = guess2 (dummy, star, &ix, &iy);
+  temp = big[ix + iy*nfast] / ufactor - dummy[0];
+  if (finite (temp)) dummy[1] = temp;
+  maxob = -HUGE_VAL;
+  chistar = 0;
+  chicos  = 0;
+  npix = 0;
+  
+  for (J = -1; J <= 1; J++) {
+    jj = iy + J;
+    if (jj < 0) continue;
+    if (jj > nslow - 1) continue;
+    
+    Bval = &big[ix - 1 + jj*nfast];
+    Nval = &noise[ix - 1 + jj*nfast];
+    
+    for (I = -1; I <= 1; I++, Bval++, Nval++) {
+      ii = ix + I;
+      if (ii < 0) continue;
+      if (ii > nfast - 1) continue;
+      if (!finite (*Nval)) continue;
+      npix ++;
+      pred = ufactor*onestar (I, J, dummy, (float *) NULL);
+      obs = *Bval;
+      temp = 1.0 / (*Nval + *Bval);
+      chistar += SQ (obs - pred) * temp;
+      sn2 = SQ (obs - sky) * temp;
+      chicos += sn2;
+      if ((obs > maxob) && (sn2 >= sn2cos)) {
+	imax = ii;
+	jmax = jj;
+	maxob = obs;
+	tnoise = temp;
+      }
+    }
+  }
+
+  /* this is meant to test if the object is mostly a single pixel event.
+     doesn't do a good job of distinguishing a single pixel event from a
+     generally poor fit to the top of the star. */
+  if ((npix >= 7) && (maxob > -HUGE_VAL)) {
+    chicos -= SQ (maxob - sky) * tnoise;
+    pointy = (chicos/chistar < discrim);
+    mprint (3, "location %d, %d,  chi-star & chi-cosmic = %f, %f\n", ix, iy, chistar, chicos);
+  }
+
+  if (pointy) {
+    mprint (2, "cosmic ray intensity, x, y: %f %d %d\n", maxob, imax, jmax);
+    star[0] = sky;
+    star[1] = maxob;
+    star[2] = imax;
+    star[3] = jmax;
+    star[4] = widobl;
+    star[5] = -1;
+    star[6] = widobl;
+  }
+  return (pointy);
+}
+
+/* We are basically comparing if the object is more like a stellar
+   object, or if it is compatible with a single high point over a
+   general sky-like region.  
+
+   we have a danger here that a wide object will boost Io
+   significantly, which in turn makes the fit to the object
+   particularly poor in the center areas.  This in turn makes the
+   object seem comparable to the sky, and therefore a cosmic.  Since
+   we really only care if the inner 9 pixels are comparable to the
+   star shape, vaguely, we can fudge this by temporarily setting Io to
+   the central pixel value.  We don't bother if that pixel is bad (NaN).
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/delete_ellipse.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/delete_ellipse.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/delete_ellipse.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "gophot.h"
+
+float delete_ellipse (float *par, float sky) {
+
+  int i, j, npix;
+  float theta, phi;
+  float xp, yp, x, y, dx, dy, Dx, Dy;
+  float Chi, dv, Dv, R2, F2, r1, r2;
+  float flux, mean;
+
+  npix = flux = 0;
+
+  dx = MAX (par[2], par[3]) + 2;
+  dy = MAX (par[2], par[3]) + 2;
+
+  for (j = par[1] - dy; j < par[1] + dy; j++) {
+    if (j < 0) continue;
+    if (j >= nslow) continue;
+    for (i = par[0] - dx; i < par[0] + dx; i++) {
+      if (i < 0) continue;
+      if (i >= nfast) continue;
+    
+      Dx = i - par[0];
+      Dy = j - par[1];
+      phi = atan2 (Dy, Dx) - RAD_DEG * par[4];
+      theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+      
+      /* this is the point on the ellipse at the same angle as ref point */
+      xp = par[2] * cos (theta);
+      yp = par[3] * sin (theta);
+    
+      x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG);
+      y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG);
+      
+      r1 = hypot (Dx, Dy);
+      r2 = hypot (x, y);
+      
+      if (r1 < r2) {
+	flux += big[i + nfast*j] - sky;
+	npix ++;
+      }
+
+    }
+  }
+  mean = flux / npix;
+  fprintf (stderr, "flux: %f, mag: %f, mean: %f\n", flux, -2.5*log10(flux), flux / npix);
+
+  for (j = par[1] - dy; j < par[1] + dy; j++) {
+    if (j < 0) continue;
+    if (j >= nslow) continue;
+    for (i = par[0] - dx; i < par[0] + dx; i++) {
+      if (i < 0) continue;
+      if (i >= nfast) continue;
+    
+      Dx = i - par[0];
+      Dy = j - par[1];
+      phi = atan2 (Dy, Dx) - RAD_DEG * par[4];
+      theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+      
+      /* this is the point on the ellipse at the same angle as ref point */
+      xp = par[2] * cos (theta);
+      yp = par[3] * sin (theta);
+    
+      x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG);
+      y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG);
+      
+      r1 = hypot (Dx, Dy);
+      r2 = hypot (x, y);
+      
+      if (r1 < r2) {
+	big[i + nfast*j] -= mean;
+      }
+      if (r1 < 1.2*r2) {
+	noise[i + nfast*j] += fac*(mean + sky);
+      }
+
+    }
+  }
+  fprintf (stderr, "flux: %f, mag: %f, mean: %f\n", flux, -2.5*log10(flux), flux / npix);
+  return (flux);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/dophot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/dophot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/dophot.c	(revision 16632)
@@ -0,0 +1,94 @@
+# include "gophot.h"
+float set_thresholds (float, float, float *, int *);
+void large_features (float, float);
+int fix_mediansky  (float);
+float get_mediansky (int, int);
+
+int dophot (void) {
+
+  bool first, lastround;
+  float factor, sky, dsky;
+  int nstar, Nit, i, j;
+  char c;
+  int xtest, ytest;
+  struct timeval now, then;  
+  
+  makenoise ();
+  make_mediansky ();
+  get_skystats (&sky, &dsky);
+  fix_mediansky (sky);
+
+  /*
+  gettimeofday (&then, (void *) NULL);
+  for (i = 0; i < nfast; i++) {
+    for (j = 0; j < nslow; j++) {
+      sky = get_mediansky (i, j);
+      big[j*nfast + i] -= sky;
+    }
+  }
+  gettimeofday (&now, (void *) NULL);
+  fprintf (stderr, "elapsed time = %.2f sec\n", 
+	   (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+
+  gfits_write_header ("test.sub", &header);
+  gfits_write_matrix ("test.sub", &matrix);
+  exit (0);
+  */
+
+  thresh = set_thresholds (sky, dsky, &factor, &Nit);
+
+  /* large_features (sky, dsky); */
+
+  first = TRUE;
+  lastround = FALSE;
+
+  for (i = 0; i < Nit + 1; i++) {
+    mprint (0, "starting loop at threshold level %f\n", thresh);
+	   
+    if (i == Nit) lastround = TRUE;
+
+    makemask ();
+
+    /* fix pos needs to be defined correctly */
+    if (fixpos && first) improve (FALSE);
+	   
+    nstar = isearch (first);
+    shape ();
+    paravg ();
+
+    improve (lastround);
+	   
+    mprint (1, " ending loop at threshold level %f\n", thresh); 
+    mprint (1, " number of new objects found on this threshold = %f\n", nstar); 
+    mprint (1, " total number of objects found so far = %d\n", nstot); 
+    
+    thresh /= factor;
+
+    first = FALSE;
+
+# if (0)
+    gfits_write_header ("test.sub", &header);
+    gfits_write_matrix ("test.sub", &matrix);
+
+    completeout (nstot);
+    fprintf (stderr, "type return to continue:  ");
+    fscanf (stdin, "%c", &c);
+# endif
+
+  }
+
+  feature_fluxes ();
+
+  if (lastround) {
+    if (flags[3] == COMPLETE) completeout (nstot);
+  }
+	   
+    /* 
+    gfits_write_header ("test.sub", &header);
+    gfits_write_matrix ("test.sub", &matrix);
+    completeout (nstot);
+    fprintf (stderr, "type return to continue:  ");
+    fscanf (stdin, "%c", &c);
+    */
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/ellipse.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/ellipse.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/ellipse.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include <math.h>
+# include <stdio.h>
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+
+int ellipse (float Sx, float Sxy, float Sy,
+	     float *area, float *amaj, float *amin, float *angle) {
+
+  float A1, A2, A3, R, root1, root2;
+
+  if (fabs(Sxy) >= 1.0 / sqrt(fabs(Sx*Sy))) {
+    *area = 0.0;
+    *amaj = 0.0;
+    *amin = 0.0;
+    *angle = 0.0;
+    /* this is a poor fit - not an ellipse but a hyperbola */
+    return (0);
+  }
+
+  A1 = 1/(2*Sx);
+  A2 = 1/(2*Sy);
+  A3 = Sxy;
+  
+  *angle = atan2(-A3, A2 - A1) / 2.0;
+  R = sqrt( SQ(A2 - A1) + SQ(A3));
+  root1 = (A1 + A2 + R);
+  root2 = (A1 + A2 - R);
+
+  *area = 2.0*M_PI/sqrt(root1*root2);
+  *amaj = 2.35482*sqrt(1.0/root2);
+  *amin = 2.35482*sqrt(1.0/root1);
+
+  return (1);
+
+}
+
+
+/* In this function, Sx & Sy represent sx^2, sy^2 
+
+   given an elliptical Gaussian of the form:
+
+   exp (-z); z = x^2 / 2 sx^2 + y^2 / 2 sy^2 + xy Sxy
+
+   Sa, Sb, and angle can be found by:
+
+   A1 = 1/(2 Sx)
+   A2 = 1/(2 Sy)
+   A3 = Sxy
+   
+   R = sqrt ((A2 - A1)^2 + A3^2)
+   root1 = (A1 + A2 + R)
+   root2 = (A1 + A2 - R)
+   
+   angle = atan2 (-A3, A2 - A1) / 2.0
+   Sa = sqrt (1.0/root2)
+   Sb = sqrt (1.0/root1)
+   
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/feature_fluxes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/feature_fluxes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/feature_fluxes.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "gophot.h"
+
+float feature_fluxes () {
+
+  int i, j, npix, n;
+  float theta, phi, cs, sn;
+  float xp, yp, x, y, dx, dy, Dx, Dy;
+  float r1, r2;
+  float flux, mean, sky;
+
+  for (n = 0; n < nregion; n++) {
+
+    npix = flux = 0;
+    
+    dx = MAX (region[n][4], region[n][5]) + 2;
+    dy = MAX (region[n][4], region[n][5]) + 2;
+    cs = cos (region[n][6] * RAD_DEG);
+    sn = sin (region[n][6] * RAD_DEG);
+    sky = region[n][0];      
+
+    for (j = region[n][3] - dy; j < region[n][3] + dy; j++) {
+      if (j < 0) continue;
+      if (j >= nslow) continue;
+      for (i = region[n][2] - dx; i < region[n][2] + dx; i++) {
+	if (i < 0) continue;
+	if (i >= nfast) continue;
+	
+	Dx = i - region[n][2];
+	Dy = j - region[n][3];
+	phi = atan2 (Dy, Dx) - RAD_DEG * region[n][6];
+	theta = atan2 (region[n][4]*sin(phi), region[n][5]*cos(phi));
+	
+	/* this is the point on the ellipse at the same angle as ref point */
+	xp = region[n][4] * cos (theta);
+	yp = region[n][5] * sin (theta);
+	
+	x = xp * cs - yp * sn;
+	y = xp * sn + yp * cs;
+	
+	r1 = hypot (Dx, Dy);
+	r2 = hypot (x, y);
+	
+	if (r1 < r2) {
+	  flux += big[i + nfast*j] - sky;
+	  npix ++;
+	}
+	
+      }
+    }
+    /* existing image has mean subtracted = flux*Npix */
+    flux += region[n][1];
+    mean = flux / npix;
+    fprintf (stderr, "sub flux: %f, mag: %f, mean: %f\n", flux, -2.5*log10(flux), flux / npix);
+    region[n][7] = flux;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/fillerup.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/fillerup.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/fillerup.c	(revision 16632)
@@ -0,0 +1,169 @@
+# include "gophot.h"
+
+fillerup (int xo, int yo, int findstats) {
+
+  float *bigval, *noiseval, ufactor2, snlim2;
+  int i, j, ilo, ihi, jlo, jhi, ix, iy, idist, nsky, maxnpt, outer;
+  int *x, *y;
+  float *z, *d;
+  float N, S, F, Sx, Sy, Sx2, Sy2, xv, yv;
+  float value, SNR, sky;
+
+  ufactor2 = SQ(ufactor);
+  snlim2 = SQ(snlim);
+  npt = 0;
+  nsky = 0;
+
+  ilo = MAX (xo - nrect[1]/2, 0);
+  ihi = MIN (xo + nrect[1]/2, nfast-1);
+  jlo = MAX (yo - nrect[2]/2, 0);
+  jhi = MIN (yo + nrect[2]/2, nslow-1);
+  
+  outer = MIN (nrect[1]/3, nrect[2]/3);
+  
+  for (j = jlo; j <= jhi; j++) {
+    bigval = &big[ilo + j*nfast];
+    noiseval = &noise[ilo + j*nfast];
+    for (i = ilo; i <= ihi; i++, bigval++, noiseval++) {
+      if (!finite (*bigval)) continue;
+      if (!finite (*noiseval)) continue;
+      if (SQ(*bigval) < (*bigval + *noiseval) * snlim2) continue;
+      if (*bigval < (*noiseval - rnoise)) continue;
+      ix = i - xo;
+      iy = j - yo;
+      xs[npt] = ix;
+      ys[npt] = iy;
+      zs[npt] = *bigval/ufactor;
+      dzs[npt] = (*bigval + *noiseval) / ufactor2;
+      idist = MAX (abs(ix), abs(iy));
+      if (idist > outer) {
+	ts[nsky] = zs[npt];
+	nsky ++;
+      }
+      npt ++;
+    }
+  }
+  
+  if (npt == 0) return (FALSE);
+  if (!findstats) return (TRUE);
+
+  if (nsky == 0) return (FALSE);
+
+  fsort (ts, nsky);
+  sky = ts[(int)(0.5*nsky)];
+  sum2 = sky;
+
+  z = zs;
+  d = dzs;
+  S = N = 0;
+  for (i = 0; i < npt; i++, z++, d++) {
+    if (*z < sky) continue;
+    N += *d;
+    S += *z - sky;
+  }
+
+  if (S < 0) return (FALSE);
+  SNR = S*S / N;
+  if (SNR < SQ(bumpcrit)) return (FALSE);
+
+  if (SNR > 49) {
+    x = xs;
+    y = ys;
+    z = zs;
+    d = dzs;
+    N = S = Sx = Sy = Sx2 = Sy2 = 0;
+    for (i = 0; i < npt; i++, x++, y++, z++, d++) {
+      idist = MAX (abs(*x), abs(*y));
+      if (idist > outer) continue;
+      if (*z < sky) continue;
+      value = *z - sky;
+      xv = *x * value;
+      yv = *y * value;
+      N += *d;
+      S += value;
+      Sx += xv;
+      Sx2 += *x * xv;
+      Sy += yv;
+      Sy2 += *y * yv;
+    }
+    xmax = Sx / S;
+    ymax = Sy / S;
+    xmax2 = fabs(Sx2 / S - xmax*xmax);
+    ymax2 = fabs(Sy2 / S - ymax*ymax);
+    maxval = S / sqrt (xmax2*ymax2);
+  } else {
+    z = zs;
+    maxval = *z;
+    maxnpt = 0;
+    for (i = 0; i < npt; i++, z++) {
+      if (*z > maxval) {
+	maxnpt = i;
+	maxval = *z;
+      }
+    }
+    xmax = xs[maxnpt];
+    ymax = ys[maxnpt];
+    xmax2 = ava[4];
+    ymax2 = ava[6];
+    maxval -= sum2; 
+ }
+
+  maxval *= ufactor;
+  sum2 *= ufactor;
+
+  if (!finite (maxval)) return (FALSE);
+  return (TRUE);
+  
+}
+
+/* adjust the errors by the deviation from the guess fit */
+filladjust (float *star) {
+
+  int i;
+  float f, df;
+
+  return (0);
+  if (star[1] < cmax/(ufactor*10)) return (0); 
+
+  for (i = 0; i < npt; i++) {
+
+    f = onestar ((int)xs[i], (int)ys[i], star, (float *) NULL);
+    
+    df = 10 * fabs(f - zs[i]);
+    dzs[i] += df/ufactor;
+  }
+
+}
+
+/* check if weighted center is in OK location 
+   weighted center is based on useable pixels, not
+   on entire box */
+centertest (float *star, int *x, int *y) {
+
+  int i;
+  float f, df, Sf, Sx, Sy, dx, dy;
+
+  Sf = Sx = Sy = 0;
+
+  for (i = 0; i < npt; i++) {
+
+    f = onestar ((int)xs[i], (int)ys[i], star, (float *) NULL);
+    
+    Sf += f;
+    Sx += f*xs[i];
+    Sy += f*ys[i];
+
+  }
+
+  dx = star[2] - Sx/Sf;
+  dy = star[3] - Sy/Sf;
+
+  if ((fabs(dx) > 0.25*nrect[1]) || (fabs(dy) > 0.25*nrect[2])) {
+    mprint (3, "center %f %f %f\n", dx, dy, Sf);
+    return (TRUE);
+  }
+
+  return (FALSE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/findsky.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/findsky.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/findsky.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "gophot.h"
+
+float findsky () {
+
+  int i, skip, nsky, bin;
+  int zvalue[0x10000], nvalue;
+  float median, *valB;
+  
+  skip = 100;
+  valB = big;
+
+  for (i = 0; i < nfast*nslow; i+=skip, valB+=skip) {
+    bin = *valB;
+    if ((bin >= 0) && (bin < 0x10000)) {
+      nvalue ++;
+      zvalue[bin] ++;
+    }
+  }
+  
+  nsky = 0;
+  for (i = 0; (i < 0x10000) && (nsky < nvalue / 2); i++) {
+    nsky += zvalue[i];
+  }
+  if (nsky < nvalue / 2) {
+    mprint (1, "weird situation: no median found\n");
+    exit (1);
+  }
+  median = i;
+  mprint (1, "median = %f\n", median);
+
+  return (median);
+}
+
+/* arguments OK */
+
+/* this median method assumes 64k data range */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/galaxy.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/galaxy.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/galaxy.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "gophot.h"
+
+/* this is kind of stupid:  this function takes two 
+   lists of the parameters for the object because 
+   star1 has x, y, relative to 0, */
+
+bool galaxy (float *star1, float *err, float *star2) {
+
+  float dummy[NPMAX], tot[4], temp, nsigma;
+  int i;
+  bool value;
+
+  value = FALSE;
+
+  for (i = 0; i < 4; i++) chi[i] = 0;
+	
+  parinterp (star2[2], star2[3], dummy);
+
+  /* if errors on sigma x or y are so large, call it a galaxy */
+  if (dummy[4] < 3*sqrt(err[4])) return (TRUE);
+  if (dummy[6] < 3*sqrt(err[6])) return (TRUE);
+
+  /* too weak a measurement to be called galaxy */
+  if (star1[4] < 2*sqrt(err[4])) return (FALSE);
+  if (star1[6] < 2*sqrt(err[6])) return (FALSE);
+  if (star1[1] < 2*sqrt(err[1])) return (FALSE); 
+
+  /*************************************************************
+   I'm rather concerned about 'parsm' where did it come from? 
+  parms[] is set in varipar_plane.c  */							
+  temp = SQ (sig[1]*dummy[4]);
+  tot[1] = MAX (parms[4], temp);
+  temp = SQ (sig[2])/(dummy[4]*dummy[6]);
+  tot[2] = MAX (parms[5], temp);
+  temp = SQ (sig[3]*dummy[6]);
+  tot[3] = MAX (parms[6], temp);
+  chi[1] = SQ (star1[4] - dummy[4]) / (tot[1] + err[4]);
+  chi[2] = SQ (star1[5] - dummy[5]) / (tot[2] + err[5]);
+  chi[3] = SQ (star1[6] - dummy[6]) / (tot[3] + err[6]);
+
+  if (star1[4] < dummy[4]) chi[1] = 0;
+  if (star1[6] < dummy[6]) chi[3] = 0;
+  chi[4] = chi[1] + chi[2] + chi[3];
+
+  mprint (2, "galaxy test, object at %f %f  %f\n", star2[2], star2[3], star2[1]);
+  mprint (2, "chisqs: %f %f %f %f\n", chi[1], chi[2], chi[3], chi[4]);
+
+  nsigma = MIN (sqrt(chi[4]), 1.0e8);
+  mprint (2, "nsigma = %f\n", nsigma);
+
+  value = chi[4] >= chicrit;
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/gophot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/gophot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/gophot.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "gophot.h"
+
+int main (int argc, char **argv) {
+
+  float tmp;
+
+  if (argc < 4) {
+    fprintf (stderr, "ERROR: usage: dophot imagename outfile paramfile\n");
+    exit (2);
+  }
+  ConfigInit (&argc, argv);
+
+  fprintf (stderr, "reading from %s, writing to %s, %s param file\n", argv[1], argv[2], argv[3]);
+
+  strcpy (files[4], argv[2]);
+
+  /* load image header and data */
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't open FITS header %s\n", argv[1]);
+    exit (1);
+  }
+  if (!gfits_read_matrix (argv[1], &matrix)) {
+    fprintf (stderr, "ERROR: can't open FITS matrix %s\n", argv[1]);
+    exit (1);
+  }
+  /* convert to float, set up noise array and axes */
+  gfits_convert_format (&header, &matrix, -32, 1.0, 0.0, 0);
+  ALLOCATE (noise, float, matrix.size);
+  big = (float *) matrix.buffer;
+  nfast = matrix.Naxis[0];
+  nslow = matrix.Naxis[1];
+ 
+  /* override config values with header values */ 
+  if (gfits_scan (&header, "SATVALUE", "%f", 1, &tmp)) itop = tmp;
+  if (gfits_scan (&header, "GAIN", "%f", 1, &tmp)) eperdn = tmp;
+  if (gfits_scan (&header, "NEWGAIN", "%f", 1, &tmp)) eperdn = tmp;
+
+  /* we are scaling the image to electrons, must also scale parameters */
+  itop *= eperdn;
+  ibot *= eperdn;
+  tmax *= eperdn;
+  cmax *= eperdn;
+  ctpersat *= eperdn;
+
+  dophot (); 
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+/* in the rest of the program:
+   NFAST = matrix.Naxis[0]  -- # of X-axis pixels 
+   NSLOW = matrix.Naxis[1]  -- # of Y-axis pixels 
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/guess.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/guess.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/guess.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "gophot.h"
+
+/* fill in values for star[NPMAX] based on rough stats and sky model */
+float guess1 (float *star, float *dummy, int ix, int iy) {
+
+  /* parinterp fills in star[4,5,6] from averages */
+  parinterp (ix, iy, star);
+
+  star[0] = sum2/ufactor;
+  star[1] = maxval/ufactor;
+  star[2] = xmax;
+  star[3] = ymax;
+
+  return (0.0);
+
+}
+
+/* fill in values for star[NPMAX] based on rough stats and sky model */
+/* use sigma_x, sigma_y from fillerup */
+float newguess (float *star, float *dummy, int ix, int iy) {
+
+  star[0] = sum2 / ufactor;
+  star[1] = maxval / ufactor;
+  star[2] = xmax;
+  star[3] = ymax;
+  star[4] = xmax2;
+  star[5] = 0;
+  star[6] = ymax2;
+  
+  return (0.0);
+}
+
+/* fill in values for star from instar, rescaling */
+float guess2 (float *star, float *instar, int *ix, int *iy) {
+
+  /* i'm concerned that the ix, iy values need to be passed back. */
+  float value;
+
+  *ix = (int) (instar[2] + 0.5);
+  *iy = (int) (instar[3] + 0.5);
+
+  star[0] = instar[0]/ufactor;
+  star[1] = instar[1]/ufactor;
+  star[2] = instar[2] - *ix;
+  star[3] = instar[3] - *iy;
+  star[4] = instar[4];
+  star[5] = instar[5];
+  star[6] = instar[6];
+
+  value = instar[0];				
+  return (value);
+}
+
+
+/* fill in values for star from instar, rescaling */
+float guess3 (float *star, float *instar, int *ix, int *iy) {
+
+  float value;
+
+  *ix = (int) (instar[2] + 0.5);
+  *iy = (int) (instar[3] + 0.5);
+
+  parinterp (instar[2], instar[3], star);
+
+  star[0] = instar[0]/ufactor;
+  star[1] = instar[1]/ufactor;
+  star[2] = instar[2] - *ix;
+  star[3] = instar[3] - *iy;
+
+  value = instar[0];				
+  return (value);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/impaper2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/impaper2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/impaper2.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include "gophot.h"
+
+impaper2 (int k) {
+
+  int i, nsky, nsort;
+  float sky, sum, r, dr, zsort[MAXFIL];
+
+  /* find median sky outside inner radius */
+
+  dr = 0.5*(SQ (0.5*arect[1]) + SQ (0.5*arect[2]));
+  nsort = 0;
+  for (i = 0; i < npt; i++) {
+    r = SQ (xs[i]) + SQ (ys[i]);
+    if (r >= dr) {
+      zsort[nsort] = zs[i];
+      nsort ++;
+    }
+  }
+  
+  if (nsort < 1) return (0);
+
+  fsort (zsort, nsort);
+        
+  sky = 0;
+  nsky = 0;
+  for (i = 0.25*nsort; i < 0.75*nsort; i++) {
+    sky += zsort[i];
+    nsky ++;
+  }
+  sky /= nsky;
+
+  sum = 0;
+  for (i = 0; i < npt; i++) {
+    sum += (zs[i] - sky);
+  }
+        
+  apple[k][1] = sum*ufactor;
+
+  return (1);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/improve.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/improve.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/improve.c	(revision 16632)
@@ -0,0 +1,117 @@
+# include "gophot.h"
+
+# define ADD +1
+# define SUB -1
+
+improve (int last) {
+
+  float err[NPMAX], star[NPMAX], sky, dx, dy, starchi;
+  int i, k, ix, iy, jmtype, niter, nfit;
+  bool skip, snok;
+
+  /* imtype may be 1-9 for regular objects, 101-109 for fixed objects */
+
+  for (i = 0; i < nstot; i++) {
+
+    /* set up flags for fixed objects */
+    fixxy = fixpos && (imtype[i] >= 100);
+    jmtype = fixxy ? imtype[i] - 100 : imtype[i];
+    /* inverse: imtype[i] = fixxy ? jmtype + 100 : jmtype; */
+
+    if (jmtype == 0) continue;
+    if (jmtype == 6) continue;
+    if (jmtype == 16) continue;
+    if (jmtype == 8) continue;
+    if (jmtype == 18) continue;
+
+    /* if (jmtype == 3) continue; */
+    if (jmtype == 2) continue;
+    if (jmtype == 12) continue;
+    if (jmtype == 10) continue;
+	   
+    /* add star back to frame, get sky, get subraster */
+    addstar (starpar[i], ADD, jmtype);
+    sky = guess3 (star, starpar[i], &ix, &iy);
+    mprint (3, " improving star %d at %d, %d\n", i, ix, iy);
+    nrect[1] = irect[1];
+    nrect[2] = irect[2];
+    fillerup (ix, iy, FALSE);  /* we don't use the center information here */
+
+    /* skip star if off picture, has negative flux, or if s/n too low for non-fixed objects */
+    skip = offpic (star, ix, iy, &dx, &dy);
+    if (star[1] <= 0) {
+      skip = TRUE;
+      starpar[i][1] = 0;
+    }
+    if (!skip && !fixxy) {
+      snok = transmask (ix,iy,sky);
+      skip = skip && !snok;
+    }
+    if (skip) {
+      jmtype = 6;
+      mprint (3, " deactivating star %d at %d, %d\n", i, ix, iy);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    /* fixed objects only vary x,y */
+    if (fixxy) {
+      nfit = NFIT0;
+      niter = 2;
+    } else {
+      nfit = NFIT1;
+      niter = nit;
+    }
+
+    filladjust (star); 
+
+    /* fit for magnitudes -- 4 param fit (or 2 for fixed obj) (initial guesses in are the previous fits) */
+    starchi = chisq (onestar, xs, ys, zs, dzs, npt, star, err, nfit, acc, parlim, niter);
+
+    /* set non-converge objects to type 4, don't bother with other calcs */
+    if (!finite(starchi)) {
+      if (jmtype != 3) jmtype = 4;
+      for (k = 0; k < NPMAX; k++) galpar[i][k] = starpar[i][k];
+      for (k = 0; k < NPMAX; k++) shadow[i][k] = starpar[i][k];
+      apple[i][4] = MIN (1.086*sqrt(err[1])/star[1], 1);
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    /* things which get negative flux, turn in to type 6 and skip */
+    if (star[1] <= 0) {
+      starpar[i][1] = 0;
+      jmtype = 6;
+      mprint (3, " deactivating star %d at %d, %d\n", i, ix, iy);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    /* this section applies to type 1 3 5 7 */
+    if ((jmtype != 2) && (jmtype != 10)) {
+      /* store the fitted values */
+      parupd (star, starpar[i], ix, iy);
+    }
+
+    if ((jmtype != 2) && (jmtype != 3) && toofaint(starpar[i], err)) jmtype = 7;
+	   
+    apple[i][4] = MIN (1, 1.086*sqrt(err[1])/star[1]);
+
+    if (last) {
+      nrect[1] = arect[1];
+      nrect[2] = arect[2];
+      fillerup (ix, iy, FALSE);
+      impaper2 (i);
+    }
+	      
+    addstar (starpar[i], SUB, jmtype);
+    imtype[i] = fixxy ? jmtype + 100 : jmtype;
+
+  }
+
+  return (0);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/isearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/isearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/isearch.c	(revision 16632)
@@ -0,0 +1,170 @@
+# include "gophot.h"
+
+int isearch (int first) {
+  
+  int jrect[3];
+  int i, j, nsprev, nfound, nnew, ngoodpts, ngoodmask, ngoodfit, nfit;
+  float dummy[2*NPMAX], star[2*NPMAX], err[NPMAX], pixt2, bestsky;
+  float tthresh, thresh2, highsky, highthresh, tmp;
+  float sky, Chi, dx, dy, rdnoise2;
+  float *Bval, *Nval;
+  bool iscosmic, isbright, isfaint, hole;
+  float get_mediansky ();
+  FILE *f;
+
+  bzero (dummy, NPMAX*sizeof(float));
+  
+  pixt2 = SQ(pixthresh);
+
+  /* use jrect as temp in isearch.c */
+  for (i = 1; i < 3; i++) {
+    jrect[i] = (first) ? krect[i] : irect[i]; 
+  }
+	
+  nsprev = nstot;
+  nnew = 0;
+  ngoodpts = 0;
+  ngoodmask = 0;
+  ngoodfit = 0;
+  thresh2 = SQ(thresh);
+  nfit = (first) ? NFIT2 : NFIT1;
+  /* on first pass or so, we use 7 par fit, not 4 par fit */
+
+  Bval = big;
+  Nval = noise;
+  for (i = 0; i < nslow; i++) {
+    for (j = 0; j < nfast; j++, Bval++, Nval++) {
+
+      /* occasionally update sky guess based on median sky image */
+      if (!(j % nthpix)) {
+	sky = get_mediansky (j, i); 
+	tthresh = sky + thresh;
+      }
+
+      imtype[nstot] = 1;
+
+      /* skip bad pixels */
+      if (*Bval < tthresh) continue;
+      if (!finite (*Nval)) continue;
+      if (*Bval < *Nval - rnoise) continue;
+
+      /* test for significant peak */
+      if (!transmask (j, i, sky)) continue;
+      nnew ++;
+
+      /* nrect is passed globally to fillerup or through - rather obscure */ 
+      nrect[1] = jrect[1];
+      nrect[2] = jrect[2];
+
+      /* fills the vectors xs, ys, zs, dzs */
+      if (!fillerup (j, i, TRUE)) continue;
+      if ((fabs(xmax) > 0.33*nrect[1]) || (fabs(ymax) > 0.33*nrect[2])) {
+	mprint (3, "centroid moved: %d %d  %f %f\n", j, i, xmax, ymax);
+      }
+
+      tmp = enuff4*jrect[1]*jrect[2];
+      if (npt < tmp) {
+	mprint (3, "skipping: npt = %d\n", npt);
+	continue;
+      }
+      ngoodpts ++;
+
+      /* if sky guess has changed significantly, retest for significant peak */
+      if (fabs(sum2 - sky) / maxval > 0.2) {
+	if (!transmask (j, i, sum2)) {
+	  mprint (3, "failed transmask on local sky, %f\n", sum2);
+	  continue;
+	}
+      }
+      ngoodmask ++;
+
+      /* fill in guess for this object */
+      if (first) {
+	newguess (star, dummy, j, i); 
+      } else {
+	guess1 (star, dummy, j, i);
+      }
+      filladjust (star); 
+
+      /* fit star using 4 parameterfit */
+      Chi = chisq (onestar, xs, ys, zs, dzs, npt, star, err, nfit, acc, parlim, nit);
+
+      /* if (finite(Chi) && ((err[2] > 0.1) || (err[3] > 0.1))) fprintf (stderr, "errors: %d %d  %f %f   %f %f   %f\n", j, i, err[2], err[3], err[4], err[6], Chi/npt); */
+      if (!finite(Chi)) {
+	mprint (3, "failed to converge:  no entry in starlist\n");
+	continue;
+      }
+      if ((fabs(star[2]) > 0.33*nrect[1]) || (fabs(star[3]) > 0.33*nrect[2])) {
+	mprint (3, "fit center moved: %d %d  %f %f\n", j, i, star[2], star[3]);
+	continue;
+      }
+      if (centertest (star, xs, ys, npt)) {
+	mprint (3, "star %d at %d %d moved\n", nstot, j, i);
+	continue;
+      }
+      if (offpic (star, j, i, &dx, &dy)) {
+	mprint (3, "fitted star off image\n");
+	continue;
+      }
+
+      /* save fit parameters */
+      parupd (star, starpar[nstot], j, i);
+      parupd (star, shadow[nstot], j, i);
+      rchisq[nstot] = Chi / npt;
+      apple[nstot][4] = MIN (1, 1.086*sqrt(err[1])/star[1]);
+      mprint (2, "star %d: %f, %f  peak: %f chisq: %f\n", nstot, starpar[nstot][2], starpar[nstot][3], maxval, rchisq[nstot]);
+      ngoodfit ++;
+
+      if (verybright (starpar[nstot])) {
+	imtype[nstot] = 10;
+	goto finish;
+      }	
+      if (cosmic (starpar[nstot])) {
+	imtype[nstot] = 8;
+	hole = oblit (starpar[nstot]);
+	goto finish_noadd;
+      }	
+      if (toofaint (starpar[nstot], err)) {
+	imtype[nstot] = 7;
+	mprint (3, "faint imtype %d\n", imtype[nstot]);
+	goto finish;
+      }
+
+    finish:
+      addstar (starpar[nstot], SUB, imtype[nstot]);
+
+    finish_noadd:
+      nstot ++;
+      if (nstot >= NSMAX) {
+	mprint (0, "too many stars!\n");
+	return (0);
+      }
+
+    }
+  }
+  nfound = nstot - nsprev;
+  mprint (0, "stars found %d, stars tested %d\n", nfound, nnew);
+  mprint (0, "ngoodpts: %d, ngoodfit: %d, ngoodmask: %d\n", ngoodpts, ngoodfit, ngoodmask);
+
+  return (nfound);
+}
+
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
+      /* before star subtraction:
+
+       Nval contains just sq(RN) (e) 
+       Bval contains counts (e)
+       dBval = sqrt(Bval + Nval)
+
+       after star subtraction:
+       
+       Nval contains fit + sq(RN)
+       Bval contains (obs-fit)
+       dBval = sqrt(Bval + Nval) [Bval' + Nval' = Bval + Nval] 
+      */       
+
+      /* note that the coordinates used in the fit are relative to j, i
+	 and are adjusted back in parupd */
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/large_features.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/large_features.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/large_features.c	(revision 16632)
@@ -0,0 +1,161 @@
+# include "gophot.h"
+
+/* these don't need to be 'static' unless we intend to call these 
+   functions outside of this file... */
+   
+static int *x;
+static int *y;
+static int Npts = 0;
+static int NPTS = 0;
+
+static int dx[] = {-1, 1, 0, 0};
+static int dy[] = {0, 0, -1, 1};
+static int Ntry = 4;
+
+static float *mediansky;
+static int Nx, Ny;
+static float fx, fy;
+
+float *copy_mediansky (int *, int *, float *, float *);
+int set_value (int, int, float);
+void large_features (float, float);
+void get_neighbors (int, int, float);
+float get_value (int, int);
+int outline (float, float, float, float, float, float, float *);
+float delete_ellipse (float *, float);
+
+void large_features (float sky, float dsky) {
+
+  int i, j, k;
+  float min, flux, dSky;
+  float Xo, Yo, dX, dY;
+  float Xmin, Xmax, Ymin, Ymax;
+  float fitpars[5];
+
+  nregion = 0;
+
+  /* use a copy to protect original */
+  mediansky = copy_mediansky (&Nx, &Ny, &fx, &fy);
+
+  dSky = sqrt(sky + rnoise);
+  dsky = MAX (dsky, dSky);
+
+  min = sky + 3*dsky;
+  fprintf (stderr, "sky %f, %f, %f\n", sky, dsky, min);
+  /* find pixels which stand above threshold */
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      if (mediansky [i + j*Nx] > min) {
+	/* this is always the first point in the group */
+	/* init the storage arrays */
+	Npts = 0;
+	NPTS = 100;
+	ALLOCATE (x, int, NPTS);
+	ALLOCATE (y, int, NPTS);
+	x[Npts] = i;
+	y[Npts] = j;
+	Npts ++;
+	get_neighbors (i, j, min);
+	/* we now have a list x, y, Npts */
+	Xmin = Xmax = x[0];
+	Ymin = Ymax = y[0];
+	for (k = 0; k < Npts; k++) {
+	  Xmin = MIN (Xmin, x[k]);
+	  Ymin = MIN (Ymin, y[k]);
+	  Xmax = MAX (Xmax, x[k]);
+	  Ymax = MAX (Ymax, y[k]);
+	}
+	Xo = 0.5*(Xmax + 1 + Xmin);
+	Yo = 0.5*(Ymax + 1 + Ymin);
+	dX = (Xmax + 1 - Xmin);
+	dY = (Ymax + 1 - Ymin);
+	convert_coords (&Xo, &Yo, &dX, &dY);
+	fprintf (stderr, "large feature: %f %f  %f %f\n", Xo, Yo, dX, dY);
+	outline (Xo, Yo, 0.4*dX, 0.4*dY, sky + 7*dsky, 2*dsky, fitpars);
+	flux = delete_ellipse (fitpars, sky);
+	fprintf (stderr, " flux: %f  %f\n", flux, sky);
+	region[nregion][0] = sky;
+	region[nregion][1] = flux;
+	region[nregion][2] = fitpars[0];
+	region[nregion][3] = fitpars[1];
+	region[nregion][4] = fitpars[2];
+	region[nregion][5] = fitpars[3];
+	region[nregion][6] = fitpars[4];
+	region[nregion][7] = flux;
+	nregion ++;
+	if (nregion == 100) {
+	  fprintf (stderr, "too many regions!\n");
+	  exit (0);
+	}
+      }
+    }
+  }
+}
+
+void get_neighbors (int ix, int iy, float min) {
+
+  int i, Ix, Iy;
+
+  for (i = 0; i < Ntry; i++) {
+    
+    Ix = ix + dx[i];
+    Iy = iy + dy[i];
+
+    if (get_value(Ix, Iy) > min) {
+      
+      x[Npts] = Ix;
+      y[Npts] = Iy;
+      Npts ++;
+      if (Npts == NPTS) {
+	NPTS += 100;
+	REALLOCATE (x, int, NPTS);
+	REALLOCATE (y, int, NPTS);
+      } 
+      
+      set_value (Ix, Iy, 0);
+      
+      get_neighbors (Ix, Iy, min);
+      
+    }
+  }
+}
+
+float get_value (int i, int j) {
+
+  float value;
+
+  if (i < 0) return (0);
+  if (i >= Nx) return (0);
+
+  if (j < 0) return (0);
+  if (j >= Ny) return (0);
+
+  value = mediansky[i + Nx*j];
+
+  return (value);
+
+}
+
+int set_value (int i, int j, float value) {
+
+  if (i < 0) return (0);
+  if (i >= Nx) return (0);
+
+  if (j < 0) return (0);
+  if (j >= Ny) return (0);
+
+  mediansky[i + Nx*j] = value;;
+
+  return (1);
+
+}
+
+convert_coords (float *X, float *Y, float *dX, float *dY) {
+
+  *X /= fx;
+  *dX /= fx;
+  *Y /= fy;
+  *dY /= fy;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/lubksb.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/lubksb.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/lubksb.c	(revision 16632)
@@ -0,0 +1,31 @@
+void lubksb (float **a, int n, int *indx, float *b) {
+
+  int i, j, ii, kk;
+  float sum;
+
+  ii = -1;
+  for (i = 0; i < n; i++) {
+    kk = indx[i];
+    sum = b[kk];
+    b[kk] = b[i];
+    if (ii != -1) {
+      for (j = ii; j < i; j++) {
+	sum -= a[i][j]*b[j];
+      }
+    } else {
+      if (sum != 0) ii = i;
+    }
+    b[i] = sum;
+  }
+
+  for (i = n-1; i >= 0; i--) {
+    sum=b[i];
+    if (i < n-1) {
+      for (j = i+1; j < n; j++) {
+	sum -= a[i][j]*b[j];
+      }
+    }
+    b[i] = sum/a[i][i];
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/ludcmp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/ludcmp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/ludcmp.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include <ohana.h>
+
+# define TINY 1.0e-20
+
+void ludcmp (float **a, int n, int *indx, float *D) {
+
+  float *vv;
+  int i, j, k, imax;
+  float aamax, sum, dum, d;
+
+  ALLOCATE (vv, float, n);
+
+  d = 1.0;
+  for (i = 0; i < n; i++) {
+    aamax = 0.0;
+    for (j = 0; j < n; j++) {
+      if (fabs (a[i][j]) > aamax) aamax = fabs (a[i][j]);
+    }
+    if (aamax == 0.0) {
+      *D = 0;
+      free (vv);
+      return;
+    }
+    vv[i] = 1.0/aamax;
+  }
+
+  for (j = 0; j < n; j++) {
+    for (i = 0; i < j; i++) {
+      sum = a[i][j];
+      for (k = 0; k < i; k++) {
+	sum -= a[i][k]*a[k][j];
+      }
+      a[i][j] = sum;
+    }
+    aamax = 0.0;
+    for (i = j; i < n; i++) {
+      sum = a[i][j];
+      for (k = 0; k < j; k++) {
+	sum -= a[i][k]*a[k][j];
+      }
+      a[i][j] = sum;
+      dum = vv[i]*fabs(sum);
+      if (dum >= aamax) {
+	imax = i;
+	aamax = dum;
+      }
+    }
+    if (j != imax) {
+      for (k = 0; k < n; k++) {
+	dum = a[imax][k];
+	a[imax][k] = a[j][k];
+	a[j][k] = dum;
+      }
+      d = -d;
+      vv[imax] = vv[j];
+    }
+    indx[j] = imax;
+    if (j != n-1) {
+      if (a[j][j] == 0.0) a[j][j] = TINY;
+      dum = 1.0 / a[j][j];
+      for (i = j+1; i < n; i++) {
+	a[i][j] = a[i][j]*dum;
+      }
+    }
+  }
+  if (a[n-1][n-1] == 0.0) a[n-1][n-1] = TINY;
+  free (vv);
+
+  *D = d;
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/makemask.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/makemask.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/makemask.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "gophot.h"
+
+makemask () {
+
+  int i, j, ii, jj;
+  float value;
+  float dumx, dumy, dummy, star[NPMAX];
+
+  dumx = 0;
+  dumy = 0;
+  dummy = parinterp (dumx, dumy, star);
+  
+  star[0] = 0;			
+  star[1] = 1;			
+  star[2] = 0;			
+  star[3] = 0;	
+  
+  for (j = 0, jj = -iyby2; j < 2*iyby2 + 1; j++, jj++) {
+    for (i = 0, ii = -ixby2; i < 2*ixby2 + 1; i++, ii++) {
+      starmask[i][j] = value = onestar (ii, jj, star, (float *) NULL);
+      mprint (2, "starmask[%d][%d]: %f\n", ii, jj, value);
+    }
+  }
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/makenoise.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/makenoise.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/makenoise.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "gophot.h"
+
+makenoise () {
+
+  int i, j;
+  float *valN, *valB;
+
+  valN = noise;
+  valB = big;
+
+  for (i = 0; i < nslow; i++) {
+    if ((i < nbadbot) || (i > nslow - nbadtop - 1)) {
+      for (j = 0; j < nfast; j++, valN++, valB++) *valN = MAGIC;
+      continue;
+    }      
+    for (j = 0; j < nfast; j++, valN++, valB++) {
+      if (j < nbadleft) {
+	*valN = MAGIC;
+	continue;
+      }
+      if (j > nfast - nbadright - 1) {
+	*valN = MAGIC;
+	continue;
+      }
+      *valB *= eperdn;
+      if (*valB > itop) {
+	*valN = MAGIC;
+	continue;
+      }
+      if (*valB <= ibot) {
+	*valN = MAGIC;
+	continue;
+      }
+      *valN = rnoise;
+    }
+  }
+}
+
+/* arguments OK */
+
+
+/* NEW CHOICES FOR NOISE AND BIG:
+
+   'big' is converted to electrons - this is the Poisson component of the error
+   'noise' will contain just the SQ(read-noise) - this is added to when a star is subtracted
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/mediansky.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/mediansky.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/mediansky.c	(revision 16632)
@@ -0,0 +1,196 @@
+# include "gophot.h"
+
+static float *mediansky;
+static int Nx, Ny;
+static float fx, fy;
+
+int make_mediansky () {
+
+  /* we have an image of nfast x nslow pix.  
+     make a new image of size sqrt(nfast) x sqrt(nslow)
+     (2k x 4k -> 45 x 63)
+  */
+
+  float *temp;
+  int i, j, I0, I1, J0, J1, I, J, n;
+  int nx, ny;
+  float Mv, Nv, Mv2, value;
+
+  Nx = sqrt (nfast);
+  Ny = sqrt (nslow);
+
+  /* nthpix is used in isearch.c to update sky guess */
+  nthpix = Nx;
+
+  fx = (float) Nx / nfast;
+  fy = (float) Ny / nslow;
+
+  ALLOCATE (mediansky, float, Nx*Ny);
+
+  nx = 1 + 1/fx;
+  ny = 1 + 1/fy;
+
+  ALLOCATE (temp, float, 2*nx*ny);
+
+  Nv = Mv = Mv2 = 0.0;
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      
+      I0 = i / fx;
+      J0 = j / fy;
+
+      I1 = (i + 1) / fx;
+      J1 = (j + 1) / fy;
+
+      n = 0;
+      temp[0] = 0;
+      
+      for (J = J0; J < J1; J++) {
+	if (J < nbadbot) continue;
+	if (J > nslow - nbadtop - 1) continue;
+	for (I = I0; I < I1; I++) {
+	  if (I < nbadleft) continue;
+	  if (I > nfast - nbadright - 1) continue;
+	  temp[n] = big[J*nfast + I];
+	  n++;
+	}
+      }
+
+      fsort (temp, n);
+      value = temp[(int)(0.5*n)];
+
+      if (n < 2) {
+	mediansky[j*Nx + i] = MAGIC;
+      } else {
+	mediansky[j*Nx + i] = value;
+      }
+    }
+  }
+  return (0);
+}
+
+/* take array which is the median sky, copy to a separate vector, 
+   sort, find median and sigma in 50% interval around median */
+
+get_skystats (float *sky, float *dsky) {
+
+  float *temp, sky2;
+  int i, Npix, Nsky;
+
+  Npix = Nx*Ny;
+
+  ALLOCATE (temp, float, Npix);
+
+  memcpy (temp, mediansky, Npix*sizeof(float));
+
+  fsort (temp, Npix);
+
+  *sky = temp[(int)(0.5*Npix)];
+
+  Nsky = 0;
+  sky2 = 0;
+  for (i = 0.25*Npix; i < 0.75*Npix; i++) {
+    if (!finite(temp[i])) continue;
+    sky2 += SQ(temp[i] - *sky);
+    Nsky ++;
+  }
+  
+  *dsky = sqrt (sky2/Nsky);
+
+  free (temp);
+
+  mprint (0, "median sky: %f %f\n", *sky, *dsky);
+
+  return (1);
+
+}
+
+fix_mediansky (float sky) {
+
+  int i;
+
+  for (i = 0; i < Nx*Ny; i++) {
+    if (!finite (mediansky[i])) {
+      mediansky[i] = sky;
+    }
+  }
+}
+
+/* this version is fast and has no edge problems. */
+
+# if (1) 
+float get_mediansky (int i, int j) {
+
+  float value;
+  int I, J;
+
+  I = i * fx;
+  J = j * fy;
+
+  value = mediansky[J*Nx + I];
+
+  return (value);
+
+}
+# endif
+
+/* this version is slow, but more accurate.
+   on the other hand, it needs to be fixed for
+   edge problems. */
+
+# if (0) 
+float get_mediansky (int i, int j) {
+
+  float Fx, Fy, Vo, Vm, Vx, Vy;
+  float value;
+  int I, J, dx, dy;
+
+  I = i * fx;
+  J = j * fy;
+
+  Vo = mediansky[J*Nx + I];
+
+  Fx = i * fx - I;
+  if (Fx < 0.5) {
+    dx = -1;
+  } else {
+    dx = +1;
+    Fx = 1.0 - Fx;
+  }
+  Vm = mediansky[J*Nx + I + dx];
+  Vx = (Vo*(0.5+Fx) + Vm*(0.5-Fx));
+
+  Fy = j * fy - J;
+  if (Fy < 0.5) {
+    dy = -1;
+  } else {
+    dy = +1;
+    Fy = 1.0 - Fy;
+  }
+  Vm = mediansky[J*Nx + I + dy*Nx];
+  Vy = (Vo*(0.5+Fy) + Vm*(0.5-Fy));
+
+  value = 0.5*(Vx + Vy);
+
+  return (value);
+
+}
+# endif
+
+float *copy_mediansky (int *nx, int *ny, float *Fx, float *Fy) {
+
+  float *temp;
+
+  ALLOCATE (temp, float, Nx*Ny);
+  memcpy (temp, mediansky, Nx*Ny*sizeof(float));
+  
+  *nx = Nx;
+  *ny = Ny;
+  *Fx = fx;
+  *Fy = fy;
+
+  return (temp);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/message.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/message.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/message.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include <stdio.h>
+# include <stdarg.h>
+
+static FILE *f;
+static int verbosity = 0;
+
+int mprint (int level, char *mode, ...) {
+
+  int status;
+  va_list argp;
+  
+  if (level > verbosity) return (0);
+
+  va_start (argp, mode);
+  
+  status = vfprintf (f, mode, argp);
+
+  va_end (argp);
+
+  return (status);
+
+}
+
+int set_verbosity (int level) {
+
+  f = stderr;
+  verbosity = level;
+  return 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/objout.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/objout.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/objout.c	(revision 16632)
@@ -0,0 +1,88 @@
+# include "gophot.h"
+# define NCHAR 104
+
+completeout () {
+
+  FILE *f;
+  int i, Nchar;
+  float gcorr, gmag;
+  float area, amajor, aminor, tilt, fmag, xc, yc, apmag, tmp;
+  char line[NCHAR];
+	
+  f = fopen (files[4], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error, can't save data in file %s\n", files[4]);
+    exit (1);
+  }
+
+  ellipse (ava[4], ava[5], ava[6], &area, &amajor, &aminor, &tilt);
+  fprintf (f, "# Average Star: %f %f %f\n", amajor, aminor, tilt);
+
+  for (i = 0; i < nregion; i++) {
+    
+    fmag = -2.5*log10 (region[i][1]);
+    gmag = -2.5*log10 (region[i][7]);
+    apmag = 99.999;
+
+    Nchar = snprintf (line, NCHAR, "%3d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %8.3f %8.3f  %8.2f",
+		      20, region[i][2], region[i][3], fmag, 0.01, region[i][0], region[i][4], region[i][5], region[i][6], 
+		      gmag, apmag, 10.0);
+    fprintf (f, "%s\n", line);
+  }
+
+  for (i = 0; i < nstot; i++) {
+         
+    fmag = 99.999;
+    gmag = 99.999;
+    apmag = 99.999;
+
+    if (imtype[i] != 8) {
+      /* pure gaussian fit mags */
+      ellipse (starpar[i][4], starpar[i][5], starpar[i][6], &area, &amajor, &aminor, &tilt);
+      tmp = area*starpar[i][1]/eperdn;
+      if (tmp > 0.0) fmag = -2.5 * log10 (tmp);
+      /* galaxy-non-gauss fit mags */
+      ellipse (shadow[i][4], shadow[i][5], shadow[i][6], &area, &amajor, &aminor, &tilt);
+      gcorr = 1.0;
+      tmp = area*gcorr*shadow[i][1]/eperdn;
+      if (tmp > 0.0) gmag = -2.5 * log10 (tmp);
+      tilt = 57.29578 * tilt;
+    } else {
+      /* get correct orientation for oblit boxes */
+      if (starpar[i][5] != -1) fmag = -99.999;
+      if (starpar[i][4] >= starpar[i][6]) {
+	amajor = starpar[i][4];
+	aminor = starpar[i][6];
+	tilt = 0.0;
+      } else {
+	amajor = starpar[i][6];
+	aminor = starpar[i][4];
+	tilt = 90.0;
+      }
+    }
+         
+    /* what is the value of the center of a pixel? */
+    /* this assumes the pixel center is at 0,0, not 0.5, 0.5 */
+    xc = starpar[i][2];
+    yc = starpar[i][3];
+
+    if (apple[i][1] > 0.0) apmag = -2.5 * log10 (apple[i][1]/eperdn);
+         
+    Nchar = snprintf (line, NCHAR, "%3d %8.2f %8.2f %8.3f %6.3f %9.2f %9.3f %9.3f %7.2f %8.3f %8.3f  %8.2f",
+	     imtype[i], xc, yc, fmag, apple[i][4], shadow[i][0], amajor, aminor, tilt, 
+	     gmag, apmag, rchisq[i]);
+    if (Nchar != NCHAR - 1) {
+      mprint (1, "funny line %d\n", i);
+    }
+    fprintf (f, "%s\n", line);
+  }         
+
+  /*
+  1    37.51  1193.91  -15.246   .034    594.48     6.657     5.654   -7.06  -15.611  -15.822
+  */  
+  fclose (f);
+
+  return (0);
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/oblims.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/oblims.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/oblims.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "gophot.h"
+
+oblims (float *star, int *jrect) {
+
+  float temp, fudgex, fudgey;
+
+  if (star[1] > 0) {
+    /* think about this line: */
+    temp = pow ((6*star[1]/nphob), 0.33333333);
+    if (star[4] > 0) {
+      fudgex = sqrt(temp*star[4]*2);
+    } else {
+      fudgex = 10;
+    }
+    if (star[6] > 0) {
+      fudgey = sqrt(temp*star[6]*2);
+    } else {
+      fudgey = 10;
+    }
+  } else {
+    fudgex = 10;
+    fudgey = 10;
+  }
+
+  mprint (3, "fudge size: %f %f\n", fudgex, fudgey);
+  jrect[1] = star[2] - fudgex;
+  jrect[2] = star[2] + fudgex;
+  jrect[3] = star[3] - fudgey;
+  jrect[4] = star[3] + fudgey;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/oblit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/oblit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/oblit.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "gophot.h"
+
+bool oblit (float *star) {
+
+  bool value;
+	
+  float wx, wy, dum, duma[NPMAX];
+  int ix, iy, ixhi, ixlo, iyhi, iylo, jx, jy;
+	
+  dum = guess2 (duma, star, &ix, &iy);
+  wx = star[4];				
+  wy = star[6];
+
+  ixhi = MIN ((int)(ix + 0.5*wx + 0.5), nfast-1);
+  ixlo = MAX ((int)(ix - 0.5*wx + 0.5), 0);
+  iyhi = MIN ((int)(iy + 0.5*wy + 0.5), nslow-1);
+  iylo = MAX ((int)(iy - 0.5*wy + 0.5), 0);
+
+  mprint (3, "obliterating following region : %d - %d, %d - %d\n", ixlo, ixhi, iylo, iyhi);
+  for (jy = iylo; jy <= iyhi; jy++) {
+    for (jx = ixlo; jx <= ixhi; jx++) {
+      big[jx+jy*nfast] = MAGIC;
+      noise[jx+jy*nfast] = MAGIC;
+    }
+  }
+
+  mprint (2, "obliteration: %d, %d (%f x %f)\n", ix, iy, wx, wy);
+
+  return (TRUE);
+
+}
+
+	
+	
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/offpic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/offpic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/offpic.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "gophot.h"
+
+bool offpic (float *star, int ix, int iy, float *dx, float *dy) {
+
+  bool nogood;
+  float x, y;
+
+  x = ix + star[2];
+  y = iy + star[3];
+  
+  *dx = 0;
+  if (x < 0) *dx = -x;
+  if (x > nfast) *dx = x - nfast;
+	
+  *dy = 0;
+  if (y < 0) *dy = -y;
+  if (y > nslow) *dy = y - nslow;
+	
+  nogood = (*dx != 0) || (*dy != 0);
+
+  if (!fixpos) nogood = nogood || (star[1] < 0);
+
+  return (nogood);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/outline.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/outline.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/outline.c	(revision 16632)
@@ -0,0 +1,188 @@
+# include "gophot.h"
+
+int Npts;
+float *xv, *yv, *zv;
+float par[5];
+float dpar[5];
+float outline_chi (float);
+
+/* fit pars[5] to ellipse at Xo, Yo, dX, dY */
+int outline (float Xo, float Yo, float dX, float dY, float Io, float dIo, float *pars) {
+  
+  int i, j, k, Nx, Ny, NPTS, BigChange, ABigChange;
+  float oChi, dchi, Chi, Chi_p, Chi_m, dp, tmp_par, nChi, tmp1, tmp2;
+  float curve, frac, value;
+
+  par[0] = Xo;
+  par[1] = Yo;
+  par[2] = dX;
+  par[3] = dY;
+  par[4] = 0.0;
+
+  dpar[0] = 10;
+  dpar[1] = 10;
+  dpar[2] = 10;
+  dpar[3] = 10;
+  dpar[4] = 10;
+
+  /* find all pixels within range Io-dIo : Io+dIo, in region about center guess */
+
+  Npts = 0;
+  NPTS = 1000;
+  ALLOCATE (xv, float, NPTS);
+  ALLOCATE (yv, float, NPTS);
+  ALLOCATE (zv, float, NPTS);
+  for (j = par[1]-2*par[3]; j < par[1]+2*par[3]; j++) {
+    if (j < 0) continue;
+    if (j >= nslow) continue;
+    for (i = par[0]-2*par[2]; i < par[0]+2*par[2]; i++) {
+      if (i < 0) continue;
+      if (i >= nfast) continue;
+      value = big[i + nfast*j];
+      if (fabs (value - Io) < dIo) {
+	xv[Npts] = i;
+	yv[Npts] = j;
+	zv[Npts] = value;
+	Npts ++;
+	if (Npts == NPTS) {
+	  NPTS += 1000;
+	  REALLOCATE (xv, float, NPTS);
+	  REALLOCATE (yv, float, NPTS);
+	  REALLOCATE (zv, float, NPTS);
+	}
+      }
+    }
+  }
+
+  if (Npts == 0) {
+    fprintf (stderr, "no valid points in box, try again\n");
+    free (xv);
+    free (yv);
+    free (zv);
+    return (FALSE);
+  }
+
+  Chi = outline_chi (Io);
+  for (j = 0; j < 15; j++) {
+    
+    oChi = Chi;
+    for (i = 0; i < 5; i++) {
+      /* find +Chi, -Chi for this par & adjust par as needed */
+
+      for (k = 0, BigChange = TRUE; (k < 3) && BigChange; k++) {
+	tmp_par = par[i];
+	par[i] = tmp_par + dpar[i];
+	Chi_p = outline_chi (Io);
+	par[i] = tmp_par - dpar[i];
+	Chi_m = outline_chi (Io);
+	
+	/* have we braketted a minimum? (curve < 0) */
+	curve = (Chi_p - Chi) * (Chi - Chi_m);
+	if (curve > 0) {
+	  dp = 2*dpar[i];
+	} else {
+	  dp = 0.5 * dpar[i] * (Chi_m - Chi_p) / (Chi_m + Chi_p - 2*Chi);
+	}      
+	if (Chi_m + Chi_p - 2*Chi == 0) dp = 0;
+	/* don't let extrapolation go too far */
+	if (fabs (dp) > 2*fabs(dpar[i])) { dp = SIGN(dp) * fabs (2*dpar[i]); }
+	
+	par[i] = tmp_par + dp;
+	Chi = outline_chi (Io);
+	
+	BigChange = FALSE;
+	if (Chi <= 1.001*oChi) {
+	  /* got better */
+	  dchi = (oChi - Chi) / oChi; 
+	  if ((dchi > 0.03) || (curve > 0)) BigChange = TRUE;
+	} else {
+	  par[i] = tmp_par;
+	  Chi = oChi;
+	  if (Chi_m < Chi) {
+	    Chi = Chi_m;
+	    par[i] = tmp_par - dpar[i];
+	  }	
+	  if (Chi_p < Chi) {
+	    Chi = Chi_p;
+	    par[i] = tmp_par + dpar[i];
+	  }	
+	}	
+	oChi = Chi;
+      }
+      if (!BigChange) dpar[i] *= 0.8;
+    }
+
+    mprint (0, "try: %d  %f   ", j, Chi);
+    for (i = 0; i < 5; i++) {
+      mprint (0, "%f ", par[i]);
+    }
+    mprint (0, "\n");
+    for (i = 0; i < 5; i++) {
+      mprint (2, "%f ", dpar[i]);
+    }
+    mprint (2, "\n");
+    dchi -= Chi;
+
+  }
+
+  free (xv);
+  free (yv);
+  free (zv);
+  
+  pars[0] = par[0];
+  pars[1] = par[1];
+  pars[2] = par[2];
+  pars[3] = par[3];
+  pars[4] = par[4];
+  return (TRUE);
+
+}
+
+/* par[0] = x
+   par[1] = y
+   par[2] = dx
+   par[3] = dy
+   par[4] = dxy
+   
+    xp = par[2] * cos (t);
+    yp = par[3] * sin (t);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+*/
+
+float outline_chi (float Io) {
+
+  int i;
+  float theta, phi;
+  float xp, yp, x, y;
+  float Chi, dv, Dv, R2, F2;
+  float cs, sn;
+
+  Chi = 0;
+
+  cs = cos (par[4] * RAD_DEG);
+  sn = sin (par[4] * RAD_DEG);
+
+  for (i = 0; i < Npts; i++) {
+    
+    phi = atan2 (yv[i] - par[1], xv[i] - par[0]) - RAD_DEG * par[4];
+    theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+
+    /* this is the point on the ellipse at the same angle as ref point */
+    xp = par[2] * cos (theta);
+    yp = par[3] * sin (theta);
+    
+    x = xp * cs - yp * sn + par[0];
+    y = xp * sn + yp * cs + par[1];
+
+    R2 = sqrt (SQ (x - xv[i]) + SQ (y - yv[i]));
+    Chi += R2;
+
+  }
+
+  Chi = Chi / Npts;
+  return (Chi);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/paravg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/paravg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/paravg.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "gophot.h"
+
+sortkey (int *index, float *key, int N) {
+
+# define SWAPFUNC(A,B){ \
+  int   itmp; itmp = index[A]; index[A] = index[B]; index[B] = itmp; \
+  float ftmp; ftmp = key[A]; key[A] = key[B]; key[B] = ftmp; \
+}
+# define COMPARE(A,B)(key[A] < key[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+paravg () {
+
+  float sum[NPMAX][2];
+  int i, j, n;
+  FILE *f;
+  char c;
+  float *ave4, *ave5, *ave6, *key;
+  int Ngood, NGOOD, *index, *idx;
+  int Nave;
+  float a4, a5, a6;
+
+  for (j = 0; j < NPAR; j++) {
+    sum[j][0] = 0;
+    sum[j][1] = 0;
+  }
+  
+  if (nstot < 1) return (0);
+
+  NGOOD = 100;
+  Ngood = 0;
+  ALLOCATE (index, int, NGOOD);
+
+  /* find good stars, store index */
+  for (i = 0; i < nstot; i++) {
+    if (starpar[i][1] < 100) continue;
+    if ((imtype[i] == 1) || (imtype[i] == 101)) {
+      index[Ngood] = i;
+      Ngood ++;
+      if (Ngood == NGOOD) {
+	NGOOD += 100;
+	REALLOCATE (index, int, NGOOD);
+      }
+    }
+  }
+  for (i = 0; i < Ngood; i++) {
+    fprintf (stderr, "S: %d %d %d  %f %f   %f %f\n", i, index[i], imtype[index[i]], starpar[index[i]][1], shaderr[index[i]][1], starpar[index[i]][4], shadow[index[i]][4]);
+  }
+
+  /* find good stars, store index */
+  if (Ngood < 10) { /* accept type 2 as well... */
+    for (i = 0; i < nstot; i++) {
+      if ((imtype[i] == 2) || (imtype[i] == 102)) {
+	index[Ngood] = i;
+	Ngood ++;
+	if (Ngood == NGOOD) {
+	  NGOOD += 100;
+	  REALLOCATE (index, int, NGOOD);
+	}
+      }
+    }
+  }
+
+  if (Ngood > 10) { /* don't change if not enough 'stars' */
+    
+    ALLOCATE (ave4, float, Ngood);
+    ALLOCATE (ave5, float, Ngood);
+    ALLOCATE (ave6, float, Ngood);
+    ALLOCATE (key,  float, Ngood);
+    ALLOCATE (idx,  int, Ngood);
+    
+    for (i = 0; i < Ngood; i++) {
+      idx[i] = i;
+      key[i] = shadow[index[i]][4];
+      ave4[i] = shadow[index[i]][4];
+      ave5[i] = shadow[index[i]][5];
+      ave6[i] = shadow[index[i]][6];
+    }
+    sortkey (idx, key, Ngood);
+
+    a4 = a5 = a6 = Nave = 0;
+    for (i = 0.4*Ngood; i < 0.6*Ngood; i++) {
+      a4 += ave4[idx[i]];
+      a5 += ave5[idx[i]];
+      a6 += ave6[idx[i]];
+      Nave ++;
+    }
+    ava[4] = a4/Nave;
+    ava[5] = a5/Nave;
+    ava[6] = a6/Nave;
+
+    free (key);
+    free (idx);
+    free (ave4);
+    free (ave5);
+    free (ave6);
+  }
+  free (index);
+  
+
+  mprint (1, "%d stars used to find parameter averages\n", Ngood);
+  mprint (1, "average values so far of shape parameters for stars: \n");
+  for (j = 4; j < NPAR; j++) mprint (1, "%f ", ava[j]);
+  mprint (1, "\n");
+
+}
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/parinterp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/parinterp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/parinterp.c	(revision 16632)
@@ -0,0 +1,10 @@
+# include "gophot.h"
+
+float parinterp (float x, float y, float *star) {
+
+  star[4] = ava[4];
+  star[5] = ava[5];
+  star[6] = ava[6];
+  
+  return (star[0]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/parupd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/parupd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/parupd.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "gophot.h"
+
+parupd (float *instar, float *outstar, int ix, int iy) {
+
+	outstar[0] = instar[0]*ufactor;
+	outstar[1] = instar[1]*ufactor;
+	outstar[2] = instar[2] + ix;
+	outstar[3] = instar[3] + iy;
+	outstar[4] = instar[4];
+	outstar[5] = instar[5];
+	outstar[6] = instar[6];
+}
+
+/* a legacy function 
+twoupd (float *instar, float *outstar, int ix, int iy) {
+
+	outstar[0] = instar[0];
+	outstar[1] = instar[1];
+	outstar[2] = instar[2] + ix;
+	outstar[3] = instar[3] + iy;
+	outstar[4] = instar[4];
+	outstar[5] = instar[5] + ix;
+	outstar[6] = instar[6] + iy;
+}
+*/
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/pseud2d.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/pseud2d.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/pseud2d.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "gophot.h"
+
+# define HALF 0.5
+# define THIRD 0.333
+# define EXPMIN -15.0
+
+float pseud2d (int ix, int iy, float *a, float *fa) {
+
+  double x, y, t5, t6, t7, T;
+  double denom, dt, pexp, R;
+  double Q;
+  float value;
+  int i;
+
+  x = ix - a[2];
+  y = iy - a[3];
+       
+  t6 = a[5]*y;
+  t5 = x/a[4];
+  t7 = y/a[6];
+
+  T = 0.5*((t5 + 2.0*t6)*x + t7*y);
+  
+  if (!finite (a[1])) fprintf (stderr, "bad star!\n");
+
+  if (T >= 0) { 
+    denom = 1.0 + T*(beta4 + HALF*beta64*T*(1.0 + THIRD*T));
+    pexp = 1.0 / denom; 
+    dt = beta4 + beta64*T*(1.0 + HALF*T);
+    if (!finite (pexp)) {
+      fprintf (stderr, "error in pseud2d: %f %f %f %d %d\n", T, denom, pexp, ix, iy); 
+      denom = 1.0 + T + HALF*beta4*T*T + THIRD*beta64*T*T*T;
+      pexp = 1.0 / denom;
+      if (!finite (pexp)) { 
+	fprintf (stderr, "error in pseud2d: %f %f %f %d %d\n", T, denom, pexp, ix, iy);
+	fprintf (stderr, "%f %f   %f %f %f\n", x, y, t5, t6, t7); 
+	fprintf (stderr, "%f %f %f\n", T, T*HALF*beta4*T, T*HALF*beta4*T*THIRD*beta64*T);
+	for (i = 0; i < 7; i++) fprintf (stderr, "%d %f\n", i, a[i]);
+	fprintf (stderr, "nstot: %d\n", nstot);
+	fprintf (stderr, "invalid value!\n");
+	exit (1);
+      } 
+    }
+   } else {
+    denom = MAX (T, EXPMIN);
+    denom = fabs (denom);
+    pexp = exp (denom);
+    denom = 1.0;
+    dt = 1.0;
+  }
+
+  value = a[1]*pexp;
+
+  if (fa != (float *) NULL) {
+    R = value*dt/denom;
+    fa[1] = pexp;
+    fa[2] = R*(t5 + t6);
+    fa[3] = R*(a[5]*x + t7);
+    fa[4] = R*t5*t5*0.5;
+    fa[6] = R*t7*t7*0.5;
+    
+    fa[5] = -R*x*y;
+    fa[0] = 1.0;
+  }
+
+  value += + a[0];
+
+  if (!finite(value)) {
+    fprintf (stderr, "error in pseud2d: %f %f %f %f\n", T, denom, pexp, a[1]);
+    exit (1);
+  }
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
+/* a[0] - sky
+   a[1] - Io
+   a[2], a[3] - X, Y
+   a[4], a[5], a[6] - shape
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/pseud4d.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/pseud4d.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/pseud4d.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "gophot.h"
+
+# define HALF 0.5
+# define THIRD 0.33333333333333
+# define EXPMIN -15
+
+float pseud4d (int ix, int iy, float *a, float *fa) {
+
+  int i, ioff;
+  float x, y;
+  float denom, T, dt, pexp[2];
+  float a2, a5, a6, a7, t5, t6, t7, value;
+	
+  a5 = 1.0/a[7];
+  a7 = 1.0/a[9];
+  a6 = a[8];
+  
+  for (i = 0; i < 2; i++) {
+
+    ioff = 3*i;
+    x = ix - a[2 + ioff];
+    y = iy - a[3 + ioff];
+       
+    t5 = a5*x;
+    t6 = a6*y;
+    t7 = a7*y;
+    T = HALF*((t5 + 2*t6)*x + t7*y);
+	   
+    if (T > 0) {
+      denom = 1.0 + T*(1.0 + HALF*beta4*T*(1.0 + THIRD*beta64*T));
+      pexp[i] = 1./denom;
+    } else {
+      denom = MAX (T, EXPMIN);
+      denom = fabs (denom);
+      pexp[i] = exp (denom);
+      denom = 1.0;
+    }
+
+    a2 = exp(a[1 + ioff]);
+    value = a2*pexp[i];
+    pexp[i] = value;
+    
+    if (fa != (float *) NULL) {
+      if (T > 0) {
+	dt = 1.0 + beta4*T*(1.0 + HALF*beta64*T);
+      } else {
+      	dt = 1.0;
+      }
+      fa[1 + ioff] = value;
+      T = pexp[i]*dt/denom;
+      fa[2 + ioff] = (a5*x + a6*y)*T;
+      fa[3 + ioff] = (a6*x + a7*y)*T;
+      
+      fa[0] = 1;
+    }      
+  }
+
+  value = pexp[0] + pexp[1] + a[0];
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
+
+/* a[0] - sky
+   a[1] - I1
+   a[2], a[3] - X1, Y1
+   a[4] - I2
+   a[5], a[6] - X2, Y2
+   a[7], a[8], a[9] - shape
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/set_thresholds.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/set_thresholds.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/set_thresholds.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "gophot.h"
+
+float set_thresholds (float sky, float dSky, float *factor, int *Nit) {
+
+  float dsky, tmp;
+
+  /* tmin starts with Nsigma above sky */
+
+  dsky = sqrt(sky + rnoise);
+  fprintf (stderr, "dsky: %f %f %f %f\n", rnoise, sky, dsky, dSky);
+  dsky = MAX (dsky, dSky);
+  tmin = tmin * dsky;
+
+  mprint (0, "gain is %f, median sky is %f, min threshold is %f\n",
+	  eperdn, sky, tmin);
+
+  /* set starting threshold */
+  tmp = pow (2.0, tfac);
+  tmax = 0.5*itop;
+  *Nit  = log (tmax / tmin) / log (tmp);
+  *factor = pow ((tmax / tmin), (1.0 / *Nit));
+
+  return (tmax);
+
+}
+
+/* we are going to evenly divide the range from 
+   sky + tmin*dsky to 0.5*itop in slices with ratios 
+   close to tfac */
+
+/* images with very messy backgrounds should not be pushed to the 
+   absolute minimum.  We let the sky sigma be the max of the 
+   formal and the measured sigmas */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/shape.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/shape.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/shape.c	(revision 16632)
@@ -0,0 +1,267 @@
+# include "gophot.h"
+
+# define ZERO_SHADOW {shadow[i][0] = 0; \
+	              shadow[i][1] = 0; \
+	              shadow[i][4] = 1; \
+                      shadow[i][5] = 0; \
+                      shadow[i][6] = 1; }
+
+/* try 7 par fit for each object, decide on object types */
+shape () {
+
+  bool notnuff, gotfaint, verybig, offp, converge;
+
+  /* watch twofpar - i think we only need 2 entries, for storage in this loop */
+  float star[NPMAX], err[NPMAX], star1[NPMAX], star2[NPMAX];
+  float sky, galchi, dx, dy, starchi;
+  int i, j, n, k, ix, iy, jmtype, nsprev;
+
+  test7 = TRUE;
+  nsprev = nstot;
+
+  for (i = 0; i < nsprev; i++) {
+    mprint (3, " determining shape for object no. %d\n", i);
+
+    gotfaint = FALSE;
+    fixxy = imtype[i] >= 100;
+    jmtype = (fixxy) ? imtype[i] - 100 : imtype[i];
+	   
+    switch (jmtype) {
+    case 7:
+      mprint (3, "too faint, skipping object %d at %f, %f\n", i, starpar[i][2], starpar[i][3]);
+      continue;
+      break;
+    case 4:
+    case 9:
+      mprint (3, "nonconverge, skipping object %d at %f, %f\n", i, starpar[i][2], starpar[i][3]);
+      continue;
+      break;
+    case 8:
+    case 18:
+    case 6:
+    case 16:
+      mprint (3, "poor obj, skipping object %d at %f, %f\n", i, starpar[i][2], starpar[i][3]);
+      ZERO_SHADOW;
+      continue;
+      break;
+    }
+
+    if (shadow[i][0] == 0) {
+      sky = guess2 (star, starpar[i], &ix, &iy);
+    } else {
+      sky = guess2 (star, shadow[i], &ix, &iy);
+    }
+
+    addstar (starpar[i], ADD, jmtype);
+
+    nrect[1] = irect[1];
+    nrect[2] = irect[2];
+    fillerup (ix, iy, FALSE);
+    notnuff = (npt < enuff7*irect[1]*irect[2]);
+
+    if (notnuff) {
+      mprint (3, "obj %d, npts %d, %d & %d - skipping star: not enough pixels for 7-parm fit \n", i, npt, ix, iy);
+      if (jmtype != 2) jmtype = 5;
+      if (jmtype == 12) beta4 = 0.01;
+      addstar (starpar[i], SUB, jmtype);
+      beta4 = 1.0;
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+
+    if (fixxy) {
+      gotfaint = !transmask (ix, iy, sky);
+      if (gotfaint) { 
+	if (jmtype != 3) jmtype = 7;
+	mprint (3, "obj %d, npts %d, %d & %d - skipping star: too faint for 7 par fit\n", i, npt, ix, iy);
+	addstar (starpar[i], SUB, jmtype);
+	imtype[i] = fixxy ? jmtype + 100 : jmtype;
+	continue;
+      }
+    }
+
+    filladjust (star); 
+    mprint (2, "obj %d, npts %d, %d & %d\n", i, npt, ix, iy);
+
+    /* fit 'extended' to star (7 parameter fit) */
+    galchi = chisq (onestar, xs, ys, zs, dzs, npt, star, err, NFIT2, acc, parlim, nit);
+    /*
+    if (finite(galchi) && ((err[4] > 0.25) || (err[6] > 0.25))) {
+      fprintf (stderr, "7 errors: %d %d  %f %f   %f %f   %f\n", ix, iy, err[2], err[3], err[4], err[6], galchi/npt);
+      fprintf (stderr, "                 %f %f   %f %f\n", star[2], star[3], star[4], star[6]);
+    }
+    */
+    if (fabs(star[5]) >= 1.0 / sqrt(fabs(star[4]*star[6]))) {
+      mprint (3, "hyperbola!  problem with %d at %f %f\n", i, starpar[i][2], starpar[i][3]);
+      /* just a warning... */
+    }
+    if ((star[4] > SQ(0.25*nrect[1])) || (star[6] > SQ(0.25*nrect[1]))) {
+     mprint (3, "warning - dubious fit for %d at %f %f\n", i, starpar[i][2], starpar[i][3]);
+      /* just a warning... */
+    } 
+    if (!finite (galchi)) {
+      /* shadow, starpar keep 4-par fit */
+      mprint (3, "non-converge object %d at %f %f\n", i, starpar[i][2], starpar[i][3]);
+      if (jmtype != 3) jmtype = 9;
+      mprint (3, "obj %d, npts %d, %d & %d .... failed to converge\n", i, npt, ix, iy);
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+    
+    /* is new fit position reasonable? */
+    if (centertest (star, xs, ys, npt) || (fabs(star[2]) > 0.33*nrect[1]) || (fabs(star[3]) > 0.33*nrect[2])) {
+      mprint (3, "fit center moved 2: %f %f  %f %f\n", starpar[i][2], starpar[i][3], star[2], star[3]);
+      jmtype = 16;
+      /* shadow, starpar keep 4-par fit */
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+      
+    /* calculate error here for type 2, 10. redone in improve for 1, 3, 5, 7 */
+    apple[i][4] = MIN (1, 1.086*sqrt(err[1])/star[1]);
+    rchisq[i] = galchi / npt;
+
+    /* save 7-par fit in shadow */
+    parupd (star, shadow[i], ix, iy);
+    for (j = 0; j < NPAR; j++) shaderr[i][j] = err[j];
+	
+    /* allow type 10 to go back to 1 and vice-versa */
+    if ((jmtype == 10) && !verybright (starpar[i])) jmtype = 1;
+    if (verybright (starpar[i])) jmtype = 10;
+
+    if (jmtype == 10) {
+      mprint (3, " very bright, keep 7 par fit only\n");
+
+      if ((thresh < tmax / 4) && (thresh > tmax/16)) {
+	/* test if type 10 can be safely split in two */
+	starchi = twofit (star, starpar[i], star1, star2);
+	/* has to be a really significant improvement */
+	if (finite(starchi) && (starchi/galchi < 10*stograt) && (starchi < 10*npt)) {
+	  mprint (3, " result-> a split star: gal-chi: %f, star-chi: %f\n", galchi, starchi);
+	  jmtype = 3;
+	  parupd (star1, shadow[i], ix, iy);
+	  parupd (star1, starpar[i], ix, iy);
+	  addstar (starpar[i], SUB, jmtype);
+	  imtype[nstot] = 3;
+	  parupd (star2, starpar[nstot], ix, iy);
+	  parupd (star2, shadow[nstot], ix, iy);	
+	  addstar (starpar[nstot], SUB, jmtype);
+	  nstot ++;
+	  continue;
+	}
+      }
+      parupd (star, starpar[i], ix, iy);
+
+      if ((thresh < tmax / 4) && (thresh > tmax/16)) {
+
+	float err2[NPMAX], galchi2;
+
+	beta4 = 0.01;
+	for (n = 0; n < NPMAX; n++) star2[n] = star[n];
+	galchi2 = chisq (onestar, xs, ys, zs, dzs, npt, star2, err2, NFIT2, acc, parlim, nit);
+	if (1.2*galchi2 < galchi) {
+	  jmtype = 12;
+	  parupd (star2, starpar[i], ix, iy);
+	  mprint (3, "extended: %f vs %f  %f %f  %f -   %d\n", galchi/npt, galchi2/npt, starpar[i][2], starpar[i][3], star[1], jmtype);
+	}
+	beta4 = 1.0;
+      }
+
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+      
+    verybig = galaxy (star, shaderr[i], starpar[i]);
+    if (jmtype == 3) verybig = verybig && (chi[4] > xtra);
+
+    /* shouldn't this test come earlier? */
+    converge = finite(galchi);
+    offp = offpic (star, ix, iy, &dx, &dy);
+    verybig = verybig && !offp && converge;;
+
+    if (!verybig || fixxy) {
+      if (jmtype != 3) jmtype = 1;
+      if (!converge) {
+	if (jmtype != 3) jmtype = 9;
+	mprint (3, "obj %d, npts %d, %d & %d .... failed to converge\n", i, npt, ix, iy);
+	addstar (starpar[i], SUB, jmtype);
+	imtype[i] = fixxy ? jmtype + 100 : jmtype;
+	continue;
+      }
+      if (offp) {
+	jmtype = 9;
+	imtype[i] = fixxy ? jmtype + 100 : jmtype;
+	mprint (3, "obj %d, npts %d, %d & %d .... fit center outside fit subraster\n", i, npt, ix, iy);
+      }
+      addstar (starpar[i], SUB, jmtype);
+      imtype[i] = fixxy ? jmtype + 100 : jmtype;
+      continue;
+    }
+	   
+    mprint (3, "obj %d, npts %d, %d & %d .... is very big....\n", i, npt, ix, iy);
+    mprint (3, ".... testing galaxy vs. double-star \n");
+    
+    starchi = twofit (star, starpar[i], star1, star2);
+
+    if (finite(starchi) && (starchi/galchi < stograt)) {
+      mprint (3, " result-> a split star: gal-chi: %f, star-chi: %f\n", galchi, starchi);
+      jmtype = 3;
+      parupd (star1, shadow[i], ix, iy);
+      parupd (star1, starpar[i], ix, iy);
+      addstar (starpar[i], SUB, jmtype);
+      imtype[nstot] = 3;
+      parupd (star2, starpar[nstot], ix, iy);
+      parupd (star2, shadow[nstot], ix, iy);	
+      addstar (starpar[nstot], SUB, jmtype);
+      nstot ++;
+    } else {
+      mprint (3, " result-> a galaxy: gal-chi: %f, star-chi: %f\n", galchi, starchi);
+      jmtype = 2;
+      parupd (star, starpar[i], ix, iy);
+      if (star[1]*star[4]*star[6]*ufactor > 20000) {
+	float err2[NPMAX], galchi2;
+
+	beta4 = 0.01;
+	for (n = 0; n < NPMAX; n++) star2[n] = star[n];
+	galchi2 = chisq (onestar, xs, ys, zs, dzs, npt, star2, err2, NFIT2, acc, parlim, nit);
+	if (1.2*galchi2 < galchi) {
+	  jmtype = 12;
+	  parupd (star2, starpar[i], ix, iy);
+	}
+	/* fprintf (stderr, "extended: %f vs %f  %f %f  %f -   %d\n", galchi/npt, galchi2/npt, starpar[i][2], starpar[i][3], star[1], jmtype);
+	 */
+	beta4 = 1.0;
+      }
+      addstar (starpar[i], SUB, jmtype);
+    }
+    imtype[i] = fixxy ? jmtype + 100 : jmtype;
+  }
+  test7 = FALSE;
+}
+
+
+
+/*****************
+
+  This routine seems really poorly written.  there is too much obfuscation.
+
+  we just need to do a few things:
+
+  1) do we try this object with 7-par fit? (if no, continue)
+
+  2) fit the object with 7-par fit
+
+  3) did it succeed? (if no, set some types)
+
+  4) should it be a type 10? (ie, very bright)
+
+  5) should it be a type 2? (ie, significantly extended)
+
+  6) should if be a type 3? (ie, split in two)
+
+  7) should it be a type 12? (ie, hubble fit)
+
+******************/
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/skyfun_plane.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/skyfun_plane.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/skyfun_plane.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "gophot.h"
+
+# define HALF 0.5
+
+float skyfun_plane (int ix, int iy, float *a, float *fa) {
+	
+  int i;
+  float value;
+
+  fa[0] = 1.0;
+  fa[1] = HALF*(ix - HALF*nfast)/(HALF*nfast);
+  fa[2] = HALF*(iy - HALF*nslow)/(HALF*nslow);
+
+  value = 0;
+  for (i = 0; i < 1; i++) {
+    value += a[i]*fa[i];
+  }
+
+  return (value);
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/toobright.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/toobright.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/toobright.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "gophot.h"
+
+bool toobright (float *star) {
+
+  bool value;
+  bool flag;
+  int jrect[5];
+  int nsat, nbad, ix, iy, ixhi, ixlo, iyhi, iylo, jx, jy;
+  float dum, duma[NPMAX];
+
+  value = FALSE;
+	
+  if (star[1] < itop/4) return (FALSE);
+
+  nsat = 0;
+  nbad = 0;
+  dum = guess2 (duma, star, &ix, &iy);
+  ixhi = MIN ((int)(ix + krect[1]/2 + 0.5), nfast - 1);
+  ixlo = MAX ((int)(ix - krect[1]/2 + 0.5), 0);
+  iyhi = MIN ((int)(iy + krect[2]/2 + 0.5), nslow - 1);
+  iylo = MAX ((int)(iy - krect[2]/2 + 0.5), 0);
+
+  for (jy = iylo; jy <= iyhi; jy++) {
+    for (jx = ixlo; jx <= ixhi; jx++) {
+      if (!finite (noise[jx+jy*nfast])) nbad ++;
+      if (big[jx+jy*nfast] >= itop) nsat ++;
+    }
+  }
+
+  value = (star[1] > cmax) || (nsat >= icrit) || (nbad >= icrit);
+
+  mprint (3, "object at: %d, %d - %d:  %d %d %f %f %f\n", ix,iy, value, nsat, nbad, star[1], big[ix+iy*nfast], noise[ix+iy*nfast]);
+
+  if (value) {
+    if (nsat >= icrit)  star[1] = ctpersat*nsat;
+    
+    oblims(star,jrect);
+    
+    star[4] = jrect[2] - jrect[1];
+    star[5] = nsat;
+    star[6] = jrect[4] - jrect[3];
+    
+    mprint (0, "%d, %d funny pixels in object at %d, %d (%f peak)\n", nsat, nbad, ix, iy, star[1]);
+  }
+
+  return (value);
+}
+
+bool verybright (float *star) {
+
+  float flux;
+
+  /* rough scaling to compare fits with different scale */
+
+  flux = star[1]*sqrt((star[4]*star[6])/(ava[4]*ava[6]));;
+
+  if (flux > cmax) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/toofaint.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/toofaint.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/toofaint.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "gophot.h"
+
+bool toofaint (float *star, float *err) {
+
+  bool value;
+  float cmin, sig2;
+
+  cmin = 1.0;
+  value = (star[1] < cmin);
+
+  if (err[1] > 0) {
+    sig2 = SQ(star[1]/ufactor) / err[1];
+    value = value || (sig2 < crit7);
+    mprint (3, "sig2 = %f (%f %f %f)\n", sig2, star[1], ufactor, err[1]);
+    mprint (3, "value, crit7: %d, %f\n", value, crit7);
+  }
+
+  return (value);
+
+}
+
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/transmask.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/transmask.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/transmask.c	(revision 16632)
@@ -0,0 +1,94 @@
+# include "gophot.h"
+
+bool transmask (int ix, int iy, float sky) {
+
+  bool value;
+  int i, j, ii, jj;
+  float tmp, tmp0, tmp1, tmp2, ratio, hump2;
+  float tmpB, tmpN, df;
+  float *Bval, *Nval, cval, tmp3;
+
+  value = FALSE;
+
+  if (test7) 
+    hump2 = crit7;
+  else
+    hump2 = SQ (bumpcrit);
+
+  tmp0 = tmp1 = tmp2 = 0;
+  tmpB = tmpN = tmp3 = 0;
+
+  cval = big[ix + iy*nfast];
+
+  jj = iy - iyby2;
+  for (j = 0; j < 2*iyby2 + 1; j++, jj++) {
+    if (jj < 0) continue;
+    if (jj > nslow - 1) continue;
+    
+    ii = ix - ixby2;
+    Bval = &big[ii + jj*nfast];
+    Nval = &noise[ii + jj*nfast];
+    for (i = 0; i < 2*ixby2 + 1; i++, ii++, Bval++, Nval++) {
+      if (ii < 0) continue;
+      if (ii > nfast - 1) continue;
+      if (!finite (*Nval)) continue;
+
+# if (1)
+      tmp0 ++;
+      tmp = starmask[i][j] / (*Nval + *Bval);
+      tmp1 += tmp*starmask[i][j];
+      tmp2 += tmp*(*Bval-sky);
+      
+# else
+
+      tmp0 ++;
+      tmp1 += (*Nval + *Bval);
+      tmp2 += (*Bval - sky);
+
+      df = (cval - *Bval);
+      tmp3 +=  df * fabs(df) / (*Nval + *Bval);
+
+# endif
+
+      tmpB += (*Bval - sky);
+      tmpN += (*Nval - rnoise);
+    }
+  }
+
+  if (tmp0 == 0) return (FALSE);
+
+  if (tmpB < tmpN) return (FALSE);  
+
+  if (tmp2 > 0) {
+    ratio = tmp2*tmp2/tmp1;
+
+# if (1)
+    if (ratio > hump2) {
+      value = TRUE;
+      mprint (3, " trigger 1 on new object: %d, %d,  %f %f   %f %f %f\n", ix, iy, ratio, tmp3, sky, tmp2, tmp1);
+      if (ratio < 1.1*hump2) mprint (3, "marginal: (s/n)**2 through mask = %f\n", ratio);
+    }
+# else
+    if ((ratio > hump2) && (tmp3 > 0.25*ratio)) {
+      value = TRUE;
+      mprint (3, " trigger 1 on new object: %d, %d,  %f %f   %f %f %f\n", ix, iy, ratio, tmp3, sky, tmp2, tmp1);
+      if (ratio < 1.1*hump2) mprint (3, "marginal: (s/n)**2 through mask = %f\n", ratio);
+    }
+# endif
+
+  }
+
+  if (value) mprint (3, " trigger 2 on new object: %d, %d\n", ix, iy);
+
+  return (value);
+
+}
+
+
+  /* t1 = 1/N
+     t2 = d/N
+     rat = N d^2 / N^2 = d^2 / N
+  */
+
+/* does not check if bump is significant in region, 
+   only if mask region is significant over sky */
Index: /branches/eam_branch_20080223/Ohana/src/gophot/src/twofit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/gophot/src/twofit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/gophot/src/twofit.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include "gophot.h"
+
+/****************************************
+ there are big problems here with the values of b and probably 
+ other things.  fix please! */
+
+/* we are fitting two stars at the location of the input star */
+/* starraw has the real X,Y coords, star is relative to centroid */
+
+float twofit (float *star, float *starraw, float *star1, float *star2) {
+
+  int i;
+  float b[2*NPMAX], err[2*NPMAX], bacc[2*NPMAX], bparlim[2*NPMAX], tstar[NPMAX];
+  bool badfit, conv;
+  float a5, a7, angle, root, root1, root2, dx2, dy2, dx, dy, value;
+  float garea, sarea, dx74, dy74, dot, fac1, fac2, dxmax, dymax;
+
+  badfit = FALSE;
+  conv = TRUE;
+
+  /* fills in values 1, 5, 6, 7, 8 */
+  parinterp (starraw[2], starraw[3], tstar);
+
+  /* this all seems way too obtuse. */
+  a5 = 1.0/star[4];
+  a7 = 1.0/star[6];
+  angle = atan2 (-2*star[5], a7 - a5)/2.0;
+  root = sqrt (SQ(a5 - a7) + 4*SQ(star[5]));
+  root1 = (a5 + a7 + root)/2.0;
+  root2 = root1 - root;
+  dx2 = star[4] - tstar[4];
+  dy2 = star[6] - tstar[6];
+  dx = sqrt (MAX (dx2, 0.0)) / 2.0;
+  dy = sqrt (MAX (dy2, 0.0)) / 2.0;
+  badfit = (MAX (dx, dy) == 0);
+  /* we can use these since dx & dy are always >= 0 */
+  dx = (cos(angle) < 0) ? -dx : dx;
+  dy = (sin(angle) < 0) ? -dy : dy;
+  garea = 1.0 / sqrt (fabs (root1*root2));
+  sarea = sqrt (fabs (tstar[4]*tstar[6]));
+  dx74 = starraw[2] - star[2];	
+  dy74 = starraw[3] - star[3];		
+  dot = dx74*dx + dy74*dy;
+  if (dot > 0) {
+    fac1 = 0.6666666;
+    fac2 = 1.3333333;
+  } else {
+    fac1 = 1.3333333;
+    fac2 = 0.6666666;
+  }
+	   
+  /* 
+     b[0] - sky
+     b[1] - I1
+     b[2], b[3] - X1, Y1
+     b[4] - I2
+     b[5], b[6] - X2, Y2
+     b[7], b[8], b[9] - shape 
+  */
+
+  b[0] = star[0];
+  b[1] = (star[1]*garea*fac2 / (sarea*2));
+  b[2] = star[2] - dx*fac1;
+  b[3] = star[3] - dy*fac1;
+  b[4] = (star[1]*garea*fac1 / (sarea*2));		
+  b[5] = star[2] + dx*fac2;
+  b[6] = star[3] + dy*fac2;
+
+  /* for reasons unclear, the fit is done in ln(Io), not Io */
+  b[1] = log(b[1]);
+  b[4] = log(b[4]); 
+
+  b[7] = tstar[4];
+  b[8] = tstar[5];
+  b[9] = tstar[6];
+
+  bacc[0] = acc[0];
+  bacc[1] = bacc[4] = acc[1];
+  bacc[2] = bacc[5] = acc[2];
+  bacc[3] = bacc[6] = acc[3];
+
+  bparlim[0] = parlim[0];
+  bparlim[1] = bparlim[4] = parlim[1];
+  bparlim[2] = bparlim[5] = parlim[2];
+  bparlim[3] = bparlim[6] = parlim[3];
+
+  dxmax = MAX (fabs(b[2]), fabs(b[5]));
+  dymax = MAX (fabs(b[3]), fabs(b[6]));
+  badfit = badfit || (dxmax > irect[1]/2.0);
+  badfit = badfit || (dymax > irect[2]/2.0);
+
+  if (!badfit) {
+    value = chisq (twostar, xs, ys, zs, dzs, npt, b, err, NFIT2, bacc, bparlim, 2*nit);
+    conv = finite (value);
+  }
+	
+  dxmax = MAX (fabs(b[2]), fabs(b[5]));
+  dymax = MAX (fabs(b[3]), fabs(b[6]));
+  badfit = badfit || (dxmax > 0.4*irect[1]);
+  badfit = badfit || (dymax > 0.4*irect[2]);
+
+  if (conv) {
+    if (b[1] < b[4]) {
+      SWAP (b[1], b[4]);
+      SWAP (b[2], b[5]);
+      SWAP (b[3], b[6]);
+    }
+    
+    star1[0] = star2[0] = b[0];
+    star1[4] = star2[4] = b[7];
+    star1[5] = star2[5] = b[8];
+    star1[6] = star2[6] = b[9];
+    star1[1] = exp(b[1]);
+    star1[2] = b[2];
+    star1[3] = b[3];
+    star2[1] = exp(b[4]);
+    star2[2] = b[5];
+    star2[3] = b[6];
+  }
+
+  badfit = badfit || centertest (star1, xs, ys);
+  badfit = badfit || centertest (star2, xs, ys);
+  if (!conv || badfit) value = MAGIC;
+
+  return (value);
+}
+/* this function uses C 0,N-1 for a[], fa[] */
Index: /branches/eam_branch_20080223/Ohana/src/imclean/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/Makefile	(revision 16632)
@@ -0,0 +1,32 @@
+default: imclean
+help:
+	@echo "make options: imclean (default)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/imclean
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+imclean: $(BIN)/imclean.$(ARCH)
+install: $(DESTBIN)/imclean
+
+IMCLEAN = \
+$(SRC)/imclean.$(ARCH).o	$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/args.$(ARCH).o		$(SRC)/sort_stars.$(ARCH).o \
+$(SRC)/AdjustHeader.$(ARCH).o	$(SRC)/find_group.$(ARCH).o \
+$(SRC)/find_trails.$(ARCH).o	$(SRC)/find_line.$(ARCH).o \
+$(SRC)/wstars.$(ARCH).o	        $(SRC)/LoadStarsDophot.$(ARCH).o \
+$(SRC)/LoadStarsSex.$(ARCH).o	$(SRC)/LoadStarsChad.$(ARCH).o	\
+$(SRC)/wfits.$(ARCH).o
+
+$(IMCLEAN): $(INC)/imclean.h
+$(BIN)/imclean.$(ARCH): $(IMCLEAN)
Index: /branches/eam_branch_20080223/Ohana/src/imclean/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/imclean/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,12 @@
+
+- imclean-1-3 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+
+2005.10.20: imclean-1-2
+	minor changes to fix -Wall errors
+	fixed exit status
+	synched with libohana (v1.5) / libfits (v1.4) changes
+
+2005.07.06: imclean-1-1
+	some changes to use the autocoded version of the SMPData structure (was Stars)
+	support for both fits and text output formats
Index: /branches/eam_branch_20080223/Ohana/src/imclean/doc/VERSIONS
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/doc/VERSIONS	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/doc/VERSIONS	(revision 16632)
@@ -0,0 +1,10 @@
+
+tag names used by imclean:
+
+AG         : Comment
+imclean-1-0 : first version under CVS
+
+USES
+libfits-1-0
+libohana-1-0
+
Index: /branches/eam_branch_20080223/Ohana/src/imclean/include/imclean.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/include/imclean.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/include/imclean.h	(revision 16632)
@@ -0,0 +1,50 @@
+# include <ohana.h>
+# include <dvo.h>
+
+enum {DOPHOT, CHAD, SEXTRACT};
+
+int    MODE;
+int    FITS_OUTPUT;
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+int    PROVIDE_ASTROM;
+int    NEWPHOTCODE;
+
+/* global variables set in parameter file */
+char   *PHOTCODE;
+char   PhotCodeFile[256];
+char   AstromFile[256];
+
+double DEFAULT_ERROR;
+double RADIUS;
+double TRAIL_WIDTH;
+int    NBINS;
+int    NPTSINLINE;
+double MIN_DENSITY;
+double NSIGMA;
+
+double RA, DEC, ZERO_POINT, MIN_SN_FSTAT;
+int CHAR_LINE, TYPE_FIELD, AP_FIELD, PSF_FIELD, HEADER_COORDS;
+
+int FIX_KEYWORD;
+char **KEYWORD, **KEYVALU, **KEYFMT;
+
+SMPData *LoadStarsDophot (char *filename, int *nstars, Header *header);
+SMPData *LoadStarsChad (char *filename, int *nstars, Header *header);
+SMPData *LoadStarsSex (char *filename, int *nstars, Header *header);
+
+void ConfigInit (int *argc, char **argv);
+void AdjustHeader (Header *header);
+void sort_stars (SMPData *X, int N);
+void find_trails (SMPData *stars, int Nstars);
+int find_group (SMPData *stars, char *mark, int Npts, int i, double *ANGLE);
+void wstars (char *filename, SMPData *stars, int Nstars, Header *header);
+
+void fix_total (SMPData *stars, int Nstars, Header *header);
+int find_line (SMPData *stars, char *mark, int Npts, int i, double *M, double *B, double Angle);
+void find_better_line (SMPData *stars, char *mark, int Npts, int i, double *M, double *B, int axis);
+
+void help ();
+void args (int argc, char **argv);
+void wfits (char *filename, SMPData *stars, int Nstars, Header *header);
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/AdjustHeader.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/AdjustHeader.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/AdjustHeader.c	(revision 16632)
@@ -0,0 +1,101 @@
+# include "imclean.h"
+
+void AdjustHeader (Header *header) {
+
+  int i;
+  double value;
+  char line[256];
+
+  if (FIX_KEYWORD) {
+    for (i = 0; i < FIX_KEYWORD; i++) {
+      if (!strcmp (KEYFMT[i], "%f")) {
+	value = atof (KEYVALU[i]);
+	gfits_modify (header, KEYWORD[i], "%le", 1, value);
+      } else {
+	gfits_modify (header, KEYWORD[i], "%s", 1, KEYVALU[i]);
+      }
+    }
+  }
+
+  /* validating the photcode name should be the job of DVO/addstar */
+  /* here we are only writing the selected photcode name to the header */
+  if (NEWPHOTCODE) {
+    gfits_modify (header, "PHOTCODE", "%s", 1, PHOTCODE);
+  }    
+
+  if (!HEADER_COORDS) {
+    int rh, rm, dd, dm;
+    float rs, ds;
+    RA = RA / 15.0;
+    rh = RA; /* rh is int */
+    rm = 60.0 * (RA - rh);
+    rs = 3600 * (RA - rh - rm / 60.0);
+    sprintf (line, "%02d:%02d:%05.2f", rh, rm, rs);
+    gfits_modify (header, "RA", "%s", 1, line);
+    dd = DEC;
+    dm = 60.0 * (DEC - dd);
+    ds = 3600 * (DEC - dd - dm / 60.0);
+    sprintf (line, "%02d:%02d:%05.2f", dd, dm, ds);
+    gfits_modify (header, "DEC", "%s", 1, line);
+  }
+ 
+  if (PROVIDE_ASTROM) {
+
+    Header astrom_header;
+    Coords coords;
+
+    if (!gfits_read_header (AstromFile, &astrom_header)) {
+      fprintf (stderr, "ERROR: can't get astrometry from %s\n", AstromFile);
+      exit (1);
+    }
+    if (!GetCoords (&coords, &astrom_header)) {
+      fprintf (stderr, "ERROR: no astrometric solution in header\n");
+      exit (1);
+    }
+    /*** use PutCoords to update header ***/
+    if (coords.Npolyterms > 1) {
+      gfits_modify (header, "CTYPE1",   "%s",  1, "RA---PLY");
+      gfits_modify (header, "CTYPE2",   "%s",  1, "DEC--PLY");
+    } else {
+      gfits_modify (header, "CTYPE1",   "%s",  1, "RA---TAN");
+      gfits_modify (header, "CTYPE2",   "%s",  1, "DEC--TAN");
+    }    
+    gfits_modify (header, "NASTRO",   "%d", 1, 1); 
+
+    gfits_modify (header, "CDELT1",   "%le", 1, coords.cdelt1); 
+    gfits_modify (header, "CDELT2",   "%le", 1, coords.cdelt2);
+    gfits_modify (header, "CRVAL1",   "%lf", 1, coords.crval1);
+    gfits_modify (header, "CRVAL2",   "%lf", 1, coords.crval2);  
+    gfits_modify (header, "CRPIX1",   "%lf", 1, coords.crpix1);
+    gfits_modify (header, "CRPIX2",   "%lf", 1, coords.crpix2);
+    gfits_modify (header, "PC001001", "%le", 1, coords.pc1_1);
+    gfits_modify (header, "PC001002", "%le", 1, coords.pc1_2);
+    gfits_modify (header, "PC002001", "%le", 1, coords.pc2_1);
+    gfits_modify (header, "PC002002", "%le", 1, coords.pc2_2);
+    gfits_modify (header, "NPLYTERM", "%d", 1, coords.Npolyterms);
+    if (coords.Npolyterms > 1) {
+      /* RA Terms */
+      gfits_modify (header, "PCA1X2Y0", "%le", 1, coords.polyterms[0][0]);   /* polyterms[0]); */
+      gfits_modify (header, "PCA1X1Y1", "%le", 1, coords.polyterms[1][0]);   /* polyterms[1]); */
+      gfits_modify (header, "PCA1X0Y2", "%le", 1, coords.polyterms[2][0]);   /* polyterms[2]); */
+      
+      if (coords.Npolyterms > 2) {
+	gfits_modify (header, "PCA1X3Y0", "%le", 1, coords.polyterms[3][0]);   /* polyterms[3]); */
+	gfits_modify (header, "PCA1X2Y1", "%le", 1, coords.polyterms[4][0]);   /* polyterms[4]); */
+	gfits_modify (header, "PCA1X1Y2", "%le", 1, coords.polyterms[5][0]);   /* polyterms[5]); */
+	gfits_modify (header, "PCA1X0Y3", "%le", 1, coords.polyterms[6][0]);   /* polyterms[6]); */
+      }
+      /* Dec Terms */
+      gfits_modify (header, "PCA2X2Y0", "%le", 1, coords.polyterms[0][1]);   /* polyterms[7]); */
+      gfits_modify (header, "PCA2X1Y1", "%le", 1, coords.polyterms[1][1]);   /* polyterms[8]); */
+      gfits_modify (header, "PCA2X0Y2", "%le", 1, coords.polyterms[2][1]);   /* polyterms[9]); */
+      
+      if (coords.Npolyterms > 2) {
+	gfits_modify (header, "PCA2X3Y0", "%le", 1, coords.polyterms[3][1]);   /* polyterms[10]); */
+	gfits_modify (header, "PCA2X2Y1", "%le", 1, coords.polyterms[4][1]);   /* polyterms[11]); */
+	gfits_modify (header, "PCA2X1Y2", "%le", 1, coords.polyterms[5][1]);   /* polyterms[12]); */
+	gfits_modify (header, "PCA2X0Y3", "%le", 1, coords.polyterms[6][1]);   /* polyterms[13]); */
+      }
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "imclean.h"
+
+void ConfigInit (int *argc, char **argv) {
+  
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "ZERO_PT",           "%lf", 0, &ZERO_POINT);
+  ScanConfig (config, "MIN_SN_FSTAT",      "%lf", 0, &MIN_SN_FSTAT);
+  ScanConfig (config, "DEFAULT_ERROR_FSTAT", "%lf", 0, &DEFAULT_ERROR);
+  ScanConfig (config, "DOPHOT_CHAR_LINE",  "%d", 0, &CHAR_LINE);
+  ScanConfig (config, "DOPHOT_TYPE_FIELD", "%d", 0, &TYPE_FIELD);
+  ScanConfig (config, "DOPHOTF_FIELD",  "%d", 0, &PSF_FIELD);
+  ScanConfig (config, "DOPHOT_AP_FIELD",   "%d", 0, &AP_FIELD);
+  ScanConfig (config, "PHOTCODE_FILE",     "%s", 0, PhotCodeFile);
+
+  /* unique to markstar */
+  ScanConfig (config, "SEARCH_RADIUS",   "%lf", 0, &RADIUS);
+  ScanConfig (config, "TRAIL_WIDTH",     "%lf", 0, &TRAIL_WIDTH);
+  ScanConfig (config, "NANGLE_BINS",     "%d",  0, &NBINS);
+  ScanConfig (config, "NPTSINLINE",      "%d",  0, &NPTSINLINE);
+  ScanConfig (config, "MIN_DENSITY",     "%lf", 0, &MIN_DENSITY);
+  ScanConfig (config, "SPACE_SIGMA",     "%lf", 0, &NSIGMA); 
+
+  free (config);
+  free (file);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsChad.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsChad.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsChad.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include "imclean.h"
+# define NBLOCK 100
+# define HIST_BINS 150
+
+SMPData *LoadStarsChad (char *filename, int *nstars, Header *header) {
+
+  FILE *f;
+  SMPData *stars;
+  int NSTARS, Nstars, i, N;
+  int status;
+  double x, y, m, sky, lsky;
+  char *buffer;
+  int Mhist[HIST_BINS], Shist[HIST_BINS], bin, sum;
+  double FWHMx, FWHMy, angle, flux;
+  int satfound, done;
+  double saturate, complete;
+  char line[256];
+
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't find object file %s\n", filename);
+    exit (1);
+  }
+
+  /* zero things that will sum */
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+  
+  N = 0;
+  Nstars = 0;
+  NSTARS = 500;
+  ALLOCATE (stars, SMPData, NSTARS);
+
+  /* for now assume file 'header' is fixed-format */
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  if (strncasecmp (line, "#seeing", 7)) {
+    fprintf (stderr, "error in header, skipping\n");
+    exit (1);
+  }
+  sscanf (line, "%*s %lf", &FWHMx);
+  FWHMy = FWHMx;
+  angle = 0;
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+
+  /* read in data from obj file */
+  /* data is not fixed format for lines, read each line one-at-a-time */
+  for (i = 0; (status = fscanf (f, "%lf %lf %*f %*f %lf %lf %*f", &x, &y, &sky, &flux)) != EOF; i++) {
+
+    if (status != 4) {
+      fprintf (stderr, "format error in file %s, line %d\n", filename, i);
+      continue;
+    }
+
+    if (flux <= 0) continue;
+    m = -2.5*log10 (flux);
+
+    if (sky < 1.0) {
+      lsky = 0.0;
+    } else {
+      lsky = log10(sky);
+    }
+
+    bin = MAX (0.0, MIN (HIST_BINS, 10.0 * (m + 15.0)));  /* stick in 0.1 mag bins */
+    Mhist[bin] ++;
+
+    m = MIN (50.0, m);
+    m = MAX (-24.0, m);
+
+    stars[Nstars].fx = 0;
+    stars[Nstars].fy = 0;
+    stars[Nstars].df = 0;
+    stars[Nstars].Mgal = 50.0;;
+    stars[Nstars].Map = 50.0;
+    stars[Nstars].X = x;
+    stars[Nstars].Y = y;
+    stars[Nstars].M = m;
+    stars[Nstars].dM = 0.01;
+    stars[Nstars].dophot = 1;
+    stars[Nstars].sky = lsky;
+    Nstars++;
+    if (Nstars == NSTARS - 1) {
+      NSTARS += 500;
+      REALLOCATE (stars, SMPData, NSTARS);
+    }
+  }
+
+  /* look at histogram, find saturation and completion limits */
+  sum = 0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  saturate = complete = 0.0;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1) - 15.0;
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i - 15.0;
+      done = TRUE;
+    }
+  }
+  
+  gfits_modify (header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  gfits_modify (header, "FWHM_X", "%lf", 1, FWHMx);
+  gfits_modify (header, "FWHM_Y", "%lf", 1, FWHMy);
+  gfits_modify (header, "ANGLE", "%lf", 1, angle);
+  gfits_modify (header, "FSATUR", "%lf", 1, (saturate + ZERO_POINT));
+  gfits_modify (header, "FLIMIT", "%lf", 1, (complete + ZERO_POINT));
+  gfits_modify (header, "NSTARS", "%d", 1, N);
+  for (i = 1; i <= 9; i++) {
+    sprintf (line, "TDOPHOT%1d", i);
+    gfits_modify (header, line, "%d", 1, 0);
+  }
+
+  *nstars = Nstars;
+  return (stars);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsDophot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsDophot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsDophot.c	(revision 16632)
@@ -0,0 +1,176 @@
+# include "imclean.h"
+# define NBLOCK 100
+# define HIST_BINS 300 
+/* the mag histogram has range 0.0 to 30.0 */
+/* m = 0.1*Mhist[i] */
+
+SMPData *LoadStarsDophot (char *filename, int *nstars, Header *header) {
+
+  FILE *f;
+  SMPData *stars;
+  int NSTARS, Nstars, i, Nline, N;
+  int type, status;
+  double x, y, m, dm, sky, lsky, fx, fy, df, Mgal, Map;
+  char *buffer;
+  int Mhist[HIST_BINS], Shist[HIST_BINS], n[20], bin, sum;
+  double FWHMx, FWHMy, angle;
+  int satfound, done;
+  double saturate, complete;
+  char line[256];
+  int MedHist[2002], NMedHist;
+  double SMedHist, dMed;
+
+  N = NMedHist = 0;
+  bzero (MedHist, 2002*sizeof(int));
+
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't find object file %s\n", filename);
+    exit (1);
+  }
+
+  /* zero things that will sum */
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+  for (i = 1; i <= 9; i++) { n[i] = 0; }
+
+  Nstars = 0;
+  NSTARS = 500;
+  ALLOCATE (stars, SMPData, NSTARS);
+
+  /* read average values from first line */
+  scan_line (f, line);
+  sscanf (line, "%*s %*s %*s %lf %lf %lf", &FWHMx, &FWHMy, &angle);
+
+  /* read in data from obj file */
+  while ((Nline = fread (buffer, CHAR_LINE, NBLOCK, f)) > 0) {
+    for (i = 0; i < Nline; i++) {
+      /* we are now using all entries on the *.obj line */
+      status = sscanf (&buffer[i*CHAR_LINE], "%d %lf %lf %lf %lf %lf %lf %lf %lf %lf %lf", 
+		       &type, &x, &y, &m, &dm, &sky, &fx, &fy, &df, &Mgal, &Map);
+      if (status != 11) {
+	fprintf (stderr, "format error in file %s, line %d\n", filename, i);
+	continue;
+      }
+
+      /* dophot magnitudes can range from 99.999 to -99.999 
+	 realistic numbers are between -20 and 0
+	 outside, we should set the value to 50.0 to force saturation */
+      
+      n[type] ++;
+      if (type == 6) continue;
+      if (type == 9) continue;
+      if (type == 8) continue;
+      if (type == 16) continue;
+      
+      if (m > 0) continue;                /* skip stars which totally fail on fit */
+      if (dm == 0.0) dm = DEFAULT_ERROR;  /* stars with poor errors, get 25.5% errors */
+      dm = MIN (0.999, MAX (0.0, dm));    /* truncate dm to fit in range 0 - 999 on output */
+
+      /* need to accumulate the median histogram thingy */
+      dMed = Map - m;
+      if ((fabs(m) < 90) && (fabs(Map) < 90) && (fabs(dMed) < 1)) {
+	bin = 1000 * (dMed + 1);
+	MedHist[bin] ++;
+	NMedHist ++;
+      }
+      
+      /* dophot provides values which are -2.5*log(counts) */
+      m    = ((m    > -25) && (m    < 0)) ? m + ZERO_POINT    : 50.0;
+      Mgal = ((Mgal > -25) && (Mgal < 0)) ? Mgal + ZERO_POINT : 50.0;
+      Map  = ((Map  > -25) && (Map  < 0)) ? Map + ZERO_POINT  : 50.0;
+
+      if (sky < 1.0) {
+	lsky = 0.0;
+      } else {
+	lsky = log10(sky);
+      }
+
+      if (MIN_SN_FSTAT*dm > 1.0) continue;  /* skip stars with errors too large */
+          
+      switch (type) {
+      case 1:
+      case 4:
+      case 7:
+	bin = MAX (0, MIN (HIST_BINS - 1, 10.0 * m));  /* stick in 0.1 mag bins */
+	Mhist[bin] ++;
+      default:
+	if (df < 0.0) df += 360.0;
+	stars[Nstars].X      = x;
+	stars[Nstars].Y      = y;
+	stars[Nstars].M      = m;
+	stars[Nstars].Mgal   = Mgal;
+	stars[Nstars].Map    = Map;
+	stars[Nstars].dM     = dm;
+	stars[Nstars].dophot = type;
+	stars[Nstars].sky    = lsky;
+	stars[Nstars].fx     = fx;
+	stars[Nstars].fy     = fy;
+	stars[Nstars].df     = df;
+	Nstars++;
+	if (Nstars == NSTARS - 1) {
+	  NSTARS += 500;
+	  REALLOCATE (stars, SMPData, NSTARS);
+	}
+      }
+    }
+
+  }    
+
+  /* look at histogram, find saturation and completion limits */
+  sum = 0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  saturate = complete = 0.0;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1);
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i;
+      done = TRUE;
+    }
+  }
+  
+  SMedHist = 0;
+  for (i = 0; (i < 2002) && (SMedHist < NMedHist / 2); i++) {
+    SMedHist += MedHist[i];
+  }
+  if (i == 2002) {
+    fprintf (stderr, "error finding (Ap - Fit) median\n");
+    SMedHist = 0;
+  } else {
+    SMedHist = 0.001*i - 1;
+    fprintf (stderr, "(Ap - Fit) median = %f\n", SMedHist);
+  }
+
+  for (i = 0; i < Nstars; i++) {
+    stars[i].Mgal += SMedHist;
+    stars[i].M += SMedHist;
+  }    
+
+  gfits_modify (header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  gfits_modify (header, "FWHM_X", "%lf", 1, FWHMx);
+  gfits_modify (header, "FWHM_Y", "%lf", 1, FWHMy);
+  gfits_modify (header, "ANGLE", "%lf", 1, angle);
+  gfits_modify (header, "FSATUR", "%lf", 1, saturate);
+  gfits_modify (header, "FLIMIT", "%lf", 1, complete);
+  gfits_modify (header, "APMIFIT", "%lf", 1, SMedHist);
+  gfits_modify (header, "NSTARS", "%d", 1, N);
+  for (i = 1; i <= 9; i++) {
+    sprintf (line, "TDOPHOT%1d", i);
+    gfits_modify (header, line, "%d", 1, n[i]);
+  }
+
+  *nstars = Nstars;
+  return (stars);
+
+}
+
+/* this function should load the stars and immediately convert them to
+   have the ZERO_PT zero point */
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsSex.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsSex.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/LoadStarsSex.c	(revision 16632)
@@ -0,0 +1,142 @@
+# include "imclean.h"
+# define NBLOCK 100
+# define HIST_BINS 300 
+
+/* good for sextractor */
+
+SMPData *LoadStarsSex (char *filename, int *nstars, Header *header) {
+
+  FILE *f;
+  SMPData *stars;
+  int NSTARS, Nstars, i, Nline, N;
+  int type, status;
+  double x, y, m, dm, sky, lsky, ftype;
+  char *buffer;
+  int Mhist[HIST_BINS], Shist[HIST_BINS], n[10], bin, sum, flags;
+  double A, A2, S2, FWHMx, FWHMy, angle, Mgal, Map;
+  int gotFWHM, satfound, done;
+  double saturate, complete;
+
+  CHAR_LINE = 105;
+  TYPE_FIELD = 0;
+  
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't find object file %s\n", filename);
+    exit (1);
+  }
+
+  /* zero things that will sum */
+  N = A = A2 = S2 = 0;
+  gotFWHM = FALSE;
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+  for (i = 1; i <= 9; i++) { n[i] = 0; }
+
+  Nstars = 0;
+  NSTARS = 500;
+  ALLOCATE (stars, SMPData, NSTARS);
+
+  /* read in data from obj file */
+  while ((Nline = fread (buffer, CHAR_LINE, NBLOCK, f)) > 0) {
+    for (i = 0; i < Nline; i++) {
+      status = sscanf (&buffer[i*CHAR_LINE + TYPE_FIELD], "%lf %lf %lf %lf %lf   %lf %lf %lf %lf %lf  %lf %d", 
+		       &ftype, &x, &y, &m, &dm, &sky, &FWHMx, &FWHMy, &angle, &Mgal, &Map, &flags);
+      if (status != 12) {
+	fprintf (stderr, "ERROR: format error in file %s, line %d\n", filename, i);
+	continue;
+      } 
+
+      if (flags > 7) continue;
+      /* if (m > 0) continue; skip stars which totally fail on fit */
+      if (dm == 0.0) dm = DEFAULT_ERROR;  
+
+      /* sextract can provide values which are -2.5*log(counts) */
+      m    += ZERO_POINT;
+      Mgal += ZERO_POINT;
+      Map  += ZERO_POINT;
+      m    = MIN (32.767, MAX (-32.767, m));
+      Mgal = MIN (32.767, MAX (-32.767, Mgal));
+      Map  = MIN (32.767, MAX (-32.767, Map));
+
+      if (sky < 1) {
+	lsky = 0.0;
+      } else {
+	lsky = log10(sky);
+      }
+
+      /* type = MAX (0, MIN (9, 5*log10(ftype) + 10)); */
+      switch (flags) {
+      case 4:
+      case 5:
+      case 6:
+      case 7:
+	type = 10;
+	break;
+      case 1:
+      case 2:
+      case 3:
+	type = 3;
+	break;
+      default:
+	type = 1;
+      }
+
+      if (MIN_SN_FSTAT*dm > 1.0) continue;
+      
+      bin = MAX (0, MIN (HIST_BINS - 1, 10.0 * m));  /* stick in 0.1 mag bins */
+      Mhist[bin] ++;
+      
+      stars[Nstars].X = x;
+      stars[Nstars].Y = y;
+      stars[Nstars].M = m;
+      stars[Nstars].dM = dm;
+      stars[Nstars].dophot = type;
+      stars[Nstars].sky = lsky;
+      
+      stars[Nstars].fx = FWHMx;
+      stars[Nstars].fy = FWHMx * (FWHMy/FWHMx);
+      stars[Nstars].df = angle;
+      stars[Nstars].Mgal = Mgal;
+      stars[Nstars].Map = Map;
+
+      Nstars++;
+      if (Nstars == NSTARS - 1) {
+	NSTARS += 500;
+	REALLOCATE (stars, SMPData, NSTARS);
+      }
+    }
+
+  }    
+
+  sum = 0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  saturate = complete = 0.0;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1);
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i;
+      done = TRUE;
+    }
+  }
+  
+  gfits_modify (header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  gfits_modify (header, "FWHM_X", "%lf", 1, FWHMx);
+  gfits_modify (header, "FWHM_Y", "%lf", 1, FWHMy);
+  gfits_modify (header, "ANGLE", "%lf", 1, angle);
+  gfits_modify (header, "FSATUR", "%lf", 1, saturate);
+  gfits_modify (header, "FLIMIT", "%lf", 1, complete);
+  gfits_modify (header, "NSTARS", "%d", 1, N);
+
+  *nstars = Nstars;
+  return (stars);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/args.c	(revision 16632)
@@ -0,0 +1,87 @@
+# include "imclean.h"
+# define NARGS 2  /* minimum is: addstar (filename) */
+
+void help () {
+
+  fprintf (stderr, "USAGE: imclean (file.fits) (file.obj) (file.cmp)\n");
+  exit (2);
+
+}
+
+void args (int argc, char **argv) {
+  
+  int i, N;
+
+  if (get_argument (argc, argv, "-help") ||
+      get_argument (argc, argv, "-h")) {
+    help ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  FITS_OUTPUT = FALSE;
+  if ((N = get_argument (argc, argv, "-fits"))) {
+    FITS_OUTPUT = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  HEADER_COORDS = TRUE;
+  if ((N = get_argument (argc, argv, "-coords"))) {
+    remove_argument (N, &argc, argv);
+    RA = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    DEC = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    HEADER_COORDS = FALSE;
+  }
+
+  NEWPHOTCODE = FALSE;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    NEWPHOTCODE = TRUE;
+    remove_argument (N, &argc, argv);
+    PHOTCODE = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  PROVIDE_ASTROM = FALSE;
+  if ((N = get_argument (argc, argv, "-astrom"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (AstromFile, argv[N]);
+    remove_argument (N, &argc, argv);
+    PROVIDE_ASTROM = TRUE;
+  }
+
+  MODE = DOPHOT;
+  if ((N = get_argument (argc, argv, "-chad"))) {
+    MODE = CHAD;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-sex"))) {
+    MODE = SEXTRACT;
+    remove_argument (N, &argc, argv);
+  }
+
+  ALLOCATE (KEYWORD, char *, 64);
+  ALLOCATE (KEYVALU, char *, 64);
+  ALLOCATE (KEYFMT, char *, 64);
+  FIX_KEYWORD = 0;
+  while ((N = get_argument (argc, argv, "-key"))) {
+    i = FIX_KEYWORD;
+    remove_argument (N, &argc, argv);
+    KEYWORD[i] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    KEYFMT[i] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    KEYVALU[i] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FIX_KEYWORD ++;
+    if (FIX_KEYWORD == 64) break;
+  }
+
+
+  if (argc != 4) help ();
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/find_group.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/find_group.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/find_group.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "imclean.h"
+
+int find_group (SMPData *stars, char *mark, int Npts, int i, double *ANGLE) {
+ 
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Xo, Yo, dX, dY, angle, limit;
+
+   /* assign some parameter values */
+  if (mark[i]) return (FALSE);
+
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS + 1);
+  bzero (A, (NBINS+1)*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  Xo = stars[i].X;
+  Yo = stars[i].Y;
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && ((dX = stars[j].X - Xo) < RADIUS); j++) {
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;  /* only NaN if dD = dR = 0 */
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && ((dX = Xo - stars[j].X) < RADIUS); j--) {
+    if (mark[j]) continue;
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      N ++;
+    }
+  }
+  if (N < 5) {
+    free (A);
+    return (FALSE);
+  }
+  limit = MAX (5, NSIGMA*sqrt((double)(N)/(double)(NBINS)));
+  for (j = 0; j < NBINS; j++) {
+    if (A[j] > limit) {
+      *ANGLE = j / (DEG_RAD*Ndegbin);
+      fprintf (stderr, "group: %f (%f %f)\n", *ANGLE, Xo, Yo);
+      free (A);
+      return (TRUE);
+    }
+  }
+  free (A);
+  return (FALSE);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/find_line.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/find_line.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/find_line.c	(revision 16632)
@@ -0,0 +1,164 @@
+# include "imclean.h"
+
+int find_line (SMPData *stars, char *mark, int Npts, int i, double *M, double *B, double Angle) {
+  
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dX, dY, Xo, Yo, angle;
+  char Flipped;
+  
+  Xo = stars[i].X;
+  Yo = stars[i].Y;
+  X = Xo;
+  Y = Yo;
+  X2 = Xo*Xo;
+  Y2 = Yo*Yo;
+  XY = Xo*Yo;
+  N = 1;
+  /* points to the right */
+  for (j = i + 1; (j < Npts) && ((dX = stars[j].X - Xo) < RADIUS); j++) {
+    if (mark[j]) continue;
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < 2*RAD_DEG) {
+	X += stars[j].X;
+	Y += stars[j].Y;
+	X2 += stars[j].X*stars[j].X;
+	Y2 += stars[j].Y*stars[j].Y;
+	N ++;
+	XY += stars[j].X*stars[j].Y;
+      }
+    }
+  }
+  /* points to the left */
+  for (j = i - 1; (j >= 0) && ((dX = Xo - stars[j].X) < RADIUS); j--) {
+    if (mark[j]) continue;
+    dY = stars[j].Y - Yo;
+    if (fabs(dY) < RADIUS) {
+      angle = atan2 (dY,dX);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < 2*RAD_DEG) {
+	X += stars[j].X;
+	Y += stars[j].Y;
+	X2 += stars[j].X*stars[j].X;
+	Y2 += stars[j].Y*stars[j].Y;
+	N ++;
+	XY += stars[j].X*stars[j].Y;
+      }
+    }
+  }
+  /* determine coeffs */
+  Flipped = 0;
+  det = 1.0 / (X2*N - X*X);
+  m = det * (XY*N - X*Y);
+  b = det * (X2*Y - XY*X);
+  if (fabs(m) > 1.1) { /* use a line of R = m*D + b instead */
+    /* fprintf (stderr, "high slope object: %f %f  -> ", m, b); */
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+    Flipped = 1;
+    /* fprintf (stderr, "%f %f\n", m, b); */
+  }
+
+  *M = m;
+  *B = b;
+  return (Flipped);
+
+}
+
+
+void find_better_line (SMPData *stars, char *mark, int Npts, int i, double *M, double *B, int axis) {
+  
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det, dist;
+  double delta, *path;
+  int NLINE, *line;
+
+  NLINE = 50;
+  ALLOCATE (line, int, NLINE);
+  ALLOCATE (path, double, NLINE);
+  
+  /* fit a line to points near line */
+  X = Y = X2 = Y2 = XY = N = 0;
+  m = *M;  b = *B;
+  for (j = 0; (j < Npts); j++) {
+    if (axis == 1) 
+      delta = stars[j].X - m*stars[j].Y - b;
+    else
+      delta = stars[j].Y - m*stars[j].X - b;
+    if (fabs(delta) < 2*TRAIL_WIDTH) {
+      X += stars[j].X;
+      Y += stars[j].Y;
+      X2 += stars[j].X*stars[j].X;
+      Y2 += stars[j].Y*stars[j].Y;
+      XY += stars[j].X*stars[j].Y;
+      line[N] = j;
+      path[N] = hypot (stars[j].X - stars[line[0]].X, stars[j].Y - stars[line[0]].Y);
+      N ++;
+      if (N == NLINE - 1) {
+	NLINE += 50;
+	REALLOCATE (line, int, NLINE);
+	REALLOCATE (path, double, NLINE);
+      }
+    }
+  }
+
+  if (N < NPTSINLINE) {
+    free (line);
+    return;
+  }
+
+  for (i = 0; i < N - NPTSINLINE + 1; i++) {
+    j = i + NPTSINLINE - 1;
+    dist = fabs (path[j] - path[i]);
+    if ((j - i) / dist < MIN_DENSITY) continue;
+    for (; (j < N) && (((j - i) / dist) > MIN_DENSITY); j++) {
+      dist = fabs (path[j] - path[i]);
+    }
+    if ((j == N) && (((j - i) / dist) > MIN_DENSITY)) j++;
+    j--;
+    for (; i < j; i++) {
+      mark[line[i]] = TRUE;
+      stars[line[i]].dophot = 0;
+    }
+    i--;
+  }
+  free (line);
+  free (path);
+
+  /* determine coeffs */
+  if (axis == 0) {
+    det = 1.0 / (X2*N - X*X);
+    m = det * (XY*N - X*Y);
+    b = det * (X2*Y - XY*X);
+  } else {
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+  }
+
+  fprintf (stderr, "%f %f %d\n", m, b, N);
+
+  *M = m;
+  *B = b;
+
+}
+
+void fix_total (SMPData *stars, int Nstars, Header *header) {
+  
+  int Ngood, i;
+
+  Ngood = 0;
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].dophot != 0) Ngood ++;
+  }
+
+  gfits_modify (header, "NSTARS", "%d", 1, Ngood);
+  
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/find_trails.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/find_trails.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/find_trails.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "imclean.h"
+
+void find_trails (SMPData *stars, int Nstars) {
+
+  int i;
+  char *mark;
+  double Angle, axis, m, b;
+  
+  ALLOCATE (mark, char, Nstars);
+  bzero (mark, Nstars);
+  
+  for (i = 0; i < Nstars; i++) {
+    /* already marked, ignore */
+    if (mark[i]) continue;
+    if (find_group (stars, mark, Nstars, i, &Angle)) {
+      /* this point has an excess nearby concentration, find the line */
+      axis = find_line (stars, mark, Nstars, i, &m, &b, Angle);
+      find_better_line (stars, mark, Nstars, i, &m, &b, axis);
+      /* mark_trail (stars, mark, Nstars, i, m, b, axis); */
+    }
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/imclean.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/imclean.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/imclean.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "imclean.h"
+
+int main (int argc, char **argv) {
+
+  Header header;
+  SMPData *stars;
+  int Nstars;
+
+  ConfigInit (&argc, argv);
+
+  args (argc, argv);
+
+  /* load in FITS header from image */
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", argv[1]);
+    exit (1);
+  }
+
+  AdjustHeader (&header);
+  
+  switch (MODE) {
+  case DOPHOT:
+    stars = LoadStarsDophot (argv[2], &Nstars, &header);
+    break;
+  case CHAD:
+    stars = LoadStarsChad (argv[2], &Nstars, &header);
+    break;
+  case SEXTRACT:
+    stars = LoadStarsSex (argv[2], &Nstars, &header);
+    break;
+  default: 
+    fprintf (stderr, "unknown mode: %d\n", MODE);
+    exit (1);
+  }
+
+  sort_stars (stars, Nstars);
+  find_trails (stars, Nstars);  
+  fix_total (stars, Nstars, &header);
+
+  if (FITS_OUTPUT) {
+    wfits (argv[3], stars, Nstars, &header); 
+  } else {
+    wstars (argv[3], stars, Nstars, &header); 
+  }
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+/* based on fstat and markstar:
+
+   0) load config data, global parameters 
+   1) load header
+   2) load data from *.obj file
+   3) eliminate bad star types: 6, 8
+   4) identify trails
+   5) get statistics on remaining stars
+
+*/
+
+/* 
+imclean (file.fits) (file.obj) (file.cmp) 
+
+ [-p photcode]
+ [-chad]
+ [-sex]
+ [-coords RA DEC] 
+ [-astrom file]
+ [-v]
+ [-key name %f value]
+ [-key name %s value]
+ (maximum of 64 keywords can be changed)
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/sort_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/sort_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/sort_stars.c	(revision 16632)
@@ -0,0 +1,13 @@
+# include "imclean.h"
+
+void sort_stars (SMPData *stars, int N) {
+
+# define SWAPFUNC(A,B){ SMPData tmp; tmp = stars[A]; stars[A] = stars[B]; stars[B] = tmp; }
+# define COMPARE(A,B)(stars[A].X < stars[B].X)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/star_stats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/star_stats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/star_stats.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "imclean.h"
+
+star_stats (Header *header, SMPData *stars, int Nstars) {
+
+  int i;
+  
+  /* zero things that will sum */
+  N = A = A2 = S2 = 0;
+  gotFWHM = FALSE;
+
+  for (i = 0; i < HIST_BINS; i++) { Mhist[i] = Shist[i] = 0; }
+  for (i = 1; i <= 9; i++) { n[i] = 0; }
+
+  for (i = 0; i < Nstars; i++) {
+    n[type] ++;
+    switch (type) {
+    case 6:  /* just throw these ones out */
+    case 8:
+    case 9:
+      break;
+    case 1:
+      sscanf (&buffer[i*CHAR_LINE + AP_FIELD], "%lf", &ap);
+      if (ap < 99) {
+	apmifit = ap - m;
+	A += apmifit / SQ(df);
+	A2 += SQ(apmifit) / SQ(df);
+	S2 += 1.0 / SQ(df);
+      } 
+      if (!gotFWHM) {
+	sscanf (&buffer[i*CHAR_LINE + PSF_FIELD], "%lf %lf %lf ", &FWHMx, &FWHMy, &angle);
+	gotFWHM = TRUE;
+      }
+    case 4:
+    case 7:
+      bin = MAX (0.0, MIN (HIST_BINS, 10.0 * (m + 15.0)));  /* stick in 0.1 mag bins */
+      Mhist[bin] ++;
+    case 2:
+    case 3:
+    case 5:
+      fprintf (g, "%6.1f %6.1f %6.3f %03d %1d %3.1f\n", x, y, m+ZERO_POINT, (int)(1000*df), type, lsky);
+      N ++; 
+    }
+  }
+
+  Ap = A / S2;
+  Ap2 = sqrt(A2 / (S2) - Ap*Ap);
+  sum = 0.0;
+  for (i = 0; i < HIST_BINS; i++) {
+    sum += Mhist[i];
+    Shist[i] = sum;
+  }
+  satfound = done = FALSE;
+  for (i = 0; (i < HIST_BINS) && !done; i++) {
+    if ((!satfound) && (Mhist[i] > 0)) {
+      saturate = 0.1*(i-1) - 15.0;
+      satfound = TRUE;
+    }
+    if (Shist[i] > 0.9*Shist[HIST_BINS - 1]) {
+      complete = 0.1*i - 15.0;
+      done = TRUE;
+    }
+  }
+  
+  gfits_modify (&header, "ZERO_PT", "%lf", 1, ZERO_POINT);
+  gfits_modify (&header, "FWHM_X", "%lf", 1, FWHMx);
+  gfits_modify (&header, "FWHM_Y", "%lf", 1, FWHMy);
+  gfits_modify (&header, "ANGLE", "%lf", 1, angle);
+  gfits_modify (&header, "APMIFIT", "%lf", 1, Ap);
+  gfits_modify (&header, "dAPMIFIT", "%lf", 1, Ap2);
+  gfits_modify (&header, "FSATUR", "%lf", 1, (saturate + ZERO_POINT));
+  gfits_modify (&header, "FLIMIT", "%lf", 1, (complete + ZERO_POINT));
+  gfits_modify (&header, "NSTARS", "%d", 1, N);
+  for (i = 1; i <= 9; i++) {
+    sprintf (line, "TDOPHOT%1d\0", i);
+    gfits_modify (&header, line, "%d", 1, n[i]);
+  }
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/wfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/wfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/wfits.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "imclean.h"
+
+void wfits (char *filename, SMPData *stars, int Nstars, Header *header) {
+
+  Matrix matrix;
+  Header theader;
+  FTable table;
+
+  header[0].extend = TRUE;
+  header[0].Naxes = 0;
+  gfits_modify (header, "NAXIS",   "%d", 1, 0);
+  gfits_modify (header, "EXTEND",  "%t", 1, TRUE);
+  gfits_modify (header, "NEXTEND", "%d", 1, 1);
+
+  /* add in some keywords to specify the datatype & software version? */
+
+  /* create (empty) data matrix */
+  gfits_create_matrix (header, &matrix);
+    
+  table.header = &theader;
+  gfits_table_set_SMPData (&table, stars, Nstars);
+
+  gfits_write_header  (filename, header);
+  gfits_write_matrix  (filename, &matrix);
+  gfits_write_Theader (filename, &theader);
+  gfits_write_table   (filename, &table);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imclean/src/wstars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imclean/src/wstars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imclean/src/wstars.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "imclean.h"
+# define NCHAR 66 /* 65 char EXCLUDING return */
+
+void wstars (char *filename, SMPData *stars, int Nstars, Header *header) {
+  
+  int i, Nchar;
+  FILE *g;
+  char line[NCHAR + 3];
+
+  g = fopen (filename, "w");
+  if (g == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file %s\n", filename);
+    exit (1);
+  }
+
+  fwrite (header[0].buffer, 1, header[0].size, g);
+
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].dophot == 0) continue;
+    Nchar = snprintf (line, NCHAR, "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", 
+		      stars[i].X, stars[i].Y, stars[i].M, 
+		      (int)(1000*stars[i].dM), stars[i].dophot, stars[i].sky, 
+		      stars[i].Mgal, stars[i].Map, stars[i].fx, stars[i].fy, stars[i].df);
+    
+    /* this is just a little funny.  NCHAR (in) includes the trailing NULL, Nchar (out) excludes it */
+    if (Nchar != NCHAR - 1) {
+      fprintf (stderr, "funny line %d (%d)\n%s\n", i, Nchar, line);
+    } else {
+      fprintf (g, "%s\n", line);
+    }
+  }
+
+  fclose (g);
+
+}
+
+/*
+
+  63.6 2869.5 17.568 157 17.568 17.568 25.01 25.00 360.0 7 2.9
+
+  63.6 2869.5 17.568 157 7 2.9
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/Makefile	(revision 16632)
@@ -0,0 +1,193 @@
+default: all
+help:
+	@echo "make options: all imregister etc (default)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/imregister
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+BASEDIR =	$(HOME)/base
+DETREND =	$(HOME)/detrend
+PHOTREG =	$(HOME)/photreg
+IMREG   =	$(HOME)/imreg
+IMPHOT  =	$(HOME)/imphot
+SPREG   =	$(HOME)/spreg
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+# programs which should be installed
+INSTALL = \
+imregister   imstatreg    \
+imsort       imsearch     \
+showiminfo   convertimreg \
+detregister  detsearch    \
+photsearch   photreg      \
+imregtable   imphotsearch \
+cameraconfig filtnames    \
+photcode     photcode-table
+
+# program under development, not installed
+DEVEL = spregister spsearch imphotmerge
+
+IMPHOTOBJ = \
+$(IMPHOT)/args.$(ARCH).o \
+$(IMPHOT)/db_load.$(ARCH).o \
+$(IMPHOT)/dumpfits.$(ARCH).o \
+$(IMPHOT)/modify.$(ARCH).o \
+$(IMPHOT)/output.$(ARCH).o \
+$(IMPHOT)/rfits.$(ARCH).o \
+$(IMPHOT)/rtext.$(ARCH).o \
+$(IMPHOT)/subset.$(ARCH).o
+
+$(SRC)/imphotsearch.$(ARCH).o \
+$(SRC)/imphotmerge.$(ARCH).o \
+$(IMPHOTOBJ): $(INC)/imphot.h $(INC)/imregister.h
+
+IMOBJ  = \
+$(IMREG)/delete.$(ARCH).o \
+$(IMREG)/iminfo.$(ARCH).o \
+$(IMREG)/load_probes.$(ARCH).o  \
+$(IMREG)/match.$(ARCH).o  \
+$(IMREG)/modify.$(ARCH).o \
+$(IMREG)/newimages.$(ARCH).o \
+$(IMREG)/output.$(ARCH).o \
+$(IMREG)/unique.$(ARCH).o \
+$(IMREG)/cadc.$(ARCH).o   \
+$(IMREG)/mosaics.$(ARCH).o   \
+$(IMREG)/ConfigPID.$(ARCH).o   \
+$(IMREG)/SetSignals.$(ARCH).o   \
+$(IMREG)/rconnect.$(ARCH).o   \
+$(IMREG)/FifoOps.$(ARCH).o   \
+$(IMREG)/SockScan.$(ARCH).o   \
+$(IMREG)/submit.$(ARCH).o \
+$(IMREG)/imregclient.$(ARCH).o
+
+$(SRC)/imsearch.$(ARCH).o \
+$(SRC)/imregister.$(ARCH).o \
+$(SRC)/imstatreg.$(ARCH).o \
+$(SRC)/showiminfo.$(ARCH).o \
+$(SRC)/imregtable.$(ARCH).o \
+$(SRC)/convertimreg.$(ARCH).o \
+$(IMREG)/args.imsearch.$(ARCH).o \
+$(IMREG)/args.imregister.$(ARCH).o \
+$(IMOBJ): $(INC)/imreg.h $(INC)/imregister.h
+
+SPOBJ  = \
+$(SPREG)/delete.$(ARCH).o   \
+$(SPREG)/match.$(ARCH).o    \
+$(SPREG)/modify.$(ARCH).o   \
+$(SPREG)/output.$(ARCH).o   \
+$(SPREG)/unique.$(ARCH).o   \
+$(SPREG)/spinfo.$(ARCH).o   \
+$(SPREG)/showinfo.$(ARCH).o \
+$(SPREG)/ConfigInit.$(ARCH).o
+
+$(SRC)/spregister.$(ARCH).o \
+$(SPREG)/args.spregister.$(ARCH).o \
+$(SRC)/spsearch.$(ARCH).o \
+$(SPREG)/args.spsearch.$(ARCH).o \
+$(SPOBJ): $(INC)/spreg.h $(INC)/imregister.h
+
+PHOTOBJ  = \
+$(PHOTREG)/delete.$(ARCH).o  \
+$(PHOTREG)/match.$(ARCH).o   \
+$(PHOTREG)/convert.$(ARCH).o \
+$(PHOTREG)/output.$(ARCH).o  \
+$(PHOTREG)/getImageData.$(ARCH).o
+
+$(SRC)/photreg.$(ARCH).o \
+$(SRC)/photsearch.$(ARCH).o \
+$(PHOTREG)/args.photreg.$(ARCH).o \
+$(PHOTREG)/args.photsearch.$(ARCH).o \
+$(PHOTOBJ): $(INC)/photreg.h $(INC)/imregister.h
+
+DETOBJ  = \
+$(DETREND)/criteria.$(ARCH).o  \
+$(DETREND)/delete.$(ARCH).o    \
+$(DETREND)/entry.$(ARCH).o     \
+$(DETREND)/image.$(ARCH).o     \
+$(DETREND)/imdef.$(ARCH).o     \
+$(DETREND)/match.$(ARCH).o     \
+$(DETREND)/modify.$(ARCH).o    \
+$(DETREND)/mosaic.$(ARCH).o    \
+$(DETREND)/output.$(ARCH).o    \
+$(DETREND)/recipe.$(ARCH).o    \
+$(DETREND)/select.$(ARCH).o    \
+$(DETREND)/unique.$(ARCH).o    \
+$(DETREND)/altpath.$(ARCH).o   \
+$(DETREND)/db_names.$(ARCH).o   \
+$(DETREND)/usage.$(ARCH).o
+
+$(SRC)/detregister.$(ARCH).o  \
+$(SRC)/detsearch.$(ARCH).o \
+$(DETREND)/args.detregister.$(ARCH).o \
+$(DETREND)/args.detsearch.$(ARCH).o \
+$(DETOBJ): $(INC)/detrend.h $(INC)/imregister.h
+
+BASEOBJ = \
+$(BASEDIR)/ConfigCamera.$(ARCH).o \
+$(BASEDIR)/ConfigFilter.$(ARCH).o \
+$(BASEDIR)/ConfigInit.$(ARCH).o   \
+$(BASEDIR)/WriteFIFO.$(ARCH).o    \
+$(BASEDIR)/get_fwhm.$(ARCH).o     \
+$(BASEDIR)/misc.$(ARCH).o         \
+$(BASEDIR)/version.$(ARCH).o      \
+$(BASEDIR)/parse_time.$(ARCH).o   \
+$(BASEDIR)/fits_scan_nchar.$(ARCH).o
+
+$(SRC)/photcode-table.$(ARCH).o \
+$(SRC)/photcode.$(ARCH).o \
+$(SRC)/cameraconfig.$(ARCH).o \
+$(SRC)/filtnames.$(ARCH).o \
+$(BASEOBJ): $(INC)/imregister.h
+
+# specific programs:
+$(BIN)/imsearch.$(ARCH)     : $(SRC)/imsearch.$(ARCH).o     $(IMREG)/args.imsearch.$(ARCH).o      $(IMOBJ)   $(BASEOBJ)
+$(BIN)/imregister.$(ARCH)   : $(SRC)/imregister.$(ARCH).o   $(IMREG)/args.imregister.$(ARCH).o    $(IMOBJ)   $(BASEOBJ)
+$(BIN)/imstatreg.$(ARCH)    : $(SRC)/imstatreg.$(ARCH).o    $(IMREG)/args.imregister.$(ARCH).o    $(IMOBJ)   $(BASEOBJ)
+$(BIN)/showiminfo.$(ARCH)   : $(SRC)/showiminfo.$(ARCH).o   $(IMREG)/args.imregister.$(ARCH).o    $(IMOBJ)   $(BASEOBJ)
+$(BIN)/imregtable.$(ARCH)   : $(SRC)/imregtable.$(ARCH).o   $(IMREG)/args.imregister.$(ARCH).o    $(IMOBJ)   $(BASEOBJ)
+$(BIN)/convertimreg.$(ARCH) : $(SRC)/convertimreg.$(ARCH).o $(IMREG)/args.imregister.$(ARCH).o    $(IMOBJ)   $(BASEOBJ)
+$(BIN)/detregister.$(ARCH)  : $(SRC)/detregister.$(ARCH).o  $(DETREND)/args.detregister.$(ARCH).o $(DETOBJ)  $(BASEOBJ)
+$(BIN)/detsearch.$(ARCH)    : $(SRC)/detsearch.$(ARCH).o    $(DETREND)/args.detsearch.$(ARCH).o   $(DETOBJ)  $(BASEOBJ)
+$(BIN)/photreg.$(ARCH)      : $(SRC)/photreg.$(ARCH).o      $(PHOTREG)/args.photreg.$(ARCH).o     $(PHOTOBJ) $(BASEOBJ)
+$(BIN)/photsearch.$(ARCH)   : $(SRC)/photsearch.$(ARCH).o   $(PHOTREG)/args.photsearch.$(ARCH).o  $(PHOTOBJ) $(BASEOBJ)
+$(BIN)/spregister.$(ARCH)   : $(SRC)/spregister.$(ARCH).o   $(SPREG)/args.spregister.$(ARCH).o    $(SPOBJ)   $(BASEOBJ)
+$(BIN)/spsearch.$(ARCH)     : $(SRC)/spsearch.$(ARCH).o     $(SPREG)/args.spsearch.$(ARCH).o      $(SPOBJ)   $(BASEOBJ)
+$(BIN)/imphotsearch.$(ARCH) : $(SRC)/imphotsearch.$(ARCH).o $(IMPHOTOBJ) $(BASEOBJ)
+$(BIN)/imphotmerge.$(ARCH)  : $(SRC)/imphotmerge.$(ARCH).o  $(IMPHOTOBJ) $(BASEOBJ)
+$(BIN)/cameraconfig.$(ARCH) : $(SRC)/cameraconfig.$(ARCH).o $(BASEOBJ)
+$(BIN)/filtnames.$(ARCH)    : $(SRC)/filtnames.$(ARCH).o    $(BASEOBJ)
+$(BIN)/photcode.$(ARCH)     : $(SRC)/photcode.$(ARCH).o     $(BASEOBJ)
+$(BIN)/photcode-table.$(ARCH) : $(SRC)/photcode-table.$(ARCH).o
+
+$(BIN)/imsort.$(ARCH): $(BIN)/imregister.$(ARCH)
+	rm -f  $(BIN)/imsort.$(ARCH)
+	cp $(BIN)/imregister.$(ARCH) $(BIN)/imsort.$(ARCH)
+
+all: $(INSTALL) $(DEVEL)
+
+$(INSTALL) $(DEVEL) : % : $(BIN)/%.$(ARCH)
+
+# utilities #################################################
+
+%.clean :
+	rm -f $(BIN)/$*.$(ARCH)
+
+%.rebuild :
+	rm -f $(BIN)/$*.$(ARCH)
+	make $(DESTBIN)/$*
+
+%.install:
+	make $(DESTBIN)/$*
+
+install:
+	for i in $(INSTALL); do make $$i.install || exit; done
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigCamera.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigCamera.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigCamera.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "imregister.h"
+
+void ConfigCamera () { 
+
+  int i;
+  char *config, ID[64], field[128], line[128];
+
+  /* load camera config file */
+  config = LoadConfigFile (CameraConfig);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find camera config file %s\n", CameraConfig);
+    exit (1);
+  }
+  
+  /* load data from config file */
+  ScanConfig (config, "NCCD", "%d", 1, &Nccd);
+  ALLOCATE (ccds, char *, Nccd);
+  ALLOCATE (ccdn, char *, Nccd);
+
+  for (i = 0; i < Nccd; i++) {
+    sprintf (field, "CCD.%d", i);
+    ScanConfig (config, field, "%s", 1, line);
+    sscanf (line, "%s", ID);
+    ccds[i] = strcreate (ID);
+  }
+
+  for (i = 0; i < Nccd; i++) {
+    sprintf (ID, "%02d", i);
+    ccdn[i] = strcreate (ID);
+  }
+}
+
+int MatchCCDNameHeader (Header *header) {
+
+  int i;
+  char ID[64];
+
+  ID[0] = 0;
+  
+  gfits_scan (header, CCDnumKeyword,  "%s", 1, ID);
+  if (!ID[0]) { 
+    fprintf (stderr, "warning, ccd id not found in header\n");
+    return (-1);
+  }
+  
+  /* compare as number if ID is a complete number (ie, 00 equiv to 0, but 00b not equiv to 0b */
+  for (i = 0; i < Nccd; i++) {
+    if (strnumcmp (ccds[i], ID)) {
+      return (i);
+    }
+  }
+  
+  fprintf (stderr, "warning: ccd %s not found in camera config file\n", ID);
+  return (-1);
+}
+
+int MatchCCDName (char *ID) {
+
+  int i;
+
+  /* compare as number if ID is a complete number (ie, 00 equiv to 0, but 00b not equiv to 0b */
+  for (i = 0; i < Nccd; i++) {
+    if (strnumcmp (ccds[i], ID)) {
+      return (i);
+    }
+  }
+  
+  fprintf (stderr, "warning: ccd %s not found in camera config file\n", ID);
+  return (-1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigFilter.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigFilter.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigFilter.c	(revision 16632)
@@ -0,0 +1,94 @@
+# include "imregister.h"
+
+void ConfigFilter () {
+
+  int i, N, code, NFILT, Nfilt, Nfield;
+  char *c, line[256], name[64];
+  FILE *f;
+
+  /* open filter list file */
+  f = fopen (FilterList, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error reading photcodes\n");
+    exit (1);
+  }
+
+  /* allocate dataspace needed */
+  NFILT = 100;
+  Nfilt = 0;
+  ALLOCATE (filternum,  int,    NFILT);
+  ALLOCATE (filtername, char *, NFILT);
+  for (i = Nfilt; i < NFILT; i++) {
+    ALLOCATE (filtername[i], char, 64);
+  }
+
+  while (scan_line (f, line) != EOF) {
+    for (c = line; isspace (*c); c++);
+    if (*c == '#') continue;
+    Nfield = sscanf (c, "%d %s", &code, name);
+    if (Nfield != 2) { continue; }
+
+    filternum[Nfilt] = code;
+    strcpy (filtername[Nfilt], name);
+    Nfilt ++;
+
+    if (Nfilt == NFILT - 1) {
+      NFILT += 100;
+      REALLOCATE (filternum,  int,    NFILT);
+      REALLOCATE (filtername, char *, NFILT);
+      for (i = Nfilt; i < NFILT; i++) {
+	REALLOCATE (filtername[i], char, 64);
+      }
+    }
+  }
+  fclose (f);
+
+  /* make filter hash table (using first available entries) */
+  ALLOCATE (filterhash, char *, Nfilt);
+  for (i = 0; i < Nfilt; i++) {
+    filterhash[i] = (char *) NULL;
+  }
+
+  for (i = 0; i < Nfilt; i++) {
+    N = filternum[i];
+    if (filterhash[N] != (char *) NULL) continue;
+    filterhash[N] = filtername[i];
+  }
+
+  NFILTER = Nfilt;
+  /* we now have NFILTER set, and filternum & filtername arrays filled */
+
+}  
+
+/* convert filter string to fixed filter names (convert all spaces to .) */
+int MatchFilterList (char *line) {
+
+  char *p;
+  int i, blank;
+
+  /* convert spaces to . */
+  blank = FALSE;
+  p = line;
+  for (i = 0; i < strlen (line); i++, p++) {
+    *p = line[i];
+    if (OHANA_WHITESPACE(line[i])) { 
+      *p = '.';
+      if (blank) p--;
+      if (!blank) blank = TRUE;
+    } else {
+      blank = FALSE;
+    }
+  }
+  *p = 0;
+
+  /* find defined filter name */
+  for (i = 0; i < NFILTER; i++) {
+    if (!strcasecmp (line, filtername[i])) {
+      /* careful: line[80] */
+      strcpy (line, filterhash[filternum[i]]);
+      return (TRUE);
+    }
+  }      
+  fprintf (stderr, "unknown filter %s\n", line);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/ConfigInit.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "imregister.h"
+
+int success;
+
+void ConfigInit (int *argc, char **argv) {
+
+  int i, NDB;
+  char *config, *file, ElixirBase[80], catdir[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+
+  success = TRUE;
+
+  WarnConfig (config, "REGISTRATION_DATABASE",       "%s", 0, ImageDB);
+  WarnConfig (config, "DETREND_DATABASE",            "%s", 0, DetrendDB);
+  WarnConfig (config, "PHOT_DATABASE",               "%s", 0, PhotDB);
+  WarnConfig (config, "TRANS_DATABASE",              "%s", 0, TransDB);
+
+  WarnConfig (config, "CATDIR",                      "%s", 0, catdir);
+  WarnConfig (config, "PHOTCODE_FILE",               "%s", 0, MasterPhotcodeFile);
+  sprintf (ImPhotDB, "%s/Images.dat", catdir);
+
+  /* small text databases: filters, camera defs */ 
+  WarnConfig (config, "TEMPERATURE_LOG",             "%s", 0, TempLogFile);
+  WarnConfig (config, "FILTER_LIST",                 "%s", 0, FilterList);
+  WarnConfig (config, "CAMERA_CONFIG",               "%s", 0, CameraConfig);
+  WarnConfig (config, "DETREND_RECIPES",             "%s", 0, RecipeFile);
+						   
+  /* pixel scale for FWHM */ 
+  WarnConfig (config, "ASEC_PIX",                    "%lf", 0, &ARCSEC_PIXEL);
+
+  /* keyword abstractions for parse_time */	   
+  WarnConfig (config, "DATE-KEYWORD",                "%s", 0, DateKeyword);
+  WarnConfig (config, "DATE-MODE",                   "%s", 0, DateMode);
+  WarnConfig (config, "UT-KEYWORD",                  "%s", 0, UTKeyword);
+  WarnConfig (config, "MJD-KEYWORD",                 "%s", 0, MJDKeyword);
+  WarnConfig (config, "JD-KEYWORD",                  "%s", 0, JDKeyword);
+						   
+  /* keyword abstractions for iminfo */		   
+  WarnConfig (config, "EXPTIME-KEYWORD",             "%s", 0, ExptimeKeyword);
+  WarnConfig (config, "IMAGETYPE-KEYWORD",           "%s", 0, ImagetypeKeyword);
+  WarnConfig (config, "CCDNUM-KEYWORD",              "%s", 0, CCDnumKeyword);
+  WarnConfig (config, "FILTER-KEYWORD",              "%s", 0, FilterKeyword);
+  WarnConfig (config, "AIRMASS-KEYWORD",             "%s", 0, AirmassKeyword);
+  WarnConfig (config, "FOCUS-KEYWORD",               "%s", 0, FocusKeyword);
+  WarnConfig (config, "ROTATION-KEYWORD",            "%s", 0, RotationKeyword);
+  WarnConfig (config, "DETTEMP-KEYWORD",             "%s", 0, DettempKeyword);
+  WarnConfig (config, "TELDATA1-KEYWORD",            "%s", 0, Teldata1Keyword);
+  WarnConfig (config, "TELDATA2-KEYWORD",            "%s", 0, Teldata2Keyword);
+  WarnConfig (config, "TELDATA3-KEYWORD",            "%s", 0, Teldata3Keyword);
+  WarnConfig (config, "CAMERA-KEYWORD",              "%s", 0, CameraKeyword);
+
+  ScanConfig (config, "CAMERA",                      "%s", 0, Camera);
+  ScanConfig (config, "SEEING_REF_CCD",              "%s", 0, SeeingREFCCD);
+
+  /* optional values */
+  ScanConfig (config, "RA-DDD-KEYWORD",              "%s", 0, RADecDegKeyword);
+  ScanConfig (config, "DEC-DDD-KEYWORD",             "%s", 0, DECDecDegKeyword);
+  ScanConfig (config, "RA-HMS-KEYWORD",              "%s", 0, RASexigKeyword);
+  ScanConfig (config, "DEC-DMS-KEYWORD",             "%s", 0, DECSexigKeyword);
+
+  if (!RADecDegKeyword[0] & !DECDecDegKeyword[0] && !RASexigKeyword[0] && !DECSexigKeyword[0]) {
+    fprintf (stderr, "missing astrometry configuration information\n");
+    success = FALSE;
+  }
+						   
+  WarnConfig (config, "imstats",                     "%s", 0, ElixirBase);
+  sprintf (ImstatFifo, "%s.photcode", ElixirBase);   
+  WarnConfig (config, "ptolemy",                     "%s", 0, ElixirBase);
+  sprintf (PtolemyFifo, "%s.photcode", ElixirBase);
+
+  if (!ScanConfig (config, "CONNECT", "%s",  0, CONNECT)) {
+    sprintf (CONNECT, "/usr/bin/rsh");
+  }
+
+  /* load Detrend Alt Databases paths */
+  NDB = 10;
+  NDetrendAltDB = 0;
+  ALLOCATE (DetrendAltDB, char *, NDB);
+  ALLOCATE (DetrendAltDB[NDetrendAltDB], char, 256);
+  for (i = 1; ScanConfig (config, "DETREND_ALT_DB", "%s", i, DetrendAltDB[NDetrendAltDB]); i++) {
+    NDetrendAltDB ++;
+    if (NDetrendAltDB == NDB) {
+      NDB += 10;
+      REALLOCATE (DetrendAltDB, char *, NDB);
+    }
+    ALLOCATE (DetrendAltDB[NDetrendAltDB], char, 256);
+  }
+  free (DetrendAltDB[NDetrendAltDB]);
+
+  if (! success) {
+    fprintf (stderr, "ERROR: problem with elixir configuration\n");
+    exit (1);
+  }
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", catdir);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
+
+void WarnConfig (char *config, char *key, char * mode, int N, void *var) {
+  if (!ScanConfig (config, key, mode, N, var)) {
+    fprintf (stderr, "missing config variable %s\n", key);
+    success = FALSE;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/WriteFIFO.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/WriteFIFO.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/WriteFIFO.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "imregister.h"
+
+int WriteFIFO (char *filename, char *line) {
+
+  int state, mode;
+  FILE *f;
+
+  f = fsetlockfile (filename, 20.0, LCK_XCLD, &state);
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't lock fifo %s\n", filename);
+    return (FALSE);
+  }
+
+  fseek (f, 0, SEEK_END);
+  fprintf (f, "%s\n", line);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (filename, mode);
+  fclearlockfile (filename, f, LCK_XCLD, &state);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/convert.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/convert.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/convert.c	(revision 16632)
@@ -0,0 +1,2 @@
+# include "imregister.h"
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/fits_scan_nchar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/fits_scan_nchar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/fits_scan_nchar.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "imregister.h"
+
+/* scan and give a warning for missing entries */
+void warn_scan (Header *header, char *field, char *format, int N, void *var) {
+  if (!gfits_scan (header, field, format, N, var)) {
+    fprintf (stderr, "WARNING: %s not found in header\n", field);
+  }
+}
+
+/* scan from header into a string of fixed length */
+int gfits_scan_nchar (Header *header, int size, char *field, int N,...) {
+
+  char tmpstr[160], *outstr; 
+  va_list argp;
+  int status;
+  
+  va_start (argp, N);
+  outstr = va_arg (argp, char *);
+  va_end (argp);
+
+  status = gfits_scan (header, field, "%s", N, tmpstr); 
+  strncpy (outstr, tmpstr, size - 1);
+  outstr[size-1] = 0; 
+
+  return (status);
+} 
+     
+void warn_scan_nchar (Header *header, int size, char *field, int N, void *var) {
+  if (!gfits_scan_nchar (header, size, field, N, var)) {
+    fprintf (stderr, "missing %s not found in header\n", field);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/misc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/misc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/misc.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include "imregister.h"
+
+static double tz = 0.0;
+void set_timezone (double dt) {
+  tz = dt;
+}
+
+/* return values:
+   0 - no trange arguments
+   1 - arguments ok
+   2 - arguments bad
+*/
+int get_trange_arguments (int *argc, char **argv, time_t **Tstart, time_t **Tstop, int *ntimes) {
+
+  int Na, N, Ntimes;
+  double trange;
+  time_t tmp, *tstart, *tstop;
+
+  /* allocate space for returned lists */
+  Ntimes = 10;
+  ALLOCATE (tstart, time_t, Ntimes);
+  ALLOCATE (tstop,  time_t, Ntimes);
+
+  for (N = 0; ; N++) {
+
+    /* find next -trange arg */
+    Na = get_argument (*argc, argv, "-trange");
+    if (Na == 0) {
+      *ntimes = N;
+      *Tstart = tstart;
+      *Tstop  = tstop;
+      return (TRUE);
+    }
+    remove_argument (Na, argc, argv);
+    
+    /* tstart */
+    if (!ohana_str_to_time (argv[Na], &tstart[N])) { 
+      return (FALSE);
+    }
+
+    /* interpret second value */
+    remove_argument (Na, argc, argv);
+    if (ohana_str_to_dtime (argv[Na], &trange)) { 
+      if (trange < 0) {
+	tstop[N]  = tstart[N];
+	tstart[N] = tstop[N] + trange;
+      } else {
+	tstop[N]  = tstart[N] + trange;
+      }
+      remove_argument (Na, argc, argv);
+      goto goodvalue;
+    }
+    if (ohana_str_to_time (argv[Na], &tstop[N])) { 
+      if (tstart[N] > tstop[N]) {
+	tmp     = tstart[N];
+	tstart[N] = tstop[N];
+	tstop[N]  = tmp;
+      }
+      remove_argument (Na, argc, argv);
+      goto goodvalue;
+    }
+    return (FALSE); /* syntax error in 2nd value */
+
+  goodvalue:
+    if (N == Ntimes - 1) {
+      Ntimes += 10;
+      REALLOCATE (tstart, time_t, Ntimes);
+      REALLOCATE (tstop,  time_t, Ntimes);
+    }
+  }
+}
+  
+int get_filter_arguments (int *argc, char **argv, int **Filt, int *Nfilt) {
+
+  int i, N, Na, NF;
+  int *filt;
+
+  /* allocate space for returned lists */
+  NF = 10;
+  ALLOCATE (filt, int, NF);
+
+  for (N = 0; ; N++) {
+
+    /* find next -trange arg */
+    Na = get_argument (*argc, argv, "-filter");
+    if (Na == 0) {
+      *Nfilt = N;
+      *Filt = filt;
+      return (TRUE);
+    }
+    if (Na > *argc - 2) return (FALSE); /* -filter F */
+    remove_argument (Na, argc, argv);
+    
+    for (i = 0; i < strlen (argv[Na]); i++) { if (isspace (argv[Na][i])) argv[Na][i] = '.'; }
+    for (i = 0; i < NFILTER; i++) {
+      if (!strcasecmp (argv[Na], filtername[i])) {
+	filt[N] = filternum[i];
+      }
+    }
+    if (filt[N] == FILTER_NONE) return (FALSE);
+    remove_argument (Na, argc, argv);
+
+    if (N == NF - 1) {
+      NF += 10;
+      REALLOCATE (filt, int, NF);
+    }
+  }
+}
+  
+   
+/* replaces WHITESPACE blocks with single . */
+void clean_spaces (char *line) {
+
+  char *out, *in;
+
+  if (line == NULL) return;
+
+  out = in = line;
+  while (*in) {
+    if (OHANA_WHITESPACE(*in)) { 
+      *out = '.';
+      out ++;
+      in ++;
+      while (*in && OHANA_WHITESPACE(*in)) in++;
+    } else {
+      *out = *in;
+      out ++;
+      in ++;
+    }
+  }
+  *out = 0;
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/parse_time.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/parse_time.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/parse_time.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "imregister.h"
+
+int parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int Nsec, hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    warn_scan (header, JDKeyword, "%lf", 1, &jd);
+    Nsec = ohana_jd_to_sec (jd);
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    warn_scan (header, MJDKeyword, "%lf", 1, &jd);
+    Nsec = ohana_mjd_to_sec (jd);
+    return (Nsec);
+  }
+    
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  warn_scan (header, UTKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (0);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (0);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (0);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (0);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (0);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  warn_scan (header, DateKeyword, "%s",  1, line);
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  Nf = 0;
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    exit (0);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/base/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/base/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/base/version.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "imregister.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+void get_version (int argc, char **argv, char *version) {
+
+  if (!get_argument (argc, argv, "-version")) return;
+
+  fprintf (stderr, "%s\n", version);
+  fprintf (stderr, "%s\n", name);
+
+  fprintf (stderr, "ohana: %s\n", ohana_version());
+  fprintf (stderr, "fits:  %s\n", gfits_version());
+  exit (2);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/altpath.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/altpath.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/altpath.c	(revision 16632)
@@ -0,0 +1,155 @@
+# include "imregister.h"
+# include "detrend.h"
+
+int SetAltpath (FITS_DB *db, DetReg *image, int Nimage, Match *match, int Nmatch) {
+  
+  int i, j, n, found, status, Nlist;
+  int *list, *current;
+  char *dBPath, infile[256], outfile[256], line[1024];
+  struct stat statbuf;
+
+  ALLOCATE (current, int, Nimage);
+  ALLOCATE (list, int, Nimage);
+  Nlist = 0;
+
+  dBPath = get_dBPath ();
+
+  /* set altpath for 'add' images */
+  if (output.Altpath == ADD) {
+    /* find images to add */
+    for (i = 0; i < Nmatch; i++) {
+      if (image[match[i].image].altpath == FALSE) {
+	list[Nlist] = match[i].image;
+	Nlist ++;
+      }
+    }
+    /* copy the masters to the altpath locations */
+    for (j = 0; j < Nlist; j++) {
+      i = list[j];
+      for (n = 0; n < NDetrendAltDB; n++) {
+	sprintf (infile, "%s/%s", dBPath, image[i].filename);
+	sprintf (outfile, "%s/%s", DetrendAltDB[n], image[i].filename);
+	status = ckpathname (outfile);
+	if (!status) {
+	  fprintf (stderr, "warning: can't make outfile directory for %s\n", outfile);
+	  continue;
+	}
+	sprintf (line, "cp %s %s", infile, outfile);
+	fprintf (stderr, "%s\n", line);
+	status = system (line);
+	if (status) {
+	  fprintf (stderr, "warning: can't make outfile directory for %s\n", outfile);
+	  continue;
+	}
+      }
+      image[i].altpath = TRUE;
+    }
+
+    /** we may later want to pull this out and put it elsewhere **/
+    gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, list, Nlist);
+    for (i = 0; i < Nmatch; i++) {
+      gfits_convert_DetReg ((DetReg *) db[0].vtable.buffer[i], sizeof (DetReg), 1);
+    }
+    gfits_db_update (db);
+    gfits_db_close (db);
+    gfits_db_free (db);
+
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  /* unset altpath for 'delete' images */
+  if (output.Altpath == DELETE) {
+    /* find images to delete */
+    for (i = 0; i < Nmatch; i++) {
+      if (image[match[i].image].altpath == TRUE) {
+	list[Nlist] = match[i].image;
+	Nlist ++;
+      }
+    }
+    /* remove the copies from the altpath locations */
+    for (j = 0; j < Nlist; j++) {
+      i = list[j];
+      image[i].altpath = FALSE;
+      for (n = 0; n < NDetrendAltDB; n++) {
+	sprintf (outfile, "%s/%s", DetrendAltDB[n], image[i].filename);
+	sprintf (line, "rm %s", outfile);
+	fprintf (stderr, "%s\n", line);
+	status = system (line);
+	if (status) {
+	  fprintf (stderr, "warning: can't delete %s\n", outfile);
+	}
+      }
+    }
+
+    /** we may later want to pull this out and put it elsewhere **/
+    gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, list, Nlist);
+    for (i = 0; i < Nmatch; i++) {
+      gfits_convert_DetReg ((DetReg *) db[0].vtable.buffer[i], sizeof (DetReg), 1);
+    }
+    gfits_db_update (db);
+    gfits_db_close (db);
+    gfits_db_free (db);
+
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  /* check for existence in altpath, set flag as appropriate */
+  if (output.Altpath == UPDATE) {
+    for (j = 0; j < Nmatch; j++) {
+      i = match[j].image;
+      list[Nlist] = i;
+      Nlist ++;
+      found = TRUE;
+      for (n = 0; found && (n < NDetrendAltDB); n++) {
+	sprintf (outfile, "%s/%s", DetrendAltDB[n], image[i].filename);
+	status = stat (outfile, &statbuf);
+	fprintf (stderr, "checking for %s, status is %d\n", outfile, status);
+	if (status == -1) found = FALSE;
+      }
+      image[i].altpath = found;
+    }
+
+    /** we may later want to pull this out and put it elsewhere **/
+    gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, list, Nlist);
+    for (i = 0; i < Nmatch; i++) {
+      gfits_convert_DetReg ((DetReg *) db[0].vtable.buffer[i], sizeof (DetReg), 1);
+    }
+    gfits_db_update (db);
+    gfits_db_close (db);
+    gfits_db_free (db);
+
+    fprintf (stderr, "SUCCESS\n");
+    exit (0);
+  }
+
+  fprintf (stderr, "unknown altpath mode: %d\n", output.Altpath);
+  return (TRUE);
+}
+
+
+int ckpathname (char *newpath) {
+  
+  int status;
+  char *path;
+  struct stat statbuf;
+  
+  path = pathname (newpath);
+  
+  status = stat (path, &statbuf);
+  if (status == -1) {
+    if (errno == ENOENT) {
+      if (mkdirhier (path, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+	fprintf (stderr, "ERROR: can't create path %s\n", path);
+	return (FALSE);
+      }
+    } else {
+      fprintf (stderr, "ERROR: problem with path %s\n", path);
+      return (FALSE);
+    }
+  }
+  free (path);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/args.detregister.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/args.detregister.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/args.detregister.c	(revision 16632)
@@ -0,0 +1,121 @@
+# include "imregister.h" 
+# include "detrend.h"
+
+/* criteria struct is global */
+int regargs (int argc, char **argv, Descriptor *descriptor) {
+
+  int N, i;
+
+  ConfigInit (&argc, argv);
+  ConfigCamera ();
+  ConfigFilter ();
+
+  output.Modify = TRUE;
+
+  /* these command line arguments will override image header info */
+  /* define time range */
+  descriptor[0].TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &descriptor[0].tstart)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &descriptor[0].tstop)) { 
+      fprintf (stderr, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    descriptor[0].TimeSelect = TRUE;
+  }
+
+  /* set optional label */
+  descriptor[0].label = strcreate ("detrend");
+  if ((N = get_argument (argc, argv, "-label"))) {
+    remove_argument (N, &argc, argv);
+    descriptor[0].label = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+ 
+  /* set optional label */
+  descriptor[0].imageID = NULL;
+  if ((N = get_argument (argc, argv, "-ID"))) {
+    remove_argument (N, &argc, argv);
+    descriptor[0].imageID = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+ 
+  /* set optional order */
+  descriptor[0].order = 0;
+  if ((N = get_argument (argc, argv, "-order"))) {
+    remove_argument (N, &argc, argv);
+    descriptor[0].order = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+ 
+  /* define image type */
+  descriptor[0].type = T_UNDEF;
+  if ((N = get_argument (argc, argv, "-type"))) {
+    remove_argument (N, &argc, argv);
+    descriptor[0].type = get_image_type (argv[N]);
+    if (descriptor[0].type == T_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image type %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+  }
+ 
+  /* define ccd number */
+  descriptor[0].CCDSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-ccd"))) {
+    remove_argument (N, &argc, argv);
+    descriptor[0].CCD = -1;
+    for (i = 0; (i < Nccd) && (descriptor[0].CCD == -1); i++) {
+      if (strnumcmp (ccds[i], argv[N])) {
+	descriptor[0].CCD = i;
+      }
+    }
+    if (descriptor[0].CCD == -1) {
+      fprintf (stderr, "ERROR: ccd %s choice out not found in camera config\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    descriptor[0].CCDSelect = TRUE;
+  }
+ 
+  /* define exposure time */
+  descriptor[0].Exptime = 0.0;
+  descriptor[0].ExptimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-exptime"))) {
+    remove_argument (N, &argc, argv);
+    descriptor[0].Exptime = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    descriptor[0].ExptimeSelect = TRUE;
+  }
+ 
+  /* define filter */
+  descriptor[0].filter = FILTER_NONE;
+  if ((N = get_argument (argc, argv, "-filter"))) {
+    remove_argument (N, &argc, argv);
+    for (i = 0; (i < NFILTER) && (descriptor[0].filter == FILTER_NONE); i++) {
+      if (!strcasecmp (argv[N], filtername[i])) {
+	descriptor[0].filter = filternum[i];
+      }
+    }      
+    if (descriptor[0].filter == FILTER_NONE) {
+      fprintf (stderr, "ERROR: invalid filter %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  /*** this program will only register SPLIT images ***/
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: detregister (filename) [config ops] -time start stop] [-type type] [-ccd N] [-filter name]\n");
+    fprintf (stderr, "ERROR - detregister not run\n");
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/args.detsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/args.detsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/args.detsearch.c	(revision 16632)
@@ -0,0 +1,384 @@
+# include "imregister.h"
+# include "detrend.h"
+
+/********* decipher all of the possible command-line options ***********/
+int args (int argc, char **argv) {
+
+  int i, N;
+  int MosaicSelect, ImageSelect, bad, Recipe, Ncrit;
+  char *ImageFile, *ImageMode, *ImageExtend;
+  Criteria base, *crit;
+  int *filt;
+  time_t *tstart, *tstop;
+
+  if ((N = get_argument (argc, argv, "-h"))) { usage (); }
+  if ((N = get_argument (argc, argv, "--help"))) { usage (); }
+  bzero (&base, sizeof (Criteria));
+
+  /* check config & command-line args */
+  ConfigInit (&argc, argv);
+  ConfigCamera ();
+  ConfigFilter ();
+
+  ImageFile = ImageMode = ImageExtend = NULL;
+
+  /* mosaic-based selection */
+  MosaicSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    remove_argument (N, &argc, argv);
+    ImageFile = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    MosaicSelect = TRUE;
+    /* check for incompatible arguments: -exptime, -filter, -time, -ccd */
+    bad = get_argument (argc, argv, "-exptime");
+    bad &= get_argument (argc, argv, "-image");
+    bad &= get_argument (argc, argv, "-filter");
+    bad &= get_argument (argc, argv, "-trange");
+    bad &= get_argument (argc, argv, "-time");
+    bad &= get_argument (argc, argv, "-ccd");
+    if (bad) { 
+      fprintf (stderr, "ERROR: syntax error: conflict with -mosaic\n");
+      exit (1);
+    }
+  }
+
+  /* image-based selection */
+  ImageSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-image"))) {
+    remove_argument (N, &argc, argv);
+    ImageFile = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImageExtend = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImageMode = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImageSelect = TRUE;
+    /* check for incompatible arguments: -exptime, -filter, -time, -ccd */
+    bad = get_argument (argc, argv, "-exptime");
+    bad &= get_argument (argc, argv, "-filter");
+    bad &= get_argument (argc, argv, "-trange");
+    bad &= get_argument (argc, argv, "-time");
+    bad &= get_argument (argc, argv, "-ccd");
+    if (bad) { 
+      fprintf (stderr, "ERROR: syntax error: conflict with -image\n");
+      exit (1);
+    }
+  }
+
+  /* define image type */
+  base.TypeSelect = FALSE;
+  base.Type = T_UNDEF;
+  if ((N = get_argument (argc, argv, "-type"))) {
+    remove_argument (N, &argc, argv);
+    base.Type = get_image_type (argv[N]);
+    if (base.Type == T_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image type %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    base.TypeSelect = TRUE;
+    if (base.Type == T_ANY) base.TypeSelect = FALSE;
+  }
+ 
+  /* image mode (mef, splt, etc) */
+  base.ModeSelect = FALSE;
+  base.Mode = M_UNDEF;
+  if ((N = get_argument (argc, argv, "-mode"))) {
+    remove_argument (N, &argc, argv);
+    base.Mode = get_image_mode (argv[N]);
+    if (base.Mode == M_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image mode %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    base.ModeSelect = TRUE;
+  }
+ 
+  /* define time / ranges */
+  tstart = tstop = NULL;
+  base.TimeSelect = base.tstart = base.tstop = 0;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    bad  = get_argument (argc, argv, "-trange");
+    bad &= ohana_str_to_time (argv[N], &base.tstart);
+    if (bad) {
+      fprintf (stderr, "ERROR: syntax error in -time\n");
+      exit (1);
+    }
+    base.tstop = base.tstart;  /* no need for dtime > 0 ? */
+    remove_argument (N, &argc, argv);
+    base.TimeSelect = 1;
+  } else {
+    if (!get_trange_arguments (&argc, argv, &tstart, &tstop, &base.TimeSelect)) {
+      fprintf (stderr, "ERROR: syntax error in -trange\n");
+      exit (1);
+    }
+  }
+
+  /* define filters */
+  base.FilterSelect = FALSE;
+  if (!get_filter_arguments (&argc, argv, &filt, &base.FilterSelect)) {
+    fprintf (stderr, "ERROR: syntax error in -filter\n");
+    exit (1);
+  }
+
+  /* define ccd number */
+  base.CCDSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-ccd"))) {
+    base.CCD = -1;
+    remove_argument (N, &argc, argv);
+    for (i = 0; (i < Nccd) && (base.CCD == -1); i++) {
+      if (strnumcmp (ccds[i], argv[N])) {
+	base.CCD = i;
+      }
+    }
+    if (base.CCD == -1) {
+      fprintf (stderr, "ERROR: ccd %s choice out not found in camera config\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    base.CCDSelect = TRUE;
+  }
+ 
+  /* define exposure time */
+  base.ExptimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-exptime"))) {
+    remove_argument (N, &argc, argv);
+    base.Exptime = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    base.ExptimeSelect = TRUE;
+  }
+ 
+  /* varients on the standard selection */
+  base.EntrySelect = FALSE;
+  if ((N = get_argument (argc, argv, "-entry"))) {
+    remove_argument (N, &argc, argv);
+    base.Entry = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    base.EntrySelect = TRUE;
+  }
+  base.MatchNumber = -1;
+  if ((N = get_argument (argc, argv, "-match"))) {
+    remove_argument (N, &argc, argv);
+    base.MatchNumber = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  base.LabelSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-label"))) {
+    remove_argument (N, &argc, argv);
+    base.Label = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    base.LabelSelect = TRUE;
+  }
+  base.NameSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    base.Name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    base.NameSelect = TRUE;
+  }
+
+  /* these options affect the output mode */
+  output.Close = FALSE;
+  if ((N = get_argument (argc, argv, "-close"))) {
+    if (!base.TimeSelect && !ImageSelect && !MosaicSelect) {       
+      fprintf (stderr, "ERROR: syntax error in -close requires one of: -time -trange -image -mosaic\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    output.Close = TRUE;
+  }
+  output.TimeMode = START;
+  if ((N = get_argument (argc, argv, "-tstop"))) {
+    remove_argument (N, &argc, argv);
+    output.TimeMode = STOP;
+  }
+  if ((N = get_argument (argc, argv, "-treg"))) {
+    remove_argument (N, &argc, argv);
+    output.TimeMode = REG;
+  }
+  output.ElixirSmart = FALSE;
+  if ((N = get_argument (argc, argv, "-ve"))) {
+    remove_argument (N, &argc, argv);
+    output.ElixirSmart = TRUE;
+  }
+  output.verbose = TRUE;
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    remove_argument (N, &argc, argv);
+    output.verbose = FALSE;
+  }
+  output.table = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-fits"))) {
+    remove_argument (N, &argc, argv);
+    output.table = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  output.bintable = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-binfits"))) {
+    remove_argument (N, &argc, argv);
+    output.bintable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  output.Criteria = FALSE;
+  if ((N = get_argument (argc, argv, "-criteria"))) {
+    output.Criteria = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  output.Chipname = FALSE;
+  if ((N = get_argument (argc, argv, "-chipname"))) {
+    output.Chipname = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* these options modify behavior */
+  output.Select = FALSE;
+  if ((N = get_argument (argc, argv, "-select"))) {
+    remove_argument (N, &argc, argv);
+    output.Select = TRUE;
+  }
+ 
+  /* these options modify behavior */
+  Recipe = FALSE;
+  if ((N = get_argument (argc, argv, "-recipe"))) {
+    remove_argument (N, &argc, argv);
+    Recipe = TRUE;
+    if (base.Type != T_UNDEF) {
+      fprintf (stderr, "-recipe and -type cannot be combined\n");
+      exit (1);
+    }
+  }
+ 
+  /* options which alter the database */
+  output.Delete = FALSE;
+  if ((N = get_argument (argc, argv, "-del"))) {
+    remove_argument (N, &argc, argv);
+    output.Delete = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-delete"))) {
+    remove_argument (N, &argc, argv);
+    output.Delete = TRUE;
+  }
+ 
+  output.Altpath = NONE;
+  if ((N = get_argument (argc, argv, "-altpath"))) {
+    if (output.Delete) {
+      fprintf (stderr, "can't combine -delete and -altpath flags\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    if (!strcasecmp (argv[N], "add")) output.Altpath = ADD;
+    if (!strcasecmp (argv[N], "delete")) output.Altpath = DELETE;
+    if (!strcasecmp (argv[N], "update")) output.Altpath = UPDATE;
+    if (!output.Altpath) { 
+      fprintf (stderr, "invalid -altpath option\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  output.Modify = FALSE;
+  if ((N = get_argument (argc, argv, "-modify"))) {
+    if (output.Delete) {
+      fprintf (stderr, "can't combine -delete and -modify flags\n");
+      exit (1);
+    }
+    if (output.Altpath) {
+      fprintf (stderr, "can't combine -altpath and -modify flags\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    output.Modify = TRUE;
+    output.ModifyEntry = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    output.ModifyValue = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    if (!strcasecmp (output.ModifyEntry, "label")) goto valid_entry;
+    if (!strcasecmp (output.ModifyEntry, "order")) goto valid_entry;
+    if (!strcasecmp (output.ModifyEntry, "mode"))  goto valid_entry;
+    if (!strcasecmp (output.ModifyEntry, "tstop")) goto valid_entry;
+    if (!strcasecmp (output.ModifyEntry, "tstart")) goto valid_entry;
+    fprintf (stderr, "invalid entry for -modify %s\n", output.ModifyEntry);
+    exit (1);
+  valid_entry:
+    if (!strcasecmp (output.ModifyEntry, "tstart") || !strcasecmp (output.ModifyEntry, "tstop")) {
+      if (!ohana_str_to_time (output.ModifyValue, &output.TimeValue)) { 
+	fprintf (stderr, "ERROR: invalid time %s\n", output.ModifyValue);
+	exit (1);
+      }
+    }
+  }
+
+  /* consistency checks */
+  if ((base.Type == T_DARK) || (base.Type == T_BIAS) || (base.Type == T_MASK)) {
+    if (base.FilterSelect) {
+      fprintf (stderr, "ERROR: filter invalid with type %s\n", get_type_name(base.Type));
+      exit (1);
+    }
+  }
+  /*
+  if ((base.Type != T_DARK) && base.ExptimeSelect) {
+    fprintf (stderr, "ERROR: exptime invalid with type %s\n", get_type_name(base.Type));
+    exit (1);
+  }
+  */
+  if (output.Select && !base.TimeSelect) {
+    fprintf (stderr, "ERROR: selection missing time\n");
+    exit (1);
+  }
+
+  /* arguments have all been read */
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: detsearch [config ops] [-mosaic name] [-image name Nx Mode] [-time start] [-type type] [-ccd N] [-filter name]\n");
+    exit (1);
+  }
+
+  /* set up criteria based on image, mosaic, or base (all mutually exclusive) */
+  crit = NULL;
+  if (ImageSelect)  
+    crit = ImageCriteria (base, ImageFile, ImageExtend, ImageMode, &Ncrit);
+  if (MosaicSelect) 
+    crit = MosaicCriteria (base, ImageFile, &Ncrit);
+  if (!MosaicSelect && !ImageSelect)
+    crit = ExpandBase (base, &Ncrit, tstart, tstop, filt);
+
+  if (Recipe) {
+    crit = ExpandRecipe (crit, &Ncrit);
+  }
+
+  Ncriteria = Ncrit;
+  criteria = crit;
+
+  return (TRUE);
+}
+
+Criteria *ExpandBase (Criteria base, int *ncrit, time_t *tstart, time_t *tstop, int *filt) {
+
+  Criteria *crit;
+  int i, j, Nc, Ncrit, Ntimes, Nfilt; 
+
+  /* expand multiple -filter, -trange options */
+  Nfilt  = base.FilterSelect;
+  Ntimes = base.TimeSelect;
+  if (Ntimes == 0) Ntimes = 1;
+  if (Nfilt  == 0) Nfilt  = 1;
+
+  Ncrit = Nfilt*Ntimes;
+  ALLOCATE (crit, Criteria, Ncrit);
+
+  Nc = 0;
+  for (i = 0; i < Nfilt; i++) {
+    for (j = 0; j < Ntimes; j++) {
+      crit[Nc] = base;
+      if (tstart != NULL) {
+	crit[Nc].tstart       = tstart[j];
+	crit[Nc].tstop        = tstop[j];
+      } 
+      if (base.FilterSelect) {
+	crit[Nc].Filter       = filt[i];
+      } 
+      Nc ++;
+    }
+  }
+  *ncrit = Ncrit;
+  return (crit);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/criteria.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/criteria.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/criteria.c	(revision 16632)
@@ -0,0 +1,219 @@
+# include "imregister.h"
+# include "detrend.h"
+
+Match CheckCriteria (DetReg *image) {
+
+  Match match;
+  int i, close, crit;
+
+  match.state = MATCH_NONE;
+  match.crit  = 0;
+  match.image = -1;
+
+  crit = 0;
+  close = FALSE;
+  for (i = 0; (i < Ncriteria) && (match.state == MATCH_NONE); i++) {
+
+    if (criteria[i].CCDSelect) {
+      if (image[0].mode == M_MEF) goto valid_ccd;
+      if (image[0].mode == M_MODES) goto valid_ccd;
+      if (image[0].ccd  == criteria[i].CCD) goto valid_ccd;
+      continue;
+    }
+  valid_ccd:
+
+    if (criteria[i].TypeSelect   && (image[0].type            != criteria[i].Type))   continue;
+    if (criteria[i].ModeSelect   && (image[0].mode            != criteria[i].Mode))   continue;
+    if (criteria[i].FilterSelect && (image[0].filter          != criteria[i].Filter)) continue;
+
+    if (criteria[i].EntrySelect  && (image[0].Nentry          != criteria[i].Entry))  continue;
+    if (criteria[i].LabelSelect  && (strcasecmp (image[0].label, criteria[i].Label))) continue;
+    if (criteria[i].NameSelect   && (strstr (image[0].filename, criteria[i].Name) == (char *) NULL)) continue;
+
+    /* looking for the best 'close' match: minimum |dt| */
+    if (criteria[i].TimeSelect   && (image[0].tstart           > criteria[i].tstop))  {
+      close = TRUE;
+      crit  = i;
+      continue;
+    } 
+    if (criteria[i].TimeSelect   && (image[0].tstop            < criteria[i].tstart)) {
+      close = TRUE;
+      crit  = i;
+      continue;
+    } 
+    match.crit  = i;
+    match.state = MATCH_PERFECT;
+  }
+
+  if ((match.state == MATCH_NONE) && close) {
+    match.crit  = crit;
+    match.state = MATCH_CLOSE;
+  }    
+  return (match);
+
+}
+
+/* 
+   the image only needs to match one criterion
+   close only counts for TimeSelect
+   multiple criteria can exist for Range, CCD, Filter
+*/
+
+Match *ExptimeCriteria (DetReg *image, int Nimage, Match *match, int *nmatch) {
+
+  int i, j, Nmatch, Nnew, NNEW, entry;
+  unsigned long dtime;
+  float Chi, ChiMin;
+  Match *new;
+
+  Nmatch = *nmatch;
+
+  Nnew = 0;
+  NNEW = 100;
+  ALLOCATE (new, Match, NNEW);
+
+  for (i = 0; i < Ncriteria; i++) {
+
+    /* find min Chi value */
+    ChiMin = HUGE;
+    for (j = 0; j < Nmatch; j++) {
+      if (match[j].crit != i) continue;
+      if (!criteria[i].ExptimeSelect) {
+	new[Nnew] = match[j];
+	Nnew ++;
+	if (Nnew == NNEW) {
+	  NNEW += 100;
+	  REALLOCATE (new, Match, NNEW);
+	}
+	continue;
+      }
+
+      entry = match[j].image;
+
+      dtime = 0;
+      if (criteria[i].TimeSelect) {
+	if (criteria[i].tstart > image[entry].tstop) 
+	  dtime = criteria[i].tstart - image[entry].tstop;
+	if (criteria[i].tstop < image[entry].tstart) 
+	  dtime = image[entry].tstart - criteria[i].tstop;
+      }
+      Chi = dtime / 864.0 + abs (criteria[i].Exptime - image[entry].exptime);
+      ChiMin = MIN (Chi, ChiMin);
+    }
+
+    /* select entries with Chi <= ChiMin */
+    for (j = 0; j < Nmatch; j++) {
+      if (match[j].crit != i) continue;
+      if (!criteria[i].ExptimeSelect) continue;
+      entry = match[j].image;
+      
+      dtime = 0;
+      if (criteria[i].TimeSelect) {
+	if (criteria[i].tstart > image[entry].tstop) 
+	  dtime = criteria[i].tstart - image[entry].tstop;
+	if (criteria[i].tstop < image[entry].tstart) 
+	  dtime = image[entry].tstart - criteria[i].tstop;
+      }
+      Chi = dtime / 864.0 + abs (criteria[i].Exptime - image[entry].exptime);
+      if (Chi <= ChiMin) {
+	new[Nnew] = match[j];
+	Nnew ++;
+	if (Nnew == NNEW) {
+	  NNEW += 100;
+	  REALLOCATE (new, Match, NNEW);
+	}
+      }
+    }
+  }
+
+  free (match);
+  *nmatch = Nnew;
+  return (new);
+}
+
+Match *CloseCriteria (DetReg *image, int Nimage, Match *match, int *nmatch) {
+
+  int i, j, Nmatch, Nnew, NNEW, Ngood, entry;
+  unsigned long dmin, dtime;
+  Match *new;
+
+  Nmatch = *nmatch;
+
+  Nnew = 0;
+  NNEW = 100;
+  ALLOCATE (new, Match, NNEW);
+
+  for (i = 0; i < Ncriteria; i++) {
+
+    Ngood = 0;
+
+    /* first include only perfect matches */
+    for (j = 0; j < Nmatch; j++) {
+      if (match[j].crit  != i) continue;
+      if (match[j].state != MATCH_PERFECT) continue;
+
+      Ngood ++;
+      new[Nnew] = match[j];
+      Nnew ++;
+      if (Nnew == NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, Match, NNEW);
+      }	
+    } 
+
+    if (Ngood) continue;
+    if (!output.Close) continue;
+    if (!criteria[i].TimeSelect) continue;
+
+    /* find closest time */
+    dmin = 0xffffffff;
+    for (j = 0; j < Nmatch; j++) {
+      if (match[j].crit  != i) continue;
+      entry = match[j].image;
+      dtime = (image[entry].tstop < criteria[i].tstart) ?  criteria[i].tstart - image[entry].tstop : image[entry].tstart - criteria[i].tstop;
+      dmin = MIN (dmin, dtime);
+    }
+
+    /* select images with dtime == dmin */
+    for (j = 0; j < Nmatch; j++) {
+      if (match[j].crit  != i) continue;
+      entry = match[j].image;
+      dtime = (image[entry].tstop < criteria[i].tstart) ?  criteria[i].tstart - image[entry].tstop : image[entry].tstart - criteria[i].tstop;
+      if (dtime <= dmin) {
+	new[Nnew] = match[j];
+	Nnew ++;
+	if (Nnew == NNEW) {
+	  NNEW += 100;
+	  REALLOCATE (new, Match, NNEW);
+	}	
+      }
+    }
+  }
+
+  free (match);
+  *nmatch = Nnew;
+  return (new);
+}
+
+
+
+
+
+/* CheckCriteria returns two pieces of information:
+   match state (MATCH_NONE, MATCH_CLOSE, MATCH_PERFECT)
+   match entry (i)
+*/
+   
+/* match[] contains all potentially valid matches.
+   if they are darks, there will be several with similar values for detdata[i].tstop
+   we want to minimize:
+   (tzero - tstop) and abs (ExpTime - detdata[i].exptime) 
+
+   Chi = (tzero - tstop) / 864 + abs (ExpTime - detdata[i].exptime)
+
+   if (tzero - tstop) = 2 days, this term contributes 200.  
+*/
+
+
+/* CloseCriteria returns all images which are either a perfect match
+   or which are close and have the same minimum time distance */
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/db_names.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/db_names.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/db_names.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "imregister.h"
+# include "detrend.h"
+
+static char *dBFile  = NULL;
+static char *dBPath  = NULL;
+static char *dBTrash = NULL;
+
+/*** these are functions to handle the special detrend.db file/trash names ****/
+
+char *set_dBFile () {
+
+  struct stat statbuf;
+  int status;
+
+  dBPath = DetrendDB;
+
+  /* define dBFile based on config data */
+  ALLOCATE (dBFile, char, strlen (dBPath) + 15);
+  sprintf (dBFile, "%s/detrend.db", dBPath);;
+  ALLOCATE (dBTrash, char, strlen (dBPath) + 15);
+  sprintf (dBTrash, "%s/trash", dBPath);
+
+  /* check on directories */
+  status = stat (dBPath, &statbuf);
+  if (output.Modify) {
+    if (status == -1) {
+      if (mkdirhier (dBPath, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+	fprintf (stderr, "ERROR: can't find or create path %s\n", dBPath);
+	exit (1);
+      }
+    }
+  }
+  if (output.Delete) {
+    status = stat (dBTrash, &statbuf);
+    if (status == -1) {
+      if (mkdirhier (dBTrash, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+	fprintf (stderr, "ERROR: detrend dB trash not found %s\n", dBTrash);
+	exit (1);
+      }
+    }
+  }
+  return (dBFile);
+}
+
+char *get_dBPath () {
+
+  return (dBPath);
+
+}
+
+int delete_image (DetReg *item) {
+  
+  int status;
+  char line[256];
+
+  if (output.verbose) fprintf (stderr, "deleting %s\n", item[0].filename);
+  sprintf (line, "mv -f %s/%s %s", dBPath, item[0].filename, dBTrash);
+  status = system (line);
+  if (status) fprintf (stderr, "trouble moving %s to trash (%s)\n", item[0].filename, dBTrash);
+
+  if (status) 
+    return (FALSE);
+  else 
+    return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/delete.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "imregister.h"
+# include "detrend.h"
+
+void DeleteSubset (FITS_DB *db, DetReg *image, int Nimage, Match *match, int Nmatch) {
+
+  int i, j;
+  int *keep, Ndel, Nsubset;
+  DetReg *subset;
+
+  ALLOCATE (keep, int, MAX (Nimage, 1));
+  for (i = 0; i < Nimage; i++) keep[i] = TRUE;
+  fprintf (stderr, "total of %d detrend images\n", Nimage);
+
+  Ndel = 0;
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    if (i == -1) continue;
+    keep[i] = FALSE;
+    Ndel ++;
+    delete_image (&image[i]);
+  }
+  fprintf (stderr, "delete %d images\n", Ndel);
+  if (Ndel == 0) { 
+    fprintf (stderr, "SUCCESS\n");
+    gfits_db_close (db);
+    exit (0);
+  }
+
+  /* create new data list */
+  Nsubset = Nimage - Ndel;
+  ALLOCATE (subset, DetReg, MAX (1, Nsubset));
+  fprintf (stderr, "keeping %d images\n", Nsubset);
+  for (j = i = 0; i < Nimage; i++) {
+    if (!keep[i]) continue;
+    subset[j] = image[i];
+    j ++;
+  }
+  free (keep);
+  free (image);
+
+  /** we may later want to pull this out and put it elsewhere **/
+  /** free db[0].theader, db[0].table.buffer? **/
+  gfits_table_set_DetReg (&db[0].ftable, subset, Nsubset);
+  gfits_db_save (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/entry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/entry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/entry.c	(revision 16632)
@@ -0,0 +1,112 @@
+# include "imregister.h"
+# include "detrend.h"
+
+DetReg DefineEntry (Descriptor descriptor) {
+  
+  struct timeval now;
+  DetReg newdata;
+
+  gettimeofday (&now, (void *) NULL);
+  
+  /* now we have all of the data (except filename), set the new entry */
+  newdata.tstart    = descriptor.tstart;
+  newdata.tstop     = descriptor.tstop;
+  newdata.treg      = now.tv_sec;
+  newdata.type      = descriptor.type;
+  newdata.filter    = descriptor.filter;
+  newdata.ccd       = descriptor.CCD;
+  newdata.exptime   = descriptor.Exptime;
+  newdata.Norder    = descriptor.order;
+  newdata.mode      = descriptor.mode;
+  newdata.altpath   = FALSE;
+  bzero (newdata.dummy, 58);
+  snprintf (newdata.label, 64, "%s", descriptor.label);
+  
+  return (newdata);
+}
+
+/* we are generating a name based on type, etc.  determine valid path */
+int SaveEntry (char *input, DetReg *newdata, char *ID) {
+
+  int status;
+  int found, Ntry, filestate;
+  char path[256], fullpath[256], filename[256], rootname[256], fullname[256], line[512];
+  char *dBPath;
+  char *filter_basename;
+  struct stat statbuf;
+  FILE *f;
+
+  filter_basename = filterhash[newdata[0].filter];
+  dBPath = get_dBPath ();
+
+  if (newdata[0].type == T_FLAT) {
+    sprintf (path, "%s/%s", get_type_name(newdata[0].type), filter_basename);
+  } else {
+    sprintf (path, "%s", get_type_name(newdata[0].type));
+  }    
+  sprintf (fullpath, "%s/%s", dBPath, path);
+
+  status = stat (fullpath, &statbuf);
+  if (status == -1) {
+    if (errno == ENOENT) {
+      if (mkdirhier (fullpath, S_IRWXU | S_IRWXG | S_IRWXO) == -1) {
+	fprintf (stderr, "ERROR: can't create path %s\n", fullpath);
+	exit (1);
+      }
+    } else {
+      fprintf (stderr, "ERROR: problem with path %s\n", fullpath);
+      exit (1);
+    }
+  }
+
+  /* base filename constructed from detrend type information */
+  switch (newdata[0].type) {
+  case T_DARK:
+  case T_BIAS:
+  case T_MASK:
+    sprintf (rootname, "%s.%s.%d.%02d", ID, get_type_name(newdata[0].type), (int)newdata[0].exptime, newdata[0].ccd);
+    break;
+  default:
+    sprintf (rootname, "%s.%s.%s.%02d", ID, get_type_name(newdata[0].type), filter_basename, newdata[0].ccd);
+  }
+
+  /* find & lock first file of the format name that does not exist */
+  found = FALSE;
+  for (Ntry = 0; !found && (Ntry < 100); Ntry++) {
+    sprintf (filename, "%s/%s.%02d.fits", path, rootname, Ntry);
+    sprintf (fullname, "%s/%s", dBPath, filename);
+    f = fsetlockfile (fullname, 2.0, LCK_XCLD, &filestate);
+    /* if there is an error, it may just mean file is locked. */
+    if (filestate == LCK_EMPTY) {
+	found = TRUE;
+	newdata[0].Nentry = Ntry;
+    } 
+  }
+  if (!found) { 
+    fprintf (stderr, "ERROR: no available target files for %s/%s?\n", path, rootname);
+    exit (1);
+  }
+  strcpy (newdata[0].filename, filename);
+    
+  if (DEBUG) {
+    fprintf (stderr, "path: %s\n", path);
+    fprintf (stderr, "fullpath: %s\n", fullpath);
+    fprintf (stderr, "filename: %s\n", filename);
+    fprintf (stderr, "dBPath: %s\n", dBPath);
+    fprintf (stderr, "line: %s\n", line);
+  }
+
+  /* copy the file to the new name, add entry to database */
+  /* we need some error checking here - complain if filename > 255 */
+  /* the copy replaces the locked file, lock remains valid */
+
+  sprintf (line, "/bin/cp -f %s %s", input, fullname);
+  status = system (line);
+  if (status) {
+    fprintf (stderr, "ERROR: failure in image copy %s to %s\n", input, fullname);
+    exit (1);
+  }
+  fclearlockfile (fullname, f, LCK_XCLD, &filestate);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/image.c	(revision 16632)
@@ -0,0 +1,90 @@
+# include "imregister.h"
+# include "detrend.h"
+
+Criteria *ImageCriteria (Criteria base, char *filename, char *ImageExtend, char *ImageMode, int *ncrit) {
+
+  int i, Ncrit;
+  Header header;
+  Criteria *crit;
+  char line[80];
+
+  Ncrit = 1;
+  ALLOCATE (crit, Criteria, Ncrit);
+
+  /* load options from the image header */
+  if (!gfits_read_header (filename, &header)) {
+    if (output.verbose) fprintf (stderr, "ERROR: trouble reading image header\n");
+    exit (1);
+  }
+
+  /* get Time from header */
+  base.tstop = base.tstart = parse_time (&header);
+  base.TimeSelect = TRUE;
+
+  /* get the CCD */
+  if (!strcasecmp (ImageMode, "SPLIT")) {
+    ALLOCATE (ImageExtend, char, 80);
+    if (!gfits_scan (&header, CCDnumKeyword, "%s", 1, ImageExtend)) {
+      fprintf (stderr, "ERROR: failure to read %s from header\n", CCDnumKeyword);
+      exit (1);
+    }
+  }
+  /* lookup CCD ID from camera config */
+  base.CCD = -1;
+  for (i = 0; (i < Nccd) && (base.CCD == -1); i++) {
+    if (strnumcmp (ccds[i], ImageExtend)) {
+      base.CCD = i;
+    }
+  }
+  if (base.CCD == -1) {
+    fprintf (stderr, "warning: ccd id %s not found\n", ImageExtend);
+    base.CCD = 0;
+  }
+
+  /* get filter from header */
+  if (!gfits_scan (&header, FilterKeyword, "%s", 1, line)) {
+    fprintf (stderr, "ERROR: trouble reading FILTER from header\n");
+    exit (1);
+  }
+  /* filter names in database have . for space */
+  base.Filter = FILTER_NONE;
+  for (i = 0; i < strlen (line); i++) { if (isspace (line[i])) line[i] = '.'; }
+  for (i = 0; (i < NFILTER) && (base.Filter == FILTER_NONE); i++) {
+    if (!strcasecmp (line, filtername[i])) {
+      base.Filter = filternum[i];
+    }
+  }      
+  if (base.Filter == FILTER_NONE) {
+    fprintf (stderr, "ERROR: invalid filter %s\n", line);
+    exit (1);
+  }
+
+  /* get exptime from header */
+  if (!gfits_scan (&header, ExptimeKeyword, "%f", 1, &base.Exptime)) {
+    fprintf (stderr, "ERROR: trouble reading EXPTIME from header\n");
+    exit (1);
+  }
+
+  /* define selections implicit in ImageSelect */
+  if (base.Type != T_MODES) {
+    base.CCDSelect = TRUE;
+  }
+  if ((base.Type != T_DARK) && (base.Type != T_BIAS) && (base.Type != T_MASK)) {
+    base.FilterSelect = TRUE;
+  } else {
+    base.FilterSelect = FALSE;
+  }      
+  if (base.Type == T_DARK) {
+    base.ExptimeSelect = TRUE;
+  } else {
+    base.ExptimeSelect = FALSE;
+  }      
+
+  /* controvesial... */
+  output.Select = TRUE;
+
+  *ncrit = Ncrit;
+  crit[0] = base;
+  return (crit);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/imdef.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/imdef.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/imdef.c	(revision 16632)
@@ -0,0 +1,149 @@
+# include "imregister.h"
+# include "detrend.h"
+
+int DefineImage (char *filename, Descriptor *descriptor) {
+
+  int i, Extend, Nextend;
+  char line[512];
+  Header header;
+
+  /* load remaining options from the image header */
+  if (!gfits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: trouble reading image header\n");
+    exit (1);
+  }
+
+  /* first decide on image TYPE */
+  if (descriptor[0].type == T_UNDEF) {
+    if (!gfits_scan (&header, ImagetypeKeyword, "%s", 1, line)) {
+      fprintf (stderr, "ERROR: failure to read %s from header\n", ImagetypeKeyword);
+      exit (1);
+    }
+    descriptor[0].type = get_image_type (line);
+    if (descriptor[0].type == T_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image type %s\n", line);
+      exit (1);
+    }
+  }    
+  /* conflicts */
+  if ((descriptor[0].type == T_DARK) && (descriptor[0].filter != FILTER_NONE)) {
+    fprintf (stderr, "ERROR: dark can't have a filter\n");
+    exit (1);
+  }
+  if ((descriptor[0].type == T_BIAS) && (descriptor[0].filter != FILTER_NONE)) {
+    fprintf (stderr, "ERROR: bias can't have a filter\n");
+    exit (1);
+  }
+  if ((descriptor[0].type == T_MASK) && (descriptor[0].filter != FILTER_NONE)) {
+    fprintf (stderr, "ERROR: mask can't have a filter\n");
+    exit (1);
+  }
+
+  /* identify MODE (MEF / SPLIT)  */
+  descriptor[0].mode = M_SPLIT;
+  Extend = FALSE;
+  gfits_scan (&header, "EXTEND", "%t", 1, &Extend);
+  if (Extend) {
+    descriptor[0].mode      = M_MEF;
+    descriptor[0].CCD       = Nccd;
+    descriptor[0].CCDSelect = TRUE;
+    gfits_scan (&header, "NEXTEND",  "%d", 1, &Nextend);
+    if (Nextend != Nccd) { 
+      fprintf (stderr, "warning: NEXTEND != Nccd (%d, %d)\n", Nextend, Nccd);
+    }      
+  }
+
+  /* modes: a special case */
+  if (descriptor[0].type == T_MODES) {
+    descriptor[0].mode      = M_MODES;
+    descriptor[0].CCD       = Nccd;
+    descriptor[0].CCDSelect = TRUE;
+  }
+
+  /* now identify CCD number */
+  if (!descriptor[0].CCDSelect) {
+    char ID[64];
+
+    descriptor[0].CCD = -1;
+    if (!gfits_scan (&header, CCDnumKeyword, "%s", 1, ID)) {
+      fprintf (stderr, "ERROR: failure to read %s from header\n", CCDnumKeyword);
+      exit (1);
+    }
+    for (i = 0; (i < Nccd) && (descriptor[0].CCD == -1); i++) {
+      if (strnumcmp (ID, ccds[i])) {
+	descriptor[0].CCD = i;
+      }
+    }
+    if (descriptor[0].CCD == -1) {
+      fprintf (stderr, "warning: ccd id not found\n");
+      descriptor[0].CCD = 0;
+    }
+    descriptor[0].CCDSelect = TRUE;
+  }
+
+  /* now get time range */
+  if (!descriptor[0].TimeSelect) {
+    if (!gfits_scan (&header, "TVSTART",   "%s", 1, line)) {
+      fprintf (stderr, "ERROR: missing start time\n");
+      exit (1);
+    }
+    if (!ohana_str_to_time (line, &descriptor[0].tstart)) { 
+      fprintf (stderr, "ERROR: invalid time %s\n", line);
+      exit (1);
+    }
+    
+    if (!gfits_scan (&header, "TVSTOP",   "%s", 1, line)) {
+      fprintf (stderr, "ERROR: missing stop time\n");
+      exit (1);
+    }
+    if (!ohana_str_to_time (line, &descriptor[0].tstop)) { 
+      fprintf (stderr, "ERROR: invalid time %s\n", line);
+      exit (1);
+    }
+  }
+
+  /* select the filter */
+  if (descriptor[0].type == T_DARK) goto skip_filter;
+  if (descriptor[0].type == T_BIAS) goto skip_filter;
+  if (descriptor[0].type == T_MASK) goto skip_filter;
+  if (descriptor[0].filter != FILTER_NONE) goto skip_filter;
+  if (!gfits_scan (&header, FilterKeyword, "%s", 1, line)) {
+    fprintf (stderr, "ERROR: failure to read %s from header\n", FilterKeyword);
+    exit (1);
+  }
+  for (i = 0; (i < NFILTER) && (descriptor[0].filter == FILTER_NONE); i++) {
+    if (!strcasecmp (line, filtername[i])) {
+      descriptor[0].filter = filternum[i];
+    }
+  }      
+  if (descriptor[0].filter == FILTER_NONE) {
+    fprintf (stderr, "ERROR: invalid filter %s\n", line);
+    exit (1);
+  }
+skip_filter:
+
+  /* set the exposure time, if needed */
+  if (descriptor[0].ExptimeSelect && (descriptor[0].type != T_DARK)) {
+    fprintf (stderr, "exposure time is not allowed for type %s\n", get_type_name(descriptor[0].type));
+    exit (1);
+  }
+  if (!descriptor[0].ExptimeSelect && (descriptor[0].type == T_DARK)) {
+    if (!gfits_scan (&header, ExptimeKeyword,  "%f", 1, &descriptor[0].Exptime)) {
+      fprintf (stderr, "ERROR: failure to read %s from header\n", ExptimeKeyword);
+      exit (1);
+    }
+  }
+
+  /* set the image ID (if not supplied) based on the camera header */
+  if (descriptor[0].imageID == NULL) {
+    if (gfits_scan (&header, "CRUNID",   "%s", 1, line)) {
+      descriptor[0].imageID = strcreate (line);
+    }
+  }
+  if (descriptor[0].imageID == NULL) {
+    descriptor[0].imageID = strcreate ("test");
+  }  
+  
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/match.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/match.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/match.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "imregister.h"
+# include "detrend.h"
+
+Match *MatchCriteria (DetReg *image, int Nimage, int *nmatch) {
+
+  int i;
+  int Nmatch, NMATCH;
+  Match result, *match;
+
+  /* find entries that matches criteria */
+  Nmatch = 0;
+  NMATCH = 100;
+  ALLOCATE (match, Match, NMATCH);
+
+  /* find set of images that matches criteria */
+  for (i = 0; i < Nimage; i++) {
+    result = CheckCriteria (&image[i]);
+    if (result.state == MATCH_NONE) continue;
+
+    result.image = i;
+    match[Nmatch] = result;
+    Nmatch ++;
+    if (Nmatch == NMATCH) {
+      NMATCH += 100;
+      REALLOCATE (match, Match, NMATCH);
+    }
+  }
+
+  *nmatch = Nmatch;
+  return (match);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/modify.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/modify.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/modify.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "imregister.h"
+# include "detrend.h"
+
+int ModifySubset (FITS_DB *db, DetReg *image, int Nimage, Match *match, int Nmatch) {
+  
+  int i, j, value;
+  int *list;
+  
+  value = M_UNDEF;
+
+  ALLOCATE (list, int, Nimage);
+  if (!strcasecmp (output.ModifyEntry, "mode")) {
+    value = get_image_mode (output.ModifyValue);
+    if (value == M_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image mode %s\n", output.ModifyValue);
+      exit (1);
+    }
+  }
+  if (!strcasecmp (output.ModifyEntry, "order")) {
+    value = atoi (output.ModifyValue);
+  }
+
+  /* list matched images */
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    list[j] = i;
+    
+    if (!strcasecmp (output.ModifyEntry, "label")) {
+      snprintf (image[i].label, 64, "%s", output.ModifyValue);
+    }
+    if (!strcasecmp (output.ModifyEntry, "order")) {
+      image[i].Norder = value;
+    }
+    if (!strcasecmp (output.ModifyEntry, "mode")) {
+      image[i].mode   = value;
+    }
+    if (!strcasecmp (output.ModifyEntry, "tstart")) {
+      image[i].tstart = output.TimeValue;
+    }
+    if (!strcasecmp (output.ModifyEntry, "tstop")) {
+      image[i].tstop  = output.TimeValue;
+    }
+  }
+
+  /** we may later want to pull this out and put it elsewhere **/
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, list, Nmatch);
+  for (i = 0; i < Nmatch; i++) {
+    gfits_convert_DetReg ((DetReg *) db[0].vtable.buffer[i], sizeof (DetReg), 1);
+  }
+  gfits_db_update (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/mosaic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/mosaic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/mosaic.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "imregister.h"
+# include "detrend.h"
+
+Criteria *MosaicCriteria (Criteria base, char *filename, int *ncrit) {
+
+  int i, Ncrit;
+  char line[80];
+  Header header;
+  Criteria *crit;
+
+  Ncrit = 1;
+  ALLOCATE (crit, Criteria, Ncrit);
+
+  /* load options from the image header */
+  if (!gfits_read_header (filename, &header)) {
+    if (output.verbose) fprintf (stderr, "ERROR: trouble reading image header\n");
+    exit (1);
+  }
+
+  /* get Time from header */
+  base.tstop = base.tstart = parse_time (&header);
+  base.TimeSelect = TRUE;
+
+  /* get filter from header */
+  if (!gfits_scan (&header, FilterKeyword, "%s", 1, line)) {
+    fprintf (stderr, "ERROR: trouble reading FILTER from header\n");
+    exit (1);
+  }
+  for (i = 0; i < strlen (line); i++) { if (isspace (line[i])) line[i] = '.'; }
+  for (i = 0; (i < NFILTER) && (base.Filter == FILTER_NONE); i++) {
+    if (!strcasecmp (line, filtername[i])) {
+      base.Filter = filternum[i];
+    }
+  }      
+  if (base.Filter == FILTER_NONE) {
+    fprintf (stderr, "ERROR: invalid filter %s\n", line);
+    exit (1);
+  }
+
+  /* get exptime from header */
+  if (!gfits_scan (&header, ExptimeKeyword, "%f", 1, &base.Exptime)) {
+    fprintf (stderr, "ERROR: trouble reading EXPTIME from header\n");
+    exit (1);
+  }
+  
+  /* other settings implied by -mosaic */
+  base.CCDSelect = FALSE;
+  if ((base.Type != T_DARK) && (base.Type != T_BIAS) && (base.Type != T_MASK)) {
+    base.FilterSelect = TRUE;
+  } else {
+    base.FilterSelect = FALSE;
+  }      
+  if (base.Type == T_DARK) {
+    base.ExptimeSelect = TRUE;
+  } else {
+    base.ExptimeSelect = FALSE;
+  }      
+  output.Select = TRUE;
+
+  *ncrit = Ncrit;
+  crit[0] = base;
+  return (crit);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/output.c	(revision 16632)
@@ -0,0 +1,289 @@
+# include "imregister.h"
+# include "detrend.h"
+
+char *RandomPath (char *dBPath);
+extern double drand48();
+
+int OutputSubset (DetReg *image, int Nimage, Match *match, int Nmatch) {
+
+  if (output.table != (char *) NULL) {
+    DumpFitsTable (output.table, image, match, Nmatch);
+  } 
+  if (output.bintable != (char *) NULL) {
+    DumpFitsBintable (output.bintable, image, match, Nmatch);
+  } 
+  PrintSubset (image, match, Nmatch);
+  if (output.verbose) fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+/* write out complete binary FITS table in format of db */
+int DumpFitsBintable (char *filename, DetReg *image, Match *match, int Nmatch) {
+
+  int i, j;
+  FILE *f;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  DetReg *subset;
+
+  ALLOCATE (subset, DetReg, MAX (1, Nmatch));
+  for (i = 0; i < Nmatch; i++){
+    j = match[i].image;
+    memcpy (&subset[i], &image[j], sizeof (DetReg));
+  }
+
+  /* open file for output */
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", filename);
+    exit (1);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_DetReg (&ftable, subset, Nmatch);
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+  fclose (f);
+  exit (0);
+}
+
+int DumpFitsTable (char *filename, DetReg *detdata, Match *match, int Nmatch) {
+  
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  DetReg *newdata;
+  FILE *f;
+  char *startstr, *stopstr, *regstr, *line, key[33], ccdinfo[16];
+  char *filtstr, *typestr, *modestr, *ccdstr, *datestr, *p;
+  int i;
+  time_t tsecond;
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* create table header */
+  gfits_create_table_header (&theader, "TABLE", "MASTER_DETREND");
+      
+  /* add current date/time to header */
+  ohana_str_to_time ("now", &tsecond);
+  datestr = ohana_sec_to_date (tsecond);
+  gfits_modify (&header,  "DATE", "%s", 1, datestr);
+  gfits_modify (&theader, "DATE", "%s", 1, datestr);
+  free (datestr);
+
+  /* define table layout */
+  gfits_define_table_column (&theader, "A32",  "KEY",        "unique identifier",         "");
+  gfits_define_table_column (&theader, "A20",  "START_TIME", "start time of measurement", "yyyy/mm/dd,hh:mm:ss");
+  gfits_define_table_column (&theader, "A20",  "STOP_TIME",  "stop time of measurement",  "yyyy/mm/dd,hh:mm:ss");
+  gfits_define_table_column (&theader, "A20",  "REG_TIME",   "time of registration",      "yyyy/mm/dd,hh:mm:ss");
+  gfits_define_table_column (&theader, "F7.1", "EXPTIME",    "exposure time",             "seconds"); 
+  gfits_define_table_column (&theader, "A10",  "IMAGETYP",   "detrend type",              "");
+  gfits_define_table_column (&theader, "A10",  "FILTER",     "filter name",               "");
+  gfits_define_table_column (&theader, "A7",   "CCDINFO",    "ccd information",                  "");
+  gfits_define_table_column (&theader, "A7",   "MODE",       "data format mode",                  "");
+  gfits_define_table_column (&theader, "I3",   "VERSION",    "image version number",      "");
+  gfits_define_table_column (&theader, "I3",   "ORDER",      "selection order",           "");
+  gfits_define_table_column (&theader, "A64",  "LABEL",      "data label",                "");
+  gfits_define_table_column (&theader, "A256", "PATH",       "filename in db",            "");
+  
+  /* define TNULL, TNVAL values */
+  gfits_modify (&theader, "TNULL1",  "%s", 1, "NULL");  /* KEY        */
+  gfits_modify (&theader, "TNULL2",  "%s", 1, "NULL");  /* START_TIME */
+  gfits_modify (&theader, "TNULL3",  "%s", 1, "NULL");  /* STOP_TIME  */
+  gfits_modify (&theader, "TNULL4",  "%s", 1, "NULL");  /* REG_TIME   */
+  gfits_modify (&theader, "TNULL5",  "%s", 1, "NaN");   /* EXPTIME    */
+  gfits_modify (&theader, "TNULL6",  "%s", 1, "NULL");  /* IMAGETYP   */
+  gfits_modify (&theader, "TNULL7",  "%s", 1, "NULL");  /* FILTER     */
+  gfits_modify (&theader, "TNULL8",  "%s", 1, "NULL");  /* CCDINFO    */
+  gfits_modify (&theader, "TNULL9",  "%s", 1, "NULL");  /* MODE       */
+  gfits_modify (&theader, "TNULL10", "%s", 1, "-100");  /* VERSION    */
+  gfits_modify (&theader, "TNULL11", "%s", 1, "-100");  /* ORDER      */
+  gfits_modify (&theader, "TNULL12", "%s", 1, "NULL");  /* LABEL      */
+  gfits_modify (&theader, "TNULL13", "%s", 1, "NULL");  /* PATH       */
+
+  gfits_modify (&theader, "TNVAL1",  "%s", 1, "NA");    /* KEY        */
+  gfits_modify (&theader, "TNVAL2",  "%s", 1, "NA");    /* START_TIME */
+  gfits_modify (&theader, "TNVAL3",  "%s", 1, "NA");    /* STOP_TIME  */
+  gfits_modify (&theader, "TNVAL4",  "%s", 1, "NA");    /* REG_TIME   */
+  gfits_modify (&theader, "TNVAL5",  "%s", 1, "Inf");   /* EXPTIME    */
+  gfits_modify (&theader, "TNVAL6",  "%s", 1, "NA");    /* IMAGETYP   */
+  gfits_modify (&theader, "TNVAL7",  "%s", 1, "NA");    /* FILTER     */
+  gfits_modify (&theader, "TNVAL8",  "%s", 1, "NA");    /* CCDINFO    */
+  gfits_modify (&theader, "TNVAL9",  "%s", 1, "NA");    /* MODE       */
+  gfits_modify (&theader, "TNVAL10", "%s", 1, "-200");  /* VERSION    */
+  gfits_modify (&theader, "TNVAL11", "%s", 1, "-200");  /* ORDER      */
+  gfits_modify (&theader, "TNVAL12", "%s", 1, "NA");    /* LABEL      */
+  gfits_modify (&theader, "TNVAL13", "%s", 1, "NA");    /* PATH       */
+
+  /* create table, add data values */
+  gfits_create_table (&theader, &table);
+  
+  /* add data to table */
+  for (i = 0; i < Nmatch; i++) {
+    newdata = &detdata[match[i].image];
+
+    /* key = 02Bk02.flat.V.00.00 */
+    p = strrchr (newdata[0].filename, '/');
+    if (p == (char *) NULL) {
+      p = newdata[0].filename;
+    } else {
+      p ++;
+    }
+    bzero (key, 33);
+    strncpy (key, p, 32);
+    if ((p = strrchr (key, '.')) != (char *) NULL) *p = 0;
+
+    startstr = ohana_sec_to_date (newdata[0].tstart);
+    stopstr  = ohana_sec_to_date (newdata[0].tstop);
+    regstr   = ohana_sec_to_date (newdata[0].treg);
+    typestr  = get_type_name(newdata[0].type);
+    modestr  = get_mode_name(newdata[0].mode);
+    filtstr  = filterhash[newdata[0].filter];
+
+    if (newdata[0].mode == M_SPLIT) {
+      ccdstr   = ccds[newdata[0].ccd];
+    } else {
+      sprintf (ccdinfo, "%-3d", newdata[0].ccd);
+      ccdstr   = ccdinfo;
+    }
+
+    line = gfits_table_print (&table, key, startstr, stopstr, regstr, 
+			     newdata[0].exptime, typestr, filtstr, ccdstr, modestr,
+			     newdata[0].Nentry, newdata[0].Norder, 
+			     newdata[0].label, newdata[0].filename);
+
+    gfits_add_rows (&table, line, 1, strlen(line));
+    free (line);
+    free (startstr);
+    free (stopstr);
+    free (regstr);
+  }
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Failure writing fits table\n");
+    return (FALSE);
+  }
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &table);
+  fclose (f);
+  exit (0);
+}
+
+/* Select, TimeMode are global */
+int PrintSubset (DetReg *detdata, Match *match, int Nmatch) {
+  
+  char *dBPath, *Path, *typestr, *filtstr, filename[128];
+  char *timestr, *modestr, *ccdstr, ccdinfo[16], ccdformat[16];
+  int i, j, Nc;
+  struct timeval now;
+  long A;
+
+  gettimeofday (&now, NULL);
+  A = now.tv_usec + now.tv_sec;
+  srand48 (A);
+
+  Nc = strlen (ccds[0]);
+  sprintf (ccdformat, "%%%dd", Nc);
+  dBPath = get_dBPath ();
+
+  /* list matched images */
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    switch (output.TimeMode) {
+    case START:
+      timestr = ohana_sec_to_date (detdata[i].tstart);
+      break;
+    case STOP:
+      timestr = ohana_sec_to_date (detdata[i].tstop);
+      break;
+    case REG:
+      timestr = ohana_sec_to_date (detdata[i].treg);
+      break;
+    default:
+      if (output.verbose) fprintf (stderr, "ERROR: bad TimeMode\n");
+      exit (1);
+    }
+
+    typestr = get_type_name(detdata[i].type);
+    modestr = get_mode_name(detdata[i].mode);
+    filtstr = filterhash[MIN (MAX (detdata[i].filter, 0), NFILTER - 1)];
+
+    if ((detdata[i].mode == M_SPLIT) && (detdata[i].ccd >= -1) && (detdata[i].ccd < Nccd)) {
+      ccdstr   = ccds[detdata[i].ccd];
+    } else {
+      sprintf (ccdinfo, ccdformat, detdata[i].ccd);
+      ccdstr   = ccdinfo;
+    }
+
+    /* output mode (Select vs List) */
+    if (output.Chipname && criteria[0].CCDSelect && detdata[i].mode == M_MEF) {
+      snprintf (filename, 128, "%s[%s]", detdata[i].filename, ccds[criteria[0].CCD]);
+    } else {
+      strcpy (filename, detdata[i].filename);
+    }
+
+    if (output.Select) {
+      if (detdata[i].altpath) {
+	Path = RandomPath (dBPath);
+      } else {
+	Path = dBPath;
+      }
+      fprintf (stdout, "%s/%s\n", Path, filename);
+    } else {
+      fprintf (stdout, "%-40s = %19s %7s %6s %6s %s %2d %2d %6.1f  %20s  %1d\n", 
+	       filename, timestr, modestr, typestr, filtstr, ccdstr,
+	       detdata[i].Nentry, detdata[i].Norder, detdata[i].exptime, detdata[i].label, detdata[i].altpath);
+    }
+    free (timestr);
+  }  
+  return (TRUE);
+}
+
+char *RandomPath (char *dBPath) {
+  
+  int N;
+
+  N = (NDetrendAltDB + 0.99)*drand48();
+  if (N == NDetrendAltDB) return (dBPath);
+  return (DetrendAltDB[N]);
+}
+
+int PrintCriteria () {
+
+  int i;
+  char *start, *stop;
+
+  for (i = 0; i < Ncriteria; i++) {
+    start = ohana_sec_to_date (criteria[i].tstart);
+    stop  = ohana_sec_to_date (criteria[i].tstop);
+    
+    fprintf (stdout, "%19s %19s %7s %6s %s %6.1f\n", 
+	     start, stop, get_type_name(criteria[i].Type), filterhash[criteria[i].Filter], 
+	     ccds[criteria[i].CCD], criteria[i].Exptime);
+
+    free (start);
+    free (stop);
+  }
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/recipe.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/recipe.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/recipe.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "imregister.h"
+# include "detrend.h"
+
+Criteria *ExpandRecipe (Criteria *base, int *Ncrit) {
+
+  int i, N, Ns, NS;
+  Criteria *crit;
+  int Nbase;
+  
+  Nbase = *Ncrit;
+  NS = Ns = 0;
+  ALLOCATE (crit, Criteria, 1);
+
+  for (N = 0; N < Nbase; N++) {
+
+    RecipeType = LoadRecipe (filterhash[base[N].Filter], &Nrecipe);
+
+    NS += Nrecipe;
+    REALLOCATE (crit, Criteria, NS);
+    
+    for (i = 0; i < Nrecipe; i++) {
+      crit[Ns] = base[N];
+      crit[Ns].TypeSelect = TRUE;
+      crit[Ns].Type = get_image_type (RecipeType[i]);
+      if (crit[Ns].Type == T_UNDEF) { 
+	fprintf (stderr, "ERROR: invalid image type %s\n", RecipeType[i]);
+	exit (1);
+      }
+      if (!strcasecmp (RecipeType[i], "bias") ||
+	  !strcasecmp (RecipeType[i], "dark") ||
+	  !strcasecmp (RecipeType[i], "mask")) {
+	crit[Ns].FilterSelect = FALSE;
+      }
+      if (!strcasecmp (RecipeType[i], "flat") ||
+	  !strcasecmp (RecipeType[i], "scatter") ||
+	  !strcasecmp (RecipeType[i], "fringe") ||
+	  !strcasecmp (RecipeType[i], "frpts") ||
+	  !strcasecmp (RecipeType[i], "modes")) {
+	crit[Ns].FilterSelect = TRUE;
+      }
+      if (!strcasecmp (RecipeType[i], "modes")) {
+	crit[Ns].CCDSelect = FALSE;
+      }
+      /*      
+      if (!strcasecmp (RecipeType[i], "dark")) {
+      crit[Ns].ExptimeSelect = TRUE;
+      } 
+      */
+      Ns ++;
+    }
+  }
+
+  *Ncrit = Ns;
+  return (crit);
+}
+
+char **LoadRecipe (char *filter, int *nrecipe) {
+  
+  char **RecipeType;
+  int Nrecipe, NRECIPE;
+
+  int Nfield, found;
+  char *c, *p1, line[256], list[256], Filter[64];
+  FILE *f;
+  
+  /* open filter list file */
+  f = fopen (RecipeFile, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error reading recipe %s\n", RecipeFile);
+    exit (1);
+  }
+
+  /* allocate dataspace needed */
+  NRECIPE = 10;
+  Nrecipe = 0;
+  ALLOCATE (RecipeType, char *, NRECIPE);
+
+  /* load data from file */
+  found = FALSE;
+  while (!found && (scan_line (f, line) != EOF)) {
+    for (c = line; isspace (*c); c++);
+    if (*c == '#') continue;
+    Nfield = sscanf (c, "%s %s", Filter, list);
+    if (Nfield != 2) { continue; }
+
+    if (!strcasecmp (filter, Filter)) found = TRUE;
+  }
+  fclose (f);  
+
+  if (!found) {
+    fprintf (stderr, "can't find filter %s\n", filter);
+    exit (1);
+  }
+
+  /* list contains word,word,word - parse these words to RecipeType */
+  p1 = list;
+  while ((c = strchr (p1, ',')) != (char *) NULL) {
+    *c = 0;
+    RecipeType[Nrecipe] = strcreate (p1);  
+    p1 = c + 1;
+    Nrecipe ++;
+    if (Nrecipe == NRECIPE) {
+      NRECIPE += 10;
+      REALLOCATE (RecipeType, char *, NRECIPE);
+    }
+  }
+  if (*p1) {
+    RecipeType[Nrecipe] = strcreate (p1);  
+    Nrecipe ++;
+  }    
+  *nrecipe = Nrecipe;
+  return (RecipeType);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/select.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/select.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/select.c	(revision 16632)
@@ -0,0 +1,90 @@
+# include "imregister.h"
+# include "detrend.h"
+
+Match SelectEntry (DetReg *image, int Nimage, Match *list, int Nlist, Criteria *crit) {
+
+  /* force a single selection */
+
+  /* at this point, all external criteria for the given detrend images
+     are equivalently good (ie, date range, filters, type, etc).  the 
+     selection here is based on other options: 
+     1) Norder         - user assigned value to force selection
+     2) tstart         - start valid time
+     3) Nentry         - version number
+     4) MatchNumber    - method to force selection 
+  */
+
+  int i, j, entry, order, matchnum;
+  int nmatch, Nmatch;
+  unsigned int tstart;
+  Match *match, *tmatch, answer;
+
+  Nmatch = Nlist;
+  match = list;
+
+  /* select all images with the same, maximum Norder */
+  nmatch = 0;
+  ALLOCATE (tmatch, Match, Nmatch);
+  order = image[match[0].image].Norder;
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    order = MAX (order, image[i].Norder);
+  }
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    if (order <= image[i].Norder) {
+      tmatch[nmatch] = match[j];
+      nmatch ++;
+    }
+  }
+  match = tmatch;
+  Nmatch = nmatch;
+
+  /* select all images with the same, maximum tstart */
+  nmatch = 0;
+  ALLOCATE (tmatch, Match, Nmatch);
+  tstart = image[match[0].image].tstart;
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    tstart = MAX (tstart, image[i].tstart);
+  }
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    if (tstart <= image[i].tstart) {
+      tmatch[nmatch] = match[j];
+      nmatch ++;
+    }
+  }
+  free (match);
+  match = tmatch;
+  Nmatch = nmatch;
+
+  /* select all images with the same, maximum Nentry */
+  nmatch = 0;
+  ALLOCATE (tmatch, Match, Nmatch);
+  entry = image[match[0].image].Nentry;
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    entry = MAX (entry, image[i].Nentry);
+  }
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j].image;
+    if (entry <= image[i].Nentry) {
+      tmatch[nmatch] = match[j];
+      nmatch ++;
+    }
+  }
+  free (match);
+  match = tmatch;
+  Nmatch = nmatch;
+
+  /* if there are multiple matches, select MatchNumber entry 
+     0-Nmatch-1 , or -1 -> -Nmatch (saturate at ends) */
+  matchnum = crit[match[0].crit].MatchNumber;
+  if (matchnum < 0) matchnum += Nmatch;
+  matchnum = MAX (0, MIN (Nmatch - 1, matchnum));
+
+  answer = match[matchnum];
+  free (match);
+  return (answer);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/detrend/unique.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/detrend/unique.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/detrend/unique.c	(revision 16632)
@@ -0,0 +1,123 @@
+# include "imregister.h"
+# include "detrend.h"
+
+/* define a list of best images which have unique properties */ 
+Match *UniqueSubset (DetReg *image, int Nimage, Match *match, int *nmatch) {
+
+  int Nsubset, Nunique, Ncrit, NCRIT;
+  int i, j, N, Nmatch, found;
+  Criteria *crit;
+  Match *subset, *unique, *local;
+
+  Nmatch = *nmatch;
+  ALLOCATE (local, Match, Nmatch);
+
+  /* create a set of complete criteria derived from the images */
+
+  Ncrit = 0;
+  NCRIT = 10;
+  ALLOCATE (crit, Criteria, NCRIT);
+  bzero (crit, (NCRIT - Ncrit)*sizeof(Criteria));
+
+  for (i = 0; i < Nmatch; i++) {
+    
+    local[i] = match[i];
+    N = match[i].image;
+    if (N == -1) continue;
+
+    found = FALSE;
+    for (j = 0; (j < Ncrit) && !found; j++) {
+      if (!cmp_crit (&crit[j], &image[N])) continue;
+      found = TRUE;
+      local[i].crit  = j;
+    }      
+    if (found) continue;
+    local[i].crit  = Ncrit;
+    set_crit (&crit[Ncrit], &image[N]);
+    Ncrit ++;
+    if (Ncrit == NCRIT) {
+      NCRIT += 10;
+      REALLOCATE (crit, Criteria, NCRIT);
+      bzero (&crit[Ncrit], (NCRIT - Ncrit)*sizeof(Criteria));
+    }
+  }
+      
+  /* we now have a set of criteria (crit, Ncrit) which describe the matched images
+     and a set of local matches (local) which link images to crit */
+
+  ALLOCATE (subset, Match, Nmatch);
+  ALLOCATE (unique, Match, Nmatch);
+
+  Nunique = 0;
+  for (i = 0; i < Ncrit; i++) {
+
+    /* extract the subset of local matches which are associated with crit[i] */
+    Nsubset= 0;
+    for (j = 0; j < Nmatch; j++) {
+      if (local[j].crit  != i) continue;
+      subset[Nsubset] = local[j];
+      Nsubset ++;
+    }
+
+    /* subset, Nsubset has a unique list of matched images */
+    unique[Nunique] = SelectEntry (image, Nimage, subset, Nsubset, crit);
+    Nunique ++;
+  }
+  free (subset);
+  free (local);
+  free (match);
+
+  match = unique;
+  *nmatch = Nunique;
+
+  return (match);
+}
+
+
+/* 
+   return list of all images that have the same value of:
+   criteria = tstart, tstop, filter, ccd, type, exptime
+*/
+
+
+int cmp_crit (Criteria *crit, DetReg *image) {
+
+  /* image and criteria need to match on:
+     tstart, tstop, filter, ccd, type, exptime
+  */
+  
+  if (crit[0].Filter  != image[0].filter ) return (FALSE);
+  if (crit[0].CCD     != image[0].ccd    ) return (FALSE);
+  if (crit[0].Type    != image[0].type   ) return (FALSE);
+  /* if (crit[0].Exptime != image[0].exptime) return (FALSE); */
+
+  if (crit[0].tstart  > image[0].tstop) return (FALSE);
+  if (crit[0].tstop   < image[0].tstart) return (FALSE);
+
+  /* we have overlapping time ranges.  set crit[0] to have the 
+     maximum of these time ranges */
+
+  crit[0].tstop  = MIN (crit[0].tstop,  image[0].tstop);
+  crit[0].tstart = MAX (crit[0].tstart, image[0].tstart);
+
+  return (TRUE);
+
+}
+
+int set_crit (Criteria *crit, DetReg *image) {
+
+  /* image and criteria need to match on:
+     tstart, tstop, filter, ccd, type, exptime
+  */
+
+  crit[0].tstart  = image[0].tstart;
+  crit[0].tstop   = image[0].tstop;  
+  crit[0].Filter  = image[0].filter; 
+  crit[0].CCD     = image[0].ccd;    
+  crit[0].Type    = image[0].type;   
+  crit[0].Exptime = image[0].exptime;
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,34 @@
+
+- imregister-1-5 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+
+- imregister-1-4:
+  * dropped IMAGE_CATALOG from config
+  * fixed imageID if not in header
+  * changed mkdirhier to updated version (libohana 1.7)
+
+- imregister-1-3:
+  * modifications to use the new DVO load functions (libdvo-1-0)
+  * minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+- imregister-1-2:
+  * substantial changes to use autocoded tables
+  * reorgainzation of db I/F code to use fits_db functions
+
+- imregister-1-1:
+  * I made a lot of very minor changes to cleanup the FITS database
+  * interactions.  These should not have any impact on behavior.
+
+- imregister-1-0:
+  * I've added the newest versions of imregister to the CVS tree with the
+  * base tag imregister-1-0 (should have used imregister-3-0? still
+  * learning about revision control).  
+
+comment from before importing to CVS:
+  imregister-3.0 represents a completely new organization of these
+  programs, with the twin goals of making the FITS table handling more
+  cleanly encapsulated and of easing the addition of a mysql database
+  engine in place of the FITS tables.  As programs from imregister-1.0
+  are adapted to match this structure, they will be moved into the
+  imregister-3.0 directory.  
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/Compatibility
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/Compatibility	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/Compatibility	(revision 16632)
@@ -0,0 +1,58 @@
+
+transearch-1.0: 
+  v1: ok
+  v2: ok
+
+transearch-2.0: 
+  v1: not compatible, exits gracefully
+  v2: ok
+
+transreg-1.0:
+  v1: ok
+  v2: not compatible, exits gracefully
+
+transreg-1.0:
+  v1: not compatible, exits gracefully
+  v2: ok
+
+photsearch-1.0:
+  v1: ok
+  v2: ok
+
+photsearch-2.0:
+  v1: not compatible, exits gracefully
+  v2: ok
+
+photreg-1.0:
+  v1: ok
+  v2: ok [creates v1]
+
+photreg-2.0:
+  v1: not compatible, exits gracefully
+  v2: ok
+
+imsearch-1.0:
+  v1, v2: ok
+  v3: not compatible, exits gracefully
+
+imregister-1.0:
+  v1, v2: ok
+  v3: not compatible ****
+
+imregister-2.0:
+  v1, v2: ok
+  v3: not compatible, exits gracefully
+
+imsort-1.0:
+  v1, v2: ok
+  v3: not compatible ****
+
+imsort-2.0:
+  v1, v2: ok
+  v3: not compatible ***
+
+imregtable-3.0:
+  v1, v2: not compatibe, exits gracefully
+  v3: ok
+
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/autocode.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/autocode.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/autocode.txt	(revision 16632)
@@ -0,0 +1,20 @@
+
+I have been working to convert these functions to use libautocode to
+generate the table I/O APIs automatically.  A single table defines the
+layout of the table as well as the C structure.  A perl script uses a
+template to generate code to perform the byte swaping, to construct
+the table and add data or extract data from the table.
+
+I discovered that 'photreg' was mis-coded in Fread: it was not
+swapping the entry for refcode.  I have put in a 'rawshort' method to
+handle this for now, but it is fragile: it will only work on
+big-endian machines.  The tables need to be updated and the entry
+returned to short.  This can be done with the existing convert
+operations.
+
+as of 2005/03/30, I have converted the spsearch, photsearch functions,
+but I have not completely tested them.
+
+I am having some errors in the table creation: some lines are dropping
+the leading ' in the wrong place.  
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/dbtools.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/dbtools.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/dbtools.txt	(revision 16632)
@@ -0,0 +1,41 @@
+
+Elixir uses several databases to store a variety of information.
+One of these databases is the photometry database, with several
+interface tools (status, nrphot, addstar, etc).  The other databases
+are manipulated with the tools found in this directory.  In addition,
+tools used to abstract the camera description, photcodes, and filters
+are included here.
+
+imregister   : add images to the image registration database (imreg.db)
+
+imsearch     : find images in imreg.db
+
+imsort       : add images to imreg.db and pass to elixir systems
+
+imstatreg    : update stats to imreg.db (fwhm, flux, bias)
+
+detregister  : add images to the detrend database
+
+detsearch    : find images in the detrend database
+
+photreg      : add photometry datapoints to zeropoint db (phot.db)
+
+photsearch   : search phot.db
+
+transreg     : add transparency points to database (trans.db)
+
+transsearch  : search trans.db
+
+photcode     : find photcode for given image
+
+filtnames    : filter name lookups
+
+cameraconfig : get configuration information for camera
+
+As in all Elixir programs, a reference to a specific CCD in a MEF
+image can be done with (file) (ccd) MEF, where the value of 'ccd' is
+one of the valid extension names, associated in the header with the
+keyword defined by CCDNUM-KEYWORD.  In addition, searches (imsearch,
+detsearch) may be restricted to specific ccds with the -ccd flag,
+which also takes the extension name ID.
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/det.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/det.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/det.txt	(revision 16632)
@@ -0,0 +1,46 @@
+
+detregister:
+-time")) {
+-label")) {
+-ID")) {
+-order")) {
+-type")) {
+-ccd")) {
+-exptime")) {
+-filter")) {
+
+detsearch:
+--help		: ok
+-ccd		: ok
+-close		: ok
+-exptime	: ok
+-filter		: ok
+-h		: ok
+-image		: ok
+-label		: ok
+-mosaic		: ok
+-recipe		: ok
+-select		: ok
+-time		: ok
+-trange		: ok
+-treg		: ok
+-tstop		: ok
+-type		: ok
+-ve		: ok
+-quiet		: ok
+
+-match		: ?
+-entry		: ok
+
+-fits		: ok
+-binfits	: ok
+-del		: ok
+-delete		: ok
+-modify		: ok
+
+--help : clean up usage statement
+
+option behavior: 
+
+-close implies -time or -trange
+-select returns best for all detrend base selection
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/detsearch.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/detsearch.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/detsearch.txt	(revision 16632)
@@ -0,0 +1,74 @@
+
+detregister / detsearch MEF support:
+
+issue of database image format:
+
+filename			type	CCD  mode
+modes/2001A.modes.R.12.00.fits  modes   12   modes
+flat/R/02Bk06.flat.R.00.00.fits flat    00   split
+flat/R/03Ak01.flat.R.00.fits    flat    12   mef
+
+detsearch / detregister concepts:
+
+selection rules:
+
+ match all simple filters 
+
+ -image foo.fits[ccd 08] matches (split 08) or (mef NCCD)
+ 
+ if CCD is defined, return foo.fits[ext] if foo.fits is MEF
+
+simple filters:
+
+ -ccd (N)                       : match ccd
+ -time yyyy/mm/dd,HH:MM:SS      : match time
+ -trange (start) (stop)         : match time range
+ -entry (value)                 : match entry (entry == version number)
+ -label (word)                  : match this label
+ -filter (name)                 : match filter
+ -exptime (value)               : match exposure time
+
+complex rules:
+ -image (filename) (ccd) (mode) : determine filters from image
+
+ -mosaic (filename)		: determine filters from image
+
+ -recipe			: determine filters from image
+
+ -type (type)                   : match type, limit valid filters
+
+ -match (value)                 : only list the Nth matched entry ???
+
+ -close                         : allow non-perfect matches
+
+ -select                        : select 'best' match
+
+display rules:
+ -tstop                         : display end of valid time range
+ -treg                          : display time of image registration
+ -ve                            : Elixir verbose (SUCCESS / ERROR) 
+ -quiet                         : Elixir quiet (no SUCCESS / ERROR) 
+
+
+behaviour rules:
+ -modify (entry) (value)        : change entry for matched images to value
+  [possible -modify entries: label, order, tstart, tstop]
+
+ -del    : delete the matched entries
+ -delete : delete the matched entries
+
+
+-image sets:  -filter, -ccd, -time, -exptime
+-mosaic sets: -filter, -time, -exptime, (-ccds?)
+-recipe sets -type, for each type, sets -
+
+possible values for -type:  mask, bias, dark, flat, fringe, scatter, modes
+
+valid filters for type selections:
+  mask:    -ccd, -label, -entry, -time || -trange
+  bias:    -ccd, -label, -entry, -time || -trange
+  dark:    -ccd, -label, -entry, -time || -trange, -exptime
+  flat:    -ccd, -label, -entry, -time || -trange, -filter
+  fringe:  -ccd, -label, -entry, -time || -trange, -filter
+  scatter: -ccd, -label, -entry, -time || -trange, -filter
+  modes:   -ccd, -label, -entry, -time || -trange, -filter
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/imreg.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/imreg.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/imreg.txt	(revision 16632)
@@ -0,0 +1,25 @@
+
+command-line options from imregister:
+-split	     - OK
+-noreg	     - OK
+
+command-line options from imsearch:
+-type	     - ok
+-etime	     - ok
+-mode	     - ok
+-ccd	     - ok
+-filter	     - ok
+-name	     - ok
+
+-treg	     -ok
+-seq	     -ok
+-pt	     -ok
+-table	     -ok
+-bintable    -ok
+-del	     -ok
+-delete	     -ok
+-newpath     -ok
+-mef2split   -ok 
+-split2mef   -ok
+
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/imregister.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/imregister.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/imregister.txt	(revision 16632)
@@ -0,0 +1,63 @@
+
+This directory contains several routines which are related to
+maintaining a small, elixir-internal databases about the images which
+have been obtained.
+
+This database can be used to find the location on disk of the images
+which we have analysed, or to display various statistics about images,
+or to find types of images which have been obtained.  
+
+The basic program is 'imregister', which places the basic information
+about an image in the database, as determined from the header.  The
+program is invoked with: {\tt imregister (filename) [-split]}.  The
+optional flag is used to tell the program to distinguish the
+individual (SPLIT) frames of a mosaic CCD from an individual CCD which
+should be treated as an isolated image.  
+
+The second program is 'imsort', which does the same task as
+'imregister', but it also sends a trigger to the IMSTAT elixir and if
+needed to the PTOLEMY elixir.  For this program, the -split flag makes
+a difference in how these images are treated in the elixir processes.
+The basic point is that a SINGLE image /fullpath/filename.fits
+produces analysis files of the form /newpath/filename.ext while a
+SPLIT image will have the form /fullpath/word/wordNN.fits and output
+files of the form /newpath/word/wordNN.ext.  
+
+May 11, 2000
+
+I have been working to clean up some of the details of the Elixir
+system.  There are three big issues I have been attempting to address.
+First, I have wanted to create a single set of Elixirs for both MEF
+and SPLIT (and even SINGLE) images.  I also want to minimize the
+number of programs are required to know something special about our
+system, our camera, or our method of naming files.  Finally, I have
+been trying to automate the selection of the appropriate detrend data.
+These are connected problems, in many ways.
+
+Here, in order, are the programs (and scripts) needed to run the
+Elixir system for which these issues are relevant:
+
+elixir.fork:  this program is launched by the camera to introduce a
+	      new image to the system.  It must understand the
+	      difference between SPLIT and MEF, and also the naming
+	      convention.
+
+imsort:	      this program adds the image to the database and passes a
+	      trigger to the elixirs ptolemy and imstats.  imsort
+	      needs to distinguish SPLIT, MEF, and SINGLE images, and
+	      it must know the naming convention.  
+
+elixir (ptolemy): this script is now independent of the mode and
+		  naming issues
+
+elixir (imstats): this script is now independent of the mode and
+		  naming issues
+
+flatten:	  this script needs to distinguish SPLIT and MEF
+		  images (it is told the mode by the input line), but
+		  it does not know the naming convention.
+
+imstats:	  this script needs to distinguish SPLIT and MEF
+		  images (it is told the mode by the input line), but
+		  it does not know the naming convention.
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/imtable.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/imtable.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/imtable.txt	(revision 16632)
@@ -0,0 +1,22 @@
+
+Image Table: run @ 6 AM in ert
+
+- for given time period:
+
+* are all images in database? (compare archive db & elixir db)
+* have all images passed imstats?
+
+- complete images should be extracted into a table, sent to CADC
+- missing images should be registered or a warning sent on failure
+  (relink on /data/kapu/elixir/cfh12k)
+
+- nostat images should be sent to imstats
+  (launch imstats to process)
+ 
+* imsearch output format CADC: 
+
+  fits_define_table_column (&theader, "A64",   "FILE",       "filename in db",        "",                              1.0, 0.0);
+  fits_define_table_column (&theader, "F7.1",  "SKY",        "background level",     "counts / pixel",                 1.0, 0.0); 
+  fits_define_table_column (&theader, "F6.1",  "BIAS",       "bias level",           "counts / pixel",                 1.0, 0.0); 
+  fits_define_table_column (&theader, "F5.2",  "FWHM",       "image quality",        "pixels",                         1.0, 0.0); 
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.2.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.2.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.2.txt	(revision 16632)
@@ -0,0 +1,63 @@
+
+problem:  imstatreg is too slow because of network I/O
+
+option 1: add mysql db to imstats system
+
+option 2: create client / server pair for imregister / imstatreg
+
+option 3: create buffer file for network I/O, local daemon for update
+
+1: best soln but will take a while
+2: ok option, but significant programming effort (worse than 1)
+3: easy programming, acceptable
+
+for imstatreg update, we need the only following data:
+
+obstime (unsigned int)
+ccd     (char or int)
+fwhm
+bias
+sky
+ra
+dec
+
+imstatreg -client:
+
+ read image info
+ load temp db
+ append data
+ close
+
+imstatreg -daemon:
+
+ load temp db
+ load main db
+ match images
+ update db
+ close db
+ empty temp db
+
+------------------------------------------------------
+
+detsearch needs optional alternative detrend.db paths
+
+- add column ALTPATH : true / false
+- add option -altpath :
+  - select images
+  - select ALTPATH images
+  - find subset 'add'
+  - find subset 'remove'
+  - 'remove': unlink files & unset ALTPATH
+  - 'add'   : copy files & set ALTPATH
+  
+
+if (ADD)    : all images in match are 'add', no images are 'delete'
+if (DELETE) : all images in match are 'delete', no images are 'add'
+if (UPDATE) : ??
+
+-----------------------------------------------------
+
+photreg / photsearch 
+
+- need to define the target photometry system in the output table.
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.old.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.old.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.old.txt	(revision 16632)
@@ -0,0 +1,12 @@
+
+there are some issues with the imregister database that should get
+addressed eventually.  currently, I am loading and saving the entire
+file each time I make a change.  this seems like a bad plan.  when we
+get a few hundred nights of images in there, we will have several
+megabytes to load, change, and save each time.  two things could
+change.  first, imregister (imsort) could only add a record at the end
+of the file.  second, the imstatreg function could find the right
+image and write over the few needed bytes.
+
+should I uses mmap to do the I/O?
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/notes.txt	(revision 16632)
@@ -0,0 +1,101 @@
+
+imsearch & CADC distribution:
+
+i need to create raw image tables for the CADC for only those images
+which have been processed (-proc t) and for which a distribution table
+has not been created.
+
+imsearch -modify help
+imsearch -modify path /oldpath /newpath
+imsearch -modify mode [mef/split] 
+imsearch -modify dist [t/f]
+
+history:
+
+v1 : < 2002.09 
+
+ - FITS table interface had errors, incorrect TFORM values
+ - imreg db used pseudo FITS table
+
+v2 : 2002.09 
+
+ - FITS table interface repaired
+ - imreg db uses pseudo FITS table
+ - unwieldy files which contain many functions (esp detsearch /
+   imsearch)
+
+v3 : 2002.11
+
+ - FITS table interface repaired
+ - imreg db converted to read FITS tables
+ - use of vtable interface introduced
+ - db interactions abstracted to allow for SQL
+ - reorganization of files
+
+v3: functions & dependancies
+
+function             : external : globals               : structs
+
+WriteFIFO            : ohana    :		        :
+LoadCameraConfig     : ohana    : ccd data, keywords	:
+MatchCCDName         : ohana    : ccd data, keywords	:
+ConfigCamera         : ohana    : ccd data, keywords	:
+LoadFilterList       : ohana    : filt data, keywords	:
+MatchFilterList      : ohana    : filt data             :
+ConfigInit           : ohana    : keywords  
+get_fwhm	     : ohana
+load_probes	     : ohana
+parse_time	     : ohana    : keywords
+get_trange_arguments : ohana
+make_backup	     : ohana
+uppercase	     : 
+check_unixtime	     : UNUSED
+sort (various)	     : 
+
+(why aren't these in libohana?)
+dms_to_ddd
+str_to_radec
+chk_time
+str_to_time
+str_to_dtime
+sec_to_jd
+jd_to_sec
+date_to_sec
+Fseek - allow for timeout...
+
+problems:
+
+ imregister2.c: args
+ imsort2.c: args, SubmitImages
+ imstatreg2.c: args
+ photcode.c: ConfigSystem (ConfigCamera ConfigFilters)
+ photreg2.c: make_backup
+ photsearch2.c: DumpFitsTable
+ showiminfo.c: args
+ transearch2: LoadFilters, DumpFitsTable
+ transreg2: make_backup
+
+main programs:
+
+cameraconfig
+convertimreg
+filtnames
+imphotsearch
+imregister2
+imsearch2
+imsort2
+imstatreg2
+photcode
+photreg2
+photsearch2
+showiminfo
+transearch
+transreg
+
+
+dependency types:
+
+external libraries
+local library
+group 
+program-specific functions
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/photdb.dat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/photdb.dat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/photdb.dat	(revision 16632)
@@ -0,0 +1,349 @@
+u 2003/02/10,13:00:46  25.3434 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:27:24  25.3435 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:33:10  25.3496 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:38:47  25.3583 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/10,13:56:21  25.3455 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/24,12:36:34  25.2875 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/24,12:37:43  25.2855 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/09,13:01:29  25.3035 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/09,13:05:05  25.3034 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/09,13:06:14  25.3004 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/02/24,12:39:01  25.3197 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/02/23,10:10:59  26.4664 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/23,10:11:59  26.4654 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/23,10:13:00  26.4604 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,12:00:51  26.4463 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,12:01:43  26.4393 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,12:02:35  26.4343 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/09,12:47:05  26.4692 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/09,12:47:48  26.4642 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/09,12:48:40  26.4624 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,10:17:28  25.9736 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,10:20:12  25.9708 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,10:20:55  25.9648 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/08,13:30:08  25.9878 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/08,13:30:51  25.9862 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/08,13:31:43  25.9816 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,12:07:20  25.9939 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,12:10:39  25.9897 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,12:09:47  25.9722 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/09,12:26:03  25.9581 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/09,12:26:55  25.9529 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/09,12:27:38  25.9617 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/12,15:18:51  26.0073 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/02/23,10:25:32  25.7384 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/23,10:28:07  25.7415 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/23,10:28:59  25.7465 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/08,13:18:37  25.7317 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/08,13:19:29  25.7307 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/08,13:20:12  25.7289 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,12:15:24  25.7579 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,12:18:51  25.7489 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/09,13:22:04  25.7434 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/09,13:23:39  25.7397 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,12:18:00  25.7399 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/09,13:22:56  25.7318 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/02/23,10:33:44  24.7826 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/23,10:36:54  24.7967 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,12:26:47  24.7562 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/09,13:12:43  24.7879 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/09,13:13:26  24.7888 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,12:23:19  24.7178 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,12:25:46  24.7117 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/09,13:11:51  24.7789 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/03/24,15:07:46  26.4566 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/03/30,13:12:34  26.4501 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+i 2003/03/25,15:12:48  25.7633 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+r 2003/03/24,15:10:56  25.9917 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/03/25,15:21:27  26.0231 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+u 2003/03/22,15:11:13  25.4630 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/03/23,15:12:14  25.3056 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+z 2003/03/24,14:59:16  24.8271 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/03/30,13:20:55  24.7152 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/04/25,09:06:28  26.4030 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,12:38:26  25.9774 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,13:14:35  25.9455 25.9780  0.0046    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/25,08:55:23  25.9287 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,08:44:44  25.9646 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,10:44:32  25.9647 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,13:05:05  26.0053 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,08:47:28  25.9676 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,13:06:05  25.9697 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,09:57:10  25.7930 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/04/25,08:58:07  25.7034 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/04/25,09:00:43  24.7533 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/06/09,14:36:14  25.2311 25.2800  0.0071    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/05/30,14:21:41  25.2892 25.2800  0.0150    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+r 2003/06/08,14:43:35  25.9302 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/02,07:20:29  25.7291 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/04,06:40:27  25.7566 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/05,06:21:27  25.5921 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/06,05:58:59  25.7441 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/08,14:48:20  25.6812 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/02,07:23:22  24.8465 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/09,14:42:25  24.7583 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/06/24,14:36:40  25.2756 25.2800  0.0361    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/29,14:36:40  25.2756 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/01,13:04:48  25.2674 25.2800  0.0365    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/05,14:51:04  25.2739 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/27,14:43:26  25.2580 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/30,14:44:00  25.1926 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/06/23,10:19:29  26.4170 26.4600  0.0112    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/24,10:28:33  26.4245 26.4600  0.0086    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/26,11:56:32  26.4183 26.4600  0.0130    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/27,10:17:02  26.4285 26.4600  0.0113    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/29,09:53:25  26.4350 26.4600  0.0274    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/28,12:25:29  26.4477 26.4600  0.0251    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/01,09:52:16  26.4206 26.4600  0.0130    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/04,10:25:06  26.4018 26.4600  0.0143    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/05,10:25:14  26.4114 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/22,14:27:01  26.4249 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/29,14:33:38  26.4104 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/01,13:01:55  26.4169 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/24,14:39:24  26.4019 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/30,14:40:59  26.3187 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/06/22,12:56:00  25.9895 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/23,10:13:35  25.9652 25.9780  0.0047    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/24,10:19:55  25.9644 25.9780  0.0033    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/26,12:02:09  25.9610 25.9780  0.0073    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/27,10:19:46  25.9708 25.9780  0.0008    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/29,09:56:18  25.9528 25.9780  0.0089    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/28,12:28:22  25.9663 25.9780  0.0058    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/01,09:55:00  25.9672 25.9780  0.0073    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/04,10:29:42  25.9544 25.9780  0.0103    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/05,10:16:36  25.9552 25.9780  0.0067    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/05,14:48:46  25.9320 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/22,14:29:45  25.9493 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/24,14:42:17  25.9354 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/27,14:49:29  25.9371 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/29,14:45:27  25.9172 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/30,14:52:30  25.9221 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/01,13:07:49  25.9294 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/07,07:42:14  25.8036 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/22,12:58:53  25.7312 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/24,10:25:49  25.7261 25.7430  0.0095    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/26,11:59:16  25.7120 25.7430  0.0099    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/27,10:22:39  25.7250 25.7430  0.0103    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/29,09:59:02  25.7016 25.7430  0.0193    6   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/28,12:30:57  25.7047 25.7430  0.0152    6   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/04,10:33:53  25.7089 25.7430  0.0085    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/05,10:21:04  25.7078 25.7430  0.0080    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/01,09:57:53  25.7179 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/22,14:22:42  25.7170 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/24,14:45:01  25.7069 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/27,14:46:36  25.7100 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/29,14:39:33  25.6881 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/30,14:46:45  25.6658 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/23,10:16:27  24.8045 24.8000  0.0426    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/24,10:22:47  24.8213 24.8000  0.0363    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/27,10:25:23  24.8190 24.8000  0.0415    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/29,10:01:55  24.7694 24.8000  0.0431    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/28,12:33:41  24.7714 24.8000  0.0408    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/01,10:00:28  24.8012 24.8000  0.0394    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/04,10:31:43  24.7981 24.8000  0.0419    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/05,10:23:05  24.7617 24.8000  0.0311    4   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/24,14:33:30  24.7644 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/27,14:52:13  24.7629 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/29,14:42:34  24.7233 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/30,14:49:37  24.7408 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/05/25,08:16:48  26.4408 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/25,14:02:24  26.4275 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/25,14:03:59  26.4430 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/26,14:50:55  26.4043 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/26,07:54:11  26.4084 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/25,08:18:23  26.3957 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,10:26:41  25.9994 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,10:27:41  25.9876 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,14:06:51  25.9703 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,14:38:23  25.9785 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/26,14:47:54  25.9553 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,14:08:26  25.9845 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,14:40:16  25.9925 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/26,07:58:30  25.9474 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,08:23:08  25.9621 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,06:04:10  25.9786 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,10:29:16  25.9440 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/05/27,06:06:54  25.7535 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,10:31:52  25.7376 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/25,14:11:19  25.7157 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,14:43:26  25.7314 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/26,14:45:01  25.7264 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/25,14:12:54  25.7356 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,14:44:52  25.7485 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/26,08:02:41  25.7276 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/25,08:27:35  25.6939 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,06:08:29  25.6955 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,10:33:27  25.6919 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/05/25,08:30:28  24.8014 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:15:38  24.7352 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:17:13  24.7520 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:39:50  24.7505 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:42:25  24.7538 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:44:52  24.7559 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,14:50:55  24.7465 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/26,08:08:00  24.6889 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/26,08:09:44  24.7414 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/25,08:32:03  24.7488 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/07/22,13:40:22  25.3017 25.2800  0.0209    6   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/31,10:28:33  25.2284 25.2800  0.0319    7   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/01,11:32:47  25.2627 25.2800  0.0124    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/22,11:26:35  25.2747 25.2800  0.0072    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/07/30,12:30:05  26.3704 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:31:32  26.3815 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:32:24  26.4011 26.4600  0.0175    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:33:15  26.3942 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:34:07  26.3715 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:34:59  26.3837 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:36:43  26.3226 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:38:26  26.3463 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:39:18  26.3810 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:12:46  26.4141 26.4600  0.0199    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:14:38  26.2761 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:44:18  26.4026 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:45:10  26.3946 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:46:10  26.4046 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:47:02  26.3942 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:47:54  26.4032 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:48:46  26.4307 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:49:37  26.4329 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/01,14:30:46  26.4302 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:35:51  26.3759 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:37:35  26.3472 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:13:46  26.3669 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:40:19  26.4117 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:41:19  26.4284 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:42:20  26.4288 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:43:11  26.3882 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:44:21  26.4019 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:45:21  26.4233 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:46:22  26.3867 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:47:13  26.4394 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:48:23  26.4528 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,12:49:23  26.4335 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:15:30  26.2898 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:16:22  26.2841 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:28:01  26.3029 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:32:12  26.2736 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:33:12  26.3506 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:34:22  26.3716 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:35:22  26.3566 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:36:14  26.3866 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:37:23  26.3626 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:38:23  26.3926 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:39:24  26.3606 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:40:16  26.3566 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:41:25  26.3863 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:42:25  26.3973 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:50:29  26.4281 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,14:51:21  26.4151 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/22,11:20:06  26.4140 26.4600  0.0058    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:36:02  26.3875 26.4600  0.0082    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:36:54  26.3962 26.4600  0.0061    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:38:47  26.3939 26.4600  0.0048    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:39:38  26.3879 26.4600  0.0071    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/01,11:24:17  26.4161 26.4600  0.0192    7   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/22,13:42:40  26.4298 26.4600  0.0089    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:23:57  26.3996 26.4600  0.0087    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:35:02  26.3865 26.4600  0.0082    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:37:55  26.3802 26.4600  0.0061    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:40:30  26.3766 26.4600  0.0064    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:41:22  26.3746 26.4600  0.0090    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:42:31  26.3733 26.4600  0.0090    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,10:43:23  26.3783 26.4600  0.0086    5   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/07/30,12:28:04  25.9364 25.9780  0.0140    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/01,14:28:45  25.9363 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/01,11:28:27  25.9590 25.9780  0.0195    7   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/22,11:22:16  25.9475 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/22,13:38:03  25.9685 25.9780  0.0152    5   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/31,10:30:43  25.9386 25.9780  0.0138    5   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/08/01,14:35:13  25.7086 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/01,11:30:28  25.7165 25.7430  0.0193    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/22,11:17:57  25.7288 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/22,13:44:49  25.7200 25.7430  0.0187    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/31,10:32:52  25.6899 25.7430  0.0179    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/08/01,14:37:06  24.7903 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/22,11:24:17  24.7831 24.8000  0.0416    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/22,13:46:50  24.7811 24.8000  0.0401    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/31,10:26:15  24.7419 24.8000  0.0384    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/21,06:16:07  24.8628 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/08/21,09:56:35  25.3331 25.2800  0.0357    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/22,06:16:24  25.4472 25.2800  0.0382    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/22,09:13:32  25.3878 25.2800  0.0050    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/25,12:39:10  25.4175 25.2800  0.0310    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/28,10:14:35  25.3980 25.2800  0.0296    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/29,08:14:38  25.3912 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/29,08:15:38  25.3885 25.2800  0.0373    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/30,09:59:02  25.3895 25.2800  0.0318    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/31,07:15:10  25.4075 25.2800  0.0273    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/09/04,08:31:03  25.3510 25.2800  0.0058    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/25,05:52:39  25.3050 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/30,07:13:00  25.4598 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/08/27,15:09:21  26.5096 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/03,15:00:34  26.5288 26.4600  0.0205    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/23,14:57:24  26.5457 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,14:25:00  26.5669 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/04,15:11:05  26.4714 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/28,07:13:09  26.5061 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/21,10:07:58  26.4956 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/22,06:24:46  26.5343 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/25,12:36:51  26.5242 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/28,10:18:54  26.5111 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/29,08:22:24  26.5010 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,09:56:44  26.5113 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/31,07:19:37  26.5286 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/04,08:28:53  26.4813 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/23,07:09:15  26.5158 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/25,05:50:21  26.4298 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,07:10:33  26.5390 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/03,05:49:29  26.4413 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/08/23,14:50:55  26.0223 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,14:27:10  26.0383 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/03,15:02:35  26.0080 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/04,15:13:14  25.9757 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,09:52:24  25.9954 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/21,09:59:36  25.9575 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/22,06:18:25  26.0393 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/22,09:15:50  26.0112 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/25,12:34:50  26.0245 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/29,08:17:57  25.9944 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/31,07:21:47  26.0173 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/23,07:05:13  26.0000 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,07:06:23  26.0434 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/03,05:45:10  25.9892 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/09/03,15:04:45  25.7557 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/23,14:52:56  25.7570 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,14:29:02  25.7823 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/04,15:06:20  25.7414 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/28,07:18:20  25.7614 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/22,06:20:35  25.7676 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/22,09:17:42  25.7562 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,09:50:24  25.7790 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/21,10:02:21  25.7279 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/25,12:41:36  25.7803 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/28,10:20:55  25.7747 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/29,08:24:25  25.7721 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/31,07:13:00  25.7795 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/04,08:33:30  25.7536 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/23,07:07:23  25.7556 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,07:08:32  25.7745 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/03,05:47:19  25.7456 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/08/27,15:18:00  24.7928 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,15:15:24  24.8363 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/03,15:09:21  24.8027 24.8000  0.0193    4   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/23,14:59:42  24.7762 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,14:33:38  24.8063 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/04,15:15:15  24.7638 24.8000  0.0355    5   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,07:21:12  24.8333 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/21,10:05:13  24.7669 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/22,09:11:13  24.7917 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/25,12:43:46  24.7967 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,10:22:56  24.8075 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/29,08:20:06  24.7902 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,09:54:25  24.8141 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/31,07:17:28  24.8038 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/04,08:35:31  24.7788 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/22,06:22:36  24.8321 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/23,07:03:04  24.7013 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/25,05:44:00  24.7611 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,07:04:13  24.8370 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/03,05:43:00  24.7850 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/photdb.src
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/photdb.src	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/photdb.src	(revision 16632)
@@ -0,0 +1,349 @@
+photreg -photcode i -trange 2003/02/08,13:18:37 1s -zp 25.7317 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/08,13:19:29 1s -zp 25.7307 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/08,13:20:12 1s -zp 25.7289 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/08,13:30:08 1s -zp 25.9878 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/08,13:30:51 1s -zp 25.9862 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/08,13:31:43 1s -zp 25.9816 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/09,12:26:03 1s -zp 25.9581 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/09,12:26:55 1s -zp 25.9529 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/09,12:27:38 1s -zp 25.9617 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/09,12:47:05 1s -zp 26.4692 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/09,12:47:48 1s -zp 26.4642 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/09,12:48:40 1s -zp 26.4624 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/09,13:01:29 1s -zp 25.3035 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/09,13:05:05 1s -zp 25.3034 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/09,13:06:14 1s -zp 25.3004 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/09,13:11:51 1s -zp 24.7789 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/09,13:12:43 1s -zp 24.7879 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/09,13:13:26 1s -zp 24.7888 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/09,13:22:04 1s -zp 25.7434 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/09,13:22:56 1s -zp 25.7318 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/09,13:23:39 1s -zp 25.7397 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:00:46 1s -zp 25.3434 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:27:24 1s -zp 25.3435 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:33:10 1s -zp 25.3496 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:38:47 1s -zp 25.3583 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/10,13:56:21 1s -zp 25.3455 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/12,15:18:51 1s -zp 26.0073 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/23,10:10:59 1s -zp 26.4664 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/23,10:11:59 1s -zp 26.4654 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/23,10:13:00 1s -zp 26.4604 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/23,10:17:28 1s -zp 25.9736 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/23,10:20:12 1s -zp 25.9708 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/23,10:20:55 1s -zp 25.9648 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/23,10:25:32 1s -zp 25.7384 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/23,10:28:07 1s -zp 25.7415 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/23,10:28:59 1s -zp 25.7465 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/23,10:33:44 1s -zp 24.7826 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/23,10:36:54 1s -zp 24.7967 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/24,12:00:51 1s -zp 26.4463 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/24,12:01:43 1s -zp 26.4393 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/02/24,12:02:35 1s -zp 26.4343 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/24,12:07:20 1s -zp 25.9939 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/24,12:09:47 1s -zp 25.9722 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/02/24,12:10:39 1s -zp 25.9897 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/24,12:15:24 1s -zp 25.7579 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/24,12:18:00 1s -zp 25.7399 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/02/24,12:18:51 1s -zp 25.7489 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/24,12:23:19 1s -zp 24.7178 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/24,12:25:46 1s -zp 24.7117 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/02/24,12:26:47 1s -zp 24.7562 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/24,12:36:34 1s -zp 25.2875 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/24,12:37:43 1s -zp 25.2855 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/02/24,12:39:01 1s -zp 25.3197 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/03/22,15:11:13 1s -zp 25.4630 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/03/23,15:12:14 1s -zp 25.3056 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/03/24,14:59:16 1s -zp 24.8271 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/03/24,15:07:46 1s -zp 26.4566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/03/24,15:10:56 1s -zp 25.9917 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/03/25,15:12:48 1s -zp 25.7633 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/03/25,15:21:27 1s -zp 26.0231 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/03/30,13:12:34 1s -zp 26.4501 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/03/30,13:20:55 1s -zp 24.7152 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/25,08:55:23 1s -zp 25.9287 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/04/25,08:58:07 1s -zp 25.7034 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/04/25,09:00:43 1s -zp 24.7533 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/04/25,09:06:28 1s -zp 26.4030 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,10:44:32 1s -zp 25.9647 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,12:38:26 1s -zp 25.9774 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,13:05:05 1s -zp 26.0053 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,13:06:05 1s -zp 25.9697 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/26,13:14:35 1s -zp 25.9455 -dzp 0.0046 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/27,08:44:44 1s -zp 25.9646 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/27,08:47:28 1s -zp 25.9676 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/04/27,09:57:10 1s -zp 25.7930 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,08:16:48 1s -zp 26.4408 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,08:18:23 1s -zp 26.3957 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/25,08:23:08 1s -zp 25.9621 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/25,08:27:35 1s -zp 25.6939 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,08:30:28 1s -zp 24.8014 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,08:32:03 1s -zp 24.7488 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,14:02:24 1s -zp 26.4275 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/25,14:03:59 1s -zp 26.4430 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/25,14:06:51 1s -zp 25.9703 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/25,14:08:26 1s -zp 25.9845 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/25,14:11:19 1s -zp 25.7157 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/25,14:12:54 1s -zp 25.7356 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:15:38 1s -zp 24.7352 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:17:13 1s -zp 24.7520 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:39:50 1s -zp 24.7505 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:42:25 1s -zp 24.7538 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:44:52 1s -zp 24.7559 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/25,14:50:55 1s -zp 24.7465 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/26,07:54:11 1s -zp 26.4084 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/26,07:58:30 1s -zp 25.9474 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/26,08:02:41 1s -zp 25.7276 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/26,08:08:00 1s -zp 24.6889 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/05/26,08:09:44 1s -zp 24.7414 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/26,14:45:01 1s -zp 25.7264 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/26,14:47:54 1s -zp 25.9553 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/05/26,14:50:55 1s -zp 26.4043 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,06:04:10 1s -zp 25.9786 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,06:06:54 1s -zp 25.7535 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,06:08:29 1s -zp 25.6955 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,10:26:41 1s -zp 25.9994 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,10:27:41 1s -zp 25.9876 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,10:29:16 1s -zp 25.9440 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,10:31:52 1s -zp 25.7376 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,10:33:27 1s -zp 25.6919 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,14:38:23 1s -zp 25.9785 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/05/27,14:40:16 1s -zp 25.9925 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,14:43:26 1s -zp 25.7314 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/05/27,14:44:52 1s -zp 25.7485 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/05/30,14:21:41 1s -zp 25.2892 -dzp 0.0150 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/02,07:20:29 1s -zp 25.7291 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/02,07:23:22 1s -zp 24.8465 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/04,06:40:27 1s -zp 25.7566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/05,06:21:27 1s -zp 25.5921 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/06,05:58:59 1s -zp 25.7441 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/08,14:43:35 1s -zp 25.9302 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/08,14:48:20 1s -zp 25.6812 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/09,14:36:14 1s -zp 25.2311 -dzp 0.0071 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/09,14:42:25 1s -zp 24.7583 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/22,12:56:00 1s -zp 25.9895 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/22,12:58:53 1s -zp 25.7312 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/22,14:22:42 1s -zp 25.7170 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/22,14:27:01 1s -zp 26.4249 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/22,14:29:45 1s -zp 25.9493 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/23,10:13:35 1s -zp 25.9652 -dzp 0.0047 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/23,10:16:27 1s -zp 24.8045 -dzp 0.0426 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/23,10:19:29 1s -zp 26.4170 -dzp 0.0112 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/24,10:19:55 1s -zp 25.9644 -dzp 0.0033 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/24,10:22:47 1s -zp 24.8213 -dzp 0.0363 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/24,10:25:49 1s -zp 25.7261 -dzp 0.0095 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/24,10:28:33 1s -zp 26.4245 -dzp 0.0086 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/24,14:33:30 1s -zp 24.7644 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/24,14:36:40 1s -zp 25.2756 -dzp 0.0361 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/24,14:39:24 1s -zp 26.4019 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/24,14:42:17 1s -zp 25.9354 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/24,14:45:01 1s -zp 25.7069 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/26,11:56:32 1s -zp 26.4183 -dzp 0.0130 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/26,11:59:16 1s -zp 25.7120 -dzp 0.0099 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/26,12:02:09 1s -zp 25.9610 -dzp 0.0073 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/27,10:17:02 1s -zp 26.4285 -dzp 0.0113 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/27,10:19:46 1s -zp 25.9708 -dzp 0.0008 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/27,10:22:39 1s -zp 25.7250 -dzp 0.0103 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/27,10:25:23 1s -zp 24.8190 -dzp 0.0415 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/27,14:43:26 1s -zp 25.2580 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/27,14:46:36 1s -zp 25.7100 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/27,14:49:29 1s -zp 25.9371 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/27,14:52:13 1s -zp 24.7629 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/28,12:25:29 1s -zp 26.4477 -dzp 0.0251 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/28,12:28:22 1s -zp 25.9663 -dzp 0.0058 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/28,12:30:57 1s -zp 25.7047 -dzp 0.0152 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/28,12:33:41 1s -zp 24.7714 -dzp 0.0408 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/29,09:53:25 1s -zp 26.4350 -dzp 0.0274 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/29,09:56:18 1s -zp 25.9528 -dzp 0.0089 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/29,09:59:02 1s -zp 25.7016 -dzp 0.0193 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/29,10:01:55 1s -zp 24.7694 -dzp 0.0431 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/29,14:33:38 1s -zp 26.4104 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/29,14:36:40 1s -zp 25.2756 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/29,14:39:33 1s -zp 25.6881 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/29,14:42:34 1s -zp 24.7233 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/29,14:45:27 1s -zp 25.9172 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/06/30,14:40:59 1s -zp 26.3187 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/06/30,14:44:00 1s -zp 25.1926 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/06/30,14:46:45 1s -zp 25.6658 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/06/30,14:49:37 1s -zp 24.7408 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/06/30,14:52:30 1s -zp 25.9221 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/01,09:52:16 1s -zp 26.4206 -dzp 0.0130 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/01,09:55:00 1s -zp 25.9672 -dzp 0.0073 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/01,09:57:53 1s -zp 25.7179 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/01,10:00:28 1s -zp 24.8012 -dzp 0.0394 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/01,13:01:55 1s -zp 26.4169 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/01,13:04:48 1s -zp 25.2674 -dzp 0.0365 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/01,13:07:49 1s -zp 25.9294 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/04,10:25:06 1s -zp 26.4018 -dzp 0.0143 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/04,10:29:42 1s -zp 25.9544 -dzp 0.0103 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/04,10:31:43 1s -zp 24.7981 -dzp 0.0419 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/04,10:33:53 1s -zp 25.7089 -dzp 0.0085 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/05,10:16:36 1s -zp 25.9552 -dzp 0.0067 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/05,10:21:04 1s -zp 25.7078 -dzp 0.0080 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/05,10:23:05 1s -zp 24.7617 -dzp 0.0311 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/05,10:25:14 1s -zp 26.4114 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/05,14:48:46 1s -zp 25.9320 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/05,14:51:04 1s -zp 25.2739 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/07,07:42:14 1s -zp 25.8036 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/21,06:16:07 1s -zp 24.8628 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/22,11:17:57 1s -zp 25.7288 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/22,11:20:06 1s -zp 26.4140 -dzp 0.0058 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/22,11:22:16 1s -zp 25.9475 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/22,11:24:17 1s -zp 24.7831 -dzp 0.0416 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/22,11:26:35 1s -zp 25.2747 -dzp 0.0072 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/22,13:38:03 1s -zp 25.9685 -dzp 0.0152 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/22,13:40:22 1s -zp 25.3017 -dzp 0.0209 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/22,13:42:40 1s -zp 26.4298 -dzp 0.0089 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/22,13:44:49 1s -zp 25.7200 -dzp 0.0187 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/22,13:46:50 1s -zp 24.7811 -dzp 0.0401 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/30,12:28:04 1s -zp 25.9364 -dzp 0.0140 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:30:05 1s -zp 26.3704 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:31:32 1s -zp 26.3815 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:32:24 1s -zp 26.4011 -dzp 0.0175 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:33:15 1s -zp 26.3942 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:34:07 1s -zp 26.3715 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:34:59 1s -zp 26.3837 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:35:51 1s -zp 26.3759 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:36:43 1s -zp 26.3226 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:37:35 1s -zp 26.3472 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:38:26 1s -zp 26.3463 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:39:18 1s -zp 26.3810 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:40:19 1s -zp 26.4117 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:41:19 1s -zp 26.4284 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:42:20 1s -zp 26.4288 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:43:11 1s -zp 26.3882 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:44:21 1s -zp 26.4019 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:45:21 1s -zp 26.4233 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:46:22 1s -zp 26.3867 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:47:13 1s -zp 26.4394 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:48:23 1s -zp 26.4528 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,12:49:23 1s -zp 26.4335 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:12:46 1s -zp 26.4141 -dzp 0.0199 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:13:46 1s -zp 26.3669 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:14:38 1s -zp 26.2761 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:15:30 1s -zp 26.2898 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:16:22 1s -zp 26.2841 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:28:01 1s -zp 26.3029 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:32:12 1s -zp 26.2736 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:33:12 1s -zp 26.3506 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:34:22 1s -zp 26.3716 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:35:22 1s -zp 26.3566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:36:14 1s -zp 26.3866 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:37:23 1s -zp 26.3626 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:38:23 1s -zp 26.3926 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:39:24 1s -zp 26.3606 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:40:16 1s -zp 26.3566 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:41:25 1s -zp 26.3863 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:42:25 1s -zp 26.3973 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:44:18 1s -zp 26.4026 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:45:10 1s -zp 26.3946 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:46:10 1s -zp 26.4046 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:47:02 1s -zp 26.3942 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:47:54 1s -zp 26.4032 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:48:46 1s -zp 26.4307 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:49:37 1s -zp 26.4329 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:50:29 1s -zp 26.4281 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/30,14:51:21 1s -zp 26.4151 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:23:57 1s -zp 26.3996 -dzp 0.0087 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/07/31,10:26:15 1s -zp 24.7419 -dzp 0.0384 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/07/31,10:28:33 1s -zp 25.2284 -dzp 0.0319 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/07/31,10:30:43 1s -zp 25.9386 -dzp 0.0138 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/07/31,10:32:52 1s -zp 25.6899 -dzp 0.0179 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:35:02 1s -zp 26.3865 -dzp 0.0082 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:36:02 1s -zp 26.3875 -dzp 0.0082 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:36:54 1s -zp 26.3962 -dzp 0.0061 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:37:55 1s -zp 26.3802 -dzp 0.0061 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:38:47 1s -zp 26.3939 -dzp 0.0048 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:39:38 1s -zp 26.3879 -dzp 0.0071 -Nmeas 6 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:40:30 1s -zp 26.3766 -dzp 0.0064 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:41:22 1s -zp 26.3746 -dzp 0.0090 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:42:31 1s -zp 26.3733 -dzp 0.0090 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/07/31,10:43:23 1s -zp 26.3783 -dzp 0.0086 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/01,11:24:17 1s -zp 26.4161 -dzp 0.0192 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/01,11:28:27 1s -zp 25.9590 -dzp 0.0195 -Nmeas 7 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/01,11:30:28 1s -zp 25.7165 -dzp 0.0193 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/01,11:32:47 1s -zp 25.2627 -dzp 0.0124 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/01,14:28:45 1s -zp 25.9363 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/01,14:30:46 1s -zp 26.4302 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/01,14:35:13 1s -zp 25.7086 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/01,14:37:06 1s -zp 24.7903 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/21,09:56:35 1s -zp 25.3331 -dzp 0.0357 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/21,09:59:36 1s -zp 25.9575 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/21,10:02:21 1s -zp 25.7279 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/21,10:05:13 1s -zp 24.7669 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/21,10:07:58 1s -zp 26.4956 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/22,06:16:24 1s -zp 25.4472 -dzp 0.0382 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/22,06:18:25 1s -zp 26.0393 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/22,06:20:35 1s -zp 25.7676 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/22,06:22:36 1s -zp 24.8321 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/22,06:24:46 1s -zp 26.5343 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/22,09:11:13 1s -zp 24.7917 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/22,09:13:32 1s -zp 25.3878 -dzp 0.0050 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/22,09:15:50 1s -zp 26.0112 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/22,09:17:42 1s -zp 25.7562 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/23,07:03:04 1s -zp 24.7013 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/23,07:05:13 1s -zp 26.0000 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/23,07:07:23 1s -zp 25.7556 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/23,07:09:15 1s -zp 26.5158 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/23,14:50:55 1s -zp 26.0223 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/23,14:52:56 1s -zp 25.7570 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/23,14:57:24 1s -zp 26.5457 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/23,14:59:42 1s -zp 24.7762 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/25,05:44:00 1s -zp 24.7611 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/25,05:50:21 1s -zp 26.4298 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/25,05:52:39 1s -zp 25.3050 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/25,12:34:50 1s -zp 26.0245 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/25,12:36:51 1s -zp 26.5242 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/25,12:39:10 1s -zp 25.4175 -dzp 0.0310 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/25,12:41:36 1s -zp 25.7803 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/25,12:43:46 1s -zp 24.7967 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/27,15:09:21 1s -zp 26.5096 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/27,15:18:00 1s -zp 24.7928 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/28,07:13:09 1s -zp 26.5061 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/28,07:18:20 1s -zp 25.7614 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/28,07:21:12 1s -zp 24.8333 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/28,10:14:35 1s -zp 25.3980 -dzp 0.0296 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/28,10:18:54 1s -zp 26.5111 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/28,10:20:55 1s -zp 25.7747 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/28,10:22:56 1s -zp 24.8075 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/28,15:15:24 1s -zp 24.8363 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/29,08:14:38 1s -zp 25.3912 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/29,08:15:38 1s -zp 25.3885 -dzp 0.0373 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/29,08:17:57 1s -zp 25.9944 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/29,08:20:06 1s -zp 24.7902 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/29,08:22:24 1s -zp 26.5010 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/29,08:24:25 1s -zp 25.7721 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/30,07:04:13 1s -zp 24.8370 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/30,07:06:23 1s -zp 26.0434 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/30,07:08:32 1s -zp 25.7745 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/30,07:10:33 1s -zp 26.5390 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/30,07:13:00 1s -zp 25.4598 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/30,09:50:24 1s -zp 25.7790 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/30,09:52:24 1s -zp 25.9954 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/30,09:54:25 1s -zp 24.8141 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/30,09:56:44 1s -zp 26.5113 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/30,09:59:02 1s -zp 25.3895 -dzp 0.0318 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/30,14:25:00 1s -zp 26.5669 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/30,14:27:10 1s -zp 26.0383 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/30,14:29:02 1s -zp 25.7823 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/30,14:33:38 1s -zp 24.8063 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/08/31,07:13:00 1s -zp 25.7795 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/08/31,07:15:10 1s -zp 25.4075 -dzp 0.0273 -Nmeas 5 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/08/31,07:17:28 1s -zp 24.8038 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/08/31,07:19:37 1s -zp 26.5286 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/08/31,07:21:47 1s -zp 26.0173 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/03,05:43:00 1s -zp 24.7850 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/09/03,05:45:10 1s -zp 25.9892 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/03,05:47:19 1s -zp 25.7456 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/03,05:49:29 1s -zp 26.4413 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/03,15:00:34 1s -zp 26.5288 -dzp 0.0205 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/09/03,15:02:35 1s -zp 26.0080 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/03,15:04:45 1s -zp 25.7557 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/03,15:09:21 1s -zp 24.8027 -dzp 0.0193 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/04,08:28:53 1s -zp 26.4813 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode u -trange 2003/09/04,08:31:03 1s -zp 25.3510 -dzp 0.0058 -Nmeas 4 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/04,08:33:30 1s -zp 25.7536 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/04,08:35:31 1s -zp 24.7788 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -photcode i -trange 2003/09/04,15:06:20 1s -zp 25.7414 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode g -trange 2003/09/04,15:11:05 1s -zp 26.4714 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode r -trange 2003/09/04,15:13:14 1s -zp 25.9757 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -photcode z -trange 2003/09/04,15:15:15 1s -zp 24.7638 -dzp 0.0355 -Nmeas 5 -Ntime 1 -label elixir
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/spdb.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/spdb.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/spdb.txt	(revision 16632)
@@ -0,0 +1,78 @@
+
+plan - use imregister / imsearch framework for spectra.db
+
+relevant database usages:
+
+use this for spectra.db ref ?
+  average.code or average.Xg
+
+
+spectra in spectra.db will have RA,DEC: join between tables using position
+
+example queries:
+
+spsearch 
+
+/* structure for Spectra Registration Database */
+typedef struct {
+  char filename[64];
+  char pathname[128];
+  char telescope[32];
+  char instrument[32];
+ 
+  char objname[64];
+
+  char mode (MEF?)
+  
+  float ra, dec;
+  float exptime;
+  float airmass;
+
+  /* spectral range representation */
+  float W0, W1, dW; 
+
+  /* spectral range start, end; average value for nm / pixel */
+
+  float sky;
+  float bias;
+  float fwhm;
+
+  float telfocus;
+  float xprobe, yprobe, zprobe;
+  float dettemp;
+  float teltemp[4];
+  float rotangle;
+
+  unsigned long int obstime;
+  unsigned long int regtime;
+} RegImage;  /* 360 bytes / image */
+
+
+outstanding questions:
+
+- convert spectral file to standard format on db insertion?
+  - uniform keywords for wavelength calibration?
+  - need header WCS
+  - single FITS file
+  - how to store discontiguous spectra? (MEF?)
+
+
+-------------------------------------------
+
+spectra examples in hand:
+
+Keck I / HiRes : 
+     - single IRAF FITS spectra
+     - BANDIDn gives def of slice (spectrum, sigma, background, raw)
+     - WATn_001 gives units (Angstroms)     
+     - wavelength = (x-CRPIX1+1) * CD1_1 + CRVAL1
+     * how do we know the orientation?
+
+Keck I / ESI : 
+     - MEF spectra (yso/keck)
+       - spload-mef converts to a single 
+
+-----
+
+database interactions vs autocode FITS tables
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/spdb2.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/spdb2.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/spdb2.txt	(revision 16632)
@@ -0,0 +1,58 @@
+
+metadata to extract:
+
+typedef struct {
+  char filename[64];
+  char pathname[128];
+  char instrument[32];
+  char telescope[32];
+  char objname[64];
+  char extname[64];
+
+  float ra, dec;
+  float exptime;
+  float airmass;
+
+  float W0, W1, dW;
+  int Nspec;				/* number of spectra associated with entry */
+
+  char mode;			/* PHU, MEF, EXT */
+  char state;			/* image state: raw, flx, etc */
+  char flag;			/* image status flags */
+  char junk[9];
+
+  unsigned long int obstime;
+  unsigned long int regtime;
+} Spectrum;
+
+
+FITS Keywords for metadata
+
+case 1:
+NAXIS  = 1
+NAXIS1 = Nw
+
+case 2:
+NAXIS  = 2
+NAXIS1 = Nw
+NAXIS2 = 1
+
+case 3:
+NAXIS  = 2
+NAXIS1 = 1
+NAXIS2 = Nw
+
+case 4:
+NAXIS  = 2
+NAXIS1 = Nw
+NAXIS2 = n   (flux, dflux, etc)
+
+case 5:
+NAXIS  = 3
+NAXIS1 = Nw
+NAXIS2 = 1
+NAXIS3 = n   (flux, dflux, etc)
+
+0         1         2         3         4         5         6         7         8
+012345678901234567890123456789012345678901234567890123456789012345678901234567890
+/data/elixir2/datdir/megacam/03Am02/taurus/L1551/VLT/spectra/2002.04.01
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/transdb.dat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/transdb.dat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/transdb.dat	(revision 16632)
@@ -0,0 +1,159 @@
+u 2003/02/24,00:00:00  25.2980 25.2800  0.0157    7   3   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/02/23,00:00:00  26.4640 26.4600  0.0026    3   3   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/02/24,00:00:00  26.4400 26.4600  0.0049    6   3   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/02/23,00:00:00  25.9700 25.9780  0.0037    3   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/02/24,00:00:00  25.9850 25.9780  0.0094    5   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/02/23,00:00:00  25.7420 25.7430  0.0033    3   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/02/24,00:00:00  25.7490 25.7430  0.0073    6   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/02/23,00:00:00  24.7900 24.8000  0.0070    2   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/02/24,00:00:00  24.7290 24.8000  0.0197    4   3   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/03/22,00:00:00  25.4630 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/03/23,00:00:00  25.3060 25.2800  0.0000    1   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/03/24,00:00:00  26.4570 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/03/30,00:00:00  26.4500 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/03/24,00:00:00  25.9920 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/03/25,00:00:00  26.0230 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/03/25,00:00:00  25.7630 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/03/24,00:00:00  24.8270 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/03/30,00:00:00  24.7150 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/04/25,00:00:00  26.4030 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/04/25,00:00:00  25.9290 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/26,00:00:00  25.9730 25.9780  0.0195   11   5   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/04/27,00:00:00  25.9080 25.9780  0.0816    5   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/04/25,00:00:00  25.7030 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/04/25,00:00:00  24.7530 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/05/30,00:00:00  25.2890 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/09,00:00:00  25.2310 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+r 2003/06/08,00:00:00  25.9300 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/02,00:00:00  25.7290 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/04,00:00:00  25.7570 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/05,00:00:00  25.5920 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/06,00:00:00  25.7440 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/08,00:00:00  25.6810 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/02,00:00:00  24.8460 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/09,00:00:00  24.7580 24.8000  0.0000    1   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/06/24,00:00:00  25.2760 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/27,00:00:00  25.2580 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/29,00:00:00  25.2760 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/06/30,00:00:00  25.1930 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/01,00:00:00  25.2670 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/05,00:00:00  25.2740 25.2800  0.0000    3   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/06/22,00:00:00  26.4250 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/23,00:00:00  26.4170 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/24,00:00:00  26.4130 26.4600  0.0113    5   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/26,00:00:00  26.4180 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/27,00:00:00  26.4280 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/28,00:00:00  26.4480 26.4600  0.0000    6   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/29,00:00:00  26.4230 26.4600  0.0123    8   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/06/30,00:00:00  26.3190 26.4600  0.0000    1   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/01,00:00:00  26.4190 26.4600  0.0019    6   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/04,00:00:00  26.4020 26.4600  0.0000    4   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/05,00:00:00  26.4110 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/06/22,00:00:00  25.9690 25.9780  0.0201    4   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/23,00:00:00  25.9650 25.9780  0.0000    6   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/24,00:00:00  25.9500 25.9780  0.0145    6   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/26,00:00:00  25.9610 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/27,00:00:00  25.9540 25.9780  0.0169    6   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/28,00:00:00  25.9660 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/29,00:00:00  25.9350 25.9780  0.0178    8   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/06/30,00:00:00  25.9220 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/01,00:00:00  25.9480 25.9780  0.0189    6   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/04,00:00:00  25.9540 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/05,00:00:00  25.9440 25.9780  0.0116    7   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/07,00:00:00  25.8040 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/06/22,00:00:00  25.7240 25.7430  0.0071    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/24,00:00:00  25.7160 25.7430  0.0096    6   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/26,00:00:00  25.7120 25.7430  0.0000    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/27,00:00:00  25.7180 25.7430  0.0075    6   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/28,00:00:00  25.7050 25.7430  0.0000    6   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/29,00:00:00  25.6950 25.7430  0.0067    8   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/06/30,00:00:00  25.6660 25.7430  0.0000    2   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/01,00:00:00  25.7180 25.7430  0.0000    3   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/04,00:00:00  25.7090 25.7430  0.0000    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/05,00:00:00  25.7080 25.7430  0.0000    4   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/06/23,00:00:00  24.8050 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/24,00:00:00  24.7930 24.8000  0.0284    8   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/27,00:00:00  24.7910 24.8000  0.0280    8   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/28,00:00:00  24.7710 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/29,00:00:00  24.7460 24.8000  0.0231    8   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/06/30,00:00:00  24.7410 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/01,00:00:00  24.8010 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/04,00:00:00  24.7980 24.8000  0.0000    6   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/05,00:00:00  24.7620 24.8000  0.0000    4   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+g 2003/05/25,00:00:00  26.4270 26.4600  0.0189    5   4   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/05/26,00:00:00  26.4060 26.4600  0.0021    2   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/05/25,00:00:00  25.9720 25.9780  0.0093    4   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/26,00:00:00  25.9510 25.9780  0.0040    3   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/05/27,00:00:00  25.9800 25.9780  0.0178    7   6   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/05/25,00:00:00  25.7150 25.7430  0.0170    3   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/26,00:00:00  25.7270 25.7430  0.0006    3   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/05/27,00:00:00  25.7260 25.7430  0.0242    6   6   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/05/25,00:00:00  24.7560 24.8000  0.0183    9   8   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/05/26,00:00:00  24.7150 24.8000  0.0262    3   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/07/22,00:00:00  25.2880 25.2800  0.0135   10   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/07/31,00:00:00  25.2280 25.2800  0.0000    7   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/01,00:00:00  25.2630 25.2800  0.0000    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/07/22,00:00:00  26.4220 26.4600  0.0079   11   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/30,00:00:00  26.3810 26.4600  0.0431   78  47   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/07/31,00:00:00  26.3850 26.4600  0.0086   59  11   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/01,00:00:00  26.4230 26.4600  0.0070    9   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/07/22,00:00:00  25.9580 25.9780  0.0105    8   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/30,00:00:00  25.9360 25.9780  0.0000    4   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/07/31,00:00:00  25.9390 25.9780  0.0000    5   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/01,00:00:00  25.9480 25.9780  0.0113    9   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/07/22,00:00:00  25.7240 25.7430  0.0044    6   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/07/31,00:00:00  25.6900 25.7430  0.0000    5   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/01,00:00:00  25.7130 25.7430  0.0039    8   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/07/21,00:00:00  24.8630 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/22,00:00:00  24.7820 24.8000  0.0010   14   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/07/31,00:00:00  24.7420 24.8000  0.0000    7   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/01,00:00:00  24.7900 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+u 2003/08/21,00:00:00  25.3330 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/22,00:00:00  25.4170 25.2800  0.0297    8   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/25,00:00:00  25.3610 25.2800  0.0563    6   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/28,00:00:00  25.3980 25.2800  0.0000    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/29,00:00:00  25.3900 25.2800  0.0013    7   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/30,00:00:00  25.4250 25.2800  0.0351    6   2   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/08/31,00:00:00  25.4070 25.2800  0.0000    5   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+u 2003/09/04,00:00:00  25.3510 25.2800  0.0000    4   1   0.2410 -0.3500  unknown  u_SDSS g_SDSS elixir
+g 2003/08/21,00:00:00  26.4960 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/22,00:00:00  26.5340 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/23,00:00:00  26.5310 26.4600  0.0150    2   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/25,00:00:00  26.4770 26.4600  0.0472    3   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/27,00:00:00  26.5100 26.4600  0.0000    3   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/28,00:00:00  26.5090 26.4600  0.0025    4   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/29,00:00:00  26.5010 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/30,00:00:00  26.5390 26.4600  0.0227    5   3   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/08/31,00:00:00  26.5290 26.4600  0.0000    2   1   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/03,00:00:00  26.4850 26.4600  0.0437    5   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+g 2003/09/04,00:00:00  26.4760 26.4600  0.0049    4   2   0.1480 -0.1500  unknown  g_SDSS r_SDSS elixir
+r 2003/08/21,00:00:00  25.9570 25.9780  0.0000    2   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/22,00:00:00  26.0250 25.9780  0.0141    2   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/23,00:00:00  26.0110 25.9780  0.0112    2   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/25,00:00:00  26.0240 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/29,00:00:00  25.9940 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/30,00:00:00  26.0260 25.9780  0.0215    3   3   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/08/31,00:00:00  26.0170 25.9780  0.0000    1   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/03,00:00:00  25.9990 25.9780  0.0094    2   2   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+r 2003/09/04,00:00:00  25.9760 25.9780  0.0000    3   1   0.0000 -0.1000  unknown  g_SDSS r_SDSS elixir
+i 2003/08/21,00:00:00  25.7280 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/22,00:00:00  25.7620 25.7430  0.0057    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/23,00:00:00  25.7560 25.7430  0.0007    2   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/25,00:00:00  25.7800 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/28,00:00:00  25.7680 25.7430  0.0067    2   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/29,00:00:00  25.7720 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/30,00:00:00  25.7790 25.7430  0.0032    4   3   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/08/31,00:00:00  25.7790 25.7430  0.0000    1   1   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/03,00:00:00  25.7510 25.7430  0.0050    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+i 2003/09/04,00:00:00  25.7470 25.7430  0.0061    4   2   0.0830 -0.0400  unknown  r_SDSS i_SDSS elixir
+z 2003/08/21,00:00:00  24.7670 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/22,00:00:00  24.8120 24.8000  0.0202    3   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/23,00:00:00  24.7390 24.8000  0.0374    2   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/25,00:00:00  24.7790 24.8000  0.0178    4   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/27,00:00:00  24.7930 24.8000  0.0000    3   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/28,00:00:00  24.8260 24.8000  0.0129    5   3   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/29,00:00:00  24.7900 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/30,00:00:00  24.8190 24.8000  0.0130    4   3   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/08/31,00:00:00  24.8040 24.8000  0.0000    2   1   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/03,00:00:00  24.7940 24.8000  0.0089    5   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
+z 2003/09/04,00:00:00  24.7710 24.8000  0.0075    7   2   0.0500 -0.0300  unknown  g_SDSS z_SDSS elixir
Index: /branches/eam_branch_20080223/Ohana/src/imregister/doc/transdb.src
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/doc/transdb.src	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/doc/transdb.src	(revision 16632)
@@ -0,0 +1,159 @@
+photreg -trans -photcode z -trange 2003/02/23,00:00:00 1s -zp 24.7900 -dzp 0.0070 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/02/23,00:00:00 1s -zp 25.7420 -dzp 0.0033 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/02/23,00:00:00 1s -zp 25.9700 -dzp 0.0037 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/02/23,00:00:00 1s -zp 26.4640 -dzp 0.0026 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode z -trange 2003/02/24,00:00:00 1s -zp 24.7290 -dzp 0.0197 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/02/24,00:00:00 1s -zp 25.2980 -dzp 0.0157 -Nmeas 7 -Ntime 3 -label elixir
+photreg -trans -photcode i -trange 2003/02/24,00:00:00 1s -zp 25.7490 -dzp 0.0073 -Nmeas 6 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/02/24,00:00:00 1s -zp 25.9850 -dzp 0.0094 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/02/24,00:00:00 1s -zp 26.4400 -dzp 0.0049 -Nmeas 6 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/03/22,00:00:00 1s -zp 25.4630 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/03/23,00:00:00 1s -zp 25.3060 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/03/24,00:00:00 1s -zp 24.8270 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/03/24,00:00:00 1s -zp 25.9920 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/03/24,00:00:00 1s -zp 26.4570 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/03/25,00:00:00 1s -zp 25.7630 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/03/25,00:00:00 1s -zp 26.0230 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/03/30,00:00:00 1s -zp 24.7150 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/03/30,00:00:00 1s -zp 26.4500 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/04/25,00:00:00 1s -zp 24.7530 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/04/25,00:00:00 1s -zp 25.7030 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/04/25,00:00:00 1s -zp 25.9290 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/04/25,00:00:00 1s -zp 26.4030 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/04/26,00:00:00 1s -zp 25.9730 -dzp 0.0195 -Nmeas 11 -Ntime 5 -label elixir
+photreg -trans -photcode r -trange 2003/04/27,00:00:00 1s -zp 25.9080 -dzp 0.0816 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode z -trange 2003/05/25,00:00:00 1s -zp 24.7560 -dzp 0.0183 -Nmeas 9 -Ntime 8 -label elixir
+photreg -trans -photcode i -trange 2003/05/25,00:00:00 1s -zp 25.7150 -dzp 0.0170 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/05/25,00:00:00 1s -zp 25.9720 -dzp 0.0093 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/05/25,00:00:00 1s -zp 26.4270 -dzp 0.0189 -Nmeas 5 -Ntime 4 -label elixir
+photreg -trans -photcode z -trange 2003/05/26,00:00:00 1s -zp 24.7150 -dzp 0.0262 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/05/26,00:00:00 1s -zp 25.7270 -dzp 0.0006 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/05/26,00:00:00 1s -zp 25.9510 -dzp 0.0040 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/05/26,00:00:00 1s -zp 26.4060 -dzp 0.0021 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/05/27,00:00:00 1s -zp 25.7260 -dzp 0.0242 -Nmeas 6 -Ntime 6 -label elixir
+photreg -trans -photcode r -trange 2003/05/27,00:00:00 1s -zp 25.9800 -dzp 0.0178 -Nmeas 7 -Ntime 6 -label elixir
+photreg -trans -photcode u -trange 2003/05/30,00:00:00 1s -zp 25.2890 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/02,00:00:00 1s -zp 24.8460 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/02,00:00:00 1s -zp 25.7290 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/04,00:00:00 1s -zp 25.7570 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/05,00:00:00 1s -zp 25.5920 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/06,00:00:00 1s -zp 25.7440 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/08,00:00:00 1s -zp 25.6810 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/08,00:00:00 1s -zp 25.9300 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/09,00:00:00 1s -zp 24.7580 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/06/09,00:00:00 1s -zp 25.2310 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/22,00:00:00 1s -zp 25.7240 -dzp 0.0071 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/22,00:00:00 1s -zp 25.9690 -dzp 0.0201 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/22,00:00:00 1s -zp 26.4250 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/23,00:00:00 1s -zp 24.8050 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/23,00:00:00 1s -zp 25.9650 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/23,00:00:00 1s -zp 26.4170 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/24,00:00:00 1s -zp 24.7930 -dzp 0.0284 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/06/24,00:00:00 1s -zp 25.2760 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/24,00:00:00 1s -zp 25.7160 -dzp 0.0096 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/24,00:00:00 1s -zp 25.9500 -dzp 0.0145 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/24,00:00:00 1s -zp 26.4130 -dzp 0.0113 -Nmeas 5 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/06/26,00:00:00 1s -zp 25.7120 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/26,00:00:00 1s -zp 25.9610 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/26,00:00:00 1s -zp 26.4180 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/27,00:00:00 1s -zp 24.7910 -dzp 0.0280 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/06/27,00:00:00 1s -zp 25.2580 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/27,00:00:00 1s -zp 25.7180 -dzp 0.0075 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/27,00:00:00 1s -zp 25.9540 -dzp 0.0169 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/27,00:00:00 1s -zp 26.4280 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/28,00:00:00 1s -zp 24.7710 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/28,00:00:00 1s -zp 25.7050 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/28,00:00:00 1s -zp 25.9660 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/28,00:00:00 1s -zp 26.4480 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/06/29,00:00:00 1s -zp 24.7460 -dzp 0.0231 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/06/29,00:00:00 1s -zp 25.2760 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/29,00:00:00 1s -zp 25.6950 -dzp 0.0067 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/06/29,00:00:00 1s -zp 25.9350 -dzp 0.0178 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/06/29,00:00:00 1s -zp 26.4230 -dzp 0.0123 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/06/30,00:00:00 1s -zp 24.7410 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/06/30,00:00:00 1s -zp 25.1930 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/06/30,00:00:00 1s -zp 25.6660 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/06/30,00:00:00 1s -zp 25.9220 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/06/30,00:00:00 1s -zp 26.3190 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/01,00:00:00 1s -zp 24.8010 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/07/01,00:00:00 1s -zp 25.2670 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/01,00:00:00 1s -zp 25.7180 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/01,00:00:00 1s -zp 25.9480 -dzp 0.0189 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/07/01,00:00:00 1s -zp 26.4190 -dzp 0.0019 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/07/04,00:00:00 1s -zp 24.7980 -dzp 0.0000 -Nmeas 6 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/04,00:00:00 1s -zp 25.7090 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/04,00:00:00 1s -zp 25.9540 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/07/04,00:00:00 1s -zp 26.4020 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/05,00:00:00 1s -zp 24.7620 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/07/05,00:00:00 1s -zp 25.2740 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/05,00:00:00 1s -zp 25.7080 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/05,00:00:00 1s -zp 25.9440 -dzp 0.0116 -Nmeas 7 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/07/05,00:00:00 1s -zp 26.4110 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/07,00:00:00 1s -zp 25.8040 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/21,00:00:00 1s -zp 24.8630 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/07/22,00:00:00 1s -zp 24.7820 -dzp 0.0010 -Nmeas 14 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/07/22,00:00:00 1s -zp 25.2880 -dzp 0.0135 -Nmeas 10 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/07/22,00:00:00 1s -zp 25.7240 -dzp 0.0044 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/07/22,00:00:00 1s -zp 25.9580 -dzp 0.0105 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/07/22,00:00:00 1s -zp 26.4220 -dzp 0.0079 -Nmeas 11 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/07/30,00:00:00 1s -zp 25.9360 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/07/30,00:00:00 1s -zp 26.3810 -dzp 0.0431 -Nmeas 78 -Ntime 47 -label elixir
+photreg -trans -photcode z -trange 2003/07/31,00:00:00 1s -zp 24.7420 -dzp 0.0000 -Nmeas 7 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/07/31,00:00:00 1s -zp 25.2280 -dzp 0.0000 -Nmeas 7 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/07/31,00:00:00 1s -zp 25.6900 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/07/31,00:00:00 1s -zp 25.9390 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/07/31,00:00:00 1s -zp 26.3850 -dzp 0.0086 -Nmeas 59 -Ntime 11 -label elixir
+photreg -trans -photcode z -trange 2003/08/01,00:00:00 1s -zp 24.7900 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/01,00:00:00 1s -zp 25.2630 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/01,00:00:00 1s -zp 25.7130 -dzp 0.0039 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/08/01,00:00:00 1s -zp 25.9480 -dzp 0.0113 -Nmeas 9 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/01,00:00:00 1s -zp 26.4230 -dzp 0.0070 -Nmeas 9 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/21,00:00:00 1s -zp 24.7670 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/21,00:00:00 1s -zp 25.3330 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/21,00:00:00 1s -zp 25.7280 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/21,00:00:00 1s -zp 25.9570 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/21,00:00:00 1s -zp 26.4960 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/22,00:00:00 1s -zp 24.8120 -dzp 0.0202 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/08/22,00:00:00 1s -zp 25.4170 -dzp 0.0297 -Nmeas 8 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/22,00:00:00 1s -zp 25.7620 -dzp 0.0057 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/08/22,00:00:00 1s -zp 26.0250 -dzp 0.0141 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/22,00:00:00 1s -zp 26.5340 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/23,00:00:00 1s -zp 24.7390 -dzp 0.0374 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/23,00:00:00 1s -zp 25.7560 -dzp 0.0007 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/08/23,00:00:00 1s -zp 26.0110 -dzp 0.0112 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/23,00:00:00 1s -zp 26.5310 -dzp 0.0150 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/25,00:00:00 1s -zp 24.7790 -dzp 0.0178 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/08/25,00:00:00 1s -zp 25.3610 -dzp 0.0563 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/25,00:00:00 1s -zp 25.7800 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/25,00:00:00 1s -zp 26.0240 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/25,00:00:00 1s -zp 26.4770 -dzp 0.0472 -Nmeas 3 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/27,00:00:00 1s -zp 24.7930 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/27,00:00:00 1s -zp 26.5100 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/28,00:00:00 1s -zp 24.8260 -dzp 0.0129 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/08/28,00:00:00 1s -zp 25.3980 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/28,00:00:00 1s -zp 25.7680 -dzp 0.0067 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/08/28,00:00:00 1s -zp 26.5090 -dzp 0.0025 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/08/29,00:00:00 1s -zp 24.7900 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/29,00:00:00 1s -zp 25.3900 -dzp 0.0013 -Nmeas 7 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/29,00:00:00 1s -zp 25.7720 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/29,00:00:00 1s -zp 25.9940 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/29,00:00:00 1s -zp 26.5010 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/08/30,00:00:00 1s -zp 24.8190 -dzp 0.0130 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode u -trange 2003/08/30,00:00:00 1s -zp 25.4250 -dzp 0.0351 -Nmeas 6 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/08/30,00:00:00 1s -zp 25.7790 -dzp 0.0032 -Nmeas 4 -Ntime 3 -label elixir
+photreg -trans -photcode r -trange 2003/08/30,00:00:00 1s -zp 26.0260 -dzp 0.0215 -Nmeas 3 -Ntime 3 -label elixir
+photreg -trans -photcode g -trange 2003/08/30,00:00:00 1s -zp 26.5390 -dzp 0.0227 -Nmeas 5 -Ntime 3 -label elixir
+photreg -trans -photcode z -trange 2003/08/31,00:00:00 1s -zp 24.8040 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode u -trange 2003/08/31,00:00:00 1s -zp 25.4070 -dzp 0.0000 -Nmeas 5 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/08/31,00:00:00 1s -zp 25.7790 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode r -trange 2003/08/31,00:00:00 1s -zp 26.0170 -dzp 0.0000 -Nmeas 1 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/08/31,00:00:00 1s -zp 26.5290 -dzp 0.0000 -Nmeas 2 -Ntime 1 -label elixir
+photreg -trans -photcode z -trange 2003/09/03,00:00:00 1s -zp 24.7940 -dzp 0.0089 -Nmeas 5 -Ntime 2 -label elixir
+photreg -trans -photcode i -trange 2003/09/03,00:00:00 1s -zp 25.7510 -dzp 0.0050 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/09/03,00:00:00 1s -zp 25.9990 -dzp 0.0094 -Nmeas 2 -Ntime 2 -label elixir
+photreg -trans -photcode g -trange 2003/09/03,00:00:00 1s -zp 26.4850 -dzp 0.0437 -Nmeas 5 -Ntime 2 -label elixir
+photreg -trans -photcode z -trange 2003/09/04,00:00:00 1s -zp 24.7710 -dzp 0.0075 -Nmeas 7 -Ntime 2 -label elixir
+photreg -trans -photcode u -trange 2003/09/04,00:00:00 1s -zp 25.3510 -dzp 0.0000 -Nmeas 4 -Ntime 1 -label elixir
+photreg -trans -photcode i -trange 2003/09/04,00:00:00 1s -zp 25.7470 -dzp 0.0061 -Nmeas 4 -Ntime 2 -label elixir
+photreg -trans -photcode r -trange 2003/09/04,00:00:00 1s -zp 25.9760 -dzp 0.0000 -Nmeas 3 -Ntime 1 -label elixir
+photreg -trans -photcode g -trange 2003/09/04,00:00:00 1s -zp 26.4760 -dzp 0.0049 -Nmeas 4 -Ntime 2 -label elixir
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/ConfigInit.c	(revision 16632)
@@ -0,0 +1,118 @@
+# include "imregister.h"
+# include "imphot.h"
+
+int success;
+
+void ConfigInitImphot (int *argc, char **argv) {
+
+  int i, NDB;
+  char *config, *file, ElixirBase[80], catdir[256];
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+
+  success = TRUE;
+
+  WarnConfig (config, "CATDIR",                      "%s", 0, catdir);
+  WarnConfig (config, "PHOTCODE_FILE",         	     "%s", 0, MasterPhotcodeFile);
+  sprintf (ImPhotDB, "%s/Images.dat", catdir);
+
+  /* small text databases: filters, camera defs */ 
+  WarnConfig (config, "TEMPERATURE_LOG",             "%s", 0, TempLogFile);
+  WarnConfig (config, "FILTER_LIST",                 "%s", 0, FilterList);
+  WarnConfig (config, "CAMERA_CONFIG",               "%s", 0, CameraConfig);
+  WarnConfig (config, "DETREND_RECIPES",             "%s", 0, RecipeFile);
+						   
+  /* pixel scale for FWHM */ 
+  WarnConfig (config, "ASEC_PIX",                    "%lf", 0, &ARCSEC_PIXEL);
+
+  /* keyword abstractions for parse_time */	   
+  WarnConfig (config, "DATE-KEYWORD",                "%s", 0, DateKeyword);
+  WarnConfig (config, "DATE-MODE",                   "%s", 0, DateMode);
+  WarnConfig (config, "UT-KEYWORD",                  "%s", 0, UTKeyword);
+  WarnConfig (config, "MJD-KEYWORD",                 "%s", 0, MJDKeyword);
+  WarnConfig (config, "JD-KEYWORD",                  "%s", 0, JDKeyword);
+						   
+  /* keyword abstractions for iminfo */		   
+  WarnConfig (config, "EXPTIME-KEYWORD",             "%s", 0, ExptimeKeyword);
+  WarnConfig (config, "IMAGETYPE-KEYWORD",           "%s", 0, ImagetypeKeyword);
+  WarnConfig (config, "CCDNUM-KEYWORD",              "%s", 0, CCDnumKeyword);
+  WarnConfig (config, "FILTER-KEYWORD",              "%s", 0, FilterKeyword);
+  WarnConfig (config, "AIRMASS-KEYWORD",             "%s", 0, AirmassKeyword);
+  WarnConfig (config, "FOCUS-KEYWORD",               "%s", 0, FocusKeyword);
+  WarnConfig (config, "ROTATION-KEYWORD",            "%s", 0, RotationKeyword);
+  WarnConfig (config, "DETTEMP-KEYWORD",             "%s", 0, DettempKeyword);
+  WarnConfig (config, "TELDATA1-KEYWORD",            "%s", 0, Teldata1Keyword);
+  WarnConfig (config, "TELDATA2-KEYWORD",            "%s", 0, Teldata2Keyword);
+  WarnConfig (config, "TELDATA3-KEYWORD",            "%s", 0, Teldata3Keyword);
+  WarnConfig (config, "CAMERA-KEYWORD",              "%s", 0, CameraKeyword);
+
+  ScanConfig (config, "CAMERA",                      "%s", 0, Camera);
+  ScanConfig (config, "SEEING_REF_CCD",              "%s", 0, SeeingREFCCD);
+
+  /* optional values */
+  ScanConfig (config, "RA-DDD-KEYWORD",              "%s", 0, RADecDegKeyword);
+  ScanConfig (config, "DEC-DDD-KEYWORD",             "%s", 0, DECDecDegKeyword);
+  ScanConfig (config, "RA-HMS-KEYWORD",              "%s", 0, RASexigKeyword);
+  ScanConfig (config, "DEC-DMS-KEYWORD",             "%s", 0, DECSexigKeyword);
+
+  if (!RADecDegKeyword[0] & !DECDecDegKeyword[0] && !RASexigKeyword[0] && !DECSexigKeyword[0]) {
+    fprintf (stderr, "missing astrometry configuration information\n");
+    success = FALSE;
+  }
+						   
+  WarnConfig (config, "imstats",                     "%s", 0, ElixirBase);
+  sprintf (ImstatFifo, "%s.photcode", ElixirBase);   
+  WarnConfig (config, "ptolemy",                     "%s", 0, ElixirBase);
+  sprintf (PtolemyFifo, "%s.photcode", ElixirBase);
+
+  if (!ScanConfig (config, "CONNECT", "%s",  0, CONNECT)) {
+    sprintf (CONNECT, "/usr/bin/rsh");
+  }
+
+  /* load Detrend Alt Databases paths */
+  NDB = 10;
+  NDetrendAltDB = 0;
+  ALLOCATE (DetrendAltDB, char *, NDB);
+  ALLOCATE (DetrendAltDB[NDetrendAltDB], char, 256);
+  for (i = 1; ScanConfig (config, "DETREND_ALT_DB", "%s", i, DetrendAltDB[NDetrendAltDB]); i++) {
+    NDetrendAltDB ++;
+    if (NDetrendAltDB == NDB) {
+      NDB += 10;
+      REALLOCATE (DetrendAltDB, char *, NDB);
+    }
+    ALLOCATE (DetrendAltDB[NDetrendAltDB], char, 256);
+  }
+  free (DetrendAltDB[NDetrendAltDB]);
+
+  if (! success) {
+    fprintf (stderr, "ERROR: problem with elixir configuration\n");
+    exit (1);
+  }
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
+
+void WarnConfig (char *config, char *key, char * mode, int N, void *var) {
+  if (!ScanConfig (config, key, mode, N, var)) {
+    fprintf (stderr, "missing config variable %s\n", key);
+    success = FALSE;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/args.c	(revision 16632)
@@ -0,0 +1,92 @@
+# include "imregister.h" 
+# include "imphot.h"
+
+/* criteria struct is global */
+int args (int argc, char **argv) {
+
+  int N;
+
+  ConfigInit (&argc, argv); /* load elixir config data */
+
+  /* interpret command-line arguments */
+  if (!get_trange_arguments (&argc, argv, &criteria.tstart, &criteria.tstop, &criteria.Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  /* select by image photcode */
+  criteria.PhotcodeSelect = FALSE;
+  criteria.photcode = 0;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    if (!(criteria.photcode = GetPhotcodeCodebyName (argv[N]))) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    criteria.PhotcodeSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.NameSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.NameSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.CodeSelect = FALSE;
+  criteria.Code = 0;
+  if ((N = get_argument (argc, argv, "-code"))) {
+    criteria.CodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    criteria.Code = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  options.table = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-fits"))) {
+    remove_argument (N, &argc, argv);
+    options.table = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  options.bintable = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-binfits"))) {
+    remove_argument (N, &argc, argv);
+    options.bintable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* desired action */
+  options.modify = FALSE;
+  options.ModifyValue = options.ModifyEntry = NULL;
+  if ((N = get_argument (argc, argv, "-flag"))) {
+    remove_argument (N, &argc, argv);
+    options.ModifyEntry = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    options.ModifyValue = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    options.modify = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  FORCE_READ = FALSE;
+  if ((N = get_argument (argc, argv, "-force"))) {
+    remove_argument (N, &argc, argv);
+    FORCE_READ = TRUE;
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: imphotsearch [config ops] [-trange start stop/delta] [-photcode code] [-fits out.fits]\n");
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/db_load.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/db_load.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/db_load.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "imregister.h"
+# include "imphot.h"
+
+enum {FITS, TEXT};
+
+int db_load (FITS_DB *db) {
+
+  int Nx, Ny, Naxis;
+  int mode, status;
+
+  /* database name must be set first */
+  if (db == NULL) {
+    fprintf (stderr, "db handle is not set\n");
+    return (FALSE);
+  }
+
+  /* init & load in FITS table data - return FALSE on error */
+  if (!gfits_fread_header (db[0].f, &db[0].header)) {
+    fprintf (stderr, "can't read primary header\n"); 
+    return (FALSE);
+  }
+
+  gfits_scan (&db[0].header, "NAXIS",  "%d", 1, &Naxis);
+  gfits_scan (&db[0].header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (&db[0].header, "NAXIS2", "%d", 1, &Ny);
+  
+  mode = FITS;
+  if ((Naxis == 2) && (Nx == 1106) && (Ny == 1024)) {
+    mode = TEXT;
+  }
+  
+  /* how do we decide if it is text or fits? must examine header */
+  if (FITS) {
+    status = rfits (db);
+  } else {
+    status = rtext (db);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/dumpfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/dumpfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/dumpfits.c	(revision 16632)
@@ -0,0 +1,141 @@
+# include "imregister.h"
+# include "imphot.h"
+
+/* write out complete binary FITS table in format of db */
+int DumpFitsBintable (char *filename, Image *image, int *match, int Nmatch) {
+
+  int i, j;
+  FILE *f;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  Image *subset;
+
+  ALLOCATE (subset, Image, MAX (1, Nmatch));
+  for (i = 0; i < Nmatch; i++){
+    j = match[i];
+    memcpy (&subset[i], &image[j], sizeof (Image));
+  }
+
+  /* open file for output */
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", filename);
+    exit (1);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_Image (&ftable, subset, Nmatch);
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+  fclose (f);
+  exit (0);
+}
+
+int DumpFitsTable (char *filename, Image *image, int *match, int Nmatch) {
+  
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  Image *subset;
+  FILE *f;
+  char *startstr, *filtstr, *datestr, *line;
+  int i;
+  double zp, dzp, ra, dec, airmass, sky;
+  time_t tsecond;
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* the ASCII table is always a little harder than the binary:
+   * we need to build the data line a bit carefully 
+   */
+
+  /* create table header */
+  gfits_create_table_header (&theader, "TABLE", "ZPTS");
+
+  /* add current date/time to header */
+  ohana_str_to_time ("now", &tsecond);
+  datestr = ohana_sec_to_date (tsecond);
+  gfits_modify (&header,  "DATE", "%s", 1, datestr);
+  gfits_modify (&theader, "DATE", "%s", 1, datestr);
+  
+  /* define table layout */
+  gfits_define_table_column (&theader, "A20",   "START_TIME", "start time of measurement", "yyyy/mm/dd,hh:mm:ss");
+  gfits_define_table_column (&theader, "A10",   "FILTER",     "filter and camera name",    "");
+  gfits_define_table_column (&theader, "F8.4",  "ZP_OBS",     "measured zero point",       "mag");
+  gfits_define_table_column (&theader, "F7.4",  "ZP_ERR",     "error on zero point",       "mag");
+  gfits_define_table_column (&theader, "F11.6", "RA",         "RA (J2000)",                "dec. degrees");
+  gfits_define_table_column (&theader, "F11.6", "DEC",        "DEC (J2000)",               "dec. degrees");
+  gfits_define_table_column (&theader, "F7.3",  "C_AIRMASS",  "airmass coeff",             "mag per airmass"); 
+  gfits_define_table_column (&theader, "F7.1",  "SKY",        "median sky flux",           "counts");
+  gfits_define_table_column (&theader, "I6",    "NSTAR",      "Number of stars in image",  "stars");
+
+  /* define TNULL, TNVAL values */
+  gfits_modify (&theader, "TNULL1",  "%s", 1, "NULL"); /* START_TIME */
+  gfits_modify (&theader, "TNULL2",  "%s", 1, "NULL"); /* FILTER     */
+  gfits_modify (&theader, "TNULL3",  "%s", 1, "NaN");  /* ZP_OBS     */
+  gfits_modify (&theader, "TNULL4",  "%s", 1, "NaN");  /* ZP_ERR     */
+  gfits_modify (&theader, "TNULL5",  "%s", 1, "NaN");  /* RA         */
+  gfits_modify (&theader, "TNULL6",  "%s", 1, "NaN");  /* DEC        */
+  gfits_modify (&theader, "TNULL7",  "%s", 1, "NaN");  /* C_AIRMASS  */
+  gfits_modify (&theader, "TNULL8",  "%s", 1, "NaN");  /* SKY        */
+  gfits_modify (&theader, "TNULL9",  "%s", 1,  "-1");  /* NSTAR      */
+
+  gfits_modify (&theader, "TNVAL1",  "%s", 1, "NA");   /* START_TIME */
+  gfits_modify (&theader, "TNVAL2",  "%s", 1, "NA");   /* FILTER     */
+  gfits_modify (&theader, "TNVAL3",  "%s", 1, "Inf");  /* ZP_OBS     */
+  gfits_modify (&theader, "TNVAL4",  "%s", 1, "Inf");  /* ZP_ERR     */
+  gfits_modify (&theader, "TNVAL5",  "%s", 1, "Inf");  /* RA         */
+  gfits_modify (&theader, "TNVAL6",  "%s", 1, "Inf");  /* DEC        */
+  gfits_modify (&theader, "TNVAL7",  "%s", 1, "Inf");  /* C_AIRMASS  */
+  gfits_modify (&theader, "TNVAL8",  "%s", 1, "Inf");  /* SKY        */
+  gfits_modify (&theader, "TNVAL9",  "%s", 1,  "-2");  /* NSTAR      */
+
+  /* add data to table */
+  for (i = 0; i < Nmatch; i++) {
+    subset   = &image[match[i]];
+    startstr = ohana_sec_to_date (subset[0].tzero);
+    filtstr  = GetPhotcodeNamebyCode (subset[0].photcode);
+    zp       = subset[0].Mcal;
+    dzp      = subset[0].dMcal;
+    XY_to_RD (&ra, &dec, 0.0, 0.0, &subset[0].coords);
+    airmass  = subset[0].secz;
+    sky      = subset[0].Myyyy + 0x8000;
+
+    /* we should get an error here if we don't construct this line correctly */
+    line = gfits_table_print (&ftable, startstr, filtstr, zp, dzp, ra, dec, airmass, sky, subset[0].nstar);
+    gfits_add_rows (&ftable, line, 1, strlen(line));
+    free (line);
+    free (startstr);
+  }
+
+  /* write data to output file */
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Failure writing fits table\n");
+    exit (1);
+  }
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+  fclose (f);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/modify.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/modify.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/modify.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "imregister.h"
+# include "imphot.h"
+
+void ModifySubset (FITS_DB *db, Image *image, int Nimage, int *match, int Nmatch) {
+
+  int i, j;
+
+  /* modify the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+
+    i = match[j];
+
+    if (options.modify) {
+      if (!strcasecmp (options.ModifyEntry, "and")) {
+	image[i].code &= atoi (options.ModifyValue);
+      }
+      if (!strcasecmp (options.ModifyEntry, "or")) {
+	image[i].code |= atoi (options.ModifyValue);
+      }
+      if (!strcasecmp (options.ModifyEntry, "xor")) {
+	image[i].code ^= atoi (options.ModifyValue);
+      }
+      if (!strcasecmp (options.ModifyEntry, "=")) {
+	image[i].code = atoi (options.ModifyValue);
+      }
+    }
+  }
+
+  /** we may later want to pull this out and put it elsewhere **/
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, match, Nmatch);
+  for (i = 0; i < Nmatch; i++) {
+    gfits_convert_Image ((Image *) db[0].vtable.buffer[i], sizeof (Image), 1);
+  }
+  gfits_db_update (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/output.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "imregister.h"
+# include "imphot.h"
+
+int output (Image *image, int *match, int Nmatch) {
+
+  int status;
+
+  /* output the selected entries */
+  if (options.table != (char *) NULL) {
+    status = DumpFitsTable (options.table, image, match, Nmatch);
+    return (TRUE);
+  } 
+
+  /* output the selected entries */
+  if (options.bintable != (char *) NULL) {
+    status = DumpFitsBintable (options.bintable, image, match, Nmatch);
+    return (TRUE);
+  } 
+
+  PrintSubset (image, match, Nmatch);
+  return (TRUE);
+}
+
+int PrintSubset (Image *image, int *match, int Nmatch) {
+
+  int i, j;
+  char *timestr, *photstr;
+  static char PhotError[] = "unknown";
+
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j];
+      
+    /* convert UNIX time to Elixir-style date string */
+    timestr = ohana_sec_to_date (image[i].tzero);
+      
+    /* convert photcode to filter name */
+    photstr = GetPhotcodeNamebyCode (image[i].photcode);
+    if (photstr == (char *) NULL) photstr = PhotError;
+      
+    fprintf (stdout, "%s %s %s  %7.4f %7.4f  %7.4f %5d %02x\n", image[i].name, photstr, timestr, 
+	     image[i].Mcal, image[i].dMcal, image[i].secz, image[i].nstar, image[i].code); 
+    free (timestr);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/rfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/rfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/rfits.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "imregister.h"
+
+/* load the rest of the db table into memory (first extension only) */
+int rfits (FITS_DB *db) {
+
+  /* database name must be set first */
+  if (db == NULL) {
+    fprintf (stderr, "db handle is not set\n");
+    return (FALSE);
+  }
+  if (!gfits_fread_matrix (db[0].f, &db[0].matrix, &db[0].header)) {
+    fprintf (stderr, "can't read primary matrix");
+    return (FALSE);
+  }
+  if (!gfits_fread_header (db[0].f, &db[0].theader)) {
+    fprintf (stderr, "can't read table header");
+    return (FALSE);
+  }
+  if (!gfits_fread_ftable_data (db[0].f, &db[0].ftable)) {
+    fprintf (stderr, "can't read table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/rtext.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/rtext.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/rtext.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "imregister.h"
+# include "imphot.h"
+
+int rtext (FITS_DB *db) {
+
+  int Nimage, size, nimage;
+  struct stat filestatus;
+  Image *image;
+
+  /* check that file size makes sense */
+  Nimage = 0;
+  gfits_scan (&db[0].header, "NIMAGES", "%d", 1, &Nimage);
+  if (stat (db[0].filename, &filestatus) == -1) {
+    if (VERBOSE) fprintf (stderr, "ERROR: failed to get status of image catalog\n");
+    exit (1);
+  }
+  size = Nimage*sizeof(Image) + db[0].header.size;
+  if (size != filestatus.st_size) {
+    int Ndata;
+
+    Ndata = (filestatus.st_size - db[0].header.size) / sizeof (Image);
+    if (VERBOSE) fprintf (stderr, "ERROR: image catalog has inconsistent size\n");
+    if (VERBOSE) fprintf (stderr, "header: %d, data: %d\n", Nimage, Ndata);
+    if (!FORCE_READ) exit (1);
+    Nimage = Ndata;
+  } 
+
+  /* create a dummy set of table information */
+  /* (original table has NAXIS = 2, change to 0) */
+  gfits_modify (&db[0].header, "NAXIS", "%d", 1, 0);
+  gfits_create_matrix (&db[0].header, &db[0].matrix);
+  gfits_table_mkheader_Image (&db[0].theader);
+  db[0].ftable.header = &db[0].theader;
+
+  /* alloc, read images */
+  ALLOCATE (image, Image, MAX (Nimage, 1));
+  nimage = fread (image, sizeof(Image), Nimage, db[0].f);
+  if (nimage != Nimage) {
+    if (VERBOSE) fprintf (stderr, "ERROR: problem loading image catalog\n");
+    exit (1);
+  } 
+  db[0].ftable.buffer = (char *) image;
+  gfits_modify (&db[0].theader, "NAXIS2", "%d", 1, Nimage);
+  db[0].theader.Naxis[1] = Nimage;
+  db[0].ftable.size = gfits_data_size (&db[0].theader);
+  
+  return (TRUE);
+}
+
+/* the old Image.dat files used a fake FITS header defining a finite data block
+   this function reads in the 
+*/
+
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imphot/subset.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imphot/subset.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imphot/subset.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "imregister.h"
+# include "imphot.h"
+
+int *subset (Image *image, int Nimage, int *nsubset) {
+
+  int i, j, status;
+  int Nsubset, NameSelectLength;
+  int *index;
+
+  NameSelectLength = 0;
+
+  /* allocate space for reference lists */
+  Nsubset = 0;
+  ALLOCATE (index, int, Nimage);
+  
+  if (criteria.NameSelect) {
+    NameSelectLength = strlen(criteria.Name);
+  }
+
+  for (i = 0; i < Nimage; i++) {
+    for (j = 0, status = FALSE; !status && (j < criteria.Ntimes); j++) {
+      status = (image[i].tzero >= criteria.tstart[j]) && (image[i].tzero <= criteria.tstop[j]);
+    }
+    if (!status && criteria.Ntimes) continue;
+    if (criteria.PhotcodeSelect && (image[i].photcode != criteria.photcode)) continue;
+    if (criteria.CodeSelect     && (image[i].code != criteria.Code)) continue;
+    if (criteria.NameSelect     && strncasecmp (image[i].name, criteria.Name, NameSelectLength)) continue;
+
+    index[Nsubset] = i;
+    Nsubset ++;
+  }
+  *nsubset = Nsubset;
+  return (index);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/ConfigPID.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/ConfigPID.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/ConfigPID.c	(revision 16632)
@@ -0,0 +1,86 @@
+# include "imregister.h"
+# include "imreg.h"
+
+static char *PIDMaster = (char *) NULL;
+
+int ConfigPID (char *pidfile) {
+
+  pid_t pid;
+  char *username, machine[256];
+  FILE *f;
+
+  ALLOCATE (username, char, 256);
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    /* no PID file, make new one */
+
+    pid = getpid ();
+
+    free (username);
+    username = getenv ("USER");
+    if (username == (char *) NULL) {
+      fprintf (stderr, "error getting username\n");
+      exit (2);
+    }
+    bzero (machine, 256);
+    if (gethostname (machine, 256)) {
+      fprintf (stderr, "error getting hostname\n");
+      exit (2);
+    }
+
+    f = fopen (pidfile, "w");
+    if (f == (FILE *) NULL) { 
+      fprintf (stderr, "can't write to PID file %s\n", pidfile);
+      exit (2);
+    }
+
+    fprintf (f, "PID:     %d\n", pid);
+    fprintf (f, "USER:    %-s\n", username);
+    fprintf (f, "MACHINE: %-s\n", machine);
+    fclose (f);
+
+    PIDMaster = pidfile;
+    return (TRUE); 
+  }
+
+  /* PID file exists, warn & exit */
+  fprintf (stderr, "elixir is apparently running:\n\n");
+  fprintf (stderr, "  machine: %s\n", machine);
+  fprintf (stderr, "  user: %s\n", username);
+  fprintf (stderr, "  PID: %d\n", pid);
+  fprintf (stderr, "  remove %s if elixir has died unexpectedly\n", pidfile);
+  Shutdown (1);
+  return (FALSE); 
+}
+
+void RemovePID () {
+  
+  if (PIDMaster == (char *) NULL) 
+    return;
+  
+  if (unlink (PIDMaster)) {
+    fprintf (stderr, "error deleting PID File %s\n", PIDMaster);
+  }   
+}
+
+int LoadPID (char *file, pid_t *pid, char *username, char *machine) {
+
+  FILE *f;
+
+  f = fopen (file, "r");
+  if (f == (FILE *) NULL) { 
+    return (FALSE);
+  }
+
+  fscanf (f, "%*s %d", pid);
+  fscanf (f, "%*s %s", username);
+  fscanf (f, "%*s %s", machine);
+  fclose (f);
+
+  return (TRUE);
+}
+
+int Shutdown (int status) {
+
+  RemovePID ();
+  exit (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/FifoOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/FifoOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/FifoOps.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "imregister.h"
+# include "imreg.h"
+
+int InitFifo (Fifo *fifo, int Nalloc, int Nextra) {
+
+  if (Nextra >= Nalloc) {
+    fprintf (stderr, "absurd fifo definition\n");
+    return (FALSE);
+  }
+
+  fifo[0].Nalloc = Nalloc;
+  fifo[0].Nextra = Nextra;
+  fifo[0].Nmaxread = Nalloc - Nextra;
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  ALLOCATE (fifo[0].buffer, char, fifo[0].Nalloc);
+
+  return (TRUE);
+
+}
+
+int FlushFifo (Fifo *fifo) {
+
+  fifo[0].Nlast = 0;
+  fifo[0].Nbuffer = 0;
+
+  return (TRUE);
+
+}
+
+/* after a shift, we can always read 
+   fifo[0].Nmaxread 
+   bytes into 
+   &fifo[0].buffer[Nbuffer] 
+   which is the byte after then end of existing data */
+
+int ShiftFifo (Fifo *fifo) {
+
+  int Nextra, Nshift;
+
+  Nextra = fifo[0].Nextra;
+  Nshift = fifo[0].Nbuffer - fifo[0].Nextra;
+  if (Nshift <= 0) return (TRUE);
+
+  memcpy (fifo[0].buffer, &fifo[0].buffer[Nshift], Nextra);
+  fifo[0].Nbuffer = Nextra;
+  fifo[0].Nlast = Nextra;
+
+  return (TRUE);
+}
+
+/* like a standard read, ReadtoFifo returns Nbytes read,
+   -1 for sock busy, or 0 for sock closed */
+
+int ReadtoFifo (Fifo *fifo, int sock) {
+
+  int Nread;
+  int Nbuffer, Nmaxread;
+
+  if (sock == 0) {
+    fprintf (stderr, "error with socket?\n");
+    return (0);
+  }
+
+  fifo[0].Nlast = fifo[0].Nbuffer;
+
+  Nbuffer = fifo[0].Nbuffer;
+  Nmaxread = fifo[0].Nmaxread;
+  Nread = read (sock, &fifo[0].buffer[Nbuffer], Nmaxread);
+
+  if (Nread > 0) fifo[0].Nbuffer += Nread;
+
+  if (Nread == -1) {
+    /* check for possible errors.  anything other than EAGAIN
+       is bad and should indicate the connection is down */
+    switch (errno) {
+    case EAGAIN:
+    case EIO:
+      Nread = -1;
+      break;
+    default:
+      fprintf (stderr, "read error: %d\n", errno);
+      Nread = 0;
+      break;
+    }
+  }
+
+  return (Nread);
+}
+
+void FreeFifo (Fifo *fifo) {
+
+  if (fifo[0].buffer != (char *) NULL) {
+    free (fifo[0].buffer);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/SetSignals.c	(revision 16632)
@@ -0,0 +1,178 @@
+# include "imregister.h"
+# include "imreg.h"
+
+void SIG_DIE (int sig) {
+  fprintf (stderr, "trapped signal %d, exiting\n", sig);
+  Shutdown (1);
+}
+
+void SIG_PIPE (int sig) {
+  fprintf (stderr, "pipe signal: %d\n", sig);
+}
+
+void SetSignals () {
+
+  /* use default settings */
+  signal (SIGKILL,   SIG_DFL);    
+  signal (SIGCONT,   SIG_DFL);    
+  signal (SIGSTOP,   SIG_DFL);    
+  signal (SIGCHLD,   SIG_DFL);
+
+  /* exit on these signals */
+  signal (SIGILL,    SIG_DIE);     
+  signal (SIGABRT,   SIG_DIE);    
+  signal (SIGFPE,    SIG_DIE);     
+  signal (SIGSEGV,   SIG_DIE);    
+  signal (SIGTERM,   SIG_DIE);    
+  signal (SIGBUS,    SIG_DIE);     
+  signal (SIGTRAP,   SIG_DIE);    
+  signal (SIGXCPU,   SIG_DIE);    
+  signal (SIGXFSZ,   SIG_DIE);    
+  signal (SIGIOT,    SIG_DIE);     
+  signal (SIGINT,    SIG_DIE);
+
+  signal (SIGPIPE,   SIG_PIPE);    
+
+  /* ignore these signals */
+  signal (SIGHUP,    SIG_IGN);
+  signal (SIGQUIT,   SIG_IGN);
+  signal (SIGALRM,   SIG_IGN);    
+  signal (SIGUSR1,   SIG_IGN);    
+  signal (SIGUSR2,   SIG_IGN);    
+  signal (SIGTSTP,   SIG_IGN);    
+  signal (SIGTTIN,   SIG_IGN);    
+  signal (SIGTTOU,   SIG_IGN);    
+  signal (SIGPROF,   SIG_IGN);    
+  signal (SIGURG,    SIG_IGN);     
+  signal (SIGVTALRM, SIG_IGN);  
+  signal (SIGIO,     SIG_IGN);      
+
+  /* signals which are not always defined */
+# ifdef SIGPOLL
+  signal (SIGPOLL,   SIG_IGN);    
+# endif
+# ifdef SIGPWR
+  signal (SIGPWR, SIG_DIE);     /* power failure (Sys V) */
+# endif
+# ifdef SIGWINCH
+  signal (SIGWINCH, SIG_IGN);   /* window resized (4.3BSD) */
+# endif
+# ifdef SIGUNUSED
+  signal (SIGUNUSED, SIG_DFL);  
+# endif
+# ifdef SIGSYS
+  signal (SIGSYS,    SIG_DIE);     
+# endif
+# ifdef SIGEMT
+ signal (SIGEMT,    SIG_DIE); 
+# endif
+# ifdef SIGSTKFLT
+  signal (SIGSTKFLT, SIG_DIE);  
+# endif
+# ifdef SIGINFO
+ signal (SIGINFO,   SIG_DIE); 
+# endif
+# ifdef SIGCLD
+  signal (SIGCLD,    SIG_DFL);     
+# endif
+# ifdef SIGLOST
+  signal (SIGLOST,   SIG_IGN); 
+# endif
+# ifdef SIGUNUSED
+  signal (SIGUNUSED,   SIG_IGN); 
+# endif
+
+}
+
+void KillProcess (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+  char line[512];
+  int i, wsock, rsock;
+  struct stat filestat;
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "imstatreg is not running\n");
+    exit (0);
+  }
+
+  /* send signal to remote machine */
+  if (!rconnect (machine, CONNECT, &rsock, &wsock)) {
+    fprintf (stderr, "can't make connection to machine %s to kill process %d\n", machine, pid);
+    exit (1);
+  }
+  sprintf (line, "kill -TERM %d\n", pid);
+  write (wsock, line, strlen (line));
+
+  for (i = 0; i < 300; i++) {
+    if (stat (pidfile, &filestat) == -1) exit (0);
+    usleep (100000);
+  }
+  fprintf (stderr, "imstatreg is still running\n");
+  exit (2);
+}
+
+void StatusProcess (char *pidfile) {
+  
+  pid_t pid;
+  char username[256], machine[256];
+
+  if (!LoadPID (pidfile, &pid, username, machine)) {
+    fprintf (stderr, "imstatreg is not running\n");
+    exit (2);
+  }
+
+  /* PID file exists, warn & exit */
+  fprintf (stderr, "imstatreg is apparently running:\n\n");
+  fprintf (stderr, "  machine: %s\n", machine);
+  fprintf (stderr, "  user: %s\n", username);
+  fprintf (stderr, "  PID: %d\n", pid);
+  fprintf (stderr, "  remove %s if imstatreg has died unexpectedly\n", pidfile);
+
+  exit (0);
+}
+
+/*
+
+  SIGHUP             1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+  SIGINT             2        A      Interrupt from keyboard
+  SIGQUIT            3        C      Quit from keyboard
+  SIGILL             4        C      Illegal Instruction
+  SIGABRT            6        C      Abort signal from abort(3)
+  SIGFPE             8        C      Floating point exception
+  SIGKILL            9       AEF     Kill signal
+  SIGSEGV           11        C      Invalid memory reference
+  SIGPIPE           13        A      Broken pipe: write to pipe with no readers
+  SIGALRM           14        A      Timer signal from alarm(2)
+  SIGTERM           15        A      Termination signal
+  SIGUSR1        30,10,16     A      User-defined signal 1
+  SIGUSR2        31,12,17     A      User-defined signal 2
+  SIGCHLD        20,17,18     B      Child stopped or terminated
+  SIGCONT        19,18,25            Continue if stopped
+  SIGSTOP        17,19,23    DEF     Stop process
+  SIGTSTP        18,20,24     D      Stop typed at tty
+  SIGTTIN        21,21,26     D      tty input for background process
+  SIGTTOU        22,22,27     D      tty output for background process
+  SIGBUS         10,7,10      C      Bus error (bad memory access)
+  SIGPOLL                     A      Pollable event (Sys V). Synonym of SIGIO
+  SIGPROF        27,27,29     A      Profiling timer expired
+  SIGSYS         12,-,12      C      Bad argument to routine (SVID)
+  SIGTRAP           5         C      Trace/breakpoint trap
+  SIGURG         16,23,21     B      Urgent condition on socket (4.2 BSD)
+  SIGVTALRM      26,26,28     A      Virtual alarm clock (4.2 BSD)
+  SIGXCPU        24,24,30     C      CPU time limit exceeded (4.2 BSD)
+  SIGXFSZ        25,25,31     C      File size limit exceeded (4.2 BSD)
+  SIGIOT            6         C      IOT trap. A synonym for SIGABRT
+  SIGEMT          7,-,7
+  SIGSTKFLT       -,16,-      A      Stack fault on coprocessor
+  SIGIO          23,29,22     A      I/O now possible (4.2 BSD)
+  SIGCLD          -,-,18             A synonym for SIGCHLD
+  SIGPWR         29,30,19     A      Power failure (System V)
+  SIGINFO         29,-,-             A synonym for SIGPWR
+  SIGLOST         -,-,-       A      File lock lost
+  SIGWINCH       28,28,20     B      Window resize signal (4.3 BSD, Sun)
+  SIGUNUSED       -,31,-      A      Unused signal (will be SIGSYS)
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/SockScan.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/SockScan.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/SockScan.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "imregister.h"
+# include "imreg.h"
+# include <errno.h>
+# define MAXTIME 10
+
+int SockScan (char *string, Fifo *fifo, int sock) {
+  
+  int i, done, status;
+
+  done = 0;
+  for (i = 0; (i < MAXTIME) && !done; i++) {
+    ShiftFifo (fifo);
+    status = ReadtoFifo (fifo, sock);
+    switch (status) {
+    case 0:
+      break;
+    case -1:
+      usleep (1000);
+      break;
+    default:
+      done = memstr (fifo[0].buffer, string, fifo[0].Nbuffer);
+      break;
+    }
+  }
+  return (status);
+}
+
+/* returns (offset to m2) + 1, or 0 if failure */ 
+int memstr (char *m1, char *m2, int n) {
+
+  int i, N;
+
+  N = strlen (m2);
+  for (i = 0; (i < n - N + 1) && memcmp (m1, m2, N); i++, m1++);
+  if (memcmp (m1, m2, N)) {
+    return (0);
+  }
+  else {
+    return (i+1);
+  }
+
+}
+ 
+/* SockScan reads from the given socket looking for the given string
+   SockScan stores data read from socket in the fifo buffer to ensure 
+   it catches the given string.  a single invocation of SockScan will 
+   wait for up to 10 msec for data to come down the pipe before giving up.
+   SockScan can only search for one string in the output stream.
+   */
+
+
+/* need a way of signalling that the socket has closed...
+   maybe change the sock entry to 0?
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/args.imregister.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/args.imregister.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/args.imregister.c	(revision 16632)
@@ -0,0 +1,109 @@
+# include "imregister.h"
+# include "imreg.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  ConfigInit (&argc, argv); /* load elixir config data */
+  ConfigCamera ();          /* load camera information */
+  ConfigFilter ();          /* load filter information */
+
+  SingleIsSplit = FALSE;
+  if ((N = get_argument (argc, argv, "-split"))) {
+    remove_argument (N, &argc, argv);
+    SingleIsSplit = TRUE;
+  }
+
+  NoReg = FALSE;
+  if ((N = get_argument (argc, argv, "-noreg"))) {
+    remove_argument (N, &argc, argv);
+    NoReg = TRUE;
+  }
+
+  output.verbose = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    output.verbose = TRUE;
+  }
+
+  NeedType = FALSE;
+  if ((N = get_argument (argc, argv, "-needtype"))) {
+    remove_argument (N, &argc, argv);
+    NeedType = TRUE;
+  }
+
+  /* all imregister programs are implicitly modifying the db */
+  output.modify = TRUE;
+  IMSORT = FALSE;
+
+  if (strstr (argv[0], "imregister") != (char *) NULL) {
+    if (argc != 2) {
+      fprintf (stderr, "ERROR: Usage: imregister (filename) [-split] [-noreg]\n");
+      exit (1);
+    }
+    return (TRUE);
+  }
+  if (strstr (argv[0], "showiminfo") != (char *) NULL) {
+    if (argc != 2) {
+      fprintf (stderr, "ERROR: Usage: showiminfo (filename) [-split] [-noreg]\n");
+      exit (1);
+    }
+    return (TRUE);
+  }
+  if (strstr (argv[0], "imsort") != (char *) NULL) {
+    if (argc != 2) {
+      fprintf (stderr, "ERROR: Usage: imsort filename(s) [-split] [-noreg]\n");
+      exit (1);
+    }
+    IMSORT = TRUE;
+    return (TRUE);
+  }
+  if (strstr (argv[0], "imstatreg") != (char *) NULL) {
+
+    char *path, *file;
+
+    CLIENT = TRUE;
+
+    /* set up name to lockfile */
+    path = pathname (ImageDB);
+    file = filebasename (ImageDB);
+    ALLOCATE (PIDFILE, char, strlen (path) + strlen (file) + 10);
+    sprintf (PIDFILE, "%s/.%s.pid", path, file);
+
+    /* create db.log and db.bfr */
+    sprintf (TempDB, "%s.bfr", ImageDB);
+    sprintf (LogFile, "%s.log", ImageDB);
+    
+    /* check for daemon mode */
+    if ((N = get_argument (argc, argv, "-daemon"))) {
+      remove_argument (N, &argc, argv);
+      CLIENT = FALSE;
+
+      /* special daemon options */
+      if (get_argument (argc, argv, "-kill"))   KillProcess (PIDFILE);
+      if (get_argument (argc, argv, "-status")) StatusProcess (PIDFILE);
+
+      LOOP_DELAY = 60;
+      if ((N = get_argument (argc, argv, "-delay"))) {
+	remove_argument (N, &argc, argv);
+	LOOP_DELAY = atof(argv[N]);
+	remove_argument (N, &argc, argv);
+      }	
+
+      if (argc != 1) {
+	fprintf (stderr, "ERROR: Usage: imstatreg -daemon [-delay N] [-status] [-kill]\n");
+	exit (1);
+      }
+      return (TRUE);
+    }
+
+    if (argc != 4) {
+      fprintf (stderr, "ERROR: Usage: imstatreg (fits) (stats) (sdat) [-split] [-noreg]\n");
+      fprintf (stderr, "       or:    imstatreg -daemon\n");
+      exit (1);
+    }
+    return (TRUE);
+  }
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/args.imsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/args.imsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/args.imsearch.c	(revision 16632)
@@ -0,0 +1,294 @@
+# include "imregister.h" 
+# include "imreg.h"
+
+/* criteria struct is global */
+int args (int argc, char **argv) {
+
+  double dt;
+  int N, i;
+
+  ConfigInit (&argc, argv); /* load elixir config data */
+  ConfigCamera ();          /* load camera information */
+  ConfigFilter ();          /* load filter information */
+
+  /* set timezone (set static in misc.c) */
+  if ((N = get_argument (argc, argv, "-tz"))) {
+    remove_argument (N, &argc, argv);
+    dt = atof (argv[N]);
+    set_timezone (dt);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* define time range */
+  criteria.Ntimes = 0;
+  if (!get_trange_arguments (&argc, argv, &criteria.tstart, &criteria.tstop, &criteria.Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  /* image type (dark, flat, bias, etc) */
+  criteria.TypeSelect = FALSE;
+  criteria.Type = T_UNDEF;
+  if ((N = get_argument (argc, argv, "-type"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Type = get_image_type (argv[N]);
+    if (criteria.Type == T_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image type %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    criteria.TypeSelect = TRUE;
+  }
+ 
+  /* image mode (split, mef, single) */
+  criteria.ModeSelect = FALSE;
+  criteria.Mode = M_UNDEF;
+  if ((N = get_argument (argc, argv, "-mode"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Mode = get_image_mode (argv[N]);
+    if (criteria.Mode == M_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image mode %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    criteria.ModeSelect = TRUE;
+  }
+
+  /* exposure time */
+  criteria.ExptimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-etime"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Exptime = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.ExptimeSelect = TRUE;
+  }
+ 
+  /* ccd number */
+  criteria.CCDSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-ccd"))) {
+    remove_argument (N, &argc, argv);
+    criteria.CCD = -1;
+    for (i = 0; (i < Nccd) && (criteria.CCD == -1); i++) {
+      if (strnumcmp (ccds[i], argv[N])) {
+	criteria.CCD = i;
+      }
+    }
+    if (criteria.CCD == -1) {
+      fprintf (stderr, "ERROR: ccd %s choice not found in camera config\n", argv[N]);
+      exit (1);
+    }
+
+    remove_argument (N, &argc, argv);
+    criteria.CCDSelect = TRUE;
+  }
+  /* select CCD seq number */
+  if ((N = get_argument (argc, argv, "-ccdn"))) {
+    remove_argument (N, &argc, argv);
+    criteria.CCD = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.CCDSelect = TRUE;
+  }
+ 
+  /* filter name */
+  criteria.FilterSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-filter"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Filter = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.FilterSelect = TRUE;
+    if (!strcasecmp (criteria.Filter, "X")) {
+      criteria.FilterSelect = FALSE;
+    }
+  }
+
+  /* string in image name */
+  criteria.NameSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.NameSelect = TRUE;
+  }
+
+  /* processed state */
+  criteria.ProcSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-proc"))) {
+    criteria.ProcSelect = TRUE;
+    remove_argument (N, &argc, argv);
+
+    criteria.Proc = -1;
+    if (!strcasecmp (argv[N], "t")) criteria.Proc = TRUE;
+    if (!strcasecmp (argv[N], "f")) criteria.Proc = FALSE;
+    remove_argument (N, &argc, argv);
+    if (criteria.Proc == -1) {
+      fprintf (stderr, "ERROR: -proc (t/f)\n");
+      exit (1);
+    }
+  }
+
+  criteria.DistSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-dist"))) {
+    criteria.DistSelect = TRUE;
+    remove_argument (N, &argc, argv);
+
+    criteria.Dist = -1;
+    if (!strcasecmp (argv[N], "t")) criteria.Dist = TRUE;
+    if (!strcasecmp (argv[N], "f")) criteria.Dist = FALSE;
+    remove_argument (N, &argc, argv);
+    if (criteria.Dist == -1) {
+      fprintf (stderr, "ERROR: -dist (t/f)\n");
+      exit (1);
+    }
+  }
+
+  /*** command-line options which modify the output list */
+  if ((N = get_argument (argc, argv, "-treg"))) {
+    remove_argument (N, &argc, argv);
+    SetOutputMode ("RegTimeMode");
+  }
+  if ((N = get_argument (argc, argv, "-seq"))) {
+    remove_argument (N, &argc, argv);
+    SetOutputMode ("CCDSeq");
+  }
+  if ((N = get_argument (argc, argv, "-pt"))) {
+    remove_argument (N, &argc, argv);
+    SetOutputMode ("PTstyle");
+  }
+  output.table = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-table"))) {
+    remove_argument (N, &argc, argv);
+    output.table = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  output.cadctable = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-cadctable"))) {
+    remove_argument (N, &argc, argv);
+    output.cadctable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  output.bintable = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-bintable"))) {
+    remove_argument (N, &argc, argv);
+    output.bintable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /*** command-line options which modify behavior (delete, modify, newpath, mef2split split2mef */
+  output.delete = FALSE;
+  output.modify = FALSE;
+  output.modify_path = FALSE; 
+  output.modify_dist = FALSE;
+  output.mef2split = FALSE; 
+  output.split2mef = FALSE;
+  output.unique = FALSE;
+
+  if ((N = get_argument (argc, argv, "-delete"))) {
+    remove_argument (N, &argc, argv);
+    output.delete = TRUE;
+  }
+
+  if ((N = get_argument (argc, argv, "-unique"))) {
+    remove_argument (N, &argc, argv);
+    output.unique = TRUE;
+  }
+
+  if ((N = get_argument (argc, argv, "-modify"))) {
+    if (output.delete) { 
+      fprintf (stderr, "can't specify more than one modifier at a time\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    output.modify = TRUE;
+    
+    /* modify part of the path */
+    if (!strcasecmp (argv[N], "path")) {
+      output.modify_path = TRUE;
+      remove_argument (N, &argc, argv);
+      output.oldpath = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      output.newpath = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      goto valid_modify;
+    }
+
+    /* modify the image mode (MEF <-> SPLIT) */
+    if (!strcasecmp (argv[N], "mode")) {
+      remove_argument (N, &argc, argv);
+      if (!strcasecmp (argv[N], "mef")) {
+	output.mef2split = TRUE;
+	remove_argument (N, &argc, argv);
+	goto valid_modify;
+      }
+      if (!strcasecmp (argv[N], "split")) {
+	output.split2mef = TRUE;
+	remove_argument (N, &argc, argv);
+	goto valid_modify;
+      }
+    }
+
+    /* modify distributed status */
+    if (!strcasecmp (argv[N], "dist")) {
+      output.modify_dist = TRUE;
+      remove_argument (N, &argc, argv);
+      if (!strcasecmp (argv[N], "t")) {
+	output.dist = TRUE;
+	remove_argument (N, &argc, argv);
+	goto valid_modify;
+      }
+      if (!strcasecmp (argv[N], "f")) {
+	output.dist = FALSE;
+	remove_argument (N, &argc, argv);
+	goto valid_modify;
+      }
+    }
+
+    /* modify the type */
+    if (!strcasecmp (argv[N], "type")) {
+      output.modify_type = TRUE;
+      remove_argument (N, &argc, argv);
+      output.type = get_image_type (argv[N]);
+      if (output.type == T_UNDEF) {
+	fprintf (stderr, "ERROR: invalid image type %s\n", argv[N]);
+	exit (1);
+      }
+      remove_argument (N, &argc, argv);
+      goto valid_modify;
+    }
+
+    /* modify the filter */
+    if (!strcasecmp (argv[N], "filter")) {
+      output.modify_filter = TRUE;
+      remove_argument (N, &argc, argv);
+      output.filter = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      goto valid_modify;
+    }
+
+    if (!strcasecmp (argv[N], "help")) {
+      fprintf (stderr, "-modify option: \n");
+      fprintf (stderr, "  -modify path (oldpath) (newpath)\n"); 
+      fprintf (stderr, "  -modify mode (mef | split)\n"); 
+      fprintf (stderr, "  -modify dist (t | f)\n"); 
+      fprintf (stderr, "  -modify type (flat, etc)\n"); 
+      fprintf (stderr, "  -modify filter (name)\n\n"); 
+      fprintf (stderr, "  mode mef : convert mef to split\n");
+      fprintf (stderr, "  mode split : convert split to mef\n");
+      exit (2);
+    }
+
+    fprintf (stderr, "invalid -modify option, try -modify help\n");
+    exit (1);
+  }
+ valid_modify:
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: imsearch [config ops] \n");
+    fprintf (stderr, "  [-type type] [-mode mode] [-trange start range] [-ccd N]\n");
+    fprintf (stderr, "  [-etime exptime] [-filter name] [-name string] [-proc t/f]\n");
+    fprintf (stderr, "  [-treg] [-seq] [-pt] [-table] [-cadctable] [-bintable]\n");
+    fprintf (stderr, "  [-delete] [-modify (options)]\n");
+    exit (1);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/cadc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/cadc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/cadc.c	(revision 16632)
@@ -0,0 +1,303 @@
+# include "imregister.h"
+# include "imreg.h"
+
+static int REFCCD;
+
+void DumpCADCTable (char *filename, RegImage *image, int *match, int Nmatch) {
+  
+  int i, Obsid, Nobsid, Nsubset, ref;
+  char *datestr, *line, hdrname[99];
+  time_t tsecond;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  RegImage *row;
+  int *index, *entry, *obsid;
+  MosaicLayout *layout;
+  int *subset;
+  double left, right, center, outer, top, bottom;
+  double iqx, iqy, iqr, iqf, iqo;
+
+  /* set REFCCD for use in GetREFIQ */
+  REFCCD = MatchCCDName (SeeingREFCCD);
+  if (REFCCD == -1) { 
+    fprintf (stderr, "ERROR: can't get reference ccd\n");
+    exit (1);
+  }
+
+  /* assign relevant mosaic layout structure */
+  layout = (MosaicLayout *) NULL;
+  if (!strcasecmp (Camera, "CFH12K"))  layout = CreateCFH12K ();
+  if (!strcasecmp (Camera, "MegaCam")) layout = CreateMegaCam ();
+  if (!strcasecmp (Camera, "MegaNorth")) layout = CreateMegaCam ();
+  if (layout == (MosaicLayout *) NULL) {
+    fprintf (stderr, "ERROR: invalid camera for CADC Table\n");
+    exit (1);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* create table header */
+  gfits_create_table_header (&theader, "TABLE", "CADC_RAW_IMAGES");
+      
+  /* add current date/time to header */
+  ohana_str_to_time ("now", &tsecond);
+  datestr = ohana_sec_to_date (tsecond);
+  gfits_modify (&header,  "DATE", "%s", 1, datestr);
+  gfits_modify (&theader, "DATE", "%s", 1, datestr);
+
+  /* define table layout */
+  gfits_define_table_column (&theader, "A99",   "FILENAME",       "filename in db",                  "");
+  gfits_define_table_column (&theader, "A99",   "HDR_FILENAME",   "image header filename",           "");
+  gfits_define_table_column (&theader, "I10",   "OBSID",          "image ID number",                 "");
+  gfits_define_table_column (&theader, "F5.2",  "OBS_IQ_REFCCD",  "image quality on reference chip", "arcsec");
+  gfits_define_table_column (&theader, "F5.2",  "OBS_IQ_CENTER",  "image quality center region",     "arcsec");
+  gfits_define_table_column (&theader, "F5.2",  "OBS_IQ_R_RATIO", "IQ ratio (outer / center)",       "");
+  gfits_define_table_column (&theader, "F5.2",  "OBS_IQ_X_RATIO", "IQ ratio (left / right)",         "");
+  gfits_define_table_column (&theader, "F5.2",  "OBS_IQ_Y_RATIO", "IQ ratio (top / bottom)",         "");
+  gfits_define_table_column (&theader, "F9.3",  "OBS_BG_VAL",     "background level",                "counts / pixel");
+
+  /* define TNULL, TNVAL values */
+  gfits_modify (&theader, "TNULL1",  "%s", 1, "NULL");  /* FILENAME       */
+  gfits_modify (&theader, "TNULL2",  "%s", 1, "NULL");  /* HDR_FILENAME   */
+  gfits_modify (&theader, "TNULL3",  "%s", 1, "0");     /* OBSID          */
+  gfits_modify (&theader, "TNULL4",  "%s", 1, "0.00");  /* OBS_IQ_REFCCD  */
+  gfits_modify (&theader, "TNULL5",  "%s", 1, "0.00");  /* OBS_IQ_CENTER  */
+  gfits_modify (&theader, "TNULL6",  "%s", 1, "0.00");  /* OBS_IQ_R_RATIO */
+  gfits_modify (&theader, "TNULL7",  "%s", 1, "0.00");  /* OBS_IQ_X_RATIO */
+  gfits_modify (&theader, "TNULL8",  "%s", 1, "0.00");  /* OBS_IQ_Y_RATIO */
+  gfits_modify (&theader, "TNULL9",  "%s", 1, "0.00");  /* OBS_BG_VAL     */
+
+  gfits_modify (&theader, "TNVAL1",  "%s", 1, "NA");    /* FILENAME     */
+  gfits_modify (&theader, "TNVAL2",  "%s", 1, "NA");    /* HDR_FILENAME */
+  gfits_modify (&theader, "TNVAL3",  "%s", 1, "-1");    /* OBSID        */
+  gfits_modify (&theader, "TNVAL4",  "%s", 1, "-1.00"); /* OBS_IQ_REFCCD  */
+  gfits_modify (&theader, "TNVAL5",  "%s", 1, "-1.00"); /* OBS_IQ_CENTER  */
+  gfits_modify (&theader, "TNVAL6",  "%s", 1, "-1.00"); /* OBS_IQ_R_RATIO */
+  gfits_modify (&theader, "TNVAL7",  "%s", 1, "-1.00"); /* OBS_IQ_X_RATIO */
+  gfits_modify (&theader, "TNVAL8",  "%s", 1, "-1.00"); /* OBS_IQ_Y_RATIO */
+  gfits_modify (&theader, "TNVAL9",  "%s", 1, "-1.00"); /* OBS_BG_VAL   */
+
+  /* create table, add data values */
+  gfits_create_table (&theader, &table);
+  
+  /* prepare indicies to handle table data */
+  GetObsIDIndex (image, match, Nmatch, &index, &entry);
+  obsid = GetUniqueObsID (image, index, entry, Nmatch, &Nobsid);
+
+  for (i = 0; i < Nobsid; i++) {
+    ref = GetREFCCD (image, index, entry, Nmatch, obsid[i]);
+    row = &image[ref];
+    Obsid = index[obsid[i]];
+    sprintf (hdrname, "%s.hdr", row[0].filename);
+
+    subset = GetObsIDSubset (image, obsid[i], index, entry, Nmatch, &Nsubset);
+    center = MosaicIQStats (image, subset, Nsubset, &layout[0].center);
+    outer  = MosaicIQStats (image, subset, Nsubset, &layout[0].outer );
+    top    = MosaicIQStats (image, subset, Nsubset, &layout[0].top   );
+    bottom = MosaicIQStats (image, subset, Nsubset, &layout[0].bottom);
+    left   = MosaicIQStats (image, subset, Nsubset, &layout[0].left  );
+    right  = MosaicIQStats (image, subset, Nsubset, &layout[0].right );
+    free (subset);
+
+    iqx = (left   == 0) ? 0 : (right / left);
+    iqy = (bottom == 0) ? 0 : (top / bottom);
+    iqr = (center == 0) ? 0 : (outer / center);
+    iqf = center * ARCSEC_PIXEL;
+    iqo = row[0].fwhm*ARCSEC_PIXEL;
+    line = gfits_table_print (&table, row[0].filename, hdrname, Obsid, iqo, iqf, iqr, iqx, iqy, row[0].sky);
+
+    gfits_add_rows (&table, line, 1, strlen(line));
+    free (line);
+  }
+  free (obsid);
+  free (index);
+  free (entry);
+
+  gfits_write_header  (filename, &header);
+  gfits_write_matrix  (filename, &matrix);
+  gfits_write_Theader (filename, &theader);
+  gfits_write_table   (filename, &table);
+  exit (0);
+}
+
+int *GetObsIDSubset (RegImage *image, int start, int *index, int *entry, int Nindex, int *Nsubset) {
+
+  int i, N, NSUBSET;
+  int *subset;
+
+  /* create output index */
+  N = 0;
+  NSUBSET = 64;
+  ALLOCATE (subset, int, NSUBSET);
+
+  /* find unique sequences */
+  for (i = start; (i < Nindex) && (index[i] == index[start]); i++) {
+    subset[N] = entry[i];
+    N++;
+    if (N == NSUBSET) {
+      NSUBSET += 64;
+      REALLOCATE (subset, int, NSUBSET);
+    }
+  }
+
+  *Nsubset = N;
+  return (subset);
+}
+
+/* return an index list of unique obs id entries at start of sequence */
+int *GetUniqueObsID (RegImage *image, int *index, int *entry, int Nindex, int *Nmatch) {
+  
+  int i, j, N, NMATCH;
+  int *match;
+
+  /* create output index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  /* find unique sequences */
+  for (i = 0; i < Nindex; ) {
+    for (j = i + 1; (j < Nindex) && (index[i] == index[j]); j++);
+
+    /* add unique entry to output list */
+    match[N] = i;
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+
+    /* j always points to the next entry */
+    i = j;
+  }
+  *Nmatch = N;
+  return (match);
+}
+
+/* return seeing for ccd == REFCCD */
+int GetREFCCD (RegImage *image, int *index, int *entry, int Nindex, int start) {
+  
+  int i, N, NMATCH;
+  int *match;
+
+  /* create output index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  /* find unique sequences */
+  for (i = start; (i < Nindex) && (index[i] == index[start]); i++) {
+    if (image[entry[i]].ccd == REFCCD) return (entry[i]);
+  }
+  return (start);
+}
+
+void GetObsIDIndex (RegImage *image, int *match, int Nmatch, int **Index, int **Entry) {
+
+  int i;
+  int *index, *entry;
+
+  /* index = OBSID */
+  ALLOCATE (index, int, Nmatch);
+  ALLOCATE (entry, int, Nmatch);
+  for (i = 0; i < Nmatch; i++) {
+    index[i] = atoi (image[match[i]].filename);
+    if (index[i] < 400000) fprintf (stderr, "warning: derived obsid < 400000\n");
+    entry[i] = match[i];
+  }
+  isortpair (index, entry, Nmatch);
+  *Index = index;
+  *Entry = entry;
+}
+
+/* match is a list of image entries with the same obsid */
+double MosaicIQStats (RegImage *image, int *match, int Nmatch, MosaicRegion *region) {
+
+  int i, j, N, Nccd;
+  double *list, value;
+
+  Nccd = region[0].Nccd;
+  ALLOCATE (list, double, Nccd);
+
+  N = 0;
+  for (i = 0; i < Nccd; i++) {
+    for (j = 0; j < Nmatch; j++) {
+      if (image[match[j]].ccd == region[0].ccd[i]) {
+	list[N] = image[match[j]].fwhm;
+	N++;
+	break;
+      }
+    }
+  }
+
+  value = SigmaClipList (list, N);
+  free (list);
+  return (value);
+}
+
+double SigmaClipList (double *list, int N) {
+
+  int i, n;
+  double median, sigma3, m1, m2;
+
+  if (N == 0) return (0.0);
+  if (N == 1) return (list[0]);
+  
+  dsort (list, N);
+  median = list[(int)(0.5*N)];
+  
+  m1 = m2 = 0;
+  for (i = 0; i < N; i++) { m1 += list[i]; m2 += SQ(list[i]); }
+  sigma3 = 3*sqrt (m2/N - m1*m1/N/N);
+  
+  m1 = n = 0;
+  for (i = 0; i < N; i++) { 
+    if (abs(list[i] - median) > sigma3) continue;
+    m1 += list[i];
+    n ++;
+  }
+
+  m2 = m1 / n;
+  return (m2);
+}
+  
+
+/* the CADC table is special: we need to report specfic IQ stats 
+   which represent the variations in focus across the mosaic. 
+   this representation is explicitly dependent on the mosaic,
+   and does not make sense for other camera types 
+   CADC table option cannot be combined with CCD filtering options
+   CADC table forces -unique, needed to make calculation
+*/
+
+/* derived CADC parameters:
+   OBS_IQ_CENTER - sigma-clip mean value of center region
+   OBS_IQ_X      - ratio of left to right regions
+   OBS_IQ_Y      - ratio of top to bottom regions
+   OBS_IQ_R      - ratio of center to edge regions
+*/
+
+/* cfh12k:
+
+   00 01 02 03 04 05
+   06 07 08 09 10 11
+
+   center: 02,03,08,09
+   outer:  00,01,04,05,06,07,10,11
+   top;    00-05
+   bottom: 06-11
+   right:  00,01,02,06,07,08
+   left:   03,04,05,09,10,11
+
+   for each region, calculate median, sigma, reject >3sigma, calculate mean
+*/
+
+/* we are guaranteed a unique set of filename / ccd values */
+/* index = OBSID = atoi (filename) */
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/delete.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "imregister.h"
+# include "imreg.h"
+
+void DeleteSubset (FITS_DB *db, RegImage *image, int Nimage, int *match, int Nmatch) {
+
+  int i, j;
+  int *keep, Ndel, Nsubset;
+  RegImage *subset;
+
+  ALLOCATE (keep, int, MAX (Nimage, 1));
+  for (i = 0; i < Nimage; i++) keep[i] = TRUE;
+  fprintf (stderr, "total of %d images\n", Nimage);
+
+  Ndel = 0;
+  for (i = 0; i < Nmatch; i++) {
+    j = match[i];
+    if (j == -1) continue;
+    keep[j] = FALSE;
+    Ndel ++;
+  }
+  fprintf (stderr, "delete %d images\n", Ndel);
+  if (Ndel == 0) { 
+    fprintf (stderr, "SUCCESS\n");
+    gfits_db_close (db);
+    exit (0);
+  }
+
+  /* create new data list */
+  Nsubset = Nimage - Ndel;
+  ALLOCATE (subset, RegImage, MAX (1, Nsubset));
+  fprintf (stderr, "keeping %d images\n", Nsubset);
+  for (j = i = 0; i < Nimage; i++) {
+    if (!keep[i]) continue;
+    subset[j] = image[i];
+    j++;
+  }
+
+  free (keep);
+  free (image);
+
+  /** we may later want to pull this out and put it elsewhere **/
+  /** free db[0].theader, db[0].table.buffer? **/
+  gfits_table_set_RegImage (&db[0].ftable, subset, Nsubset);
+  gfits_db_save (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/iminfo.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/iminfo.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/iminfo.c	(revision 16632)
@@ -0,0 +1,165 @@
+# include "imregister.h"
+# include "imreg.h"
+
+char *getcwd_cfht ();
+
+RegImage *iminfo (char *filename) {
+
+  RegImage *image;
+  Header header;
+  int extend;
+  int Naxes, Nextend, Nseq;
+  char Imagetype[80], line[80];
+  struct timeval now;
+  char *name, *cwd, *tempname;
+  double tmp;
+
+  ALLOCATE (image, RegImage, 1);
+  bzero (image, sizeof (RegImage));
+
+  /* load in FITS header from image */
+  if (!gfits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", filename);
+    exit (1);
+  }
+
+  /* find the important header keyword values */
+  image[0].obstime = parse_time (&header);
+
+  gettimeofday (&now, (void *) NULL);
+  image[0].regtime = now.tv_sec;
+
+  image[0].sky = image[0].fwhm = image[0].bias = 0;
+  
+  /* default for a single CCD frame */
+  Naxes = 2; 
+  extend = FALSE;
+  image[0].mode     = M_SINGLE;
+  image[0].flag     = 0;
+  image[0].ccd      = 0;
+  image[0].seq      = 0;
+  image[0].seqtime  = 0;
+
+  /* determine data layout (SINGLE, SPLIT, MEF, CUBE, SLICE) */
+  gfits_scan (&header, "EXTEND",  "%t", 1, &extend);
+  gfits_scan (&header, "NAXIS",  "%d", 1, &Naxes);
+  if (extend) { /* MEF file */
+    gfits_scan (&header, "NEXTEND",  "%d", 1, &Nextend);
+    image[0].mode = M_MEF;
+    image[0].ccd  = Nextend;
+  } 
+  /* need to distinguish MEF, CUBE, and MEF-CUBE */
+  if (Naxes == 3) { /* data cube */
+    gfits_scan (&header, "NAXIS3",  "%d", 1, &Nseq);
+    if (image[0].mode == M_MEF) {
+      fprintf (stderr, "MEF-CUBE not ready\n");
+      exit (1);
+    }
+    image[0].mode = M_CUBE;
+    image[0].seq  = Nseq;
+    /* abstract this name somewhere ? */
+    gfits_scan (&header, "SEQTIME", "%f", 1, &image[0].seqtime);
+  }
+  if (SingleIsSplit && (image[0].mode == M_SINGLE)) {
+    image[0].mode = M_SPLIT;
+    image[0].ccd  = MatchCCDNameHeader (&header);
+  }
+  /* is there a better way to id a 'split' image? */
+
+  /* extract other relevant data from header */
+  gfits_scan (&header, ImagetypeKeyword,  "%s", 1, &Imagetype);
+
+  /* grab the image type : if not defined, set to 'none' */
+  image[0].type = get_image_type (Imagetype);
+  if (NeedType && (image[0].type == T_UNDEF)) {
+    fprintf (stderr, "ERROR: skipping unknown image type\n");
+    exit (1);
+  } else {
+    image[0].type = T_NONE;
+  }
+
+  /* grab interesting info from header */
+  gfits_scan (&header, ExptimeKeyword,    "%f", 1, &image[0].exptime);
+  gfits_scan (&header, AirmassKeyword,    "%f", 1, &image[0].airmass);
+  gfits_scan (&header, FocusKeyword,      "%f", 1, &image[0].telfocus);
+  gfits_scan (&header, Teldata1Keyword,   "%f", 1, &image[0].xprobe);
+  gfits_scan (&header, Teldata2Keyword,   "%f", 1, &image[0].yprobe);
+  gfits_scan (&header, Teldata3Keyword,   "%f", 1, &image[0].zprobe);
+  gfits_scan (&header, DettempKeyword,    "%f", 1, &image[0].dettemp);
+  gfits_scan (&header, RotationKeyword,   "%f", 1, &image[0].rotangle);
+
+  /* force strings to fit in available space (32 bytes) */
+  gfits_scan (&header, CameraKeyword,     "%s", 1, line);
+  strncpy (image[0].instrument, line, 31);
+  image[0].instrument[31] = 0;
+
+  gfits_scan (&header, FilterKeyword, "%s", 1, line);
+  MatchFilterList (line);
+  strncpy (image[0].filter, line, 31);
+  image[0].filter[31] = 0;
+
+  /* header has RA & DEC in decimal degrees */
+  if (RADecDegKeyword[0] & DECDecDegKeyword[0]) {
+    gfits_scan (&header, RADecDegKeyword,  "%f", 1, &image[0].ra);
+    gfits_scan (&header, DECDecDegKeyword, "%f", 1, &image[0].dec);
+  } else {
+    if (RASexigKeyword[0] & DECSexigKeyword[0]) {
+      gfits_scan (&header, RASexigKeyword,  "%s", 1, line);
+      ohana_dms_to_ddd (&tmp, line);
+      image[0].ra = 15*tmp;
+      gfits_scan (&header, DECSexigKeyword, "%s", 1, &line);
+      ohana_dms_to_ddd (&tmp, line);
+      image[0].dec = tmp;
+    }
+  }
+
+  /* this segment is strongly CFHT dependent.  also it is somewhat
+     poor: the file must have the probes in the right order.
+     load_probes checks the data validity, but has no gurantee that
+     the right range has been loaded */
+
+  /* to change the selected probes, change:
+     1) the probes[] entries below
+     2) the entries in the program 'gettemps' */
+
+  /* the probes have to agree with the entries in the program 'gettemps' */
+  {
+    double pvalues[4];
+    static int probes[] = {2, 36, 43, 45};
+    if (load_probes (TempLogFile, image[0].obstime, probes, pvalues, 4)) {
+	image[0].teltemp_0 = pvalues[0];
+	image[0].teltemp_1 = pvalues[1];
+	image[0].teltemp_2 = pvalues[2];
+	image[0].teltemp_3 = pvalues[3];
+    } else {
+      fprintf (stderr, "failure to get probe data\n");
+      image[0].teltemp_0 = 200.0;
+      image[0].teltemp_1 = 200.0;
+      image[0].teltemp_2 = 200.0;
+      image[0].teltemp_3 = 200.0;
+    }
+  }
+  /* this should be a call to an external function... */
+  
+  /* extract the file name and the path */
+  name = filebasename (filename);
+  strcpy (image[0].filename, name);
+  name = pathname (filename);
+  if (name[0] != '/') {
+    cwd = getcwd_cfht (NULL, 1024);
+    ALLOCATE (tempname, char, strlen (cwd) + strlen (name) + 2);
+    if (!strcmp (name, ".")) {
+      sprintf (tempname, "%s", cwd);
+    } else {
+      sprintf (tempname, "%s/%s", cwd, name);
+    }      
+    free (name);
+    free (cwd);
+    name = tempname;
+  }    
+  strcpy (image[0].pathname, name);
+
+  return (image);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/imregclient.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/imregclient.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/imregclient.c	(revision 16632)
@@ -0,0 +1,93 @@
+# include "imregister.h"
+# include "imreg.h"
+
+int imregclient (char *fitsfile, char *statfile, char *datfile) {
+
+  int i, Nentry, Nslice, status, tmpint;
+  FILE *f;
+  RegImage *image;
+  FITS_DB db;
+
+  Nentry = 0;
+  image = iminfo (fitsfile);
+  
+  /* if images is MEF or SPLIT/SINGLE, load stats file */
+  /* get stats file (has sky, bias, etc) */
+  switch (image[0].mode) {
+  case M_MEF:
+  case M_SPLIT:
+    f = fopen (statfile, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file.stats\n");
+      exit (1);
+    }
+    fscanf (f, "%f %f", &image[0].sky, &image[0].bias);
+    fclose (f);
+    image[0].fwhm = get_fwhm (datfile);
+    Nentry = 1;
+    break;
+  case M_SINGLE:
+    f = fopen (statfile, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file.stats\n");
+      exit (1);
+    }
+    status = fscanf (f, "%d %f %f", &tmpint, &image[0].sky, &image[0].fwhm);
+    image[0].ccd = tmpint;
+    fclose (f);
+    Nentry = 1;
+    break;
+  case M_CUBE:
+    f = fopen (statfile, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file.stats\n");
+      exit (1);
+    }
+    status = 3;
+    Nslice = image[0].seq;
+    Nentry = Nslice + 1;
+    REALLOCATE (image, RegImage, Nentry);
+    for (i = 0; i < Nentry; i++) {
+      image[i] = image[0];
+      status = fscanf (f, "%d %f %f", &tmpint, &image[i].sky, &image[i].fwhm);
+      image[i].seq = tmpint;
+      if (image[i].seq == Nslice) continue;
+      image[i].obstime += image[0].seqtime*image[i].seq;
+    }
+    fclose (f);
+    Nentry = i;
+    break;
+  }
+  if (NoReg) dump_data (image, Nentry);
+
+  db.lockstate = LCK_HARD;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  if (!gfits_db_lock (&db, TempDB)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    gfits_db_create (&db);
+    gfits_table_set_RegImage (&db.ftable, NULL, 0);
+  } else {  
+    if (!gfits_db_load (&db)) {
+      fprintf (stderr, "ERROR: failure to load db\n");
+      gfits_db_close (&db);
+      exit (1);
+    }
+  }
+
+  gfits_convert_RegImage (image, sizeof (RegImage), Nentry);
+  gfits_table_to_vtable (&db.ftable, &db.vtable, 0, 0);
+  gfits_vadd_rows (&db.vtable, (char *) image, Nentry, sizeof(RegImage));
+
+  gfits_db_update (&db);
+  gfits_db_close (&db);
+  gfits_db_free (&db);
+
+  fprintf (stderr, "SUCCESS: wrote temp image data\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/match.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/match.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/match.c	(revision 16632)
@@ -0,0 +1,78 @@
+# include "imregister.h"
+# include "imreg.h"
+
+int *match_criteria (RegImage *image, int Nimage, int *Nmatch) {
+
+  int i, j, Nname;
+  int N, NMATCH;
+  int *match;
+  int reject;
+
+  /* create selection index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  Nname = 0;
+  if (criteria.NameSelect) Nname = strlen (criteria.Name);
+  
+  /* find entries that matches criteria */
+  for (i = 0; i < Nimage; i++) {
+    for (j = 0, reject = TRUE; reject && (j < criteria.Ntimes); j++) {
+      reject = (image[i].obstime + image[i].exptime < criteria.tstart[j]) || (image[i].obstime > criteria.tstop[j]);
+    }
+    if (criteria.Ntimes && reject) continue;
+    if (criteria.FilterSelect  && (strcasecmp (image[i].filter, criteria.Filter))) continue;
+    if (criteria.ModeSelect    && (image[i].mode != criteria.Mode)) continue;
+    if (criteria.CCDSelect     && (image[i].ccd != criteria.CCD)) continue;
+    if (criteria.TypeSelect    && (image[i].type != criteria.Type)) continue;
+    if (criteria.ExptimeSelect && (fabs (image[i].exptime - criteria.Exptime) > 5.0)) continue;
+    if (criteria.NameSelect    && (strncasecmp (image[i].filename, criteria.Name, Nname))) continue;
+    if (criteria.ProcSelect    && (criteria.Proc ^ (image[i].bias != 0.0))) continue;
+    if (criteria.DistSelect    && (criteria.Dist ^ (image[i].flag && IMREG_DIST))) continue;
+
+    match[N] = i;
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+  }
+  *Nmatch = N;
+  return (match);
+}
+
+int *match_images (RegImage *image, int Nimage, RegImage *subset, int Nsubset, int *Nmatch) {
+  
+  int i, j, N, Nfound;
+  int *match;
+
+  /* find matching images - very inefficient : sort by obstime, find those first? */
+  ALLOCATE (match, int, Nsubset);
+  for (j = 0; j < Nsubset; j++) {
+    match[j] = -1;
+    for (i = 0; (match[j] == -1) && (i < Nimage); i++) {
+      if (image[i].obstime > subset[j].obstime + 1) continue;
+      if (image[i].obstime < subset[j].obstime - 1) continue;
+      if (image[i].ccd != subset[j].ccd) continue;
+      match[j] = i;
+    }
+  }
+  
+  Nfound = 0;
+  for (i = 0; i < Nsubset; i++) {
+    /* set the new values for this image */
+    N = match[i];
+    if (N == -1) continue;
+    image[N].fwhm = subset[i].fwhm; 
+    image[N].bias = subset[i].bias; 
+    image[N].sky  = subset[i].sky; 
+    image[N].ra   = subset[i].ra; 
+    image[N].dec  = subset[i].dec; 
+    /* if the image is MEF, these were not correctly assigned by imsort.
+       this step uses the values from the split ccd image */
+    Nfound ++;
+  }
+  *Nmatch = Nfound;
+  return (match);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/modify.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/modify.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/modify.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "imregister.h"
+# include "imreg.h"
+
+void ModifySubset (FITS_DB *db, RegImage *image, int Nimage, int *match, int Nmatch) {
+
+  int i, j, Nold;
+  char *tmppath;
+  char *ext, *root, *path, dist;
+
+  Nold = 0;
+  tmppath = NULL;
+
+  /* create some necessary variables */
+  if (output.modify_path) { 
+    Nold = strlen (output.oldpath);
+    ALLOCATE (tmppath, char, 128);
+  }
+  if (output.modify_dist) {
+    dist = (output.dist) ? 0xff : ~IMREG_DIST;
+  }
+
+  /* modify the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+
+    i = match[j];
+
+    if (output.modify_path) {
+      if (!strncmp (image[i].pathname, output.oldpath, Nold)) {
+	strcpy (tmppath, &image[i].pathname[Nold]);
+	snprintf (image[i].pathname, 128, "%s%s", output.newpath, tmppath);
+      }
+    }
+
+    if (output.mef2split) {
+      if (image[i].mode == M_MEF) {
+	root = filerootname (image[i].filename);
+	ext = fileextname (image[i].filename);
+	path = strcreate (image[i].pathname);
+
+	snprintf (image[i].pathname, 128, "%s/%s", path, root);
+	snprintf (image[i].filename, 64,  "%s%02d.%s", root, image[i].ccd, ext);
+	image[i].mode = M_SPLIT;
+	free (root);
+	free (ext);
+	free (path);
+      }
+    }
+
+    if (output.split2mef) {
+      if (image[i].mode == M_SPLIT) {
+	ext  = fileextname (image[i].filename);
+	root = filebasename (image[i].pathname);
+	path = pathname (image[i].pathname);
+
+	snprintf (image[i].pathname, 128, "%s", path);
+	snprintf (image[i].filename, 64,  "%s.%s", root, ext);
+	image[i].mode = M_MEF;
+	free (root);
+	free (ext);
+	free (path);
+      }
+    }
+
+    if (output.modify_dist) {
+      if (output.dist)  image[i].flag |=  IMREG_DIST;
+      if (!output.dist) image[i].flag &= ~IMREG_DIST;
+    }
+
+    if (output.modify_filter) {
+      strncpy (image[i].filter, output.filter, 31);
+    }
+
+    if (output.modify_type) {
+      image[i].type = output.type;
+    }
+
+  }
+
+  /** we may later want to pull this out and put it elsewhere **/
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, match, Nmatch);
+  for (i = 0; i < Nmatch; i++) {
+    gfits_convert_RegImage ((RegImage *) db[0].vtable.buffer[i], sizeof (RegImage), 1);
+  }
+  gfits_db_update (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+
+/* 
+   MEF                      SPLIT
+   /path/filename.fits <--> /path/filename/filenameNN.fits
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/mosaics.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/mosaics.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/mosaics.c	(revision 16632)
@@ -0,0 +1,163 @@
+# include "imregister.h"
+# include "imreg.h"
+
+MosaicLayout *CreateCFH12K () {
+
+  MosaicLayout *layout;
+
+  ALLOCATE (layout, MosaicLayout, 1);
+
+  layout[0].center.Nccd = 4;
+  ALLOCATE (layout[0].center.ccd, int, layout[0].center.Nccd);
+  layout[0].center.ccd[0] = 2;
+  layout[0].center.ccd[1] = 3;
+  layout[0].center.ccd[2] = 8;
+  layout[0].center.ccd[3] = 9;
+
+  layout[0].outer.Nccd = 8;
+  ALLOCATE (layout[0].outer.ccd, int, layout[0].outer.Nccd);
+  layout[0].outer.ccd[0] = 0;
+  layout[0].outer.ccd[1] = 1;
+  layout[0].outer.ccd[2] = 4;
+  layout[0].outer.ccd[3] = 5;
+  layout[0].outer.ccd[4] = 6;
+  layout[0].outer.ccd[5] = 7;
+  layout[0].outer.ccd[6] = 10;
+  layout[0].outer.ccd[7] = 11;
+
+  layout[0].top.Nccd = 6;
+  ALLOCATE (layout[0].top.ccd, int, layout[0].top.Nccd);
+  layout[0].top.ccd[0] = 0;
+  layout[0].top.ccd[1] = 1;
+  layout[0].top.ccd[2] = 2;
+  layout[0].top.ccd[3] = 3;
+  layout[0].top.ccd[4] = 4;
+  layout[0].top.ccd[5] = 5;
+
+  layout[0].bottom.Nccd = 6;
+  ALLOCATE (layout[0].bottom.ccd, int, layout[0].bottom.Nccd);
+  layout[0].bottom.ccd[0] = 6;
+  layout[0].bottom.ccd[1] = 7;
+  layout[0].bottom.ccd[2] = 8;
+  layout[0].bottom.ccd[3] = 9;
+  layout[0].bottom.ccd[4] = 10;
+  layout[0].bottom.ccd[5] = 11;
+
+  layout[0].left.Nccd = 6;
+  ALLOCATE (layout[0].left.ccd, int, layout[0].left.Nccd);
+  layout[0].left.ccd[0] = 0;
+  layout[0].left.ccd[1] = 1;
+  layout[0].left.ccd[2] = 2;
+  layout[0].left.ccd[3] = 6;
+  layout[0].left.ccd[4] = 7;
+  layout[0].left.ccd[5] = 8;
+
+  layout[0].right.Nccd = 6;
+  ALLOCATE (layout[0].right.ccd, int, layout[0].right.Nccd);
+  layout[0].right.ccd[0] = 3;
+  layout[0].right.ccd[1] = 4;
+  layout[0].right.ccd[2] = 5;
+  layout[0].right.ccd[3] = 9;
+  layout[0].right.ccd[4] = 10;
+  layout[0].right.ccd[5] = 11;
+
+  return (layout);
+}
+
+MosaicLayout *CreateMegaCam () {
+
+  MosaicLayout *layout;
+
+  ALLOCATE (layout, MosaicLayout, 1);
+
+  layout[0].center.Nccd = 10;
+  ALLOCATE (layout[0].center.ccd, int, layout[0].center.Nccd);
+  layout[0].center.ccd[0] = 11;
+  layout[0].center.ccd[1] = 12;
+  layout[0].center.ccd[2] = 13;
+  layout[0].center.ccd[3] = 14;
+  layout[0].center.ccd[4] = 15;
+  layout[0].center.ccd[5] = 20;
+  layout[0].center.ccd[6] = 21;
+  layout[0].center.ccd[7] = 22;
+  layout[0].center.ccd[8] = 23;
+  layout[0].center.ccd[9] = 24;
+
+  layout[0].outer.Nccd = 26;
+  ALLOCATE (layout[0].outer.ccd, int, layout[0].outer.Nccd);
+  layout[0].outer.ccd[0] = 0;
+  layout[0].outer.ccd[1] = 1;
+  layout[0].outer.ccd[2] = 2;
+  layout[0].outer.ccd[3] = 3;
+  layout[0].outer.ccd[4] = 4;
+  layout[0].outer.ccd[5] = 5;
+  layout[0].outer.ccd[6] = 6;
+  layout[0].outer.ccd[7] = 7;
+  layout[0].outer.ccd[8] = 8;
+  layout[0].outer.ccd[9] = 9;
+  layout[0].outer.ccd[10] = 10;
+  layout[0].outer.ccd[11] = 16;
+  layout[0].outer.ccd[12] = 17;
+  layout[0].outer.ccd[13] = 18;
+  layout[0].outer.ccd[14] = 19;
+  layout[0].outer.ccd[15] = 25;
+  layout[0].outer.ccd[16] = 26;
+  layout[0].outer.ccd[17] = 27;
+  layout[0].outer.ccd[18] = 28;
+  layout[0].outer.ccd[19] = 29;
+  layout[0].outer.ccd[20] = 30;
+  layout[0].outer.ccd[21] = 31;
+  layout[0].outer.ccd[22] = 32;
+  layout[0].outer.ccd[23] = 33;
+  layout[0].outer.ccd[24] = 34;
+  layout[0].outer.ccd[25] = 35;
+
+  layout[0].top.Nccd = 9;
+  ALLOCATE (layout[0].top.ccd, int, layout[0].top.Nccd);
+  layout[0].top.ccd[0] = 0;
+  layout[0].top.ccd[1] = 1;
+  layout[0].top.ccd[2] = 2;
+  layout[0].top.ccd[3] = 3;
+  layout[0].top.ccd[4] = 4;
+  layout[0].top.ccd[5] = 5;
+  layout[0].top.ccd[6] = 6;
+  layout[0].top.ccd[7] = 7;
+  layout[0].top.ccd[8] = 8;
+
+  layout[0].bottom.Nccd = 9;
+  ALLOCATE (layout[0].bottom.ccd, int, layout[0].bottom.Nccd);
+  layout[0].bottom.ccd[0] = 27;
+  layout[0].bottom.ccd[1] = 28;
+  layout[0].bottom.ccd[2] = 29;
+  layout[0].bottom.ccd[3] = 30;
+  layout[0].bottom.ccd[4] = 31;
+  layout[0].bottom.ccd[5] = 32;
+  layout[0].bottom.ccd[6] = 33;
+  layout[0].bottom.ccd[7] = 34;
+  layout[0].bottom.ccd[8] = 35;
+
+  layout[0].left.Nccd = 8;
+  ALLOCATE (layout[0].left.ccd, int, layout[0].left.Nccd);
+  layout[0].left.ccd[0] = 0;
+  layout[0].left.ccd[1] = 1;
+  layout[0].left.ccd[2] = 9;
+  layout[0].left.ccd[3] = 10;
+  layout[0].left.ccd[4] = 18;
+  layout[0].left.ccd[5] = 19;
+  layout[0].left.ccd[6] = 27;
+  layout[0].left.ccd[7] = 28;
+
+  layout[0].right.Nccd = 8;
+  ALLOCATE (layout[0].right.ccd, int, layout[0].right.Nccd);
+  layout[0].right.ccd[0] = 7;
+  layout[0].right.ccd[1] = 8;
+  layout[0].right.ccd[2] = 16;
+  layout[0].right.ccd[3] = 17;
+  layout[0].right.ccd[4] = 25;
+  layout[0].right.ccd[5] = 26;
+  layout[0].right.ccd[6] = 34;
+  layout[0].right.ccd[7] = 35;
+
+  return (layout);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/newimages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/newimages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/newimages.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "imregister.h"
+# include "imreg.h"
+
+RegImage *newimages (RegImage *image, int *Nimage) {
+
+  int i, Nnew;
+  RegImage *regimage;
+
+  Nnew = 0;
+  regimage = NULL;
+
+  /* identify new entries based on mode */
+  switch (image[0].mode) {
+  case M_CUBE:
+    Nnew = image[0].seq + 1;
+    ALLOCATE (regimage, RegImage, Nnew);
+    regimage[0] = image[0];
+    for (i = 1; i < Nnew; i++) {
+      regimage[i] = image[0]; 
+      regimage[i].seq = i - 1;
+      regimage[i].mode = M_SLICE;
+      regimage[i].obstime += image[0].seqtime*regimage[i].seq;
+    }
+    break;
+  case M_MEF:
+    Nnew = image[0].ccd;
+    ALLOCATE (regimage, RegImage, Nnew);
+    for (i = 0; i < Nnew; i++) {
+      regimage[i] = image[0]; 
+      regimage[i].ccd = i;
+    }
+    break;
+  case M_SPLIT:
+  case M_SINGLE:
+    Nnew = 1;
+    regimage = &image[0];
+    break;
+  }
+  *Nimage = Nnew;
+  return (regimage);
+}
+
+
+/* meaning of image fields for different data modes:
+
+   mode      ccd                    seq
+   SINGLE    0                      0
+   SPLIT     ccd seq number         0
+   MEF       Nccd                   0
+   CUBE      ccd seq number         Nseq
+   SLICE     ccd seq number         seq number
+   CUBE-MEF  Nccd                   Nseq
+   SLICE-MEF Nccd                   seq number
+
+*/
+
+/*
+ we need to consider modifying this to separately ID MEF/SPLIT/SINGLE and CUBE/SLICE 
+ for the moment, we are keeping this the same as the old style
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/output.c	(revision 16632)
@@ -0,0 +1,251 @@
+# include "imregister.h"
+# include "imreg.h"
+
+static int RegTimeMode = FALSE;
+static int CCDSeq = FALSE;
+static int PTstyle = FALSE;
+
+void SetOutputMode (char *mode) {
+
+  if (!strcmp (mode, "RegTimeMode")) {
+    RegTimeMode = TRUE;
+    return;
+  }
+  if (!strcmp (mode, "CCDSeq")) {
+    CCDSeq = TRUE;
+    return;
+  }
+  if (!strcmp (mode, "PTstyle")) {
+    PTstyle = TRUE;
+    return;
+  }
+
+}
+
+/* given a subset list, write out the selected images, if desired */
+void OutputSubset (RegImage *image, int Nimage, int *match, int Nmatch) {
+
+  if (output.table != (char *) NULL) {
+    DumpFitsTable (output.table, image, match, Nmatch);
+  } 
+
+  if (output.bintable != (char *) NULL) {
+    DumpFitsBintable (output.bintable, image, match, Nmatch);
+  } 
+
+  if (output.cadctable != (char *) NULL) {
+    DumpCADCTable (output.cadctable, image, match, Nmatch);
+  } 
+
+  PrintSubset (image, match, Nmatch);
+  if (output.verbose) fprintf (stderr, "SUCCESS\n");
+
+  exit (0);
+}
+
+/* write out complete binary FITS table in format of db */
+void DumpFitsBintable (char *filename, RegImage *image, int *match, int Nmatch) {
+
+  int i, j;
+  FILE *f;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  RegImage *subset;
+
+  /* extract subset list to single array */
+  ALLOCATE (subset, RegImage, MAX (1, Nmatch));
+  for (i = 0; i < Nmatch; i++){
+    j = match[i];
+    memcpy (&subset[i], &image[j], sizeof (RegImage));
+  }
+
+  /* open file for output */
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", filename);
+    exit (1);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_RegImage (&ftable, subset, Nmatch);
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+  fclose (f);
+  exit (0);
+}
+
+void DumpFitsTable (char *filename, RegImage *image, int *match, int Nmatch) {
+  
+  int i;
+  char *obsstr, *regstr, *line, dummy[64];
+  char *modestr, *typestr, *ccdstr, *datestr;
+  time_t tsecond;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  RegImage *subset;
+
+  bzero (dummy, 64);
+  memset (dummy, ' ', 63);
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* create table header */
+  gfits_create_table_header (&theader, "TABLE", "IMAGE_DATABASE");
+      
+  /* add current date/time to header */
+  ohana_str_to_time ("now", &tsecond);
+  datestr = ohana_sec_to_date (tsecond);
+  gfits_modify (&header,  "DATE", "%s", 1, datestr);
+  gfits_modify (&theader, "DATE", "%s", 1, datestr);
+
+  /* define table layout */
+  gfits_define_table_column (&theader, "A64",   "FILE",       "filename in db",        "");
+  gfits_define_table_column (&theader, "A128",  "PATH",       "fullpath in db",        "");
+  gfits_define_table_column (&theader, "A32",   "FILTER",     "filter name",           "");
+  gfits_define_table_column (&theader, "A32",   "INSTRUMENT", "instrument",            "");
+  gfits_define_table_column (&theader, "A6",    "CCD",        "ccd identifier",        "");
+  gfits_define_table_column (&theader, "A6",    "MODE",       "mef/split/etc",         "");
+  gfits_define_table_column (&theader, "A8",    "TYPE",       "object/flat/bias/etc",  "");
+  gfits_define_table_column (&theader, "A25",   "JUNK",       "space for expansion",   "");
+  gfits_define_table_column (&theader, "F6.1",  "EXPTIME",    "exposure time",        "seconds");
+  gfits_define_table_column (&theader, "F5.3",  "AIRMASS",    "airmass",              "");
+  gfits_define_table_column (&theader, "F7.1",  "SKY",        "background level",     "counts / pixel");
+  gfits_define_table_column (&theader, "F6.1",  "BIAS",       "bias level",           "counts / pixel");
+  gfits_define_table_column (&theader, "F5.2",  "FWHM",       "image quality",        "pixels");
+  gfits_define_table_column (&theader, "F5.1",  "TELFOCUS",   "telescope focus",      "microns");
+  gfits_define_table_column (&theader, "F5.1",  "XPROBE",     "bonnette probe x pos", "microns");
+  gfits_define_table_column (&theader, "F5.1",  "YPROBE",     "bonnette probe y pos", "microns");
+  gfits_define_table_column (&theader, "F5.1",  "ZPROBE",     "bonnette focus",       "microns");
+  gfits_define_table_column (&theader, "F5.1",  "DETTEMP",    "detector temperature", "deg celcius");
+  gfits_define_table_column (&theader, "F5.1",  "TELTEMP0",   "other temperature",    "deg celcius");
+  gfits_define_table_column (&theader, "F5.1",  "TELTEMP1",   "other temperature",    "deg celcius");
+  gfits_define_table_column (&theader, "F5.1",  "TELTEMP2",   "other temperature",    "deg celcius");
+  gfits_define_table_column (&theader, "F5.1",  "TELTEMP3",   "other temperature",    "deg celcius");
+  gfits_define_table_column (&theader, "F5.1",  "ROTANGLE",   "camear rotation angle", "degrees");
+  gfits_define_table_column (&theader, "F10.6", "RA",         "image ra",              "degrees");
+  gfits_define_table_column (&theader, "F10.6", "DEC",        "image dec",             "degrees");
+  gfits_define_table_column (&theader, "A20",   "OBS_TIME",   "time of measurement",   "seconds since Jan 1, 1970 UT");
+  gfits_define_table_column (&theader, "A20",   "REG_TIME",   "time of registration",  "seconds since Jan 1, 1970 UT");
+
+  /* create table, add data values */
+  gfits_create_table (&theader, &table);
+  
+  /* add data to table */
+  for (i = 0; i < Nmatch; i++) {
+    subset = &image[match[i]];
+    obsstr   = ohana_sec_to_date (subset[0].obstime);
+    regstr   = ohana_sec_to_date (subset[0].regtime);
+    typestr  = get_type_name(subset[0].type);
+    modestr  = get_mode_name(subset[0].mode);
+    ccdstr   = ccds[(int)subset[0].ccd];
+
+    line = gfits_table_print (&table, subset[0].pathname, subset[0].filename, 
+			     subset[0].filter, subset[0].instrument, ccdstr,
+			     modestr, typestr, dummy, 
+			     subset[0].exptime, subset[0].airmass, 
+			     subset[0].sky, subset[0].bias, subset[0].fwhm, 
+			     subset[0].telfocus, subset[0].xprobe, subset[0].yprobe, subset[0].zprobe, 
+			     subset[0].dettemp, 
+			     subset[0].teltemp_0, subset[0].teltemp_1, subset[0].teltemp_2, subset[0].teltemp_3,
+			     subset[0].rotangle, 
+			     subset[0].ra, subset[0].dec, 
+			     obsstr, regstr);
+
+    gfits_add_rows (&table, line, 1, strlen(line));
+    free (line);
+    free (obsstr);
+    free (regstr);
+  }
+
+  gfits_write_header  (filename, &header);
+  gfits_write_matrix  (filename, &matrix);
+  gfits_write_Theader (filename, &theader);
+  gfits_write_table   (filename, &table);
+  exit (0);
+}
+
+/* Select, TimeMode are global */
+int PrintSubset (RegImage *image, int *match, int Nmatch) {
+  
+  char ccdstr[64];  
+  int i, j;
+  char *modestr, *typestr, *timestr, *root, *path;
+
+  /* print the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+    
+    i = match[j];
+
+    modestr = get_mode_name (image[i].mode);
+    typestr = get_type_name (image[i].type);
+    timestr = RegTimeMode ? ohana_sec_to_date (image[i].regtime) : ohana_sec_to_date (image[i].obstime);
+
+    if (CCDSeq) {
+      sprintf (ccdstr, "%02d", image[i].ccd);
+    } else {
+      if ((image[i].ccd < 0) || (image[i].ccd >= Nccd)) {
+	sprintf (ccdstr, "%02d", image[i].ccd);
+      } else {
+      sprintf (ccdstr, "%s", ccds[(int)image[i].ccd]);
+      }
+    }      
+
+    if (PTstyle) {
+      root = filerootname (image[i].filename);
+
+      /* do i want ccdstr? add a dot? 654321o.ccd00.ext */
+      if (image[i].mode == M_MEF) {
+	fprintf (stdout, "%s/%s %s/%s%02d %s %s\n", image[i].pathname, image[i].filename, root, root, image[i].ccd, ccdstr, modestr);
+      }
+
+      if (image[i].mode == M_SPLIT) {
+	path = basename (image[i].pathname);
+	fprintf (stdout, "%s/%s %s/%s %s %s\n", image[i].pathname, image[i].filename, path, root, ccdstr, "SPLIT");
+      }
+
+      if ((image[i].mode == M_SINGLE) || (image[i].mode == M_CUBE)) {
+	fprintf (stdout, "%s/%s %s 0 %s\n", image[i].pathname, image[i].filename, root, modestr);
+      }
+    } else {
+      /* this is somewhat poor: I have predefined a subset of value, and I can't guarantee that 'filter' has no spaces */
+      fprintf (stdout, "%5d %6s %6s %s  ", i, typestr, modestr, ccdstr);
+      fprintf (stdout, "%s %s  ", image[i].pathname, image[i].filename);
+      fprintf (stdout, "%s %f %s %f %f %f\n", image[i].filter, image[i].exptime, 
+	       timestr, image[i].fwhm, image[i].bias, image[i].sky);
+    }
+
+    free (timestr);
+  }
+  return (TRUE);
+}
+
+int dump_data (RegImage *image, int Nimage) {
+
+  int i;
+
+  for (i = 0; i < Nimage; i++) {
+    fprintf (stdout, "%s %f %f %f %s\n", image[i].filename, image[i].fwhm, image[i].sky, image[i].bias, image[i].filter);
+  }
+
+  fprintf (stdout, "SUCCESS\n");
+  exit (0);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/rconnect.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/rconnect.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/rconnect.c	(revision 16632)
@@ -0,0 +1,100 @@
+# include "imregister.h"
+# include "imreg.h"
+
+/* rconnect opens a remote shell on hostname and returns two file descriptors:
+   one for read, one for write */
+
+int rconnect (char *hostname, char *command, int *rsock, int *wsock) {
+
+  int i, rfd[2], wfd[2], status;
+  pid_t pid;
+  char buffer[0x4000];
+  char *file;
+  Fifo fifo;
+
+  InitFifo (&fifo, 0x4000, 0x1000);
+
+  status = pipe (rfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+  status = pipe (wfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (FALSE);
+  }
+
+  file = filebasename (command);
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    fprintf (stderr, "starting remote connection to %s...", hostname);
+    /* close the excess sockets */
+    close (wfd[1]);
+    close (rfd[0]);
+    dup2 (wfd[0], STDIN_FILENO);
+    dup2 (rfd[1], STDOUT_FILENO);
+    dup2 (rfd[1], STDERR_FILENO);
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    status = execl (command, file, hostname, "/bin/csh", NULL); 
+    fprintf (stderr, "error starting remote shell process\n");
+    Shutdown (1);
+  }
+  *wsock = wfd[1];
+  *rsock = rfd[0];
+  close (wfd[0]);
+  close (rfd[1]);
+  
+  fcntl (*rsock, F_SETFL, O_NONBLOCK);
+  fcntl (*wsock, F_SETFL, O_NONBLOCK);
+
+  sprintf (buffer, "echo PTOLEMY STARTED\n");
+  status = write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  /* try to get evidence connection is alive - wait upto a few seconds */
+  status = -1;
+  for (i = 0; (i < 300) && (status == -1); i++) {
+    fcntl (*rsock, F_SETFL, O_NONBLOCK);
+    status = SockScan ("PTOLEMY STARTED", &fifo, *rsock);
+    if (!(i % 30)) fprintf (stderr, ".");
+    if (status == 0) {
+      fprintf (stderr, "socket closed unexpectedly\n");
+      close (*wsock);
+      close (*rsock);
+      return (FALSE);
+    }
+  }
+  if (i == -1) {
+    fprintf (stderr, "timeout while connecting\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+  fprintf (stderr, "Connected\n");
+
+  /* the onintr command works with csh/tcsh type shells to
+     prevent trapping of SIGTERM, used to kill hung jobs.
+     for bash/sh type shells, you can use SIGQUIT instead
+     without setting onintr */
+  sprintf (buffer, "onintr\n");
+  write (*wsock, buffer, strlen(buffer));
+  if ((status == -1) && (errno == EPIPE)) {
+    fprintf (stderr, "socket closed unexpectedly\n");
+    close (*wsock);
+    close (*rsock);
+    return (FALSE);
+  }
+
+  FreeFifo (&fifo);
+  return (pid);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/submit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/submit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/submit.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "imregister.h"
+# include "imreg.h"
+
+int SubmitImages (RegImage *image) {
+
+  int i;
+  char line[1024], *root, *path;
+
+  /* send these images to FIFOs for imstat and ptolemy */ 
+
+  if (image[0].mode == M_MEF) {
+    for (i = 0; i < image[0].ccd; i++) {
+      root = filerootname (image[0].filename);
+      if (i < Nccd) {
+	sprintf (line, "%s/%s %s/%s%s %s %s", image[0].pathname, image[0].filename, root, root, ccdn[i], ccds[i], "MEF");
+      } else {
+	sprintf (line, "%s/%s %s/%sxx none %s", image[0].pathname, image[0].filename, root, root, "MEF");
+      }
+      if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+      if (image[0].type == T_OBJECT) {
+	if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+      }
+    }
+  } 
+
+  if (image[0].mode == M_SINGLE) {
+    root = filerootname (image[0].filename);
+    sprintf (line, "%s/%s %s %02d %s", image[0].pathname, image[0].filename, root, 0, "SINGLE");
+    if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+    if (image[0].type == T_OBJECT) {
+      if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+    }
+  } 
+
+  if (image[0].mode == M_CUBE) {
+    root = filerootname (image[0].filename);
+    sprintf (line, "%s/%s %s %02d %s", image[0].pathname, image[0].filename, root, 0, "CUBE");
+    if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+    if (image[0].type == T_OBJECT) {
+      if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+    }
+  } 
+
+  if (image[0].mode == M_SPLIT) {
+    path = basename (image[0].pathname);
+    root = filerootname (image[0].filename);
+    sprintf (line, "%s/%s %s/%s %02d %s", image[0].pathname, image[0].filename, path, root, image[0].ccd, "SPLIT");
+    if (!WriteFIFO (ImstatFifo, line)) return (FALSE);
+    if (image[0].type == T_OBJECT) {
+      if (!WriteFIFO (PtolemyFifo, line)) return (FALSE);
+    }
+  }    
+
+  return (TRUE);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/imregister/imreg/unique.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/imreg/unique.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/imreg/unique.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "imregister.h"
+# include "imreg.h"
+
+void sortstr (char **S, int *X, int N) {
+
+# define SWAPFUNC(A,B){ \
+  char *tmp = S[A]; S[A] = S[B]; S[B] = tmp; \
+  int  itmp = X[A]; X[A] = X[B]; X[B] = itmp; \
+}
+# define COMPARE(A,B)(strcmp(S[A], S[B]) < 0)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+/* input is a subset index of image list, output is a new subset */
+int *unique_entries (RegImage *image, int Nimage, int *subset, int *Nmatch) {
+
+  int i, j, k, m, Nsubset;
+  int N, NMATCH;
+  int *match, *entry;
+  char idxline[128];
+  char **index;
+
+  if (!output.unique) return (subset);
+
+  /* create output index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  Nsubset = *Nmatch;
+
+  /* index = filename.ccd */
+  ALLOCATE (index, char *, Nsubset);
+  ALLOCATE (entry, int, Nsubset);
+  for (i = 0; i < Nsubset; i++) {
+    sprintf (idxline, "%s.%02d", image[subset[i]].filename, image[subset[i]].ccd);
+    index[i] = strcreate (idxline);
+    entry[i] = subset[i];
+  }
+  sortstr (index, entry, Nsubset);
+
+  /* find unique sequences */
+  for (i = 0; i < Nsubset; ) {
+    for (j = i + 1; (j < Nsubset) && (!strcmp (index[i], index[j])); j++);
+
+    /* find first entry with bias != 0, else entry i */
+    m = i;
+    for (k = i; k < j; k++) {
+      if (image[entry[k]].bias != 0) {
+	m = k;
+	break;
+      }
+    }
+    
+    /* add unique entry to output list */
+    match[N] = entry[m];
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+
+    /* j always points to the next entry */
+    i = j;
+  }
+
+  for (i = 0; i < Nsubset; i++) free (index[i]);
+  free (index);
+  free (entry);
+  free (subset);
+
+  *Nmatch = N;
+  return (match);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/include/detrend.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/include/detrend.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/include/detrend.h	(revision 16632)
@@ -0,0 +1,111 @@
+
+typedef struct {
+  int state; /* none, close, perfect */
+  int crit;  /* which criterion? */
+  int image; /* which detrend image? */
+} Match;
+
+typedef struct {
+  int TimeSelect;    time_t tstart, tstop;
+  char *label; 
+  char *imageID;
+  int order;
+  int type;
+  char mode;
+  int CCDSelect;     int CCD;
+  int ExptimeSelect; float Exptime;
+  int filter;
+} Descriptor;
+
+/* MosaicSelect & ImageSelect define these values */
+typedef struct {
+  int ModeSelect;    int Mode;
+  int TypeSelect;    int Type;
+  int CCDSelect;     int CCD;
+  int FilterSelect;  int Filter;
+  int EntrySelect;   int Entry;
+  int LabelSelect;   char *Label;
+  int NameSelect;    char *Name;
+  int ExptimeSelect; float Exptime;
+  int TimeSelect;    time_t tstart, tstop;
+  int MatchNumber;
+} Criteria;
+
+int Ncriteria;
+Criteria *criteria;
+
+struct {
+  int Select;
+  int Delete;
+  int Modify;
+  int Altpath;
+  int ElixirSmart;
+  int TimeMode;
+  int Recipe;
+  int Close;
+  int Criteria;
+  int Chipname;
+
+  char *ModifyEntry, *ModifyValue;
+  time_t TimeValue;
+  
+  int verbose;
+  char *table;
+  char *bintable;
+} output;
+
+/* altpath values */
+enum {NONE, ADD, DELETE, UPDATE};
+enum {START, STOP, REG};
+enum {UNLOCK, LOCK, IGNORE};
+enum {MATCH_NONE, MATCH_CLOSE, MATCH_PERFECT};
+
+# define DEBUG 0
+
+char **RecipeType;
+int Nrecipe;
+
+int SingleIsSplit;
+int NoReg;
+
+int regargs (int argc, char **argv, Descriptor *descriptor);
+int args (int argc, char **argv);
+int DefineImage (char *filename, Descriptor *descriptor);
+DetReg DefineEntry (Descriptor descriptor);
+
+char *set_dBFile ();
+char *get_dBPath ();
+int delete_image (DetReg *image);
+
+int SaveEntry (char *input, DetReg *newdata, char *ID);
+
+char **LoadRecipe (char *filter, int *nrecipe);
+
+Match *MatchCriteria (DetReg *image, int Nimage, int *nmatch);
+Match *UniqueSubset (DetReg *image, int Nimage, Match *match, int *nmatch);
+Match *ExptimeCriteria (DetReg *image, int Nimage, Match *match, int *nmatch);
+Match *CloseCriteria (DetReg *image, int Nimage, Match *match, int *nmatch);
+
+Match CheckCriteria (DetReg *image);
+
+int OutputSubset (DetReg *image, int Nimage, Match *match, int Nmatch);
+int DumpFitsTable (char *filename, DetReg *detdata, Match *match, int Nmatch);
+int PrintSubset (DetReg *detdata, Match *match, int Nmatch);
+Match SelectEntry (DetReg *image, int Nimage, Match *list, int Nlist, Criteria *crit);
+
+int usage ();
+Criteria *MosaicCriteria (Criteria base, char *filename, int *ncrit);
+Criteria *ImageCriteria (Criteria base, char *filename, char *ImageExtend, char *ImageMode, int *ncrit);
+Criteria *ExpandBase (Criteria base, int *ncrit, time_t *tstart, time_t *tstop, int *filt);
+Criteria *ExpandRecipe (Criteria *base, int *Ncrit);
+
+int escape (int mode, char *message);
+int DumpFitsBintable (char *filename, DetReg *image, Match *match, int Nmatch);
+int cmp_crit (Criteria *crit, DetReg *image);
+int set_crit (Criteria *crit, DetReg *image);
+int ckpathname (char *newpath);
+int PrintCriteria ();
+
+int SetAltpath (FITS_DB *db, DetReg *image, int Nimage, Match *match, int Nmatch);
+int ModifySubset (FITS_DB *db, DetReg *image, int Nimage, Match *match, int Nmatch);
+void DeleteSubset (FITS_DB *db, DetReg *image, int Nimage, Match *match, int Nmatch);
Index: /branches/eam_branch_20080223/Ohana/src/imregister/include/imphot.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/include/imphot.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/include/imphot.h	(revision 16632)
@@ -0,0 +1,29 @@
+
+struct {
+  int PhotcodeSelect; int photcode;
+  int NameSelect;     char *Name;
+  int Ntimes;         time_t *tstart, *tstop;
+  int CodeSelect;     int Code;
+} criteria;
+
+struct {
+  int   modify;
+  char *ModifyValue;
+  char *ModifyEntry;
+  char *table;
+  char *bintable;
+} options;
+
+int VERBOSE;
+int FORCE_READ;
+
+int db_load (FITS_DB *db);
+int args (int argc, char **argv);
+int DumpFitsBintable (char *filename, Image *image, int *match, int Nmatch);
+int DumpFitsTable (char *filename, Image *image, int *match, int Nmatch);
+void ModifySubset (FITS_DB *db, Image *image, int Nimage, int *match, int Nmatch);
+int PrintSubset (Image *image, int *match, int Nmatch);
+int output (Image *image, int *match, int Nmatch);
+int rfits (FITS_DB *db);
+int rtext (FITS_DB *db);
+int *subset (Image *image, int Nimage, int *nsubset);
Index: /branches/eam_branch_20080223/Ohana/src/imregister/include/imreg.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/include/imreg.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/include/imreg.h	(revision 16632)
@@ -0,0 +1,130 @@
+# include <signal.h>
+
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nmaxread;
+  int   Nextra;
+  int   Nlast;
+  int   Nbuffer;
+} Fifo;
+
+struct {
+  int ModeSelect;    int Mode;
+  int TypeSelect;    int Type;
+  int CCDSelect;     int CCD;
+  int FilterSelect;  char *Filter;
+  int EntrySelect;   int Entry;
+  int LabelSelect;   char *Label;
+  int ExptimeSelect; float Exptime;
+  int TimeSelect;    unsigned long Time;
+  int NameSelect;    char *Name;
+  int ProcSelect;    int Proc;
+  int DistSelect;    int Dist;
+  int Ntimes;        time_t *tstart, *tstop;
+  int MatchNumber;
+  int Close;
+} criteria;
+
+struct {
+  int delete;
+  int modify;
+
+  int modify_path;
+  char *oldpath, *newpath;
+
+  int unique;
+  int mef2split, split2mef;
+  int modify_dist, dist;
+  int modify_filter, modify_type, type;
+  char *filter;
+
+  int HST;
+  int verbose;
+  char *table;
+  char *bintable;
+  char *cadctable;
+} output;
+
+typedef struct {
+  int *ccd;
+  int Nccd;
+  char name[64];
+} MosaicRegion;
+
+typedef struct {
+  MosaicRegion center;
+  MosaicRegion outer;
+  MosaicRegion top;
+  MosaicRegion bottom;
+  MosaicRegion left;
+  MosaicRegion right;
+} MosaicLayout;
+
+enum {UNLOCK, LOCK, IGNORE};
+
+int SingleIsSplit;
+int NeedType;
+int NoReg;
+int IMSORT;
+int CLIENT;
+char *PIDFILE;
+int LOOP_DELAY;
+
+int args (int argc, char **argv);
+
+void DeleteSubset (FITS_DB *db, RegImage *image, int Nimage, int *match, int Nmatch);
+RegImage *iminfo (char *filename);
+
+int *match_criteria (RegImage *image, int Nimage, int *Nmatch);
+int *match_images (RegImage *image, int Nimage, RegImage *subset, int Nsubset, int *Nmatch);
+
+RegImage *newimages (RegImage *image, int *Nimage);
+
+void ModifySubset (FITS_DB *db, RegImage *image, int Nimage, int *match, int Nmatch);
+void SetOutputMode (char *mode);
+void OutputSubset (RegImage *image, int Nimage, int *match, int Nmatch);
+void DumpFitsBintable (char *filename, RegImage *image, int *match, int Nmatch);
+void DumpFitsTable (char *filename, RegImage *image, int *match, int Nmatch);
+int PrintSubset (RegImage *image, int *match, int Nmatch);
+int dump_data (RegImage *image, int Nimage);
+int SubmitImages (RegImage *image);
+int load_probes (char *filename, unsigned long tzero, int *wantprobe, double *values, int Nprobe);
+int define_table (Header *header, Matrix *matrix, Header *theader, FTable *table);
+void set_timezone (double dt);
+
+void DumpCADCTable (char *filename, RegImage *image, int *match, int Nmatch);
+int *GetObsIDSubset (RegImage *image, int start, int *index, int *entry, int Nindex, int *Nsubset);
+int *GetUniqueObsID (RegImage *image, int *index, int *entry, int Nindex, int *Nmatch);
+void GetObsIDIndex (RegImage *image, int *match, int Nmatch, int **Index, int **Entry);
+double SigmaClipList (double *list, int N);
+double MosaicIQStats (RegImage *image, int *match, int Nmatch, MosaicRegion *region);
+MosaicLayout *CreateCFH12K ();
+MosaicLayout *CreateMegaCam ();
+int GetREFCCD (RegImage *image, int *index, int *entry, int Nindex, int start);
+
+int imregclient (char *fitsfile, char *statfile, char *datfile);
+void SIG_DIE (int sig);
+void SIG_PIPE (int sig);
+void SetSignals ();
+void KillProcess (char *pidfile);
+void StatusProcess (char *pidfile);
+int close_lock_db ();
+int ConfigPID (char *pidfile);
+int print_db_status (char *message);
+int escape (int mode, char *message);
+
+int LoadPID (char *file, pid_t *pid, char *username, char *machine);
+int Shutdown (int status);
+void RemovePID ();
+int rconnect (char *hostname, char *command, int *rsock, int *wsock);
+
+int InitFifo (Fifo *fifo, int Nalloc, int Nextra);
+int FlushFifo (Fifo *fifo);
+int ShiftFifo (Fifo *fifo);
+int ReadtoFifo (Fifo *fifo, int sock);
+void FreeFifo (Fifo *fifo);
+int SockScan (char *string, Fifo *fifo, int sock);
+int memstr (char *m1, char *m2, int n);
+
+int *unique_entries (RegImage *image, int Nimage, int *subset, int *Nmatch);
Index: /branches/eam_branch_20080223/Ohana/src/imregister/include/imregister.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/include/imregister.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/include/imregister.h	(revision 16632)
@@ -0,0 +1,100 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <errno.h>
+# include <time.h>
+# include <ctype.h>
+# include <stdlib.h>
+
+/* config variables from very old versions - remove?
+char ImageTemplate[256];
+char DBServer[256];
+*/
+
+char ImstatFifo[256];
+char PtolemyFifo[256];
+
+char ImageDB[256];
+char DetrendDB[256];
+char PhotDB[256];
+char TransDB[256];
+char ImPhotDB[256];
+char TempDB[256];
+char LogFile[256];
+char CONNECT[64];
+
+int  NDetrendAltDB;
+char **DetrendAltDB;
+
+char PhotCodeFile[256];
+char TempLogFile[256];
+char FilterList[256];
+char CameraConfig[256];
+char RecipeFile[256];
+
+char DateKeyword[64];
+char DateMode[64];
+char UTKeyword[64];
+char MJDKeyword[64];
+char JDKeyword[64];
+char ExptimeKeyword[16];
+char ImagetypeKeyword[16];
+char CCDnumKeyword[16];
+char FilterKeyword[16];
+char AirmassKeyword[16];
+char FocusKeyword[16];
+char RotationKeyword[16];
+char DettempKeyword[16];
+char Teldata1Keyword[16];
+char Teldata2Keyword[16];
+char Teldata3Keyword[16];
+char RADecDegKeyword[16];
+char DECDecDegKeyword[16];
+char RASexigKeyword[16];
+char DECSexigKeyword[16];
+char CameraKeyword[16];
+char Camera[64];
+char SeeingREFCCD[64];
+double ARCSEC_PIXEL;
+
+/* global vars used by camera info */
+char **ccds, **ccdn;
+int  Nccd;
+
+/* global vars used by filter abstraction */
+# define FILTER_ANY  -1 
+# define FILTER_NONE 0
+int NFILTER;
+char **filtername;
+char **filterhash;
+int   *filternum;
+
+int get_trange_arguments (int *argc, char **argv, time_t **Tstart, time_t **Tstop, int *ntimes);
+int get_filter_arguments (int *argc, char **argv, int **Filt, int *Nfilt);
+
+int parse_time (Header *header);
+void sort (float *value, int N);
+void dsort (double *value, int N);
+void sortstr (char **S, int *X, int N);
+void sortpair (int *X, int *Y, int N);
+
+void ConfigCamera ();
+int MatchCCDNameHeader (Header *header);
+int MatchCCDName (char *ID);
+void ConfigFilter ();
+int MatchFilterList (char *line);
+void ConfigInit (int *argc, char **argv);
+void WarnConfig (char *config, char *key, char * mode, int N, void *var);
+int WriteFIFO (char *filename, char *line);
+double get_fwhm (char *filename);
+
+void get_version (int argc, char **argv, char *version);
+int set_db (char *filename);
+
+void warn_scan (Header *header, char *field, char *format, int N, void *var);
+int gfits_scan_nchar (Header *header, int size, char *field, int N,...);
+void warn_scan_nchar (Header *header, int size, char *field, int N, void *var);
+
+void clean_spaces (char *line);
+
+/* where is this defined ?? */
+char *basename (char *);
Index: /branches/eam_branch_20080223/Ohana/src/imregister/include/mosaics.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/include/mosaics.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/include/mosaics.h	(revision 16632)
@@ -0,0 +1,63 @@
+
+MosaicLayout *CreateCFH12K () {
+
+  MosaicLayout *layout;
+
+  ALLOCATE (layout, MosaicLayout, 1);
+
+  layout[0].center.Nccd = 4;
+  ALLOCATE (layout[0].center.ccd, int, layout[0].center.Nccd);
+  layout[0].center.ccd[0] = 2;
+  layout[0].center.ccd[1] = 3;
+  layout[0].center.ccd[2] = 8;
+  layout[0].center.ccd[3] = 9;
+
+  layout[0].outer.Nccd = 8;
+  ALLOCATE (layout[0].outer.ccd, int, layout[0].outer.Nccd);
+  layout[0].outer.ccd[0] = 0;
+  layout[0].outer.ccd[1] = 1;
+  layout[0].outer.ccd[2] = 4;
+  layout[0].outer.ccd[3] = 5;
+  layout[0].outer.ccd[4] = 6;
+  layout[0].outer.ccd[5] = 7;
+  layout[0].outer.ccd[6] = 10;
+  layout[0].outer.ccd[7] = 11;
+
+  layout[0].top.Nccd = 6;
+  ALLOCATE (layout[0].top.ccd, int, layout[0].top.Nccd);
+  layout[0].top.ccd[0] = 0;
+  layout[0].top.ccd[1] = 1;
+  layout[0].top.ccd[2] = 2;
+  layout[0].top.ccd[3] = 3;
+  layout[0].top.ccd[4] = 4;
+  layout[0].top.ccd[5] = 5;
+
+  layout[0].bottom.Nccd = 6;
+  ALLOCATE (layout[0].bottom.ccd, int, layout[0].bottom.Nccd);
+  layout[0].bottom.ccd[0] = 6;
+  layout[0].bottom.ccd[1] = 7;
+  layout[0].bottom.ccd[2] = 8;
+  layout[0].bottom.ccd[3] = 9;
+  layout[0].bottom.ccd[4] = 10;
+  layout[0].bottom.ccd[5] = 11;
+
+  layout[0].left.Nccd = 6;
+  ALLOCATE (layout[0].left.ccd, int, layout[0].left.Nccd);
+  layout[0].left.ccd[0] = 0;
+  layout[0].left.ccd[1] = 1;
+  layout[0].left.ccd[2] = 2;
+  layout[0].left.ccd[3] = 6;
+  layout[0].left.ccd[4] = 7;
+  layout[0].left.ccd[5] = 8;
+
+  layout[0].right.Nccd = 6;
+  ALLOCATE (layout[0].right.ccd, int, layout[0].right.Nccd);
+  layout[0].right.ccd[0] = 3;
+  layout[0].right.ccd[1] = 4;
+  layout[0].right.ccd[2] = 5;
+  layout[0].right.ccd[3] = 9;
+  layout[0].right.ccd[4] = 10;
+  layout[0].right.ccd[5] = 11;
+
+  return (layout);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/include/photreg.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/include/photreg.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/include/photreg.h	(revision 16632)
@@ -0,0 +1,45 @@
+# include <signal.h>
+
+struct {
+  int Ntimes;         time_t *tstart, *tstop;
+  int PhotCodeSelect; int photcode;
+  int LabelSelect;    char *Label;
+} criteria;
+
+struct {
+  int delete;
+  int modify;
+
+  int HST;
+  int verbose;
+  int convert;
+  char *table;
+  char *bintable;
+  char *cadctable;
+
+  int equiv;
+  int offset;
+  char *db;
+  int photcodenames;
+} output;
+
+enum {UNLOCK, LOCK, IGNORE};
+
+int args (int argc, char **argv);
+int regargs (int argc, char **argv, PhotPars *);
+
+void DeleteSubset (FITS_DB *db, PhotPars *photpars, int Nphotpars, int *match, int Nmatch);
+int *match_criteria (PhotPars *photpars, int Nphotpars, int *Nmatch);
+
+void OutputSubset (PhotPars *photpars, int Nphotpars, int *match, int Nmatch);
+
+void DumpFitsBintable (char *filename, PhotPars *image, int *match, int Nmatch);
+void DumpFitsTable (char *filename, PhotPars *image, int *match, int Nmatch);
+int PrintSubset (PhotPars *image, int *match, int Nmatch);
+
+void set_timezone (double dt);
+void getImageData (char *Image, char *ImageCCD, char *ImageMode);
+int escape (int mode, char *message);
+
+PhotPars *PhotParsOld_to_PhotPars (PhotParsOld *input, int Nphotpars);
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/include/spreg.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/include/spreg.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/include/spreg.h	(revision 16632)
@@ -0,0 +1,105 @@
+# include <signal.h>
+
+enum {
+  SPMODE_UKN,				/* unknown mode */
+  SPMODE_PHU,				/* one spectrum, primary header unit */
+  SPMODE_MEF,				/* spectrum group, extensions */
+  SPMODE_EXT,				/* one of a spectrum group, extension */
+  SPMODE_N
+};
+
+enum {
+  SPSTATE_UKN,				/* unknown state */
+  SPSTATE_RAW,				/* raw image counts */
+  SPSTATE_FLT,				/* flattened image counts */
+  SPSTATE_CLN,				/* clean extraction */
+  SPSTATE_WAV,				/* wavelength calibrated */
+  SPSTATE_FLX,				/* flux calibrated (implies WAV) */
+  SPSTATE_N
+};
+
+struct {
+  int Ntimes;           time_t *tstart, *tstop;
+  int ModeSelect;       int Mode;
+  int StateSelect;      int State;
+  int ExptimeSelect;    float Exptime;
+  int FilenameSelect;   char *Filename;
+  int ObjectSelect;     char *Object;
+  int TelescopeSelect;  char *Telescope;
+  int InstrumentSelect; char *Instrument;
+  int MatchNumber;
+} criteria;
+
+struct {
+  int delete;
+  int modify;
+
+  int unique;
+  int modify_path;
+  char *oldpath, *newpath;
+
+  int modify_mode, mode;
+  int modify_state, state;
+
+  int HST;
+  int verbose;
+  char *table;
+  char *bintable;
+} output;
+
+typedef struct {
+  int *ccd;
+  int Nccd;
+  char name[64];
+} MosaicRegion;
+
+typedef struct {
+  MosaicRegion center;
+  MosaicRegion outer;
+  MosaicRegion top;
+  MosaicRegion bottom;
+  MosaicRegion left;
+  MosaicRegion right;
+} MosaicLayout;
+
+enum {UNLOCK, LOCK, IGNORE};
+
+int SingleIsSplit;
+int NeedType;
+int NoReg;
+int IMSORT;
+int CLIENT;
+char *PIDFILE;
+int LOOP_DELAY;
+int DUMP;
+
+char SpectrumDB[64];
+char ObjectKeyword[64];
+char TelescopeKeyword[64];
+
+
+int args (int argc, char **argv);
+int *match_criteria (Spectrum *spectrum, int Nspectrum, int *Nmatch);
+int *unique_entries (Spectrum *spectrum, int Nspectrum, int *subset, int *Nmatch);
+
+void ModifySubset (FITS_DB *db, Spectrum *spectrum, int Nspectrum, int *match, int Nmatch);
+void DeleteSubset (FITS_DB *db, Spectrum *spectrum, int Nspectrum, int *match, int Nmatch);
+void OutputSubset (Spectrum *spectrum, int Nspectrum, int *match, int Nmatch);
+
+void SetOutputMode (char *mode);
+void DumpFitsBintable (char *filename, Spectrum *spectrum, int *match, int Nmatch);
+void DumpFitsTable (char *filename, Spectrum *spectrum, int *match, int Nmatch);
+int PrintSubset (Spectrum *spectrum, int *match, int Nmatch);
+int dump_data (Spectrum *spectrum, int Nspectrum);
+
+Spectrum *spinfo (char *filename);
+int *match_spectrums (Spectrum *subset, int Nsubset, int *Nmatch);
+int SubmitSpectrums (Spectrum *spectrum);
+void set_timezone (double dt);
+
+void showinfo (Spectrum *spec);
+int escape (int mode, char *message);
+int set_spectra (Spectrum *new, int Nnew);
+Spectrum *get_spectra (int *N);
+
+void ConfigInitSpec (int *argc, char **argv);
Index: /branches/eam_branch_20080223/Ohana/src/imregister/photreg/args.photreg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/photreg/args.photreg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/photreg/args.photreg.c	(revision 16632)
@@ -0,0 +1,137 @@
+# include "imregister.h"
+# include "photreg.h"
+
+void usage ();
+
+int regargs (int argc, char **argv, PhotPars *newdata) {
+
+  int *list, Nlist;
+  int N, Ntimes;
+  time_t *tstart, *tstop;
+  PhotCode *photcode, *depcode;
+
+  ConfigInit (&argc, argv);
+
+  photcode = NULL;
+  output.modify = TRUE;
+  bzero (newdata, sizeof(PhotPars));
+
+  if (get_argument (argc, argv, "-h")) usage ();
+  if (get_argument (argc, argv, "--help")) usage ();
+
+  /* set the required database */
+  output.db = strcreate ("phot");
+  if ((N = get_argument (argc, argv, "-trans"))) {
+    remove_argument (N, &argc, argv);
+    output.db = strcreate ("trans");
+  }
+
+  /*** optional fields ***/
+  strcpy (newdata[0].label, "elixir");
+  if ((N = get_argument (argc, argv, "-label"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (newdata[0].label, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  newdata[0].Nmeas = 1;
+  if ((N = get_argument (argc, argv, "-Nmeas"))) {
+    remove_argument (N, &argc, argv);
+    newdata[0].Nmeas = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  newdata[0].Ntime = 1;
+  if ((N = get_argument (argc, argv, "-Ntime"))) {
+    remove_argument (N, &argc, argv);
+    newdata[0].Ntime = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.offset = FALSE;
+  if ((N = get_argument (argc, argv, "-offset"))) {
+    remove_argument (N, &argc, argv);
+    output.offset = TRUE;
+  }
+
+  /**** required arguments ****/
+  if (!get_trange_arguments (&argc, argv, &tstart, &tstop, &Ntimes)) usage ();
+  if (Ntimes != 1) usage ();
+  newdata[0].tstart = tstart[0];
+  newdata[0].tstop = tstop[0];
+
+  if (!get_argument (argc, argv, "-zp")) goto required;
+  if (!get_argument (argc, argv, "-dzp")) goto required;
+  if (!get_argument (argc, argv, "-photcode")) goto required;
+
+  /* observed zero point */
+  if ((N = get_argument (argc, argv, "-zp"))) {
+    remove_argument (N, &argc, argv);
+    newdata[0].ZP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  } 
+
+  /* error on observed zero point */
+  if ((N = get_argument (argc, argv, "-dzp"))) {
+    remove_argument (N, &argc, argv);
+    newdata[0].dZP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* photcode system */
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    if ((photcode = GetPhotcodebyName (argv[N])) == NULL) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  /* remainding newdata values can be set once photcode is known 
+     be careful about consistency for offset definition:
+     dM == ZPi - ZPo  (ZPo = nominal zero point, ZPi = specific observed zero point)
+     ie, clouds = -dM (ZPi < ZPo)
+  */
+  
+  /* find first (!) dep photcode which is equivalent to this code */
+  list = GetPhotcodeEquivList (photcode[0].code, &Nlist);
+  depcode = GetPhotcodebyCode (list[0]);
+
+  newdata[0].photcode = photcode[0].code;
+  newdata[0].refcode  = photcode[0].equiv;
+  newdata[0].X        = photcode[0].X[0];
+  newdata[0].c1       = photcode[0].c1;
+  newdata[0].c2       = photcode[0].c2;
+  
+  newdata[0].K        = depcode[0].K;
+  newdata[0].ZPo      = 0.001*photcode[0].C + 0.001*depcode[0].C;
+  if (output.offset) newdata[0].ZP += newdata[0].ZPo;
+  return (TRUE);
+
+required:
+  fprintf (stderr, "missing required fields\n");
+  usage ();
+  return (FALSE);
+}
+
+/* differences between phot.db & trans.db:
+
+   Ntime : photreg = 1 : transreg = N
+   dBFile: phot.db     : trans.db
+   ASCII EXTNAME: IMAGE_ZPTS : SUMMARY_ZPTS
+   BINARY EXTNAME: ZERO_POINTS_3.0 : TRANS_POINTS_3.0
+   
+   photreg -photcode B -zp 26.1 -dzp 0.02 -date 2003/1/1,10:00:00 -Nmeas 5 -Ntime 1 -db trans
+   photreg -photcode B -zp 26.1 -dzp 0.02 -date 2003/1/1,10:00:00 -Nmeas 5 -Ntime 1 -db trans
+
+   photsearch -db trans
+   photsearch -db phot
+   
+*/
+
+void usage () {  
+  fprintf (stderr, "USAGE: photreg (-zp zp) (-dzp dzp) (-trange start range|end) (-photcode code)\n");
+  fprintf (stderr, "       [-label label] [-offset] [-Nmeas N] [-Ntime N] [-db trans]\n");
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/photreg/args.photsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/photreg/args.photsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/photreg/args.photsearch.c	(revision 16632)
@@ -0,0 +1,126 @@
+# include "imregister.h"
+# include "photreg.h"
+
+int args (int argc, char **argv) {
+
+  int N, equiv;
+
+  ConfigInit (&argc, argv);
+  ConfigCamera ();
+  ConfigFilter ();
+
+  criteria.Ntimes = 0;
+  if (!get_trange_arguments (&argc, argv, &criteria.tstart, &criteria.tstop, &criteria.Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  criteria.PhotCodeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    if ((criteria.photcode = GetPhotcodeCodebyName (argv[N])) == 0) {
+      fprintf (stderr, "ERROR: photcode not found in table\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    criteria.PhotCodeSelect = TRUE;
+  }
+
+  criteria.LabelSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-label"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Label = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.LabelSelect = TRUE;
+  }
+
+  output.delete = FALSE;
+  if ((N = get_argument (argc, argv, "-delete"))) {
+    remove_argument (N, &argc, argv);
+    output.delete = TRUE;
+  }
+
+  output.equiv = FALSE;
+  if ((N = get_argument (argc, argv, "-equiv"))) {
+    remove_argument (N, &argc, argv);
+    output.equiv = TRUE;
+  }
+
+  output.offset = FALSE;
+  if ((N = get_argument (argc, argv, "-offset"))) {
+    remove_argument (N, &argc, argv);
+    output.offset = TRUE;
+  }
+
+  output.table = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-table"))) {
+    remove_argument (N, &argc, argv);
+    output.table = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.bintable = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-bintable"))) {
+    remove_argument (N, &argc, argv);
+    output.bintable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.verbose = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    output.verbose = TRUE;
+  }
+
+  output.photcodenames = TRUE;
+  if ((N = get_argument (argc, argv, "-photcodes"))) {
+    remove_argument (N, &argc, argv);
+    output.photcodenames = FALSE;
+  }
+
+  output.convert = FALSE;
+  if ((N = get_argument (argc, argv, "-convert"))) {
+    remove_argument (N, &argc, argv);
+    output.convert = TRUE;
+    if (output.delete || output.modify) {
+      fprintf (stderr, "can't change old format table\n");
+      exit (1);
+    }
+  }
+
+  if ((N = get_argument (argc, argv, "-image"))) {
+    remove_argument (N, &argc, argv);
+    if (argc < N + 3) {
+      fprintf (stderr, "missing arguments to -image\n");
+      exit (1);
+    }
+    getImageData (argv[N], argv[N+1], argv[N+2]);
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+    remove_argument (N, &argc, argv);
+  }
+
+  output.db = strcreate ("phot");
+  if ((N = get_argument (argc, argv, "-trans"))) {
+    remove_argument (N, &argc, argv);
+    output.db = strcreate ("trans");
+  }
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: photsearch [config ops] [-v] [-version]\n");
+    fprintf (stderr, "       [-trange start stop/range] [-photcode code]\n");
+    fprintf (stderr, "       [-label label] [-delete]\n");
+    fprintf (stderr, "       [-table table.fits] [-bintable bintable.fits]\n");
+    exit (1);
+  }
+ 
+  /* set up photcode information */
+  if (criteria.PhotCodeSelect && output.equiv) {
+    if (!(equiv = GetPhotcodeEquivCodebyCode (criteria.photcode))) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (1);
+    }
+    criteria.photcode = equiv;
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/photreg/convert.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/photreg/convert.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/photreg/convert.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "imregister.h"
+# include "photreg.h"
+
+PhotPars *PhotParsOld_to_PhotPars (PhotParsOld *input, int Nphotpars) {
+
+  int i;
+  PhotPars *output;
+
+  ALLOCATE (output, PhotPars, Nphotpars);
+
+  for (i = 0; i < Nphotpars; i++) {
+    output[i].ZP       = input[i].ZP;
+    output[i].ZPo      = input[i].ZPo;
+    output[i].dZP      = input[i].dZP;
+    output[i].K        = input[i].K;
+    output[i].X        = input[i].X;
+    output[i].tstart   = input[i].tstart;
+    output[i].tstop    = input[i].tstop;
+    output[i].c1       = input[i].c1;
+    output[i].c2       = input[i].c2;
+    output[i].photcode = input[i].photcode;
+    strcpy (output[i].label, input[i].label);
+    output[i].Nmeas = 0;
+    output[i].Ntime = 0;
+  }
+  return (output);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/photreg/delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/photreg/delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/photreg/delete.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "imregister.h"
+# include "photreg.h"
+
+void DeleteSubset (FITS_DB *db, PhotPars *photdata, int Nphotdata, int *match, int Nmatch) {
+
+  int i, j;
+  int *keep, Ndel, Nsubset;
+  PhotPars *subset;
+
+  ALLOCATE (keep, int, MAX (Nphotdata, 1));
+  for (i = 0; i < Nphotdata; i++) keep[i] = TRUE;
+  fprintf (stderr, "total of %d photdata\n", Nphotdata);
+
+  Ndel = 0;
+  for (i = 0; i < Nmatch; i++) {
+    j = match[i];
+    if (j == -1) continue;
+    keep[j] = FALSE;
+    Ndel ++;
+  }
+  fprintf (stderr, "delete %d photdata\n", Ndel);
+
+  if (Ndel == 0) { 
+    fprintf (stderr, "SUCCESS\n");
+    gfits_db_close (db);
+    gfits_db_free (db);
+    exit (0);
+  }
+
+  /* create new data list */
+  Nsubset = Nphotdata - Ndel;
+  ALLOCATE (subset, PhotPars, MAX (1, Nsubset));
+  fprintf (stderr, "keeping %d photdata\n", Nsubset);
+  for (j = i = 0; i < Nphotdata; i++) {
+    if (!keep[i]) continue;
+    subset[j] = photdata[i];
+    j++;
+  }
+
+  gfits_table_set_PhotPars (&db[0].ftable, subset, Nsubset);
+  gfits_db_save (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/photreg/getImageData.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/photreg/getImageData.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/photreg/getImageData.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "imregister.h"
+# include "photreg.h"
+
+void getImageData (char *Image, char *ImageCCD, char *ImageMode) {
+
+  Header header;
+  char detector[64], filter[64], photcode[64];
+  int i, ccd, Nfilter;
+  
+  /* extract time & photcode from header */
+
+  /* load options from the image header */
+  if (!gfits_read_header (Image, &header)) {
+    if (output.verbose) fprintf (stderr, "ERR: trouble reading image header\n");
+    exit (1);
+  }
+
+  /* get time from image header */
+  ALLOCATE (criteria.tstart, time_t, 1);
+  ALLOCATE (criteria.tstart, time_t, 1);
+  criteria.tstart[0] = parse_time (&header);
+  criteria.tstop[0] = criteria.tstart[0] + 1;
+  criteria.Ntimes = 1;
+
+  /** determine photcode from header **/
+  /* get camera */
+  gfits_scan (&header, CameraKeyword, "%s", 1, detector);
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(detector); i++) { if (isspace (detector[i])) detector[i] = '.'; }
+    
+  /* get filter */
+  Nfilter = FILTER_NONE;
+  gfits_scan (&header, FilterKeyword,   "%s", 1, filter);
+  for (i = 0; i < strlen (filter); i++) { if (isspace (filter[i])) filter[i] = '.'; }
+  for (i = 0; (i < NFILTER) && (Nfilter == FILTER_NONE); i++) {
+    if (!strcasecmp (filter, filtername[i])) {
+      Nfilter = filternum[i];
+    }
+  }      
+  if (Nfilter == FILTER_NONE) {
+    fprintf (stderr, "ERR: invalid filter %s\n", filter);
+    exit (1);
+  }
+  strcpy (filter, filtername[Nfilter]);
+
+  /* get ccd number */
+  if (!strcasecmp (ImageCCD, "phu")) {
+    ccd = 0;
+  } else {
+   if (!strcasecmp (ImageMode, "mef")) {
+     ccd = MatchCCDName (ImageCCD);
+   } else {
+     ccd = -1;
+     gfits_scan (&header, CCDnumKeyword,  "%d", 1, &ccd);
+   }  
+   if (ccd == -1) {
+     fprintf (stderr, "ERR: invalid ccd %s %s\n", ImageCCD, ImageMode);
+     exit (1);
+   }
+  }
+
+  sprintf (photcode, "%s.%s.%02d", detector, filter, ccd);
+  if (!(criteria.photcode = GetPhotcodeCodebyName (photcode))) {
+    fprintf (stderr, "ERR: photcode not found table\n");
+    exit (1);
+  }
+  criteria.PhotCodeSelect = TRUE;
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/photreg/match.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/photreg/match.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/photreg/match.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "imregister.h"
+# include "photreg.h"
+
+int *match_criteria (PhotPars *photdata, int Nphotdata, int *Nmatch) {
+
+  int i, j;
+  int N, NMATCH;
+  int *match;
+  int reject;
+
+  /* create selection index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  /* find entries that matches criteria */
+  for (i = 0; i < Nphotdata; i++) {
+    for (j = 0, reject = TRUE; reject && (j < criteria.Ntimes); j++) {
+      reject = (photdata[i].tstop < criteria.tstart[j]) || (photdata[i].tstart > criteria.tstop[j]);
+    }
+    if (criteria.Ntimes && reject) continue;
+    if (criteria.PhotCodeSelect && (photdata[i].photcode != criteria.photcode)) continue;
+    if (criteria.LabelSelect && strcmp (photdata[i].label, criteria.Label)) continue;
+
+    match[N] = i;
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+  }
+  *Nmatch = N;
+  return (match);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/photreg/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/photreg/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/photreg/output.c	(revision 16632)
@@ -0,0 +1,240 @@
+# include "imregister.h"
+# include "photreg.h"
+
+static char PhotError[] = "unknown";
+static char PhotNA[] = "unknown";
+
+/* given a subset list, write out the selected images, if desired */
+void OutputSubset (PhotPars *photdata, int Nphotdata, int *match, int Nmatch) {
+
+  if (output.table != (char *) NULL) {
+    DumpFitsTable (output.table, photdata, match, Nmatch);
+  } 
+
+  if (output.bintable != (char *) NULL) {
+    DumpFitsBintable (output.bintable, photdata, match, Nmatch);
+  } 
+
+  PrintSubset (photdata, match, Nmatch);
+  if (output.verbose) fprintf (stderr, "SUCCESS\n");
+
+  exit (0);
+}
+
+/* write out complete binary FITS table in format of db */
+void DumpFitsBintable (char *filename, PhotPars *photdata, int *match, int Nmatch) {
+
+  int i, j;
+  FILE *f;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  PhotPars *subset;
+
+  /* extract subset of input data */
+  ALLOCATE (subset, PhotPars, MAX (1, Nmatch));
+  for (i = 0; i < Nmatch; i++){
+    j = match[i];
+    memcpy (&subset[i], &photdata[j], sizeof (PhotPars));
+  }
+
+  /* open file for output */
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", filename);
+    exit (1);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_PhotPars (&ftable, subset, Nmatch);
+
+  /* EXTNAME is set to ZERO_POINTS_3.0 by default */
+  if (!strcmp (output.db, "trans")) {
+    gfits_modify (&theader, "EXTNAME", "%s", 1, "TRANS_POINTS_3.0");
+  }
+
+  gfits_write_header  (filename, &header);
+  gfits_write_matrix  (filename, &matrix);
+  gfits_write_Theader (filename, &theader);
+  gfits_write_table   (filename, &ftable);
+  fclose (f);
+  exit (0);
+}
+
+/** add ASCII table to autocode? **/
+void DumpFitsTable (char *filename, PhotPars *photdata, int *index, int Nkeep) {
+  
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  PhotPars *newdata;
+  FILE *f;
+  char *startstr, *stopstr, *datestr, *line;
+  char *c1, *c2, *code, *photsys, *extname;
+  int i;
+  time_t tsecond;
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* create table header */
+  if (!strcmp (output.db, "phot")) {
+    extname = strcreate ("IMAGE_ZPTS");
+  } else {
+    extname = strcreate ("SUMMARY_ZPTS");
+  }
+  gfits_create_table_header (&theader, "TABLE", extname);
+    
+  /* add current date/time to header */
+  ohana_str_to_time ("now", &tsecond);
+  datestr = ohana_sec_to_date ((unsigned int) tsecond);
+  gfits_modify (&header,  "DATE", "%s", 1, datestr);
+  gfits_modify (&theader, "DATE", "%s", 1, datestr);
+  free (datestr);
+     
+  /* define table layout */
+  gfits_define_table_column (&theader, "F8.4", "ZP_OBS",       "measured zero point",       "mag");
+  gfits_define_table_column (&theader, "F8.4", "ZP_REF",       "nominal zero point",        "mag");
+  gfits_define_table_column (&theader, "F7.4", "ZP_ERR",       "error on zero point",       "mag");
+  gfits_define_table_column (&theader, "F7.3", "C_AIRMASS",    "airmass coeff",             "mag per airmass"); 
+  gfits_define_table_column (&theader, "F6.3", "C_COLOR",      "color coeff",               "mag per mag");
+  gfits_define_table_column (&theader, "A20",  "START_TIME",   "start time of measurement", "yyyy/mm/dd,hh:mm:ss");
+  gfits_define_table_column (&theader, "A20",  "STOP_TIME",    "stop time of measurement",  "yyyy/mm/dd,hh:mm:ss");
+  gfits_define_table_column (&theader, "A12",  "C1_NAME",      "filter 1 for color",        "");
+  gfits_define_table_column (&theader, "A12",  "C2_NAME",      "filter 2 for color",        "");
+  gfits_define_table_column (&theader, "I6",   "NSTARS",       "number of stars used",      "");
+  gfits_define_table_column (&theader, "I6",   "NTIMES",       "number of unique images",   "");
+  gfits_define_table_column (&theader, "A12",  "INT_PHOT_SYS", "internal photom system",    "");
+  gfits_define_table_column (&theader, "A12",  "REF_PHOT_SYS", "reference photom system",   "");
+  gfits_define_table_column (&theader, "A70",  "LABEL",        "data label",                "");
+  
+  /* define TNULL, TNVAL values */
+  gfits_modify (&theader, "TNULL1",  "%s", 1, "NaN");   /* ZP_OBS     */
+  gfits_modify (&theader, "TNULL2",  "%s", 1, "NaN");   /* ZP_REF     */
+  gfits_modify (&theader, "TNULL3",  "%s", 1, "NaN");   /* ZP_ERR     */
+  gfits_modify (&theader, "TNULL4",  "%s", 1, "NaN");   /* C_AIRMASS  */
+  gfits_modify (&theader, "TNULL5",  "%s", 1, "NaN");   /* C_COLOR    */
+  gfits_modify (&theader, "TNULL6",  "%s", 1, "NULL");  /* START_TIME */
+  gfits_modify (&theader, "TNULL7",  "%s", 1, "NULL");  /* STOP_TIME  */
+  gfits_modify (&theader, "TNULL8",  "%s", 1, "NULL");  /* C1_NAME    */
+  gfits_modify (&theader, "TNULL9",  "%s", 1, "NULL");  /* C2_NAME    */
+  gfits_modify (&theader, "TNULL10", "%s", 1, "NULL");  /* NSTARS     */
+  gfits_modify (&theader, "TNULL11", "%s", 1, "NULL");  /* NTIMES     */
+  gfits_modify (&theader, "TNULL12", "%s", 1, "NULL");  /* INT_PHOT_SYS */
+  gfits_modify (&theader, "TNULL13", "%s", 1, "NULL");  /* REF_PHOT_SYS */
+  gfits_modify (&theader, "TNULL14", "%s", 1, "NULL");  /* LABEL      */
+
+  gfits_modify (&theader, "TNVAL1",  "%s", 1, "Inf");   /* ZP_OBS       */
+  gfits_modify (&theader, "TNVAL2",  "%s", 1, "Inf");   /* ZP_REF       */
+  gfits_modify (&theader, "TNVAL3",  "%s", 1, "Inf");   /* ZP_ERR       */
+  gfits_modify (&theader, "TNVAL4",  "%s", 1, "Inf");   /* C_AIRMASS    */
+  gfits_modify (&theader, "TNVAL5",  "%s", 1, "Inf");   /* C_COLOR      */
+  gfits_modify (&theader, "TNVAL6",  "%s", 1, "NA");    /* START_TIME   */
+  gfits_modify (&theader, "TNVAL7",  "%s", 1, "NA");    /* STOP_TIME    */
+  gfits_modify (&theader, "TNVAL8",  "%s", 1, "NA");    /* C1_NAME      */
+  gfits_modify (&theader, "TNVAL9",  "%s", 1, "NA");    /* C2_NAME      */
+  gfits_modify (&theader, "TNVAL10", "%s", 1, "NA");    /* NSTARS       */
+  gfits_modify (&theader, "TNVAL11", "%s", 1, "NA");    /* NTIMES       */
+  gfits_modify (&theader, "TNVAL12", "%s", 1, "NA");    /* INT_PHOT_SYS */
+  gfits_modify (&theader, "TNVAL13", "%s", 1, "NA");    /* REF_PHOT_SYS */
+  gfits_modify (&theader, "TNVAL14", "%s", 1, "NA");    /* LABEL        */
+
+  /* create table, add data values */
+  gfits_create_table (&theader, &table);
+  
+  /* add data to table */
+  for (i = 0; i < Nkeep; i++) {
+    newdata = &photdata[index[i]];
+    startstr = ohana_sec_to_date (newdata[0].tstart);
+    stopstr = ohana_sec_to_date (newdata[0].tstop);
+    code    = GetPhotcodeNamebyCode (newdata[0].photcode);
+    photsys = GetPhotcodeNamebyCode (newdata[0].refcode);
+    c1      = GetPhotcodeNamebyCode (newdata[0].c1);
+    c2      = GetPhotcodeNamebyCode (newdata[0].c2);
+    if (code    == (char *) NULL) code    = PhotNA;
+    if (photsys == (char *) NULL) photsys = PhotNA;
+    if (c1      == (char *) NULL) c1      = PhotNA;
+    if (c2      == (char *) NULL) c2      = PhotNA;
+
+    line = gfits_table_print (&table, newdata[0].ZP, newdata[0].ZPo, newdata[0].dZP, 
+	      newdata[0].K, newdata[0].X, startstr, stopstr,
+	      c1, c2, newdata[0].Nmeas, newdata[0].Ntime, code, photsys, newdata[0].label);
+    if (!gfits_add_rows (&table, line, 1, strlen(line))) {
+      fprintf (stderr, "error writing dataline");
+      exit (1);
+    }
+
+    free (line);
+    free (startstr);
+    free (stopstr);
+  }
+ 
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Failure writing fits table\n");
+    exit (1);
+  }
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &table);
+  fclose (f);
+  exit (0);
+}
+
+/* Select, TimeMode are global */
+int PrintSubset (PhotPars *photdata, int *match, int Nmatch) {
+  
+  int i, j;
+  char *photstr, *timestr, *c1, *c2, *refcode;
+  
+  /* print the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+    
+    i = match[j];
+    
+    /* convert UNIX time to Elixir-style date string */
+    timestr = ohana_sec_to_date (photdata[i].tstart);
+    
+    if (output.photcodenames) {
+      /* convert photcode to filter name */
+      photstr = GetPhotcodeNamebyCode (photdata[i].photcode);
+      refcode = GetPhotcodeNamebyCode (photdata[i].refcode);
+      c1      = GetPhotcodeNamebyCode (photdata[i].c1);
+      c2      = GetPhotcodeNamebyCode (photdata[i].c2);
+
+      if (photstr == NULL) photstr = PhotError;
+      if (refcode == NULL) refcode = PhotError;
+      if (c1      == NULL) c1      = PhotError;
+      if (c2      == NULL) c2      = PhotError;
+      
+      fprintf (stdout, "%s %s  %7.4f %7.4f %7.4f  %3d %3d  %7.4f %7.4f  %s  %s %s %s\n", 
+	       photstr, timestr, photdata[i].ZP, photdata[i].ZPo, photdata[i].dZP, photdata[i].Nmeas, photdata[i].Ntime, 
+	       photdata[i].X, photdata[i].K, refcode, c1, c2, photdata[i].label); 
+    } else {
+      fprintf (stdout, "%4d %s  %7.4f %7.4f %7.4f  %3d %3d  %7.4f %7.4f  %4d %4d %4d  %s\n", 
+	       photdata[i].photcode, timestr, photdata[i].ZP, photdata[i].ZPo, photdata[i].dZP, photdata[i].Nmeas, 
+	       photdata[i].Ntime, photdata[i].X, photdata[i].K, 
+	       photdata[i].refcode, photdata[i].c1, photdata[i].c2, photdata[i].label); 
+    }
+      
+    free (timestr);
+  }
+  return (TRUE);
+}
+
+/**** the pre-autocode implementation of this program failed to byte-swap refcode!
+      any tables from before the new implementation have to be treated carefully
+****/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/ConfigInit.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int success;
+
+void ConfigInitSpec (int *argc, char **argv) {
+
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+
+  success = TRUE;
+
+  WarnConfig (config, "SPECTRUM_DATABASE",       "%s", 0, SpectrumDB);
+
+  /* keyword abstractions for parse_time */	   
+  WarnConfig (config, "DATE-KEYWORD",                "%s", 0, DateKeyword);
+  WarnConfig (config, "DATE-MODE",                   "%s", 0, DateMode);
+  WarnConfig (config, "UT-KEYWORD",                  "%s", 0, UTKeyword);
+  WarnConfig (config, "MJD-KEYWORD",                 "%s", 0, MJDKeyword);
+  WarnConfig (config, "JD-KEYWORD",                  "%s", 0, JDKeyword);
+						   
+  /* keyword abstractions for spinfo */		   
+  WarnConfig (config, "EXPTIME-KEYWORD",             "%s", 0, ExptimeKeyword);
+  WarnConfig (config, "AIRMASS-KEYWORD",             "%s", 0, AirmassKeyword);
+  WarnConfig (config, "CAMERA-KEYWORD",              "%s", 0, CameraKeyword);
+  WarnConfig (config, "OBJECT-KEYWORD",              "%s", 0, ObjectKeyword);
+  WarnConfig (config, "TELESCOPE-KEYWORD",           "%s", 0, TelescopeKeyword);
+
+  /* semi-optional values */
+  ScanConfig (config, "RA-DDD-KEYWORD",              "%s", 0, RADecDegKeyword);
+  ScanConfig (config, "DEC-DDD-KEYWORD",             "%s", 0, DECDecDegKeyword);
+  ScanConfig (config, "RA-HMS-KEYWORD",              "%s", 0, RASexigKeyword);
+  ScanConfig (config, "DEC-DMS-KEYWORD",             "%s", 0, DECSexigKeyword);
+  if (!RADecDegKeyword[0] & !DECDecDegKeyword[0] && !RASexigKeyword[0] && !DECSexigKeyword[0]) {
+    fprintf (stderr, "missing astrometry configuration information\n");
+    success = FALSE;
+  }
+
+  if (! success) {
+    fprintf (stderr, "ERROR: problem with elixir configuration\n");
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/args.spregister.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/args.spregister.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/args.spregister.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  ConfigInitSpec (&argc, argv); /* load elixir config data */
+
+  NoReg = FALSE;
+  if ((N = get_argument (argc, argv, "-noreg"))) {
+    remove_argument (N, &argc, argv);
+    NoReg = TRUE;
+  }
+
+  DUMP = FALSE;
+  if ((N = get_argument (argc, argv, "-dump"))) {
+    remove_argument (N, &argc, argv);
+    DUMP = TRUE;
+  }
+
+  output.verbose = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    output.verbose = TRUE;
+  }
+
+  NeedType = FALSE;
+  if ((N = get_argument (argc, argv, "-needtype"))) {
+    remove_argument (N, &argc, argv);
+    NeedType = TRUE;
+  }
+
+  /* all imregister programs are implicitly modifying the db */
+  output.modify = TRUE;
+  IMSORT = FALSE;
+
+  if (argc != 2) {
+    fprintf (stderr, "ERROR: Usage: spregister (filename) [-noreg]\n");
+    exit (1);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/args.spsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/args.spsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/args.spsearch.c	(revision 16632)
@@ -0,0 +1,176 @@
+# include "imregister.h" 
+# include "spreg.h"
+
+/* criteria struct is global */
+int args (int argc, char **argv) {
+
+  double dt;
+  int N;
+
+  ConfigInitSpec (&argc, argv); /* load elixir config data */
+
+  /* set timezone (set static in misc.c) */
+  if ((N = get_argument (argc, argv, "-tz"))) {
+    remove_argument (N, &argc, argv);
+    dt = atof (argv[N]);
+    set_timezone (dt);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* define time range */
+  criteria.Ntimes = 0;
+  if (!get_trange_arguments (&argc, argv, &criteria.tstart, &criteria.tstop, &criteria.Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  /* exposure time */
+  criteria.ExptimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-etime"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Exptime = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.ExptimeSelect = TRUE;
+  }
+ 
+  /* image type (dark, flat, bias, etc) */
+  criteria.StateSelect = FALSE;
+
+ 
+  /* image mode (split, mef, single) */
+  criteria.ModeSelect = FALSE;
+  /*
+  criteria.Mode = M_UNDEF;
+  if ((N = get_argument (argc, argv, "-mode"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Mode = get_image_mode (argv[N]);
+    if (criteria.Mode == M_UNDEF) {
+      fprintf (stderr, "ERROR: invalid image mode %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    criteria.ModeSelect = TRUE;
+  }
+  */
+
+  /* string in image name */
+  criteria.FilenameSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-filename"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Filename = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.FilenameSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.ObjectSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-object"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Object = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.ObjectSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.TelescopeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-tel"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Telescope = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.TelescopeSelect = TRUE;
+  }
+
+  /* string in image name */
+  criteria.InstrumentSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-inst"))) {
+    remove_argument (N, &argc, argv);
+    criteria.Instrument = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    criteria.InstrumentSelect = TRUE;
+  }
+
+  /*** command-line options which modify the output list */
+  if ((N = get_argument (argc, argv, "-treg"))) {
+    remove_argument (N, &argc, argv);
+    SetOutputMode ("RegTimeMode");
+  }
+  output.table = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-table"))) {
+    remove_argument (N, &argc, argv);
+    output.table = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  output.bintable = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-bintable"))) {
+    remove_argument (N, &argc, argv);
+    output.bintable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /*** command-line options which modify behavior (delete, modify, newpath, mef2split split2mef */
+  output.delete = FALSE;
+  output.modify = FALSE;
+  output.modify_path = FALSE; 
+  output.unique = FALSE;
+
+  if ((N = get_argument (argc, argv, "-delete"))) {
+    remove_argument (N, &argc, argv);
+    output.delete = TRUE;
+  }
+
+  if ((N = get_argument (argc, argv, "-unique"))) {
+    remove_argument (N, &argc, argv);
+    output.unique = TRUE;
+  }
+
+  if ((N = get_argument (argc, argv, "-modify"))) {
+    if (output.delete) { 
+      fprintf (stderr, "can't specify more than one modifier at a time\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    output.modify = TRUE;
+    
+    /* modify part of the path */
+    if (!strcasecmp (argv[N], "path")) {
+      output.modify_path = TRUE;
+      remove_argument (N, &argc, argv);
+      output.oldpath = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      output.newpath = strcreate (argv[N]);
+      remove_argument (N, &argc, argv);
+      goto valid_modify;
+    }
+
+    /* modify distributed status */
+    if (!strcasecmp (argv[N], "mode")) {
+      output.modify_mode = TRUE;
+      remove_argument (N, &argc, argv);
+      output.mode = atoi(argv[N]);
+      remove_argument (N, &argc, argv);
+      goto valid_modify;
+    }
+
+    if (!strcasecmp (argv[N], "help")) {
+      fprintf (stderr, "-modify option: \n");
+      fprintf (stderr, "  -modify path (oldpath) (newpath)\n"); 
+      fprintf (stderr, "  -modify mode (mef | split)\n"); 
+      exit (2);
+    }
+
+    fprintf (stderr, "invalid -modify option, try -modify help\n");
+    exit (1);
+  }
+ valid_modify:
+
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: imsearch [config ops] \n");
+    fprintf (stderr, "  [-type type] [-mode mode] [-trange start range] [-ccd N]\n");
+    fprintf (stderr, "  [-etime exptime] [-filter name] [-name string] [-proc t/f]\n");
+    fprintf (stderr, "  [-treg] [-seq] [-pt] [-table] [-cadctable] [-bintable]\n");
+    fprintf (stderr, "  [-delete] [-modify (options)]\n");
+    exit (1);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/delete.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include "imregister.h"
+# include "spreg.h"
+
+void DeleteSubset (FITS_DB *db, Spectrum *spectrum, int Nspectrum, int *match, int Nmatch) {
+
+  int i, j;
+  int *keep, Nbad, Nsubset;
+  Spectrum *subset;
+
+  ALLOCATE (keep, int, MAX (Nspectrum, 1));
+  for (i = 0; i < Nspectrum; i++) keep[i] = TRUE;
+  fprintf (stderr, "total of %d spectra\n", Nspectrum);
+
+  Nbad = 0;
+  for (i = 0; i < Nmatch; i++) {
+    j = match[i];
+    if (j == -1) continue;
+    keep[j] = FALSE;
+    Nbad ++;
+  }
+  fprintf (stderr, "delete %d spectra\n", Nbad);
+  if (Nbad == 0) { 
+    fprintf (stderr, "SUCCESS\n");
+    gfits_db_close (db);
+    exit (0);
+  }
+
+  Nsubset = Nspectrum - Nbad;
+  ALLOCATE (subset, Spectrum, MAX (1, Nsubset));
+  fprintf (stderr, "keeping %d spectra\n", Nsubset);
+  for (j = i = 0; i < Nspectrum; i++) {
+    if (!keep[i]) continue;
+    subset[j] = spectrum[i];
+    j++;
+  }
+  free (keep);
+  free (spectrum);
+
+  /** we may later want to pull this out and put it elsewhere **/
+  /** free db[0].theader, db[0].table.buffer? **/
+  gfits_table_set_Spectrum (&db[0].ftable, subset, Nsubset);
+  gfits_db_save (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/match.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/match.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/match.c	(revision 16632)
@@ -0,0 +1,87 @@
+# include "imregister.h"
+# include "spreg.h"
+
+int *match_criteria (Spectrum *spectrum, int Nspectrum, int *Nmatch) {
+
+  int i, j;
+  int N, NMATCH;
+  int *match;
+  int reject;
+  int Nfilename, Nobject, Ntelescope, Ninstrument;
+
+  /* create selection index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  Nfilename = Nobject = Ntelescope = Ninstrument = 0;
+
+  if (criteria.FilenameSelect)   Nfilename   = strlen (criteria.Filename);
+  if (criteria.ObjectSelect)     Nobject     = strlen (criteria.Object);
+  if (criteria.TelescopeSelect)  Ntelescope  = strlen (criteria.Telescope);
+  if (criteria.InstrumentSelect) Ninstrument = strlen (criteria.Instrument);
+
+  /* find entries that matches criteria */
+  for (i = 0; i < Nspectrum; i++) {
+    for (j = 0, reject = TRUE; reject && (j < criteria.Ntimes); j++) {
+      reject = (spectrum[i].obstime + spectrum[i].exptime < criteria.tstart[j]) || (spectrum[i].obstime > criteria.tstop[j]);
+    }
+    if (criteria.Ntimes && reject) continue;
+    if (criteria.ModeSelect    && (spectrum[i].mode  != criteria.Mode)) continue;
+    if (criteria.StateSelect   && (spectrum[i].state != criteria.State)) continue;
+
+    if (criteria.ExptimeSelect && (fabs (spectrum[i].exptime - criteria.Exptime) > 5.0)) continue;
+
+    if (criteria.FilenameSelect   && (strncasecmp (spectrum[i].filename, criteria.Filename, Nfilename))) continue;
+    if (criteria.ObjectSelect     && (strncasecmp (spectrum[i].objname, criteria.Object, Nobject))) continue;
+    if (criteria.TelescopeSelect  && (strncasecmp (spectrum[i].telescope, criteria.Telescope, Ntelescope))) continue;
+    if (criteria.InstrumentSelect && (strncasecmp (spectrum[i].instrument, criteria.Instrument, Ninstrument))) continue;
+
+    match[N] = i;
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+  }
+  *Nmatch = N;
+  return (match);
+}
+
+# if (0)
+
+int *match_spectra (Spectrum *subset, int Nsubset, int *Nmatch) {
+  
+  int i, j, N, Nspectrum, Nfound;
+  int *match;
+  Spectrum *spectrum;
+
+  spectrum = get_spectra (&Nspectrum);
+
+  /* find matching spectra - very inefficient : sort by obstime, find those first? */
+  ALLOCATE (match, int, Nsubset);
+  for (j = 0; j < Nsubset; j++) {
+    match[j] = -1;
+    for (i = 0; (match[j] == -1) && (i < Nspectrum); i++) {
+      if (spectrum[i].obstime > subset[j].obstime + 1) continue;
+      if (spectrum[i].obstime < subset[j].obstime - 1) continue;
+      match[j] = i;
+    }
+  }
+  
+  Nfound = 0;
+  for (i = 0; i < Nsubset; i++) {
+    /* set the new values for this spectrum */
+    N = match[i];
+    if (N == -1) continue;
+    spectrum[N].ra   = subset[i].ra; 
+    spectrum[N].dec  = subset[i].dec; 
+    /* if the spectrum is MEF, these were not correctly assigned by imsort.
+       this step uses the values from the split ccd spectrum */
+    Nfound ++;
+  }
+  *Nmatch = Nfound;
+  return (match);
+}
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/modify.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/modify.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/modify.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "imregister.h"
+# include "spreg.h"
+
+void ModifySubset (FITS_DB *db, Spectrum *spectrum, int Nspectrum, int *match, int Nmatch) {
+
+  int i, j, Nold;
+  char *tmppath;
+
+  Nold = 0;
+  tmppath = NULL;
+
+  /* create some necessary variables */
+  if (output.modify_path) { 
+    Nold = strlen (output.oldpath);
+    ALLOCATE (tmppath, char, 128);
+  }
+
+  /* modify the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+
+    i = match[j];
+
+    if (output.modify_path) {
+      if (!strncmp (spectrum[i].pathname, output.oldpath, Nold)) {
+	strcpy (tmppath, &spectrum[i].pathname[Nold]);
+	snprintf (spectrum[i].pathname, 128, "%s%s", output.newpath, tmppath);
+      }
+    }
+
+    if (output.modify_mode) {
+      spectrum[i].mode = output.mode;
+    }
+
+    if (output.modify_state) {
+      spectrum[i].state = output.state;
+    }
+  }
+
+  /** we may later want to pull this out and put it elsewhere **/
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, match, Nmatch);
+  for (i = 0; i < Nmatch; i++) {
+    gfits_convert_Spectrum ((Spectrum *) db[0].vtable.buffer[i], sizeof (Spectrum), 1);
+  }
+  gfits_db_update (db);
+  gfits_db_close (db);
+  gfits_db_free (db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/output.c	(revision 16632)
@@ -0,0 +1,174 @@
+# include "imregister.h"
+# include "spreg.h"
+
+static int RegTimeMode = FALSE;
+
+void SetOutputMode (char *mode) {
+
+  if (!strcmp (mode, "RegTimeMode")) {
+    RegTimeMode = TRUE;
+    return;
+  }
+  return;
+}
+
+/* given a subset list, write out the selected spectra, if desired */
+void OutputSubset (Spectrum *spectrum, int Nspectra, int *match, int Nmatch) {
+
+  if (output.table != (char *) NULL) {
+    DumpFitsTable (output.table, spectrum, match, Nmatch);
+  } 
+
+  if (output.bintable != (char *) NULL) {
+    DumpFitsBintable (output.bintable, spectrum, match, Nmatch);
+  } 
+
+  PrintSubset (spectrum, match, Nmatch);
+  exit (0);
+}
+
+/* write out complete binary FITS table in format of db */
+void DumpFitsBintable (char *filename, Spectrum *spectrum, int *match, int Nmatch) {
+
+  int i, j;
+  FILE *f;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  Spectrum *subset;
+
+  /* extract subset list to single array */
+  ALLOCATE (subset, Spectrum, MAX (1, Nmatch));
+  for (i = 0; i < Nmatch; i++){
+    j = match[i];
+    memcpy (&subset[i], &spectrum[j], sizeof (Spectrum));
+  }
+
+  /* open file for output */
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", filename);
+    exit (1);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+
+  ftable.header = &theader;
+  gfits_table_set_Spectrum (&ftable, subset, Nmatch);
+
+  gfits_fwrite_header   (f, &header);
+  gfits_fwrite_matrix   (f, &matrix);
+  gfits_fwrite_Theader  (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+  fclose (f);
+  exit (0);
+}
+
+/* write out an ASCII table */
+void DumpFitsTable (char *filename, Spectrum *spectrum, int *match, int Nmatch) {
+  
+  int i;
+  char *obsstr, *regstr, *line, *datestr;
+  time_t tsecond;
+  FILE *f;
+  Header header, theader;
+  Matrix matrix;
+  FTable ftable;
+  Spectrum *subset;
+
+  /* create primary header */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 1);
+  
+  /* the ASCII table is always a little harder than the binary:
+   * we need to build the data line a bit carefully 
+   */
+
+  /* create an empty table which we will fill in by hand */
+  ftable.header = &theader;
+  gfits_table_set_SpectrumASCII (&ftable, NULL, 0);
+  
+  /* add data to table */
+  for (i = 0; i < Nmatch; i++) {
+    subset = &spectrum[match[i]];
+    obsstr = ohana_sec_to_date (subset[0].obstime);
+    regstr = ohana_sec_to_date (subset[0].regtime);
+
+    /* we should get an error here if we don't construct this line correctly */
+    line = gfits_table_print (&ftable, subset[0].filename, subset[0].pathname, subset[0].instrument, 
+			     subset[0].telescope, subset[0].objname, subset[0].extname, 
+			     subset[0].ra, subset[0].dec, subset[0].exptime, subset[0].airmass, 
+			     subset[0].Ws, subset[0].We, subset[0].dW, 
+			     subset[0].Nspec, obsstr, regstr,
+			     subset[0].mode, subset[0].state, subset[0].flag);
+
+    gfits_add_rows (&ftable, line, 1, strlen(line));
+    free (line);
+    free (obsstr);
+    free (regstr);
+  }
+
+  /* add current date/time to header */
+  ohana_str_to_time ("now", &tsecond);
+  datestr = ohana_sec_to_date (tsecond);
+  gfits_modify (&header,  "DATE", "%s", 1, datestr);
+  gfits_modify (&theader, "DATE", "%s", 1, datestr);
+
+  /* open file for output */
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", filename);
+    exit (1);
+  }
+
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &ftable);
+  fclose (f);
+
+  exit (0);
+}
+
+/* Select, TimeMode are global */
+int PrintSubset (Spectrum *spectrum, int *match, int Nmatch) {
+  
+  int i, j;
+  char *timestr;
+
+  /* print the selected entries */
+  for (j = 0; j < Nmatch; j++) {
+    i = match[j];
+    
+    timestr = RegTimeMode ? ohana_sec_to_date (spectrum[i].regtime) : ohana_sec_to_date (spectrum[i].obstime);
+
+    /* predefined subset of values */
+    fprintf (stdout, "%5d %20s %s %s %s %s ", i, timestr, spectrum[i].pathname, spectrum[i].filename, spectrum[i].objname, spectrum[i].telescope);
+    fprintf (stdout, "%5.1f %5.3f %.1f %.1f %.2f\n", spectrum[i].exptime, spectrum[i].airmass, spectrum[i].Ws, spectrum[i].We, spectrum[i].dW);
+
+    free (timestr);
+  }
+  return (TRUE);
+}
+
+int dump_data (Spectrum *spectrum, int Nspectrum) {
+
+  int i;
+
+  for (i = 0; i < Nspectrum; i++) {
+    fprintf (stdout, "%s %s %f %f %f %f\n", spectrum[i].filename, spectrum[i].objname, spectrum[i].exptime, spectrum[i].airmass, spectrum[i].Ws, spectrum[i].We);
+  }
+
+  fprintf (stdout, "SUCCESS\n");
+  exit (0);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/showinfo.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/showinfo.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/showinfo.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "imregister.h"
+# include "spreg.h"
+
+void showinfo (Spectrum *spec) {
+
+  char *obstime, *regtime;
+
+  fprintf (stderr, "\n");
+  fprintf (stderr, "filename: %s\n",   spec[0].filename);
+  fprintf (stderr, "pathname: %s\n",   spec[0].pathname);
+  fprintf (stderr, "extname:  %s\n\n",   spec[0].extname);
+
+  fprintf (stderr, "instrument: %s\n\n", spec[0].instrument);
+  fprintf (stderr, "telescope: %s\n\n", spec[0].telescope);
+
+
+  fprintf (stderr, "mode: %d, state: %d, flag: %x\n\n", spec[0].mode, spec[0].state, spec[0].flag);
+
+  fprintf (stderr, "exptime: %f, airmass: %f\n", spec[0].exptime, spec[0].airmass);
+  fprintf (stderr, "ra: %f, dec: %f\n", spec[0].ra, spec[0].dec);
+  fprintf (stderr, "objname: %s\n\n", spec[0].objname);
+
+  fprintf (stderr, "Ws: %f, We: %f, dW: %f\n", spec[0].Ws, spec[0].We, spec[0].dW);
+  fprintf (stderr, "Nspec: %d\n", spec[0].Nspec);
+
+  obstime = ohana_sec_to_date (spec[0].obstime);
+  regtime = ohana_sec_to_date (spec[0].regtime);
+
+  fprintf (stderr, "obstime: %s\n", obstime);
+  fprintf (stderr, "regtime: %s\n", regtime);
+
+  exit (0);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/spinfo.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/spinfo.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/spinfo.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "imregister.h"
+# include "spreg.h"
+
+Spectrum *spinfo (char *filename) {
+
+  Spectrum *spectrum;
+  Header header;
+  char line[80];
+  struct timeval now;
+  char *name, *cwd, *tempname;
+  double tmp;
+
+  ALLOCATE (spectrum, Spectrum, 1);
+  bzero (spectrum, sizeof (Spectrum));
+
+  /* load in FITS header from image */
+  if (!gfits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", filename);
+    exit (1);
+  }
+
+  /* get filename */
+  name = filebasename (filename);
+  snprintf (spectrum[0].filename, 32, "%s", name);
+  free (name);
+
+  /* get pathname (add cwd if not absolute) */
+  name = pathname (filename);
+  if (name[0] != '/') {
+    cwd = getcwd (NULL, 64 - strlen(name) - 2);
+    if (cwd == (char *) NULL) {
+      cwd = strcreate ("longpath");
+      /* pathname is limited to 64 chars.  if it is toolong, 
+	 we put in the word 'longpath'.  no other useful solution. */
+    }
+    ALLOCATE (tempname, char, strlen (cwd) + strlen (name) + 2);
+    if (!strcmp (name, ".")) {
+      sprintf (tempname, "%s", cwd);
+    } else {
+      sprintf (tempname, "%s/%s", cwd, name);
+    }      
+    free (name);
+    free (cwd);
+    name = tempname;
+  }    
+  snprintf (spectrum[0].pathname, 64, "%s", name);
+  free (name);
+
+  /* find the important header keyword values */
+  spectrum[0].obstime = parse_time (&header);
+
+  gettimeofday (&now, (void *) NULL);
+  spectrum[0].regtime = now.tv_sec;
+
+  warn_scan_nchar (&header, 16, ObjectKeyword,    1, spectrum[0].objname);
+  warn_scan_nchar (&header, 16, CameraKeyword,    1, spectrum[0].instrument);
+  warn_scan_nchar (&header, 16, TelescopeKeyword, 1, spectrum[0].telescope);
+
+  clean_spaces (spectrum[0].objname);
+  clean_spaces (spectrum[0].instrument);
+  clean_spaces (spectrum[0].telescope);
+
+  warn_scan (&header, ExptimeKeyword,    "%f", 1, &spectrum[0].exptime);
+  warn_scan (&header, AirmassKeyword,    "%f", 1, &spectrum[0].airmass);
+
+  /* grab coordinates from header */
+  if (RADecDegKeyword[0] & DECDecDegKeyword[0]) {
+    /* expect RA & DEC in decimal degrees */
+    warn_scan (&header, RADecDegKeyword,  "%f", 1, &spectrum[0].ra);
+    warn_scan (&header, DECDecDegKeyword, "%f", 1, &spectrum[0].dec);
+  } else {
+    if (RASexigKeyword[0] & DECSexigKeyword[0]) {
+      /* expect RA & DEC in hh:mm:ss, dd:mm:ss */
+      warn_scan (&header, RASexigKeyword,  "%s", 1, line);
+      ohana_dms_to_ddd (&tmp, line);
+      spectrum[0].ra = 15*tmp;
+      warn_scan (&header, DECSexigKeyword, "%s", 1, &line);
+      ohana_dms_to_ddd (&tmp, line);
+      spectrum[0].dec = tmp;
+    }
+  }
+
+  /* for now we will not try to determine the mode, state, or 
+     wavelength ranges from the header.  set these with -modify
+     or on the command line on insert.  later on, we can add the logic */
+  
+  spectrum[0].mode  = SPMODE_UKN;
+  spectrum[0].state = SPSTATE_UKN;
+  spectrum[0].Nspec = 1;
+  spectrum[0].flag  = 0;
+  
+  { 
+    int Nx;
+    float crpix, crval, cd11;
+
+    warn_scan (&header, "CRPIX1", "%f", 1, &crpix);
+    warn_scan (&header, "CRVAL1", "%f", 1, &crval);
+    if (!gfits_scan (&header, "CDELT1", "%f", 1, &cd11))
+      warn_scan (&header, "CD1_1", "%f", 1, &cd11);
+    
+    gfits_scan (&header, "NAXIS1", "%d", 1, &Nx);
+
+    spectrum[0].Ws = (1  - crpix)*cd11 + crval;
+    spectrum[0].We = (Nx - crpix)*cd11 + crval;
+    spectrum[0].dW = cd11;
+  }
+  
+  strcpy (spectrum[0].extname, "PHU");
+  
+  return (spectrum);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/spreg/unique.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/spreg/unique.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/spreg/unique.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "imregister.h"
+# include "spreg.h"
+
+void sortstr (char **S, int *X, int N) {
+
+# define SWAPFUNC(A,B){ \
+  char *tmp = S[A]; S[A] = S[B]; S[B] = tmp; \
+  int  itmp = X[A]; X[A] = X[B]; X[B] = itmp; \
+}
+# define COMPARE(A,B)(strcmp(S[A], S[B]) < 0)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+/* input is a subset index of spectrum list, output is a new subset */
+int *unique_entries (Spectrum *spectrum, int Nspectrum, int *subset, int *Nmatch) {
+
+  int i, j, m, Nsubset;
+  int N, NMATCH;
+  int *match, *entry;
+  char idxline[128];
+  char **index;
+
+  if (!output.unique) return (subset);
+
+  /* create output index */
+  N = 0;
+  NMATCH = 1000;
+  ALLOCATE (match, int, NMATCH);
+
+  Nsubset = *Nmatch;
+
+  /* index = filename */
+  ALLOCATE (index, char *, Nsubset);
+  ALLOCATE (entry, int, Nsubset);
+  for (i = 0; i < Nsubset; i++) {
+    sprintf (idxline, "%s", spectrum[subset[i]].filename);
+    index[i] = strcreate (idxline);
+    entry[i] = subset[i];
+  }
+  sortstr (index, entry, Nsubset);
+
+  /* find unique sequences */
+  for (i = 0; i < Nsubset; ) {
+    for (j = i + 1; (j < Nsubset) && (!strcmp (index[i], index[j])); j++);
+    m = i;
+    
+    /* add unique entry to output list */
+    match[N] = entry[m];
+    N ++;
+    if (N == NMATCH) {
+      NMATCH += 1000;
+      REALLOCATE (match, int, NMATCH);
+    }
+
+    /* j always points to the next entry */
+    i = j;
+  }
+
+  for (i = 0; i < Nsubset; i++) free (index[i]);
+  free (index);
+  free (entry);
+  free (subset);
+
+  *Nmatch = N;
+  return (match);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/cameraconfig.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/cameraconfig.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/cameraconfig.c	(revision 16632)
@@ -0,0 +1,262 @@
+# include "imregister.h"
+static char *version = "cameraconfig $Revision: 1.3 $";
+
+void usage ();
+
+int main (int argc, char **argv) {
+
+  int i, Nccd, Nx, Ny, mosaic_x, mosaic_y, N, use_biassec;
+  int dx, dy;
+  char *config, *file;
+  char CameraConfig[256];
+  char field[64], line[256], keyword[64];
+  char ID[64], *IDsel;
+  double x, y, Xo, Yo, theta;
+  int Choice, GetID, SEQ, GetN, Nsel;
+  int NCCD, AXES, CCDS, CCDN, XOFF, YOFF, XFLIP, YFLIP, XO, YO, THETA;
+  int AXIS0, AXIS1, MOSAIC_X, MOSAIC_Y, DATASEC, BIASSEC, USE_BIASSEC;
+  char datasec[64], biassec[64];
+
+  bzero (ID, 64);
+  get_version (argc, argv, version);
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  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);
+  }
+  if (!ScanConfig (config, "CAMERA_CONFIG", "%s", 0, CameraConfig)) {
+    fprintf (stderr, "ERROR: can't find CAMERA_CONFIG in configuration file\n");
+    exit (1);
+  }
+  free (config);
+  free (file);
+
+  /* load camera config file */
+  config = LoadConfigFile (CameraConfig);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find camera config file %s\n", CameraConfig);
+    exit (1);
+  }
+
+  if (argc == 1) { 
+    fprintf (stderr, "USAGE: cameraconfig [-options]\n");
+    fprintf (stderr, "using %s for config information\n", CameraConfig);
+    exit (1);
+  }
+
+  /* command line options */
+  if ((N = get_argument (argc, argv, "-h"))) usage ();
+
+  /* command line options */
+  NCCD = FALSE;
+  if ((N = get_argument (argc, argv, "-Nccd"))) {
+    remove_argument (N, &argc, argv);
+    NCCD = TRUE;
+  }
+
+  AXES = FALSE;
+  if ((N = get_argument (argc, argv, "-axes"))) {
+    remove_argument (N, &argc, argv);
+    AXES = TRUE;
+  }
+
+  AXIS0 = FALSE;
+  if ((N = get_argument (argc, argv, "-axis0"))) {
+    remove_argument (N, &argc, argv);
+    AXIS0 = TRUE;
+  }
+
+  AXIS1 = FALSE;
+  if ((N = get_argument (argc, argv, "-axis1"))) {
+    remove_argument (N, &argc, argv);
+    AXIS1 = TRUE;
+  }
+
+  MOSAIC_X = FALSE;
+  if ((N = get_argument (argc, argv, "-mosaicx"))) {
+    remove_argument (N, &argc, argv);
+    MOSAIC_X = TRUE;
+  }
+  MOSAIC_Y = FALSE;
+  if ((N = get_argument (argc, argv, "-mosaicy"))) {
+    remove_argument (N, &argc, argv);
+    MOSAIC_Y = TRUE;
+  }
+
+  CCDS = FALSE;
+  if ((N = get_argument (argc, argv, "-ccds"))) {
+    remove_argument (N, &argc, argv);
+    CCDS = TRUE;
+  }
+
+  CCDN = FALSE;
+  if ((N = get_argument (argc, argv, "-ccdn"))) {
+    remove_argument (N, &argc, argv);
+    CCDN = TRUE;
+  }
+
+  SEQ = FALSE;
+  if ((N = get_argument (argc, argv, "-seq"))) {
+    remove_argument (N, &argc, argv);
+    SEQ = TRUE;
+  }
+
+  XOFF = FALSE;
+  if ((N = get_argument (argc, argv, "-xoff"))) {
+    remove_argument (N, &argc, argv);
+    XOFF = TRUE;
+  }
+
+  YOFF = FALSE;
+  if ((N = get_argument (argc, argv, "-yoff"))) {
+    remove_argument (N, &argc, argv);
+    YOFF = TRUE;
+  }
+
+  XO = FALSE;
+  if ((N = get_argument (argc, argv, "-Xo"))) {
+    remove_argument (N, &argc, argv);
+    XO = TRUE;
+  }
+
+  YO = FALSE;
+  if ((N = get_argument (argc, argv, "-Yo"))) {
+    remove_argument (N, &argc, argv);
+    YO = TRUE;
+  }
+
+  THETA = FALSE;
+  if ((N = get_argument (argc, argv, "-theta"))) {
+    remove_argument (N, &argc, argv);
+    THETA = TRUE;
+  }
+
+  XFLIP = FALSE;
+  if ((N = get_argument (argc, argv, "-xflip"))) {
+    remove_argument (N, &argc, argv);
+    XFLIP = TRUE;
+  }
+
+  YFLIP = FALSE;
+  if ((N = get_argument (argc, argv, "-yflip"))) {
+    remove_argument (N, &argc, argv);
+    YFLIP = TRUE;
+  }
+
+  DATASEC = FALSE;
+  if ((N = get_argument (argc, argv, "-datasec"))) {
+    remove_argument (N, &argc, argv);
+    DATASEC = TRUE;
+  }
+  BIASSEC = FALSE;
+  if ((N = get_argument (argc, argv, "-biassec"))) {
+    remove_argument (N, &argc, argv);
+    BIASSEC = TRUE;
+  }
+  USE_BIASSEC = FALSE;
+  if ((N = get_argument (argc, argv, "-usebiassec"))) {
+    remove_argument (N, &argc, argv);
+    USE_BIASSEC = TRUE;
+  }
+
+  GetID = FALSE;
+  Nsel = 0;
+  if ((N = get_argument (argc, argv, "-ID"))) {
+    GetID = TRUE;
+    remove_argument (N, &argc, argv);
+    Nsel = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  GetN = FALSE;
+  IDsel = NULL;
+  if ((N = get_argument (argc, argv, "-N"))) {
+    GetN = TRUE;
+    remove_argument (N, &argc, argv);
+    IDsel = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) { 
+    fprintf (stderr, "USAGE: cameraconfig [-options]\n");
+    exit (1);
+  }
+
+  /* load data from config file */
+  ScanConfig (config, "NCCD", "%d", 1, &Nccd);
+  ScanConfig (config, "NAXIS1", "%d", 1, &Nx);
+  ScanConfig (config, "NAXIS2", "%d", 1, &Ny);
+  ScanConfig (config, "MOSAIC_X", "%d", 1, &mosaic_x);
+  ScanConfig (config, "MOSAIC_Y", "%d", 1, &mosaic_y);
+  ScanConfig (config, "USE_BIASSEC", "%d", 1, &use_biassec);
+  
+  if (NCCD) fprintf (stdout, "%d\n", Nccd);
+  if (AXES) fprintf (stdout, "%d %d\n", Nx, Ny);
+  if (AXIS0) fprintf (stdout, "%d\n", Nx);
+  if (AXIS1) fprintf (stdout, "%d\n", Ny);
+  if (MOSAIC_X) fprintf (stdout, "%d\n", mosaic_x);
+  if (MOSAIC_Y) fprintf (stdout, "%d\n", mosaic_y);
+  if (USE_BIASSEC) fprintf (stdout, "%d\n", use_biassec);
+  
+  ScanConfig (config, "CHIPID_KEYWORD", "%s", 1, keyword);
+  
+  Choice = SEQ || CCDS || CCDN || XOFF || YOFF || XFLIP || YFLIP || DATASEC || BIASSEC || XO || YO || THETA;
+
+  for (i = 0; i < Nccd; i++) {
+    sprintf (field, "CCD.%d", i);
+    ScanConfig (config, field, "%s", 1, line);
+    sscanf (line, "%s %lf %lf %d %d %s %s %lf %lf %lf", 
+	    ID, &x, &y, &dx, &dy, datasec, biassec, &Xo, &Yo, &theta);
+
+    if (GetN  && strnumcmp (IDsel, ID)) fprintf (stdout, "%d\n", i);
+    if (GetID && (Nsel == i)) fprintf (stdout, "%s\n", ID);
+    if (SEQ)     fprintf (stdout, "%d ", i);
+    if (CCDS)    fprintf (stdout, "%s ", ID);
+    if (CCDN)    fprintf (stdout, "%02d", i);
+    if (XOFF)    fprintf (stdout, "%f ", x);
+    if (YOFF)    fprintf (stdout, "%f ", y);
+    if (XFLIP)   fprintf (stdout, "%d ", dx);
+    if (YFLIP)   fprintf (stdout, "%d ", dy);
+    if (DATASEC) fprintf (stdout, "%s ", datasec);
+    if (BIASSEC) fprintf (stdout, "%s ", biassec);
+
+    if (XO)      fprintf (stdout, "%7.1f ", Xo);
+    if (YO)      fprintf (stdout, "%7.1f ", Yo);
+    if (THETA)   fprintf (stdout, "%7.3f ", theta);
+
+    if (Choice) fprintf (stdout, "\n");
+
+  }
+
+  exit (0);
+}
+
+void usage () {
+
+  fprintf (stderr, "cameraconfig [option] : lookup camera parameters\n");
+  fprintf (stderr, "   -Nccd         : number of CCDs\n");
+  fprintf (stderr, "   -axes         : x & y dimensions\n");
+  fprintf (stderr, "   -axis0        : x dimension (CCD)\n");
+  fprintf (stderr, "   -axis1        : y dimension (CCD)\n");
+  fprintf (stderr, "   -mosaicx      : x dimension (mosaic)\n");
+  fprintf (stderr, "   -mosaicy      : y dimension (mosaic)\n");
+  fprintf (stderr, "   -usebiassec   : use header BIASSEC\n");
+
+  fprintf (stderr, "   -seq          : chip sequence number\n");
+  fprintf (stderr, "   -ccds         : chip extension ID\n");
+  fprintf (stderr, "   -xoff         : x offset in mosaic\n");
+  fprintf (stderr, "   -yoff         : y offset in mosaic\n");
+  fprintf (stderr, "   -xflip        : x flip in mosaic\n");
+  fprintf (stderr, "   -yflip        : y flip in mosaic\n");
+  fprintf (stderr, "   -datasec      : DATASEC value\n");
+  fprintf (stderr, "   -biassec      : BIASSEC value\n");
+
+  fprintf (stderr, "   -ID [N]       : return ID for seq\n");
+  fprintf (stderr, "   -N [ID]       : return seq for ID\n");
+  exit (2);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/convertimreg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/convertimreg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/convertimreg.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "imregister.h"
+# include "imreg.h"
+static char *version = "convertimreg $Revision: 3.4 $";
+
+int main (int argc, char **argv) {
+ 
+  FILE *f;
+  Header header;
+  RegImage *pimage;
+  int i, Nimage, status, lockstate, dbstate;
+  int *match;
+  
+  get_version (argc, argv, version);
+  ConfigInit (&argc, argv);
+  ConfigCamera ();
+  ConfigFilter ();
+  
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: convertregdb (input) (output)\n");
+    fprintf (stderr, "       convert old pseudo-FITS table imreg db to FITS table\n");
+    exit (1);
+  }
+  
+  /* load old-style pseudo-FITS table db */
+  lockstate = LCK_SOFT;
+
+  /* lock database (soft) */
+  f = fsetlockfile (argv[1], 300.0, lockstate, &dbstate);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open db\n");
+    exit (1);
+  }
+  Fseek (f, 0, SEEK_SET);
+
+  /* load in database header */
+  if (!gfits_load_header (f, &header)) {
+    fprintf (stderr, "ERROR: trouble reading database header\n");
+    fclearlockfile (argv[1], f, lockstate, &dbstate);
+    exit (1);
+  }
+
+  /* load existing data from database */
+  gfits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  ALLOCATE (pimage, RegImage, Nimage);
+  status = fread (pimage, sizeof(RegImage), Nimage, f);
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: header and data in dB don't match (%d vs %d)\n", Nimage, status);
+    fclearlockfile (argv[1], f, lockstate, &dbstate);
+    exit (1);
+  }
+  fclearlockfile (argv[1], f, lockstate, &dbstate);
+  gfits_convert_RegImage (pimage, sizeof (RegImage), Nimage);
+
+  /* create complete subset */
+  ALLOCATE (match, int, Nimage);
+  for (i = 0; i < Nimage; i++) match[i] = i;
+
+  DumpFitsBintable (argv[2], pimage, match, Nimage);
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/detregister.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/detregister.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/detregister.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include "imregister.h"
+# include "detrend.h"
+static char *version = "detregister $Revision: 3.5 $";
+
+int main (int argc, char **argv) {
+ 
+  char *dBFile;
+  DetReg newdata;
+  Descriptor descriptor;
+  FITS_DB db;
+  
+  get_version (argc, argv, version);
+  regargs (argc, argv, &descriptor);
+  DefineImage (argv[1], &descriptor);
+
+  newdata = DefineEntry (descriptor);
+  SaveEntry (argv[1], &newdata, descriptor.imageID);
+
+  db.lockstate = LCK_HARD;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  dBFile = set_dBFile ();
+  if (!gfits_db_lock (&db, dBFile)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    gfits_db_create (&db);    
+    gfits_table_set_DetReg (&db.ftable, NULL, 0);
+  } else {  
+    if (!gfits_db_load (&db)) {
+      fprintf (stderr, "ERROR: failure to load db\n");
+      gfits_db_close (&db);
+      exit (1);
+    }
+  }
+
+  gfits_convert_DetReg (&newdata, sizeof (DetReg), 1);
+  gfits_table_to_vtable (&db.ftable, &db.vtable, 0, 0);
+  gfits_vadd_rows (&db.vtable, (char *) &newdata, 1, sizeof(DetReg));
+
+  gfits_db_update (&db);
+  gfits_db_close (&db);
+  gfits_db_free (&db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+/* detrend files created by mkdetrend have names of the following form:
+   
+   TYPE.CCD.FILTER.CRUN.NUMBER.fits 
+   
+   ie:
+   
+   bias.02.0.01Ak3.0.fits
+   
+   When they are registered, the NUMBER component needs to be
+   updated to match the next available number.
+   
+   This is a bit tricky.  We can easily identify 
+   TYPE, CCD, FILTER, and extrapolate to the NUMBER, but 
+   unambiguously identifying the CRUN is harder.  We could make it a 
+   required keyword on the command line, or insert it in the
+   image header and request it if it doesn't exist?
+
+    required fields:
+
+    tstart
+    tstop
+    type
+    ccd
+
+    filename (automatic)
+    treg (automatic)
+
+    case type 
+      flat:
+      ring:
+      scat:
+        filter is required
+      default:
+        filter is none
+
+    case type
+      dark:
+        exptime is required
+      bias:
+        exptime is 0.0
+      default:
+        exptime is NaN
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/detsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/detsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/detsearch.c	(revision 16632)
@@ -0,0 +1,91 @@
+# include "imregister.h"
+# include "detrend.h"
+static char *version = "detsearch $Revision: 3.8 $";
+
+int main (int argc, char **argv) {
+ 
+  int Nmatch, Ndetrend;
+  char *dBFile;
+  FITS_DB db;
+  Match *match;
+  DetReg *detrend;
+
+  /* args searches the argument list and generates an array of criteria */
+  get_version (argc, argv, version);
+  args (argc, argv);
+
+  if (output.Criteria) PrintCriteria ();
+	
+  db.lockstate = (output.Modify || output.Delete) ? LCK_HARD : LCK_SOFT;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  dBFile = set_dBFile ();
+  if (!gfits_db_lock (&db, dBFile)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  
+  if (!gfits_db_load (&db)) {
+    fprintf (stderr, "ERROR: failure to load db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+
+  if (!output.Modify && !output.Delete && !output.Altpath) gfits_db_close (&db);
+  detrend = gfits_table_get_DetReg (&db.ftable, &Ndetrend, &db.swapped);
+  
+  match = MatchCriteria (detrend, Ndetrend, &Nmatch);          /* match basic criteria */
+  match = ExptimeCriteria (detrend, Ndetrend, match, &Nmatch); /* reduce matches based on Exptime */
+  match = CloseCriteria (detrend, Ndetrend, match, &Nmatch);   /* reduce matches based on closeness */
+
+  if (output.Select) {
+    match = UniqueSubset (detrend, Ndetrend, match, &Nmatch);
+    if (Nmatch == 0) {
+      if (output.verbose) fprintf (stderr, "ERROR: can't find any valid detrend files (%s %s %d)\n", get_type_name(criteria[0].Type), filtername[criteria[0].Filter], criteria[0].CCD);
+      gfits_db_close (&db);
+      exit (1);
+    }
+  }
+
+  if (output.Altpath) SetAltpath (&db, detrend, Ndetrend, match, Nmatch);
+  if (output.Modify) ModifySubset (&db, detrend, Ndetrend, match, Nmatch);
+  if (output.Delete) DeleteSubset (&db, detrend, Ndetrend, match, Nmatch);
+
+  OutputSubset (detrend, Ndetrend, match, Nmatch);
+  exit (0);
+}
+
+/*
+
+selection options:
+
+CCDSelect
+TypeSelect
+TimeSelect
+FilterSelect
+ExptimeSelect
+EntrySelect
+LabelSelect
+
+
+ functional modes:
+
+   1) list - list all images that apply to a restrictive set of criteria
+   
+   2) select - choose the reference image(s)
+
+   3) delete - delete a set of images
+
+   4) modify - alter fields for a set of images
+
+   
+   methods to define criteria
+
+   - command line  [-time -type -ccd -filter -exptime]
+   - image  -> define time, filter, ccd
+   - mosaic -> define time, filter, exptime
+   - recipe -> defile type list based on filter
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/filtnames.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/filtnames.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/filtnames.c	(revision 16632)
@@ -0,0 +1,168 @@
+# include "imregister.h"
+static char *version = "filtnames $Revision: 1.2 $";
+
+typedef struct {
+  int code, calibrated;
+  char name[64], ref[64], c1[64], c2[64];
+} FiltCode;
+
+int main (int argc, char **argv) {
+
+  int i, code, Ncode, Nmatch, Nfield, N, Select, CalibrationData;
+  int Nfiltcode, NFILTCODE;
+  char *config, *file, *target;
+  char FilterList[256];
+  char name[64], ref[64], c1[64], c2[64], line[256], *c;
+  FILE *f;
+  FiltCode *filtcode;
+
+  get_version (argc, argv, version);
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (!ScanConfig (config, "FILTER_LIST", "%s", 0, FilterList)) {
+    fprintf (stderr, "ERROR: can't find FILTER_LIST in configuration file\n");
+    exit (1);
+  }
+  free (config);
+  free (file);
+
+  /* image type (dark, flat, bias, etc) */
+  Select = TRUE;
+  if ((N = get_argument (argc, argv, "-all"))) {
+    remove_argument (N, &argc, argv);
+    Select = FALSE;
+  }
+ 
+  /* image type (dark, flat, bias, etc) */
+  CalibrationData = FALSE;
+  if ((N = get_argument (argc, argv, "-cal"))) {
+    remove_argument (N, &argc, argv);
+    CalibrationData = TRUE;
+  }
+ 
+  if (argc != 2) { 
+    fprintf (stderr, "USAGE: filtnames (filtername)\n");
+    fprintf (stderr, "       filtnames list : list all unique filters\n");
+    fprintf (stderr, "       [-all] : list all names for given filter(s)\n");
+    fprintf (stderr, "       [-cal] : print calibration data for filter(s)\n");
+    exit (1);
+  }
+
+  target = argv[1];
+  for (i = 0; i < strlen (target); i++) { if (isspace (target[i])) target[i] = '.'; }
+
+  /* open filter list file */
+  f = fopen (FilterList, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error reading photcodes\n");
+    exit (1);
+  }
+
+  /* load filter list & codes */
+  NFILTCODE = 100;
+  Nfiltcode = 0;
+  ALLOCATE (filtcode, FiltCode, NFILTCODE);
+
+  while (scan_line (f, line) != EOF) {
+    for (c = line; isspace (*c); c++);
+    if (*c == '#') continue;
+    if (*c == 0) continue;
+    Nfield = sscanf (c, "%d %s %s %s %*s %s", &code, name, ref, c1, c2);
+    if ((Nfield != 2) && (Nfield != 5)) {
+      fprintf (stderr, "error reading line: %s\n", c);
+      exit (1);
+    }
+
+    filtcode[Nfiltcode].code = code;
+    filtcode[Nfiltcode].calibrated = FALSE;
+    strcpy (filtcode[Nfiltcode].name, name);
+    filtcode[Nfiltcode].ref[0] = 0;
+    filtcode[Nfiltcode].c1[0] = 0;
+    filtcode[Nfiltcode].c2[0] = 0;
+    if (Nfield == 5) {
+      filtcode[Nfiltcode].calibrated = TRUE;
+      strcpy (filtcode[Nfiltcode].ref, ref);
+      strcpy (filtcode[Nfiltcode].c1, c1);
+      strcpy (filtcode[Nfiltcode].c2, c2);
+    }
+    Nfiltcode ++;
+
+    if (Nfiltcode == NFILTCODE - 1) {
+      NFILTCODE += 100;
+      REALLOCATE (filtcode, FiltCode, NFILTCODE);
+    }
+  }
+
+  /* special target: list -- list all filters */
+  if (!strcasecmp (target, "list")) {
+    
+    int *uniq, Nuniq, j, found;
+    ALLOCATE (uniq, int, Nfiltcode);
+
+    /* identify unique filter codes */
+    Nuniq = 0;
+    for (i = 0; i < Nfiltcode; i++) {
+      found = FALSE;
+      for (j = 0; !found && (j < Nuniq); j++) {
+	if (filtcode[i].code == uniq[j]) found = TRUE;
+      }
+      if (found) continue;
+      uniq[Nuniq] = filtcode[i].code;
+      Nuniq ++;
+    }
+
+    /* list the entries of the unique codes.  skip code == 0 (none) */
+    for (i = 0; i < Nuniq; i++) {
+      if (uniq[i] == 0) continue;
+      for (j = 0; j < Nfiltcode; j++) {
+	if (uniq[i] != filtcode[j].code) continue;
+	if (CalibrationData) {
+	  fprintf (stdout, "%s %d %s %s %s\n", filtcode[j].name, filtcode[j].calibrated, filtcode[j].ref, filtcode[j].c1, filtcode[j].c2);
+	} else {
+	  fprintf (stdout, "%s\n", filtcode[j].name);
+	}
+	if (Select) break;
+      }
+    }
+    exit (0);
+  }
+
+  /* find given name in filter list (case insensitive) */
+  Ncode = 0;
+  for (i = 0; i < Nfiltcode; i++) {
+    if (strcasecmp (target, filtcode[i].name)) continue;
+    Ncode = filtcode[i].code;
+    break;
+  }
+  if (!Ncode) {
+    fprintf (stderr, "no filter match found\n");
+    exit (1);
+  }
+
+  /* find first entry with this code */
+  Nmatch = 0;
+  for (i = 0; i < Nfiltcode; i++) {
+    if (Ncode != filtcode[i].code) continue;
+    if (CalibrationData) {
+      fprintf (stdout, "%s %d %s %s %s\n", filtcode[i].name, filtcode[i].calibrated, filtcode[i].ref, filtcode[i].c1, filtcode[i].c2);
+    } else {
+      fprintf (stdout, "%s\n", filtcode[i].name);
+    }
+    Nmatch ++;
+    if (Select) break;
+  }
+
+  if (!Nmatch) {
+    fprintf (stderr, "no filter code error: code mis-match\n");
+    exit (1);
+  }
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/imphotmerge.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/imphotmerge.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/imphotmerge.c	(revision 16632)
@@ -0,0 +1,177 @@
+# include "imregister.h"
+
+/*** this needs to be written using dvo_image functions !!! ***/
+
+Image *LoadImageTable (FILE *f, Header *header, int *nimage);
+static char *version = "imphotcopy $Revision: 1.6 $";
+
+int main (int argc, char **argv) {
+ 
+  Header header, theader;
+  Image *image, *input;
+  FILE *f, *g;
+  int i, j, status, N;
+  char *dBFile;
+  int Nimage, Ninput, *index, Ntimes;
+  time_t *tstart, *tstop;
+  int VERBOSE, PHOTCODE, dbstate;
+  int PhotCodeSelect, Nin;
+  char *FitsOutput, *NameSelect;
+  int NameSelectLength;
+
+  get_version (argc, argv, version);
+  ConfigInit (&argc, argv);
+
+  /* interpret command-line arguments */
+  if (!get_trange_arguments (&argc, argv, &tstart, &tstop, &Ntimes)) {
+    fprintf (stderr, "ERROR: syntax error\n");
+    exit (1);
+  }
+
+  /* select by image photcode */
+  PhotCodeSelect = FALSE;
+  PHOTCODE = 0;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    if (!(PHOTCODE = GetPhotcodeCodebyName (argv[N]))) {
+      fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    PhotCodeSelect = TRUE;
+  }
+
+  /* string in image name */
+  NameSelect = (char *) NULL;
+  NameSelectLength = 0;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    NameSelect = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    NameSelectLength = strlen (NameSelect);
+  }
+
+  FitsOutput = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-fits"))) {
+    remove_argument (N, &argc, argv);
+    FitsOutput = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: imphotmerge (input) (target) [config ops] [-trange start stop/delta] [-photcode code]\n");
+    exit (1);
+  }
+ 
+  /* load image database - still a non-FITS file */
+  dBFile = argv[2];
+
+  f = fsetlockfile (dBFile, 120.0, LCK_HARD, &dbstate);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't set lock on %s, state is %d\n", dBFile, dbstate);
+    exit (1);
+  }
+  image = LoadImageTable (f, &header, &Nimage);
+
+  /* load input table */
+  g = fopen (argv[1], "r");
+  if (g == (FILE *) NULL) {
+    fprintf (stderr, "error opening input data file\n");
+    exit (1);
+  }
+  input = LoadImageTable (g, &theader, &Ninput);
+  fclose (g);
+
+  /* allocate space for reference lists */
+  Nin = 0;
+  ALLOCATE (index, int, Ninput);
+  
+  /* these filters are applied to input NOT image */
+  for (i = 0; i < Ninput; i++) {
+    for (j = 0, status = FALSE; !status && (j < Ntimes); j++) {
+      status = (input[i].tzero >= tstart[j]) && (input[i].tzero <= tstop[j]);
+    }
+    if (!status && Ntimes) continue;
+    if (PhotCodeSelect && (input[i].photcode != PHOTCODE)) continue;
+    if ((NameSelect != (char *) NULL) && (strncasecmp (input[i].name, NameSelect, NameSelectLength))) continue;
+
+    index[Nin] = i;
+    Nin ++;
+  }
+
+  /* add new images to images */
+  REALLOCATE (image, Image, Nimage + Nin);
+  for (j = 0, i = Nimage; i < Nimage + Nin; i++, j++) {
+    image[i] = input[index[j]];
+  }
+  Nimage += Nin;
+  gfits_modify (&header, "NIMAGES", "%d", 1, Nimage);
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = Fwrite (header.buffer, 1, header.size, f, "char");
+  if (status != header.size) {
+    fprintf (stderr, "ERROR: failed writing data to image header\n");
+    exit (0);
+  }
+
+  /* position to end of file for new image data */
+  fseek (f, header.size, SEEK_SET);
+  status = Fwrite (image, sizeof(Image), Nimage, f, "image");
+  if (status != Nimage) {
+    fprintf (stderr, "ERROR: failed writing data to image catalog\n");
+    exit (0);
+  }
+
+  fclearlockfile (dBFile, f, LCK_HARD, &dbstate);
+
+  if (VERBOSE) fprintf (stderr, "SUCCESS\n");
+  exit (0);
+
+}
+
+Image *LoadImageTable (FILE *f, Header *header, int *nimage) {
+
+  int Nimage, Ndata, Nread, size;
+  struct stat filestatus;
+  Image *image;
+
+  /* read header */
+  if (!gfits_fread_header (f, header)) {
+    fprintf (stderr, "ERROR: can't read image catalog\n");
+    exit (1);
+  }
+
+  /* check that file size makes sense */
+  Nimage = 0;
+  gfits_scan (header, "NIMAGES", "%d", 1, &Nimage);
+  if (fstat (fileno(f), &filestatus) == -1) {
+    fprintf (stderr, "ERROR: failed to get status of image catalog\n");
+    exit (1);
+  }
+  size = Nimage*sizeof(Image) + header[0].size;
+  if (size != filestatus.st_size) {
+    Ndata = (filestatus.st_size - header[0].size) / sizeof (Image);
+    fprintf (stderr, "ERROR: image catalog has inconsistent size\n");
+    fprintf (stderr, "header: %d, data: %d\n", Nimage, Ndata);
+    Nimage = Ndata;
+  } 
+
+  /* alloc, read images */
+  ALLOCATE (image, Image, MAX (Nimage, 1));
+  Nread = Fread (image, sizeof(Image), Nimage, f, "image");
+  if (Nread != Nimage) {
+    fprintf (stderr, "ERROR: problem loading image catalog\n");
+    exit (1);
+  } 
+
+  *nimage = Nimage;
+  return (image);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/imphotsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/imphotsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/imphotsearch.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "imregister.h"
+# include "imphot.h"
+
+static char *version = "imphotsearch $Revision: 1.10 $";
+
+int main (int argc, char **argv) {
+ 
+  int Nmatch, Nimage;
+  int *match;
+  Image *image;
+  FITS_DB db;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+ 
+  db.lockstate = (options.modify) ? LCK_HARD : LCK_SOFT;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  /* don't create a new image table if not available */
+  if (!gfits_db_lock (&db, ImPhotDB)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  /* we use a varient of gfits_db_load since the file may be in text format */
+  if (!dvo_image_load (&db, VERBOSE, FORCE_READ)) {
+    fprintf (stderr, "ERROR: failure to load db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (!options.modify) gfits_db_close (&db);
+
+  image = gfits_table_get_Image (&db.ftable, &Nimage, &db.swapped);
+
+  match = subset (image, Nimage, &Nmatch);
+  if (options.modify) ModifySubset (&db, image, Nimage, match, Nmatch);
+
+  output (image, match, Nmatch);
+
+  if (VERBOSE) fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/imregister.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/imregister.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/imregister.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "imregister.h"
+# include "imreg.h"
+static char *version = "imregister $Revision: 3.8 $";
+
+int main (int argc, char **argv) {
+ 
+  int Nregimage;
+  RegImage *image, *regimage;
+  FITS_DB db;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+
+  image = iminfo (argv[1]);
+  regimage = newimages (image, &Nregimage);
+
+  if (NoReg) goto skip_reg;
+
+  db.lockstate = LCK_HARD;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  if (!gfits_db_lock (&db, ImageDB)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    gfits_db_create (&db);
+    gfits_table_set_RegImage (&db.ftable, NULL, 0);
+  } else {  
+    if (!gfits_db_load (&db)) {
+      fprintf (stderr, "ERROR: failure to load db\n");
+      gfits_db_close (&db);
+      exit (1);
+    }
+  }
+
+  gfits_convert_RegImage (regimage, sizeof (RegImage), Nregimage);
+  gfits_table_to_vtable (&db.ftable, &db.vtable, 0, 0);
+  gfits_vadd_rows (&db.vtable, (char *) regimage, Nregimage, sizeof(RegImage));
+
+  gfits_db_update (&db);
+  gfits_db_close (&db);
+  gfits_db_free (&db);
+
+skip_reg:
+  if (IMSORT) SubmitImages (image);
+  fprintf (stderr, "SUCCESS: registered %s\n", argv[1]);
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/imregtable.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/imregtable.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/imregtable.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "imregister.h"
+# include "imreg.h"
+static char *version = "imregtable $Revision: 3.8 $";
+
+int main (int argc, char **argv) {
+ 
+  int Nimage;
+  char *infile;
+  RegImage *image;
+  Header header;
+  Header theader;
+  Matrix matrix;
+  FTable ftable;
+  FITS_DB db;
+
+  get_version (argc, argv, version);
+  ConfigInit (&argc, argv);
+  ConfigCamera ();
+  ConfigFilter ();
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: imregtable (table)\n");
+    exit (1);
+  }
+
+  /* load in table data */
+  infile = argv[1];
+
+  /* need to error check these */
+  ftable.header = &theader;
+  gfits_read_header  (infile, &header);
+  gfits_read_matrix  (infile, &matrix);
+  gfits_read_ftable  (infile, &ftable, "IMAGE_DATABASE");
+
+  image = gfits_table_get_RegImage (&ftable, &Nimage, NULL);
+
+  /* load database table */
+  db.lockstate = LCK_HARD;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  if (!gfits_db_lock (&db, ImageDB)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    gfits_db_create (&db);
+    gfits_table_set_RegImage (&db.ftable, NULL, 0);
+  } else {  
+    if (!gfits_db_load (&db)) {
+      fprintf (stderr, "ERROR: failure to load db\n");
+      gfits_db_close (&db);
+      exit (1);
+    }
+  }
+
+  gfits_convert_RegImage (image, sizeof (RegImage), Nimage);
+  gfits_table_to_vtable (&db.ftable, &db.vtable, 0, 0);
+  gfits_vadd_rows (&db.vtable, (char *) image, Nimage, sizeof(RegImage));
+
+  gfits_db_update (&db);
+  gfits_db_close (&db);
+  gfits_db_free (&db);
+
+  fprintf (stderr, "SUCCESS: registered %s\n", argv[1]);
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/imsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/imsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/imsearch.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "imregister.h"
+# include "imreg.h"
+static char *version = "imsearch $Revision: 3.7 $";
+
+int main (int argc, char **argv) {
+ 
+  int Nmatch, Nimage, *match;
+  RegImage *image;
+  FITS_DB db;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+
+  db.lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  if (!gfits_db_lock (&db, ImageDB)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (!gfits_db_load (&db)) {
+    fprintf (stderr, "ERROR: failure to load db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+
+  if (!output.modify && !output.delete) gfits_db_close (&db);
+
+  image = gfits_table_get_RegImage (&db.ftable, &Nimage, &db.swapped);
+  
+  match = match_criteria (image, Nimage, &Nmatch);
+  match = unique_entries (image, Nimage, match, &Nmatch);
+
+  if (output.modify) ModifySubset (&db, image, Nimage, match, Nmatch);
+  if (output.delete) DeleteSubset (&db, image, Nimage, match, Nmatch);
+
+  OutputSubset (image, Nimage, match, Nmatch);
+  exit (0);
+}
+
+/* 
+
+FITS table version:
+
+   load_db - open, read in database, store as RegImage structure
+   match   - return index 'match' to matched images
+   modify  - change value of selected images
+             write out subset of rows
+   delete  - remove selected images from image structure
+             write out entire table
+   output  - write out subset in various formats
+
+   get_images returns pointer to complete image structure
+
+
+SQL version:
+
+   load_db - set up connection
+   match   - convert criteria to SQL where clause and do:
+             'select from images [where clause]'
+             images structure is filled with result from query
+   modify  - change value of subset selection (identical)
+             update selected rows
+   delete  - user where clause and do 
+             'delete from images where clause'
+   output  - (identical)
+
+   get_images returns pointer to image subset from query
+   match[i] = i
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/imstatreg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/imstatreg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/imstatreg.c	(revision 16632)
@@ -0,0 +1,116 @@
+# include "imregister.h"
+# include "imreg.h"
+static char *version = "imstatreg $Revision: 3.16 $";
+
+int main (int argc, char **argv) {
+ 
+  int i, child;
+  int *match, Nmatch, Nimage, Nsubset;
+  FILE *f;
+  RegImage *image, *subset;
+  FITS_DB image_db, temp_db;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+  SetSignals ();
+
+  if (CLIENT) imregclient (argv[1], argv[2], argv[3]);
+
+  /* fork in background */
+  child = fork ();
+  if (child == -1) {
+    fprintf (stderr, "error forking imstatreg -daemon \n");
+    exit (1);
+  } 
+  if (child !=  0) {
+    fprintf (stderr, "starting imstatreg, logging to %s\n", LogFile);
+    exit (0);
+  }
+
+  /* child process, check for previous process */
+  ConfigPID (PIDFILE);
+
+  /* redirect stderr, stdout to logfile */
+  f = freopen (LogFile, "a", stdout);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open log file %s, writing to stderr\n", LogFile);
+  } else {
+    /* an error here will be missed, but is unlikely since we have access in the above test */
+    f = freopen (LogFile, "a", stderr);
+  }
+
+  image_db.lockstate = LCK_HARD;
+  image_db.timeout   = 300.0;
+  gfits_db_init (&image_db);
+
+  temp_db.lockstate = LCK_HARD;
+  temp_db.timeout   = 300.0;
+  gfits_db_init (&temp_db);
+
+  /* start loop */
+  while (1) {
+
+    /* check / load / delete temporary database */
+    if (!gfits_db_lock (&temp_db, TempDB)) {
+      gfits_db_close (&temp_db);
+      fprintf (stderr, "error locking temp db (path missing? access permission?)\n");
+      exit (1);
+    }
+    if (temp_db.dbstate == LCK_EMPTY) {
+      fprintf (stderr, "temporary database empty\n");
+      gfits_db_close (&temp_db);
+      goto next;
+    } 
+    if (!gfits_db_load (&temp_db)) {
+      fprintf (stderr, "error reading temp db\n");
+      exit (1);
+    }
+    subset = gfits_table_get_RegImage (&temp_db.ftable, &Nsubset, &temp_db.swapped);
+    fprintf (stderr, "temporary database read\n");
+
+    /* delete, unlock existing database */
+    truncate (TempDB, 0);
+    gfits_db_close (&temp_db);
+    fprintf (stderr, "temporary database closed\n");
+ 
+    /* check / load main database */
+    if (!gfits_db_lock (&image_db, ImageDB)) {
+      gfits_db_close (&image_db);
+      fprintf (stderr, "error locking image db (path missing? access permission?)\n");
+      exit (1);
+    }
+    if (temp_db.dbstate == LCK_EMPTY) {
+      fprintf (stderr, "main database empty\n");
+      gfits_db_close (&image_db);
+      gfits_db_free (&temp_db);
+      goto next;
+      /* this is a type of error: we read entries from the
+	 temp db, but there were no entries to match in the main db
+	 we will just drop the temp db data */
+    }
+    image = gfits_table_get_RegImage (&image_db.ftable, &Nimage, &image_db.swapped);
+    fprintf (stderr, "main database read\n");
+
+    /* match temp image with main images */
+    match = match_images (image, Nimage, subset, Nsubset, &Nmatch);
+    if (Nmatch != Nsubset) fprintf (stderr, "WARNING: some images missed\n");
+
+    /* update entries in main db */
+    gfits_vtable_from_ftable (&image_db.ftable, &image_db.vtable, match, Nmatch);
+    for (i = 0; i < Nmatch; i++) {
+      gfits_convert_RegImage ((RegImage *) image_db.vtable.buffer[i], sizeof (RegImage), 1);
+    }
+    gfits_db_update (&image_db);
+    gfits_db_close (&image_db);
+
+    gfits_db_free (&image_db);
+    gfits_db_free (&temp_db);
+    if (match != NULL) free (match);
+    if (image != NULL) free (image);
+      
+  next:
+    fflush (stderr);
+    fflush (stdout);
+    sleep (LOOP_DELAY);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/photcode-table.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/photcode-table.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/photcode-table.c	(revision 16632)
@@ -0,0 +1,102 @@
+# include "imregister.h"
+enum {NONE, IMPORT, EXPORT};
+
+char CatdirPhotcodeFile[256];
+char MasterPhotcodeFile[256];
+
+int args (int argc, char **argv);
+int ConfigInitLocal (int *argc, char **argv);
+void GetConfig (char *config, char *field, char *format, int N, void *ptr);
+void usage ();
+
+int main (int argc, char **argv) {
+
+  int mode;
+
+  ConfigInitLocal (&argc, argv);
+  mode = args (argc, argv);
+    
+  if (mode == IMPORT) {
+    LoadPhotcodesText (MasterPhotcodeFile);
+    SavePhotcodesFITS (CatdirPhotcodeFile);
+    exit (0);
+  }
+
+  if (mode == EXPORT) {
+    LoadPhotcodesFITS (CatdirPhotcodeFile);
+    SavePhotcodesText (MasterPhotcodeFile);
+    exit (0);
+  }
+
+  usage ();
+  exit (1);
+}
+
+int args (int argc, char **argv) {
+
+  int N, mode;
+
+  /* check for help request */
+  if (get_argument (argc, argv, "-help")) usage ();
+  if (get_argument (argc, argv, "-h")) usage ();
+
+  mode = NONE;
+  if ((N = get_argument (argc, argv, "-import"))) {
+    mode = IMPORT;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-export"))) {
+    mode = EXPORT;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) usage ();
+
+  strcpy (MasterPhotcodeFile, argv[1]);
+  return (mode);
+}
+
+int ConfigInitLocal (int *argc, char **argv) {
+
+  char *config, *file;
+  char CATDIR[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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);
+  }
+  // if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  GetConfig (config, "CATDIR",                 	"%s",  0, CATDIR);
+  // GetConfig (config, "PHOTCODE_FILE",          	"%s",  0, MasterPhotcodeFile);
+  
+  // set the CATDIR version based on CATDIR
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+
+  free (config);
+  free (file);
+  return TRUE;
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
+
+void usage () {
+
+  fprintf (stderr, "USAGE: photcode-table -export (textfile) [-D CATDIR catdir]\n");
+  fprintf (stderr, "USAGE: photcode-table -import (textfile) [-D CATDIR catdir]\n");
+  exit (2);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/photcode.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/photcode.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/photcode.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "imregister.h"
+static char *version = "photcode $Revision: 3.4 $";
+
+int main (int argc, char **argv) {
+
+  Header header;
+  char detector[80], filter[80], *ID;
+  int i, ccd, VERBOSE, N, Nfilter;
+
+  get_version (argc, argv, version);
+  ConfigInit (&argc, argv);
+  ConfigCamera ();
+  ConfigFilter ();
+
+  VERBOSE = TRUE;
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = FALSE;
+  }
+
+  if (argc != 4) { 
+    fprintf (stderr, "USAGE: photcode (file.fits) (ccd) (mode)\n");
+    exit (1);
+  }
+
+  /* read in image header */
+  if (!gfits_read_header (argv[1], &header)) {
+    if (VERBOSE) fprintf (stderr, "ERROR: can't find image file %s (1)\n", argv[1]);
+    exit (1);
+  }
+
+  gfits_scan (&header, CameraKeyword, "%s", 1, detector);
+  for (i = 0; i < strlen(detector); i++) { detector[i] = toupper (detector[i]); }
+  for (i = 0; i < strlen(detector); i++) { if (isspace (detector[i])) detector[i] = '.'; }
+
+  gfits_scan (&header, FilterKeyword,   "%s", 1, filter);
+  for (i = 0; i < strlen (filter); i++) { if (isspace (filter[i])) filter[i] = '.'; }
+  Nfilter = FILTER_NONE;
+  for (i = 0; (i < NFILTER) && (Nfilter == FILTER_NONE); i++) {
+    if (!strcasecmp (filter, filtername[i])) {
+      Nfilter = filternum[i];
+    }
+  }      
+  if (Nfilter == FILTER_NONE) {
+    fprintf (stderr, "ERROR: invalid filter %s\n", filter);
+    exit (1);
+  }
+  strcpy (filter, filterhash[Nfilter]);
+
+  if (!strcasecmp (argv[3], "mef")) {
+    ID = strcreate (argv[2]);
+  } else {
+    ALLOCATE (ID, char, 80);
+    gfits_scan (&header, CCDnumKeyword,  "%s", 1, ID);
+  }
+  ccd = -1;
+  for (i = 0; (i < Nccd) && (ccd == -1); i++) {
+    if (strnumcmp (ccds[i], ID)) {
+      ccd = i;
+    }
+  }
+  if (ccd == -1) {
+    fprintf (stderr, "warning: ccd %d not found in camera config file\n", ccd);
+    ccd = 0;
+  }
+
+  fprintf (stdout, "%s.%s.%02d\n", detector, filter, ccd);
+
+  exit (0);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/photreg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/photreg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/photreg.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "imregister.h"
+# include "photreg.h"
+static char *version = "photreg $Revision: 1.9 $";
+
+int main (int argc, char **argv) {
+ 
+  char *filename;
+  PhotPars newdata;
+  FITS_DB db;
+  
+  get_version (argc, argv, version);
+  regargs (argc, argv, &newdata);
+
+  db.lockstate = LCK_HARD;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  filename = PhotDB;
+  if (!strcmp (output.db, "trans")) filename = TransDB;
+
+  if (!gfits_db_lock (&db, filename)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    gfits_db_create (&db);
+    gfits_table_set_PhotPars (&db.ftable, NULL, 0);
+    /* EXTNAME is set to ZERO_POINTS_3.0 by default */
+    if (!strcmp (output.db, "trans")) {
+      gfits_modify (&db.theader, "EXTNAME", "%s", 1, "TRANS_POINTS_3.0");
+    }
+  } else {  
+    if (!gfits_db_load (&db)) {
+      fprintf (stderr, "ERROR: failure to load db\n");
+      gfits_db_close (&db);
+      exit (1);
+    }
+  }
+
+  /** we may later want to pull this out and put it elsewhere **/
+  gfits_convert_PhotPars (&newdata, sizeof (PhotPars), 1);
+  gfits_table_to_vtable (&db.ftable, &db.vtable, 0, 0);
+  gfits_vadd_rows (&db.vtable, (char *) &newdata, 1, sizeof(PhotPars));
+
+  gfits_db_update (&db);
+  gfits_db_close (&db);
+  gfits_db_free (&db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+  /* data values are set in args by matching flags */
+
+/*** stick the header, table, theader, ftable creation in a single API? ***/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/photsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/photsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/photsearch.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "imregister.h"
+# include "photreg.h"
+static char *version = "photsearch $Revision: 1.9 $";
+
+int main (int argc, char **argv) {
+
+  char *filename;
+  int Nmatch, Nphotpars;
+  int *match;
+  FITS_DB db;
+  PhotPars *photpars;
+  PhotParsOld *photpars_old;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+
+  db.lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  if (!strcmp (output.db, "phot")) {
+    filename = PhotDB;
+  } else {
+    filename = TransDB;
+  }
+
+  if (!gfits_db_lock (&db, filename)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  
+  if (!gfits_db_load (&db)) {
+    fprintf (stderr, "ERROR: failure to load db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+
+  if (!output.modify && !output.delete) gfits_db_close (&db);
+
+  /* add test to EXTNAME? */
+  if (output.convert) {
+    photpars_old = gfits_table_get_PhotParsOld (&db.ftable, &Nphotpars, &db.swapped);
+    photpars = PhotParsOld_to_PhotPars (photpars_old, Nphotpars);
+  } else {
+    photpars = gfits_table_get_PhotPars (&db.ftable, &Nphotpars, &db.swapped);
+  }
+
+  match = match_criteria (photpars, Nphotpars, &Nmatch);
+
+  if (output.delete) DeleteSubset (&db, photpars, Nphotpars, match, Nmatch);
+
+  OutputSubset (photpars, Nphotpars, match, Nmatch);
+  exit (0);
+}
+
+  /* db selection is set in args, based on -trans */
+
+/* valid EXTNAME values:
+
+   phot, !output.convert, bintable: "ZERO_POINTS_3.0"
+   phot, !output.convert, table:    "IMAGE_ZPTS"
+
+   trans, !output.convert, bintable: "TRANS_POINTS_3.0"
+   trans, !output.convert, table:    "SUMMARY_ZPTS"
+
+   phot, !output.convert, bintable: "ZERO_POINTS"
+   phot, !output.convert, table:    "IMAGE_ZPTS"
+
+   trans, !output.convert, bintable: "TRANS_POINTS"
+   trans, !output.convert, table:    "SUMMARY_ZPTS"
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/showiminfo.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/showiminfo.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/showiminfo.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "imregister.h"
+# include "imreg.h"
+static char *version = "showiminfo $Revision: 3.2 $";
+
+int main (int argc, char **argv) {
+ 
+  char *obstime, *regtime;
+  RegImage *image, im;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+  image = iminfo (argv[1]);
+  im = image[0];
+  
+  fprintf (stderr, "\n");
+  fprintf (stderr, "filename: %s\n",   im.filename);
+  fprintf (stderr, "pathname: %s\n",   im.pathname);
+  fprintf (stderr, "filter: %s\n",     im.filter);
+  fprintf (stderr, "instrument: %s\n\n", im.instrument);
+
+  fprintf (stderr, "ccd: %d, mode: %d, type: %d\n\n", im.ccd, im.mode, im.type);
+
+  fprintf (stderr, "exptime: %f, airmass: %f, telfocus: %f\n", im.exptime, im.airmass, im.telfocus);
+  fprintf (stderr, "xprobe: %f, yprobe: %f, zprobe: %f\n", im.xprobe, im.yprobe, im.zprobe);
+  fprintf (stderr, "dettemp: %f, temp0: %f temp1: %f, temp2: %f, temp3: %f\n\n", 
+	   im.dettemp, im.teltemp_0, im.teltemp_1, im.teltemp_2, im.teltemp_3);
+
+  fprintf (stderr, "ra: %f, dec: %f, rotangle: %f\n", im.ra, im.dec, im.rotangle);
+
+  obstime = ohana_sec_to_date (im.obstime);
+  regtime = ohana_sec_to_date (im.regtime);
+
+  fprintf (stderr, "obstime: %s\n", obstime);
+  fprintf (stderr, "regtime: %s\n", regtime);
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/spregister.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/spregister.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/spregister.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "imregister.h"
+# include "spreg.h"
+static char *version = "spregister $Revision: 1.9 $";
+
+int main (int argc, char **argv) {
+ 
+  Spectrum *spectrum;
+  FITS_DB db;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+
+  spectrum = spinfo (argv[1]);
+
+  if (DUMP) showinfo (spectrum);
+
+  if (NoReg) exit (0);
+
+  db.lockstate = LCK_HARD;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  if (!gfits_db_lock (&db, SpectrumDB)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    gfits_db_create (&db);
+    gfits_table_set_Spectrum (&db.ftable, NULL, 0);
+  } else {  
+    if (!gfits_db_load (&db)) {
+      fprintf (stderr, "ERROR: failure to load db\n");
+      gfits_db_close (&db);
+      exit (1);
+    }
+  }
+
+  gfits_convert_Spectrum (spectrum, sizeof (Spectrum), 1);
+  gfits_table_to_vtable (&db.ftable, &db.vtable, 0, 0);
+  gfits_vadd_rows (&db.vtable, (char *) spectrum, 1, sizeof(Spectrum));
+
+  gfits_db_update (&db);
+  gfits_db_close (&db);
+  gfits_db_free (&db);
+
+  fprintf (stderr, "SUCCESS\n");
+  exit (0);
+}
+
+
+/* notes:
+   SpectrumDB set in args:ConfigInit by config variable SPECTRUM_DB
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/imregister/src/spsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/imregister/src/spsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/imregister/src/spsearch.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "imregister.h"
+# include "spreg.h"
+static char *version = "spsearch $Revision: 1.8 $";
+
+int main (int argc, char **argv) {
+ 
+  int Nmatch, Nspectrum, *match;
+  Spectrum *spectrum;
+  FITS_DB db;
+
+  get_version (argc, argv, version);
+  args (argc, argv);
+
+  db.lockstate = (output.modify || output.delete) ? LCK_HARD : LCK_SOFT;
+  db.timeout   = 300.0;
+  gfits_db_init (&db);
+
+  if (!gfits_db_lock (&db, SpectrumDB)) {
+    fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+  if (!gfits_db_load (&db)) {
+    fprintf (stderr, "ERROR: failure to load db\n");
+    gfits_db_close (&db);
+    exit (1);
+  }
+
+  if (!output.modify && !output.delete) gfits_db_close (&db);
+
+  spectrum = gfits_table_get_Spectrum (&db.ftable, &Nspectrum, &db.swapped);
+  
+  match = match_criteria (spectrum, Nspectrum, &Nmatch);
+  match = unique_entries (spectrum, Nspectrum, match, &Nmatch);
+
+  if (output.modify) ModifySubset (&db, spectrum, Nspectrum, match, Nmatch);
+  if (output.delete) DeleteSubset (&db, spectrum, Nspectrum, match, Nmatch);
+
+  OutputSubset (spectrum, Nspectrum, match, Nmatch);
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/Makefile	(revision 16632)
@@ -0,0 +1,76 @@
+default: kapa
+help:
+	@echo "make options: kapa (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/kapa
+LIB	=	$(HOME)/lib
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+EDIR	=	$(HOME)/event
+GDIR	=	$(HOME)/graph
+SDIR	=	$(HOME)/setup
+INC	=	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+LDDEPS  = $(DESTLIB)/libkapa.a $(DESTLIB)/libdvo.a $(DESTLIB)/libFITS.a $(DESTLIB)/libohana.a
+INDEPS  = $(DESTINC)/kapa.h $(DESTINC)/dvo.h $(DESTINC)/gfitsio.h $(DESTINC)/ohana.h
+
+kapa: $(BIN)/kapa.$(ARCH)
+install: $(DESTBIN)/kapa
+
+# local source / object files ########################
+EOBJ = \
+$(EDIR)/CheckPipe.$(ARCH).o               $(EDIR)/Stop.$(ARCH).o               \
+$(EDIR)/EventLoop.$(ARCH).o         	  $(EDIR)/Reconfig.$(ARCH).o           \
+$(EDIR)/SetFont.$(ARCH).o           	  $(EDIR)/PositionPicture.$(ARCH).o\
+$(EDIR)/InterpretKeys.$(ARCH).o     	  $(EDIR)/Refresh.$(ARCH).o		\
+$(EDIR)/SetSection.$(ARCH).o		  $(EDIR)/FlushDisplay.$(ARCH).o	\
+$(EDIR)/Resize.$(ARCH).o
+
+GOBJ = \
+$(GDIR)/DrawObjects.$(ARCH).o             $(GDIR)/DrawFrame.$(ARCH).o       	\
+$(GDIR)/DrawText.$(ARCH).o		  $(GDIR)/LoadObject.$(ARCH).o		\
+$(GDIR)/ErasePlot.$(ARCH).o		  $(GDIR)/LoadBox.$(ARCH).o		\
+$(GDIR)/SetLimits.$(ARCH).o               $(GDIR)/PSObjects.$(ARCH).o		\
+$(GDIR)/DrawLabels.$(ARCH).o              $(GDIR)/LoadLabels.$(ARCH).o		\
+$(GDIR)/cursor.$(ARCH).o 		  $(GDIR)/PSFrame.$(ARCH).o		\
+$(GDIR)/LoadPtext.$(ARCH).o		  $(GDIR)/DrawPtext.$(ARCH).o		\
+$(GDIR)/PSLabels.$(ARCH).o		  $(GDIR)/PSPtext.$(ARCH).o		\
+$(GDIR)/PPMit.$(ARCH).o	          \
+
+BDRAW = \
+$(GDIR)/bDrawIt.$(ARCH).o	  	  $(GDIR)/bDrawFrame.$(ARCH).o          \
+$(GDIR)/bDrawLabels.$(ARCH).o             $(GDIR)/bDrawObjects.$(ARCH).o        \
+$(GDIR)/PNGit.$(ARCH).o \
+
+SOBJ = \
+$(SDIR)/CheckColors.$(ARCH).o             $(SDIR)/MakeGC.$(ARCH).o             \
+$(SDIR)/CheckDisplayName.$(ARCH).o  	  $(SDIR)/MapWindow.$(ARCH).o          \
+$(SDIR)/CheckFontName.$(ARCH).o     	  $(SDIR)/NameWindow.$(ARCH).o         \
+$(SDIR)/CheckGeometry.$(ARCH).o     	  $(SDIR)/OpenDisplay.$(ARCH).o        \
+$(SDIR)/CloseDisplay.$(ARCH).o      	  $(SDIR)/QuitX.$(ARCH).o              \
+$(SDIR)/CreateWindow.$(ARCH).o      	  $(SDIR)/SetNormalHints.$(ARCH).o     \
+$(SDIR)/DefineLayout.$(ARCH).o      	  $(SDIR)/SetUpDisplay.$(ARCH).o       \
+$(SDIR)/SetUpWindow.$(ARCH).o        	  $(SDIR)/args.$(ARCH).o               \
+$(SDIR)/GetColor.$(ARCH).o          	  $(SDIR)/SetWMHints.$(ARCH).o         \
+$(SDIR)/LoadFont.$(ARCH).o          	  $(SDIR)/TopWindow.$(ARCH).o          \
+$(SDIR)/Ximage.$(ARCH).o             \
+$(SDIR)/MakeCursor.$(ARCH).o
+
+OBJ  =  $(EOBJ) $(GOBJ) $(SOBJ) $(BDRAW)
+
+# dependancy rules for include files ########################
+$(OBJ): $(INC)/Ximage.h \
+	$(INC)/constants.h \
+	$(INC)/structures.h \
+	$(INC)/prototypes.h
+
+$(OBJ): $(INDEPS) $(LDDEPS)
+
+$(BIN)/kapa.$(ARCH): $(OBJ)
Index: /branches/eam_branch_20080223/Ohana/src/kapa/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/kapa/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,31 @@
+
+- kapa 1.6 : 2006.08.23
+  * some PNG fixes
+  * converted to gfits APIs (forces libfits 1.6)
+  * removed items moved to libkapa
+
+- kapa 1.5
+  * fixed residual label text
+  * fixed box -axis,-label,-ticks bug (was ignoring user input) 
+  * dropped unused axis.label (is replaced by label.text)
+  * fixed bug in event loop which missed certain mask types
+  * fixed bDrawLabel error
+  * changed comms to libkapa functions
+
+- kapa 1.4
+  * major work to allow noX operation
+  * added bDraw functions
+  * integrated with libkapa
+
+kapa-1-3: released 2005.10.20
+  changed cursor interaction (returns name for keys)
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+kapa-1-2: released 2005.08.15
+  cleaned up complaints from -Wall -Werror.  mostly defining 
+  prototypes, removing unused variables, pushing Graphcolors
+    into the MakeColormap function 
+
+kapa-1-1:
+  fixed up the event loop to reduce excess cpu spinning.
+  cleaned up the color structure
Index: /branches/eam_branch_20080223/Ohana/src/kapa/doc/VERSIONS
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/doc/VERSIONS	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/doc/VERSIONS	(revision 16632)
@@ -0,0 +1,5 @@
+
+tag names used by kapa:
+
+TAG         : Comment
+kapa-1-0    : first version under CVS
Index: /branches/eam_branch_20080223/Ohana/src/kapa/doc/input
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/doc/input	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/doc/input	(revision 16632)
@@ -0,0 +1,87 @@
+
+macro colortest
+  lim 0 1 0 1; clear; box
+
+  style -x 2 -pt 0 -sz 3.0
+  dot -c black     0.1 0.9
+  dot -c white     0.2 0.9
+  dot -c red       0.3 0.9
+  dot -c pink      0.4 0.9
+  dot -c orange    0.5 0.9
+  dot -c yellow    0.1 0.8
+  dot -c wheat     0.2 0.8
+  dot -c gold      0.3 0.8
+  dot -c green     0.4 0.8
+  dot -c darkgreen 0.5 0.8
+  dot -c blue      0.1 0.7
+  dot -c skyblue   0.2 0.7
+  dot -c indigo    0.3 0.7
+  dot -c violet    0.4 0.7
+  dot -c grey10    0.5 0.7
+  dot -c grey20    0.1 0.6
+  dot -c grey30    0.2 0.6
+  dot -c grey40    0.3 0.6
+  dot -c grey50    0.4 0.6
+  dot -c grey60    0.5 0.6
+  dot -c grey70    0.1 0.5
+  dot -c grey80    0.2 0.5
+  dot -c grey90    0.3 0.5
+end
+
+macro colortest2
+  lim 0 1 0 1; clear; box
+
+  style -x 2 -pt 7 -sz 3.0
+  dot -c black     0.1 0.9
+  dot -c white     0.2 0.9
+  dot -c red       0.3 0.9
+  dot -c pink      0.4 0.9
+  dot -c orange    0.5 0.9
+  dot -c yellow    0.1 0.8
+  dot -c wheat     0.2 0.8
+  dot -c gold      0.3 0.8
+  dot -c green     0.4 0.8
+  dot -c darkgreen 0.5 0.8
+  dot -c blue      0.1 0.7
+  dot -c skyblue   0.2 0.7
+  dot -c indigo    0.3 0.7
+  dot -c violet    0.4 0.7
+  dot -c grey10    0.5 0.7
+  dot -c grey20    0.1 0.6
+  dot -c grey30    0.2 0.6
+  dot -c grey40    0.3 0.6
+  dot -c grey50    0.4 0.6
+  dot -c grey60    0.5 0.6
+  dot -c grey70    0.1 0.5
+  dot -c grey80    0.2 0.5
+  dot -c grey90    0.3 0.5
+end
+
+macro pltest
+  lim 0 1 0 1; clear; box
+
+  style -x 2 -pt 7 -sz 3.0 -lw 2
+  dot -c black     0.1 0.9
+  dot -c white     0.2 0.9
+  dot -c red       0.3 0.9
+  dot -c pink      0.4 0.9
+  dot -c orange    0.5 0.9
+  dot -c yellow    0.1 0.8
+  dot -c wheat     0.2 0.8
+  dot -c gold      0.3 0.8
+  dot -c green     0.4 0.8
+  dot -c darkgreen 0.5 0.8
+  dot -c blue      0.1 0.7
+  dot -c skyblue   0.2 0.7
+  dot -c indigo    0.3 0.7
+  dot -c violet    0.4 0.7
+  dot -c grey10    0.5 0.7
+  dot -c grey20    0.1 0.6
+  dot -c grey30    0.2 0.6
+  dot -c grey40    0.3 0.6
+  dot -c grey50    0.4 0.6
+  dot -c grey60    0.5 0.6
+  dot -c grey70    0.1 0.5
+  dot -c grey80    0.2 0.5
+  dot -c grey90    0.3 0.5
+end
Index: /branches/eam_branch_20080223/Ohana/src/kapa/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/doc/notes.txt	(revision 16632)
@@ -0,0 +1,36 @@
+
+2005.11.27
+
+	I am improving the functionality of kapa so that it does not
+	need to have an X server to build PNG / PPM / PS plots.
+	Before, I generated the PNG / PPM plots from the screen image
+	by using an X function to examine the color of each pixel and
+	generate the corresponding PNG/PPM image.  This implied that
+	an X server was required even if the window was not being
+	looked at.  The PS version of the plots were not quite so
+	difficult: the PS code is generated from the plot when the PS
+	output file is constructed.  I decided to implement the
+	equivalent concept for the PNG/PPM images. 
+
+	I have build a set of drawing functions which are used by the
+	PNG function (PPM not yet implemented) to create the PNG image
+	buffer from the graphic objects stored by Kapa.  This
+	subsystem is called bDraw.  Most of the drawing functions
+	correspond to just the primitive point, line, and circle
+	functions.  I have implemented bDrawPoint, bDrawLine,
+	bDrawCircle, and demonstrated the complete concept.  At this
+	point, only a few features are missing:
+
+	- line weight.  the bDraw functions do not respect the value
+          of the line weight (which is available to them).  All lines
+          and circles are drawn as line weight 1.
+
+	- line type.  no line type data is used. (Kapa probably over
+          respects it: it should not apply the line type to the point
+          plotting)
+
+	- rectangles and triangles.  several of the point-types are
+          constructed by calling bDrawRect, bDrawTri, neither of which
+          are implemented at this time.
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/CheckPipe.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/CheckPipe.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/CheckPipe.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include "Ximage.h"
+# define STRCONST(A) ((int)(0x1000000*A[0] + 0x10000*A[1] + 0x100*A[2] + 0x1*A[3]))
+
+int CheckPipe () {
+
+  int status;
+  char buffer[32];
+
+  /***** read (4 byte) message word from socket ****/
+  status = read (sock, buffer, 4);
+  buffer[4] = 0;
+  switch (status) {
+  case -1:                          /* no input from pipe: continue */
+    return (TRUE);
+    break;
+
+  case 0:
+    fprintf (stderr, "pipe has died!\n");
+    return (FALSE);
+    break;
+
+  case 4:
+    break;
+
+  default:
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+    break;
+  }
+  
+  /***** handle different messages ****/
+  if (!strcmp (buffer, "QUIT")) return (FALSE);
+  
+  if (!strcmp (buffer, "PSIT")) {
+    status = PSit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PNGF")) {
+    status = PNGit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "PPMF")) {
+    status = PPMit ();
+    write (sock, "DONE", 4);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "RSIZ")) {
+    status = Resize ();
+    return (status);
+  }
+
+  if (!strcmp (buffer, "PLOT")) {
+    status = LoadObject ();
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "LIMS")) {
+    KiiSendMessage (sock, "%8.1f %8.1f ", 
+		    section[TheSection].axis[0].dfx, 
+		    section[TheSection].axis[1].dfy);
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "SLIM")) {
+    status = SetLimits ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "LABL")) {
+    status = LoadLabels ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "LSEC")) {
+    status = ListSection ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "DSEC")) {
+    status = SetSection (FALSE);
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "SSEC")) {
+    status = SetSection (TRUE);
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "PTXT")) {
+    status = LoadPtext ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "FONT")) {
+    status = SetFont ();
+    return (TRUE);
+  }
+  
+  if (!strcmp (buffer, "CURS")) {
+    cursor ();
+    return (TRUE);
+  }
+  
+  /* Erase Section */
+  if (!strcmp (buffer, "ERAS")) {
+    status = ErasePlot (TRUE);
+    return (status);
+  }
+  
+  /* Don't Erase Section */
+  if (!strcmp (buffer, "ERSS")) {
+    status = ErasePlot (FALSE);
+    return (status);
+  }
+  
+  if (!strcmp (buffer, "DBOX")) {
+    status = LoadBox ();
+    return (status);
+  }
+  
+  fprintf (stderr, "unknown signal %s\n", buffer);
+
+  return (TRUE);
+
+}
+
+
+    
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/EventLoop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/EventLoop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/EventLoop.c	(revision 16632)
@@ -0,0 +1,139 @@
+# include "Ximage.h"
+
+/* # define IgnoreMask (long) (ButtonPressMask | ClientMessage | ButtonReleaseMask | KeyPressMask | PointerMotionMask) */
+
+/* list events being selected below, all other masks are ignored */ 
+# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask))
+
+int LastEvent (Display *display, int type, XEvent *event) {
+
+  int found;
+
+  found = FALSE;
+  while (XCheckTypedEvent (display, type, event)) {
+    found = TRUE;
+  }
+  return (found);
+}
+
+int EventLoop () {
+  
+  XEvent          event;
+  int             status;
+  Display        *display;
+  
+  if (USE_XWINDOW) Refresh (1);
+
+  status = TRUE;
+  while (status) {
+    
+    if (!CheckPipe ()) return (FALSE);
+    
+    if (!USE_XWINDOW) {
+      usleep (50000);
+      continue;
+    }
+
+    if (XEventsQueued (graphic.display, QueuedAfterFlush) < 1) {
+	/* fprintf (stderr, "."); */
+      usleep (50000);
+      continue;
+    }
+
+    display = graphic.display;
+
+    /* grab the last entry for these events */
+    if (LastEvent (display, ConfigureNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, CirculateNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, Expose,          &event)) Refresh (1);
+
+    if (LastEvent (display, MappingNotify,   &event)) XRefreshKeyboardMapping ((XMappingEvent *) &event);
+
+    /* drop and ignore the following StructureNotifyMask events */
+    LastEvent (display, GravityNotify, &event);
+    LastEvent (display, ReparentNotify, &event);
+    LastEvent (display, MapNotify, &event);
+    LastEvent (display, UnmapNotify, &event);
+
+    /* remove those events we will ignore */
+    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;
+
+    /* events to remove which have no mask component */
+    while (XCheckTypedEvent (display, MappingNotify, &event)) continue;
+    while (XCheckTypedEvent (display, ClientMessage, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionClear, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionNotify, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionRequest, &event)) continue;
+  }
+  return (status);
+}
+
+# if (0)
+
+/* all masks from X.h for reference: */
+
+#define NoEventMask                     0L
+#define KeyPressMask                    (1L<<0)
+#define KeyReleaseMask                  (1L<<1)
+#define ButtonPressMask                 (1L<<2)
+#define ButtonReleaseMask               (1L<<3)
+#define EnterWindowMask                 (1L<<4)
+#define LeaveWindowMask                 (1L<<5)
+#define PointerMotionMask               (1L<<6)
+#define PointerMotionHintMask           (1L<<7)
+#define Button1MotionMask               (1L<<8)
+#define Button2MotionMask               (1L<<9)
+#define Button3MotionMask               (1L<<10)
+#define Button4MotionMask               (1L<<11)
+#define Button5MotionMask               (1L<<12)
+#define ButtonMotionMask                (1L<<13)
+#define KeymapStateMask                 (1L<<14)
+#define ExposureMask                    (1L<<15)
+#define VisibilityChangeMask            (1L<<16)
+#define StructureNotifyMask             (1L<<17)
+#define ResizeRedirectMask              (1L<<18)
+#define SubstructureNotifyMask          (1L<<19)
+#define SubstructureRedirectMask        (1L<<20)
+#define FocusChangeMask                 (1L<<21)
+#define PropertyChangeMask              (1L<<22)
+#define ColormapChangeMask              (1L<<23)
+#define OwnerGrabButtonMask             (1L<<24)
+
+/* all events from X.h for reference: */
+
+#define KeyPress                2
+#define KeyRelease              3
+#define ButtonPress             4
+#define ButtonRelease           5
+#define MotionNotify            6
+#define EnterNotify             7
+#define LeaveNotify             8
+#define FocusIn                 9
+#define FocusOut                10
+#define KeymapNotify            11
+#define Expose                  12
+#define GraphicsExpose          13
+#define NoExpose                14
+#define VisibilityNotify        15
+#define CreateNotify            16
+#define DestroyNotify           17
+#define UnmapNotify             18
+#define MapNotify               19
+#define MapRequest              20
+#define ReparentNotify          21
+#define ConfigureNotify         22
+#define ConfigureRequest        23
+#define GravityNotify           24
+#define ResizeRequest           25
+#define CirculateNotify         26
+#define CirculateRequest        27
+#define PropertyNotify          28
+#define SelectionClear          29
+#define SelectionRequest        30
+#define SelectionNotify         31
+#define ColormapNotify          32
+#define ClientMessage           33
+#define MappingNotify           34
+#define LASTEvent               35      /* must be bigger than any event # */
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/FlushDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/FlushDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/FlushDisplay.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+void FlushDisplay () {
+
+  struct timeval now;
+  int flush;
+  double dtime;
+
+  if (!USE_XWINDOW) return;
+
+  flush = FALSE;
+  if (!reftimeset) {
+    flush = TRUE;
+    gettimeofday (&reftime, NULL);
+  } 
+
+  gettimeofday (&now, NULL);
+  dtime = DTIME (now, reftime);
+
+  if (dtime > 0.1) {
+    flush = TRUE;
+  }
+
+  if (flush) {
+    XFlush (graphic.display);
+    reftime = now;
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/InterpretKeys.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/InterpretKeys.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/InterpretKeys.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+int InterpretKeys (XEvent *event) {
+
+  int    status;
+  KeySym keysym;
+  char            string[10];
+  XComposeStatus  composestatus;
+
+  XLookupString ((XKeyEvent *)event, string, 9, &keysym, &composestatus);
+
+  switch (keysym) {
+
+  default:
+    status = TRUE;
+  }
+
+  return (status);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/InterpretPresses.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/InterpretPresses.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/InterpretPresses.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+
+int 
+InterpretPresses (graphic, layout, event)
+Graphic        graphic[];
+Layout         layout[];
+XButtonEvent   event[];
+{
+
+  int             status, done, this_button, x, y, old_cursor;
+  KeySym          keysym;
+  Button         *button;
+
+  status = TRUE;
+  this_button = event[0].button;
+  
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].picture)) {
+    Reorient (graphic, layout, event);
+  }
+
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].cmapbar)) {
+    DragColorbar (graphic, layout, event);
+  }
+
+  /* if on an exisiting button, Invert, wait for release, then go (or not) */
+  if ((button = CheckButtons (event, layout)) != (Button *) NULL) {
+    InvertButton (graphic, button); 
+    done = FALSE;
+    while (!done) { /* wait for release of this button */
+      XNextEvent (graphic[0].display, (XEvent *) event);
+      if ((event[0].type == ButtonRelease) && (event[0].button == this_button)) {
+	done = TRUE;
+      }
+    }
+    DrawButton (graphic, button);
+    if (InButton (event, button)) {
+      switch (event[0].button) {
+      case 1:
+	status = button[0].function_1(graphic, layout);
+	break;
+      case 2:
+	status = button[0].function_2(graphic, layout);
+	break;
+      case 3:
+	status = button[0].function_3(graphic, layout);
+	break;
+      }
+    }
+    else {
+      return (status);
+    }
+  }
+
+  return (status);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/PositionPicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/PositionPicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/PositionPicture.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include "Ximage.h"
+
+void PositionPicture (Layout *layout) {
+
+  int fontsize, bump, Nc;
+  double PADx, PADy, Dx, Dy;
+  double PXm, PXp, PYm, PYp;
+  double X0, Y0, dX, dY;
+  char string[64], *fontname;
+
+  fontname = GetRotFont (&fontsize);
+
+  /* window has outer bounding box with margins Wx, Wy 
+     section commands subdivide the internal box (Dx,Dy)
+   */
+
+  PADx = MAX (graphic.dx / 20.0, fontsize);
+  PADy = MAX (graphic.dy / 20.0, fontsize);
+  Dx = graphic.dx - 2*PADx;
+  Dy = graphic.dy - 2*PADy;
+
+  /* each graph has a padding PXm, PXp, PYm, PYp */
+  PXm = (layout[0].axis[1].islabel) ? 4*fontsize : 0;
+  PXp = (layout[0].axis[3].islabel) ? 4*fontsize : 0;
+  PYm = (layout[0].axis[0].islabel) ? 4*fontsize : 0;
+  PYp = (layout[0].axis[2].islabel) ? 4*fontsize : 0;
+ 
+  X0 = PADx + PXm + (Dx * layout[0].x);
+  Y0 = PADy + PYm + (Dy * layout[0].y);
+  dX = (Dx * layout[0].dx) - PXp - PXm;
+  dY = (Dy * layout[0].dy) - PYp - PYm;
+
+  /* define locations of coordinate axes */
+  layout[0].axis[0].fx  = X0;
+  layout[0].axis[0].fy  = graphic.dy - Y0;
+  layout[0].axis[0].dfx = dX;
+  layout[0].axis[0].dfy = 0;
+  
+  layout[0].axis[1].fx  = X0;
+  layout[0].axis[1].fy  = graphic.dy - Y0;
+  layout[0].axis[1].dfx = 0;
+  layout[0].axis[1].dfy = -dY;
+
+  layout[0].axis[2].fx  = X0;
+  layout[0].axis[2].fy  = graphic.dy - Y0 - dY;
+  layout[0].axis[2].dfx = dX;
+  layout[0].axis[2].dfy = 0;
+
+  layout[0].axis[3].fx  = X0 + dX;
+  layout[0].axis[3].fy  = graphic.dy - Y0;
+  layout[0].axis[3].dfx = 0;
+  layout[0].axis[3].dfy = -dY;
+
+  PADx = 0.8*fontsize + 2;
+  PADy = 3.0*fontsize + 4;
+
+  /* define locations of axis labels */
+  layout[0].label[LABELX0].x = layout[0].axis[0].fx + 0.5*layout[0].axis[0].dfx;
+  bump = (layout[0].axis[0].islabel) ? PADy : PADx;
+  layout[0].label[LABELX0].y = layout[0].axis[0].fy + bump;
+
+  layout[0].label[LABELX1].x = layout[0].axis[2].fx + 0.5*layout[0].axis[2].dfx;
+  bump = (layout[0].axis[2].islabel) ? PADy : PADx;
+  layout[0].label[LABELX1].y = layout[0].axis[2].fy - bump;
+
+  sprintf (string, "%4g", layout[0].axis[1].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g", layout[0].axis[1].max);
+  Nc = MAX (Nc, strlen (string));
+
+  layout[0].label[LABELY0].y = layout[0].axis[1].fy + 0.5*layout[0].axis[1].dfy;
+  bump = (layout[0].axis[1].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  layout[0].label[LABELY0].x = layout[0].axis[1].fx - bump;
+
+  sprintf (string, "%4g", layout[0].axis[1].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g", layout[0].axis[1].max);
+  Nc = MAX (Nc, strlen (string));
+
+  layout[0].label[LABELY1].y = layout[0].axis[3].fy + 0.5*layout[0].axis[3].dfy;
+  bump = (layout[0].axis[3].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  layout[0].label[LABELY1].x = layout[0].axis[3].fx + bump;
+  
+  /* these are wrong and have to be adjusted to sit in the corners */
+
+  layout[0].label[LABELUL].x = layout[0].axis[2].fx - PADx;
+  layout[0].label[LABELUL].y = layout[0].axis[2].fy - PADx;
+  layout[0].label[LABELUR].x = layout[0].axis[2].fx + layout[0].axis[2].dfx + PADx;
+  layout[0].label[LABELUR].y = layout[0].axis[2].fy - PADx;
+  layout[0].label[LABELLL].x = layout[0].axis[0].fx - PADx;
+  layout[0].label[LABELLL].y = layout[0].axis[0].fy + PADx;
+  layout[0].label[LABELLR].x = layout[0].axis[0].fx + layout[0].axis[0].dfx + PADx;
+  layout[0].label[LABELLR].y = layout[0].axis[0].fy + PADx;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/Reconfig.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/Reconfig.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/Reconfig.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "Ximage.h"
+
+int Reconfig (XEvent *event) {
+
+  int i;
+
+  if ((graphic.dx == event[0].xconfigure.width) &&
+      (graphic.dy == event[0].xconfigure.height)) 
+    return (TRUE);
+
+  graphic.dx = MAX(event[0].xconfigure.width,  MIN_WIDTH); 
+  graphic.dy = MAX(event[0].xconfigure.height, MIN_HEIGHT);
+
+  for (i = 0; i < Nsection; i++) {
+    PositionPicture (&section[i]);
+  }
+
+  XClearWindow (graphic.display, graphic.window);
+
+  Refresh (1);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/Refresh.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/Refresh.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/Refresh.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+
+void Refresh (int mode) {
+
+  int i;
+  
+  if (!USE_XWINDOW) return;
+  if (HAVE_BACKING) return;
+
+  /* XClearWindow   (graphic.display, graphic.window); */
+  XSetForeground (graphic.display, graphic.gc, graphic.back);
+  XFillRectangle (graphic.display, graphic.window, graphic.gc, 0, 0, graphic.dx, graphic.dy);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+  
+  for (i = 0; i < Nsection; i++) {
+    DrawFrame   (&section[i]);
+    DrawObjects (&section[i]);
+    DrawLabels  (&section[i]);
+    DrawPtext   (&section[i]);
+  }
+
+  FlushDisplay ();
+ 
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/Resize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/Resize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/Resize.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "Ximage.h"
+
+int Resize () {
+ 
+  int i;
+  unsigned int NX, NY;
+
+  KiiScanMessage (sock, "%d %d", &NX, &NY);
+
+  if ((graphic.dx == NX) && (graphic.dy == NY)) 
+    return (TRUE);
+
+  graphic.dx = MAX(NX, 50); 
+  graphic.dy = MAX(NY, 50); 
+
+  if (USE_XWINDOW) XResizeWindow (graphic.display, graphic.window, NX, NY);
+
+  for (i = 0; i < Nsection; i++) {
+    PositionPicture (&section[i]);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic.display, graphic.window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/SetFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/SetFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/SetFont.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+int SetFont () {
+  
+  char buffer[256], name[64];
+  int status, size;
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%s", name);
+  
+  status = read (sock, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%d", &size);
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  SetRotFont (name, size);
+  
+  return (TRUE);
+  
+}
+
+/*
+  layout[0].X = 0;
+  layout[0].Y = 0;
+  layout[0].expand = 1;
+  */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/SetSection.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/SetSection.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/SetSection.c	(revision 16632)
@@ -0,0 +1,114 @@
+# include "Ximage.h"
+
+int SetSection (int SwitchSection) {
+  
+  int i, NewSection, ThisSection, MoveSection;
+  char name[128];
+  double x, y, dx, dy;
+
+  if (SwitchSection) {
+    KiiScanMessage (sock, "%s", name);
+  } else {
+    KiiScanMessage (sock, "%s %lf %lf %lf %lf", name, &x, &y, &dx, &dy);
+  }    
+
+  NewSection = FALSE;
+  MoveSection = FALSE;
+  ThisSection = -1;
+  for (i = 0; i < Nsection; i++) {
+    if (!strcmp (name, section[i].name)) {
+      ThisSection = i;
+      break;
+    }
+  }
+
+  if (ThisSection == -1) {
+    if (SwitchSection) {
+      fprintf (stderr, "section %s not found\n", name);
+      return (TRUE);
+    }
+    NewSection = TRUE;
+    Nsection ++;
+    REALLOCATE (section, Layout, Nsection);
+    ThisSection = Nsection - 1;
+    strcpy (section[ThisSection].name, name);
+    section[ThisSection].Nobjects = 0;
+    section[ThisSection].Nptext = 0;
+    ALLOCATE (section[ThisSection].objects, Gobjects, 1);  /* allocate so later free will not crash! */
+    section[ThisSection].objects[0].x   = section[ThisSection].objects[0].y   = section[ThisSection].objects[0].z = (float *) NULL;
+    section[ThisSection].objects[0].dxm = section[ThisSection].objects[0].dxp = (float *) NULL;
+    section[ThisSection].objects[0].dym = section[ThisSection].objects[0].dyp = (float *) NULL;
+    ALLOCATE (section[ThisSection].ptext, Label, 1);       /* allocate so later free will not crash! */
+    for (i = 0; i < 4; i++) {
+      section[ThisSection].axis[i].min = 0;
+      section[ThisSection].axis[i].max = 1;
+      section[ThisSection].axis[i].isaxis = FALSE;
+      section[ThisSection].axis[i].areticks = FALSE;
+      section[ThisSection].axis[i].islabel = FALSE;
+    }    
+    for (i = 0; i < 8; i++) {
+      strcpy (section[ThisSection].label[i].text, "");
+    }
+  }
+
+  if (!SwitchSection) {
+    if (!NewSection && (section[ThisSection].x != x)) MoveSection = TRUE;
+    section[ThisSection].x = x;
+    if (!NewSection && (section[ThisSection].y != y)) MoveSection = TRUE;
+    section[ThisSection].y = y;
+    if (!NewSection && (section[ThisSection].dx != dx)) MoveSection = TRUE;
+    section[ThisSection].dx = dx;
+    if (!NewSection && (section[ThisSection].dy != dy)) MoveSection = TRUE;
+    section[ThisSection].dy = dy;
+
+    if (NewSection || MoveSection) {
+      PositionPicture (&section[ThisSection]);
+    }
+
+    if (MoveSection) {
+      XClearWindow (graphic.display, graphic.window);
+      Refresh (1);
+    } 
+    if (NewSection) {
+    }      
+  }
+
+  TheSection = ThisSection;
+
+  return (TRUE);
+  
+}
+
+int ListSection () {
+  
+  int i, ThisSection;
+  char name[128];
+
+  KiiScanMessage (sock, "%s", name);
+
+  if (!strcmp (name, "*")) {
+    for (i = 0; i < Nsection; i++) {
+      fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	       section[i].name, section[i].x, section[i].y, section[i].dx, section[i].dy);
+    }
+    return (TRUE);
+  }
+
+  ThisSection = -1;
+  for (i = 0; i < Nsection; i++) {
+    if (!strcmp (name, section[i].name)) {
+      ThisSection = i;
+      break;
+    }
+  }
+  if (ThisSection == -1) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	   section[ThisSection].name, 
+	   section[ThisSection].x, section[ThisSection].y, 
+	   section[ThisSection].dx, section[ThisSection].dy);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/event/Stop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/event/Stop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/event/Stop.c	(revision 16632)
@@ -0,0 +1,8 @@
+# include "Ximage.h"
+
+int Stop () {
+  return (FALSE);
+}
+
+/******  this function looks stupid, but it has to be like this:
+  it is called as a pointer to function **/
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawFrame.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawFrame.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawFrame.c	(revision 16632)
@@ -0,0 +1,161 @@
+# include "Ximage.h"
+# define DrawLine(X,Y,DX,DY) (XDrawLine (graphic.display, graphic.window, graphic.gc, (int)(X), (int)(Y), (int)(X+DX), (int)(Y+DY)))
+  
+void DrawFrame (Layout *layout) {
+  
+  int i, fx, fy, dfx, dfy, P, IsLabel;
+  double range, major, minor, first, next;
+
+  DrawRotTextInit (graphic.display, graphic.window, graphic.gc, graphic.fore, graphic.back);
+
+  /* each axis is drawn independently, but ticks and labels are placed according to
+     perpendicular distance. */
+  for (i = 0; i < 4; i++) {
+    fx = layout[0].axis[i].fx;
+    fy = layout[0].axis[i].fy;
+    dfx = layout[0].axis[i].dfx;
+    dfy = layout[0].axis[i].dfy;
+    P = hypot ((double)layout[0].axis[(i+1)%2].dfx, (double)layout[0].axis[(i+1)%2].dfy);
+
+    if (layout[0].axis[i].isaxis) {
+      DrawLine (fx, fy, dfx, dfy);
+    }
+    
+    if (layout[0].axis[i].areticks) {
+      range = layout[0].axis[i].max - layout[0].axis[i].min;
+      AxisTickScale (&layout[0].axis[i], &major, &minor);
+
+      first = minor*((int)(layout[0].axis[i].min/minor));
+      if ((range > 0) && (first < layout[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > layout[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= layout[0].axis[i].max)) || ((range < 0) && (next >= layout[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = layout[0].axis[i].islabel;
+	DrawTick (fx, fy, dfx, dfy, P, layout[0].axis[i].min, layout[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+}
+
+void DrawTick (int fx, int fy, int dfx, int dfy, 
+	       int P, double min, double max, 
+	       double value, int mode, int naxis) {
+  
+  int x, y, dx, dy, pos, dir, fontsize;
+  double size, n;
+  char string[64], *fontname;
+
+  if (mode) { 
+    size = MAX (0.02, 7.0 / P); 
+  } else {
+    size = MAX (0.01, 4.0 / P); 
+  }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+# ifdef IN_AND_OUT_TICKS
+# define GAP 0.03
+# else
+# define GAP 0.01
+# endif
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+    pos = 0;
+    
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value/(max-min)) < 0.001) { value = 0.0; }
+    sprintf (string, "%4g", value);
+    DrawRotText (x, y, string, pos, 0.0);
+  }
+  
+}
+
+
+void AxisTickScale (Axis *axis, double *major, double *minor) {
+
+  double range, lrange, factor, mantis, fmantis, power;
+
+  range = axis[0].max - axis[0].min;
+
+  lrange = log10(MAX(fabs(range), 1e-30));
+  mantis = modf (lrange, &factor);
+  if (mantis < 0.0) {
+    mantis += 1.0;
+    factor -= 1.0;
+  }
+  
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  *major = 0.5 * power;
+  *minor = 0.1 * power;
+  
+  if ((fmantis >= 1.0) && (fmantis <  1.999)) {
+    *major = 0.5 * power;
+    *minor = 0.1 * power;
+    if (axis[0].areticks == 1) {
+      *major = 1.0 * power;
+      *minor = 0.2 * power;
+    }	  
+  }
+  if ((fmantis >= 1.999) && (fmantis <  3.999)) {
+    *major = 1.0 * power;
+    *minor = 0.2 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 3.999) && (fmantis <  5.999)) {
+    *major = 1.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 5.999) && (fmantis <   7.999)) {
+    *major = 2.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.5 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 7.999) && (fmantis <  10.000)) {
+    *major = 2.5 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 5.0 * power;
+      *minor = 1.0 * power;
+    }	  
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawLabels.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+  
+void DrawLabels (Layout *layout) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+  DrawRotTextInit (graphic.display, graphic.window, graphic.gc, graphic.fore, graphic.back);
+
+  /* each label is drawn independently */
+  for (i = 0; i < 8; i++) {
+    if (strcmp (layout[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = layout[0].label[i].x;
+      y = layout[0].label[i].y;
+      SetRotFont (layout[0].label[i].font, layout[0].label[i].size);
+      DrawRotText (x, y, layout[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+          
+ 6____7___8 
+  |       | 
+  |       | 
+ 3|   4   |5
+  |       |
+  |       |
+  ---------
+  0   1   2
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawObjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawObjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawObjects.c	(revision 16632)
@@ -0,0 +1,619 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,X2,Y2) (XDrawLine (graphic.display, graphic.window, graphic.gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawRectangle(X1,Y1,X2,Y2) (XDrawRectangle (graphic.display, graphic.window, graphic.gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define FillRectangle(X1,Y1,X2,Y2) (XFillRectangle (graphic.display, graphic.window, graphic.gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawCircle(X,Y,R) (XDrawArc (graphic.display, graphic.window, graphic.gc, (int)(X-R+0.5), (int)(Y-R+0.5), abs(2*R+0.5), abs(2*R+0.5), 0, 23040))
+
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y0, double X1, double Y1);
+
+/* draw all objects for this Layout */
+int DrawObjects (Layout *layout) {
+  
+  int i;
+  
+  for (i = 0; i < layout[0].Nobjects; i++) {
+    if (DEBUG) fprintf (stderr, "object: %d\n", i);
+    if (DEBUG) fprintf (stderr, "Npts: %d\n", layout[0].objects[i].Npts);
+    DrawObjectN (layout, &layout[0].objects[i]);
+  }    
+  return (TRUE);
+}
+
+/* Draw a specific object in the layout */
+int DrawObjectN (Layout *layout, Gobjects *object) {
+  
+  static char dash[2] = {5,10};
+  static char dot[2] = {3,3};
+  int lweight;
+  
+  lweight = MAX (0, MIN (10, object[0].lweight));
+
+  /* set line type */
+  switch (object[0].ltype) {
+  case 0:
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  case 1:
+    XSetDashes (graphic.display, graphic.gc, 100, dash, 2);
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  case 2:
+    XSetDashes (graphic.display, graphic.gc, 10, dot, 2);
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  default:
+    XSetLineAttributes (graphic.display, graphic.gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  }
+
+  XSetForeground (graphic.display, graphic.gc, graphic.color[object[0].color]);
+
+  switch (object[0].style) {
+  case CONNECT: 
+    DrawConnect (layout, object);
+    break;
+  case HISTOGRAM:
+    DrawHistogram (layout, object);
+    break;
+  case POINTS:
+    DrawPoints (layout, object);
+    break;
+  }
+    
+  if (object[0].etype & 0x01) {
+    DrawYErrors (layout, object);
+  }
+  if (object[0].etype & 0x02) {
+    DrawXErrors (layout, object);
+  }
+
+  XSetLineAttributes (graphic.display, graphic.gc, 0, LineSolid, CapNotLast, JoinMiter);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+  return (TRUE);
+}
+
+/******/
+void DrawConnect (Layout *layout, Gobjects *object) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    
+    ClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+  
+}
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+  
+
+/******/
+void DrawHistogram (Layout *layout, Gobjects *object) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/******/
+void DrawPoints (Layout *layout, Gobjects *object) {
+
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+  
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic.dx + graphic.dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i] + 1, sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i] + 1, sy - d*z[i] - 1, sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i] + 1, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d*z[i];  points[0].y = sy + 0.58*d*z[i];  
+	    points[1].x = sx + d*z[i];  points[1].y = sy + 0.58*d*z[i];  
+	    points[2].x = sx;           points[2].y = sy - 1.15*d*z[i];  
+	    points[3].x = sx - d*z[i];  points[3].y = sy + 0.58*d*z[i];  
+	    XFillPolygon (graphic.display, graphic.window, graphic.gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	if (!(finite(x[i+1]) && finite(y[i+1]))) continue;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } 
+  /**** points are not scaled by object.z ***/
+  else {
+    d = object[0].size * 0.5 * (graphic.dx + graphic.dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d + 1, sy);
+	    DrawLine (sx, sy - d, sx, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    /* XDrawLine is a little funny, this is needed to fix endpost errors */
+	    DrawLine (sx + d + 1, sy - d - 1, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d + 1, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d;  points[0].y = sy + 0.58*d;  
+	    points[1].x = sx + d;  points[1].y = sy + 0.58*d;  
+	    points[2].x = sx;      points[2].y = sy - 1.15*d;  
+	    points[3].x = sx - d;  points[3].y = sy + 0.58*d;  
+	    XFillPolygon (graphic.display, graphic.window, graphic.gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx,     sy - 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/******/
+void DrawXErrors (Layout *layout, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[1].dfy*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy))) 
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/******/
+void DrawYErrors (Layout *layout, Gobjects *object) {
+
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = sx0 + dyp[i]*mxj;
+    sy1 = sy0 + dyp[i]*myj;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawPtext.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawPtext.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawPtext.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "Ximage.h"
+  
+void DrawPtext (Layout *layout) {
+  
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic.display, graphic.gc, graphic.fore);
+  DrawRotTextInit (graphic.display, graphic.window, graphic.gc, graphic.fore, graphic.back);
+
+  for (i = 0; i < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      DrawRotText (x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawText.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawText.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/DrawText.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+  
+/* Draw text centered at x,y */
+
+void DrawText (int x, int y, char *string, int pos) {
+
+  char *c;
+  int dx, dy;
+
+  for (c = string; (*c == ' ') || (*c == '\t'); c++);
+  if (*c == 0) return;
+  
+  dx  = XTextWidth (graphic.font, c, strlen(c));
+  dy  = graphic.font[0].ascent;
+  switch (pos) {
+  case 0: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y + dy,   c, strlen(c)); break;
+  case 1: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y + dy,   c, strlen(c)); break;
+  case 2: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y + dy,   c, strlen(c)); break;
+  case 3: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y + dy/2, c, strlen(c)); break;
+  case 4: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y + dy/2, c, strlen(c)); break;
+  case 5: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y + dy/2, c, strlen(c)); break;
+  case 6: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx,   y,        c, strlen(c)); break;
+  case 7: XDrawString (graphic.display, graphic.window, graphic.gc, x - dx/2, y,        c, strlen(c)); break;
+  case 8: XDrawString (graphic.display, graphic.window, graphic.gc, x,        y,        c, strlen(c)); break;
+  }
+}
+
+/*
+            
+ 6____7___8
+  |       | 
+  |       | 
+ 3|   4   |5
+  |       |
+  |       |
+  ---------
+ 0    1   2
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/ErasePlot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/ErasePlot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/ErasePlot.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "Ximage.h"
+# define TESTFREE(a) { if ((a) != (float *) NULL) free (a);}
+
+int ErasePlot (int ClearSection) {
+  
+  int i, j;
+
+  for (j = 0; j < Nsection; j++) {
+
+    /* free data objects, then re-alloc those needed */
+    for (i = 0; i < section[j].Nobjects; i++) {
+      TESTFREE (section[j].objects[i].x);
+      TESTFREE (section[j].objects[i].y);
+      TESTFREE (section[j].objects[i].z);
+      TESTFREE (section[j].objects[i].dxm);
+      TESTFREE (section[j].objects[i].dxp);
+      TESTFREE (section[j].objects[i].dym);
+      TESTFREE (section[j].objects[i].dyp);
+    }
+    
+    /* reset axes and labels */
+    for (i = 0; i < 4; i++) {
+      section[j].axis[i].isaxis = FALSE;
+      section[j].axis[i].islabel = FALSE;
+      section[j].axis[i].areticks = FALSE;
+    }
+    for (i = 0; i < 8; i++) {
+      strcpy (section[j].label[i].text, "");
+    }
+    
+    /* free objects and text entries, or re-zero */
+    if (ClearSection && (j != 0)) {
+      free (section[j].objects);
+      free (section[j].ptext);
+    } else {
+      section[j].Nobjects = 0;
+      REALLOCATE (section[j].objects, Gobjects, 1);
+      section[j].Nptext = 0;
+      REALLOCATE (section[j].ptext, Label, 1);
+    }
+  }
+
+  if (ClearSection) {
+    Nsection = 1;
+    TheSection = 0;
+    REALLOCATE (section, Layout, Nsection);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic.display, graphic.window);
+  Refresh (1);
+
+  return (TRUE);
+  
+}
+
+
+/** note that 'section' is the global variable
+    of type 'Layout' which carries data and info 
+    about each graph section 
+**/
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadBox.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "Ximage.h"
+
+int LoadBox () {
+  
+  int i, status;
+  char Axis[16], Labels[16], Ticks[16];
+  Layout *layout;
+  
+  layout = &section[TheSection];
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", 
+		  &layout[0].axis[0].min, &layout[0].axis[0].max, 
+		  &layout[0].axis[1].min, &layout[0].axis[1].max);
+
+  layout[0].axis[3].min = layout[0].axis[1].min;
+  layout[0].axis[3].max = layout[0].axis[1].max;
+  layout[0].axis[2].min = layout[0].axis[0].min;
+  layout[0].axis[2].max = layout[0].axis[0].max;
+  
+  KiiScanMessage (sock, "%s %s %s", Axis, Labels, Ticks);
+
+  for (i = 0; i < 4; i++) {
+    switch (Axis[i]) {
+    case '0':
+      layout[0].axis[i].isaxis = FALSE;
+      break;
+    case '1':
+      layout[0].axis[i].isaxis = TRUE;
+      break;
+    case '2':
+      layout[0].axis[i].isaxis = TRUE;
+      break;
+    }
+    switch (Ticks[i]) {
+    case '0':
+      layout[0].axis[i].areticks = FALSE;
+      break;
+    case '1':
+      layout[0].axis[i].areticks = TRUE;
+      break;
+    case '2':
+      layout[0].axis[i].areticks = 2;
+      break;
+    }
+    switch (Labels[i]) {
+    case '0':
+      layout[0].axis[i].islabel = FALSE;
+      break;
+    case '1':
+      layout[0].axis[i].islabel = TRUE;
+      break;
+    case '2':
+      layout[0].axis[i].islabel = (i < 2);
+      break;
+    }
+  }
+
+  if (USE_XWINDOW) DrawFrame (layout);
+  status = TRUE;
+  if (status) {
+    for (i = 0; i < Nsection; i++) {
+      PositionPicture (&section[i]);
+    }
+    if (USE_XWINDOW) XClearWindow (graphic.display, graphic.window);
+    Refresh (1);
+  } else {
+    FlushDisplay ();
+  } 
+
+  return (TRUE);
+  
+}
+
+/*
+  layout[0].X = 0;
+  layout[0].Y = 0;
+  layout[0].expand = 1;
+*/
+  
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadLabels.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "Ximage.h"
+
+int LoadLabels () {
+  
+  char *c, *label;
+  int mode, size, Nbytes;
+  Layout *layout;
+  
+  layout = &section[TheSection];
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  KiiScanMessage (sock, "%d", &mode);
+  label = KiiRecvData (sock);
+
+  bzero (layout[0].label[mode].text, LABEL_MAXLEN);
+
+  Nbytes = MIN (strlen(label), LABEL_MAXLEN - 1);
+  strncpy (layout[0].label[mode].text, label, Nbytes);
+  label[Nbytes] = 0;
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  c = GetRotFont (&size);
+  layout[0].label[mode].size = size;
+  strcpy (layout[0].label[mode].font, c);
+  if (USE_XWINDOW) DrawLabels (layout);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
+
+/*
+  layout[0].X = 0;
+  layout[0].Y = 0;
+  layout[0].expand = 1;
+  */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadObject.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadObject.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadObject.c	(revision 16632)
@@ -0,0 +1,185 @@
+# include "Ximage.h"
+# include <errno.h>
+
+int LoadObject () {
+  
+  int N;
+  Layout *layout;
+
+  layout = &section[TheSection];
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  N = layout[0].Nobjects;
+  layout[0].Nobjects ++;
+  REALLOCATE (layout[0].objects, Gobjects, layout[0].Nobjects);
+  layout[0].objects[N].x = layout[0].objects[N].y = layout[0].objects[N].z = (float *) NULL;
+  layout[0].objects[N].dxm = layout[0].objects[N].dxp = (float *) NULL;
+  layout[0].objects[N].dym = layout[0].objects[N].dyp = (float *) NULL;
+  
+  KiiScanMessage (sock, "%d %d %d %d %d %d %d %lf %lf",
+		  &layout[0].objects[N].Npts, &layout[0].objects[N].style, 
+		  &layout[0].objects[N].ptype, &layout[0].objects[N].ltype, 
+		  &layout[0].objects[N].etype, &layout[0].objects[N].ebar, 
+		  &layout[0].objects[N].color, 
+		  &layout[0].objects[N].lweight, &layout[0].objects[N].size);
+  
+  if (DEBUG) fprintf (stderr, "%d %d %d %d %d %d %d %lf %lf\n",
+		      layout[0].objects[N].Npts, layout[0].objects[N].style, 
+		      layout[0].objects[N].ptype, layout[0].objects[N].ltype, 
+		      layout[0].objects[N].etype, layout[0].objects[N].ebar, 
+		      layout[0].objects[N].color, 
+		      layout[0].objects[N].lweight, layout[0].objects[N].size);
+  
+  /* force valid ranges */
+  if ((layout[0].objects[N].color > KapaColormapSize()) || (layout[0].objects[N].color < 0))
+    layout[0].objects[N].color = 0;
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf",
+		  &layout[0].objects[N].x0, &layout[0].objects[N].x1, 
+		  &layout[0].objects[N].y0, &layout[0].objects[N].y1);
+  
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  if (!LoadVectorData (layout, N, "x")) {
+    FreeObjectData (&layout[0].objects[N]);
+    layout[0].Nobjects --;
+    REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+  }
+    
+  if (!LoadVectorData (layout, N, "y")) {
+    FreeObjectData (&layout[0].objects[N]);
+    layout[0].Nobjects --;
+    REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+  }
+  if (layout[0].objects[N].size < 0.0) {
+    if (!LoadVectorData (layout, N, "z")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+  }
+  if (layout[0].objects[N].etype & 0x01) {
+    if (!LoadVectorData (layout, N, "dym")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+    if (!LoadVectorData (layout, N, "dyp")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+  }
+  if (layout[0].objects[N].etype & 0x02) {
+    if (!LoadVectorData (layout, N, "dxm")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+    if (!LoadVectorData (layout, N, "dxp")) {
+      FreeObjectData (&layout[0].objects[N]);
+      layout[0].Nobjects --;
+      REALLOCATE (layout[0].objects, Gobjects, MAX (1, layout[0].Nobjects));
+    }
+  }
+
+  if (DEBUG) fprintf (stderr, "loaded %d objects, using object %d\n", layout[0].objects[N].Npts, N);
+
+  if (USE_XWINDOW) DrawObjectN (layout, &layout[0].objects[layout[0].Nobjects-1]);
+  FlushDisplay ();
+
+  return (TRUE);
+  
+}
+
+/* load data for the named component */
+int LoadVectorData (Layout *layout, int N, char *type) {
+  
+  int Npts, Ninpts, status, Ntry;
+  int bytes_left;
+  char *buff;
+
+  buff = NULL;
+  Npts = layout[0].objects[N].Npts;
+  status = 1;
+  if (!strcmp (type, "x")) {
+    ALLOCATE (layout[0].objects[N].x, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].x;
+  }
+  if (!strcmp (type, "y")) {
+    ALLOCATE (layout[0].objects[N].y, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].y;
+  }
+  if (!strcmp (type, "z")) {
+    ALLOCATE (layout[0].objects[N].z, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].z;
+  }
+  if (!strcmp (type, "dxm")) {
+    ALLOCATE (layout[0].objects[N].dxm, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dxm;
+  }
+  if (!strcmp (type, "dxp")) {
+    ALLOCATE (layout[0].objects[N].dxp, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dxp;
+  }
+  if (!strcmp (type, "dym")) {
+    ALLOCATE (layout[0].objects[N].dym, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dym;
+  }
+  if (!strcmp (type, "dyp")) {
+    ALLOCATE (layout[0].objects[N].dyp, float, MAX (1, Npts));
+    buff = (char *) layout[0].objects[N].dyp;
+  }
+
+  bytes_left = Npts*sizeof (float);
+
+  Ntry = 0;
+  if (DEBUG) fprintf (stderr, "starting vector load\n");
+  Ninpts = 0;
+  while (bytes_left > 0) {
+    status = read (sock, buff, bytes_left);
+    if (DEBUG) fprintf (stderr, "status: %d, %d\n", status, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      Ninpts += status;
+      bytes_left -= status;
+      buff = (char *)(buff + status);
+      Ntry = 0;
+      continue;
+    }
+    if (errno == EAGAIN) {
+      Ntry ++;
+      if (Ntry > 100) {
+	fprintf (stderr, "kapa communication error\n");
+	return (FALSE);
+      }
+      usleep (10000);
+      continue;
+    }
+    perror ("kapa load");
+  }
+  if (Ninpts != Npts*sizeof(float)) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", Ninpts, (unsigned int)(Npts*sizeof(float)));
+    return (FALSE);
+  }
+  if (DEBUG) fprintf (stderr, "done vector load\n");
+  return (TRUE);
+
+}
+
+void FreeObjectData (Gobjects *object) {
+
+  if (object[0].x != (float *) NULL) free (object[0].x);
+  if (object[0].y != (float *) NULL) free (object[0].y);
+  if (object[0].z != (float *) NULL) free (object[0].z);
+
+  if (object[0].dxm != (float *) NULL) free (object[0].dxm);
+  if (object[0].dxp != (float *) NULL) free (object[0].dxp);
+  if (object[0].dym != (float *) NULL) free (object[0].dym);
+  if (object[0].dyp != (float *) NULL) free (object[0].dyp);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadPtext.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadPtext.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/LoadPtext.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "Ximage.h"
+
+int LoadPtext () {
+  
+  char *string;
+  int N, size;
+  double tX, tY, tT, L;
+  Layout *layout;
+  
+  layout = &section[TheSection];
+  
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  
+  layout[0].Nptext = MAX (layout[0].Nptext, 0);
+  N = layout[0].Nptext;
+  layout[0].Nptext++;
+  REALLOCATE (layout[0].ptext, Label, layout[0].Nptext);
+
+  KiiScanMessage (sock, "%lf %lf %lf", &tX, &tY, &tT);
+
+  L = layout[0].axis[0].dfx;
+  layout[0].ptext[N].x = L * (tX - layout[0].axis[0].min) / (layout[0].axis[0].max - layout[0].axis[0].min) + layout[0].axis[0].fx;
+
+  L = layout[0].axis[1].dfy;
+  layout[0].ptext[N].y = L * (tY - layout[0].axis[1].min) / (layout[0].axis[1].max - layout[0].axis[1].min) + layout[0].axis[1].fy;
+
+  layout[0].ptext[N].angle = tT;
+
+  bzero (layout[0].ptext[N].text, LABEL_MAXLEN);
+
+  string = KiiRecvData (sock);
+  strcpy (layout[0].ptext[N].text, string);
+  free (string);
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  
+  string = GetRotFont (&size);
+  layout[0].ptext[N].size = size;
+  strcpy (layout[0].ptext[N].font, string);
+
+  if (USE_XWINDOW) DrawPtext (layout);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/PNGit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/PNGit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/PNGit.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "Ximage.h"
+
+int PNGit () {
+
+  FILE *f;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color *palette;
+  int Npalette;
+  char filename[1024];
+  int Nbytes, status;
+
+  bDrawBuffer *buffer;
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", "Xgraph.png");
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_voidp) NULL, (png_voidp) NULL);
+  if (!png_ptr) {
+    fprintf (stderr, "can't get png structure\n");
+    fclose (f);
+    return (TRUE);
+  }
+
+  info_ptr = png_create_info_struct (png_ptr);
+  if (!info_ptr) {
+    fprintf (stderr, "can't get png info structure\n");
+    png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
+    fclose (f);
+    return (TRUE);
+  }
+
+  if (setjmp (png_ptr[0].jmpbuf)) {
+    fprintf (stderr, "can't get png return\n");
+    png_destroy_write_struct (&png_ptr, &info_ptr);
+    fclose (f);
+    return (TRUE);
+  }
+
+  png_init_io (png_ptr, f);
+
+  /* see docs for write-row-callback to provide progress info */
+
+  png_set_IHDR (png_ptr, info_ptr, graphic.dx, graphic.dy, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 
+
+  /* png_set_IHDR (png_ptr, info_ptr, graphic.dx, graphic.dy, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); */
+
+  palette = KapaPNGPalette (&Npalette);
+  png_set_PLTE (png_ptr, info_ptr, palette, Npalette); 
+ 
+  png_write_info (png_ptr, info_ptr);
+
+  buffer = bDrawIt ();
+
+  png_write_image (png_ptr, buffer[0].pixels);
+  png_write_end (png_ptr, info_ptr);
+  png_destroy_write_struct (&png_ptr, &info_ptr);
+  
+  bDrawBufferFree (buffer);
+  free (palette);
+  fclose (f);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/PPMit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/PPMit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/PPMit.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "Ximage.h"
+
+int PPMit () {
+
+  FILE *f;
+  char *line, filename[1024];
+  int Nbytes, status, dx, dy, i, j, Npalette, color;
+  png_color *palette;
+
+  bDrawBuffer *buffer;
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+  
+  palette = KapaPNGPalette (&Npalette);
+
+  dx = graphic.dx;
+  dy = graphic.dy;
+  
+  fprintf (f, "P6\n");
+  fprintf (f, "%d %d\n", dx, dy);
+  fprintf (f, "255\n");
+
+  buffer = bDrawIt ();
+
+  ALLOCATE (line, char, 3*dx);
+
+  for (i = 0; i < dy; i++) {
+    for (j = 0; j < dx; j++) {
+      color = buffer[0].pixels[i][j];
+      line[3*j + 0] = palette[color].red;
+      line[3*j + 1] = palette[color].green;
+      line[3*j + 2] = palette[color].blue;
+    }
+    fwrite (line, 3, dx, f);
+  }
+  fclose (f);
+  
+  bDrawBufferFree (buffer);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSFrame.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSFrame.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSFrame.c	(revision 16632)
@@ -0,0 +1,99 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,DX,DY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, Y1, X1+DX, Y1+DY))
+
+int PSFrame (Layout *layout, FILE *f) {
+  
+  int i, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+
+  /* each axis is drawn independently */
+  fontname = GetRotFont (&fontsize);
+  fprintf (f, "1 setlinewidth\n");
+  for (i = 0; i < 4; i++) {
+    fx = layout[0].axis[i].fx;
+    fy = graphic.dy - layout[0].axis[i].fy;
+    dfx = layout[0].axis[i].dfx;
+    dfy = -layout[0].axis[i].dfy;
+    P = hypot ((double)layout[0].axis[(i+1)%2].dfx, (double)layout[0].axis[(i+1)%2].dfy);
+
+    if (layout[0].axis[i].isaxis) { DrawLine (fx, fy, dfx, dfy); }
+    
+    if (layout[0].axis[i].areticks) {
+      range = layout[0].axis[i].max - layout[0].axis[i].min;
+      AxisTickScale (&layout[0].axis[i], &major, &minor);
+
+      first = minor*((int)(layout[0].axis[i].min/minor));
+      if ((range > 0) && (first < layout[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > layout[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= layout[0].axis[i].max)) || ((range < 0) && (next >= layout[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = layout[0].axis[i].islabel;
+	PSTick (f, fx, fy, dfx, dfy, P, layout[0].axis[i].min, layout[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void PSTick (FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  pos = size = 0;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = -1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g", value);
+    PSRotText (f, (int)x, (int)y, string, pos, 0.0);
+  }
+}
+
+  /* 
+  dx = size*dfy*n;	
+  dy = size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  
+  dx = -size*dfy*n;	
+  dy = -size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  */
+  
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSLabels.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+  
+void PSLabels (Layout *layout, FILE *f) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (layout[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = layout[0].label[i].x;
+      y = graphic.dy - layout[0].label[i].y;
+      SetRotFont (layout[0].label[i].font, layout[0].label[i].size); 
+      PSRotText (f, x, y, layout[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSObjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSObjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSObjects.c	(revision 16632)
@@ -0,0 +1,685 @@
+# include "Ximage.h"
+# define XOFFSET 60
+# define YOFFSET 60
+
+void ClipLinePS (double, double, double, double, double, double, double, double, FILE *);
+
+static char *name = "$Name: not supported by cvs2svn $";
+
+int PSit () {
+
+  int i, pageMode, scaleMode;
+  double scale;
+  FILE *f;
+  char filename[1024], pagename[1024], *version;
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (sock, "%s %s %d %d", filename, pagename, &scaleMode, &pageMode);
+
+  if (pageMode == KAPA_PS_NEWPAGE) {
+    f = fopen (filename, "a+");
+  } else {
+    f = fopen (filename, "w");
+  }
+  if (f == NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  /* two scaling options: expand to fit page / keep absolute size */ 
+  if (scaleMode) {
+    scale = MIN (fabs(500.0 / graphic.dx), fabs (700.0 / graphic.dy));
+  } else {
+    scale = 72.0 / 96.0; /* ratio of screen pixels to points */
+  }
+
+  switch (pageMode) {
+    case KAPA_PS_NEWPLOT:
+      fprintf (f, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+      fprintf (f, "%%%%Title: %s\n", filename);
+      version = strip_version (name);
+      fprintf (f, "%%%%Creator: Kapa (%s)\n", version);
+      free (version);
+      fprintf (f, "%%%%BoundingBox: %d %d %.0f %.0f\n", 
+	       XOFFSET, YOFFSET, XOFFSET + scale*graphic.dx, YOFFSET + scale*graphic.dy);
+      fprintf (f, "%%%%Pages: 1\n");
+      fprintf (f, "%%%%DocumentFonts:\n");
+      fprintf (f, "%%%%EndComments\n");
+      fprintf (f, "%%%%EndProlog\n");
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_NEWPAGE:
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_RAWPAGE:
+      break;
+  } 
+  fprintf (f, "gsave %% encloses picture\n");
+  fprintf (f, "%% local abbreviations\n");
+  fprintf (f, "/Times-Roman findfont 14 scalefont setfont\n");
+  fprintf (f, "/T {moveto show stroke} def\n");
+  fprintf (f, "/B { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath stroke } def\n");
+  fprintf (f, "/F { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath fill stroke } def\n");
+  fprintf (f, "/C {0 360 arc stroke} def\n");
+  fprintf (f, "/L {newpath moveto lineto stroke} def\n\n");
+  fprintf (f, "/TF {newpath moveto lineto lineto fill stroke} def\n\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) {
+    fprintf (f, " %d %d translate\n", XOFFSET, YOFFSET);
+    fprintf (f, "  %f  %f scale\n", scale, scale);
+  }
+
+  for (i = 0; i < Nsection; i++) {
+    PSFrame (&section[i], f); 
+    PSObjects (&section[i], f);
+    PSLabels (&section[i], f);
+    PSPtext (&section[i], f);
+  }
+  
+  fprintf (f, "grestore %% end of picture\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) fprintf (f, "showpage\n");
+
+  fclose (f);
+  return (TRUE);
+
+}
+
+# define DrawLine(X1,Y1,X2,Y2) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, graphic.dy - Y1, X2, graphic.dy - Y2))
+# define DrawCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f C\n", (X1), (graphic.dy - Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X-0.5*dX), (graphic.dy-Y-0.5*dY)))
+# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X-0.5*dX), (graphic.dy-Y-0.5*dY)))
+# define FillTriangle(X1,Y1,X2,Y2, X3, Y3) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f TF\n", (X1), (graphic.dy-Y1), (X2), (graphic.dy-Y2), (X3), (graphic.dy-Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+int PSObjects (Layout *layout, FILE *f) {
+  
+  int i;
+  double lweight;
+  static char dash[] = "5";
+  static char dot[] = "3";
+  
+  for (i = 0; i < layout[0].Nobjects; i++) {
+    switch (layout[0].objects[i].ltype) {
+    case 0:
+      break;
+    case 1:
+      fprintf (f, "[%s] 0 setdash\n", dash);
+      break;
+    case 2:
+      fprintf (f, "[%s] 0 setdash\n", dot);
+      break;
+    default:
+      break;
+    }
+    
+    lweight = MAX (0, MIN (10, layout[0].objects[i].lweight));
+    fprintf (f, "%.1f setlinewidth\n", lweight);
+    fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(layout[0].objects[i].color));
+
+    switch (layout[0].objects[i].style) {
+    case CONNECT: 
+      PSConnect (layout, &layout[0].objects[i], f);
+      break;
+    case HISTOGRAM:
+      PSHistogram (layout, &layout[0].objects[i], f);
+      break;
+    case POINTS:
+      PSPoints (layout, &layout[0].objects[i], f);
+      break;
+    }
+
+    if (layout[0].objects[i].etype & 0x01) {
+      PSYErrors (layout, &layout[0].objects[i], f);
+    }
+    if (layout[0].objects[i].etype & 0x02) {
+      PSXErrors (layout, &layout[0].objects[i], f);
+    }
+    fprintf (f, "[] 0 setdash\n");
+    fprintf (f, "0.00 0.00 0.00 setrgbcolor\n");
+  }
+  return (TRUE);
+}
+
+/*******/
+void PSConnect (Layout *layout, Gobjects *object, FILE *f) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void ClipLinePS (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0, FILE *f) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+
+/*******/
+void PSHistogram (Layout *layout, Gobjects *object, FILE *f) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/*******/
+void PSPoints (Layout *layout, Gobjects *object, FILE *f) {
+ 
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);  
+
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /* below here, code is identical with DrawObjects */
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic.dx + graphic.dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
+	    /*
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	    */
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } else {
+    d = object[0].size * 0.5 * (graphic.dx + graphic.dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d, sy);
+	    DrawLine (sx, sy - d, sx, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d, sy - d, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    /*
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	    */
+	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d);
+	    DrawLine (sx + d, sy - 0.58*d, sx,     sy + 1.15*d);
+	    DrawLine (sx,     sy + 1.15*d, sx - d, sy - 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx,     sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/*******/
+void PSXErrors (Layout *layout, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[1].dfy*0.03;
+   
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+
+    
+/*******/
+void PSYErrors (Layout *layout, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+  
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSPtext.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSPtext.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/PSPtext.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+  
+void PSPtext (Layout *layout, FILE *f) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = graphic.dy - layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      PSRotText (f, x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/SetLimits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/SetLimits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/SetLimits.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+int SetLimits () {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Layout *layout;
+
+  layout = &section[TheSection];
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", &xmin, &xmax, &ymin, &ymax);
+
+  layout[0].axis[2].min = layout[0].axis[0].min = xmin;
+  layout[0].axis[2].max = layout[0].axis[0].max = xmax;
+  layout[0].axis[3].min = layout[0].axis[1].min = ymin; 
+  layout[0].axis[3].max = layout[0].axis[1].max = ymax;
+  
+  for (i = 0; i < layout[0].Nobjects; i++) {
+    layout[0].objects[i].x0 = xmin;
+    layout[0].objects[i].x1 = xmax;
+    layout[0].objects[i].y0 = ymin;
+    layout[0].objects[i].y1 = ymax;
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic.display, graphic.window);
+  Refresh (1);
+
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawFrame.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawFrame.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawFrame.c	(revision 16632)
@@ -0,0 +1,89 @@
+# include "Ximage.h"
+
+int bDrawFrame (Layout *layout) {
+  
+  int i, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+
+  /* each axis is drawn independently */
+  fontname = GetRotFont (&fontsize);
+  for (i = 0; i < 4; i++) {
+    fx  = layout[0].axis[i].fx;
+    fy  = layout[0].axis[i].fy;
+    dfx = layout[0].axis[i].dfx;
+    dfy = layout[0].axis[i].dfy;
+    P = hypot ((double)layout[0].axis[(i+1)%2].dfx, (double)layout[0].axis[(i+1)%2].dfy);
+
+    if (layout[0].axis[i].isaxis) { 
+      bDrawLine (fx, fy, fx+dfx, fy+dfy); 
+    }
+    
+    if (layout[0].axis[i].areticks) {
+      range = layout[0].axis[i].max - layout[0].axis[i].min;
+
+      AxisTickScale (&layout[0].axis[i], &major, &minor);
+
+      first = minor*((int)(layout[0].axis[i].min/minor));
+      if ((range > 0) && (first < layout[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > layout[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= layout[0].axis[i].max)) || ((range < 0) && (next >= layout[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = layout[0].axis[i].islabel;
+	bDrawTick (fx, fy, dfx, dfy, P, layout[0].axis[i].min, layout[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void bDrawTick (double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  pos = size = 0;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  bDrawLine (x, y, x+dx, y+dy);
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g", value);
+    bDrawRotText ((int)x, (int)y, string, pos, 0.0);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawIt.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawIt.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawIt.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "Ximage.h"
+
+bDrawBuffer *bDrawIt () {
+
+  int i;
+  bDrawBuffer *buffer;
+  bDrawColor black;
+
+  black = KapaColorByName ("black");
+
+  buffer = bDrawBufferCreate (graphic.dx, graphic.dy);
+  bDrawSetBuffer (buffer);
+  bDrawSetStyle (black, 0, 0);
+  
+  for (i = 0; i < Nsection; i++) {
+    bDrawFrame (&section[i]); 
+    bDrawObjects (&section[i]);
+    bDrawLabels (&section[i]);
+    bDrawPtext (&section[i]);
+  }
+  
+  return (buffer);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawLabels.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "Ximage.h"
+  
+void bDrawLabels (Layout *layout) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (layout[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = layout[0].label[i].x;
+      y = layout[0].label[i].y;
+      SetRotFont (layout[0].label[i].font, layout[0].label[i].size); 
+      bDrawRotText (x, y, layout[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+void bDrawPtext (Layout *layout) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < layout[0].Nptext; i++) {
+    if (strcmp (layout[0].ptext[i].text, "")) {
+      angle = layout[0].ptext[i].angle;
+      x = layout[0].ptext[i].x;
+      y = layout[0].ptext[i].y;
+      SetRotFont (layout[0].ptext[i].font, layout[0].ptext[i].size);
+      bDrawRotText (x, y, layout[0].ptext[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+/*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+*/
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawObjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawObjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/bDrawObjects.c	(revision 16632)
@@ -0,0 +1,570 @@
+# include "Ximage.h"
+
+# define DrawLine(X1,Y1,X2,Y2) (bDrawLine ((X1), (Y1), (X2), (Y2)))
+# define DrawCircle(X1,Y1,R) (bDrawCircle ((X1), (Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (bDrawRectOpen ((X-0.5*dX), (Y-0.5*dY), (X+0.5*dX), (Y+0.5*dY)))
+# define FillRectangle(X,Y,dX,dY) (bDrawRectFill ((X-0.5*dX), (Y-0.5*dY), (X+0.5*dX), (Y+0.5*dY)))
+# define FillTriangle(X1,Y1,X2,Y2,X3,Y3) (bDrawTriFill ((X1), (Y1), (X2), (Y2), (X3), (Y3)))
+# define OpenTriangle(X1,Y1,X2,Y2,X3,Y3) (bDrawTriOpen ((X1), (Y1), (X2), (Y2), (X3), (Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+int bDrawObjects (Layout *layout) {
+  
+  int i;
+  int type;
+  int weight;
+  bDrawColor color;
+  bDrawColor black;
+  
+  black = KapaColorByName ("black");
+  for (i = 0; i < layout[0].Nobjects; i++) {
+
+    weight = MAX (0, MIN (10, layout[0].objects[i].lweight));
+    type = layout[0].objects[i].ltype;    
+    color = layout[0].objects[i].color;
+    bDrawSetStyle (color, weight, type);
+
+    switch (layout[0].objects[i].style) {
+    case CONNECT: 
+      bDrawConnect (layout, &layout[0].objects[i]);
+      break;
+    case HISTOGRAM:
+      bDrawHistogram (layout, &layout[0].objects[i]);
+      break;
+    case POINTS:
+      bDrawPoints (layout, &layout[0].objects[i]);
+      break;
+    }
+
+    if (layout[0].objects[i].etype & 0x01) {
+      bDrawYErrors (layout, &layout[0].objects[i]);
+    }
+    if (layout[0].objects[i].etype & 0x02) {
+      bDrawXErrors (layout, &layout[0].objects[i]);
+    }
+  }
+  bDrawSetStyle (black, 0, 0);
+  return (TRUE);
+}
+
+void bDrawConnect (Layout *layout, Gobjects *object) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    bDrawClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void bDrawClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+
+/*******/
+void bDrawHistogram (Layout *layout, Gobjects *object) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = layout[0].axis[0].fx;
+  X1 = layout[0].axis[0].fx + layout[0].axis[0].dfx;
+  Y0 = layout[0].axis[1].fy;
+  Y1 = layout[0].axis[1].fy + layout[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/*******/
+void bDrawPoints (Layout *layout, Gobjects *object) {
+ 
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);  
+
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /* below here, code is identical with DrawObjects */
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic.dx + graphic.dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    OpenTriangle (sx - d*z[i], sy + 0.58*d*z[i], sx, sy - 1.15*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } else {
+    d = object[0].size * 0.5 * (graphic.dx + graphic.dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d, sy);
+	    DrawLine (sx, sy - d, sx, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d, sy - d, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    OpenTriangle (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d, sx, sy - 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx,     sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > layout[0].axis[0].fx) && (sx < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	    (sy < layout[0].axis[1].fy) && (sy > layout[0].axis[1].fy + layout[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/*******/
+void bDrawXErrors (Layout *layout, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[1].dfy*0.03;
+   
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/*******/
+void bDrawYErrors (Layout *layout, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+  
+  mxi = layout[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = layout[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = layout[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = layout[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  layout[0].axis[0].fx - object[0].x0*layout[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*layout[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*layout[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  layout[0].axis[1].fy - object[0].y0*layout[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*layout[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > layout[0].axis[0].fx) && (sx0 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy0 < layout[0].axis[1].fy) && (sy0 > layout[0].axis[1].fy + layout[0].axis[1].dfy)) ||
+	((sx1 > layout[0].axis[0].fx) && (sx1 < layout[0].axis[0].fx + layout[0].axis[0].dfx) &&
+	 (sy1 < layout[0].axis[1].fy) && (sy1 > layout[0].axis[1].fy + layout[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/graph/cursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/graph/cursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/graph/cursor.c	(revision 16632)
@@ -0,0 +1,112 @@
+# include "Ximage.h"
+
+/* # define IgnoreMask (long) (ClientMessage | ButtonReleaseMask | PointerMotionMask) */
+# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask))
+
+int LastEvent (Display *display, int type, XEvent *event);
+
+int cursor () {
+
+  Display        *display;
+  XEvent          event;
+  KeySym          keysym;
+  int             status, value;
+  XComposeStatus  composestatus;
+  char            string[10], line[40], *name;
+  double          x, y;
+  char            buffer[10];
+  Layout         *layout;
+  XButtonEvent   *mouse_event;
+
+  layout = &section[TheSection];
+
+  while (1) {
+    
+    /* check the pipe for messages */
+    status = read (sock, buffer, 4);
+    buffer[4] = 0;
+    
+    if (status == -1) goto events;
+    if (status ==  0) return (FALSE);
+    if (status ==  4) {
+      if (!strcmp (buffer, "NCUR")) return (TRUE);
+      goto events;
+    }
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+
+  events:
+    if (XEventsQueued (graphic.display, QueuedAfterFlush) < 1) {
+      usleep (50000);
+      continue;
+    }
+
+    /* check for x events */
+    display = graphic.display;
+
+    /* grab the last entry for these events */
+    if (LastEvent (display, ConfigureNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, CirculateNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, Expose,          &event)) Refresh (1);
+
+    if (LastEvent (display, MappingNotify,   &event)) XRefreshKeyboardMapping ((XMappingEvent *) &event);
+	
+    /* drop and ignore the following StructureNotifyMask events */
+    LastEvent (display, GravityNotify, &event);
+    LastEvent (display, ReparentNotify, &event);
+    LastEvent (display, MapNotify, &event);
+    LastEvent (display, UnmapNotify, &event);
+
+    /* handle button presses */
+    if (LastEvent (display, ButtonPress,     &event)) {
+      mouse_event = (XButtonEvent *) &event;
+      sprintf (string, "Button%d", mouse_event[0].button);
+      x = (mouse_event[0].x - layout[0].axis[0].fx)*(layout[0].axis[0].max - layout[0].axis[0].min)/layout[0].axis[0].dfx + layout[0].axis[0].min;
+      y = (mouse_event[0].y - layout[0].axis[1].fy)*(layout[0].axis[1].max - layout[0].axis[1].min)/layout[0].axis[1].dfy + layout[0].axis[1].min;
+      snprintf (line, 40, "%12s %12.6f %12.6f ", string, x, y);
+      write (sock, line, 40);
+    }
+
+    /* handle key presses */
+    if (LastEvent (display, KeyPress,        &event)) {
+      value = XLookupString ((XKeyEvent *) &event, string, 9, &keysym, &composestatus);
+      name = XKeysymToString (keysym);
+
+      // ignore unmapped keys
+      if (name == NULL) continue;
+
+      x = (event.xkey.x - layout[0].axis[0].fx)*(layout[0].axis[0].max - layout[0].axis[0].min)/layout[0].axis[0].dfx + layout[0].axis[0].min;
+      y = (event.xkey.y - layout[0].axis[1].fy)*(layout[0].axis[1].max - layout[0].axis[1].min)/layout[0].axis[1].dfy + layout[0].axis[1].min;
+
+      // skip the following keys: 
+      if (!strcmp (name, "Shift_L")) continue;
+      if (!strcmp (name, "Shift_R")) continue;
+      if (!strcmp (name, "Control_L")) continue;
+      if (!strcmp (name, "Control_R")) continue;
+      if (!strcmp (name, "Alt_L")) continue;
+      if (!strcmp (name, "Alt_R")) continue;
+      if (!strcmp (name, "Super_L")) continue;
+      if (!strcmp (name, "Super_R")) continue;
+      if (!strcmp (name, "Caps_Lock")) continue;
+      if (!strcmp (name, "Pause")) continue;
+      if (!strcmp (name, "Continue")) continue;
+      if (!strcmp (name, "Num_Lock")) continue;
+      if (!strcmp (name, "Scroll_Lock")) continue;
+      if (!strcmp (name, "Print")) continue;
+      if (!strcmp (name, "(null)")) continue;
+
+      snprintf (line, 40, "%12s %12.6f %12.6f ", name, x, y);
+      write (sock, line, 40);
+    }
+
+    /* remove those events we will ignore */
+    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;
+
+    /* events to remove which have no mask component */
+    while (XCheckTypedEvent (display, ClientMessage, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionClear, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionNotify, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionRequest, &event)) continue;
+  }
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/Ximage.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/Ximage.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/Ximage.h	(revision 16632)
@@ -0,0 +1,7 @@
+# include <Xohana.h>
+# include <dvo.h>
+# include <kapa.h>
+# include "constants.h"
+# include "structures.h"
+# include "prototypes.h"
+# include "globals.h"
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/alphabet.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/alphabet.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/alphabet.h	(revision 16632)
@@ -0,0 +1,53 @@
+# include "../rotfont/times8.h"
+# include "../rotfont/times12.h"
+# include "../rotfont/times14.h"
+# include "../rotfont/times18.h"
+# include "../rotfont/times24.h"
+
+# include "../rotfont/courier8.h"
+# include "../rotfont/courier12.h"
+# include "../rotfont/courier14.h"
+# include "../rotfont/courier18.h"
+# include "../rotfont/courier24.h"
+
+# include "../rotfont/helvetica8.h"
+# include "../rotfont/helvetica12.h"
+# include "../rotfont/helvetica14.h"
+# include "../rotfont/helvetica18.h"
+# include "../rotfont/helvetica24.h"
+
+# include "../rotfont/symbol8.h"
+# include "../rotfont/symbol12.h"
+# include "../rotfont/symbol14.h"
+# include "../rotfont/symbol18.h"
+# include "../rotfont/symbol24.h"
+
+# define DEFFONT 1
+static FontSet HardwiredFonts[] = {
+  {times8font,  "times", 8},
+  {times12font, "times", 12},
+  {times14font, "times", 14},
+  {times18font, "times", 18},
+  {times24font, "times", 24},
+  
+  {courier8font,  "courier", 8},
+  {courier12font, "courier", 12},
+  {courier14font, "courier", 14},
+  {courier18font, "courier", 18},
+  {courier24font, "courier", 24},
+  
+  {helvetica8font,  "helvetica", 8},
+  {helvetica12font, "helvetica", 12},
+  {helvetica14font, "helvetica", 14},
+  {helvetica18font, "helvetica", 18},
+  {helvetica24font, "helvetica", 24},
+  
+  {symbol8font,  "symbol", 8},
+  {symbol12font, "symbol", 12},
+  {symbol14font, "symbol", 14},
+  {symbol18font, "symbol", 18},
+  {symbol24font, "symbol", 24}
+};
+
+/* put these as static in RotFont.c with accessor functions */
+# define NROT 256
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/buttons.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/buttons.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/buttons.h	(revision 16632)
@@ -0,0 +1,120 @@
+#define PS_width 25
+#define PS_height 25
+static char PS_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x81, 0x3f, 0x00,
+   0x82, 0x67, 0x60, 0x00, 0x02, 0x26, 0x40, 0x00, 0x02, 0x24, 0x40, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x02, 0xc6, 0x00, 0x00,
+   0x82, 0x07, 0x07, 0x00, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x18, 0x00,
+   0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x40, 0x00,
+   0x02, 0x00, 0xc0, 0x00, 0x02, 0x10, 0x80, 0x00, 0x02, 0x10, 0xc0, 0x00,
+   0x02, 0x60, 0x60, 0x00, 0x02, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00}; 
+#define grey_width 25
+#define grey_height 25
+static char grey_bits[] = {
+   0x90, 0x40, 0xf7, 0x01, 0x04, 0xaa, 0xad, 0x01, 0x68, 0xd5, 0xfe, 0x01,
+   0x82, 0x28, 0xdb, 0x01, 0x10, 0xd2, 0x75, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xac, 0x50, 0xbf, 0x01, 0x00, 0xaa, 0xf9, 0x01, 0x52, 0xd5, 0xd6, 0x01,
+   0x80, 0x28, 0x6f, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x44, 0xad, 0xba, 0x01,
+   0x90, 0x50, 0xf7, 0x01, 0x02, 0xaa, 0xcd, 0x01, 0x68, 0xd5, 0x7e, 0x01,
+   0x80, 0x28, 0xfb, 0x01, 0x14, 0xd2, 0xb5, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xaa, 0x50, 0xdf, 0x01, 0x00, 0xaa, 0x79, 0x01, 0x50, 0xd5, 0xf6, 0x01,
+   0x84, 0x28, 0xaf, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x40, 0xad, 0xda, 0x01,
+   0x90, 0x50, 0x77, 0x01};
+#define rainbow_width 25
+#define rainbow_height 25
+static char rainbow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0x00, 0x00, 0x70, 0x00, 0x01, 0x00, 0x0c, 0x7f, 0x00,
+   0x00, 0xe3, 0x80, 0x01, 0xc0, 0x9c, 0xff, 0x00, 0x20, 0x62, 0x00, 0x01,
+   0x90, 0x99, 0xff, 0x00, 0x48, 0x76, 0x00, 0x01, 0x24, 0x09, 0x00, 0x00,
+   0x94, 0x06, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
+   0xa5, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+   0x2a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00};
+#define recenter_width 25
+#define recenter_height 25
+static char recenter_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0x30, 0x00, 0x18, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x30, 0x00, 0x08, 0x00, 0x20, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x0c, 0x7c, 0x60, 0x00,
+   0x04, 0x7c, 0x40, 0x00, 0x0c, 0x7c, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x18, 0x00, 0x30, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x0e, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define puns_width 25
+#define puns_height 25
+static char puns_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xd8, 0x01,
+   0x00, 0x0c, 0x37, 0x00, 0xf8, 0xc9, 0x6f, 0x00, 0x0c, 0xde, 0xf0, 0x00,
+   0x06, 0x5b, 0x1f, 0x00, 0x7b, 0xd9, 0x0c, 0x00, 0xc9, 0x70, 0x06, 0x00,
+   0x81, 0x71, 0x03, 0x00, 0x78, 0xb9, 0x39, 0x00, 0xc8, 0xdb, 0x0f, 0x00,
+   0x84, 0xf7, 0x7f, 0x00, 0x04, 0xff, 0xc3, 0x00, 0xe6, 0xfe, 0x8e, 0x00,
+   0x9a, 0x7d, 0x0b, 0x00, 0x08, 0xbc, 0x01, 0x00, 0x08, 0xfc, 0x3f, 0x00,
+   0x0c, 0xff, 0x78, 0x00, 0x84, 0x39, 0x60, 0x00, 0x40, 0x38, 0x40, 0x00,
+   0x60, 0x38, 0x40, 0x00, 0x20, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+   0x00, 0xd6, 0x00, 0x00};
+#define red_width 25
+#define red_height 25
+static char red_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x03, 0x00,
+   0x20, 0x07, 0x06, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x06, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0xe0, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe0, 0xc3, 0x00, 0x00,
+   0x20, 0xc0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
+   0x20, 0x00, 0x06, 0x00, 0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x18, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define green_width 25
+#define green_height 25
+static char green_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00,
+   0x00, 0x06, 0x04, 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x80, 0x0f, 0x00, 0x40, 0xc0, 0x30, 0x00,
+   0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x08, 0x00,
+   0x00, 0x03, 0x08, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, 0xc0, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define blue_width 25
+#define blue_height 25
+static char blue_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0x00, 0x00,
+   0xc0, 0x83, 0x07, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0x40, 0x80, 0x07, 0x00, 0x40, 0xe0, 0x0c, 0x00, 0xc0, 0x3f, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x06, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0xc0, 0x80, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define yellow_width 25
+#define yellow_height 25
+static char yellow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
+   0x80, 0x01, 0x0c, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x02, 0x02, 0x00,
+   0x00, 0x84, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define hms_width 25
+#define hms_height 25
+static char hms_bits[] = {
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0xf0, 0x00, 0x1e, 0xef, 0x89, 0x00,
+   0x22, 0x11, 0x09, 0x00, 0x22, 0x11, 0x71, 0x00, 0x22, 0x11, 0x81, 0x00,
+   0x22, 0x11, 0x89, 0x00, 0x22, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x1e, 0xc7, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x5c, 0xb8, 0xb8, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x42, 0x84, 0x84, 0x00, 0x42, 0x84, 0x84, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x5c, 0xb9, 0xb8, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/constants.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/constants.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/constants.h	(revision 16632)
@@ -0,0 +1,45 @@
+/* hardwired values for some window parameters */
+
+# define EVENT_MASK (long) \
+(ButtonPressMask \
+ | ClientMessage \
+ | ButtonReleaseMask \
+ | KeyPressMask \
+ | ExposureMask \
+ | StructureNotifyMask \
+ | PointerMotionMask)
+
+# define DEFAULT_CURSOR XC_crosshair
+# define BORDER_WIDTH 2
+# define MIN_WIDTH 250
+# define MIN_HEIGHT 250
+# define LABEL_MAXLEN 128
+
+/* label names */
+# define LABELX0 0
+# define LABELY0 1
+# define LABELX1 2
+# define LABELY1 3
+# define LABELUL 4
+# define LABELUR 5
+# define LABELLL 6
+# define LABELLR 7
+
+/* EVENT_MASK consists of:
+
+ExposureMask        : Expose
+StructureNotifyMask : CirculateNotify | 
+                      ConfigureNotify | 
+                      DestroyNotify   | 
+		      GravityNotify   | 
+		      MapNotify       |
+		      ReparentNotify  |
+		      UnmapNotify
+ButtonPressMask     : ButtonPress
+ButtonReleaseMask   : ButtonRelease
+KeyPressMask        : KeyPress
+PointerMotionMask   : MotionNotify
+(always)            : ClientMessage 
+(always)            : MappingNotify
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/globals.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/globals.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/globals.h	(revision 16632)
@@ -0,0 +1,21 @@
+
+int HAVE_BACKING;
+int DEBUG;
+int USE_XWINDOW;
+int MAP_WINDOW;
+int FOREGROUND;
+char *NAME_WINDOW;
+
+/* file descriptor for socket connection to mana */
+int sock; 
+
+/* each layout / section defines one of the active portions of the graphics window
+   there may be an arbitrary number of sections, and each section may fill an arbitrary
+   rectangle in the X window.  The startup configuration assumes 1 section filling the 
+   entire X window. */
+
+Layout *section;
+int    Nsection, TheSection;
+
+/* graphic defines the basic details of the X window */
+Graphic graphic;
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/arrow.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/arrow.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/arrow.h	(revision 16632)
@@ -0,0 +1,4 @@
+#define arrow_width 6
+#define arrow_height 9
+static char arrow_bits[] = {
+   0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/back.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/back.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/back.h	(revision 16632)
@@ -0,0 +1,6 @@
+#define back_width 16
+#define back_height 16
+static char back_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x3f, 0xc0, 0x3f,
+   0xf0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0x3f,
+   0x00, 0x3c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/down.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/down.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/down.h	(revision 16632)
@@ -0,0 +1,4 @@
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/fore.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/fore.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/fore.h	(revision 16632)
@@ -0,0 +1,6 @@
+#define fore_width 16
+#define fore_height 16
+static char fore_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0xfc, 0x00, 0xfc, 0x03,
+   0xfc, 0x0f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x0f, 0xfc, 0x03, 0xfc, 0x00,
+   0x3c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/icon.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/icon.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/icon.h	(revision 16632)
@@ -0,0 +1,13 @@
+#define icon_width 29
+#define icon_height 29
+static unsigned char icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/stop.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/stop.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/icons/stop.h	(revision 16632)
@@ -0,0 +1,6 @@
+#define stop_width 16
+#define stop_height 16
+static char stop_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/prototypes.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/prototypes.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/prototypes.h	(revision 16632)
@@ -0,0 +1,132 @@
+Button       *CheckButtons        PROTO((XButtonEvent *, Layout *));
+void          CheckColors         PROTO((int *, char **));
+void          CheckDisplayName    PROTO((int *, char **, char *));
+void          CheckFontName       PROTO((int *, char **, char *));
+void          CheckGeometry       PROTO((int *, char **));
+int           CheckPipe           PROTO(());
+void          CreateWindow        PROTO((Window, int, long));
+void          DefineLayout        PROTO((int, char **));
+void          DrawConnect         PROTO((Layout *, Gobjects *));
+void          DrawFrame           PROTO((Layout *));
+void          DrawHistogram       PROTO((Layout *, Gobjects *));
+void          DrawLabels          PROTO((Layout *));
+int           DrawObjectN         PROTO((Layout *, Gobjects *));
+int           DrawObjects         PROTO((Layout *));
+void          DrawPoints          PROTO((Layout *, Gobjects *));
+void          DrawXErrors         PROTO((Layout *, Gobjects *));
+void          DrawYErrors         PROTO((Layout *, Gobjects *));
+int           ErasePlot           PROTO(());
+unsigned long GetColor            PROTO((Display *, char *, Colormap, unsigned long));
+int           GetColormapSize     PROTO(());
+char         *GetRGBString        PROTO((int N));
+int           InButton            PROTO((XButtonEvent *, Button *));
+int           InPicture           PROTO((XButtonEvent *, Picture *));
+int           ListSection         PROTO(());
+int           LoadBox             PROTO(());
+void          LoadFont            PROTO((int *, char **, char *));
+int           LoadLabels          PROTO(());
+int           LoadObject          PROTO(());
+int           LoadPtext           PROTO(());
+int           LoadVectorData      PROTO((Layout *, int, char *));
+void          MakeColormap        PROTO((int, char **));
+void          MakeCursor          PROTO((unsigned int));
+void          MapWindow           PROTO(());
+void          NameWindow          PROTO((char *));
+Display      *OpenDisplay         PROTO((char *, int *));
+int           PNGit               PROTO(());
+int           PPMit               PROTO(());
+void          PSConnect           PROTO((Layout *, Gobjects *, FILE *));
+int           PSFrame             PROTO((Layout *, FILE *));
+void          PSHistogram         PROTO((Layout *, Gobjects *, FILE *));
+void          PSLabels            PROTO((Layout *, FILE *));
+int           PSObjects           PROTO((Layout *, FILE *));
+void          PSPoints            PROTO((Layout *, Gobjects *, FILE *));
+void          PSXErrors           PROTO((Layout *, Gobjects *, FILE *));
+void          PSYErrors           PROTO((Layout *, Gobjects *, FILE *));
+int           PSit                PROTO(());
+void          PositionPicture     PROTO((Layout *));
+void          QuitX               PROTO((Display *, char *, char *));
+int           Reconfig            PROTO((XEvent *));
+void          Refresh             PROTO((int));
+void          Remap               PROTO((Layout *, Matrix  *));
+int           Resize              PROTO(());
+int           SetFont             PROTO(());
+int           SetLimits           PROTO(());
+void          SetNormalHints      PROTO(());
+int           SetSection          PROTO((int SwitchSection));
+void          SetUpDisplay        PROTO((int *, char **));
+void          SetUpWindow         PROTO((int *, char **));
+void          SetWMHints          PROTO((Icon *));
+void          TopWindow           PROTO((Icon *));
+int           cursor              PROTO(());
+int           get_argument        PROTO((int, char **, char *));
+void          hh_hms              PROTO((char *, double, double, char));
+int           remove_argument     PROTO((int, int *, char **));
+
+void MakeGC ();
+
+int EventLoop ();
+void CloseDisplay ();
+int args (int *argc, char **argv);
+
+void DrawPtext (Layout *layout);
+void FlushDisplay ();
+void AxisTickScale (Axis *axis, double *major, double *minor);
+void DrawFrame (Layout *layout);
+void DrawTick (int fx, int fy, int dfx, int dfy, int P, double min, double max, double value, int mode, int naxis);
+void FreeObjectData (Gobjects *object);
+void PSPtext (Layout *layout, FILE *f);
+void PSTick (FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis);
+
+/* kapa bDraw Functions */
+int bDrawObjects (Layout *layout);
+void bDrawConnect (Layout *layout, Gobjects *object);
+void bDrawClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0);
+void bDrawHistogram (Layout *layout, Gobjects *object);
+void bDrawPoints (Layout *layout, Gobjects *object);
+void bDrawXErrors (Layout *layout, Gobjects *object);
+void bDrawYErrors (Layout *layout, Gobjects *object);
+
+int bDrawFrame (Layout *layout);
+void bDrawTick (double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis);
+void bDrawLabels (Layout *layout);
+void bDrawPtext (Layout *layout);
+
+bDrawBuffer *bDrawIt ();
+
+/******************* XGRAPH **
+void          StatusBox           PROTO((Graphic *, Layout *));
+void          ResetColorbar       PROTO((Graphic *, Layout *, double, double));
+void          Reorient            PROTO((Graphic *, Layout *, XButtonEvent *));
+void          PaintOverlay        PROTO((Graphic *, Layout *, int));
+void          MakeGC              PROTO((Graphic *));
+void          InvertButton        PROTO((Graphic *, Button *));
+void          FlashButton         PROTO((Graphic *, Button *));
+void          DrawButton          PROTO((Graphic *, Button *));
+void          DrawBitmap          PROTO((Graphic *, int, int, int, int, char *, int));
+void          DragColorbar        PROTO((Graphic *, Layout *, XButtonEvent *));
+void          CrossHairs          PROTO((Graphic *, Layout *));
+void          CreateZoom          PROTO((Layout *, Graphic *, double, double));
+void          CreatePicture       PROTO((Layout *, Graphic *));
+int           rainbow             PROTO((Graphic *, Layout *));
+int           puns                PROTO((Graphic *, Layout *));
+int           greycolors          PROTO((Graphic *, Layout *));
+int           UpdatePointer       PROTO((Graphic *, Layout *, XMotionEvent *));
+int           ToggleDEG           PROTO((Graphic *, Layout *));
+int           Stop                PROTO((Graphic *, Layout *));
+int           SaveOverlay         PROTO((Graphic *, Layout *));
+int           Rescale             PROTO((Graphic *, Layout *));
+int           RecenterRescale     PROTO((Graphic *, Layout *));
+int           Recenter            PROTO((Graphic *, Layout *));
+int           Overlay3            PROTO((Graphic *, Layout *));
+int           Overlay2            PROTO((Graphic *, Layout *));
+int           Overlay1            PROTO((Graphic *, Layout *));
+int           Overlay0            PROTO((Graphic *, Layout *));
+int           NewPicture          PROTO((Graphic *, Layout *));
+int           LoadOverlay         PROTO((Graphic *, Layout *));
+int           InterpretPresses    PROTO((Graphic *, Layout *, XButtonEvent *));
+int           InterpretKeys       PROTO((Graphic *, Layout *, XEvent *));
+int           EventLoop           PROTO((Graphic *, Layout *));
+int           EraseOverlay        PROTO((Graphic *, Layout *));
+int           CSaveOverlay        PROTO((Graphic *, Layout *));
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kapa/include/structures.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/include/structures.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/include/structures.h	(revision 16632)
@@ -0,0 +1,120 @@
+
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;
+  int            screen;
+  int            depth;
+  Window         window;
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  int            dx, dy;
+  Colormap       colormap;
+  unsigned long  fore;
+  unsigned long  back;
+  unsigned long  *color;
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      text;              /* does this have a picture or text? */
+  int      width, height;
+  char    *bitmap;          /* picture on button */
+  int    (*function_1) ();  /* mouse_button 1 function */
+  int    (*function_2) ();  /* mouse_button 2 function */
+  int    (*function_3) ();  /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  unsigned char *bits;
+} Icon;
+
+typedef struct {
+  int      dx, dy, x, y;
+  XImage  *pix;
+  char    *data;
+} Picture;
+
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int x, y;
+  int dx, dy;
+  double angle;
+  int  size;
+  char font[64]; 
+  char text[LABEL_MAXLEN];
+} Label;
+
+typedef struct {
+  int Nobjects;
+  unsigned long color;
+  Object *objects;
+} Overlay;
+  
+typedef struct {
+  float *x, *y, *z, *dxp, *dxm, *dyp, *dym;
+  int Npts;
+  int style, ptype, ltype, color, etype, ebar;
+  double lweight, size;
+  double x0, x1, y0, y1;  /* limits for this object */
+} Gobjects;
+
+typedef struct {
+  double min, max;
+  char isaxis, areticks, islabel, islog;
+  double fx, dfx, fy, dfy;  /* axis location on graphic */
+} Axis;
+
+/******** Here we define the Layout struct specific to this program  *******/
+typedef struct {
+  Axis      axis[4];    /* coordinate axes */
+  Label     label[8];   /* fixed axis labels */
+
+  Gobjects *objects;    /* graphic objects */    
+  int      Nobjects;    
+
+  Label    *ptext;      /* placed text labels */
+  int      Nptext;      
+
+  double   x, dx;      /* location of plot on window ( 0 - 1, 0 - 1 ) */
+  double   y, dy; 
+
+  char     name[LABEL_MAXLEN];  /* name of the section */
+
+} Layout;
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckColors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckColors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckColors.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+/************** CheckColors *************/
+void CheckColors (int *argc, char **argv) {
+
+  char *temp_name;
+  int N;
+
+  graphic.fore = BlackPixel (graphic.display, graphic.screen);
+  temp_name = XGetDefault (graphic.display, argv[0], "Foreground");
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -fg color\n");
+      exit (0);
+    }
+  }
+  if (temp_name != (char *) NULL) 
+    graphic.fore = GetColor (graphic.display, temp_name, graphic.colormap, graphic.fore);
+
+  graphic.back = WhitePixel (graphic.display, graphic.screen);
+  temp_name = XGetDefault (graphic.display, argv[0], "Background");
+  if ((N = get_argument (*argc, argv, "-bg"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -bg color\n");
+      exit (0);
+    }
+  }  
+  if (temp_name != (char *)NULL) 
+    graphic.back = GetColor (graphic.display, temp_name, graphic.colormap, graphic.back);
+ 
+}
+
+  /* here we define the values for foreground and background
+     if -fg, or -bg exist, or if Foreground or Background are set in .Xdefaults, 
+     use those.  foreground defaults to black, background defaults to white. */
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckDisplayName.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckDisplayName.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckDisplayName.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+/************** CheckDisplayName *************/
+void CheckDisplayName (int *argc, char **argv, char *display_name) {
+
+  int N;
+
+  display_name[0] = 0;
+  if ((N = get_argument (*argc, argv, "-d"))) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+
+  if ((N = get_argument (*argc, argv, "-display"))) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckFontName.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckFontName.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckFontName.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/************** CheckFontName *************/
+void CheckFontName (int *argc, char **argv, char *fontname) {
+
+  int N;
+
+  if ((N = get_argument (*argc, argv, "-font"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -font fontname\n");
+      exit (0);
+    }
+  }   
+  if ((N = get_argument (*argc, argv, "-fn"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -fn fontname\n");
+      exit (0);
+    }
+  }   
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckGeometry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckGeometry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/CheckGeometry.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "Ximage.h"
+
+/************** CheckGeometry *************/
+void CheckGeometry (int *argc, char **argv) {
+
+  int status, x, y, N;
+  unsigned int dx, dy;
+  int X, Y, dX, dY;
+  char *temp_name;
+  
+  temp_name = XGetDefault (graphic.display, argv[0], "geometry");
+  if ((N = get_argument (*argc, argv, "-geom"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -geom DisplayName\n");
+      exit (0);
+    }
+  }
+
+  X = 10;
+  Y = 10;
+  dX = 512;
+  dY = 512;
+  if (temp_name != (char *)NULL) {  
+    status = XParseGeometry (temp_name, &x, &y, &dx, &dy);
+    if (status & XValue) X = x;
+    if (status & YValue) Y = y;
+    if (status & WidthValue) {
+      dX = dx;
+    }
+    if (status & HeightValue) {
+      dY = dy;
+    }
+    if (status & XNegative) X  = DisplayWidth  (graphic.display, graphic.screen) - dX + X;
+    if (status & YNegative) Y  = DisplayHeight (graphic.display, graphic.screen) - dY + Y;
+  }
+
+  graphic.x = X;
+  graphic.y = Y;
+  graphic.dx = dX;
+  graphic.dy = dY; 
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/CloseDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/CloseDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/CloseDisplay.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "Ximage.h"
+
+/************** CloseDisplay *************/
+void CloseDisplay () {
+  XFreeFont (graphic.display, graphic.font); 
+  XFreeGC (graphic.display, graphic.gc);
+  XDestroySubwindows (graphic.display, graphic.window);
+  XDestroyWindow (graphic.display, graphic.window);
+  XFlush (graphic.display);
+  XCloseDisplay (graphic.display);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/CreateWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/CreateWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/CreateWindow.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+
+/************** CreateWindow *************/
+void CreateWindow (Window parent, int border, long events) {
+
+  XSetWindowAttributes attributes;
+  unsigned long attribute_mask;
+  Visual *visual = CopyFromParent;
+
+  HAVE_BACKING = (DoesBackingStore (ScreenOfDisplay(graphic.display, graphic.screen)) == Always);
+
+  if (HAVE_BACKING) {
+    attributes.backing_store = Always;
+    attribute_mask = CWBackingStore | CWBackPixel | CWBorderPixel | CWEventMask;
+  } else {
+    attribute_mask = CWBackPixel | CWBorderPixel | CWEventMask;
+  }
+
+  attributes.background_pixel = graphic.back;
+  attributes.border_pixel     = graphic.fore;
+  attributes.event_mask       = events;
+
+  graphic.window = XCreateWindow (graphic.display, parent, 
+				     graphic.x, graphic.y, 
+				     graphic.dx, graphic.dy, 
+				     border, CopyFromParent,
+				     InputOutput, visual, 
+				     attribute_mask, &attributes);
+
+  if (graphic.window == (Window) None)
+    QuitX (graphic.display, "", "error: could not open window");
+
+  XSelectInput (graphic.display, graphic.window, events);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/DefineLayout.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/DefineLayout.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/DefineLayout.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "Ximage.h"
+# define PAD 40
+
+/* general initialization for things not specific to X */
+void DefineLayout (int argc, char **argv) {
+
+  int i;
+  
+  /** initiate connection with server **/
+  if (!FOREGROUND) {	
+    if (argc < 2) {
+      fprintf (stderr, "socket path not specified\n");
+      exit (0);
+    }
+    sock = KiiWait (argv[1]);
+  }
+
+  InitRotFonts ();
+
+  /** set up defaults for display region **/
+  /* default startup uses one graphic region, filling the window */
+  
+  Nsection = 1;
+  ALLOCATE (section, Layout, Nsection);
+  TheSection = 0;
+
+  /* set up axis positions */
+  for (i = 0; i < 4; i++) {
+    section[0].axis[i].min = 0.0;
+    section[0].axis[i].max = 1.0;
+    section[0].axis[i].isaxis = FALSE;
+    section[0].axis[i].areticks = FALSE;
+    section[0].axis[i].islabel = FALSE;
+  }    
+  for (i = 0; i < 8; i++) {
+    strcpy (section[0].label[i].text, "");
+  }
+  section[0].x  = 0;
+  section[0].dx = 1; 
+  section[0].y  = 0; 
+  section[0].dy = 1; 
+  strcpy (section[0].name, "default");
+
+  PositionPicture (&section[0]);
+
+  section[0].Nobjects = 0;
+  section[0].Nptext = 0;
+
+  ALLOCATE (section[0].objects, Gobjects, 1);  /* allocate so later free will not crash! */
+  section[0].objects[0].x   = section[0].objects[0].y   = section[0].objects[0].z = (float *) NULL;
+  section[0].objects[0].dxm = section[0].objects[0].dxp = (float *) NULL;
+  section[0].objects[0].dym = section[0].objects[0].dyp = (float *) NULL;
+  
+  ALLOCATE (section[0].ptext, Label, 1);       /* allocate so later free will not crash! */
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/GetColor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/GetColor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/GetColor.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+
+/************** GetColor *************/
+unsigned long 
+GetColor (display, name, colormap, default_color)
+Display  *display;
+char      name[];
+Colormap  colormap;
+unsigned long default_color;
+{
+
+  unsigned long color;
+  XColor rgbcolor, hardwarecolor;
+  int status;
+
+  color = default_color;
+  status = XLookupColor (display, colormap, name, &rgbcolor, &hardwarecolor);
+  if (status) {
+    status = XAllocColor (display, colormap, &hardwarecolor);
+    if (status) {
+      color = hardwarecolor.pixel;
+    }
+  }
+  return (color);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/LoadFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/LoadFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/LoadFont.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** LoadFont *************/
+void LoadFont (int *argc, char **argv, char *default_name) {
+
+  char name[400];
+  char *temp_name;
+
+  temp_name = XGetDefault (graphic.display, argv[0], "Font");
+  if (temp_name == (char *) NULL) 
+    strcpy (name, default_name);
+  else 
+    strcpy (name, temp_name);
+
+  CheckFontName (argc, argv, name);
+
+  graphic.font = XLoadQueryFont (graphic.display, name);
+  if (graphic.font == (XFontStruct *) NULL) {
+    fprintf (stderr, "Could not load fond %s, using %s\n", name, default_name);
+    graphic.font = XLoadQueryFont (graphic.display, default_name);
+    if (graphic.font == (XFontStruct *) NULL) {
+      graphic.font = XLoadQueryFont (graphic.display, "fixed");
+      fprintf (stderr, "Could not load fond %s, using %s\n", default_name, "fixed");
+    }
+  }
+
+  if (graphic.font != (XFontStruct *) NULL) 
+    XSetFont (graphic.display, graphic.gc, graphic.font[0].fid);
+  else
+    QuitX (graphic.display, "Error: could not load font", name);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/MakeCursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/MakeCursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/MakeCursor.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** MakeCursor *************/
+void MakeCursor (unsigned int which_cursor) {
+
+  graphic.cursor = XCreateFontCursor (graphic.display, (unsigned) which_cursor);
+
+  if (graphic.cursor != (Cursor) None) XDefineCursor (graphic.display, graphic.window, graphic.cursor);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/MakeGC.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/MakeGC.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/MakeGC.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "Ximage.h"
+
+/************** MakeGC *************/
+void MakeGC () {
+
+  XGCValues gcvalues;
+
+  gcvalues.foreground = graphic.fore;
+  gcvalues.background = graphic.back;
+  graphic.gc = XCreateGC (graphic.display, graphic.window, 
+			     GCForeground | GCBackground, &gcvalues);
+  if (graphic.gc == 0)
+    QuitX (graphic.display, "Error in creating a Graphics Context", "");
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/MapWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/MapWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/MapWindow.c	(revision 16632)
@@ -0,0 +1,10 @@
+# include "Ximage.h"
+
+/************** MapWindow *************/
+void MapWindow () {
+
+  XMapRaised (graphic.display, graphic.window);
+  XMapSubwindows (graphic.display, graphic.window);
+  FlushDisplay ();
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/NameWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/NameWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/NameWindow.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** NameWindow *************/
+void NameWindow (char *Name) {
+
+  char       *name;
+  char       *class_name;
+  char       *class_type;
+  XClassHint *classhints;
+
+  name = strrchr (Name, '/');
+  if (name != NULL) 
+    name ++;
+  else 
+    name = Name;
+
+  class_type = class_name = name;
+  classhints = XAllocClassHint ();
+
+  if (classhints != (XClassHint *) NULL)  {
+    classhints[0].res_name = class_name;
+    classhints[0].res_class = class_type;
+    XSetClassHint (graphic.display, graphic.window, classhints);
+    XFree (classhints);
+  }
+  
+  XStoreName (graphic.display, graphic.window, name);
+  XSetIconName (graphic.display, graphic.window, name);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/OpenDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/OpenDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/OpenDisplay.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "Ximage.h"
+
+/************** OpenDisplay *************/
+Display *OpenDisplay (char *display_name, int *screen) {
+
+  Display *display;
+  
+  display = XOpenDisplay (display_name);
+  if (display != (Display *) NULL) *screen = DefaultScreen (display);
+  if (display == (Display *) NULL) {
+    fprintf (stderr, "Error could not open X display to %s\n", XDisplayName (display_name));
+    exit (0);
+  }
+  
+  return (display);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/QuitX.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/QuitX.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/QuitX.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "Ximage.h"
+
+/************** QuitX *************/
+void QuitX (Display *display, char *error_message, char *error_file) {
+
+  fprintf (stderr, "Error: %s%s\n", error_message, error_file);
+  XCloseDisplay (display);
+  exit (0);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetNormalHints.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetNormalHints.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetNormalHints.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "Ximage.h"
+
+/************** SetNormalHints  *************/
+void SetNormalHints () {
+
+  XSizeHints *sizehints;
+
+  sizehints = XAllocSizeHints ();
+
+  if (sizehints != (XSizeHints *) NULL)  {
+    sizehints[0].x = graphic.x;
+    sizehints[0].y = graphic.x;
+    sizehints[0].width = graphic.dx;
+    sizehints[0].height = graphic.dy;
+    sizehints[0].min_width = MIN_WIDTH;
+    sizehints[0].min_height = MIN_HEIGHT;    
+    sizehints[0].flags = USPosition | USSize | PMinSize;
+
+    sizehints[0].base_width = graphic.dx;
+    sizehints[0].base_height = graphic.dy;
+    sizehints[0].flags |= PBaseSize;
+    
+    XSetWMNormalHints (graphic.display, graphic.window, sizehints);
+    XFree (sizehints);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetUpDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetUpDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetUpDisplay.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+/************** SetUpDisplay *************/
+void SetUpDisplay (int *argc, char **argv) {
+
+  char display_name[120];
+
+  CheckDisplayName (argc, argv, display_name);
+
+  graphic.display  = OpenDisplay     (display_name,   &graphic.screen);
+  graphic.colormap = DefaultColormap (graphic.display, graphic.screen);
+  graphic.depth    = DefaultDepth    (graphic.display, graphic.screen);
+  CheckColors (argc, argv);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetUpWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetUpWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetUpWindow.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "Ximage.h"
+# include "icons/icon.h"
+
+/************** SetUpWindow *************/
+void SetUpWindow (int *argc, char **argv) {
+
+  Icon icon;
+  char *name;
+  int Ncolors;
+
+  icon.width = icon_width;
+  icon.height = icon_height;
+  icon.bits = icon_bits;
+
+  CheckGeometry (argc, argv);
+  TopWindow (&icon);
+  LoadFont (argc, argv, "fixed"); 
+
+  FlushDisplay ();
+  XSetWindowBackground (graphic.display, graphic.window, graphic.back);
+
+  SetNormalHints ();
+  SetWMHints (&icon);
+
+  if (NAME_WINDOW == NULL) {
+    NameWindow ("Kapa");
+  } else {
+    ALLOCATE (name, char, strlen(NAME_WINDOW) + 10);
+    sprintf (name, "Kapa %s", NAME_WINDOW);
+    NameWindow (name);
+    free (name);
+  }
+
+  graphic.color = KapaX11colors (graphic.display, graphic.colormap, graphic.fore, &Ncolors);
+  if (MAP_WINDOW) MapWindow (graphic);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetWMHints.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetWMHints.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/SetWMHints.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+
+/************** SetWMHints  *************/
+void SetWMHints (Icon *icon) {
+
+  XWMHints *wmhints;
+
+  wmhints = XAllocWMHints ();
+  if (wmhints != (XWMHints *) NULL) {
+    wmhints[0].initial_state = NormalState;
+    wmhints[0].input = True;
+    if (icon[0].pixmap != (Pixmap) None) {
+      wmhints[0].icon_pixmap = icon[0].pixmap;
+      wmhints[0].icon_mask = icon[0].pixmap;
+      wmhints[0].flags = StateHint | InputHint | IconPixmapHint | IconMaskHint;
+    } else {
+      wmhints[0].flags = StateHint | InputHint;
+    }
+    
+    XSetWMHints (graphic.display, graphic.window, wmhints);
+    XFree (wmhints);
+
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/TopWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/TopWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/TopWindow.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+/************** TopWindow *************/
+void TopWindow (Icon *icon) {
+
+  Window rootwindow;
+
+  rootwindow = RootWindow (graphic.display, graphic.screen);
+
+  CreateWindow (rootwindow, BORDER_WIDTH, EVENT_MASK);
+  MakeGC ();
+
+  icon[0].pixmap = XCreateBitmapFromData (graphic.display, graphic.window, (char *) icon[0].bits, icon[0].width, icon[0].height);
+
+  MakeCursor (DEFAULT_CURSOR);
+  XFreeCursor (graphic.display, graphic.cursor);
+  FlushDisplay ();
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/Ximage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/Ximage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/Ximage.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "Ximage.h"
+
+int main (int argc, char **argv) {
+  
+  /* this is a lame place to put this default */
+  graphic.x = 10;
+  graphic.y = 10;
+  graphic.dx = 512;
+  graphic.dy = 512; 
+
+  args (&argc, argv);
+
+  if (USE_XWINDOW) SetUpDisplay (&argc, argv); /* skip if Xless */
+  if (USE_XWINDOW) SetUpWindow (&argc, argv);  /* skip if Xless */
+
+  DefineLayout (argc, argv); 
+  EventLoop ();
+
+  if (USE_XWINDOW) CloseDisplay ();
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa/setup/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa/setup/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa/setup/args.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+int args (int *argc, char **argv) {
+
+  int N;
+
+  MAP_WINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-nomap"))) {
+    remove_argument(N, argc, argv);
+    MAP_WINDOW = FALSE;
+  }
+
+  NAME_WINDOW = NULL;
+  if ((N = get_argument (*argc, argv, "-name"))) {
+    remove_argument(N, argc, argv);
+    NAME_WINDOW = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+  }
+
+  USE_XWINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-noX"))) {
+    remove_argument(N, argc, argv);
+    USE_XWINDOW = FALSE;
+  }
+
+  if ((N = get_argument (*argc, argv, "-debug"))) {
+    remove_argument(N, argc, argv);
+    DEBUG = TRUE;
+  } else {
+    DEBUG = FALSE;
+  }
+
+  FOREGROUND = FALSE;
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    remove_argument(N, argc, argv);
+    FOREGROUND = TRUE;
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+bin
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/Makefile	(revision 16632)
@@ -0,0 +1,94 @@
+default: kapa
+help:
+	@echo "make options: kapa (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/kapa2
+LIB	=	$(HOME)/lib
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+INC	=	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+LDDEPS  = $(DESTLIB)/libkapa.a $(DESTLIB)/libdvo.a $(DESTLIB)/libFITS.a $(DESTLIB)/libohana.a
+INDEPS  = $(DESTINC)/kapa.h $(DESTINC)/dvo.h $(DESTINC)/gfitsio.h $(DESTINC)/ohana.h
+
+kapa: $(BIN)/kapa.$(ARCH)
+install: $(DESTBIN)/kapa
+
+KAPA = \
+$(SRC)/kapa.$(ARCH).o                     $(SRC)/args.$(ARCH).o               \
+$(SRC)/SetUpGraphic.$(ARCH).o             $(SRC)/NameWindow.$(ARCH).o         \
+$(SRC)/CheckColors.$(ARCH).o              $(SRC)/MakeGC.$(ARCH).o             \
+$(SRC)/CheckDisplayName.$(ARCH).o  	  $(SRC)/MapWindow.$(ARCH).o          \
+$(SRC)/CheckGeometry.$(ARCH).o     	  $(SRC)/OpenDisplay.$(ARCH).o        \
+$(SRC)/CloseDisplay.$(ARCH).o      	  $(SRC)/QuitX.$(ARCH).o              \
+$(SRC)/CreateWindow.$(ARCH).o      	  $(SRC)/SetNormalHints.$(ARCH).o     \
+$(SRC)/GetColor.$(ARCH).o          	  $(SRC)/SetWMHints.$(ARCH).o         \
+$(SRC)/LoadFont.$(ARCH).o          	  $(SRC)/TopWindow.$(ARCH).o          \
+$(SRC)/MakeCursor.$(ARCH).o		  $(SRC)/FlushDisplay.$(ARCH).o       \
+$(SRC)/LoadObject.$(ARCH).o		  $(SRC)/LoadFrame.$(ARCH).o	      \
+$(SRC)/LoadTextlines.$(ARCH).o		  $(SRC)/LoadLabels.$(ARCH).o         \
+$(SRC)/DrawObjects.$(ARCH).o              $(SRC)/DrawFrame.$(ARCH).o          \
+$(SRC)/DrawTextlines.$(ARCH).o		  $(SRC)/DrawLabels.$(ARCH).o         \
+$(SRC)/PSObjects.$(ARCH).o		  $(SRC)/PSFrame.$(ARCH).o            \
+$(SRC)/PSLabels.$(ARCH).o		  $(SRC)/PSTextlines.$(ARCH).o        \
+$(SRC)/bDrawObjects.$(ARCH).o	  	  $(SRC)/bDrawFrame.$(ARCH).o         \
+$(SRC)/bDrawLabels.$(ARCH).o              $(SRC)/bDrawIt.$(ARCH).o            \
+$(SRC)/PNGit.$(ARCH).o                    $(SRC)/PPMit.$(ARCH).o	      \
+$(SRC)/PSit.$(ARCH).o                     $(SRC)/CrossHairs.$(ARCH).o         \
+$(SRC)/CheckPipe.$(ARCH).o                $(SRC)/EventLoop.$(ARCH).o          \
+$(SRC)/Reconfig.$(ARCH).o                 $(SRC)/Refresh.$(ARCH).o            \
+$(SRC)/Layout.$(ARCH).o		  	  $(SRC)/Sections.$(ARCH).o	      \
+$(SRC)/Graphs.$(ARCH).o                   $(SRC)/SetGraphSize.$(ARCH).o       \
+$(SRC)/Resize.$(ARCH).o                   $(SRC)/ErasePlots.$(ARCH).o         \
+$(SRC)/EraseImage.$(ARCH).o         	  $(SRC)/SetToolbox.$(ARCH).o         \
+$(SRC)/EraseCurrentPlot.$(ARCH).o         $(SRC)/EraseSections.$(ARCH).o      \
+$(SRC)/SetSection.$(ARCH).o		  $(SRC)/DefineSection.$(ARCH).o      \
+$(SRC)/SetLimits.$(ARCH).o                $(SRC)/SetFont.$(ARCH).o            \
+$(SRC)/Center.$(ARCH).o                   $(SRC)/Remap.$(ARCH).o              \
+$(SRC)/Remap8.$(ARCH).o                   $(SRC)/Remap16.$(ARCH).o            \
+$(SRC)/Remap24.$(ARCH).o                  $(SRC)/Remap32.$(ARCH).o            \
+$(SRC)/LoadPicture.$(ARCH).o              $(SRC)/Image.$(ARCH).o              \
+$(SRC)/SetImageSize.$(ARCH).o             $(SRC)/GetPixelCount.$(ARCH).o      \
+$(SRC)/StatusBox.$(ARCH).o                $(SRC)/UpdateStatusBox.$(ARCH).o    \
+$(SRC)/DrawButton.$(ARCH).o               $(SRC)/DrawBitmap.$(ARCH).o         \
+$(SRC)/hh_hms.$(ARCH).o	                  $(SRC)/CreateZoom.$(ARCH).o         \
+$(SRC)/CreatePicture.$(ARCH).o            $(SRC)/CreateColorbar.$(ARCH).o     \
+$(SRC)/MakeColormap.$(ARCH).o		  $(SRC)/SetColormap.$(ARCH).o        \
+$(SRC)/PaintOverlay.$(ARCH).o		  $(SRC)/SetGraphData.$(ARCH).o       \
+$(SRC)/LoadOverlay.$(ARCH).o		  $(SRC)/EraseOverlay.$(ARCH).o       \
+$(SRC)/SaveOverlay.$(ARCH).o              $(SRC)/SetImageData.$(ARCH).o       \
+$(SRC)/CSaveOverlay.$(ARCH).o		  $(SRC)/EraseOverlay.$(ARCH).o       \
+$(SRC)/CheckVisual.$(ARCH).o              $(SRC)/CursorOps.$(ARCH).o          \
+$(SRC)/InterpretKeys.$(ARCH).o            $(SRC)/InterpretPresses.$(ARCH).o   \
+$(SRC)/DragColorbar.$(ARCH).o             $(SRC)/Reorient.$(ARCH).o           \
+$(SRC)/InButton.$(ARCH).o                 $(SRC)/InPicture.$(ARCH).o          \
+$(SRC)/CheckButtons.$(ARCH).o             $(SRC)/InvertButton.$(ARCH).o       \
+$(SRC)/UpdatePointer.$(ARCH).o            $(SRC)/JPEGit24.$(ARCH).o           \
+$(SRC)/bDrawOverlay.$(ARCH).o             $(SRC)/ButtonFunctions.$(ARCH).o    \
+$(SRC)/PSimage.$(ARCH).o                  $(SRC)/PSPixmap.$(ARCH).o           \
+$(SRC)/PSOverlay.$(ARCH).o                $(SRC)/SetChannel.$(ARCH).o         \
+$(SRC)/SetColorScale.$(ARCH).o            $(SRC)/ColorCube.$(ARCH).o          \
+$(SRC)/ColorHistogram.$(ARCH).o           $(SRC)/CreateWide.$(ARCH).o
+
+#$(SRC)/CreateZoom8.$(ARCH).o              $(SRC)/CreateZoom16.$(ARCH).o       \
+#$(SRC)/CreateZoom24.$(ARCH).o             $(SRC)/CreateZoom32.$(ARCH).o       \
+
+OBJ  =  $(KAPA)
+
+# dependancy rules for include files ########################
+$(OBJ): $(INC)/Ximage.h \
+	$(INC)/constants.h \
+	$(INC)/structures.h \
+	$(INC)/prototypes.h
+
+$(OBJ): $(INDEPS) $(LDDEPS)
+
+$(BIN)/kapa.$(ARCH): $(OBJ)
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/doc/UpgradeConcepts.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/doc/UpgradeConcepts.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/doc/UpgradeConcepts.txt	(revision 16632)
@@ -0,0 +1,54 @@
+
+2007.05.08
+
+  User Commands:
+  * Add a section (position, type, name)
+  * Add a section element (add graph, add image)
+  * Del a section (by name)
+  * Del a section element (del graph, del image)
+  * Resize window (resizes each section)
+  * Set active section
+  * Get active section
+
+2007.05.06
+
+I am examining plans to upgrade the Kapa / Kii programs.  I have several ideas on this topic:
+
+* Completely merge the code base.  There are many common features, and
+  the merge will be easy.  The biggest difference between them from a
+  programming point of view is that Kapa uses global variables for the
+  layout and graphic (and other minor data), while Kii passes around
+  the Graphic / Layout elements.
+
+  The more object-oriented way to do this is to have private static
+  data for these concepts and to provide accessor functions to operate
+  on or retreive these pointers.  
+
+* Allow an arbitrary number of the graph / image widgets.  The image
+  widget should be considered a single item, which includes the main
+  image window, the zoom box, the status box, the buttons, etc.  The
+  positioning of the multiple graph / image elements in a single
+  window could be equivalent to the 'section' command for the graph
+  sub-boxes.  An image or a graph could be place at any X,Y,dX,dY
+  position with X,Y having a range of 0-1.  In addition, a graph
+  could be optionally tied to a specific image, with the location
+  determined by the image window location (ie, outer box of the image
+  window matched to bounding box of the graph).
+
+* Event parsing would need to go through the list of graph / image
+  elements to determine if the corresond to any of them.  
+
+* Drawing should be done in the order: images first, graphs second.
+  The sequence for the images and / or graphs should be adjustable.
+
+* create an equivalent to the zoom box which is a wide full-view of
+  the current image.
+
+* add the image flipping; this may be easiest using multiple versions
+  of the code with the correct sign flips...
+
+* carry the image data as a full 32 bit buffer
+
+* (optionally?) listed on an IP socket?
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/Ximage.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/Ximage.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/Ximage.h	(revision 16632)
@@ -0,0 +1,15 @@
+# include <X11/Xatom.h>
+# include <X11/Xlib.h>
+# include <X11/Xresource.h>
+# include <X11/Xutil.h>
+# include <X11/cursorfont.h>
+# include <X11/keysym.h>
+# include <X11/keysymdef.h>
+
+# include <ohana.h>
+# include <dvo.h>
+# include <kapa.h>
+# include "constants.h"
+# include "structures.h"
+# include "prototypes.h"
+# include "globals.h"
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/alphabet.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/alphabet.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/alphabet.h	(revision 16632)
@@ -0,0 +1,53 @@
+# include "../rotfont/times8.h"
+# include "../rotfont/times12.h"
+# include "../rotfont/times14.h"
+# include "../rotfont/times18.h"
+# include "../rotfont/times24.h"
+
+# include "../rotfont/courier8.h"
+# include "../rotfont/courier12.h"
+# include "../rotfont/courier14.h"
+# include "../rotfont/courier18.h"
+# include "../rotfont/courier24.h"
+
+# include "../rotfont/helvetica8.h"
+# include "../rotfont/helvetica12.h"
+# include "../rotfont/helvetica14.h"
+# include "../rotfont/helvetica18.h"
+# include "../rotfont/helvetica24.h"
+
+# include "../rotfont/symbol8.h"
+# include "../rotfont/symbol12.h"
+# include "../rotfont/symbol14.h"
+# include "../rotfont/symbol18.h"
+# include "../rotfont/symbol24.h"
+
+# define DEFFONT 1
+static FontSet HardwiredFonts[] = {
+  {times8font,  "times", 8},
+  {times12font, "times", 12},
+  {times14font, "times", 14},
+  {times18font, "times", 18},
+  {times24font, "times", 24},
+  
+  {courier8font,  "courier", 8},
+  {courier12font, "courier", 12},
+  {courier14font, "courier", 14},
+  {courier18font, "courier", 18},
+  {courier24font, "courier", 24},
+  
+  {helvetica8font,  "helvetica", 8},
+  {helvetica12font, "helvetica", 12},
+  {helvetica14font, "helvetica", 14},
+  {helvetica18font, "helvetica", 18},
+  {helvetica24font, "helvetica", 24},
+  
+  {symbol8font,  "symbol", 8},
+  {symbol12font, "symbol", 12},
+  {symbol14font, "symbol", 14},
+  {symbol18font, "symbol", 18},
+  {symbol24font, "symbol", 24}
+};
+
+/* put these as static in RotFont.c with accessor functions */
+# define NROT 256
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/buttons.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/buttons.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/buttons.h	(revision 16632)
@@ -0,0 +1,120 @@
+#define PS_width 25
+#define PS_height 25
+static char PS_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x81, 0x3f, 0x00,
+   0x82, 0x67, 0x60, 0x00, 0x02, 0x26, 0x40, 0x00, 0x02, 0x24, 0x40, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x02, 0xc6, 0x00, 0x00,
+   0x82, 0x07, 0x07, 0x00, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x18, 0x00,
+   0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x40, 0x00,
+   0x02, 0x00, 0xc0, 0x00, 0x02, 0x10, 0x80, 0x00, 0x02, 0x10, 0xc0, 0x00,
+   0x02, 0x60, 0x60, 0x00, 0x02, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00}; 
+#define grey_width 25
+#define grey_height 25
+static char grey_bits[] = {
+   0x90, 0x40, 0xf7, 0x01, 0x04, 0xaa, 0xad, 0x01, 0x68, 0xd5, 0xfe, 0x01,
+   0x82, 0x28, 0xdb, 0x01, 0x10, 0xd2, 0x75, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xac, 0x50, 0xbf, 0x01, 0x00, 0xaa, 0xf9, 0x01, 0x52, 0xd5, 0xd6, 0x01,
+   0x80, 0x28, 0x6f, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x44, 0xad, 0xba, 0x01,
+   0x90, 0x50, 0xf7, 0x01, 0x02, 0xaa, 0xcd, 0x01, 0x68, 0xd5, 0x7e, 0x01,
+   0x80, 0x28, 0xfb, 0x01, 0x14, 0xd2, 0xb5, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xaa, 0x50, 0xdf, 0x01, 0x00, 0xaa, 0x79, 0x01, 0x50, 0xd5, 0xf6, 0x01,
+   0x84, 0x28, 0xaf, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x40, 0xad, 0xda, 0x01,
+   0x90, 0x50, 0x77, 0x01};
+#define rainbow_width 25
+#define rainbow_height 25
+static char rainbow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0x00, 0x00, 0x70, 0x00, 0x01, 0x00, 0x0c, 0x7f, 0x00,
+   0x00, 0xe3, 0x80, 0x01, 0xc0, 0x9c, 0xff, 0x00, 0x20, 0x62, 0x00, 0x01,
+   0x90, 0x99, 0xff, 0x00, 0x48, 0x76, 0x00, 0x01, 0x24, 0x09, 0x00, 0x00,
+   0x94, 0x06, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
+   0xa5, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+   0x2a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00};
+#define recenter_width 25
+#define recenter_height 25
+static char recenter_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0x30, 0x00, 0x18, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x30, 0x00, 0x08, 0x00, 0x20, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x0c, 0x7c, 0x60, 0x00,
+   0x04, 0x7c, 0x40, 0x00, 0x0c, 0x7c, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x18, 0x00, 0x30, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x0e, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define heat_width 25
+#define heat_height 25
+static char heat_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xd8, 0x01,
+   0x00, 0x0c, 0x37, 0x00, 0xf8, 0xc9, 0x6f, 0x00, 0x0c, 0xde, 0xf0, 0x00,
+   0x06, 0x5b, 0x1f, 0x00, 0x7b, 0xd9, 0x0c, 0x00, 0xc9, 0x70, 0x06, 0x00,
+   0x81, 0x71, 0x03, 0x00, 0x78, 0xb9, 0x39, 0x00, 0xc8, 0xdb, 0x0f, 0x00,
+   0x84, 0xf7, 0x7f, 0x00, 0x04, 0xff, 0xc3, 0x00, 0xe6, 0xfe, 0x8e, 0x00,
+   0x9a, 0x7d, 0x0b, 0x00, 0x08, 0xbc, 0x01, 0x00, 0x08, 0xfc, 0x3f, 0x00,
+   0x0c, 0xff, 0x78, 0x00, 0x84, 0x39, 0x60, 0x00, 0x40, 0x38, 0x40, 0x00,
+   0x60, 0x38, 0x40, 0x00, 0x20, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+   0x00, 0xd6, 0x00, 0x00};
+#define red_width 25
+#define red_height 25
+static char red_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x03, 0x00,
+   0x20, 0x07, 0x06, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x06, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0xe0, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe0, 0xc3, 0x00, 0x00,
+   0x20, 0xc0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
+   0x20, 0x00, 0x06, 0x00, 0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x18, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define green_width 25
+#define green_height 25
+static char green_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00,
+   0x00, 0x06, 0x04, 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x80, 0x0f, 0x00, 0x40, 0xc0, 0x30, 0x00,
+   0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x08, 0x00,
+   0x00, 0x03, 0x08, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, 0xc0, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define blue_width 25
+#define blue_height 25
+static char blue_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0x00, 0x00,
+   0xc0, 0x83, 0x07, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0x40, 0x80, 0x07, 0x00, 0x40, 0xe0, 0x0c, 0x00, 0xc0, 0x3f, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x06, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0xc0, 0x80, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define yellow_width 25
+#define yellow_height 25
+static char yellow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
+   0x80, 0x01, 0x0c, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x02, 0x02, 0x00,
+   0x00, 0x84, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define hms_width 25
+#define hms_height 25
+static char hms_bits[] = {
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0xf0, 0x00, 0x1e, 0xef, 0x89, 0x00,
+   0x22, 0x11, 0x09, 0x00, 0x22, 0x11, 0x71, 0x00, 0x22, 0x11, 0x81, 0x00,
+   0x22, 0x11, 0x89, 0x00, 0x22, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x1e, 0xc7, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x5c, 0xb8, 0xb8, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x42, 0x84, 0x84, 0x00, 0x42, 0x84, 0x84, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x5c, 0xb9, 0xb8, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/constants.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/constants.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/constants.h	(revision 16632)
@@ -0,0 +1,93 @@
+/* hardwired values for some window parameters */
+
+# define EVENT_MASK (long) \
+(ButtonPressMask \
+ | ClientMessage \
+ | ButtonReleaseMask \
+ | KeyPressMask \
+ | ExposureMask \
+ | StructureNotifyMask \
+ | PointerMotionMask)
+
+# define NCHANNELS 3
+# define NPIXELS_DYNAMIC 128
+
+// XXX for the moment, this is set to match the values in SetColorScale3D_CC
+# define NPIXELS_STATIC 4600
+
+# define PAD1  3
+# define PAD2  5
+# define TEXTPAD 25
+# define COLORPAD 10
+# define TEXT_Y 15
+# define ZOOM_X 152
+# define ZOOM_Y 152
+# define NOVERLAYS 4
+# define BUTTON_WIDTH 28
+# define BUTTON_HEIGHT 28
+
+# define DEFAULT_CURSOR XC_crosshair
+# define BORDER_WIDTH 2
+# define MIN_WIDTH 50
+# define MIN_HEIGHT 50
+# define LABEL_MAXLEN 128
+
+typedef enum {
+    KAPA_SCALE_1D,
+    KAPA_SCALE_3D_RUFF,
+    KAPA_SCALE_3D_FULL
+} KapaColorScaleMode;
+
+/* label names */
+typedef enum {
+  LABELX0,
+  LABELY0,
+  LABELX1,
+  LABELY1,
+  LABELUL,
+  LABELUR,
+  LABELLL,
+  LABELLR
+} KapaLabelMode;
+
+typedef enum {
+  KAPA_CHANNEL_RED,
+  KAPA_CHANNEL_GREEN,
+  KAPA_CHANNEL_BLUE,
+} KapaChannels;
+
+// use an enum to identify the 3 dimensions:
+typedef enum {
+  CC_X,
+  CC_Y,
+  CC_Z,
+} CCDimen;
+
+/* EVENT_MASK consists of:
+
+ExposureMask        : Expose
+StructureNotifyMask : CirculateNotify | 
+                      ConfigureNotify | 
+                      DestroyNotify   | 
+		      GravityNotify   | 
+		      MapNotify       |
+		      ReparentNotify  |
+		      UnmapNotify
+ButtonPressMask     : ButtonPress
+ButtonReleaseMask   : ButtonRelease
+KeyPressMask        : KeyPress
+PointerMotionMask   : MotionNotify
+(always)            : ClientMessage 
+(always)            : MappingNotify
+
+*/
+
+# define NOVERLAYS 4
+/* number of overlays is defined here.
+   the number is also crucial in the following files:
+   PositionPictures.c
+   MakeColormap.c
+   prototypes.h
+*/
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/globals.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/globals.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/globals.h	(revision 16632)
@@ -0,0 +1,28 @@
+
+int   ACTIVE_CURSOR;
+int   HAVE_BACKING;
+int   DEBUG;
+int   USE_XWINDOW;
+int   MAP_WINDOW;
+int   FOREGROUND;
+char *NAME_WINDOW;
+
+/* these should be absorbed into KapaImageWidget 
+int OVERLAY[NOVERLAYS];
+int MOVE_POINTER;
+int DECIMAL_DEG;
+*/
+
+/* file descriptor for socket connection to mana */
+// int sock; 
+
+/* each layout / section defines one of the active portions of the graphics window
+   there may be an arbitrary number of sections, and each section may fill an arbitrary
+   rectangle in the X window.  The startup configuration assumes 1 section filling the 
+   entire X window. */
+
+// Layout *section;
+// int    Nsection, TheSection;
+
+/* graphic defines the basic details of the X window */
+// Graphic graphic;
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/icons.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/icons.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/icons.h	(revision 16632)
@@ -0,0 +1,43 @@
+
+#define icon_width 29
+#define icon_height 29
+static unsigned char icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04,
+   0x04, 0x41, 0x10, 0x04, 0x04, 0x41, 0x10, 0x04, 0xfc, 0xff, 0xff, 0x07,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/* *** icons for buttons, not used ***
+#define arrow_width 6
+#define arrow_height 9
+static char arrow_bits[] = {
+   0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define back_width 16
+#define back_height 16
+static char back_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x3f, 0xc0, 0x3f,
+   0xf0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0x3f,
+   0x00, 0x3c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+#define fore_width 16
+#define fore_height 16
+static char fore_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0xfc, 0x00, 0xfc, 0x03,
+   0xfc, 0x0f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x0f, 0xfc, 0x03, 0xfc, 0x00,
+   0x3c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00};
+#define stop_width 16
+#define stop_height 16
+static char stop_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/kii.proto.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/kii.proto.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/kii.proto.h	(revision 16632)
@@ -0,0 +1,124 @@
+
+/* top-level program */
+int           args                PROTO((int *argc, char **argv));
+void          SetUpDisplay        PROTO((Graphic *, int *, char **));
+void          SetUpWindow         PROTO((Graphic *, int *, char **));
+void          DefineLayout        PROTO((Layout *, Graphic *, int, char **));
+int           EventLoop           PROTO((Graphic *, Layout *));
+void          CloseDisplay        PROTO((Graphic *));
+
+/* SetUpDisplay */
+void          CheckDisplayName    PROTO((int *, char **, char *));
+Display      *OpenDisplay         PROTO((char *, int *));
+void	      CheckVisual	  PROTO((Graphic *graphic, int *argc, char **argv));
+void          CheckColors         PROTO((Graphic *, int *, char **));
+
+/* SetUpWindow */
+void          CheckGeometry       PROTO((int *, char **, Graphic *));
+void          TopWindow           PROTO((Graphic *, Icon *));
+void           CreateWindow       PROTO((Graphic *, Window, int, long));
+void           MakeGC             PROTO((Graphic *));
+void           MakeCursor         PROTO((Graphic *, unsigned int));
+void          LoadFont            PROTO((Graphic *, int *, char **, char *));
+void           CheckFontName      PROTO((int *, char **, char *));
+void          SetNormalHints      PROTO((Graphic *));
+void          SetWMHints          PROTO((Graphic *, Icon *));
+void          NameWindow          PROTO((Graphic *, char *));
+void          MapWindow           PROTO((Graphic *));
+
+/* DefineLayout - fns below may be called if layout is changed? */
+void          PositionPictures    PROTO((Layout *, Graphic *));
+
+void          MakeColormap        PROTO((Graphic *, Layout *, int, char **));
+int	      SetColormap	  PROTO((Graphic *graphic, Layout *layout, char *name));
+void          CreateColorbar      PROTO((Layout *, Graphic *));
+void          CreatePicture       PROTO((Layout *, Graphic *));
+
+/* EventLoop */
+int           CheckPipe           PROTO((Graphic *, Layout *));
+int           Reconfig            PROTO((Graphic *, Layout *, XEvent *));
+void          Refresh             PROTO((Graphic *, Layout *, int));
+int           UpdatePointer       PROTO((Graphic *, Layout *, XMotionEvent *));
+int           InterpretKeys       PROTO((Graphic *, Layout *, XEvent *));
+int           InterpretPresses    PROTO((Graphic *, Layout *, XButtonEvent *));
+
+/* CheckPipe */
+int           NewPicture          PROTO((Graphic *, Layout *));
+int           EraseOverlay        PROTO((Graphic *, Layout *));
+int           LoadOverlay         PROTO((Graphic *, Layout *));
+int	      LoadTickmarks	  PROTO((Graphic *graphic, Layout *layout));
+int           SaveOverlay         PROTO((Graphic *, Layout *));
+int           CSaveOverlay        PROTO((Graphic *, Layout *));
+int	      PSit		  PROTO((Graphic *graphic, Layout *layout, int Raw));
+int	      JPEGit		  PROTO((Graphic *graphic, Layout *layout));
+int	      JPEGit24		  PROTO((Graphic *graphic, Layout *layout));
+int	      Resize		  PROTO((Graphic *graphic, Layout *layout));
+int	      Center		  PROTO((Graphic *graphic, Layout *layout));
+
+/* imagezoom functions */
+void          CreateZoom          PROTO((Layout *, Graphic *, double, double));
+void	      CreateZoom8	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      CreateZoom16	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      CreateZoom24	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      CreateZoom32	  PROTO((Layout *layout, Graphic *graphic, double x, double y));
+void	      UpdateStatusBox	  PROTO((Graphic *graphic, Layout *layout, double x, double y, double z, int mode));
+void          CrossHairs          PROTO((Graphic *, Layout *));
+
+/* X image drawing functions */
+void          Reorient            PROTO((Graphic *, Layout *, double, double, int));
+void          ReorientOnButton    PROTO((Graphic *, Layout *, XButtonEvent *));
+int	      Recenter		  PROTO((Graphic *graphic, Layout *layout));
+void          PaintOverlay        PROTO((Graphic *, Layout *, int));
+void	      PaintTickmarks	  PROTO((Graphic *graphic, Layout *layout));
+void          Remap               PROTO((Graphic *, Layout *, Matrix  *));
+void	      Remap8		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+void	      Remap16		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+void	      Remap24		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+void	      Remap32		  PROTO((Graphic *graphic, Layout *layout, Matrix *matrix));
+
+/* PS image drawing functions */
+void	      ConvertPixmap8	  PROTO((Layout *layout, FILE *f));
+void	      ConvertPixmap16	  PROTO((Layout *layout, FILE *f));
+void	      ConvertPixmap24	  PROTO((Layout *layout, FILE *f));
+void	      ConvertPixmap32	  PROTO((Layout *layout, FILE *f));
+void	      DrawOverlay	  PROTO((Graphic *graphic, Layout *layout, int N, FILE *f, int extra));
+
+/* JPEG image drawing functions */
+void	      bDrawOverlay	  PROTO((Layout *layout, int N));
+
+/***** Prototypes for image ***************/
+void          StatusBox           PROTO((Graphic *, Layout *));
+
+/***** Prototypes for action ***************/
+int           InPicture           PROTO((XButtonEvent *, Picture *));
+int           Stop                PROTO((Graphic *, Layout *));
+void          DragColorbar        PROTO((Graphic *, Layout *, XButtonEvent *));
+void          ResetColorbar       PROTO((Graphic *, Layout *, double, double));
+
+/***** Prototypes for button ***************/
+Button       *CheckButtons        PROTO((XButtonEvent *, Layout *));
+void          DrawButton          PROTO((Graphic *, Button *));
+void          FlashButton         PROTO((Graphic *, Button *));
+int           InButton            PROTO((XButtonEvent *, Button *));
+void          InvertButton        PROTO((Graphic *, Button *));
+int           greycolors          PROTO((Graphic *, Layout *));
+int           rainbow             PROTO((Graphic *, Layout *));
+int           puns                PROTO((Graphic *, Layout *));
+int           Recenter            PROTO((Graphic *, Layout *));
+int           RecenterRescale     PROTO((Graphic *, Layout *));
+int           Rescale             PROTO((Graphic *, Layout *));
+int           ToggleDEG           PROTO((Graphic *, Layout *));
+int           Overlay0            PROTO((Graphic *, Layout *));
+int           Overlay1            PROTO((Graphic *, Layout *));
+int           Overlay2            PROTO((Graphic *, Layout *));
+int           Overlay3            PROTO((Graphic *, Layout *));
+
+/***** Prototypes for xtools ***************/
+void	      Screen_to_Image     PROTO((double *x1, double *y1, double x2, double y2, Layout *layout));
+void	      Image_to_Screen	  PROTO((double *x1, double *y1, double x2, double y2, Layout *layout));
+unsigned long GetColor            PROTO((Display *, char *, Colormap, unsigned long));
+void          QuitX               PROTO((Display *, char *, char *));
+void          hh_hms              PROTO((char *, double, double, char));
+void          DrawBitmap          PROTO((Graphic *, int, int, int, int, char *, int));
+int	      cursor		  PROTO((Graphic *graphic, Layout *layout));
+void	      FlushDisplay	  PROTO((Display *display));
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/kii.struct.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/kii.struct.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/kii.struct.h	(revision 16632)
@@ -0,0 +1,129 @@
+
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;
+  int            screen;
+  int            depth;
+  Window         window;
+  Visual        *visual;
+  int            visualclass;
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  int            dx, dy;
+  Colormap       colormap;
+  unsigned long  Npixels, pixels[256];
+  int            Nbits;
+  /*
+  unsigned long  fore;
+  unsigned long  back;
+  */
+  unsigned long  black, white;
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      text;              /* does this have a picture or text? */
+  int      width, height;
+  char    *bitmap;          /* picture on button */
+  int    (*function_1) ();  /* mouse_button 1 function */
+  int    (*function_2) ();  /* mouse_button 2 function */
+  int    (*function_3) ();  /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  char  *bits;
+} Icon;
+
+typedef struct {
+  int      dx, dy, x, y;
+  XImage  *pix;
+  char *data;
+} Picture;
+
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int Nobjects;
+  unsigned long color;
+  Object *objects;
+} Overlay;
+  
+/******** Here we define the Layout struct specific to this program  *******/
+typedef struct {
+  /* objects on the mana window */
+  Picture  picture;
+  Picture  cmapbar;
+  Picture  zoom;
+  Button   PS_button;
+  Button   recenter_button;
+  Button   hms_button; /* toggle HMS/DECIMAL mode (DECIMAL_DEG macro) */
+  Button   grey_button;
+  Button   rainbow_button;
+  Button   puns_button;
+  Button   overlay_button[NOVERLAYS];
+  Overlay  overlay[NOVERLAYS];
+  Overlay  tickmarks;
+  int      text_x, text_y;
+
+  /* file descriptor for socket connection to mana */
+  int Ximage; 
+
+  /* data mana needs */
+  Matrix   matrix;         /* data for picture */
+  double   X, Y;           /* image pixel at screen center */
+  int      expand;         /* zoomscale */
+  double   zero, range;    /* zero, range for picture to cmap */
+  double   max, min;       /* zero, range for data to z-value */
+  double   start, slope;   /* zero, range for cmap to pixels */
+  double   x, y, z;        /* last pointer coords */
+  Coords   coords;
+  char     file[1024];     /* name of file */
+  char     buffer_name[1024];  /* name of buffer */
+
+  /* fundamental pieces */
+  unsigned long  black;
+  unsigned long  white;
+  XColor   cmap[256];
+  int      Npixels;
+
+} Layout;
+
+/* this routine is independent of the number of overlays */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/prototypes.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/prototypes.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/prototypes.h	(revision 16632)
@@ -0,0 +1,250 @@
+
+/* top-level program */
+int	      args		  PROTO((int *argc, char **argv));
+void          SetUpGraphic        PROTO((int *argc, char **argv));
+void          DefineLayout        PROTO((int, char **));
+int	      EventLoop		  PROTO(());
+void	      CloseDisplay	  PROTO(());
+
+/* SetUpGraphic */
+char         *CheckDisplayName    PROTO((int *argc, char **argv));
+Display      *OpenDisplay         PROTO((char *name, int *screen));
+void          CheckColors         PROTO((Graphic *graphic, int *argc, char **argv));
+
+/* SetUpWindow */
+void          CheckGeometry       PROTO((Graphic *graphic, int *argc, char **argv));
+void          TopWindow           PROTO((Graphic *graphic, Icon *icon));
+void          CreateWindow        PROTO((Graphic *graphic, Window parent, int border, long events));
+void	      MakeGC	    	  PROTO((Graphic *graphic));
+void          MakeCursor          PROTO((Graphic *graphic, unsigned int cursor));
+void          LoadFont            PROTO((Graphic *graphic, int *argc, char **argv, char *default_name));
+void          SetNormalHints      PROTO((Graphic *graphic));
+void          SetWMHints          PROTO((Graphic *graphic, Icon *icon));
+void          NameWindow          PROTO((Graphic *graphic, char *name));
+void          MapWindow           PROTO((Graphic *graphic));
+void          CheckVisual         PROTO((Graphic *graphic, int *argc, char **argv));
+
+/* X drawing utilities */
+void	      DrawFrame		  PROTO((KapaGraphWidget *graph));
+int           DrawObjects         PROTO((KapaGraphWidget *graph));
+void          DrawLabels          PROTO((KapaGraphWidget *graph));
+void	      DrawTextlines	  PROTO((KapaGraphWidget *graph));
+void          DrawConnect         PROTO((KapaGraphWidget *graph, Gobjects *objects));
+void          DrawHistogram       PROTO((KapaGraphWidget *graph, Gobjects *objects));
+int           DrawObjectN         PROTO((KapaGraphWidget *graph, Gobjects *objects));
+void          DrawPoints          PROTO((KapaGraphWidget *graph, Gobjects *objects));
+void          DrawXErrors         PROTO((KapaGraphWidget *graph, Gobjects *objects));
+void          DrawYErrors         PROTO((KapaGraphWidget *graph, Gobjects *objects));
+void	      DrawTick		  PROTO((int fx, int fy, int dfx, int dfy, int P, double min, double max, double value, int mode, int naxis));
+void	      AxisTickScale	  PROTO((Axis *axis, double *major, double *minor));
+
+/* EventLoop */
+int           PScommand           PROTO((int sock));
+int           CheckPipe           PROTO(());
+int           Reconfig            PROTO((XEvent *event));
+void          Refresh             PROTO(());
+
+/* CheckPipe */
+int           PNGit               PROTO((int sock));
+int           PPMit               PROTO((int sock));
+int           LoadFrame           PROTO((int sock));
+int           LoadObject          PROTO((int sock));
+int           LoadLabels          PROTO((int sock));
+int           LoadTextlines       PROTO((int sock));
+int           Resize              PROTO((int sock));
+int           GetLimits           PROTO((int sock));
+int           SetLimits           PROTO((int sock));
+int           SetSection          PROTO((int sock));
+int           ListSection         PROTO((int sock));
+int           MoveSection         PROTO((int sock));
+int           DefineSection       PROTO((int sock));
+int           SetFont             PROTO((int sock));
+int           EraseCurrentPlot    PROTO((void));
+int           ErasePlots          PROTO((void));
+int           EraseSections       PROTO((void));
+int           EraseImage          PROTO((void));
+int           SetGraphData        PROTO((int sock));
+int           GetGraphData        PROTO((int sock));
+int           SetImageData        PROTO((int sock));
+int           GetImageData        PROTO((int sock));
+int           SetImageCoords      PROTO((int sock));
+int           GetImageCoords      PROTO((int sock));
+int           GetImageRange       PROTO((int sock));
+int           SetChannel          PROTO((int sock));
+int           SetColormapFromPipe PROTO((int sock));
+
+int           LoadVectorData      PROTO((int sock, KapaGraphWidget *graph, int N, char *type));
+
+/* Section Utilities */
+Section      *InitSection	  PROTO(());
+void          FreeSection	  PROTO((Section *section));
+void          FreeSections	  PROTO(());
+Section      *AddSection	  PROTO((char *name, float x, float y, float dx, float dy));
+int           DelSection	  PROTO((char *name));
+int           GetSectionByName	  PROTO((char *name));
+int           GetNumberOfSections PROTO(());
+Section      *GetSectionByNumber  PROTO((int N));
+Section      *GetActiveSection	  PROTO(());
+int           SetActiveSectionByNumber PROTO((int N));
+int           ListSection         PROTO((int sock));
+void          SetSectionSizes     PROTO((Section *section));
+
+KapaGraphWidget *InitGraph        PROTO(());
+void          DrawGraph           PROTO((KapaGraphWidget *graph));
+void          SetGraphSize        PROTO((Section *section));
+void          FreeGraph           PROTO((KapaGraphWidget *graph));
+
+void          InitLayout          PROTO((int argc, char **argv));
+
+/* PS drawing utilities */
+int           PSit                PROTO((char *filename, char *pagename, int scaleMode, int pageMode));
+int           PSFrame             PROTO((KapaGraphWidget *graph, FILE *f));
+int           PSObjects           PROTO((KapaGraphWidget *graph, FILE *f));
+void          PSLabels            PROTO((KapaGraphWidget *graph, FILE *f));
+void	      PSTextlines	  PROTO((KapaGraphWidget *graph, FILE *f));
+void          PSConnect           PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+void          PSHistogram         PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+void          PSPoints            PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+void          PSXErrors           PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+void          PSYErrors           PROTO((KapaGraphWidget *graph, Gobjects *objects, FILE *f));
+void	      PSTick		  PROTO((FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis));
+void          ClipLinePS          PROTO((double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0, FILE *f));
+int           PSimage    	  PROTO((KapaImageWidget *image, FILE *f));
+void 	      PSOverlay  	  PROTO((KapaImageWidget *image, int N, FILE *f, int extra));
+void 	      PSPixmap8  	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+void 	      PSPixmap16 	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+void 	      PSPixmap24 	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+void 	      PSPixmap32 	  PROTO((Graphic *graphic, KapaImageWidget *image, FILE *f));
+
+/* kapa bDraw Functions */
+int	      bDrawFrame	  PROTO((KapaGraphWidget *graph));
+int	      bDrawObjects	  PROTO((KapaGraphWidget *graph));
+void	      bDrawLabels	  PROTO((KapaGraphWidget *graph));
+void	      bDrawTextlines	  PROTO((KapaGraphWidget *graph));
+void	      bDrawConnect	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+void	      bDrawHistogram	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+void	      bDrawPoints	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+void	      bDrawXErrors	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+void	      bDrawYErrors	  PROTO((KapaGraphWidget *graph, Gobjects *object));
+void	      bDrawTick		  PROTO((double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis));
+void	      bDrawClipLine	  PROTO((double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0));
+bDrawBuffer  *bDrawIt		  PROTO(());
+void          bDrawGraph          PROTO((KapaGraphWidget *graph));
+
+/* misc support */
+int           LastEvent           PROTO((Display *display, int type, XEvent *event));
+void	      FreeObjectData	  PROTO((Gobjects *object));
+void	      FlushDisplay	  PROTO(());
+unsigned long GetColor            PROTO((Display *display, char *name, Colormap colormap, unsigned long default_color));
+void          QuitX               PROTO((Display *display, char *message));
+Graphic      *GetGraphic          PROTO(());
+int           GetPixelCount       PROTO((int sock));
+
+int           Center              PROTO(());
+void          SetColorScale       PROTO((Graphic *graphic, KapaImageWidget *image));
+void          SetColorScale1D     PROTO((Graphic *graphic, KapaImageWidget *image));
+int           SetColorScale3D     PROTO((Graphic *graphic, KapaImageWidget *image));
+void          Remap               PROTO((Graphic *graphic, KapaImageWidget *image));
+void          Remap8              PROTO((Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix));
+void          Remap16             PROTO((Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix));
+void          Remap24             PROTO((Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix));
+void          Remap32             PROTO((Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix));
+int           LoadPicture         PROTO((int sock));
+
+KapaImageWidget *InitImageWidget  PROTO(());
+int           InitImageChannel    PROTO((KapaImageChannel *channel));
+void          FreeImage           PROTO((KapaImageWidget *image));
+void          SetImageSize        PROTO((Section *section));
+
+void          InitButtonSize      PROTO((Button *button, int width, int height, char *bitmap));
+void          InitButtonFunc      PROTO((Button *button, int (*function)()));
+void          DrawImage           PROTO((KapaImageWidget *image));
+void          DrawButton          PROTO((Graphic *graphic, Button *button));
+void          DrawBitmap          PROTO((Graphic *graphic, int x, int y, int dx, int dy, char *bitmap, int mode));
+void          CrossHairs          PROTO((Graphic *graphic, Picture *image));
+void          hh_hms              PROTO((char *line, double ra, double dec, char sep));
+
+int           SetColormap         PROTO((char *name));
+void          MakeColormap        PROTO((int argc, char **argv));
+
+void          PaintOverlay        PROTO((Graphic *graphic, KapaImageWidget *image, int N));
+void          PaintTickmarks      PROTO((Graphic *graphic, KapaImageWidget *image));
+
+void          Picture_to_Image    PROTO((double *x1, double *y1, double x2, double y2, Picture *picture));
+void          Screen_to_Image     PROTO((double *x1, double *y1, double x2, double y2, Picture *picture));
+void          Image_to_Picture    PROTO((double *x1, double *y1, double x2, double y2, Picture *picture));
+void          Image_to_Screen     PROTO((double *x1, double *y1, double x2, double y2, Picture *picture));
+void          Picture_Lower 	  PROTO((int *i_start, int *j_start, Matrix *matrix, Picture *picture));
+void          Picture_Upper 	  PROTO((int *i_end, int *j_end, Matrix *matrix, Picture *picture));
+
+void          DragColorbar        PROTO((Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event));
+void          ResetColorbar       PROTO((Graphic *graphic, double start, double slope));
+void          ReorientOnButton    PROTO((Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event));
+void          Reorient            PROTO((Graphic *graphic, KapaImageWidget *image, double X, double Y, int mode));
+
+Button       *CheckButtons        PROTO((XButtonEvent *event, KapaImageWidget *image));
+int           InButton            PROTO((XButtonEvent *event, Button *button));
+int           InPicture           PROTO((XButtonEvent *event, Picture *picture));
+
+/* Button Functions */
+int           greycolors	  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      heat		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      rainbow		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Recenter		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Rescale		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      RecenterRescale	  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      ToggleDEG		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay0		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay1		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay2		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      Overlay3		  PROTO((Graphic *graphic, KapaImageWidget *image));
+int	      PSfunction	  PROTO((Graphic *graphic, KapaImageWidget *image));
+
+/* misc functions */
+void 	      SetToolbox   (int sock);
+int  	      EraseOverlay (int sock);
+int  	      LoadOverlay  (int sock);
+int  	      SaveOverlay  (int sock);
+int  	      CSaveOverlay (int sock);
+int  	      JPEGit24     (int sock);
+
+int  	      UpdatePointer (Graphic *graphic, XMotionEvent *event);
+int  	      InterpretPresses (Graphic *graphic, XButtonEvent *event);
+int  	      InterpretKeys (Graphic *graphic, XKeyEvent *event);
+void 	      InitPipe (char *namedSocket);
+void 	      EraseGraph (KapaGraphWidget *graph);
+void 	      StatusBox (Graphic *graphic, KapaImageWidget *image);
+
+void 	      CreatePicture (KapaImageWidget *image, Graphic *graphic);
+void 	      CreateColorbar (KapaImageWidget *image, Graphic *graphic);
+void 	      CreateZoom (Graphic *graphic, KapaImageWidget *image);
+void 	      CreateWide (Graphic *graphic, KapaImageWidget *image);
+void 	      UpdateStatusBox (Graphic *graphic, KapaImageWidget *image, double x, double y, double z, int mode);
+
+// void 	      CreateZoom8  (KapaImageWidget *image, Graphic *graphic, double x, double y);
+// void 	      CreateZoom16 (KapaImageWidget *image, Graphic *graphic, double x, double y);
+// void 	      CreateZoom24 (KapaImageWidget *image, Graphic *graphic, double x, double y);
+// void 	      CreateZoom32 (KapaImageWidget *image, Graphic *graphic, double x, double y);
+
+int  	      GetActiveSocket ();
+void 	      InvertButton (Graphic *graphic, Button *button);
+void 	      bDrawOverlay (KapaImageWidget *image, int N);
+
+/* color cube tools */
+CCNode *CCNodeAlloc ();
+CCNode *CCFindChild (CCNode *node, float x, float y, float z);
+int CCSplitNode (CCNode *node);
+int CCSplitNodeIterate (CCNode *node, int current, int max);
+void CCNodeFree (CCNode *node);
+CCNode *CCFindBottom (CCNode *top, float x, float y, float z);
+int CCNodeExtractCounts (CCNode *node, float **values, int *nvalues, int *NVALUES);
+int CCNodeDivideLimit (CCNode *node, float minValue);
+int CCNodeInitCounts (CCNode *node, float value);
+
+/* 3D color histogram */
+void ColorHistogram (KapaImageWidget *image, CCNode *cube);
+void CCNodeSetColorPixels (KapaImageWidget *image, CCNode *cube);
+int CCNodeSetColorMap (CCNode *node, XColor *cmap, int Npixels, int *current);
+
+int SetColorScale3D_CC (Graphic *graphic, KapaImageWidget *image);
+int SetColorCubeHistogram ();
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/include/structures.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/include/structures.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/include/structures.h	(revision 16632)
@@ -0,0 +1,209 @@
+
+/*** 3C color cube histogram tree thingy ***/
+typedef struct CCNode {
+  // for the moment, this structure is specific to the color-histogram analysis.  if
+  // this were a void *pointer and we defined some additional apis, we could use this
+  // structure to track any 3D space
+  int count;    
+  int pixel;
+  char bottom;
+  float min[3]; // min value for each of the 3 dimensions for this node
+  float mid[3]; // mid-point for each of the 3 dimensions for this node
+  float max[3]; // max value for each of the 3 dimensions for this node
+  struct CCNode *sub[2][2][2];
+} CCNode;
+
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;     // X display pointer
+  int            screen;      // X screen number
+  int            depth;
+  Window         window;
+  Visual        *visual;
+  int            visualclass; // is visual dynamic? (XXX change name?)
+  int            Nbits;	      // pixel depth in bits (8, 16, 24, 32)
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  unsigned int   dx, dy;
+  CCNode        *cube;
+  XColor        *cmap;
+  Colormap       colormap;
+  unsigned long *color;      // graph plotting colors
+  int            Ncolors;
+
+  unsigned long *pixels;      // image pixel colors
+  int Npixels;		      // number of pixels
+
+  int            ColorScaleMode; // single colormap for all images??
+  int nRed;
+  int nBlue;
+  int nGreen;
+
+  unsigned long  fore;	      // basic foreground color 
+  unsigned long  back;	      // basic background color
+
+  unsigned long  overlay_color[NOVERLAYS]; // image plotting colors 
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      width, height;     /* size of the bitmap */
+  char    *bitmap;            /* picture on button */
+  int    (*function_1) ();    /* mouse_button 1 function */
+  int    (*function_2) ();    /* mouse_button 2 function */
+  int    (*function_3) ();    /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  unsigned char *bits;
+} Icon;
+
+typedef struct {
+  int      x, y;	      // location of picture in graphic
+  int      dx, dy;	      // size of picture
+  int      DX, DY;	      // size of displayed picture (must be updated with new images...)
+  int      expand;	      // zoomscale
+  double   X,  Y;	      // center of image in picture
+  char     flipx, flipy;      // parity (0 = +; 1 = -)
+  XImage  *pix;
+  char    *data;
+} Picture;
+
+// objects associated with a KiiImage
+// XXX rename thi
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int x, y;
+  int dx, dy;
+  double angle;
+  int  size;
+  char font[64]; 
+  char text[LABEL_MAXLEN];
+} Label;
+
+typedef struct {
+  int active;
+  int Nobjects;
+  unsigned long color;
+  KiiOverlay *objects;
+} Overlay;
+  
+typedef struct {
+  float *x, *y, *z, *dxp, *dxm, *dyp, *dym;
+  int Npts;
+  int style, ptype, ltype, color, etype, ebar;
+  double lweight, size;
+  double x0, x1, y0, y1;  /* limits for this object */
+} Gobjects;
+
+typedef struct {
+  double min, max;
+  char isaxis, areticks, islabel, islog;
+  double fx, dfx, fy, dfy;  /* axis location on graphic */
+} Axis;
+
+// a single graph in the display window
+typedef struct {
+  Axis      axis[4];    /* coordinate axes */
+  Label     label[8];   /* fixed axis labels */
+  Graphdata data;       /* current graph data */
+
+  Gobjects *objects;    /* graphic objects */    
+  int      Nobjects;    
+
+  Label    *textline;      /* placed text labels */
+  int      Ntextline;      
+} KapaGraphWidget;
+
+typedef struct {
+  // data associated with this image element
+  Matrix   matrix;         /* data for picture */
+  double   zero, range;    /* zero, range for picture to cmap */
+  double   max, min;       /* zero, range for data to z-value */
+  double   start, slope;   /* zero, range for cmap to pixels */
+  Coords   coords;
+  char     file[1024];     /* name of file */
+  char     name[1024];     /* name of buffer */
+} KapaImageChannel;
+
+// a single image in the display window
+typedef struct {
+  // picture components of the image element
+  Picture  picture;	      // the primary view of the image
+  Picture  zoom;	      // the zoom window
+  Picture  wide;	      // the wide-view window
+  Picture  cmapbar;	      // the colormap bar
+
+  // the control buttons
+  Button   PS_button;
+  Button   recenter_button;
+  Button   hms_button; /* toggle HMS/DECIMAL mode (DECIMAL_DEG macro) */
+  Button   grey_button;
+  Button   rainbow_button;
+  Button   heat_button;
+  Button   overlay_button[NOVERLAYS];
+
+  // location of the status box
+  int      text_x, text_y;
+  int      text_dx, text_dy, text_dyo;
+  int      location;	      // position of the zoom/status widgets (0 = none, 1-4 = bottom,left,top,right)
+  int      MovePointer;
+  int      DecimalDegrees;
+
+  // double   X, Y;           /* image pixel at screen center */
+  // double   x, y, z;        /* last pointer coords */
+
+  Overlay  overlay[NOVERLAYS];
+  Overlay  tickmarks;
+
+  unsigned short   *pixmap;   // lookup table for image pixel value to pixel index
+  int      nPixels;
+ 
+  KapaImageChannel *image;
+  KapaImageChannel channel[NCHANNELS];
+} KapaImageWidget;
+
+typedef struct {
+  KapaGraphWidget *graph;
+  KapaImageWidget *image;
+  float  x,  y;
+  float dx, dy;
+  char *name;
+} Section;
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/ButtonFunctions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/ButtonFunctions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/ButtonFunctions.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include "Ximage.h"
+
+int PSfunction (Graphic *graphic, KapaImageWidget *image) {
+
+  int status;
+
+  status = PSit ("kapa.ps", "default", TRUE, KAPA_PS_NEWPLOT);
+  return (status);
+}
+
+int greycolors (Graphic *graphic, KapaImageWidget *image) {
+  SetColormap ("greyscale");
+  CreateColorbar (image, graphic);
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  CreateZoom (graphic, image); 
+  CreateWide (graphic, image); 
+  Refresh ();
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int heat (Graphic *graphic, KapaImageWidget *image) {
+  SetColormap ("heat");
+  CreateColorbar (image, graphic);
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  CreateZoom (graphic, image); 
+  CreateWide (graphic, image); 
+  Refresh ();
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int rainbow (Graphic *graphic, KapaImageWidget *image) {
+  SetColormap ("rainbow");
+  CreateColorbar (image, graphic);
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  CreateZoom (graphic, image); 
+  CreateWide (graphic, image); 
+  Refresh ();
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int Recenter (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].picture.X = 0.5*image[0].image[0].matrix.Naxis[0];
+  image[0].picture.Y = 0.5*image[0].image[0].matrix.Naxis[1];
+ 
+  Remap (graphic, image);
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Rescale (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].picture.expand = 1;
+  Remap (graphic, image);
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int RecenterRescale (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].picture.X = 0.5*image[0].image[0].matrix.Naxis[0];
+  image[0].picture.Y = 0.5*image[0].image[0].matrix.Naxis[1];
+  image[0].picture.expand = 1;
+ 
+  Remap (graphic, image);
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int ToggleDEG (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].picture.flipy = !image[0].picture.flipy;
+  image[0].zoom.flipy = !image[0].zoom.flipy;
+  image[0].wide.flipy = !image[0].wide.flipy;
+  image[0].DecimalDegrees = image[0].DecimalDegrees ^ TRUE;
+  StatusBox (graphic, image);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/*********** overlay_button functions ************/
+int Overlay0 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[0].active = image[0].overlay[0].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay1 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[1].active = image[0].overlay[1].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay2 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[2].active = image[0].overlay[2].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay3 (Graphic *graphic, KapaImageWidget *image) {
+
+  image[0].overlay[3].active = image[0].overlay[3].active ^ TRUE;
+  Refresh ();
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/* this routine is NOT independent of the number of overlays */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CSaveOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CSaveOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CSaveOverlay.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+
+int CSaveOverlay (int sock) {
+
+  char filename[256], *type;
+  int i, N;
+  double ra, dec, ra1, dec1, x1, y1, dra, ddec;
+  FILE *f;
+  Section *section;
+  KapaImageWidget *image;
+
+  KiiScanMessage (sock, "%*s %d %s", &N, filename);
+  
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    if (image[0].overlay[N].objects[i].type == KII_OVERLAY_LINE) {
+      XY_to_RD (&ra, &dec, image[0].overlay[N].objects[i].x, image[0].overlay[N].objects[i].y, &image[0].image[0].coords);
+      x1 = image[0].overlay[N].objects[i].x + image[0].overlay[N].objects[i].dx;
+      y1 = image[0].overlay[N].objects[i].y + image[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &image[0].image[0].coords);
+      dra = (ra1 - ra);
+      ddec = (dec1 - dec);
+    } else {
+      XY_to_RD (&ra, &dec, image[0].overlay[N].objects[i].x, image[0].overlay[N].objects[i].y, &image[0].image[0].coords);
+      x1 = image[0].overlay[N].objects[i].x;
+      y1 = image[0].overlay[N].objects[i].y + image[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &image[0].image[0].coords);
+      ddec = fabs (dec1 - dec);
+      x1 = image[0].overlay[N].objects[i].x + image[0].overlay[N].objects[i].dx;
+      y1 = image[0].overlay[N].objects[i].y;
+      XY_to_RD (&ra1, &dec1, x1, y1, &image[0].image[0].coords);
+      dra = cos (dec*RAD_DEG) * fabs (ra1 - ra);
+    }
+    type = KiiOverlayTypeByNumber (image[0].overlay[N].objects[i].type);
+    if (type == NULL) continue;
+    fprintf (f, "%s %lf %lf %lf %lf\n", type, ra, dec, dra, ddec);
+   }
+  fclose (f);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Center.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Center.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Center.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "Ximage.h"
+
+int Center (int sock) {
+
+  int zoom;
+  double X, Y;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  KiiScanMessage (sock, "%lf %lf %d", &X,  &Y, &zoom);
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+  if (image == NULL) return (TRUE);
+
+  image[0].picture.X = X;
+  image[0].picture.Y = Y;
+  if ((zoom != 0) && (zoom != -1)) {
+    image[0].picture.expand = zoom;
+  }
+
+  if (USE_XWINDOW) {
+    Remap (graphic, image);
+    Refresh ();
+    XFlush (graphic[0].display);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckButtons.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckButtons.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckButtons.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include "Ximage.h"
+
+/******** Here we test the Buttons specific to this program  *******/
+Button *CheckButtons (XButtonEvent  *event, KapaImageWidget *image) {
+
+  int i;
+  Button *button;
+  button = (Button *) NULL;
+
+  if (InButton (event, &image[0].recenter_button)) 
+    button = &image[0].recenter_button;
+
+  if (InButton (event, &image[0].grey_button)) 
+    button = &image[0].grey_button;
+
+  if (InButton (event, &image[0].rainbow_button)) 
+    button = &image[0].rainbow_button;
+
+  if (InButton (event, &image[0].heat_button)) 
+    button = &image[0].heat_button;
+
+  if (InButton (event, &image[0].PS_button)) 
+    button = &image[0].PS_button;
+
+  if (InButton (event, &image[0].hms_button)) 
+    button = &image[0].hms_button;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (InButton (event, &image[0].overlay_button[i])) 
+      button = &image[0].overlay_button[i];
+  }
+
+  return (button);
+
+}
+
+/* To define a button, you must:
+
+   0) add the button to the Image structure in structures.h
+   1) place the info about the button in PositionPicture.c
+   2) (make any bitmaps needed and put them in buttons.h
+   3) place an entry in CheckButtons.c
+   4) Add the button to Refresh.c
+   5) create the button's function
+   6) add it to the Makefile
+   7) add it to the prototypes
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckColors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckColors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckColors.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "Ximage.h"
+
+/************** CheckColors *************/
+void CheckColors (Graphic *graphic, int *argc, char **argv) {
+
+  char *temp_name;
+  int N;
+
+  graphic->fore = BlackPixel (graphic->display, graphic->screen);
+  temp_name = XGetDefault (graphic->display, argv[0], "Foreground");
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -fg color\n");
+      exit (0);
+    }
+    remove_argument (N, argc, argv);
+    temp_name = argv[N];
+    remove_argument (N, argc, argv);
+  } 
+  if (temp_name != NULL) {
+    graphic->fore = GetColor (graphic->display, temp_name, graphic->colormap, graphic->fore);
+  }
+
+  graphic->back = WhitePixel (graphic->display, graphic->screen);
+  temp_name = XGetDefault (graphic->display, argv[0], "Background");
+  if ((N = get_argument (*argc, argv, "-bg"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -bg color\n");
+      exit (0);
+    }
+    remove_argument (N, argc, argv);
+    temp_name = argv[N];
+    remove_argument (N, argc, argv);
+  } 
+  if (temp_name != NULL) {
+    graphic->back = GetColor (graphic->display, temp_name, graphic->colormap, graphic->back);
+  }
+  return;
+}
+
+  /* here we define the values for foreground and background
+     if -fg, or -bg exist, or if Foreground or Background are set in .Xdefaults, 
+     use those.  foreground defaults to black, background defaults to white. */
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckDisplayName.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckDisplayName.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckDisplayName.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** CheckDisplayName *************/
+char *CheckDisplayName (int *argc, char **argv) {
+
+  char *name = NULL;
+  int N;
+
+  if ((N = get_argument (*argc, argv, "-d"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+    return (name);
+  }
+
+  if ((N = get_argument (*argc, argv, "-display"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+    return (name);
+  }
+  return (NULL);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckGeometry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckGeometry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckGeometry.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "Ximage.h"
+
+/************** CheckGeometry *************/
+void CheckGeometry (Graphic *graphic, int *argc, char **argv) {
+
+  int status, N;
+  char *temp_name;
+  
+  temp_name = XGetDefault (graphic->display, argv[0], "geometry");
+  if ((N = get_argument (*argc, argv, "-geom"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -geom DisplayName\n");
+      exit (0);
+    }
+    remove_argument (N, argc, argv);
+    temp_name = argv[N];
+    remove_argument (N, argc, argv);
+  }
+  if (temp_name == NULL) return;
+
+  status = XParseGeometry (temp_name, &graphic->x, &graphic->y, &graphic->dx, &graphic->dy);
+  if (status & XNegative) graphic->x += DisplayWidth  (graphic->display, graphic->screen) - graphic->dx;
+  if (status & YNegative) graphic->y += DisplayHeight (graphic->display, graphic->screen) - graphic->dy;
+
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckPipe.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckPipe.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckPipe.c	(revision 16632)
@@ -0,0 +1,315 @@
+# include "Ximage.h"
+# define STRCONST(A) ((int)(0x1000000*A[0] + 0x10000*A[1] + 0x100*A[2] + 0x1*A[3]))
+
+static KapaSockAddress Address;
+static int InitSocket = -1;
+static int sock = -1;
+
+// we can supply a port here, with only small changes
+void InitPipe (char *namedSocket) {
+
+  if (namedSocket == NULL) {
+    InitSocket = KapaServerInit (&Address);
+  } else {
+    sock = KapaWaitNamedSocket (namedSocket);
+  }
+  return;
+}
+
+int GetActiveSocket () {
+  return (sock);
+}
+
+// after we have processed the command, we unblock the socket
+# define FINISHED(A) { fcntl (sock, F_SETFL, O_NONBLOCK); return (A); }
+
+int CheckPipe () {
+
+  int status;
+  char word[5];
+
+  // check if we have a valid connection. if not, see if we can get one
+  if (sock == -1) {
+    sock = KapaServerWait (InitSocket, &Address);
+    if (sock == -1) return (TRUE);
+    close (InitSocket); /* stop listening for new connections */
+    fcntl (sock, F_SETFL, O_NONBLOCK);  
+  }
+
+  /***** read (4 byte) message word from socket ****/
+  status = read (sock, word, 4);
+  word[4] = 0;
+  switch (status) {
+  case -1:                          /* no input from pipe: continue */
+    return (TRUE);
+    break;
+
+  case 0:
+    fprintf (stderr, "pipe has died!\n");
+    return (FALSE);
+    break;
+
+  case 4:
+    break;
+
+  default:
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+    break;
+  }
+  
+  /* once we get a command, we block to ensure we get complete messages */
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+
+  /***** handle different messages ****/
+  if (ACTIVE_CURSOR) {
+    if (strcmp (word, "NCUR")) {
+      fprintf (stderr, "wrong end message %s\n", word);
+      KiiSendCommand (sock, 4, "DONE");
+      FINISHED (TRUE);
+    }
+    ACTIVE_CURSOR = FALSE;
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  } 
+
+  if (!strcmp (word, "QUIT")) FINISHED (FALSE);
+  
+  if (!strcmp (word, "CURS")) {
+    ACTIVE_CURSOR = TRUE;
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "PSIT")) {
+    status = PScommand (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "PNGF")) {
+    status = PNGit (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "PPMF")) {
+    status = PPMit (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "DBOX")) {
+    status = LoadFrame (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "PLOT")) {
+    status = LoadObject (sock);
+    // LoadObject sends its own handshake
+    // KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  if (!strcmp (word, "LABL")) {
+    status = LoadLabels (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "PTXT")) {
+    status = LoadTextlines (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "RSIZ")) {
+    status = Resize (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "GLIM")) {
+    GetLimits (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SLIM")) {
+    status = SetLimits (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GSTY")) {
+    GetGraphData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SSTY")) {
+    status = SetGraphData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SIMC")) {
+    SetImageCoords (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GIMC")) {
+    GetImageCoords (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GIMR")) {
+    GetImageRange (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "GIMD")) {
+    GetImageData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SIMD")) {
+    status = SetImageData (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "TOOL")) {
+    SetToolbox (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "SSEC")) {
+    status = SetSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "LSEC")) {
+    status = ListSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "DSEC")) {
+    status = DefineSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "MSEC")) {
+    status = MoveSection (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  if (!strcmp (word, "FONT")) {
+    status = SetFont (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+  
+  /* Erase Section */
+  if (!strcmp (word, "ERSC")) {
+    status = EraseCurrentPlot ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  /* Erase Plots */
+  if (!strcmp (word, "ERSP")) {
+    status = ErasePlots ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+  
+  /* Erase Sections */
+  if (!strcmp (word, "ERSS")) {
+    status = EraseSections ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  /* Erase Image */
+  if (!strcmp (word, "ERSI")) {
+    status = EraseImage ();
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  /* Erase Overlay for this section */
+  if (!strcmp (word, "ERSO")) {
+    status = EraseOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "READ")) {
+    status = LoadPicture (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "LOAD")) {
+    status = LoadOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CHAN")) {
+    status = SetChannel (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CMAP")) {
+    status = SetColormapFromPipe (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "SAVE")) {
+    status = SaveOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CSVE")) {
+    status = CSaveOverlay (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "JPEG")) {
+    status = JPEGit24 (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "CENT")) {
+    status = Center (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (status);
+  }
+
+  if (!strcmp (word, "NPIX")) {
+    GetPixelCount (sock);
+    KiiSendCommand (sock, 4, "DONE");
+    FINISHED (TRUE);
+  }
+
+  fprintf (stderr, "unknown signal %s\n", word);
+  KiiSendCommand (sock, 4, "DONE");
+  FINISHED (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckVisual.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckVisual.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CheckVisual.c	(revision 16632)
@@ -0,0 +1,182 @@
+# include "Ximage.h"
+
+/* DirectColor doesn't seem to work, even though it is available:
+   I cannot use XAllocColorCells to get pixels under DirectColor
+*/
+
+/* static int try_visual[] = {5, 3, 1, 4, 2, 0}; */
+
+void CheckVisual (Graphic *graphic, int *argc, char **argv) {
+
+  int i, Nfound, N;
+  int isColor, isDefault, isDynamic;
+  XVisualInfo *visual_list, visual_temp;
+  unsigned long planes[3];
+  XPixmapFormatValues *pixmaps;
+  int Npixmaps;
+
+  if (DEBUG) {
+    fprintf (stderr, "DirectColor: %d\n", DirectColor);
+    fprintf (stderr, "PseudoColor: %d\n", PseudoColor);
+    fprintf (stderr, "TrueColor:   %d\n", TrueColor);
+    fprintf (stderr, "GrayScale:   %d\n", GrayScale);
+    fprintf (stderr, "StaticColor: %d\n", StaticColor);
+    fprintf (stderr, "StaticGray:  %d\n", StaticGray);
+  }
+
+  visual_temp.screen = graphic[0].screen;
+  
+  /* find available visuals */
+  visual_list = XGetVisualInfo (graphic[0].display, VisualScreenMask, &visual_temp, &Nfound);
+  if (Nfound == 0) {
+    fprintf (stderr, "error finding useful visual\n");
+    exit (0);
+  }
+  
+  /* check default visual first */ 
+  for (i = 0; (i < Nfound) && (graphic[0].visual != visual_list[i].visual); i++);
+  if (i == Nfound) {
+    fprintf (stderr, "default visual not found??\n");
+    exit (0);
+  }
+
+  // set these based on selected visual
+  isColor = isDefault = isDynamic = FALSE;
+
+  // attempt to select the most desirable type of visual: Default as PseudoColor (XXX is it still true?)
+  if (DEBUG) fprintf (stderr, "default visual class is %d\n", visual_list[i].class);
+  if (visual_list[i].class == PseudoColor) {
+    isColor = isDefault = isDynamic = TRUE;
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: PseudoColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != PseudoColor); i++);
+  if (i != Nfound) {
+    isColor = isDynamic = TRUE;
+    if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: GrayScale (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != GrayScale); i++);
+  if (i != Nfound) {
+    isDynamic = TRUE;
+    if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: TrueColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != TrueColor); i++);
+  if (i != Nfound) {
+    isColor = TRUE;
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: TrueColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticColor); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  // attempt to select the most desirable type of visual: TrueColor (XXX is it still true?)
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticGray); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    isDefault = (graphic[0].visual == visual_list[i].visual);
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  test_pixels:
+
+  /* need to make a colormap if 
+     1) the selected visual is not the default 
+     2) there are not enough colors available */
+
+  /* NEED TO ADD A COUPLE LINES DEFINING THE VARIOUS HARD COLORS (BLACK, WHITE, AND THE OVERLAYS) */
+
+  // allow user to force a private colormap
+  if ((N = get_argument (*argc, argv, "-private"))) {
+    remove_argument(N, argc, argv);
+    isDefault = FALSE;
+  } 
+
+  // allocate a private colormap, if needed
+  if (!isDefault) {
+    if (DEBUG) fprintf (stderr, "allocated private colormap\n");
+    graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+  }
+
+  if (isDynamic) {
+    /* allocate color cells */
+    ALLOCATE (graphic[0].pixels, unsigned long, NPIXELS_DYNAMIC);
+    ALLOCATE (graphic[0].cmap,   XColor,        NPIXELS_DYNAMIC);
+    for (graphic[0].Npixels = NPIXELS_DYNAMIC; graphic[0].Npixels >= 16; graphic[0].Npixels -= 4) {
+      if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
+      if (XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels)) {
+	break;
+      }
+    }
+
+    /* insufficient cells, can we make a private colormap? */
+    if (graphic[0].Npixels < 16) {
+      if (!isDefault) {
+	fprintf (stderr, "can't allocate enough cells in private colormap\n");
+	exit (0);
+      }
+      if (DEBUG) fprintf (stderr, "can't allocate enough cells, using private colormap\n");
+      graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+
+      for (graphic[0].Npixels = NPIXELS_DYNAMIC; graphic[0].Npixels >= 16; graphic[0].Npixels -= 4) {
+	if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
+	if (XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels)) {
+	  break;
+	}
+      }
+
+      if ((N = get_argument (*argc, argv, "-colorcount"))) {
+	fprintf (stderr, "kapa can grab %d colors\n", graphic[0].Npixels);
+	exit (0);
+      } 
+      if (graphic[0].Npixels < 16) {
+	fprintf (stderr, "can't even allocate enough cells in private colormap\n");
+	exit (0);
+      }
+    }
+  } else {
+    // XXX allocate the unsigned long *pixels here and above
+    ALLOCATE (graphic[0].pixels, unsigned long, NPIXELS_STATIC);
+    ALLOCATE (graphic[0].cmap,   XColor,        NPIXELS_STATIC);
+    graphic[0].Npixels = NPIXELS_STATIC;
+  }
+
+  if ((N = get_argument (*argc, argv, "-colorcount"))) {
+    fprintf (stderr, "kii can grab %d colors\n", graphic[0].Npixels);
+    exit (0);
+  } 
+  
+  pixmaps = XListPixmapFormats (graphic[0].display, &Npixmaps);
+  for (i = 0; i < Npixmaps; i++) {
+    if (pixmaps[i].depth == graphic[0].depth) {
+      graphic[0].Nbits = pixmaps[i].bits_per_pixel;
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CloseDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CloseDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CloseDisplay.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "Ximage.h"
+
+/************** CloseDisplay *************/
+void CloseDisplay () {
+
+  Graphic *graphic;
+
+  if (!USE_XWINDOW) return;
+
+  graphic = GetGraphic();
+  XFreeFont (graphic->display, graphic->font); 
+  XFreeGC (graphic->display, graphic->gc);
+  XDestroySubwindows (graphic->display, graphic->window);
+  XDestroyWindow (graphic->display, graphic->window);
+  XFlush (graphic->display);
+  XCloseDisplay (graphic->display);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/ColorCube.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/ColorCube.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/ColorCube.c	(revision 16632)
@@ -0,0 +1,225 @@
+# include "Ximage.h"
+
+/* these functions are used to generate an appropriately-sampled color map for a given image.
+   we assume that only a limited number of colors can be allocated (start with, eg, 1024, grow to
+   64k or so).  the RGB image is constructed from the 32bit images, each with their own zero and
+   scale.  We want to allocate set of color cells which sample the actual colors available in the
+   image data.  We generate a 3D histogram of the actual data values.  The histogram is generated
+   using a k-d tree. */
+
+// the k-d tree is built of a bunch of nodes, each of which represents a cubic region in the 3D
+// color space.  each node may be occupied, or may point to a set of 8 children, subdividing the
+// cube into equal cubes.
+
+// NOTE : nothing in this file specifies a relationship between x,y,z and red,blue,green
+
+// set of operations needed:
+
+// allocate empty, bottom-level node
+CCNode *CCNodeAlloc () {
+
+  CCNode *node;
+  int ix, iy, iz;
+
+  ALLOCATE (node, CCNode, 1);
+  node->count = 0;
+  node->pixel = 0;
+  node->bottom = TRUE;
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	node->sub[ix][iy][iz] = NULL;
+      }
+    }
+  }
+  return node;
+}
+
+// given a coordinate and a containing node, find the corresponding child node (if any)
+CCNode *CCFindChild (CCNode *node, float x, float y, float z) {
+
+  int ix, iy, iz;
+
+  assert (x >= node->min[CC_X]);
+  assert (y >= node->min[CC_Y]);
+  assert (z >= node->min[CC_Z]);
+
+  assert (x <= node->max[CC_X]);
+  assert (y <= node->max[CC_Y]);
+  assert (z <= node->max[CC_Z]);
+
+  if (node->bottom) return NULL; // already at the bottom
+
+  ix = (x < node->mid[CC_X]) ? 0 : 1;
+  iy = (y < node->mid[CC_Y]) ? 0 : 1;
+  iz = (z < node->mid[CC_Z]) ? 0 : 1;
+  
+  return node->sub[ix][iy][iz];
+}
+
+// given a coordinate and a containing node, find the corresponding child node (if any)
+int CCSplitNode (CCNode *node) {
+
+  CCNode *child;
+  int ix, iy, iz;
+
+  // trying to split an already split node
+  if (!node->bottom) return FALSE;
+
+  node->bottom = FALSE;
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	child = CCNodeAlloc();
+	child->min[CC_X] = (ix == 0) ? node->min[CC_X] : node->mid[CC_X];
+	child->min[CC_Y] = (iy == 0) ? node->min[CC_Y] : node->mid[CC_Y];
+	child->min[CC_Z] = (iz == 0) ? node->min[CC_Z] : node->mid[CC_Z];
+	child->max[CC_X] = (ix == 0) ? node->mid[CC_X] : node->max[CC_X];
+	child->max[CC_Y] = (iy == 0) ? node->mid[CC_Y] : node->max[CC_Y];
+	child->max[CC_Z] = (iz == 0) ? node->mid[CC_Z] : node->max[CC_Z];
+
+	child->mid[CC_X] = 0.5*(child->min[CC_X] + child->max[CC_X]);
+	child->mid[CC_Y] = 0.5*(child->min[CC_Y] + child->max[CC_Y]);
+	child->mid[CC_Z] = 0.5*(child->min[CC_Z] + child->max[CC_Z]);
+
+	node->sub[ix][iy][iz] = child;
+      }
+    }
+  }
+  return TRUE;
+}
+
+int CCSplitNodeIterate (CCNode *node, int current, int max) {
+
+  int ix, iy, iz;
+
+  if (current == max) return TRUE;
+  current ++;
+
+  CCSplitNode (node);
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCSplitNodeIterate (node->sub[ix][iy][iz], current, max);
+      }
+    }
+  }
+  return TRUE;
+}
+
+// allocate empty, bottom-level node
+void CCNodeFree (CCNode *node) {
+
+  int ix, iy, iz;
+
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	if (node->sub[ix][iy][iz]) CCNodeFree (node->sub[ix][iy][iz]);
+      }
+    }
+  }
+  free (node);
+  return;
+}
+
+// given a coordinate and a containing node, find the corresponding child node (if any)
+CCNode *CCFindBottom (CCNode *top, float x, float y, float z) {
+
+  CCNode *node;
+  CCNode *next;
+
+  assert (x >= top->min[CC_X]);
+  assert (y >= top->min[CC_Y]);
+  assert (z >= top->min[CC_Z]);
+
+  assert (x <= top->max[CC_X]);
+  assert (y <= top->max[CC_Y]);
+  assert (z <= top->max[CC_Z]);
+
+  node = top;
+  next = CCFindChild (node, x, y, z);
+  while (next != NULL) {
+    node = next;
+    next = CCFindChild (node, x, y, z);
+  }
+
+  return node;
+}
+
+// iterate over the CCNode tree to generate a single, 1d vector of all data values
+// XXX this function is specific to the color histogram concept
+int CCNodeExtractCounts (CCNode *node, float **values, int *nvalues, int *NVALUES) {
+
+  int ix, iy, iz;
+
+  if (*values == NULL) {
+    nvalues[0] = 0;
+    NVALUES[0] = 32;
+    ALLOCATE (*values, float, NVALUES[0]);
+  }
+
+  if (node->bottom) {
+    values[0][nvalues[0]] = node->count;
+    nvalues[0] ++;
+    if (nvalues[0] >= NVALUES[0]) {
+      NVALUES[0] += 32;
+      REALLOCATE (*values, float, NVALUES[0]);
+    }
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeExtractCounts (node->sub[ix][iy][iz], values, nvalues, NVALUES);
+      }
+    }
+  }
+  return TRUE;
+}
+
+// iterate over the CCNode tree and subdivide any bottom level nodes with value > minValue
+// XXX this function is specific to the color histogram concept
+int CCNodeDivideLimit (CCNode *node, float minValue) {
+
+  int ix, iy, iz;
+
+  if (node->bottom) {
+    if (node->count > minValue) {
+      CCSplitNode (node);
+    }
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeDivideLimit (node->sub[ix][iy][iz], minValue);
+      }
+    }
+  }
+  return TRUE;
+}
+
+// iterate over the CCNode tree and subdivide any bottom level nodes with value > minValue
+// XXX this function is specific to the color histogram concept
+int CCNodeInitCounts (CCNode *node, float value) {
+
+  int ix, iy, iz;
+
+  if (node->bottom) {
+    node->count = value;
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeInitCounts (node->sub[ix][iy][iz], value);
+      }
+    }
+  }
+  return TRUE;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/ColorHistogram.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/ColorHistogram.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/ColorHistogram.c	(revision 16632)
@@ -0,0 +1,188 @@
+# include "Ximage.h"
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+void ColorHistogram (KapaImageWidget *image, CCNode *cube) {
+
+  int i, DX, DY, nPixels;
+  float *rData, *bData, *gData, rValue, gValue, bValue;
+  float redSlope, blueSlope, greenSlope;
+  float redStart, blueStart, greenStart;
+  CCNode *node;
+
+  // Input images are scaled to 0.0 - 1.0 floating point range.  These values are accumulated in the
+  // 3d histogram.  Use the histogram to allocate colors or subdivide the top-populated histogram
+  // cells and re-evaluated.   
+
+  // set start & slope for red (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_RED].range != 0.0) {
+    redSlope = 1.0 / image[0].channel[KAPA_CHANNEL_RED].range;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero / image[0].channel[KAPA_CHANNEL_RED].range;
+  } else {
+    redSlope = 1.0;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero;
+  }
+  // set start & slope for blue (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_BLUE].range != 0.0) {
+    blueSlope = 1.0 / image[0].channel[KAPA_CHANNEL_BLUE].range;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero / image[0].channel[KAPA_CHANNEL_BLUE].range;
+  } else {
+    blueSlope = 1.0;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero;
+  }
+  // set start & slope for green (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_GREEN].range != 0.0) {
+    greenSlope = 1.0 / image[0].channel[KAPA_CHANNEL_GREEN].range;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero / image[0].channel[KAPA_CHANNEL_GREEN].range;
+  } else {
+    greenSlope = 1.0;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero;
+  }
+
+  DX = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1];
+  // XXX check on equal size for all three channels
+
+  nPixels = DX*DY;
+
+  // loop over pixels, convert data values to range values (0.0 - 1.0), increment 3D histogram cell
+  rData = (float *) image[0].channel[KAPA_CHANNEL_RED].matrix.buffer;
+  bData = (float *) image[0].channel[KAPA_CHANNEL_BLUE].matrix.buffer;
+  gData = (float *) image[0].channel[KAPA_CHANNEL_GREEN].matrix.buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, rData++, bData++, gData++) {
+    rValue = *rData * redSlope   - redStart;
+    if (rValue < 0.0) rValue = 0.0;
+    if (rValue > 1.0) rValue = 1.0;
+    if (isnan(rValue)) rValue = 0.0;
+    if (isinf(rValue)) rValue = 1.0;
+
+    bValue = *bData * blueSlope  - blueStart;
+    if (bValue < 0.0) bValue = 0.0;
+    if (bValue > 1.0) bValue = 1.0;
+    if (isnan(bValue)) bValue = 0.0;
+    if (isinf(bValue)) bValue = 1.0;
+
+    gValue = *gData * greenSlope - greenStart;
+    if (gValue < 0.0) gValue = 0.0;
+    if (gValue > 1.0) gValue = 1.0;
+    if (isnan(gValue)) gValue = 0.0;
+    if (isinf(gValue)) gValue = 1.0;
+
+    // XXX at the moment, we are saturating before supplying to this function
+    // NOTE : x,y,z = red,green,blue
+    node = CCFindBottom (cube, rValue, gValue, bValue);
+    node->count ++;
+  }
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+void CCNodeSetColorPixels (KapaImageWidget *image, CCNode *cube) {
+
+  int i, DX, DY, nPixels;
+  float *rData, *bData, *gData, rValue, gValue, bValue;
+  unsigned short *oData;
+  float redSlope, blueSlope, greenSlope;
+  float redStart, blueStart, greenStart;
+  CCNode *node;
+
+  // Input images are scaled to 0.0 - 1.0 floating point range.  These values are accumulated in the
+  // 3d histogram.  Use the histogram to allocate colors or subdivide the top-populated histogram
+  // cells and re-evaluated.   
+
+  // set start & slope for red (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_RED].range != 0.0) {
+    redSlope = 1.0 / image[0].channel[KAPA_CHANNEL_RED].range;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero / image[0].channel[KAPA_CHANNEL_RED].range;
+  } else {
+    redSlope = 1.0;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero;
+  }
+  // set start & slope for blue (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_BLUE].range != 0.0) {
+    blueSlope = 1.0 / image[0].channel[KAPA_CHANNEL_BLUE].range;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero / image[0].channel[KAPA_CHANNEL_BLUE].range;
+  } else {
+    blueSlope = 1.0;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero;
+  }
+  // set start & slope for green (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_GREEN].range != 0.0) {
+    greenSlope = 1.0 / image[0].channel[KAPA_CHANNEL_GREEN].range;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero / image[0].channel[KAPA_CHANNEL_GREEN].range;
+  } else {
+    greenSlope = 1.0;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero;
+  }
+
+  DX = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1];
+  // XXX check on equal size for all three channels
+
+  nPixels = DX*DY;
+  if (image[0].nPixels != nPixels) {
+    REALLOCATE (image[0].pixmap, unsigned short, nPixels);
+    image[0].nPixels = nPixels;
+  }
+
+  // loop over pixels, convert data values to range values (0.0 - 1.0), increment 3D histogram cell
+  rData = (float *) image[0].channel[KAPA_CHANNEL_RED].matrix.buffer;
+  bData = (float *) image[0].channel[KAPA_CHANNEL_BLUE].matrix.buffer;
+  gData = (float *) image[0].channel[KAPA_CHANNEL_GREEN].matrix.buffer;
+
+  oData = image[0].pixmap;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, rData++, bData++, gData++, oData++) {
+    rValue = *rData * redSlope   - redStart;
+    if (rValue < 0.0) rValue = 0.0;
+    if (rValue > 1.0) rValue = 1.0;
+    if (isnan(rValue)) rValue = 0.0;
+    if (isinf(rValue)) rValue = 1.0;
+
+    bValue = *bData * blueSlope  - blueStart;
+    if (bValue < 0.0) bValue = 0.0;
+    if (bValue > 1.0) bValue = 1.0;
+    if (isnan(bValue)) bValue = 0.0;
+    if (isinf(bValue)) bValue = 1.0;
+
+    gValue = *gData * greenSlope - greenStart;
+    if (gValue < 0.0) gValue = 0.0;
+    if (gValue > 1.0) gValue = 1.0;
+    if (isnan(gValue)) gValue = 0.0;
+    if (isinf(gValue)) gValue = 1.0;
+
+    // XXX at the moment, we are saturating before supplying to this function
+    // NOTE : x,y,z = red,green,blue 
+    node = CCFindBottom (cube, rValue, gValue, bValue);
+    *oData = node->pixel;
+  }
+}
+
+// iterate over the CCNode tree and subdivide any bottom level nodes with value > minValue
+// XXX this function is specific to the color histogram concept
+// NOTE : x,y,z = red,green,blue 
+int CCNodeSetColorMap (CCNode *node, XColor *cmap, int Npixels, int *current) {
+
+  int ix, iy, iz;
+
+  if (node->bottom) {
+    cmap[current[0]].red   = node->mid[CC_X]*0xffff;
+    cmap[current[0]].green = node->mid[CC_Y]*0xffff;
+    cmap[current[0]].blue  = node->mid[CC_Z]*0xffff;
+    cmap[current[0]].flags = DoRed | DoGreen | DoBlue;
+    node->pixel = current[0];
+    current[0] ++;
+    assert (current[0] <= Npixels);
+    return TRUE;
+  }
+  
+  for (ix = 0; ix < 2; ix++) {
+    for (iy = 0; iy < 2; iy++) {
+      for (iz = 0; iz < 2; iz++) {
+	CCNodeSetColorMap (node->sub[ix][iy][iz], cmap, Npixels, current);
+      }
+    }
+  }
+  return TRUE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateColorbar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateColorbar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateColorbar.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+
+void CreateColorbar (KapaImageWidget *image, Graphic *graphic) {
+
+  int i, j, dx, dy, extra, start;
+  unsigned long  pixvalue;
+  unsigned int  *out24;
+  unsigned char *out8;
+
+  dx = image[0].cmapbar.dx;
+  dy = image[0].cmapbar.dy;
+
+  /* create the cmap scale */
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (image[0].cmapbar.data, char, dx*dy);
+    out8 = (unsigned char *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out8[j*dx + i] = pixvalue;
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].cmapbar.data, dx, dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (image[0].cmapbar.data, char, 2*dy*dx);
+    out8 = (unsigned char *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = 2*j*dx + 2*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].cmapbar.data, dx, dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (dx * 3) % 4;
+    REALLOCATE (image[0].cmapbar.data, char, dy*(3*dx + extra));
+    out8 = (unsigned char *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = j*(3*dx+extra) + 3*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+	out8[start + 2] = 0x0000ff & (pixvalue >> 16);
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+
+  case 32:
+    REALLOCATE (image[0].cmapbar.data, char, 4*dx*dy);
+    out24 = (unsigned int *) image[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = graphic[0].cmap[(int)(i*graphic[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out24[j*dx + i] = pixvalue;
+      }
+    }
+    image[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					 image[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreatePicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreatePicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreatePicture.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "Ximage.h"
+
+void CreatePicture (KapaImageWidget *image, Graphic *graphic) {
+
+  int i, j, extra;
+  unsigned char *c;
+  unsigned int *l;
+  unsigned int start, start1, start2, start3;
+
+  start = graphic[0].back;
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (image[0].wide.data,    char, image[0].wide.dx*image[0].wide.dy);
+    REALLOCATE (image[0].zoom.data,    char, image[0].zoom.dx*image[0].zoom.dy);
+    REALLOCATE (image[0].picture.data, char, image[0].picture.dx*image[0].picture.dy);
+    c = (unsigned char *) image[0].picture.data;
+    for (i = 0; i < (image[0].picture.dx*image[0].picture.dy); i++, c++)
+      *c = start;
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (image[0].wide.data,    char, 2*image[0].wide.dx*image[0].wide.dy);
+    REALLOCATE (image[0].zoom.data,    char, 2*image[0].zoom.dx*image[0].zoom.dy);
+    REALLOCATE (image[0].picture.data, char, 2*image[0].picture.dy*image[0].picture.dx);
+    c = (unsigned char *) image[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    for (i = 0; i < image[0].picture.dy; i++) {
+      for (j = 0; j < image[0].picture.dx; j++, c+=2) {
+	c[0] = start1;
+	c[1] = start2;
+      }
+    }
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (image[0].picture.dx * 3) % 4;
+    REALLOCATE (image[0].wide.data, char, image[0].wide.dy*(3*image[0].wide.dx+extra));
+    REALLOCATE (image[0].zoom.data, char, image[0].zoom.dy*(3*image[0].zoom.dx+extra));
+    REALLOCATE (image[0].picture.data, char, image[0].picture.dy*(3*image[0].picture.dx+extra));
+    c = (unsigned char *) image[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    start3 = 0x0000ff & (start >> 16);
+    for (i = 0; i < image[0].picture.dy; i++) {
+      for (j = 0; j < image[0].picture.dx; j++, c+=3) {
+	c[0] = start1;
+	c[1] = start2;
+	c[2] = start3;
+      }
+      c+=extra;
+    }
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 24, 0);
+    break;
+
+  case 32:
+    REALLOCATE (image[0].wide.data,    char, 4*image[0].wide.dx*image[0].wide.dy);
+    REALLOCATE (image[0].zoom.data,    char, 4*image[0].zoom.dx*image[0].zoom.dy);
+    REALLOCATE (image[0].picture.data, char, 4*image[0].picture.dx*image[0].picture.dy);
+    l = (unsigned int *) image[0].picture.data;
+    for (i = 0; i < (image[0].picture.dx*image[0].picture.dy); i++, l++)
+      *l = start;
+    image[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  image[0].picture.data, image[0].picture.dx, image[0].picture.dy, 32, 0);
+    break;
+  }
+    
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateWide.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateWide.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateWide.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+void CreateWide (Graphic *graphic, KapaImageWidget *image) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    Remap8  (graphic, image, &image->wide, &image->image->matrix);
+    break;
+  case 16:
+    Remap16 (graphic, image, &image->wide, &image->image->matrix);
+    break;
+  case 24:
+    Remap24 (graphic, image, &image->wide, &image->image->matrix);
+    break;
+  case 32:
+    Remap32 (graphic, image, &image->wide, &image->image->matrix);
+    break;
+  }    
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateWindow.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+
+/************** CreateWindow *************/
+void CreateWindow (Graphic *graphic, Window parent, int border, long events) {
+
+  XSetWindowAttributes attributes;
+  unsigned long attribute_mask;
+  Visual *visual = CopyFromParent;
+
+  HAVE_BACKING = (DoesBackingStore (ScreenOfDisplay(graphic->display, graphic->screen)) == Always);
+  HAVE_BACKING = FALSE;
+
+  if (HAVE_BACKING) {
+    attributes.backing_store = Always;
+    attribute_mask = CWBackingStore | CWBackPixel | CWBorderPixel | CWEventMask;
+  } else {
+    attribute_mask = CWBackPixel | CWBorderPixel | CWEventMask;
+  }
+
+  attributes.background_pixel = graphic->back;
+  attributes.border_pixel     = graphic->fore;
+  attributes.event_mask       = events;
+
+  graphic->window = XCreateWindow (graphic->display, parent, 
+				     graphic->x, graphic->y, 
+				     graphic->dx, graphic->dy, 
+				     border, CopyFromParent,
+				     InputOutput, visual, 
+				     attribute_mask, &attributes);
+
+  if (graphic->window == (Window) None)
+    QuitX (graphic->display, "error: could not open window");
+
+  XSelectInput (graphic->display, graphic->window, events);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+void CreateZoom (Graphic *graphic, KapaImageWidget *image) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    Remap8  (graphic, image, &image->zoom, &image->image->matrix);
+    break;
+  case 16:
+    Remap16 (graphic, image, &image->zoom, &image->image->matrix);
+    break;
+  case 24:
+    Remap24 (graphic, image, &image->zoom, &image->image->matrix);
+    break;
+  case 32:
+    Remap32 (graphic, image, &image->zoom, &image->image->matrix);
+    break;
+  }    
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom16.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom16.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom16.c	(revision 16632)
@@ -0,0 +1,144 @@
+# include "Ximage.h"
+
+void CreateZoom16 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+# if (0)
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  float *imdata, *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long back;
+  unsigned char back1, back2;
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, 2*dy*dx);
+    bzero (image[0].zoom.data, image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 16, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff &  graphic[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 8);
+  }
+  back = graphic[0].back;
+  back1 = 0x0000ff & back;
+  back2 = 0x0000ff & (back >> 8);
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) image[0].zoom.data;
+  imdata  = (float *) image[0].image[0].matrix.buffer;
+  in_pix  = &imdata[DX*(int)MAX(Ry,0) + (int)MAX(Rx,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) {
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+    }
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[2*j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2+=2) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+      }
+    }
+    out_pix += 2*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=2) {
+	pixelN = PixelLookup(*in_pix2);
+	out_pix[0] = pixel1[pixelN];
+	out_pix[1] = pixel2[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixelN = PixelLookup(*in_pix2);
+	pixvalue1 = pixel1[pixelN];
+	pixvalue2 = pixel2[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=2*(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=2) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	  }
+	}
+      }
+    }
+    out_pix -= 2*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2+=2) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+      }
+    }
+  } 
+  
+  out_pix = &data[2*j_end*dx];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) { 
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+    }
+  }
+
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 16, 0);
+  
+# endif
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom24.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom24.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom24.c	(revision 16632)
@@ -0,0 +1,178 @@
+# include "Ximage.h"
+
+void CreateZoom24 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+# if (0)
+  int i, j, ii, jj, extra;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  float *imdata, *in_pix, *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned long back;
+  unsigned char back1, back2, back3;
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+  extra = 4 - (dx * 3) % 4;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, dy*(3*dx+extra));
+    bzero (image[0].zoom.data, image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff &  graphic[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 16);
+  }
+  back = graphic[0].back;
+  back1 = 0x0000ff & back;
+  back2 = 0x0000ff & (back >> 8);
+  back3 = 0x0000ff & (back >> 16);
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) image[0].zoom.data;
+  imdata  = (float *) image[0].image[0].matrix.buffer;
+  in_pix  = &imdata[DX*(int)MAX(Ry,0) + (int)MAX(Rx,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix += extra;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	pixelN = PixelLookup(*in_pix2);
+	out_pix[0] = pixel1[pixelN];
+	out_pix[1] = pixel2[pixelN];
+	out_pix[2] = pixel3[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixelN   = PixelLookup(*in_pix2);
+	pixvalue1 = pixel1[pixelN];
+	pixvalue2 = pixel2[pixelN];
+	pixvalue3 = pixel3[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  */
+
+  out_pix = &data[j_end*(3*dx+extra)];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix+=extra;
+  }
+
+  /*
+  out_pix = (unsigned char *) image[0].zoom.data;
+  for (i = 0; i < dx*dy; i++) {
+    out_pix[3*i + 0] = back1;
+    out_pix[3*i + 1] = back2;
+    out_pix[3*i + 2] = back3;
+  }
+  for (j = 0; j < dy/2; j++) {
+    for (i = 0; i < dx; i++) {
+      out_pix[j*(extra + 3*dx) + 3*i + 0] = pixel1[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 1] = pixel2[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 2] = pixel3[10];
+    }
+
+  }
+  */
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, 24, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+  
+# endif
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom32.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom32.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom32.c	(revision 16632)
@@ -0,0 +1,138 @@
+# include "Ximage.h"
+
+void CreateZoom32 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Ix, Iy;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2;
+  unsigned short *in_pix, *in_pix2;
+  unsigned long *pixel, pixvalue;
+  unsigned long back;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, 4*image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  ALLOCATE (pixel, unsigned long, graphic[0].Npixels);
+
+  // local array for pixel values
+  for (i = 0; i < graphic[0].Npixels; i++) { 
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  // set up expansions
+  assert ((image[0].zoom.expand >= 1) || (image[0].zoom.expand <= -2));
+  expand = expand_in = expand_out = 1.0;
+  if (image[0].zoom.expand > 0) {
+    expand = 1 / (1.0*image[0].zoom.expand);
+    expand_out = image[0].zoom.expand;
+    expand_in  = 1;
+  }
+  if (image[0].zoom.expand < 0) {
+    expand = fabs((double)image[0].zoom.expand);
+    expand_out = 1;
+    expand_in  = -image[0].zoom.expand;
+  }
+
+  // define the image sizes
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  
+  // x, y are the closest lit screen pixel to 0,0
+  Picture_Lower (&i_start, &j_start, &image[0].image[0].matrix, &image[0].zoom);
+
+  // x, y are the closest lit screen pixel to dx, dy
+  Picture_Upper (&i_end, &j_end, &image[0].image[0].matrix, &image[0].zoom);
+
+  // Ix,Iy are the first displayed image pixel
+  Picture_to_Image (&Ix, &Iy, i_start, j_start, &image[0].zoom);
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) image[0].zoom.data;
+  in_pix  = &image[0].pixmap[DX*(int)MAX(Iy,0) + (int)MAX(Ix,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  // XXX can we just drop this?
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    *out_pix = back;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+    } else {
+      // equiv to : out_pix += (i_end - i_start) + [expand_out - (i_end - i_start) % expand_out]
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue; 
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+    assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);
+  } 
+  assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  
+  assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);
+
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)image[0].zoom.data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+  assert (out_pix - (unsigned int *)image[0].zoom.data <= dx*dy);
+
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 32, 0);
+  
+  free (pixel);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom8.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom8.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CreateZoom8.c	(revision 16632)
@@ -0,0 +1,130 @@
+# include "Ximage.h"
+
+void CreateZoom8 (KapaImageWidget *image, Graphic *graphic, double x, double y) {
+
+# if (0)
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY, pixelN;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2;
+  float *imdata, *in_pix, *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long back;
+
+  if (image[0].image[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (image[0].zoom.data, char, image[0].zoom.dx*image[0].zoom.dy);
+    bzero (image[0].zoom.data, image[0].zoom.dx*image[0].zoom.dy);
+    image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 8, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = graphic[0].cmap[i].pixel;
+  }
+  back = graphic[0].back;
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  zoomscale = MAX (5, image[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  dx = image[0].zoom.dx;
+  dy = image[0].zoom.dy;
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned char *) image[0].zoom.data;
+  imdata  = (float *) image[0].image[0].matrix.buffer;
+  in_pix  = &imdata[DX*(int)MAX(Ry,0) + (int)MAX(Rx,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = back;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = back;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	pixelN = PixelLookup(*in_pix2);
+	*out_pix = pixel[pixelN];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixelN   = PixelLookup(*in_pix2);
+	pixvalue = pixel[pixelN];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned char *) image[0].zoom.data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+
+  image[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					image[0].zoom.data, image[0].zoom.dx, image[0].zoom.dy, 8, 0);
+  
+# endif
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CrossHairs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CrossHairs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CrossHairs.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include "Ximage.h"
+
+void CrossHairs (Graphic *graphic, Picture *image) {
+
+  int x0, x1, x5, x7;
+  int y0, y2, y4, y5;
+  double zoomscale;
+
+  // is this totally wrong??
+  zoomscale = image[0].expand;
+  x0 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 2.5) + image[0].x;
+  x5 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 0.5) + image[0].x;
+  x7 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 0.5) + image[0].x;
+  x1 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 2.5) + image[0].x;
+						    	 
+  y4 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 2.5) + image[0].y;
+  y2 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 0.5) + image[0].y;
+  y0 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 0.5) + image[0].y;
+  y5 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 2.5) + image[0].y;
+
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0, x5, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y0, x5, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y5, x7, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y0, x1, y0);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2, x5, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y2, x5, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y4, x7, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y2, x1, y2);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0+1, x5-1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y0+1, x5-1, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y5, x7+1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y0+1, x1, y0+1);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2-1, x5-1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y2-1, x5-1, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y4, x7+1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y2-1, x1, y2-1);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/CursorOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/CursorOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/CursorOps.c	(revision 16632)
@@ -0,0 +1,121 @@
+# include "Ximage.h"
+
+// input coordinates are relative to the picture bounding box
+void Picture_to_Image (double *x1, double *y1, double x2, double y2, Picture *picture) {
+
+  double expand, dx, dy;
+
+  expand = 1.0;
+  if (picture[0].expand > 0) {
+    expand = 1 / (1.0*picture[0].expand);
+  } else {
+    expand = fabs((double)picture[0].expand);
+  }
+  
+  // pixel coordinates in picture frame
+  dx = expand*(x2 - 0.5*picture[0].dx);
+  dy = expand*(y2 - 0.5*picture[0].dy);
+
+  // picture[0].X,Y is the image coordinate in the center of the picture
+  *x1 = picture[0].flipx ? picture[0].X - dx : picture[0].X + dx;
+  *y1 = picture[0].flipy ? picture[0].Y - dy : picture[0].Y + dy;
+}
+
+// input coordinates are relative to the X window
+void Screen_to_Image (double *x1, double *y1, double x2, double y2, Picture *picture) {
+
+  double xp, yp;
+
+  // pixel coordinates in picture frame
+  xp = x2 - picture[0].x;
+  yp = y2 - picture[0].y;
+
+  Picture_to_Image (x1, y1, xp, yp, picture);
+}
+
+void Image_to_Picture (double *x1, double *y1, double x2, double y2, Picture *picture) {
+
+  double expand, dx, dy;
+
+  /* notice that here, expand is the reciprocal of the expand above */
+  expand = 1.0;
+  if (picture[0].expand > 0) {
+    expand = picture[0].expand;
+  } else {
+    expand = 1 / fabs((double)picture[0].expand);
+  }
+  
+  // pixel coordinates in picture frame
+  dx = picture[0].flipx ? picture[0].X - x2 : x2 - picture[0].X;
+  dy = picture[0].flipy ? picture[0].Y - y2 : y2 - picture[0].Y;
+    
+  *x1 = expand*dx + 0.5*picture[0].dx;
+  *y1 = expand*dy + 0.5*picture[0].dy;
+}
+
+void Image_to_Screen (double *x1, double *y1, double x2, double y2, Picture *picture) {
+
+  double xp, yp;
+
+  Image_to_Picture (&xp, &yp, x2, y2, picture);
+
+  // pixel coordinates in screen frame
+  *x1 = xp + picture[0].x;
+  *y1 = yp + picture[0].y;
+}
+
+// input coordinates are relative to the picture bounding box
+void Picture_Lower (int *i_start, int *j_start, Matrix *matrix, Picture *picture) {
+
+  double Ix, Iy, Sx, Sy;
+
+  // Ix, Iy are the image coordinates of the specified screen pixel
+  Picture_to_Image (&Ix, &Iy, 0.0, 0.0, picture);
+
+  // Ix, Iy are now limited to valid image coordinates
+  Ix = MIN (MAX (Ix, 0), matrix[0].Naxis[0]);
+  Iy = MIN (MAX (Iy, 0), matrix[0].Naxis[1]);
+
+  // round up (down) to nearest pixel boundary
+  if (Ix > (int)(Ix)) {
+    Ix = picture[0].flipx ? (int)(Ix) : (int)(Ix) + 1;
+  }
+  if (Iy > (int)(Iy)) {
+    Iy = picture[0].flipy ? (int)(Iy) : (int)(Iy) + 1;
+  }
+
+  // Sx, Sy are the screen coordinates of the Ix,Iy pixel
+  Image_to_Picture (&Sx, &Sy, Ix, Iy, picture);
+
+  // i_start, j_start are now limited to valid screen coordinates
+  *i_start = MIN (MAX (Sx, 0), picture[0].dx);
+  *j_start = MIN (MAX (Sy, 0), picture[0].dy);
+}
+  
+// input coordinates are relative to the picture bounding box
+void Picture_Upper (int *i_end, int *j_end, Matrix *matrix, Picture *picture) {
+
+  double Ix, Iy, Sx, Sy;
+
+  // Ix, Iy are the image coordinates of the specified screen pixel
+  Picture_to_Image (&Ix, &Iy, picture[0].dx, picture[0].dy, picture);
+
+  // Ix, Iy are now limited to valid image coordinates
+  Ix = MIN (MAX (Ix, 0), matrix[0].Naxis[0]);
+  Iy = MIN (MAX (Iy, 0), matrix[0].Naxis[1]);
+
+  // round down (up) to nearest pixel boundary
+  if (Ix > (int)(Ix)) {
+    Ix = picture[0].flipx ? (int)(Ix) + 1 : (int)(Ix);
+  }
+  if (Iy > (int)(Iy)) {
+    Iy = picture[0].flipy ? (int)(Iy) + 1: (int)(Iy);
+  }
+
+  // Sx, Sy are the screen coordinates of the Ix,Iy pixel
+  Image_to_Picture (&Sx, &Sy, Ix, Iy, picture);
+
+  // i_start, j_start are now limited to valid screen coordinates
+  *i_end = MIN (MAX (Sx, 0), picture[0].dx);
+  *j_end = MIN (MAX (Sy, 0), picture[0].dy);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DefineSection.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DefineSection.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DefineSection.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+// define the section, but do not create a graph or image 
+int DefineSection (int sock) {
+  
+  int N, MoveSection;
+  char name[128];
+  double x, y, dx, dy;
+  Section *section;
+
+  KiiScanMessage (sock, "%s %lf %lf %lf %lf", name, &x, &y, &dx, &dy);
+
+  MoveSection = FALSE;
+
+  N = GetSectionByName (name);
+  if (N < 0) {
+    section = AddSection (name, x, y, dx, dy);
+    MoveSection = TRUE;
+  } else {
+    section = GetSectionByNumber (N);
+    SetActiveSectionByNumber (N);
+
+    if (section[0].x != x)   MoveSection = TRUE;
+    if (section[0].y != y)   MoveSection = TRUE;
+    if (section[0].dx != dx) MoveSection = TRUE;
+    if (section[0].dy != dy) MoveSection = TRUE;
+
+    section[0].x = x;
+    section[0].y = y;
+    section[0].dx = dx;
+    section[0].dy = dy;
+  }
+
+  if (MoveSection) {
+    SetSectionSizes (section);
+    Refresh (1);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DragColorbar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DragColorbar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DragColorbar.c	(revision 16632)
@@ -0,0 +1,106 @@
+# include "Ximage.h"
+/* future expansion: warp mouse to the right spot for the current settings */
+
+void DragColorbar (Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event) {
+
+  double          frac_x, oldfrac_x, frac_y, oldfrac_y, start, slope;
+  int             X, Y;
+  XEvent          event;
+  XMotionEvent   *move;
+  int             xstatus, Npix, center;
+
+  if (!graphic[0].visualclass) return;
+
+  X = mouse_event[0].x;
+  Y = mouse_event[0].y;
+  Npix = graphic[0].Npixels;
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  oldfrac_x = oldfrac_y = 10;
+  
+  while (1) {
+    frac_x = X / (1.0*graphic[0].dx);
+    frac_x = MAX (0, frac_x);
+    frac_x = MIN (1, frac_x);
+    frac_y = Y / (1.0*graphic[0].dy);
+    frac_y = MAX (0, frac_y);
+    frac_y = MIN (1, frac_y);
+    switch (mouse_event[0].button) {
+    case 1:
+      center = frac_x*Npix;
+      slope = Npix / (1 + 4*frac_y*frac_y*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    case 2:
+      start = 0;
+      slope = 1;
+      break;
+    case 3:
+      center = (Npix/2.0 - start) / slope;
+      slope = Npix / (1 + 4*frac_x*frac_x*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    }
+
+    if ((frac_x != oldfrac_x) || (frac_y != oldfrac_y)) {
+      ResetColorbar (graphic, start, slope);
+    }
+    oldfrac_x = frac_x;
+    oldfrac_y = frac_y;
+      
+    if ((xstatus = XCheckMaskEvent (graphic[0].display, EVENT_MASK, &event))) {
+      
+      switch (event.type)  {
+	
+      case MotionNotify:
+	if ((xstatus = XPending (graphic[0].display)) < 2) {
+	  move = (XMotionEvent *) &event;
+	  X = move[0].x;
+	  Y = move[0].y;
+	}
+	break;
+	
+      case ButtonPress:
+      case ButtonRelease:
+	image[0].image[0].start = start;	
+	image[0].image[0].slope = slope;
+	return;
+	break;
+	
+      }
+    }
+  }
+  
+}
+
+void ResetColorbar (Graphic *graphic, double start, double slope) {
+
+  int i, j;
+  XColor cmap[256];
+
+  if (!graphic[0].visualclass) return;
+
+  for (i = 0; i < graphic[0].Npixels; i++) {
+    cmap[i] = graphic[0].cmap[i];
+    j = start + i * slope;
+    if (j < 0) {
+      cmap[i].red = graphic[0].cmap[0].red;
+      cmap[i].blue = graphic[0].cmap[0].blue;
+      cmap[i].green = graphic[0].cmap[0].green;
+    }
+    else {
+      if (j >= graphic[0].Npixels) {
+	cmap[i].red = graphic[0].cmap[graphic[0].Npixels-1].red;
+	cmap[i].blue = graphic[0].cmap[graphic[0].Npixels-1].blue;
+	cmap[i].green = graphic[0].cmap[graphic[0].Npixels-1].green;
+      }
+      else {
+	cmap[i].red = graphic[0].cmap[j].red;
+	cmap[i].blue = graphic[0].cmap[j].blue;
+	cmap[i].green = graphic[0].cmap[j].green;
+      }
+    }
+  }
+
+  XStoreColors(graphic[0].display, graphic[0].colormap, cmap, graphic[0].Npixels);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawBitmap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawBitmap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawBitmap.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+
+void DrawBitmap (Graphic *graphic, int x, int y, int dx, int dy, char *bitmap, int mode) {
+
+  int i, j, byte_line, byte, bit, flag;
+  unsigned long int fore, back;
+
+  fore = graphic[0].fore;
+  back = graphic[0].back;
+
+  if (mode == 0) {
+    fore = graphic[0].fore;
+    back = graphic[0].back;
+    graphic[0].fore = back;
+    graphic[0].back = back;
+  }
+    
+  if (mode == 2) {
+    fore = graphic[0].fore;
+    back = graphic[0].back;
+    graphic[0].fore = back;
+    graphic[0].back = fore;
+  }
+    
+  
+  byte_line = (int) ((dx + 7) / 8);
+  for (i = 0; i < dy; i++) {
+    for (j = 0; j < dx; j++) {
+      byte = byte_line * i + (j / 8);
+      bit = j % 8;
+      flag = 0x01 & (bitmap[byte] >> bit);
+      if (flag)
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+      else 
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+      XDrawPoint (graphic[0].display, graphic[0].window, 
+		  graphic[0].gc, x + j, y + i);
+    }
+  }
+  if (mode == 0) {
+    graphic[0].fore = fore;
+    graphic[0].back = back;
+  }
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawButton.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawButton.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawButton.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "Ximage.h"
+
+void DrawButton (Graphic *graphic, Button *button) {
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  XDrawRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+
+  DrawBitmap (graphic, 
+	      button[0].x + (button[0].dx - button[0].width) / 2 + 1, 
+	      button[0].y + (button[0].dy - button[0].height) / 2 + 1, 
+	      button[0].width, button[0].height, 
+	      button[0].bitmap, 1);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+}
+
+# if (0)
+  if (button[0].text) {
+    dX = XTextWidth (graphic[0].font, button[0].bitmap, strlen(button[0].bitmap));
+    y = button[0].y + (button[0].dy + graphic[0].font[0].ascent)/2;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 button[0].x + (button[0].dx - dX) / 2, y,
+		 button[0].bitmap, strlen(button[0].bitmap));
+  } else {
+    DrawBitmap (graphic, 
+		button[0].x + (button[0].dx - button[0].width) / 2 + 1, 
+		button[0].y + (button[0].dy - button[0].height) / 2 + 1, 
+		button[0].width, button[0].height, 
+		button[0].bitmap, 1);
+  }
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawFrame.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawFrame.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawFrame.c	(revision 16632)
@@ -0,0 +1,179 @@
+# include "Ximage.h"
+# define MIN_RANGE 1e-10
+# define DrawLine(X,Y,DX,DY) (XDrawLine (graphic->display, graphic->window, graphic->gc, (int)(X), (int)(Y), (int)(X+DX), (int)(Y+DY)))
+  
+static Graphic *graphic;
+
+void DrawFrame (KapaGraphWidget *graph) {
+  
+  int i, fx, fy, dfx, dfy, P, IsLabel;
+  double range, major, minor, first, next;
+
+  graphic = GetGraphic();
+
+  // XXX why is this called for every redraw?
+  DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->fore, graphic->back);
+
+  /* each axis is drawn independently, but ticks and labels are placed according to
+     perpendicular distance. */
+  for (i = 0; i < 4; i++) {
+    fx = graph[0].axis[i].fx;
+    fy = graph[0].axis[i].fy;
+    dfx = graph[0].axis[i].dfx;
+    dfy = graph[0].axis[i].dfy;
+    P = hypot ((double)graph[0].axis[(i+1)%2].dfx, (double)graph[0].axis[(i+1)%2].dfy);
+
+    if (graph[0].axis[i].isaxis) {
+      DrawLine (fx, fy, dfx, dfy);
+    }
+    
+    if (graph[0].axis[i].areticks) {
+      if (isnan(graph[0].axis[i].min) || isinf(graph[0].axis[i].min)) continue;
+      if (isnan(graph[0].axis[i].max) || isinf(graph[0].axis[i].max)) continue;
+
+      range = graph[0].axis[i].max - graph[0].axis[i].min;
+      if (fabs(range) < MIN_RANGE) continue;
+
+      if (fabs(range) < MIN_RANGE) {
+	range = (range < 0) ? -MIN_RANGE : +MIN_RANGE;
+      }
+
+      AxisTickScale (&graph[0].axis[i], &major, &minor);
+
+      first = minor*((int)(graph[0].axis[i].min/minor));
+      if ((range > 0) && (first < graph[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > graph[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= graph[0].axis[i].max)) || ((range < 0) && (next >= graph[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = graph[0].axis[i].islabel;
+	DrawTick (fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+}
+
+void DrawTick (int fx, int fy, int dfx, int dfy, 
+	       int P, double min, double max, 
+	       double value, int mode, int naxis) {
+  
+  int x, y, dx, dy, pos, dir, fontsize;
+  double size, n;
+  char string[64], *fontname;
+
+  if (mode) { 
+    size = MAX (0.02, 7.0 / P); 
+  } else {
+    size = MAX (0.01, 4.0 / P); 
+  }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+# ifdef IN_AND_OUT_TICKS
+# define GAP 0.03
+# else
+# define GAP 0.01
+# endif
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+    pos = 0;
+    
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value/(max-min)) < 0.001) { value = 0.0; }
+    sprintf (string, "%4g", value);
+    DrawRotText (x, y, string, pos, 0.0);
+  }
+  
+}
+
+
+void AxisTickScale (Axis *axis, double *major, double *minor) {
+
+  double range, lrange, factor, mantis, fmantis, power;
+
+  range = axis[0].max - axis[0].min;
+  if (fabs(range) < MIN_RANGE) {
+    range = (range < 0) ? -MIN_RANGE : +MIN_RANGE;
+  }
+
+  lrange = log10(MAX(fabs(range), MIN_RANGE));
+  mantis = modf (lrange, &factor);
+  if (mantis < 0.0) {
+    mantis += 1.0;
+    factor -= 1.0;
+  }
+  
+  power = MAX(pow(10.0, factor), MIN_RANGE);
+  fmantis = pow(10.0, mantis);
+  *major = MAX(0.5 * power, MIN_RANGE);
+  *minor = MAX(0.1 * power, MIN_RANGE);
+  
+  if ((fmantis >= 1.0) && (fmantis <  1.999)) {
+    *major = 0.5 * power;
+    *minor = 0.1 * power;
+    if (axis[0].areticks == 1) {
+      *major = 1.0 * power;
+      *minor = 0.2 * power;
+    }	  
+  }
+  if ((fmantis >= 1.999) && (fmantis <  3.999)) {
+    *major = 1.0 * power;
+    *minor = 0.2 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 3.999) && (fmantis <  5.999)) {
+    *major = 1.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.0 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 5.999) && (fmantis <   7.999)) {
+    *major = 2.0 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 2.5 * power;
+      *minor = 0.5 * power;
+    }	  
+  }
+  if ((fmantis >= 7.999) && (fmantis <  10.000)) {
+    *major = 2.5 * power;
+    *minor = 0.5 * power;
+    if (axis[0].areticks == 1) {
+      *major = 5.0 * power;
+      *minor = 1.0 * power;
+    }	  
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawLabels.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "Ximage.h"
+  
+void DrawLabels (KapaGraphWidget *graph) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->fore, graphic->back);
+
+  /* each label is drawn independently */
+  for (i = 0; i < 8; i++) {
+    if (strcmp (graph[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = graph[0].label[i].x;
+      y = graph[0].label[i].y;
+      SetRotFont (graph[0].label[i].font, graph[0].label[i].size);
+      DrawRotText (x, y, graph[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+          
+ 6____7___8 
+  |       | 
+  |       | 
+ 3|   4   |5
+  |       |
+  |       |
+  ---------
+  0   1   2
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawObjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawObjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawObjects.c	(revision 16632)
@@ -0,0 +1,624 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,X2,Y2) (XDrawLine (graphic->display, graphic->window, graphic->gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawRectangle(X1,Y1,X2,Y2) (XDrawRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define FillRectangle(X1,Y1,X2,Y2) (XFillRectangle (graphic->display, graphic->window, graphic->gc, (int)(X1+0.5), (int)(Y1+0.5), (int)(X2+0.5), (int)(Y2+0.5)))
+# define DrawCircle(X,Y,R) (XDrawArc (graphic->display, graphic->window, graphic->gc, (int)(X-R+0.5), (int)(Y-R+0.5), abs(2*R+0.5), abs(2*R+0.5), 0, 23040))
+
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+static Graphic *graphic;
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y0, double X1, double Y1);
+
+/* draw all objects for this Graph */
+int DrawObjects (KapaGraphWidget *graph) {
+  
+  int i;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    if (DEBUG) fprintf (stderr, "object: %d\n", i);
+    if (DEBUG) fprintf (stderr, "Npts: %d\n", graph[0].objects[i].Npts);
+    DrawObjectN (graph, &graph[0].objects[i]);
+  }    
+  return (TRUE);
+}
+
+/* Draw a specific object in the graph */
+int DrawObjectN (KapaGraphWidget *graph, Gobjects *object) {
+  
+  static char dash[2] = {5,10};
+  static char dot[2] = {3,3};
+  int lweight;
+  
+  // this function calls all of the supporting Draw... functions below
+  graphic = GetGraphic();
+
+  lweight = MAX (0, MIN (10, object[0].lweight));
+
+  /* set line type */
+  switch (object[0].ltype) {
+  case 0:
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  case 1:
+    XSetDashes (graphic->display, graphic->gc, 100, dash, 2);
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  case 2:
+    XSetDashes (graphic->display, graphic->gc, 10, dot, 2);
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineOnOffDash, CapNotLast, JoinMiter);
+    break;
+  default:
+    XSetLineAttributes (graphic->display, graphic->gc, lweight, LineSolid, CapNotLast, JoinMiter);
+    break;
+  }
+
+  XSetForeground (graphic->display, graphic->gc, graphic->color[object[0].color]);
+
+  switch (object[0].style) {
+  case CONNECT: 
+    DrawConnect (graph, object);
+    break;
+  case HISTOGRAM:
+    DrawHistogram (graph, object);
+    break;
+  case POINTS:
+    DrawPoints (graph, object);
+    break;
+  }
+    
+  if (object[0].etype & 0x01) {
+    DrawYErrors (graph, object);
+  }
+  if (object[0].etype & 0x02) {
+    DrawXErrors (graph, object);
+  }
+
+  XSetLineAttributes (graphic->display, graphic->gc, 0, LineSolid, CapNotLast, JoinMiter);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  return (TRUE);
+}
+
+/******/
+void DrawConnect (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    
+    ClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+  
+}
+
+void ClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+  
+
+/******/
+void DrawHistogram (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/******/
+void DrawPoints (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+  
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic->dx + graphic->dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d*z[i], sy - d*z[i], 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i] + 1, sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i] + 1, sy - d*z[i] - 1, sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i] + 1, sy + d*z[i] + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d*z[i];  points[0].y = sy + 0.58*d*z[i];  
+	    points[1].x = sx + d*z[i];  points[1].y = sy + 0.58*d*z[i];  
+	    points[2].x = sx;           points[2].y = sy - 1.15*d*z[i];  
+	    points[3].x = sx - d*z[i];  points[3].y = sy + 0.58*d*z[i];  
+	    XFillPolygon (graphic->display, graphic->window, graphic->gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	if (!(finite(x[i+1]) && finite(y[i+1]))) continue;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } 
+  /**** points are not scaled by object.z ***/
+  else {
+    d = object[0].size * 0.5 * (graphic->dx + graphic->dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx - d, sy - d, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d + 1, sy);
+	    DrawLine (sx, sy - d, sx, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    /* XDrawLine is a little funny, this is needed to fix endpost errors */
+	    DrawLine (sx + d + 1, sy - d - 1, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d + 1, sy + d + 1);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      XPoint points[4];
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    points[0].x = sx - d;  points[0].y = sy + 0.58*d;  
+	    points[1].x = sx + d;  points[1].y = sy + 0.58*d;  
+	    points[2].x = sx;      points[2].y = sy - 1.15*d;  
+	    points[3].x = sx - d;  points[3].y = sy + 0.58*d;  
+	    XFillPolygon (graphic->display, graphic->window, graphic->gc, points, 4, Convex, CoordModeOrigin);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy + 0.58*d);
+	    DrawLine (sx, sy, sx,     sy - 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/******/
+void DrawXErrors (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy))) 
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/******/
+void DrawYErrors (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = sx0 + dyp[i]*mxj;
+    sy1 = sy0 + dyp[i]*myj;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawTextlines.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawTextlines.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/DrawTextlines.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+  
+void DrawTextlines (KapaGraphWidget *graph) {
+  
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  fontname = GetRotFont (&size);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  DrawRotTextInit (graphic->display, graphic->window, graphic->gc, graphic->fore, graphic->back);
+
+  for (i = 0; i < graph[0].Ntextline; i++) {
+    if (strcmp (graph[0].textline[i].text, "")) {
+      angle = graph[0].textline[i].angle;
+      x = graph[0].textline[i].x;
+      y = graph[0].textline[i].y;
+      SetRotFont (graph[0].textline[i].font, graph[0].textline[i].size);
+      DrawRotText (x, y, graph[0].textline[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseCurrentPlot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseCurrentPlot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseCurrentPlot.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+// erase just the current plot
+int EraseCurrentPlot () {
+  
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) return (TRUE);
+
+  EraseGraph (section->graph);
+  
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseImage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseImage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseImage.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+int EraseImage () {
+
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+  if (image == NULL) return (TRUE);
+
+  FreeImage (image);
+  section->image = NULL;
+
+  if (USE_XWINDOW) Refresh ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseOverlay.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+
+int EraseOverlay (int sock) {
+
+  int i, N;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image = section->image;
+  if (image == NULL) return (TRUE);
+
+  KiiScanCommand (sock, 16, "%*s %d", &N);
+
+  if (N > NOVERLAYS) {
+    REALLOCATE (image[0].tickmarks.objects, KiiOverlay, 1);
+    image[0].tickmarks.Nobjects = 0;
+  } else {
+    for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+      if (image[0].overlay[N].objects[i].type == KII_OVERLAY_TEXT) {
+	free (image[0].overlay[N].objects[i].text);
+      }
+    }
+    REALLOCATE (image[0].overlay[N].objects, KiiOverlay, 1);
+    image[0].overlay[N].Nobjects = 0;
+    image[0].overlay[N].active = FALSE;
+  }
+
+  if (USE_XWINDOW) Refresh ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/ErasePlots.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/ErasePlots.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/ErasePlots.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+// erase all plots, keep the sections
+int ErasePlots () {
+  
+  int i, Nsection;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+  
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      EraseGraph (section->graph);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseSections.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseSections.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/EraseSections.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+int EraseSections () {
+  
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+  
+  FreeSections ();
+  AddSection ("default", 0.0, 0.0, 1.0, 1.0);
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/EventLoop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/EventLoop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/EventLoop.c	(revision 16632)
@@ -0,0 +1,141 @@
+# include "Ximage.h"
+
+/* list events being selected below, all other masks are ignored */ 
+# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | PointerMotionMask))
+
+int LastEvent (Display *display, int type, XEvent *event) {
+
+  int found;
+
+  found = FALSE;
+  while (XCheckTypedEvent (display, type, event)) {
+    found = TRUE;
+  }
+  return (found);
+}
+
+int EventLoop () {
+  
+  int      status;
+  XEvent   event;
+  Display *display;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+  display = graphic->display;
+  
+  if (USE_XWINDOW) Refresh (1);
+
+  status = TRUE;
+  while (status) {
+    
+    if (!CheckPipe ()) return (FALSE);
+    
+    if (!USE_XWINDOW) {
+      usleep (50000);
+      continue;
+    }
+
+    if (XEventsQueued (display, QueuedAfterFlush) < 1) {
+      /* fprintf (stderr, "."); */
+      usleep (50000);
+      continue;
+    }
+
+    /* grab the last entry for these events */
+    if (LastEvent (display, ConfigureNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, CirculateNotify, &event)) Reconfig (&event);
+    if (LastEvent (display, Expose,          &event)) Refresh (1);
+    if (LastEvent (display, MappingNotify,   &event)) XRefreshKeyboardMapping ((XMappingEvent *) &event);
+    if (LastEvent (display, MotionNotify,    &event)) UpdatePointer (graphic, (XMotionEvent *) &event);
+    if (LastEvent (display, ButtonPress,     &event)) InterpretPresses (graphic, (XButtonEvent *) &event);
+    if (LastEvent (display, KeyPress,        &event)) InterpretKeys (graphic, (XKeyEvent *) &event);
+
+    /* drop and ignore the following StructureNotifyMask events */
+    LastEvent (display, GravityNotify, &event);
+    LastEvent (display, ReparentNotify, &event);
+    LastEvent (display, MapNotify, &event);
+    LastEvent (display, UnmapNotify, &event);
+
+    /* remove those events we will ignore */
+    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;
+
+    /* events to remove which have no mask component */
+    while (XCheckTypedEvent (display, MappingNotify, &event)) continue;
+    while (XCheckTypedEvent (display, ClientMessage, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionClear, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionNotify, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionRequest, &event)) continue;
+  }
+  return (status);
+}
+
+# if (0)
+
+/* all masks from X.h for reference: */
+
+#define NoEventMask                     0L
+#define KeyPressMask                    (1L<<0)
+#define KeyReleaseMask                  (1L<<1)
+#define ButtonPressMask                 (1L<<2)
+#define ButtonReleaseMask               (1L<<3)
+#define EnterWindowMask                 (1L<<4)
+#define LeaveWindowMask                 (1L<<5)
+#define PointerMotionMask               (1L<<6)
+#define PointerMotionHintMask           (1L<<7)
+#define Button1MotionMask               (1L<<8)
+#define Button2MotionMask               (1L<<9)
+#define Button3MotionMask               (1L<<10)
+#define Button4MotionMask               (1L<<11)
+#define Button5MotionMask               (1L<<12)
+#define ButtonMotionMask                (1L<<13)
+#define KeymapStateMask                 (1L<<14)
+#define ExposureMask                    (1L<<15)
+#define VisibilityChangeMask            (1L<<16)
+#define StructureNotifyMask             (1L<<17)
+#define ResizeRedirectMask              (1L<<18)
+#define SubstructureNotifyMask          (1L<<19)
+#define SubstructureRedirectMask        (1L<<20)
+#define FocusChangeMask                 (1L<<21)
+#define PropertyChangeMask              (1L<<22)
+#define ColormapChangeMask              (1L<<23)
+#define OwnerGrabButtonMask             (1L<<24)
+
+/* all events from X.h for reference: */
+
+#define KeyPress                2
+#define KeyRelease              3
+#define ButtonPress             4
+#define ButtonRelease           5
+#define MotionNotify            6
+#define EnterNotify             7
+#define LeaveNotify             8
+#define FocusIn                 9
+#define FocusOut                10
+#define KeymapNotify            11
+#define Expose                  12
+#define GraphicsExpose          13
+#define NoExpose                14
+#define VisibilityNotify        15
+#define CreateNotify            16
+#define DestroyNotify           17
+#define UnmapNotify             18
+#define MapNotify               19
+#define MapRequest              20
+#define ReparentNotify          21
+#define ConfigureNotify         22
+#define ConfigureRequest        23
+#define GravityNotify           24
+#define ResizeRequest           25
+#define CirculateNotify         26
+#define CirculateRequest        27
+#define PropertyNotify          28
+#define SelectionClear          29
+#define SelectionRequest        30
+#define SelectionNotify         31
+#define ColormapNotify          32
+#define ClientMessage           33
+#define MappingNotify           34
+#define LASTEvent               35      /* must be bigger than any event # */
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/FlushDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/FlushDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/FlushDisplay.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "Ximage.h"
+
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+void FlushDisplay () {
+
+  struct timeval now;
+  int flush;
+  double dtime;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  if (!USE_XWINDOW) return;
+
+  flush = FALSE;
+  if (!reftimeset) {
+    flush = TRUE;
+    gettimeofday (&reftime, NULL);
+  } 
+
+  gettimeofday (&now, NULL);
+  dtime = DTIME (now, reftime);
+
+  if (dtime > 0.1) {
+    flush = TRUE;
+  }
+
+  if (flush) {
+    XFlush (graphic->display);
+    reftime = now;
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/GetColor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/GetColor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/GetColor.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+/************** GetColor *************/
+unsigned long GetColor (Display *display, char *name, Colormap colormap, unsigned long default_color) {
+
+  int status;
+  XColor rgbcolor, hardwarecolor;
+
+  status = XLookupColor (display, colormap, name, &rgbcolor, &hardwarecolor);
+  if (!status) return (default_color);
+
+  status = XAllocColor (display, colormap, &hardwarecolor);
+  if (!status) return (default_color);
+
+  return (hardwarecolor.pixel);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/GetPixelCount.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/GetPixelCount.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/GetPixelCount.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "Ximage.h"
+
+int GetPixelCount (int sock) {
+  
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  KiiSendMessage (sock, "NPIX: %8d", graphic->Npixels);
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Graphs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Graphs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Graphs.c	(revision 16632)
@@ -0,0 +1,118 @@
+# include "Ximage.h"
+
+/* initialize graph data */
+KapaGraphWidget *InitGraph () {
+
+  int i;
+  KapaGraphWidget *graph;
+
+  ALLOCATE (graph, KapaGraphWidget, 1);
+
+  /* set up axis positions */
+  for (i = 0; i < 4; i++) {
+    graph[0].axis[i].min = 0.0;
+    graph[0].axis[i].max = 1.0;
+    graph[0].axis[i].isaxis = FALSE;
+    graph[0].axis[i].areticks = FALSE;
+    graph[0].axis[i].islabel = FALSE;
+  }    
+  for (i = 0; i < 8; i++) {
+    strcpy (graph[0].label[i].text, "");
+  }
+
+  graph[0].data.xmin = 0.0;
+  graph[0].data.xmax = 1.0;
+  graph[0].data.ymin = 0.0;
+  graph[0].data.ymax = 1.0;
+
+  graph[0].data.style 	= 2; 		// points
+  graph[0].data.ptype 	= 2;		// + for points
+  graph[0].data.ltype 	= 0;		// solid line
+  graph[0].data.etype 	= 0;		// no error bars
+  graph[0].data.ebar  	= 0;		// no cross bar
+  graph[0].data.color 	= 0;		// black
+  graph[0].data.lweight = 0.5;		// line weight of 0.5
+  graph[0].data.size    = 1.0;		// point size of 1.0
+
+  graph[0].Nobjects = 0;
+  graph[0].Ntextline = 0;
+
+  ALLOCATE (graph[0].objects, Gobjects, 1);  /* allocate so later free will not crash! */
+  ALLOCATE (graph[0].textline, Label, 1);    /* allocate so later free will not crash! */
+
+  graph[0].objects[0].x   = graph[0].objects[0].y   = graph[0].objects[0].z = NULL;
+  graph[0].objects[0].dxm = graph[0].objects[0].dxp = NULL;
+  graph[0].objects[0].dym = graph[0].objects[0].dyp = NULL;
+
+  return (graph);
+}
+
+void DrawGraph (KapaGraphWidget *graph) {
+  if (graph == NULL) return;
+  DrawFrame    (graph);
+  DrawObjects  (graph);
+  DrawLabels   (graph);
+  DrawTextlines(graph);
+}
+
+/* remove objects */
+void EraseGraph (KapaGraphWidget *graph) {
+
+  int i;
+
+  if (graph == NULL) return;
+
+  /* free data objects, then re-alloc those needed */
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    FREE (graph[0].objects[i].x);
+    FREE (graph[0].objects[i].y);
+    FREE (graph[0].objects[i].z);
+    FREE (graph[0].objects[i].dxm);
+    FREE (graph[0].objects[i].dxp);
+    FREE (graph[0].objects[i].dym);
+    FREE (graph[0].objects[i].dyp);
+  }
+    
+  /* reset axes and labels */
+  for (i = 0; i < 4; i++) {
+    graph[0].axis[i].isaxis = FALSE;
+    graph[0].axis[i].islabel = FALSE;
+    graph[0].axis[i].areticks = FALSE;
+  }
+  for (i = 0; i < 8; i++) {
+    strcpy (graph[0].label[i].text, "");
+  }
+    
+  graph[0].Nobjects = 0;
+  graph[0].Ntextline = 0;
+  REALLOCATE (graph[0].objects, Gobjects, 1);
+  REALLOCATE (graph[0].textline, Label, 1);
+
+  graph[0].objects[0].x   = graph[0].objects[0].y   = graph[0].objects[0].z = NULL;
+  graph[0].objects[0].dxm = graph[0].objects[0].dxp = NULL;
+  graph[0].objects[0].dym = graph[0].objects[0].dyp = NULL;
+}
+
+/* remove objects */
+void FreeGraph (KapaGraphWidget *graph) {
+
+  int i;
+
+  if (graph == NULL) return;
+
+  /* free data objects, then re-alloc those needed */
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    FREE (graph[0].objects[i].x);
+    FREE (graph[0].objects[i].y);
+    FREE (graph[0].objects[i].z);
+    FREE (graph[0].objects[i].dxm);
+    FREE (graph[0].objects[i].dxp);
+    FREE (graph[0].objects[i].dym);
+    FREE (graph[0].objects[i].dyp);
+  }
+    
+  FREE (graph[0].objects);
+  FREE (graph[0].textline);
+  free (graph);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Image.c	(revision 16632)
@@ -0,0 +1,205 @@
+# include "Ximage.h"
+# include "buttons.h"
+
+int InitImageChannel (KapaImageChannel *channel) {
+
+  /** set up a bunch of default things **/
+  channel->zero = 0;
+  channel->range = 1;
+  channel->start = 0;
+  channel->slope = 1;
+
+  channel->coords.Npolyterms = 0;
+  channel->matrix.size = 0; /* a flag to show there is no data in the matrix */
+  ALLOCATE (channel->matrix.buffer, char, 1);  /* allocate so later free will not crash! */
+
+  return (TRUE);
+}
+
+/* initialization for things not specific to X */
+KapaImageWidget *InitImageWidget () {
+
+  int i;
+  KapaImageWidget *image;
+  Graphic *graphic;
+
+  graphic = GetGraphic ();
+
+  ALLOCATE (image, KapaImageWidget, 1);
+  memset (image, 0, sizeof(KapaImageWidget));
+
+  for (i = 0; i < NCHANNELS; i++) {
+    InitImageChannel (&image[0].channel[i]);
+  }
+  image[0].image = &image[0].channel[0];
+
+  image[0].nPixels = 0;
+  ALLOCATE (image[0].pixmap, unsigned short, 1);  /* allocate so later free will not crash! */
+
+  // XXXX this has been moved to graphic, which may be wrong
+  // image[0].ColorScaleMode = KAPA_SCALE_1D;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    image[0].overlay[i].Nobjects = 0;
+    ALLOCATE (image[0].overlay[i].objects, KiiOverlay, 1);  /* allocate so later free will not crash! */
+    image[0].overlay[i].active = FALSE;
+    image[0].overlay[i].color = graphic[0].overlay_color[i];
+  }
+
+  // set the center and expansion for the pictures:
+  image[0].picture.X      = 0.0;
+  image[0].picture.Y      = 0.0;
+  image[0].picture.expand = 1;
+  image[0].picture.flipx  = FALSE;
+  image[0].picture.flipy  = FALSE;
+
+  image[0].zoom.X      	  = 0.0;
+  image[0].zoom.Y      	  = 0.0;
+  image[0].zoom.expand 	  = +5;
+  image[0].zoom.flipx  	  = FALSE;
+  image[0].zoom.flipy  	  = FALSE;
+
+  image[0].wide.X      	  = 0.0;
+  image[0].wide.Y      	  = 0.0;
+  image[0].wide.expand 	  = -5;
+  image[0].wide.flipx  	  = FALSE;
+  image[0].wide.flipy  	  = FALSE;
+
+  image[0].location = 4;
+
+  image[0].MovePointer = TRUE;
+  image[0].DecimalDegrees  = TRUE;
+  ALLOCATE (image[0].picture.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (image[0].cmapbar.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (image[0].zoom.data, char, 1);      /* allocate so later free will not crash! */
+  ALLOCATE (image[0].wide.data, char, 1);      /* allocate so later free will not crash! */
+
+  InitButtonSize (&image[0].PS_button, PS_width, PS_height, PS_bits);
+  InitButtonFunc (&image[0].PS_button, PSfunction);
+
+  InitButtonSize (&image[0].grey_button, grey_width, grey_height, grey_bits);
+  InitButtonFunc (&image[0].grey_button, greycolors);
+
+  InitButtonSize (&image[0].rainbow_button, rainbow_width, rainbow_height, rainbow_bits);
+  InitButtonFunc (&image[0].rainbow_button, rainbow);
+
+  InitButtonSize (&image[0].heat_button, heat_width, heat_height, heat_bits);
+  InitButtonFunc (&image[0].heat_button, heat);
+
+  InitButtonSize (&image[0].recenter_button, recenter_width, recenter_height, recenter_bits);
+  image[0].recenter_button.function_1 = Recenter;
+  image[0].recenter_button.function_2 = RecenterRescale;
+  image[0].recenter_button.function_3 = Rescale;
+
+  InitButtonSize (&image[0].overlay_button[0], red_width, red_height, red_bits);
+  InitButtonFunc (&image[0].overlay_button[0], Overlay0);
+
+  InitButtonSize (&image[0].overlay_button[1], green_width, green_height, green_bits);
+  InitButtonFunc (&image[0].overlay_button[1], Overlay1);
+
+  InitButtonSize (&image[0].overlay_button[2], blue_width, blue_height, blue_bits);
+  InitButtonFunc (&image[0].overlay_button[2], Overlay2);
+
+  InitButtonSize (&image[0].overlay_button[3], yellow_width, yellow_height, yellow_bits);
+  InitButtonFunc (&image[0].overlay_button[3], Overlay3);
+
+  InitButtonSize (&image[0].hms_button, hms_width, hms_height, hms_bits);
+  InitButtonFunc (&image[0].hms_button, ToggleDEG);
+
+  return (image);
+}
+
+void InitButtonSize (Button *button, int width, int height, char *bitmap) {
+  button->dx = BUTTON_WIDTH;
+  button->dy = BUTTON_HEIGHT;
+  button->width = width;
+  button->height = height;
+  button->bitmap = bitmap;
+}
+
+void InitButtonFunc (Button *button, int (*function)()) {
+  button->function_1 = function;
+  button->function_2 = function;
+  button->function_3 = function;
+}
+
+void DrawImage (KapaImageWidget *image) {
+
+  int i;
+  Graphic *graphic;
+
+  if (image == NULL) return;
+
+  graphic = GetGraphic ();
+
+  XSetForeground (graphic[0].display,  graphic[0].gc, graphic[0].fore);
+  XDrawRectangle (graphic[0].display,  graphic[0].window, graphic[0].gc, 
+		  image[0].picture.x,  image[0].picture.y, 
+		  image[0].picture.dx+1, image[0].picture.dy+1);
+  
+  XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	     image[0].picture.pix, 0, 0, 
+	     image[0].picture.x + 1, image[0].picture.y + 1, 
+	     image[0].picture.dx, image[0].picture.dy);
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (image[0].overlay[i].active) {
+      PaintOverlay (graphic, image, i);
+    }
+  }
+
+  if (image[0].location) {
+    XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	       image[0].cmapbar.pix, 0, 0, 
+	       image[0].cmapbar.x, image[0].cmapbar.y, 
+	       image[0].cmapbar.dx, image[0].cmapbar.dy);
+
+    XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	       image[0].wide.pix, 0, 0, 
+	       image[0].wide.x, image[0].wide.y, 
+	       image[0].wide.dx, image[0].wide.dy);
+
+    CrossHairs (graphic, &image[0].zoom);
+  
+    /* erase everything below zoom box, then draw */
+    /*
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    image[0].text_x, image[0].text_x, image[0].text_dx, image[0].text_dy); 
+    */    
+    DrawButton (graphic, &image[0].PS_button);
+    DrawButton (graphic, &image[0].recenter_button);
+    DrawButton (graphic, &image[0].grey_button);
+    DrawButton (graphic, &image[0].rainbow_button);
+    DrawButton (graphic, &image[0].heat_button);
+    DrawButton (graphic, &image[0].hms_button);
+
+    for (i = 0; i < NOVERLAYS; i++) {
+      DrawButton (graphic, &image[0].overlay_button[i]);
+    }
+    StatusBox (graphic, image);
+  }
+
+  FlushDisplay (graphic[0].display);
+}
+
+void FreeImage (KapaImageWidget *image) {
+
+  int i;
+
+  if (image == NULL) return;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    free (image[0].overlay[i].objects);
+  }
+  for (i = 0; i < NCHANNELS; i++) {
+    free (image[0].channel[i].matrix.buffer);
+  }
+  free (image[0].pixmap);
+  free (image[0].picture.data);
+  free (image[0].cmapbar.data);
+  free (image[0].zoom.data);
+  free (image[0].wide.data);
+
+  free (image);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/InButton.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/InButton.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/InButton.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "Ximage.h"
+
+int InButton (XButtonEvent *button_event, Button *button) {
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= button[0].x) && (x <= button[0].x + button[0].dx) &&
+	    (y >= button[0].y) && (y <= button[0].y + button[0].dy));
+
+  return (answer);
+
+}
+
+/*** make this a macro? ***/
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/InPicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/InPicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/InPicture.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+int InPicture (XButtonEvent *button_event, Picture *picture) {
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= picture[0].x) && (x <= picture[0].x + picture[0].dx) &&
+	    (y >= picture[0].y) && (y <= picture[0].y + picture[0].dy));
+
+  return (answer);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/InterpretKeys.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/InterpretKeys.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/InterpretKeys.c	(revision 16632)
@@ -0,0 +1,169 @@
+# include "Ximage.h"
+
+int InterpretKeys (Graphic *graphic, XKeyEvent *event) {
+
+  float           *imdata;
+  double 	   X, Y, Z, R, D, offset;
+  int    	   sock, DX, DY, modstate;
+  char   	  *name, string[16];
+  KeySym           keysym;
+  XComposeStatus   composestatus;
+  Section         *section;
+  KapaImageWidget *image;
+  KapaGraphWidget *graph;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+  graph   = section->graph;
+
+  XLookupString (event, string, 9, &keysym, &composestatus);
+  modstate = event[0].state;
+
+  // return graph coords by default, image if graph does not exist
+  // XXX allow user to choose graph or image coords
+  if (ACTIVE_CURSOR) {
+
+    sock = GetActiveSocket ();
+    if (sock == -1) goto skip_cursor;
+
+    name = XKeysymToString (keysym);
+
+    // skip the following keys: 
+    if (name == NULL) goto skip_cursor;
+    if (!strcmp (name, "Shift_L")) goto skip_cursor;
+    if (!strcmp (name, "Shift_R")) goto skip_cursor;
+    if (!strcmp (name, "Control_L")) goto skip_cursor;
+    if (!strcmp (name, "Control_R")) goto skip_cursor;
+    if (!strcmp (name, "Alt_L")) goto skip_cursor;
+    if (!strcmp (name, "Alt_R")) goto skip_cursor;
+    if (!strcmp (name, "Super_L")) goto skip_cursor;
+    if (!strcmp (name, "Super_R")) goto skip_cursor;
+    if (!strcmp (name, "Caps_Lock")) goto skip_cursor;
+    if (!strcmp (name, "Pause")) goto skip_cursor;
+    if (!strcmp (name, "Continue")) goto skip_cursor;
+    if (!strcmp (name, "Num_Lock")) goto skip_cursor;
+    if (!strcmp (name, "Scroll_Lock")) goto skip_cursor;
+    if (!strcmp (name, "Print")) goto skip_cursor;
+    if (!strcmp (name, "(null)")) goto skip_cursor;
+
+    Z = -1;
+
+    if (graph) {
+      X = (event[0].x - graph[0].axis[0].fx)*(graph[0].axis[0].max - graph[0].axis[0].min)/graph[0].axis[0].dfx + graph[0].axis[0].min;
+      Y = (event[0].y - graph[0].axis[1].fy)*(graph[0].axis[1].max - graph[0].axis[1].min)/graph[0].axis[1].dfy + graph[0].axis[1].min;
+      XY_to_RD (&R, &D, X, Y, &graph[0].data.coords);
+    } 
+    if (image && !graph) {
+      if (event[0].x < image[0].picture.x) goto skip_cursor;
+      if (event[0].y < image[0].picture.y) goto skip_cursor;
+      if (event[0].x > image[0].picture.x + image[0].picture.dx) goto skip_cursor;
+      if (event[0].y > image[0].picture.y + image[0].picture.dy) goto skip_cursor;
+      Screen_to_Image (&X, &Y, (double)event[0].x, (double)event[0].y, &image[0].picture);
+      XY_to_RD (&R, &D, X, Y, &image[0].image[0].coords);
+
+      DX = image[0].image[0].matrix.Naxis[0];
+      DY = image[0].image[0].matrix.Naxis[1];
+
+      if (X < 0) goto off_image;
+      if (Y < 0) goto off_image;
+      if (X >= DX) goto off_image;
+      if (Y >= DY) goto off_image;
+      imdata = (float *) image[0].image[0].matrix.buffer;
+      Z      = imdata[DX*(int)(Y) + (int)(X)];
+    }
+  off_image:
+    KiiSendMessage (sock, "%12s %12.6f %12.6f %12.6f %12.6f %12.6f", name, X, Y, Z, R, D);
+  }
+
+skip_cursor:
+  if (image == NULL) return (TRUE);
+
+  // offset is in image pixels: 
+  // 0.5 image pixels is 1 screen pixel for expand == +2
+  // 2.0 image pixels is 1 screen pixel for expand == -2
+  if (image[0].picture.expand == 0) image[0].picture.expand = 1;
+  offset = (image[0].picture.expand > 0) ? 1.0 / image[0].picture.expand : -image[0].picture.expand;
+  if (modstate & ControlMask) offset *= 100;
+
+  switch (keysym) {
+
+    case XK_F1:
+      image[0].image = &image[0].channel[0];
+      SetColorScale (graphic, image);
+      Remap (graphic, image);
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, 0);
+      break;
+
+    case XK_F2:
+      image[0].image = &image[0].channel[1];
+      SetColorScale (graphic, image);
+      Remap (graphic, image);
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, 0);
+      break;
+
+    case XK_F3:
+      image[0].image = &image[0].channel[2];
+      SetColorScale (graphic, image);
+      Remap (graphic, image);
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, 0);
+      break;
+
+    case XK_KP_Home:
+    case XK_Home:
+      image[0].picture.expand = 1;
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, 0);
+      break;
+    case XK_KP_End:
+    case XK_End:
+      image[0].picture.expand = 1;
+      Reorient (graphic, image, 0.5*image[0].image[0].matrix.Naxis[0], 0.5*image[0].image[0].matrix.Naxis[1], 0);
+      break;
+    case XK_KP_Enter:
+    case XK_KP_Begin:
+    case XK_Return:
+      Screen_to_Image (&X, &Y, event[0].x + 0.5, event[0].y + 0.5, &image[0].picture);
+      Reorient (graphic, image, X, Y, 0);
+      break;
+    case XK_Prior:
+    case XK_KP_Prior:
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, +1);
+      break;
+    case XK_Next:
+    case XK_KP_Next:
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, -1);
+      break;
+    case XK_Up:
+    case XK_KP_Up:
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y + offset, 0);
+      break;
+    case XK_Down:
+    case XK_KP_Down:
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y - offset, 0);
+      break;
+    case XK_Left:
+    case XK_KP_Left:
+      Reorient (graphic, image, image[0].picture.X + offset, image[0].picture.Y, 0);
+      break;
+    case XK_Right:
+    case XK_KP_Right:
+      Reorient (graphic, image, image[0].picture.X - offset, image[0].picture.Y, 0);
+      break;
+
+    case XK_KP_Add:
+      image[0].image[0].zero += 0.1*image[0].image[0].range;
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, 0);
+      break;
+    case XK_KP_Subtract:
+      image[0].image[0].zero -= 0.1*image[0].image[0].range;
+      Reorient (graphic, image, image[0].picture.X, image[0].picture.Y, 0);
+      break;
+
+    case XK_Tab:
+      image[0].MovePointer = image[0].MovePointer ^ TRUE;
+      if (image[0].MovePointer) UpdatePointer (graphic, (XMotionEvent *)event);
+      break;
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/InterpretPresses.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/InterpretPresses.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/InterpretPresses.c	(revision 16632)
@@ -0,0 +1,118 @@
+# include "Ximage.h"
+
+int InterpretPresses (Graphic *graphic, XButtonEvent *event) {
+
+  int              sock, DX, DY, status, done, this_button;
+  char             name[16];
+  double           X, Y, Z, R, D;
+  float           *imdata;
+  Button          *button;
+  Section         *section;
+  KapaImageWidget *image;
+  KapaGraphWidget *graph;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+  graph   = section->graph;
+
+  // return graph coords by default, image if graph does not exist
+  // XXX allow user to choose graph or image coords
+  if (ACTIVE_CURSOR) {
+    sock = GetActiveSocket ();
+    if (sock == -1) goto skip_cursor;
+
+    sprintf (name, "Button%d", event[0].button);
+    if (graph) {
+      X = (event[0].x - graph[0].axis[0].fx)*(graph[0].axis[0].max - graph[0].axis[0].min)/graph[0].axis[0].dfx + graph[0].axis[0].min;
+      Y = (event[0].y - graph[0].axis[1].fy)*(graph[0].axis[1].max - graph[0].axis[1].min)/graph[0].axis[1].dfy + graph[0].axis[1].min;
+      XY_to_RD (&R, &D, X, Y, &graph[0].data.coords);
+    } 
+    if (image && !graph) {
+      if (event[0].x < image[0].picture.x) goto skip_cursor;
+      if (event[0].y < image[0].picture.y) goto skip_cursor;
+      if (event[0].x > image[0].picture.x + image[0].picture.dx) goto skip_cursor;
+      if (event[0].y > image[0].picture.y + image[0].picture.dy) goto skip_cursor;
+      Screen_to_Image (&X, &Y, event[0].x + 0.5, event[0].y + 0.5, &image[0].picture);
+
+      XY_to_RD (&R, &D, X, Y, &image[0].image[0].coords);
+
+      DX = image[0].image[0].matrix.Naxis[0];
+      DY = image[0].image[0].matrix.Naxis[1];
+
+      if (X < 0) goto off_image;
+      if (Y < 0) goto off_image;
+      if (X >= DX) goto off_image;
+      if (Y >= DY) goto off_image;
+      imdata = (float *) image[0].image[0].matrix.buffer;
+      Z      = imdata[DX*(int)(Y) + (int)(X)];
+    }
+  off_image:
+    KiiSendMessage (sock, "%12s %12.6f %12.6f %12.6f %12.6f %12.6f", name, X, Y, Z, R, D);
+  }
+
+skip_cursor:
+  status = TRUE;
+  this_button = event[0].button;
+
+  // XXX add graph buttons here
+  if (image == NULL) return (TRUE);
+  
+  if ((event[0].type == ButtonPress) && InPicture (event, &image[0].picture)) {
+    ReorientOnButton (graphic, image, event);
+  }
+
+  if ((event[0].type == ButtonPress) && InPicture (event, &image[0].cmapbar)) {
+    DragColorbar (graphic, image, event);
+  }
+
+  /* if on an exisiting button, Invert, wait for release, then go (or not) */
+  if ((button = CheckButtons (event, image)) != (Button *) NULL) {
+    InvertButton (graphic, button); 
+    done = FALSE;
+    while (!done) { /* wait for release of this button */
+      XNextEvent (graphic[0].display, (XEvent *) event);
+      if ((event[0].type == ButtonRelease) && (event[0].button == this_button)) {
+	done = TRUE;
+      }
+    }
+    DrawButton (graphic, button);
+    if (InButton (event, button)) {
+      switch (event[0].button) {
+      case 1:
+	status = button[0].function_1(graphic, image);
+	break;
+      case 2:
+	status = button[0].function_2(graphic, image);
+	break;
+      case 3:
+	status = button[0].function_3(graphic, image);
+	break;
+      }
+    } else {
+      return (status);
+    }
+  }
+  return (status);
+}
+
+void ReorientOnButton (Graphic *graphic, KapaImageWidget *image, XButtonEvent *mouse_event) {
+
+  double X, Y;
+
+  Screen_to_Image (&X, &Y, mouse_event[0].x + 0.5, mouse_event[0].y + 0.5, &image[0].picture);
+
+  switch (mouse_event[0].button) {
+    case 1:
+      Reorient (graphic, image, X, Y, 0);
+      break;
+    case 2:
+      Reorient (graphic, image, X, Y, -1);
+      break;
+    case 3:
+      Reorient (graphic, image, X, Y, +1);
+      break;
+    default:
+      break;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/InvertButton.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/InvertButton.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/InvertButton.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+void InvertButton (Graphic *graphic, Button *button) {
+
+  unsigned long fore, back;
+
+  fore =  graphic[0].fore;
+  back =  graphic[0].back;
+
+  graphic[0].fore = back;
+  graphic[0].back = fore;
+
+  DrawButton (graphic, button);
+  FlushDisplay (graphic[0].display);
+  
+  graphic[0].fore = fore;
+  graphic[0].back = back;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/JPEGit24.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/JPEGit24.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/JPEGit24.c	(revision 16632)
@@ -0,0 +1,216 @@
+# include "Ximage.h"
+# include "jpeglib.h"
+
+# define WHITE_R 255
+# define WHITE_G 255
+# define WHITE_B 255
+
+// XXX this currently writes out the jpeg for just the active image
+int JPEGit24 (int sock) {
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
+  JSAMPLE *image_buffer;	/* Points to data for current line */
+  JSAMPLE *line_buffer;	        /* Points to data for current line */
+  Section *section;
+  Graphic *graphic;
+  KapaImageWidget *image;
+
+  int ii, i, j;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  int quality;
+  int expand_in, expand_out;
+  double expand, Ix, Iy;
+  unsigned char *out_pix;
+  unsigned short *in_pix, *in_pix_ref;
+  unsigned char *pixel1, *pixel2, *pixel3;
+  char filename[1024];
+  FILE *f;
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (sock, "%s", filename);
+
+  graphic = GetGraphic();
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+
+  /***** JPEG init calls */
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_compress (&cinfo);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Kii: failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  jpeg_stdio_dest(&cinfo, f);
+  
+  quality = 75;
+  cinfo.image_width = image[0].picture.dx; 	/* image width and height, in pixels */
+  cinfo.image_height = image[0].picture.dy;
+# ifdef GREYSCALE
+  cinfo.input_components = 1;		        /* # of color components per pixel */
+  cinfo.in_color_space = JCS_GRAYSCALE; 	/* colorspace of input image */
+# else 
+  cinfo.input_components = 3;		        
+  cinfo.in_color_space = JCS_RGB; 	
+# endif
+  jpeg_set_defaults (&cinfo);
+  jpeg_set_quality (&cinfo, quality, TRUE       /* limit to baseline-JPEG values */);
+  jpeg_start_compress (&cinfo, TRUE);
+
+  ALLOCATE (pixel1, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixel2, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixel3, unsigned char, graphic[0].Npixels);
+
+  /** cmap[i].pixel must be defined even if X is not used **/
+  for (i = 0; i < graphic[0].Npixels; i++) { /* set up pixel array */
+    pixel1[i] = graphic[0].cmap[i].red >> 8;
+    pixel2[i] = graphic[0].cmap[i].green >> 8;
+    pixel3[i] = graphic[0].cmap[i].blue >> 8;
+  }
+
+  assert ((image[0].picture.expand >= 1) || (image[0].picture.expand <= -2));
+  expand = expand_in = expand_out = 1.0;
+  if (image[0].picture.expand > 0) {
+    expand = 1 / (1.0*image[0].picture.expand);
+    expand_out = image[0].picture.expand;
+    expand_in  = 1;
+  }
+  if (image[0].picture.expand < 0) {
+    expand = fabs((double)image[0].picture.expand);
+    expand_out = 1;
+    expand_in  = -image[0].picture.expand;
+  }
+
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  DX = image[0].image[0].matrix.Naxis[0];
+  DY = image[0].image[0].matrix.Naxis[1];
+
+  // x, y are the closest lit screen pixel to 0,0
+  Picture_Lower (&i_start, &j_start, &image[0].image[0].matrix, &image[0].picture);
+
+  // x, y are the closest lit screen pixel to dx, dy
+  Picture_Upper (&i_end, &j_end, &image[0].image[0].matrix, &image[0].picture);
+
+  // Ix,Iy are the first displayed image pixel
+  Picture_to_Image (&Ix, &Iy, i_start, j_start, &image[0].picture);
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  /* output line buffer */
+  ALLOCATE (image_buffer, JSAMPLE, 3*dx*dy);
+  ALLOCATE (line_buffer, JSAMPLE, 3*dx);
+
+  in_pix_ref  = &image[0].pixmap[DX*(int)MAX(Iy,0) + (int)MAX(Ix,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix+=3) {
+    out_pix[0] = WHITE_R;
+    out_pix[1] = WHITE_G;
+    out_pix[2] = WHITE_B;
+  }
+  for (j = 0; j < j_start; j++) {
+    memcpy (&image_buffer[j*3*dx], line_buffer, 3*dx);
+  }
+  
+  /*** fill in the image data region ***/
+  for (j = j_start; j < j_end; j+= expand_out, in_pix_ref += expand_in*DX) {
+    
+    /* create one output image line */
+    in_pix = in_pix_ref;
+    out_pix = line_buffer;
+
+    /**** fill in area to the left of the picture ****/
+    for (i = 0; i < i_start; i++, out_pix+=3) {
+      out_pix[0] = WHITE_R;
+      out_pix[1] = WHITE_G;
+      out_pix[2] = WHITE_B;
+    }
+    
+    /*** fill in the picture region ***/
+    for (i = i_start; i < i_end; i+=expand_out, in_pix+=expand_in) {
+      for (ii = 0; ii < expand_out; ii++, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix];
+	out_pix[1] = pixel2[*in_pix];
+	out_pix[2] = pixel3[*in_pix];
+      }
+    }
+    
+    /**** fill in area to the right of the picture ****/
+    for (i = i_end; i < dx; i++, out_pix+=3) {
+      out_pix[0] = WHITE_R;
+      out_pix[1] = WHITE_G;
+      out_pix[2] = WHITE_B;
+    }
+
+    /* write out the image line expand_out times */
+    for (i = 0; i < expand_out; i++) {
+      memcpy (&image_buffer[(j + i)*3*dx], line_buffer, 3*dx);
+    }
+  }
+
+  /**** fill in top area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix+=3) { 
+    out_pix[0] = WHITE_R;
+    out_pix[1] = WHITE_G;
+    out_pix[2] = WHITE_B;
+  }
+  for (j = j_end; j < dy; j++) {
+    memcpy (&image_buffer[j*3*dx], line_buffer, 3*dx);
+  }
+
+
+  /* I need to write the overlay objects on the jpeg image.
+     if i can write / overwrite data in jpeg buffer, then do it here,
+     otherwise i need to create a temporary image buffer, then write the 
+     scanlines to that buffer */
+
+  {
+    int Npalette;
+    png_color *palette;
+    bDrawColor white, color;
+    bDrawBuffer *buffer;
+
+    palette = KapaPNGPalette (&Npalette);
+
+    buffer = bDrawBufferCreate (dx, dy);
+    bDrawSetBuffer (buffer);
+    for (i = 0; i < NOVERLAYS; i++) {
+      if (image[i].overlay[i].active) bDrawOverlay (image, i);
+    }
+
+    white = KapaColorByName ("white");
+    for (j = 0; j < dy; j++) {
+      for (i = 0; i < dx; i++) {
+	color = buffer[0].pixels[j][i];
+	if (color == white) continue;
+	image_buffer[j*3*dx + 3*i + 0] = palette[color].red;
+	image_buffer[j*3*dx + 3*i + 1] = palette[color].green;
+	image_buffer[j*3*dx + 3*i + 2] = palette[color].blue;
+      }
+    }
+    bDrawBufferFree (buffer);
+  }
+
+  for (i = 0; i < dy; i++) {
+    row_pointer[0] = &image_buffer[i*3*dx];
+    (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
+  }
+
+  jpeg_finish_compress (&cinfo);
+  fclose (f);
+  jpeg_destroy_compress (&cinfo);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Layout.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Layout.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Layout.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+static char default_colormap[] = "grayscale";
+
+void InitLayout (int argc, char **argv) {
+
+  int N;
+  Section *section;
+  char *namedSocket = NULL;
+  
+  namedSocket = NULL;
+  if ((N = get_argument (argc, argv, "-socket"))) { 
+    remove_argument (N, &argc, argv);
+    namedSocket = argv[N];
+    remove_argument (N, &argc, argv);
+  }
+
+  // if we specify a named socket, wait until we are contacted
+  // otherwise, open an INET sock and check occasionally for requests
+  InitPipe (namedSocket);
+
+  ACTIVE_CURSOR = FALSE;
+
+  /* get the display colors */
+  if (USE_XWINDOW) {
+    MakeColormap (argc, argv);
+  } else {
+    char *colormap;
+    colormap = default_colormap;
+    if ((N = get_argument (argc, argv, "-cm"))) {
+      remove_argument (N, &argc, argv);
+      colormap = argv[N];
+    }
+    SetColormap (colormap);
+  }
+
+  /* move this out of here... */
+  if (argc != 1) {
+    fprintf (stderr, "USAGE: kapa\n");
+    exit (0);
+  }
+
+  InitRotFonts ();
+
+  /* create basic section, empty of image or graph */
+  section = AddSection ("default", 0.0, 0.0, 1.0, 1.0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadFont.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "Ximage.h"
+
+/************** LoadFont *************/
+void LoadFont (Graphic *graphic, int *argc, char **argv, char *default_name) {
+
+  int N;
+  char *name;
+
+  name = XGetDefault (graphic->display, argv[0], "Font");
+  if (name == NULL) name = default_name;
+
+  /* check for command-line options */
+  if ((N = get_argument (*argc, argv, "-font"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -font fontname\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = argv[N];
+    remove_argument(N, argc, argv);
+  }   
+  if ((N = get_argument (*argc, argv, "-fn"))) {
+    if (*argc <= N + 1) {
+      fprintf (stderr, "error: usage is -fn fontname\n");
+      exit (0);
+    }
+    remove_argument(N, argc, argv);
+    name = argv[N];
+    remove_argument(N, argc, argv);
+  } 
+
+  graphic->font = XLoadQueryFont (graphic->display, name);
+  if ((graphic->font == NULL) && (name != default_name)) {
+    fprintf (stderr, "Could not load requested font %s, trying %s\n", name, default_name);
+    graphic->font = XLoadQueryFont (graphic->display, default_name);
+  }
+  if (graphic->font == NULL) {
+    fprintf (stderr, "Could not load font %s, using %s\n", default_name, "fixed");
+    graphic->font = XLoadQueryFont (graphic->display, "fixed");
+  }
+  if (graphic->font == NULL) {
+    QuitX (graphic->display, "Error: could not load font");
+  }
+
+  XSetFont (graphic->display, graphic->gc, graphic->font[0].fid);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadFrame.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadFrame.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadFrame.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+
+int LoadFrame (int sock) {
+  
+  int i;
+  char Axis[16], Labels[16], Ticks[16];
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", 
+		  &graph[0].axis[0].min, &graph[0].axis[0].max, 
+		  &graph[0].axis[1].min, &graph[0].axis[1].max);
+
+  graph[0].axis[3].min = graph[0].axis[1].min;
+  graph[0].axis[3].max = graph[0].axis[1].max;
+  graph[0].axis[2].min = graph[0].axis[0].min;
+  graph[0].axis[2].max = graph[0].axis[0].max;
+  
+  KiiScanMessage (sock, "%s %s %s", Axis, Labels, Ticks);
+
+  for (i = 0; i < 4; i++) {
+    switch (Axis[i]) {
+    case '0':
+      graph[0].axis[i].isaxis = FALSE;
+      break;
+    case '1':
+      graph[0].axis[i].isaxis = TRUE;
+      break;
+    case '2':
+      graph[0].axis[i].isaxis = TRUE;
+      break;
+    }
+    switch (Ticks[i]) {
+    case '0':
+      graph[0].axis[i].areticks = FALSE;
+      break;
+    case '1':
+      graph[0].axis[i].areticks = TRUE;
+      break;
+    case '2':
+      graph[0].axis[i].areticks = 2;
+      break;
+    }
+    switch (Labels[i]) {
+    case '0':
+      graph[0].axis[i].islabel = FALSE;
+      break;
+    case '1':
+      graph[0].axis[i].islabel = TRUE;
+      break;
+    case '2':
+      graph[0].axis[i].islabel = (i < 2);
+      break;
+    }
+  }
+
+  SetSectionSizes (section);
+  if (USE_XWINDOW) DrawFrame (graph);
+  FlushDisplay ();
+
+  /* XXX why did I do this??? */
+# if (0)
+  status = TRUE;
+  if (status) {
+    for (i = 0; i < Nsection; i++) {
+      PositionPicture (&section[i]);
+    }
+    if (USE_XWINDOW) XClearWindow (graphic.display, graphic.window);
+    Refresh (1);
+  } else {
+    FlushDisplay ();
+  } 
+# endif
+
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadLabels.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "Ximage.h"
+
+int LoadLabels (int sock) {
+  
+  char *c, *label;
+  int mode, size, Nbytes;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  KiiScanMessage (sock, "%d", &mode);
+  label = KiiRecvData (sock);
+
+  bzero (graph[0].label[mode].text, LABEL_MAXLEN);
+
+  Nbytes = MIN (strlen(label), LABEL_MAXLEN - 1);
+  strncpy (graph[0].label[mode].text, label, Nbytes);
+  label[Nbytes] = 0;
+  
+  c = GetRotFont (&size);
+  graph[0].label[mode].size = size;
+  strcpy (graph[0].label[mode].font, c);
+  if (USE_XWINDOW) DrawLabels (graph);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadObject.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadObject.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadObject.c	(revision 16632)
@@ -0,0 +1,231 @@
+# include "Ximage.h"
+# include <errno.h>
+# define DEBUG 0
+
+int LoadObject (int sock) {
+  
+  int N;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  N = graph[0].Nobjects;
+  graph[0].Nobjects ++;
+  REALLOCATE (graph[0].objects, Gobjects, graph[0].Nobjects);
+  graph[0].objects[N].x = graph[0].objects[N].y = graph[0].objects[N].z = (float *) NULL;
+  graph[0].objects[N].dxm = graph[0].objects[N].dxp = (float *) NULL;
+  graph[0].objects[N].dym = graph[0].objects[N].dyp = (float *) NULL;
+  
+  KiiScanMessage (sock, "%d %d %d %d %d %d %d %lf %lf",
+		  &graph[0].objects[N].Npts, &graph[0].objects[N].style, 
+		  &graph[0].objects[N].ptype, &graph[0].objects[N].ltype, 
+		  &graph[0].objects[N].etype, &graph[0].objects[N].ebar, 
+		  &graph[0].objects[N].color, 
+		  &graph[0].objects[N].lweight, &graph[0].objects[N].size);
+  
+  if (DEBUG) fprintf (stderr, "%d %d %d %d %d %d %d %lf %lf\n",
+		      graph[0].objects[N].Npts, graph[0].objects[N].style, 
+		      graph[0].objects[N].ptype, graph[0].objects[N].ltype, 
+		      graph[0].objects[N].etype, graph[0].objects[N].ebar, 
+		      graph[0].objects[N].color, 
+		      graph[0].objects[N].lweight, graph[0].objects[N].size);
+  
+  /* force valid ranges */
+  if ((graph[0].objects[N].color > KapaColormapSize()) || (graph[0].objects[N].color < 0))
+    graph[0].objects[N].color = 0;
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf",
+		  &graph[0].objects[N].x0, &graph[0].objects[N].x1, 
+		  &graph[0].objects[N].y0, &graph[0].objects[N].y1);
+
+  // acknowledge receipt of the metadata
+  KiiSendCommand (sock, 4, "DONE"); 
+  
+  // XXX Currently, I require these in a special order.  The data includes a message defining the
+  // object type.  This could be made more flexible by using the information (though we still need
+  // to know how many items will be sent)
+
+  if (!LoadVectorData (sock, graph, N, "x")) {
+    FreeObjectData (&graph[0].objects[N]);
+    graph[0].Nobjects --;
+    REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+  }
+    
+  if (!LoadVectorData (sock, graph, N, "y")) {
+    FreeObjectData (&graph[0].objects[N]);
+    graph[0].Nobjects --;
+    REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+  }
+  if (graph[0].objects[N].size < 0.0) {
+    if (!LoadVectorData (sock, graph, N, "z")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+  }
+  if (graph[0].objects[N].etype & 0x01) {
+    if (!LoadVectorData (sock, graph, N, "dym")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+    if (!LoadVectorData (sock, graph, N, "dyp")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+  }
+  if (graph[0].objects[N].etype & 0x02) {
+    if (!LoadVectorData (sock, graph, N, "dxm")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+    if (!LoadVectorData (sock, graph, N, "dxp")) {
+      FreeObjectData (&graph[0].objects[N]);
+      graph[0].Nobjects --;
+      REALLOCATE (graph[0].objects, Gobjects, MAX (1, graph[0].Nobjects));
+    }
+  }
+
+  if (DEBUG) fprintf (stderr, "loaded %d objects, using object %d\n", graph[0].objects[N].Npts, N);
+
+  if (USE_XWINDOW) DrawObjectN (graph, &graph[0].objects[graph[0].Nobjects-1]);
+  FlushDisplay ();
+
+  return (TRUE);
+  
+}
+
+int LoadVectorData (int sock, KapaGraphWidget *graph, int N, char *type) {
+  
+  int i, Npts, Ninpts, status, Ntry;
+  int bytes_left;
+  char *byte, *buffer, type_send[16], tmp;
+  int Npts_send, Nbytes_send, swap_client, swap_host;
+
+  buffer = NULL;
+  Npts = graph[0].objects[N].Npts;
+
+  KiiWaitAnswer (sock, "PLOB");
+  KiiScanMessage (sock, "%s %d %d %d", type_send, &Npts_send, &Nbytes_send, &swap_client);
+  if (strcmp (type, type_send)) {
+    fprintf (stderr, "Kapa Communication error: unexpected data type %s vs %s\n", type_send, type);
+  }
+  if (Npts_send != Npts) {
+    fprintf (stderr, "Kapa Communication error: unexpected number of points %d vs %d\n", Npts_send, Npts);
+  }
+  if (Nbytes_send != Npts_send*sizeof(float)) {
+    fprintf (stderr, "Kapa Communication error: unexpected data size %d vs %ld\n", Nbytes_send, Npts_send*sizeof(float));
+  }
+
+  status = 1;
+  if (!strcmp (type, "x")) {
+    ALLOCATE (graph[0].objects[N].x, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].x;
+  }
+  if (!strcmp (type, "y")) {
+    ALLOCATE (graph[0].objects[N].y, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].y;
+  }
+  if (!strcmp (type, "z")) {
+    ALLOCATE (graph[0].objects[N].z, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].z;
+  }
+  if (!strcmp (type, "dxm")) {
+    ALLOCATE (graph[0].objects[N].dxm, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dxm;
+  }
+  if (!strcmp (type, "dxp")) {
+    ALLOCATE (graph[0].objects[N].dxp, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dxp;
+  }
+  if (!strcmp (type, "dym")) {
+    ALLOCATE (graph[0].objects[N].dym, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dym;
+  }
+  if (!strcmp (type, "dyp")) {
+    ALLOCATE (graph[0].objects[N].dyp, float, MAX (1, Npts));
+    buffer = (char *) graph[0].objects[N].dyp;
+  }
+
+  bytes_left = Npts*sizeof (float);
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+
+  // read the vector data as raw binary in client machine byte order (floats)
+  Ntry = 0;
+  if (DEBUG) fprintf (stderr, "starting vector load\n");
+  Ninpts = 0;
+  byte = buffer;
+  while (bytes_left > 0) {
+    status = read (sock, byte, bytes_left);
+    if (DEBUG) fprintf (stderr, "status: %d, %d\n", status, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      Ninpts += status;
+      bytes_left -= status;
+      byte = (char *)(byte + status);
+      Ntry = 0;
+      continue;
+    }
+    if (errno == EAGAIN) {
+      Ntry ++;
+      if (Ntry > 100) {
+	fprintf (stderr, "kapa communication error\n");
+	return (FALSE);
+      }
+      usleep (10000);
+      continue;
+    }
+    perror ("kapa load");
+  }
+
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  KiiSendCommand (sock, 4, "DONE"); 
+
+# ifdef BYTE_SWAP
+  swap_host = 1;
+# else 
+  swap_host = 0;
+# endif  
+
+  // if host and client have opposite swap parities, word swap the incoming data
+  // SWAP_WORD is strangely defined... it takes the number of the start byte in a
+  // buffer called 'byte'
+  if ((swap_host && !swap_client) || (!swap_host && swap_client)) {
+    byte = buffer;
+    for (i = 0; i < Nbytes_send; i+=4) {
+      SWAP_WORD (i);
+    }
+  }
+
+  if (Ninpts != Npts*sizeof(float)) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", Ninpts, (unsigned int)(Npts*sizeof(float)));
+    return (FALSE);
+  }
+  if (DEBUG) fprintf (stderr, "done vector load\n");
+  return (TRUE);
+
+}
+
+void FreeObjectData (Gobjects *object) {
+
+  if (object[0].x != (float *) NULL) free (object[0].x);
+  if (object[0].y != (float *) NULL) free (object[0].y);
+  if (object[0].z != (float *) NULL) free (object[0].z);
+
+  if (object[0].dxm != (float *) NULL) free (object[0].dxm);
+  if (object[0].dxp != (float *) NULL) free (object[0].dxp);
+  if (object[0].dym != (float *) NULL) free (object[0].dym);
+  if (object[0].dyp != (float *) NULL) free (object[0].dyp);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadOverlay.c	(revision 16632)
@@ -0,0 +1,128 @@
+# include "Ximage.h"
+
+int LoadOverlay (int sock) {
+  
+  int i, j, Ntotal, Nbytes, Nread, Nfound, Ntext, Nobjects, overnum;
+  int Noverlay, Ntextdata;
+  char *textdata, *buffer, *p, *q;
+  Section *section;
+  KapaImageWidget *image;
+  Graphic *graphic;
+  KiiOverlayBase *overlay;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiScanMessage (sock, "%d %d %d %d", &overnum, &Noverlay, &Ntext, &Ntextdata);
+
+  // XXX need to validate overnum 
+  if ((overnum < 0) || (overnum >= NOVERLAYS)) overnum = 0;
+
+  // read the overlay data as binary 
+  Ntotal = 0;
+  Nbytes = Noverlay*sizeof(KiiOverlayBase);
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  ALLOCATE (overlay, KiiOverlayBase, Noverlay);
+  buffer = (char *) overlay;
+  while (Nbytes > 0) { 
+    Nread = read (sock, &buffer[Ntotal], Nbytes);
+    // fprintf (stderr, "read: %d of %d remaining, %d so far, %d expected\n", Nread, Nbytes, Ntotal, Noverlay*sizeof(KiiOverlayBase));
+    if (Nread == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      free (overlay);
+      fcntl (sock, F_SETFL, !O_NONBLOCK);  
+      return (FALSE);
+    }
+    if (Nread != -1) { /* pipe has data */
+      Nbytes -= Nread;
+      Ntotal += Nread;
+    }
+  }
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  KiiSendCommand (sock,  4, "DONE");
+
+  // read the textdata as binary
+  Ntotal = 0;
+  Nbytes = Ntextdata;
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  ALLOCATE (textdata, char, Ntextdata);
+  while (Nbytes > 0) { 
+    Nread = read (sock, &textdata[Ntotal], Nbytes);
+    if (Nread == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      free (textdata);
+      free (overlay);
+      fcntl (sock, F_SETFL, !O_NONBLOCK);  
+      return (FALSE);
+    }
+    if (Nread != -1) { /* pipe has data */
+      Nbytes -= Nread;
+      Ntotal += Nread;
+    }
+  }
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+  KiiSendCommand (sock,  4, "DONE");
+
+  // add new overlay objects to existing data
+  Nobjects = image[0].overlay[overnum].Nobjects + Noverlay;
+  REALLOCATE (image[0].overlay[overnum].objects, KiiOverlay, Nobjects);
+
+  j = image[0].overlay[overnum].Nobjects;
+  for (i = 0; i < Noverlay; i++, j++) {
+    image[0].overlay[overnum].objects[j].x     = overlay[i].x;
+    image[0].overlay[overnum].objects[j].y     = overlay[i].y;
+    image[0].overlay[overnum].objects[j].dx    = overlay[i].dx;
+    image[0].overlay[overnum].objects[j].dy    = overlay[i].dy;
+    image[0].overlay[overnum].objects[j].angle = overlay[i].angle;
+    image[0].overlay[overnum].objects[j].type  = overlay[i].type;
+    image[0].overlay[overnum].objects[j].text  = NULL;
+  }
+
+  // parse the text data : text lines are separated by '\n', one per text entry
+  p = textdata;
+  Nfound = 0;
+  for (i = 0; i < Noverlay; i++) {
+    if (overlay[i].type != KII_OVERLAY_TEXT) continue;
+    if (Nfound >= Ntext) {
+      fprintf (stderr, "inconsistent number of text lines\n");
+      break;
+    }
+    if (! *p) {
+      fprintf (stderr, "inconsistent number of text lines\n");
+      break;
+    }
+    q = strchr (p, '\n');
+    if (q == NULL) {
+      fprintf (stderr, "inconsistent text line\n");
+      break;
+    }
+    j = image[0].overlay[overnum].Nobjects + i;
+    image[0].overlay[overnum].objects[j].text = strncreate (p, q-p);
+    p = q + 1;
+    Nfound ++;
+  }
+  if (Nfound != Ntext) {
+    fprintf (stderr, "read %d text lines, expected %d\n", Nfound, Ntext);
+  }
+
+  free (textdata);
+  free (overlay);
+
+  image[0].overlay[overnum].Nobjects = Nobjects;
+  image[0].overlay[overnum].active = TRUE;
+
+  if (USE_XWINDOW) {
+    for (i = 0; i < NOVERLAYS; i++) {
+      if (image[0].overlay[i].active) {
+	PaintOverlay (graphic, image, i);
+      }
+    }
+    XFlush (graphic[0].display);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadPicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadPicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadPicture.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "Ximage.h"
+
+int LoadPicture (int sock) {
+
+  Header header;
+  char *buff;
+  int status, bytes_left;
+  Section *section;
+  KapaImageWidget *image;
+  Graphic *graphic;
+  double Xoffset, Yoffset, wx;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+  
+  KiiSendMessage (sock, "%d", graphic->Npixels);
+
+  // when we load a new picture, use the same orientation as the old picture
+  Xoffset = 0.0;
+  Yoffset = 0.0;
+  if (image[0].image[0].matrix.size) {
+    Xoffset = image[0].picture.X - 0.5*image[0].image[0].matrix.Naxis[0];
+    Yoffset = image[0].picture.Y - 0.5*image[0].image[0].matrix.Naxis[1];
+  }
+
+  gfits_init_header (&header);
+  header.Naxes = 2;
+  KiiScanMessage (sock, "%d %d %d %d %lf %lf", &header.Naxis[0], &header.Naxis[1]);
+  KiiScanMessage (sock, "%d %d %d %d %lf %lf", &header.bitpix, &header.unsign, &header.bzero, &header.bscale);
+  KiiScanMessage (sock, "%lf %lf %s %s",  &image[0].image[0].zero, &image[0].image[0].range, image[0].image[0].name, image[0].image[0].file);
+  KiiScanMessage (sock, "%lf %lf %d", &image[0].image[0].min,  &image[0].image[0].max, &header.size);
+  KiiScanMessage (sock, "%lf %f %f %f %f", &image[0].image[0].coords.crval1, &image[0].image[0].coords.crpix1, &image[0].image[0].coords.cdelt1, &image[0].image[0].coords.pc1_1, &image[0].image[0].coords.pc1_2);
+  KiiScanMessage (sock, "%lf %f %f %f %f", &image[0].image[0].coords.crval2, &image[0].image[0].coords.crpix2, &image[0].image[0].coords.cdelt2, &image[0].image[0].coords.pc2_1, &image[0].image[0].coords.pc2_2);
+  KiiScanMessage (sock, "%s", image[0].image[0].coords.ctype);
+
+  gfits_free_matrix (&image[0].image[0].matrix);
+  gfits_create_matrix (&header, &image[0].image[0].matrix);
+
+  // reference point for image is the center pixel
+  image[0].picture.X = 0.5*header.Naxis[0] + Xoffset;
+  image[0].picture.Y = 0.5*header.Naxis[1] + Yoffset;
+
+  // choose expand for wide to guarantee we fit:
+  wx = MAX ((header.Naxis[0] / (float) image[0].wide.dx), (header.Naxis[1] / (float) image[0].wide.dy));
+  if (wx > 1.0) {
+    image[0].wide.expand = -wx;
+  } else {
+    image[0].wide.expand = 1.0 / wx;
+  }    
+  image[0].wide.X = 0.5*header.Naxis[0];
+  image[0].wide.Y = 0.5*header.Naxis[1];
+
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+
+  status = 1;
+  buff = image[0].image[0].matrix.buffer;
+  bytes_left = header.size;
+  image[0].image[0].matrix.size = 0;
+  while (bytes_left > 0) {
+    status = read (sock, buff, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      image[0].image[0].matrix.size += status;
+      bytes_left -= status;
+      buff = (char *)(buff + status);
+    }
+  }
+
+  fcntl (sock, F_SETFL, !O_NONBLOCK);  
+
+  if (DEBUG) fprintf (stderr, "read %d bytes\n", image[0].image[0].matrix.size);
+  /* it it not obvious this condition should kill kii, but ... */
+  if (image[0].image[0].matrix.size != header.size) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", header.size, image[0].image[0].matrix.size);
+    return (FALSE);
+  }
+
+  if (!USE_XWINDOW) return (TRUE);
+
+  SetColorScale (graphic, image);
+  Remap (graphic, image);
+  CreateWide (graphic, image);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh ();
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadTextlines.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadTextlines.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadTextlines.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+
+int LoadTextlines (int sock) {
+  
+  char *string;
+  int N, size;
+  double tX, tY, tT, L;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+    if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+
+  graph[0].Ntextline = MAX (graph[0].Ntextline, 0);
+  N = graph[0].Ntextline;
+  graph[0].Ntextline++;
+  REALLOCATE (graph[0].textline, Label, graph[0].Ntextline);
+
+  KiiScanMessage (sock, "%lf %lf %lf", &tX, &tY, &tT);
+
+  L = graph[0].axis[0].dfx;
+  graph[0].textline[N].x = L * (tX - graph[0].axis[0].min) / (graph[0].axis[0].max - graph[0].axis[0].min) + graph[0].axis[0].fx;
+
+  L = graph[0].axis[1].dfy;
+  graph[0].textline[N].y = L * (tY - graph[0].axis[1].min) / (graph[0].axis[1].max - graph[0].axis[1].min) + graph[0].axis[1].fy;
+
+  graph[0].textline[N].angle = tT;
+
+  bzero (graph[0].textline[N].text, LABEL_MAXLEN);
+
+  string = KiiRecvData (sock);
+  strcpy (graph[0].textline[N].text, string);
+  free (string);
+  
+  string = GetRotFont (&size);
+  graph[0].textline[N].size = size;
+  strcpy (graph[0].textline[N].font, string);
+
+  if (USE_XWINDOW) DrawTextlines (graph);
+  
+  FlushDisplay ();
+  
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadTickmarks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadTickmarks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/LoadTickmarks.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+int LoadTickmarks (int sock) {
+  
+  char line[129], type[16];
+  double x, y, dx, dy;
+  int status, NOBJECTS, Nobjects, done;
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image   = section->image;
+
+  Nobjects = image[0].tickmarks.Nobjects;
+  NOBJECTS = Nobjects + 100;
+  REALLOCATE (image[0].tickmarks.objects, KiiOverlay, NOBJECTS);
+  
+  done = FALSE;
+  while (!done) {
+    status = read (sock, line, 128); 
+    line[128] = 0; 
+
+    if (!strncmp (line, "DONE", 4)) {
+      done = TRUE;
+      break;
+    }
+    
+    sscanf (line, "%s %lf %lf %lf %lf\n", type, &x, &y, &dx, &dy);
+    
+    if (strcmp (type, "TEXT") && strcmp (type, "LINE") && strcmp (type, "BOX") && strcmp (type, "CIRCLE")) {  /* skip */
+      fprintf (stderr, "don't know %s, skipping\n", type);
+      continue;
+    }
+    
+    strcpy (image[0].tickmarks.objects[Nobjects].type, type);
+    image[0].tickmarks.objects[Nobjects].x = x;
+    image[0].tickmarks.objects[Nobjects].y = y;
+    image[0].tickmarks.objects[Nobjects].dx = dx;
+    image[0].tickmarks.objects[Nobjects].dy = dy;
+    
+    if (!strcmp (type, "TEXT")) { /* dx = Nchar, dy = angle (not yet used) */
+      status = read (sock, line, 128); 
+      line[128] = 0; 
+      ALLOCATE (image[0].tickmarks.objects[Nobjects].text, char, (int) dx + 1);
+      strncpy (image[0].tickmarks.objects[Nobjects].text, line, (int) dx);
+      image[0].tickmarks.objects[Nobjects].text[(int)dx] = 0;
+    }      
+    
+    Nobjects++;
+    if (Nobjects >= NOBJECTS) {
+      NOBJECTS = Nobjects + 100;
+      REALLOCATE (image[0].tickmarks.objects, KiiOverlay, NOBJECTS);
+    }
+
+  }
+
+  REALLOCATE (image[0].tickmarks.objects, KiiOverlay, MAX(Nobjects, 1));
+  image[0].tickmarks.Nobjects = Nobjects;
+
+  if (USE_XWINDOW) Refresh ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeColormap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeColormap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeColormap.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "Ximage.h"
+
+static char default_cmap[] = "grayscale";
+
+void MakeColormap (int argc, char **argv) {
+
+  int i, N, status;
+  char *temp_name;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* hardwired colors - white, black -- for drawing text and overlay graphics */
+  temp_name = XGetDefault (graphic[0].display, argv[0], "ROverlay");
+  graphic[0].overlay_color[0] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "red"    : temp_name), graphic[0].colormap, graphic[0].fore);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "GOverlay");
+  graphic[0].overlay_color[1] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "green"  : temp_name), graphic[0].colormap, graphic[0].fore);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "BOverlay");
+  graphic[0].overlay_color[2] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "blue"   : temp_name), graphic[0].colormap, graphic[0].fore);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "YOverlay");
+  graphic[0].overlay_color[3] = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "yellow" : temp_name), graphic[0].colormap, graphic[0].fore);
+
+  for (i = 0; i < graphic[0].Npixels; i++) {
+    graphic[0].cmap[i].pixel = graphic[0].pixels[i];
+  }
+
+  /* decide on a color map */
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Colormap");
+  if ((N = get_argument (argc, argv, "-cm"))) {
+    if (N + 1 < argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -cm ColormapName\n");
+      exit (1);
+    }
+  }
+  if (temp_name == (char *) NULL) temp_name = default_cmap;
+
+  status = SetColormap (temp_name);
+  if (!status) {
+    fprintf (stderr, "invalid colormap, using default %s\n", default_cmap);
+    temp_name = default_cmap;
+    status = SetColormap (temp_name);
+    if (!status) {
+      fprintf (stderr, "problem with default colormap\n");
+      exit (1);
+    }
+  }
+}
+
+/* this routine is NOT independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeCursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeCursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeCursor.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** MakeCursor *************/
+void MakeCursor (Graphic *graphic, unsigned int cursor) {
+
+  graphic->cursor = XCreateFontCursor (graphic->display, (unsigned) cursor);
+
+  if (graphic->cursor != (Cursor) None) XDefineCursor (graphic->display, graphic->window, graphic->cursor);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeGC.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeGC.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/MakeGC.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "Ximage.h"
+
+/************** MakeGC *************/
+void MakeGC (Graphic *graphic) {
+
+  XGCValues gcvalues;
+
+  gcvalues.foreground = graphic->fore;
+  gcvalues.background = graphic->back;
+  graphic->gc = XCreateGC (graphic->display, graphic->window, 
+			     GCForeground | GCBackground, &gcvalues);
+  if (graphic->gc == 0)
+    QuitX (graphic->display, "Error in creating a Graphics Context");
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/MapWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/MapWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/MapWindow.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** MapWindow *************/
+void MapWindow (Graphic *graphic) {
+
+  XMapRaised (graphic->display, graphic->window);
+  XMapSubwindows (graphic->display, graphic->window);
+  FlushDisplay (graphic);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/NameWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/NameWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/NameWindow.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "Ximage.h"
+
+/************** NameWindow *************/
+void NameWindow (Graphic *graphic, char *Name) {
+
+  char       *name;
+  char       *class_name;
+  char       *class_type;
+  XClassHint *classhints;
+
+  name = strrchr (Name, '/');
+  if (name != NULL) 
+    name ++;
+  else 
+    name = Name;
+
+  class_type = class_name = name;
+  classhints = XAllocClassHint ();
+
+  if (classhints != (XClassHint *) NULL)  {
+    classhints[0].res_name = class_name;
+    classhints[0].res_class = class_type;
+    XSetClassHint (graphic->display, graphic->window, classhints);
+    XFree (classhints);
+  }
+  
+  XStoreName (graphic->display, graphic->window, name);
+  XSetIconName (graphic->display, graphic->window, name);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/OpenDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/OpenDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/OpenDisplay.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** OpenDisplay *************/
+Display *OpenDisplay (char *name, int *screen) {
+
+  Display *display;
+  
+  display = XOpenDisplay (name);
+  if (display == NULL) {
+    fprintf (stderr, "Error could not open X display to %s\n", XDisplayName (name));
+    exit (0);
+  }
+  *screen = DefaultScreen (display);
+  return (display);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PNGit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PNGit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PNGit.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "Ximage.h"
+
+int PNGit (int sock) {
+
+  FILE *f;
+  png_structp png_ptr;
+  png_infop info_ptr;
+  png_color *palette;
+  int Npalette;
+  char filename[1024];
+  int Nbytes, status;
+  bDrawBuffer *buffer;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", "Xgraph.png");
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, (png_voidp) NULL, (png_voidp) NULL, (png_voidp) NULL);
+  if (!png_ptr) {
+    fprintf (stderr, "can't get png structure\n");
+    fclose (f);
+    return (TRUE);
+  }
+
+  info_ptr = png_create_info_struct (png_ptr);
+  if (!info_ptr) {
+    fprintf (stderr, "can't get png info structure\n");
+    png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
+    fclose (f);
+    return (TRUE);
+  }
+
+  if (setjmp (png_ptr[0].jmpbuf)) {
+    fprintf (stderr, "can't get png return\n");
+    png_destroy_write_struct (&png_ptr, &info_ptr);
+    fclose (f);
+    return (TRUE);
+  }
+
+  png_init_io (png_ptr, f);
+
+  /* see docs for write-row-callback to provide progress info */
+
+  png_set_IHDR (png_ptr, info_ptr, graphic->dx, graphic->dy, 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); 
+
+  /* png_set_IHDR (png_ptr, info_ptr, graphic->dx, graphic->dy, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); */
+
+  palette = KapaPNGPalette (&Npalette);
+  png_set_PLTE (png_ptr, info_ptr, palette, Npalette); 
+ 
+  png_write_info (png_ptr, info_ptr);
+
+  buffer = bDrawIt ();
+
+  png_write_image (png_ptr, buffer[0].pixels);
+  png_write_end (png_ptr, info_ptr);
+  png_destroy_write_struct (&png_ptr, &info_ptr);
+  
+  bDrawBufferFree (buffer);
+  free (palette);
+  fclose (f);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PPMit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PPMit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PPMit.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "Ximage.h"
+
+int PPMit (int sock) {
+
+  FILE *f;
+  char *line, filename[1024];
+  int Nbytes, status, dx, dy, i, j, Npalette, color;
+  png_color *palette;
+  bDrawBuffer *buffer;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (sock, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (sock, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+  
+  palette = KapaPNGPalette (&Npalette);
+
+  dx = graphic->dx;
+  dy = graphic->dy;
+  
+  fprintf (f, "P6\n");
+  fprintf (f, "%d %d\n", dx, dy);
+  fprintf (f, "255\n");
+
+  buffer = bDrawIt ();
+
+  ALLOCATE (line, char, 3*dx);
+
+  for (i = 0; i < dy; i++) {
+    for (j = 0; j < dx; j++) {
+      color = buffer[0].pixels[i][j];
+      line[3*j + 0] = palette[color].red;
+      line[3*j + 1] = palette[color].green;
+      line[3*j + 2] = palette[color].blue;
+    }
+    fwrite (line, 3, dx, f);
+  }
+  fclose (f);
+  
+  bDrawBufferFree (buffer);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSFrame.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSFrame.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSFrame.c	(revision 16632)
@@ -0,0 +1,105 @@
+# include "Ximage.h"
+# define DrawLine(X1,Y1,DX,DY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, Y1, X1+DX, Y1+DY))
+
+int PSFrame (KapaGraphWidget *graph, FILE *f) {
+  
+  int i, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  /* each axis is drawn independently */
+  fontname = GetRotFont (&fontsize);
+  fprintf (f, "1 setlinewidth\n");
+  for (i = 0; i < 4; i++) {
+    fx = graph[0].axis[i].fx;
+    fy = graphic->dy - graph[0].axis[i].fy;
+    dfx = graph[0].axis[i].dfx;
+    dfy = -graph[0].axis[i].dfy;
+    P = hypot ((double)graph[0].axis[(i+1)%2].dfx, (double)graph[0].axis[(i+1)%2].dfy);
+
+    if (graph[0].axis[i].isaxis) { DrawLine (fx, fy, dfx, dfy); }
+    
+    if (graph[0].axis[i].areticks) {
+      if (isnan(graph[0].axis[i].min) || isinf(graph[0].axis[i].min)) continue;
+      if (isnan(graph[0].axis[i].max) || isinf(graph[0].axis[i].max)) continue;
+
+      range = graph[0].axis[i].max - graph[0].axis[i].min;
+      AxisTickScale (&graph[0].axis[i], &major, &minor);
+
+      first = minor*((int)(graph[0].axis[i].min/minor));
+      if ((range > 0) && (first < graph[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > graph[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= graph[0].axis[i].max)) || ((range < 0) && (next >= graph[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = graph[0].axis[i].islabel;
+	PSTick (f, fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void PSTick (FILE *f, double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  pos = size = 0;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = -1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  DrawLine (x, y, dx, dy);
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g", value);
+    PSRotText (f, (int)x, (int)y, string, pos, 0.0);
+  }
+}
+
+  /* 
+  dx = size*dfy*n;	
+  dy = size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  
+  dx = -size*dfy*n;	
+  dy = -size*dfx*n;
+  DrawLine (x, y, dx, dy);
+  */
+  
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSLabels.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "Ximage.h"
+  
+void PSLabels (KapaGraphWidget *graph, FILE *f) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (graph[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = graph[0].label[i].x;
+      y = graphic->dy - graph[0].label[i].y;
+      SetRotFont (graph[0].label[i].font, graph[0].label[i].size); 
+      PSRotText (f, x, y, graph[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSObjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSObjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSObjects.c	(revision 16632)
@@ -0,0 +1,600 @@
+# include "Ximage.h"
+
+# define DrawLine(X1,Y1,X2,Y2) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f L\n", X1, graphic->dy - Y1, X2, graphic->dy - Y2))
+# define DrawCircle(X1,Y1,R) (fprintf (f, " %6.2f %6.2f %6.2f C\n", (X1), (graphic->dy - Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f B\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
+# define FillRectangle(X,Y,dX,dY) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f F\n", (dX), (dY), (X-0.5*dX), (graphic->dy-Y-0.5*dY)))
+# define FillTriangle(X1,Y1,X2,Y2, X3, Y3) (fprintf (f, " %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f TF\n", (X1), (graphic->dy-Y1), (X2), (graphic->dy-Y2), (X3), (graphic->dy-Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+static Graphic *graphic;
+
+int PSObjects (KapaGraphWidget *graph, FILE *f) {
+  
+  int i;
+  double lweight;
+  static char dash[] = "5";
+  static char dot[] = "3";
+  
+  graphic = GetGraphic();
+
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    switch (graph[0].objects[i].ltype) {
+    case 0:
+      break;
+    case 1:
+      fprintf (f, "[%s] 0 setdash\n", dash);
+      break;
+    case 2:
+      fprintf (f, "[%s] 0 setdash\n", dot);
+      break;
+    default:
+      break;
+    }
+    
+    lweight = MAX (0, MIN (10, graph[0].objects[i].lweight));
+    fprintf (f, "%.1f setlinewidth\n", lweight);
+    fprintf (f, "%s setrgbcolor\n", KapaColorRGBString(graph[0].objects[i].color));
+
+    switch (graph[0].objects[i].style) {
+    case CONNECT: 
+      PSConnect (graph, &graph[0].objects[i], f);
+      break;
+    case HISTOGRAM:
+      PSHistogram (graph, &graph[0].objects[i], f);
+      break;
+    case POINTS:
+      PSPoints (graph, &graph[0].objects[i], f);
+      break;
+    }
+
+    if (graph[0].objects[i].etype & 0x01) {
+      PSYErrors (graph, &graph[0].objects[i], f);
+    }
+    if (graph[0].objects[i].etype & 0x02) {
+      PSXErrors (graph, &graph[0].objects[i], f);
+    }
+    fprintf (f, "[] 0 setdash\n");
+    fprintf (f, "0.00 0.00 0.00 setrgbcolor\n");
+  }
+  return (TRUE);
+}
+
+/*******/
+void PSConnect (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    ClipLinePS (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1, f);
+    /* DrawLine (sx0, sy0, sx1, sy1); */
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void ClipLinePS (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0, FILE *f) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+
+/*******/
+void PSHistogram (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/*******/
+void PSPoints (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+ 
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);  
+
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /* below here, code is identical with DrawObjects */
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic->dx + graphic->dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
+	    /*
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	    */
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy + 0.58*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx + d*z[i], sy + 0.58*d*z[i], sx,          sy - 1.15*d*z[i]);
+	    DrawLine (sx,          sy - 1.15*d*z[i], sx - d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } else {
+    d = object[0].size * 0.5 * (graphic->dx + graphic->dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d, sy);
+	    DrawLine (sx, sy - d, sx, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d, sy - d, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    /*
+	    DrawLine (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d);
+	    DrawLine (sx + d, sy + 0.58*d, sx,     sy - 1.15*d);
+	    DrawLine (sx,     sy - 1.15*d, sx - d, sy + 0.58*d);
+	    */
+	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d);
+	    DrawLine (sx + d, sy - 0.58*d, sx,     sy + 1.15*d);
+	    DrawLine (sx,     sy + 1.15*d, sx - d, sy - 0.58*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx,     sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/*******/
+void PSXErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
+   
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+
+    
+/*******/
+void PSYErrors (KapaGraphWidget *graph, Gobjects *object, FILE *f) {
+  
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+  
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSOverlay.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "Ximage.h"
+
+void PSOverlay (KapaImageWidget *image, int N, FILE *f, int extra) {
+
+  int i;
+  double X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax;
+  double expand, X0, Y0;
+ 
+  expand = 1.0;
+  if (image[0].picture.expand > 0) {
+    expand = 1 / (1.0*image[0].picture.expand);
+  }
+  if (image[0].picture.expand < 0) {
+    expand = fabs((double)image[0].picture.expand);
+  }
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, &image[0].picture);
+  X0 -= image[0].picture.x;
+  Y0 -= image[0].picture.y;
+
+  Xmin = 0;
+  Ymin = 0;
+  Xmax = image[0].picture.dx;
+  Ymax = image[0].picture.dy;
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    X  = (image[0].overlay[N].objects[i].x)/expand + X0;
+    Y =  Ymax - (image[0].overlay[N].objects[i].y)/expand - Y0;
+    dX = (image[0].overlay[N].objects[i].dx)/expand;
+    dY = (image[0].overlay[N].objects[i].dy)/expand;
+    
+    switch (image[0].overlay[N].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	    ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	  break;
+	}
+	fprintf (f, " %6.1f %6.1f %6.1f %6.1f L\n", X + extra, Y + extra, (X+dX + extra), (Y-dY + extra));
+	break;
+      case KII_OVERLAY_TEXT:
+	if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	    ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	  break;
+	}
+	fprintf (f, "(%s) %6.1f %6.1f T\n", image[0].overlay[N].objects[i].text, X + extra, Y + extra); 
+	break;
+      case KII_OVERLAY_BOX:
+	if (((X - 0.5*dX < Xmin) && (X + 0.5*dX < Xmin)) || ((X - 0.5*dX > Xmax) && (X + 0.5*dX > Xmax)) ||
+	    ((Y - 0.5*dY < Ymin) && (Y + 0.5*dY < Ymin)) || ((Y - 0.5*dY > Ymax) && (Y + 0.5*dY > Ymax))) {
+	  break;
+	}
+	fprintf (f, " %6.1f %6.1f %6.1f %6.1f B\n", (dX + 2*extra), (dY + 2*extra), (X - 0.5*dX - extra), (Y - 0.5*dY - extra));
+	break;
+      case KII_OVERLAY_CIRCLE:
+	if (((X - dX < Xmin) && (X + dX < Xmin)) || ((X - dX > Xmax) && (X + dX > Xmax)) ||
+	    ((Y - dY < Ymin) && (Y + dY < Ymin)) || ((Y - dY > Ymax) && (Y + dY > Ymax))) {
+	  break;
+	}
+	// XXX add in the rotated ellipse version (rotate in PS space)
+	fprintf (f, " %6.1f %6.1f %6.1f C\n", X, Y, fabs(dX + extra));
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSPixmap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSPixmap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSPixmap.c	(revision 16632)
@@ -0,0 +1,185 @@
+# include "Ximage.h"
+
+// XXX this stuff has been broken by the conversion to the pixmap stuff
+
+void PSPixmap8 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned char *buff;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)image[0].picture.data + image[0].picture.dx*(image[0].picture.dy - 1);
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+
+void PSPixmap16 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned short *buff;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned short *)image[0].picture.data + image[0].picture.dx*(image[0].picture.dy - 1);
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+
+void PSPixmap24 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, dx, dy, val, extra;
+  unsigned char *buff;
+  unsigned long color, byte;
+  double Nchar, Npix, start, slope, frac;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  dx = image[0].picture.dx;
+  dy = image[0].picture.dy;
+  extra = 4 - (dx * 3) % 4;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)&image[0].picture.data[(dy - 1)*(3*dx + extra)];
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < dy; i++) {
+    for (k = 0; k < dx; k++, buff+=3) {
+      if (*buff == back) {
+	val = Nchar;
+      } else {
+	color = 0;
+	byte = buff[2];
+	color = (byte << 16);
+	byte = buff[1];
+	color |= (byte << 8);
+	byte = buff[0];
+	color |= byte;
+	for (m = 0; (graphic[0].cmap[m].pixel != color) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*3*dx + extra;
+  }
+  return;
+}
+
+void PSPixmap32 (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned int *buff;
+  unsigned long back;
+
+  Nchar = 255.0;
+  Npix = graphic[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned int *)image[0].picture.data + image[0].picture.dx*(image[0].picture.dy - 1);
+  slope = image[0].image[0].slope;
+  start = image[0].image[0].start;
+  back  = graphic[0].back;
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+
+# if (0)
+// XXX needs work!
+void PSPixmap32_RGB (Graphic *graphic, KapaImageWidget *image, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned int *buff;
+  unsigned long back;
+  unsigned char 
+
+  ALLOCATE (pixelR, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixelG, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixelB, unsigned char, graphic[0].Npixels);
+
+  /** cmap[i].pixel must be defined even if X is not used **/
+  for (i = 0; i < graphic[0].Npixels; i++) { /* set up pixel array */
+    pixelR[i] = graphic[0].cmap[i].red >> 8;
+    pixelG[i] = graphic[0].cmap[i].green >> 8;
+    pixelB[i] = graphic[0].cmap[i].blue >> 8;
+  }
+
+  for (i = 0; i < image[0].picture.dy; i++) {
+    for (k = 0; k < image[0].picture.dx; k++, buff++) {
+      if (*buff == back) 
+	val = Nchar;
+      else {
+	for (m = 0; (graphic[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*image[0].picture.dx;
+  }
+  return;
+}
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSTextlines.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSTextlines.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSTextlines.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "Ximage.h"
+  
+void PSTextlines (KapaGraphWidget *graph, FILE *f) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < graph[0].Ntextline; i++) {
+    if (strcmp (graph[0].textline[i].text, "")) {
+      angle = graph[0].textline[i].angle;
+      x = graph[0].textline[i].x;
+      y = graphic->dy - graph[0].textline[i].y;
+      SetRotFont (graph[0].textline[i].font, graph[0].textline[i].size);
+      PSRotText (f, x, y, graph[0].textline[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+  /* pos values
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|   8   |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+  */
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSimage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSimage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSimage.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "Ximage.h"
+
+int PSimage (KapaImageWidget *image, FILE *f) {
+  
+  int i;
+  Graphic *graphic;
+
+  if (!USE_XWINDOW) {
+    fprintf (stderr, "PSimage not working yet for no X mode\n");
+    return (TRUE);
+  }
+
+  graphic = GetGraphic();
+
+  fprintf (f, " newpath 0 0 moveto %d 0 lineto %d %d lineto 0 %d lineto closepath clip\n\n", 
+	   image[0].picture.dx, image[0].picture.dx, image[0].picture.dy, image[0].picture.dy);
+  fprintf (f, "gsave %% encloses image\n");
+  fprintf (f, "%d %d 8\n", image[0].picture.dx, image[0].picture.dy);
+  fprintf (f, "[1 0 0 1 0 0]\n");
+  fprintf (f, "{currentfile %d string readhexstring pop} image\n\n", image[0].picture.dx);
+
+  /******** First we draw the picture itself ********/
+  /* in !USE_XWINDOW, we'll have to change this to use the JPEG function */
+  switch (graphic[0].Nbits) {
+  case 8:
+    PSPixmap8 (graphic, image, f);
+    break;
+  case 16:
+    PSPixmap16 (graphic, image, f);
+    break;
+  case 24:
+    PSPixmap24 (graphic, image, f);
+    break;
+  case 32:
+    PSPixmap32 (graphic, image, f);
+    break;
+  }
+
+  fprintf (f, "grestore %% end of image\n");
+  fprintf (f, "stroke\n");
+
+  // should we have a 'gsave / grestore' container here?
+  fprintf (f, "%% plot overlay objects\n");
+  fprintf (f, "1 setgray\n");
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (image[0].overlay[i].active) {
+      fprintf (f, "%% overlay %d\n", i);
+      PSOverlay (image, i, f, 0);
+    }
+  }
+  fprintf (f, "0 setgray\n");
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (image[0].overlay[i].active) {
+      fprintf (f, "%% overlay %d\n", i);
+      PSOverlay (image, i, f, 1);
+    }
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PSit.c	(revision 16632)
@@ -0,0 +1,107 @@
+# include "Ximage.h"
+# define XOFFSET 60
+# define YOFFSET 60
+
+static char *name = "$Name: not supported by cvs2svn $";
+static Graphic *graphic;
+
+int PScommand (int sock) {
+
+  int status, scaleMode, pageMode;
+  char filename[1024], pagename[1024];
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (sock, "%s %s %d %d", filename, pagename, &scaleMode, &pageMode);
+  status = PSit (filename, pagename, scaleMode, pageMode);
+  return (status);
+}
+
+int PSit (char *filename, char *pagename, int scaleMode, int pageMode) {
+
+  int i, Nsection;
+  double scale;
+  FILE *f;
+  char *version;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  if (pageMode == KAPA_PS_NEWPAGE) {
+    f = fopen (filename, "a+");
+  } else {
+    f = fopen (filename, "w");
+  }
+  if (f == NULL) {
+    fprintf (stderr, "can't open output file %s\n", filename);
+    return (TRUE);  /* true because otherwise it quits kapa! */
+  }
+
+  /* two scaling options: expand to fit page / keep absolute size */ 
+  if (scaleMode) {
+    scale = MIN (fabs(500.0 / graphic->dx), fabs (700.0 / graphic->dy));
+  } else {
+    scale = 72.0 / 96.0; /* ratio of screen pixels to points */
+  }
+
+  switch (pageMode) {
+    case KAPA_PS_NEWPLOT:
+      fprintf (f, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+      fprintf (f, "%%%%Title: %s\n", filename);
+      version = strip_version (name);
+      fprintf (f, "%%%%Creator: Kapa (%s)\n", version);
+      free (version);
+      fprintf (f, "%%%%BoundingBox: %d %d %.0f %.0f\n", 
+	       XOFFSET, YOFFSET, XOFFSET + scale*graphic->dx, YOFFSET + scale*graphic->dy);
+      fprintf (f, "%%%%Pages: 1\n");
+      fprintf (f, "%%%%DocumentFonts:\n");
+      fprintf (f, "%%%%EndComments\n");
+      fprintf (f, "%%%%EndProlog\n");
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_NEWPAGE:
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_RAWPAGE:
+      break;
+  } 
+  fprintf (f, "gsave %% encloses picture\n");
+  fprintf (f, "%% local abbreviations\n");
+  fprintf (f, "/Times-Roman findfont 14 scalefont setfont\n");
+  fprintf (f, "/T {moveto show stroke} def\n");
+  fprintf (f, "/B { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath stroke } def\n");
+  fprintf (f, "/F { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath fill stroke } def\n");
+  fprintf (f, "/C {0 360 arc stroke} def\n");
+  fprintf (f, "/L {newpath moveto lineto stroke} def\n\n");
+  fprintf (f, "/TF {newpath moveto lineto lineto fill stroke} def\n\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) {
+    fprintf (f, " %d %d translate\n", XOFFSET, YOFFSET);
+    fprintf (f, "  %f  %f scale\n", scale, scale);
+  }
+
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+    section = GetSectionByNumber (i);
+    if (section->graph) {
+      PSFrame (section->graph, f); 
+      PSObjects (section->graph, f);
+      PSLabels (section->graph, f);
+      PSTextlines (section->graph, f);
+    }
+    if (section->image) {
+      PSimage (section->image, f);
+    }
+  }
+  
+  fprintf (f, "grestore %% end of picture\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) fprintf (f, "showpage\n");
+
+  fclose (f);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PaintOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PaintOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PaintOverlay.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+
+void PaintOverlay (Graphic *graphic, KapaImageWidget *image, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int x, y, X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double t, expand, X0, Y0;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, image[0].overlay[N].color);
+  
+  expand = 1.0;
+  if (image[0].picture.expand > 0) {
+    expand = 1 / (1.0*image[0].picture.expand);
+  }
+  if (image[0].picture.expand < 0) {
+    expand = fabs((double)image[0].picture.expand);
+  }
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, &image[0].picture);
+
+  Xmin = image[0].picture.x;
+  Ymin = image[0].picture.y;
+  Xmax = image[0].picture.x + image[0].picture.dx;
+  Ymax = image[0].picture.y + image[0].picture.dy;
+  Xrange = image[0].picture.dx;
+  Yrange = image[0].picture.dy;
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    X  = image[0].overlay[N].objects[i].x/expand + X0;
+    Y =  image[0].overlay[N].objects[i].y/expand + Y0;
+    dX = image[0].overlay[N].objects[i].dx/expand;
+    dY = image[0].overlay[N].objects[i].dy/expand;
+    if ((X + dX < Xmin) || (X - dX > Xmax) ||
+	(Y + dY < Ymin) || (Y - dY > Ymax)) {
+      continue;
+    }
+
+    /* for a LINE, (x, y) is the start, (dx, dy) is the distance to end
+       for a CIRCLE (x, y) is the center, (dx, dy) is the radius 
+       for a BOX (x, y) is the center, (dx, dy) is the width */
+
+    switch (image[0].overlay[N].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	// the angle makes no sense for a line...
+	XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+	break;
+      case KII_OVERLAY_TEXT:
+	// XXX currently we ignore the rectangle angle
+	XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, image[0].overlay[N].objects[i].text, strlen(image[0].overlay[N].objects[i].text));
+	break;
+      case KII_OVERLAY_BOX:
+	dx = MAX (abs(dX),2) / 2;
+	dy = MAX (abs(dY),2) / 2;
+	// XXX currently we ignore the rectangle angle
+	XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy);
+	break;
+      case KII_OVERLAY_CIRCLE:
+	dx = MAX (abs(dX),2);
+	dy = MAX (abs(dY),2);
+	if (image[0].overlay[N].objects[i].angle == 0.0) {
+	  XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy, 0, 23040);
+	} else {
+	  // very stupid rotate ellipse drawing:
+	  double angle = image[0].overlay[N].objects[i].angle * RAD_DEG;
+	  double cs = cos(angle);
+	  double sn = sin(angle);
+	  // XXX dt should be based on the size of the ellipse...
+	  for (t = 0; t < 2*M_PI; t+=0.05) {
+	    x = X + dx*cos(t)*cs + dy*sin(t)*sn;
+	    y = Y - dx*cos(t)*sn + dy*sin(t)*cs;
+	    XDrawPoint (graphic[0].display, graphic[0].window, graphic[0].gc, x, y);
+	  }
+	}
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/PaintTickmarks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/PaintTickmarks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/PaintTickmarks.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "Ximage.h"
+
+void PaintTickmarks (Graphic *graphic, KapaImageWidget *image) {
+
+  int i;
+  int X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+
+  Xmin = image[0].picture.x;
+  Ymin = image[0].picture.y;
+  Xmax = image[0].picture.x + image[0].picture.dx;
+  Ymax = image[0].picture.y + image[0].picture.dy;
+  Xrange = image[0].picture.dx;
+  Yrange = image[0].picture.dy;
+
+  for (i = 0; i < image[0].tickmarks.Nobjects; i++) {
+    X  = image[0].tickmarks.objects[i].x * Xrange + Xmin;
+    Y  = image[0].tickmarks.objects[i].y * Yrange + Ymin;
+    dX = image[0].tickmarks.objects[i].dx * Xrange;
+    dY = image[0].tickmarks.objects[i].dy * Yrange;
+
+    switch (image[0].overlay[0].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+	break;
+      case KII_OVERLAY_TEXT:
+	if (image[0].tickmarks.objects[i].dy == 0) {
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+	    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-11, 6*strlen(image[0].tickmarks.objects[i].text), 11); 
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+	    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, image[0].tickmarks.objects[i].text, strlen(image[0].tickmarks.objects[i].text));
+	}
+	if (image[0].tickmarks.objects[i].dy == 90) {
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+	    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-6*strlen(image[0].tickmarks.objects[i].text), 11, 6*strlen(image[0].tickmarks.objects[i].text)); 
+	    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+	    /* XDrawRotString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, image[0].tickmarks.objects[i].text, strlen(image[0].tickmarks.objects[i].text)); */
+	}
+	break;
+      case KII_OVERLAY_BOX:
+	XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (int)(X - 0.5*dX), (int)(Y - 0.5*dY), abs(dX), abs(dY));
+	break;
+      case KII_OVERLAY_CIRCLE:
+	XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, X - dX, Y - dY, abs(2*dX), abs(2*dY), 0, 23040);
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/QuitX.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/QuitX.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/QuitX.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "Ximage.h"
+
+/************** QuitX *************/
+void QuitX (Display *display, char *error_message) {
+
+  fprintf (stderr, "Error: %s\n", error_message);
+  XCloseDisplay (display);
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Reconfig.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Reconfig.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Reconfig.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+
+// XXX merge this code with Resize
+int Reconfig (XEvent *event) {
+
+  int i, Nsection, NX, NY;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  // XXX keep this min limit (or modify for !USE_XWINDOW)?
+  NX = MAX(event[0].xconfigure.width, MIN_WIDTH); 
+  NY = MAX(event[0].xconfigure.height, MIN_HEIGHT); 
+
+  // if the new size is the same as the old size, do nothing.
+  if ((graphic->dx == NX) && (graphic->dy == NY)) return (TRUE);
+
+  // set the new window size
+  graphic->dx = NX; 
+  graphic->dy = NY; 
+
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      SetSectionSizes (section);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Refresh.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Refresh.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Refresh.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "Ximage.h"
+
+void Refresh () {
+
+  int i, Nsection;
+  Graphic *graphic;
+  Section *section;
+
+  if (!USE_XWINDOW) return;
+  // if (HAVE_BACKING) return;
+
+  graphic = GetGraphic();
+  
+  /* XClearWindow   (graphic.display, graphic.window); */
+  XSetForeground (graphic->display, graphic->gc, graphic->back);
+  XFillRectangle (graphic->display, graphic->window, graphic->gc, 0, 0, graphic->dx, graphic->dy);
+  XSetForeground (graphic->display, graphic->gc, graphic->fore);
+  
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      DrawImage (section->image);
+      DrawGraph (section->graph);
+  }
+
+  FlushDisplay ();
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+void Remap (Graphic *graphic, KapaImageWidget *image) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    Remap8  (graphic, image, &image->picture, &image->image->matrix);
+    break;
+  case 16:
+    Remap16 (graphic, image, &image->picture, &image->image->matrix);
+    break;
+  case 24:
+    Remap24 (graphic, image, &image->picture, &image->image->matrix);
+    break;
+  case 32:
+    Remap32 (graphic, image, &image->picture, &image->image->matrix);
+    break;
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap16.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap16.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap16.c	(revision 16632)
@@ -0,0 +1,136 @@
+# include "Ximage.h"
+
+# define MY_SWAP_BYTE(W) { \
+  char tmp, *X; \
+  X = (char *) &W; \
+  tmp = X[0]; X[0] = X[1]; X[1] = tmp; }
+
+void Remap16 (Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;
+  int dx, dy, DX, DY;
+  double expand, Ix, Iy;
+  int expand_in, expand_out;
+  unsigned short *out_pix, *out_pix2, *data;
+  unsigned short *in_pix, *in_pix2;
+  unsigned short *pixel, pixvalue;
+  unsigned short back;
+  int swap_client, swap_server, swap_bytes;
+
+  ALLOCATE (pixel, unsigned short, graphic[0].Npixels);
+
+# ifdef BYTE_SWAP
+  swap_client = 1;
+# else 
+  swap_client = 0;
+# endif  
+
+  swap_server = ImageByteOrder (graphic[0].display);
+  swap_bytes = !(swap_client ^ swap_server);
+
+  // local array for pixel values (is this working??)
+  for (i = 0; i < graphic[0].Npixels; i++) { /* set up pixel array */
+    pixel[i] = 0xffff &  graphic[0].cmap[i].pixel;
+    if (swap_bytes) MY_SWAP_BYTE (pixel[i]);
+  }
+  back = 0xffff & graphic[0].back;
+  if (swap_bytes) MY_SWAP_BYTE (back);
+  // XXX not certain this is the correct solution...
+
+  // set up expansions
+  assert ((picture[0].expand >= 1) || (picture[0].expand <= -2));
+  expand = expand_in = expand_out = 1.0;
+  if (picture[0].expand > 0) {
+    expand = 1 / (1.0*picture[0].expand);
+    expand_out = picture[0].expand;
+    expand_in  = 1;
+  }
+  if (picture[0].expand < 0) {
+    expand = fabs((double)picture[0].expand);
+    expand_out = 1;
+    expand_in  = -picture[0].expand;
+  }
+
+  // define the image boundaries
+  dx = picture[0].dx;
+  dy = picture[0].dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  // x, y are the closest lit screen pixel to 0,0
+  Picture_Lower (&i_start, &j_start, matrix, picture);
+
+  // x, y are the closest lit screen pixel to dx, dy
+  Picture_Upper (&i_end, &j_end, matrix, picture);
+
+  // Ix,Iy are the first displayed image pixel
+  Picture_to_Image (&Ix, &Iy, i_start, j_start, picture);
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned short *) picture[0].data;
+  in_pix  = &image[0].pixmap[DX*(int)MAX(Iy,0) + (int)MAX(Ix,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    *out_pix = back;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue; 
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+  } 
+  
+  /**** fill in top area ****/
+  out_pix = &data[j_end*dx];
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix++) { 
+      *out_pix = back;
+    }
+  }
+
+  picture[0].pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					picture[0].data, picture[0].dx, picture[0].dy, 16, 0);
+
+  free (pixel);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap24.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap24.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap24.c	(revision 16632)
@@ -0,0 +1,149 @@
+# include "Ximage.h"
+
+void Remap24 (Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback, extra;
+  int dx, dy, DX, DY;
+  double expand, Ix, Iy;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned short *in_pix, *in_pix2;
+  unsigned char *pixel1, *pixel2, *pixel3;
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned char back1, back2, back3;
+
+  ALLOCATE (pixel1, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixel2, unsigned char, graphic[0].Npixels);
+  ALLOCATE (pixel3, unsigned char, graphic[0].Npixels);
+
+  // local arrays for pixel values
+  for (i = 0; i < graphic[0].Npixels; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff &  graphic[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (graphic[0].cmap[i].pixel >> 16);
+  }
+  back1 = 0x0000ff & (graphic[0].back >>  0);
+  back2 = 0x0000ff & (graphic[0].back >>  8);
+  back3 = 0x0000ff & (graphic[0].back >> 16);
+
+  // set up expansions
+  assert ((picture[0].expand >= 1) || (picture[0].expand <= -2));
+  expand = expand_in = expand_out = 1.0;
+  if (picture[0].expand == 0) /* set up expansions */
+    picture[0].expand = 1;
+  if (picture[0].expand > 0) {
+    expand = 1 / (1.0*picture[0].expand);
+    expand_out = picture[0].expand;
+    expand_in  = 1;
+  }
+  if (picture[0].expand < 0) {
+    expand = fabs((double)picture[0].expand);
+    expand_out = 1;
+    expand_in  = -picture[0].expand;
+  }
+
+  dx = picture[0].dx;
+  dy = picture[0].dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  // each row is padded to a 4-byte word
+  extra = 4 - (dx * 3) % 4;
+
+  // x, y are the closest lit screen pixel to 0,0
+  Picture_Lower (&i_start, &j_start, matrix, picture);
+
+  // x, y are the closest lit screen pixel to dx, dy
+  Picture_Upper (&i_end, &j_end, matrix, picture);
+
+  // Ix,Iy are the first displayed image pixel
+  Picture_to_Image (&Ix, &Iy, i_start, j_start, picture);
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+  
+  data = out_pix = (unsigned char *) picture[0].data;
+  in_pix  = &image[0].pixmap[DX*(int)MAX(Iy,0) + (int)MAX(Ix,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix += extra;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+	out_pix[2] = pixel3[*in_pix2];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	pixvalue3 = pixel3[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = back1;
+	out_pix2[1] = back2;
+	out_pix2[2] = back3;
+      }
+    }
+  } 
+  
+  /**** fill in top area ****/
+  out_pix = &data[j_end*(3*dx+extra)];
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = back1;
+      out_pix[1] = back2;
+      out_pix[2] = back3;
+    }
+    out_pix+=extra;
+  }
+
+  picture[0].pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					picture[0].data, picture[0].dx, picture[0].dy, 32, 0);
+
+  free (pixel1);
+  free (pixel2);
+  free (pixel3);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap32.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap32.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap32.c	(revision 16632)
@@ -0,0 +1,161 @@
+# include "Ximage.h"
+
+# define MY_SWAP_INT(A,B) { int tmp; tmp = A; A = B; B = tmp; }
+
+# define MY_SWAP_WORD(W) { \
+  char tmp, *X; \
+  X = (char *) &W; \
+  tmp = X[0]; X[0] = X[3]; X[3] = tmp; \
+  tmp = X[1]; X[1] = X[2]; X[2] = tmp; }
+
+void Remap32 (Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback, inDX, inDY;
+  int dx, dy, DX, DY;
+  double expand, Ix, Iy;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2;
+  unsigned short *in_pix, *in_pix2;
+  unsigned long *pixel, pixvalue;
+  unsigned long back;
+  int swap_client, swap_server, swap_bytes;
+
+  ALLOCATE (pixel, unsigned long, graphic[0].Npixels);
+
+# ifdef BYTE_SWAP
+  swap_client = 1;
+# else 
+  swap_client = 0;
+# endif  
+
+  swap_server = ImageByteOrder (graphic[0].display);
+  swap_bytes = !(swap_client ^ swap_server);
+
+  // local array for pixel values
+  for (i = 0; i < graphic[0].Npixels; i++) { 
+    pixel[i] = graphic[0].cmap[i].pixel;
+    if (swap_bytes) MY_SWAP_WORD(pixel[i]);
+  }
+  back = graphic[0].back;
+  if (swap_bytes) MY_SWAP_WORD(back);
+
+  // set up expansions
+  assert ((picture[0].expand >= 1) || (picture[0].expand <= -2));
+  expand = expand_in = expand_out = 1.0;
+  if (picture[0].expand > 0) {
+    expand = 1 / (1.0*picture[0].expand);
+    expand_out = picture[0].expand;
+    expand_in  = 1;
+  }
+  if (picture[0].expand < 0) {
+    expand = fabs((double)picture[0].expand);
+    expand_out = 1;
+    expand_in  = -picture[0].expand;
+  }
+
+  // define the image sizes
+  dx = picture[0].dx;
+  dy = picture[0].dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  // x, y are the closest lit screen pixel to 0,0
+  Picture_Lower (&i_start, &j_start, matrix, picture);
+
+  // x, y are the closest lit screen pixel to dx, dy
+  Picture_Upper (&i_end, &j_end, matrix, picture);
+
+  if (i_end < i_start) MY_SWAP_INT (i_start, i_end);
+  if (j_end < j_start) MY_SWAP_INT (j_start, j_end);
+
+  // Ix,Iy are the first displayed image pixel
+  Picture_to_Image (&Ix, &Iy, i_start, j_start, picture);
+  Ix = MIN (MAX (0, Ix), DX - 1);
+  Iy = MIN (MAX (0, Iy), DY - 1);
+  // XXX not completely consistent with the i_start, i_end range...
+
+  // we need to offset because i_start points to the bottom edge of Ix
+  // if (picture[0].flipx) Ix -= 1.0;
+  // if (picture[0].flipy) Iy -= 1.0;
+
+  inDX = picture[0].flipx ? -1 : +1;
+  inDY = picture[0].flipy ? -1 : +1;
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) picture[0].data;
+  in_pix  = &image[0].pixmap[DX*(int)MAX(Iy,0) + (int)MAX(Ix,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    *out_pix = back;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += inDY*expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2 += inDX*expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2 += inDX, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    // assert (in_pix2 - image[0].pixmap <= DX*DY);
+    // assert (in_pix2 - image[0].pixmap >= 0);
+    // assert (in_pix - image[0].pixmap <= DX*DY);
+    // assert (in_pix - image[0].pixmap >= 0);
+
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+    // assert (out_pix - (unsigned int *)picture[0].data <= dx*dy);
+    // assert (out_pix - (unsigned int *)picture[0].data >= 0);
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  // assert (out_pix - (unsigned int *)picture[0].data <= dx*dy);
+  // assert (out_pix - (unsigned int *)picture[0].data >= 0);
+
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)picture[0].data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+
+  picture[0].pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					picture[0].data, picture[0].dx, picture[0].dy, 32, 0);
+
+  free (pixel);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap8.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap8.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Remap8.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include "Ximage.h"
+
+void Remap8 (Graphic *graphic, KapaImageWidget *image, Picture *picture, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;
+  int dx, dy, DX, DY;
+  double expand, Ix, Iy;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2;
+  unsigned short *in_pix,  *in_pix2;
+  unsigned char *pixel, pixvalue;
+  unsigned char back;
+
+  ALLOCATE (pixel, unsigned char, graphic[0].Npixels);
+
+  // local array for pixel values
+  for (i = 0; i < graphic[0].Npixels; i++) {
+    pixel[i] = 0xff & graphic[0].cmap[i].pixel;
+  }
+  back = 0xff & graphic[0].back;
+
+  // set up expansions
+  assert ((picture[0].expand >= 1) || (picture[0].expand <= -2));
+  expand = expand_in = expand_out = 1.0;
+  if (picture[0].expand == 0) /* set up expansions */
+    picture[0].expand = 1;
+  if (picture[0].expand > 0) {
+    expand = 1 / (1.0*picture[0].expand);
+    expand_out = picture[0].expand;
+    expand_in  = 1;
+  }
+  if (picture[0].expand < 0) {
+    expand = fabs((double)picture[0].expand);
+    expand_out = 1;
+    expand_in  = -picture[0].expand;
+  }
+
+  // define the image boundaries
+  dx = picture[0].dx;
+  dy = picture[0].dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  // x, y are the closest lit screen pixel to 0,0
+  Picture_Lower (&i_start, &j_start, matrix, picture);
+
+  // x, y are the closest lit screen pixel to dx, dy
+  Picture_Upper (&i_end, &j_end, matrix, picture);
+
+  // Ix,Iy are the first displayed image pixel
+  Picture_to_Image (&Ix, &Iy, i_start, j_start, picture);
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned char *) picture[0].data;
+  in_pix  = &image[0].pixmap[DX*(int)MAX(Iy,0) + (int)MAX(Ix,0)];
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    *out_pix = back;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+    } else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = back;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned char *)picture[0].data < dx*dy); j++, out_pix++) { 
+    *out_pix = back;
+  }
+  picture[0].pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					picture[0].data, picture[0].dx, picture[0].dy, 8, 0);
+  free (pixel);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Reorient.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Reorient.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Reorient.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include "Ximage.h"
+
+void Reorient (Graphic *graphic, KapaImageWidget *image, double X, double Y, int mode) {
+
+  Picture *picture;
+
+  picture = &image[0].picture;
+
+  if (picture[0].expand == 0) picture[0].expand = 1;
+
+  if ((picture[0].X == X) && (picture[0].Y == Y) && (mode == 0)) {
+    Refresh ();
+    XFlush (graphic[0].display);
+    return;
+  }
+
+  switch (mode) {
+  case 0:
+    if ((picture[0].X != X) || (picture[0].Y != Y)) {
+      picture[0].X = X;
+      picture[0].Y = Y;
+    }
+    break;
+  case -1: 
+    picture[0].expand--;
+    if ((picture[0].expand == 0) || (picture[0].expand == -1)) picture[0].expand = -2;
+    picture[0].X = X;
+    picture[0].Y = Y;
+    break;
+  case +1:
+    picture[0].expand++;
+    if ((picture[0].expand == 0) || (picture[0].expand == -1)) picture[0].expand = 1;
+    picture[0].X = X;
+    picture[0].Y = Y;
+    break;
+  }
+
+  Remap (graphic, image);
+  Refresh ();
+ 
+  XFlush (graphic[0].display);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Rescale.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Rescale.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Rescale.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "Ximage.h"
+
+void Rescale (Graphic *graphic, KapaImageWidget *image, Matrix *matrix) {
+
+  int i, j, DX, DY, value;
+  float *iData;
+  unsigned short *oData;
+  float slope;
+  float start;
+  unsigned short MaxValue;
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  oData = graphic[0].pixmap;
+  iData = (float *) matrix[0].buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < DX; i++) {
+    for (j = 0; j < DY; j++, iData++, oData++) {
+      value = slope * iData - start;
+      if (value < 0) value = 0;
+      if (value > MaxValue) value = MaxValue;
+      *oData = value;
+    }
+  }
+}
+
+/** in order to call this function, graphic[0].pixmap must be allocated to match the
+ * current matrix (current channel) 
+ */
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Resize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Resize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Resize.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+
+// XXX Should there be a base command + KiiMessage command?
+int Resize (int sock) {
+ 
+  int i, Nsection;
+  unsigned int NX, NY;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  KiiScanMessage (sock, "%d %d", &NX, &NY);
+
+  // XXX keep this min limit (or modify for !USE_XWINDOW)?
+  NX = MAX(NX, MIN_WIDTH); 
+  NY = MAX(NY, MIN_HEIGHT); 
+
+  // if the new size is the same as the old size, do nothing.
+  if ((graphic->dx == NX) && (graphic->dy == NY)) return (TRUE);
+
+  // set the new window size
+  graphic->dx = NX; 
+  graphic->dy = NY; 
+
+  if (USE_XWINDOW) XResizeWindow (graphic->display, graphic->window, NX, NY);
+
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      SetSectionSizes (section);
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SaveOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SaveOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SaveOverlay.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+
+int SaveOverlay (int sock) {
+
+  int i, N;
+  char filename[256], *type;
+  FILE *f;
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+
+  KiiScanMessage (sock, "%*s %d %s", &N, filename);
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    type = KiiOverlayTypeByNumber (image[0].overlay[N].objects[i].type);
+    if (type == NULL) continue;
+    fprintf (f, "%s %lf %lf %lf %lf\n", 
+	     type,
+	     image[0].overlay[N].objects[i].x,
+	     image[0].overlay[N].objects[i].y,
+	     image[0].overlay[N].objects[i].dx,
+	     image[0].overlay[N].objects[i].dy);
+  }
+  fclose (f);
+  return (TRUE);
+}
+
+/* this is asymmetric with LoadOverlay.c.  In that case, the client reads the file and sends
+ * the overlay objects to kapa.  In this case, kapa writes the file directly... 
+ */
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/Sections.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/Sections.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/Sections.c	(revision 16632)
@@ -0,0 +1,218 @@
+# include "Ximage.h"
+
+static int  ActiveSection  = 0;
+static int       Nsections = 0;
+static Section **sections = NULL;
+
+Section *InitSection () {
+
+  Section *section;
+  ALLOCATE (section, Section, 1);
+
+  section[0].graph = NULL;
+  section[0].image = NULL;
+  section[0].x = 0;
+  section[0].y = 0;
+  section[0].dx = 0;
+  section[0].dy = 0;
+
+  section[0].name = NULL;
+  return (section);
+}
+
+void FreeSection (Section *section) {
+
+  if (section == NULL) return;
+  FreeGraph (section[0].graph);
+  FreeImage (section[0].image);
+  FREE (section[0].name);
+  free (section);
+}
+
+void FreeSections () {
+
+  int i;
+
+  for (i = 0; i < Nsections; i++) {
+    FreeSection (sections[i]);
+  }
+  free (sections);
+  Nsections = 0;
+  sections = NULL;
+}
+
+Section *AddSection (char *name, float x, float y, float dx, float dy) {
+
+  int N;
+
+  N = Nsections;
+
+  if (sections == NULL) {
+    Nsections = 1;
+    ALLOCATE (sections, Section *, Nsections);
+  } else {
+    Nsections ++;
+    REALLOCATE (sections, Section *, MAX (1, Nsections));
+  }
+  sections[N] = InitSection();
+  sections[N][0].name = strcreate (name);
+  sections[N][0].x = x;
+  sections[N][0].y = y;
+  sections[N][0].dx = dx;
+  sections[N][0].dy = dy;
+  ActiveSection = N;
+  return (sections[N]);
+}
+
+int DelSection (char *name) {
+
+  int i, j;
+
+  for (i = 0; i < Nsections; i++) {
+    if (strcmp (name, sections[i][0].name)) continue;
+    FreeSection (sections[i]);
+    for (j = i; j < Nsections - 1; j++) {
+      sections[j] = sections[j+1];
+    }
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+int GetSectionByName (char *name) {
+
+  int i;
+
+  for (i = 0; i < Nsections; i++) {
+    if (strcmp (name, sections[i][0].name)) continue;
+    return (i);
+  }
+  return (-1);
+}
+
+int GetNumberOfSections () {
+  return (Nsections);
+}
+
+Section *GetSectionByNumber (int N) {
+  if (N >= Nsections) return NULL;
+  if (N < 0) return NULL;
+  return sections[N];
+}
+
+Section *GetActiveSection () {
+  int N;
+  N = ActiveSection;
+  return (sections[N]);
+}
+
+int SetActiveSectionByNumber (int N) {
+  if (N >= Nsections) return FALSE;
+  if (N < 0) return FALSE;
+  ActiveSection = N;
+  return TRUE;
+}
+
+int ListSection (int sock) {
+  
+  int i, ThisSection;
+  char name[128];
+
+  KiiScanMessage (sock, "%s", name);
+
+  if (!strcmp (name, "*")) {
+    for (i = 0; i < Nsections; i++) {
+      fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	       sections[i][0].name, sections[i][0].x, sections[i][0].y, sections[i][0].dx, sections[i][0].dy);
+    }
+    return (TRUE);
+  }
+
+  ThisSection = -1;
+  for (i = 0; i < Nsections; i++) {
+    if (!strcmp (name, sections[i][0].name)) {
+      ThisSection = i;
+      break;
+    }
+  }
+  if (ThisSection == -1) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  fprintf (stderr, "%s: %6.3f %6.3f %6.3f %6.3f\n", 
+	   sections[ThisSection][0].name, 
+	   sections[ThisSection][0].x,  sections[ThisSection][0].y, 
+	   sections[ThisSection][0].dx, sections[ThisSection][0].dy);
+  return (TRUE);
+}
+
+void SetSectionSizes (Section *section) {
+
+    SetGraphSize (section);
+    SetImageSize (section);
+    return;
+}
+
+// return TRUE even for nonsense cases to avoid quitting kapa
+int MoveSection (int sock) {
+
+  int i, N;
+  char name[128];
+  char direction[16];
+  Section *tmpSection = NULL;
+
+  KiiScanMessage (sock, "%s %s", name, direction);
+  
+  N = GetSectionByName (name);
+  if (N < 0) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "up")) {
+      if (N < 0) return (TRUE);
+      if (N > Nsections - 2) return (TRUE);
+      tmpSection = sections[N];
+      sections[N] = sections[N+1];
+      sections[N+1] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "down")) {
+      if (N < 1) return (TRUE);
+      if (N > Nsections - 1) return (TRUE);
+      tmpSection = sections[N];
+      sections[N] = sections[N-1];
+      sections[N-1] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "top")) {
+      if (N < 0) return (TRUE);
+      if (N > Nsections - 2) return (TRUE);
+      tmpSection = sections[N];
+      for (i = N; i < Nsections - 1; i++) {
+	sections[i] = sections[i+1];
+      }
+      sections[i] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+
+  if (!strcasecmp (direction, "bottom")) {
+      if (N < 1) return (TRUE);
+      if (N > Nsections - 1) return (TRUE);
+      tmpSection = sections[N];
+      for (i = N; i >= 1; i--) {
+	sections[i] = sections[i-1];
+      }
+      sections[i] = tmpSection;
+      Refresh (1);
+      return (TRUE);
+  }
+  fprintf (stderr, "unknown direction %s for MoveSection\n", direction);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetChannel.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetChannel.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetChannel.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+int SetChannel (int sock) {
+  
+  int Nchannel;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiScanMessage (sock, "%d", &Nchannel);
+
+  if (Nchannel <  0) return (TRUE);
+  if (Nchannel >= NCHANNELS) return (TRUE);
+  
+  image[0].image = &image[0].channel[Nchannel];
+  SetColorScale (graphic, image);
+
+  if (!USE_XWINDOW) return (TRUE);
+
+  Remap (graphic, image);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh ();
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+}
+
+int SetColormapFromPipe (int sock) {
+  
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+  char colormap[256];
+  int status;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiScanMessage (sock, "%s", colormap);
+
+  status = SetColormap (colormap);
+  if (!status) fprintf (stderr, "unknown colormap %s\n", colormap);
+
+  SetColorScale (graphic, image);
+  if (!USE_XWINDOW) return (TRUE);
+
+  Remap (graphic, image);
+  Refresh ();
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetColorScale.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetColorScale.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetColorScale.c	(revision 16632)
@@ -0,0 +1,243 @@
+# include "Ximage.h"
+
+void SetColorScale (Graphic *graphic, KapaImageWidget *image) {
+
+  switch (graphic[0].ColorScaleMode) {
+    case KAPA_SCALE_1D:
+      SetColorScale1D (graphic, image);
+      break;
+    case KAPA_SCALE_3D_RUFF:
+      // fall-back on 1D colors (ie, if images are mis-matched)
+      if (!SetColorScale3D (graphic, image)) {
+	graphic[0].ColorScaleMode = KAPA_SCALE_1D;
+	SetColorScale1D (graphic, image);
+      }
+      break;
+    case KAPA_SCALE_3D_FULL:
+      // fall-back on 1D colors (ie, if images are mis-matched)
+      if (!SetColorScale3D_CC (graphic, image)) {
+	graphic[0].ColorScaleMode = KAPA_SCALE_1D;
+	SetColorScale1D (graphic, image);
+      }
+      break;
+    default:
+      fprintf (stderr, "programming error in kapa: unknown color scale mode\n");
+      return;
+  }
+  return;
+}
+
+void SetColorScale1D (Graphic *graphic, KapaImageWidget *image) {
+  int i, DX, DY, value, nPixels;
+  float *iData;
+  unsigned short *oData;
+  float slope;
+  float start;
+  unsigned short MaxValue;
+  Matrix *matrix;
+
+  // define the color transform parameters
+  MaxValue = graphic[0].Npixels - 1;
+  if (image[0].image[0].range != 0.0) {
+    slope = graphic[0].Npixels / image[0].image[0].range;
+    start = graphic[0].Npixels * image[0].image[0].zero / image[0].image[0].range;
+  } else {
+    slope = 1.0;
+    start = image[0].image[0].zero;
+  }
+
+  matrix = &image->image->matrix;
+
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  nPixels = DX*DY;
+  if (image[0].nPixels != nPixels) {
+    REALLOCATE (image[0].pixmap, unsigned short, nPixels);
+    image[0].nPixels = nPixels;
+  }
+
+  oData = image[0].pixmap;
+  iData = (float *) matrix[0].buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, iData++, oData++) {
+    value = *iData * slope - start;
+    if (value < 0) value = 0;
+    if (value > MaxValue) value = MaxValue;
+    *oData = value;
+  }
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+// XXX this uses a crude, uniform-spacing cube
+int SetColorScale3D (Graphic *graphic, KapaImageWidget *image) {
+
+  int i, DX, DY, nPixels, rValue, gValue, bValue;
+  float *rData, *bData, *gData;
+  unsigned short *oData;
+  float redSlope, blueSlope, greenSlope;
+  float redStart, blueStart, greenStart;
+
+  DX = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[1];
+
+  if (DX != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1]) return FALSE;
+  if (DX != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[1]) return FALSE;
+
+  // define the color transform parameters
+  unsigned short maxRed = graphic[0].nRed - 1;
+  unsigned short maxBlue = graphic[0].nBlue - 1;
+  unsigned short maxGreen = graphic[0].nGreen - 1;
+
+  // set start & slope for red (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_RED].range != 0.0) {
+    redSlope = graphic[0].nRed / image[0].channel[KAPA_CHANNEL_RED].range;
+    redStart = graphic[0].nRed * image[0].channel[KAPA_CHANNEL_RED].zero / image[0].channel[KAPA_CHANNEL_RED].range;
+  } else {
+    redSlope = 1.0;
+    redStart = image[0].channel[KAPA_CHANNEL_RED].zero;
+  }
+  // set start & slope for blue (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_BLUE].range != 0.0) {
+    blueSlope = graphic[0].nBlue / image[0].channel[KAPA_CHANNEL_BLUE].range;
+    blueStart = graphic[0].nBlue * image[0].channel[KAPA_CHANNEL_BLUE].zero / image[0].channel[KAPA_CHANNEL_BLUE].range;
+  } else {
+    blueSlope = 1.0;
+    blueStart = image[0].channel[KAPA_CHANNEL_BLUE].zero;
+  }
+  // set start & slope for green (channel 0)
+  if (image[0].channel[KAPA_CHANNEL_GREEN].range != 0.0) {
+    greenSlope = graphic[0].nGreen / image[0].channel[KAPA_CHANNEL_GREEN].range;
+    greenStart = graphic[0].nGreen * image[0].channel[KAPA_CHANNEL_GREEN].zero / image[0].channel[KAPA_CHANNEL_GREEN].range;
+  } else {
+    greenSlope = 1.0;
+    greenStart = image[0].channel[KAPA_CHANNEL_GREEN].zero;
+  }
+
+  nPixels = DX*DY;
+  if (image[0].nPixels != nPixels) {
+    REALLOCATE (image[0].pixmap, unsigned short, nPixels);
+    image[0].nPixels = nPixels;
+  }
+
+  oData = image[0].pixmap;
+  rData = (float *) image[0].channel[KAPA_CHANNEL_RED].matrix.buffer;
+  bData = (float *) image[0].channel[KAPA_CHANNEL_BLUE].matrix.buffer;
+  gData = (float *) image[0].channel[KAPA_CHANNEL_GREEN].matrix.buffer;
+
+  // convert pixel data values to pixel index values (0 - Npixel)
+  for (i = 0; i < nPixels; i++, rData++, bData++, gData++, oData++) {
+    rValue = *rData * redSlope   - redStart;
+    if (rValue < 0) rValue = 0;
+    if (rValue > maxRed) rValue = maxRed;
+
+    bValue = *bData * blueSlope  - blueStart;
+    if (bValue < 0) bValue = 0;
+    if (bValue > maxBlue) bValue = maxBlue;
+
+    gValue = *gData * greenSlope - greenStart;
+    if (gValue < 0) gValue = 0;
+    if (gValue > maxGreen) gValue = maxGreen;
+
+    *oData = gValue + bValue * (maxGreen + 1) + rValue * (maxGreen + 1) * (maxBlue + 1);
+  }
+  return TRUE;
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+int SetColorCubeHistogram () {
+
+  int i, DX, DY, Nvalues, NVALUES, Npixels, Nmin;
+  float *values;
+  CCNode *cube;
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) return (FALSE);
+  image = section->image;
+
+  DX = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[0];
+  DY = image[0].channel[KAPA_CHANNEL_RED].matrix.Naxis[1];
+  if (DX != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_GREEN].matrix.Naxis[1]) return FALSE;
+  if (DX != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[0]) return FALSE;
+  if (DY != image[0].channel[KAPA_CHANNEL_BLUE].matrix.Naxis[1]) return FALSE;
+
+  // create the top-level cube
+  if (graphic[0].cube != NULL) {
+    CCNodeFree (graphic[0].cube);
+  }
+  graphic[0].cube = CCNodeAlloc();
+
+  cube = graphic[0].cube;
+  cube->min[CC_X] = cube->min[CC_Y] = cube->min[CC_Z] = 0.0;
+  cube->max[CC_X] = cube->max[CC_Y] = cube->max[CC_Z] = 1.0;
+  cube->mid[CC_X] = cube->mid[CC_Y] = cube->mid[CC_Z] = 0.5;
+
+  // subdivide cube into first, uniform division (4x4x4)
+  CCSplitNodeIterate (cube, 0, 2);
+
+  // need to allocate at least 64 + NPASS*7*NSPLIT pixels (overestimate if 64 < NSPLIT)
+# define NPASS 5
+# define NSPLIT 128
+
+  for (i = 0; i < NPASS; i++) {
+    // generate histogram
+    ColorHistogram (image, cube);
+
+    // extract histogram values
+    values  = NULL;
+    Nvalues = 0;
+    NVALUES = 0;
+    CCNodeExtractCounts (cube, &values, &Nvalues, &NVALUES);
+  
+    // select top N cells
+    fsort (values, Nvalues);
+
+    // split nodes with more than value[n]
+    Nmin = MAX (0, Nvalues - NSPLIT);
+    CCNodeDivideLimit (cube, values[Nmin]);
+    free (values);
+
+    CCNodeInitCounts (cube, 0.0);
+  }
+
+  // generate histogram
+  ColorHistogram (image, cube);
+  
+  // convert histogram 3D values to cmap colors
+  Npixels = 0;
+  CCNodeSetColorMap (cube, graphic[0].cmap, graphic[0].Npixels, &Npixels);
+
+  // store the colors
+  if (USE_XWINDOW) {
+    if (graphic[0].visualclass) {
+      XStoreColors(graphic[0].display, graphic[0].colormap, graphic[0].cmap, Npixels);
+    } else {
+      for (i = 0; i < Npixels; i++) {
+	if (XAllocColor (graphic[0].display, graphic[0].colormap, &graphic[0].cmap[i]) == 0) {
+	  fprintf (stderr, "error on %d\n", i);
+	}
+      }
+    }
+  }
+  return TRUE;
+}
+
+// in 3D we use channels 0,1,2 to choose the pixel from the cube
+int SetColorScale3D_CC (Graphic *graphic, KapaImageWidget *image) {
+
+  CCNode *cube;
+
+  // create the top-level cube
+  cube = graphic[0].cube;
+  CCNodeSetColorPixels (image, cube);
+  return TRUE;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetColormap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetColormap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetColormap.c	(revision 16632)
@@ -0,0 +1,159 @@
+# include "Ximage.h"
+
+# define SETVALUE(VAR,VALUE,MINVAL,MAXVAL) { \
+  float tmp = (VALUE); \
+  if (tmp < MINVAL) { \
+    VAR = MINVAL; \
+  } else if (tmp > MAXVAL) { \
+    VAR = MAXVAL; \
+  } else { \
+    VAR = tmp; \
+  } }   
+
+int SetColormap (char *name) {
+
+  int i, red, blue, green;
+  float scale, blueRef, redRef, greenRef;
+  Graphic *graphic;
+
+  graphic = GetGraphic();
+
+  // the "fullcolor" colormap is uniquely defined for each image;
+  // defer to the 'SetColorScale' step
+  if (!strcasecmp (name, "fullcolor")) {
+    graphic[0].ColorScaleMode = KAPA_SCALE_3D_FULL;
+    if (SetColorCubeHistogram ()) return TRUE;
+  }
+
+  // very simple color model: evenly spaced cube 
+  if (!strcasecmp (name, "ruffcolor")) {
+      graphic[0].nRed  = pow (graphic[0].Npixels, 0.333);
+      graphic[0].nBlue = pow (graphic[0].Npixels, 0.333);
+      graphic[0].nGreen = graphic[0].Npixels / (graphic[0].nRed * graphic[0].nBlue);
+
+      // red,green,blue are values in range 0x0000 to 0xffff
+      float redScale = 0xffff / (graphic[0].nRed - 1);
+      float blueScale = 0xffff / (graphic[0].nBlue - 1);
+      float greenScale = 0xffff / (graphic[0].nGreen - 1);
+
+      i = 0;
+      for (red = 0; red < graphic[0].nRed; red++) {  
+	  for (blue = 0; blue < graphic[0].nBlue; blue++) {  
+	      for (green = 0; green < graphic[0].nGreen; green++, i++) {  
+		  SETVALUE (graphic[0].cmap[i].red,   red*redScale, 0, 0xffff);
+		  SETVALUE (graphic[0].cmap[i].blue,  blue*blueScale, 0, 0xffff);
+		  SETVALUE (graphic[0].cmap[i].green, green*greenScale, 0, 0xffff);
+		  graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+	      }
+	  }
+      }
+
+      // all other modes are 1D: set the flag:
+      graphic[0].ColorScaleMode = KAPA_SCALE_3D_RUFF;
+      goto store_colors;
+  }
+
+  // all other modes are 1D: set the flag:
+  graphic[0].ColorScaleMode = KAPA_SCALE_1D;
+
+  // red,green,blue are values in range 0x0000 to 0xffff
+  scale = 0xffff / (graphic[0].Npixels - 1);
+
+  /* greyscale */
+  if ((!strcasecmp (name, "grayscale")) || (!strcasecmp (name, "greyscale"))) {
+    for (i = 0; i < graphic[0].Npixels; i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   0xffff - i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].green, 0xffff - i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].blue,  0xffff - i*scale, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* -grayscale */
+  if ((!strcasecmp (name, "-grayscale")) || (!strcasecmp (name, "-greyscale"))) {
+    for (i = 0; i < graphic[0].Npixels; i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].green, i*scale, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].blue,  i*scale, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* heat */
+  if (!strcasecmp (name, "Heat")) {
+    greenRef = 0.25*graphic[0].Npixels*scale*2.0;
+    blueRef  = 0.50*graphic[0].Npixels*scale*2.0;
+    for (i = 0; i < (int)(0.25*graphic[0].Npixels); i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   2*i*scale, 0, 0xffff);
+      graphic[0].cmap[i].green = 0;
+      graphic[0].cmap[i].blue  = 0;
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = 0.25*graphic[0].Npixels; i < 0.50*graphic[0].Npixels; i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   2*i*scale,            0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].green, 2*i*scale - greenRef, 0, 0xffff);
+      graphic[0].cmap[i].blue = 0;
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*graphic[0].Npixels); i < (int)(0.75*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red = 0xffff;
+      SETVALUE (graphic[0].cmap[i].green, 2*i*scale - greenRef, 0, 0xffff);
+      SETVALUE (graphic[0].cmap[i].blue,  2*i*scale - blueRef,  0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.75*graphic[0].Npixels); i < graphic[0].Npixels; i++) {  
+      graphic[0].cmap[i].red   = 0xffff;
+      graphic[0].cmap[i].green = 0xffff;
+      SETVALUE (graphic[0].cmap[i].blue,  2*i*scale - blueRef,  0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* rainbow */
+  if (!strcasecmp (name, "Rainbow")) {
+    redRef   = 0.25*graphic[0].Npixels*scale*4.0;
+    greenRef = 0.50*graphic[0].Npixels*scale*4.0;
+    blueRef  = 0.50*graphic[0].Npixels*scale*4.0;
+    for (i = 0; i < (int)(0.25*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red   = 0;
+      graphic[0].cmap[i].green = 0;
+      SETVALUE (graphic[0].cmap[i].blue,  4*i*scale,           0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*graphic[0].Npixels); i < (int)(0.50*graphic[0].Npixels); i++) {  
+      SETVALUE (graphic[0].cmap[i].red,   4*i*scale - redRef,  0, 0xffff);
+      graphic[0].cmap[i].green = 0;
+      SETVALUE (graphic[0].cmap[i].blue,  blueRef - 4*i*scale, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*graphic[0].Npixels); i < (int)(0.75*graphic[0].Npixels); i++) {  
+      graphic[0].cmap[i].red  = 0xffff;
+      SETVALUE (graphic[0].cmap[i].green,  4*i*scale - greenRef, 0, 0xffff);
+      graphic[0].cmap[i].blue = 0;
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    blueRef  = 0.75*graphic[0].Npixels*scale*4.0;
+    for (i = (int)(0.75*graphic[0].Npixels); i < graphic[0].Npixels; i++) {  
+      graphic[0].cmap[i].red   = 0xffff;
+      graphic[0].cmap[i].green = 0xffff;
+      SETVALUE (graphic[0].cmap[i].blue,  4*i*scale - blueRef, 0, 0xffff);
+      graphic[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  return (FALSE);
+
+ store_colors:
+  if (!USE_XWINDOW) return (TRUE);
+  if (graphic[0].visualclass) {
+    XStoreColors(graphic[0].display, graphic[0].colormap, graphic[0].cmap, graphic[0].Npixels);
+  } else {
+    for (i = 0; i < graphic[0].Npixels; i++) {
+      if (XAllocColor (graphic[0].display, graphic[0].colormap, &graphic[0].cmap[i]) == 0) {
+	fprintf (stderr, "error on %d\n", i);
+      }
+    }
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetFont.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+int SetFont (int sock) {
+  
+  char name[64];
+  int size;
+  
+  KiiScanCommand (sock, 16, "%s", name);
+  KiiScanCommand (sock, 16, "%d", &size);
+
+  SetRotFont (name, size);
+  
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphData.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphData.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphData.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include "Ximage.h"
+
+int SetGraphData (int sock) {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Graphic *graphic;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  // get graph data from client 
+  KiiScanMessage (sock, "%d %d %d %d %d %d %lf %lf", 
+		  &graph[0].data.style, 
+		  &graph[0].data.ptype, 
+		  &graph[0].data.ltype, 
+		  &graph[0].data.etype, 
+		  &graph[0].data.ebar, 
+		  &graph[0].data.color, 
+		  &graph[0].data.lweight, 
+		  &graph[0].data.size);
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", 
+		  &graph[0].data.xmin, 
+		  &graph[0].data.xmax, 
+		  &graph[0].data.ymin, 
+		  &graph[0].data.ymax);
+
+  KiiScanMessage (sock, "%f %f %f %f", 
+		  &graph[0].data.coords.pc1_1, &graph[0].data.coords.pc2_2,
+		  &graph[0].data.coords.pc1_2, &graph[0].data.coords.pc2_1);
+
+  KiiScanMessage (sock, "%d %d %s", 
+		  &graph[0].data.flipeast, &graph[0].data.flipnorth,
+		  graph[0].data.coords.ctype);
+
+  KiiScanMessage (sock, "%lf %lf %f %f %f %f", 
+		  &graph[0].data.coords.crval1,
+		  &graph[0].data.coords.crval2,
+		  &graph[0].data.coords.crpix1,
+		  &graph[0].data.coords.crpix2,
+		  &graph[0].data.coords.cdelt1,
+		  &graph[0].data.coords.cdelt2);
+
+
+
+  xmin = graph[0].data.xmin;
+  xmax = graph[0].data.xmax;
+  ymin = graph[0].data.ymin;
+  ymax = graph[0].data.ymax;
+
+  // XXX there are now two things which track the graph limits
+  // make sure these are kept in sync (or drop one!)
+  graph[0].axis[2].min = graph[0].axis[0].min = xmin;
+  graph[0].axis[2].max = graph[0].axis[0].max = xmax;
+  graph[0].axis[3].min = graph[0].axis[1].min = ymin; 
+  graph[0].axis[3].max = graph[0].axis[1].max = ymax;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    graph[0].objects[i].x0 = xmin;
+    graph[0].objects[i].x1 = xmax;
+    graph[0].objects[i].y0 = ymin;
+    graph[0].objects[i].y1 = ymax;
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetGraphData (int sock) {
+  
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+
+  KiiSendMessage (sock, "%8d %d %d %d %d %d %f %f", 
+		  graph[0].data.style, 
+		  graph[0].data.ptype, graph[0].data.ltype, 
+		  graph[0].data.etype, graph[0].data.ebar, graph[0].data.color, 
+		  graph[0].data.lweight, graph[0].data.size);
+
+  KiiSendMessage (sock, "%g %g %g %g", 
+		  graph[0].data.xmin, graph[0].data.xmax, 
+		  graph[0].data.ymin, graph[0].data.ymax);
+
+  KiiSendMessage (sock, "%g %g %g %g", 
+		  graph[0].data.coords.pc1_1, graph[0].data.coords.pc2_2,
+		  graph[0].data.coords.pc1_2, graph[0].data.coords.pc2_1);
+
+  KiiSendMessage (sock, "%d %d %s", 
+		  graph[0].data.flipeast, graph[0].data.flipnorth,
+		  graph[0].data.coords.ctype);
+
+  KiiSendMessage (sock, "%g %g %g %g %g %g", 
+		  graph[0].data.coords.crval1,
+		  graph[0].data.coords.crval2,
+		  graph[0].data.coords.crpix1,
+		  graph[0].data.coords.crpix2,
+		  graph[0].data.coords.cdelt1,
+		  graph[0].data.coords.cdelt2);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphSize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphSize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphSize.c	(revision 16632)
@@ -0,0 +1,128 @@
+# include "Ximage.h"
+
+/* Set the dimensions of the specific graph based on the current window size.  The graph
+   is placed within the window at the fractional position defined by the section */
+
+void SetGraphSize (Section *section) {
+
+  int fontsize, bump, Nc;
+  int textpad, textdY, WdY; 
+  double PADx, PADy, Dx, Dy;
+  double PXm, PXp, PYm, PYp;
+  double X0, Y0, dX, dY;
+  char string[64], *fontname;
+  KapaGraphWidget *graph;
+  Graphic *graphic;
+
+  if (section == NULL) return;
+  graph = section->graph;
+  if (graph == NULL) return;
+
+  graphic = GetGraphic ();
+  fontname = GetRotFont (&fontsize);
+
+  PADx = MAX (graphic->dx / 20.0, fontsize);
+  PADy = MAX (graphic->dy / 20.0, fontsize);
+  Dx = graphic->dx - 2*PADx;
+  Dy = graphic->dy - 2*PADy;
+
+  /* each graph has a padding PXm, PXp, PYm, PYp */
+  PXm = (graph[0].axis[1].islabel) ? 4*fontsize : 0;
+  PXp = (graph[0].axis[3].islabel) ? 4*fontsize : 0;
+  PYm = (graph[0].axis[0].islabel) ? 4*fontsize : 0;
+  PYp = (graph[0].axis[2].islabel) ? 4*fontsize : 0;
+ 
+  /* basic size of the graph in Xwindow coordinates */
+  X0 = PADx + PXm + (Dx * section[0].x);
+  Y0 = PADy + PYm + (Dy * section[0].y);
+  dX = (Dx * section[0].dx) - PXp - PXm;
+  dY = (Dy * section[0].dy) - PYp - PYm;
+
+  // if we are tied to an image, make mods as needed
+  if (section->image) {
+    textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+    textdY = 6*textpad + 7*PAD1;
+    WdY = MAX (ZOOM_Y, textdY + 2*BUTTON_HEIGHT + PAD1);
+
+    switch (section->image->location) {
+      case 1:
+	Y0 = graphic[0].dy * section[0].y + 2*PAD1 + WdY + 2; // tied to image in Y
+	dY = graphic[0].dy * section[0].dy - 5*PAD1 - WdY - COLORPAD + 1;
+	break;
+      case 3:
+	dY = graphic[0].dy * section[0].dy - 5*PAD1 - WdY - COLORPAD - PADy - PYm;
+	break;
+      case 2:
+	X0 = graphic[0].dx * section[0].x  + 2*PAD1 + ZOOM_X;
+	dX = graphic[0].dx * section[0].dx - 3*PAD1 - ZOOM_X;
+	break;
+      case 4:
+	dX = graphic[0].dx * section[0].dx - 3*PAD1 - ZOOM_X - PADx - PXm;
+	break;
+    }
+  }
+
+  /* define locations of coordinate axes */
+  graph[0].axis[0].fx  = X0;
+  graph[0].axis[0].fy  = graphic->dy - Y0;
+  graph[0].axis[0].dfx = dX;
+  graph[0].axis[0].dfy = 0;
+  
+  graph[0].axis[1].fx  = X0;
+  graph[0].axis[1].fy  = graphic->dy - Y0;
+  graph[0].axis[1].dfx = 0;
+  graph[0].axis[1].dfy = -dY;
+
+  graph[0].axis[2].fx  = X0;
+  graph[0].axis[2].fy  = graphic->dy - Y0 - dY;
+  graph[0].axis[2].dfx = dX;
+  graph[0].axis[2].dfy = 0;
+
+  graph[0].axis[3].fx  = X0 + dX;
+  graph[0].axis[3].fy  = graphic->dy - Y0;
+  graph[0].axis[3].dfx = 0;
+  graph[0].axis[3].dfy = -dY;
+
+  PADx = 0.8*fontsize + 2;
+  PADy = 3.0*fontsize + 4;
+
+  /* define locations of axis labels */
+  graph[0].label[LABELX0].x = graph[0].axis[0].fx + 0.5*graph[0].axis[0].dfx;
+  bump = (graph[0].axis[0].islabel) ? PADy : PADx;
+  graph[0].label[LABELX0].y = graph[0].axis[0].fy + bump;
+
+  graph[0].label[LABELX1].x = graph[0].axis[2].fx + 0.5*graph[0].axis[2].dfx;
+  bump = (graph[0].axis[2].islabel) ? PADy : PADx;
+  graph[0].label[LABELX1].y = graph[0].axis[2].fy - bump;
+
+  /* check for the max size of the axis label */
+  sprintf (string, "%4g", graph[0].axis[1].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g", graph[0].axis[1].max);
+  Nc = MAX (Nc, strlen (string));
+
+  graph[0].label[LABELY0].y = graph[0].axis[1].fy + 0.5*graph[0].axis[1].dfy;
+  bump = (graph[0].axis[1].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  graph[0].label[LABELY0].x = graph[0].axis[1].fx - bump;
+
+  sprintf (string, "%4g", graph[0].axis[3].min);
+  Nc = strlen (string);
+  sprintf (string, "%4g", graph[0].axis[3].max);
+  Nc = MAX (Nc, strlen (string));
+
+  graph[0].label[LABELY1].y = graph[0].axis[3].fy + 0.5*graph[0].axis[3].dfy;
+  bump = (graph[0].axis[3].islabel) ? (0.8*Nc*fontsize + 1) : PADx;
+  graph[0].label[LABELY1].x = graph[0].axis[3].fx + bump;
+  
+  /* these are wrong and have to be adjusted to sit in the corners */
+
+  graph[0].label[LABELUL].x = graph[0].axis[2].fx - PADx;
+  graph[0].label[LABELUL].y = graph[0].axis[2].fy - PADx;
+  graph[0].label[LABELUR].x = graph[0].axis[2].fx + graph[0].axis[2].dfx + PADx;
+  graph[0].label[LABELUR].y = graph[0].axis[2].fy - PADx;
+  graph[0].label[LABELLL].x = graph[0].axis[0].fx - PADx;
+  graph[0].label[LABELLL].y = graph[0].axis[0].fy + PADx;
+  graph[0].label[LABELLR].x = graph[0].axis[0].fx + graph[0].axis[0].dfx + PADx;
+  graph[0].label[LABELLR].y = graph[0].axis[0].fy + PADx;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphStyle.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphStyle.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetGraphStyle.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "Ximage.h"
+
+int SetGraphStyle (int sock) {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Graphic *graphic;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  // get graph style from client 
+  KiiScanMessage (sock, "%d %d %d %d %d %d %lf %lf", 
+		  &graph[0].style.style, 
+		  &graph[0].style.ptype, 
+		  &graph[0].style.ltype, 
+		  &graph[0].style.etype, 
+		  &graph[0].style.ebar, 
+		  &graph[0].style.color, 
+		  &graph[0].style.lweight, 
+		  &graph[0].style.size);
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", 
+		  &graph[0].style.xmin, 
+		  &graph[0].style.xmax, 
+		  &graph[0].style.ymin, 
+		  &graph[0].style.ymax);
+
+  xmin = graph[0].style.xmin;
+  xmax = graph[0].style.xmax;
+  ymin = graph[0].style.ymin;
+  ymax = graph[0].style.ymax;
+
+  // XXX there are now two things which track the graph limits
+  // make sure these are kept in sync (or drop one!)
+  graph[0].axis[2].min = graph[0].axis[0].min = xmin;
+  graph[0].axis[2].max = graph[0].axis[0].max = xmax;
+  graph[0].axis[3].min = graph[0].axis[1].min = ymin; 
+  graph[0].axis[3].max = graph[0].axis[1].max = ymax;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    graph[0].objects[i].x0 = xmin;
+    graph[0].objects[i].x1 = xmax;
+    graph[0].objects[i].y0 = ymin;
+    graph[0].objects[i].y1 = ymax;
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetGraphStyle (int sock) {
+  
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+
+  KiiSendMessage (sock, "%8d %d %d %d %d %d %f %f", 
+		  graph[0].style.style, 
+		  graph[0].style.ptype, graph[0].style.ltype, 
+		  graph[0].style.etype, graph[0].style.ebar, graph[0].style.color, 
+		  graph[0].style.lweight, graph[0].style.size);
+  KiiSendMessage (sock, "%g %g %g %g", 
+		  graph[0].style.xmin, graph[0].style.xmax, 
+		  graph[0].style.ymin, graph[0].style.ymax);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetImageData.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetImageData.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetImageData.c	(revision 16632)
@@ -0,0 +1,134 @@
+# include "Ximage.h"
+
+int SetImageData (int sock) {
+  
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+  
+  // get image data from client 
+  KiiScanMessage (sock, "%lf %lf %s", 
+		  &image[0].image[0].zero, 
+		  &image[0].image[0].range, 
+		  image[0].image[0].name, 
+		  image[0].image[0].file);
+
+  // XXX when we go to 32bit, this should remap the image
+  // if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  // Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetImageData (int sock) {
+  
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiSendMessage (sock, "%g %g %s %s", 
+		  image[0].image[0].zero,
+		  image[0].image[0].range,
+		  image[0].image[0].name,
+		  image[0].image[0].file);
+
+  return (TRUE);
+}
+
+int SetImageCoords (int sock) {
+  
+  Graphic *graphic;
+  Section *section;
+  KapaImageWidget *image;
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+  
+  KiiScanMessage (sock, "%f %f %f %f", 
+		  &image[0].image[0].coords.pc1_1, &image[0].image[0].coords.pc2_2,
+		  &image[0].image[0].coords.pc1_2, &image[0].image[0].coords.pc2_1);
+
+  KiiScanMessage (sock, "%s", image[0].image[0].coords.ctype);
+
+  KiiScanMessage (sock, "%lf %lf %f %f %f %f", 
+		  &image[0].image[0].coords.crval1,
+		  &image[0].image[0].coords.crval2,
+		  &image[0].image[0].coords.crpix1,
+		  &image[0].image[0].coords.crpix2,
+		  &image[0].image[0].coords.cdelt1,
+		  &image[0].image[0].coords.cdelt2);
+
+  return (TRUE);  
+}
+
+int GetImageCoords (int sock) {
+  
+  Section *section;
+  KapaImageWidget *image;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  KiiSendMessage (sock, "%g %g %g %g", 
+		  image[0].image[0].coords.pc1_1, image[0].image[0].coords.pc2_2,
+		  image[0].image[0].coords.pc1_2, image[0].image[0].coords.pc2_1);
+
+  KiiSendMessage (sock, "%s", image[0].image[0].coords.ctype);
+
+  KiiSendMessage (sock, "%g %g %g %g %g %g", 
+		  image[0].image[0].coords.crval1,
+		  image[0].image[0].coords.crval2,
+		  image[0].image[0].coords.crpix1,
+		  image[0].image[0].coords.crpix2,
+		  image[0].image[0].coords.cdelt1,
+		  image[0].image[0].coords.cdelt2);
+
+  return (TRUE);
+}
+
+int GetImageRange (int sock) {
+  
+  Section *section;
+  KapaImageWidget *image;
+  double Xmin, Xmax, Ymin, Ymax;
+
+  section = GetActiveSection();
+  if (section->image == NULL) {
+    section->image = InitImageWidget ();
+    SetSectionSizes (section);
+  }
+  image = section->image;
+
+  Picture_to_Image (&Xmin, &Ymin, 0.0, 0.0, &image[0].picture);
+  Picture_to_Image (&Xmax, &Ymax, image[0].picture.dx, image[0].picture.dy, &image[0].picture);
+
+  KiiSendMessage (sock, "%g %g %g %g", Xmin, Xmax, Ymin, Ymax);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetImageSize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetImageSize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetImageSize.c	(revision 16632)
@@ -0,0 +1,355 @@
+# include "Ximage.h"
+
+/* Set the dimensions of the specific image based on the current window size.  The image
+   is placed within the window at the fractional position defined by the section */
+
+// XXX currently only set to fill the window; does not adjust for section range
+void SetImageSize (Section *section) {
+
+  int Xs, Ys, dX, dY;
+  int textpad, textdY, WdY; 
+  KapaImageWidget *image;
+  KapaGraphWidget *graph;
+  Graphic *graphic;
+
+  if (section == NULL) return;
+  image = section->image;
+  if (image == NULL) return;
+  graph = section->graph;
+
+  graphic = GetGraphic ();
+
+  /* the image is placed within the graphic window in region specified by section */
+  Xs = graphic[0].dx * section[0].x;
+  Ys = graphic[0].dy * (1 - section[0].y - section[0].dy);
+  dX = graphic[0].dx * section[0].dx;
+  dY = graphic[0].dy * section[0].dy;
+
+  switch (image[0].location) {
+    case 0:
+      if (section->graph) {
+	  image[0].picture.x  = graph[0].axis[0].fx;
+	  image[0].picture.y  = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	  image[0].picture.dx = MAX(graph[0].axis[0].dfx + 1, 1);
+	  image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	  image[0].picture.x  = Xs + PAD1;
+	  image[0].picture.y  = Ys + PAD1;
+	  image[0].picture.dx = dX - 2*PAD1; 
+	  image[0].picture.dy = dY - 2*PAD1;
+      }
+      if (USE_XWINDOW) CreatePicture (image, graphic);
+      Remap (graphic, image);
+      return;
+
+    case 1:
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      textdY = 6*textpad + 7*PAD1;
+      WdY = MAX (ZOOM_Y, textdY + 2*BUTTON_HEIGHT + PAD1);
+
+      if (section->graph) {
+	  image[0].picture.x = graph[0].axis[0].fx;
+	  image[0].picture.y = Ys + 2*PAD1 + COLORPAD;
+	  image[0].picture.dx = graph[0].axis[0].dfx;
+	  image[0].picture.dy = dY - 5*PAD1 - WdY - COLORPAD;
+      } else {
+	  image[0].picture.x  = Xs + PAD1;
+	  image[0].picture.y  = Ys + 2*PAD1 + COLORPAD;
+	  image[0].picture.dx = dX - 2*PAD1; 
+	  image[0].picture.dy = dY - 5*PAD1 - WdY - COLORPAD;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = Xs + PAD1;
+      image[0].zoom.y = image[0].picture.y + image[0].picture.dy + PAD1;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      image[0].text_x = image[0].zoom.x + image[0].zoom.dx + PAD1;
+      image[0].text_y = image[0].zoom.y;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].text_x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].wide.dx = ZOOM_X; 
+      image[0].wide.dy = ZOOM_Y;
+      image[0].wide.x = image[0].recenter_button.x + image[0].recenter_button.dx + PAD1;
+      image[0].wide.y = image[0].PS_button.y;
+      break;
+
+    case 3:
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      textdY = 6*textpad + 7*PAD1;
+      WdY = MAX (ZOOM_Y, textdY + 2*BUTTON_HEIGHT + PAD1);
+
+      if (section->graph) {
+	image[0].picture.x = graph[0].axis[0].fx;
+	image[0].picture.y = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	image[0].picture.dx = MAX(graph[0].axis[0].dfx, 1);
+	image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	image[0].picture.dx = dX - 2*PAD1; 
+	image[0].picture.dy = dY - 5*PAD1 - WdY - COLORPAD;
+	image[0].picture.x = Xs + PAD1;
+	image[0].picture.y = Ys + 4*PAD1 + COLORPAD + WdY;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = Xs + PAD1;
+      image[0].zoom.y = Ys + 2*PAD1 + COLORPAD;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      image[0].text_x = image[0].zoom.x + image[0].zoom.dx + PAD1;
+      image[0].text_y = image[0].zoom.y;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].text_x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].wide.dx = ZOOM_X; 
+      image[0].wide.dy = ZOOM_Y;
+      image[0].wide.x = image[0].PS_button.x;
+      image[0].wide.y = image[0].PS_button.y + BUTTON_HEIGHT + PAD1;
+      break;
+
+    case 2:
+
+      if (section->graph) {
+	image[0].picture.x = Xs + 2*PAD1 + ZOOM_X;
+	image[0].picture.y = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X; 
+	image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X; 
+	image[0].picture.dy = dY - 3*PAD1 - COLORPAD;
+	image[0].picture.x = Xs + 2*PAD1 + ZOOM_X;
+	image[0].picture.y = Ys + 2*PAD1 + COLORPAD;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = Xs + PAD1;
+      image[0].zoom.y = image[0].picture.y;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      image[0].text_x = image[0].zoom.x;
+      image[0].text_y = image[0].zoom.y + image[0].zoom.dy + PAD1;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].zoom.x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].wide.dx = ZOOM_X; 
+      image[0].wide.dy = ZOOM_Y;
+      image[0].wide.x = image[0].recenter_button.x + image[0].recenter_button.dx + PAD1;
+      image[0].wide.y = image[0].PS_button.y;
+      break;
+
+    case 4:
+
+      if (section->graph) {
+	image[0].picture.x = graph[0].axis[0].fx;
+	image[0].picture.y = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X - graph[0].axis[0].fx; 
+	image[0].picture.dy = MAX(fabs(graph[0].axis[1].dfy) - 1, 1);
+      } else {
+	image[0].picture.dx = dX - 3*PAD1 - ZOOM_X; 
+	image[0].picture.dy = dY - 3*PAD1 - COLORPAD;
+	image[0].picture.x = Xs + PAD1;
+	image[0].picture.y = Ys + 2*PAD1 + COLORPAD;
+      }
+
+      image[0].cmapbar.dx = dX - 2*PAD1; 
+      image[0].cmapbar.dy = COLORPAD;
+      image[0].cmapbar.x = Xs + PAD1;
+      image[0].cmapbar.y = Ys + PAD1;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].zoom.dx = ZOOM_X; 
+      image[0].zoom.dy = ZOOM_Y;
+      image[0].zoom.x = image[0].picture.x + image[0].picture.dx + PAD1;
+      image[0].zoom.y = image[0].picture.y;
+
+      /** everything below is tied in x-dir to the zoom box **/
+      textpad = USE_XWINDOW ? graphic[0].font[0].ascent : 10;
+      image[0].text_x = image[0].zoom.x;
+      image[0].text_y = image[0].zoom.y + image[0].zoom.dy + PAD1;
+      image[0].text_dx = ZOOM_X;
+      image[0].text_dy = 6*textpad + 7*PAD1;
+      image[0].text_dyo = 3*textpad + 4*PAD1;
+
+      image[0].overlay_button[0].x = image[0].text_x;
+      image[0].overlay_button[0].y = image[0].text_y + image[0].text_dy + PAD1;
+   
+      image[0].overlay_button[1].x = image[0].overlay_button[0].x + image[0].overlay_button[0].dx + PAD1;
+      image[0].overlay_button[1].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[2].x = image[0].overlay_button[1].x + image[0].overlay_button[1].dx + PAD1;
+      image[0].overlay_button[2].y = image[0].overlay_button[0].y;
+
+      image[0].overlay_button[3].x = image[0].overlay_button[2].x + image[0].overlay_button[2].dx + PAD1;
+      image[0].overlay_button[3].y = image[0].overlay_button[0].y;
+
+      image[0].hms_button.x = image[0].overlay_button[3].x + image[0].overlay_button[3].dx + PAD1;
+      image[0].hms_button.y = image[0].overlay_button[0].y;
+
+      image[0].PS_button.x = image[0].zoom.x;
+      image[0].PS_button.y = image[0].overlay_button[0].y + BUTTON_HEIGHT + PAD1;
+
+      /** everything below is tied to the PS_button in y-dir + the neighbor in x-dir **/
+      image[0].grey_button.x = image[0].PS_button.x + image[0].PS_button.dx + PAD1;
+      image[0].grey_button.y = image[0].PS_button.y;
+
+      image[0].rainbow_button.x = image[0].grey_button.x + image[0].grey_button.dx + PAD1;
+      image[0].rainbow_button.y = image[0].PS_button.y;
+
+      image[0].heat_button.x = image[0].rainbow_button.x + image[0].rainbow_button.dx + PAD1;
+      image[0].heat_button.y = image[0].PS_button.y;
+
+      image[0].recenter_button.x = image[0].heat_button.x + image[0].heat_button.dx + PAD1;
+      image[0].recenter_button.y = image[0].PS_button.y;
+
+      // XXX zoom should scale somewhat with the image? (with a min and a max)
+      // XXX actually, it is limited by the buttons and status region
+      image[0].wide.dx = ZOOM_X; 
+      image[0].wide.dy = ZOOM_Y;
+      image[0].wide.x = image[0].PS_button.x;
+      image[0].wide.y = image[0].PS_button.y + BUTTON_HEIGHT + PAD1;
+      break;
+
+    default:
+      abort ();
+      break;
+  }
+
+  if (USE_XWINDOW) {
+    CreatePicture (image, graphic);
+    CreateColorbar (image, graphic);
+    CreateZoom (graphic, image); 
+    CreateWide (graphic, image); 
+  }
+  Remap (graphic, image);
+
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetLimits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetLimits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetLimits.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "Ximage.h"
+
+int SetLimits (int sock) {
+  
+  int i;
+  double xmin, xmax, ymin, ymax;
+  Graphic *graphic;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  KiiScanMessage (sock, "%lf %lf %lf %lf", &xmin, &xmax, &ymin, &ymax);
+
+  graphic = GetGraphic();
+
+  section = GetActiveSection();
+  if (section->graph == NULL) {
+    section->graph = InitGraph ();
+    SetSectionSizes (section);
+  }
+  graph = section->graph;
+  
+  graph[0].axis[2].min = graph[0].axis[0].min = xmin;
+  graph[0].axis[2].max = graph[0].axis[0].max = xmax;
+  graph[0].axis[3].min = graph[0].axis[1].min = ymin; 
+  graph[0].axis[3].max = graph[0].axis[1].max = ymax;
+  
+  for (i = 0; i < graph[0].Nobjects; i++) {
+    graph[0].objects[i].x0 = xmin;
+    graph[0].objects[i].x1 = xmax;
+    graph[0].objects[i].y0 = ymin;
+    graph[0].objects[i].y1 = ymax;
+  }
+
+  if (USE_XWINDOW) XClearWindow (graphic->display, graphic->window);
+  Refresh (1);
+
+  return (TRUE);  
+}
+
+int GetLimits (int sock) {
+  
+  double dX, dY;
+  Section *section;
+  KapaGraphWidget *graph;
+
+  section = GetActiveSection();
+  graph = section->graph;
+
+  if (graph == NULL) {
+    dX = 0.0;
+    dY = 0.0;
+  } else {
+    dX = graph[0].axis[0].dfx;
+    dY = graph[0].axis[1].dfy;
+  }
+
+  KiiSendMessage (sock, "%8.1f %8.1f ", dX, dY);
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetNormalHints.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetNormalHints.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetNormalHints.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/************** SetNormalHints  *************/
+void SetNormalHints (Graphic *graphic) {
+
+  XSizeHints *sizehints;
+
+  sizehints = XAllocSizeHints ();
+  if (sizehints == NULL) return;
+
+  sizehints[0].x = graphic->x;
+  sizehints[0].y = graphic->x;
+  sizehints[0].width = graphic->dx;
+  sizehints[0].height = graphic->dy;
+  sizehints[0].min_width = MIN_WIDTH;
+  sizehints[0].min_height = MIN_HEIGHT;    
+
+  // XXX : can we drop the position flag 
+  // sizehints[0].flags = USPosition | USSize | PMinSize;
+  sizehints[0].flags = USSize | PMinSize;
+
+  sizehints[0].base_width = graphic->dx;
+  sizehints[0].base_height = graphic->dy;
+  sizehints[0].flags |= PBaseSize;
+    
+  XSetWMNormalHints (graphic->display, graphic->window, sizehints);
+  XFree (sizehints);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetSection.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetSection.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetSection.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+// set active section
+int SetSection (int sock) {
+  
+  int N;
+  char name[128];
+
+  KiiScanMessage (sock, "%s", name);
+  
+  N = GetSectionByName (name);
+  if (N < 0) {
+    fprintf (stderr, "section %s not found\n", name);
+    return (TRUE);
+  }
+
+  SetActiveSectionByNumber (N);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetToolbox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetToolbox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetToolbox.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+
+// set the position of the image toolbox
+void SetToolbox (int sock) {
+
+  int location;
+  Section *section;
+  Graphic *graphic;
+
+  KiiScanMessage (sock, "%d", &location);
+  if ((location < 0) || (location > 4)) {
+    fprintf (stderr, "invalid toolbox location %d\n", location);
+    return;
+  }
+
+  graphic = GetGraphic ();
+  section = GetActiveSection();
+  if (section->image == NULL) { 
+    section->image = InitImageWidget ();
+  }
+  section->image->location = location;
+  SetSectionSizes (section);
+
+  if (!USE_XWINDOW) return;
+
+  Remap (graphic, section->image);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh ();
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic->display);
+
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetUpGraphic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetUpGraphic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetUpGraphic.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "Ximage.h"
+# include "icons.h"
+
+static Graphic *graphic = NULL;
+
+/************** SetUpDisplay *************/
+void SetUpGraphic (int *argc, char **argv) {
+
+  Icon icon;
+  char *name;
+  int Ncolors;
+
+  ALLOCATE (graphic, Graphic, 1);
+  graphic->x  = 10;
+  graphic->y  = 10;
+  graphic->dx = 512;
+  graphic->dy = 512; 
+
+  if (!USE_XWINDOW) {
+    ALLOCATE (graphic[0].pixels, unsigned long, NPIXELS_STATIC);
+    ALLOCATE (graphic[0].cmap,   XColor,        NPIXELS_STATIC);
+    graphic[0].Npixels = NPIXELS_STATIC;
+    graphic[0].cube = NULL;
+    return;
+  }
+
+  name = CheckDisplayName (argc, argv);
+
+  graphic->display  = OpenDisplay     (name,    &graphic->screen);
+  graphic->colormap = DefaultColormap (graphic->display, graphic->screen);
+  graphic->depth    = DefaultDepth    (graphic->display, graphic->screen);
+  graphic->visual   = DefaultVisual   (graphic->display, graphic->screen);
+  if (name != NULL) free (name);
+
+  CheckVisual (graphic, argc, argv);
+  CheckColors (graphic, argc, argv);
+
+  icon.width = icon_width;
+  icon.height = icon_height;
+  icon.bits = icon_bits;
+
+  CheckGeometry (graphic, argc, argv);
+  TopWindow (graphic, &icon);
+  LoadFont (graphic, argc, argv, "fixed"); 
+
+  // FlushDisplay (graphic);
+  XSetWindowBackground (graphic->display, graphic->window, graphic->back);
+
+  SetNormalHints (graphic);
+  SetWMHints (graphic, &icon);
+
+  if (NAME_WINDOW == NULL) {
+    NameWindow (graphic, "Kapa");
+  } else {
+    ALLOCATE (name, char, strlen(NAME_WINDOW) + 10);
+    sprintf (name, "Kapa %s", NAME_WINDOW);
+    NameWindow (graphic, name);
+    free (name);
+  }
+
+  graphic->color = KapaX11colors (graphic->display, graphic->colormap, graphic->fore, &Ncolors);
+  if (MAP_WINDOW) MapWindow (graphic);
+  return;
+}
+
+Graphic *GetGraphic () {
+  return graphic;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetWMHints.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetWMHints.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/SetWMHints.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+/************** SetWMHints  *************/
+void SetWMHints (Graphic *graphic, Icon *icon) {
+
+  XWMHints *wmhints;
+
+  wmhints = XAllocWMHints ();
+  if (wmhints == NULL) return;
+
+  wmhints[0].initial_state = NormalState;
+  wmhints[0].input = True;
+  if (icon[0].pixmap != (Pixmap) None) {
+    wmhints[0].icon_pixmap = icon[0].pixmap;
+    wmhints[0].icon_mask = icon[0].pixmap;
+    wmhints[0].flags = StateHint | InputHint | IconPixmapHint | IconMaskHint;
+  } else {
+    wmhints[0].flags = StateHint | InputHint;
+  }
+    
+  XSetWMHints (graphic->display, graphic->window, wmhints);
+  XFree (wmhints);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/StatusBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/StatusBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/StatusBox.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+void StatusBox (Graphic *graphic, KapaImageWidget *image) {
+
+  double  x, y, z;
+
+  z = -1;
+
+  if (image[0].MovePointer) {
+    x = 0.5*image[0].image[0].matrix.Naxis[0];
+    y = 0.5*image[0].image[0].matrix.Naxis[1];
+    // z = -1;
+    image[0].zoom.X = x;
+    image[0].zoom.Y = y;
+    // image[0].z = z;
+  } else {
+    x = image[0].zoom.X;
+    y = image[0].zoom.Y;
+    // z = image[0].z;
+  }
+  
+  UpdateStatusBox (graphic, image, x, y, z, 1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/TopWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/TopWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/TopWindow.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "Ximage.h"
+
+/************** TopWindow *************/
+void TopWindow (Graphic *graphic, Icon *icon) {
+
+  Window rootwindow;
+
+  rootwindow = RootWindow (graphic->display, graphic->screen);
+
+  CreateWindow (graphic, rootwindow, BORDER_WIDTH, EVENT_MASK);
+  MakeGC (graphic);
+
+  icon[0].pixmap = XCreateBitmapFromData (graphic->display, graphic->window, (char *) icon[0].bits, icon[0].width, icon[0].height);
+
+  MakeCursor (graphic, DEFAULT_CURSOR);
+  XFreeCursor (graphic->display, graphic->cursor);
+  // FlushDisplay (graphic);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/UpdatePointer.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/UpdatePointer.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/UpdatePointer.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "Ximage.h"
+
+int UpdatePointer (Graphic *graphic, XMotionEvent *event) {
+
+  int textpad;
+  double  x, y, z;
+  float *data;
+  char line[100];
+  Section *section;
+  KapaImageWidget *image;
+
+  // XXX select the window element which contains the event
+  section = GetActiveSection();
+  image   = section->image;
+  if (image == NULL) return (TRUE);
+  if (!image[0].location) return (TRUE);
+
+  if (image[0].MovePointer && InPicture ((XButtonEvent *)event, &image[0].picture)) {
+
+    data = (float *) image[0].image[0].matrix.buffer;
+    Screen_to_Image (&x, &y, event[0].x + 0.5, event[0].y + 0.5, &image[0].picture);
+
+    z = -1;
+    if (x < 0) goto skip;
+    if (x >= image[0].image[0].matrix.Naxis[0]) goto skip;
+    if (y < 0) goto skip;
+    if (y >= image[0].image[0].matrix.Naxis[1]) goto skip;
+    z = data[(int)(y)*image[0].image[0].matrix.Naxis[0] + (int)(x)];
+
+  skip:
+    image[0].zoom.X = x;
+    image[0].zoom.Y = y;
+    
+    UpdateStatusBox (graphic, image, x, y, z, 0);
+    XFlush (graphic[0].display);
+      
+    CreateZoom (graphic, image);  
+    XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	       image[0].zoom.pix, 0, 0, 
+	       image[0].zoom.x, image[0].zoom.y, 
+	       image[0].zoom.dx, image[0].zoom.dy);
+    CrossHairs (graphic, &image[0].zoom);
+    XFlush (graphic[0].display);
+  }
+  
+  if (InPicture ((XButtonEvent *)event, &image[0].cmapbar)) {
+    z = image[0].image[0].zero  + image[0].image[0].range * (event[0].x - image[0].cmapbar.x) / image[0].cmapbar.dx;
+    textpad = graphic[0].font[0].ascent;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+                  image[0].text_x + 1, image[0].text_y + 1, ZOOM_X - 2, textpad + PAD1 + 1);
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+    bzero (line, 100);
+    sprintf (line, "%22.3f", z);
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+                 image[0].text_x + PAD1, image[0].text_y + textpad + PAD1, 
+		 line, strlen(line));
+    
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/UpdateStatusBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/UpdateStatusBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/UpdateStatusBox.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "Ximage.h"
+
+void UpdateStatusBox (Graphic *graphic, KapaImageWidget *image, double x, double y, double z, int mode) {
+
+  int textpad;
+  double ra, dec; 
+  char line[100];
+
+  XY_to_RD (&ra, &dec, x, y, &image[0].image[0].coords);
+
+  textpad = graphic[0].font[0].ascent;
+
+  if (mode) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    image[0].text_x, image[0].text_y, image[0].text_dx, image[0].text_dy);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+    XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    image[0].text_x, image[0].text_y, image[0].text_dx, image[0].text_dy);
+  
+    bzero (line, 100);
+    sprintf (line, "(%d x %d) @ %d                                         ", 
+	     image[0].picture.dx, image[0].picture.dy, image[0].picture.expand); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 image[0].text_x + PAD1, image[0].text_y + 4*textpad + 4*PAD1, line, 25);
+    
+    bzero (line, 100);
+    sprintf (line, "%-25s", image[0].image[0].file); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 image[0].text_x + PAD1, image[0].text_y + 5*textpad + 5*PAD1, line, strlen(line));
+    
+    bzero (line, 100);
+    sprintf (line, "(%s)                                          ", image[0].image[0].name); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 image[0].text_x + PAD1, image[0].text_y + 6*textpad + 6*PAD1, line, 25);
+    
+  } else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].back);
+    // XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].overlay_color[1]);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    image[0].text_x+1, image[0].text_y+1, image[0].text_dx-1, image[0].text_dyo-2);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].fore);
+  }
+  bzero (line, 100);
+  sprintf (line, "%22.3f", z);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       image[0].text_x + PAD1, image[0].text_y + textpad + PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  sprintf (line, "%10.1f %10.1f", x, y);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       image[0].text_x + PAD1, image[0].text_y + 2*textpad + 2*PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  if (image[0].DecimalDegrees) {
+    sprintf (line, "%10.6f %10.6f", ra, dec); 
+  } else {
+    hh_hms (line, ra, dec, ':');
+  }
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       image[0].text_x + PAD1, image[0].text_y + 3*textpad + 3*PAD1, line, strlen(line));
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/args.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+int args (int *argc, char **argv) {
+
+  int N;
+
+  MAP_WINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-nomap"))) {
+    remove_argument(N, argc, argv);
+    MAP_WINDOW = FALSE;
+  }
+
+  NAME_WINDOW = NULL;
+  if ((N = get_argument (*argc, argv, "-name"))) {
+    remove_argument(N, argc, argv);
+    NAME_WINDOW = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+  }
+
+  USE_XWINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-noX"))) {
+    remove_argument(N, argc, argv);
+    USE_XWINDOW = FALSE;
+  }
+
+  if ((N = get_argument (*argc, argv, "-debug"))) {
+    remove_argument(N, argc, argv);
+    DEBUG = TRUE;
+  } else {
+    DEBUG = FALSE;
+  }
+
+  FOREGROUND = FALSE;
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    remove_argument(N, argc, argv);
+    FOREGROUND = TRUE;
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawFrame.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawFrame.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawFrame.c	(revision 16632)
@@ -0,0 +1,92 @@
+# include "Ximage.h"
+
+int bDrawFrame (KapaGraphWidget *graph) {
+  
+  int i, P, IsLabel, fontsize;
+  double fx, fy, dfx, dfy, range, major, minor, first, next;
+  char *fontname;
+
+  /* each axis is drawn independently */
+  fontname = GetRotFont (&fontsize);
+  for (i = 0; i < 4; i++) {
+    fx  = graph[0].axis[i].fx;
+    fy  = graph[0].axis[i].fy;
+    dfx = graph[0].axis[i].dfx;
+    dfy = graph[0].axis[i].dfy;
+    P = hypot ((double)graph[0].axis[(i+1)%2].dfx, (double)graph[0].axis[(i+1)%2].dfy);
+
+    if (graph[0].axis[i].isaxis) { 
+      bDrawLine (fx, fy, fx+dfx, fy+dfy); 
+    }
+    
+    if (graph[0].axis[i].areticks) {
+      if (isnan(graph[0].axis[i].min) || isinf(graph[0].axis[i].min)) continue;
+      if (isnan(graph[0].axis[i].max) || isinf(graph[0].axis[i].max)) continue;
+
+      range = graph[0].axis[i].max - graph[0].axis[i].min;
+
+      AxisTickScale (&graph[0].axis[i], &major, &minor);
+
+      first = minor*((int)(graph[0].axis[i].min/minor));
+      if ((range > 0) && (first < graph[0].axis[i].min)) {
+	first += minor;
+      }
+      if ((range < 0) && (first > graph[0].axis[i].min)) {
+	first -= minor;
+      }
+      for (next = first; ((range > 0) && (next <= graph[0].axis[i].max)) || ((range < 0) && (next >= graph[0].axis[i].max));) {
+	IsLabel = FALSE;
+	if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || 
+	    (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)) ||
+	    (fabs ((int)((next - 0.5*minor)/major) - (next/major)) < 0.5*(minor/major)))
+	  IsLabel = graph[0].axis[i].islabel;
+	bDrawTick (fx, fy, dfx, dfy, P, graph[0].axis[i].min, graph[0].axis[i].max, next, IsLabel, i);
+	if (range > 0) 
+	  next += minor;
+	else 
+	  next -= minor;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void bDrawTick (double fx, double fy, double dfx, double dfy, int P, double min, double max, double value, int mode, int naxis) {
+  
+  int pos, dir, fontsize;
+  double size, n, x, y, dx, dy;
+  char string[64], *fontname;
+
+  pos = size = 0;
+
+  if (mode == 1) { size = MAX (0.02, 7.0 / P); }
+  if (mode == 0) { size = MAX (0.01, 4.0 / P); }
+  
+  n = P / sqrt ((double)(dfx*dfx + dfy*dfy));
+  x = fx + (value-min)*dfx/(max - min);
+  y = fy + (value-min)*dfy/(max - min);
+
+  dir = +1;
+  if ((naxis == 0) || (naxis == 1)) dir *= -1;
+  dx = dir*size*dfy*n;	
+  dy = dir*size*dfx*n;
+  
+  bDrawLine (x, y, x+dx, y+dy);
+
+  if (mode == 1) {
+    fontname = GetRotFont (&fontsize);
+
+    /* temporarily assume rectilinear axes */
+    if (naxis == 0) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 1; }
+    if (naxis == 2) { dx = 0; dy = -dir*(0.8*fontsize + 1); pos = 7; }
+
+    if (naxis == 1) { dy = 0; dx = -(0.8*fontsize + 1); pos = 3; }
+    if (naxis == 3) { dy = 0; dx = +(0.8*fontsize + 1); pos = 5; }
+
+    x = fx + (value-min)*dfx/(max - min) + dx;
+    y = fy + (value-min)*dfy/(max - min) + dy;
+    if (fabs(value) < 1e-14) { value = 0.0; }
+    sprintf (string, "%g", value);
+    bDrawRotText ((int)x, (int)y, string, pos, 0.0);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawIt.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawIt.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawIt.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "Ximage.h"
+
+bDrawBuffer *bDrawIt () {
+
+  int i, Nsection;
+  bDrawBuffer *buffer;
+  bDrawColor black;
+  Graphic *graphic;
+  Section *section;
+
+  graphic = GetGraphic();
+
+  black = KapaColorByName ("black");
+
+  buffer = bDrawBufferCreate (graphic->dx, graphic->dy);
+  bDrawSetBuffer (buffer);
+  bDrawSetStyle (black, 0, 0);
+  
+  // reset the sizes for all sections
+  Nsection = GetNumberOfSections ();
+  for (i = 0; i < Nsection; i++) {
+      section = GetSectionByNumber (i);
+      bDrawGraph (section->graph);
+      // bDrawImage (section->image);
+  }
+
+  return (buffer);
+}
+
+void bDrawGraph (KapaGraphWidget *graph) {
+  if (graph == NULL) return;
+  bDrawFrame (graph); 
+  bDrawObjects (graph);
+  bDrawLabels (graph);
+  bDrawTextlines (graph);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawLabels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawLabels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawLabels.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "Ximage.h"
+  
+void bDrawLabels (KapaGraphWidget *graph) {
+  
+  int i, pos, x, y, size;
+  double angle;
+  char *fontname;
+
+  pos = 0;
+  fontname = GetRotFont (&size);
+  for (i = 0; i < 8; i++) {
+    if (strcmp (graph[0].label[i].text, "")) {
+      angle = 0;
+      switch (i) {
+      case 0: pos = 7; break;
+      case 1: pos = 1; angle = -90; break;
+      case 2: pos = 1; break;
+      case 3: pos = 1; angle =  90; break;
+      case 4: pos = 2; break;
+      case 5: pos = 0; break;
+      case 6: pos = 8; break;
+      case 7: pos = 6; break;
+      }	
+      x = graph[0].label[i].x;
+      y = graph[0].label[i].y;
+      SetRotFont (graph[0].label[i].font, graph[0].label[i].size); 
+      bDrawRotText (x, y, graph[0].label[i].text, pos, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+void bDrawTextlines (KapaGraphWidget *graph) {
+
+  int i, x, y, size;
+  double angle;
+  char *fontname;
+
+  fontname = GetRotFont (&size);
+  for (i = 0; i < graph[0].Ntextline; i++) {
+    if (strcmp (graph[0].textline[i].text, "")) {
+      angle = graph[0].textline[i].angle;
+      x = graph[0].textline[i].x;
+      y = graph[0].textline[i].y;
+      SetRotFont (graph[0].textline[i].font, graph[0].textline[i].size);
+      bDrawRotText (x, y, graph[0].textline[i].text, 5, angle);
+    }
+  }
+  SetRotFont (fontname, size);
+}
+
+/*
+            
+ 4____2___5 
+  |       | 
+  |       | 
+ 1|       |3
+  |       |
+  |       |
+  ---------
+  6   0   7
+
+*/
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawObjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawObjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawObjects.c	(revision 16632)
@@ -0,0 +1,574 @@
+# include "Ximage.h"
+
+# define DrawLine(X1,Y1,X2,Y2) (bDrawLine ((X1), (Y1), (X2), (Y2)))
+# define DrawCircle(X1,Y1,R) (bDrawCircle ((X1), (Y1), (R)))
+# define DrawRectangle(X,Y,dX,dY) (bDrawRectOpen ((X-0.5*dX), (Y-0.5*dY), (X+0.5*dX), (Y+0.5*dY)))
+# define FillRectangle(X,Y,dX,dY) (bDrawRectFill ((X-0.5*dX), (Y-0.5*dY), (X+0.5*dX), (Y+0.5*dY)))
+# define FillTriangle(X1,Y1,X2,Y2,X3,Y3) (bDrawTriFill ((X1), (Y1), (X2), (Y2), (X3), (Y3)))
+# define OpenTriangle(X1,Y1,X2,Y2,X3,Y3) (bDrawTriOpen ((X1), (Y1), (X2), (Y2), (X3), (Y3)))
+# define CONNECT 0
+# define HISTOGRAM 1
+# define POINTS 2
+
+static Graphic *graphic;
+
+int bDrawObjects (KapaGraphWidget *graph) {
+  
+  int i;
+  int type;
+  int weight;
+  bDrawColor color;
+  bDrawColor black;
+  
+  graphic = GetGraphic();
+
+  black = KapaColorByName ("black");
+  for (i = 0; i < graph[0].Nobjects; i++) {
+
+    weight = MAX (0, MIN (10, graph[0].objects[i].lweight));
+    type = graph[0].objects[i].ltype;    
+    color = graph[0].objects[i].color;
+    bDrawSetStyle (color, weight, type);
+
+    switch (graph[0].objects[i].style) {
+    case CONNECT: 
+      bDrawConnect (graph, &graph[0].objects[i]);
+      break;
+    case HISTOGRAM:
+      bDrawHistogram (graph, &graph[0].objects[i]);
+      break;
+    case POINTS:
+      bDrawPoints (graph, &graph[0].objects[i]);
+      break;
+    }
+
+    if (graph[0].objects[i].etype & 0x01) {
+      bDrawYErrors (graph, &graph[0].objects[i]);
+    }
+    if (graph[0].objects[i].etype & 0x02) {
+      bDrawXErrors (graph, &graph[0].objects[i]);
+    }
+  }
+  bDrawSetStyle (black, 0, 0);
+  return (TRUE);
+}
+
+void bDrawConnect (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    bDrawClipLine (sx0, sy0, sx1, sy1, X0, Y0, X1, Y1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+void bDrawClipLine (double x0, double y0, double x1, double y1, double X0, double Y1, double X1, double Y0) {
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x0,y0 if outside box */
+  if ((x0 < X0) && (x1 >= X0)) {
+    y0 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X0;
+  }
+  if ((x0 > X1) && (x1 <= X1)) {
+    y0 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x0 = X1;
+  }
+  if ((y0 < Y0) && (y1 >= Y0)) {
+    x0 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y0;
+  }
+  if ((y0 > Y1) && (y1 <= Y1)) {
+    x0 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y0 = Y1;
+  }
+
+  /* skip line segement if both points are beyond box */
+  if ((x0 <= X0) && (x1 <= X0)) return;
+  if ((x0 >= X1) && (x1 >= X1)) return;
+  if ((y0 <= Y0) && (y1 <= Y0)) return;
+  if ((y0 >= Y1) && (y1 >= Y1)) return;
+
+  /* replace x1,y1 if outside box */
+  if ((x1 < X0) && (x0 >= X0)) {
+    y1 = y0 + (X0 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X0;
+  }
+  if ((x1 > X1) && (x0 <= X1)) {
+    y1 = y0 + (X1 - x0)*(y1 - y0)/(x1 - x0);
+    x1 = X1;
+  }
+  if ((y1 < Y0) && (y0 >= Y0)) {
+    x1 = x0 + (Y0 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y0;
+  }
+  if ((y1 > Y1) && (y0 <= Y1)) {
+    x1 = x0 + (Y1 - y0)*(x1 - x0)/(y1 - y0);
+    y1 = Y1;
+  }
+  DrawLine (x0, y0, x1, y1);
+}
+
+/*******/
+void bDrawHistogram (KapaGraphWidget *graph, Gobjects *object) {
+
+  int i;
+  float *x, *y;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sxa;
+  double X0, X1, Y0, Y1;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0); 
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0); 
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  X0 = graph[0].axis[0].fx;
+  X1 = graph[0].axis[0].fx + graph[0].axis[0].dfx;
+  Y0 = graph[0].axis[1].fy;
+  Y1 = graph[0].axis[1].fy + graph[0].axis[1].dfy;
+
+  /* find the first valid datapoint */
+  x = object[0].x; y = object[0].y;
+  for (i = 0; (i < object[0].Npts) && !(finite(x[i]) && finite(y[i])); i++);
+  if (i >= object[0].Npts) return;
+  sx0 = x[i]*mxi + y[i]*mxj + bx;
+  sy0 = x[i]*myi + y[i]*myj + by;
+  sx0 = MIN (MAX (sx0, X0), X1);
+  sy0 = MAX (MIN (sy0, Y0), Y1);
+  
+  /* continue with rest of points */
+  for (i++; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]))) continue;
+    sx1 = x[i]*mxi + y[i]*mxj + bx;
+    sy1 = x[i]*myi + y[i]*myj + by;
+    sx1 = MIN (MAX (sx1, X0), X1);
+    sy1 = MAX (MIN (sy1, Y0), Y1);
+    sxa = 0.5*(sx0 + sx1);
+    DrawLine (sx0, sy0, sxa, sy0);
+    DrawLine (sxa, sy0, sxa, sy1);
+    DrawLine (sxa, sy1, sx1, sy1);
+    sx0 = sx1; sy0 = sy1;
+  }
+}
+
+/*******/
+void bDrawPoints (KapaGraphWidget *graph, Gobjects *object) {
+ 
+  int i;
+  float *x, *y, *z;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx, sy, d, sx1, sy1, sx2, sy2;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);  
+ 
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);  
+
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  /* below here, code is identical with DrawObjects */
+  /**** points are scaled by object.z ***/
+  if (object[0].size < 0) {
+    d = 0.5 * (graphic->dx + graphic->dy) * 0.01;
+    x = object[0].x; y = object[0].y; z = object[0].z;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {	/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d*z[i], 2*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d*z[i], sy, sx + d*z[i], sy);
+	    DrawLine (sx, sy - d*z[i], sx, sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {	/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d*z[i], sy - d*z[i], sx - d*z[i], sy + d*z[i]);
+	    DrawLine (sx - d*z[i], sy - d*z[i], sx + d*z[i], sy + d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d*z[i], sy - 0.58*d*z[i], sx + d*z[i], sy - 0.58*d*z[i], sx, sy + 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    OpenTriangle (sx - d*z[i], sy + 0.58*d*z[i], sx, sy - 1.15*d*z[i], sx + d*z[i], sy + 0.58*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx + d*z[i], sy + 0.58*d*z[i]);
+	    DrawLine (sx, sy, sx,          sy - 1.15*d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d*z[i]);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	/* connect a pair of points */
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  } else {
+    d = object[0].size * 0.5 * (graphic->dx + graphic->dy) * 0.003;
+    x = object[0].x; y = object[0].y;
+    if (object[0].ptype == 0) {	/* filled box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 1) {		/* open box */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+   	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawRectangle (sx, sy, 2*d, 2*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 2) { /* cross */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx - d, sy, sx + d, sy);
+	    DrawLine (sx, sy - d, sx, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 3) {		/* x */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx + d, sy - d, sx - d, sy + d);
+	    DrawLine (sx - d, sy - d, sx + d, sy + d);
+	  }
+      }
+    }
+    if (object[0].ptype == 4) {	/* filled triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    FillTriangle (sx - d, sy - 0.58*d, sx + d, sy - 0.58*d, sx, sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 5) {	/* open triangle */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    OpenTriangle (sx - d, sy + 0.58*d, sx + d, sy + 0.58*d, sx, sy - 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 6) {	/* Y */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawLine (sx, sy, sx - d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx + d, sy - 0.58*d);
+	    DrawLine (sx, sy, sx,     sy + 1.15*d);
+	  }
+      }
+    }
+    if (object[0].ptype == 7) {	/* 0 */
+      for (i = 0; i < object[0].Npts; i++) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx = x[i]*mxi + y[i]*mxj + bx;
+	sy = x[i]*myi + y[i]*myj + by;
+	if ((sx > graph[0].axis[0].fx) && (sx < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	    (sy < graph[0].axis[1].fy) && (sy > graph[0].axis[1].fy + graph[0].axis[1].dfy))
+	  {
+	    DrawCircle (sx, sy, d);
+	  }
+      }
+    }
+    if (object[0].ptype == 100) {	
+      for (i = 0; i + 1 < object[0].Npts; i+=2) {
+	if (!(finite(x[i]) && finite(y[i]))) continue;
+	sx1 = x[i]*mxi + y[i]*mxj + bx;
+	sy1 = x[i]*myi + y[i]*myj + by;
+	sx2 = x[i+1]*mxi + y[i+1]*mxj + bx;
+	sy2 = x[i+1]*myi + y[i+1]*myj + by;
+	DrawLine (sx1, sy1, sx2, sy2);
+      }
+    }
+  }
+}
+    
+/*******/
+void bDrawXErrors (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dxm, *dxp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dxp = object[0].dxp; dxm = object[0].dxm; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[1].dfy*0.03;
+   
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] + dxp[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] + dxp[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dxm[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = (x[i] - dxm[i])*mxi + y[i]*mxj + bx;
+    sy1 = (x[i] - dxm[i])*myi + y[i]*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sy1 - sz;
+	  sx11 = sy1 + sz;
+	  DrawLine (sx1, sx10, sx1, sx11);
+	}
+      }
+  }
+}
+    
+/*******/
+void bDrawYErrors (KapaGraphWidget *graph, Gobjects *object) {
+  
+  int i, bar;
+  float *x, *y, *dym, *dyp;
+  double mxi, mxj, myi, myj, bxi, bxj, byi, byj, bx, by;
+  double sx0, sy0, sx1, sy1, sz, sx10, sx11;
+  
+  mxi = graph[0].axis[0].dfx / (object[0].x1 - object[0].x0);
+  mxj = graph[0].axis[1].dfx / (object[0].y1 - object[0].y0);
+  myi = graph[0].axis[0].dfy / (object[0].x1 - object[0].x0);
+  myj = graph[0].axis[1].dfy / (object[0].y1 - object[0].y0);
+  
+  bxi  =  graph[0].axis[0].fx - object[0].x0*graph[0].axis[0].dfx/(object[0].x1 - object[0].x0);
+  bxj  =  -object[0].y0*graph[0].axis[1].dfx/(object[0].y1 - object[0].y0);
+  byi  =  -object[0].x0*graph[0].axis[0].dfy/(object[0].x1 - object[0].x0);
+  byj  =  graph[0].axis[1].fy - object[0].y0*graph[0].axis[1].dfy/(object[0].y1 - object[0].y0);
+  
+  bx = bxi + bxj;
+  by = byi + byj;
+  
+  x = object[0].x; y = object[0].y; dyp = object[0].dyp; dym = object[0].dym; 
+  bar = object[0].ebar; sz = object[0].size*graph[0].axis[0].dfx*0.03;
+  
+  for (i = 0; i < object[0].Npts; i++) {
+    if (!(finite(x[i]) && finite(y[i]) && finite(dyp[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] + dyp[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] + dyp[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+    if (!(finite(x[i]) && finite(y[i]) && finite(dym[i]))) continue;
+    sx0 = x[i]*mxi + y[i]*mxj + bx;
+    sy0 = x[i]*myi + y[i]*myj + by;
+    sx1 = x[i]*mxi + (y[i] - dym[i])*mxj + bx;
+    sy1 = x[i]*myi + (y[i] - dym[i])*myj + by;
+    if (((sx0 > graph[0].axis[0].fx) && (sx0 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy0 < graph[0].axis[1].fy) && (sy0 > graph[0].axis[1].fy + graph[0].axis[1].dfy)) ||
+	((sx1 > graph[0].axis[0].fx) && (sx1 < graph[0].axis[0].fx + graph[0].axis[0].dfx) &&
+	 (sy1 < graph[0].axis[1].fy) && (sy1 > graph[0].axis[1].fy + graph[0].axis[1].dfy)))
+      {
+	DrawLine (sx0, sy0, sx1, sy1);
+	if (bar) {
+	  sx10 = sx1 - sz;
+	  sx11 = sx1 + sz;
+	  DrawLine (sx10, sy1, sx11, sy1);
+	}
+      }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/bDrawOverlay.c	(revision 16632)
@@ -0,0 +1,101 @@
+# include "Ximage.h"
+# define INFRONT 4
+
+static char name[4][16] = {"red", "green", "blue", "yellow"};
+
+void bDrawOverlay (KapaImageWidget *image, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double expand, X0, Y0;
+  bDrawColor color;
+ 
+  /* translate color to bDrawColors : image[0].overlay[N].color */
+  color = KapaColorByName (name[N]);
+  bDrawSetStyle (color, 0, 0);
+  
+  expand = 1.0;
+  if (image[0].picture.expand > 0) {
+    expand = 1 / (1.0*image[0].picture.expand);
+  }
+  if (image[0].picture.expand < 0) {
+    expand = fabs((double)image[0].picture.expand);
+  }
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, &image[0].picture);
+  X0 -= image[0].picture.x;
+  Y0 -= image[0].picture.y;
+
+  Xmin = 0;
+  Ymin = 0;
+  Xmax = image[0].picture.dx;
+  Ymax = image[0].picture.dy;
+  Xrange = image[0].picture.dx;
+  Yrange = image[0].picture.dy;
+
+  for (i = 0; i < image[0].overlay[N].Nobjects; i++) {
+    if (N == INFRONT) {
+      X  = image[0].overlay[N].objects[i].x * Xrange;
+      Y  = image[0].overlay[N].objects[i].y * Yrange;
+      dX = image[0].overlay[N].objects[i].dx * Xrange;
+      dY = image[0].overlay[N].objects[i].dy * Yrange;
+    } else {
+      X  = image[0].overlay[N].objects[i].x/expand + X0;
+      Y =  image[0].overlay[N].objects[i].y/expand + Y0;
+      dX = image[0].overlay[N].objects[i].dx/expand;
+      dY = image[0].overlay[N].objects[i].dy/expand;
+    }
+    if ((X + dX < Xmin) || (X - dX > Xmax) ||
+	(Y + dY < Ymin) || (Y - dY > Ymax)) {
+      continue;
+    }
+
+    /* for a LINE, (x, y) is the start, (dx, dy) is the distance to end
+       for a CIRCLE (x, y) is the center, (dx, dy) is the radius 
+       for a BOX (x, y) is the center, (dx, dy) is the width */
+
+    switch (image[0].overlay[N].objects[i].type) {
+      case KII_OVERLAY_LINE:
+	bDrawLine (X, Y, (X+dX), (Y+dY));
+	break;
+      case KII_OVERLAY_TEXT:
+	bDrawRotText (X, Y, image[0].overlay[N].objects[i].text, 8, 0.0);
+	break;
+      case KII_OVERLAY_BOX:
+	dx = MAX (abs(dX),2) / 2;
+	dy = MAX (abs(dY),2) / 2;
+	bDrawRectOpen ((X-dx), (Y-dy), (X+dx), (Y+dy));
+	// bDrawRectOpen ((X-dx), (Y-dy), (X), (Y));
+	break;
+      case KII_OVERLAY_CIRCLE:
+	dx = MAX (abs(dX),2);
+	dy = MAX (abs(dY),2);
+	if (image[0].overlay[N].objects[i].angle == 0.0) {
+	  bDrawArc (X, Y, dx, dy, 0, 360);
+	} else {
+	  // very stupid rotate ellipse drawing:
+	  double x, y, t;
+	  double angle = image[0].overlay[N].objects[i].angle * RAD_DEG;
+	  double cs = cos(angle);
+	  double sn = sin(angle);
+	  // XXX dt should be based on the size of the ellipse...
+	  for (t = 0; t < 2*M_PI; t+=0.05) {
+	    x = X + dx*cos(t)*cs + dy*sin(t)*sn;
+	    y = Y - dx*cos(t)*sn + dy*sin(t)*cs;
+	    bDrawPoint (x, y);
+	  }
+	}
+	break;
+      default:
+	fprintf (stderr, "skipping unknown object\n");
+	break;
+    }
+  }
+  
+  /* translate color to bDrawColors : image[0].overlay[N].color */
+  bDrawSetStyle (color, 0, 0);
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/hh_hms.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/hh_hms.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/hh_hms.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+void hh_hms (char *line, double ra, double dec, char sep) {
+
+  int h, m, flag;
+  double s;
+  
+  ra /= 15.0;  /* convert from degrees to hours */
+  flag = SIGN(ra);
+  ra *= flag;
+  h = ra;
+  m = 60.000001*(ra - h);
+  s = 3600*(ra - h - m / 60.0);
+  if (flag > 0)
+    sprintf (line, " %02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  else
+    sprintf (line, "-%02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  
+  flag = SIGN(dec);
+  dec *= flag;
+  h = dec;
+  m = 60.000001*(dec - h);
+  s = 3600*(dec - h - m / 60.0);
+  if (flag > 0)
+    sprintf (&line[13], " %02d%c%02d%c%04.1f", h, sep, m, sep, s);
+  else
+    sprintf (&line[13], "-%02d%c%02d%c%04.1f", h, sep, m, sep, s);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/src/kapa.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/src/kapa.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/src/kapa.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "Ximage.h"
+
+int main (int argc, char **argv) {
+  
+  args (&argc, argv);
+
+  SetUpGraphic (&argc, argv);
+
+  InitLayout (argc, argv);
+  EventLoop ();
+
+  CloseDisplay ();
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/test/input
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/test/input	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/test/input	(revision 16632)
@@ -0,0 +1,38 @@
+
+macro test1
+  mcreate a 512 512
+  set x = xramp(a)
+  tv x 0 512
+end
+
+macro go
+  mcreate a 512 512
+  set x = xramp(a)
+  set y = yramp(a)
+  set z = sqrt((x-256)^2 + (y-256)^2)
+  tvchannel 1
+  tv x 0 512
+  tvchannel 2
+  tv y 0 512
+  tvchannel 3
+  tv z 0 512
+end
+
+macro test
+  rd r dub.red.fits
+  rd g dub.green.fits
+  rd b dub.blue.fits
+  set R = r*(r >= 0) + (r + 256)*(r < 0)
+  set G = g*(g >= 0) + (g + 256)*(g < 0)
+  set B = b*(b >= 0) + (b + 256)*(b < 0)
+  tvchannel 1
+  tv R 0 256
+  tvchannel 2
+  tv G 0 256
+  tvchannel 3
+  tv B 0 256
+
+  tvcolor ruffcolor
+  sleep 1
+  tvcolor fullcolor
+end
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/CheckTextLines.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/CheckTextLines.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/CheckTextLines.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/******** Here we test the TextLines specific to this program  ****
+TextLine *
+CheckTextLines (graphic, event, layout)
+Graphic         graphic[];
+XEvent          event[];
+Layout          layout[];
+{
+
+  TextLine *textline;
+  textline = (TextLine *) NULL;
+
+  if (InTextLine (graphic, event, &layout[0].zero))
+    textline = &layout[0].zero;
+  if (InTextLine (graphic, event, &layout[0].range))
+    textline = &layout[0].range;
+  if (InTextLine (graphic, event, &layout[0].effects))
+    textline = &layout[0].effects;
+  if (InTextLine (graphic, event, &layout[0].command))
+    textline = &layout[0].command;
+
+  return (textline);
+
+}
+
+
+***/
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DownArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DownArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DownArrow.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+DownArrow (button_event, height, width, SB_x, SB_y)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (width - SB_y)));
+    return (answer);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawCursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawCursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawCursor.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+
+DrawCursor (graphic, textline)    
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int dx, label_width, DX, text_width, i;
+
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+    dx  = XTextWidth (graphic[0].font, &textline[0].text[i - 1], 
+		      textline[0].cursor - i + 1) + arrow_width;
+  }
+  else 
+    dx  = XTextWidth (graphic[0].font, textline[0].text, textline[0].cursor);
+
+  XDrawLine (graphic[0].display, 
+	     graphic[0].window, 
+	     graphic[0].gc, 
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + YBorder,
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + textline[0].dy - YBorder);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawTextBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawTextBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawTextBox.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* DrawTextBox ****************/
+DrawTextBox (graphic, textbox)
+Graphic      graphic[];
+TextBox      textbox[];
+{
+
+  int X, Y, y, dy, Nlines, i;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  textbox[0].x  + 1,  textbox[0].y + 1,
+		  XBorder - 2, textbox[0].dy - 2);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textbox[0].x,  textbox[0].y,
+		    textbox[0].dx, textbox[0].dy);
+  }
+
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  Nlines = (textbox[0].dy - 2*YBorder) / dy;
+
+  for (i = 0; (i < Nlines) && (i < textbox[0].Nlines); i++) {
+    y = textbox[0].y + graphic[0].font[0].ascent + dy*i + YBorder;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textbox[0].x + XBorder, y,
+		 textbox[0].text[i], 
+		 strlen(textbox[0].text[i]));
+  }
+
+  if (Nlines < textbox[0].Nlines) {
+    DrawBitmap (graphic, 
+		textbox[0].x + textbox[0].dx - down_width - 2,
+		textbox[0].y + textbox[0].dy - down_height - 2,
+		down_width, down_height, down_bits, 1);
+  }
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].cursor_line != -1) {
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawTextLine.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawTextLine.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/DrawTextLine.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+DrawTextLine (graphic, textline)
+Graphic  graphic[];
+TextLine textline[];
+{
+
+  int y;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textline[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textline[0].x,  textline[0].y,
+		    textline[0].dx, textline[0].dy);
+  }
+
+  y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+  XDrawString (graphic[0].display, 
+	       graphic[0].window, 
+	       graphic[0].gc, 
+	       textline[0].x + XBorder, y,
+	       textline[0].label, 
+	       strlen(textline[0].label));
+  RedrawString (graphic, textline);
+
+  if (textline[0].cursor != -1)
+    DrawCursor (graphic, textline);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/InTextBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/InTextBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/InTextBox.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* InTextBox ****************/
+int
+InTextBox (graphic, event, textbox)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextBox          textbox[];
+{
+
+  int answer;
+  int i, x, y, Y, X, dy;
+  int minX, maxX, minY, maxY;
+  
+  x = event[0].x;
+  y = event[0].y;
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  
+  minX = textbox[0].x;
+  maxX = textbox[0].x + textbox[0].dx;
+  minY = textbox[0].y;
+  maxY = textbox[0].y + textbox[0].dy;
+  if (dy*textbox[0].Nlines + 2*YBorder < textbox[0].dy)
+    maxY = textbox[0].y + dy*textbox[0].Nlines + 2*YBorder;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+  
+  /* find the cursor position, erase the old arrow and draw a new arrow */
+  if (answer) {
+    if (textbox[0].cursor_line != -1) {
+      Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+      X = textbox[0].x + (XBorder - arrow_width) / 2;
+      DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 0);
+    }
+    textbox[0].cursor_line = (y - textbox[0].y - YBorder)/dy;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+    textbox[0].cursor_x = x;
+    textbox[0].cursor_y = y;
+    XFlush (graphic[0].display);
+  }
+  
+  return (answer);
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/InTextLine.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/InTextLine.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/InTextLine.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int
+InTextLine (graphic, event, textline)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextLine         textline[];
+{
+
+  int answer, done;
+  int i, x, dx, y, text_width, label_width;
+  int minX, maxX, minY, maxY;
+  char testline[1000];
+
+  x = event[0].x;
+  y = event[0].y;
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  minX = textline[0].x + XBorder + label_width;
+  maxX = textline[0].x + textline[0].dx;
+  minY = textline[0].y;
+  maxY = textline[0].y + textline[0].dy;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+
+  /* find the cursor position and draw a vertical bar */
+  if (answer) {
+    text_width  = XTextWidth (graphic[0].font, 
+			      textline[0].text,
+			      strlen(textline[0].text));
+    
+    if (x >= minX + text_width) {
+      textline[0].cursor = strlen (textline[0].text);
+    }
+    else {
+      for (i = 1, done = FALSE; (i <= strlen (textline[0].text)) && !done; i++) {
+	dx  = XTextWidth (graphic[0].font, 
+			  textline[0].text, i);
+	if (x < minX + dx) {
+	  textline[0].cursor = i - 1;
+	  done = TRUE;
+	}
+      }
+    }
+    DrawCursor (graphic, textline);
+  }    
+  XFlush (graphic[0].display);
+  
+  return (answer);
+  
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/LeftArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/LeftArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/LeftArrow.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+LeftArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && (m_y < SB_x));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/RedrawString.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/RedrawString.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/RedrawString.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+#define arrow_width 6
+#define arrow_height 9
+RedrawString (graphic, textline)
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int label_width, text_width, y, i, DX;
+  static char arrow_bits[] = {
+    0x00, 0x10, 0x18, 0x1c, 0x1e, 0x1c, 0x18, 0x10, 0x00};
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    DrawBitmap (graphic, 
+		textline[0].x + XBorder + label_width,
+		textline[0].y + YBorder + (textline[0].dy - arrow_height)/2,
+		arrow_width, arrow_height, arrow_bits, 1);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width + arrow_width, y,
+		 &textline[0].text[i - 1], 
+		 strlen(&textline[0].text[i - 1]));
+    XFlush (graphic[0].display);
+  }
+  else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width, y,
+		 textline[0].text, 
+		 strlen(textline[0].text));
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/RightArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/RightArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/RightArrow.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+RightArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > (height - SB_x - SB_y)) && 
+	    (m_y < (height - SB_y)));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/TextLineEntry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/TextLineEntry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/TextLineEntry.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int 
+TextLineEntry (graphic, textline, keyevent)
+Graphic        graphic[];
+TextLine       textline[];
+XKeyEvent     *keyevent;
+{
+
+  int i, status, N;
+  char dummy[3];
+  XComposeStatus compose_status;
+  KeySym keysym;
+
+  status = TRUE;
+  strcpy (textline[0].old_text, textline[0].text);
+  bzero (&textline[0].text[strlen(textline[0].text)], 
+	 1024 - strlen(textline[0].text));
+  i = textline[0].cursor;
+
+
+  N = XLookupString (keyevent, dummy, 1, &keysym, &compose_status);
+  switch (keysym) {
+  case XK_BackSpace:
+  case XK_Delete:
+    if (textline[0].cursor > 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i - 1], 
+	     strlen(&textline[0].text[i]) + 1);
+      RedrawString (graphic, textline);
+      textline[0].cursor --;
+      DrawCursor (graphic, textline);
+    }
+    break;
+  case XK_Left:
+    RedrawString (graphic, textline);
+    textline[0].cursor --;
+    if (textline[0].cursor < 0)
+      textline[0].cursor = 0;
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Right:
+    RedrawString (graphic, textline);
+    textline[0].cursor ++;
+    if (textline[0].cursor > strlen (textline[0].text))
+      textline[0].cursor = strlen (textline[0].text);
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Return:
+    RedrawString (graphic, textline);
+    textline[0].cursor = -1;
+    status = FALSE;
+    break;
+  case XK_d:
+  case XK_D: 
+    if (dummy[0] == 4) { /* a control-d was typed! */
+      if (textline[0].cursor < strlen(textline[0].text)) {
+	bcopy (&textline[0].text[i + 1], &textline[0].text[i], 
+	       strlen(&textline[0].text[i]));
+	RedrawString (graphic, textline);
+	DrawCursor (graphic, textline);
+      }
+      break;  /* WARNING: this case MUST come before default.
+		 anything between this and default will be executed
+		 if no cntl-d is typed! */
+    }
+  default:
+    if (N != 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i + 1], 
+	     strlen(&textline[0].text[i]));
+      textline[0].text[i] = dummy[0];
+      RedrawString (graphic, textline);
+      textline[0].cursor ++;
+      DrawCursor (graphic, textline);
+    }
+  }
+  return (status);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/UpArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/UpArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/UpArrow.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+UpArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > SB_x) && 
+	    (m_x < (SB_x + SB_y)));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/xScrollBar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/xScrollBar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/xScrollBar.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+xScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > SB_x) && 
+	    (m_y < (height - SB_x - SB_y)));
+  f1 = (double)(m_y - SB_x);
+  f2 = (double)(height - 2*SB_x - SB_y);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/yScrollBar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/yScrollBar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kapa2/textbox/yScrollBar.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+yScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (SB_x + SB_y)) && 
+	    (m_x < (width - SB_y)));
+  f1 = (double)(m_x - SB_x - SB_y);
+  f2 = (double)(width - 2*SB_y - SB_x);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+	
Index: /branches/eam_branch_20080223/Ohana/src/kii/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/Makefile	(revision 16632)
@@ -0,0 +1,96 @@
+default: kii
+help:
+	@echo "make options: kii (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/kii
+LIB	=	$(HOME)/lib
+BIN	=	$(HOME)/bin
+BDIR	=	$(HOME)/button
+CDIR	=	$(HOME)/colorbar
+EDIR	=	$(HOME)/event
+MDIR	=	$(HOME)/misc
+ODIR	=	$(HOME)/overlay
+PDIR	=	$(HOME)/picture
+SDIR	=	$(HOME)/setup
+ZDIR	=	$(HOME)/zoom
+INC	=	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+kii: $(BIN)/kii.$(ARCH)
+install: $(DESTBIN)/kii
+
+# local source / object files ########################
+BOBJ = \
+$(BDIR)/ButtonFunctions.$(ARCH).o         $(BDIR)/InButton.$(ARCH).o           \
+$(BDIR)/CheckButtons.$(ARCH).o     	  $(BDIR)/InPicture.$(ARCH).o          \
+$(BDIR)/DrawButton.$(ARCH).o       	  $(BDIR)/InvertButton.$(ARCH).o       \
+$(BDIR)/FlashButton.$(ARCH).o      	  $(BDIR)/PSit.$(ARCH).o		\
+$(BDIR)/JPEGit.$(ARCH).o		  $(BDIR)/ConvertPixmap.$(ARCH).o
+
+COBJ = \
+$(CDIR)/CreateColorbar.$(ARCH).o          $(CDIR)/SetColormap.$(ARCH).o        \
+$(CDIR)/DragColorbar.$(ARCH).o
+
+EOBJ = \
+$(EDIR)/CheckPipe.$(ARCH).o               $(EDIR)/Stop.$(ARCH).o               \
+$(EDIR)/EventLoop.$(ARCH).o         	  $(EDIR)/Reconfig.$(ARCH).o           \
+$(EDIR)/InterpretKeys.$(ARCH).o     	  $(EDIR)/Refresh.$(ARCH).o            \
+$(EDIR)/InterpretPresses.$(ARCH).o  	  $(EDIR)/FlushDisplay.$(ARCH).o
+
+MOBJ = \
+$(MDIR)/hh_hms.$(ARCH).o		  
+
+OOBJ = \
+$(ODIR)/EraseOverlay.$(ARCH).o            $(ODIR)/PaintOverlay.$(ARCH).o       \
+$(ODIR)/LoadOverlay.$(ARCH).o   	  $(ODIR)/SaveOverlay.$(ARCH).o        \
+$(ODIR)/DrawOverlay.$(ARCH).o		  $(ODIR)/CSaveOverlay.$(ARCH).o       \
+$(ODIR)/PaintTickmarks.$(ARCH).o          $(ODIR)/LoadTickmarks.$(ARCH).o      \
+$(ODIR)/bDrawOverlay.$(ARCH).o
+
+POBJ = \
+$(PDIR)/CreatePicture.$(ARCH).o           $(PDIR)/Reorient.$(ARCH).o           \
+$(PDIR)/NewPicture.$(ARCH).o        	  $(PDIR)/Center.$(ARCH).o             \
+$(PDIR)/PositionPictures.$(ARCH).o  	  $(PDIR)/StatusBox.$(ARCH).o          \
+$(PDIR)/CursorOps.$(ARCH).o 		  $(PDIR)/Resize.$(ARCH).o 		\
+$(PDIR)/Remap8.$(ARCH).o 		  $(PDIR)/Remap24.$(ARCH).o 		\
+$(PDIR)/Remap.$(ARCH).o             	  $(PDIR)/Remap32.$(ARCH).o		\
+$(PDIR)/Remap16.$(ARCH).o		  $(PDIR)/JPEGit24.$(ARCH).o            \
+$(PDIR)/cursor.$(ARCH).o
+
+SOBJ = \
+$(SDIR)/CheckColors.$(ARCH).o             $(SDIR)/MakeGC.$(ARCH).o             \
+$(SDIR)/CheckDisplayName.$(ARCH).o  	  $(SDIR)/MapWindow.$(ARCH).o          \
+$(SDIR)/CheckFontName.$(ARCH).o     	  $(SDIR)/NameWindow.$(ARCH).o         \
+$(SDIR)/CheckGeometry.$(ARCH).o     	  $(SDIR)/OpenDisplay.$(ARCH).o        \
+$(SDIR)/CloseDisplay.$(ARCH).o      	  $(SDIR)/QuitX.$(ARCH).o              \
+$(SDIR)/CreateWindow.$(ARCH).o      	  $(SDIR)/SetNormalHints.$(ARCH).o     \
+$(SDIR)/DefineLayout.$(ARCH).o      	  $(SDIR)/SetUpDisplay.$(ARCH).o       \
+$(SDIR)/DrawBitmap.$(ARCH).o        	  $(SDIR)/SetUpWindow.$(ARCH).o        \
+$(SDIR)/GetColor.$(ARCH).o          	  $(SDIR)/SetWMHints.$(ARCH).o         \
+$(SDIR)/LoadFont.$(ARCH).o          	  $(SDIR)/TopWindow.$(ARCH).o          \
+$(SDIR)/MakeColormap.$(ARCH).o      	  $(SDIR)/Ximage.$(ARCH).o             \
+$(SDIR)/MakeCursor.$(ARCH).o              $(SDIR)/CheckVisual.$(ARCH).o	       \
+$(SDIR)/args.$(ARCH).o
+
+ZOBJ = \
+$(ZDIR)/UpdatePointer.$(ARCH).o      \
+$(ZDIR)/CrossHairs.$(ARCH).o		  $(ZDIR)/UpdateStatusBox.$(ARCH).o	\
+$(ZDIR)/CreateZoom.$(ARCH).o              $(ZDIR)/CreateZoom32.$(ARCH).o        \
+$(ZDIR)/CreateZoom8.$(ARCH).o             $(ZDIR)/CreateZoom24.$(ARCH).o	\
+$(ZDIR)/CreateZoom16.$(ARCH).o
+
+OBJ  =  $(BOBJ) $(COBJ) $(EOBJ) $(MOBJ) $(OOBJ) $(POBJ) $(SOBJ) $(ZOBJ)
+
+# dependancy rules for include files ########################
+$(OBJ): $(INC)/Ximage.h \
+	$(INC)/constants.h \
+	$(INC)/structures.h \
+	$(INC)/prototypes.h
+
+$(BIN)/kii.$(ARCH): $(OBJ)
Index: /branches/eam_branch_20080223/Ohana/src/kii/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/ButtonFunctions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/ButtonFunctions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/ButtonFunctions.c	(revision 16632)
@@ -0,0 +1,126 @@
+# include "Ximage.h"
+
+static char *GREY = "greyscale";
+static char *PUNS = "Puns";
+static char *RAINBOW = "Rainbow";
+
+int greycolors (Graphic *graphic, Layout *layout) {
+  char *name;
+  name = GREY;
+  SetColormap (graphic, layout, name);
+  CreateColorbar (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix);
+  CreateZoom (layout, graphic, 0, 0); 
+  Refresh (graphic, layout, 0);
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int puns (Graphic *graphic, Layout *layout) {
+  char *name;
+  name = PUNS;
+  SetColormap (graphic, layout, name);
+  CreateColorbar (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix);
+  CreateZoom (layout, graphic, 0, 0); 
+  Refresh (graphic, layout, 0);
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int rainbow (Graphic *graphic, Layout *layout) {
+  char *name;
+  name = RAINBOW;
+  SetColormap (graphic, layout, name);
+  CreateColorbar (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix);
+  CreateZoom (layout, graphic, 0, 0); 
+  Refresh (graphic, layout, 0);
+  XFlush (graphic[0].display);
+  return (TRUE);
+}
+
+int Recenter (Graphic *graphic, Layout *layout) {
+
+  layout[0].X = 0;
+  layout[0].Y = 0;
+ 
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Rescale (Graphic *graphic, Layout *layout) {
+
+  layout[0].expand = 1;
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int RecenterRescale (Graphic *graphic, Layout *layout) {
+
+  layout[0].X = 0;
+  layout[0].Y = 0;
+  layout[0].expand = 1;
+ 
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int ToggleDEG (Graphic *graphic, Layout *layout) {
+
+  DECIMAL_DEG = DECIMAL_DEG ^ TRUE;
+  StatusBox (graphic, layout);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/*********** overlay_button functions ************/
+int Overlay0 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[0] = OVERLAY[0] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay1 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[1] = OVERLAY[1] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay2 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[2] = OVERLAY[2] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+int Overlay3 (Graphic *graphic, Layout *layout) {
+
+  OVERLAY[3] = OVERLAY[3] ^ TRUE;
+  Refresh (graphic, layout, 0);
+  FlushDisplay (graphic[0].display);
+  return (TRUE);
+
+}
+
+/* this routine is NOT independent of the number of overlays */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/CheckButtons.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/CheckButtons.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/CheckButtons.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+# define PAD_X 10
+# define PAD_Y 10
+# define NPLANES 1
+# define NPIXELS 255
+
+/******** Here we test the Buttons specific to this program  *******/
+Button *
+CheckButtons (event, layout)
+XButtonEvent  event[];
+Layout        layout[];
+{
+
+  int i;
+  Button *button;
+  button = (Button *) NULL;
+
+  if (InButton (event, &layout[0].recenter_button)) 
+    button = &layout[0].recenter_button;
+
+  if (InButton (event, &layout[0].grey_button)) 
+    button = &layout[0].grey_button;
+
+  if (InButton (event, &layout[0].rainbow_button)) 
+    button = &layout[0].rainbow_button;
+
+  if (InButton (event, &layout[0].puns_button)) 
+    button = &layout[0].puns_button;
+
+  if (InButton (event, &layout[0].PS_button)) 
+    button = &layout[0].PS_button;
+
+  if (InButton (event, &layout[0].hms_button)) 
+    button = &layout[0].hms_button;
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (InButton (event, &layout[0].overlay_button[i])) 
+      button = &layout[0].overlay_button[i];
+  }
+
+  return (button);
+
+}
+
+
+/* To define a button, you must:
+
+   0) add the button to the Layout structure in structures.h
+   1) place the info about the button in PositionPicture.c
+   2) (make any bitmaps needed and put them in buttons.h
+   3) place an entry in CheckButtons.c
+   4) Add the button to Refresh.c
+   5) create the button's function
+   6) add it to the Makefile
+   7) add it to the prototypes
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/ConvertPixmap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/ConvertPixmap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/ConvertPixmap.c	(revision 16632)
@@ -0,0 +1,262 @@
+# include "Ximage.h"
+
+void ConvertPixmap8 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned char *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*layout[0].picture.dx;
+  }
+  return;
+}
+
+void ConvertPixmap16 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned short *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned short *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*layout[0].picture.dx;
+  }
+  return;
+}
+
+void ConvertPixmap24 (Layout *layout, FILE *f) {
+
+  int i, k, m, dx, dy, val, extra;
+  unsigned char *buff;
+  unsigned long color, byte;
+  double Nchar, Npix, start, slope, frac;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  extra = 4 - (dx * 3) % 4;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned char *)&layout[0].picture.data[(dy - 1)*(3*dx + extra)];
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < dy; i++) {
+    for (k = 0; k < dx; k++, buff+=3) {
+      color = 0;
+      byte = buff[2];
+      color = (byte << 16);
+      byte = buff[1];
+      color |= (byte << 8);
+      byte = buff[0];
+      color |= byte;
+      for (m = 0; (layout[0].cmap[m].pixel != color) && (m < Npix); m++);
+      val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*3*dx + extra;
+  }
+  return;
+}
+
+void ConvertPixmap32 (Layout *layout, FILE *f) {
+
+  int i, k, m, val;
+  double Nchar, Npix, start, slope, frac;
+  unsigned int *buff;
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  /* start at the last line, print lines in decending order */
+  buff = (unsigned int *)layout[0].picture.data + layout[0].picture.dx*(layout[0].picture.dy - 1);
+  slope = layout[0].slope;
+  start = layout[0].start;
+
+  for (i = 0; i < layout[0].picture.dy; i++) {
+    for (k = 0; k < layout[0].picture.dx; k++, buff++) {
+      if (*buff == layout[0].white) 
+	val = Nchar;
+      else {
+	for (m = 0; (layout[0].cmap[m].pixel != *buff) && (m < Npix); m++);
+	val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix);
+      }
+      fprintf (f, "%02x", val);
+      if (!((k+1) % 40)) fprintf (f, "\n"); 
+    }
+    fprintf (f, "\n");
+    buff -= 2*layout[0].picture.dx;
+  }
+  return;
+}
+
+# if (0)
+void ConvertPixmap (Layout *layout, File *f) {
+  
+  /* set up expansions */
+  expand = expand_in = expand_out = 1.0;
+  if (layout[0].expand == 0)
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  /* output line buffer */
+  ALLOCATE (line_buffer, char, dx);
+
+  in_pix_ref  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  Nchar = 255.0;
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+
+  /**** fill in bottom area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix++) {
+    *out_pix = WHITE;
+  }
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++) {
+      fprintf (f, "%02x", val);
+      if ((Npt % 40) == 0) {
+	fprintf (f, "\n");
+      }
+    }
+  }
+  
+  /*** fill in the image data region ***/
+  for (j = j_start; j < j_end; j+= expand_out, in_pix_ref += expand_in*DX) {
+    
+    /* create one output image line */
+    in_pix = in_pix_ref;
+    out_pix = line_buffer;
+
+    /**** fill in area to the left of the picture ****/
+    for (i = 0; i < i_start; i++, out_pix+=3) {
+      *out_pix = WHITE;
+    }
+    
+    /*** fill in the picture region ***/
+    for (i = i_start; i < i_end; i+=expand_out, in_pix+=expand_in) {
+      for (ii = 0; ii < expand_out; ii++, out_pix++) {
+	*out_pix = *in_pix*frac;
+      }
+    }
+    
+    /**** fill in area to the right of the picture ****/
+    for (i = i_end; i < dx; i++, out_pix++) {
+      *out_pix = WHITE;
+    }
+
+    /* write out the image line expand_out times */
+    for (j = 0; j < expand_out; j++) {
+      for (i = 0; i < dx; i++) {
+	fprintf (f, "%02x", val);
+	if ((Npt % 40) == 0) {
+	  fprintf (f, "\n");
+	}
+      }
+    }
+  }
+
+  /**** fill in top area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix++) { 
+    *out_pix = WHITE;
+  }
+  for (j = j_end; j < dy; j++) {
+    for (i = 0; i < dx; i++) {
+      fprintf (f, "%02x", val);
+      if ((Npt % 40) == 0) {
+	fprintf (f, "\n");
+      }
+    }
+  }
+}
+# endif
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/DrawButton.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/DrawButton.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/DrawButton.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "Ximage.h"
+
+void
+DrawButton (graphic, button)
+Graphic graphic[];
+Button button[];
+{
+  
+  int y, dX;
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  XDrawRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  button[0].x,  button[0].y,
+		  button[0].dx, button[0].dy);
+
+  if (button[0].text) {
+    dX = XTextWidth (graphic[0].font, button[0].bitmap, strlen(button[0].bitmap));
+    y = button[0].y + (button[0].dy + graphic[0].font[0].ascent)/2;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 button[0].x + (button[0].dx - dX) / 2, y,
+		 button[0].bitmap, strlen(button[0].bitmap));
+  }
+  else {
+    DrawBitmap (graphic, 
+		button[0].x + (button[0].dx - button[0].width) / 2 + 1, 
+		button[0].y + (button[0].dy - button[0].height) / 2 + 1, 
+		button[0].width, button[0].height, 
+		button[0].bitmap, 1);
+  }
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/FlashButton.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/FlashButton.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/FlashButton.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "Ximage.h"
+
+void FlashButton (Graphic *graphic, Button *button) {
+
+  unsigned long black, white;
+
+  black =  graphic[0].black;
+  white =  graphic[0].white;
+  graphic[0].black = white;
+  graphic[0].white = black;
+
+  DrawButton (graphic, button);
+  XFlush (graphic[0].display);
+/*  usleep (20000);  removed - not a standard C sleep command, apparently! */
+  
+  graphic[0].black = black;
+  graphic[0].white = white;
+  DrawButton (graphic, button);
+  XFlush (graphic[0].display);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/InButton.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/InButton.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/InButton.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "Ximage.h"
+
+int
+InButton (button_event, button)
+XButtonEvent *button_event;
+Button button[];
+{
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= button[0].x) && (x <= button[0].x + button[0].dx) &&
+	    (y >= button[0].y) && (y <= button[0].y + button[0].dy));
+
+  return (answer);
+
+}
+
+/*** make this a macro? ***/
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/InPicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/InPicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/InPicture.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+int
+InPicture (button_event, picture)
+XButtonEvent *button_event;
+Picture picture[];
+{
+
+  int answer;
+  int x, y;
+
+  x = button_event[0].x;
+  y = button_event[0].y;
+  
+  answer = ((x >= picture[0].x) && (x <= picture[0].x + picture[0].dx) &&
+	    (y >= picture[0].y) && (y <= picture[0].y + picture[0].dy));
+
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/InvertButton.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/InvertButton.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/InvertButton.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+void InvertButton (Graphic *graphic, Button *button) {
+
+  unsigned long black, white;
+
+  black =  graphic[0].black;
+  white =  graphic[0].white;
+
+  graphic[0].black = white;
+  graphic[0].white = black;
+
+  DrawButton (graphic, button);
+  FlushDisplay (graphic[0].display);
+  
+  graphic[0].black = black;
+  graphic[0].white = white;
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/JPEGit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/JPEGit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/JPEGit.c	(revision 16632)
@@ -0,0 +1,153 @@
+# include "Ximage.h"
+# include "jpeglib.h"
+
+int JPEGit (Graphic *graphic, Layout *layout) {
+  
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
+  JSAMPLE *image_buffer;	/* Points to data for current line */
+
+  int j, k, m;
+  unsigned char *buff;
+  double Nchar, Npix, start, slope, frac;
+  int quality;
+  unsigned long pcolor;
+
+  char filename[1024];
+  int Nbytes, status;
+
+  XImage *tmpimage;
+
+  FILE *f;
+  
+  /* expect a line telling the number of bytes and a filename */
+  status = read (layout[0].Ximage, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (layout[0].Ximage, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  /* 
+  switch (graphic[0].Nbits) {
+  case 8:
+    break;
+  case 16:
+    fprintf (stderr, "converter to 16 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  case 24:
+    fprintf (stderr, "converter to 24 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  case 32:
+    fprintf (stderr, "converter to 32 bit not yet implemented\n");
+    return (TRUE);
+    break;
+  }
+  */
+
+  /* set up the error handler , initialize the JPEG compression object. */
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_compress (&cinfo);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  jpeg_stdio_dest(&cinfo, f);
+  
+  quality = 75;
+  cinfo.image_width = layout[0].picture.dx; 	/* image width and height, in pixels */
+  cinfo.image_height = layout[0].picture.dy;
+# ifdef GREYSCALE
+  cinfo.input_components = 1;		        /* # of color components per pixel */
+  cinfo.in_color_space = JCS_GRAYSCALE; 	/* colorspace of input image */
+# else 
+  cinfo.input_components = 3;		        
+  cinfo.in_color_space = JCS_RGB; 	
+# endif
+  jpeg_set_defaults (&cinfo);
+  jpeg_set_quality (&cinfo, quality, TRUE       /* limit to baseline-JPEG values */);
+  jpeg_start_compress (&cinfo, TRUE);
+
+  ALLOCATE (image_buffer, JSAMPLE, 3*layout[0].picture.dx);
+  buff = (unsigned char *)layout[0].picture.data;
+  slope = layout[0].slope;
+  start = layout[0].start;
+  Nchar = 255.0;                                /* range of output values */
+  Npix = layout[0].Npixels;
+  frac = Nchar / Npix;
+  
+  {
+    XWindowAttributes WindowAttributes;
+    Pixmap tmp_pixmap;
+    Window tmp_window;
+    
+    XGetWindowAttributes (graphic[0].display, graphic[0].window, &WindowAttributes);
+    
+    tmp_pixmap = XCreatePixmap (graphic[0].display, graphic[0].window, graphic[0].dx, graphic[0].dy, WindowAttributes.depth);
+
+    tmp_window = graphic[0].window;
+    graphic[0].window = tmp_pixmap;
+
+    Refresh (graphic, layout, 0);
+
+    tmpimage = XGetImage (graphic[0].display, graphic[0].window, layout[0].picture.x+1, layout[0].picture.y+1, layout[0].picture.dx, layout[0].picture.dy, 0xffffffff, ZPixmap);
+
+    for (j = 0; (j < layout[0].picture.dy) && (cinfo.next_scanline < cinfo.image_height); j++) {
+      for (k = 0; k < layout[0].picture.dx; k++) {
+	pcolor = XGetPixel (tmpimage, k, j);
+	if (pcolor == layout[0].white) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = Nchar;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[0].color) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = 0;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[1].color) { 
+	  image_buffer[3*k+0] = 0;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[2].color) { 
+	  image_buffer[3*k+0] = 0;
+	  image_buffer[3*k+1] = 0;
+	  image_buffer[3*k+2] = Nchar;
+	  continue;
+	}
+	if (pcolor == layout[0].overlay[3].color) { 
+	  image_buffer[3*k+0] = Nchar;
+	  image_buffer[3*k+1] = Nchar;
+	  image_buffer[3*k+2] = 0;
+	  continue;
+	}
+	for (m = 0; (layout[0].cmap[m].pixel != pcolor) && (m < Npix); m++);
+	/* val = Nchar - frac * MIN (MAX (start + m * slope, 0), Npix); */
+	image_buffer[3*k+0] = layout[0].cmap[m].red / 256;
+	image_buffer[3*k+1] = layout[0].cmap[m].green / 256;
+	image_buffer[3*k+2] = layout[0].cmap[m].blue / 256;
+      }
+      row_pointer[0] = image_buffer;
+      (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
+    }
+    graphic[0].window = tmp_window;
+    XFreePixmap (graphic[0].display, tmp_pixmap);
+  }
+
+  XDestroyImage (tmpimage);
+
+  jpeg_finish_compress (&cinfo);
+  fclose (f);
+  jpeg_destroy_compress (&cinfo);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/button/PSit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/button/PSit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/button/PSit.c	(revision 16632)
@@ -0,0 +1,131 @@
+# include "Ximage.h"
+# define PADDING 10
+# define XOFFSET 60
+# define YOFFSET 60
+
+static char *name = "$Name: not supported by cvs2svn $";
+
+int PSit (Graphic *graphic, Layout *layout, int Raw) {
+  
+  FILE *f;
+  int i, pageMode, scaleMode;
+  double scale;
+  char filename[1024], pagename[1024], *version;
+
+  /* expect a line telling the number of bytes and a filename */
+  KiiScanMessage (layout[0].Ximage, "%s %s %d %d", filename, pagename, &scaleMode, &pageMode);
+
+  if (pageMode == KAPA_PS_NEWPAGE) {
+    f = fopen (filename, "a+");
+  } else {
+    f = fopen (filename, "w");
+  }
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  
+  if (!USE_XWINDOW) {
+    fprintf (stderr, "PS not working yet\n");
+    return (TRUE);
+  }
+
+  if (scaleMode) {
+    scale = MIN ((500.0/(double)layout[0].picture.dx), (700.0/(double)layout[0].picture.dy));
+  } else {
+    scale = 72.0 / 96.0; /* ratio of screen pixels to points */
+  }
+
+  switch (pageMode) {
+    case KAPA_PS_NEWPLOT:
+      fprintf (f, "%%!PS-Adobe-2.0 EPSF-2.0\n");
+      fprintf (f, "%%%%Title: %s\n", filename);
+      version = strip_version (name);
+      fprintf (f, "%%%%Creator: Ki'i (%s)\n", version);
+      free (version);
+      fprintf (f, "%%%%BoundingBox: %d %d %.0f %.0f\n", 
+	       XOFFSET - PADDING, YOFFSET - PADDING, 
+	       scale*layout[0].picture.dx + PADDING + XOFFSET, 
+	       scale*layout[0].picture.dy + PADDING + YOFFSET);
+      fprintf (f, "%%%%Pages: 1\n");
+      fprintf (f, "%%%%DocumentFonts:\n");
+      fprintf (f, "%%%%EndComments\n");
+      fprintf (f, "%%%%EndProlog\n");
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_NEWPAGE:
+      fprintf (f, "%%%%Page: %s\n\n", pagename);
+      break;
+
+    case KAPA_PS_RAWPAGE:
+      break;
+  } 
+
+  fprintf (f, "gsave %% encloses picture\n");
+  fprintf (f, "%% local abbreviations\n");
+  fprintf (f, "/Times-Roman findfont 18 scalefont setfont\n");
+  fprintf (f, "/T {moveto show stroke} def\n");
+  fprintf (f, "/B { newpath moveto dup 0 exch rlineto exch dup 0 rlineto exch -1 mul\n");
+  fprintf (f, " 0 exch rlineto -1 mul 0 rlineto closepath stroke } def\n");
+  fprintf (f, "/C {0 360 arc stroke} def\n");
+  fprintf (f, "/L {newpath moveto lineto stroke} def\n\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) {
+    fprintf (f, " %d %d translate\n", XOFFSET, YOFFSET);
+    fprintf (f, "  %f  %f scale\n", scale, scale);
+  }
+
+  fprintf (f, " newpath 0 0 moveto %d 0 lineto %d %d lineto 0 %d lineto closepath clip\n\n", 
+	   layout[0].picture.dx, layout[0].picture.dx, layout[0].picture.dy, layout[0].picture.dy);
+  fprintf (f, "gsave %% encloses image\n");
+  fprintf (f, "%d %d 8\n", layout[0].picture.dx, layout[0].picture.dy);
+  fprintf (f, "[1 0 0 1 0 0]\n");
+  fprintf (f, "{currentfile %d string readhexstring pop} image\n\n", layout[0].picture.dx);
+
+  /******** First we draw the picture itself ********/
+  /* in !USE_XWINDOW, we'll have to change this to use the JPEG function */
+  switch (graphic[0].Nbits) {
+  case 8:
+    ConvertPixmap8 (layout, f);
+    break;
+  case 16:
+    ConvertPixmap16 (layout, f);
+    break;
+  case 24:
+    ConvertPixmap24 (layout, f);
+    break;
+  case 32:
+    ConvertPixmap32 (layout, f);
+    break;
+  }
+
+  fprintf (f, "grestore %% end of image\n");
+  fprintf (f, "stroke\n");
+  fprintf (f, "%% plot overlay objects\n");
+  fprintf (f, "1 setgray\n");
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i]) {
+      fprintf (f, "%% overlay %d\n", i);
+      DrawOverlay (graphic, layout, i, f, 0);
+    }
+  }
+  fprintf (f, "0 setgray\n");
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i]) {
+      fprintf (f, "%% overlay %d\n", i);
+      DrawOverlay (graphic, layout, i, f, 1);
+    }
+  }
+  
+  fprintf (f, "grestore %% end of picture\n");
+
+  if (pageMode != KAPA_PS_RAWPAGE) fprintf (f, "showpage\n");
+
+  fclose (f);
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/colorbar/CreateColorbar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/colorbar/CreateColorbar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/colorbar/CreateColorbar.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+
+void CreateColorbar (Layout *layout, Graphic *graphic) {
+
+  int i, j, dx, dy, extra, start;
+  unsigned long  pixvalue;
+  unsigned int  *out24;
+  unsigned char *out8;
+
+  dx = layout[0].cmapbar.dx;
+  dy = layout[0].cmapbar.dy;
+
+  /* create the cmap scale */
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (layout[0].cmapbar.data, char, dx*dy);
+    out8 = (unsigned char *) layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out8[j*dx + i] = pixvalue;
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (layout[0].cmapbar.data, char, 2*dy*dx);
+    out8 = (unsigned char *) layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = 2*j*dx + 2*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (dx * 3) % 4;
+    REALLOCATE (layout[0].cmapbar.data, char, dy*(3*dx + extra));
+    out8 = (unsigned char *) layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	start = j*(3*dx+extra) + 3*i;
+	out8[start + 0] = 0x0000ff & pixvalue;
+	out8[start + 1] = 0x0000ff & (pixvalue >> 8);
+	out8[start + 2] = 0x0000ff & (pixvalue >> 16);
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+
+  case 32:
+    REALLOCATE (layout[0].cmapbar.data, char, 4*dx*dy);
+    out24 = (unsigned int *) layout[0].cmapbar.data;
+    for (i = 0; i < dx; i++) {
+      pixvalue = layout[0].cmap[(int)(i*layout[0].Npixels/dx)].pixel;
+      for (j = 0; j < dy; j++) {
+	out24[j*dx + i] = pixvalue;
+      }
+    }
+    layout[0].cmapbar.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].cmapbar.data, dx, dy, 32, 0);
+    break;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/colorbar/DragColorbar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/colorbar/DragColorbar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/colorbar/DragColorbar.c	(revision 16632)
@@ -0,0 +1,107 @@
+# include "Ximage.h"
+/* future expansion: warp mouse to the right spot for the current settings */
+
+void DragColorbar (Graphic *graphic, Layout *layout, XButtonEvent *mouse_event) {
+
+  double          frac_x, oldfrac_x, frac_y, oldfrac_y, start, slope;
+  int             X, Y;
+  XEvent          event;
+  XMotionEvent   *move;
+  int             xstatus, Npix, center;
+
+  if (!graphic[0].visualclass) return;
+
+  X = mouse_event[0].x;
+  Y = mouse_event[0].y;
+  Npix = layout[0].Npixels;
+  slope = layout[0].slope;
+  start = layout[0].start;
+  oldfrac_x = oldfrac_y = 10;
+  
+  while (1) {
+    frac_x = X / (1.0*graphic[0].dx);
+    frac_x = MAX (0, frac_x);
+    frac_x = MIN (1, frac_x);
+    frac_y = Y / (1.0*graphic[0].dy);
+    frac_y = MAX (0, frac_y);
+    frac_y = MIN (1, frac_y);
+    switch (mouse_event[0].button) {
+    case 1:
+      center = frac_x*Npix;
+      slope = Npix / (1 + 4*frac_y*frac_y*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    case 2:
+      start = 0;
+      slope = 1;
+      break;
+    case 3:
+      center = (Npix/2.0 - start) / slope;
+      slope = Npix / (1 + 4*frac_x*frac_x*Npix);
+      start = Npix/2.0 - center*slope;
+      break;
+    }
+
+    if ((frac_x != oldfrac_x) || (frac_y != oldfrac_y)) {
+      ResetColorbar (graphic, layout, start, slope);
+    }
+    oldfrac_x = frac_x;
+    oldfrac_y = frac_y;
+      
+    if ((xstatus = XCheckMaskEvent (graphic[0].display, EVENT_MASK, &event))) {
+      
+      switch (event.type)  {
+	
+      case MotionNotify:
+	if ((xstatus = XPending (graphic[0].display)) < 2) {
+	  move = (XMotionEvent *) &event;
+	  X = move[0].x;
+	  Y = move[0].y;
+	}
+	break;
+	
+      case ButtonPress:
+      case ButtonRelease:
+	layout[0].start = start;	
+	layout[0].slope = slope;
+	return;
+	break;
+	
+      }
+    }
+  }
+  
+}
+
+void ResetColorbar (Graphic *graphic, Layout *layout, double start, double slope) {
+
+  int i, j;
+  XColor cmap[256];
+
+  if (!graphic[0].visualclass) return;
+
+  for (i = 0; i < layout[0].Npixels; i++) {
+    cmap[i] = layout[0].cmap[i];
+    j = start + i * slope;
+    if (j < 0) {
+      cmap[i].red = layout[0].cmap[0].red;
+      cmap[i].blue = layout[0].cmap[0].blue;
+      cmap[i].green = layout[0].cmap[0].green;
+    }
+    else {
+      if (j >= layout[0].Npixels) {
+	cmap[i].red = layout[0].cmap[layout[0].Npixels-1].red;
+	cmap[i].blue = layout[0].cmap[layout[0].Npixels-1].blue;
+	cmap[i].green = layout[0].cmap[layout[0].Npixels-1].green;
+      }
+      else {
+	cmap[i].red = layout[0].cmap[j].red;
+	cmap[i].blue = layout[0].cmap[j].blue;
+	cmap[i].green = layout[0].cmap[j].green;
+      }
+    }
+  }
+
+  XStoreColors(graphic[0].display, graphic[0].colormap, cmap, layout[0].Npixels);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/colorbar/SetColormap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/colorbar/SetColormap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/colorbar/SetColormap.c	(revision 16632)
@@ -0,0 +1,101 @@
+# include "Ximage.h"
+
+/*** this function uses only private colormaps.  it should try the standard colormap
+     first to get better control over the smooth greyscales ***/
+
+int SetColormap (Graphic *graphic, Layout *layout, char *name) {
+
+  int i;
+
+  /* greyscale */
+  if ((!strcmp (name, "grayscale")) || (!strcmp (name, "greyscale"))) {
+    for (i = 0; i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*(255 - 255*i/layout[0].Npixels);
+      layout[0].cmap[i].green = 256*(255 - 255*i/layout[0].Npixels);
+      layout[0].cmap[i].blue = 256*(255 - 255*i/layout[0].Npixels);
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* heat */
+  if (!strcmp (name, "Puns")) {
+    for (i = 0; i < (int)(0.25*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].green = 0;
+      layout[0].cmap[i].blue = 0;
+      layout[0].cmap[i].red = MIN (256*255, 256*255*2*i/(1.0*layout[0].Npixels));  
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*layout[0].Npixels); i < (int)(0.50*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = MIN (256*255, 256*255*2*i/(1.0*layout[0].Npixels));
+      layout[0].cmap[i].green = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.25));
+      layout[0].cmap[i].blue = 0;
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*layout[0].Npixels); i < (int)(0.75*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.25));
+      layout[0].cmap[i].blue = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.50));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.75*layout[0].Npixels); i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = 256*255;
+      layout[0].cmap[i].blue = MIN (256*255, 256*255*2*(i/(1.0*layout[0].Npixels) - 0.50));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* -grayscale */
+  if ((!strcmp (name, "-grayscale")) || (!strcmp (name, "-greyscale"))) {
+    for (i = 0; i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*(255*i/layout[0].Npixels);
+      layout[0].cmap[i].green = 256*(255*i/layout[0].Npixels);
+      layout[0].cmap[i].blue = 256*(255*i/layout[0].Npixels);
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  /* rainbow */
+  if (!strcmp (name, "Rainbow")) {
+    for (i = 0; i < (int)(0.25*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 0;
+      layout[0].cmap[i].green = 0;
+      layout[0].cmap[i].blue = 256*(255*4*(i/(1.0*layout[0].Npixels)));  
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.25*layout[0].Npixels); i < (int)(0.50*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 256*(255*4*((i/(1.0*layout[0].Npixels)) - 0.25));
+      layout[0].cmap[i].green = 0;
+      layout[0].cmap[i].blue = 256*(255*4*(0.50 - (i/(1.0*layout[0].Npixels))));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.50*layout[0].Npixels); i < (int)(0.75*layout[0].Npixels); i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = 256*(255*4*((i/(1.0*layout[0].Npixels)) - 0.50));
+      layout[0].cmap[i].blue = 0;
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    for (i = (int)(0.75*layout[0].Npixels); i < layout[0].Npixels; i++) {  
+      layout[0].cmap[i].red = 256*255;
+      layout[0].cmap[i].green = 256*255;
+      layout[0].cmap[i].blue = 256*(255*4*((i/(1.0*layout[0].Npixels)) - 0.75));
+      layout[0].cmap[i].flags = DoRed | DoGreen | DoBlue;
+    }
+    goto store_colors;
+  }
+  return (FALSE);
+
+ store_colors:
+  if (!USE_XWINDOW) return (TRUE);
+  if (graphic[0].visualclass) {
+    XStoreColors(graphic[0].display, graphic[0].colormap, layout[0].cmap, layout[0].Npixels);
+  } else {
+    for (i = 0; i < layout[0].Npixels; i++) {
+      if (XAllocColor (graphic[0].display, graphic[0].colormap, &layout[0].cmap[i]) == 0) {
+	fprintf (stderr, "error on %d\n", i);
+      }
+    }
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,34 @@
+
+- kii 1.6 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+  * added keyboard events
+  * removed items moved to libkapa
+  * added test scripts
+
+- kii 1.5
+  * fixed bug in event loop which missed certain mask types
+  * added arrows and up/down keys to window events
+  * added ReorientOnButton / changed Reorient
+  * fixed errors wrt bDraw / fonts
+
+- kii 1.4
+  * major work to allow noX operation
+  * added bDraw functions
+  * integrated with libkapa
+
+kii-1-3: released 2005.10.20
+  - changed cursor interaction (returns name for keys)
+  - minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+kii-1-2:
+  - cleaned up the event loop to reduce CPU spinning
+
+kii-1-1: 
+  - cleaned up the update / refresh process to correctly handle
+    uncovered portions.
+  - cleaned up the event loop to handle slow traffic better
+  - cleanup up the cursor event loop in the same way
+  - fixed crash on non-printing cursor keys
+
+kii-1-0:
+  imported to CVS 
Index: /branches/eam_branch_20080223/Ohana/src/kii/doc/VERSIONS
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/doc/VERSIONS	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/doc/VERSIONS	(revision 16632)
@@ -0,0 +1,9 @@
+
+tag names used by kapa:
+
+TAG         : Comment
+kii-1-0     : first version under CVS
+
+USES
+libfits-1-0
+libohana-1-0
Index: /branches/eam_branch_20080223/Ohana/src/kii/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/doc/notes.txt	(revision 16632)
@@ -0,0 +1,29 @@
+
+2005.12.05
+
+  I have been making some improvements to Kapa / Kii, and am
+  planning on further advances.  Here are some of the features
+  I'd like to add:
+
+  - library function calls (see libfuncs.txt)
+
+  - named plotting styles (line, histogram, points)
+  - add y-based histogram 
+  - move point-to-point to a style
+  - explore standard colormaps to get better greyscale
+  - merge kapa and kii common code?
+  - kapa / kii device Number in title bar
+
+  - complete kapa plotting features in kii 
+  - axis labels on kii image
+  - kapa (and kii) axis labels, frame in color
+  - image-plotting in kapa
+
+  - three selectable kii image buffers
+  - true-color kii representation 
+  
+  - color PS for kii (currently only B&W)
+  - refresh picture after new colormap
+  - DVO regions corresponding to Kapa 'sections' on any window
+
+  - push argv/argc entries all into args, push options into globals.
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/CheckPipe.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/CheckPipe.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/CheckPipe.c	(revision 16632)
@@ -0,0 +1,140 @@
+# include "Ximage.h"
+# define STRCONST(A) ((int)(0x1000000*A[0] + 0x10000*A[1] + 0x100*A[2] + 0x1*A[3]))
+# define DEBUG 0
+
+static int ActiveCursor = FALSE;
+
+int CheckPipe (Graphic *graphic, Layout *layout) {
+
+  int status;
+  char buffer[20];
+
+  /* attempt to read 4 bytes from stdin */
+  bzero (buffer, 20);
+  status = read (layout[0].Ximage, buffer, 4);
+  buffer[4] = 0;
+
+  switch (status) {
+  case -1:
+    /* no input from pipe: continue */
+    return (TRUE);
+    break;
+
+  case 0:
+    fprintf (stderr, "pipe has died!\n");
+    return (FALSE);
+    break;
+
+  case 4:
+    if (DEBUG) fprintf (stderr, "got signal %s from pipe\n", buffer);
+    break;
+
+  default:
+    fprintf (stderr, "weird signal: too many or few bytes!  %d\n", status);
+    return (TRUE);
+    break;
+  }
+  
+  /* In Active Cursor mode, we can only receive the NCUR signal */
+  if (ActiveCursor) {
+    if (!strcmp (buffer, "NCUR")) {
+      ActiveCursor = FALSE;
+      return (2);
+    }
+    fprintf (stderr, "unknown signal (AC) %s\n", buffer);
+    return (TRUE);
+  }
+
+  /* If Active Cursor mode is off, we can receive other signal */
+  if (!strcmp (buffer, "QUIT")) {
+    if (DEBUG) fprintf (stderr, "Goodbye!\n");
+    return (FALSE);
+  }
+  
+  if (!strcmp (buffer, "READ")) {
+    status = NewPicture (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CURS")) {
+    ActiveCursor = TRUE;
+    status = cursor (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "NCUR")) {
+    fprintf (stderr, "error: not in active cursor mode\n");
+    return (TRUE);
+  }
+
+  if (!strcmp (buffer, "ERAS")) {
+    status = EraseOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "LOAD")) {
+    status = LoadOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "TICK")) {
+    status = LoadTickmarks (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "SAVE")) {
+    status = SaveOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "PSIT")) {
+    /** this one needs work : ConvertPixmapN fails for !USE_XWINDOW */
+    status = PSit (graphic, layout, 0);
+    write (layout[0].Ximage, "DONE", 4);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "PSRW")) {
+    /** this one needs work : ConvertPixmapN fails for !USE_XWINDOW */
+    status = PSit (graphic, layout, 1);
+    write (layout[0].Ximage, "DONE", 4);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "JPEG")) {
+    status = JPEGit24 (graphic, layout);
+    write (layout[0].Ximage, "DONE", 4);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "RSIZ")) {
+    status = Resize (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CSVE")) {
+    status = CSaveOverlay (graphic, layout);
+    return (status);
+  }
+
+  if (!strcmp (buffer, "CENT")) {
+    status = Center (graphic, layout);
+    return (status);
+  }
+
+  /* is this no longer used ?
+  if (!strcmp (buffer, "NPIX")) {
+    sprintf (buffer, "NPIX:   %8d", layout[0].Npixels);
+    write (layout[0].Ximage, buffer, 16);
+    return (TRUE);
+  }
+  */
+
+  fprintf (stderr, "unknown signal %s\n", buffer);
+
+  return (TRUE);
+
+}
+
+
+    
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/EventLoop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/EventLoop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/EventLoop.c	(revision 16632)
@@ -0,0 +1,80 @@
+# include "Ximage.h"
+
+/* # define IgnoreMask (long) (ClientMessage | ButtonReleaseMask) */
+# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | PointerMotionMask))
+
+int LastEvent (Display *display, int type, XEvent *event) {
+
+  int found;
+
+  found = FALSE;
+  while (XCheckTypedEvent (display, type, event)) {
+    found = TRUE;
+  }
+  return (found);
+}
+
+int EventLoop (Graphic *graphic, Layout *layout) {
+  
+  XEvent          event;
+  int             status;
+  Display        *display;
+  
+  if (USE_XWINDOW) Refresh (graphic, layout, 1);
+
+  status = TRUE;
+  while (status) {
+    
+    if (!CheckPipe (graphic, layout))
+      return (FALSE);
+    
+    if (!USE_XWINDOW) {
+      usleep (50000);
+      continue;
+    }
+
+    if (XEventsQueued (graphic[0].display, QueuedAfterFlush) < 1) {
+      usleep (10000);
+      continue;
+    }
+
+    display = graphic[0].display;
+
+    /* grab the last entry for these events */
+    if (LastEvent (display, ConfigureNotify, &event)) Reconfig (graphic, layout, &event);
+    if (LastEvent (display, CirculateNotify, &event)) Reconfig (graphic, layout, &event);
+    if (LastEvent (display, Expose,          &event)) Refresh (graphic, layout, 1);
+    if (LastEvent (display, MotionNotify,    &event)) UpdatePointer (graphic, layout, (XMotionEvent *) &event);
+    if (LastEvent (display, ButtonPress,     &event)) InterpretPresses (graphic, layout, (XButtonEvent *) &event);
+    if (LastEvent (display, KeyPress,        &event)) InterpretKeys (graphic, layout, &event);
+
+    if (LastEvent (display, MappingNotify,   &event)) XRefreshKeyboardMapping ((XMappingEvent *) &event);
+
+    /* drop and ignore the following StructureNotifyMask events */
+    LastEvent (display, GravityNotify, &event);
+    LastEvent (display, ReparentNotify, &event);
+    LastEvent (display, MapNotify, &event);
+    LastEvent (display, UnmapNotify, &event);
+
+    /* remove those events we will ignore */
+    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;
+
+    /* events to remove which have no mask component */
+    while (XCheckTypedEvent (display, MappingNotify, &event)) continue;
+    while (XCheckTypedEvent (display, ClientMessage, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionClear, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionNotify, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionRequest, &event)) continue;
+  }
+  return (status);
+}
+
+# if (0)
+/* WARNING: this is defined because the HP UX installation i have does not
+seem to know this structure, though it should.  Clearly a need for autoconf.. */
+struct Ktimeval {
+  unsigned long tv_sec;         /* seconds */
+  long          tv_usec;        /* and microseconds */
+};
+# endif
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/FlushDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/FlushDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/FlushDisplay.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "Ximage.h"
+
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+void FlushDisplay (Display *display) {
+
+  struct timeval now;
+  int flush;
+  double dtime;
+
+  flush = FALSE;
+  if (!reftimeset) {
+    flush = TRUE;
+    gettimeofday (&reftime, NULL);
+  } 
+
+  gettimeofday (&now, NULL);
+  dtime = DTIME (now, reftime);
+
+  if (dtime > 0.1) {
+    flush = TRUE;
+  }
+
+  if (flush) {
+    XFlush (display);
+    reftime = now;
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/InterpretKeys.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/InterpretKeys.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/InterpretKeys.c	(revision 16632)
@@ -0,0 +1,82 @@
+# include "Ximage.h"
+
+int InterpretKeys (Graphic *graphic, Layout *layout, XEvent *event) {
+
+  double X, Y, offset;
+  int    modstate;
+  char   string[10];
+  KeySym keysym;
+  XComposeStatus  composestatus;
+  XKeyEvent *keyevent;
+
+  keyevent = (XKeyEvent *) event;
+  XLookupString (keyevent, string, 9, &keysym, &composestatus);
+  modstate = keyevent[0].state;
+
+  // offset is in image pixels: 
+  // 0.5 image pixels is 1 screen pixel for expand == +2
+  // 2.0 image pixels is 1 screen pixel for expand == -2
+  if (layout[0].expand == 0) layout[0].expand = 1;
+  offset = (layout[0].expand > 0) ? 1.0 / layout[0].expand : -layout[0].expand;
+  if (modstate & ControlMask) offset *= 100;
+
+  switch (keysym) {
+
+    case XK_KP_Home:
+    case XK_Home:
+      layout[0].expand = 1;
+      Reorient (graphic, layout, layout[0].X, layout[0].Y, 0);
+      break;
+    case XK_KP_End:
+    case XK_End:
+      layout[0].expand = 1;
+      Reorient (graphic, layout, 0, 0, 0);
+      break;
+    case XK_KP_Enter:
+    case XK_KP_Begin:
+    case XK_Return:
+      Screen_to_Image (&X, &Y, (double)keyevent[0].x, (double)keyevent[0].y, layout);
+      X = 0.5*layout[0].matrix.Naxis[0] - X;
+      Y = 0.5*layout[0].matrix.Naxis[1] - Y;
+      Reorient (graphic, layout, X, Y, 0);
+      break;
+    case XK_Prior:
+    case XK_KP_Prior:
+      Reorient (graphic, layout, layout[0].X, layout[0].Y, +1);
+      break;
+    case XK_Next:
+    case XK_KP_Next:
+      Reorient (graphic, layout, layout[0].X, layout[0].Y, -1);
+      break;
+    case XK_Up:
+    case XK_KP_Up:
+      Reorient (graphic, layout, layout[0].X, layout[0].Y + offset, 0);
+      break;
+    case XK_Down:
+    case XK_KP_Down:
+      Reorient (graphic, layout, layout[0].X, layout[0].Y - offset, 0);
+      break;
+    case XK_Left:
+    case XK_KP_Left:
+      Reorient (graphic, layout, layout[0].X + offset, layout[0].Y, 0);
+      break;
+    case XK_Right:
+    case XK_KP_Right:
+      Reorient (graphic, layout, layout[0].X - offset, layout[0].Y, 0);
+      break;
+
+    case XK_Tab:
+      MOVE_POINTER = MOVE_POINTER ^ TRUE;
+      if (MOVE_POINTER) UpdatePointer (graphic, layout, (XMotionEvent *)event);
+      break;
+  }
+
+  return (TRUE);
+}
+
+/* other keys we might want to use:
+
+  
+
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/InterpretPresses.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/InterpretPresses.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/InterpretPresses.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+
+int InterpretPresses (Graphic *graphic, Layout *layout, XButtonEvent *event) {
+
+  int             status, done, this_button;
+  Button         *button;
+
+  status = TRUE;
+  this_button = event[0].button;
+  
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].picture)) {
+    ReorientOnButton (graphic, layout, event);
+  }
+
+  if ((event[0].type == ButtonPress) && InPicture (event, &layout[0].cmapbar)) {
+    DragColorbar (graphic, layout, event);
+  }
+
+  /* if on an exisiting button, Invert, wait for release, then go (or not) */
+  if ((button = CheckButtons (event, layout)) != (Button *) NULL) {
+    InvertButton (graphic, button); 
+    done = FALSE;
+    while (!done) { /* wait for release of this button */
+      XNextEvent (graphic[0].display, (XEvent *) event);
+      if ((event[0].type == ButtonRelease) && (event[0].button == this_button)) {
+	done = TRUE;
+      }
+    }
+    DrawButton (graphic, button);
+    if (InButton (event, button)) {
+      switch (event[0].button) {
+      case 1:
+	status = button[0].function_1(graphic, layout);
+	break;
+      case 2:
+	status = button[0].function_2(graphic, layout);
+	break;
+      case 3:
+	status = button[0].function_3(graphic, layout);
+	break;
+      }
+    }
+    else {
+      return (status);
+    }
+  }
+
+  return (status);
+
+}
+
+void ReorientOnButton (Graphic *graphic, Layout *layout, XButtonEvent *mouse_event) {
+
+  double X, Y;
+
+  Screen_to_Image (&X, &Y, (double)mouse_event[0].x, (double)mouse_event[0].y, layout);
+  X = 0.5*layout[0].matrix.Naxis[0] - X;
+  Y = 0.5*layout[0].matrix.Naxis[1] - Y;
+
+  switch (mouse_event[0].button) {
+    case 1:
+      Reorient (graphic, layout, X, Y, 0);
+      break;
+    case 2:
+      Reorient (graphic, layout, X, Y, -1);
+      break;
+    case 3:
+      Reorient (graphic, layout, X, Y, +1);
+      break;
+    default:
+      break;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/NextEvent.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/NextEvent.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/NextEvent.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+/************** NextEvent *************/
+void
+NextEvent (graphic, event, keysym)
+Graphic graphic[];
+XEvent *event;
+KeySym *keysym;
+{
+  int status;
+
+  status = FALSE;
+
+  while (!status) {
+    XNextEvent (graphic[0].display, event);
+    status = ParseEvent (graphic, event, keysym);
+  }
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/ParseEvent.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/ParseEvent.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/ParseEvent.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "Ximage.h"
+
+/************** ParseEvent *************/
+int
+ParseEvent (graphic, event, keysym)
+Graphic graphic[];
+XEvent *event;
+KeySym *keysym;
+{
+
+  XComposeStatus composestatus;
+  char string[10];
+  int status;
+ 
+  status = FALSE;
+  switch (event[0].type) {
+  case ButtonPress:
+    status = TRUE;
+    break;
+  case ButtonRelease:
+    status = TRUE;
+    break;
+  case ClientMessage:
+    status = TRUE;
+    break;
+  case MotionNotify:
+    status = TRUE;
+    break;
+  case PropertyNotify:
+    status = TRUE;
+    break;
+  case SelectionClear:
+    status = TRUE;
+    break;
+  case SelectionNotify:
+    status = TRUE;
+    break;
+  case SelectionRequest:
+    status = TRUE;
+    break;
+  case ConfigureNotify:
+    if ((graphic[0].dx != event[0].xconfigure.width) || 
+	(graphic[0].dy != event[0].xconfigure.height))
+      status = TRUE;
+    break;
+  case Expose:
+    status = TRUE;
+    if (event[0].xexpose.count != 0)
+      status = FALSE;
+    break;
+  case KeyPress:
+    status = TRUE;
+    XLookupString ((XKeyEvent *)event, string, 9, keysym, &composestatus);
+    break;
+  case MappingNotify:
+    XRefreshKeyboardMapping ((XMappingEvent *)event);
+    break;
+  }
+
+  return (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/Reconfig.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/Reconfig.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/Reconfig.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+# define MAX_STRING 100
+
+int Reconfig (Graphic *graphic, Layout *layout, XEvent *event) {
+  
+  if ((graphic[0].dx == event[0].xconfigure.width) &&
+      (graphic[0].dy == event[0].xconfigure.height)) 
+    return (TRUE);
+
+  graphic[0].dx = MAX(event[0].xconfigure.width,  MIN_WIDTH); 
+  graphic[0].dy = MAX(event[0].xconfigure.height, MIN_HEIGHT);
+
+  XClearWindow (graphic[0].display, graphic[0].window);
+  PositionPictures (layout, graphic);
+  CreateColorbar (layout, graphic);
+  CreatePicture (layout, graphic);
+  Remap (graphic, layout, &layout[0].matrix); 
+  Refresh (graphic, layout, 1);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/Refresh.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/Refresh.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/Refresh.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "Ximage.h"
+# define NPOINTS 10
+
+void Refresh (Graphic *graphic, Layout *layout, int mode) {
+
+  int i;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, layout[0].black);
+  XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		  layout[0].picture.x, layout[0].picture.y, 
+		  layout[0].picture.dx + 1, layout[0].picture.dy + 1);
+  
+  XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	     layout[0].picture.pix, 0, 0, 
+	     layout[0].picture.x + 1, layout[0].picture.y + 1, 
+	     layout[0].picture.dx, layout[0].picture.dy);
+
+  XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	     layout[0].cmapbar.pix, 0, 0, 
+	     layout[0].cmapbar.x, layout[0].cmapbar.y, 
+	     layout[0].cmapbar.dx, layout[0].cmapbar.dy);
+
+  CrossHairs (graphic, layout);
+
+  for (i = 0; i < NOVERLAYS; i++) {
+    if (OVERLAY[i])
+      PaintOverlay (graphic, layout, i);
+  }
+  PaintTickmarks (graphic, layout);
+
+  if (mode == 1) {
+    /* erase everything below zoom box, then draw */
+    XSetForeground (graphic[0].display, graphic[0].gc, layout[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    layout[0].text_x, layout[0].text_x, layout[0].zoom.dx, graphic[0].dy); 
+    
+    DrawButton (graphic, &layout[0].PS_button);
+    DrawButton (graphic, &layout[0].recenter_button);
+    DrawButton (graphic, &layout[0].grey_button);
+    DrawButton (graphic, &layout[0].rainbow_button);
+    DrawButton (graphic, &layout[0].puns_button);
+    DrawButton (graphic, &layout[0].hms_button);
+
+    for (i = 0; i < NOVERLAYS; i++) {
+      DrawButton (graphic, &layout[0].overlay_button[i]);
+    }
+  }
+
+  StatusBox (graphic, layout);
+
+  FlushDisplay (graphic[0].display);
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/event/Stop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/event/Stop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/event/Stop.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+
+int
+Stop (graphic, layout)
+Graphic   graphic[];
+Layout    layout[];
+{
+  return (FALSE);
+}
+
+
+
+
+
+
+/******  this function looks stupid, but it has to be like this:
+  it is called as a pointer to function **/
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/Ximage.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/Ximage.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/Ximage.h	(revision 16632)
@@ -0,0 +1,8 @@
+# include <Xohana.h>
+# include <dvo.h>
+# include <kapa.h>
+# include "constants.h"
+# include "structures.h"
+# include "prototypes.h"
+
+/* dvo.h is used only for Coords */
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/buttons.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/buttons.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/buttons.h	(revision 16632)
@@ -0,0 +1,120 @@
+#define PS_width 25
+#define PS_height 25
+static char PS_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x81, 0x3f, 0x00,
+   0x82, 0x67, 0x60, 0x00, 0x02, 0x26, 0x40, 0x00, 0x02, 0x24, 0x40, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00, 0x02, 0x24, 0x00, 0x00,
+   0x02, 0x24, 0x00, 0x00, 0x02, 0x64, 0x00, 0x00, 0x02, 0xc6, 0x00, 0x00,
+   0x82, 0x07, 0x07, 0x00, 0xfe, 0x01, 0x0c, 0x00, 0x02, 0x00, 0x18, 0x00,
+   0x02, 0x00, 0x20, 0x00, 0x02, 0x00, 0x60, 0x00, 0x02, 0x00, 0x40, 0x00,
+   0x02, 0x00, 0xc0, 0x00, 0x02, 0x10, 0x80, 0x00, 0x02, 0x10, 0xc0, 0x00,
+   0x02, 0x60, 0x60, 0x00, 0x02, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00}; 
+#define grey_width 25
+#define grey_height 25
+static char grey_bits[] = {
+   0x90, 0x40, 0xf7, 0x01, 0x04, 0xaa, 0xad, 0x01, 0x68, 0xd5, 0xfe, 0x01,
+   0x82, 0x28, 0xdb, 0x01, 0x10, 0xd2, 0x75, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xac, 0x50, 0xbf, 0x01, 0x00, 0xaa, 0xf9, 0x01, 0x52, 0xd5, 0xd6, 0x01,
+   0x80, 0x28, 0x6f, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x44, 0xad, 0xba, 0x01,
+   0x90, 0x50, 0xf7, 0x01, 0x02, 0xaa, 0xcd, 0x01, 0x68, 0xd5, 0x7e, 0x01,
+   0x80, 0x28, 0xfb, 0x01, 0x14, 0xd2, 0xb5, 0x01, 0x40, 0xad, 0xee, 0x01,
+   0xaa, 0x50, 0xdf, 0x01, 0x00, 0xaa, 0x79, 0x01, 0x50, 0xd5, 0xf6, 0x01,
+   0x84, 0x28, 0xaf, 0x01, 0x28, 0xd2, 0xfd, 0x01, 0x40, 0xad, 0xda, 0x01,
+   0x90, 0x50, 0x77, 0x01};
+#define rainbow_width 25
+#define rainbow_height 25
+static char rainbow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x80, 0xff, 0x00, 0x00, 0x70, 0x00, 0x01, 0x00, 0x0c, 0x7f, 0x00,
+   0x00, 0xe3, 0x80, 0x01, 0xc0, 0x9c, 0xff, 0x00, 0x20, 0x62, 0x00, 0x01,
+   0x90, 0x99, 0xff, 0x00, 0x48, 0x76, 0x00, 0x01, 0x24, 0x09, 0x00, 0x00,
+   0x94, 0x06, 0x00, 0x00, 0x52, 0x01, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
+   0xa5, 0x00, 0x00, 0x00, 0x55, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00,
+   0x2a, 0x00, 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00,
+   0x15, 0x00, 0x00, 0x00};
+#define recenter_width 25
+#define recenter_height 25
+static char recenter_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0xe0, 0x00, 0x0e, 0x00, 0x30, 0x00, 0x18, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x30, 0x00, 0x08, 0x00, 0x20, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00, 0x0c, 0x7c, 0x60, 0x00,
+   0x04, 0x7c, 0x40, 0x00, 0x0c, 0x7c, 0x60, 0x00, 0x0c, 0x38, 0x60, 0x00,
+   0x0c, 0x00, 0x60, 0x00, 0x08, 0x00, 0x20, 0x00, 0x18, 0x00, 0x30, 0x00,
+   0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x0e, 0x00,
+   0x80, 0xef, 0x03, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define puns_width 25
+#define puns_height 25
+static char puns_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0xd8, 0x01,
+   0x00, 0x0c, 0x37, 0x00, 0xf8, 0xc9, 0x6f, 0x00, 0x0c, 0xde, 0xf0, 0x00,
+   0x06, 0x5b, 0x1f, 0x00, 0x7b, 0xd9, 0x0c, 0x00, 0xc9, 0x70, 0x06, 0x00,
+   0x81, 0x71, 0x03, 0x00, 0x78, 0xb9, 0x39, 0x00, 0xc8, 0xdb, 0x0f, 0x00,
+   0x84, 0xf7, 0x7f, 0x00, 0x04, 0xff, 0xc3, 0x00, 0xe6, 0xfe, 0x8e, 0x00,
+   0x9a, 0x7d, 0x0b, 0x00, 0x08, 0xbc, 0x01, 0x00, 0x08, 0xfc, 0x3f, 0x00,
+   0x0c, 0xff, 0x78, 0x00, 0x84, 0x39, 0x60, 0x00, 0x40, 0x38, 0x40, 0x00,
+   0x60, 0x38, 0x40, 0x00, 0x20, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 0x00,
+   0x00, 0xd6, 0x00, 0x00};
+#define red_width 25
+#define red_height 25
+static char red_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xfc, 0x03, 0x00,
+   0x20, 0x07, 0x06, 0x00, 0xe0, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00, 0x20, 0x00, 0x08, 0x00,
+   0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x06, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0xe0, 0x00, 0x00, 0x20, 0x7e, 0x00, 0x00, 0xe0, 0xc3, 0x00, 0x00,
+   0x20, 0xc0, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0x80, 0x01, 0x00,
+   0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x20, 0x00, 0x03, 0x00,
+   0x20, 0x00, 0x06, 0x00, 0x20, 0x00, 0x0c, 0x00, 0x20, 0x00, 0x18, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define green_width 25
+#define green_height 25
+static char green_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00,
+   0x00, 0x06, 0x04, 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0x40, 0x80, 0x0f, 0x00, 0x40, 0xc0, 0x30, 0x00,
+   0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00,
+   0x40, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x08, 0x00,
+   0x00, 0x03, 0x08, 0x00, 0x00, 0x7e, 0x0e, 0x00, 0x00, 0xc0, 0x03, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define blue_width 25
+#define blue_height 25
+static char blue_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xfe, 0x00, 0x00,
+   0xc0, 0x83, 0x07, 0x00, 0xc0, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x04, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0x40, 0x80, 0x07, 0x00, 0x40, 0xe0, 0x0c, 0x00, 0xc0, 0x3f, 0x08, 0x00,
+   0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00, 0x40, 0x00, 0x08, 0x00,
+   0x40, 0x00, 0x0c, 0x00, 0x40, 0x00, 0x06, 0x00, 0x40, 0x00, 0x02, 0x00,
+   0xc0, 0x80, 0x03, 0x00, 0x40, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define yellow_width 25
+#define yellow_height 25
+static char yellow_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x18, 0x00,
+   0x80, 0x01, 0x0c, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0x02, 0x02, 0x00,
+   0x00, 0x84, 0x01, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x58, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x10, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x20, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+   0x00, 0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x00, 0x00, 0x00, 0x00};
+#define hms_width 25
+#define hms_height 25
+static char hms_bits[] = {
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+   0x02, 0x00, 0x00, 0x00, 0x02, 0x01, 0xf0, 0x00, 0x1e, 0xef, 0x89, 0x00,
+   0x22, 0x11, 0x09, 0x00, 0x22, 0x11, 0x71, 0x00, 0x22, 0x11, 0x81, 0x00,
+   0x22, 0x11, 0x89, 0x00, 0x22, 0x01, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00,
+   0x1e, 0xc7, 0xf1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0x80, 0x00,
+   0x40, 0x80, 0x80, 0x00, 0x5c, 0xb8, 0xb8, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x42, 0x84, 0x84, 0x00, 0x42, 0x84, 0x84, 0x00, 0x62, 0xc4, 0xc4, 0x00,
+   0x5c, 0xb9, 0xb8, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/constants.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/constants.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/constants.h	(revision 16632)
@@ -0,0 +1,58 @@
+# define PAD1  5
+# define PAD2  3
+# define TEXTPAD 25
+# define COLORPAD 10
+# define TEXT_Y 15
+# define ZOOM_X 170
+# define ZOOM_Y 170
+# define NOVERLAYS 4
+/* number of overlays is defined here.
+   the number is also crucial in the following files:
+   PositionPictures.c
+   MakeColormap.c
+   prototypes.h
+*/
+
+# define DEFAULT_CURSOR XC_crosshair
+# define BORDER_WIDTH 2
+# define MIN_WIDTH 10
+# define MIN_HEIGHT 20
+# define AssignText(X,T) allocate (X, char, strlen (T)); strcpy (X, T);
+# define AssignData(X,T,N) allocate (X, char, N); bcopy (T, X, N);
+
+int OVERLAY[NOVERLAYS];
+int MOVE_POINTER;
+int DECIMAL_DEG;
+int DEBUG;
+int FOREGROUND;
+int USE_XWINDOW;
+int MAP_WINDOW;
+char *NAME_WINDOW;
+
+# define EVENT_MASK (long) \
+(ButtonPressMask \
+ | ClientMessage \
+ | ButtonReleaseMask \
+ | KeyPressMask \
+ | ExposureMask \
+ | StructureNotifyMask \
+ | PointerMotionMask)
+
+/* EVENT_MASK consists of:
+
+ExposureMask        : Expose
+StructureNotifyMask : CirculateNotify | 
+                      ConfigureNotify | 
+                      DestroyNotify   | 
+		      GravityNotify   | 
+		      MapNotify       |
+		      ReparentNotify  |
+		      UnmapNotify
+ButtonPressMask     : ButtonPress
+ButtonReleaseMask   : ButtonRelease
+KeyPressMask        : KeyPress
+PointerMotionMask   : MotionNotify
+(always)            : ClientMessage 
+(always)            : MappingNotify
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/icons/arrow.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/icons/arrow.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/icons/arrow.h	(revision 16632)
@@ -0,0 +1,4 @@
+#define arrow_width 6
+#define arrow_height 9
+static char arrow_bits[] = {
+   0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/icons/back.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/icons/back.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/icons/back.h	(revision 16632)
@@ -0,0 +1,6 @@
+#define back_width 16
+#define back_height 16
+static char back_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x3f, 0xc0, 0x3f,
+   0xf0, 0x3f, 0xfc, 0x3f, 0xfc, 0x3f, 0xf0, 0x3f, 0xc0, 0x3f, 0x00, 0x3f,
+   0x00, 0x3c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/icons/down.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/icons/down.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/icons/down.h	(revision 16632)
@@ -0,0 +1,4 @@
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/icons/fore.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/icons/fore.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/icons/fore.h	(revision 16632)
@@ -0,0 +1,6 @@
+#define fore_width 16
+#define fore_height 16
+static char fore_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x3c, 0x00, 0xfc, 0x00, 0xfc, 0x03,
+   0xfc, 0x0f, 0xfc, 0x3f, 0xfc, 0x3f, 0xfc, 0x0f, 0xfc, 0x03, 0xfc, 0x00,
+   0x3c, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/icons/icon.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/icons/icon.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/icons/icon.h	(revision 16632)
@@ -0,0 +1,13 @@
+#define icon_width 30
+#define icon_height 30
+static char icon_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00,
+   0x00, 0xfe, 0x0f, 0x00, 0x00, 0xff, 0x1f, 0x00, 0xc0, 0x0f, 0x7e, 0x00,
+   0xe0, 0x01, 0xf0, 0x00, 0xe0, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff, 0x01,
+   0xb8, 0xff, 0xbf, 0x03, 0xb8, 0x03, 0xb8, 0x03, 0xb8, 0xe3, 0xb8, 0x03,
+   0x9c, 0xf3, 0x39, 0x07, 0x9c, 0xfb, 0x3b, 0x07, 0x9c, 0xfb, 0x3b, 0x07,
+   0x9c, 0xfb, 0x3b, 0x07, 0x9c, 0xf3, 0x39, 0x07, 0xb8, 0xe3, 0xb8, 0x03,
+   0xb8, 0x03, 0xb8, 0x03, 0xb8, 0xff, 0xbf, 0x03, 0xf0, 0xff, 0xff, 0x01,
+   0xe0, 0xff, 0xff, 0x00, 0xe0, 0x01, 0xf0, 0x00, 0xc0, 0x0f, 0x7e, 0x00,
+   0x00, 0xff, 0x1f, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xf0, 0x01, 0x00,
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/icons/stop.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/icons/stop.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/icons/stop.h	(revision 16632)
@@ -0,0 +1,6 @@
+#define stop_width 16
+#define stop_height 16
+static char stop_bits[] = {
+   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
+   0xf8, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/prototypes.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/prototypes.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/prototypes.h	(revision 16632)
@@ -0,0 +1,116 @@
+
+int args (int *argc, char **argv);
+
+void bDrawOverlay (Layout *layout, int N);
+
+int SetColormap (Graphic *graphic, Layout *layout, char *name);
+void FlushDisplay (Display *display);
+int Recenter (Graphic *graphic, Layout *layout);
+void DrawOverlay (Graphic *graphic, Layout *layout, int N, FILE *f, int extra);
+int cursor (Graphic *graphic, Layout *layout);
+int PSit (Graphic *graphic, Layout *layout, int Raw);
+int JPEGit (Graphic *graphic, Layout *layout);
+int JPEGit24 (Graphic *graphic, Layout *layout);
+int Resize (Graphic *graphic, Layout *layout);
+int Center (Graphic *graphic, Layout *layout);
+int LoadTickmarks (Graphic *graphic, Layout *layout);
+void PaintTickmarks (Graphic *graphic, Layout *layout);
+void Screen_to_Image (double *x1, double *y1, double x2, double y2, Layout *layout);
+void Image_to_Screen (double *x1, double *y1, double x2, double y2, Layout *layout);
+void UpdateStatusBox (Graphic *graphic, Layout *layout, double x, double y, double z, int mode);
+void Remap8 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void Remap16 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void Remap24 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void Remap32 (Graphic *graphic, Layout *layout, Matrix *matrix);
+void CheckVisual (Graphic *graphic, int *argc, char **argv);
+void CreateZoom8 (Layout *layout, Graphic *graphic, double x, double y);
+void CreateZoom16 (Layout *layout, Graphic *graphic, double x, double y);
+void CreateZoom24 (Layout *layout, Graphic *graphic, double x, double y);
+void CreateZoom32 (Layout *layout, Graphic *graphic, double x, double y);
+
+void ConvertPixmap8  (Layout *layout, FILE *f);
+void ConvertPixmap16 (Layout *layout, FILE *f);
+void ConvertPixmap24 (Layout *layout, FILE *f);
+void ConvertPixmap32 (Layout *layout, FILE *f);
+
+
+/***** Prototypes for image ***************/
+
+void          PositionPictures    PROTO((Layout *, Graphic *));
+void          CreateColorbar      PROTO((Layout *, Graphic *));
+void          CreatePicture       PROTO((Layout *, Graphic *));
+void          CreateZoom          PROTO((Layout *, Graphic *, double, double));
+void          Remap               PROTO((Graphic *, Layout *, Matrix  *));
+int           NewPicture          PROTO((Graphic *, Layout *));
+void          Reorient            PROTO((Graphic *, Layout *, double, double, int));
+void          ReorientOnButton    PROTO((Graphic *, Layout *, XButtonEvent *));
+int           UpdatePointer       PROTO((Graphic *, Layout *, XMotionEvent *));
+void          CrossHairs          PROTO((Graphic *, Layout *));
+int           LoadOverlay         PROTO((Graphic *, Layout *));
+int           SaveOverlay         PROTO((Graphic *, Layout *));
+int           CSaveOverlay         PROTO((Graphic *, Layout *));
+int           EraseOverlay        PROTO((Graphic *, Layout *));
+void          StatusBox           PROTO((Graphic *, Layout *));
+void          PaintOverlay        PROTO((Graphic *, Layout *, int));
+
+/***** Prototypes for action ***************/
+
+int           CheckPipe           PROTO((Graphic *, Layout *));
+void          DefineLayout        PROTO((Layout *, Graphic *, int, char **));
+int           EventLoop           PROTO((Graphic *, Layout *));
+int           InPicture           PROTO((XButtonEvent *, Picture *));
+int           InterpretKeys       PROTO((Graphic *, Layout *, XEvent *));
+int           InterpretPresses    PROTO((Graphic *, Layout *, XButtonEvent *));
+int           Reconfig            PROTO((Graphic *, Layout *, XEvent *));
+void          Refresh             PROTO((Graphic *, Layout *, int));
+int           Stop                PROTO((Graphic *, Layout *));
+int           PSit                PROTO((Graphic *, Layout *, int));
+int           get_argument        PROTO((int, char **, char *));
+int           remove_argument     PROTO((int, int *, char **));
+void          DragColorbar        PROTO((Graphic *, Layout *, XButtonEvent *));
+void          ResetColorbar       PROTO((Graphic *, Layout *, double, double));
+void          MakeColormap        PROTO((Graphic *, Layout *, int, char **));
+
+/***** Prototypes for button ***************/
+
+Button       *CheckButtons        PROTO((XButtonEvent *, Layout *));
+void          DrawButton          PROTO((Graphic *, Button *));
+void          FlashButton         PROTO((Graphic *, Button *));
+int           InButton            PROTO((XButtonEvent *, Button *));
+void          InvertButton        PROTO((Graphic *, Button *));
+int           greycolors          PROTO((Graphic *, Layout *));
+int           rainbow             PROTO((Graphic *, Layout *));
+int           puns                PROTO((Graphic *, Layout *));
+int           Recenter            PROTO((Graphic *, Layout *));
+int           RecenterRescale     PROTO((Graphic *, Layout *));
+int           Rescale             PROTO((Graphic *, Layout *));
+int           ToggleDEG           PROTO((Graphic *, Layout *));
+int           Overlay0            PROTO((Graphic *, Layout *));
+int           Overlay1            PROTO((Graphic *, Layout *));
+int           Overlay2            PROTO((Graphic *, Layout *));
+int           Overlay3            PROTO((Graphic *, Layout *));
+
+/***** Prototypes for xtools ***************/
+
+void          CheckColors         PROTO((Graphic *, int *, char **));
+void          CheckDisplayName    PROTO((int *, char **, char *));
+void          CheckFontName       PROTO((int *, char **, char *));
+void          CheckGeometry       PROTO((int *, char **, Graphic *));
+void          CloseDisplay        PROTO((Graphic *));
+void          CreateWindow        PROTO((Graphic *, Window, int, long));
+void          DrawBitmap          PROTO((Graphic *, int, int, int, int, char *, int));
+unsigned long GetColor            PROTO((Display *, char *, Colormap, unsigned long));
+void          LoadFont            PROTO((Graphic *, int *, char **, char *));
+void          MakeCursor          PROTO((Graphic *, unsigned int));
+void          MakeGC              PROTO((Graphic *));
+void          MapWindow           PROTO((Graphic *));
+void          NameWindow          PROTO((Graphic *, char *));
+Display      *OpenDisplay         PROTO((char *, int *));
+void          QuitX               PROTO((Display *, char *, char *));
+void          SetNormalHints      PROTO((Graphic *));
+void          SetUpDisplay        PROTO((Graphic *, int *, char **));
+void          SetUpWindow         PROTO((Graphic *, int *, char **));
+void          SetWMHints          PROTO((Graphic *, Icon *));
+void          TopWindow           PROTO((Graphic *, Icon *));
+
+void          hh_hms              PROTO((char *, double, double, char));
Index: /branches/eam_branch_20080223/Ohana/src/kii/include/structures.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/include/structures.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/include/structures.h	(revision 16632)
@@ -0,0 +1,128 @@
+/**************** Graphic carries X info around ****************/
+typedef struct {
+  Display       *display;
+  int            screen;
+  int            depth;
+  Window         window;
+  Visual        *visual;
+  int            visualclass;
+  GC             gc;
+  XFontStruct   *font;
+  Cursor         cursor;
+  int            x,  y;
+  int            dx, dy;
+  Colormap       colormap;
+  unsigned long  Npixels, pixels[256];
+  int            Nbits;
+  /*
+  unsigned long  fore;
+  unsigned long  back;
+  */
+  unsigned long  black, white;
+} Graphic;
+
+/**************** X related "widget" structures ****************/
+typedef struct {
+  int      x, y, dx, dy;      /* position and size */
+  int      text;              /* does this have a picture or text? */
+  int      width, height;
+  char    *bitmap;          /* picture on button */
+  int    (*function_1) ();  /* mouse_button 1 function */
+  int    (*function_2) ();  /* mouse_button 2 function */
+  int    (*function_3) ();  /* mouse_button 3 function */
+} Button;
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  char    *label;          /* label on TextLine */
+  char     text[1024];     /* words of TextLine */
+  char     old_text[1024]; /* words of TextLine */
+  int      outline;        /* draw an outline?  */ 
+  int      cursor;         /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextLine;
+
+typedef char STRING[1024];
+
+typedef struct {
+  int      x, y, dx, dy;   /* position and size */
+  STRING  *text;           /* words of TextLine */
+  int      Nlines;
+  int      outline;        /* draw an outline?  */ 
+  int      cursor_line;    /* cursor line */
+  int      cursor_x;       /* location of cursor (if selected) */
+  int      cursor_y;       /* location of cursor (if selected) */
+  int    (*function) ();   /* textline function */
+} TextBox;
+
+/**************** general structures ****************/
+typedef struct {
+  Pixmap pixmap;
+  int    width;
+  int    height;
+  char  *bits;
+} Icon;
+
+typedef struct {
+  int      dx, dy, x, y;
+  XImage  *pix;
+  char *data;
+} Picture;
+
+typedef struct {
+  char type[10];
+  double x, y;
+  double dx, dy;
+  double angle;
+  char  *text;
+} Object;
+
+typedef struct {
+  int Nobjects;
+  unsigned long color;
+  Object *objects;
+} Overlay;
+  
+/******** Here we define the Layout struct specific to this program  *******/
+typedef struct {
+  /* objects on the mana window */
+  Picture  picture;
+  Picture  cmapbar;
+  Picture  zoom;
+  Button   PS_button;
+  Button   recenter_button;
+  Button   hms_button; /* toggle HMS/DECIMAL mode (DECIMAL_DEG macro) */
+  Button   grey_button;
+  Button   rainbow_button;
+  Button   puns_button;
+  Button   overlay_button[NOVERLAYS];
+  Overlay  overlay[NOVERLAYS];
+  Overlay  tickmarks;
+  int      text_x, text_y;
+
+  /* file descriptor for socket connection to mana */
+  int Ximage; 
+
+  /* data mana needs */
+  Matrix   matrix;         /* data for picture */
+  double   X, Y;           /* image pixel at screen center */
+  int      expand;         /* zoomscale */
+  double   zero, range;    /* zero, range for picture to cmap */
+  double   max, min;       /* zero, range for data to z-value */
+  double   start, slope;   /* zero, range for cmap to pixels */
+  double   x, y, z;        /* last pointer coords */
+  Coords   coords;
+  char     file[1024];     /* name of file */
+  char     buffer_name[1024];  /* name of buffer */
+
+  /* fundamental pieces */
+  unsigned long  black;
+  unsigned long  white;
+  XColor   cmap[256];
+  int      Npixels;
+
+} Layout;
+
+/* this routine is independent of the number of overlays */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/misc/hh_hms.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/misc/hh_hms.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/misc/hh_hms.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+void hh_hms (char *line, double ra, double dec, char sep) {
+
+  int h, m, flag;
+  double s;
+  
+  ra /= 15.0;  /* convert from degrees to hours */
+  flag = SIGN(ra);
+  ra *= flag;
+  h = ra;
+  m = 60.000001*(ra - h);
+  s = 3600*(ra - h - m / 60.0);
+  if (flag > 0)
+    sprintf (line, " %02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  else
+    sprintf (line, "-%02d%c%02d%c%04.1f  ", h, sep, m, sep, s);
+  
+  flag = SIGN(dec);
+  dec *= flag;
+  h = dec;
+  m = 60.000001*(dec - h);
+  s = 3600*(dec - h - m / 60.0);
+  if (flag > 0)
+    sprintf (&line[13], " %02d%c%02d%c%04.1f", h, sep, m, sep, s);
+  else
+    sprintf (&line[13], "-%02d%c%02d%c%04.1f", h, sep, m, sep, s);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/CSaveOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/CSaveOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/CSaveOverlay.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "Ximage.h"
+
+/*************/
+int CSaveOverlay (Graphic *graphic, Layout *layout) {
+
+  char buffer[256], filename[256];
+  int i, status, Nbytes, N;
+  double ra, dec, ra1, dec1, x1, y1, dra, ddec;
+  FILE *f;
+
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &Nbytes); 
+  status = read (layout[0].Ximage, buffer, Nbytes); 
+  buffer[Nbytes] = 0; 
+  sscanf (buffer, "%*s %d %s", &N, filename);
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "LINE")) {
+      XY_to_RD (&ra, &dec, layout[0].overlay[N].objects[i].x, layout[0].overlay[N].objects[i].y, &layout[0].coords);
+      x1 = layout[0].overlay[N].objects[i].x + layout[0].overlay[N].objects[i].dx;
+      y1 = layout[0].overlay[N].objects[i].y + layout[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &layout[0].coords);
+      dra = (ra1 - ra);
+      ddec = (dec1 - dec);
+    } else {
+      XY_to_RD (&ra, &dec, layout[0].overlay[N].objects[i].x, layout[0].overlay[N].objects[i].y, &layout[0].coords);
+      x1 = layout[0].overlay[N].objects[i].x;
+      y1 = layout[0].overlay[N].objects[i].y + layout[0].overlay[N].objects[i].dy;
+      XY_to_RD (&ra1, &dec1, x1, y1, &layout[0].coords);
+      ddec = fabs (dec1 - dec);
+      x1 = layout[0].overlay[N].objects[i].x + layout[0].overlay[N].objects[i].dx;
+      y1 = layout[0].overlay[N].objects[i].y;
+      XY_to_RD (&ra1, &dec1, x1, y1, &layout[0].coords);
+      dra = cos (dec*RAD_DEG) * fabs (ra1 - ra);
+    }
+    fprintf (f, "%s %lf %lf %lf %lf\n", layout[0].overlay[N].objects[i].type, ra, dec, dra, ddec);
+   }
+  fclose (f);
+  return (TRUE);
+}
+
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/DrawOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/DrawOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/DrawOverlay.c	(revision 16632)
@@ -0,0 +1,82 @@
+# include "Ximage.h"
+# define INFRONT 3
+
+void DrawOverlay (Graphic *graphic, Layout *layout, int N, FILE *f, int extra) {
+
+  int i;
+  double X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax;
+  double expand, X0, Y0;
+ 
+  expand = 1.0;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+  }
+  /*  
+  X0 =  (layout[0].X + 1 - 0.5*layout[0].matrix.Naxis[0])/expand + 0.5*layout[0].picture.dx;
+  Y0 =  (layout[0].Y + 1 - 0.5*layout[0].matrix.Naxis[1])/expand + 0.5*layout[0].picture.dy;
+  */
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, layout);
+  X0 -= layout[0].picture.x;
+  Y0 -= layout[0].picture.y;
+
+  Xmin = 0;
+  Ymin = 0;
+  Xmax = layout[0].picture.dx;
+  Ymax = layout[0].picture.dy;
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    if (N == INFRONT) {
+      X  = layout[0].overlay[N].objects[i].x * Xmax;
+      Y  = layout[0].overlay[N].objects[i].y * Ymax;
+      dX = layout[0].overlay[N].objects[i].dx * Xmax;
+      dY = layout[0].overlay[N].objects[i].dy * Ymax;
+    } else {
+      X  = (layout[0].overlay[N].objects[i].x)/expand + X0;
+      Y =  Ymax - (layout[0].overlay[N].objects[i].y)/expand - Y0;
+      dX = (layout[0].overlay[N].objects[i].dx)/expand;
+      dY = (layout[0].overlay[N].objects[i].dy)/expand;
+    }
+    
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "LINE")) {
+      if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	  ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, " %6.1f %6.1f %6.1f %6.1f L\n", X + extra, Y + extra, (X+dX + extra), (Y-dY + extra));
+      continue;
+    }
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "TEXT")) {
+      if (((X < Xmin) && (X + dX < Xmin)) || ((X > Xmax) && (X + dX > Xmax)) ||
+	  ((Y < Ymin) && (Y + dY < Ymin)) || ((Y > Ymax) && (Y + dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, "(%s) %6.1f %6.1f T\n", layout[0].overlay[N].objects[i].text, X + extra, Y + extra); 
+      continue;
+    }
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "BOX")) {
+      if (((X - 0.5*dX < Xmin) && (X + 0.5*dX < Xmin)) || ((X - 0.5*dX > Xmax) && (X + 0.5*dX > Xmax)) ||
+	  ((Y - 0.5*dY < Ymin) && (Y + 0.5*dY < Ymin)) || ((Y - 0.5*dY > Ymax) && (Y + 0.5*dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, " %6.1f %6.1f %6.1f %6.1f B\n", (dX + 2*extra), (dY + 2*extra), (X - 0.5*dX - extra), (Y - 0.5*dY - extra));
+      continue;
+    }
+    if (!strcmp (layout[0].overlay[N].objects[i].type, "CIRCLE")) {
+      if (((X - dX < Xmin) && (X + dX < Xmin)) || ((X - dX > Xmax) && (X + dX > Xmax)) ||
+	  ((Y - dY < Ymin) && (Y + dY < Ymin)) || ((Y - dY > Ymax) && (Y + dY > Ymax))) {
+	continue;
+      }
+      fprintf (f, " %6.1f %6.1f %6.1f C\n", X, Y, fabs(dX + extra));
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping\n", layout[0].overlay[N].objects[i].type);
+  }
+  
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/EraseOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/EraseOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/EraseOverlay.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+int EraseOverlay (Graphic *graphic, Layout *layout) {
+
+  char buffer[256];
+  int i, status, N;
+
+  fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &N); 
+  if (N > NOVERLAYS) {
+    REALLOCATE (layout[0].tickmarks.objects, Object, 1);
+    layout[0].tickmarks.Nobjects = 0;
+  } else {
+    for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+      if (!strcmp (layout[0].overlay[N].objects[i].type, "TEXT")) {
+	free (layout[0].overlay[N].objects[i].text);
+      }
+    }
+    REALLOCATE (layout[0].overlay[N].objects, Object, 1);
+    layout[0].overlay[N].Nobjects = 0;
+    OVERLAY[N] = FALSE;
+  }
+
+  if (USE_XWINDOW) Refresh (graphic, layout, 0);
+
+  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/LoadOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/LoadOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/LoadOverlay.c	(revision 16632)
@@ -0,0 +1,104 @@
+# include "Ximage.h"
+
+int LoadOverlay (graphic, layout)
+     Graphic graphic[];
+     Layout  layout[];
+{
+  
+  char line[17], *buffer, *buff, type[16], string[128];
+  double x, y, dx, dy;
+  int Nin, bytes, status;
+  int i, N, NOBJECTS, Nobjects, Nstart, done;
+
+  ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+  bzero (buffer, 65536);
+  done = FALSE;
+
+  fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+
+  status = read (layout[0].Ximage, line, 16); 
+  line[16] = 0; 
+  sscanf (line, "%*s %d", &N); 
+  Nstart = layout[0].overlay[N].Nobjects;
+
+  while (!done) {
+    status = read (layout[0].Ximage, line, 16); 
+    line[16] = 0; 
+    
+    if (!strncmp (line, "DONE", 4)) {
+      done = TRUE;
+      break;
+    }
+
+    if (!strncmp (line, "NLINES", 6)) {
+      sscanf (line, "%*s %d", &Nin);
+      buff = buffer;
+      bytes = 128*Nin;
+      fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+      while (bytes > 0) { 
+	status = read (layout[0].Ximage, buff, bytes);
+	if (status == 0) {  /* No more pipe */
+	  fprintf (stderr, "error: pipe closed\n");
+	  free (buffer);
+	  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+	  return (FALSE);
+	}
+	if (status != -1) { /* pipe has data */
+	  bytes -= status;
+	  buff = (char *)(buff + status);
+	}
+      }
+      fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+      /* parse buffer data */
+      NOBJECTS = layout[0].overlay[N].Nobjects + Nin;
+      Nobjects = layout[0].overlay[N].Nobjects;
+      REALLOCATE (layout[0].overlay[N].objects, Object, NOBJECTS);
+      for (i = 0; i < Nin; i++) {
+	sscanf (&buffer[i*128], "%s %lf %lf %lf %lf\n", type, &x, &y, &dx, &dy);
+
+	if (strcasecmp (type, "TEXT") && strcasecmp (type, "LINE") && strcasecmp (type, "BOX") && strcasecmp (type, "CIRCLE")) {  /* skip */
+	  fprintf (stderr, "don't know %s, skipping\n", type);
+	  continue;
+	}
+
+	if (!strcasecmp (type, "TEXT")) { /* end of objects */
+	  sscanf (&buffer[i*128], "%s %lf %lf %s\n", type, &x, &y, string);
+	}
+	
+	strcpy (layout[0].overlay[N].objects[Nobjects].type, type);
+	layout[0].overlay[N].objects[Nobjects].x = x;
+	layout[0].overlay[N].objects[Nobjects].y = y;
+	if (!strcmp (type, "TEXT")) {
+	  layout[0].overlay[N].objects[Nobjects].dx = 0;
+	  layout[0].overlay[N].objects[Nobjects].dy = 0;
+	  layout[0].overlay[N].objects[Nobjects].text = strcreate (string);
+	} else {
+	  layout[0].overlay[N].objects[Nobjects].dx = dx;
+	  layout[0].overlay[N].objects[Nobjects].dy = dy;
+	}
+	Nobjects++;
+      }
+      REALLOCATE (layout[0].overlay[N].objects, Object, MAX(Nobjects, 1));
+      layout[0].overlay[N].Nobjects = Nobjects;
+    }
+  }
+
+  free (buffer);
+  REALLOCATE (layout[0].overlay[N].objects, Object, MAX (1, layout[0].overlay[N].Nobjects));
+  OVERLAY[N] = TRUE;
+  /*  Refresh (graphic, layout, 0); */
+  if (USE_XWINDOW) {
+    for (i = 0; i < NOVERLAYS; i++) {
+      if (OVERLAY[i])
+	PaintOverlay (graphic, layout, i);
+    }
+    PaintTickmarks (graphic, layout);
+    XFlush (graphic[0].display);
+  }
+  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+  return (TRUE);
+
+}
+
+
+/* this routine is independent of the number of overlays */
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/LoadTickmarks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/LoadTickmarks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/LoadTickmarks.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "Ximage.h"
+
+int LoadTickmarks (Graphic *graphic, Layout *layout) {
+  
+  char line[129], type[16];
+  double x, y, dx, dy;
+  int status, NOBJECTS, Nobjects, done;
+
+  fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+
+  Nobjects = layout[0].tickmarks.Nobjects;
+  NOBJECTS = Nobjects + 100;
+  REALLOCATE (layout[0].tickmarks.objects, Object, NOBJECTS);
+  
+  done = FALSE;
+  while (!done) {
+    status = read (layout[0].Ximage, line, 128); 
+    line[128] = 0; 
+
+    if (!strncmp (line, "DONE", 4)) {
+      done = TRUE;
+      break;
+    }
+    
+    sscanf (line, "%s %lf %lf %lf %lf\n", type, &x, &y, &dx, &dy);
+    
+    if (strcmp (type, "TEXT") && strcmp (type, "LINE") && strcmp (type, "BOX") && strcmp (type, "CIRCLE")) {  /* skip */
+      fprintf (stderr, "don't know %s, skipping\n", type);
+      continue;
+    }
+    
+    strcpy (layout[0].tickmarks.objects[Nobjects].type, type);
+    layout[0].tickmarks.objects[Nobjects].x = x;
+    layout[0].tickmarks.objects[Nobjects].y = y;
+    layout[0].tickmarks.objects[Nobjects].dx = dx;
+    layout[0].tickmarks.objects[Nobjects].dy = dy;
+    
+    if (!strcmp (type, "TEXT")) { /* dx = Nchar, dy = angle (not yet used) */
+      status = read (layout[0].Ximage, line, 128); 
+      line[128] = 0; 
+      ALLOCATE (layout[0].tickmarks.objects[Nobjects].text, char, (int) dx + 1);
+      strncpy (layout[0].tickmarks.objects[Nobjects].text, line, (int) dx);
+      layout[0].tickmarks.objects[Nobjects].text[(int)dx] = 0;
+    }      
+    
+    Nobjects++;
+    if (Nobjects >= NOBJECTS) {
+      NOBJECTS = Nobjects + 100;
+      REALLOCATE (layout[0].tickmarks.objects, Object, NOBJECTS);
+    }
+
+  }
+
+  REALLOCATE (layout[0].tickmarks.objects, Object, MAX(Nobjects, 1));
+  layout[0].tickmarks.Nobjects = Nobjects;
+
+  if (USE_XWINDOW) Refresh (graphic, layout, 0);
+
+  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+  return (TRUE);
+  
+}
+
+
+/* this routine is independent of the number of overlays */
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/PaintOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/PaintOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/PaintOverlay.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "Ximage.h"
+# define INFRONT 4
+
+void PaintOverlay (Graphic *graphic, Layout *layout, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double expand, X0, Y0;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, layout[0].overlay[N].color);
+  
+  expand = 1.0;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+  }
+  /* 
+  X = 0.5*layout[0].matrix.Naxis[0] - expand*((int)(0.5*layout[0].picture.dx + 0.5) - 0.0) - layout[0].X;
+  Y = 0.5*layout[0].matrix.Naxis[1] - expand*((int)(0.5*layout[0].picture.dy + 0.5) - 0.0) - layout[0].Y;  
+  X0 =  (layout[0].X + 1 - (int)(0.5*layout[0].matrix.Naxis[0] + 0.5) - X + (int)X)/expand + layout[0].picture.x + 0.5*layout[0].picture.dx;
+  Y0 =  (layout[0].Y + 1 - (int)(0.5*layout[0].matrix.Naxis[1] + 0.5) - Y + (int)Y)/expand + layout[0].picture.y + 0.5*layout[0].picture.dy;
+  */
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, layout);
+
+  Xmin = layout[0].picture.x;
+  Ymin = layout[0].picture.y;
+  Xmax = layout[0].picture.x + layout[0].picture.dx;
+  Ymax = layout[0].picture.y + layout[0].picture.dy;
+  Xrange = layout[0].picture.dx;
+  Yrange = layout[0].picture.dy;
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    if (N == INFRONT) {
+      X  = layout[0].overlay[N].objects[i].x * Xrange + Xmin;
+      Y  = layout[0].overlay[N].objects[i].y * Yrange + Ymin;
+      dX = layout[0].overlay[N].objects[i].dx * Xrange;
+      dY = layout[0].overlay[N].objects[i].dy * Yrange;
+    } else {
+      X  = layout[0].overlay[N].objects[i].x/expand + X0;
+      Y =  layout[0].overlay[N].objects[i].y/expand + Y0;
+      dX = layout[0].overlay[N].objects[i].dx/expand;
+      dY = layout[0].overlay[N].objects[i].dy/expand;
+    }
+    if ((X + dX < Xmin) || (X - dX > Xmax) ||
+	(Y + dY < Ymin) || (Y - dY > Ymax)) {
+      continue;
+    }
+
+    /* for a LINE, (x, y) is the start, (dx, dy) is the distance to end
+       for a CIRCLE (x, y) is the center, (dx, dy) is the radius 
+       for a BOX (x, y) is the center, (dx, dy) is the width */
+
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "LINE")) {
+      XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "TEXT")) {
+      XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, layout[0].overlay[N].objects[i].text, strlen(layout[0].overlay[N].objects[i].text));
+      continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "BOX")) {
+      dx = MAX (abs(dX),2) / 2;
+      dy = MAX (abs(dY),2) / 2;
+      XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy);
+       continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "CIRCLE")) {
+      dx = MAX (abs(dX),2);
+      dy = MAX (abs(dY),2);
+      XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, (X - dx), (Y - dy), 2*dx, 2*dy, 0, 23040);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", layout[0].overlay[N].objects[i].type);
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/PaintTickmarks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/PaintTickmarks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/PaintTickmarks.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+# define INFRONT 3
+/* # include "rotletters.h" */
+
+void PaintTickmarks (Graphic *graphic, Layout *layout) {
+
+  int i;
+  int X, Y, dX, dY;
+  int Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+ 
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+  Xmin = layout[0].picture.x;
+  Ymin = layout[0].picture.y;
+  Xmax = layout[0].picture.x + layout[0].picture.dx;
+  Ymax = layout[0].picture.y + layout[0].picture.dy;
+  Xrange = layout[0].picture.dx;
+  Yrange = layout[0].picture.dy;
+
+  for (i = 0; i < layout[0].tickmarks.Nobjects; i++) {
+    X  = layout[0].tickmarks.objects[i].x * Xrange + Xmin;
+    Y  = layout[0].tickmarks.objects[i].y * Yrange + Ymin;
+    dX = layout[0].tickmarks.objects[i].dx * Xrange;
+    dY = layout[0].tickmarks.objects[i].dy * Yrange;
+
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "LINE")) {
+      XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "TEXT")) {
+      if (layout[0].tickmarks.objects[i].dy == 0) {
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].white);
+	XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-11, 6*strlen(layout[0].tickmarks.objects[i].text), 11); 
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].black);
+	XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, layout[0].tickmarks.objects[i].text, strlen(layout[0].tickmarks.objects[i].text));
+      }
+      if (layout[0].tickmarks.objects[i].dy == 90) {
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].white);
+	XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y-6*strlen(layout[0].tickmarks.objects[i].text), 11, 6*strlen(layout[0].tickmarks.objects[i].text)); 
+	XSetForeground (graphic[0].display, graphic[0].gc, layout[0].black);
+	/* XDrawRotString (graphic[0].display, graphic[0].window, graphic[0].gc, X, Y, layout[0].tickmarks.objects[i].text, strlen(layout[0].tickmarks.objects[i].text)); */
+      }
+      continue;
+    }
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "BOX")) {
+      XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, (int)(X - 0.5*dX), (int)(Y - 0.5*dY), abs(dX), abs(dY));
+       continue;
+    }
+    if (!strcmp (layout[0].tickmarks.objects[i].type, "CIRCLE")) {
+      XDrawArc (graphic[0].display, graphic[0].window, graphic[0].gc, X - dX, Y - dY, abs(2*dX), abs(2*dY), 0, 23040);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", layout[0].tickmarks.objects[i].type);
+  }
+  
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
+
+/* this routine is independent of the number of overlays */
+
+
+/*
+XDrawRotString (dpy, win, gc, X, Y, text, len)
+     
+*/
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/RotFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/RotFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/RotFont.c	(revision 16632)
@@ -0,0 +1,124 @@
+# include "Ximage.h"
+# include "alphabet.h"
+  
+static int Nrotfonts;
+static FontSet *RotFonts;
+
+static char currentname[64];
+static int  currentsize;
+static double currentscale;
+static RotFont *currentfont;
+
+void InitRotFonts () {
+
+  int i, Nhardwired;
+
+  Nhardwired = sizeof (HardwiredFonts) / sizeof (FontSet);
+  
+  Nrotfonts = Nhardwired;
+  ALLOCATE (RotFonts, FontSet, Nrotfonts);
+  
+  for (i = 0; i < Nhardwired; i++) {
+    RotFonts[i] = HardwiredFonts[i];
+  }
+
+  currentfont = RotFonts[DEFFONT].font;
+  currentscale = 1.0;
+  strcpy (currentname, RotFonts[DEFFONT].name);
+  currentsize = RotFonts[DEFFONT].size;
+}
+
+int SetRotFont (char *name, int size) {
+  
+  int i, nsize, msize, bsize, bigger, dsize, match, good;
+
+  bigger = good = match = -1;
+  dsize = 10000;
+  bsize = 10000;
+  for (i = 0; i < Nrotfonts; i++) {
+    if (!strcasecmp (RotFonts[i].name, name)) {
+      good = i;
+      nsize = abs (RotFonts[i].size - size);
+      if (nsize < dsize) {
+	match = i;
+	dsize = nsize;
+      }
+      msize = RotFonts[i].size - size;
+      if ((msize < bsize) && (msize >= 0)) {
+	bigger = i;
+	bsize = msize;
+      }
+    }
+  }
+  
+  if ((match == -1) && (good != -1)) match = good;
+  if (bigger != -1) match = bigger;
+  if (match != -1) {
+    currentfont = RotFonts[match].font;
+    currentscale = (double) size / RotFonts[match].size;
+    currentsize = size;
+    strcpy (currentname, name);
+    return (TRUE);
+  } else {
+    fprintf (stderr, "no matching font\n");
+    return (FALSE);
+  }
+
+}
+  
+char *GetRotFont (int *size) {
+
+  *size = currentsize;
+  return (currentname);
+
+}
+
+RotFont *GetRotFontData (double *scale) {
+  *scale = currentscale;
+  return (currentfont);
+}
+
+int RotStrlen (char *c) {
+
+  int i, N, dX, code;
+  double scale; 
+  
+  scale = currentscale;
+
+  /* find string length */
+  dX = 0;
+
+  code = FALSE;
+  for (i = 0; i < strlen (c); i++) {
+    N = (int)(c[i]);
+    /* skip non-printing characters */
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) { /* super-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 95) { /* sub-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 124) { /* normal-script */
+	scale = currentscale;
+	continue;
+      }
+      if (N == 92) { /* backslash */
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) { /* font-code */
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    dX += scale*currentfont[N].dx + 1;
+  }
+  return (dX);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/SaveOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/SaveOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/SaveOverlay.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "Ximage.h"
+
+/*************/
+int 
+SaveOverlay (graphic, layout)
+     Graphic graphic[];
+     Layout  layout[];
+{
+
+  char buffer[256], filename[256];
+  int i, status, Nbytes, N;
+  FILE *f;
+
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &Nbytes); 
+  status = read (layout[0].Ximage, buffer, Nbytes); 
+  buffer[Nbytes] = 0; 
+  sscanf (buffer, "%*s %d %s", &N, filename);
+  
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "could not open %s\n", filename);
+    return (TRUE);
+  }
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    fprintf (f, "%s %lf %lf %lf %lf\n", 
+	     layout[0].overlay[N].objects[i].type,
+	     layout[0].overlay[N].objects[i].x,
+	     layout[0].overlay[N].objects[i].y,
+	     layout[0].overlay[N].objects[i].dx,
+	     layout[0].overlay[N].objects[i].dy);
+  }
+  fclose (f);
+  return (TRUE);
+}
+
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/overlay/bDrawOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/overlay/bDrawOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/overlay/bDrawOverlay.c	(revision 16632)
@@ -0,0 +1,93 @@
+# include "Ximage.h"
+# define INFRONT 4
+
+static char name[4][16] = {"red", "green", "blue", "yellow"};
+
+void bDrawOverlay (Layout *layout, int N) {
+
+  int i;
+  int dX, dY, dx, dy;
+  int X, Y, Xmin, Ymin, Xmax, Ymax, Xrange, Yrange;
+  double expand, X0, Y0;
+  bDrawColor color;
+ 
+  /* translate color to bDrawColors : layout[0].overlay[N].color */
+  color = KapaColorByName (name[N]);
+  bDrawSetStyle (color, 0, 0);
+  
+  expand = 1.0;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+  }
+  /* 
+  X = 0.5*layout[0].matrix.Naxis[0] - expand*((int)(0.5*layout[0].picture.dx + 0.5) - 0.0) - layout[0].X;
+  Y = 0.5*layout[0].matrix.Naxis[1] - expand*((int)(0.5*layout[0].picture.dy + 0.5) - 0.0) - layout[0].Y;  
+  X0 =  (layout[0].X + 1 - (int)(0.5*layout[0].matrix.Naxis[0] + 0.5) - X + (int)X)/expand + layout[0].picture.x + 0.5*layout[0].picture.dx;
+  Y0 =  (layout[0].Y + 1 - (int)(0.5*layout[0].matrix.Naxis[1] + 0.5) - Y + (int)Y)/expand + layout[0].picture.y + 0.5*layout[0].picture.dy;
+  */
+
+  Image_to_Screen (&X0, &Y0, 0.0, 0.0, layout);
+  X0 -= layout[0].picture.x;
+  Y0 -= layout[0].picture.y;
+
+  Xmin = 0;
+  Ymin = 0;
+  Xmax = layout[0].picture.dx;
+  Ymax = layout[0].picture.dy;
+  Xrange = layout[0].picture.dx;
+  Yrange = layout[0].picture.dy;
+
+  for (i = 0; i < layout[0].overlay[N].Nobjects; i++) {
+    if (N == INFRONT) {
+      X  = layout[0].overlay[N].objects[i].x * Xrange;
+      Y  = layout[0].overlay[N].objects[i].y * Yrange;
+      dX = layout[0].overlay[N].objects[i].dx * Xrange;
+      dY = layout[0].overlay[N].objects[i].dy * Yrange;
+    } else {
+      X  = layout[0].overlay[N].objects[i].x/expand + X0;
+      Y =  layout[0].overlay[N].objects[i].y/expand + Y0;
+      dX = layout[0].overlay[N].objects[i].dx/expand;
+      dY = layout[0].overlay[N].objects[i].dy/expand;
+    }
+    if ((X + dX < Xmin) || (X - dX > Xmax) ||
+	(Y + dY < Ymin) || (Y - dY > Ymax)) {
+      continue;
+    }
+
+    /* for a LINE, (x, y) is the start, (dx, dy) is the distance to end
+       for a CIRCLE (x, y) is the center, (dx, dy) is the radius 
+       for a BOX (x, y) is the center, (dx, dy) is the width */
+
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "LINE")) {
+      bDrawLine (X, Y, (X+dX), (Y+dY));
+      continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "TEXT")) {
+      bDrawRotText (X, Y, layout[0].overlay[N].objects[i].text, 8, 0.0);
+      continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "BOX")) {
+      dx = MAX (abs(dX),2) / 2;
+      dy = MAX (abs(dY),2) / 2;
+      bDrawRectOpen ((X-dx), (Y-dy), (X+dx), (Y+dy));
+      // bDrawRectOpen ((X-dx), (Y-dy), (X), (Y));
+       continue;
+    }
+    if (!strcasecmp (layout[0].overlay[N].objects[i].type, "CIRCLE")) {
+      dx = MAX (abs(dX),2);
+      dy = MAX (abs(dY),2);
+      bDrawArc (X, Y, dx, dy, 0, 360);
+      continue;
+    }
+    fprintf (stderr, "don't know %s, skipping (PO)\n", layout[0].overlay[N].objects[i].type);
+  }
+  
+  /* translate color to bDrawColors : layout[0].overlay[N].color */
+  bDrawSetStyle (color, 0, 0);
+}
+
+/* this routine is independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Center.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Center.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Center.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "Ximage.h"
+
+int Center (Graphic *graphic, Layout *layout) {
+
+  char buffer[1024];
+  int status, zoom, Nbytes;
+  double X, Y;
+
+  fcntl (layout[0].Ximage, F_SETFL, !O_NONBLOCK);  
+  status = read (layout[0].Ximage, buffer, 16); 
+  buffer[16] = 0; 
+  sscanf (buffer, "%*s %d", &Nbytes); 
+  status = read (layout[0].Ximage, buffer, Nbytes); 
+  buffer[status] = 0; /* make the string easy to parse */ 
+  sscanf (buffer, "%lf %lf %d", &X,  &Y, &zoom);
+
+  layout[0].X = 0.5*layout[0].matrix.Naxis[0] - X;
+  layout[0].Y = 0.5*layout[0].matrix.Naxis[1] - Y;
+  if ((zoom != 0) && (zoom != -1)) {
+    layout[0].expand = zoom;
+  }
+
+  if (USE_XWINDOW) {
+    Remap (graphic, layout, &layout[0].matrix);
+    Refresh (graphic, layout, 0);
+    XFlush (graphic[0].display);
+  }
+
+  fcntl (layout[0].Ximage, F_SETFL, O_NONBLOCK);  
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/CreatePicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/CreatePicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/CreatePicture.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include "Ximage.h"
+
+void CreatePicture (Layout *layout, Graphic *graphic) {
+
+  int i, j, extra;
+  unsigned char *c;
+  unsigned int *l;
+  unsigned int start, start1, start2, start3;
+
+  start = layout[0].white;
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    REALLOCATE (layout[0].picture.data, char, layout[0].picture.dx*layout[0].picture.dy);
+    c = (unsigned char *) layout[0].picture.data;
+    for (i = 0; i < (layout[0].picture.dx*layout[0].picture.dy); i++, c++)
+      *c = start;
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 8, 0);
+    break;
+
+  case 16:
+    REALLOCATE (layout[0].picture.data, char, 2*layout[0].picture.dy*layout[0].picture.dx);
+    c = (unsigned char *) layout[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    for (i = 0; i < layout[0].picture.dy; i++) {
+      for (j = 0; j < layout[0].picture.dx; j++, c+=2) {
+	c[0] = start1;
+	c[1] = start2;
+      }
+    }
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 16, 0);
+    break;
+
+  case 24:
+    extra = 4 - (layout[0].picture.dx * 3) % 4;
+    REALLOCATE (layout[0].picture.data, char, layout[0].picture.dy*(3*layout[0].picture.dx+extra));
+    c = (unsigned char *) layout[0].picture.data;
+    start1 = 0x0000ff & (start);
+    start2 = 0x0000ff & (start >> 8);
+    start3 = 0x0000ff & (start >> 16);
+    for (i = 0; i < layout[0].picture.dy; i++) {
+      for (j = 0; j < layout[0].picture.dx; j++, c+=3) {
+	c[0] = start1;
+	c[1] = start2;
+	c[2] = start3;
+      }
+      c+=extra;
+    }
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 24, 0);
+    break;
+
+  case 32:
+    ALLOCATE (layout[0].picture.data, char, (4*layout[0].picture.dx*layout[0].picture.dy + 32));
+    memset (layout[0].picture.data, 0xbd, 4*layout[0].picture.dx*layout[0].picture.dy + 30);
+    l = (unsigned int *) layout[0].picture.data;
+    for (i = 0; i < (layout[0].picture.dx*layout[0].picture.dy); i++, l++)
+      *l = start;
+    layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					  layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 32, 0);
+    break;
+  }
+    
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/CursorOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/CursorOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/CursorOps.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "Ximage.h"
+
+void Screen_to_Image (double *x1, double *y1, double x2, double y2, Layout *layout) {
+
+  double expand;
+
+  expand = 1.0;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+  }
+  
+  *x1 = expand*(x2 - layout[0].picture.x - 0.5*layout[0].picture.dx) + 0.5*layout[0].matrix.Naxis[0] - layout[0].X;
+  *y1 = expand*(y2 - layout[0].picture.y - 0.5*layout[0].picture.dy) + 0.5*layout[0].matrix.Naxis[1] - layout[0].Y;
+  
+}
+
+void Image_to_Screen (double *x1, double *y1, double x2, double y2, Layout *layout) {
+
+  double expand;
+
+  /* notice that here, expand is the reciprocal of the expand above */
+  expand = 1.0;
+  if (layout[0].expand > 0) {
+    expand = abs(layout[0].expand);
+  }
+  if (layout[0].expand < 0) {
+    expand = 1 / ((double)abs(layout[0].expand));
+  }
+  
+  *x1 = (x2 - 0.5*layout[0].matrix.Naxis[0] + layout[0].X) * expand + layout[0].picture.x + 0.5*layout[0].picture.dx;
+  *y1 = (y2 - 0.5*layout[0].matrix.Naxis[1] + layout[0].Y) * expand + layout[0].picture.y + 0.5*layout[0].picture.dy;
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/JPEGit24.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/JPEGit24.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/JPEGit24.c	(revision 16632)
@@ -0,0 +1,225 @@
+# include "Ximage.h"
+# include "jpeglib.h"
+
+# define WHITE_R 255
+# define WHITE_G 255
+# define WHITE_B 255
+
+int JPEGit24 (Graphic *graphic, Layout *layout) {
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
+  JSAMPLE *image_buffer;	/* Points to data for current line */
+  JSAMPLE *line_buffer;	        /* Points to data for current line */
+
+  int ii, i, j;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  int status, Nbytes, quality;
+  int expand_in, expand_out;
+  double expand, Rx, Ry, X, Y;
+  unsigned char *out_pix, *in_pix, *in_pix_ref;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  char filename[1024];
+  FILE *f;
+
+  /* expect a line telling the number of bytes and a filename */
+  status = read (layout[0].Ximage, filename, 16);
+  filename[16] = 0;
+  sscanf (filename, "%*s %d", &Nbytes);
+  status = read (layout[0].Ximage, filename, Nbytes);
+  filename[status] = 0; /* make the string easy to parse */
+
+  /***** JPEG init calls */
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_compress (&cinfo);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "Kii: failed to open %s for output\n", filename);
+    return (TRUE);
+  }
+  jpeg_stdio_dest(&cinfo, f);
+  
+  quality = 75;
+  cinfo.image_width = layout[0].picture.dx; 	/* image width and height, in pixels */
+  cinfo.image_height = layout[0].picture.dy;
+# ifdef GREYSCALE
+  cinfo.input_components = 1;		        /* # of color components per pixel */
+  cinfo.in_color_space = JCS_GRAYSCALE; 	/* colorspace of input image */
+# else 
+  cinfo.input_components = 3;		        
+  cinfo.in_color_space = JCS_RGB; 	
+# endif
+  jpeg_set_defaults (&cinfo);
+  jpeg_set_quality (&cinfo, quality, TRUE       /* limit to baseline-JPEG values */);
+  jpeg_start_compress (&cinfo, TRUE);
+
+  /** cmap[i].pixel must be defined even if X is not used **/
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = layout[0].cmap[i].red >> 8;
+    pixel2[i] = layout[0].cmap[i].green >> 8;
+    pixel3[i] = layout[0].cmap[i].blue >> 8;
+  }
+
+  expand = expand_in = expand_out = 1.0;
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  /* output line buffer */
+  ALLOCATE (image_buffer, JSAMPLE, 3*dx*dy);
+  ALLOCATE (line_buffer, JSAMPLE, 3*dx);
+
+  in_pix_ref  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix+=3) {
+    out_pix[0] = WHITE_R;
+    out_pix[1] = WHITE_G;
+    out_pix[2] = WHITE_B;
+  }
+  for (j = 0; j < j_start; j++) {
+    memcpy (&image_buffer[j*3*dx], line_buffer, 3*dx);
+  }
+  
+  /*** fill in the image data region ***/
+  for (j = j_start; j < j_end; j+= expand_out, in_pix_ref += expand_in*DX) {
+    
+    /* create one output image line */
+    in_pix = in_pix_ref;
+    out_pix = line_buffer;
+
+    /**** fill in area to the left of the picture ****/
+    for (i = 0; i < i_start; i++, out_pix+=3) {
+      out_pix[0] = WHITE_R;
+      out_pix[1] = WHITE_G;
+      out_pix[2] = WHITE_B;
+    }
+    
+    /*** fill in the picture region ***/
+    for (i = i_start; i < i_end; i+=expand_out, in_pix+=expand_in) {
+      for (ii = 0; ii < expand_out; ii++, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix];
+	out_pix[1] = pixel2[*in_pix];
+	out_pix[2] = pixel3[*in_pix];
+      }
+    }
+    
+    /**** fill in area to the right of the picture ****/
+    for (i = i_end; i < dx; i++, out_pix+=3) {
+      out_pix[0] = WHITE_R;
+      out_pix[1] = WHITE_G;
+      out_pix[2] = WHITE_B;
+    }
+
+    /* write out the image line expand_out times */
+    for (i = 0; i < expand_out; i++) {
+      memcpy (&image_buffer[(j + i)*3*dx], line_buffer, 3*dx);
+    }
+  }
+
+  /**** fill in top area ****/
+  out_pix = line_buffer;
+  for (i = 0; i < dx; i++, out_pix+=3) { 
+    out_pix[0] = WHITE_R;
+    out_pix[1] = WHITE_G;
+    out_pix[2] = WHITE_B;
+  }
+  for (j = j_end; j < dy; j++) {
+    memcpy (&image_buffer[j*3*dx], line_buffer, 3*dx);
+  }
+
+
+  /* I need to write the overlay objects on the jpeg image.
+     if i can write / overwrite data in jpeg buffer, then do it here,
+     otherwise i need to create a temporary image buffer, then write the 
+     scanlines to that buffer */
+
+  {
+    int Npalette;
+    png_color *palette;
+    bDrawColor white, color;
+    bDrawBuffer *buffer;
+
+    palette = KapaPNGPalette (&Npalette);
+
+    buffer = bDrawBufferCreate (dx, dy);
+    bDrawSetBuffer (buffer);
+    for (i = 0; i < NOVERLAYS; i++) {
+      if (OVERLAY[i]) bDrawOverlay (layout, i);
+    }
+
+    white = KapaColorByName ("white");
+    for (j = 0; j < dy; j++) {
+      for (i = 0; i < dx; i++) {
+	color = buffer[0].pixels[j][i];
+	if (color == white) continue;
+	image_buffer[j*3*dx + 3*i + 0] = palette[color].red;
+	image_buffer[j*3*dx + 3*i + 1] = palette[color].green;
+	image_buffer[j*3*dx + 3*i + 2] = palette[color].blue;
+      }
+    }
+    bDrawBufferFree (buffer);
+  }
+
+  for (i = 0; i < dy; i++) {
+    row_pointer[0] = &image_buffer[i*3*dx];
+    (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
+  }
+
+  jpeg_finish_compress (&cinfo);
+  fclose (f);
+  jpeg_destroy_compress (&cinfo);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/NewPicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/NewPicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/NewPicture.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "Ximage.h"
+
+int NewPicture (Graphic *graphic, Layout *layout) {
+
+  Header header;
+  char *buff;
+  int status, bytes_left, socket;
+ 
+  socket = layout[0].Ximage;
+
+  KiiSendMessage (socket, "%d", layout[0].Npixels);
+
+  fcntl (socket, F_SETFL, !O_NONBLOCK);  
+
+  header.Naxes = 2;
+
+  KiiScanMessage (socket, "%d %d %d %d %lf %lf", &header.Naxis[0], &header.Naxis[1]);
+  KiiScanMessage (socket, "%d %d %d %d %lf %lf", &header.bitpix, &header.unsign, &header.bzero, &header.bscale);
+  KiiScanMessage (socket, "%lf %lf",  &layout[0].zero, &layout[0].range);
+  KiiScanMessage (socket, "%lf %lf %d", &layout[0].min,  &layout[0].max, &header.size);
+  KiiScanMessage (socket, "%lf %f %f %f %f", &layout[0].coords.crval1, &layout[0].coords.crpix1, &layout[0].coords.cdelt1, &layout[0].coords.pc1_1, &layout[0].coords.pc1_2);
+  KiiScanMessage (socket, "%lf %f %f %f %f", &layout[0].coords.crval2, &layout[0].coords.crpix2, &layout[0].coords.cdelt2, &layout[0].coords.pc2_1, &layout[0].coords.pc2_2);
+	  
+  KiiScanMessage (socket, "%s %s %s", layout[0].coords.ctype, layout[0].file, layout[0].buffer_name);
+
+  gfits_free_matrix (&layout[0].matrix);
+  gfits_create_matrix (&header, &layout[0].matrix);
+
+  fcntl (socket, F_SETFL, O_NONBLOCK);  
+
+  status = 1;
+  buff = layout[0].matrix.buffer;
+  bytes_left = header.size;
+  layout[0].matrix.size = 0;
+  while (bytes_left > 0) {
+    status = read (socket, buff, bytes_left);
+    if (status == 0) {  /* No more pipe */
+      fprintf (stderr, "error: pipe closed\n");
+      return (FALSE);
+    }
+    if (status != -1) { /* pipe has data */
+      layout[0].matrix.size += status;
+      bytes_left -= status;
+      buff = (char *)(buff + status);
+    }
+  }
+
+  if (DEBUG) fprintf (stderr, "read %d bytes\n", layout[0].matrix.size);
+  /* it it not obvious this condition should kill kii, but ... */
+  if (layout[0].matrix.size != header.size) {  
+    fprintf (stderr, "error: expected %d bytes, but got only %d\n", header.size, layout[0].matrix.size);
+    return (FALSE);
+  }
+
+  if (!USE_XWINDOW) return (TRUE);
+
+  Remap (graphic, layout, &layout[0].matrix);
+  if (DEBUG) fprintf (stderr, "remapped image\n");
+  Refresh (graphic, layout, 0);
+  if (DEBUG) fprintf (stderr, "refreshed\n");
+  XFlush (graphic[0].display);
+
+  return (TRUE);
+
+}
+
+/*
+   layout[0].X = 0;
+   layout[0].Y = 0;
+   layout[0].expand = 1;
+*/
+  
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/PositionPictures.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/PositionPictures.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/PositionPictures.c	(revision 16632)
@@ -0,0 +1,152 @@
+# include "Ximage.h" 
+# include "buttons.h"
+# define BUTTON_WIDTH 28
+# define BUTTON_HEIGHT 28
+
+void PositionPictures (Layout *layout, Graphic *graphic) {
+
+  layout[0].cmapbar.dx = graphic[0].dx - 2*PAD1; 
+  layout[0].cmapbar.dy = COLORPAD;
+  layout[0].cmapbar.x = PAD1;
+  layout[0].cmapbar.y = PAD1;
+
+  layout[0].zoom.dx = ZOOM_X; 
+  layout[0].zoom.dy = ZOOM_Y;
+  layout[0].zoom.x = graphic[0].dx - PAD1 - ZOOM_X;
+  layout[0].zoom.y = layout[0].cmapbar.y + layout[0].cmapbar.dy + PAD2;
+
+  layout[0].picture.dx = layout[0].zoom.x - 2*PAD1 - 25; 
+  layout[0].picture.dy = graphic[0].dy - 2*PAD1 - PAD2 - COLORPAD - 25;
+  layout[0].picture.x = PAD1 + 25;
+  layout[0].picture.y = PAD1 + PAD2 + COLORPAD;
+
+  /** everything below is tied in x-dir to the zoom box **/
+  layout[0].text_x = layout[0].zoom.x;
+  layout[0].text_y = layout[0].zoom.y + layout[0].zoom.dy + PAD2;
+
+  /*  layout[0].PS_button.y = graphic[0].dy - BUTTON_HEIGHT - PAD1; */
+  layout[0].PS_button.x = layout[0].zoom.x + 5;
+  layout[0].PS_button.y = 2*ZOOM_Y;
+  layout[0].PS_button.dx = BUTTON_WIDTH;
+  layout[0].PS_button.dy = BUTTON_HEIGHT;
+  layout[0].PS_button.text = FALSE;
+  layout[0].PS_button.width = PS_width;
+  layout[0].PS_button.height = PS_height;
+  layout[0].PS_button.bitmap = PS_bits;
+  layout[0].PS_button.function_1 = PSit;
+  layout[0].PS_button.function_2 = PSit;
+  layout[0].PS_button.function_3 = PSit;
+
+  /** everything below is tied to the PS_button in y-dir **/
+  layout[0].grey_button.x = layout[0].PS_button.x + layout[0].PS_button.dx + PAD1;
+  layout[0].grey_button.y = layout[0].PS_button.y;
+  layout[0].grey_button.dx = BUTTON_WIDTH;
+  layout[0].grey_button.dy = BUTTON_HEIGHT;
+  layout[0].grey_button.text = FALSE;
+  layout[0].grey_button.width = grey_width;
+  layout[0].grey_button.height = grey_height;
+  layout[0].grey_button.bitmap = grey_bits;
+  layout[0].grey_button.function_1 = greycolors;
+  layout[0].grey_button.function_2 = greycolors;
+  layout[0].grey_button.function_3 = greycolors;
+
+  layout[0].rainbow_button.x = layout[0].grey_button.x + layout[0].grey_button.dx + PAD1;
+  layout[0].rainbow_button.y = layout[0].PS_button.y;
+  layout[0].rainbow_button.dx = BUTTON_WIDTH;
+  layout[0].rainbow_button.dy = BUTTON_HEIGHT;
+  layout[0].rainbow_button.text = FALSE;
+  layout[0].rainbow_button.width = rainbow_width;
+  layout[0].rainbow_button.height = rainbow_height;
+  layout[0].rainbow_button.bitmap = rainbow_bits;
+  layout[0].rainbow_button.function_1 = rainbow;
+  layout[0].rainbow_button.function_2 = rainbow;
+  layout[0].rainbow_button.function_3 = rainbow;
+
+  layout[0].puns_button.x = layout[0].rainbow_button.x + layout[0].rainbow_button.dx + PAD1;
+  layout[0].puns_button.y = layout[0].PS_button.y;
+  layout[0].puns_button.dx = BUTTON_WIDTH;
+  layout[0].puns_button.dy = BUTTON_HEIGHT;
+  layout[0].puns_button.text = FALSE;
+  layout[0].puns_button.width = puns_width;
+  layout[0].puns_button.height = puns_height;
+  layout[0].puns_button.bitmap = puns_bits;
+  layout[0].puns_button.function_1 = puns;
+  layout[0].puns_button.function_2 = puns;
+  layout[0].puns_button.function_3 = puns;
+
+  layout[0].recenter_button.x = layout[0].puns_button.x + layout[0].puns_button.dx + PAD1;
+  layout[0].recenter_button.y = layout[0].PS_button.y;
+  layout[0].recenter_button.dx = BUTTON_WIDTH;
+  layout[0].recenter_button.dy = BUTTON_HEIGHT;
+  layout[0].recenter_button.text = FALSE;
+  layout[0].recenter_button.width = recenter_width;
+  layout[0].recenter_button.height = recenter_height;
+  layout[0].recenter_button.bitmap = recenter_bits;
+  layout[0].recenter_button.function_1 = Recenter;
+  layout[0].recenter_button.function_2 = RecenterRescale;
+  layout[0].recenter_button.function_3 = Rescale;
+
+  layout[0].overlay_button[0].x = layout[0].zoom.x + 5;
+  layout[0].overlay_button[0].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[0].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[0].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[0].text = FALSE;
+  layout[0].overlay_button[0].width = red_width;
+  layout[0].overlay_button[0].height = red_height;
+  layout[0].overlay_button[0].bitmap = red_bits;
+  layout[0].overlay_button[0].function_1 = Overlay0;
+  layout[0].overlay_button[0].function_2 = Overlay0;
+  layout[0].overlay_button[0].function_3 = Overlay0;
+		   	   
+  layout[0].overlay_button[1].x = layout[0].overlay_button[0].x + layout[0].overlay_button[0].dx + PAD1;
+  layout[0].overlay_button[1].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[1].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[1].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[1].text = FALSE;
+  layout[0].overlay_button[1].width = green_width;
+  layout[0].overlay_button[1].height = green_height;
+  layout[0].overlay_button[1].bitmap = green_bits;
+  layout[0].overlay_button[1].function_1 = Overlay1;
+  layout[0].overlay_button[1].function_2 = Overlay1;
+  layout[0].overlay_button[1].function_3 = Overlay1;
+
+  layout[0].overlay_button[2].x = layout[0].overlay_button[1].x + layout[0].overlay_button[1].dx + PAD1;
+  layout[0].overlay_button[2].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[2].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[2].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[2].text = FALSE;
+  layout[0].overlay_button[2].width = blue_width;
+  layout[0].overlay_button[2].height = blue_height;
+  layout[0].overlay_button[2].bitmap = blue_bits;
+  layout[0].overlay_button[2].function_1 = Overlay2;
+  layout[0].overlay_button[2].function_2 = Overlay2;
+  layout[0].overlay_button[2].function_3 = Overlay2;
+		   	   
+  layout[0].overlay_button[3].x = layout[0].overlay_button[2].x + layout[0].overlay_button[2].dx + PAD1;
+  layout[0].overlay_button[3].y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].overlay_button[3].dx = BUTTON_WIDTH;
+  layout[0].overlay_button[3].dy = BUTTON_HEIGHT;
+  layout[0].overlay_button[3].text = FALSE;
+  layout[0].overlay_button[3].width = yellow_width;
+  layout[0].overlay_button[3].height = yellow_height;
+  layout[0].overlay_button[3].bitmap = yellow_bits;
+  layout[0].overlay_button[3].function_1 = Overlay3;
+  layout[0].overlay_button[3].function_2 = Overlay3;
+  layout[0].overlay_button[3].function_3 = Overlay3;
+
+  layout[0].hms_button.x = layout[0].overlay_button[3].x + layout[0].overlay_button[3].dx + PAD1;
+  layout[0].hms_button.y = layout[0].PS_button.y - BUTTON_HEIGHT - PAD1;
+  layout[0].hms_button.dx = BUTTON_WIDTH;
+  layout[0].hms_button.dy = BUTTON_HEIGHT;
+  layout[0].hms_button.text = FALSE;
+  layout[0].hms_button.width = hms_width;
+  layout[0].hms_button.height = hms_height;
+  layout[0].hms_button.bitmap = hms_bits;
+  layout[0].hms_button.function_1 = ToggleDEG;
+  layout[0].hms_button.function_2 = ToggleDEG;
+  layout[0].hms_button.function_3 = ToggleDEG;
+
+}
+
+
+/* this routine is dependent on the number of Overlays */
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+void Remap (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    Remap8 (graphic, layout, matrix);
+    break;
+  case 16:
+    Remap16 (graphic, layout, matrix);
+    break;
+  case 24:
+    Remap24 (graphic, layout, matrix);
+    break;
+  case 32:
+    Remap32 (graphic, layout, matrix);
+    break;
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap16.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap16.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap16.c	(revision 16632)
@@ -0,0 +1,153 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap16 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long white;
+  unsigned char white1, white2;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 16);
+  }
+  white = layout[0].white;
+  white1 = 0x00ff & white;
+  white2 = 0x00ff & (white >> 8);
+
+  expand = expand_in = expand_out = 1.0;
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].picture.data;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[2*j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+    out_pix += 2*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=2) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=2*(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=2) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	  }
+	}
+      }
+    }
+    out_pix -= 2*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  */
+  
+  out_pix = &data[2*j_end*dx];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 16, 0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap24.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap24.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap24.c	(revision 16632)
@@ -0,0 +1,164 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap24 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback, extra;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned long white;
+  unsigned char white1, white2, white3;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 16);
+  }
+  white = layout[0].white;
+  white1 = 0x0000ff & white;
+  white2 = 0x0000ff & (white >> 8);
+  white3 = 0x0000ff & (white >> 16);
+
+  expand = expand_in = expand_out = 1.0;
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+  extra = 4 - (dx * 3) % 4;
+
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].picture.data;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix += extra;
+  }
+  
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+	out_pix[2] = pixel3[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	pixvalue3 = pixel3[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  */
+  
+  out_pix = &data[j_end*(3*dx+extra)];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix+=extra;
+  }
+
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 32, 0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap32.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap32.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap32.c	(revision 16632)
@@ -0,0 +1,132 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap32 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  expand = expand_in = expand_out = 1.0;
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) layout[0].picture.data;
+  in_pix  = (unsigned char *) (matrix[0].buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = white;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+      /* *out_pix = *(pixel + *in_pix2);  */
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)layout[0].picture.data < dx*dy); j++, out_pix++) { 
+    *out_pix = white;
+  }
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 32, 0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap8.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap8.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Remap8.c	(revision 16632)
@@ -0,0 +1,132 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+void Remap8 (Graphic *graphic, Layout *layout, Matrix *matrix) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, Rx, Ry, X, Y;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  expand = expand_in = expand_out = 1.0;
+  if (layout[0].expand == 0) /* set up expansions */
+    layout[0].expand = 1;
+  if (layout[0].expand > 0) {
+    expand = 1 / (1.0*layout[0].expand);
+    expand_out = layout[0].expand;
+    expand_in  = 1;
+  }
+  if (layout[0].expand < 0) {
+    expand = fabs((double)layout[0].expand);
+    expand_out = 1;
+    expand_in  = -layout[0].expand;
+  }
+
+  dx = layout[0].picture.dx;
+  dy = layout[0].picture.dy;
+  DX = matrix[0].Naxis[0];
+  DY = matrix[0].Naxis[1];
+  /* X,Y are the image coordinates of the first image pixel */
+  X = MAX(0.5*(DX - dx*expand) - layout[0].X, 0);
+  if ((int)X != X) 
+    X = (int) X + 1;
+  else 
+    X = (int) X;
+  Y = MAX(0.5*(DY - dy*expand) - layout[0].Y, 0);
+  if ((int)Y != Y) 
+    Y = (int) Y + 1;
+  else 
+    Y = (int) Y;
+
+  /* Rx,Ry are the screen coordinates of the first image pixel */
+  Rx = (X + layout[0].X - 0.5*DX)/expand + 0.5*dx;
+  Ry = (Y + layout[0].Y - 0.5*DY)/expand + 0.5*dy;
+
+  i_start = MIN (MAX (Rx, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (Ry, 0), dy - expand_out + 1);
+  
+  if (layout[0].expand > 0) {
+    i_end = MAX (MIN (i_start + ((int)(expand*(dx-i_start)))/expand, expand_out*(DX-X) + Rx), 0);
+    j_end = MAX (MIN (j_start + ((int)(expand*(dy-j_start)))/expand, expand_out*(DY-Y) + Ry), 0);
+  } else {
+    i_end = MAX (MIN (dx, (DX-X)/expand + Rx), 0);
+    j_end = MAX (MIN (dy, (DY-Y)/expand + Ry), 0);
+  }    
+
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned char *) layout[0].picture.data;
+  in_pix  = (unsigned char *) matrix[0].buffer + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = white;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; (i_start > 0) && (jj < expand_out); jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	*out_pix = pixel[*in_pix2];
+      }
+      /* *out_pix = *(pixel + *in_pix2);  */
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = pixel[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned char *)layout[0].picture.data < dx*dy); j++, out_pix++) { 
+    *out_pix = white;
+  }
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, layout[0].picture.dx, layout[0].picture.dy, 8, 0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Reorient.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Reorient.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Reorient.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+
+void Reorient (Graphic *graphic, Layout *layout, double X, double Y, int mode) {
+
+  if (layout[0].expand == 0)
+    layout[0].expand = 1;
+
+  switch (mode) {
+  case 0:
+    if ((layout[0].X != X) || (layout[0].Y != Y)) {
+      layout[0].X = X;
+      layout[0].Y = Y;
+    }
+    break;
+  case -1: 
+    layout[0].expand--;
+    if ((layout[0].expand == 0) || (layout[0].expand == -1))
+      layout[0].expand = -2;
+    if (layout[0].expand < -30) {
+      fprintf (stderr, "can't get smaller!\n");
+      layout[0].expand = -30;
+      return;
+    }
+    layout[0].X = X;
+    layout[0].Y = Y;
+    break;
+  case +1:
+    layout[0].expand++;
+    if ((layout[0].expand == 0) || (layout[0].expand == -1))
+      layout[0].expand = 1;
+    if (layout[0].expand > 30) {
+      fprintf (stderr, "can't get bigger!\n");
+      layout[0].expand = 30;
+      return;
+    }
+    layout[0].X = X;
+    layout[0].Y = Y;
+    break;
+  }
+
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+ 
+  XFlush (graphic[0].display);
+}
+
+# if (0) /* the "warp" function seems to be a problem on SUNs for some reason */
+  XQueryPointer (graphic[0].display, graphic[0].window, &dummy1, &dummy1, &dummy2, &dummy2, &x, &y, &dummy3); 
+  if ((x > layout[0].picture.x) && (x < layout[0].picture.x + layout[0].picture.dx) &&
+      (y > layout[0].picture.y) && (y < layout[0].picture.y + layout[0].picture.dy) &&
+      ((mouse_event[0].button == 2) || (mouse_event[0].button == 3))) {
+    XWarpPointer (graphic[0].display, None, graphic[0].window, 0, 0, 0, 0, 
+		  layout[0].picture.x + 0.5*layout[0].picture.dx,
+		  layout[0].picture.y + 0.5*layout[0].picture.dy);
+  }
+# endif
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Rescale.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Rescale.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Rescale.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+void
+Rescale (graphic, layout)
+Graphic graphic[];
+Layout  layout[];
+{
+
+  fprintf (stdout, "enter new zero, range: ");
+  fscanf (stdin, "%lf%lf", &layout[0].zero, &layout[0].range);
+
+  Remap (graphic, layout, &layout[0].matrix);
+  Refresh (graphic, layout, 0);
+  
+  XFlush (graphic[0].display);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/Resize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/Resize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/Resize.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+int Resize (Graphic *graphic, Layout *layout) {
+ 
+  unsigned int NX, NY;
+
+  KiiScanMessage (layout[0].Ximage, "%d %d", &NX, &NY);
+
+  NX += ZOOM_X + 3*PAD1 + 25;
+  NY += 2*PAD1 + PAD2 + COLORPAD + 25;
+
+  if ((graphic[0].dx == NX) && (graphic[0].dy == NY)) 
+    return (TRUE);
+
+  graphic[0].dx = MAX(NX, 50); 
+  graphic[0].dy = MAX(NY, 50); 
+
+  if (USE_XWINDOW) XResizeWindow (graphic[0].display, graphic[0].window, NX, NY);
+
+  PositionPictures (layout, graphic);
+
+  if (USE_XWINDOW) {
+    CreateColorbar (layout, graphic);
+    CreatePicture (layout, graphic);
+    Remap (graphic, layout, &layout[0].matrix); 
+    XClearWindow (graphic[0].display, graphic[0].window);
+    Refresh (graphic, layout, 1);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/StatusBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/StatusBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/StatusBox.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "Ximage.h"
+
+void
+StatusBox (graphic, layout)
+Graphic        graphic[];
+Layout         layout[];
+{
+
+  double  x, y, z;
+
+  if (MOVE_POINTER) {
+    x = 0.5*layout[0].matrix.Naxis[0];
+    y = 0.5*layout[0].matrix.Naxis[1];
+    z = -1;
+    layout[0].x = x;
+    layout[0].y = y;
+    layout[0].z = z;
+  }
+  else {
+    x = layout[0].x;
+    y = layout[0].y;
+    z = layout[0].z;
+  }
+  
+  UpdateStatusBox (graphic, layout, x, y, z, 1);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/TestPicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/TestPicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/TestPicture.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "Ximage.h"
+
+int 
+TestPicture (graphic, layout)
+     Graphic graphic[];
+     Layout  layout[];
+{
+
+  Header header;
+  char buffer[1024], *buff;
+  int status, bytes_left, Nbytes, i, j;
+  double frac;
+
+  gfits_free_matrix (&layout[0].matrix);
+
+  header.Naxes = 2;
+  header.Naxis[0] = 512;
+  header.Naxis[1] = 512;
+  header.bitpix = 8;
+  header.unsign = 0;
+  header.bzero = 0;
+  header.bscale = 1;
+
+  layout[0].zero = 0;
+  layout[0].range = layout[0].Npixels;
+  layout[0].min = 0; 
+  layout[0].max = layout[0].Npixels;
+  
+  gfits_create_matrix (&header, &layout[0].matrix);
+
+  frac = layout[0].Npixels / (512.0*512.0);
+  buff = layout[0].matrix.buffer;
+  for (i = 0; i < 512; i++) {
+    for (j = 0; j < 512; j++, buff++) {
+      *buff = (int)(i*j*frac);
+    }
+  }
+
+/*
+  Remap (layout, &layout[0].matrix);
+  layout[0].picture.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].picture.data, 
+					layout[0].picture.dx, layout[0].picture.dy, 8, 0);
+
+  (DEBUG) && fprintf (stderr, "remapped image\n", layout[0].matrix.size);
+  Refresh (graphic, layout);
+  
+  (DEBUG) && fprintf (stderr, "refreshed\n", layout[0].matrix.size);
+  XFlush (graphic[0].display);
+*/
+}
+
+
+/*
+   layout[0].X = 0;
+   layout[0].Y = 0;
+   layout[0].expand = 1;
+*/
+  
Index: /branches/eam_branch_20080223/Ohana/src/kii/picture/cursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/picture/cursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/picture/cursor.c	(revision 16632)
@@ -0,0 +1,82 @@
+# include "Ximage.h"
+
+# define IgnoreMask (long) (~(StructureNotifyMask | SubstructureNotifyMask | ExposureMask | KeyPressMask | ButtonPressMask | PointerMotionMask))
+
+int LastEvent (Display *display, int type, XEvent *event);
+
+int cursor (Graphic *graphic, Layout *layout) {
+
+  Display        *display;
+  XEvent          event;
+  KeySym          keysym;
+  int             status;
+  XComposeStatus  composestatus;
+  char            string[10], line[40], *name;
+  double          x, y;
+  
+  while (1) {
+    
+    status = CheckPipe (graphic, layout);
+    if (status == 0) return (FALSE);
+    if (status == 2) return (TRUE);
+    if (status == 1) goto events;
+
+  events:
+    if (XEventsQueued (graphic[0].display, QueuedAfterFlush) < 1) {
+      usleep (10000);
+      continue;
+    }
+
+    display = graphic[0].display;
+
+    /* only do the last entry for these events */
+    /* this ignores the return status from these functions */
+    if (LastEvent (display, ConfigureNotify, &event)) Reconfig (graphic, layout, &event);
+    if (LastEvent (display, Expose,          &event)) Refresh (graphic, layout, 1);
+    if (LastEvent (display, MappingNotify,   &event)) XRefreshKeyboardMapping ((XMappingEvent *) &event);
+    if (LastEvent (display, MotionNotify,    &event)) UpdatePointer (graphic, layout, (XMotionEvent *) &event);
+    if (LastEvent (display, ButtonPress,     &event)) InterpretPresses (graphic, layout, (XButtonEvent *) &event);
+    if (LastEvent (display, KeyPress,        &event)) {
+      status = XLookupString ((XKeyEvent *) &event, string, 9, &keysym, &composestatus);
+
+      if (event.xkey.x < layout[0].picture.x) continue;
+      if (event.xkey.x > layout[0].picture.x + layout[0].picture.dx) continue;
+      if (event.xkey.y < layout[0].picture.y) continue;
+      if (event.xkey.y > layout[0].picture.y + layout[0].picture.dy) continue;
+	
+      Screen_to_Image (&x, &y, (double)event.xkey.x, (double)event.xkey.y, layout);
+      name = XKeysymToString (keysym);
+
+      // skip the following keys: 
+      if (!strcmp (name, "Shift_L")) continue;
+      if (!strcmp (name, "Shift_R")) continue;
+      if (!strcmp (name, "Control_L")) continue;
+      if (!strcmp (name, "Control_R")) continue;
+      if (!strcmp (name, "Alt_L")) continue;
+      if (!strcmp (name, "Alt_R")) continue;
+      if (!strcmp (name, "Super_L")) continue;
+      if (!strcmp (name, "Super_R")) continue;
+      if (!strcmp (name, "Caps_Lock")) continue;
+      if (!strcmp (name, "Pause")) continue;
+      if (!strcmp (name, "Continue")) continue;
+      if (!strcmp (name, "Num_Lock")) continue;
+      if (!strcmp (name, "Scroll_Lock")) continue;
+      if (!strcmp (name, "Print")) continue;
+      if (!strcmp (name, "(null)")) continue;
+
+      snprintf (line, 40, "%12s %12.6f %12.6f ", name, x, y);
+      write (layout[0].Ximage, line, 40);
+    }
+
+    /* remove those events we will ignore */
+    while (XCheckMaskEvent (display, IgnoreMask, &event)) continue;
+
+    /* events to remove which have no mask component */
+    while (XCheckTypedEvent (display, MappingNotify, &event)) continue;
+    while (XCheckTypedEvent (display, ClientMessage, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionClear, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionNotify, &event)) continue;
+    while (XCheckTypedEvent (display, SelectionRequest, &event)) continue;
+  }
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/DownArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/DownArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/DownArrow.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+DownArrow (button_event, height, width, SB_x, SB_y)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (width - SB_y)));
+    return (answer);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/LeftArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/LeftArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/LeftArrow.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+LeftArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && (m_y < SB_x));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/RightArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/RightArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/RightArrow.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+RightArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > (height - SB_x - SB_y)) && 
+	    (m_y < (height - SB_y)));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/ScrollBars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/ScrollBars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/ScrollBars.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+void
+ScrollBars (display, window, gc, height, width, SB_x, SB_y, f_x, f_y)
+Display *display;
+Window window;
+GC gc;
+int width, height, SB_x, SB_y;
+double f_x, f_y;
+{
+  
+  int x, y;
+
+  y = height - SB_y;
+  XDrawLine (display, window, gc, 0, y, width, y);
+  XDrawLine (display, window, gc, SB_x, 0, SB_x, height);
+  XDrawLine (display, window, gc, 0, SB_x, SB_x, SB_x);
+  x = width - SB_y;
+  y = height - SB_y;
+  XDrawLine (display, window, gc, x, y, x, height);
+  y = height - SB_x - SB_y;
+  XDrawLine (display, window, gc, 0, y, SB_x, y);
+  x = SB_y + SB_x;
+  y = height - SB_y;
+  XDrawLine (display, window, gc, x, y, x, height);
+  x = (width - 2*SB_y - SB_x) * f_x + SB_x + SB_y;
+  y = (height - 2*SB_x - SB_y) * f_y + SB_x;
+  XDrawLine (display, window, gc, x, height - SB_y, x, height);
+  XDrawLine (display, window, gc, x + 1, height - SB_y, x + 1, height);
+  XDrawLine (display, window, gc, 0, y, SB_x, y);
+  XDrawLine (display, window, gc, 0, y+1, SB_x, y+1);
+  y = height - SB_y;
+  XFillRectangle (display, window, gc, 0, y, SB_x, SB_y);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/UpArrow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/UpArrow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/UpArrow.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+UpArrow (button_event, height, width, SB_x, SB_y) 
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+{
+
+  int answer, m_x, m_y;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > SB_x) && 
+	    (m_x < (SB_x + SB_y)));
+  return (answer);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/xScrollBar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/xScrollBar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/xScrollBar.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int 
+xScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_x < SB_x) && 
+	    (m_y > SB_x) && 
+	    (m_y < (height - SB_x - SB_y)));
+  f1 = (double)(m_y - SB_x);
+  f2 = (double)(height - 2*SB_x - SB_y);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/yScrollBar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/yScrollBar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/scrollbar/yScrollBar.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "Ximage"
+# include "ScrollBars.h"
+
+int
+yScrollBar (button_event, height, width, SB_x, SB_y, f)
+XButtonEvent *button_event;
+int height, width, SB_x, SB_y;
+double *f;
+{
+
+  int answer, m_x, m_y;
+  double f1, f2;
+
+  m_x = button_event -> x;
+  m_y = button_event -> y;
+  answer = ((m_y > (height - SB_y)) && 
+	    (m_x > (SB_x + SB_y)) && 
+	    (m_x < (width - SB_y)));
+  f1 = (double)(m_x - SB_x - SB_y);
+  f2 = (double)(width - 2*SB_y - SB_x);
+  *f = f1 / f2;
+  return (answer);
+
+}
+
+	
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckColors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckColors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckColors.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "Ximage.h"
+
+/************** CheckColors *************/
+void CheckColors (Graphic *graphic, int *argc, char **argv) {
+
+  char *temp_name;
+  int N;
+
+  /* here we define the values for "black" (blackground) and "white" (whiteground)
+     if -fg, or -bg exist, or if Foreground or Background are set in .Xdefaults, 
+     use those.  blackground defaults to Black, whiteground defaults to White. */
+
+  graphic[0].black = BlackPixel (graphic[0].display, graphic[0].screen);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Foreground");
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -fg color\n");
+      exit (0);
+    }
+  }
+  if (temp_name != (char *)NULL) 
+    graphic[0].black = GetColor (graphic[0].display, temp_name, graphic[0].colormap, graphic[0].black);
+
+  graphic[0].white = WhitePixel (graphic[0].display, graphic[0].screen);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Background");
+  if ((N = get_argument (*argc, argv, "-bg"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -bg color\n");
+      exit (0);
+    }
+  }  
+  if (temp_name != (char *)NULL) 
+    graphic[0].white = GetColor (graphic[0].display, temp_name, graphic[0].colormap, graphic[0].white);
+ 
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckDisplayName.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckDisplayName.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckDisplayName.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+/************** CheckDisplayName *************/
+void CheckDisplayName (int *argc, char **argv, char *display_name) {
+
+  int N;
+
+  display_name[0] = 0;
+  if ((N = get_argument (*argc, argv, "-d"))) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+  if ((N = get_argument (*argc, argv, "-display"))) {
+    if (N + 1 < *argc) {
+      strcpy (display_name, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is [-display/-d] DisplayName\n");
+      exit (0);
+    }
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckFontName.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckFontName.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckFontName.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "Ximage.h"
+
+/************** CheckFontName *************/
+void CheckFontName (int *argc, char **argv, char *fontname) {
+
+  int N;
+
+  if ((N = get_argument (*argc, argv, "-font"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -font fontname\n");
+      exit (0);
+    }
+  }   
+  if ((N = get_argument (*argc, argv, "-fn"))) {
+    if (N + 1 < *argc) {
+      strcpy (fontname, argv[N + 1]);
+      remove_argument(N, argc, argv);
+      remove_argument(N, argc, argv);
+    } else {
+      fprintf (stderr, "error: usage is -fn fontname\n");
+      exit (0);
+    }
+  }   
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckGeometry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckGeometry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckGeometry.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "Ximage.h"
+
+/************** CheckGeometry *************/
+void CheckGeometry (int *argc, char **argv, Graphic *graphic) {
+
+  int status, x, y, N;
+  unsigned int dx, dy;
+  int X, Y, dX, dY;
+  char *temp_name;
+  
+  temp_name = XGetDefault (graphic[0].display, argv[0], "geometry");
+  if ((N = get_argument (*argc, argv, "-geom"))) {
+    if (N + 1 < *argc) {
+      temp_name = argv[N+1];
+    }
+    else {
+      fprintf (stderr, "error: usage is -geom DisplayName\n");
+      exit (0);
+    }
+  }
+  X = 10;
+  Y = 10;
+  dX = 512 + 2*PAD1 + PAD1 + ZOOM_X;
+  dY = 512 + 2*PAD1 + PAD2 + COLORPAD;
+  if (temp_name != (char *)NULL) {  
+    status = XParseGeometry (temp_name, &x, &y, &dx, &dy);
+    if (status & XValue)
+      X = x;
+    if (status & YValue)
+      Y = y;
+    if (status & WidthValue) {
+      dX = dx + 2*PAD1 + PAD1 + ZOOM_X;
+      dX = MAX (dX, MIN_WIDTH);
+    }
+    if (status & HeightValue) {
+      dY = dy + 2*PAD1 + PAD2 + COLORPAD + 42;
+      dY = MAX (dY, MIN_HEIGHT);
+    }
+    if (status & XNegative)
+      X  = DisplayWidth  (graphic[0].display, graphic[0].screen) - dX + X;
+    if (status & YNegative)
+      Y  = DisplayHeight (graphic[0].display, graphic[0].screen) - dY + Y;
+  }
+
+  graphic[0].x = X;
+  graphic[0].y = Y;
+  graphic[0].dx = dX;
+  graphic[0].dy = dY; 
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckVisual.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckVisual.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/CheckVisual.c	(revision 16632)
@@ -0,0 +1,196 @@
+# include "Ximage.h"
+# define NPIXELS 64
+
+/* DirectColor doesn't seem to work, even though it is available:
+   I cannot use XAllocColorCells to get pixels under DirectColor
+*/
+
+/* static int try_visual[] = {5, 3, 1, 4, 2, 0}; */
+
+void CheckVisual (Graphic *graphic, int *argc, char **argv) {
+
+  int i, Nfound, N;
+  int col, def, dyn;
+  XVisualInfo *visual_list, visual_temp;
+  unsigned long planes[3];
+  XPixmapFormatValues *pixmaps;
+  int Npixmaps;
+
+  if (DEBUG) {
+    fprintf (stderr, "DirectColor: %d\n", DirectColor);
+    fprintf (stderr, "PseudoColor: %d\n", PseudoColor);
+    fprintf (stderr, "TrueColor: %d\n", TrueColor);
+    fprintf (stderr, "GrayScale: %d\n", GrayScale);
+    fprintf (stderr, "StaticColor: %d\n", StaticColor);
+    fprintf (stderr, "StaticGray: %d\n", StaticGray);
+  }
+
+  visual_temp.screen = graphic[0].screen;
+  
+  /* find available visuals */
+  visual_list = XGetVisualInfo (graphic[0].display, VisualScreenMask, &visual_temp, &Nfound);
+  if (Nfound == 0) {
+    fprintf (stderr, "error finding useful visual\n");
+    exit (0);
+  }
+  
+  /* check default visual first */ 
+  for (i = 0; (i < Nfound) && (graphic[0].visual != visual_list[i].visual); i++);
+  if (i == Nfound) {
+    fprintf (stderr, "default visual not found??\n");
+    exit (0);
+  }
+
+  col = def = dyn = FALSE;
+  if (DEBUG) fprintf (stderr, "default visual class is %d\n", visual_list[i].class);
+  switch (visual_list[i].class) {
+  case PseudoColor:
+    col = def = dyn = TRUE;
+    graphic[0].visual = visual_list[i].visual;
+    graphic[0].visualclass = TRUE;
+    goto test_pixels;
+    break;
+  default:
+    break;
+  }
+
+  for (i = 0; i < Nfound; i++) {
+    switch (visual_list[i].class) {
+    case PseudoColor:
+      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+      col = dyn = TRUE;
+      if (graphic[0].visual == visual_list[i].visual) {
+	def = TRUE;
+      } else {
+	graphic[0].visual = visual_list[i].visual;
+      }
+      graphic[0].visualclass = TRUE;
+      goto test_pixels;
+      break;
+    default:
+      break;
+    }
+  }
+
+  for (i = 0; i < Nfound; i++) {
+    switch (visual_list[i].class) {
+    case GrayScale:
+      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
+      dyn = TRUE;
+      if (graphic[0].visual == visual_list[i].visual) {
+	def = TRUE;
+      } else {
+	graphic[0].visual = visual_list[i].visual;
+      }
+      graphic[0].visualclass = TRUE;
+      goto test_pixels;
+      break;
+    default:
+      break;
+    }
+  }
+
+  for (i = 0; (i < Nfound) && (visual_list[i].class != TrueColor); i++);
+  if (i != Nfound) {
+    col = TRUE;
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticColor); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticGray); i++);
+  if (i != Nfound) {
+    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
+    if (graphic[0].visual == visual_list[i].visual) {
+      def = TRUE;
+    } else {
+      graphic[0].visual = visual_list[i].visual;
+    }
+    graphic[0].visualclass = FALSE;
+    goto test_pixels;
+  }
+
+  test_pixels:
+
+  /* need to make a colormap if 
+     1) the selected visual is not the default 
+     2) there are not enough colors available */
+
+  /* NEED TO ADD A COUPLE LINES DEFINING THE VARIOUS HARD COLORS (BLACK, WHITE, AND THE OVERLAYS) */
+
+  if ((N = get_argument (*argc, argv, "-private"))) {
+    remove_argument(N, argc, argv);
+    def = FALSE;
+  } 
+
+  if (!def) {
+    if (DEBUG) fprintf (stderr, "allocated private colormap\n");
+    graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+  }
+
+  if (dyn) {
+    /* allocate color cells  */
+    for (graphic[0].Npixels = NPIXELS;
+	 ((graphic[0].Npixels >= 16) && 
+	  !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
+	 graphic[0].Npixels -= 4) {
+      if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
+    }
+
+
+    /* make private colormap  */
+    if (graphic[0].Npixels < 16) {
+      fprintf (stderr, "can't allocate enough cells, using private colormap\n");
+      graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
+      for (graphic[0].Npixels = NPIXELS;
+	   ((graphic[0].Npixels >= 16) && 
+	    !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
+	   graphic[0].Npixels -= 4);
+
+      if ((N = get_argument (*argc, argv, "-colorcount"))) {
+	fprintf (stderr, "kii can grab %d colors\n", (int) graphic[0].Npixels);
+	exit (0);
+      } 
+      if (graphic[0].Npixels < 16) {
+	fprintf (stderr, "can't even allocate enough cells in private colormap\n");
+	exit (0);
+      }
+    }
+  }
+
+  if (!dyn) {
+    graphic[0].Npixels = 256;
+    fprintf (stderr, "can't use dynamic colors, color scrollbar inactive\n");
+    fprintf (stderr, " this can be avoided by using a dynamic visual class\n");
+    fprintf (stderr, " (see Kii help page for details)\n");
+  }
+
+  if ((N = get_argument (*argc, argv, "-colorcount"))) {
+    fprintf (stderr, "kii can grab %d colors\n", (int) graphic[0].Npixels);
+    exit (0);
+  } 
+  
+  pixmaps = XListPixmapFormats (graphic[0].display, &Npixmaps);
+  for (i = 0; i < Npixmaps; i++) {
+    if (pixmaps[i].depth == graphic[0].depth) {
+      graphic[0].Nbits = pixmaps[i].bits_per_pixel;
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/CloseDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/CloseDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/CloseDisplay.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** CloseDisplay *************/
+void CloseDisplay (Graphic *graphic) {
+
+  XFlush (graphic[0].display);
+  XFreeFont (graphic[0].display, graphic[0].font); 
+  XFreeGC (graphic[0].display, graphic[0].gc);
+  XDestroySubwindows (graphic[0].display, graphic[0].window);
+  XDestroyWindow (graphic[0].display, graphic[0].window);
+  XFlush (graphic[0].display);
+  XCloseDisplay (graphic[0].display);
+  return;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/CreateWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/CreateWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/CreateWindow.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "Ximage.h"
+
+/************** CreateWindow *************/
+void
+CreateWindow (graphic, parent, border, events)
+Graphic       graphic[];
+Window        parent;
+int           border;
+long          events;
+{
+
+  XSetWindowAttributes attributes;
+  unsigned long attribute_mask;
+
+  attributes.background_pixel = graphic[0].white;
+  attributes.border_pixel     = graphic[0].black;
+  attributes.event_mask       = events;
+  attributes.colormap         = graphic[0].colormap;
+  attribute_mask              = CWBackPixel | CWBorderPixel | CWEventMask | CWColormap;
+
+  graphic[0].window = XCreateWindow (graphic[0].display, parent, 
+				     graphic[0].x, graphic[0].y, 
+				     graphic[0].dx, graphic[0].dy, 
+				     border, graphic[0].depth,
+				     InputOutput, graphic[0].visual, 
+				     attribute_mask, &attributes);
+
+  if (graphic[0].window == (Window) None)
+    QuitX (graphic[0].display, "", "error: could not open window");
+
+  XSelectInput (graphic[0].display, graphic[0].window, events);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/DefineLayout.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/DefineLayout.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/DefineLayout.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "Ximage.h"
+
+static char default_colormap[] = "grayscale";
+
+void DefineLayout (Layout *layout, Graphic *graphic, int argc, char **argv) {
+
+  int i, N;
+  char *colormap;
+
+  /** initiate connection with mana **/
+  if (!FOREGROUND) {
+    if (argc < 2) {
+      fprintf (stderr, "socket path not specified\n");
+      exit (0);
+    }
+    layout[0].Ximage = KiiWait (argv[1]);
+  }
+
+  PositionPictures (layout, graphic);
+  
+  /* get the display colors */
+  if (USE_XWINDOW) {
+    MakeColormap (graphic, layout, argc, argv);
+  } else {
+    colormap = default_colormap;
+    if ((N = get_argument (argc, argv, "-cm"))) {
+      remove_argument (N, &argc, argv);
+      colormap = argv[N];
+    }
+    layout[0].Npixels = 256;
+    SetColormap (graphic, layout, colormap);
+  }
+
+  /** set up a bunch of default things **/
+  layout[0].X = layout[0].Y = 0;
+  layout[0].expand = 1;
+  layout[0].zero = 0;
+  layout[0].range = 1;
+  layout[0].coords.Npolyterms = 0;
+  for (i = 0; i < NOVERLAYS; i++) {
+    layout[0].overlay[i].Nobjects = 0;
+    ALLOCATE (layout[0].overlay[i].objects, Object, 1);  /* allocate so later free will not crash! */
+    OVERLAY[i] = FALSE;
+  }
+  layout[0].matrix.size = 0; /* a flag to show there is no data in the matrix */
+
+  MOVE_POINTER = TRUE;
+  DECIMAL_DEG  = TRUE;
+  ALLOCATE (layout[0].matrix.buffer, char, 1);  /* allocate so later free will not crash! */
+  ALLOCATE (layout[0].picture.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (layout[0].cmapbar.data, char, 1);   /* allocate so later free will not crash! */
+  ALLOCATE (layout[0].zoom.data, char, 1);      /* allocate so later free will not crash! */
+
+  if (USE_XWINDOW) {
+    CreatePicture (layout, graphic);
+    CreateColorbar (layout, graphic);
+    CreateZoom (layout, graphic, 0, 0); 
+  }
+}
+
+/* this routine is independent of the number of overlays */
+
+  /* cmap = the mapping of value to color in kii
+     colormap = the set of pixel -> color representation in X */
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/DrawBitmap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/DrawBitmap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/DrawBitmap.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "Ximage.h"
+
+void
+DrawBitmap (graphic, x, y, dx, dy, bitmap, mode)
+Graphic     graphic[];
+int         x, y, dx, dy;
+char        bitmap[];
+int         mode;
+{
+
+  int i, j, byte_line, byte, bit, flag;
+  unsigned long int black, white;
+
+  black = graphic[0].black;
+  white = graphic[0].white;
+
+  if (mode == 0) {
+    black = graphic[0].black;
+    white = graphic[0].white;
+    graphic[0].black = white;
+    graphic[0].white = white;
+  }
+    
+  if (mode == 2) {
+    black = graphic[0].black;
+    white = graphic[0].white;
+    graphic[0].black = white;
+    graphic[0].white = black;
+  }
+    
+  
+  byte_line = (int) ((dx + 7) / 8);
+  for (i = 0; i < dy; i++) {
+    for (j = 0; j < dx; j++) {
+      byte = byte_line * i + (j / 8);
+      bit = j % 8;
+      flag = 0x01 & (bitmap[byte] >> bit);
+      if (flag)
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+      else 
+	XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+      XDrawPoint (graphic[0].display, graphic[0].window, 
+		  graphic[0].gc, x + j, y + i);
+    }
+  }
+  if (mode == 0) {
+    graphic[0].black = black;
+    graphic[0].white = white;
+  }
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/GetColor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/GetColor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/GetColor.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "Ximage.h"
+
+/************** GetColor *************/
+unsigned long 
+GetColor (display, name, colormap, default_color)
+Display  *display;
+char      name[];
+Colormap  colormap;
+unsigned long default_color;
+{
+
+  unsigned long color;
+  XColor rgbcolor, hardwarecolor;
+  int status;
+
+  color = default_color;
+  status = XLookupColor (display, colormap, name, &rgbcolor, &hardwarecolor);
+  if (status) {
+    status = XAllocColor (display, colormap, &hardwarecolor);
+    if (status) {
+      color = hardwarecolor.pixel;
+    }
+  }
+  return (color);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/LoadFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/LoadFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/LoadFont.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "Ximage.h"
+
+/************** LoadFont *************/
+void
+LoadFont (graphic, argc, argv, default_name)
+Graphic   graphic[];
+int      *argc;
+char     *argv[];
+char      default_name[];
+{
+
+  char name[400];
+
+  strcpy (name, default_name);
+  CheckFontName (argc, argv, name);
+  graphic[0].font = XLoadQueryFont (graphic[0].display, name);
+  if (graphic[0].font == (XFontStruct *) NULL) {
+    fprintf (stderr, "Could not load fond %s, using %s\n", name, default_name);
+    graphic[0].font = XLoadQueryFont (graphic[0].display, default_name);
+    if (graphic[0].font == (XFontStruct *) NULL) {
+      graphic[0].font = XLoadQueryFont (graphic[0].display, "fixed");
+      fprintf (stderr, "Could not load fond %s, using %s\n", 
+	       default_name, "fixed");
+    }
+  }
+  if (graphic[0].font != (XFontStruct *) NULL) 
+    XSetFont (graphic[0].display, graphic[0].gc, graphic[0].font[0].fid);
+  else
+    QuitX (graphic[0].display, "Error: could not load font", name);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeColormap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeColormap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeColormap.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "Ximage.h"
+# define NPIXELS 64
+
+static char default_cmap[] = "grayscale";
+
+void MakeColormap (Graphic *graphic, Layout *layout, int argc, char **argv) {
+
+  int i, N, status;
+  char *temp_name;
+
+  /* hardwired colors - white, black -- for drawing text and overlay graphics */
+  layout[0].white = graphic[0].white;
+  layout[0].black = graphic[0].black;
+  layout[0].start = 0;
+  layout[0].slope = 1;
+  temp_name = XGetDefault (graphic[0].display, argv[0], "ROverlay");
+  layout[0].overlay[0].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "red"    : temp_name), graphic[0].colormap, graphic[0].black);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "GOverlay");
+  layout[0].overlay[1].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "green"  : temp_name), graphic[0].colormap, graphic[0].black);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "BOverlay");
+  layout[0].overlay[2].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "blue"   : temp_name), graphic[0].colormap, graphic[0].black);
+  temp_name = XGetDefault (graphic[0].display, argv[0], "YOverlay");
+  layout[0].overlay[3].color = GetColor (graphic[0].display, (temp_name == (char *) NULL ? "yellow" : temp_name), graphic[0].colormap, graphic[0].black);
+
+  layout[0].Npixels = graphic[0].Npixels;
+  for (i = 0; i < layout[0].Npixels; i++) 
+    layout[0].cmap[i].pixel = graphic[0].pixels[i];
+
+  /* decide on a color map */
+  temp_name = XGetDefault (graphic[0].display, argv[0], "Colormap");
+  if ((N = get_argument (argc, argv, "-cm"))) {
+    if (N + 1 < argc) {
+      temp_name = argv[N+1];
+    } else {
+      fprintf (stderr, "error: usage is -cm ColormapName\n");
+      exit (1);
+    }
+  }
+  if (temp_name == (char *) NULL) temp_name = default_cmap;
+
+  status = SetColormap (graphic, layout, temp_name);
+  if (!status) {
+    fprintf (stderr, "invalid colormap, using default %s\n", default_cmap);
+    temp_name = default_cmap;
+    status = SetColormap (graphic, layout, temp_name);
+    if (!status) {
+      fprintf (stderr, "problem with default colormap\n");
+      exit (1);
+    }
+  }
+}
+
+/* this routine is NOT independent of the number of overlays */
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeCursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeCursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeCursor.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "Ximage.h"
+
+/************** MakeCursor *************/
+void
+MakeCursor  (graphic, which_cursor)
+Graphic      graphic[];
+unsigned int which_cursor;
+{
+
+  graphic[0].cursor = XCreateFontCursor (graphic[0].display, 
+					 (unsigned) which_cursor);
+  if (graphic[0].cursor != (Cursor) None)
+    XDefineCursor (graphic[0].display, graphic[0].window, graphic[0].cursor);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeGC.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeGC.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/MakeGC.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** MakeGC *************/
+void MakeGC (Graphic *graphic) {
+
+  XGCValues gcvalues;
+
+  gcvalues.foreground = graphic[0].black;
+  gcvalues.background = graphic[0].white;
+  graphic[0].gc = XCreateGC (graphic[0].display, graphic[0].window, 
+			     GCForeground | GCBackground, &gcvalues);
+  if (graphic[0].gc == 0)
+    QuitX (graphic[0].display, "Error in creating a Graphics Context", "");
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/MapWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/MapWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/MapWindow.c	(revision 16632)
@@ -0,0 +1,13 @@
+# include "Ximage.h"
+
+/************** MapWindow *************/
+void
+MapWindow (graphic)
+Graphic    graphic[];
+{
+
+  XMapRaised (graphic[0].display, graphic[0].window);
+  XMapSubwindows (graphic[0].display, graphic[0].window);
+  XFlush (graphic[0].display);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/NameWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/NameWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/NameWindow.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "Ximage.h"
+
+/************** NameWindow *************/
+void NameWindow (Graphic *graphic, char *name) {
+
+  char       *class_name;
+  char       *class_type;
+  XClassHint *classhints;
+
+  class_type = class_name = name;
+
+  classhints = XAllocClassHint ();
+
+  if (classhints != (XClassHint *) NULL)  {
+    classhints[0].res_name = class_name;
+    classhints[0].res_class = class_type;
+    XSetClassHint (graphic[0].display, graphic[0].window, classhints);
+    XFree (classhints);
+  }
+  
+  XStoreName (graphic[0].display, graphic[0].window, name);
+  XSetIconName (graphic[0].display, graphic[0].window, name);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/OpenDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/OpenDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/OpenDisplay.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "Ximage.h"
+
+/************** OpenDisplay *************/
+Display *OpenDisplay (char *display_name, int *screen) {
+
+  Display *display;
+  
+  display = XOpenDisplay (display_name);
+  if (display != (Display *) NULL)
+    *screen = DefaultScreen (display);
+  if (display == (Display *) NULL) {
+    fprintf (stderr, "Error could not open X display to %s\n", 
+	     XDisplayName (display_name));
+    exit (0);
+  }
+
+  return (display);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/QuitX.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/QuitX.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/QuitX.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "Ximage.h"
+
+/************** QuitX *************/
+void
+QuitX (display, error_message, error_file)
+Display *display;
+char error_message[], error_file[];
+{
+
+  fprintf (stderr, "Error: %s%s\n", error_message, error_file);
+  XCloseDisplay (display);
+  exit (0);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/SetNormalHints.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/SetNormalHints.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/SetNormalHints.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "Ximage.h"
+
+/************** SetNormalHints  *************/
+void
+SetNormalHints (graphic)
+Graphic         graphic[];
+{
+
+  XSizeHints *sizehints;
+
+  sizehints = XAllocSizeHints ();
+
+  if (sizehints != (XSizeHints *) NULL)  {
+    sizehints[0].x = graphic[0].x;
+    sizehints[0].y = graphic[0].x;
+    sizehints[0].width = graphic[0].dx;
+    sizehints[0].height = graphic[0].dy;
+    sizehints[0].min_width = MIN_WIDTH;
+    sizehints[0].min_height = MIN_HEIGHT;    
+    sizehints[0].flags = USPosition | USSize | PMinSize;
+
+    sizehints[0].base_width = graphic[0].dx;
+    sizehints[0].base_height = graphic[0].dy;
+    sizehints[0].flags |= PBaseSize;
+    
+    XSetWMNormalHints (graphic[0].display, graphic[0].window, sizehints);
+    XFree (sizehints);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/SetUpDisplay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/SetUpDisplay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/SetUpDisplay.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "Ximage.h"
+
+/************** SetUpDisplay *************/
+void SetUpDisplay (Graphic *graphic, int *argc, char **argv) {
+
+  char display_name[120];
+
+  CheckDisplayName (argc, argv, display_name); 
+
+  /* set default values */
+  graphic[0].display  = OpenDisplay (display_name, &graphic[0].screen);
+  graphic[0].colormap = DefaultColormap (graphic[0].display, graphic[0].screen);
+  graphic[0].depth    = DefaultDepth    (graphic[0].display, graphic[0].screen);
+  graphic[0].visual   = DefaultVisual   (graphic[0].display, graphic[0].screen);
+
+  /* get the basic colors */
+  CheckVisual (graphic, argc, argv);
+  CheckColors (graphic, argc, argv);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/SetUpWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/SetUpWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/SetUpWindow.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+# include "icons/icon.h"
+
+/************** SetUpWindow *************/
+void SetUpWindow (Graphic *graphic, int *argc, char **argv) {
+
+  Icon icon;
+  char *name;
+
+  icon.width = icon_width;
+  icon.height = icon_height;
+  icon.bits = icon_bits;
+
+  CheckGeometry (argc, argv, graphic);
+  TopWindow (graphic, &icon);
+  LoadFont (graphic, argc, argv, "fixed"); 
+
+  XFlush (graphic[0].display);
+  XSetWindowBackground (graphic[0].display, graphic[0].window, graphic[0].white);
+
+  SetNormalHints (graphic);
+  SetWMHints (graphic, &icon);
+
+  if (NAME_WINDOW == NULL) {
+    NameWindow (graphic, "Ki'i");
+  } else {
+    ALLOCATE (name, char, strlen(NAME_WINDOW) + 10);
+    sprintf (name, "Ki'i %s", NAME_WINDOW);
+    NameWindow (graphic, name);
+    free (name);
+  }
+
+  if (MAP_WINDOW) MapWindow (graphic);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/SetWMHints.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/SetWMHints.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/SetWMHints.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "Ximage.h"
+
+/************** SetWMHints  *************/
+void
+SetWMHints (graphic, icon) 
+Graphic     graphic[];
+Icon        icon[];
+{
+  XWMHints *wmhints;
+
+  wmhints = XAllocWMHints ();
+  if (wmhints != (XWMHints *)NULL) {
+    wmhints[0].initial_state = NormalState;
+    wmhints[0].input = True;
+    if (icon[0].pixmap != (Pixmap) None) {
+      wmhints[0].icon_pixmap = icon[0].pixmap;
+      wmhints[0].icon_mask = icon[0].pixmap;
+      wmhints[0].flags = StateHint | InputHint | IconPixmapHint | IconMaskHint;
+    }
+    else 
+      wmhints[0].flags = StateHint | InputHint;
+    
+    XSetWMHints (graphic[0].display, graphic[0].window, wmhints);
+    XFree (wmhints);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/TopWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/TopWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/TopWindow.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "Ximage.h"
+
+/************** TopWindow *************/
+void TopWindow (Graphic *graphic, Icon *icon) {
+
+  Window rootwindow;
+
+  rootwindow = RootWindow (graphic[0].display, graphic[0].screen);
+
+  CreateWindow (graphic, rootwindow, BORDER_WIDTH, EVENT_MASK);
+  MakeGC (graphic);
+  icon[0].pixmap = XCreateBitmapFromData (graphic[0].display,
+					graphic[0].window, 
+					icon[0].bits, 
+					icon[0].width, 
+					icon[0].height);
+  MakeCursor (graphic, DEFAULT_CURSOR);
+  XFreeCursor (graphic[0].display, graphic[0].cursor);
+  XFlush (graphic[0].display);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/Ximage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/Ximage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/Ximage.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "Ximage.h"
+
+int main (int argc, char **argv) {
+
+  Graphic graphic;
+  Layout  layout;
+  
+  args (&argc, argv);
+
+  bzero (&graphic, sizeof(Graphic));
+  bzero (&layout, sizeof(Layout));
+
+  if (USE_XWINDOW) SetUpDisplay (&graphic, &argc, argv);
+  if (USE_XWINDOW) {
+    SetUpWindow (&graphic, &argc, argv);
+  } else {
+    graphic.x = 10;
+    graphic.y = 10;
+    graphic.dx = 512 + 2*PAD1 + PAD1 + ZOOM_X;
+    graphic.dy = 512 + 2*PAD1 + PAD2 + COLORPAD;
+  }
+
+  DefineLayout (&layout, &graphic, argc, argv);
+  EventLoop (&graphic, &layout);
+
+  if (USE_XWINDOW) CloseDisplay (&graphic);
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/setup/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/setup/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/setup/args.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "Ximage.h"
+
+int args (int *argc, char **argv) {
+
+  int N;
+
+  MAP_WINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-nomap"))) {
+    remove_argument(N, argc, argv);
+    MAP_WINDOW = FALSE;
+  }
+
+  NAME_WINDOW = NULL;
+  if ((N = get_argument (*argc, argv, "-name"))) {
+    remove_argument(N, argc, argv);
+    NAME_WINDOW = strcreate (argv[N]);
+    remove_argument(N, argc, argv);
+  }
+
+  USE_XWINDOW = TRUE;
+  if ((N = get_argument (*argc, argv, "-noX"))) {
+    remove_argument(N, argc, argv);
+    USE_XWINDOW = FALSE;
+  }
+
+  DEBUG = FALSE;
+  if ((N = get_argument (*argc, argv, "-debug"))) {
+    remove_argument(N, argc, argv);
+    DEBUG = TRUE;
+  }
+
+  FOREGROUND = FALSE;
+  if ((N = get_argument (*argc, argv, "-fg"))) {
+    remove_argument(N, argc, argv);
+    FOREGROUND = TRUE;
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/test/jpeg.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/test/jpeg.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/test/jpeg.sh	(revision 16632)
@@ -0,0 +1,17 @@
+
+macro kii-test
+  mcreate z 512 512
+  set a = xramp (z)
+  tv a 0 512
+
+  load red sample.reg
+
+  create x 64 512 64
+  vload red x x -type circle -size 5
+  vload blue x x -type box -size 3
+  vload yellow x x -type line -size 10
+
+  jpeg -name test.png
+  ps -name test.ps
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/test/regions.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/test/regions.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/test/regions.sh	(revision 16632)
@@ -0,0 +1,32 @@
+
+$KII = kii -noX
+
+macro go
+ mcreate a 512 512
+ set b = yramp (a)
+ tv b 0 512
+ create x 0 512 64
+ set y = 1.1*x
+ vload red x x
+ vload red x y
+ set y = x + 10
+ vload blue -type line x y
+ set y = x + 20
+ vload green -type circle x y -size 3.0
+ set y = x + 30
+ vload yellow -type box x y -size 5.0
+
+ for i 1 6
+  vload red -type box x y -size $i
+  vload blue -type circle x y -size $i
+ end
+
+ jpeg -name test.jpg
+
+ resize 512 512
+ center 256 256 1
+ jpeg -name test2.jpg
+
+ center 256 256 3
+ jpeg -name test3.jpg
+end
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/CheckTextLines.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/CheckTextLines.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/CheckTextLines.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "Ximage.h"
+
+/******** Here we test the TextLines specific to this program  ****
+TextLine *
+CheckTextLines (graphic, event, layout)
+Graphic         graphic[];
+XEvent          event[];
+Layout          layout[];
+{
+
+  TextLine *textline;
+  textline = (TextLine *) NULL;
+
+  if (InTextLine (graphic, event, &layout[0].zero))
+    textline = &layout[0].zero;
+  if (InTextLine (graphic, event, &layout[0].range))
+    textline = &layout[0].range;
+  if (InTextLine (graphic, event, &layout[0].effects))
+    textline = &layout[0].effects;
+  if (InTextLine (graphic, event, &layout[0].command))
+    textline = &layout[0].command;
+
+  return (textline);
+
+}
+
+
+***/
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawCursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawCursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawCursor.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+
+DrawCursor (graphic, textline)    
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int dx, label_width, DX, text_width, i;
+
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+    dx  = XTextWidth (graphic[0].font, &textline[0].text[i - 1], 
+		      textline[0].cursor - i + 1) + arrow_width;
+  }
+  else 
+    dx  = XTextWidth (graphic[0].font, textline[0].text, textline[0].cursor);
+
+  XDrawLine (graphic[0].display, 
+	     graphic[0].window, 
+	     graphic[0].gc, 
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + YBorder,
+	     textline[0].x + label_width + XBorder + dx, 
+	     textline[0].y + textline[0].dy - YBorder);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawTextBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawTextBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawTextBox.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* DrawTextBox ****************/
+DrawTextBox (graphic, textbox)
+Graphic      graphic[];
+TextBox      textbox[];
+{
+
+  int X, Y, y, dy, Nlines, i;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XFillRectangle (graphic[0].display, 
+		  graphic[0].window,
+		  graphic[0].gc,
+		  textbox[0].x  + 1,  textbox[0].y + 1,
+		  XBorder - 2, textbox[0].dy - 2);
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textbox[0].x,  textbox[0].y,
+		    textbox[0].dx, textbox[0].dy);
+  }
+
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  Nlines = (textbox[0].dy - 2*YBorder) / dy;
+
+  for (i = 0; (i < Nlines) && (i < textbox[0].Nlines); i++) {
+    y = textbox[0].y + graphic[0].font[0].ascent + dy*i + YBorder;
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textbox[0].x + XBorder, y,
+		 textbox[0].text[i], 
+		 strlen(textbox[0].text[i]));
+  }
+
+  if (Nlines < textbox[0].Nlines) {
+    DrawBitmap (graphic, 
+		textbox[0].x + textbox[0].dx - down_width - 2,
+		textbox[0].y + textbox[0].dy - down_height - 2,
+		down_width, down_height, down_bits, 1);
+  }
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textbox[0].cursor_line != -1) {
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawTextLine.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawTextLine.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/DrawTextLine.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+DrawTextLine (graphic, textline)
+Graphic  graphic[];
+TextLine textline[];
+{
+
+  int y;
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  if (textline[0].outline) {
+    XDrawRectangle (graphic[0].display, 
+		    graphic[0].window,
+		    graphic[0].gc,
+		    textline[0].x,  textline[0].y,
+		    textline[0].dx, textline[0].dy);
+  }
+
+  y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+  XDrawString (graphic[0].display, 
+	       graphic[0].window, 
+	       graphic[0].gc, 
+	       textline[0].x + XBorder, y,
+	       textline[0].label, 
+	       strlen(textline[0].label));
+  RedrawString (graphic, textline);
+
+  if (textline[0].cursor != -1)
+    DrawCursor (graphic, textline);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/InTextBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/InTextBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/InTextBox.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "Ximage.h"
+# define XBorder 10
+# define YBorder 2
+# define arrow_width 6
+# define arrow_height 9
+static char arrow_bits[] = {
+  0x00, 0x02, 0x06, 0x0e, 0x1e, 0x0e, 0x06, 0x02, 0x00};
+#define down_width 9
+#define down_height 6
+static char down_bits[] = {
+   0x00, 0x00, 0xfe, 0x00, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00, 0x00};
+
+/******************* InTextBox ****************/
+int
+InTextBox (graphic, event, textbox)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextBox          textbox[];
+{
+
+  int answer;
+  int i, x, y, Y, X, dy;
+  int minX, maxX, minY, maxY;
+  
+  x = event[0].x;
+  y = event[0].y;
+  dy = graphic[0].font[0].ascent + graphic[0].font[0].descent;
+  
+  minX = textbox[0].x;
+  maxX = textbox[0].x + textbox[0].dx;
+  minY = textbox[0].y;
+  maxY = textbox[0].y + textbox[0].dy;
+  if (dy*textbox[0].Nlines + 2*YBorder < textbox[0].dy)
+    maxY = textbox[0].y + dy*textbox[0].Nlines + 2*YBorder;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+  
+  /* find the cursor position, erase the old arrow and draw a new arrow */
+  if (answer) {
+    if (textbox[0].cursor_line != -1) {
+      Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+      X = textbox[0].x + (XBorder - arrow_width) / 2;
+      DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 0);
+    }
+    textbox[0].cursor_line = (y - textbox[0].y - YBorder)/dy;
+    X = textbox[0].x + (XBorder - arrow_width) / 2;
+    Y = textbox[0].y + dy*textbox[0].cursor_line + YBorder + (dy - arrow_height)/2;
+    DrawBitmap (graphic, X, Y, arrow_width, arrow_height, arrow_bits, 1);
+    textbox[0].cursor_x = x;
+    textbox[0].cursor_y = y;
+    XFlush (graphic[0].display);
+  }
+  
+  return (answer);
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/InTextLine.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/InTextLine.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/InTextLine.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int
+InTextLine (graphic, event, textline)
+Graphic          graphic[];
+XButtonEvent    *event;
+TextLine         textline[];
+{
+
+  int answer, done;
+  int i, x, dx, y, text_width, label_width;
+  int minX, maxX, minY, maxY;
+  char testline[1000];
+
+  x = event[0].x;
+  y = event[0].y;
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  minX = textline[0].x + XBorder + label_width;
+  maxX = textline[0].x + textline[0].dx;
+  minY = textline[0].y;
+  maxY = textline[0].y + textline[0].dy;
+
+  answer = ((x >= minX) && (x <= maxX) && (y >= minY) && (y <= maxY));
+
+  /* find the cursor position and draw a vertical bar */
+  if (answer) {
+    text_width  = XTextWidth (graphic[0].font, 
+			      textline[0].text,
+			      strlen(textline[0].text));
+    
+    if (x >= minX + text_width) {
+      textline[0].cursor = strlen (textline[0].text);
+    }
+    else {
+      for (i = 1, done = FALSE; (i <= strlen (textline[0].text)) && !done; i++) {
+	dx  = XTextWidth (graphic[0].font, 
+			  textline[0].text, i);
+	if (x < minX + dx) {
+	  textline[0].cursor = i - 1;
+	  done = TRUE;
+	}
+      }
+    }
+    DrawCursor (graphic, textline);
+  }    
+  XFlush (graphic[0].display);
+  
+  return (answer);
+  
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/RedrawString.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/RedrawString.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/RedrawString.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+
+#define arrow_width 6
+#define arrow_height 9
+RedrawString (graphic, textline)
+Graphic       graphic[];
+TextLine      textline[];
+{
+
+  int label_width, text_width, y, i, DX;
+  static char arrow_bits[] = {
+    0x00, 0x10, 0x18, 0x1c, 0x1e, 0x1c, 0x18, 0x10, 0x00};
+  
+  label_width  = XTextWidth (graphic[0].font, 
+			     textline[0].label,
+			     strlen(textline[0].label));
+  
+  text_width  = XTextWidth (graphic[0].font, 
+			    textline[0].text,
+			    strlen(textline[0].text));
+
+  if (label_width + text_width + 2*XBorder > textline[0].dx) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    DX = textline[0].dx - label_width - 2*XBorder - arrow_width;
+    for (i = 1; (i < strlen (textline[0].text)) && (text_width > DX); i++) {
+      text_width  = XTextWidth (graphic[0].font, 
+				&textline[0].text[i],
+				strlen(&textline[0].text[i]));
+    }
+
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    DrawBitmap (graphic, 
+		textline[0].x + XBorder + label_width,
+		textline[0].y + YBorder + (textline[0].dy - arrow_height)/2,
+		arrow_width, arrow_height, arrow_bits, 1);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width + arrow_width, y,
+		 &textline[0].text[i - 1], 
+		 strlen(&textline[0].text[i - 1]));
+    XFlush (graphic[0].display);
+  }
+  else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		    textline[0].x + XBorder + label_width, 
+		    textline[0].y + YBorder, 
+		    textline[0].dx - XBorder - label_width, 
+		    textline[0].dy - 2*YBorder + 1);
+    
+    y = textline[0].y + (textline[0].dy + graphic[0].font[0].ascent) / 2;
+    
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    XDrawString (graphic[0].display, 
+		 graphic[0].window, 
+		 graphic[0].gc, 
+		 textline[0].x + XBorder + label_width, y,
+		 textline[0].text, 
+		 strlen(textline[0].text));
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/textline/TextLineEntry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/textline/TextLineEntry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/textline/TextLineEntry.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "Ximage.h"
+# define XBorder 5
+# define YBorder 2
+
+int 
+TextLineEntry (graphic, textline, keyevent)
+Graphic        graphic[];
+TextLine       textline[];
+XKeyEvent     *keyevent;
+{
+
+  int i, status, N;
+  char dummy[3];
+  XComposeStatus compose_status;
+  KeySym keysym;
+
+  status = TRUE;
+  strcpy (textline[0].old_text, textline[0].text);
+  bzero (&textline[0].text[strlen(textline[0].text)], 
+	 1024 - strlen(textline[0].text));
+  i = textline[0].cursor;
+
+
+  N = XLookupString (keyevent, dummy, 1, &keysym, &compose_status);
+  switch (keysym) {
+  case XK_BackSpace:
+  case XK_Delete:
+    if (textline[0].cursor > 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i - 1], 
+	     strlen(&textline[0].text[i]) + 1);
+      RedrawString (graphic, textline);
+      textline[0].cursor --;
+      DrawCursor (graphic, textline);
+    }
+    break;
+  case XK_Left:
+    RedrawString (graphic, textline);
+    textline[0].cursor --;
+    if (textline[0].cursor < 0)
+      textline[0].cursor = 0;
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Right:
+    RedrawString (graphic, textline);
+    textline[0].cursor ++;
+    if (textline[0].cursor > strlen (textline[0].text))
+      textline[0].cursor = strlen (textline[0].text);
+    DrawCursor (graphic, textline);
+    break;
+  case XK_Return:
+    RedrawString (graphic, textline);
+    textline[0].cursor = -1;
+    status = FALSE;
+    break;
+  case XK_d:
+  case XK_D: 
+    if (dummy[0] == 4) { /* a control-d was typed! */
+      if (textline[0].cursor < strlen(textline[0].text)) {
+	bcopy (&textline[0].text[i + 1], &textline[0].text[i], 
+	       strlen(&textline[0].text[i]));
+	RedrawString (graphic, textline);
+	DrawCursor (graphic, textline);
+      }
+      break;  /* WARNING: this case MUST come before default.
+		 anything between this and default will be executed
+		 if no cntl-d is typed! */
+    }
+  default:
+    if (N != 0) {
+      bcopy (&textline[0].text[i], &textline[0].text[i + 1], 
+	     strlen(&textline[0].text[i]));
+      textline[0].text[i] = dummy[0];
+      RedrawString (graphic, textline);
+      textline[0].cursor ++;
+      DrawCursor (graphic, textline);
+    }
+  }
+  return (status);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom (Layout *layout, Graphic *graphic, double x, double y) {
+
+  switch (graphic[0].Nbits) {
+  case 8:
+    CreateZoom8 (layout, graphic, x, y);
+    break;
+
+  case 16:
+    CreateZoom16 (layout, graphic, x, y);
+    break;
+
+  case 24:
+    CreateZoom24 (layout, graphic, x, y);
+    break;
+
+  case 32:
+    CreateZoom32 (layout, graphic, x, y);
+    break;
+  }    
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom.new
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom.new	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom.new	(revision 16632)
@@ -0,0 +1,112 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+
+void
+CreateZoom (layout, graphic, x, y)
+Layout layout[];
+Graphic graphic[];
+double x, y;
+{
+
+  int i, j, ii, jj, X, Y;
+  int zvalue;
+  double value, expand, zero, range, zoomscale;
+  double X0, Y0, Rx, Ry, Rz1, Rz2;
+  int expand_int, dx, dy, DX, DY, Npixels, yfac;
+  Visual *visual = CopyFromParent;
+  unsigned long pixel;
+
+
+  /* create a test pattern image to put in layout[0].picture */
+  if (layout[0].matrix.size == 0) {
+    REALLOCATE (layout[0].zoom.data, char, layout[0].zoom.dx*layout[0].zoom.dy);
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+  }
+  else {
+    for (i = 0; i < 256; i++) 
+      pixel[i] = layout[0].cmap[i].pixel;
+    white = layout[0].white;
+    
+    zoomscale = MAX (5, layout[0].expand + 5);
+    expand = 1 / zoomscale;
+    expand_out = (int) zoomscale;
+    expand_in  = 1;
+    
+    dx = layout[0].zoom.dx;
+    dy = layout[0].zoom.dy;
+    DX = layout[0].matrix.Naxis[0];
+    DY = layout[0].matrix.Naxis[1];
+    Rx = DX/2 - dx*expand/2.0 - X0;
+    Ry = DY/2 - dy*expand/2.0 - Y0;  
+    
+    /* reassign as much for speed as clarity here */
+    X0 = 0.5*layout[0].matrix.Naxis[0] - x;
+    Y0 = 0.5*layout[0].matrix.Naxis[1] - y;
+    dx = layout[0].picture.dx;
+    dy = layout[0].picture.dy;
+    DX = matrix[0].Naxis[0];
+    DY = matrix[0].Naxis[1];
+    Rx = DX/2 - dx*expand/2.0 - X0;
+    Ry = DY/2 - dy*expand/2.0 - Y0;
+    
+    i_start = MAX (-Rx / expand, 0);
+    j_start = MAX (-Ry / expand, 0);
+    i_end   = MIN ((DX - Rx)/expand, dx - expand_out + 1);
+    j_end   = MIN ((DY - Ry)/expand, dy - expand_out + 1);
+    
+    in_pix = (short *) matrix[0].buffer;
+    out_pix = layout[0].zoom.data;
+    for (j = 0; j < j_start; j++) {
+      for (i = 0; i < dx; i++, out_pix++) {
+	*out_pix = white;
+      }
+    }
+    
+  for (j = j_start; j < j_end; j+= expand_out) {
+    Y = XPIX (j, Ry, expand);
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix = layout[0].zoom.data + (j+jj)*dx;  /* fencepost errors? */
+      for (i = 0; i < i_start; i++, out_pix++) {
+	*out_pix = white;
+      }
+    }
+    out_pix = layout[0].zoom.data + j*dx + i_start;  
+    X = XPIX (i_start, Rx, expand);
+    in_pix2 = in_pix + DX*Y + X;
+    for (i = i_start; i < i_end; i+= expand_out, in_pix2+= expand_in) { 
+      zvalue = 0x003f & *in_pix2;
+      for (ii = 0; ii < expand_out; ii++, out_pix++) {
+	for (jj = 0; jj < expand_out; jj++) {
+	  *(out_pix + jj*dx) = *(pixel + zvalue);
+	}
+      }
+    }
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix = layout[0].zoom.data + (j+jj)*dx + i_end;  /* fencepost errors? */
+      for (i = i_end; i < dx; i++, out_pix++) {
+	*out_pix = white;
+      }
+    }
+  }
+  for (j = j_end; j < dy; j++) {
+    out_pix = layout[0].picture.data + j*dx;
+    for (i = 0; i < dx; i++, out_pix++) {
+      *out_pix = white;
+    }
+  }
+}
+	
+  /*** here, if expand is < 1 (fractional expansion), we sparsely sample the 
+    original image, instead of box averaging - do we like this?  well, 
+    it speeds things up alot! ***/
+
+
+
+
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].zoom.data, 
+					layout[0].zoom.dx, layout[0].zoom.dy, 8, 0);
+  
+}
+
+ 
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom16.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom16.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom16.c	(revision 16632)
@@ -0,0 +1,134 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom16 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256];
+  unsigned char pixvalue1, pixvalue2;
+  unsigned long white;
+  unsigned char white1, white2;
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, 2*dy*dx);
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 16, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+  }
+  white = layout[0].white;
+  white1 = 0x0000ff & white;
+  white2 = 0x0000ff & (white >> 8);
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].zoom.data;
+  in_pix  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[2*j*dx];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+    out_pix += 2*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=2) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 2*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=2*(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=2) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	  }
+	}
+      }
+    }
+    out_pix -= 2*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + 2*jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2+=2) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+      }
+    }
+  } 
+  
+  out_pix = &data[2*j_end*dx];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=2) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+    }
+  }
+
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, 16, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom24.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom24.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom24.c	(revision 16632)
@@ -0,0 +1,167 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom24 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj, extra;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned char *out_pix, *out_pix2, *data;
+  unsigned char *in_pix,  *in_pix2;
+  unsigned char pixel1[256], pixel2[256], pixel3[256];
+  unsigned char pixvalue1, pixvalue2, pixvalue3;
+  unsigned long white;
+  unsigned char white1, white2, white3;
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  extra = 4 - (dx * 3) % 4;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, dy*(3*dx+extra));
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel1[i] = 0x0000ff & layout[0].cmap[i].pixel;
+    pixel2[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 8);
+    pixel3[i] = 0x0000ff & (layout[0].cmap[i].pixel >> 16);
+  }
+  white = layout[0].white;
+  white1 = 0x0000ff & white;
+  white2 = 0x0000ff & (white >> 8);
+  white3 = 0x0000ff & (white >> 16);
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  data = out_pix = (unsigned char *) layout[0].zoom.data;
+  in_pix  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < j_start; j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) {
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix += extra;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, in_pix += expand_in*DX) {
+    out_pix = &data[j*(3*dx+extra)];
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*(3*dx + extra);
+      for (i = 0; i < i_start; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+    out_pix += 3*i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix+=3) {
+	out_pix[0] = pixel1[*in_pix2];
+	out_pix[1] = pixel2[*in_pix2];
+	out_pix[2] = pixel3[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= 3*expand_out) { 
+	pixvalue1 = pixel1[*in_pix2];
+	pixvalue2 = pixel2[*in_pix2];
+	pixvalue3 = pixel3[*in_pix2];
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=3*(dx-expand_out)+extra) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2+=3) {
+	    out_pix2[0] = pixvalue1; 
+	    out_pix2[1] = pixvalue2; 
+	    out_pix2[2] = pixvalue3; 
+	  }
+	}
+      }
+    }
+    out_pix -= 3*dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*(3*dx+extra);
+      for (i = i_end; i < dx; i++, out_pix2+=3) {
+	out_pix2[0] = white1;
+	out_pix2[1] = white2;
+	out_pix2[2] = white3;
+      }
+    }
+  } 
+  
+  /*
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  */
+
+  out_pix = &data[j_end*(3*dx+extra)];
+  /**** fill in top area ****/
+  for (j = 0; j < (dy - j_end); j++) {
+    for (i = 0; i < dx; i++, out_pix+=3) { 
+      out_pix[0] = white1;
+      out_pix[1] = white2;
+      out_pix[2] = white3;
+    }
+    out_pix+=extra;
+  }
+
+  /*
+  out_pix = (unsigned char *) layout[0].zoom.data;
+  for (i = 0; i < dx*dy; i++) {
+    out_pix[3*i + 0] = white1;
+    out_pix[3*i + 1] = white2;
+    out_pix[3*i + 2] = white3;
+  }
+  for (j = 0; j < dy/2; j++) {
+    for (i = 0; i < dx; i++) {
+      out_pix[j*(extra + 3*dx) + 3*i + 0] = pixel1[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 1] = pixel2[10];
+      out_pix[j*(extra + 3*dx) + 3*i + 2] = pixel3[10];
+    }
+
+  }
+  */
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, 24, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom32.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom32.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom32.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom32 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  unsigned int *out_pix, *out_pix2, *data;
+  unsigned char  *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, 4*layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (unsigned int *) layout[0].zoom.data;
+  data = (unsigned int *) layout[0].zoom.data;
+  in_pix  = (unsigned char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) {
+    out_pix[0] = white;
+  }
+
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	out_pix[0] = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++) {
+	out_pix[0] = pixel[*in_pix2];
+      }
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = *(pixel + *in_pix2);
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    out_pix2[0] = pixvalue; 
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	out_pix2[0] = white;
+      }
+    }
+    out_pix += (dx - i_end);
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= (expand_out - (j_end - j_start) % expand_out);
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - (unsigned int *)layout[0].zoom.data < dx*dy); j++, out_pix++) { 
+    out_pix[0] = white;
+  }
+
+  out_pix = (unsigned int *)layout[0].zoom.data;
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 32, 0);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom8.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom8.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/CreateZoom8.c	(revision 16632)
@@ -0,0 +1,140 @@
+# include "Ximage.h"
+# define XPIX(x,Rx,S) (x*S + Rx)
+# define ZPIX(value,Rz1,Rz2) (value*Rz1 - Rz2)
+# define FRAC(a) ((a) - (int)(a))
+
+void CreateZoom8 (Layout *layout, Graphic *graphic, double x, double y) {
+
+  int i, j, ii, jj;
+  int i_start, i_end, j_start, j_end;
+  int dropback;  /* this is a bit of a kludge... */
+  int dx, dy, DX, DY;
+  double expand, zoomscale, Rx, Ry;
+  int expand_in, expand_out;
+  char  *out_pix, *out_pix2;
+  char  *in_pix,  *in_pix2;
+  unsigned long pixel[256], pixvalue;
+  unsigned long white;
+
+  if (layout[0].matrix.size == 0) {  /* create a test pattern */
+    REALLOCATE (layout[0].zoom.data, char, layout[0].zoom.dx*layout[0].zoom.dy);
+    bzero (layout[0].zoom.data, layout[0].zoom.dx*layout[0].zoom.dy);
+    layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+				       layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 8, 0);
+    return;
+  }
+
+  for (i = 0; i < 256; i++) { /* set up pixel array */
+    pixel[i] = layout[0].cmap[i].pixel;
+  }
+  white = layout[0].white;
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  expand = 1 / zoomscale;
+  expand_out = (int) zoomscale;
+  expand_in  = 1;
+
+  /*
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = 0.5*(DX - (dx - 1)*expand) - x;
+  Ry = 0.5*(DY - (dy - 1)*expand) - y;
+  data coords of 0,0 point in pic array 
+  X = 0.5*layout[0].matrix.Naxis[0] - expand*((int)(0.5*layout[0].zoom.dx + 0.5) - 0.0) - layout[0].X;
+  Y = 0.5*layout[0].matrix.Naxis[1] - expand*((int)(0.5*layout[0].zoom.dy + 0.5) - 0.0) - layout[0].Y;  
+  i_start = MIN (MAX (-Rx / expand, 0), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, 0), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = layout[0].zoom.data;
+  in_pix  = (char *) (layout[0].matrix.buffer) + DX*(int)MAX(Y,0) + (int)MAX(X,0);
+
+  */
+
+  dx = layout[0].zoom.dx;
+  dy = layout[0].zoom.dy;
+  DX = layout[0].matrix.Naxis[0];
+  DY = layout[0].matrix.Naxis[1];
+  Rx = x - expand*(int)(0.5*(dx + 1)) + 1;
+  Ry = y - expand*(int)(0.5*(dy + 1)) + 1;
+
+  i_start = MIN (MAX (-Rx / expand, (1 - FRAC(Rx)) / expand), dx - expand_out + 1);
+  j_start = MIN (MAX (-Ry / expand, (1 - FRAC(Ry)) / expand), dy - expand_out + 1);
+  i_end   = MAX (MIN ((DX-Rx) / expand, dx - expand_out + 1), 0);
+  j_end   = MAX (MIN ((DY-Ry) / expand, dy - expand_out + 1), 0);
+  dropback = expand_out - (i_end - i_start) % expand_out;
+  if ((i_end - i_start) % expand_out == 0) dropback = 0;
+
+  out_pix = (char *) layout[0].zoom.data;
+  in_pix  = (char *) (layout[0].matrix.buffer) + DX*(int)MAX(Ry,0) + (int)MAX(Rx,0);
+
+  /********** below we do the mapping from buffer pixels (in) to picture pixels (out) **********/
+
+  if ((i_end < i_start) || (j_end < j_start)) {
+    for (j = 0; j < dx*dy; j++, out_pix++) 
+      *out_pix = white;
+    return;
+  } 
+  
+  /**** fill in bottom area ****/
+  for (j = 0; j < dx*j_start; j++, out_pix++) 
+    *out_pix = white;
+  
+  for (j = j_start; j < j_end; j+= expand_out, out_pix+=(expand_out-1)*dx, in_pix += expand_in*DX) {
+
+    /**** fill in area to the left of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) { 
+      out_pix2 = out_pix + jj*dx;
+      for (i = 0; i < i_start; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += i_start;
+    
+    /*** fill in the picture region ***/
+    in_pix2 = in_pix;
+    if (expand_out == 1) {
+      for (i = i_start; i < i_end; i++, in_pix2+= expand_in, out_pix++)
+	*out_pix = *(pixel + *in_pix2); 
+    }
+    else {
+      for (i = i_start; i < i_end; i+= expand_out, in_pix2++, out_pix+= expand_out) { 
+	pixvalue = *(pixel + *in_pix2);
+	out_pix2 = out_pix;
+	for (jj = 0; jj < expand_out; jj++, out_pix2+=(dx-expand_out)) {
+	  for (ii = 0; ii < expand_out; ii++, out_pix2++) {
+	    *out_pix2 = pixvalue;
+	  }
+	}
+      }
+    }
+    out_pix -= dropback;
+    
+    /**** fill in area to the right of the picture ****/
+    for (jj = 0; jj < expand_out; jj++) {
+      out_pix2 = out_pix + jj*dx;
+      for (i = i_end; i < dx; i++, out_pix2++) {
+	*out_pix2 = white;
+      }
+    }
+    out_pix += (dx - i_end);
+    
+  } 
+  
+  if ((j_end - j_start) % expand_out > 0)
+    out_pix -= expand_out - (j_end - j_start) % expand_out;
+  
+  /**** fill in top area ****/
+  for (j = 0; (j < dx*(dy - j_end)) && (out_pix - layout[0].zoom.data < dx*dy); j++, out_pix++) { 
+    *out_pix = white;
+  }
+
+  layout[0].zoom.pix = XCreateImage (graphic[0].display, graphic[0].visual, graphic[0].depth, ZPixmap, 0, 
+					layout[0].zoom.data, layout[0].zoom.dx, layout[0].zoom.dy, 8, 0);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/CrossHairs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/CrossHairs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/CrossHairs.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "Ximage.h"
+
+void CrossHairs (Graphic *graphic, Layout *layout) {
+
+  int x0, x1, x5, x7;
+  int y0, y2, y4, y5;
+  double zoomscale;
+
+  zoomscale = MAX (5, layout[0].expand + 5);
+  x0 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 2.5) + layout[0].zoom.x;
+  x5 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale - 0.5) + layout[0].zoom.x;
+  x7 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 0.5) + layout[0].zoom.x;
+  x1 = (zoomscale) * (0.5 * (ZOOM_X + 1) / zoomscale + 2.5) + layout[0].zoom.x;
+						    	 
+  y4 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 2.5) + layout[0].zoom.y;
+  y2 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale - 0.5) + layout[0].zoom.y;
+  y0 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 0.5) + layout[0].zoom.y;
+  y5 = (zoomscale) * (0.5 * (ZOOM_Y + 1) / zoomscale + 2.5) + layout[0].zoom.y;
+
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0, x5, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y0, x5, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y5, x7, y0);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y0, x1, y0);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2, x5, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5, y2, x5, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y4, x7, y2);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7, y2, x1, y2);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y0+1, x5-1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y0+1, x5-1, y5);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y5, x7+1, y0+1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y0+1, x1, y0+1);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x0, y2-1, x5-1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x5-1, y2-1, x5-1, y4);
+
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y4, x7+1, y2-1);
+  XDrawLine (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	     x7+1, y2-1, x1, y2-1);
+
+  XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/UpdatePointer.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/UpdatePointer.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/UpdatePointer.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "Ximage.h"
+# define FRAC(a) ((a) - (int)(a))
+
+int UpdatePointer (Graphic *graphic, Layout *layout, XMotionEvent *event) {
+
+  int textpad;
+  double  x, y, z;
+  char line[100];
+
+  if (MOVE_POINTER && InPicture ((XButtonEvent *)event, &layout[0].picture)) {
+
+    Screen_to_Image (&x, &y, (double)event[0].x, (double)event[0].y, layout);
+
+    if ((x >= 0) && (x < layout[0].matrix.Naxis[0]) && (y >= 0) && (y < layout[0].matrix.Naxis[1])) {
+      /*
+      X = event[0].x - layout[0].picture.x;
+      Y = event[0].y - layout[0].picture.y;
+      pix = MIN (MAX (X + Y*layout[0].picture.dx, 0), layout[0].picture.dx*layout[0].picture.dy - 1);
+      z = layout[0].range * layout[0].picture.data[pix] / layout[0].Npixels + layout[0].zero;
+      */
+      z = -1;
+    }
+    else
+      z = -1;
+    layout[0].x = x;
+    layout[0].y = y;
+    layout[0].z = z;
+    
+    UpdateStatusBox (graphic, layout, x, y, z, 0);
+    XFlush (graphic[0].display);
+      
+    CreateZoom (layout, graphic, x, y);  
+    XPutImage (graphic[0].display, graphic[0].window, graphic[0].gc,
+	       layout[0].zoom.pix, 0, 0, 
+	       layout[0].zoom.x, layout[0].zoom.y, 
+	       layout[0].zoom.dx, layout[0].zoom.dy);
+    CrossHairs (graphic, layout);
+    XFlush (graphic[0].display);
+    
+  }
+  
+  if (InPicture ((XButtonEvent *)event, &layout[0].cmapbar)) {
+    z = layout[0].zero  + layout[0].range * (event[0].x - layout[0].cmapbar.x) / layout[0].cmapbar.dx;
+    textpad = graphic[0].font[0].ascent;
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+                  layout[0].text_x + 1, layout[0].text_y + 1, ZOOM_X - 2, textpad + PAD1 + 1);
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    bzero (line, 100);
+    sprintf (line, "%25.2f", z);
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+                 layout[0].text_x + PAD1, layout[0].text_y + textpad + PAD1, 
+		 line, strlen(line));
+    
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/kii/zoom/UpdateStatusBox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/kii/zoom/UpdateStatusBox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/kii/zoom/UpdateStatusBox.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "Ximage.h"
+
+void UpdateStatusBox (Graphic *graphic, Layout *layout, double x, double y, double z, int mode) {
+
+  int textpad;
+  double ra, dec; 
+  char line[100];
+
+  XY_to_RD (&ra, &dec, x, y, &layout[0].coords);
+
+  textpad = graphic[0].font[0].ascent;
+
+  if (mode) {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    layout[0].text_x, layout[0].text_y, ZOOM_X, 6*textpad+7*PAD1);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+    XDrawRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    layout[0].text_x, layout[0].text_y, ZOOM_X, 6*textpad+7*PAD1);
+  
+    bzero (line, 100);
+    sprintf (line, "(%d x %d) @ %d                                         ", 
+	     layout[0].picture.dx, layout[0].picture.dy, layout[0].expand); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 layout[0].text_x + PAD1, layout[0].text_y + 4*textpad + 4*PAD1, line, 25);
+    
+    bzero (line, 100);
+    sprintf (line, "%-25s", layout[0].file); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 layout[0].text_x + PAD1, layout[0].text_y + 5*textpad + 5*PAD1, line, strlen(line));
+    
+    bzero (line, 100);
+    sprintf (line, "(%s)                                          ", layout[0].buffer_name); 
+    XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+		 layout[0].text_x + PAD1, layout[0].text_y + 6*textpad + 6*PAD1, line, 25);
+    
+  } else {
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].white);
+    XFillRectangle (graphic[0].display, graphic[0].window, graphic[0].gc,
+		    layout[0].text_x + 1, layout[0].text_y + 1, ZOOM_X - 2, 3*textpad+3*PAD1 +1);  
+    XSetForeground (graphic[0].display, graphic[0].gc, graphic[0].black);
+  }
+  bzero (line, 100);
+  sprintf (line, "%25.3f", z);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       layout[0].text_x + PAD1, layout[0].text_y + textpad + PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  sprintf (line, "%12.1f %12.1f", x, y);
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       layout[0].text_x + PAD1, layout[0].text_y + 2*textpad + 2*PAD1, line, strlen(line));
+  
+  bzero (line, 100);
+  if (DECIMAL_DEG) {
+    sprintf (line, "%12.6f %12.6f", ra, dec); 
+  } else {
+    hh_hms (line, ra, dec, ':');
+  }
+  XDrawString (graphic[0].display, graphic[0].window, graphic[0].gc, 
+	       layout[0].text_x + PAD1, layout[0].text_y + 3*textpad + 3*PAD1, line, strlen(line));
+  
+ 
+}
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+include
+lib
+src
+tex
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/Makefile	(revision 16632)
@@ -0,0 +1,76 @@
+default: autocode
+help:
+	@echo "make options: install autocode latex objects"
+
+include ../../Makefile.System
+HOME	=	$(ROOT)/src/libautocode
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	= 	$(HOME)/doc
+DEF	=	$(HOME)/def
+TEX	=	$(HOME)/tex
+INC	=	$(HOME)/include
+ASRC    =       $(SRC)
+AINC    =       $(INC)
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+latex:    $(LIBTEX)
+objects:  $(AOBJS)
+install:  $(DESTINC)/autocode.h $(DESTLIB)/libautocode.a $(DESTLIB)/libautocode.$(DLLTYPE)
+autocode: $(INC)/autocode.h $(LIB)/libautocode.$(ARCH).a $(LIB)/libautocode.$(ARCH).$(DLLTYPE)
+
+# this library is not normally installed: the objects in the
+# file included below are rolled into libdvo 
+include Makefile.Targets
+
+LIBTEX = \
+$(TEX)/coords.tex \
+$(TEX)/average.tex \
+$(TEX)/secfilt.tex \
+$(TEX)/measure.tex \
+$(TEX)/missing.tex \
+$(TEX)/photcode.tex \
+$(TEX)/image.tex 
+
+$(LIB)/libautocode.$(ARCH).a: $(AOBJS)
+$(LIB)/libautocode.$(ARCH).$(DLLTYPE): $(AOBJS)
+
+$(DESTLIB)/libautocode.a:  $(LIB)/libautocode.$(ARCH).a
+$(DESTLIB)/libautocode.$(DLLTYPE): $(LIB)/libautocode.$(ARCH).$(DLLTYPE)
+$(DESTINC)/autocode.h : $(INC)/autocode.h
+
+$(AOBJS): $(DEF)/autocode.c $(DESTINC)/autocode.h
+
+$(INC)/autocode.h: $(AINCS) $(DEF)/autocode.h $(DEF)/common.h
+	cat $(DEF)/common.h >  $(INC)/autocode.h
+	cat $(AINCS)        >> $(INC)/autocode.h
+	@echo "# endif"     >> $(INC)/autocode.h
+	@echo done with autocode.h
+
+$(INC)/%.h: $(DEF)/%.d $(DEF)/autocode.h $(DEF)/common.h
+	@if [ ! -d $(INC) ]; then mkdir -p $(INC); fi
+	./generate $< $(DEF)/autocode.h $@
+
+$(SRC)/%.c: $(DEF)/%.d $(DEF)/autocode.c $(INC)/%.h
+	@if [ ! -d $(SRC) ]; then mkdir -p $(SRC); fi
+	./generate $< $(DEF)/autocode.c $@
+
+$(TEX)/%.tex: $(DEF)/%.d $(DEF)/autocode.tex
+	@if [ ! -d $(TEX) ]; then mkdir -p $(TEX); fi
+	./generate $< $(DEF)/autocode.tex $@
+
+clean:	cleandef
+cleandef:
+	rm -f `find src -name "*.c"`
+	rm -f `find include -name "*.h"`
+# 	this is an unusual target!  it deletes .c and .h files!
+
+.PRECIOUS: $(SRC)/%.c
+.PRECIOUS: $(LIB)/%.$(ARCH).a
+.PRECIOUS: $(LIB)/%.$(ARCH).$(DLLTYPE)
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/Makefile.Targets
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/Makefile.Targets	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/Makefile.Targets	(revision 16632)
@@ -0,0 +1,94 @@
+
+AOBJS = \
+$(ASRC)/coords.$(ARCH).o \
+$(ASRC)/average.$(ARCH).o \
+$(ASRC)/average-loneos.$(ARCH).o \
+$(ASRC)/average-elixir.$(ARCH).o \
+$(ASRC)/average-panstarrs-dev-0.$(ARCH).o \
+$(ASRC)/average-panstarrs-dev-1.$(ARCH).o \
+$(ASRC)/average-ps1-dev-1.$(ARCH).o \
+$(ASRC)/secfilt.$(ARCH).o \
+$(ASRC)/secfilt-loneos.$(ARCH).o \
+$(ASRC)/secfilt-elixir.$(ARCH).o \
+$(ASRC)/secfilt-panstarrs-dev-0.$(ARCH).o \
+$(ASRC)/secfilt-panstarrs-dev-1.$(ARCH).o \
+$(ASRC)/secfilt-ps1-dev-1.$(ARCH).o \
+$(ASRC)/measure.$(ARCH).o \
+$(ASRC)/measure-loneos.$(ARCH).o \
+$(ASRC)/measure-elixir.$(ARCH).o \
+$(ASRC)/measure-panstarrs-dev-0.$(ARCH).o \
+$(ASRC)/measure-panstarrs-dev-1.$(ARCH).o \
+$(ASRC)/measure-ps1-dev-1.$(ARCH).o \
+$(ASRC)/missing.$(ARCH).o \
+$(ASRC)/photcode.$(ARCH).o \
+$(ASRC)/photcode-elixir.$(ARCH).o \
+$(ASRC)/photcode-ps1-dev-1.$(ARCH).o \
+$(ASRC)/image.$(ARCH).o \
+$(ASRC)/image-loneos.$(ARCH).o \
+$(ASRC)/image-elixir.$(ARCH).o \
+$(ASRC)/image-panstarrs-dev-0.$(ARCH).o \
+$(ASRC)/image-panstarrs-dev-1.$(ARCH).o \
+$(ASRC)/image-ps1-dev-1.$(ARCH).o \
+$(ASRC)/regimage.$(ARCH).o \
+$(ASRC)/detreg.$(ARCH).o \
+$(ASRC)/photreg.$(ARCH).o \
+$(ASRC)/photreg-old.$(ARCH).o \
+$(ASRC)/ps1_dev_0.$(ARCH).o \
+$(ASRC)/ps1_dev_1.$(ARCH).o \
+$(ASRC)/smpdata.$(ARCH).o \
+$(ASRC)/getstar-ps1-dev-0.$(ARCH).o \
+$(ASRC)/getstar-ps1-dev-1.$(ARCH).o \
+$(ASRC)/getstar-ps1-dev-2.$(ARCH).o \
+$(ASRC)/spectrum.$(ARCH).o \
+$(ASRC)/spectrum-ascii.$(ARCH).o \
+$(ASRC)/Stars.$(ARCH).o \
+$(ASRC)/GSCRegion.$(ARCH).o \
+$(ASRC)/AddstarClientOptions.$(ARCH).o \
+$(ASRC)/SkyRegion.$(ARCH).o
+
+AINCS = \
+$(AINC)/coords.h \
+$(AINC)/average.h \
+$(AINC)/average-loneos.h \
+$(AINC)/average-elixir.h \
+$(AINC)/average-panstarrs-dev-0.h \
+$(AINC)/average-panstarrs-dev-1.h \
+$(AINC)/average-ps1-dev-1.h \
+$(AINC)/secfilt.h \
+$(AINC)/secfilt-loneos.h \
+$(AINC)/secfilt-elixir.h \
+$(AINC)/secfilt-panstarrs-dev-0.h \
+$(AINC)/secfilt-panstarrs-dev-1.h \
+$(AINC)/secfilt-ps1-dev-1.h \
+$(AINC)/measure.h \
+$(AINC)/measure-loneos.h \
+$(AINC)/measure-elixir.h \
+$(AINC)/measure-panstarrs-dev-0.h \
+$(AINC)/measure-panstarrs-dev-1.h \
+$(AINC)/measure-ps1-dev-1.h \
+$(AINC)/missing.h \
+$(AINC)/photcode.h \
+$(AINC)/photcode-elixir.h \
+$(AINC)/photcode-ps1-dev-1.h \
+$(AINC)/image.h \
+$(AINC)/image-loneos.h \
+$(AINC)/image-elixir.h \
+$(AINC)/image-panstarrs-dev-0.h \
+$(AINC)/image-panstarrs-dev-1.h \
+$(AINC)/image-ps1-dev-1.h \
+$(AINC)/regimage.h \
+$(AINC)/detreg.h \
+$(AINC)/photreg.h \
+$(AINC)/photreg-old.h \
+$(AINC)/ps1_dev_0.h \
+$(AINC)/ps1_dev_1.h \
+$(AINC)/getstar-ps1-dev-0.h \
+$(AINC)/getstar-ps1-dev-1.h \
+$(AINC)/getstar-ps1-dev-2.h \
+$(AINC)/smpdata.h \
+$(AINC)/spectrum.h \
+$(AINC)/spectrum-ascii.h \
+$(AINC)/Stars.h \
+$(AINC)/GSCRegion.h \
+$(AINC)/AddstarClientOptions.h \
+$(AINC)/SkyRegion.h
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/AddstarClientOptions.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/AddstarClientOptions.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/AddstarClientOptions.d	(revision 16632)
@@ -0,0 +1,22 @@
+STRUCT  AddstarClientOptions
+EXTNAME OPTIONS
+TYPE    BINTABLE
+SIZE    76
+
+FIELD     Nsigma,           NSIGMA,               double,         match radius in terms of astrometric error 
+FIELD     radius,           RADIUS,		  double,         match radius in arcsec (default)
+FIELD  	  mode,             MODE,                 int,            data source mode
+FIELD  	  existing_regions, EXISTING_REGIONS,     int,            use only existing regions
+FIELD  	  only_match,       ONLY_MATCH,           int,            only update matched stars
+FIELD  	  skip_missed,      SKIP_MISSED,          int,            .
+FIELD  	  replace,          REPLACE,              int,            .
+FIELD  	  closest,          CLOSEST,              int,            .
+FIELD  	  nosort,           NOSORT,               int,            .
+FIELD  	  update,           UPDATE,               int,            .
+FIELD  	  only_images,      ONLY_IMAGES,          int,            .
+FIELD  	  calibrate,        CALIBRATE,            int,            .
+FIELD  	  quality_airmass,  HQ_AIRMASS,           int,            use high-quality airmass?
+FIELD  	  mosaic,           MOSAIC,               int,            does this image require a mosaic coordinate system?
+FIELD  	  photcode,         PHOTCODE,             int,     	  photocode of input data
+FIELD  	  timeref,          TIMEREF,              e_time,  	  time/date of input data (REFLIST only?)
+FIELD  	  imageID,          IMAGE_ID,             unsigned int,   reference to image
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/GSCRegion.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/GSCRegion.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/GSCRegion.d	(revision 16632)
@@ -0,0 +1,8 @@
+STRUCT  GSCRegion
+EXTNAME OPTIONS
+TYPE    BINTABLE
+SIZE    288
+
+FIELD   filename,   FILENAME,   char[256],   catalog filename
+FIELD   DEC,        DEC,        double[2],   Dec boundaries
+FIELD   RA,         DEC,        double[2],   RA boundaries
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/SkyRegion.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/SkyRegion.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/SkyRegion.d	(revision 16632)
@@ -0,0 +1,17 @@
+STRUCT  SkyRegion
+EXTNAME SKY_REGION
+TYPE    BINTABLE
+SIZE    56
+
+FIELD   Rmin,	   R_MIN,	   float, 
+FIELD   Rmax,	   R_MAX,	   float, 
+FIELD   Dmin,	   D_MIN,	   float, 
+FIELD   Dmax,	   D_MAX,	   float, 
+FIELD   childS,	   CHILD_S,	   int,           sequence number in full table of first child
+FIELD   childE,	   CHILD_E,	   int,           sequence number in full table of last child + 1
+FIELD   parent,	   PARENT,	   int,           sequence number in full table of parent
+FIELD   index,     INDEX,          int,           sequence number in full table of this entry
+FIELD   depth,	   DEPTH,	   char,          depth of this entry
+FIELD   child,	   CHILD,	   char,          does this entry have children?
+FIELD   table,	   TABLE,	   char,          does this entry have a table?
+FIELD   name,      NAME,           char[21],      name / filename
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/Stars.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/Stars.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/Stars.d	(revision 16632)
@@ -0,0 +1,57 @@
+STRUCT  Stars
+EXTNAME STARS
+TYPE    BINTABLE
+SIZE    244
+
+FIELD     X,                X,          double,    x coordinate on image,	     pixels
+FIELD     Y,                Y,          double,    y coordinate on image,	     pixels
+FIELD     dX,               dX,         double,    x coordinate error,	             pixels
+FIELD     dY,               dY,         double,    y coordinate error,  	     pixels
+FIELD     R,                R,          double,    ra coordinate on sky,	     decimal degrees
+FIELD     D,                D,          double,    dec coordinate on sky,	     decimal degrees
+FIELD     dR,               dR,         double,    ra error,			     arcsec
+FIELD     dD,               dD,         double,    dec error,			     arcsec
+FIELD     uR,               U_RA,       double,    proper motion in RA,		     milliarcsec/year
+FIELD     uD,               U_DEC,      double,    proper motion in DEC,	     milliarcsec/year
+FIELD     duR,              U_RA_ERR,   double,    p-m error in RA,		     milliarcsec/year
+FIELD     duD,              U_DEC_ERR,  double,    p-m error in DEC,		     milliarcsec/year
+FIELD     P,                PAR,        double,    parallax,			     milliarcsec
+FIELD     dP,               PAR_ERR,    double,    parallax error,		     milliarcsec
+FIELD     M,                M,          double,    instrumental mag
+FIELD     dM,               DM,         double,    error on mag
+FIELD     sky,              SKY,        double,    local sky counts
+FIELD     dsky,             dSKY,       double,    local sky error counts
+FIELD     fx,               FX,         double,    object FWHM x-dir,		     pixels?
+FIELD     fy,               FY,         double,    object FWHM y-dir,		     pixels?
+FIELD     df,               DF,         double,    object position angle,	     degrees
+FIELD     Mgal,             MGAL,       double,    alternative (galaxy) magnitude
+FIELD     Map,              MAP,        double,    alternative (aperture) magnitude
+FIELD     Mpeak,            MPEAK,      double,    alternative (peak) magnitude
+FIELD     detID,            ID,         int,       detection identifier
+FIELD     found,            FOUND,      int,       found in database catalog?
+FIELD     t,                T,          e_time,    date/time of exposure (UNIX)
+FIELD     dt,               EXPTIME,    float,     exposure time,                    2.5*log(exptime)
+FIELD     psfProb,          PSF_PROB,   float
+FIELD     crNsigma,         CR_NSIGMA,  float
+FIELD     extNsigma,        EXT_NSIGMA, float
+FIELD     psfQual,          PSF_QUAL,   float
+FIELD     Mcal,             MCAL,       float,     image cal mag,	             mag
+FIELD     airmass,          AIRMASS,    float,     (airmass - 1),		     airmass
+FIELD     az,     	    AZ,         float,     azimuth
+FIELD     code,             CODE,       short
+FIELD     nFrames,          N_FRAMES,   short
+FIELD     flags,            FLAGS,      short
+FIELD     dophot,           DOPHOT,     char,      dophot type code
+FIELD     dummy,            DUMMY,      char
+
+# XXX I'm going to need azimuth (or load from image header?)
+
+# double:   24 * 8 : 192
+# int/float:10 * 4 :  40
+# short:     2 * 2 :   4
+# char:      4 * 1 :   4
+
+# this structure is only used internally and for interprocess communication (addstar)
+# dR, uR, etc should be better defined at the pole...
+# define down the types to floats where reasonable (all but R,D)?
+# R,D should be in ICRS, J2000, epoch 2000 : precess as needed, apply p-m as needed
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.c	(revision 16632)
@@ -0,0 +1,126 @@
+# include "autocode.h"
+
+int gfits_convert_$STRUCT ($STRUCT *data, int size, int nitems) {
+
+  int i;
+  unsigned char *byte, tmp;
+
+  if (size != $SIZE) { 
+    fprintf (stderr, "ERROR: mismatch in data types $STRUCT: %d vs %d\n",
+	     size, $SIZE);
+    exit (1);
+  }
+
+  /* provide initial values to avoid compiler warnings for non-BYTE_SWAP arch */
+  i = tmp = 0;
+  byte = NULL;
+
+# ifdef BYTE_SWAP
+  byte = (unsigned char *) data;
+  for (i = 0; i < nitems; i++, byte += $SIZE) {
+    /** BYTE SWAP **/
+  }
+# endif  
+
+  return (TRUE);
+} 
+
+/*** add test of EXTNAME and header-defined columns? ***/
+/* return internal structure representation */
+$STRUCT *gfits_table_get_$STRUCT (FTable *ftable, int *Ndata, int *swapped) {
+
+  $STRUCT *data;
+
+  *Ndata = ftable[0].header[0].Naxis[1];
+  data = ($STRUCT *) ftable[0].buffer;
+  if ((swapped == NULL) || (*swapped == FALSE)) {
+    gfits_convert_$STRUCT (data, sizeof ($STRUCT), *Ndata);
+    gfits_table_scale_data (ftable);
+    if (swapped != NULL) *swapped = TRUE;
+  }
+  return (data);
+}
+
+int gfits_table_set_$STRUCT (FTable *ftable, $STRUCT *data, int Ndata) {
+
+  Header *header;
+
+  header = ftable[0].header;
+
+  /* create table header */
+  gfits_create_table_header (header, "$TYPE", "$EXTNAME");
+
+  /* define table layout */
+  /** TABLE DEFINITION **/
+
+  /* create table */
+  gfits_create_table (header, ftable);
+
+  /* add data values */
+  gfits_table_scale_data (ftable);
+  gfits_convert_$STRUCT (data, sizeof ($STRUCT), Ndata);
+  gfits_add_rows (ftable, (char *) data, Ndata, sizeof ($STRUCT));
+
+  return (TRUE);
+}
+
+int gfits_table_mkheader_$STRUCT (Header *header) {
+
+  /* create table header */
+  gfits_create_table_header (header, "$TYPE", "$EXTNAME");
+
+  /* define table layout */
+  /** TABLE DEFINITION **/
+
+  return (TRUE);
+}
+
+int Send_$STRUCT (int device, $STRUCT *data, int Ndata, int copy) {
+
+  int Nbytes;
+  $STRUCT *tmpdata;
+
+  Nbytes = Ndata * sizeof ($STRUCT);
+
+  if (copy) {
+    ALLOCATE (tmpdata, $STRUCT, Ndata);
+    memcpy (tmpdata, data, Nbytes);
+  } else {
+    tmpdata = data;
+  }
+
+  gfits_convert_$STRUCT (tmpdata, sizeof ($STRUCT), Ndata);
+
+  SendCommand (device, 16, "NVALUE: %6d", Ndata);
+  SendCommand (device, 16, "NBYTES: %6d", Nbytes);
+  write (device, tmpdata, Nbytes);
+  
+  /* perform handshaking? */
+
+  return (TRUE);
+}
+
+int Recv_$STRUCT (int device, $STRUCT **data, int *Ndata) {
+
+  int ndata;
+  IOBuffer message;
+  $STRUCT *tmpdata;
+
+  ExpectCommand (device, 16, 1.0, &message);
+  sscanf (message.buffer, "%*s %d", &ndata);
+  FreeIOBuffer (&message);
+  
+  /* what is reasonable for timeout? */
+  ExpectMessage (device, 1.0, &message);
+  
+  tmpdata = ($STRUCT *) message.buffer;
+  gfits_convert_$STRUCT (tmpdata, sizeof ($STRUCT), ndata);
+
+  /* double-check data length? */
+  /* perform handshaking? */
+
+  *Ndata = ndata;
+  *data = tmpdata;
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.h	(revision 16632)
@@ -0,0 +1,9 @@
+
+/** STRUCT DEFINITION **/
+
+$STRUCT *gfits_table_get_$STRUCT (FTable *table, int *Ndata, int *swapped);
+int      gfits_table_set_$STRUCT (FTable *ftable, $STRUCT *data, int Ndata);
+int      gfits_table_mkheader_$STRUCT (Header *header);
+int      gfits_convert_$STRUCT ($STRUCT *data, int size, int nitems);
+int Send_$STRUCT (int device, $STRUCT *data, int Ndata, int copy);
+int Recv_$STRUCT (int device, $STRUCT **data, int *Ndata);
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/autocode.tex	(revision 16632)
@@ -0,0 +1,13 @@
+
+\begin{table}[h]
+\begin{center}
+\caption{\label{$STRUCT} $DESCRIPTION (EXTNAME: {\tt $STRUCT})}
+\begin{tabular}{|l|l|l|l|}
+\hline
+name        & type           & description                 & units \\
+\hline
+%%% LATEX TABLE DEFINITION 
+\hline
+\end{tabular}
+\end{center}
+\end{table}
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-elixir.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-elixir.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-elixir.d	(revision 16632)
@@ -0,0 +1,19 @@
+STRUCT  Average_Elixir
+EXTNAME DVO_AVERAGE_ELIXIR
+TYPE    BINTABLE
+SIZE    32
+
+# elements of data structure / FITS table
+
+FIELD R,              RA,         float,            RA,                	       	  decimal degrees 
+FIELD D,              DEC,        float,            DEC,               	       	  decimal degrees 
+FIELD M,              MAG,        short,            primary mag,       	       	  millimag
+FIELD Nm,             NMEAS,      unsigned short,   number of measures
+FIELD Nn,             NMISS,      unsigned short,   number of missings
+FIELD Xp,             SIGMA_POS,  short, 	    position scatter,   	  1/100 arcsec
+FIELD Xm,             CHISQ_MAG,  short, 	    chisq for primary mag,        [100*log(value)]  ?
+FIELD code,           code,       unsigned short,   ID code (star; ghost; etc)
+FIELD offset,         offset,     int,     	    offset to first measurement
+FIELD missing,        missing,    int,     	    offset to first missing obs
+FIELD dM,             MAG_ERR,    short,            error on primary mag,         millimag
+FIELD Xg,             Xg,         short,            best chisq value
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-loneos.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-loneos.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-loneos.d	(revision 16632)
@@ -0,0 +1,17 @@
+STRUCT  Average_Loneos
+EXTNAME DVO_AVERAGE_LONEOS
+TYPE    BINTABLE
+SIZE    28
+
+# elements of data structure / FITS table
+
+FIELD R,              RA,         float,            RA,                	       	  decimal degrees 
+FIELD D,              DEC,        float,            DEC,               	       	  decimal degrees 
+FIELD M,              MAG,        short,            primary mag,       	       	  millimag
+FIELD Nm,             NMEAS,      unsigned short,   number of measures
+FIELD Nn,             NMISS,      unsigned short,   number of missings
+FIELD Xp,             SIGMA_POS,  short, 	    position scatter,   	  1/100 arcsec
+FIELD Xm,             CHISQ_MAG,  short, 	    chisq for primary mag,        [1000*value]  ?
+FIELD code,           code,       unsigned short,   ID code (star; ghost; etc)
+FIELD offset,         offset,     int,     	    offset to first measurement
+FIELD missing,        missing,    int,     	    offset to first missing obs
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-panstarrs-dev-0.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-panstarrs-dev-0.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-panstarrs-dev-0.d	(revision 16632)
@@ -0,0 +1,40 @@
+STRUCT       Average_Panstarrs_DEV_0
+EXTNAME      DVO_AVERAGE_PANSTARRS_DEV_0
+TYPE         BINTABLE
+SIZE         72
+DESCRIPTION  DVO Average Object Table
+
+# elements of data structure / FITS table
+
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD dR,             RA_ERR,     float,            RA error                      arcsec
+FIELD dD,             DEC_ERR,    float,            DEC error                     arcsec
+
+FIELD uR,             U_RA,       float,            RA*cos(D) proper-motion,      arcsec/year
+FIELD uD,             U_DEC,      float,            DEC proper-motion,            arcsec/year
+FIELD duR,            V_RA_ERR,   float,            RA*cos(D) p-m error,          arcsec/year
+FIELD duD,            V_DEC_ERR,  float,            DEC p-m error,                arcsec/year
+FIELD P,              PAR,        float,            parallax,			  arcsec
+FIELD dP,             PAR_ERR,    float,            parallax error,               arcsec
+
+FIELD Xp,             SIGMA_POS,  short, 	    position scatter,   	  1/100 arcsec
+FIELD Nm,             NMEAS,      unsigned short,   number of measures
+FIELD Nn,             NMISS,      unsigned short,   number of missings
+FIELD code,           code,       unsigned short,   ID code (star; ghost; etc)
+FIELD offset,         offset,     int,     	    offset to first measurement
+FIELD missing,        missing,    int,     	    offset to first missing obs
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD objID_hi,       OBJ_ID_HI,    unsigned int,   ID upper bytes
+FIELD objID_lo,       OBJ_ID_LO,    unsigned int,   ID lower bytes
+
+# this structure should only be used for internal representations
+# the average-FORMAT structures should be used for external representations
+# note that the average magnitudes are stored in the 'secfilt' table (change this name??)
+# the index for the secfilt table is just Nsecfilt times the index for the average table.
+
+# the DVO object IDs are generated internally and are not equivalent to the PSPS object IDs
+# probably need to add position chisq
+
+# XXX include the number of measurements used to determine the positional information?
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-panstarrs-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-panstarrs-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-panstarrs-dev-1.d	(revision 16632)
@@ -0,0 +1,40 @@
+STRUCT       Average_Panstarrs_DEV_1
+EXTNAME      DVO_AVERAGE_PANSTARRS_DEV_1
+TYPE         BINTABLE
+SIZE         72
+DESCRIPTION  DVO Average Object Table
+
+# elements of data structure / FITS table
+
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD dR,             RA_ERR,     float,            RA error                      arcsec
+FIELD dD,             DEC_ERR,    float,            DEC error                     arcsec
+
+FIELD uR,             U_RA,       float,            RA*cos(D) proper-motion,      arcsec/year
+FIELD uD,             U_DEC,      float,            DEC proper-motion,            arcsec/year
+FIELD duR,            V_RA_ERR,   float,            RA*cos(D) p-m error,          arcsec/year
+FIELD duD,            V_DEC_ERR,  float,            DEC p-m error,                arcsec/year
+FIELD P,              PAR,        float,            parallax,			  arcsec
+FIELD dP,             PAR_ERR,    float,            parallax error,               arcsec
+
+FIELD Xp,             SIGMA_POS,  short, 	    position scatter,   	  1/100 arcsec
+FIELD Nm,             NMEAS,      unsigned short,   number of measures
+FIELD Nn,             NMISS,      unsigned short,   number of missings
+FIELD code,           code,       unsigned short,   ID code (star; ghost; etc)
+FIELD offset,         offset,     int,     	    offset to first measurement
+FIELD missing,        missing,    int,     	    offset to first missing obs
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD objID_hi,       OBJ_ID_HI,    unsigned int,   ID upper bytes
+FIELD objID_lo,       OBJ_ID_LO,    unsigned int,   ID lower bytes
+
+# this structure should only be used for internal representations
+# the average-FORMAT structures should be used for external representations
+# note that the average magnitudes are stored in the 'secfilt' table (change this name??)
+# the index for the secfilt table is just Nsecfilt times the index for the average table.
+
+# the DVO object IDs are generated internally and are not equivalent to the PSPS object IDs
+# probably need to add position chisq
+
+# XXX include the number of measurements used to determine the positional information?
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-ps1-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-ps1-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-ps1-dev-1.d	(revision 16632)
@@ -0,0 +1,40 @@
+STRUCT       Average_PS1_DEV_1
+EXTNAME      DVO_AVERAGE_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         72
+DESCRIPTION  DVO Average Object Table
+
+# elements of data structure / FITS table
+
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD dR,             RA_ERR,     float,            RA error                      arcsec
+FIELD dD,             DEC_ERR,    float,            DEC error                     arcsec
+
+FIELD uR,             U_RA,       float,            RA*cos(D) proper-motion,      arcsec/year
+FIELD uD,             U_DEC,      float,            DEC proper-motion,            arcsec/year
+FIELD duR,            V_RA_ERR,   float,            RA*cos(D) p-m error,          arcsec/year
+FIELD duD,            V_DEC_ERR,  float,            DEC p-m error,                arcsec/year
+FIELD P,              PAR,        float,            parallax,			  arcsec
+FIELD dP,             PAR_ERR,    float,            parallax error,               arcsec
+
+FIELD Xp,             SIGMA_POS,  short, 	    position scatter,   	  1/100 arcsec
+FIELD Nm,             NMEAS,      unsigned short,   number of measures
+FIELD Nn,             NMISS,      unsigned short,   number of missings
+FIELD code,           code,       unsigned short,   ID code (star; ghost; etc)
+FIELD offset,         offset,     int,     	    offset to first measurement
+FIELD missing,        missing,    int,     	    offset to first missing obs
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD objID_hi,       OBJ_ID_HI,    unsigned int,   ID upper bytes
+FIELD objID_lo,       OBJ_ID_LO,    unsigned int,   ID lower bytes
+
+# this structure should only be used for internal representations
+# the average-FORMAT structures should be used for external representations
+# note that the average magnitudes are stored in the 'secfilt' table (change this name??)
+# the index for the secfilt table is just Nsecfilt times the index for the average table.
+
+# the DVO object IDs are generated internally and are not equivalent to the PSPS object IDs
+# probably need to add position chisq
+
+# XXX include the number of measurements used to determine the positional information?
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-ps1-dev-2.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-ps1-dev-2.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/average-ps1-dev-2.d	(revision 16632)
@@ -0,0 +1,43 @@
+STRUCT       Average_PS1_DEV_2
+EXTNAME      DVO_AVERAGE_PS1_DEV_2
+TYPE         BINTABLE
+SIZE         72
+DESCRIPTION  DVO Average Object Table
+
+# elements of data structure / FITS table
+
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD dR,             RA_ERR,     float,            RA error                      arcsec
+FIELD dD,             DEC_ERR,    float,            DEC error                     arcsec
+
+FIELD uR,             U_RA,       float,            RA*cos(D) proper-motion,      arcsec/year
+FIELD uD,             U_DEC,      float,            DEC proper-motion,            arcsec/year
+FIELD duR,            V_RA_ERR,   float,            RA*cos(D) p-m error,          arcsec/year
+FIELD duD,            V_DEC_ERR,  float,            DEC p-m error,                arcsec/year
+FIELD P,              PAR,        float,            parallax,			  arcsec
+FIELD dP,             PAR_ERR,    float,            parallax error,               arcsec
+
+FIELD Xp,             SIGMA_POS,  short, 	    position scatter,   	  1/100 arcsec
+FIELD Npsf,           NPSF,       unsigned short,   number of psf measurements
+FIELD Next,           NEXT,       unsigned short,   number of extended measurements
+FIELD Nmiss,          NMISS,      unsigned short,   number of missings
+FIELD psfOffset,      OFF_PSF,    int,     	    offset to first measurement
+FIELD extOffset,      OFF_EXT,    int,     	    offset to first measurement
+FIELD missOffset,     OFF_MISS,   int,     	    offset to first missing obs
+
+FIELD code,           code,       unsigned short,   ID code (star; ghost; etc)
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD objID_hi,       OBJ_ID_HI,  unsigned int,     ID upper bytes
+FIELD objID_lo,       OBJ_ID_LO,  unsigned int,     ID lower bytes
+
+# this structure should only be used for internal representations
+# the average-FORMAT structures should be used for external representations
+# note that the average magnitudes are stored in the 'secfilt' table (change this name??)
+# the index for the secfilt table is just Nsecfilt times the index for the average table.
+
+# the DVO object IDs are generated internally and are not equivalent to the PSPS object IDs
+# probably need to add position chisq
+
+# XXX include the number of measurements used to determine the positional information?
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/average.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/average.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/average.d	(revision 16632)
@@ -0,0 +1,40 @@
+STRUCT       Average
+EXTNAME      DVO_AVERAGE
+TYPE         BINTABLE
+SIZE         72
+DESCRIPTION  DVO Average Object Table
+
+# elements of data structure / FITS table
+
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD dR,             RA_ERR,     float,            RA error                      arcsec
+FIELD dD,             DEC_ERR,    float,            DEC error                     arcsec
+
+FIELD uR,             U_RA,       float,            RA*cos(D) proper-motion,      arcsec/year
+FIELD uD,             U_DEC,      float,            DEC proper-motion,            arcsec/year
+FIELD duR,            V_RA_ERR,   float,            RA*cos(D) p-m error,          arcsec/year
+FIELD duD,            V_DEC_ERR,  float,            DEC p-m error,                arcsec/year
+FIELD P,              PAR,        float,            parallax,			  arcsec
+FIELD dP,             PAR_ERR,    float,            parallax error,               arcsec
+
+FIELD Xp,             SIGMA_POS,  short, 	    position scatter,   	  1/100 arcsec
+FIELD Nm,             NMEAS,      unsigned short,   number of measures
+FIELD Nn,             NMISS,      unsigned short,   number of missings
+FIELD code,           code,       unsigned short,   ID code (star; ghost; etc)
+FIELD offset,         offset,     int,     	    offset to first measurement
+FIELD missing,        missing,    int,     	    offset to first missing obs
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD objID_hi,       OBJ_ID_HI,    unsigned int,   ID upper bytes
+FIELD objID_lo,       OBJ_ID_LO,    unsigned int,   ID lower bytes
+
+# this structure should only be used for internal representations
+# the average-FORMAT structures should be used for external representations
+# note that the average magnitudes are stored in the 'secfilt' table (change this name??)
+# the index for the secfilt table is just Nsecfilt times the index for the average table.
+
+# the DVO object IDs are generated internally and are not equivalent to the PSPS object IDs
+# probably need to add position chisq
+
+# XXX include the number of measurements used to determine the positional information?
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/common.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/common.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/common.h	(revision 16632)
@@ -0,0 +1,56 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+# ifndef AUTOCODE_H
+# define AUTOCODE_H
+/* matched endif is added by Makefile */
+
+# ifndef TRUE
+# define TRUE (1)
+# define FALSE (0)
+# endif
+
+# define SWAP_BYTE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+1]; byte[X+1] = tmp;
+# define SWAP_WORD(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+3]; byte[X+3] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+2]; byte[X+2] = tmp;
+# define SWAP_DBLE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+7]; byte[X+7] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+6]; byte[X+6] = tmp; \
+  tmp = byte[X+2]; byte[X+2] = byte[X+5]; byte[X+5] = tmp; \
+  tmp = byte[X+3]; byte[X+3] = byte[X+4]; byte[X+4] = tmp;
+
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef darwin_x86
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+# ifdef dec
+# define BYTE_SWAP
+# endif
+
+# define e_time unsigned int
+# define e_void long long
+# define rawshort short
+
+/*** rawshort is used to handle the broken pre-autocode photreg tables
+     fix the tables and remove this
+***/
+
+/*** this file uses data types which must have fixed sizes regardless 
+     of the platform.  It originally used the basic C primitives: 
+       float, double, int, short int, unsigned long int, etc.
+     this breaks under 64 bit (and probably on other systems).
+     I should define internal data types which should be set by the 
+     use of # define statements if needed.  I will cheat for now and use
+     the time_t to replace unsigned long int in this file 
+***/
+
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/coords.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/coords.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/coords.d	(revision 16632)
@@ -0,0 +1,20 @@
+STRUCT       Coords
+EXTNAME      COORDS
+TYPE         BINTABLE
+SIZE         120
+DESCRIPTION  DVO Coordinate Transformation Table
+
+# elements of the Coords structure
+FIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+FIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+FIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+FIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+FIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+FIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+FIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+FIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+FIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+FIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+FIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+FIELD  ctype,            CTYPE,                char[15],      coordinate type
+FIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/detreg.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/detreg.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/detreg.d	(revision 16632)
@@ -0,0 +1,21 @@
+STRUCT  DetReg
+EXTNAME DETREND_DATABASE
+TYPE    BINTABLE
+SIZE    416
+
+# elements of data structure / FITS table
+
+FIELD tstart,         START_TIME, e_time,    start time of measurement, seconds since 1970 Jan 01 UT
+FIELD tstop,          STOP_TIME,  e_time,    stop time of measurement,  seconds since Jan 1, 1970 UT
+FIELD treg,           REG_TIME,   e_time,    time of registration,      seconds since Jan 1, 1970 UT
+FIELD exptime,        EXPTIME,    float,     exposure time,             seconds
+FIELD type,           IMAGETYP,   int,       detrend type number
+FIELD filter,         FILTER,     int,       filter number
+FIELD ccd,            CCDNUM,     int,       ccd number
+FIELD Nentry,         VERSION,    int,       image version number
+FIELD Norder,         ORDER,      int,       selection order
+FIELD mode,           MODE,       char,      image mode
+FIELD altpath,        ALTPATH,    char,      available on alt db paths, true for data on alt db paths
+FIELD dummy,          RESERVED,   char[58],  space for additions,       for future expansion
+FIELD label,          LABEL,      char[64],  data label
+FIELD filename,       PATH,       char[256], filename in db
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/extend-ps1-dev-2.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/extend-ps1-dev-2.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/extend-ps1-dev-2.d	(revision 16632)
@@ -0,0 +1,57 @@
+STRUCT       Extend_PS1_DEV_1
+EXTNAME      DVO_EXTEND_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         104
+DESCRIPTION  DVO Detection Extended Source Parameters Table 
+
+FIELD dR,             D_RA,         	  float,          RA offset,                	  arcsec
+FIELD dD,             D_DEC,        	  float,          DEC offset,               	  arcsec
+FIELD M,              MAG,          	  float,          catalog mag,       	       	  mag
+FIELD dM,             MAG_ERR,      	  float,          mag error,                    mag
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+# I don't actually have these indexed, but this lets us match back to the measurement
+FIELD detID,          DET_ID,       	  unsigned int,   detection ID
+FIELD imageID,        IMAGE_ID,     	  unsigned int,   reference to image
+FIELD photcode,       PHOTCODE,     	  unsigned short, photcode
+
+FIELD FWx,            EXT_MAJOR,    	  float,          object fwhm major axis
+FIELD FWy,            EXT_MINOR,    	  float,          object fwhm minor axis
+FIELD theta,          EXT_THETA,    	  float,          angle wrt ccd X dir
+
+FIELD petroMag,       PETRO_MAG,    	  float,          petrosian mag
+FIELD petroMagErr,    PETRO_MAG_ERR,	  float,          petrosian mag
+FIELD petroRad,       PETRO_RADIUS,       float,          petrosian mag
+FIELD petroRadErr,    PETRO_RADIUS_ERR,   float,          petrosian mag
+
+FIELD kronMag,        KRON_MAG,    	  float,          kron mag
+FIELD kronMagErr,     KRON_MAG_ERR,	  float,          kron mag
+FIELD kronRad,        KRON_RADIUS,     	  float,          kron mag
+FIELD kronRadErr,     KRON_RADIUS_ERR, 	  float,          kron mag
+
+FIELD isophotMag,     ISOPHOT_MAG,    	  float,          isophot mag
+FIELD isophotMagErr,  ISOPHOT_MAG_ERR,	  float,          isophot mag
+FIELD isophotRad,     ISOPHOT_RADIUS,     float,          isophot mag
+FIELD isophotRadErr,  ISOPHOT_RADIUS_ERR, float,          isophot mag
+
+FIELD fluxR0,         FLUX_VAL_R_00,      float,          flux in annulus 0
+FIELD fluxR1,         FLUX_VAL_R_01,      float,          flux in annulus 1
+FIELD fluxR2,         FLUX_VAL_R_02,      float,          flux in annulus 2
+FIELD fluxR3,         FLUX_VAL_R_03,      float,          flux in annulus 3
+FIELD fluxR4,         FLUX_VAL_R_04,      float,          flux in annulus 4
+FIELD fluxR5,         FLUX_VAL_R_05,      float,          flux in annulus 5
+
+FIELD fluxR0err,      FLUX_ERR_R_00,      float,          flux error in annulus 0
+FIELD fluxR1err,      FLUX_ERR_R_01,      float,          flux error in annulus 1
+FIELD fluxR2err,      FLUX_ERR_R_02,      float,          flux error in annulus 2
+FIELD fluxR3err,      FLUX_ERR_R_03,      float,          flux error in annulus 3
+FIELD fluxR4err,      FLUX_ERR_R_04,      float,          flux error in annulus 4
+FIELD fluxR5err,      FLUX_ERR_R_05,      float,          flux error in annulus 5
+
+FIELD fluxR0var,      FLUX_VAR_R_00,      float,          flux var in annulus 0
+FIELD fluxR1var,      FLUX_VAR_R_01,      float,          flux var in annulus 1
+FIELD fluxR2var,      FLUX_VAR_R_02,      float,          flux var in annulus 2
+FIELD fluxR3var,      FLUX_VAR_R_03,      float,          flux var in annulus 3
+FIELD fluxR4var,      FLUX_VAR_R_04,      float,          flux var in annulus 4
+FIELD fluxR5var,      FLUX_VAR_R_05,      float,          flux var in annulus 5
+
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-0.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-0.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-0.d	(revision 16632)
@@ -0,0 +1,17 @@
+STRUCT       Getstar_PS1_DEV_0
+EXTNAME      GETSTAR_PS1_DEV_0
+TYPE         BINTABLE
+SIZE         32
+DESCRIPTION  Getstar output file
+
+# elements of data structure / FITS table
+
+# average R,D are epoch & equinox J2000.0
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD mag,            MAG,        float,            average magnitude in requested photcode
+FIELD c1,             MAG_C1,     float,            average magnitude in color term 1
+FIELD c2,             MAG_C2,     float,            average magnitude in color term 2
+
+FIELD photcode,       PHOTCODE,   unsigned short,   photcode for this mag
+FIELD code,           CODE,       unsigned short,   ID code (star; ghost; etc)
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-1.d	(revision 16632)
@@ -0,0 +1,22 @@
+STRUCT       Getstar_PS1_DEV_1
+EXTNAME      GETSTAR_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         48
+DESCRIPTION  Getstar output file
+
+# elements of data structure / FITS table
+
+# average R,D are epoch & equinox J2000.0
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD uR,             U_RA,       float,            RA*cos(D) proper-motion,      arcsec/year
+FIELD uD,             U_DEC,      float,            DEC proper-motion,            arcsec/year
+FIELD P,              PAR,        float,            parallax,			  arcsec
+
+FIELD mag,            MAG,        float,            average magnitude in requested photcode
+FIELD c1,             MAG_C1,     float,            average magnitude in color term 1
+FIELD c2,             MAG_C2,     float,            average magnitude in color term 2
+
+FIELD photcode,       PHOTCODE,   unsigned short,   photcode for this mag
+FIELD code,           CODE,       unsigned short,   ID code (star; ghost; etc)
+FIELD dummy,          DUMMY,      char[4],          padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-2.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-2.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/getstar-ps1-dev-2.d	(revision 16632)
@@ -0,0 +1,28 @@
+STRUCT       Getstar_PS1_DEV_2
+EXTNAME      GETSTAR_PS1_DEV_2
+TYPE         BINTABLE
+SIZE         64
+DESCRIPTION  Getstar output file
+
+# elements of data structure / FITS table
+
+# average R,D are epoch & equinox J2000.0
+FIELD R,              RA,         double,           RA,                	       	  decimal degrees 
+FIELD D,              DEC,        double,           DEC,               	       	  decimal degrees 
+FIELD dR,             RA_ERR,     float,            RA error                      arcsec
+FIELD dD,             DEC_ERR,    float,            DEC error                     arcsec
+
+FIELD uR,             U_RA,       float,            RA*cos(D) proper-motion,      arcsec/year
+FIELD uD,             U_DEC,      float,            DEC proper-motion,            arcsec/year
+FIELD duR,            V_RA_ERR,   float,            RA*cos(D) p-m error,          arcsec/year
+FIELD duD,            V_DEC_ERR,  float,            DEC p-m error,                arcsec/year
+
+FIELD P,              PAR,        float,            parallax,			  arcsec
+FIELD dP,             PAR_ERR,    float,            parallax error,               arcsec
+
+FIELD mag,            MAG,        float,            average magnitude in requested photcode
+FIELD c1,             MAG_C1,     float,            average magnitude in color term 1
+FIELD c2,             MAG_C2,     float,            average magnitude in color term 2
+
+FIELD photcode,       PHOTCODE,   unsigned short,   photcode for this mag
+FIELD code,           CODE,       unsigned short,   ID code (star; ghost; etc)
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ascii.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ascii.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ascii.d	(revision 16632)
@@ -0,0 +1,18 @@
+# name of structure type
+STRUCT  ImageASCII
+EXTNAME IMAGE
+TYPE    TABLE
+SIZE    328
+
+# elements of data structure / FITS table
+FIELD obstime,    START_TIME, char[20],    start time of measurement, yyyy/mm/dd,hh:mm:ss
+FIELD filter,  	  FILTER,     char[10],    filter and camera name    
+FIELD ZP,      	  ZP_OBS,     float[8.4],  measured zero point,       mag
+FIELD dZP,     	  ZP_ERR,     float[7.4],  error on zero point,       mag
+FIELD ra,      	  RA,         float[11.6], RA (J2000),                dec. degrees
+FIELD dec,     	  DEC,        float[11.6], DEC (J2000),               dec. degrees
+FIELD airmass, 	  C_AIRMASS,  float[7.3],  airmass coeff,             mag per airmass 
+FIELD sky,     	  SKY,        float[7.1],  median sky flux,           counts
+FIELD Nstar,   	  NSTAR,      int[6],      Number of stars in image,  stars
+
+## XXX is this used?
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-elixir.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-elixir.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-elixir.d	(revision 16632)
@@ -0,0 +1,59 @@
+STRUCT  Image_Elixir
+EXTNAME DVO_IMAGE_ELIXIR
+TYPE 	BINTABLE
+SIZE 	240
+
+# elements of the image structure
+
+SUBSTRUCT coords,           COORDS,               Coords,        astrometric data
+SUBFIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+SUBFIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+SUBFIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+SUBFIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+SUBFIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+SUBFIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+SUBFIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+SUBFIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+SUBFIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+SUBFIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+SUBFIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+SUBFIELD  ctype,            CTYPE,                char[15],      coordinate type
+SUBFIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
+
+FIELD 	  tzero,            TZERO,                e_time,         readout time (row 0)
+FIELD 	  nstar,            NSTAR,                unsigned int,   number of stars on image
+FIELD 	  secz,             SECZ,                 short,      	  airmass,                   milliairmass
+FIELD 	  NX,               NX,                   short,      	  image width
+FIELD 	  NY,               NY,                   short,      	  image height
+FIELD 	  apmifit,          APMIFIT,              short,      	  aperture correction,       millimag
+FIELD 	  dapmifit,         DAPMIFIT,             short,      	  apmifit error,             millimag
+FIELD 	  source,           SOURCE,               short,      	  identifier for CCD,
+FIELD 	  Mcal,             MCAL,                 short,      	  calibration mag,           millimag
+FIELD 	  dMcal,            DMCAL,                short,      	  error on Mcal,             millimag
+FIELD 	  Xm,               XM,                   short,      	  image chisq,               10*log(value)
+FIELD 	  name,             NAME,                 char[32],       name of original image 
+FIELD 	  detection_limit,  DETECTION_LIMIT,      unsigned char,  detection limit,           10*mag
+FIELD 	  saturation_limit, SATURATION_LIMIT,     unsigned char,  saturation limit,          10*mag
+FIELD 	  cerror,           CERROR,               unsigned char,  astrometric error,         50*arcsec
+FIELD 	  fwhm_x,           FWHM_X,               unsigned char,  PSF x width,               25*arcsec
+FIELD 	  fwhm_y,           FWHM_Y,               unsigned char,  PSF y width,               25*arcsec
+FIELD 	  trate,            TRATE,                unsigned char,  scan rate,                 100 usec/pixel
+FIELD 	  exptime,          EXPTIME,              float,          exposure time,             seconds
+FIELD 	  code,             CODE,                 char,           image quality flag
+FIELD 	  ccdnum,           CCDNUM,               unsigned char,  CCD ID number
+FIELD 	  dummy,            DUMMY,                char[20],       unused
+FIELD 	  order,            ORDER,                short,      	  Mrel 2D polynomical order 
+FIELD 	  Mx,               MX,                   short,      	  Mrel polyterm
+FIELD 	  My,               MY,                   short,      	  Mrel polyterm
+FIELD 	  Mxx,              MXX,                  short,      	  Mrel polyterm
+FIELD 	  Mxy,              MXY,                  short,      	  Mrel polyterm
+FIELD 	  Myy,              MYY,                  short,      	  Mrel polyterm
+FIELD 	  Mxxx,             MXXX,                 short,      	  Mrel polyterm
+FIELD 	  Mxxy,             MXXY,                 short,      	  Mrel polyterm
+FIELD 	  Mxyy,             MXYY,                 short,      	  Mrel polyterm
+FIELD 	  Myyy,             MYYY,                 short,      	  Mrel polyterm
+FIELD 	  Mxxxx,            MXXXX,                short,      	  Mrel polyterm
+FIELD 	  Mxxxy,            MXXXY,                short,      	  Mrel polyterm
+FIELD 	  Mxxyy,            MXXYY,                short,      	  Mrel polyterm
+FIELD 	  Mxyyy,            MXYYY,                short,      	  Mrel polyterm
+FIELD 	  Myyyy,            MYYYY,                short,      	  Mrel polyterm
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-loneos.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-loneos.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-loneos.d	(revision 16632)
@@ -0,0 +1,59 @@
+STRUCT  Image_Loneos
+EXTNAME DVO_IMAGE_LONEOS
+TYPE 	BINTABLE
+SIZE 	240
+
+# elements of the image structure
+
+SUBSTRUCT coords,           COORDS,               Coords,        astrometric data
+SUBFIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+SUBFIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+SUBFIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+SUBFIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+SUBFIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+SUBFIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+SUBFIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+SUBFIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+SUBFIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+SUBFIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+SUBFIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+SUBFIELD  ctype,            CTYPE,                char[15],      coordinate type
+SUBFIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
+
+FIELD 	  tzero,            TZERO,                e_time,         readout time (row 0)
+FIELD 	  nstar,            NSTAR,                unsigned int,   number of stars on image
+FIELD 	  secz,             SECZ,                 short,      	  airmass,                   milliairmass
+FIELD 	  NX,               NX,                   short,      	  image width
+FIELD 	  NY,               NY,                   short,      	  image height
+FIELD 	  apmifit,          APMIFIT,              short,      	  aperture correction,       millimag
+FIELD 	  dapmifit,         DAPMIFIT,             short,      	  apmifit error,             millimag
+FIELD 	  source,           SOURCE,               short,      	  identifier for CCD,
+FIELD 	  Mcal,             MCAL,                 short,      	  calibration mag,           millimag
+FIELD 	  dMcal,            DMCAL,                short,      	  error on Mcal,             millimag
+FIELD 	  Xm,               XM,                   short,      	  image chisq,               10*log(value)
+FIELD 	  name,             NAME,                 char[32],       name of original image 
+FIELD 	  detection_limit,  DETECTION_LIMIT,      unsigned char,  detection limit,           10*mag
+FIELD 	  saturation_limit, SATURATION_LIMIT,     unsigned char,  saturation limit,          10*mag
+FIELD 	  cerror,           CERROR,               unsigned char,  astrometric error,         50*arcsec
+FIELD 	  fwhm_x,           FWHM_X,               unsigned char,  PSF x width,               25*arcsec
+FIELD 	  fwhm_y,           FWHM_Y,               unsigned char,  PSF y width,               25*arcsec
+FIELD 	  trate,            TRATE,                unsigned char,  scan rate,                 100 usec/pixel
+FIELD 	  exptime,          EXPTIME,              float,          exposure time,             seconds
+FIELD 	  code,             CODE,                 char,           image quality flag
+FIELD 	  ccdnum,           CCDNUM,               unsigned char,  CCD ID number
+FIELD 	  dummy,            DUMMY,                char[20],       unused
+FIELD 	  order,            ORDER,                short,      	  Mrel 2D polynomical order 
+FIELD 	  Mx,               MX,                   short,      	  Mrel polyterm
+FIELD 	  My,               MY,                   short,      	  Mrel polyterm
+FIELD 	  Mxx,              MXX,                  short,      	  Mrel polyterm
+FIELD 	  Mxy,              MXY,                  short,      	  Mrel polyterm
+FIELD 	  Myy,              MYY,                  short,      	  Mrel polyterm
+FIELD 	  Mxxx,             MXXX,                 short,      	  Mrel polyterm
+FIELD 	  Mxxy,             MXXY,                 short,      	  Mrel polyterm
+FIELD 	  Mxyy,             MXYY,                 short,      	  Mrel polyterm
+FIELD 	  Myyy,             MYYY,                 short,      	  Mrel polyterm
+FIELD 	  Mxxxx,            MXXXX,                short,      	  Mrel polyterm
+FIELD 	  Mxxxy,            MXXXY,                short,      	  Mrel polyterm
+FIELD 	  Mxxyy,            MXXYY,                short,      	  Mrel polyterm
+FIELD 	  Mxyyy,            MXYYY,                short,      	  Mrel polyterm
+FIELD 	  Myyyy,            MYYYY,                short,      	  Mrel polyterm
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-panstarrs-dev-0.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-panstarrs-dev-0.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-panstarrs-dev-0.d	(revision 16632)
@@ -0,0 +1,70 @@
+STRUCT       Image_Panstarrs_DEV_0
+EXTNAME      DVO_IMAGE_PANSTARRS_DEV_0
+TYPE         BINTABLE
+SIZE         256
+DESCRIPTION  DVO Image Table 
+
+# elements of the image structure
+
+SUBSTRUCT coords,           COORDS,               Coords,        astrometric data
+SUBFIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+SUBFIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+SUBFIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+SUBFIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+SUBFIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+SUBFIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+SUBFIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+SUBFIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+SUBFIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+SUBFIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+SUBFIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+SUBFIELD  ctype,            CTYPE,                char[15],      coordinate type
+SUBFIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
+# 120 bytes
+
+FIELD 	  tzero,            TZERO,                e_time,         readout time (row 0)
+FIELD 	  nstar,            NSTAR,                unsigned int,   number of stars on image
+FIELD 	  secz,             SECZ,                 float,      	  airmass,                   mag
+FIELD 	  NX,               NX,                   short,      	  image width
+FIELD 	  NY,               NY,                   short,      	  image height
+FIELD 	  apmifit,          APMIFIT,              float,      	  aperture correction,       mag
+FIELD 	  dapmifit,         DAPMIFIT,             float,      	  apmifit error,             mag
+FIELD 	  Mcal,             MCAL,                 float,      	  calibration mag,           mag
+FIELD 	  dMcal,            DMCAL,                float,      	  error on Mcal,             mag
+FIELD 	  Xm,               XM,                   short,      	  image chisq,               10*log(value)
+FIELD 	  photcode,         PHOTCODE,             short,      	  identifier for CCD,
+FIELD 	  exptime,          EXPTIME,              float,          exposure time,             seconds
+FIELD     sidtime,          ST,			  float,          sidereal time of exposure
+FIELD     latitude,         LAT,		  float,          observatory latitude,      degrees
+# 40 bytes
+
+FIELD 	  name,             NAME,                 char[32],       name of original image 
+FIELD 	  detection_limit,  DETECTION_LIMIT,      unsigned char,  detection limit,           10*mag
+FIELD 	  saturation_limit, SATURATION_LIMIT,     unsigned char,  saturation limit,          10*mag
+FIELD 	  cerror,           CERROR,               unsigned char,  astrometric error,         50*arcsec
+FIELD 	  fwhm_x,           FWHM_X,               unsigned char,  PSF x width,               25*arcsec
+FIELD 	  fwhm_y,           FWHM_Y,               unsigned char,  PSF y width,               25*arcsec
+FIELD 	  trate,            TRATE,                unsigned char,  scan rate,                 100 usec/pixel
+FIELD 	  code,             CODE,                 char,           image quality flag
+FIELD 	  ccdnum,           CCDNUM,               unsigned char,  CCD ID number
+FIELD 	  imageID_hi,       IMAGE_ID_HI,          unsigned int,   ID upper bytes
+FIELD 	  imageID_lo,       IMAGE_ID_LO,          unsigned int,   ID lower bytes
+# 48 bytes 
+
+FIELD 	  dummy,            DUMMY,                char[10],       unused
+FIELD 	  order,            ORDER,                short,      	  Mrel 2D polynomical order 
+FIELD 	  Mx,               MX,                   short,      	  Mrel polyterm
+FIELD 	  My,               MY,                   short,      	  Mrel polyterm
+FIELD 	  Mxx,              MXX,                  short,      	  Mrel polyterm
+FIELD 	  Mxy,              MXY,                  short,      	  Mrel polyterm
+FIELD 	  Myy,              MYY,                  short,      	  Mrel polyterm
+FIELD 	  Mxxx,             MXXX,                 short,      	  Mrel polyterm
+FIELD 	  Mxxy,             MXXY,                 short,      	  Mrel polyterm
+FIELD 	  Mxyy,             MXYY,                 short,      	  Mrel polyterm
+FIELD 	  Myyy,             MYYY,                 short,      	  Mrel polyterm
+FIELD 	  Mxxxx,            MXXXX,                short,      	  Mrel polyterm
+FIELD 	  Mxxxy,            MXXXY,                short,      	  Mrel polyterm
+FIELD 	  Mxxyy,            MXXYY,                short,      	  Mrel polyterm
+FIELD 	  Mxyyy,            MXYYY,                short,      	  Mrel polyterm
+FIELD 	  Myyyy,            MYYYY,                short,      	  Mrel polyterm
+# 40 bytes
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-panstarrs-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-panstarrs-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-panstarrs-dev-1.d	(revision 16632)
@@ -0,0 +1,70 @@
+STRUCT       Image_Panstarrs_DEV_1
+EXTNAME      DVO_IMAGE_PANSTARRS_DEV_1
+TYPE         BINTABLE
+SIZE         288
+DESCRIPTION  DVO Image Table 
+
+# elements of the image structure
+
+SUBSTRUCT coords,           COORDS,               Coords,        astrometric data
+SUBFIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+SUBFIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+SUBFIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+SUBFIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+SUBFIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+SUBFIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+SUBFIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+SUBFIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+SUBFIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+SUBFIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+SUBFIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+SUBFIELD  ctype,            CTYPE,                char[15],      coordinate type
+SUBFIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
+# 120 bytes
+
+FIELD 	  tzero,            TZERO,                e_time,         readout time (row 0)
+FIELD 	  nstar,            NSTAR,                unsigned int,   number of stars on image
+FIELD 	  secz,             SECZ,                 float,      	  airmass,                   mag
+FIELD 	  NX,               NX,                   short,      	  image width
+FIELD 	  NY,               NY,                   short,      	  image height
+FIELD 	  apmifit,          APMIFIT,              float,      	  aperture correction,       mag
+FIELD 	  dapmifit,         DAPMIFIT,             float,      	  apmifit error,             mag
+FIELD 	  Mcal,             MCAL,                 float,      	  calibration mag,           mag
+FIELD 	  dMcal,            DMCAL,                float,      	  error on Mcal,             mag
+FIELD 	  Xm,               XM,                   short,      	  image chisq,               10*log(value)
+FIELD 	  photcode,         PHOTCODE,             short,      	  identifier for CCD,
+FIELD 	  exptime,          EXPTIME,              float,          exposure time,             seconds
+FIELD     sidtime,          ST,			  float,          sidereal time of exposure
+FIELD     latitude,         LAT,		  float,          observatory latitude,      degrees
+# 40 bytes
+
+FIELD 	  name,             NAME,                 char[64],       name of original image 
+FIELD 	  detection_limit,  DETECTION_LIMIT,      unsigned char,  detection limit,           10*mag
+FIELD 	  saturation_limit, SATURATION_LIMIT,     unsigned char,  saturation limit,          10*mag
+FIELD 	  cerror,           CERROR,               unsigned char,  astrometric error,         50*arcsec
+FIELD 	  fwhm_x,           FWHM_X,               unsigned char,  PSF x width,               25*arcsec
+FIELD 	  fwhm_y,           FWHM_Y,               unsigned char,  PSF y width,               25*arcsec
+FIELD 	  trate,            TRATE,                unsigned char,  scan rate,                 100 usec/pixel
+FIELD 	  code,             CODE,                 char,           image quality flag
+FIELD 	  ccdnum,           CCDNUM,               unsigned char,  CCD ID number
+FIELD 	  imageID_hi,       IMAGE_ID_HI,          unsigned int,   ID upper bytes
+FIELD 	  imageID_lo,       IMAGE_ID_LO,          unsigned int,   ID lower bytes
+# 48 bytes 
+
+FIELD 	  dummy,            DUMMY,                char[10],       unused
+FIELD 	  order,            ORDER,                short,      	  Mrel 2D polynomical order 
+FIELD 	  Mx,               MX,                   short,      	  Mrel polyterm
+FIELD 	  My,               MY,                   short,      	  Mrel polyterm
+FIELD 	  Mxx,              MXX,                  short,      	  Mrel polyterm
+FIELD 	  Mxy,              MXY,                  short,      	  Mrel polyterm
+FIELD 	  Myy,              MYY,                  short,      	  Mrel polyterm
+FIELD 	  Mxxx,             MXXX,                 short,      	  Mrel polyterm
+FIELD 	  Mxxy,             MXXY,                 short,      	  Mrel polyterm
+FIELD 	  Mxyy,             MXYY,                 short,      	  Mrel polyterm
+FIELD 	  Myyy,             MYYY,                 short,      	  Mrel polyterm
+FIELD 	  Mxxxx,            MXXXX,                short,      	  Mrel polyterm
+FIELD 	  Mxxxy,            MXXXY,                short,      	  Mrel polyterm
+FIELD 	  Mxxyy,            MXXYY,                short,      	  Mrel polyterm
+FIELD 	  Mxyyy,            MXYYY,                short,      	  Mrel polyterm
+FIELD 	  Myyyy,            MYYYY,                short,      	  Mrel polyterm
+# 40 bytes
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ps1-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ps1-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ps1-dev-1.d	(revision 16632)
@@ -0,0 +1,69 @@
+STRUCT       Image_PS1_DEV_1
+EXTNAME      DVO_IMAGE_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         288
+DESCRIPTION  DVO Image Table 
+
+# elements of the image structure
+
+SUBSTRUCT coords,           COORDS,               Coords,        astrometric data
+SUBFIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+SUBFIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+SUBFIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+SUBFIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+SUBFIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+SUBFIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+SUBFIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+SUBFIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+SUBFIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+SUBFIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+SUBFIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+SUBFIELD  ctype,            CTYPE,                char[15],      coordinate type
+SUBFIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
+# 120 bytes
+
+FIELD 	  tzero,            TZERO,                e_time,         readout time (row 0)
+FIELD 	  nstar,            NSTAR,                unsigned int,   number of stars on image
+FIELD 	  secz,             SECZ,                 float,      	  airmass,                   mag
+FIELD 	  NX,               NX,                   short,      	  image width
+FIELD 	  NY,               NY,                   short,      	  image height
+FIELD 	  apmifit,          APMIFIT,              float,      	  aperture correction,       mag
+FIELD 	  dapmifit,         DAPMIFIT,             float,      	  apmifit error,             mag
+FIELD 	  Mcal,             MCAL,                 float,      	  calibration mag,           mag
+FIELD 	  dMcal,            DMCAL,                float,      	  error on Mcal,             mag
+FIELD 	  Xm,               XM,                   short,      	  image chisq,               10*log(value)
+FIELD 	  photcode,         PHOTCODE,             short,      	  identifier for CCD,
+FIELD 	  exptime,          EXPTIME,              float,          exposure time,             seconds
+FIELD     sidtime,          ST,			  float,          sidereal time of exposure
+FIELD     latitude,         LAT,		  float,          observatory latitude,      degrees
+# 40 bytes
+
+FIELD 	  name,             NAME,                 char[64],       name of original image 
+FIELD 	  detection_limit,  DETECTION_LIMIT,      unsigned char,  detection limit,           10*mag
+FIELD 	  saturation_limit, SATURATION_LIMIT,     unsigned char,  saturation limit,          10*mag
+FIELD 	  cerror,           CERROR,               unsigned char,  astrometric error,         50*arcsec
+FIELD 	  fwhm_x,           FWHM_X,               unsigned char,  PSF x width,               25*arcsec
+FIELD 	  fwhm_y,           FWHM_Y,               unsigned char,  PSF y width,               25*arcsec
+FIELD 	  trate,            TRATE,                unsigned char,  scan rate,                 100 usec/pixel
+FIELD 	  code,             CODE,                 char,           image quality flag
+FIELD 	  ccdnum,           CCDNUM,               unsigned char,  CCD ID number
+FIELD 	  imageID,          IMAGE_ID,             unsigned int,   image ID
+# 44 bytes 
+
+FIELD 	  dummy,            DUMMY,                char[14],       unused
+FIELD 	  order,            ORDER,                short,      	  Mrel 2D polynomical order 
+FIELD 	  Mx,               MX,                   short,      	  Mrel polyterm
+FIELD 	  My,               MY,                   short,      	  Mrel polyterm
+FIELD 	  Mxx,              MXX,                  short,      	  Mrel polyterm
+FIELD 	  Mxy,              MXY,                  short,      	  Mrel polyterm
+FIELD 	  Myy,              MYY,                  short,      	  Mrel polyterm
+FIELD 	  Mxxx,             MXXX,                 short,      	  Mrel polyterm
+FIELD 	  Mxxy,             MXXY,                 short,      	  Mrel polyterm
+FIELD 	  Mxyy,             MXYY,                 short,      	  Mrel polyterm
+FIELD 	  Myyy,             MYYY,                 short,      	  Mrel polyterm
+FIELD 	  Mxxxx,            MXXXX,                short,      	  Mrel polyterm
+FIELD 	  Mxxxy,            MXXXY,                short,      	  Mrel polyterm
+FIELD 	  Mxxyy,            MXXYY,                short,      	  Mrel polyterm
+FIELD 	  Mxyyy,            MXYYY,                short,      	  Mrel polyterm
+FIELD 	  Myyyy,            MYYYY,                short,      	  Mrel polyterm
+# 40 bytes
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ps1-dev-2.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ps1-dev-2.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image-ps1-dev-2.d	(revision 16632)
@@ -0,0 +1,69 @@
+STRUCT       Image_PS1_DEV_1
+EXTNAME      DVO_IMAGE_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         288
+DESCRIPTION  DVO Image Table 
+
+# elements of the image structure
+
+SUBSTRUCT coords,           COORDS,               Coords,        astrometric data
+SUBFIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+SUBFIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+SUBFIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+SUBFIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+SUBFIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+SUBFIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+SUBFIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+SUBFIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+SUBFIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+SUBFIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+SUBFIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+SUBFIELD  ctype,            CTYPE,                char[15],      coordinate type
+SUBFIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
+# 120 bytes
+
+FIELD 	  tzero,            TZERO,                e_time,         readout time (row 0)
+FIELD 	  nstar,            NSTAR,                unsigned int,   number of stars on image
+FIELD 	  secz,             SECZ,                 float,      	  airmass,                   mag
+FIELD 	  NX,               NX,                   short,      	  image width
+FIELD 	  NY,               NY,                   short,      	  image height
+FIELD 	  apmifit,          APMIFIT,              float,      	  aperture correction,       mag
+FIELD 	  dapmifit,         DAPMIFIT,             float,      	  apmifit error,             mag
+FIELD 	  Mcal,             MCAL,                 float,      	  calibration mag,           mag
+FIELD 	  dMcal,            DMCAL,                float,      	  error on Mcal,             mag
+FIELD 	  Xm,               XM,                   short,      	  image chisq,               10*log(value)
+FIELD 	  photcode,         PHOTCODE,             short,      	  identifier for CCD,
+FIELD 	  exptime,          EXPTIME,              float,          exposure time,             seconds
+FIELD     sidtime,          ST,			  float,          sidereal time of exposure
+FIELD     latitude,         LAT,		  float,          observatory latitude,      degrees
+# 40 bytes
+
+FIELD 	  name,             NAME,                 char[64],       name of original image 
+FIELD 	  detection_limit,  DETECTION_LIMIT,      unsigned char,  detection limit,           10*mag
+FIELD 	  saturation_limit, SATURATION_LIMIT,     unsigned char,  saturation limit,          10*mag
+FIELD 	  cerror,           CERROR,               unsigned char,  astrometric error,         50*arcsec
+FIELD 	  fwhm_x,           FWHM_X,               unsigned char,  PSF x width,               25*arcsec
+FIELD 	  fwhm_y,           FWHM_Y,               unsigned char,  PSF y width,               25*arcsec
+FIELD 	  trate,            TRATE,                unsigned char,  scan rate,                 100 usec/pixel
+FIELD 	  code,             CODE,                 char,           image quality flag
+FIELD 	  ccdnum,           CCDNUM,               unsigned char,  CCD ID number
+FIELD 	  imageID,          IMAGE_ID,             unsigned int,   image ID
+# 44 bytes 
+
+FIELD 	  dummy,            DUMMY,                char[14],       unused
+FIELD 	  order,            ORDER,                short,      	  Mrel 2D polynomical order 
+FIELD 	  Mx,               MX,                   short,      	  Mrel polyterm
+FIELD 	  My,               MY,                   short,      	  Mrel polyterm
+FIELD 	  Mxx,              MXX,                  short,      	  Mrel polyterm
+FIELD 	  Mxy,              MXY,                  short,      	  Mrel polyterm
+FIELD 	  Myy,              MYY,                  short,      	  Mrel polyterm
+FIELD 	  Mxxx,             MXXX,                 short,      	  Mrel polyterm
+FIELD 	  Mxxy,             MXXY,                 short,      	  Mrel polyterm
+FIELD 	  Mxyy,             MXYY,                 short,      	  Mrel polyterm
+FIELD 	  Myyy,             MYYY,                 short,      	  Mrel polyterm
+FIELD 	  Mxxxx,            MXXXX,                short,      	  Mrel polyterm
+FIELD 	  Mxxxy,            MXXXY,                short,      	  Mrel polyterm
+FIELD 	  Mxxyy,            MXXYY,                short,      	  Mrel polyterm
+FIELD 	  Mxyyy,            MXYYY,                short,      	  Mrel polyterm
+FIELD 	  Myyyy,            MYYYY,                short,      	  Mrel polyterm
+# 40 bytes
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/image.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/image.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/image.d	(revision 16632)
@@ -0,0 +1,69 @@
+STRUCT       Image
+EXTNAME      DVO_IMAGE
+TYPE         BINTABLE
+SIZE         288
+DESCRIPTION  DVO Image Table 
+
+# elements of the image structure
+
+SUBSTRUCT coords,           COORDS,               Coords,        astrometric data
+SUBFIELD  crval1,           CRVAL1,               double,   	 coordinate at reference pixel
+SUBFIELD  crval2,           CRVAL2,               double,  	 coordinate at reference pixel
+SUBFIELD  crpix1,           CRPIX1,               float,   	 coordinate of reference pixel
+SUBFIELD  crpix2,           CRPIX2,               float,   	 coordinate of reference pixel
+SUBFIELD  cdelt1,           CDELT1,               float,   	 degrees per pixel
+SUBFIELD  cdelt2,           CDELT2,               float,    	 degrees per pixel
+SUBFIELD  pc1_1,            PC1_1,                float,    	 rotation matrix
+SUBFIELD  pc1_2,            PC1_2,                float,    	 rotation matrix
+SUBFIELD  pc2_1,            PC2_1,                float,    	 rotation matrix
+SUBFIELD  pc2_2,            PC2_2,                float,    	 rotation matrix
+SUBFIELD  polyterms,        POLYTERMS,            float[7][2],	 higher order warping terms
+SUBFIELD  ctype,            CTYPE,                char[15],      coordinate type
+SUBFIELD  Npolyterms,       NPOLYTERMS,           char,     	 order of polynomial
+# 120 bytes
+
+FIELD 	  tzero,            TZERO,                e_time,         readout time (row 0)
+FIELD 	  nstar,            NSTAR,                unsigned int,   number of stars on image
+FIELD 	  secz,             SECZ,                 float,      	  airmass,                   mag
+FIELD 	  NX,               NX,                   unsigned short, image width
+FIELD 	  NY,               NY,                   unsigned short, image height
+FIELD 	  apmifit,          APMIFIT,              float,      	  aperture correction,       mag
+FIELD 	  dapmifit,         DAPMIFIT,             float,      	  apmifit error,             mag
+FIELD 	  Mcal,             MCAL,                 float,      	  calibration mag,           mag
+FIELD 	  dMcal,            DMCAL,                float,      	  error on Mcal,             mag
+FIELD 	  Xm,               XM,                   short,      	  image chisq,               10*log(value)
+FIELD 	  photcode,         PHOTCODE,             short,      	  identifier for CCD,
+FIELD 	  exptime,          EXPTIME,              float,          exposure time,             seconds
+FIELD     sidtime,          ST,			  float,          sidereal time of exposure
+FIELD     latitude,         LAT,		  float,          observatory latitude,      degrees
+# 40 bytes
+
+FIELD 	  name,             NAME,                 char[64],       name of original image 
+FIELD 	  detection_limit,  DETECTION_LIMIT,      unsigned char,  detection limit,           10*mag
+FIELD 	  saturation_limit, SATURATION_LIMIT,     unsigned char,  saturation limit,          10*mag
+FIELD 	  cerror,           CERROR,               unsigned char,  astrometric error,         50*arcsec
+FIELD 	  fwhm_x,           FWHM_X,               unsigned char,  PSF x width,               25*arcsec
+FIELD 	  fwhm_y,           FWHM_Y,               unsigned char,  PSF y width,               25*arcsec
+FIELD 	  trate,            TRATE,                unsigned char,  scan rate,                 100 usec/pixel
+FIELD 	  code,             CODE,                 char,           image quality flag
+FIELD 	  ccdnum,           CCDNUM,               unsigned char,  CCD ID number
+FIELD 	  imageID,          IMAGE_ID,             unsigned int,   image ID
+# 48 bytes 
+
+FIELD 	  dummy,            DUMMY,                char[14],       unused
+FIELD 	  order,            ORDER,                short,      	  Mrel 2D polynomical order 
+FIELD 	  Mx,               MX,                   short,      	  Mrel polyterm
+FIELD 	  My,               MY,                   short,      	  Mrel polyterm
+FIELD 	  Mxx,              MXX,                  short,      	  Mrel polyterm
+FIELD 	  Mxy,              MXY,                  short,      	  Mrel polyterm
+FIELD 	  Myy,              MYY,                  short,      	  Mrel polyterm
+FIELD 	  Mxxx,             MXXX,                 short,      	  Mrel polyterm
+FIELD 	  Mxxy,             MXXY,                 short,      	  Mrel polyterm
+FIELD 	  Mxyy,             MXYY,                 short,      	  Mrel polyterm
+FIELD 	  Myyy,             MYYY,                 short,      	  Mrel polyterm
+FIELD 	  Mxxxx,            MXXXX,                short,      	  Mrel polyterm
+FIELD 	  Mxxxy,            MXXXY,                short,      	  Mrel polyterm
+FIELD 	  Mxxyy,            MXXYY,                short,      	  Mrel polyterm
+FIELD 	  Mxyyy,            MXYYY,                short,      	  Mrel polyterm
+FIELD 	  Myyyy,            MYYYY,                short,      	  Mrel polyterm
+# 40 bytes
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-elixir.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-elixir.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-elixir.d	(revision 16632)
@@ -0,0 +1,23 @@
+STRUCT  Measure_Elixir
+EXTNAME DVO_MEASURE_ELIXIR
+TYPE    BINTABLE
+SIZE    32
+
+# elements of data structure / FITS table
+
+FIELD dR,             D_RA,       short,          RA offset,                	  1/100 arcsec
+FIELD dD,             D_DEC,      short,          DEC offset,               	  1/100 arcsec
+FIELD M,              MAG,        short,          catalog mag,       	       	  millimag
+FIELD Mcal,           Mcal,       short,          image cal mag,	          millimag
+FIELD Mgal,           Mgal,       short,          galaxy mag,			  millimag
+FIELD airmass,        airmass,    short,          (airmass - 1),		  milliairmass
+FIELD FWx,            FWx,        short,          object fwhm major axis,         1/100 of arcsec 
+FIELD dM,             dM,         unsigned char,  mag error,                      millimag
+FIELD fwy,            fwy,        unsigned char,  object fwhm minor/major ratio
+FIELD theta,          theta,      unsigned char,  angle wrt ccd X dir,            (0xff/360) deg
+FIELD dophot,         dophot,     char,           dophot type
+FIELD source,         source,     unsigned short, photcode
+FIELD t,              t,          unsigned int,   time in seconds (UNIX)
+FIELD averef,         averef,     unsigned int,   reference to average entry      
+FIELD dt,             dt,         short,          exposure time,                  2500*log(exptime)
+FIELD flags,          flags,      unsigned short, flags for various uses  
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-loneos.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-loneos.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-loneos.d	(revision 16632)
@@ -0,0 +1,16 @@
+STRUCT  Measure_Loneos
+EXTNAME DVO_MEASURE_LONEOS
+TYPE    BINTABLE
+SIZE    20
+
+# elements of data structure / FITS table
+
+FIELD dR,             D_RA,       short,          RA offset,                	  1/100 arcsec
+FIELD dD,             D_DEC,      short,          DEC offset,               	  1/100 arcsec
+FIELD M,              MAG,        short,          catalog mag,       	       	  millimag
+FIELD Mcal,           Mcal,       short,          image cal mag,	          millimag
+FIELD dM,             dM,         unsigned char,  mag error,                      millimag
+FIELD dophot,         dophot,     char,           dophot type
+FIELD source,         source,     unsigned short, photcode
+FIELD t,              t,          unsigned int,   time in seconds (UNIX)
+FIELD averef,         averef,     unsigned int,   reference to average entry      
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-panstarrs-dev-0.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-panstarrs-dev-0.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-panstarrs-dev-0.d	(revision 16632)
@@ -0,0 +1,54 @@
+STRUCT       Measure_Panstarrs_DEV_0
+EXTNAME      DVO_MEASURE_PANSTARRS_DEV_0
+TYPE         BINTABLE
+SIZE         96
+DESCRIPTION  DVO Detection Measurement Table 
+
+FIELD dR,             D_RA,         float,          RA offset,                	  arcsec
+FIELD dD,             D_DEC,        float,          DEC offset,               	  arcsec
+FIELD M,              MAG,          float,          catalog mag,       	       	  mag
+FIELD Mcal,           M_CAL,        float,          image cal mag,	          mag
+FIELD Mgal,           M_GAL,        float,          galaxy mag,			  mag
+FIELD dM,             MAG_ERR,      float,          mag error,                    mag
+FIELD dt,             M_TIME,       float,          exposure time,                2.5*log(exptime)
+
+# note that with airmass = 1.0 / cos(90 - alt), we have full alt/az representation
+FIELD airmass,        AIRMASS,      float,          (airmass - 1),		  airmass
+FIELD az,             AZ,           float,          telescope azimuth
+
+# new field elements needed for Pan-STARRS:
+FIELD Xccd,           X_CCD,        float,          X coord on chip,               pixels
+FIELD Yccd,           Y_CCD,        float,          Y coord on chip,               pixels
+
+# could these be packed into fewer bits?
+FIELD Sky,            SKY_FLUX,     float,          local estimate of sky flux,    counts/sec
+FIELD dSky,           SKY_FLUX_ERR, float,          local estimate of sky flux,    counts/sec
+
+FIELD t,              TIME,         unsigned int,   time in seconds (UNIX)
+FIELD averef,         AVE_REF,      unsigned int,   reference to average entry      
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD detID_hi,       DET_ID_HI,    unsigned int,   ID upper bytes
+FIELD detID_lo,       DET_ID_LO,    unsigned int,   ID lower bytes
+
+FIELD imageID_hi,     IMAGE_ID_HI,  unsigned int,   reference to image
+FIELD imageID_lo,     IMAGE_ID_LO,  unsigned int,   reference to image
+
+FIELD FWx,            FWHM_MAJOR,   short,          object fwhm major axis,       1/100 of arcsec 
+FIELD FWy,            FWHM_MINOR,   short,          object fwhm minor axis,       1/100 of arcsec 
+FIELD theta,          PSF_THETA,    short,          angle wrt ccd X dir,          (0xffff/360) deg
+FIELD photcode,       PHOTCODE,     unsigned short, photcode
+
+FIELD flags,          FLAGS,        unsigned short, flags for various uses  
+
+FIELD dXccd,          X_CCD_ERR,    short,          X coord error on chip,         pixels
+FIELD dYccd,          Y_CCD_ERR,    short,          Y coord error on chip,         pixels
+
+# do we need more resolution than a short? should this be a log?
+FIELD qPSF,           PSF_QF,       short,          psf coverage/quality factor
+
+FIELD dophot,         DOPHOT,       char,           dophot type
+FIELD stargal,        STAR_GAL,     char,           star-galaxy separator
+
+# we need extra bytes for padding purposes...
+FIELD dummy,          DUMMY,        char[2],        padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-panstarrs-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-panstarrs-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-panstarrs-dev-1.d	(revision 16632)
@@ -0,0 +1,54 @@
+STRUCT       Measure_Panstarrs_DEV_1
+EXTNAME      DVO_MEASURE_PANSTARRS_DEV_1
+TYPE         BINTABLE
+SIZE         96
+DESCRIPTION  DVO Detection Measurement Table 
+
+FIELD dR,             D_RA,         float,          RA offset,                	  arcsec
+FIELD dD,             D_DEC,        float,          DEC offset,               	  arcsec
+FIELD M,              MAG,          float,          catalog mag,       	       	  mag
+FIELD Mcal,           M_CAL,        float,          image cal mag,	          mag
+FIELD Mgal,           M_GAL,        float,          galaxy mag,			  mag
+FIELD dM,             MAG_ERR,      float,          mag error,                    mag
+FIELD dt,             M_TIME,       float,          exposure time,                2.5*log(exptime)
+
+# note that with airmass = 1.0 / cos(90 - alt), we have full alt/az representation
+FIELD airmass,        AIRMASS,      float,          (airmass - 1),		  airmass
+FIELD az,             AZ,           float,          telescope azimuth
+
+# new field elements needed for Pan-STARRS:
+FIELD Xccd,           X_CCD,        float,          X coord on chip,               pixels
+FIELD Yccd,           Y_CCD,        float,          Y coord on chip,               pixels
+
+# could these be packed into fewer bits?
+FIELD Sky,            SKY_FLUX,     float,          local estimate of sky flux,    counts/sec
+FIELD dSky,           SKY_FLUX_ERR, float,          local estimate of sky flux,    counts/sec
+
+FIELD t,              TIME,         unsigned int,   time in seconds (UNIX)
+FIELD averef,         AVE_REF,      unsigned int,   reference to average entry      
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD detID_hi,       DET_ID_HI,    unsigned int,   ID upper bytes
+FIELD detID_lo,       DET_ID_LO,    unsigned int,   ID lower bytes
+
+FIELD imageID_hi,     IMAGE_ID_HI,  unsigned int,   reference to image
+FIELD imageID_lo,     IMAGE_ID_LO,  unsigned int,   reference to image
+
+FIELD FWx,            FWHM_MAJOR,   short,          object fwhm major axis,       1/100 of arcsec 
+FIELD FWy,            FWHM_MINOR,   short,          object fwhm minor axis,       1/100 of arcsec 
+FIELD theta,          PSF_THETA,    short,          angle wrt ccd X dir,          (0xffff/360) deg
+FIELD photcode,       PHOTCODE,     unsigned short, photcode
+
+FIELD flags,          FLAGS,        unsigned short, flags for various uses  
+
+FIELD dXccd,          X_CCD_ERR,    short,          X coord error on chip,         pixels
+FIELD dYccd,          Y_CCD_ERR,    short,          Y coord error on chip,         pixels
+
+# do we need more resolution than a short? should this be a log?
+FIELD qPSF,           PSF_QF,       short,          psf coverage/quality factor
+
+FIELD dophot,         DOPHOT,       char,           dophot type
+FIELD stargal,        STAR_GAL,     char,           star-galaxy separator
+
+# we need extra bytes for padding purposes...
+FIELD dummy,          DUMMY,        char[2],        padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-ps1-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-ps1-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-ps1-dev-1.d	(revision 16632)
@@ -0,0 +1,56 @@
+STRUCT       Measure_PS1_DEV_1
+EXTNAME      DVO_MEASURE_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         104
+DESCRIPTION  DVO Detection Measurement Table 
+
+FIELD dR,             D_RA,         float,          RA offset,                	  arcsec
+FIELD dD,             D_DEC,        float,          DEC offset,               	  arcsec
+FIELD M,              MAG,          float,          catalog mag,       	       	  mag
+FIELD Mcal,           M_CAL,        float,          image cal mag,	          mag
+FIELD Mgal,           M_GAL,        float,          galaxy mag,			  mag
+FIELD dM,             MAG_ERR,      float,          mag error,                    mag
+FIELD dt,             M_TIME,       float,          exposure time,                2.5*log(exptime)
+
+# note that with airmass = 1.0 / cos(90 - alt), we have full alt/az representation
+FIELD airmass,        AIRMASS,      float,          (airmass - 1),		  airmass
+FIELD az,             AZ,           float,          telescope azimuth
+
+# new field elements needed for Pan-STARRS:
+FIELD Xccd,           X_CCD,        float,          X coord on chip,               pixels
+FIELD Yccd,           Y_CCD,        float,          Y coord on chip,               pixels
+
+# could these be packed into fewer bits?
+FIELD Sky,            SKY_FLUX,     float,          local estimate of sky flux,    counts/sec
+FIELD dSky,           SKY_FLUX_ERR, float,          local estimate of sky flux,    counts/sec
+
+FIELD t,              TIME,         unsigned int,   time in seconds (UNIX)
+FIELD averef,         AVE_REF,      unsigned int,   reference to average entry      
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD detID,          DET_ID,       unsigned int,   detection ID
+FIELD imageID,        IMAGE_ID,     unsigned int,   reference to image
+
+# do we need more resolution than a short? should this be a log?
+FIELD qPSF,           PSF_QF,       float,          psf coverage/quality factor
+FIELD psfProb,        PSF_PROB,     float,          psf coverage/quality factor
+FIELD crNsigma,       CR_NSIGMA,    float,          psf coverage/quality factor
+FIELD extNsigma,      EXT_NSIGMA,   float,          psf coverage/quality factor
+
+FIELD FWx,            FWHM_MAJOR,   short,          object fwhm major axis,       1/100 of arcsec 
+FIELD FWy,            FWHM_MINOR,   short,          object fwhm minor axis,       1/100 of arcsec 
+FIELD theta,          PSF_THETA,    short,          angle wrt ccd X dir,          (0xffff/360) deg
+FIELD photcode,       PHOTCODE,     unsigned short, photcode
+
+FIELD dXccd,          X_CCD_ERR,    short,          X coord error on chip,         pixels
+FIELD dYccd,          Y_CCD_ERR,    short,          Y coord error on chip,         pixels
+
+FIELD dbFlags,        DB_FLAGS,     unsigned short, flags for various uses  
+FIELD photFlags,      PHOT_FLAGS,   unsigned short, flags supplied by photometry program
+
+FIELD stargal,        STAR_GAL,     char,           star-galaxy separator
+
+# absorb these into photFlags?
+FIELD dophot,         DOPHOT,       char,           dophot type
+
+FIELD dummy,          DUMMY,        char[2],        padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-ps1-dev-2.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-ps1-dev-2.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure-ps1-dev-2.d	(revision 16632)
@@ -0,0 +1,56 @@
+STRUCT       Measure_PS1_DEV_1
+EXTNAME      DVO_MEASURE_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         104
+DESCRIPTION  DVO Detection Measurement Table 
+
+FIELD dR,             D_RA,         float,          RA offset,                	  arcsec
+FIELD dD,             D_DEC,        float,          DEC offset,               	  arcsec
+FIELD M,              MAG,          float,          catalog mag,       	       	  mag
+FIELD Mcal,           M_CAL,        float,          image cal mag,	          mag
+FIELD Mgal,           M_GAL,        float,          galaxy mag,			  mag
+FIELD dM,             MAG_ERR,      float,          mag error,                    mag
+FIELD dt,             M_TIME,       float,          exposure time,                2.5*log(exptime)
+
+# note that with airmass = 1.0 / cos(90 - alt), we have full alt/az representation
+FIELD airmass,        AIRMASS,      float,          (airmass - 1),		  airmass
+FIELD az,             AZ,           float,          telescope azimuth
+
+# new field elements needed for Pan-STARRS:
+FIELD Xccd,           X_CCD,        float,          X coord on chip,               pixels
+FIELD Yccd,           Y_CCD,        float,          Y coord on chip,               pixels
+
+# could these be packed into fewer bits?
+FIELD Sky,            SKY_FLUX,     float,          local estimate of sky flux,    counts/sec
+FIELD dSky,           SKY_FLUX_ERR, float,          local estimate of sky flux,    counts/sec
+
+FIELD t,              TIME,         unsigned int,   time in seconds (UNIX)
+FIELD averef,         AVE_REF,      unsigned int,   reference to average entry      
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD detID,          DET_ID,       unsigned int,   detection ID
+FIELD imageID,        IMAGE_ID,     unsigned int,   reference to image
+
+# do we need more resolution than a short? should this be a log?
+FIELD qPSF,           PSF_QF,       float,          psf coverage/quality factor
+FIELD psfProb,        PSF_PROB,     float,          psf coverage/quality factor
+FIELD crNsigma,       CR_NSIGMA,    float,          psf coverage/quality factor
+FIELD extNsigma,      EXT_NSIGMA,   float,          psf coverage/quality factor
+
+FIELD FWx,            FWHM_MAJOR,   short,          object fwhm major axis,       1/100 of arcsec 
+FIELD FWy,            FWHM_MINOR,   short,          object fwhm minor axis,       1/100 of arcsec 
+FIELD theta,          PSF_THETA,    short,          angle wrt ccd X dir,          (0xffff/360) deg
+FIELD photcode,       PHOTCODE,     unsigned short, photcode
+
+FIELD dXccd,          X_CCD_ERR,    short,          X coord error on chip,         pixels
+FIELD dYccd,          Y_CCD_ERR,    short,          Y coord error on chip,         pixels
+
+FIELD dbFlags,        DB_FLAGS,     unsigned short, flags for various uses  
+FIELD photFlags,      PHOT_FLAGS,   unsigned short, flags supplied by photometry program
+
+FIELD stargal,        STAR_GAL,     char,           star-galaxy separator
+
+# absorb these into photFlags?
+FIELD dophot,         DOPHOT,       char,           dophot type
+
+FIELD dummy,          DUMMY,        char[2],        padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/measure.d	(revision 16632)
@@ -0,0 +1,56 @@
+STRUCT       Measure
+EXTNAME      DVO_MEASURE
+TYPE         BINTABLE
+SIZE         104
+DESCRIPTION  DVO Detection Measurement Table 
+
+FIELD dR,             D_RA,         float,          RA offset,                	  arcsec
+FIELD dD,             D_DEC,        float,          DEC offset,               	  arcsec
+FIELD M,              MAG,          float,          catalog mag,       	       	  mag
+FIELD Mcal,           M_CAL,        float,          image cal mag,	          mag
+FIELD Mgal,           M_GAL,        float,          galaxy mag,			  mag
+FIELD dM,             MAG_ERR,      float,          mag error,                    mag
+FIELD dt,             M_TIME,       float,          exposure time,                2.5*log(exptime)
+
+# note that with airmass = 1.0 / cos(90 - alt), we have full alt/az representation
+FIELD airmass,        AIRMASS,      float,          (airmass - 1),		  airmass
+FIELD az,             AZ,           float,          telescope azimuth
+
+# new field elements needed for Pan-STARRS:
+FIELD Xccd,           X_CCD,        float,          X coord on chip,               pixels
+FIELD Yccd,           Y_CCD,        float,          Y coord on chip,               pixels
+
+# could these be packed into fewer bits?
+FIELD Sky,            SKY_FLUX,     float,          local estimate of sky flux,    counts/sec
+FIELD dSky,           SKY_FLUX_ERR, float,          local estimate of sky flux,    counts/sec
+
+FIELD t,              TIME,         unsigned int,   time in seconds (UNIX)
+FIELD averef,         AVE_REF,      unsigned int,   reference to average entry      
+
+# Pan-STARRS uses a 64-bit detection ID.  keep this in two 32 bit ints for backwards compatibility?
+FIELD detID,          DET_ID,       unsigned int,   detection ID
+FIELD imageID,        IMAGE_ID,     unsigned int,   reference to image
+
+# do we need more resolution than a short? should this be a log?
+FIELD qPSF,           PSF_QF,       float,          psf coverage/quality factor
+FIELD psfProb,        PSF_PROB,     float,          psf coverage/quality factor
+FIELD crNsigma,       CR_NSIGMA,    float,          psf coverage/quality factor
+FIELD extNsigma,      EXT_NSIGMA,   float,          psf coverage/quality factor
+
+FIELD FWx,            FWHM_MAJOR,   short,          object fwhm major axis,       1/100 of arcsec 
+FIELD FWy,            FWHM_MINOR,   short,          object fwhm minor axis,       1/100 of arcsec 
+FIELD theta,          PSF_THETA,    short,          angle wrt ccd X dir,          (0xffff/360) deg
+FIELD photcode,       PHOTCODE,     unsigned short, photcode
+
+FIELD dXccd,          X_CCD_ERR,    short,          X coord error on chip,         pixels
+FIELD dYccd,          Y_CCD_ERR,    short,          Y coord error on chip,         pixels
+
+FIELD dbFlags,        DB_FLAGS,     unsigned short, flags for various uses  
+FIELD photFlags,      PHOT_FLAGS,   unsigned short, flags supplied by photometry program
+
+FIELD stargal,        STAR_GAL,     char,           star-galaxy separator
+
+# absorb these into photFlags?
+FIELD dophot,         DOPHOT,       char,           dophot type
+
+FIELD dummy,          DUMMY,        char[2],        padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/missing.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/missing.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/missing.d	(revision 16632)
@@ -0,0 +1,8 @@
+STRUCT       Missing
+EXTNAME      DVO_MISSING
+TYPE         BINTABLE
+SIZE         4
+DESCRIPTION  DVO Non-Detection Table 
+
+# elements of data structure / FITS table
+FIELD t,               TIME,        unsigned int,    time in seconds
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-elixir.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-elixir.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-elixir.d	(revision 16632)
@@ -0,0 +1,20 @@
+STRUCT       PhotCode_Elixir
+EXTNAME      DVO_PHOTCODE_ELIXIR
+TYPE         BINTABLE
+SIZE         80
+DESCRIPTION  DVO Photcode Description Table 
+
+# elements of data structure / FITS table
+FIELD  code,          CODE,           unsigned short, code number (stored in Measure.source) 
+FIELD  name,          NAME,           char[32],       name for filter combination 
+FIELD  type,          TYPE,           char,           PRI/SEC/DEP/REF 
+FIELD  dummy,         DUMMY,          char[3],        padding
+FIELD  C,             C_LAM,          short,          primary phot calibration terms (millimags) 
+FIELD  dC,            C_LAM_ERR,      short,          primary phot calibration terms (millimags) 
+FIELD  dX,            X_ERR,          short,          primary phot calibration terms (millimags) 
+FIELD  K,             K,              float,          secondary phot calibration terms (millimags) 
+FIELD  c1,            C1,             int,            color is average.M[c1] - average.M[c2] 
+FIELD  c2,            C2,             int,            color is average.M[c1] - average.M[c2] 
+FIELD  equiv,         EQUIV,          int,            this dependent filter is equivalent to equiv PRI/SEC
+FIELD  Nc,            NC,             int,            number of color terms 
+FIELD  X,             X,              float[4],       color terms $X[0]*mc + X[1]*mc^2 + X[2]*mc^3$, etc 
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-ps1-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-ps1-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-ps1-dev-1.d	(revision 16632)
@@ -0,0 +1,23 @@
+STRUCT       PhotCode_PS1_DEV_1
+EXTNAME      DVO_PHOTCODE_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         104
+DESCRIPTION  DVO Photcode Description Table 
+
+# elements of data structure / FITS table
+FIELD  code,         CODE,          unsigned short, code number (stored in Measure.source) 
+FIELD  name,         NAME,          char[32],       name for filter combination 
+FIELD  type,         TYPE,          char,           PRI/SEC/DEP/REF 
+FIELD  dummy,        DUMMY,         char[3],        padding
+FIELD  C,            C_LAM,         short,          primary phot calibration terms (millimags) 
+FIELD  dC,           C_LAM_ERR,     short,          primary phot calibration terms (millimags) 
+FIELD  dX,           X_ERR,         short,          primary phot calibration terms (millimags) 
+FIELD  K,            K,             float,          secondary phot calibration terms (millimags) 
+FIELD  c1,           C1,            int,            color is average.M[c1] - average.M[c2] 
+FIELD  c2,           C2,            int,            color is average.M[c1] - average.M[c2] 
+FIELD  equiv,        EQUIV,         int,            this dependent filter is equivalent to equiv PRI/SEC
+FIELD  Nc,           NC,            int,            number of color terms 
+FIELD  X,            X,             float[4],       color terms $X[0]*mc + X[1]*mc^2 + X[2]*mc^3$, etc 
+FIELD  astromScale,  ASTROM_SCALE,  float,          astrom error = mag error * astromScale
+FIELD  photSysErr,   PHOT_SYS_ERR,  float,          systematic photometric error
+FIELD  padding,      PADDING,       float[4],       placeholder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-ps1-dev-2.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-ps1-dev-2.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode-ps1-dev-2.d	(revision 16632)
@@ -0,0 +1,23 @@
+STRUCT       PhotCode_PS1_DEV_1
+EXTNAME      DVO_PHOTCODE_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         104
+DESCRIPTION  DVO Photcode Description Table 
+
+# elements of data structure / FITS table
+FIELD  code,         CODE,          unsigned short, code number (stored in Measure.source) 
+FIELD  name,         NAME,          char[32],       name for filter combination 
+FIELD  type,         TYPE,          char,           PRI/SEC/DEP/REF 
+FIELD  dummy,        DUMMY,         char[3],        padding
+FIELD  C,            C_LAM,         short,          primary phot calibration terms (millimags) 
+FIELD  dC,           C_LAM_ERR,     short,          primary phot calibration terms (millimags) 
+FIELD  dX,           X_ERR,         short,          primary phot calibration terms (millimags) 
+FIELD  K,            K,             float,          secondary phot calibration terms (millimags) 
+FIELD  c1,           C1,            int,            color is average.M[c1] - average.M[c2] 
+FIELD  c2,           C2,            int,            color is average.M[c1] - average.M[c2] 
+FIELD  equiv,        EQUIV,         int,            this dependent filter is equivalent to equiv PRI/SEC
+FIELD  Nc,           NC,            int,            number of color terms 
+FIELD  X,            X,             float[4],       color terms $X[0]*mc + X[1]*mc^2 + X[2]*mc^3$, etc 
+FIELD  astromScale,  ASTROM_SCALE,  float,          astrom error = mag error * astromScale
+FIELD  photSysErr,   PHOT_SYS_ERR,  float,          systematic photometric error
+FIELD  padding,      PADDING,       float[4],       placeholder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/photcode.d	(revision 16632)
@@ -0,0 +1,23 @@
+STRUCT       PhotCode
+EXTNAME      DVO_PHOTCODE_RAW
+TYPE         BINTABLE
+SIZE         104
+DESCRIPTION  DVO Photcode Description Table 
+
+# elements of data structure / FITS table
+FIELD  code,         CODE,          unsigned short, code number (stored in Measure.source) 
+FIELD  name,         NAME,          char[32],       name for filter combination 
+FIELD  type,         TYPE,          char,           PRI/SEC/DEP/REF 
+FIELD  dummy,        DUMMY,         char[3],        padding
+FIELD  C,            C_LAM,         short,          primary phot calibration terms (millimags) 
+FIELD  dC,           C_LAM_ERR,     short,          primary phot calibration terms (millimags) 
+FIELD  dX,           X_ERR,         short,          primary phot calibration terms (millimags) 
+FIELD  K,            K,             float,          secondary phot calibration terms (millimags) 
+FIELD  c1,           C1,            int,            color is average.M[c1] - average.M[c2] 
+FIELD  c2,           C2,            int,            color is average.M[c1] - average.M[c2] 
+FIELD  equiv,        EQUIV,         int,            this dependent filter is equivalent to equiv PRI/SEC
+FIELD  Nc,           NC,            int,            number of color terms 
+FIELD  X,            X,             float[4],       color terms $X[0]*mc + X[1]*mc^2 + X[2]*mc^3$, etc 
+FIELD  astromScale,  ASTROM_SCALE,  float,          astrom error = mag error * astromScale
+FIELD  photSysErr,   PHOT_SYS_ERR,  float,          systematic photometric error
+FIELD  padding,      PADDING,       float[4],       placeholder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/photreg-old.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/photreg-old.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/photreg-old.d	(revision 16632)
@@ -0,0 +1,18 @@
+STRUCT PhotParsOld
+EXTNAME ZERO_POINTS
+TYPE BINTABLE
+SIZE 100
+
+# elements of data structure / FITS table
+
+FIELD ZP,    	  ZP_OBS,     float,       measured zero point,       mag
+FIELD ZPo,   	  ZP_REF,     float, 	   nominal zero point,        mag
+FIELD dZP,   	  ZP_ERR,     float, 	   error on zero point,       mag
+FIELD K,     	  C_AIRMASS,  float, 	   airmass coeff,             mag per airmass
+FIELD X,     	  C_COLOR,    float, 	   color coeff,               mag per mag
+FIELD tstart,	  START_TIME, e_time,      start time of measurement, seconds since 1 Jan 1970 UT
+FIELD tstop, 	  STOP_TIME,  e_time,      stop time of measurement,  seconds since 1 Jan 1970 UT
+FIELD c1,    	  C1_CODE,    short, 	   code 1 for color,          photcode
+FIELD c2,    	  C2_CODE,    short, 	   code 2 for color,          photcode
+FIELD photcode,   PHOTCODE,   short, 	   photcode,                  photcode
+FIELD label,      LABEL,      char[66],    data label
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/photreg.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/photreg.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/photreg.d	(revision 16632)
@@ -0,0 +1,21 @@
+STRUCT PhotPars
+EXTNAME ZERO_POINTS_3.0
+TYPE BINTABLE
+SIZE 108
+
+# elements of data structure / FITS table
+
+FIELD ZP,    	  ZP_OBS,     float,       measured zero point,       mag
+FIELD ZPo,   	  ZP_REF,     float, 	   nominal zero point,        mag
+FIELD dZP,   	  ZP_ERR,     float, 	   error on zero point,       mag
+FIELD K,     	  C_AIRMASS,  float, 	   airmass coeff,             mag per airmass
+FIELD X,     	  C_COLOR,    float, 	   color coeff,               mag per mag
+FIELD tstart,	  START_TIME, e_time,      start time of measurement, seconds since 1 Jan 1970 UT
+FIELD tstop, 	  STOP_TIME,  e_time,      stop time of measurement,  seconds since 1 Jan 1970 UT
+FIELD c1,    	  C1_CODE,    short, 	   code 1 for color,          photcode
+FIELD c2,    	  C2_CODE,    short, 	   code 2 for color,          photcode
+FIELD photcode,   PHOTCODE,   short, 	   photcode,                  photcode
+FIELD label,      LABEL,      char[64],    data label
+FIELD refcode,    REFCODE,    rawshort,	   photcode,                  photcode
+FIELD Ntime,      N_TIME,     int, 	   number of times
+FIELD Nmeas,      N_MEAS,     int, 	   number of measurements
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/ps1_dev_0.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/ps1_dev_0.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/ps1_dev_0.d	(revision 16632)
@@ -0,0 +1,24 @@
+# name of structure type
+STRUCT  PS1_DEV_0
+EXTNAME PS1_DEV_0
+TYPE    BINTABLE
+SIZE    64
+
+# elements of data structure / FITS table
+FIELD detID,    IPP_IDET,      	  unsigned int, detection ID
+FIELD X,      	X_PSF,    	  float,    x coord,              pixels
+FIELD Y,      	Y_PSF,    	  float,    y coord,              pixels
+FIELD dX,      	X_PSF_SIG,    	  float,    x coord error,        pixels
+FIELD dY,      	Y_PSF_SIG,    	  float,    y coord error,        pixels
+FIELD M,      	PSF_INST_MAG,     float,    inst mags,            mags
+FIELD dM,     	PSF_INST_MAG_SIG, float,    inst mag error,       mags
+FIELD Mpeak,    PEAK_FLUX_AS_MAG, float,    inst mag error,       mags
+FIELD sky,    	SKY,              float,    sky flux,             cnts/sec
+FIELD dSky,    	SKY_SIG,          float,    sky flux errorf       cnts/sec
+FIELD psfProb,  PSF_PROBABILITY,  float,    psf probability
+FIELD fx,     	PSF_WIDTH_X,      float,    semi-major,           pixels
+FIELD fy,     	PSF_WIDTH_Y,      float,    semi-minor,           pixels
+FIELD df,     	PSF_THETA,        float,    ellipse angle,        degrees
+FIELD psfQual, 	PSF_QF,           float,    quality factor
+FIELD nFrames, 	N_FRAMES,         short,    images overlapping peak
+FIELD dummy,  	DUMMY,            short,    padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/ps1_dev_1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/ps1_dev_1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/ps1_dev_1.d	(revision 16632)
@@ -0,0 +1,26 @@
+# name of structure type
+STRUCT  PS1_DEV_1
+EXTNAME PS1_DEV_1
+TYPE    BINTABLE
+SIZE    72
+
+# elements of data structure / FITS table
+FIELD detID,     IPP_IDET,     	   unsigned int, detection ID
+FIELD X,      	 X_PSF,    	   float,    x coord,              pixels
+FIELD Y,      	 Y_PSF,    	   float,    y coord,              pixels
+FIELD dX,      	 X_PSF_SIG,    	   float,    x coord error,        pixels
+FIELD dY,      	 Y_PSF_SIG,    	   float,    y coord error,        pixels
+FIELD M,      	 PSF_INST_MAG,     float,    inst mags,            mags
+FIELD dM,     	 PSF_INST_MAG_SIG, float,    inst mag error,       mags
+FIELD Mpeak,     PEAK_FLUX_AS_MAG, float,    inst mag error,       mags
+FIELD sky,    	 SKY,              float,    sky flux,             cnts/sec
+FIELD dSky,    	 SKY_SIG,          float,    sky flux errorf       cnts/sec
+FIELD psfProb,   PSF_PROBABILITY,  float,    psf probability
+FIELD crNsigma,  CR_NSIGMA,        float,    Nsigma deviations from PSF to CF
+FIELD extNsigma, EXT_NSIGMA,       float,    Nsigma deviations from PSF to EXT
+FIELD fx,     	 PSF_WIDTH_X,      float,    semi-major,           pixels
+FIELD fy,     	 PSF_WIDTH_Y,      float,    semi-minor,           pixels
+FIELD df,     	 PSF_THETA,        float,    ellipse angle,        degrees
+FIELD psfQual, 	 PSF_QF,           float,    quality factor
+FIELD nFrames, 	 N_FRAMES,         short,    images overlapping peak
+FIELD flags,  	 FLAGS,            short,    padding
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/regimage.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/regimage.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/regimage.d	(revision 16632)
@@ -0,0 +1,40 @@
+STRUCT  RegImage
+EXTNAME IMAGE_DATABASE
+TYPE    BINTABLE
+SIZE    360
+
+# elements of data structure / FITS table
+
+FIELD filename,         FILE,       char[64],     filename in db
+FIELD pathname,     	PATH,       char[128],    fullpath in db
+FIELD filter,       	FILTER,     char[32],     filter name
+FIELD instrument,   	INSTRUMENT, char[32],     instrument
+FIELD ccd,	        CCD,        char,   	  ccd identifier
+FIELD mode,	        MODE,       char,   	  mef/split/etc
+FIELD type,	        TYPE,       char,   	  object/flat/bias/etc
+FIELD flag,	        FLAG,       char,   	  data flags
+FIELD seqtime,          SEQTIME,    float,        exposure time per slice,   seconds
+FIELD seq,	        SEQ,        char,   	  sequence number
+FIELD junk,	        JUNK,       char[19],     space for expansion
+FIELD exptime,	        EXPTIME,    float,  	  exposure time,             seconds
+FIELD airmass,	        AIRMASS,    float,  	  airmass
+FIELD sky,	        SKY,        float,  	  background level,          counts / pixel
+FIELD bias,	        BIAS,       float,  	  bias level,                counts / pixel
+FIELD fwhm,	        FWHM,       float,  	  image quality,             pixels
+FIELD telfocus,	        TELFOCUS,   float,  	  telescope focus,           microns
+FIELD xprobe,	        XPROBE,     float,  	  bonnette probe x pos,      microns
+FIELD yprobe,	        YPROBE,     float,  	  bonnette probe y pos,      microns
+FIELD zprobe,	        ZPROBE,     float,  	  bonnette focus,            microns
+FIELD dettemp,	        DETTEMP,    float,  	  detector temperature,      deg celcius
+FIELD teltemp_0,       	TELTEMP0,   float,  	  other temperature,         deg celcius
+FIELD teltemp_1,       	TELTEMP1,   float,  	  other temperature,         deg celcius
+FIELD teltemp_2,       	TELTEMP2,   float,  	  other temperature,         deg celcius
+FIELD teltemp_3,       	TELTEMP3,   float,  	  other temperature,         deg celcius
+FIELD rotangle,	        ROTANGLE,   float,  	  camera rotation angle,     degrees
+FIELD ra,	        RA,         float,  	  image ra,                  degrees
+FIELD dec,	        DEC,        float,  	  image dec,                 degrees
+FIELD obstime,	        OBS_TIME,   e_time, 	  time of measurement,       seconds since 01 Jan 1970 UT
+FIELD regtime,	        REG_TIME,   e_time, 	  time of registration,      seconds since 01 Jan 1970 UT
+
+# take care of the memory padding boundaries when using 'junk' for new elements
+# which are not of type char!
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-elixir.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-elixir.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-elixir.d	(revision 16632)
@@ -0,0 +1,9 @@
+STRUCT  SecFilt_Elixir
+EXTNAME DVO_SECFILT_ELIXIR
+TYPE    BINTABLE
+SIZE    6
+
+# elements of data structure / FITS table
+FIELD  M,  MAG,      short,                other mags,       millimags
+FIELD  Xm, MAG_CHI,  short,                chisq on mag
+FIELD  dM, MAG_ERR,  short,                scatter on mag
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-loneos.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-loneos.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-loneos.d	(revision 16632)
@@ -0,0 +1,8 @@
+STRUCT  SecFilt_Loneos
+EXTNAME DVO_SECFILT_LONEOS
+TYPE    BINTABLE
+SIZE    4
+
+# elements of data structure / FITS table
+FIELD  M,  MAG,      short,                other mags,       millimags
+FIELD  Xm, MAG_CHI,  short,                chisq on mag
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-panstarrs-dev-0.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-panstarrs-dev-0.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-panstarrs-dev-0.d	(revision 16632)
@@ -0,0 +1,13 @@
+STRUCT       SecFilt_Panstarrs_DEV_0
+EXTNAME      DVO_SECFILT_PANSTARRS_DEV_0
+TYPE         BINTABLE
+SIZE         16
+DESCRIPTION  DVO SecFilt : Secondary Filter Data 
+
+# elements of data structure / FITS table
+FIELD  M,     MAG,      float,                other mags,       mags
+FIELD  dM,    MAG_ERR,  float,                scatter on mag,   mags
+FIELD  Xm,    MAG_CHI,  short,                chisq on mag,     [100*log(value)]
+FIELD  Ncode, NCODE,    short,                number of detections in band
+FIELD  Nused, NUSED,    short,                number of detections used in average
+FIELD  dummy, JUNK,     short,                place holder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-panstarrs-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-panstarrs-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-panstarrs-dev-1.d	(revision 16632)
@@ -0,0 +1,13 @@
+STRUCT       SecFilt_Panstarrs_DEV_1
+EXTNAME      DVO_SECFILT_PANSTARRS_DEV_1
+TYPE         BINTABLE
+SIZE         16
+DESCRIPTION  DVO SecFilt : Secondary Filter Data 
+
+# elements of data structure / FITS table
+FIELD  M,     MAG,      float,                other mags,       mags
+FIELD  dM,    MAG_ERR,  float,                scatter on mag,   mags
+FIELD  Xm,    MAG_CHI,  short,                chisq on mag,     [100*log(value)]
+FIELD  Ncode, NCODE,    short,                number of detections in band
+FIELD  Nused, NUSED,    short,                number of detections used in average
+FIELD  dummy, JUNK,     short,                place holder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-ps1-dev-1.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-ps1-dev-1.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-ps1-dev-1.d	(revision 16632)
@@ -0,0 +1,13 @@
+STRUCT       SecFilt_PS1_DEV_1
+EXTNAME      DVO_SECFILT_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         16
+DESCRIPTION  DVO SecFilt : Secondary Filter Data 
+
+# elements of data structure / FITS table
+FIELD  M,     MAG,      float,                other mags,       mags
+FIELD  dM,    MAG_ERR,  float,                scatter on mag,   mags
+FIELD  Xm,    MAG_CHI,  short,                chisq on mag,     [100*log(value)]
+FIELD  Ncode, NCODE,    short,                number of detections in band
+FIELD  Nused, NUSED,    short,                number of detections used in average
+FIELD  dummy, JUNK,     short,                place holder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-ps1-dev-2.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-ps1-dev-2.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt-ps1-dev-2.d	(revision 16632)
@@ -0,0 +1,13 @@
+STRUCT       SecFilt_PS1_DEV_1
+EXTNAME      DVO_SECFILT_PS1_DEV_1
+TYPE         BINTABLE
+SIZE         16
+DESCRIPTION  DVO SecFilt : Secondary Filter Data 
+
+# elements of data structure / FITS table
+FIELD  M,     MAG,      float,                other mags,       mags
+FIELD  dM,    MAG_ERR,  float,                scatter on mag,   mags
+FIELD  Xm,    MAG_CHI,  short,                chisq on mag,     [100*log(value)]
+FIELD  Ncode, NCODE,    short,                number of detections in band
+FIELD  Nused, NUSED,    short,                number of detections used in average
+FIELD  dummy, JUNK,     short,                place holder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/secfilt.d	(revision 16632)
@@ -0,0 +1,13 @@
+STRUCT       SecFilt
+EXTNAME      DVO_SECFILT
+TYPE         BINTABLE
+SIZE         16
+DESCRIPTION  DVO SecFilt : Secondary Filter Data 
+
+# elements of data structure / FITS table
+FIELD  M,     MAG,      float,                other mags,       mags
+FIELD  dM,    MAG_ERR,  float,                scatter on mag,   mags
+FIELD  Xm,    MAG_CHI,  short,                chisq on mag,     [100*log(value)]
+FIELD  Ncode, NCODE,    short,                number of detections in band
+FIELD  Nused, NUSED,    short,                number of detections used in average
+FIELD  dummy, JUNK,     short,                place holder
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/smpdata.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/smpdata.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/smpdata.d	(revision 16632)
@@ -0,0 +1,19 @@
+# name of structure type
+STRUCT  SMPData
+EXTNAME SMPFILE
+TYPE    BINTABLE
+SIZE    44
+
+# elements of data structure / FITS table
+FIELD X,      X_PIX,      float,    x coord,              pixels
+FIELD Y,      Y_PIX,      float,    y coord,              pixels
+FIELD M,      MAG_RAW,    float,    inst mags,            mags
+FIELD dM,     MAG_ERR,    float,    inst mag error,       mags
+FIELD Mgal,   MAG_GAL,    float,    galaxy mag,           mags
+FIELD Map,    MAG_AP,     float,    aperture mag,         mags
+FIELD sky,    LOG_SKY,    float,    log-10 of sky,        cnts/sec
+FIELD fx,     FWHM_X,     float,    semi-major,           pixels
+FIELD fy,     FWHM_Y,     float,    semi-minor,           pixels
+FIELD df,     THETA,      float,    ellipse angle,        degrees
+FIELD dophot, DOPHOT,     char,     dophot type,          none
+FIELD dummy,  DUMMY,      char[3],  padding,              none
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/spectrum-ascii.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/spectrum-ascii.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/spectrum-ascii.d	(revision 16632)
@@ -0,0 +1,29 @@
+# name of structure type
+STRUCT  SpectrumASCII
+EXTNAME SPECTRUM
+TYPE    TABLE
+SIZE    262
+
+# elements of data structure / FITS table
+FIELD filename,   FILENAME,   char[32],    filename in db,        
+FIELD pathname,   PATHNAME,   char[64],    fullpath in db,        
+FIELD instrument, INSTRUMENT, char[16],    instrument,            
+FIELD telescope,  TELESCOPE,  char[16],    telescope,             
+FIELD objname,    OBJNAME,    char[16],    object name,           
+FIELD extname,    EXTNAME,    char[16],    extname in file,       
+
+FIELD ra,         RA,         float[10.6], ra,                    degrees
+FIELD dec,        DEC,        float[10.6], dec,                   degrees
+FIELD exptime,    EXPTIME,    float[6.1],  exposure time,         seconds
+FIELD airmass,    AIRMASS,    float[5.3],  airmass,               none
+FIELD Ws,         Ws,         float[7.2],  spectral range start,  Angstrom
+FIELD We,         We,         float[7.2],  spectral range end,    Angstrom
+FIELD dW,         dW,         float[7.2],  spectral resolution,   Angstrom / pix
+	       			      
+FIELD Nspec,      NSPECTRA,   int[3],      number of spectra,     none
+FIELD obstime,    OBS_TIME,   char[20],    time of measurement,   yyyy/mm/dd
+FIELD regtime,    REG_TIME,   char[20],    time of registration,  yyyy/mm/dd
+	       			      
+FIELD mode,       MODE,       int[2],      phu/mef/ext,           
+FIELD state,      STATE,      int[2],      raw/wav/flx/etc,       
+FIELD flag,       FLAG,       int[3],      status flags,          
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/def/spectrum.d
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/def/spectrum.d	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/def/spectrum.d	(revision 16632)
@@ -0,0 +1,31 @@
+STRUCT  Spectrum
+EXTNAME SPECTRUM_DATABASE
+TYPE    BINTABLE
+SIZE    216
+
+# elements of data structure / FITS table
+	       			      
+FIELD ra,         RA,         float,     ra,                    degrees
+FIELD dec,        DEC,        float,     dec,                   degrees
+FIELD exptime,    EXPTIME,    float,     exposure time,         seconds
+FIELD airmass,    AIRMASS,    float,     airmass,               
+FIELD Ws,         Ws,         float,     spectral range start,  Angstrom
+FIELD We,         We,         float,     spectral range end,    Angstrom
+FIELD dW,         dW,         float,     spectral resolution,   Angstrom / pix
+	       			      
+FIELD Nspec,      NSPECTRA,   int,       number of spectra,     
+FIELD obstime,    OBS_TIME,   int,       time of measurement,   seconds since 1 Jan 1970 UT
+FIELD regtime,    REG_TIME,   int,       time of registration,  seconds since 1 Jan 1970 UT
+	       			      
+FIELD mode,       MODE,       char,      phu/mef/ext           
+FIELD state,      STATE,      char,      raw/wav/flx/etc       
+FIELD flag,       FLAG,       char,      status flags
+FIELD extra,      EXTRA,      char[13],  room for expansion
+
+FIELD pathname,   PATHNAME,   char[64],  fullpath in db
+FIELD filename,   FILENAME,   char[32],  filename in db
+FIELD extname,    EXTNAME,    char[16],  extname in file,       
+
+FIELD instrument, INSTRUMENT, char[16],  instrument,            
+FIELD telescope,  TELESCOPE,  char[16],  telescope,             
+FIELD objname,    OBJNAME,    char[16],  object name,           
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,44 @@
+
+- libautocode 1.5
+  * converted to gfits APIs (forces libfits 1.6)
+  * fixed comma errors in average tables
+
+- libautocode 1.4
+  * added average-pmtest.d
+  * added autocode.tex, tex interpretation
+  * added proper-motion, etc to Stars.d
+  * added proper-motion, etc to average.d
+  * DESCRIPTION element for tex tables
+
+- libautocode 1.3
+  * added SkyRegion.d
+  * added AddstarClientOptions
+  * fixed e_void ptr in generate
+  * cleaned up signed/unsigned inconsistencies
+
+libautocode-1-2
+  added support for Comm functions (Send/Recv structure)
+  changed internal precision to doubles (RA/DEC) and floats (MAG)
+  dropped all internal millimag representations
+  made panstarrs format higher precisions than elixir
+  added the following new structures to support multiple data formats:
+     average-elixir
+     image-ascii
+     image-elixir
+     image-loneos
+     image-panstarrs
+     measure-elixir
+     measure-panstarrs
+     secfilt-elixir
+     secfilt-loneos
+     secfilt-panstarrs
+  added these structures for addstar client/server comms
+     AddstarClientOptions
+     GSCRegion
+     Stars
+
+libautocode-1-1
+  added the measure, average entries to autocode tables
+
+libautocode-1-0
+  import to CVS
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/doc/autocode.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/doc/autocode.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/doc/autocode.txt	(revision 16632)
@@ -0,0 +1,71 @@
+
+This directory contains a collection of autocoded FITS I/O routines
+used to define FITS Table DB functions.  
+
+The autocoder program is a perl script 'generate'.  This scripts takes
+as input a schema file and a template source code file, and produces
+an output file from these two inputs.  A single schema file is meant
+to be associated with a single data concept which is being coded.  For
+example, in the case of the FITS DB tables, a single schema file
+defines a single FITS table, or equivalently, a single C structure
+representing a row in that FITS table.
+
+Schema File
+
+The schema file currently consists of two types of information.
+
+First, there are simple keyword / name pairs which the autocoder
+simply applies as a direct replacement anywhere in the template.  For
+example, the keyword NAME replaces any instance of "$NAME" in the
+template with the corresponding value.  
+
+Second, there is a special type of keyword: FIELD.  The FIELD entry
+defines an entry in the data structure.  The FIELD entry is followed
+by the following comma-separated pieces of information:
+
+- the element name
+- the element data type
+- the element description
+- the element physical unit
+
+Template File
+
+The template file is a source code in whatever language is desired.
+Within the template, the defined keywords may be used as desired,
+wherever needed.  In addition, there are special directives which
+invoke additional special behavior.  All special directives have the
+form of comments within their target language.  They are replaced with
+a block of code in that target language, normally one which iterates
+over the FIELD elements of the schema file.  As such, the directive
+appropriate for one language should not be used within code for a
+different language.  Here is a list of existing special directives:
+
+/** STRUCT DEFINITION **/
+
+This tells the autocoder to create a structure definition for the
+schema.  The structure definition creates a structure with elements
+based on the FIELD entries, with the name $NAME (NOTE: this is perhaps
+making too much of an assumption.  we could require the template to
+provide the wrapper: "typedef struct { } $NAME;" and have the
+autocoder only insert the field lines).  
+
+/** TABLE DEFINITION **/
+
+This tells the autocoder to output the lines which add a column to an
+exiting empty table.  The assumption is that the template contains
+code to initialize a table.  It then invokes the table definition
+code, which defines each of the appropriate columns.  This is perhaps
+followed by some code which finalizes the table definition.  (Note:
+the code output by the autocoder in this block is not very flexible:
+it the current example, it explicitly uses the Elixir FITS Table
+functions, and refers to some data elements in the template code.  The
+latter could possibly be more abstracted with the keyword / value
+pairs, but in any case, the autocoded lines will have to be
+constructed somewhat by hand for a specific API set.
+
+/** BYTE SWAP **/
+
+This tells the autocoder to output code defining the byte swaps
+appropriat to the data structure.  Again, the resulting code depends a
+bit on the intended use and API set.
+
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/doc/notes.txt	(revision 16632)
@@ -0,0 +1,138 @@
+
+FITS I/O APIs
+
+  - I/O to a binary FITS table
+  - one extension per file?
+  - no locking
+  - always read/write to/from matched structure
+  - user needs to supply idiosyncratic conversions
+
+  - basic APIs:
+    - fits_read_datatable_NAME
+    - fits_write_datatable_NAME
+    - fits_IO_convert_NAME
+    - fits_fread_datatable_NAME
+    - fits_fwrite_datatable_NAME
+
+FITS db APIs
+
+Basic Rules:
+
+  - All db files are Binary FITS tables
+  - There is only one extension per file
+  - The PHU contains basic information like status & date
+  - There is no data array for the PHU (NAXIS = 0)
+
+typedef struct {
+  FILE *f;
+  char *filename;
+  Header header;
+  FTable ftable;
+  int Nrows;
+  int Ncols;
+  int Nbyte;
+  int lockstate;
+  int lockreq;
+  NAME *data;
+} NAME_DB;
+
+NAME_DB *NAME_DB_Init (NAME_DB *db);
+
+  - 
+
+NAME_DB *NAME_DB_Load (char *filename, int lockreq);
+
+  - lock the database file
+  - load PHU
+  - load the header
+  - validate the EXTNAME
+  - validate the header
+  - load the data into ftable
+  - convert to memory format
+
+  * if SOFT & database file does not exist (file is empty), 
+    - return structure w/ 0 entries
+
+  * if HARD & database file does not exist (file is empty), 
+    - open, lock, return structure w/ 0 entries
+
+  * if database file cannot be locked
+    - return an error (NULL)
+
+  * if header does not validate: 
+    - unlock file
+    - return an error (NULL)
+
+NAME_DB *NAME_DB_Loadset (char *filename, int lockreq, int start, int Nrows);
+
+  - lock the database file
+  - load PHU
+  - load the header
+  - validate the EXTNAME
+  - validate the header
+  - load the data into vtable
+  - convert to memory format
+
+  * if database file does not exist (file is empty), 
+    - open, lock, return structure w/ 0 entries
+  * if requested entries don't exist
+    - unlock file
+    - return an error (NULL)
+
+NAME_DB *NAME_DB_Save ();
+
+  - if Nrows = 0, delete the file
+
+  - write PHU
+  - write header
+  - write ftable
+
+  - if vtable: 
+    - update 
+  - if ftable: 
+    - update 
+
+NAME_DB *NAME_DB_Saveset ();
+
+  - if Nrows = 0, delete the file
+
+  - write PHU
+  - write header
+  - write ftable
+
+  - if vtable: 
+    - update 
+  - if ftable: 
+    - update 
+
+NAME_DB *NAME_DB_Free ();
+
+  - unlock file
+
+
+---
+
+DVO tables
+
+I am converting all DVO tables to have an internal representation of
+the table with the necessary precision (ie, double for RA & DEC, etc),
+and a set of external representations in which the precision and
+available columns are truncated to fit a specific representation.  the
+autocode tables then include the internal name (ie, measure.d) and the
+external versions (ie, measure-elixir.d, etc).  
+
+To pursue this, I have modifed the definion of measure.d to replace,
+eg, dR with dR_PS.  I am now compiling all of ohana and looking for
+places where the new name is needed in the code, stopping the
+compilation.  (In the process, I am being forced to clean up the
+relphot - at least - coding problems: unused variables, undeclared
+functions, etc).  After I have made the changes, I will search for all
+instances of dR_PS and return them to their original.
+
+The only things to watch for in this process are units for the
+values.  In the older code, the value of measure.dR was interpreted as
+1/100th of an arcsec.  Everywhere this was the interpretation must be
+changed to make the value represent 1 arcsec.  This will also be an
+issue for the internal magnitude representations, which all use
+millimags...
+
Index: /branches/eam_branch_20080223/Ohana/src/libautocode/generate
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libautocode/generate	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libautocode/generate	(revision 16632)
@@ -0,0 +1,384 @@
+#!/usr/bin/env perl
+
+$VERBOSE = 0;
+if ($ARGV[0] eq "-v") { $VERBOSE = 1; shift @ARGV; }
+if (@ARGV != 3) { die "generate (schema) (template) (output)\n"; }
+
+$schema   = $ARGV[0];
+$template = $ARGV[1];
+$output   = $ARGV[2];
+
+&parse_schema;
+&parse_template;
+exit 0;
+
+sub parse_schema {
+    open (FILE, "$schema");
+    @list = <FILE>;
+    close (FILE);
+
+    $NAME    = "";
+    $FILE    = "";
+    $Nfield  = 0;
+    $TIMEOUT = 0;
+
+    &init_key ("DESCRIPTION");
+    &init_key ("TIMEOUT");
+    &init_key ("EXTNAME");
+    &init_key ("STRUCT");
+    &init_key ("NAME");
+    &init_key ("FILE");
+    &init_key ("SIZE");
+    &init_key ("TYPE");
+
+    foreach $line (@list) {
+	chop $line;
+	($key, $value) = split (" ", $line, 2);
+	
+	# strip white space from the following
+	if ($key eq "TYPE")    { ($value) = $value =~ m|\s*(\S+)\s*|; }
+	if ($key eq "SIZE")    { ($value) = $value =~ m|\s*(\S+)\s*|; }
+	if ($key eq "STRUCT")  { ($value) = $value =~ m|\s*(\S+)\s*|; }
+	if ($key eq "EXTNAME") { ($value) = $value =~ m|\s*(\S+)\s*|; }
+
+	&set_keypair ($key, $value);
+
+	# these are used internally (not just a replacement)
+	if ($key eq "TYPE")    { $TYPE = $value;   }
+	if ($key eq "SIZE")    { $SIZE = $value;   }
+	if ($key eq "STRUCT")  { $STRUCT = $value; }
+
+	# not a simple key/value entry
+ 	if (($key eq "FIELD") || ($key eq "SUBSTRUCT") || ($key eq "SUBFIELD")) {
+	    ($element, $field, $format, $comment, $unit) = split (/,\s+/, $value, 5);
+	    if ($VERBOSE) { printf "%-20s %-20s %-15s %-35s %-10s\n", $element, $field, $format, $comment, $unit; }
+	    push @element, $element;
+	    push @field,   $field;
+	    push @format,  $format;
+	    push @comment, $comment;
+	    push @unit,    $unit;
+	    push @mode,    $key;
+	}
+    }
+    $Nexpect = 0;
+    if ($TYPE eq "BINTABLE") { $Nexpect = &count_bintablesize; }
+    if ($TYPE eq "TABLE")    { $Nexpect = &count_tablesize;    }
+    if (! $Nexpect) { die "missing valid TYPE\n"; }
+    if ($Nexpect != $SIZE) { die "size mismatch: $Nexpect vs $SIZE\n"; }
+}
+
+sub parse_template {
+    open (FILE, $template);
+    @list = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$output");
+
+    foreach $line (@list) {
+	
+	&check_keypairs;
+
+	print FILE $line;
+
+	# fill in structure
+	if ($line =~ m|/\*\* STRUCT DEFINITION \*\*/|) {
+	    &write_structure;
+	}
+
+	# fill in latex table description
+	if ($line =~ m|%%% LATEX TABLE DEFINITION|) {
+	    &write_latex;
+	}
+
+	# fill in structure
+	if ($line =~ m|/\*\* TABLE DEFINITION \*\*/|) {
+	    if ($TYPE eq "BINTABLE") { &write_bintabledefs; }
+	    if ($TYPE eq "TABLE")    { &write_tabledefs; }
+	}
+
+	# fill in swaps
+	if ($line =~ m|/\*\* BYTE SWAP \*\*/|) {
+	    &write_byteswaps;
+	}
+    }
+    close (FILE);
+}
+
+sub write_bintabledefs {
+
+    for ($i = 0; $i < @field; $i++) {
+	# skip SUBSTRUCT type of entries:
+	if ($mode[$i] eq "SUBSTRUCT") { next; }
+
+	($type, $Np) = &get_type_array ($format[$i]);
+	
+	# rawshort is a short without byteswapping
+
+	$pt1 = 0;
+	if ($type eq "char")          { $pt1 = "A"; }
+	if ($type eq "byte")   	      { $pt1 = "B"; }
+	if ($type eq "unsigned char") { $pt1 = "B"; }
+	if ($type eq "rawshort")      { $pt1 = "I"; }
+	if ($type eq "short")  	      { $pt1 = "I"; }
+	if ($type eq "unsigned short"){ $pt1 = "I"; }
+	if ($type eq "int")    	      { $pt1 = "J"; }
+	if ($type eq "unsigned int")  { $pt1 = "J"; }
+	if ($type eq "e_time") 	      { $pt1 = "J"; }
+	if ($type eq "float")  	      { $pt1 = "E"; }
+	if ($type eq "double") 	      { $pt1 = "D"; }
+
+	if ($type eq "e_void") 	      { $pt1 = "B"; $Np = 8*$Np; }
+	# e_void is a 64 bit pointer, cast to size_t.  its value is not loaded
+	# from the table.
+
+	if (!$pt1) { die "unknown type $type"; }
+
+	if ($Np == 1) {
+	    $pt2 = $pt1;
+	} else {
+	    $pt2 = sprintf "%d%s", $Np, $pt1;
+	}
+
+	printf FILE "  gfits_define_bintable_column (header, ";
+	printf FILE "%-8s",               "\"$pt2\", ";
+	printf FILE "%-20s",              "\"$field[$i]\", ";
+	printf FILE "%-35s",              "\"$comment[$i]\", ";
+	printf FILE "%-20s 1.0, 0.0);\n", "\"$unit[$i]\", ";
+    }
+
+}
+
+sub write_latex {
+
+    for ($i = 0; $i < @field; $i++) {
+	# skip SUBSTRUCT type of entries:
+	if ($mode[$i] eq "SUBSTRUCT") { next; }
+
+	($type, $Np) = &get_type_array ($format[$i]);
+
+	if ($type eq "e_time") 	      { $type = "unsigned int"; }
+
+	# print STDOUT "$field[$i] .. $type[$i] .. $comment[$i] .. $unit[$i]\n";
+
+        printf FILE "%-20s & ",       "\\code{$field[$i]} ";
+	printf FILE "%-20s & ",       "$type";
+	printf FILE "%-35s & ",       "$comment[$i]";
+	printf FILE "%-20s \\\\ \n",  "$unit[$i]";
+    }
+}
+
+sub get_type_array {
+    
+    my ($format) = $_[0];
+    my ($type);
+    my ($Np, $N1, $N2, $N3);
+
+    $type = $N1 = $N2 = $N3 = $Np = 0;
+    if (!$type) {
+	($type, $N1, $N2, $N3) = $format =~ m|^(.w+)\[(\d+)\]\[(\d+)\]\[(\d+)\]|;
+	$Np = $N1*$N2*$N3;
+    }
+    if (!$type) {
+	($type, $N1, $N2)      = $format =~ m|^(.+)\[(\d+)\]\[(\d+)\]|;
+	$Np = $N1*$N2;
+    } 
+    if (!$type) {
+	($type, $N1)           = $format =~ m|^(.+)\[(\d+)\]|;
+	$Np = $N1;
+    }
+    if (!$type) { 
+	$type                  = $format; 
+	$Np = 1;
+    }
+    # print "type: $type, Np: $Np\n";
+    if ($Np == 0) { die "syntax error in format/array\n"; }
+    return ($type, $Np);
+}
+
+sub write_tabledefs {
+
+    for ($i = 0; $i < @field; $i++) {
+	# skip SUBSTRUCT type of entries:
+	if ($mode[$i] eq "SUBSTRUCT") { next; }
+
+	($type, $N1, $N2)      = $format[$i] =~ m|^(\w+)\[(\d+)\]\[(\d+)\]|;
+	if ($N2) { die "ASCII table cannot have multi-valued column"; }
+
+	($type, $length) = $format[$i] =~ m|^(\w+)\[([\d\.]+)\]|;
+	if (!$type && !$length) { die "format must be specified for ASCII table"; }
+
+	$pt1 = 0;
+	if ($type eq "char")   	      { $pt1 = sprintf "A%s", $length; }
+	if ($type eq "byte")   	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "unsigned char") { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "rawshort")      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "short")  	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "unsigned short"){ $pt1 = sprintf "I%s", $length; }
+	if ($type eq "int")    	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "unsigned int")  { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "e_time") 	      { $pt1 = sprintf "I%s", $length; }
+	if ($type eq "float")  	      { $pt1 = sprintf "F%s", $length; }
+	if ($type eq "double") 	      { $pt1 = sprintf "F%s", $length; }
+
+	if ($type eq "e_void") 	      { $pt1 = sprintf "I%s", $length; }
+
+	if (!$pt1) { die "unknown type $type"; }
+
+	printf FILE "  gfits_define_table_column (header, ";
+	printf FILE "%-8s",      "\"$pt1\", ";
+	printf FILE "%-20s",     "\"$field[$i]\", ";
+	printf FILE "%-35s",     "\"$comment[$i]\", ";
+	printf FILE "%-20s);\n", "\"$unit[$i]\"";
+    }
+
+}
+
+sub write_structure {
+    print FILE "typedef struct {\n";
+    for ($i = 0; $i < @element; $i++) {
+	# skip SUBFIELD entries
+	if ($mode[$i] eq "SUBFIELD") { next; }
+
+	# here we only want to match the pattern [1][2][3]..[N]
+	($type, $array) = $format[$i] =~ m|^(\w+)(\[.*\])|;
+	# print "type: $type, array: $array\n";
+	if (!$type && !$array) { $type = $format[$i]; }
+
+	if ($array && (($TYPE eq "BINTABLE") || ($type eq "char"))) {
+	    $pt2 = sprintf "%s%s;", $element[$i], $array;
+	} else {
+	    $pt2 = sprintf "%s;", $element[$i];
+	}
+
+	if ($unit[$i] eq "") {
+	    $pt3 = sprintf "// %s", $comment[$i];
+	} else {
+	    $pt3 = sprintf "// %s (%s)", $comment[$i], $unit[$i];
+	}
+	printf FILE "  %-16s %-21s %s\n", $type, $pt2, $pt3;
+    }    
+    print FILE "} $STRUCT;\n";
+}
+
+# this does not work with ASCII tables, 
+# but should not be needed for ASCII tables!
+sub write_byteswaps {
+    if ($TYPE eq "TABLE") {
+	printf FILE "/*** no byteswaps for ASCII tables ***/\n";
+	return;
+    }
+    $N = 0;
+    for ($i = 0; $i < @field; $i++) {
+	# skip SUBSTRUCT type of entries:
+	if ($mode[$i] eq "SUBSTRUCT") { next; }
+
+	($type, $Np) = &get_type_array ($format[$i]);
+
+	# rawshort is a patch for old photreg tables: provide a fix for the tables
+	# some photreg tables were not byteswapped for certain columns
+
+	$n = 0;
+	if ($type eq "char") 	      { $N +=   $Np; next; }
+	if ($type eq "byte") 	      { $N +=   $Np; next; }
+	if ($type eq "unsigned char") { $N +=   $Np; next; }
+	if ($type eq "rawshort")      { $N += 2*$Np; next; }
+	if ($type eq "short")  	      { $T = "BYTE"; $n = 2; }
+	if ($type eq "unsigned short"){ $T = "BYTE"; $n = 2; }
+	if ($type eq "int")    	      { $T = "WORD"; $n = 4; }
+	if ($type eq "unsigned int")  { $T = "WORD"; $n = 4; }
+	if ($type eq "e_time") 	      { $T = "WORD"; $n = 4; }
+	if ($type eq "e_void") 	      { $T = "DBLE"; $n = 8; }
+	if ($type eq "float")  	      { $T = "WORD"; $n = 4; }
+	if ($type eq "double") 	      { $T = "DBLE"; $n = 8; }
+	if (!$n) { die "unknown type $type"; }
+	for ($j = 0; $j < $Np; $j++) {
+	    printf FILE "    SWAP_%s (%d); // %s\n", $T, $N, $field[$i];
+	    $N += $n;
+	}
+    }
+}
+
+sub count_bintablesize {
+
+    $Nbytes = 0;
+    for ($i = 0; $i < @field; $i++) {
+	# skip SUBSTRUCT type of entries:
+	if ($mode[$i] eq "SUBSTRUCT") { next; }
+
+	# add [\d\.] to match ascii-type formats
+	($type, $Np) = &get_type_array ($format[$i]);
+
+	$valid = 0;
+	if ($type eq "char")   	       { $Nbytes += 1*$Np; $valid = 1; }
+	if ($type eq "byte")   	       { $Nbytes += 1*$Np; $valid = 1; }
+	if ($type eq "unsigned char")  { $Nbytes += 1*$Np; $valid = 1; }
+	if ($type eq "rawshort")       { $Nbytes += 2*$Np; $valid = 1; }
+	if ($type eq "short")  	       { $Nbytes += 2*$Np; $valid = 1; }
+	if ($type eq "unsigned short") { $Nbytes += 2*$Np; $valid = 1; }
+	if ($type eq "int")    	       { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "unsigned int")   { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "e_time") 	       { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "e_void") 	       { $Nbytes += 8*$Np; $valid = 1; }
+	if ($type eq "float")  	       { $Nbytes += 4*$Np; $valid = 1; }
+	if ($type eq "double") 	       { $Nbytes += 8*$Np; $valid = 1; }
+	if (!$valid) { die "unknown type $type"; }
+    }
+    return ($Nbytes);
+}
+
+sub count_tablesize {
+
+    $Nbytes = 0;
+    for ($i = 0; $i < @field; $i++) {
+	# skip SUBSTRUCT type of entries:
+	if ($mode[$i] eq "SUBSTRUCT") { next; }
+
+	($fpt) = $format[$i] =~ m|^\w+\[([\d\.]+)\]|;
+	$length = int($fpt);
+	# print "$format[$i], $length, $fpt\n";
+	if ($length == 0) { die "ASCII table format requires field size"; }
+	$Nbytes += $length;
+    }
+    return ($Nbytes);
+}
+
+sub init_key {
+    my ($key)   = $_[0];
+
+    push @key, $key;
+    push @value, "";
+}
+
+sub set_keypair {
+    my ($i);
+    my ($key)   = $_[0];
+    my ($value) = $_[1];
+
+    for ($i = 0; $i < @key; $i++) {
+	if ($key eq $key[$i]) {
+	    if ($value[$i] ne "") { die "key is multiply defined\n"; }
+	    $value[$i] = $value;
+	    return;
+	}
+    }
+}
+
+sub check_keypairs {
+    my ($i);
+    for ($i = 0; $i < @key; $i++) {
+	# if ($VERBOSE) { print "$key[$i]  -- $value[$i]\n"; }
+	if ($line =~ m|\$$key[$i]|) {
+	    if ($value[$i] eq "") { die "missing value for required key $key[$i]\n"; }
+	    $line =~ s|\$$key[$i]|$value[$i]|g;
+	}
+    }
+}
+
+# we need to find the structure size, including padding 
+# i'm not sure I know the answer to this: it is probably 
+# the total number of bytes rounded up to the largest 
+# data item in the structure (ie, 8 for a double, etc)
+# if we have the size, then we can double check the structure
+# against the expectation at runtime.  for the moment,
+# calculate by hand and add to def.d file 
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+lib
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/Makefile	(revision 16632)
@@ -0,0 +1,116 @@
+default: install
+help:
+	@echo "make options: install libdvo clean dist"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/libdvo
+AUTO	=	$(ROOT)/src/libautocode
+LIB	= 	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	=	$(HOME)/include
+ASRC	=	$(AUTO)/src
+AINC	=	$(AUTO)/include
+ADEF	=	$(AUTO)/def
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS) -lFITS -lohana
+
+default: install
+install: $(DESTLIB)/libdvo.a $(DESTLIB)/libdvo.$(DLLTYPE)
+libdvo: $(LIB)/libdvo.$(ARCH).a $(LIB)/libdvo.$(ARCH).$(DLLTYPE)
+
+DEFS = \
+$(DESTINC)/loneos_defs.h \
+$(DESTINC)/elixir_defs.h \
+$(DESTINC)/panstarrs_dev_0_defs.h \
+$(DESTINC)/panstarrs_dev_1_defs.h \
+$(DESTINC)/ps1_dev_1_defs.h
+
+INCS = $(DEFS) $(DESTINC)/dvo.h $(DESTINC)/autocode.h
+
+OBJS = \
+$(SRC)/version.$(ARCH).o	 \
+$(SRC)/coordops.$(ARCH).o	 \
+$(SRC)/dvosorts.$(ARCH).o	 \
+$(SRC)/dvo_photcode_ops.$(ARCH).o \
+$(SRC)/dvo_photcode_convert_elixir.$(ARCH).o \
+$(SRC)/dvo_photcode_convert_ps1_dev_1.$(ARCH).o \
+$(SRC)/dvo_photcode_ops.$(ARCH).o \
+$(SRC)/LoadPhotcodes.$(ARCH).o   \
+$(SRC)/LoadPhotcodesText.$(ARCH).o   \
+$(SRC)/LoadPhotcodesFITS.$(ARCH).o   \
+$(SRC)/SavePhotcodesText.$(ARCH).o   \
+$(SRC)/SavePhotcodesFITS.$(ARCH).o   \
+$(SRC)/imreg_datatypes.$(ARCH).o \
+$(SRC)/mosaic_astrom.$(ARCH).o   \
+$(SRC)/fits_db.$(ARCH).o	 \
+$(SRC)/photfits.$(ARCH).o        \
+$(SRC)/dvo_image.$(ARCH).o       \
+$(SRC)/dvo_image_raw.$(ARCH).o   \
+$(SRC)/dvo_catalog.$(ARCH).o     \
+$(SRC)/dvo_catalog_raw.$(ARCH).o       \
+$(SRC)/dvo_catalog_mef.$(ARCH).o       \
+$(SRC)/dvo_catalog_split.$(ARCH).o     \
+$(SRC)/dvo_catalog_create.$(ARCH).o    \
+$(SRC)/dvo_catalog_chipcoords.$(ARCH).o \
+$(SRC)/dvo_convert.$(ARCH).o           \
+$(SRC)/dvo_convert_elixir.$(ARCH).o    \
+$(SRC)/dvo_convert_loneos.$(ARCH).o    \
+$(SRC)/dvo_convert_panstarrs_DEV_0.$(ARCH).o \
+$(SRC)/dvo_convert_panstarrs_DEV_1.$(ARCH).o \
+$(SRC)/dvo_convert_PS1_DEV_1.$(ARCH).o \
+$(SRC)/skyregion_io.$(ARCH).o    \
+$(SRC)/skyregion_gsc.$(ARCH).o    \
+$(SRC)/skyregion_ops.$(ARCH).o
+
+# $(SRC)/dvo_convert_panstarrs.$(ARCH).o \
+# $(SRC)/dvo_convert_pmtest.$(ARCH).o \
+
+include ../libautocode/Makefile.Targets
+
+$(OBJS): $(INCS)
+
+$(LIB)/libdvo.$(ARCH).a:  $(AOBJS) $(OBJS)
+$(LIB)/libdvo.$(ARCH).$(DLLTYPE): $(AOBJS) $(OBJS)
+
+$(DESTLIB)/libdvo.a:  $(LIB)/libdvo.$(ARCH).a
+$(DESTLIB)/libdvo.$(DLLTYPE): $(LIB)/libdvo.$(ARCH).$(DLLTYPE)
+
+# dependency rules for the autocode files
+
+$(AOBJS): $(ADEF)/autocode.c $(DESTINC)/autocode.h
+
+$(DESTINC)/autocode.h: $(AINC)/autocode.h
+	@if [ ! -d $(DESTINC) ]; then mkdir -p $(DESTINC); fi
+	rm -f $@
+	cp $< $@
+
+$(AINC)/autocode.h: $(AINCS) $(ADEF)/autocode.h $(ADEF)/common.h
+	@echo "make $@ from $^"
+	cd $(AUTO) && make $@
+
+# generic rule for AINCS
+$(AINC)/%.h : $(ADEF)/%.d $(ADEF)/autocode.h $(ADEF)/common.h
+	@echo "make $@ from $^"
+	cd $(AUTO) && make $@
+
+# generic rule for ASRC
+$(ASRC)/%.c : $(ADEF)/%.d $(ADEF)/autocode.c $(AINC)/%.h
+	@echo "make $@ from $^"
+	cd $(AUTO) && make $@
+
+# generic rule for AOBJS
+$(ASRC)/%.$(ARCH).o : $(ASRC)/%.c
+	@echo "make $@ from $^"
+	cd $(AUTO) && make $@
+
+tabletest: install
+	gcc -L$(LIBDIR) -I$(INCDIR) -o tabletest $(SRC)/tabletest.c -ldvo -lFITS -lohana -lm
+
+clean: cleandef
+cleandef:
+	cd $(AUTO) && make clean
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,20 @@
+
+- libdvo 1.3 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+  * unified DVO APIs
+  * fixed DVO API naming (dvo_catalog..., dvo_image...)
+  * fixes to polynomial conversions in coords.c
+  * less restrictive ctypes for polynomials (coords.c)
+  * fixes to dvo locking strategy
+
+- libdvo 1.2
+  * added PMTEST format
+  * added dvo_image_lock,unlock functions
+  * fixes to the skyregion support
+  * dropped _PS from average.R,D,M
+  * fixed bug in coord interpretation of CROTA2
+  * fixed reallocation logic in skyregions
+
+- libdvo 1.1
+  * added skyregion support functions and structures
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-catalogs.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-catalogs.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-catalogs.txt	(revision 16632)
@@ -0,0 +1,70 @@
+
+// APIs related to the DVO catalogs:
+
+load_catalog (Catalog *catalog, int VERBOSE);
+
+dvo_catalog_lock (Catalog *catalog, int lockmode);
+// lockmode: SOFT, XCLD, HARD
+
+dvo_catalog_unlock (Catalog *catalog);
+
+dvo_catalog_load (Catalog *catalog, int VERBOSE, int mode);
+// format: INTERNAL, LONEOS, ELIXIR, PANSTARRS, PMTEST, etc.
+// layout: RAW, MEF, SPLIT
+// mode:   READ, WRITE
+
+// returns
+//   DVO_CAT_OPEN_FAIL:  failure to lock catalog
+//   DVO_CAT_OPEN_OK:    success: file is locked and opened
+//   DVO_CAT_OPEN_EMPTY: success: file is locked but empty
+
+ the catalog is opened and the data for each of the elements (average,
+ measure, etc) is loaded if requested.  Whether or not the data is
+ loaded, the values of catalog.Naves_disk,Naves_off,Naverage are set
+ to match the segment of data loaded.  this API always loads either
+ the entire data set, or none.  If none, the offset value is set to
+ point at the end of the table.
+
+dvo_catalog_save (Catalog *catalog, int VERBOSE);
+// format: INTERNAL, LONEOS, ELIXIR, PANSTARRS, PMTEST, etc.
+// layout: RAW, MEF, SPLIT
+// mode:   READ, WRITE
+
+dvo_catalog_init (Catalog *catalog);
+
+dvo_catalog_create (Catalog *catalog);
+
+dvo_catalog_check (Catalog *catalog, int Nsecfilt, int extend);
+// check an existing catalog against the identified Nsecfilt value
+// if (Nsecfilt == catalog[0].Nsecfilt) OK
+// if (Nsecfilt <  catalog[0].Nsecfilt) ERROR
+// if (Nsecfilt >  catalog[0].Nsecfilt) && extend) extend
+// if (Nsecfilt >  catalog[0].Nsecfilt) && !extend) ERROR
+
+
+several possible cases:
+
+- open and read an existing catalog / create if missing
+- open and read an existing catalog / error if missing (can be ignored)
+
+dvo_catalog_open (Catalog *catalog, int mode); 
+
+dvo_catalog_load_segment_average (Catalog *catalog, int start, int Nrows)
+
+ this function reads in the requested number of rows from the catalog
+ for the Average and SecFilt tables only.  It is possible within the
+ DVO framework to examine the average values in slices.  
+
+dvo_catalog_load_segment_measure (Catalog *catalog, int start, int Nrows)
+
+ this function reads in the requested number of rows from the catalog
+ for the Measure table only.  It is not guaranteed to be possible to
+ examine the measure values in slices if reference is needed to their
+ average values.
+
+dvo_catalog_load_segment_missing (Catalog *catalog, int start, int Nrows)
+
+ this function reads in the requested number of rows from the catalog
+ for the Missing table only.  It is not guaranteed to be possible to
+ examine the missing values in slices if reference is needed to their
+ average values.
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-images.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-images.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-images.txt	(revision 16632)
@@ -0,0 +1,7 @@
+
+the dvo image table is not extremely efficient.  it is unsorted, and
+spatial searches consist of complete scans of the table.
+
+a spatial index could consist of five cardinal points for each square
+image (4 corners and the center) or a central point and max radius.
+table would consist each would be
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-int-nan.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-int-nan.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-int-nan.txt	(revision 16632)
@@ -0,0 +1,14 @@
+
+we have a variety of data fields which use char, short, int or long as
+a data type.  we need a value which can mean NAN in that context.
+these are defined in dvo.h as elements of the enum DVO_INT_NAN.  
+
+2007.11.07 : I am going through the code base and replacing the
+        deprecated values NO_ERR and NO_MAG with their equivalent
+        DVO_INT_NAN names.  At the same time, where ever the internal
+        value is a float or double, these must be converted to real
+        NAN values.  These may once have used char, short, or int
+        internally, and were not updated correctly.  
+
+	* watch out for Xm : PhotXm returns -1, not NAN for invalid entry,
+	  secfilt.Xm is short (use NAN_S_SHORT?)
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-structures.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-structures.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/doc/dvo-structures.txt	(revision 16632)
@@ -0,0 +1,178 @@
+
+2008.01.31
+
+  For testing the quality of the extended source measurements, I need
+  to include them somehow within DVO.  My plan is to have a set of
+  extended source tables linked to the average tables, parallel to the
+  measure tables.  One issue is: how many rows in this table?  I think
+  I need to have room for all fields measured by psphot  Another
+  question: do I use a fixed layout I/O file, or do I use the header
+  to read only the columns of interest.  I can do the latter, and it
+  is only a little slower.
+
+2007.02.22
+
+I have several DVO improvements to implement.  I need to plan them a
+bit carefully.  Here are my thoughts on these updates.
+
+- add chip X,Y to measure table
+
+  this is a fairly simple addition.  In addstar/find_matches, I just need
+  to assign the X,Y value from the incoming star data.  For loading
+  old catalogs which don't include X,Y in the table, I need to
+  calculate the X,Y position based on the R,D after finding the
+  matching image.  I have code to do this calculation currently in
+  dvo/photometry.c for looking up X,Y on the fly.  once this is moved
+  into the load functions, it will not be needed in photometry.c
+
+- remove PRI/SEC and only use secfilt table for mags
+
+  this is not a very difficult change, conceptually, but it may be a
+  fair amount of work.  all of the functions which currently switch on
+  the case of PRI/SEC just need to look in the secfilt location.  the
+  value of Nsec needs to increase by 1.  the load from tables which
+  used PRI/SEC need to move the PRI values to the correct location in
+  secfilt
+
+  eventually, rename 'secfilt' to a better name choice
+
+- add image, average, measure IDs
+
+  for PS1, the image and measure need to be generated by the external
+  software.  they would just be part of the input stream.  for the
+  case were the IDs are not supplied, DVO needs to generate them in a
+  unique way.  I probably need to understand / define that mechanism
+  before tackling this problem.
+
+  one point: I need to keep the old averef index.  how do this index
+  and the objID work together?
+
+- link measure to image
+
+  temporariliy use an index like averef?
+
+- move photcode table to catdir (also zero points)
+
+  should be fairly easy: just like the SkyTable, look in the catdir
+  first, then generate from the default text table if it is missing.
+
+- color term as a function of mosaic position
+ 
+- mextract field,field,field 
+
+  this should not be a very difficult job.  just add a loop to the
+  avextract / mextract functions.
+
+- mextract field(s) where condition
+
+  this is a bit trickier, and could make use of the code in the dvo
+  math functions
+
+- dvo select from mysql
+
+  not very difficult: need to define the commands to select the
+  database and set up a connection, then parse the select line into
+  the appropriate format.  just need to as the db for the type of the
+  fields that are requested: must be numerical.
+
+  select field,field,field from table where condition
+
+- change vectors to doubles
+
+  probably not a terrible job.  this will depend on how the union is
+  defined.  I don't want this to explode the size of an image!
+
+---------
+
+I now have the ability to load and save DVO databases in old formats,
+with automatic conversion to the current 'internal' representations
+for the average, measure, and image tables.  an important concern with
+this process is ensuring that we track the old layout names and avoid
+breaking existing databases.  Here is a list of old databases, some of
+which may not have been written with the right names, or with
+inaccurate names.  these can be fixed by setting the FORMAT and MODE
+header keywords with the 'fits_insert' command:
+
+- LONEOS : old-style cmp files (ie, RAW), with the 'LONEOS' format.
+- CFHT Elixir databases: cmp files, ELIXIR format
+- Brandon's Taurus db: incorrect 'PANSTARRS' format, should be called
+  'PSTEST1'.  drop support for this eventually? have brandon migrate to
+  the new panstarrs formats?
+
+I am going to use the following naming convention for future db table
+updates:
+
+- PANSTARRS.DEV.0, PANSTARRS.DEV.1, etc
+- PANSTARRS.PS1.0, PANSTARRS.PS1.1, etc
+- PANSTARRS.PS4.0, PANSTARRS.PS4.1, etc
+
+The next version of the DVO format needs several major changes:
+
+  - unique IDs in the measure and average tables.
+  - reference to the source image in the measure table.
+  - chip X,Y coordinates and errors in the measure table
+
+  - remove primary average magnitude from average.d and only use
+    the secfilt.d table for the average magnitudes
+
+These are fairly substantial modifications.  Can I do these changes on
+an appropriate timescale to get Dave Monet working with relastro?  Is
+it necessary to do these all at once?
+
+------
+
+DVO has undergone at least two bit-incompatible versions of the data
+structures to date: the 'loneos' version and the 'elixir' version.  
+
+the 'loneos' version was used for the loneos database currently still
+in my dataspace.
+
+the 'elixir' version, which extended some of the structures and added
+the Secfilt concept, was added at CFHT and is used for all of the
+existing CFHT elixir databases.
+
+For DVO-2 development, I will need to make a few modifications to
+those tables.  It will be useful to allow versions of DVO which
+interact with these different versions correctly.  At one level, this
+simply means changing the structures in the included file.  More
+difficult is that certain functions use elements of the structures
+from one version which are not available in the other versions.  
+
+I am going to explore this process briefly to get DVO-2 started,
+particularly so I can solve the astrometric problems which are
+currently limited by the use of floats to represent RA & DEC.  
+
+I am going to make the selection of the structures depend on #define
+values in the header files.  Currently, everybody which works with the
+dvo files includes loneos.h.  This should be broken out to a loneos.h,
+elixir.h, panstarrs.h, etc, all independently included from within
+dvo.h, which will be the include file called within the user-level
+programs.
+
+Translations
+
+/* average data as stored in the LONEOS database -- must be translated on load */
+
+Loneos:Measure -> Elixir:Measure
+/* OLD LONEOS VERSION.  NOT BYTE COMPATIBLE WITH NEW VERSION 
+   (can be loaded with translation, losing the exptime,
+   and limited the number of Naverage to 0xffffff - in load_catalog) */
+
+------
+
+the DVO structure Catalog contains the data from a single sky patch, including:
+    average, measure, missing, and secfilt.  
+
+the catalog may be saved in one of 4 modes (catalog.catmode):
+    raw   : the old Elixir style which is a header + 4 binary tables
+    mef   : catalog is a single file with header and 4 fits tables
+    split : catalog is 5 files, one with the header and one for each table
+    mysql : catalog is 4 (or 5?) mysql tables
+
+    in split mode, the filename is the file of the descriptive header
+    and the averages, the measure, missing, and secfilt data are
+    stored in additional files referenced in the header and named
+    based on the filename (replacing extension .cpa with .cpb, .cpc,
+    .cpd, for example)
+
+    
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/doc/fits_db.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/doc/fits_db.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/doc/fits_db.txt	(revision 16632)
@@ -0,0 +1,5 @@
+
+FITS_DB represents a FITS table file, including the primary header,
+any existing matrix, the table header, and the table data as either an
+ftable (real) or vtable (virtual) FITS table.  
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/doc/notes.txt	(revision 16632)
@@ -0,0 +1,55 @@
+
+Adding a new dvo catalog format.  Assume the new format name is 'foo'.
+
+1) create the autocode definition files for average, measure, secfilt, image
+   these files must be a subset of the internal versions of these same
+   tables.  if you intend to add fields which don't exist in the
+   internal tables, you must update the internal tables as well.  the
+   naming convention is: average-foo.d, etc.
+
+2) add the new definition files to libautocode/Makefile.Targets (both
+   .o and .h lists).
+
+3) set the STRUCT and EXTNAME for these definitions files to have a
+   unique value. the naming convention for EXTNAME is DVO_AVERAGE_FOO
+   and for STRUCT is AverageFoo (add version info with underscores and
+   uppercase, eg: AveragePanstarrs_DEV_0, AveragePanstarrs_PS1_2).
+
+4) create a DVOTableFormat entry for the new format
+   (libdvo/include/dvo.h).  the naming convetion is DVO_FORMAT_FOO.
+
+5) add an entry for the new format in dvo_catalog_catformat
+ (libdvo/src/dvo_catalog.c).  The name should be "FOO".
+
+6) add entry for structure size in dvo_catalog_load_raw
+   (libdvo/src/dvo_catalog_raw.c), since this is not available from
+   the header.
+
+7) add entries in ReadRawAverage, WriteRawAverage, ReadRawMeasure,
+   WriteRawMeasure, ReadRawSecFilt, WriteRawSecFilt.  Make sure to use
+   the new STRUCT names. the conversion function gfit_convert_Foo will
+   be automatically generated.
+
+8) add entry in WriteRawAverage, making sure to use the new STRUCT
+   name. the conversion function gfit_convert_Foo will be
+   automatically generated.  
+
+9) create a new conversion file dvo_convert_foo.c and define the
+   internal to Foo conversions.
+
+* Note some esoteric format issues:  
+
+  - LONEOS and ELIXIR lack chip coordinates, and must apply an
+    on-the-fly conversion, implemented in dvo_catalog_chipcoords. 
+
+  - LONEOS and ELIXIR use the old primary/secondary photcode concept,
+    and must have one photcode dataset extracted from the average
+    table on read and resupplied on write.  this happens in
+    dvo_catalog_save_mef, dvo_catalog_save_raw,
+    dvo_catalog_save_split, dvo_catalog_update_split
+
+  - LONEOS and ELIXIR have old versions where the header does not
+    specify the type explicitly.  the functions dvo_catalog_load_raw
+    and dvo_image_load_raw identify these types based on special
+    keywords.
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/include/dvo.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/include/dvo.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/include/dvo.h	(revision 16632)
@@ -0,0 +1,425 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <autocode.h>
+
+# ifndef DVO_H
+# define DVO_H
+
+/* DVO table modes */
+typedef enum {DVO_MODE_UNDEF, DVO_MODE_RAW, DVO_MODE_MEF, DVO_MODE_SPLIT, DVO_MODE_MYSQL} DVOTableMode;
+
+/* DVO table formats */
+typedef enum {DVO_FORMAT_UNDEF, 
+	      DVO_FORMAT_INTERNAL, 
+	      DVO_FORMAT_ELIXIR, 
+	      DVO_FORMAT_LONEOS, 
+	      DVO_FORMAT_PANSTARRS_DEV_0,
+	      DVO_FORMAT_PANSTARRS_DEV_1,
+	      DVO_FORMAT_PS1_DEV_1
+} DVOTableFormat;
+
+/* image data modes in RegImage */
+typedef enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE} ElixirDetrendTypes;
+typedef enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE} ElixirDetrendModes;
+
+typedef enum {DVO_CAT_OPEN_FAIL, DVO_CAT_OPEN_OK, DVO_CAT_OPEN_EMPTY} DVOCatalogOpenModes;
+
+typedef enum {
+  PROJ_NONE, // undefined
+  PROJ_ZEA, // zenithal
+  PROJ_ZPL, // zenithal
+  PROJ_ARC, // zenithal
+  PROJ_STG, // zenithal
+  PROJ_SIN, // zenithal
+  PROJ_TAN, // zenithal
+  PROJ_DIS, // zenithal (TAN + polyterms)
+  PROJ_LIN, // cartesian
+  PROJ_PLY, // cartesian
+  PROJ_WRP, // cartesian
+  PROJ_AIT, // pseudocyl
+  PROJ_GLS, // pseudocyl
+  PROJ_PAR, // pseudocyl
+} OhanaProjection;
+
+typedef enum {
+  PROJ_MODE_NONE,
+  PROJ_MODE_CARTESIAN,
+  PROJ_MODE_ZENITHAL,
+  PROJ_MODE_PSEUDOCYL,
+} OhanaProjectionMode;
+
+// these are used as NAN for types of int values
+typedef enum {
+    NAN_S_CHAR  = 0x7f,
+    NAN_U_CHAR  = 0xff,   // was NO_ERR
+    NAN_S_SHORT = 0x7fff, // was NO_MAG
+    NAN_U_SHORT = 0xffff, 
+    NAN_S_INT   = 0x7fffffff,
+    NAN_U_INT   = 0xffffffff,
+} DVO_INT_NAN;
+
+# ifndef NAN
+# ifndef BYTE_SWAP
+#  define __nan_bytes           { 0x7f, 0xc0, 0, 0 }
+# else
+#  define __nan_bytes           { 0, 0, 0xc0, 0x7f }
+# endif
+static union { unsigned char __c[4]; float __d; } __nan_union
+    __attribute_used__ = { __nan_bytes };
+# define NAN    (__nan_union.__d)
+# endif
+
+/* RegImage.flag values */
+# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
+
+/* catalog values to be loaded */
+# define LOAD_NONE 	0x00
+# define LOAD_AVES 	0x01
+# define LOAD_MEAS 	0x02
+# define LOAD_MISS 	0x04
+# define LOAD_SECF 	0x08 
+# define LOAD_MEAS_META 0x10
+
+/* photometry code types */
+// # define PHOT_PRI 0x01
+# define PHOT_SEC 0x02
+# define PHOT_DEP 0x03
+# define PHOT_REF 0x04
+# define PHOT_ALT 0x05  /* never stored, only for look-ups */
+# define PHOT_MAG 0x06  /* generic magnitude; never stored */
+
+/* Image.code values.  these are codes to note bad images */
+# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
+# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
+# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
+# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
+# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
+
+/* Measure.flags values */
+# define ID_MEAS_NOCAL        0x0001
+# define ID_MEAS_POOR         0x0002
+# define ID_MEAS_SKIP         0x0004
+# define ID_MEAS_AREA         0x0008
+# define BLEND_IMAGE          0x0100 
+# define BLEND_CATALOG        0x0200
+# define BLEND_IMAGE_NEIGHBOR 0x1000
+# define ID_MEAS_TRAIL        0x2000
+# define ID_MEAS_GHOST        0x4000
+
+/* some subtle distinctions between the blend flags:
+   BLEND_IMAGE: the star on an image is matched with more 
+   than one star in the catalog (image has worse seeing than catalog)
+   BLEND_CATALOG: the star in the catalog is matched with more 
+   than one star on the image (image has better seeing than catalog)
+   CALIBRATED: relative photometry has been performed on this measurement
+   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
+   than one star in the catalog, but not in the same catalog file.
+*/
+
+/* Average.code values */
+# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
+# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_VARIABLE   0x2000 /* not currently set? */
+# define ID_ASTEROID   0x2000 /* identified with an asteroid */
+# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
+# define ID_MOVING     0x8000
+# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
+# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
+# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
+# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
+# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
+
+/*** general dvo structures (internal use only / not IO) ***/
+
+/* FITS DB structure */
+typedef struct {
+  FILE  *f;
+  char  *filename;
+  int    dbstate;
+  int    lockstate;
+  double timeout;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  VTable vtable;
+  int    mode;          /* what data storage mode is used for disk file? */
+  int    format;        /* what data format is used for disk file? */
+  int    virtual;       /* is table in ftable or vtable? */
+  int    swapped;       /* is table in internal byte-order? */
+} FITS_DB;
+
+/* the basic HST GSC layout corresponds to a depth of 3 */
+# define SKY_DEPTH_HST 3
+
+/* SkyRegion : better implementation than GSCRegion */
+typedef struct {
+  int Nregions;
+  char **filename;
+  SkyRegion *regions;
+} SkyTable;
+
+typedef struct {
+  int Nregions;
+  int ownElements; 				  /* does this list own filename, regions? */
+  char **filename;
+  SkyRegion **regions;
+} SkyList;
+
+# if (0)
+/* structure for data on a catalog region */
+typedef struct {
+  char filename[256];
+  double DEC[2], RA[2];
+} GSCRegion;
+# endif
+
+typedef struct {
+  int Ncode;					  // number of photcodes
+  int Nsecfilt;					  // number of average magnitudes
+  int hashcode[0x10000];		  // index from photcode value to sequence
+  int hashNsec[0x10000];		  // index from photcode value to Nsec seq
+  int codeNsec[0x10000];		  // index from Nsec seq to photcode value
+  PhotCode *code;
+} PhotCodeData;
+
+/* a catalog contains this data */
+typedef struct Catalog {
+  char *filename;			/* catalog file */
+  FILE *f;  				/* file descriptor */
+  Header  header;
+
+  /* data in the catalog file */
+  Average *average;
+  Measure *measure; 
+  Missing *missing; 
+  SecFilt *secfilt;
+
+  int Nsecfilt;  /* number of secfilt entries for each average entry */
+  int Naverage,   Nmeasure,   Nmissing,   Nsecf_mem;  /* current number of each component in memory */
+  int Naves_disk, Nmeas_disk, Nmiss_disk, Nsecf_disk; /* current number of each component on disk */
+  int Naves_off,  Nmeas_off,  Nmiss_off,  Nsecf_off;  /* index of first loaded data value */
+
+  /* note the different counting for Nsecfilt:
+     number of secfilt rows on disk is: Nave_disk * Nsecfilt
+     number of secfilt rows in mem  is: Naverage * Nsecfilt
+     *** that is just silly, and bad: convert to using Nsec_mem, Nsec_disk, Nsec_off.
+     *** unless we always require the secfilt and average entries to be loaded sychronously.
+   */
+
+  /* pointers to split data files */
+  struct Catalog *measure_catalog;		/* measure catalog data (split) */
+  struct Catalog *missing_catalog;		/* missing catalog data (split) */
+  struct Catalog *secfilt_catalog;		/* secfilt catalog data (split) */
+
+  /* extra catalog information */
+  int lockmode;
+  int catmode;				/* storage mode (raw, mef, split, mysql) */
+  int catformat;			/* storage format (elixir, panstarrs, etc) */
+  int catflags;				/* choices to be loaded */
+  int sorted;				/* is measure table average-sorted? */
+  
+  /* pointers for data manipulation */
+  int *found;
+  int *image;
+  int *mosaic;
+  float *X;
+  float *Y;
+
+} Catalog;
+
+/*** prototypes ***/
+
+/* in gfits_db.c */
+int   gfits_db_init                PROTO((FITS_DB *db));
+int   gfits_db_create              PROTO((FITS_DB *db));
+int   gfits_db_lock                PROTO((FITS_DB *db, char *filename));
+int   gfits_db_load                PROTO((FITS_DB *db));
+int   gfits_db_load_segment        PROTO((FITS_DB *db, int start, int Nrows));
+int   gfits_db_save                PROTO((FITS_DB *db));
+int   gfits_db_update              PROTO((FITS_DB *db));
+int   gfits_db_close               PROTO((FITS_DB *db));
+int   gfits_db_free                PROTO((FITS_DB *db));
+
+/* in coords.c, using libautocode/def/coords.d */
+int  XY_to_LM (double *L, double *M, double x,  double y,   Coords *coords);
+int  LM_to_XY (double *x,  double *y,   double L, double M, Coords *coords);
+int  RD_to_LM (double *L, double *M, double ra,  double dec,   Coords *coords);
+int  LM_to_RD (double *ra, double *dec,   double L, double M, Coords *coords);
+int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
+int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
+int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
+int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
+int  GetCoords (Coords *coords, Header *header);
+int  PutCoords (Coords *coords, Header *header);
+void RegisterMosaic (Coords *coords);
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
+OhanaProjection GetProjection (char *ctype);
+int SetProjection (char *ctype, OhanaProjection proj);
+OhanaProjectionMode GetProjectionMode (OhanaProjection proj);
+
+char *libdvo_version ();
+
+int GetRegisteredMosaic ();
+int FindMosaicForImage (Image *images, int Nimages, int entry);
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
+int BuildChipMatch (Image *images, int Nimages);
+void SetImageCorners (double *X, double *Y, Image *image);
+
+short int putMi (double value);
+double getMi (short int value);
+void returnMcal (Image *image, double *c);
+void assignMcal (Image *image, double *c, int order);
+double applyMcal (Image *image, double x, double y);
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order);
+
+PhotCode *GetPhotcodebyName (char *name);
+PhotCode *GetPhotcodeEquivbyName (char *name);
+PhotCode *GetPhotcodebyCode (int code);
+PhotCode *GetPhotcodebyNsec (int Nsec);
+PhotCode *GetPhotcodeEquivbyCode (int code);
+char     *GetPhotcodeNamebyCode (int code);
+
+float PhotInst (Measure *measure);
+float PhotCat (Measure *measure);
+float PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+float PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+float PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+float PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+float PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+float PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+float PhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+float PhotColorForCode (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);
+
+PhotCodeData *GetPhotcodeTable ();
+
+int LoadPhotcodes (char *catdir_file, char *master_file);
+int LoadPhotcodesText (char *filename);
+int LoadPhotcodesFITS (char *filename);
+int SavePhotcodesText (char *filename);
+int SavePhotcodesFITS (char *filename);
+
+void PrintPhotcodeNamebyCode (FILE *f, char *format, int code);
+
+int GetPhotcodeCodebyName (char *name);
+int GetPhotcodeEquivCodebyName (char *name);
+int GetPhotcodeEquivCodebyCode (int code);
+int GetPhotcodeNsec (int code);
+int GetPhotcodeNsecfilt ();
+void SetZeroPoint (double ZP);
+double GetZeroPoint ();
+int *GetPhotcodeEquivList (int code, int *nlist);
+void ParseColorTerms (char *terms, float *X, int *N);
+
+int get_image_type (char *name);
+char *get_type_name (int type);
+int get_image_mode (char *name);
+char *get_mode_name (int mode);
+
+/* these functions refer to the DVO structures defined in the includes above
+ *  they are being replaced with autocode entries (drop when totally autocoded)
+ */
+
+int   Fread (void *ptr, int size, int nitems, FILE *f, char *type);
+int   Fwrite (void *ptr, int size, int nitems, FILE *f, char *type);
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+int   ConvertStruct (char *buffer, int size, int Nbytes, char *type);
+
+/** dvo_catalog APIs */
+void dvo_catalog_init (Catalog *catalog, int complete);
+void dvo_catalog_create (SkyRegion *region, Catalog *catalog);
+void dvo_catalog_free (Catalog *catalog);
+void dvo_catalog_free_data (Catalog *catalog);
+int dvo_catalog_check (Catalog *catalog, int Nsecfilt, int extend);
+int dvo_catalog_lock (Catalog *catalog, int lockmode);
+int dvo_catalog_unlock (Catalog *catalog);
+int dvo_catalog_load (Catalog *catalog, int VERBOSE);
+int dvo_catalog_open (Catalog *catalog, SkyRegion *region, int VERBOSE, char *iomode);
+int dvo_catalog_save (Catalog *catalog, char VERBOSE);
+int dvo_catalog_update (Catalog *catalog, char VERBOSE);
+int dvo_catalog_catformat (char *catformat);
+int dvo_catalog_catmode (char *catmode);
+void dvo_catalog_test (Catalog *catalog, int halt);
+
+/* catmode-specific APIs */
+int dvo_catalog_load_raw (Catalog *catalog, int VERBOSE);
+int dvo_catalog_save_raw (Catalog *catalog, char VERBOSE);
+int dvo_catalog_load_mef (Catalog *catalog, int VERBOSE);
+int dvo_catalog_save_mef (Catalog *catalog, char VERBOSE);
+int dvo_catalog_load_split (Catalog *catalog, int VERBOSE);
+int dvo_catalog_save_split (Catalog *catalog, char VERBOSE);
+int dvo_catalog_update_split (Catalog *catalog, char VERBOSE);
+
+int dvo_catalog_load_segment (Catalog *catalog, int VERBOSE, int start, int Nrows);
+int dvo_catalog_load_segment_split (Catalog *catalog, int VERBOSE, int start, int Nrows);
+
+/*** conversion functions / I/O conversions ***/
+Average *ReadRawAverage (FILE *f, int Naverage, int format, SecFilt **primary);
+Measure *ReadRawMeasure (FILE *f, int Nmeasure, int format);
+SecFilt *ReadRawSecFilt (FILE *f, int Nsecfilt, int format);
+int WriteRawAverage (FILE *f, Average *average, int Naverage, int format, SecFilt *primary);
+int WriteRawMeasure (FILE *f, Measure *measure, int Nmeasure, int format);
+int WriteRawSecFilt (FILE *f, SecFilt *secfilt, int Nsecfilt, int format);
+
+Average *FtableToAverage (FTable *ftable, int *Naverage, int *format, SecFilt **primary);
+Measure *FtableToMeasure (FTable *ftable, int *Nmeasure, int *format);
+SecFilt *FtableToSecFilt (FTable *ftable, int *Nsecfilt, int *format);
+int FtableToImage (FTable *ftable, Header *theader, int *format);
+
+int AverageToFtable (FTable *ftable, Average *average, int Naverage, int format, SecFilt *primary);
+int MeasureToFtable (FTable *ftable, Measure *measure, int Nmeasure, int format);
+int SecFiltToFtable (FTable *ftable, SecFilt *secfilt, int Nsecfilt, int format);
+int ImageToFtable (FTable *ftable, Header *theader, int format);
+int ImageToVtable (VTable *vtable, Header *theader, int format);
+
+# include "loneos_defs.h"
+# include "elixir_defs.h"
+# include "panstarrs_dev_0_defs.h"
+# include "panstarrs_dev_1_defs.h"
+# include "ps1_dev_1_defs.h"
+
+/*** DVO image db I/O Functions ***/
+int dvo_image_lock (FITS_DB *db, char *filename, double timeout, int lockstate);
+int dvo_image_unlock (FITS_DB *db);
+int dvo_image_load (FITS_DB *db, int VERBOSE, int FORCE_READ);
+int dvo_image_save (FITS_DB *db, int VERBOSE);
+int dvo_image_update (FITS_DB *db, int VERBOSE);
+int dvo_image_load_raw (FITS_DB *db, int VERBOSE, int FORCE_READ);
+int dvo_image_update_raw (FITS_DB *db, int VERBOSE);
+int dvo_image_save_raw (FITS_DB *db, int VERBOSE);
+int dvo_image_addrows (FITS_DB *db, Image *new, int Nnew);
+void dvo_image_create (FITS_DB *db, double ZeroPoint);
+
+/* skyregion APIs */
+int        SkyTableSave        	   PROTO((SkyTable *table, char *filename));
+SkyTable  *SkyTableLoad        	   PROTO((char *filename, int VERBOSE));
+SkyTable  *SkyTableFromGSC     	   PROTO((char *filename, int depth, int VERBOSE));
+SkyTable  *SkyTableLoadOptimal 	   PROTO((char *catdir, char *SKYFILE, char *GSCFILE, int depth, int VERBOSE));
+int        SkyTableSetDepth    	   PROTO((SkyTable *sky, int depth));
+SkyList   *SkyRegionByPoint    	   PROTO((SkyTable *table, int depth, double ra, double dec));
+SkyList   *SkyListByPoint      	   PROTO((SkyTable *table, double ra, double dec));
+SkyList   *SkyListByRadius     	   PROTO((SkyTable *table, int depth, double RA, double DEC, double radius));
+SkyList   *SkyListByPatch      	   PROTO((SkyTable *table, int depth, SkyRegion *patch));
+SkyList   *SkyListByName      	   PROTO((SkyTable *table, char *name));
+SkyList   *SkyListByImage      	   PROTO((SkyTable *table, int depth, Image *image));
+SkyList   *SkyListByBounds     	   PROTO((SkyTable *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax));
+SkyList   *SkyListChildrenByBounds PROTO((SkyTable *table, int No, int depth, double Rmin, double Rmax, double Dmin, double Dmax));
+int        SkyListMerge     	   PROTO((SkyList **outlist, SkyList *newlist));
+int        SkyListFree             PROTO((SkyList *list));
+int        SkyTableFree            PROTO((SkyTable *table));
+int        SkyListSetFilenames     PROTO((SkyList *list, char *path, char *ext));
+int        SkyTableSetFilenames    PROTO((SkyTable *sky, char *path, char *ext));
+
+/* dvo-specific sorting functions */
+void sortave (Average *ave, int N);
+void sort_image_subset (Image *image, int *subset, int N);
+void sort_coords_index (double *X, double *Y, int *S, int N);
+void sort_stars_ra (Stars *stars, int N);
+void sort_regions (SkyRegion *region, int N);
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/include/dvo.update.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/include/dvo.update.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/include/dvo.update.h	(revision 16632)
@@ -0,0 +1,399 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <autocode.h>
+
+# ifndef DVO_H
+# define DVO_H
+
+/*
+  # define ELIXIR 1
+  # define PANSTARRS 0
+  # define LONEOS 0
+*/
+
+/*** named data values (convert all to enums?) ***/
+
+/* DVO table modes */
+enum {DVO_MODE_UNDEF, DVO_MODE_RAW, DVO_MODE_MEF, DVO_MODE_SPLIT, DVO_MODE_MYSQL} DVOTableMode;
+
+/* DVO table formats */
+enum {DVO_FORMAT_UNDEF, DVO_FORMAT_INTERNAL, DVO_FORMAT_ELIXIR, DVO_FORMAT_LONEOS, DVO_FORMAT_PANSTARRS, DVO_FORMAT_PMTEST} DVOTableFormat;
+
+/* image data modes in RegImage */
+enum {T_UNDEF = -1, T_NONE, T_OBJECT, T_DARK, T_BIAS, T_FLAT, T_MASK, T_FRINGE, T_SCATTER, T_MODES, T_FRINGEPTS, T_ANY, N_TYPE};
+enum {M_UNDEF = -1, M_NONE, M_MEF, M_SPLIT, M_SINGLE, M_CUBE, M_SLICE, M_MODES, N_MODE};
+
+typedef enum {
+    PROJ_NONE, // undefined
+    PROJ_ZEA, // zenithal
+    PROJ_ZPL, // zenithal
+    PROJ_ARC, // zenithal
+    PROJ_STG, // zenithal
+    PROJ_SIN, // zenithal
+    PROJ_TAN, // zenithal
+    PROJ_DIS, // zenithal (TAN + polyterms)
+    PROJ_LIN, // cartesian
+    PROJ_PLY, // cartesian
+    PROJ_WRP, // cartesian
+    PROJ_AIT, // pseudocyl
+    PROJ_GLS, // pseudocyl
+    PROJ_PAR, // pseudocyl
+} OhanaProjections;
+
+typedef enum {
+  PROJ_MODE_NONE,
+  PROJ_MODE_CARTESIAN,
+  PROJ_MODE_ZENITHAL,
+  PROJ_MODE_PSEUDOCYL,
+} OhanaProjectionModes;
+
+/* RegImage.flag values */
+# define IMREG_DIST  0x01 /* image distributed, only imregister-3.0 */
+
+/* catalog values to be loaded */
+# define LOAD_AVES 	0x01
+# define LOAD_MEAS 	0x02
+# define LOAD_MISS 	0x04
+# define LOAD_SECF 	0x08 
+# define LOAD_MEAS_META 0x10
+
+/* invalid mag value */
+# define NO_MAG    0x7fff
+# define NO_ERR    0xff
+
+/* photometry code types */
+# define PHOT_PRI 0x01
+# define PHOT_SEC 0x02
+# define PHOT_DEP 0x03
+# define PHOT_REF 0x04
+# define PHOT_ALT 0x05  /* never stored, only for look-ups */
+
+/* Image.code values.  these are codes to note bad images */
+# define ID_IMAGE_NEW   0x0000  /* no nrphot attempted */
+# define ID_IMAGE_NOCAL 0x0001  /* used within nrphot to mean "don't apply fit" */
+# define ID_IMAGE_POOR  0x0002  /* relphot says image is bad */
+# define ID_IMAGE_SKIP  0x0004  /* external information image is bad */
+# define ID_IMAGE_FEW   0x0008  /* currently too few measurements for good value */
+
+/* Measure.flags values */
+# define ID_MEAS_NOCAL        0x0001
+# define ID_MEAS_POOR         0x0002
+# define ID_MEAS_SKIP         0x0004
+# define ID_MEAS_AREA         0x0008
+# define BLEND_IMAGE          0x0100 
+# define BLEND_CATALOG        0x0200
+# define BLEND_IMAGE_NEIGHBOR 0x1000
+# define ID_MEAS_TRAIL        0x2000
+# define ID_MEAS_GHOST        0x4000
+
+/* some subtle distinctions between the blend flags:
+   BLEND_IMAGE: the star on an image is matched with more 
+   than one star in the catalog (image has worse seeing than catalog)
+   BLEND_CATALOG: the star in the catalog is matched with more 
+   than one star on the image (image has better seeing than catalog)
+   CALIBRATED: relative photometry has been performed on this measurement
+   BLEND_IMAGE_NEIGHBOR: the star on an image is matched with more 
+   than one star in the catalog, but not in the same catalog file.
+*/
+
+/* Average.code values */
+# define ID_STAR_FEW   0x0001 /* used within relphot: skip star */
+# define ID_STAR_POOR  0x0002 /* used within relphot: skip star */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_VARIABLE   0x2000 /* not currently set? */
+# define ID_ASTEROID   0x2000 /* identified with an asteroid */
+# define ID_BAD_OBJECT 0x4000 /* if all measurements are bad, set this bit */
+# define ID_MOVING     0x8000
+# define ID_ROCK       0xa000 /* 0x8000 + 0x2000 */
+# define ID_GHOST      0xc001 /* 0x8000 + 0x4000 + 0x0001 */
+# define ID_TRAIL      0xc002 /* 0x8000 + 0x4000 + 0x0002 */
+# define ID_BLEED      0xc003 /* 0x8000 + 0x4000 + 0x0003 */ 
+# define ID_COSMIC     0xc004 /* 0x8000 + 0x4000 + 0x0004 */ 
+
+/*** general dvo structures (internal use only / not IO) ***/
+
+/* FITS DB structure */
+typedef struct {
+  FILE  *f;
+  char  *filename;
+  int    dbstate;
+  int    lockstate;
+  double timeout;
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  VTable vtable;
+  int    mode;          /* what data storage mode is used for disk file? */
+  int    format;        /* what data format is used for disk file? */
+  int    virtual;       /* is table in ftable or vtable? */
+  int    swapped;       /* is table in internal byte-order? */
+} FITS_DB;
+
+/* the basic HST GSC layout corresponds to a depth of 3 */
+# define SKY_DEPTH_HST 3
+
+/* SkyRegion : better implementation than GSCRegion */
+typedef struct {
+  int Nregions;
+  char **filename;
+  SkyRegion *regions;
+} SkyTable;
+
+typedef struct {
+  int Nregions;
+  char **filename;
+  SkyRegion **regions;
+} SkyList;
+
+# if (0)
+/* structure for data on a catalog region */
+typedef struct {
+  char filename[256];
+  double DEC[2], RA[2];
+} GSCRegion;
+# endif
+
+typedef struct {
+  int Ncode;
+  int Nsecfilt;
+  int hashcode[0x10000];
+  int hashNsec[0x10000];
+  PhotCode *code;
+} PhotCodeData;
+
+/* a catalog contains this data */
+typedef struct Catalog {
+  char *filename;			/* catalog file */
+  FILE *f;  				/* file descriptor */
+  Header  header;
+
+  /* data in the catalog file */
+  Average *average;
+  Measure *measure; 
+  Missing *missing; 
+  SecFilt *secfilt;
+  int Naverage, Nmeasure, Nmissing, Nsecfilt;   /* current number of each component */
+  int Nave_disk, Nmeas_disk, Nmiss_disk;        /* number of component on disk */
+  int Nmeas_off;			        /* dist seq of first loaded data value */
+  /* note the different counting for Nsecfilt */
+
+  /* pointers to split data files */
+  struct Catalog *measure_catalog;		/* measure catalog data (split) */
+  struct Catalog *missing_catalog;		/* missing catalog data (split) */
+  struct Catalog *secfilt_catalog;		/* secfilt catalog data (split) */
+
+  /* extra catalog information */
+  int lockmode;
+  int catmode;				/* storage mode (raw, mef, split, mysql) */
+  int catformat;			/* storage format (elixir, panstarrs, etc) */
+  int catflags;				/* choices to be loaded */
+  int sorted;				/* is measure table average-sorted? */
+  
+  /* pointers for data manipulation */
+  int *found;
+  int *image;
+  int *mosaic;
+  float *X;
+  float *Y;
+
+} Catalog;
+
+/*** prototypes ***/
+
+/* in gfits_db.c */
+int   gfits_db_init                PROTO((FITS_DB *db));
+int   gfits_db_create              PROTO((FITS_DB *db));
+int   gfits_db_lock                PROTO((FITS_DB *db, char *filename));
+int   gfits_db_load                PROTO((FITS_DB *db));
+int   gfits_db_load_segment        PROTO((FITS_DB *db, int start, int Nrows));
+int   gfits_db_save                PROTO((FITS_DB *db));
+int   gfits_db_update              PROTO((FITS_DB *db));
+int   gfits_db_close               PROTO((FITS_DB *db));
+int   gfits_db_free                PROTO((FITS_DB *db));
+
+/* in coords.c, using libautocode/def/coords.d */
+int  XY_to_RD (double *ra, double *dec, double x,  double y,   Coords *coords);
+int  RD_to_XY (double *x,  double *y,   double ra, double dec, Coords *coords);
+int  fXY_to_RD (float *ra, float *dec, double x,  double y,   Coords *coords);
+int  fRD_to_XY (float *x,  float *y,   double ra, double dec, Coords *coords);
+int  GetCoords (Coords *coords, Header *header);
+int  PutCoords (Coords *coords, Header *header);
+void RegisterMosaic (Coords *coords);
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch);
+
+int FindMosaicForImage (Image *images, int Nimages, int entry);
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry);
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry);
+int BuildChipMatch (Image *images, int Nimages);
+void SetImageCorners (double *X, double *Y, Image *image);
+
+short int putMi (double value);
+double getMi (short int value);
+void returnMcal (Image *image, double *c);
+void assignMcal (Image *image, double *c, int order);
+double applyMcal (Image *image, double x, double y);
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order);
+
+PhotCode *GetPhotcodebyName (char *name);
+PhotCode *GetPhotcodeEquivbyName (char *name);
+PhotCode *GetPhotcodebyCode (int code);
+PhotCode *GetPhotcodebyNsec (int Nsec);
+PhotCode *GetPhotcodeEquivbyCode (int code);
+char     *GetPhotcodeNamebyCode (int code);
+
+float PhotInst (Measure *measure);
+float PhotCat (Measure *measure);
+float PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+float PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+float PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+float PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+float PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+float PhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+float PhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+
+# if (0)
+short iPhotInst (Measure *measure);
+short iPhotAbs (Measure *measure);
+short iPhotCat (Measure *measure);
+short iPhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+short iPhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+short iPhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+short iPhotXm (PhotCode *code, Average *average, SecFilt *secfilt);
+short iPhotdM (PhotCode *code, Average *average, SecFilt *secfilt);
+# endif
+
+float iPhotColor (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code);
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color);
+
+int LoadPhotcodes (char *filename);
+int GetPhotcodeCodebyName (char *name);
+int GetPhotcodeEquivCodebyName (char *name);
+int GetPhotcodeEquivCodebyCode (int code);
+int GetPhotcodeNsec (int code);
+int GetPhotcodeNsecfilt ();
+void SetZeroPoint (double ZP);
+int *GetPhotcodeEquivList (int code, int *nlist);
+void ParseColorTerms (char *terms, float *X, int *N);
+
+int get_image_type (char *name);
+char *get_type_name (int type);
+int get_image_mode (char *name);
+char *get_mode_name (int mode);
+
+/* these functions refer to the DVO structures defined in the includes above
+ *  they are being replaced with autocode entries (drop when totally autocoded)
+ */
+
+int   Fread (void *ptr, int size, int nitems, FILE *f, char *type);
+int   Fwrite (void *ptr, int size, int nitems, FILE *f, char *type);
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+int   ConvertStruct (char *buffer, int size, int Nbytes, char *type);
+
+/** dvo_catalog APIs */
+void dvo_catalog_init (Catalog *catalog, int complete);
+void dvo_catalog_create (SkyRegion *region, Catalog *catalog);
+void dvo_catalog_free (Catalog *catalog);
+int dvo_catalog_check (Catalog *catalog, int Nsecfilt, int extend);
+int dvo_catalog_lock (Catalog *catalog, int lockmode);
+int dvo_catalog_unlock (Catalog *catalog);
+int dvo_catalog_load (Catalog *catalog, int VERBOSE);
+int dvo_catalog_open (Catalog *catalog, SkyRegion *region, int VERBOSE, char *iomode);
+int dvo_catalog_save (Catalog *catalog, char VERBOSE);
+int dvo_catalog_update (Catalog *catalog, char VERBOSE);
+int dvo_catalog_catformat (char *catformat);
+int dvo_catalog_catmode (char *catmode);
+void dvo_catalog_test (Catalog *catalog, int halt);
+
+/* catmode-specific APIs */
+int dvo_catalog_load_raw (Catalog *catalog, int VERBOSE);
+int dvo_catalog_save_raw (Catalog *catalog, char VERBOSE);
+int dvo_catalog_load_mef (Catalog *catalog, int VERBOSE);
+int dvo_catalog_save_mef (Catalog *catalog, char VERBOSE);
+int dvo_catalog_load_split (Catalog *catalog, int VERBOSE);
+int dvo_catalog_save_split (Catalog *catalog, char VERBOSE);
+int dvo_catalog_update_split (Catalog *catalog, char VERBOSE);
+
+/*** conversion functions / I/O conversions ***/
+Average *ReadRawAverage (FILE *f, int Naverage, int format);
+Measure *ReadRawMeasure (FILE *f, int Nmeasure, int format);
+SecFilt *ReadRawSecFilt (FILE *f, int Nsecfilt, int format);
+int WriteRawAverage (FILE *f, Average *average, int Naverage, int format);
+int WriteRawMeasure (FILE *f, Measure *measure, int Nmeasure, int format);
+int WriteRawSecFilt (FILE *f, SecFilt *secfilt, int Nsecfilt, int format);
+
+Average *FtableToAverage (FTable *ftable, int *Naverage, int *format);
+Average *AverageLoneosToInternal (AverageLoneos *in, int Nvalues);
+Average *AverageElixirToInternal (AverageElixir *in, int Nvalues);
+Average *AveragePanstarrsToInternal (AveragePanstarrs *in, int Nvalues);
+Average *AveragePMtestToInternal (AveragePMtest *in, int Nvalues);
+AverageLoneos *AverageInternalToLoneos (Average *in, int Nvalues);
+AverageElixir *AverageInternalToElixir (Average *in, int Nvalues);
+AveragePanstarrs *AverageInternalToPanstarrs (Average *in, int Nvalues);
+AveragePMtest *AverageInternalToPMtest (Average *in, int Nvalues);
+
+Measure *FtableToMeasure (FTable *ftable, int *Nmeasure, int *format);
+Measure *MeasureLoneosToInternal (MeasureLoneos *in, int Nvalues);
+Measure *MeasureElixirToInternal (MeasureElixir *in, int Nvalues);
+Measure *MeasurePanstarrsToInternal (MeasurePanstarrs *in, int Nvalues);
+MeasureLoneos *MeasureInternalToLoneos (Measure *in, int Nvalues);
+MeasureElixir *MeasureInternalToElixir (Measure *in, int Nvalues);
+MeasurePanstarrs *MeasureInternalToPanstarrs (Measure *in, int Nvalues);
+
+SecFilt *FtableToSecFilt (FTable *ftable, int *Nsecfilt, int *format);
+SecFilt *SecFiltLoneosToInternal (SecFiltLoneos *in, int Nvalues);
+SecFilt *SecFiltElixirToInternal (SecFiltElixir *in, int Nvalues);
+SecFilt *SecFiltPanstarrsToInternal (SecFiltPanstarrs *in, int Nvalues);
+SecFiltLoneos *SecFiltInternalToLoneos (SecFilt *in, int Nvalues);
+SecFiltElixir *SecFiltInternalToElixir (SecFilt *in, int Nvalues);
+SecFiltPanstarrs *SecFiltInternalToPanstarrs (SecFilt *in, int Nvalues);
+
+int AverageToFtable (FTable *ftable, Average *average, int Naverage, int format);
+int MeasureToFtable (FTable *ftable, Measure *measure, int Nmeasure, int format);
+int SecFiltToFtable (FTable *ftable, SecFilt *secfilt, int Nsecfilt, int format);
+
+/*** DVO image db I/O Functions ***/
+int dvo_image_lock (FITS_DB *db, char *filename, double timeout, int lockstate);
+int dvo_image_unlock (FITS_DB *db);
+int dvo_image_load (FITS_DB *db, int VERBOSE, int FORCE_READ);
+int dvo_image_save (FITS_DB *db, int VERBOSE);
+int dvo_image_update (FITS_DB *db, int VERBOSE);
+int dvo_image_load_raw (FITS_DB *db, int VERBOSE, int FORCE_READ);
+int dvo_image_update_raw (FITS_DB *db, int VERBOSE);
+int dvo_image_save_raw (FITS_DB *db, int VERBOSE);
+int dvo_image_addrows (FITS_DB *db, Image *new, int Nnew);
+void dvo_image_create (FITS_DB *db, double ZeroPoint);
+
+int FtableToImage (FTable *ftable, Header *theader, int *format);
+int ImageToFtable (FTable *ftable, Header *theader, int format);
+int ImageToVtable (VTable *vtable, Header *theader, int format);
+Image *ImageElixirToInternal (ImageElixir *in, int Nvalues);
+ImageElixir *ImageInternalToElixir (Image *in, int Nvalues);
+Image *ImageLoneosToInternal (ImageLoneos *in, int Nvalues);
+ImageLoneos *ImageInternalToLoneos (Image *in, int Nvalues);
+Image *ImagePanstarrsToInternal (ImagePanstarrs *in, int Nvalues);
+ImagePanstarrs *ImageInternalToPanstarrs (Image *in, int Nvalues);
+
+/* skyregion APIs */
+int        SkyTableSave        	   PROTO((SkyTable *table, char *filename));
+SkyTable  *SkyTableLoad        	   PROTO((char *filename, int VERBOSE));
+SkyTable  *SkyTableFromGSC     	   PROTO((char *filename, int depth, int VERBOSE));
+SkyTable  *SkyTableLoadOptimal 	   PROTO((char *catdir, char *SKYFILE, char *GSCFILE, int depth, int VERBOSE));
+int        SkyTableSetDepth    	   PROTO((SkyTable *sky, int depth));
+SkyList   *SkyRegionByPoint    	   PROTO((SkyTable *table, int depth, double ra, double dec));
+SkyList   *SkyListByPoint      	   PROTO((SkyTable *table, double ra, double dec));
+SkyList   *SkyListByRadius     	   PROTO((SkyTable *table, int depth, double RA, double DEC, double radius));
+SkyList   *SkyListByPatch      	   PROTO((SkyTable *table, int depth, SkyRegion *patch));
+SkyList   *SkyListByName      	   PROTO((SkyTable *table, char *name));
+SkyList   *SkyListByImage      	   PROTO((SkyTable *table, int depth, Image *image));
+SkyList   *SkyListByBounds     	   PROTO((SkyTable *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax));
+SkyList   *SkyListChildrenByBounds PROTO((SkyTable *table, int No, int depth, double Rmin, double Rmax, double Dmin, double Dmax));
+int        SkyListFree             PROTO((SkyList *list, int ELEMENTS));
+int        SkyTableFree            PROTO((SkyTable *table));
+int        SkyListSetFilenames     PROTO((SkyList *list, char *path, char *ext));
+int        SkyTableSetFilenames    PROTO((SkyTable *sky, char *path, char *ext));
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/include/elixir_defs.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/include/elixir_defs.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/include/elixir_defs.h	(revision 16632)
@@ -0,0 +1,11 @@
+Image 		       	*Image_Elixir_ToInternal (Image_Elixir *in, int Nvalues);
+Image_Elixir 	       	*ImageInternalTo_Elixir (Image *in, int Nvalues);
+Average 	       	*Average_Elixir_ToInternal (Average_Elixir *in, int Nvalues, SecFilt **primary);
+Average_Elixir 	        *AverageInternalTo_Elixir (Average *in, int Nvalues, SecFilt *primary);
+Measure 	       	*Measure_Elixir_ToInternal (Measure_Elixir *in, int Nvalues);
+Measure_Elixir 	        *MeasureInternalTo_Elixir (Measure *in, int Nvalues);
+SecFilt 	       	*SecFilt_Elixir_ToInternal (SecFilt_Elixir *in, int Nvalues);
+SecFilt_Elixir 	       	*SecFiltInternalTo_Elixir (SecFilt *in, int Nvalues);
+
+PhotCode *PhotCode_Elixir_To_Internal (PhotCode_Elixir *in, int Nvalues);
+PhotCode_Elixir *PhotCode_Internal_To_Elixir (PhotCode *in, int Nvalues);
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/include/loneos_defs.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/include/loneos_defs.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/include/loneos_defs.h	(revision 16632)
@@ -0,0 +1,8 @@
+Image 		       	*Image_Loneos_ToInternal (Image_Loneos *in, int Nvalues);
+Image_Loneos 	       	*ImageInternalTo_Loneos (Image *in, int Nvalues);
+Average                	*Average_Loneos_ToInternal (Average_Loneos *in, int Nvalues, SecFilt **primary);
+Average_Loneos 	        *AverageInternalTo_Loneos (Average *in, int Nvalues, SecFilt *primary);
+Measure                	*Measure_Loneos_ToInternal (Measure_Loneos *in, int Nvalues);
+Measure_Loneos 	        *MeasureInternalTo_Loneos (Measure *in, int Nvalues);
+SecFilt 	       	*SecFilt_Loneos_ToInternal (SecFilt_Loneos *in, int Nvalues);
+SecFilt_Loneos 	       	*SecFiltInternalTo_Loneos (SecFilt *in, int Nvalues);
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/include/panstarrs_dev_0_defs.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/include/panstarrs_dev_0_defs.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/include/panstarrs_dev_0_defs.h	(revision 16632)
@@ -0,0 +1,8 @@
+Image 		       	*Image_Panstarrs_DEV_0_ToInternal (Image_Panstarrs_DEV_0 *in, int Nvalues);
+Image_Panstarrs_DEV_0  	*ImageInternalTo_Panstarrs_DEV_0 (Image *in, int Nvalues);
+Average 	       	*Average_Panstarrs_DEV_0_ToInternal (Average_Panstarrs_DEV_0 *in, int Nvalues, SecFilt **primary);
+Average_Panstarrs_DEV_0 *AverageInternalTo_Panstarrs_DEV_0 (Average *in, int Nvalues, SecFilt *primary);
+Measure 	       	*Measure_Panstarrs_DEV_0_ToInternal (Measure_Panstarrs_DEV_0 *in, int Nvalues);
+Measure_Panstarrs_DEV_0 *MeasureInternalTo_Panstarrs_DEV_0 (Measure *in, int Nvalues);
+SecFilt 	       	*SecFilt_Panstarrs_DEV_0_ToInternal (SecFilt_Panstarrs_DEV_0 *in, int Nvalues);
+SecFilt_Panstarrs_DEV_0 *SecFiltInternalTo_Panstarrs_DEV_0 (SecFilt *in, int Nvalues);
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/include/panstarrs_dev_1_defs.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/include/panstarrs_dev_1_defs.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/include/panstarrs_dev_1_defs.h	(revision 16632)
@@ -0,0 +1,8 @@
+Image 		       	*Image_Panstarrs_DEV_1_ToInternal (Image_Panstarrs_DEV_1 *in, int Nvalues);
+Image_Panstarrs_DEV_1  	*ImageInternalTo_Panstarrs_DEV_1 (Image *in, int Nvalues);
+Average 	       	*Average_Panstarrs_DEV_1_ToInternal (Average_Panstarrs_DEV_1 *in, int Nvalues, SecFilt **primary);
+Average_Panstarrs_DEV_1 *AverageInternalTo_Panstarrs_DEV_1 (Average *in, int Nvalues, SecFilt *primary);
+Measure 	       	*Measure_Panstarrs_DEV_1_ToInternal (Measure_Panstarrs_DEV_1 *in, int Nvalues);
+Measure_Panstarrs_DEV_1 *MeasureInternalTo_Panstarrs_DEV_1 (Measure *in, int Nvalues);
+SecFilt 	       	*SecFilt_Panstarrs_DEV_1_ToInternal (SecFilt_Panstarrs_DEV_1 *in, int Nvalues);
+SecFilt_Panstarrs_DEV_1 *SecFiltInternalTo_Panstarrs_DEV_1 (SecFilt *in, int Nvalues);
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/include/ps1_dev_1_defs.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/include/ps1_dev_1_defs.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/include/ps1_dev_1_defs.h	(revision 16632)
@@ -0,0 +1,11 @@
+Image 		       	*Image_PS1_DEV_1_ToInternal (Image_PS1_DEV_1 *in, int Nvalues);
+Image_PS1_DEV_1  	*ImageInternalTo_PS1_DEV_1 (Image *in, int Nvalues);
+Average 	       	*Average_PS1_DEV_1_ToInternal (Average_PS1_DEV_1 *in, int Nvalues, SecFilt **primary);
+Average_PS1_DEV_1       *AverageInternalTo_PS1_DEV_1 (Average *in, int Nvalues, SecFilt *primary);
+Measure 	       	*Measure_PS1_DEV_1_ToInternal (Measure_PS1_DEV_1 *in, int Nvalues);
+Measure_PS1_DEV_1       *MeasureInternalTo_PS1_DEV_1 (Measure *in, int Nvalues);
+SecFilt 	       	*SecFilt_PS1_DEV_1_ToInternal (SecFilt_PS1_DEV_1 *in, int Nvalues);
+SecFilt_PS1_DEV_1       *SecFiltInternalTo_PS1_DEV_1 (SecFilt *in, int Nvalues);
+
+PhotCode *PhotCode_PS1_DEV_1_To_Internal (PhotCode_PS1_DEV_1 *in, int Nvalues);
+PhotCode_PS1_DEV_1 *PhotCode_Internal_To_PS1_DEV_1 (PhotCode *in, int Nvalues);
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/lib/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/lib/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/lib/.cvsignore	(revision 16632)
@@ -0,0 +1,3 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.darwin.dylib
+*.darwin_x86.dylib
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodes.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include <dvo.h>
+
+int LoadPhotcodes (char *catdir_file, char *master_file) {
+
+  /* first try to load the photcodes from the specified CATDIR location */
+  if (LoadPhotcodesFITS (catdir_file)) return TRUE;
+  
+  /* next try to load the photcodes from the master text photcode file */
+  /* automatically (or on demand?) save the text file to the FITS version */
+  if (LoadPhotcodesText (master_file)) { 
+      if (!check_file_access (catdir_file, TRUE, TRUE)) return TRUE;
+      SavePhotcodesFITS (catdir_file);
+      return TRUE;
+  }
+
+  return FALSE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodesFITS.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodesFITS.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodesFITS.c	(revision 16632)
@@ -0,0 +1,123 @@
+# include <dvo.h>
+
+/* this is a read-only function to load the FITS photcode file into the internal photcode table */
+/* locking is used to avoid collisions with programs trying to update the photcodes values */
+/* XXX better distinction between NOT FOUND and FAILURE */
+int LoadPhotcodesFITS (char *filename) {
+
+  PhotCodeData *table = NULL;
+  PhotCode *photcode;
+  FITS_DB db;
+  char extname[80];
+
+  int i, code, Ncode, Nsec, Nsecfilt;
+
+  /* XXX choose more sensible lock timeouts! */
+  db.lockstate = LCK_SOFT;
+  db.timeout   = 10.0;
+  gfits_db_init (&db);
+
+  /* does this mean the db is empty, non-existent, or has access errors? */
+  // XXX we need better error handling here
+  if (!gfits_db_lock (&db, filename)) {
+    // fprintf (stderr, "ERROR: failure to lock db\n");
+    gfits_db_close (&db);
+    return FALSE;
+  }
+  if (db.dbstate == LCK_EMPTY) {
+    // fprintf (stderr, "ERROR: db is empty\n");
+    gfits_db_close (&db);
+    return FALSE;
+  } 
+  if (!gfits_db_load (&db)) {
+    // fprintf (stderr, "ERROR: failure to load db\n");
+    gfits_db_close (&db);
+    return FALSE;
+  }
+  gfits_db_close (&db);
+
+  /* convert FITS format data to internal format (just byteswaps) */
+  gfits_scan (&db.theader, "EXTNAME", "%s", 1, extname);
+
+  if (!strcmp (extname, "DVO_PHOTCODE") || !strcmp (extname, "DVO_PHOTCODE_ELIXIR")) {
+    PhotCode_Elixir *photcode_elixir = gfits_table_get_PhotCode_Elixir (&db.ftable, &Ncode, &db.swapped);
+    photcode = PhotCode_Elixir_To_Internal (photcode_elixir, Ncode);
+    free (photcode_elixir);
+  } 
+
+  if (!strcmp (extname, "DVO_PHOTCODE_PS1_DEV_1")) {
+    PhotCode_PS1_DEV_1 *photcode_ps1_dev_1 = gfits_table_get_PhotCode_PS1_DEV_1 (&db.ftable, &Ncode, &db.swapped);
+    photcode = PhotCode_PS1_DEV_1_To_Internal (photcode_ps1_dev_1, Ncode);
+    free (photcode_ps1_dev_1);
+  } 
+
+  table = GetPhotcodeTable ();
+  if (table[0].code != NULL) free (table[0].code);
+  /* we are using a 16-bit int for the photcodes, so these indexes can be fixed-length */
+  /* XXX if we need to go with a larger photcode, we'll need to use a sequenced index and a
+     binary search to get to a given value (0x100000000 ints would take quite a few
+     bytes...) */
+  for (i = 0; i < 0x10000; i++) {
+    table[0].hashcode[i] = -1;
+    table[0].hashNsec[i] = -1;
+    table[0].codeNsec[i] = -1;
+  }
+
+  /* set up photcode indexes (see dvo_photcode_ops.c) */
+  Nsecfilt = 0;
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_ALT) continue; /* no hashcode for ALT codes */
+    if (table[0].hashcode[photcode[i].code] != -1) {
+      fprintf (stderr, "duplicate photcodes in file\n");
+      code = table[0].hashcode[photcode[i].code];
+      fprintf (stderr, "conflict between %s (%d) and %s (%d)\n",
+	       photcode[i].name, photcode[i].code, photcode[code].name, photcode[code].code);
+      free (photcode);
+      return FALSE;
+    }
+    table[0].hashcode[photcode[i].code] = i;
+    if (photcode[i].type == PHOT_SEC) {
+      table[0].hashNsec[photcode[i].code] = Nsecfilt;
+      table[0].codeNsec[Nsecfilt] = photcode[i].code;
+      Nsecfilt ++;
+    }
+  }
+
+  // validity check for references
+  // photcode.equiv of 0 means "undefined"
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_DEP) {
+      if (photcode[i].equiv == 0) continue;
+      Nsec = table[0].hashcode[photcode[i].equiv];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for dependent photcode is not in photcodes\n");
+	free (photcode);
+	return FALSE;
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for dependent photcode is not an average photcode\n");
+	free (photcode);
+	return FALSE;
+      }
+    }
+    if (photcode[i].type == PHOT_ALT) {
+      Nsec = table[0].hashcode[photcode[i].code];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for alternate photcode is not in photcodes\n");
+	free (photcode);
+	return FALSE;
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for alternate photcode is not an average photcode\n");
+	free (photcode);
+	return FALSE;
+      }
+    }
+  }
+
+  table[0].code     = photcode;
+  table[0].Ncode    = Ncode;
+  table[0].Nsecfilt = Nsecfilt;
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodesText.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodesText.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/LoadPhotcodesText.c	(revision 16632)
@@ -0,0 +1,230 @@
+# include <dvo.h>
+
+static int PhotcodeNumberOrName (char *word) {
+
+  int value;
+  char *endpt;
+
+  if (!strcmp (word, "-")) return (0);
+
+  value = strtol (word, &endpt, 10);
+  if (endpt != word + strlen(word)) {
+    value = GetPhotcodeCodebyName (word);
+  }
+  return (value);
+}
+
+/* load the text photcode table */
+int LoadPhotcodesText (char *filename) {
+  
+  /* XXX fix these */
+  PhotCodeData *table = NULL;
+  PhotCode *photcode;
+
+  FILE *f;
+  int i, Nsecfilt, Nsec, Ncode, NPHOTCODE, Nfield;
+  int code;
+  char *c;
+  char line[256], **c1_names, **c2_names, **eq_names;
+  char name[32], type[32], Zero[32], Airmass[32], Offset[32],
+    C1[32], C2[32], Slope[32], Color[32], Primary[32];
+
+  table = GetPhotcodeTable ();
+  if (table[0].code != NULL) free (table[0].code);
+  /* we are using a 16-bit int for the photcodes, so these indexes can be fixed-length */
+  /* XXX if we need to go with a larger photcode, we'll need to use a sequenced index and a
+     binary search to get to a given value (0x100000000 ints would take quite a few
+     bytes...) */
+  for (i = 0; i < 0x10000; i++) {
+    table[0].hashcode[i] = -1;
+    table[0].hashNsec[i] = -1;
+    table[0].codeNsec[i] = -1;
+  }
+
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    table[0].Ncode    = 0;
+    table[0].Nsecfilt = 0;
+    table[0].code     = (PhotCode *) NULL;
+    return (FALSE);
+  }
+
+  Ncode = 0;
+  NPHOTCODE = 10;
+  ALLOCATE (photcode, PhotCode, NPHOTCODE);
+  ALLOCATE (eq_names, char *,   NPHOTCODE);
+  ALLOCATE (c1_names, char *,   NPHOTCODE);
+  ALLOCATE (c2_names, char *,   NPHOTCODE);
+
+  while (scan_line (f, line) != EOF) {
+    for (c = line; isspace (*c); c++);
+    if (*c == '#') continue;
+    Nfield = sscanf (c, "%d %s %s %s %s %s %s %s %s %s %s", 
+		     &code, name, type, Zero, Airmass, Offset, C1, C2, Slope, Color, Primary);
+
+    // XXX to add the AstromError (and PhotError) terms, we need to add them to the photcode structure, and
+    // define methods to read (at least) the old and the new photcode versions.
+
+    if (Nfield != 11) { continue; }
+    
+    if (!code) {
+	fprintf (stderr, "photcode values may not be 0: fix %s\n", name);
+	return (FALSE);
+    }
+
+    photcode[Ncode].type = 0;
+    photcode[Ncode].code = code;
+    memset (photcode[Ncode].name, 0, 32);
+    strcpy (photcode[Ncode].name, name);
+
+    if (!strncasecmp (type, "pri", 3)) {
+      photcode[Ncode].type  = PHOT_SEC;
+    }
+    if (!strncasecmp (type, "sec", 3)) {
+      photcode[Ncode].type  = PHOT_SEC;
+    }
+    if (!strncasecmp (type, "dep", 3)) {
+      photcode[Ncode].type  = PHOT_DEP;
+    }
+    if (!strncasecmp (type, "ref", 3)) {
+      photcode[Ncode].type  = PHOT_REF;
+    }
+    if (!strncasecmp (type, "alt", 3)) {
+      /* alt photcodes are a little different: they have the SAME photcode as an existing
+	 pri/sec photcode, but define an alternate transformation for that code */
+      photcode[Ncode].type  = PHOT_ALT;
+    }
+
+    switch (photcode[Ncode].type) {
+      case PHOT_SEC:
+      case PHOT_ALT:
+      case PHOT_DEP:
+	photcode[Ncode].C     = 1000*atof (Zero);
+	photcode[Ncode].K     = atof (Airmass);
+	photcode[Ncode].dC    = 1000*atof (Offset);
+	photcode[Ncode].dX    = 1000*atof (Color);
+	c1_names[Ncode]       = strcreate (C1);
+	c2_names[Ncode]       = strcreate (C2);
+	eq_names[Ncode]       = strcreate (Primary);
+	ParseColorTerms (Slope, photcode[Ncode].X, &photcode[Ncode].Nc);
+	break;
+
+      case PHOT_REF:
+	photcode[Ncode].C     = 0;
+	photcode[Ncode].K     = 0;
+	photcode[Ncode].dC    = 0;
+	photcode[Ncode].dX    = 0;
+	c1_names[Ncode]       = strcreate ("0");
+	c2_names[Ncode]       = strcreate ("0");
+	eq_names[Ncode]       = strcreate (Primary);
+	photcode[Ncode].X[0]  = 0;
+	photcode[Ncode].Nc    = 0;
+	break;
+
+      default:
+	fprintf (stderr, "error: invalid photcode type\n");
+	exit (2);
+    }      
+
+    if (!photcode[Ncode].type) {
+      fprintf (stderr, "error in Photfile: unknown type %s\n", type);
+    }
+
+    Ncode++;
+    if (Ncode == NPHOTCODE) {
+      NPHOTCODE += 10;
+      REALLOCATE (photcode, PhotCode, NPHOTCODE);
+      REALLOCATE (eq_names, char *,   NPHOTCODE);
+      REALLOCATE (c1_names, char *,   NPHOTCODE);
+      REALLOCATE (c2_names, char *,   NPHOTCODE);
+    }
+  }
+  fclose (f);
+  
+  // convert the named references (c1, c2, equiv) to code values
+  for (i = 0; i < Ncode; i++) {
+    photcode[i].c1    = PhotcodeNumberOrName (c1_names[i]);
+    photcode[i].c2    = PhotcodeNumberOrName (c2_names[i]);
+    photcode[i].equiv = PhotcodeNumberOrName (eq_names[i]);
+    free (c1_names[i]);
+    free (c2_names[i]);
+    free (eq_names[i]);
+  }
+  free (c1_names);
+  free (c2_names);
+  free (eq_names);
+
+  /* set up photcode indexes (see dvo_photcode_ops.c) */
+  Nsecfilt = 0;
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_ALT) continue; /* no hashcode for ALT codes */
+    if (table[0].hashcode[photcode[i].code] != -1) {
+      fprintf (stderr, "duplicate photcodes in file\n");
+      code = table[0].hashcode[photcode[i].code];
+      fprintf (stderr, "conflict between %s (%d) and %s (%d)\n",
+	       photcode[i].name, photcode[i].code, photcode[code].name, photcode[code].code);
+      free (photcode);
+      return (FALSE);
+    }
+    table[0].hashcode[photcode[i].code] = i;
+    if (photcode[i].type == PHOT_SEC) {
+      table[0].hashNsec[photcode[i].code] = Nsecfilt;
+      table[0].codeNsec[Nsecfilt] = photcode[i].code;
+      Nsecfilt ++;
+    }
+  }
+
+  // validity check for references
+  // photcode.equiv of 0 means "undefined"
+  for (i = 0; i < Ncode; i++) {
+    if (photcode[i].type == PHOT_DEP) {
+      if (photcode[i].equiv == 0) continue;
+      Nsec = table[0].hashcode[photcode[i].equiv];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for dependent photcode is not a valid photcode\n");
+	free (photcode);
+	return (FALSE);
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for dependent photcode is not an average photcode\n");
+	free (photcode);
+	return (FALSE);
+      }
+    }
+    if (photcode[i].type == PHOT_ALT) {
+      Nsec = table[0].hashcode[photcode[i].code];
+      if ((Nsec >= Ncode) || (Nsec < 0)) {
+	fprintf (stderr, "reference for alternate photcode is not in photcodes\n");
+	free (photcode);
+	return (FALSE);
+      }
+      if (photcode[Nsec].type != PHOT_SEC) {
+	fprintf (stderr, "reference for alternate photcode is not an average photcode\n");
+	free (photcode);
+	return (FALSE);
+      }
+    }
+  }
+  table[0].code     = photcode;
+  table[0].Ncode    = Ncode;
+  table[0].Nsecfilt = Nsecfilt;
+
+  return (TRUE);
+}
+
+# define NCTERMS 4
+void ParseColorTerms (char *terms, float *X, int *N) {
+
+  int i;
+  char *p;
+
+  p = terms;
+
+  for (i = 0; (p != NULL) && (i < NCTERMS); i++) {
+    X[i] = atof (p);
+    p = strchr (p, ',');
+    if (p == (char *) NULL) continue;
+    p ++;
+  }
+  *N = i;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/SavePhotcodesFITS.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/SavePhotcodesFITS.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/SavePhotcodesFITS.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include <dvo.h>
+
+/* this function saves the FITS photcode file into the internal photcode table */
+/* locking is used to avoid collisions with programs trying to update the photcodes values */
+/* XXX better distinction between NOT FOUND and FAILURE */
+int SavePhotcodesFITS (char *filename) {
+
+  PhotCodeData *table = NULL;
+  FITS_DB db;
+
+  table = GetPhotcodeTable ();
+  if (table == NULL) {
+    fprintf (stderr, "ERROR: no internal photcode table is defined\n");
+    return FALSE;
+  }
+
+  /* XXX choose more sensible lock timeouts! */
+  db.lockstate = LCK_XCLD;
+  db.timeout   = 10.0;
+  gfits_db_init (&db);
+
+  /* does this mean the db is empty, non-existent, or has access errors? */
+  if (!gfits_db_lock (&db, filename)) {
+    fprintf (stderr, "ERROR: failure to lock db, cannot save photcode table to %s\n", filename);
+    gfits_db_close (&db);
+    return FALSE;
+  }
+
+  // for the moment, we simply support the latest photcode format for output
+  // XXX update this as needed as new formats are defined
+  PhotCode_PS1_DEV_1 *photcode_output = PhotCode_Internal_To_PS1_DEV_1 (table[0].code, table[0].Ncode);
+
+  /* convert FITS format data to internal format (byteswaps & EXTNAME) */
+  gfits_db_create (&db);
+  gfits_table_set_PhotCode_PS1_DEV_1 (&db.ftable, photcode_output, table[0].Ncode);
+  gfits_db_save (&db);
+  gfits_db_close (&db);
+
+  free (photcode_output);
+
+  return TRUE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/SavePhotcodesText.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/SavePhotcodesText.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/SavePhotcodesText.c	(revision 16632)
@@ -0,0 +1,94 @@
+# include <dvo.h>
+# define SCALE 0.001
+
+static char *PHOT_SEC_NAME = "sec";
+static char *PHOT_ALT_NAME = "alt";
+static char *PHOT_REF_NAME = "ref";
+static char *PHOT_DEP_NAME = "dep";
+
+/* this function saves the FITS photcode file into the internal photcode table */
+/* locking is used to avoid collisions with programs trying to update the photcodes values */
+/* XXX better distinction between NOT FOUND and FAILURE */
+int SavePhotcodesText (char *filename) {
+
+  PhotCodeData *table = NULL;
+  struct stat filestat;
+  char *type;
+  int i, j, status;
+  FILE *f;
+
+  table = GetPhotcodeTable ();
+  if (table == NULL) {
+    fprintf (stderr, "ERROR: no internal photcode table is defined\n");
+    return FALSE;
+  }
+
+  /* check if file exists */
+  status = stat (filename, &filestat);
+  if (status == -1) {
+    if (errno != ENOENT) {
+      fprintf (stderr, "ERROR: problem accessing output path for%s\n", filename);
+      return FALSE;
+    }
+  } else {
+    make_backup (filename);
+  } 
+
+  f = fopen (filename, "w");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: problem creating photcode file %s\n", filename);
+    return FALSE;
+  }
+
+  for (i = 0; i < table[0].Ncode; i++) {
+    switch (table[0].code[i].type) {
+      case PHOT_SEC:
+	type = PHOT_SEC_NAME;
+	break;
+      case PHOT_ALT:
+	type = PHOT_ALT_NAME;
+	break;
+      case PHOT_REF:
+	type = PHOT_REF_NAME;
+	break;
+      case PHOT_DEP:
+	type = PHOT_DEP_NAME;
+	break;
+      default:
+	fprintf (stderr, "ERROR: problem with photcode type for %s\n", GetPhotcodeNamebyCode(table[0].code[i].code));
+	return FALSE;
+    }
+
+    fprintf (f, "  %-5d %-18s  %4s  %6.3f %6.3f %5.3f ",
+	     table[0].code[i].code,
+	     GetPhotcodeNamebyCode (table[0].code[i].code),
+	     type,
+	     table[0].code[i].C*SCALE, 
+	     table[0].code[i].K*SCALE, 
+	     table[0].code[i].dC*SCALE);
+
+    PrintPhotcodeNamebyCode (f, "%5d ", table[0].code[i].c1);
+    PrintPhotcodeNamebyCode (f, "%5d ", table[0].code[i].c2);
+
+    for (j = 0; j < table[0].code[i].Nc - 1; j++) {
+      fprintf (f, " %f,", table[0].code[i].X[j]);
+    }
+    fprintf (f, "%f %d ", table[0].code[i].X[j], table[0].code[i].dX);
+    PrintPhotcodeNamebyCode (f, "%5d ", table[0].code[i].equiv);
+    fprintf (f, "\n");
+  }
+  fclose (f);
+  return TRUE;
+}
+
+void PrintPhotcodeNamebyCode (FILE *f, char *format, int code) {
+
+  char *name;
+  
+  name = GetPhotcodeNamebyCode (code);
+  if (name == NULL) {
+    fprintf (f, "    - ");
+  } else {
+    fprintf (f, format, code);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/coordops.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/coordops.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/coordops.c	(revision 16632)
@@ -0,0 +1,742 @@
+# include <dvo.h>
+
+static Coords *mosaic = NULL;
+
+void RegisterMosaic (Coords *coords) {
+  mosaic = coords;
+}
+
+int XY_to_LM (double *L, double *M, double x, double y, Coords *coords) {
+
+  double X, Y;
+
+  /** convert pixel coordinates to cartesian system **/
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+
+  *L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  *M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+
+  /** extra polynomial terms **/
+  if (coords[0].Npolyterms > 1) {
+    *L += X*X*coords[0].polyterms[0][0] + X*Y*coords[0].polyterms[1][0] + Y*Y*coords[0].polyterms[2][0];
+    *M += X*X*coords[0].polyterms[0][1] + X*Y*coords[0].polyterms[1][1] + Y*Y*coords[0].polyterms[2][1];
+  }
+  if (coords[0].Npolyterms > 2) {
+    *L += X*X*X*coords[0].polyterms[3][0] + X*X*Y*coords[0].polyterms[4][0] + X*Y*Y*coords[0].polyterms[5][0] + Y*Y*Y*coords[0].polyterms[6][0];
+    *M += X*X*X*coords[0].polyterms[3][1] + X*X*Y*coords[0].polyterms[4][1] + X*Y*Y*coords[0].polyterms[5][1] + Y*Y*Y*coords[0].polyterms[6][1];
+  }
+
+  return (TRUE);
+}
+
+int LM_to_RD (double *ra, double *dec, double L, double M, Coords *coords) {
+
+  OhanaProjection proj;
+  OhanaProjectionMode mode;
+  double R, T, Z, Z2, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+
+  proj = GetProjection (coords[0].ctype);
+  mode = GetProjectionMode (proj);
+  if (proj == PROJ_NONE) return (FALSE);
+  if (proj == PROJ_MODE_NONE) return (FALSE);
+
+  stht = ctht = 1;
+
+  /** Locally Cartesian Projections **/
+  if (mode == PROJ_MODE_CARTESIAN) {
+    *ra  = L + coords[0].crval1;
+    *dec = M + coords[0].crval2;
+
+    /* mosaic astrometry : WRP is chip astrometry; apply mosaic (DIS) term */
+    if (proj == PROJ_WRP) {
+      if (mosaic == NULL) return (FALSE);
+      XY_to_RD (ra, dec, *ra, *dec, mosaic);
+    }
+    return (TRUE);
+  }
+  
+  /** Zenithal Projections **/
+  if (mode == PROJ_MODE_ZENITHAL) {
+    R = hypot (L,M);
+    if ((L == 0) && (M == 0)) {
+      sphi = 0;
+      cphi = 1;
+    } else {
+      sphi =  L / R;
+      cphi = -M / R;
+    }
+
+    switch (proj) {
+      case PROJ_TAN:
+      case PROJ_DIS:
+	// R = cot (theta) = cos(theta) / sin(theta)
+	if (R == 0) {
+	  stht = 1.0;
+	  ctht = 0.0;
+	} else {
+	  T = DEG_RAD / R;
+	  stht =   T / sqrt ( 1.0 + T*T);
+	  ctht = 1.0 / sqrt ( 1.0 + T*T);
+	}
+	break;
+      case PROJ_STG:
+	// R = (180/pi) [2 cos (theta)  / 1 + sin (theta)]
+	stht = (4 - RAD_DEG*R) / (4 + RAD_DEG*R);
+	ctht = sqrt (1 - stht*stht);
+	break;
+      case PROJ_SIN:
+	// R = (180/pi) cos (theta)
+	ctht = RAD_DEG * R;
+	stht = sqrt (1 - ctht*ctht);
+	break;
+      case PROJ_ARC:
+	// R = 90 - theta (degrees)
+	ctht = sin (RAD_DEG * R);
+	stht = cos (RAD_DEG * R);
+	break;
+      case PROJ_ZEA:
+      case PROJ_ZPL:
+	if (R > 2*DEG_RAD) {
+	  *ra = L;
+	  *dec = M;
+	  return (FALSE);
+	}
+	stht = 1 - 0.5*SQ(R*RAD_DEG);
+	ctht = sqrt (1 - stht*stht);
+	break;
+      default:
+	return (FALSE);
+    }
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+    sdel = stht*sdp - ctht*cphi*cdp;
+    salp = ctht*sphi;
+    calp = stht*cdp + ctht*cphi*sdp;
+    alpha = atan2 (salp, calp);
+    delta = asin (sdel);
+    
+    *ra  = DEG_RAD*alpha + coords[0].crval1;
+    *dec = DEG_RAD*delta;
+
+    /* rationalize ra range 0 - 360.0 */
+    while (*ra < 0.0)   *ra += 360.0;
+    while (*ra > 360.0) *ra -= 360.0;
+
+    return (TRUE);
+  }
+  
+  /**** Other Conventional Projections ****/
+  if (mode == PROJ_MODE_PSEUDOCYL) {
+    switch (proj) {
+      case PROJ_AIT:
+      Z2 = (1.0 - SQ(RAD_DEG*0.25*L) - SQ(RAD_DEG*0.5*M));
+      if (Z2 < 0) return (FALSE);
+      Z = sqrt (Z2);
+      alpha = 2.0 * DEG_RAD * atan2 (RAD_DEG*0.5*Z*L, 2.0*Z2 - 1.0);
+      delta = DEG_RAD * asin (RAD_DEG*M*Z);
+      break;
+      
+      case PROJ_GLS:
+	/* L,M in degrees, alpha,delta in degrees */
+	alpha = L / cos (RAD_DEG * M);
+	delta = M;
+	break;
+      case PROJ_PAR:
+	/* L,M in degrees, alpha,delta in degrees */
+	alpha = L / (1.0 - SQ(2.0*M/180));
+	delta = 3 * DEG_RAD * asin (M/180.0);
+	break;
+      default:
+	return (FALSE);
+    }
+    *ra  = alpha + coords[0].crval1;
+    *dec = delta + coords[0].crval2;
+
+    /* rationalize ra range 0 - 360.0 */
+    while (*ra < 0.0)   *ra += 360.0;
+    while (*ra > 360.0) *ra -= 360.0;
+
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+int RD_to_LM (double *L, double *M, double ra, double dec, Coords *coords) {
+
+  double phi, theta;
+  double Lo, Mo;
+  double sphi, cphi, stht, ctht;
+  double salp, calp, sdel, cdel, sdp, cdp;
+  double P, A, Rc;
+  OhanaProjection proj;
+  OhanaProjectionMode mode;
+
+  *L = *M = 0;
+
+  proj = GetProjection (coords[0].ctype);
+  mode = GetProjectionMode (proj);
+  if (proj == PROJ_NONE) return (FALSE);
+  if (proj == PROJ_MODE_NONE) return (FALSE);
+
+  /**** Locally Cartesian Projections ****/
+  if (mode == PROJ_MODE_CARTESIAN) {
+    if (proj == PROJ_WRP) {
+      if (mosaic == NULL) return (FALSE);
+      RD_to_XY (&Lo, &Mo, ra, dec, mosaic);
+      *L = (Lo - coords[0].crval1);
+      *M = (Mo - coords[0].crval2);
+      return (TRUE);
+    }
+    *L = (ra  - coords[0].crval1);
+    *M = (dec - coords[0].crval2);
+    return (TRUE);
+  }
+  
+  /**** Zenithal Projections ****/
+  if (mode == PROJ_MODE_ZENITHAL) {
+    sdp  = sin(RAD_DEG*coords[0].crval2);
+    cdp  = cos(RAD_DEG*coords[0].crval2);
+    salp = sin(RAD_DEG*(ra - coords[0].crval1));
+    calp = cos(RAD_DEG*(ra - coords[0].crval1));
+    sdel = sin(RAD_DEG*dec);
+    cdel = cos(RAD_DEG*dec);
+
+    stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+    sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+    cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+
+    // L = +R sin(phi)
+    // M = -R cos(phi)
+
+    switch (proj) {
+      case PROJ_TAN:
+      case PROJ_DIS:
+	// R = cot (theta) = cos(theta) / sin(theta)
+	Rc = hypot(sphi, cphi);
+	*L = (stht == 0) ? 180.0 * sphi / Rc :  +DEG_RAD * sphi / stht;
+	*M = (stht == 0) ? 180.0 * cphi / Rc :  -DEG_RAD * cphi / stht;
+	return (stht > 0);
+      case PROJ_STG:
+	// R = 2 cos(theta) / [1 + sin(theta)]
+	Rc = DEG_RAD * 2 / (1 + stht);
+	*L = +Rc * sphi;
+	*M = -Rc * cphi;
+	return (stht > 0);
+      case PROJ_SIN:
+	// R = cos(theta)
+	*L = +DEG_RAD * sphi;
+	*M = -DEG_RAD * cphi;
+	return (stht > 0);
+      case PROJ_ARC:
+	// R = 90 - theta
+	ctht = hypot(sphi, cphi);
+	theta = atan2 (stht, ctht);
+	Rc = 90 - DEG_RAD * theta;
+	*L = (ctht == 0.0) ? 0.0 : +Rc * sphi / ctht ;
+	*M = (ctht == 0.0) ? 0.0 : -Rc * cphi / ctht ;
+	return (TRUE);
+      case PROJ_ZEA:
+      case PROJ_ZPL:
+	// R = 90 - theta
+	Rc = DEG_RAD * M_SQRT2 / sqrt (1 + stht);
+	*L =  Rc * sphi;
+	*M = -Rc * cphi;
+	return (stht > 0);
+      default:
+	return (FALSE);
+    }
+    return (FALSE);
+  }
+
+  /**** Other Standard Projections ****/
+  if (mode == PROJ_MODE_PSEUDOCYL) {
+    switch (proj) {
+      case PROJ_AIT:
+	phi = RAD_DEG*(ra - coords[0].crval1);
+	theta = RAD_DEG*(dec - coords[0].crval2);
+	P = 1.0 + cos (theta) * cos (0.5*phi);
+	if (P == 0.0) {
+	  *L =  0.0;
+	  *M =  0.0;
+	  return (TRUE);
+	} 
+	A =  DEG_RAD * sqrt (2.0 / P);
+	*L =  2.0 * A * cos (theta) * sin (0.5*phi);
+	*M =  A * sin (theta);
+	return (TRUE);
+      case PROJ_GLS:
+	phi = ra - coords[0].crval1;
+	theta = dec - coords[0].crval2;
+	*L = phi * cos(RAD_DEG * theta);
+	*M = theta;
+	return (TRUE);
+      case PROJ_PAR:
+	phi = ra - coords[0].crval1;
+	theta = dec - coords[0].crval2;
+	*L = phi * (2.0*cos(2*RAD_DEG*theta/3.0) - 1);
+	*M = 180.0 * sin (RAD_DEG*theta/3.0);
+	return (TRUE);
+      default:
+	return (FALSE);
+    }
+    return (FALSE);
+  }
+  return (FALSE);
+}
+
+int LM_to_XY (double *x, double *y, double L, double M, Coords *coords) {
+
+  int i;
+  double determ;
+  double X, Y, Lo, Mo, dL, dM;
+
+  *x = 0;
+  *y = 0;
+
+  /* convert L,M to X,Y */
+  determ = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  X = determ * (coords[0].pc2_2*L - coords[0].pc1_2*M);
+  Y = determ * (coords[0].pc1_1*M - coords[0].pc2_1*L);
+
+  /** extra polynomial terms **/
+  if (coords[0].Npolyterms > 1) {
+    for (i = 0; i < 10; i++) {
+      Lo = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+      Mo = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+      if (coords[0].Npolyterms > 1) {
+	Lo += X*X*coords[0].polyterms[0][0] + X*Y*coords[0].polyterms[1][0] + Y*Y*coords[0].polyterms[2][0];
+	Mo += X*X*coords[0].polyterms[0][1] + X*Y*coords[0].polyterms[1][1] + Y*Y*coords[0].polyterms[2][1];
+      }
+      if (coords[0].Npolyterms > 2) {
+	Lo += X*X*X*coords[0].polyterms[3][0] + X*X*Y*coords[0].polyterms[4][0] + X*Y*Y*coords[0].polyterms[5][0] + Y*Y*Y*coords[0].polyterms[6][0];
+	Mo += X*X*X*coords[0].polyterms[3][1] + X*X*Y*coords[0].polyterms[4][1] + X*Y*Y*coords[0].polyterms[5][1] + Y*Y*Y*coords[0].polyterms[6][1];
+      }
+      dL = (L - Lo);
+      dM = (M - Mo);
+
+      X += determ * (coords[0].pc2_2*dL - coords[0].pc1_2*dM);
+      Y += determ * (coords[0].pc1_1*dM - coords[0].pc2_1*dM);
+    }
+  }
+  /* check for correct size (iterate?) */
+
+  *x = X / coords[0].cdelt1 + coords[0].crpix1;
+  *y = Y / coords[0].cdelt2 + coords[0].crpix2;
+
+  return (TRUE);
+}
+
+int XY_to_RD (double *ra, double *dec, double x, double y, Coords *coords) {
+
+  double L, M;
+  int status;
+
+  status = XY_to_LM (&L, &M, x, y, coords);
+  if (!status) return FALSE;
+
+  status = LM_to_RD (ra, dec, L, M, coords);
+  return (status);
+}
+
+int RD_to_XY (double *x, double *y, double ra, double dec, Coords *coords) {
+
+  double L, M;
+  int status;
+
+  status = RD_to_LM (&L, &M, ra, dec, coords);
+
+  if (finite(L) && finite(M)) {
+      LM_to_XY (x, y, L, M, coords);
+  } else {
+      *x = L;
+      *y = M;
+  }
+  return (status);
+}
+
+int fRD_to_XY (float *x, float *y, double ra, double dec, Coords *coords) {
+
+  int status;
+  double tmpx, tmpy;
+
+  status = RD_to_XY (&tmpx, &tmpy, ra, dec, coords);
+  *x = tmpx;
+  *y = tmpy;
+  
+  return (status);
+
+}
+
+int fXY_to_RD (float *ra, float *dec, double x, double y, Coords *coords) {
+
+  int status;
+  double tmpr, tmpd;
+
+  status = XY_to_RD (&tmpr, &tmpd, x, y, coords);
+  *ra = tmpr;
+  *dec = tmpd;
+  
+  return (status);
+
+}
+
+int GetCoords (Coords *coords, Header *header) {
+  
+  int status, itmp, Polynomial, Polyterm;
+  double Lambda, rotate, scale;
+  double equinox;
+  char *ctype;
+  
+  rotate = 0.0;
+  coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+  coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+  coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+  coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+  coords[0].Npolyterms = 1;
+  strcpy (coords[0].ctype, "NONE");
+  
+  status = FALSE; 
+  if (gfits_scan (header, "CTYPE2", "%s", 1, coords[0].ctype)) {
+    status  = gfits_scan (header, "CRVAL1", "%lf", 1, &coords[0].crval1);
+    status &= gfits_scan (header, "CRPIX1", "%f", 1, &coords[0].crpix1);
+    status &= gfits_scan (header, "CRVAL2", "%lf", 1, &coords[0].crval2);  
+    status &= gfits_scan (header, "CRPIX2", "%f", 1, &coords[0].crpix2);
+
+    if (gfits_scan (header, "CDELT1", "%f", 1, &coords[0].cdelt1)) {
+      status &= gfits_scan (header, "CDELT2", "%f", 1, &coords[0].cdelt2);
+      if (gfits_scan (header, "CROTA2", "%lf", 1, &rotate)) {
+	Lambda = coords[0].cdelt2 / coords[0].cdelt1;
+	coords[0].pc1_1 =  cos(rotate*RAD_DEG);
+	coords[0].pc1_2 = -sin(rotate*RAD_DEG) * Lambda;
+	coords[0].pc2_1 =  sin(rotate*RAD_DEG) / Lambda;
+	coords[0].pc2_2 =  cos(rotate*RAD_DEG);
+      }
+      if (gfits_scan (header, "PC001001", "%f", 1, &coords[0].pc1_1)) {
+	status &= gfits_scan (header, "PC001002", "%f", 1, &coords[0].pc1_2);
+	status &= gfits_scan (header, "PC002001", "%f", 1, &coords[0].pc2_1);
+	status &= gfits_scan (header, "PC002002", "%f", 1, &coords[0].pc2_2);
+      }
+
+      /* set NPLYTERM based on header.  if NPLYTERM is missing, it should have a 
+	 value of 0, unless the projection type is one of PLY, DIS, WRP, in which
+	 case it should be set to 3 */
+      ctype = &coords[0].ctype[4];
+      Polynomial = !strcmp (ctype, "-PLY") || !strcmp (ctype, "-DIS") || !strcmp (ctype, "-WRP");
+      Polyterm = gfits_scan (header, "NPLYTERM", "%d", 1, &itmp);
+
+      coords[0].Npolyterms = 0;
+      if (Polynomial && !Polyterm) coords[0].Npolyterms = 1;
+      if (Polyterm) coords[0].Npolyterms = itmp;
+
+      switch (coords[0].Npolyterms) {
+	case 3:
+	  status &= gfits_scan (header, "PCA1X3Y0", "%f", 1, &coords[0].polyterms[3][0]);
+	  status &= gfits_scan (header, "PCA1X2Y1", "%f", 1, &coords[0].polyterms[4][0]);
+	  status &= gfits_scan (header, "PCA1X1Y2", "%f", 1, &coords[0].polyterms[5][0]);
+	  status &= gfits_scan (header, "PCA1X0Y3", "%f", 1, &coords[0].polyterms[6][0]);
+	  status &= gfits_scan (header, "PCA2X3Y0", "%f", 1, &coords[0].polyterms[3][1]);
+	  status &= gfits_scan (header, "PCA2X2Y1", "%f", 1, &coords[0].polyterms[4][1]);
+	  status &= gfits_scan (header, "PCA2X1Y2", "%f", 1, &coords[0].polyterms[5][1]);
+	  status &= gfits_scan (header, "PCA2X0Y3", "%f", 1, &coords[0].polyterms[6][1]);
+	case 2:
+	  status &= gfits_scan (header, "PCA1X2Y0", "%f", 1, &coords[0].polyterms[0][0]);
+	  status &= gfits_scan (header, "PCA1X1Y1", "%f", 1, &coords[0].polyterms[1][0]);
+	  status &= gfits_scan (header, "PCA1X0Y2", "%f", 1, &coords[0].polyterms[2][0]);
+	  status &= gfits_scan (header, "PCA2X2Y0", "%f", 1, &coords[0].polyterms[0][1]);
+	  status &= gfits_scan (header, "PCA2X1Y1", "%f", 1, &coords[0].polyterms[1][1]);
+	  status &= gfits_scan (header, "PCA2X0Y2", "%f", 1, &coords[0].polyterms[2][1]);
+	case 0:
+	case 1:
+	  break;
+      }
+    } else {
+      if (gfits_scan (header, "CD1_1", "%f", 1, &coords[0].pc1_1)) {
+	status &= gfits_scan (header, "CD1_2", "%f", 1, &coords[0].pc1_2);
+	status &= gfits_scan (header, "CD2_1", "%f", 1, &coords[0].pc2_1);
+	status &= gfits_scan (header, "CD2_2", "%f", 1, &coords[0].pc2_2);
+	/* renormalize */
+	scale = hypot (coords[0].pc1_1, coords[0].pc1_2);
+	coords[0].cdelt1 = coords[0].cdelt2 = scale;
+	coords[0].pc1_1 /= scale;
+	coords[0].pc1_2 /= scale;
+	coords[0].pc2_1 /= scale;
+	coords[0].pc2_2 /= scale;
+      } else {
+	status = FALSE;
+      }
+    }
+  } else {
+    /* some of my thesis data uses this simple linear model - convert on read? */
+    if (gfits_scan (header, "RA_O", "%lf", 1, &coords[0].crval1)) {
+      status  = gfits_scan (header, "RA_X", "%f", 1, &coords[0].pc1_1);
+      status &= gfits_scan (header, "RA_Y", "%f", 1, &coords[0].pc1_2);
+      status &= gfits_scan (header, "DEC_O", "%lf", 1, &coords[0].crval2);  
+      status &= gfits_scan (header, "DEC_X", "%f", 1, &coords[0].pc2_1);
+      status &= gfits_scan (header, "DEC_Y", "%f", 1, &coords[0].pc2_2);
+      coords[0].crpix1 = coords[0].crpix2 = 0.0;
+      coords[0].cdelt1 = coords[0].cdelt2 = 1.0;
+      strcpy (coords[0].ctype, "GENE");
+    }
+  }
+  if (status) {
+    if (!gfits_scan (header, "EQUINOX", "%lf", 1, &equinox)) {
+      if (!gfits_scan (header, "EPOCH", "%lf", 1, &equinox)) {
+	equinox = 2000.0;
+      }
+    }
+    if (fabs (equinox - 2000.0) > 0.1) {
+      coords_precess (&coords[0].crval1, &coords[0].crval2, equinox, 2000.0);
+    } 
+  }
+  if (!status) {
+    fprintf (stderr, "error getting all elements for coordinate mode %s\n", coords[0].ctype);
+    coords[0].crval1 = coords[0].crpix1 = coords[0].cdelt1 = 0.0;
+    coords[0].crval2 = coords[0].crpix2 = coords[0].cdelt2 = 0.0;
+    coords[0].pc1_1 = coords[0].pc2_2 = 1.0;
+    coords[0].pc2_1 = coords[0].pc1_2 = 0.0;
+    strcpy (coords[0].ctype, "NONE");
+  }
+  return (status);
+}
+
+int PutCoords (Coords *coords, Header *header) {
+  
+  int OldAIPS;
+  char csys[16], ctype[16];
+  double rotate, Lambda;
+
+  /* modifications to the ctype? */
+  OldAIPS = FALSE;
+  gfits_modify (header, "CTYPE2",   "%s",  1, coords[0].ctype);
+  if (!strcmp(coords[0].ctype, "MM")) {
+    gfits_modify (header, "CTYPE1",   "%s",  1, "LL");
+    OldAIPS = TRUE;
+  } else {
+    strcpy (csys, "NONE");
+    if (!strncmp (coords[0].ctype, "DEC-", 4)) strcpy (csys, "RA--");
+    if (!strncmp (coords[0].ctype, "GLAT", 4)) strcpy (csys, "GLON");
+    if (!strncmp (coords[0].ctype, "ELAT", 4)) strcpy (csys, "ELON");
+    if (!strncmp (coords[0].ctype, "HLAT", 4)) strcpy (csys, "HLON");
+    if (!strncmp (coords[0].ctype, "SLAT", 4)) strcpy (csys, "SLON");
+    if (!strcmp (csys, "NONE")) return (FALSE);
+    sprintf (ctype, "%s-%s", csys, &coords[0].ctype[5]);
+    gfits_modify (header, "CTYPE1",   "%s",  1, ctype);
+  }    
+
+  gfits_modify (header, "CDELT1",   "%le", 1, coords[0].cdelt1); 
+  gfits_modify (header, "CDELT2",   "%le", 1, coords[0].cdelt2);
+  gfits_modify (header, "CRVAL1",   "%lf", 1, coords[0].crval1);
+  gfits_modify (header, "CRVAL2",   "%lf", 1, coords[0].crval2);  
+  gfits_modify (header, "CRPIX1",   "%lf", 1, coords[0].crpix1);
+  gfits_modify (header, "CRPIX2",   "%lf", 1, coords[0].crpix2);
+
+  if (OldAIPS) {
+    Lambda = coords[0].cdelt2 / coords[0].cdelt1;
+    rotate = DEG_RAD*atan2 (coords[0].pc2_1*Lambda, coords[0].pc1_1);
+    gfits_modify (header, "CROTA1", "%f", 1, rotate);
+    gfits_modify (header, "CROTA2", "%f", 1, rotate);
+    return (TRUE);
+  } 
+
+  gfits_modify (header, "PC001001", "%le", 1, coords[0].pc1_1);
+  gfits_modify (header, "PC001002", "%le", 1, coords[0].pc1_2);
+  gfits_modify (header, "PC002001", "%le", 1, coords[0].pc2_1);
+  gfits_modify (header, "PC002002", "%le", 1, coords[0].pc2_2);
+  gfits_modify (header, "NPLYTERM", "%d",  1, coords[0].Npolyterms);
+
+  /* RA Terms */
+  if (coords[0].Npolyterms > 1) {
+    gfits_modify (header, "PCA1X2Y0", "%le", 1, coords[0].polyterms[0][0]);   /* polyterms[0]); */
+    gfits_modify (header, "PCA1X1Y1", "%le", 1, coords[0].polyterms[1][0]);   /* polyterms[1]); */
+    gfits_modify (header, "PCA1X0Y2", "%le", 1, coords[0].polyterms[2][0]);   /* polyterms[2]); */
+  }
+  if (coords[0].Npolyterms > 2) {
+    gfits_modify (header, "PCA1X3Y0", "%le", 1, coords[0].polyterms[3][0]);   /* polyterms[3]); */
+    gfits_modify (header, "PCA1X2Y1", "%le", 1, coords[0].polyterms[4][0]);   /* polyterms[4]); */
+    gfits_modify (header, "PCA1X1Y2", "%le", 1, coords[0].polyterms[5][0]);   /* polyterms[5]); */
+    gfits_modify (header, "PCA1X0Y3", "%le", 1, coords[0].polyterms[6][0]);   /* polyterms[6]); */
+  }
+
+  /* Dec Terms */
+  if (coords[0].Npolyterms > 1) {
+    gfits_modify (header, "PCA2X2Y0", "%le", 1, coords[0].polyterms[0][1]);   /* polyterms[7]); */
+    gfits_modify (header, "PCA2X1Y1", "%le", 1, coords[0].polyterms[1][1]);   /* polyterms[8]); */
+    gfits_modify (header, "PCA2X0Y2", "%le", 1, coords[0].polyterms[2][1]);   /* polyterms[9]); */
+  }
+  if (coords[0].Npolyterms > 2) {
+    gfits_modify (header, "PCA2X3Y0", "%le", 1, coords[0].polyterms[3][1]);   /* polyterms[10]); */
+    gfits_modify (header, "PCA2X2Y1", "%le", 1, coords[0].polyterms[4][1]);   /* polyterms[11]); */
+    gfits_modify (header, "PCA2X1Y2", "%le", 1, coords[0].polyterms[5][1]);   /* polyterms[12]); */
+    gfits_modify (header, "PCA2X0Y3", "%le", 1, coords[0].polyterms[6][1]);   /* polyterms[13]); */
+  }
+  return (TRUE);
+}
+
+void coords_precess (double *ra, double *dec, double in_epoch, double out_epoch) {
+
+  double T;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  
+  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;
+  
+  A = *ra;
+  D = *dec;
+  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;
+  
+  *ra = RA;
+  *dec = DEC; 
+}
+
+/* -PLY projection is an extrapolation of the -TAN projection. 
+   In addition to the usual linear terms of CRPIXi, PC00i00j, there are 
+   higher order polynomial terms (up to 3rd order):
+   Axis 1 terms:
+   PCA1X2Y0 = coords.polyterm[0][0] = x^2                                             
+   PCA1X1Y1 = coords.polyterm[1][0] = xy                                          
+   PCA1X0Y2 = coords.polyterm[2][0] = y^2                                             
+   PCA1X3Y0 = coords.polyterm[3][0] = x^3                                             
+   PCA1X2Y1 = coords.polyterm[4][0] = x^2 y                                             
+   PCA1X1Y2 = coords.polyterm[5][0] = x y^2                                             
+   PCA1X0Y3 = coords.polyterm[6][0] = y^2                                              
+   Axis 2 terms:
+   PCA2X2Y0 = coords.polyterm[0][1] = x^2                                               
+   PCA2X1Y1 = coords.polyterm[1][1] = xy                                                
+   PCA2X0Y2 = coords.polyterm[2][1] = y^2                                               
+   PCA2X3Y0 = coords.polyterm[3][1] = x^3                                               
+   PCA2X2Y1 = coords.polyterm[4][1] = x^2 y                                             
+   PCA2X1Y2 = coords.polyterm[5][1] = x y^2                                             
+   PCA2X0Y3 = coords.polyterm[6][1] = y^2                                               
+*/
+
+# if (0)
+
+  /** convert pixel coordinates to cartesian system **/
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  if (Polynomi) {
+    if (coords[0].Npolyterms > 2) {
+      X += coords[0].cdelt1*(x*x*coords[0].polyterms[0][0] + x*y*coords[0].polyterms[1][0] + y*y*coords[0].polyterms[2][0]);
+      Y += coords[0].cdelt2*(x*x*coords[0].polyterms[0][1] + x*y*coords[0].polyterms[1][1] + y*y*coords[0].polyterms[2][1]);
+    }
+    if (coords[0].Npolyterms > 2) {
+      X += coords[0].cdelt1*(x*x*x*coords[0].polyterms[3][0] + x*x*y*coords[0].polyterms[4][0] + x*y*y*coords[0].polyterms[5][0] + y*y*y*coords[0].polyterms[6][0]);
+      Y += coords[0].cdelt2*(x*x*x*coords[0].polyterms[3][1] + x*x*y*coords[0].polyterms[4][1] + x*y*y*coords[0].polyterms[5][1] + y*y*y*coords[0].polyterms[6][1]);
+    }
+  }
+
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+/** this code is the old method used for higher order terms.  they
+    are essentially 6th order, with weird coupled terms.
+    I don't think any real data used these terms, but they should 
+    be re-calculated, I would think 
+**/
+
+# endif
+
+/*
+
+Projections and Transformations
+
+The Coords structure is used to represent the standard FITS header representations of the WCS terms.
+The FITS WCS encapsulates several concepts in one system: coordinate frame, projection, and
+transformations.  The ctype variable defines both the frame (ie, RA/DEC, GLON/GLAT, etc) and the
+projection (ie, AIT, SIN, TAN, etc).  The associated terms (PC00i00j) define transformations from
+the projection system to another linear coordinate system.  I have extended the basic WCS
+transformation terms to include higher-order polynomial terms.  The presence of higher-order terms
+is indicated in the header by the NPLYTERM keyword, with a value greater than 1 (a value of 0 or 1
+implies no higher-order coefficients).  The coefficients have keywords of the form PCAnXiYj where
+'n' is the axis corresponding to the dependent variable, 'i' is the order of the X component and 'j'
+is the order of the Y component.  A value of 2 indicates that the second-order coefficients are
+defined (PCAnX2Y0, PCAnX1Y1, PCAnX0Y2); A value of 3 indicates that the third-order coefficients are
+also defined (PCAnX3Y0, PCAnX2Y1, PCAnX1Y2, PCAnX0Y3).  Some headers in the past were generated
+without the NPLYTERM keyword.  a value of PLY, DIS, or WRP for the projection without a
+corresponding value for NPLYTERM implies that the value should be interpreted as '3'.
+
+*/
+
+  /* PLY is equiv to LIN with higher order terms
+     ZPL is equiv to ZEA with higher order terms
+     DIS is equiv to TAN with higher order terms
+     WRP is equiv to PLY, with implied mosaic */
+
+OhanaProjection GetProjection (char *ctype) {
+  if (!strcmp(&ctype[4], "-ZEA")) return PROJ_ZEA;
+  if (!strcmp(&ctype[4], "-ZPL")) return PROJ_ZPL;
+  if (!strcmp(&ctype[4], "-ARC")) return PROJ_ARC;
+  if (!strcmp(&ctype[4], "-STG")) return PROJ_STG;
+  if (!strcmp(&ctype[4], "-SIN")) return PROJ_SIN;
+  if (!strcmp(&ctype[0], "MM"))   return PROJ_SIN; // note ctype[0]
+  if (!strcmp(&ctype[4], "-TAN")) return PROJ_TAN;
+  if (!strcmp(&ctype[4], "-DIS")) return PROJ_DIS;
+  if (!strcmp(&ctype[4], "-LIN")) return PROJ_LIN;
+  if (!strcmp(&ctype[0], "GENE")) return PROJ_LIN; // note ctype[0]
+  if (!strcmp(&ctype[4], "-PLY")) return PROJ_PLY;
+  if (!strcmp(&ctype[4], "-WRP")) return PROJ_WRP;
+  if (!strcmp(&ctype[4], "-AIT")) return PROJ_AIT;
+  if (!strcmp(&ctype[4], "-GLS")) return PROJ_GLS;
+  if (!strcmp(&ctype[4], "-PAR")) return PROJ_PAR;
+  return PROJ_NONE;
+}
+  
+int SetProjection (char *ctype, OhanaProjection proj) {
+  switch (proj) {
+    case PROJ_ZEA: strcpy(&ctype[4], "-ZEA"); return TRUE;
+    case PROJ_ZPL: strcpy(&ctype[4], "-ZPL"); return TRUE;
+    case PROJ_ARC: strcpy(&ctype[4], "-ARC"); return TRUE;
+    case PROJ_STG: strcpy(&ctype[4], "-STG"); return TRUE;
+    case PROJ_SIN: strcpy(&ctype[4], "-SIN"); return TRUE;
+    case PROJ_TAN: strcpy(&ctype[4], "-TAN"); return TRUE;
+    case PROJ_DIS: strcpy(&ctype[4], "-DIS"); return TRUE;
+    case PROJ_LIN: strcpy(&ctype[4], "-LIN"); return TRUE;
+    case PROJ_PLY: strcpy(&ctype[4], "-PLY"); return TRUE;
+    case PROJ_WRP: strcpy(&ctype[4], "-WRP"); return TRUE;
+    case PROJ_AIT: strcpy(&ctype[4], "-AIT"); return TRUE;
+    case PROJ_GLS: strcpy(&ctype[4], "-GLS"); return TRUE;
+    case PROJ_PAR: strcpy(&ctype[4], "-PAR"); return TRUE;
+    case PROJ_NONE: return FALSE;
+  }
+  return FALSE;
+}  
+
+OhanaProjectionMode GetProjectionMode (OhanaProjection proj) {
+  switch (proj) {
+    case PROJ_ZEA:
+    case PROJ_ZPL:
+    case PROJ_ARC:
+    case PROJ_STG:
+    case PROJ_SIN:
+    case PROJ_TAN:
+    case PROJ_DIS:
+      return PROJ_MODE_ZENITHAL;
+    case PROJ_LIN: 
+    case PROJ_PLY: 
+    case PROJ_WRP: 
+      return PROJ_MODE_CARTESIAN;
+    case PROJ_AIT:
+    case PROJ_GLS:
+    case PROJ_PAR:
+      return PROJ_MODE_PSEUDOCYL;
+    default: 
+      return PROJ_MODE_NONE;
+  }
+  return PROJ_MODE_NONE;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog.c	(revision 16632)
@@ -0,0 +1,420 @@
+# include <dvo.h>
+# define DEBUG 1
+
+void dvo_catalog_test (Catalog *catalog, int halt) {
+
+  Catalog *subcat;
+
+  // fprintf (stderr, "catalog: Naverage = %d, average = %zx\n", catalog[0].Naverage, (size_t) catalog[0].average);
+  // fprintf (stderr, "catalog: Nmeasure = %d, measure = %zx\n", catalog[0].Nmeasure, (size_t) catalog[0].measure);
+  // fprintf (stderr, "catalog: Nmissing = %d, missing = %zx\n", catalog[0].Nmissing, (size_t) catalog[0].missing);
+  // fprintf (stderr, "catalog: Nsecfilt = %d, secfilt = %zx\n", catalog[0].Nsecfilt, (size_t) catalog[0].secfilt);
+
+  if (!catalog[0].measure || !catalog[0].secfilt) {
+    fprintf (stderr, "error: %s\n", catalog[0].filename);
+    if (halt) abort ();
+  }
+
+  // XXX test that things are correctly initialized
+  if (catalog[0].catmode != DVO_MODE_SPLIT) return;
+
+  subcat = catalog[0].measure_catalog;
+  if (subcat) {
+    if (subcat[0].measure_catalog || subcat[0].secfilt_catalog || subcat[0].missing_catalog) {
+      fprintf (stderr, "error in init\n");
+      abort ();
+    }
+  }
+  subcat = catalog[0].missing_catalog;
+  if (subcat) {
+    if (subcat[0].measure_catalog || subcat[0].secfilt_catalog || subcat[0].missing_catalog) {
+      fprintf (stderr, "error in init\n");
+      abort ();
+    }
+  }
+  subcat = catalog[0].secfilt_catalog;
+  if (subcat) {
+    if (subcat[0].measure_catalog || subcat[0].secfilt_catalog || subcat[0].missing_catalog) {
+      fprintf (stderr, "error in init\n");
+      abort ();
+    }
+  }
+}
+
+int dvo_catalog_catformat (char *catformat) {
+  
+  /* set the specified CATFORMAT */
+  if (!strcasecmp (catformat, "INTERNAL"))        return (DVO_FORMAT_INTERNAL);
+  if (!strcasecmp (catformat, "LONEOS"))    	  return (DVO_FORMAT_LONEOS);
+  if (!strcasecmp (catformat, "ELIXIR"))    	  return (DVO_FORMAT_ELIXIR);
+  if (!strcasecmp (catformat, "PANSTARRS_DEV_0")) return (DVO_FORMAT_PANSTARRS_DEV_0);
+  if (!strcasecmp (catformat, "PANSTARRS_DEV_1")) return (DVO_FORMAT_PANSTARRS_DEV_1);
+  if (!strcasecmp (catformat, "PS1_DEV_1"))       return (DVO_FORMAT_PS1_DEV_1);
+  return (DVO_FORMAT_UNDEF);
+}
+
+int dvo_catalog_catmode (char *catmode) {
+
+  /* set the specified CATMODE */
+  if (!strcasecmp (catmode, "RAW"))   return (DVO_MODE_RAW);
+  if (!strcasecmp (catmode, "MEF"))   return (DVO_MODE_MEF);
+  if (!strcasecmp (catmode, "SPLIT")) return (DVO_MODE_SPLIT);
+  return (DVO_MODE_UNDEF);
+}
+
+// init all data, or just catalog data
+void dvo_catalog_init (Catalog *catalog, int complete) {
+
+  // the following are used to guide open/create/load
+  if (complete) {
+    catalog[0].f = NULL;
+    catalog[0].filename = NULL;
+
+    catalog[0].lockmode = 0;
+    catalog[0].catmode  = 0;
+    catalog[0].catformat = 0;
+    catalog[0].catflags = 0;
+    catalog[0].sorted = 0;
+    catalog[0].Nsecfilt = 0;
+  }
+
+  gfits_init_header (&catalog[0].header);
+
+  // the following describe the catalog files on disk
+  catalog[0].average = NULL;
+  catalog[0].measure = NULL; 
+  catalog[0].missing = NULL; 
+  catalog[0].secfilt = NULL;
+  
+  catalog[0].Naverage = 0;
+  catalog[0].Nmeasure = 0;
+  catalog[0].Nmissing = 0;
+  catalog[0].Nsecf_mem = 0;
+
+  catalog[0].Naves_disk = 0;
+  catalog[0].Nmeas_disk = 0;
+  catalog[0].Nmiss_disk = 0;
+  catalog[0].Nsecf_disk = 0;
+
+  catalog[0].Naves_off  = 0;
+  catalog[0].Nmeas_off  = 0;
+  catalog[0].Nmiss_off  = 0;
+  catalog[0].Nsecf_off  = 0;
+
+  /* pointers to SPLIT data files */
+  catalog[0].measure_catalog = NULL;
+  catalog[0].missing_catalog = NULL;
+  catalog[0].secfilt_catalog = NULL;
+
+  /* pointers for data manipulation */
+  catalog[0].found = NULL;
+  catalog[0].image = NULL;
+  catalog[0].mosaic = NULL;
+  catalog[0].X = NULL;
+  catalog[0].Y = NULL;
+}
+
+/* possible exit status for lock_catalog: 
+   DVO_CAT_OPEN_FAIL - failure (including lock failure)
+   DVO_CAT_OPEN_OK - success
+   DVO_CAT_OPEN_EMPTY - empty file (file may be open or closed!) 
+*/
+int dvo_catalog_lock (Catalog *catalog, int lockmode) {
+
+  int dbstate;
+
+  /* record lockmode choice */
+  catalog[0].lockmode = lockmode;
+
+  /* set lock on database, create stream f */
+  // fprintf (stderr, "locking: %s\n", catalog[0].filename);
+  catalog[0].f = fsetlockfile (catalog[0].filename, 3600.0, catalog[0].lockmode, &dbstate);
+
+  if (dbstate == LCK_MISSING) return (DVO_CAT_OPEN_EMPTY);
+  if (dbstate == LCK_EMPTY)   return (DVO_CAT_OPEN_EMPTY);
+  if (catalog[0].f == NULL)   return (DVO_CAT_OPEN_FAIL);
+
+  fseek (catalog[0].f, 0, SEEK_SET);
+  return (DVO_CAT_OPEN_OK);
+}
+
+int dvo_catalog_unlock (Catalog *catalog) {
+
+  int fd, dbstate;
+  struct stat filestat;
+
+  if (catalog[0].f == (FILE *) NULL) return (2);
+  fflush (catalog[0].f);
+  // fprintf (stderr, "unlocking: %s\n", catalog[0].filename);
+
+  // attempt to unlink an empty file
+  fd = fileno (catalog[0].f);
+  if (!fstat (fd, &filestat)) {
+    if (filestat.st_size == 0) {
+      unlink (catalog[0].filename);
+    }
+  }
+
+  fclearlockfile (catalog[0].filename, catalog[0].f, catalog[0].lockmode, &dbstate);
+
+  if (catalog[0].catmode == DVO_MODE_SPLIT) {
+    if (catalog[0].measure_catalog != NULL) dvo_catalog_unlock (catalog[0].measure_catalog);
+    if (catalog[0].missing_catalog != NULL) dvo_catalog_unlock (catalog[0].missing_catalog);
+    if (catalog[0].secfilt_catalog != NULL) dvo_catalog_unlock (catalog[0].secfilt_catalog);
+  }
+  return (1);
+}
+
+// open an existing catalog file or or create a new one as needed (iomode == "w")
+// returns FALSE if a catalog could not be opened
+// returns TRUE if the catalog was empty
+// XXX allow stdout as destination (don't lock)
+enum {DVO_OPEN_NONE, DVO_OPEN_READ, DVO_OPEN_WRITE, DVO_OPEN_UPDATE};
+int dvo_catalog_open (Catalog *catalog, SkyRegion *region, int VERBOSE, char *iomode) {
+
+  int Nsecfilt, mode;
+
+  mode = DVO_OPEN_NONE;
+  if (!strcasecmp (iomode, "r")) mode = DVO_OPEN_READ;
+  if (!strcasecmp (iomode, "w")) mode = DVO_OPEN_WRITE;
+  if (!strcasecmp (iomode, "a")) mode = DVO_OPEN_UPDATE;
+  if (mode == DVO_OPEN_NONE) return (FALSE);
+
+  // save the expected Nsecfilt value for testing
+  Nsecfilt = catalog[0].Nsecfilt;
+
+  dvo_catalog_init (catalog, FALSE);
+
+  catalog[0].lockmode  = LCK_XCLD;
+  if (mode == DVO_OPEN_READ) catalog[0].lockmode  = LCK_SOFT;
+  
+  // XXX make a backup?  always?
+  if (!check_file_access (catalog[0].filename, TRUE, VERBOSE)) {
+    if (VERBOSE) fprintf (stderr, "no permission to access %s\n", catalog[0].filename);
+    return (FALSE);
+  }
+
+  if (VERBOSE) fprintf (stderr, "opening %s\n", catalog[0].filename);
+  
+  switch (dvo_catalog_lock (catalog, catalog[0].lockmode)) {
+  case DVO_CAT_OPEN_FAIL:
+    if (VERBOSE) fprintf (stderr, "can't lock file %s\n", catalog[0].filename);
+    return (FALSE);
+  case DVO_CAT_OPEN_OK:
+    if (!dvo_catalog_load (catalog, VERBOSE)) {
+      if (VERBOSE) fprintf (stderr, "failure loading catalog\n");
+      return (FALSE);
+    }
+    if (!dvo_catalog_check (catalog, Nsecfilt, TRUE)) {
+      if (VERBOSE) fprintf (stderr, "can't reduce number of secondary filters\n");
+      return (FALSE);
+    }
+    if (VERBOSE) fprintf (stderr, "loaded existing file %s\n", catalog[0].filename);
+    break;
+  case DVO_CAT_OPEN_EMPTY:
+    if ((mode == DVO_OPEN_READ) || (mode == DVO_OPEN_UPDATE)) return (TRUE);
+    catalog[0].Nsecfilt = Nsecfilt;
+    dvo_catalog_create (region, catalog); /* fills in new header info */
+    if (VERBOSE) fprintf (stderr, "creating new file %s\n", catalog[0].filename);
+    break;
+  }
+  return (TRUE);
+}
+
+// load an existing dvo_catalog currenly, the catmode information is carried per
+// catalog.  the user-set value of catmode will set the output mode for new
+// tables an old table will keep its mode.
+int dvo_catalog_load (Catalog *catalog, int VERBOSE) {
+  
+  int Naxis, split, status;
+  char measure[80];
+
+  dvo_catalog_init (catalog, FALSE);
+
+  // load the main catalog header, determine characteristics
+  if (!gfits_fread_header (catalog[0].f, &catalog[0].header)) {
+    if (VERBOSE) fprintf (stderr, "failure to read main catalog header\n");
+    return (FALSE);
+  }
+  // check if the table has been sorted or not 
+  status = gfits_scan (&catalog[0].header, "SORTED", "%t", 1, &catalog[0].sorted);
+  if (!status) catalog[0].sorted = TRUE;
+
+  // determine catmode
+  if (!gfits_scan (&catalog[0].header, "NAXIS", "%d", 1, &Naxis)) {
+    if (VERBOSE) fprintf (stderr, "can't determine catalog db mode\n");
+    return (FALSE);
+  }
+  catalog[0].catmode = DVO_MODE_MEF;
+  split = gfits_scan (&catalog[0].header, "MEASURE", "%s", 1, measure);
+  if (split) catalog[0].catmode = DVO_MODE_SPLIT;
+  if (Naxis == 2) catalog[0].catmode = DVO_MODE_RAW;
+  /* don't use Naxis == 2 and split mode! */
+
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_RAW)\n");
+      dvo_catalog_load_raw (catalog, VERBOSE);
+      break;
+    case DVO_MODE_MEF:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_MEF)\n");
+      dvo_catalog_load_mef (catalog, VERBOSE);
+      break;
+    case DVO_MODE_SPLIT:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_SPLIT)\n");
+      dvo_catalog_load_split (catalog, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "error getting catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+// write out the data, unlink if empty?  'save' means: write out all data currently in
+// memory.  NOTE: this is currently not always possible: for non-SPLIT moe files, this
+// operation may require expanding the file size, which does not automatically happen
+int dvo_catalog_save (Catalog *catalog, char VERBOSE) {
+
+  // set the 'sorted' header keyword
+  gfits_modify (&catalog[0].header, "SORTED",  "%t", 1, catalog[0].sorted);
+
+  // XXX handle return status
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      dvo_catalog_save_raw (catalog, VERBOSE);
+      break;
+    case DVO_MODE_MEF:
+      dvo_catalog_save_mef (catalog, VERBOSE);
+      break;
+    case DVO_MODE_SPLIT:
+      dvo_catalog_save_split (catalog, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "invalid catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+// write out the in-memory data which extends beyond the data on disk.  NOTE: this is
+// currently only possible for the SPLIT mode.
+int dvo_catalog_update (Catalog *catalog, char VERBOSE) {
+
+  // set the 'sorted' header keyword
+  catalog[0].sorted = FALSE;
+  gfits_modify (&catalog[0].header, "SORTED",  "%t", 1, catalog[0].sorted);
+
+  /* update is only valid for catmode SPLIT */
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      fprintf (stderr, "not allowed for RAW mode\n");
+      break;
+    case DVO_MODE_MEF:
+      fprintf (stderr, "not allowed for MEF mode\n");
+      break;
+    case DVO_MODE_SPLIT:
+      dvo_catalog_update_split (catalog, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "failure updating catalog\n");
+      fprintf (stderr, "invalid catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+int dvo_catalog_check (Catalog *catalog, int Nsecfilt, int extend) {
+
+  int i, j, Nextra, in, out;
+  SecFilt *insec, *outsec;
+
+  if (Nsecfilt == 0) return (TRUE); // if Nsecfilt is not set, don't do this check
+  if (catalog[0].Nsecfilt == Nsecfilt) return (TRUE);
+  if (catalog[0].Nsecfilt > Nsecfilt) return (FALSE);
+  if ((catalog[0].Nsecfilt < Nsecfilt) && !extend) return (FALSE);
+
+  if ((catalog[0].Nsecfilt < Nsecfilt) && extend) {
+    Nextra = Nsecfilt - catalog[0].Nsecfilt;
+    insec = catalog[0].secfilt;
+    ALLOCATE (outsec, SecFilt, catalog[0].Naverage * Nsecfilt);
+    for (in = out = i = 0; i < catalog[0].Naverage; i++) {
+      for (j = 0; j < catalog[0].Nsecfilt; j++, in++, out++) {
+	outsec[out].M  = insec[in].M;
+	outsec[out].dM = insec[in].dM;
+	outsec[out].Xm = insec[in].Xm;
+      }
+      for (j = 0; j < Nextra; j++, out++) {
+	outsec[out].M  = NAN;
+	outsec[out].dM = NAN;
+	outsec[out].Xm = NAN_S_SHORT;
+      }
+    }
+    free (catalog[0].secfilt);
+    catalog[0].secfilt = outsec;
+    catalog[0].Nsecfilt = Nsecfilt;
+    catalog[0].Nsecf_mem = Nsecfilt * catalog[0].Naverage;
+  }
+  return (TRUE);
+}
+
+void dvo_catalog_free (Catalog *catalog) {
+  dvo_catalog_free_data (catalog);
+  gfits_free_header (&catalog[0].header);
+}
+
+void dvo_catalog_free_data (Catalog *catalog) {
+
+  /* free, initialize data structures */
+  if (catalog[0].average != NULL) {
+    free (catalog[0].average); 
+    catalog[0].Naverage = 0;
+    catalog[0].average = NULL;
+  }
+  if (catalog[0].measure != NULL) {
+    free (catalog[0].measure); 
+    catalog[0].Nmeasure = 0;
+    catalog[0].measure = NULL;
+  }
+  if (catalog[0].missing != NULL) {
+    free (catalog[0].missing); 
+    catalog[0].Nmissing = 0;
+    catalog[0].missing = NULL;
+  }
+  if (catalog[0].secfilt != NULL) {
+    free (catalog[0].secfilt); 
+    catalog[0].Nsecf_mem = 0;
+    catalog[0].secfilt = NULL;
+  }
+}
+
+/*
+  mode   : items to read (LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF)
+  format : what table structure on disk (INTERNAL, LONEOS, etc, )
+  style  : raw, mef, split, mysql
+*/
+
+int dvo_catalog_load_segment (Catalog *catalog, int VERBOSE, int start, int Nrows) {
+
+  switch (catalog[0].catmode) {
+    case DVO_MODE_RAW:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_RAW)\n");
+      fprintf (stderr, "cannot do this in raw mode\n");
+      // dvo_catalog_load_segment_raw (catalog, VERBOSE, start, Nrows);
+      break;
+    case DVO_MODE_MEF:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_MEF)\n");
+      fprintf (stderr, "cannot do this in mef mode\n");
+      // dvo_catalog_load_segment_mef (catalog, VERBOSE, start, Nrows);
+      break;
+    case DVO_MODE_SPLIT:
+      if (VERBOSE) fprintf (stderr, "reading catalog (mode DVO_MODE_SPLIT)\n");
+      dvo_catalog_load_segment_split (catalog, VERBOSE, start, Nrows);
+      break;
+    default:
+      fprintf (stderr, "error getting catalog mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_chipcoords.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_chipcoords.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_chipcoords.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include <dvo.h>
+
+int dvo_match_image (Image *image, int Nimage, unsigned int T, short int S) {
+
+  int N, Nlo, Nhi, N1, N2;
+
+  /* bracket first value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].tzero < T) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  N1 = Nlo;
+
+  /* bracket last value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].tzero > T) {
+      Nhi = N;
+    } else {
+      Nlo = N - 1;
+    }
+  }
+  N2 = Nhi;
+
+  for (N = N1; N < N2; N++) {
+    if ((image[N].tzero == T) && (image[N].photcode == S)) {
+      return (N);
+    }
+  }
+  return (-1);
+}
+
+// if necessary, determine chip coordinates for all measures
+int dvo_catalog_chipcoords (Catalog *catalog, Image *image, int Nimage) {
+
+  int i, j, m, N;
+  double ra, dec, x, y;
+  Average *average;
+  Measure *measure;
+
+  if (catalog[0].catformat == DVO_FORMAT_LONEOS) goto do_convert;  // special conversion for LONEOS
+  if (catalog[0].catformat == DVO_FORMAT_ELIXIR) goto do_convert;  // special conversion for ELIXIR
+  return TRUE;
+
+do_convert:
+  average = catalog[0].average;
+  measure = catalog[0].measure;
+  
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    m = average[i].offset;
+    for (j = 0; j < average[i].Nm; j++, m++) {
+      ra  = average[i].R - measure[m].dR / 3600.0;
+      dec = average[i].D - measure[m].dD / 3600.0;
+      N = dvo_match_image (image, Nimage, measure[m].t, measure[m].photcode);
+      if (N == -1) continue;
+      RD_to_XY (&x, &y, ra, dec, &image[N].coords);
+      measure[m].Xccd = x;
+      measure[m].Yccd = y;
+    }
+  }
+  return TRUE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_create.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_create.c	(revision 16632)
@@ -0,0 +1,139 @@
+# include <dvo.h>
+# define DEBUG 0
+
+// create a new dvo catalog file (if split, lock extra files as well?)
+// catalog internals which must be set:
+// catalog[0].filename
+// catalog[0].catmode
+// catalog[0].catformat (used by dvo_catalog_save)
+// catalog[0].lockmode
+void dvo_catalog_create (SkyRegion *region, Catalog *catalog) {
+
+  int length;
+  char *path, *root, *file, *line;
+  time_t now;
+
+  if (DEBUG) fprintf (stderr, "new catalog file: %s\n", catalog[0].filename);
+
+  // init the data values, not the internals listed above
+  dvo_catalog_init (catalog, FALSE);
+
+  /* for RAW mode, make header a fake image */
+  if (catalog[0].catmode == DVO_MODE_RAW) {
+    catalog[0].header.bitpix   = 16;
+    catalog[0].header.Naxes    = 2;
+    catalog[0].header.Naxis[0] = 1;
+    catalog[0].header.Naxis[1] = 1;
+  }
+  gfits_create_header (&catalog[0].header);
+  
+  if (catalog[0].catmode == DVO_MODE_SPLIT) {
+    path = pathname (catalog[0].filename);
+    root = filerootname (catalog[0].filename);
+    length = strlen(path) + strlen(root) + 6;
+
+    /* define measure catalog file */
+    ALLOCATE (catalog[0].measure_catalog, Catalog, 1);
+    dvo_catalog_init (catalog[0].measure_catalog, TRUE);
+
+    /* create basic data for measure catalog file */
+    gfits_create_header (&catalog[0].measure_catalog[0].header);
+    ALLOCATE (catalog[0].measure_catalog[0].filename, char, length);
+    sprintf (catalog[0].measure_catalog[0].filename, "%s/%s.cpm", path, root);
+    file = filebasename (catalog[0].measure_catalog[0].filename);
+    gfits_modify (&catalog[0].header, "MEASURE", "%s", 1, file);
+    free (file);
+
+    /* define missing catalog file */
+    ALLOCATE (catalog[0].missing_catalog, Catalog, 1);
+    dvo_catalog_init (catalog[0].missing_catalog, TRUE);
+
+    /* create basic data for missing catalog file */
+    gfits_create_header (&catalog[0].missing_catalog[0].header);
+    ALLOCATE (catalog[0].missing_catalog[0].filename, char, length);
+    sprintf (catalog[0].missing_catalog[0].filename, "%s/%s.cpn", path, root);
+    file = filebasename (catalog[0].missing_catalog[0].filename);
+    gfits_modify (&catalog[0].header, "MISSING", "%s", 1, file);
+    free (file);
+
+    /* define secfilt catalog file */
+    ALLOCATE (catalog[0].secfilt_catalog, Catalog, 1);
+    dvo_catalog_init (catalog[0].secfilt_catalog, TRUE);
+
+    /* create basic data for secfilt catalog file */
+    gfits_create_header (&catalog[0].secfilt_catalog[0].header);
+    ALLOCATE (catalog[0].secfilt_catalog[0].filename, char, length);
+    sprintf (catalog[0].secfilt_catalog[0].filename, "%s/%s.cps", path, root);
+    file = filebasename (catalog[0].secfilt_catalog[0].filename);
+    gfits_modify (&catalog[0].header, "SECFILT", "%s", 1, file);
+    free (file);
+    free (path);
+    free (root);
+
+    // lock the additional split files
+    // XXX clear residual locks if we fail
+    if (dvo_catalog_lock (catalog[0].measure_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
+      fprintf (stderr, "error with file lock\n");
+      exit (2);
+    }
+    if (dvo_catalog_lock (catalog[0].missing_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
+      fprintf (stderr, "error with file lock\n");
+      exit (2);
+    }
+    if (dvo_catalog_lock (catalog[0].secfilt_catalog, catalog[0].lockmode) != DVO_CAT_OPEN_EMPTY) {
+      fprintf (stderr, "error with file lock\n");
+      exit (2);
+    }
+
+  }    
+
+  /* write RA,DEC range in header */
+  if (region) {
+    gfits_modify (&catalog[0].header, "RA0",  "%lf", 1, region[0].Rmin);
+    gfits_modify (&catalog[0].header, "DEC0", "%lf", 1, region[0].Dmin);
+    gfits_modify (&catalog[0].header, "RA1",  "%lf", 1, region[0].Rmax);
+    gfits_modify (&catalog[0].header, "DEC1", "%lf", 1, region[0].Dmax);
+  }
+
+  /* write creation date in header */
+  ohana_str_to_time ("now", &now);
+  line = ohana_sec_to_date (now);
+  gfits_modify (&catalog[0].header, "DATE", "%s", 1, line);
+  free (line);
+
+  /* dummy allocation so realloc will succeed */
+  ALLOCATE (catalog[0].average, Average, 1);
+  ALLOCATE (catalog[0].measure, Measure, 1);
+  ALLOCATE (catalog[0].missing, Missing, 1);
+  ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+
+  /* setup secondary filters to match photcodes:
+   * Nsecfilt is number of filters.  Number of entries in array is
+   * Nsecfilt * Naverage.  At this point, N entries == 0
+   */
+}
+  
+int dvo_catalog_set_range (Catalog *catalog) {
+
+  int i;
+  double Rmin, Rmax, Dmin, Dmax;
+
+  /* determine RA,DEC range */
+  Rmin = 360.0;
+  Rmax =   0.0;
+  Dmin = +90.0;
+  Dmax = -90.0;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Rmin = MIN (Rmin, catalog[0].average[i].R);
+    Rmax = MAX (Rmax, catalog[0].average[i].R);
+    Dmin = MIN (Dmin, catalog[0].average[i].D);
+    Dmax = MAX (Dmax, catalog[0].average[i].D);
+  }
+
+  /* write RA,DEC range in header */
+  gfits_modify (&catalog[0].header, "RA0",  "%lf", 1, Rmin);
+  gfits_modify (&catalog[0].header, "DEC0", "%lf", 1, Dmin);
+  gfits_modify (&catalog[0].header, "RA1",  "%lf", 1, Rmax);
+  gfits_modify (&catalog[0].header, "DEC1", "%lf", 1, Dmax);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_mef.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_mef.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_mef.c	(revision 16632)
@@ -0,0 +1,333 @@
+# include <dvo.h>
+
+int dvo_catalog_load_mef (Catalog *catalog, int VERBOSE) {
+  
+  int Nitems, Nbytes, Nexpect, Naverage, Nmeasure, Nmissing, Nsecfilt;
+  FILE *f;
+
+  Header header;
+  Matrix matrix;
+  FTable ftable;
+  SecFilt *primary;
+
+  f = catalog[0].f;
+  ftable.header = &header;
+
+  /* move pointer past header -- must be already read (load_catalog) */
+  fseek (f, catalog[0].header.size, SEEK_SET);
+
+  /* matrix should be empty */
+  if (!gfits_fread_matrix (f, &matrix, &catalog[0].header)) {
+    if (VERBOSE) fprintf (stderr, "can't read primary matrix");
+    return (FALSE);
+  }
+  /* get the components from the header */
+  if (!gfits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &Naverage)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &Nmeasure)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NMISS",    "%d", 1, &Nmissing)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;
+
+  /* save the current number so we can do partial updates */
+  catalog[0].Naves_disk = Naverage;
+  catalog[0].Nmeas_disk = Nmeasure;
+  catalog[0].Nmiss_disk = Nmissing;
+  catalog[0].Nsecf_disk = Naverage * Nsecfilt;
+
+  /**  Nsecfilt is unusual: it does not list the number of data items in the table
+       instead, the number of items is Nsecfilt * Naverage.  **/
+  catalog[0].Nsecfilt = Nsecfilt;
+
+  /* default values, but we will assign these a valid value before we exit (even if empty) */
+  catalog[0].average = NULL;
+  catalog[0].measure = NULL;
+  catalog[0].missing = NULL;
+  catalog[0].secfilt = NULL;
+
+  /* validate table mode */
+
+  /* read Average table header */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table average header");
+    return (FALSE);
+  }
+  /* read Average table data (or skip) */
+  if (catalog[0].catflags & LOAD_AVES) {
+    if (!gfits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average data");
+      return (FALSE);
+    }
+    /* old versions of DVO stored one of the average magnitudes in Average. we save this if needed */
+    catalog[0].average = FtableToAverage (&ftable, &Naverage, &catalog[0].catformat, &primary);
+    if (Naverage != catalog[0].Naves_disk) {
+      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naves_disk);
+    }
+    catalog[0].Naverage = catalog[0].Naves_disk;
+    catalog[0].Naves_off = 0;
+  } else {
+    Nbytes = gfits_data_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+    ALLOCATE (catalog[0].average, Average, 1);
+    catalog[0].Naverage = 0;
+    catalog[0].Naves_off = catalog[0].Naves_disk;
+  }
+  gfits_free_header (&header);
+  /** free the ftable or not? data is being used still..? **/
+
+  /* read Measure table header */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table measure header");
+    return (FALSE);
+  }
+  /* read Measure table data */
+  if (catalog[0].catflags & LOAD_MEAS) {
+    if (!gfits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure data");
+      return (FALSE);
+    }
+    catalog[0].measure = FtableToMeasure (&ftable, &catalog[0].Nmeasure, &catalog[0].catformat);
+    if (Nmeasure != catalog[0].Nmeas_disk) {
+      fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, catalog[0].Nmeas_disk);
+    }
+    catalog[0].Nmeasure = catalog[0].Nmeas_disk;
+    catalog[0].Nmeas_off = 0;
+  } else {
+    Nbytes = gfits_data_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+    ALLOCATE (catalog[0].measure, Measure, 1);
+    catalog[0].Nmeasure = 0;
+    catalog[0].Nmeas_off = catalog[0].Nmeas_disk;
+  }
+
+  /* read Missing table header */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table missing header");
+    return (FALSE);
+  }
+  /* read Missing table data */
+  if (catalog[0].catflags & LOAD_MISS) {
+    if (!gfits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing data");
+      return (FALSE);
+    }
+    /* no conversions currently defined */
+    catalog[0].missing = gfits_table_get_Missing (&ftable, &catalog[0].Nmissing, NULL);
+    if (Nmissing != catalog[0].Nmiss_disk) {
+      fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, catalog[0].Nmiss_disk);
+    }
+    catalog[0].Nmissing = catalog[0].Nmiss_disk;
+    catalog[0].Nmiss_off = 0;
+  } else {
+    Nbytes = gfits_data_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+    ALLOCATE (catalog[0].missing, Missing, 1);
+    catalog[0].Nmissing = 0;
+    catalog[0].Nmiss_off = catalog[0].Nmiss_disk;
+  }
+
+  /* read secfilt table header */
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read table secfilt header");
+    return (FALSE);
+  }
+  /* read secfilt table data */
+  if (catalog[0].catflags & LOAD_SECF) {
+    if (!gfits_fread_ftable_data (f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table secfilt data");
+      return (FALSE);
+    }
+
+    /* how many entries do we expect from the secfilt table? */
+    Nexpect = catalog[0].Nsecfilt * catalog[0].Naverage;
+    catalog[0].secfilt = FtableToSecFilt (&ftable, &Nitems, &catalog[0].catformat);
+    if (Nexpect != Nitems) {
+      fprintf (stderr, "Warning: mismatch between Nsecfilt items in PHU and Table headers (%d vs %d)\n", Nexpect, Nitems);
+    }
+
+    /* if primary is defined, we were supplied with one additional average magnitude from Average
+       we need to interleave these magnitudes with the secfilt entries just loaded */
+    if (primary != NULL) {
+      int Ntmpfilt, Ntotal, i, j;
+      SecFilt *tmpfilt;
+      tmpfilt  = catalog[0].secfilt;
+      Ntmpfilt = catalog[0].Nsecfilt;
+      Nsecfilt = catalog[0].Nsecfilt + 1;
+      Ntotal = Nsecfilt * catalog[0].Naves_disk;
+      ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal);
+      for (i = 0; i < catalog[0].Naves_disk; i++) {
+	catalog[0].secfilt[i*Nsecfilt + 0] = primary[i];
+	for (j = 0; j < Ntmpfilt; j++) {
+	  catalog[0].secfilt[i*Nsecfilt + j + 1] = tmpfilt[i*Ntmpfilt + j];
+	}
+      }		
+      catalog[0].Nsecfilt = Nsecfilt;
+      catalog[0].Nsecf_disk = Ntotal;
+      free (primary);
+    } 
+    catalog[0].Nsecf_mem = catalog[0].Nsecf_disk;
+    catalog[0].Nsecf_off = 0;
+  } else {
+    /* no real need to skip the data array here... */
+    Nbytes = gfits_data_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+    if (primary != NULL) {
+      free (primary);
+      catalog[0].Nsecfilt ++;
+      catalog[0].Nsecf_disk =  catalog[0].Nsecfilt * catalog[0].Naves_disk;
+    }
+    ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+    catalog[0].Nsecf_mem = 0;
+    catalog[0].Nsecf_off = catalog[0].Nsecf_disk;
+  }
+
+  return (TRUE);
+}
+
+/* XXX need to decompose the primary and secfilt entries for Elixir and Loneos */
+/* save_catalog_mef writes a complete new file from scratch */
+int dvo_catalog_save_mef (Catalog *catalog, char VERBOSE) {
+
+  int Nitems;
+  FILE *f;
+  Matrix matrix;
+  Header header;
+  FTable ftable;
+  SecFilt *primary;
+  SecFilt *secfilt;
+  int i, j, Nsecfilt, Nallfilt, Ntotal;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  /* for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary */
+  if ((catalog[0].catformat == DVO_FORMAT_ELIXIR) || // special case for ELIXIR 
+      (catalog[0].catformat == DVO_FORMAT_LONEOS)) { // special case for LONEOS
+    Nallfilt = catalog[0].Nsecfilt;
+    Nsecfilt = catalog[0].Nsecfilt - 1;
+    Ntotal = Nsecfilt * catalog[0].Naverage;
+    ALLOCATE (primary, SecFilt, catalog[0].Naverage);
+    ALLOCATE (secfilt, SecFilt, Ntotal);
+
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      primary[i] = catalog[0].secfilt[i*Nallfilt + 0];
+      for (j = 0; j < Nsecfilt; j++) {
+	secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1];
+      }
+    }		
+  } else {
+    primary = NULL;
+    secfilt = catalog[0].secfilt;
+    Nsecfilt = catalog[0].Nsecfilt;
+  }
+
+  /* make sure header is consistent with data */
+  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt);
+  gfits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
+
+  f = catalog[0].f;
+  /* rewind file pointers and truncate */
+  fseek (f, 0, SEEK_SET);
+  ftruncate (fileno (catalog[0].f), 0);
+  ftable.header = &header;
+
+  /* write table PHU header */
+  if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+    fprintf (stderr, "can't write primary header");
+    goto failure;
+  }
+
+  /* this is probably a NOP, do I have to keep it in? */
+  gfits_create_matrix (&catalog[0].header, &matrix);
+  if (!gfits_fwrite_matrix  (catalog[0].f, &matrix)) {
+    fprintf (stderr, "can't write primary matrix");
+    goto failure;
+  }
+  gfits_free_matrix (&matrix);
+
+  /* write out Average table (convert to FITS table format) */
+  AverageToFtable (&ftable, catalog[0].average, catalog[0].Naverage, catalog[0].catformat, primary);
+  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    goto failure;
+  }
+  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    goto failure;
+  }
+  gfits_free_table (&ftable);
+  gfits_free_header (&header);
+
+  /* write out Measure table (convert to FITS table format) */
+  MeasureToFtable (&ftable, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
+  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    goto failure;
+  }
+  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    goto failure;
+  }
+  gfits_free_table (&ftable);
+  gfits_free_header (&header);
+
+  /* write out Missing table (convert to FITS table format) */
+  gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing);
+  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    goto failure;
+  }
+  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    goto failure;
+  }
+  gfits_free_table (&ftable);
+  gfits_free_header (&header);
+
+  /* write out SecFilt table (convert to FITS table format) */
+  Nitems = catalog[0].Naverage * Nsecfilt;
+  SecFiltToFtable (&ftable, secfilt, Nitems, catalog[0].catformat);
+  if (!gfits_fwrite_Theader (catalog[0].f, &header)) {
+    fprintf (stderr, "can't write table header");
+    goto failure;
+  }
+  if (!gfits_fwrite_table (catalog[0].f, &ftable)) {
+    fprintf (stderr, "can't write table data");
+    goto failure;
+  }
+  gfits_free_table (&ftable);
+  gfits_free_header (&header);
+
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (TRUE);
+
+failure:
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (FALSE);
+}
+
+/*
+  catalog data is:
+  header (bitpix == 8)
+  matrix (empty)
+  average header
+  average table
+  measure header
+  measure table
+  missing header
+  missing table
+  secfilt header
+  secfilt table
+*/
+   
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_raw.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_raw.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_raw.c	(revision 16632)
@@ -0,0 +1,594 @@
+# include <dvo.h>
+
+/* read data from raw-style catalog file; set data format values based on file */
+
+int dvo_catalog_load_raw (Catalog *catalog, int VERBOSE) {
+  
+  int Nitems, nitems;
+  int i, Nmeas, Nmiss, size;
+  int NewMeasure, Nskip;
+  int AverageSize, MeasureSize, MissingSize, SecFiltSize;
+  FILE *f;
+  struct stat filestatus;
+  char format[80], telescope[80];
+  SecFilt *primary;
+
+  f = catalog[0].f;
+
+  /* move pointer past header -- must be already read (load_catalog) */
+  fseek (f, catalog[0].header.size, SEEK_SET);
+
+  /* get the components from the header */
+  catalog[0].Naverage = catalog[0].Nmeasure = catalog[0].Nmissing = catalog[0].Nsecfilt = 0;
+  if (!gfits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &catalog[0].Naverage)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &catalog[0].Nmeasure)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NMISS",    "%d", 1, &catalog[0].Nmissing)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &catalog[0].Nsecfilt)) catalog[0].Nsecfilt = 0;
+
+  /* determine catalog format */
+  catalog[0].catformat = DVO_FORMAT_UNDEF;
+  if (gfits_scan (&catalog[0].header, "FORMAT",  "%s", 1, format)) {
+    catalog[0].catformat = dvo_catalog_catformat (format);
+    if (catalog[0].catformat != DVO_FORMAT_UNDEF) goto got_format;
+  }
+  /* special cases: old versions of the DB tables which were poorly identified */
+  if (gfits_scan (&catalog[0].header, "NEWMEAS",  "%t", 1, &NewMeasure)) {
+    catalog[0].catformat = DVO_FORMAT_ELIXIR; // special case for ELIXIR
+    goto got_format;
+  }
+  if (gfits_scan (&catalog[0].header, "TELESCOP",  "%s", 1, telescope)) {
+    if (!strncmp (telescope, "LONEOS", strlen("LONEOS"))) {
+      catalog[0].catformat = DVO_FORMAT_LONEOS; // special case for LONEOS
+      goto got_format;
+    }
+    if (!strncmp (telescope, "1.3m McGraw-Hill", strlen("1.3m McGraw-Hill"))) {
+      catalog[0].catformat = DVO_FORMAT_ELIXIR; // special case for ELIXIR
+      goto got_format;
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "cannot determine catalog format\n");
+  return (FALSE);
+
+// this macro generates the case statements for each type
+# define FORMAT_CASE(NAME,TYPE) \
+  case DVO_FORMAT_##NAME: { \
+    AverageSize = sizeof(Average_##TYPE); \
+    MeasureSize = sizeof(Measure_##TYPE); \
+    SecFiltSize = sizeof(SecFilt_##TYPE); \
+    break; }
+
+got_format:
+  /* determine datatype sizes */
+  switch (catalog[0].catformat) {
+    case DVO_FORMAT_INTERNAL: {
+      AverageSize = sizeof(Average);
+      MeasureSize = sizeof(Measure);
+      SecFiltSize = sizeof(SecFilt);
+      break;
+    }
+
+      FORMAT_CASE (LONEOS, Loneos);
+      FORMAT_CASE (ELIXIR, Elixir);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1, PS1_DEV_1);
+
+    default:
+      fprintf (stderr, "programming error in phot_catalog_raw\n");
+      exit (2);
+  }
+# undef FORMAT_CASE
+
+  MissingSize = sizeof (Missing);
+
+  /* predicted file size - for double checking data validity */
+  size = catalog[0].header.size;
+  size += AverageSize * catalog[0].Naverage;
+  size += MeasureSize * catalog[0].Nmeasure;
+  size += MissingSize * catalog[0].Nmissing;
+  size += SecFiltSize * catalog[0].Nsecfilt * catalog[0].Naverage;
+
+  /* check that file size makes sense */
+  if (stat (catalog[0].filename, &filestatus) == -1) {
+    if (VERBOSE) fprintf (stderr, "failed to get status of catalog\n");
+    return (FALSE);
+  }
+  if (size > filestatus.st_size) {
+    if (VERBOSE) {
+      fprintf (stderr, "star catalog has inconsistent size\n");
+      fprintf (stderr, "average: %d = %d bytes\n", catalog[0].Naverage, catalog[0].Naverage*AverageSize);
+      fprintf (stderr, "measure: %d = %d bytes\n", catalog[0].Nmeasure, catalog[0].Nmeasure*MeasureSize);
+      fprintf (stderr, "missing: %d = %d bytes\n", catalog[0].Nmissing, catalog[0].Nmissing*MissingSize);
+      fprintf (stderr, "secfilt: %d = %d bytes\n", catalog[0].Nsecfilt, catalog[0].Nsecfilt*SecFiltSize*catalog[0].Naverage);
+      fprintf (stderr, "expect: %d, found: %d\n", size, (int)filestatus.st_size);
+    }
+    return (FALSE);
+  } 
+  if (size < filestatus.st_size) {
+    if (VERBOSE) fprintf (stderr, "warning: file larger than expected\n");
+  } 
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars yet in catalog %s\n", catalog[0].filename);
+    return (TRUE);
+  }
+
+  /* read and convert the averages (use a macro to clean this up?) */
+  /* old versions of DVO stored one of the average magnitudes in Average. we save this if needed */
+  if (catalog[0].catflags & LOAD_AVES) {
+    catalog[0].average = ReadRawAverage (catalog[0].f, catalog[0].Naverage, catalog[0].catformat, &primary);
+  } else {
+    /* skip over averages */
+    Nskip = catalog[0].Naverage * AverageSize;
+    fseek (f, Nskip, SEEK_CUR); 
+  }    
+  
+  /* read and convert the measures (use a macro to clean this up?) */
+  if (catalog[0].catflags & LOAD_MEAS) {
+    catalog[0].measure = ReadRawMeasure (catalog[0].f, catalog[0].Nmeasure, catalog[0].catformat);
+  } else {
+    /* skip over measures */
+    Nskip = catalog[0].Nmeasure * MeasureSize;
+    fseek (f, Nskip, SEEK_CUR); 
+  }    
+
+  /* read and convert missing */
+  if (catalog[0].catflags & LOAD_MISS) {
+    ALLOCATE (catalog[0].missing, Missing, MAX (catalog[0].Nmissing, 1));
+    Nitems = catalog[0].Nmissing;
+    nitems = fread (catalog[0].missing, MissingSize, Nitems, f);
+    if (nitems != Nitems) {
+      if (VERBOSE) fprintf (stderr, "failed to read missing from catalog file %s (%d vs %d)\n", catalog[0].filename, nitems, Nitems);
+      return (FALSE);
+    }
+    gfits_convert_Missing (catalog[0].missing, MissingSize, Nitems);
+  } else {
+    /* skip over missings */
+    Nskip = catalog[0].Nmissing * MissingSize;
+    fseek (f, Nskip, SEEK_CUR); 
+  }
+  
+  /* read and convert secfilt */
+  if (catalog[0].catflags & LOAD_SECF) {
+    Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+    catalog[0].secfilt = ReadRawSecFilt (catalog[0].f, Nitems, catalog[0].catformat);
+
+    /* if primary is defined, we were supplied with one additional average magnitude from Average
+       we need to interleave these magnitudes with the secfilt entries just loaded */
+    if (primary != NULL) {
+      int Ntmpfilt, Nsecfilt, Ntotal, i, j;
+      SecFilt *tmpfilt;
+      tmpfilt  = catalog[0].secfilt;
+      Ntmpfilt = catalog[0].Nsecfilt;
+      Nsecfilt = catalog[0].Nsecfilt + 1;
+      Ntotal = Nsecfilt * catalog[0].Naverage;
+      ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal);
+      for (i = 0; i < catalog[0].Naverage; i++) {
+	catalog[0].secfilt[i*Nsecfilt + 0] = primary[i];
+	for (j = 0; j < Ntmpfilt; j++) {
+	  catalog[0].secfilt[i*Nsecfilt + j + 1] = tmpfilt[i*Ntmpfilt + j];
+	}
+      }		
+      catalog[0].Nsecfilt = Nsecfilt;
+      catalog[0].Nsecf_mem = Ntotal;
+      free (primary);
+    } 
+
+  } else {
+    /* skip over secfilts */
+    Nskip = catalog[0].Nsecfilt * catalog[0].Naverage * SecFiltSize;
+    fseek (f, Nskip, SEEK_CUR); 
+    if (primary != NULL) free (primary);
+  }
+
+  if (VERBOSE) fprintf (stderr, "read %d stars from catalog file %s (%d measurements, %d missing, %d secondary filters)\n", 
+			catalog[0].Naverage, catalog[0].filename, catalog[0].Nmeasure, catalog[0].Nmissing, catalog[0].Nsecfilt);
+
+  /* check data integrity */
+  if (catalog[0].catflags & LOAD_AVES) {
+    for (i = Nmeas = Nmiss = 0; i < catalog[0].Naverage; i++) {
+      Nmeas += catalog[0].average[i].Nm; 
+      Nmiss += catalog[0].average[i].Nn; 
+    }
+    if ((Nmeas != catalog[0].Nmeasure) || (Nmiss != catalog[0].Nmissing)) {
+      if (VERBOSE) {
+	fprintf (stderr, "****** data in catalog %s is corrupt, sums don't check\n", catalog[0].filename);
+	fprintf (stderr, "****** Nmeas: %d, %d\n", Nmeas, catalog[0].Nmeasure);
+	fprintf (stderr, "****** Nmiss: %d, %d\n", Nmiss, catalog[0].Nmissing);
+      }
+      return (FALSE);
+    }
+  }
+
+  /* save the current number so we can do partial updates */
+  catalog[0].Naves_disk = catalog[0].Naverage;
+  catalog[0].Nmeas_disk = catalog[0].Nmeasure;
+  catalog[0].Nmiss_disk = catalog[0].Nmissing;
+
+  return (TRUE);
+}
+
+int dvo_catalog_save_raw (Catalog *catalog, char VERBOSE) {
+
+  int Nitems, nitems;
+  FILE *f;
+  SecFilt *primary;
+  SecFilt *secfilt;
+  int i, j, Nsecfilt, Nallfilt, Ntotal;
+
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  /* for the appropriate types, pull out the first secfilt and pass to WriteRawAverage as primary */
+  if ((catalog[0].catformat == DVO_FORMAT_ELIXIR) || // special case for ELIXIR
+      (catalog[0].catformat == DVO_FORMAT_LONEOS)) { // special case for LONEOS
+    Nallfilt = catalog[0].Nsecfilt;
+    Nsecfilt = catalog[0].Nsecfilt - 1;
+    Ntotal = Nsecfilt * catalog[0].Naverage;
+    ALLOCATE (primary, SecFilt, catalog[0].Naverage);
+    ALLOCATE (secfilt, SecFilt, Ntotal);
+
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      primary[i] = catalog[0].secfilt[i*Nallfilt + 0];
+      for (j = 0; j < Nsecfilt; j++) {
+	secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1];
+      }
+    }		
+  } else {
+    primary = NULL;
+    secfilt = catalog[0].secfilt;
+    Nsecfilt = catalog[0].Nsecfilt;
+  }
+
+  /* make sure header is consistent with data */
+  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, catalog[0].Naverage);
+  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, catalog[0].Nmeasure);
+  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, catalog[0].Nmissing);
+  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, catalog[0].Nsecfilt);
+
+  /* specify the appropriate data format */
+  if (catalog[0].catformat == DVO_FORMAT_INTERNAL)  	  gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "INTERNAL");
+  if (catalog[0].catformat == DVO_FORMAT_LONEOS)    	  gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "LONEOS");
+  if (catalog[0].catformat == DVO_FORMAT_ELIXIR)    	  gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "ELIXIR");
+  if (catalog[0].catformat == DVO_FORMAT_PANSTARRS_DEV_0) gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PANSTARRS_DEV_0");
+  if (catalog[0].catformat == DVO_FORMAT_PANSTARRS_DEV_1) gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PANSTARRS_DEV_1");
+  if (catalog[0].catformat == DVO_FORMAT_PS1_DEV_1)       gfits_modify (&catalog[0].header, "FORMAT", "%s", 1, "PS1_DEV_1");
+
+  /* rewind file pointers and truncate file */
+  f = catalog[0].f;
+  fseek (f, 0, SEEK_SET);
+  ftruncate (fileno (catalog[0].f), 0);
+
+  /* write header data (use gfits_write_header?) */
+  nitems = fwrite (catalog[0].header.buffer, 1, catalog[0].header.size, f);
+  if (nitems != catalog[0].header.size) {
+    if (VERBOSE) fprintf (stderr, "failed to write header\n");
+    goto failure;
+  }
+
+  /* write averages and measures */
+  WriteRawAverage (f, catalog[0].average, catalog[0].Naverage, catalog[0].catformat, primary);
+  WriteRawMeasure (f, catalog[0].measure, catalog[0].Nmeasure, catalog[0].catformat);
+
+  /* write missing data */
+  Nitems = catalog[0].Nmissing;
+  gfits_convert_Missing (catalog[0].missing, sizeof(Missing), Nitems);
+  nitems = fwrite (catalog[0].missing, sizeof(Missing), Nitems, f);
+  if (nitems != Nitems) {
+    if (VERBOSE) fprintf (stderr, "failed to write catalog file missing %s\n", catalog[0].filename);
+    goto failure;
+  }
+
+  Nitems = catalog[0].Naverage * catalog[0].Nsecfilt;
+  WriteRawSecFilt (f, catalog[0].secfilt, Nitems, catalog[0].catformat);
+
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (TRUE);
+
+failure:
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (FALSE);
+}
+
+/*** 
+     some warnings:
+     - need to be wary of exit condition errors
+***/
+
+/** Average / Raw Table conversions **/
+
+/* in the Elixir and Loneos cases, we are supplied with an average magnitude in Average
+   in these cases, save these values in primary; otherwise set primary to NULL */
+
+Average *ReadRawAverage (FILE *f, int Naverage, int format, SecFilt **primary) {
+
+  Average *average;
+
+  *primary = NULL;
+
+// this macro generates the case statements for each type
+# define FORMAT_CASE(NAME,TYPE) \
+    case DVO_FORMAT_##NAME: { \
+      int nitems; \
+      Average_##TYPE *tmpAverage; \
+      ALLOCATE (tmpAverage, Average_##TYPE, MAX (Naverage, 1)); \
+      nitems = fread (tmpAverage, sizeof(Average_##TYPE), Naverage, f); \
+      if (nitems != Naverage) { \
+	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage); \
+	return (NULL); \
+      } \
+      gfits_convert_Average_##TYPE (tmpAverage, sizeof(Average_##TYPE), Naverage); \
+      average = Average_##TYPE##_ToInternal (tmpAverage, Naverage, primary); \
+      free (tmpAverage); \
+      break; } \
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      int nitems;
+      ALLOCATE (average, Average, MAX (Naverage, 1));
+      nitems = fread (average, sizeof(Average), Naverage, f);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to read averages (%d vs %d)\n", nitems, Naverage);
+	return (NULL);
+      }
+      gfits_convert_Average (average, sizeof(Average), Naverage);
+      break; }
+
+      FORMAT_CASE (LONEOS, Loneos);
+      FORMAT_CASE (ELIXIR, Elixir);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1, PS1_DEV_1);
+
+    default:
+      fprintf (stderr, "error reading measures\n");
+      return (NULL);
+  }
+# undef FORMAT_CASE
+
+  return (average);
+}
+
+/* accepts and converts internal average formats and outputs 
+   raw data in the specified format */
+int WriteRawAverage (FILE *f, Average *average, int Naverage, int format, SecFilt *primary) {
+
+// this macro generates the case statements for each type
+# define FORMAT_CASE(NAME,TYPE) \
+    case DVO_FORMAT_##NAME: { \
+      int nitems; \
+      Average_##TYPE *tmpAverage; \
+      tmpAverage = AverageInternalTo_##TYPE (average, Naverage, primary); \
+      gfits_convert_Average_##TYPE (tmpAverage, sizeof(Average_##TYPE), Naverage); \
+      nitems = fwrite (tmpAverage, sizeof(Average_##TYPE), Naverage, f); \
+      free (tmpAverage); \
+      if (nitems != Naverage) { \
+	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage); \
+	return (FALSE); \
+      } \
+      break; }
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      int nitems;
+      gfits_convert_Average (average, sizeof(Average), Naverage);
+      nitems = fwrite (average, sizeof(Average), Naverage, f);
+      if (nitems != Naverage) {
+	fprintf (stderr, "failed to write averages (%d vs %d)\n", nitems, Naverage);
+	return (FALSE);
+      }
+      break; }
+
+      FORMAT_CASE (LONEOS, Loneos);
+      FORMAT_CASE (ELIXIR, Elixir);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1, PS1_DEV_1);
+
+    default:
+      fprintf (stderr, "error writing averages\n");
+      return (FALSE);
+  }
+# undef FORMAT_CASE
+
+  return (TRUE);
+}
+
+/** Average / Raw Table conversions **/
+
+Measure *ReadRawMeasure (FILE *f, int Nmeasure, int format) {
+
+  Measure *measure;
+
+// this macro generates the case statements for each type
+# define FORMAT_CASE(NAME,TYPE) \
+    case DVO_FORMAT_##NAME: { \
+      int nitems; \
+      Measure_##TYPE *tmpMeasure; \
+      ALLOCATE (tmpMeasure, Measure_##TYPE, MAX (Nmeasure, 1)); \
+      nitems = fread (tmpMeasure, sizeof(Measure_##TYPE), Nmeasure, f); \
+      if (nitems != Nmeasure) { \
+	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure); \
+	return (NULL); \
+      } \
+      gfits_convert_Measure_##TYPE (tmpMeasure, sizeof(Measure_##TYPE), Nmeasure); \
+      measure = Measure_##TYPE##_ToInternal (tmpMeasure, Nmeasure); \
+      free (tmpMeasure); \
+      break; }
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      int nitems;
+      ALLOCATE (measure, Measure, MAX (Nmeasure, 1));
+      nitems = fread (measure, sizeof(Measure), Nmeasure, f);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to read measures (%d vs %d)\n", nitems, Nmeasure);
+	return (NULL);
+      }
+      gfits_convert_Measure (measure, sizeof(Measure), Nmeasure);
+      break; }
+
+      FORMAT_CASE (LONEOS, Loneos);
+      FORMAT_CASE (ELIXIR, Elixir);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1, PS1_DEV_1);
+
+    default:
+      fprintf (stderr, "error reading measures\n");
+      return (NULL);
+  }
+# undef FORMAT_CASE
+
+  return (measure);
+}
+
+/* accepts and converts internal measure formats and outputs 
+   raw data in the specified format */
+int WriteRawMeasure (FILE *f, Measure *measure, int Nmeasure, int format) {
+
+// this macro generates the case statements for each type
+# define FORMAT_CASE(NAME,TYPE) \
+    case DVO_FORMAT_##NAME: { \
+      int nitems; \
+      Measure_##TYPE *tmpMeasure; \
+      tmpMeasure = MeasureInternalTo_##TYPE (measure, Nmeasure); \
+      gfits_convert_Measure_##TYPE (tmpMeasure, sizeof(Measure_##TYPE), Nmeasure); \
+      nitems = fwrite (tmpMeasure, sizeof(Measure_##TYPE), Nmeasure, f); \
+      free (tmpMeasure); \
+      if (nitems != Nmeasure) { \
+	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure); \
+	return (FALSE); \
+      } \
+      break; }
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      int nitems;
+      gfits_convert_Measure (measure, sizeof(Measure), Nmeasure);
+      nitems = fwrite (measure, sizeof(Measure), Nmeasure, f);
+      if (nitems != Nmeasure) {
+	fprintf (stderr, "failed to write measures (%d vs %d)\n", nitems, Nmeasure);
+	return (FALSE);
+      }
+      break; }
+
+      FORMAT_CASE (LONEOS, Loneos);
+      FORMAT_CASE (ELIXIR, Elixir);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1, PS1_DEV_1);
+
+    default:
+      fprintf (stderr, "error writing measures\n");
+      return (FALSE);
+  }
+# undef FORMAT_CASE
+
+  return (TRUE);
+}
+
+/** SecFilt / Raw Table conversions **/
+
+SecFilt *ReadRawSecFilt (FILE *f, int Nsecfilt, int format) {
+
+  SecFilt *secfilt;
+
+// this macro generates the case statements for each type
+# define FORMAT_CASE(NAME,TYPE) \
+    case DVO_FORMAT_##NAME: { \
+      int nitems; \
+      SecFilt_##TYPE *tmpSecFilt; \
+      ALLOCATE (tmpSecFilt, SecFilt_##TYPE, MAX (Nsecfilt, 1)); \
+      nitems = fread (tmpSecFilt, sizeof(SecFilt_##TYPE), Nsecfilt, f); \
+      if (nitems != Nsecfilt) { \
+	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt); \
+	return (NULL); \
+      } \
+      gfits_convert_SecFilt_##TYPE (tmpSecFilt, sizeof(SecFilt_##TYPE), Nsecfilt); \
+      secfilt = SecFilt_##TYPE##_ToInternal (tmpSecFilt, Nsecfilt); \
+      free (tmpSecFilt); \
+      break; }
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      int nitems;
+      ALLOCATE (secfilt, SecFilt, MAX (Nsecfilt, 1));
+      nitems = fread (secfilt, sizeof(SecFilt), Nsecfilt, f);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to read secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (NULL);
+      }
+      gfits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
+      break; }
+
+      FORMAT_CASE (LONEOS, Loneos);
+      FORMAT_CASE (ELIXIR, Elixir);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1, PS1_DEV_1);
+
+    default:
+      fprintf (stderr, "error reading measures\n");
+      return (NULL);
+  }
+# undef FORMAT_CASE
+
+  return (secfilt);
+}
+
+/* accepts and converts internal secfilt formats and outputs 
+   raw data in the specified format */
+int WriteRawSecFilt (FILE *f, SecFilt *secfilt, int Nsecfilt, int format) {
+
+// this macro generates the case statements for each type
+# define FORMAT_CASE(NAME,TYPE) \
+    case DVO_FORMAT_##NAME: { \
+      int nitems; \
+      SecFilt_##TYPE *tmpSecFilt; \
+      tmpSecFilt = SecFiltInternalTo_##TYPE (secfilt, Nsecfilt); \
+      gfits_convert_SecFilt_##TYPE (tmpSecFilt, sizeof(SecFilt_##TYPE), Nsecfilt); \
+      nitems = fwrite (tmpSecFilt, sizeof(SecFilt_##TYPE), Nsecfilt, f); \
+      free (tmpSecFilt); \
+      if (nitems != Nsecfilt) { \
+	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt); \
+	return (FALSE); \
+      } \
+      break; }
+
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      int nitems;
+      gfits_convert_SecFilt (secfilt, sizeof(SecFilt), Nsecfilt);
+      nitems = fwrite (secfilt, sizeof(SecFilt), Nsecfilt, f);
+      if (nitems != Nsecfilt) {
+	fprintf (stderr, "failed to write secfilts (%d vs %d)\n", nitems, Nsecfilt);
+	return (FALSE);
+      }
+      break; }
+
+      FORMAT_CASE (LONEOS, Loneos);
+      FORMAT_CASE (ELIXIR, Elixir);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1, PS1_DEV_1);
+
+    default:
+      fprintf (stderr, "error writing secfilts\n");
+      return (FALSE);
+  }
+# undef FORMAT_CASE
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_split.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_catalog_split.c	(revision 16632)
@@ -0,0 +1,852 @@
+# include <dvo.h>
+
+// return options: 
+// * error (cannot lock, open, read, etc)
+// * empty (file is not found)
+// * ok
+
+int dvo_catalog_secfilt_to_primary (Catalog *catalog, SecFilt **myPrimary, SecFilt **mySecfilt, int *myNsecfilt) {
+
+  int i, j, Nallfilt, Nsecfilt, Ntotal;
+
+  SecFilt *primary;
+  SecFilt *secfilt;
+
+  if (catalog[0].secfilt == NULL) {       
+    fprintf (stderr, "missing secfilt, cannot build output averages (dvo_catalog_split.c)\n");
+    exit (1);
+  }
+  secfilt = catalog[0].secfilt;
+
+  // XXX this translation only works if we have loaded / created a matched average/secfilt set
+  assert (catalog[0].Nsecf_mem == catalog[0].Nsecfilt*catalog[0].Naverage);
+
+  Nallfilt = catalog[0].Nsecfilt;
+  Nsecfilt = catalog[0].Nsecfilt - 1;
+  Ntotal = Nsecfilt * catalog[0].Naverage;
+  ALLOCATE (primary, SecFilt, catalog[0].Naverage);
+  ALLOCATE (secfilt, SecFilt, Ntotal);
+
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    primary[i] = secfilt[i*Nallfilt + 0];
+    for (j = 0; j < Nsecfilt; j++) {
+      secfilt[i*Nsecfilt + j] = catalog[0].secfilt[i*Nallfilt + j + 1];
+    }
+  }		
+  catalog[0].Nsecfilt --;
+  catalog[0].Nsecf_mem = catalog[0].Naverage*catalog[0].Nsecfilt;
+
+  *myPrimary = primary;
+  *mySecfilt = secfilt;
+  *myNsecfilt = Nsecfilt;
+  return (TRUE);
+}
+
+int dvo_catalog_primary_to_secfilt (Catalog *catalog, SecFilt *primary, int Naves) {
+
+  int Ntmpfilt, Nsecfilt, Ntotal, i, j;
+  SecFilt *tmpfilt;
+
+  tmpfilt  = catalog[0].secfilt;
+  Ntmpfilt = catalog[0].Nsecfilt;
+
+  // we do NOT modify Nsecf_disk; this operation only modifies in in-memory values
+
+  catalog[0].Nsecfilt ++;
+  Nsecfilt = catalog[0].Nsecfilt;
+  Ntotal = Nsecfilt * Naves;
+
+  catalog[0].Nsecf_mem = Ntotal;
+
+  ALLOCATE (catalog[0].secfilt, SecFilt, Ntotal);
+  for (i = 0; i < Naves; i++) {
+    catalog[0].secfilt[i*Nsecfilt + 0] = primary[i];
+    for (j = 0; j < Ntmpfilt; j++) {
+      catalog[0].secfilt[i*Nsecfilt + j + 1] = tmpfilt[i*Ntmpfilt + j];
+    }
+  }		
+  free (tmpfilt);
+  free (primary);
+  return (TRUE);
+}
+
+int dvo_catalog_save_subcat (Catalog *catalog, FTable *ftable, int start, int Nrows, int Ndisk, int Ntotal) {
+
+  Matrix matrix;
+
+  /* rewind file pointers and truncate (file is still open) */
+  fseek (catalog->f, 0, SEEK_SET);
+
+  // write PHU header
+  if (!gfits_fwrite_header  (catalog->f, &catalog->header)) {
+    fprintf (stderr, "can't write primary header");
+    return (FALSE);
+  }
+
+  // write the PHU matrix; this is probably a NOP, do I have to keep it in?
+  gfits_create_matrix (&catalog->header, &matrix);
+  if (!gfits_fwrite_matrix  (catalog->f, &matrix)) {
+    fprintf (stderr, "can't write primary matrix");
+    gfits_free_matrix (&matrix);
+    return (FALSE);
+  }
+  gfits_free_matrix (&matrix);
+
+  // write the table data
+  if (!gfits_fwrite_ftable_range (catalog->f, ftable, start, Nrows, Ndisk, Ntotal)) {
+    fprintf (stderr, "can't write table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int dvo_catalog_open_subcat (Catalog *catalog, Catalog **Subcat, Header *header, char *name, int VERBOSE) {
+
+  int Nskip, status;
+  char *path, string[80];
+  Catalog *subcat;
+
+  /* in split mode, we need to init & open the corresponding measure file (even if we do not read
+   * any data in at this stage) */
+  ALLOCATE (subcat, Catalog, 1);
+  dvo_catalog_init (subcat, TRUE);
+
+  *Subcat = subcat;
+
+  /* needed to find the split files below */
+  path = pathname (catalog[0].filename);
+
+  /* get split filename from main header (paths relative to cpt file) */
+  if (!gfits_scan (&catalog[0].header, name,  "%s", 1, string)) {
+    free (path);
+    return (DVO_CAT_OPEN_FAIL);
+  }
+  ALLOCATE (subcat[0].filename, char, strlen(path) + strlen(string) + 2);
+  sprintf (subcat[0].filename, "%s/%s", path, string);
+  free (path);
+
+  /* lock & open catalog file */
+  status = dvo_catalog_lock (subcat, catalog[0].lockmode);
+  if (status != DVO_CAT_OPEN_OK) {
+    if (VERBOSE) {
+      if (status == DVO_CAT_OPEN_EMPTY) {
+	fprintf (stderr, "%s (%s) is empty\n", name, subcat[0].filename);
+      } else {
+	fprintf (stderr, "failure to lock %s (%s)\n", name, subcat[0].filename);
+      }
+    }
+    return (status);
+  }
+
+  /* read PHU */
+  if (!gfits_load_header (subcat[0].f, &subcat[0].header)) {
+    if (VERBOSE) fprintf (stderr, "error reading %s header: %s\n", name, subcat[0].filename);
+    return (DVO_CAT_OPEN_FAIL);
+  }
+  Nskip = gfits_data_size (&subcat[0].header);
+  fseek (subcat[0].f, Nskip, SEEK_CUR);
+
+  /* read Measure table header */
+  if (!gfits_fread_header (subcat[0].f, header)) {
+    if (VERBOSE) fprintf (stderr, "can't read %s PHU header\n", name);
+    gfits_free_header (&subcat[0].header);
+    return (DVO_CAT_OPEN_FAIL);
+  }
+  return (DVO_CAT_OPEN_OK);
+}
+
+int dvo_catalog_load_split (Catalog *catalog, int VERBOSE) {
+
+  int Nbytes, Nitems, Naverage, Nmeasure, Nmissing, Nsecfilt, status;
+  Header header;
+  FTable ftable;
+  SecFilt *primary;
+
+  /* ftable header storage for below */
+  ftable.header = &header;
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+  primary = NULL;
+
+  /* get the components from the header - these duplicate information in the split files (NAXIS2) */
+  if (!gfits_scan (&catalog[0].header, "NSTARS",   "%d", 1, &Naverage)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NMEAS",    "%d", 1, &Nmeasure)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NMISS",    "%d", 1, &Nmissing)) return (FALSE);
+  if (!gfits_scan (&catalog[0].header, "NSECFILT", "%d", 1, &Nsecfilt)) Nsecfilt = 0;
+
+  /* save the current number so we can do partial updates */
+  catalog[0].Naves_disk = Naverage;
+  catalog[0].Nmeas_disk = Nmeasure;
+  catalog[0].Nmiss_disk = Nmissing;
+  catalog[0].Nsecf_disk = Naverage * Nsecfilt;
+
+  /**  Nsecfilt is unusual: it does not list the number of data items in the table
+       instead, the number of items is Nsecfilt * Naverage.  **/
+  catalog[0].Nsecfilt  = Nsecfilt;
+
+  /* default values, but we will assign these a valid value before we exit (even if empty) */
+  catalog[0].average = NULL;
+  catalog[0].measure = NULL;
+  catalog[0].missing = NULL;
+  catalog[0].secfilt = NULL;
+
+  /*** Average Table ***/
+  if (catalog[0].catflags & LOAD_AVES) {
+    /* move pointer past header -- must be already read (load_catalog) */
+    Nbytes = catalog[0].header.size + gfits_data_size (&catalog[0].header);
+    fseek (catalog[0].f, Nbytes, SEEK_SET);
+    /* read Average table header */
+    if (!gfits_fread_header (catalog[0].f, &header)) { 
+      if (VERBOSE) fprintf (stderr, "can't read table average header");
+      return (FALSE);
+    }
+    /* read Average table data : format is irrelevant here */
+    if (!gfits_fread_ftable_data (catalog[0].f, &ftable)) { 
+      if (VERBOSE) fprintf (stderr, "can't read table average data");
+      return (FALSE);
+    }
+    /* convert the saved version of the table to the internal version.  Old versions of DVO stored
+     * one of the average magnitudes in Average.  We save this in case it is needed below.  NOTE:
+     * primary is only used if we read in the secfilt table, otherwise it should be freed */
+    catalog[0].average = FtableToAverage (&ftable, &Naverage, &catalog[0].catformat, &primary);
+    if (Naverage != catalog[0].Naves_disk) {
+      fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, catalog[0].Naves_disk);
+    }
+    gfits_free_header (&header);
+    catalog[0].Naverage = catalog[0].Naves_disk;
+    catalog[0].Naves_off = 0;
+  } else {
+    ALLOCATE (catalog[0].average, Average, 1);
+    catalog[0].Naverage = 0;
+    catalog[0].Naves_off = catalog[0].Naves_disk;
+  }
+
+  /*** Measure Table ***/
+  status = dvo_catalog_open_subcat (catalog, &catalog[0].measure_catalog, ftable.header, "MEASURE", VERBOSE);
+  if (status == DVO_CAT_OPEN_FAIL) {
+    return (FALSE);
+  }
+  if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nmeas_disk > 0)) {
+    return (FALSE);
+  }
+  if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_MEAS)) {
+    // XXX this allows an empty Measure catalog with non-empty Average catalog : is that OK?
+    /* read Measure table data */
+    if (!gfits_fread_ftable_data (catalog[0].measure_catalog[0].f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure data\n");
+      return (FALSE);
+    }
+    /* convert data format to internal : returns number of row read in Nmeasure */
+    catalog[0].measure = FtableToMeasure (&ftable, &Nmeasure, &catalog[0].catformat);
+    if (Nmeasure != catalog[0].Nmeas_disk) {
+      fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, catalog[0].Nmeas_disk);
+    }
+    catalog[0].Nmeasure = catalog[0].Nmeas_disk;
+    catalog[0].Nmeas_off = 0;
+  } else {
+    // XXX is it necessary to generate a template header here?
+    gfits_create_header (&catalog[0].measure_catalog[0].header);
+    ALLOCATE (catalog[0].measure, Measure, 1);
+    catalog[0].Nmeasure = 0;
+    catalog[0].Nmeas_off = catalog[0].Nmeas_disk;
+  }
+  gfits_free_header (&header);
+
+  /*** Missing Table ***/
+  status = dvo_catalog_open_subcat (catalog, &catalog[0].missing_catalog, ftable.header, "MISSING", VERBOSE);
+  if (status == DVO_CAT_OPEN_FAIL) {
+    return (FALSE);
+  }
+  if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nmiss_disk > 0)) {
+    return (FALSE);
+  }
+  if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_MISS)) {
+    /* read Missing table data */
+    if (!gfits_fread_ftable_data (catalog[0].missing_catalog[0].f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing data\n");
+      return (FALSE);
+    }
+    /* no conversions currently defined : this just does the byte swap */
+    catalog[0].missing = gfits_table_get_Missing (&ftable, &Nmissing, NULL);
+    if (Nmissing != catalog[0].Nmiss_disk) {
+      fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, catalog[0].Nmiss_disk);
+    }
+    catalog[0].Nmissing = catalog[0].Nmiss_disk;
+    catalog[0].Nmiss_off = 0;
+  } else {
+    // XXX is it necessary to generate a template header here?
+    gfits_create_header (&catalog[0].missing_catalog[0].header);
+    ALLOCATE (catalog[0].missing, Missing, 1);
+    catalog[0].Nmissing = 0;
+    catalog[0].Nmiss_off = catalog[0].Nmiss_disk;
+  }
+  gfits_free_header (ftable.header);
+
+  /*** Secfilt Table ***/
+  status = dvo_catalog_open_subcat (catalog, &catalog[0].secfilt_catalog, ftable.header, "SECFILT", VERBOSE);
+  if (status == DVO_CAT_OPEN_FAIL) {
+    return (FALSE);
+  }
+  if ((status == DVO_CAT_OPEN_EMPTY) && (catalog[0].Nsecf_disk > 0)) {
+    return (FALSE);
+  }
+  if ((status != DVO_CAT_OPEN_EMPTY) && (catalog[0].catflags & LOAD_SECF)) {
+    /* read secfilt table data */
+    if (!gfits_fread_ftable_data (catalog[0].secfilt_catalog[0].f, &ftable)) {
+      if (VERBOSE) fprintf (stderr, "can't read table secfilt data\n");
+      return (FALSE);
+    }
+    catalog[0].secfilt = FtableToSecFilt (&ftable, &Nitems, &catalog[0].catformat);
+    if (Nitems != catalog[0].Nsecf_disk) {
+      fprintf (stderr, "Warning: mismatch between Nsecfilt items in PHU and Table headers (%d vs %d)\n", Nitems, catalog[0].Nsecf_disk);
+    }
+    catalog[0].Nsecf_mem = catalog[0].Nsecf_disk;
+    catalog[0].Nsecf_off = 0;
+
+    /* if primary is defined, we were supplied with one additional average magnitude from Average
+       we need to interleave these magnitudes with the secfilt entries just loaded */
+    if (primary != NULL) {
+      // this modifies catalog.Nsecf_mem,Nsecfilt
+      dvo_catalog_primary_to_secfilt (catalog, primary, catalog[0].Naves_disk);
+    } 
+  } else {
+    if (primary != NULL) {
+      free (primary);
+      catalog[0].Nsecfilt ++;
+    }
+    gfits_create_header (&catalog[0].secfilt_catalog[0].header);
+    ALLOCATE (catalog[0].secfilt, SecFilt, 1);
+    catalog[0].Nsecf_mem = 0;
+    catalog[0].Nsecf_off = catalog[0].Nsecf_disk;
+  }
+  gfits_free_header (ftable.header);
+
+  return (TRUE);
+}
+
+// I need to always read both average and secfilt at the same time to correctly manage the
+// primary secfilt values...
+int dvo_catalog_load_segment_split (Catalog *catalog, int VERBOSE, int start, int Nrows) {
+
+  int Nbytes, Naverage, Nexpect, Nitems, Nmeasure, Nmissing;
+  Header header;
+  FTable ftable;
+  SecFilt *primary;
+
+  /* ftable header storage for below */
+  ftable.header = &header;
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+  primary = NULL;
+
+  /*** Average (& SecFilt) Table ***/
+  if (catalog[0].catflags & LOAD_AVES) {
+
+    /*** load the Average data ***/
+    /* move pointer past header and matrix -- must be already read (load_catalog) */
+    Nbytes = catalog[0].header.size + gfits_data_size (&catalog[0].header);
+    fseek (catalog[0].f, Nbytes, SEEK_SET);
+    /* read Average table header */
+    if (!gfits_fread_header (catalog[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average header");
+      return (FALSE);
+    }
+    /* read Average table data : format is irrelevant here */
+    if (!gfits_fread_ftable_range (catalog[0].f, &ftable, start, Nrows)) {
+      if (VERBOSE) fprintf (stderr, "can't read table average data");
+      return (FALSE);
+    }
+
+    /* convert the saved version of the table to the internal version.  Old versions of DVO stored
+     * one of the average magnitudes in Average.  We save this in case it is needed below.  NOTE:
+     * primary is only used if we read in the secfilt table, otherwise it should be freed */
+    catalog[0].average = FtableToAverage (&ftable, &Naverage, &catalog[0].catformat, &primary);
+    if (Naverage != Nrows) {
+      // XXX this condition denotes the eof has been reached; not an error or a warning
+      // fprintf (stderr, "Warning: mismatch between Naverage in PHU and Table headers (%d vs %d)\n", Naverage, Nrows);
+    }
+    gfits_free_header (&header);
+    catalog[0].Naverage = Naverage;
+    catalog[0].Naves_off = start;
+
+    /*** load the secfilt data ***/
+    Catalog *subcat = catalog[0].secfilt_catalog;
+
+    /* move pointer past header -- must be already read (load_catalog) */
+    Nbytes = subcat[0].header.size + gfits_data_size (&subcat[0].header);
+    fseek (subcat[0].f, Nbytes, SEEK_SET);
+
+    /* read Secfilt table header */
+    if (!gfits_fread_header (subcat[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure header");
+      return (FALSE);
+    }
+    /* read Secfilt table data : format is irrelevant here */
+    if (!gfits_fread_ftable_range (subcat[0].f, &ftable, start*catalog[0].Nsecfilt, catalog[0].Naverage*catalog[0].Nsecfilt)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure data");
+      return (FALSE);
+    }
+
+    Nexpect = catalog[0].Naverage * catalog[0].Nsecfilt;
+    catalog[0].secfilt = FtableToSecFilt (&ftable, &Nitems, &catalog[0].catformat);
+    if (Nitems != Nexpect) {
+      fprintf (stderr, "Warning: mismatch between Nsecfilt items in PHU and Table headers (%d vs %d)\n", Nitems, Nexpect);
+    }
+    catalog[0].Nsecf_mem = catalog[0].Naverage * catalog[0].Nsecfilt;
+    catalog[0].Nsecf_off = start               * catalog[0].Nsecfilt;
+
+    /* if primary is defined, we were supplied with one additional average magnitude from Average
+       we need to interleave these magnitudes with the secfilt entries just loaded */
+    if (primary != NULL) {
+      dvo_catalog_primary_to_secfilt (catalog, primary, Nrows);
+    } 
+    gfits_free_header (&header);
+  }
+
+  // XXX check the open status of the catalog
+  if (catalog[0].catflags & LOAD_MEAS) {
+
+    Catalog *subcat = catalog[0].measure_catalog;
+
+    /* move pointer past header -- must be already read (load_catalog) */
+    Nbytes = subcat[0].header.size + gfits_data_size (&subcat[0].header);
+    fseek (subcat[0].f, Nbytes, SEEK_SET);
+
+    /* read Measure table header */
+    if (!gfits_fread_header (subcat[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure header");
+      return (FALSE);
+    }
+    /* read Measure table data : format is irrelevant here */
+    if (!gfits_fread_ftable_range (subcat[0].f, &ftable, start, Nrows)) {
+      if (VERBOSE) fprintf (stderr, "can't read table measure data");
+      return (FALSE);
+    }
+
+    /* convert data format to internal : returns number of row read in Nmeasure */
+    catalog[0].measure = FtableToMeasure (&ftable, &Nmeasure, &catalog[0].catformat);
+    if (Nmeasure != Nrows) {
+      fprintf (stderr, "Warning: mismatch between Nmeasure in PHU and Table headers (%d vs %d)\n", Nmeasure, Nrows);
+    }
+    gfits_free_header (&header);
+    catalog[0].Nmeasure = Nmeasure;
+    catalog[0].Nmeas_off = start;
+  }
+
+  // XXX check the open status of the catalog?
+  if (catalog[0].catflags & LOAD_MISS) {
+
+    Catalog *subcat = catalog[0].missing_catalog;
+
+    /* move pointer past header -- must be already read (load_catalog) */
+    Nbytes = subcat[0].header.size + gfits_data_size (&subcat[0].header);
+    fseek (subcat[0].f, Nbytes, SEEK_SET);
+
+    /* read Missing table header */
+    if (!gfits_fread_header (subcat[0].f, &header)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing header");
+      return (FALSE);
+    }
+    /* read Missing table data : format is irrelevant here */
+    if (!gfits_fread_ftable_range (subcat[0].f, &ftable, start, Nrows)) {
+      if (VERBOSE) fprintf (stderr, "can't read table missing data");
+      return (FALSE);
+    }
+
+    /* no conversions currently defined : this just does the byte swap */
+    catalog[0].missing = gfits_table_get_Missing (&ftable, &Nmissing, NULL);
+    if (Nmissing != Nrows) {
+      fprintf (stderr, "Warning: mismatch between Nmissing in PHU and Table headers (%d vs %d)\n", Nmissing, Nrows);
+    }
+    gfits_free_header (&header);
+    catalog[0].Nmissing = Nmissing;
+    catalog[0].Nmiss_off = start;
+  }
+  return (TRUE);
+}
+
+/* save_catalog_split writes all data currently in memory to disk */
+int dvo_catalog_save_split (Catalog *catalog, char VERBOSE) {
+
+  int Nitems;
+  Header header;
+  FTable ftable;
+  SecFilt *primary, *secfilt;
+  int Nsecfilt;
+  int Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new;
+  int first, start, Nrows;
+
+  ftable.header = &header;
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+  primary = NULL;
+  
+  // skip empty catalogs: it is illegal to have Measures without corresponding Averages
+  Naves_disk_new = MAX (catalog[0].Naves_disk, catalog[0].Naverage + catalog[0].Naves_off);
+  if (Naves_disk_new == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  // for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary
+  switch (catalog[0].catformat) {
+    case DVO_FORMAT_ELIXIR: // special case for ELIXIR
+    case DVO_FORMAT_LONEOS: // special case for LONEOS
+      dvo_catalog_secfilt_to_primary (catalog, &primary, &secfilt, &Nsecfilt);
+      break;
+    default:
+      primary = NULL;
+      secfilt = catalog[0].secfilt;
+      Nsecfilt = catalog[0].Nsecfilt;
+      break;
+  }
+
+  Nmeas_disk_new = MAX (catalog[0].Nmeas_disk, catalog[0].Nmeasure + catalog[0].Nmeas_off);
+  Nmiss_disk_new = MAX (catalog[0].Nmiss_disk, catalog[0].Nmissing + catalog[0].Nmiss_off);
+  Nsecf_disk_new = MAX (catalog[0].Nsecf_disk, catalog[0].Naverage*Nsecfilt + catalog[0].Nsecf_off);
+
+  /* make sure header is consistent with data */
+  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, Naves_disk_new);
+  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, Nmeas_disk_new);
+  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, Nmiss_disk_new);
+  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt);
+  gfits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
+
+  /* in split mode, we can save only part of the data */ 
+
+  /*** Average Table ***/
+  if ((catalog[0].catflags & LOAD_AVES) && (catalog[0].average != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Naves_off; // first disk row to write
+    Nrows  = catalog[0].Naverage - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= catalog[0].Naverage);
+    assert (catalog[0].Naves_disk >= catalog[0].Naves_off);
+
+    /* convert internal to external format */
+    if (!AverageToFtable (&ftable, &catalog[0].average[first], Nrows, catalog[0].catformat, primary)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    if (!dvo_catalog_save_subcat (catalog, &ftable, start, Nrows, catalog[0].Naves_disk, Naves_disk_new)) {
+      fprintf (stderr, "failure writing Average table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  } else {
+    // even if we do not save the average table, we need to keep the header in sync
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (catalog[0].f, 0, SEEK_SET);
+
+    /* write table PHU header - always write this out */
+    /* XXX EAM : check if disk file size has changed */
+    if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      goto failure;
+    }
+  }
+
+  /*** Measure Table ***/
+  if ((catalog[0].catflags & LOAD_MEAS) && (catalog[0].measure != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Nmeas_off; // first disk row to write
+    Nrows  = catalog[0].Nmeasure - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= catalog[0].Nmeasure);
+    assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off);
+
+    // convert to external table format
+    if (!MeasureToFtable (&ftable, &catalog[0].measure[first], Nrows, catalog[0].catformat)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Measure table
+    if (!dvo_catalog_save_subcat (catalog[0].measure_catalog, &ftable, start, Nrows, catalog[0].Nmeas_disk, Nmeas_disk_new)) {
+      fprintf (stderr, "trouble writing Measure table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Missing Table ***/
+  if ((catalog[0].catflags & LOAD_MISS) && (catalog[0].missing != NULL)) {
+
+    if (catalog[0].Nmiss_off != 0) {
+      fprintf (stderr, "inconsistency: Missing table cannot be written in segments\n");
+      goto failure;
+    }
+
+    // convert to external table format
+    if (!gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Missing table (must write out entire table)
+    if (!dvo_catalog_save_subcat (catalog[0].missing_catalog, &ftable, 0, catalog[0].Nmissing, catalog[0].Nmissing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble writing Missing Table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Secfilt Table ***/
+  if ((catalog[0].catflags & LOAD_SECF) && (catalog[0].secfilt != NULL)) {
+
+    first  = 0;                    // first row in memory to write
+    start  = catalog[0].Nsecf_off; // first disk row to write
+    Nitems = catalog[0].Nsecf_mem;
+    Nrows  = Nitems - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= Nitems);
+    assert (catalog[0].Nsecf_disk >= catalog[0].Nsecf_off);
+    // XXX check these for consistency...
+
+    // convert to external table format
+    SecFiltToFtable (&ftable, &secfilt[first], Nrows, catalog[0].catformat);
+
+    // write out SecFilt table
+    if (!dvo_catalog_save_subcat (catalog[0].secfilt_catalog, &ftable, start, Nrows, catalog[0].Nsecf_disk, Nsecf_disk_new)) {
+      fprintf (stderr, "failure writing SecFilt table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (TRUE);
+
+failure:
+  /* free temp storage */
+  gfits_free_header (&header);
+  gfits_free_table (&ftable);
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (FALSE);
+}
+
+/* update_catalog_split only writes new lines to file. */
+int dvo_catalog_update_split (Catalog *catalog, char VERBOSE) {
+
+  int Nitems;
+  Header header;
+  FTable ftable;
+  SecFilt *primary, *secfilt;
+  int Nsecfilt;
+  int Naves_disk_new, Nmeas_disk_new, Nmiss_disk_new, Nsecf_disk_new;
+  int first, start, Nrows;
+
+  ftable.header = &header;
+  ftable.buffer = NULL;
+  header.buffer = NULL;
+
+  // skip empty catalogs: it is illegal to have Measures without corresponding Averages
+  Naves_disk_new = MAX (catalog[0].Naves_disk, catalog[0].Naverage + catalog[0].Naves_off);
+  if (Naves_disk_new == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (TRUE);
+  }
+
+  // for the appropriate types, pull out the first secfilt and pass to AverageToFtable as primary 
+  switch (catalog[0].catformat) {
+    case DVO_FORMAT_ELIXIR: // special case for ELIXIR
+    case DVO_FORMAT_LONEOS: // special case for LONEOS
+      dvo_catalog_secfilt_to_primary (catalog, &primary, &secfilt, &Nsecfilt);
+      break;
+    default:
+      primary = NULL;
+      secfilt = catalog[0].secfilt;
+      Nsecfilt = catalog[0].Nsecfilt;
+      break;
+  }
+
+  Nmeas_disk_new = MAX (catalog[0].Nmeas_disk, catalog[0].Nmeasure + catalog[0].Nmeas_off);
+  Nmiss_disk_new = MAX (catalog[0].Nmiss_disk, catalog[0].Nmissing + catalog[0].Nmiss_off);
+  Nsecf_disk_new = MAX (catalog[0].Nsecf_disk, catalog[0].Naverage*Nsecfilt + catalog[0].Nsecf_off);
+
+  /* make sure header is consistent with data */
+  gfits_modify (&catalog[0].header, "NSTARS",   "%d", 1, Naves_disk_new);
+  gfits_modify (&catalog[0].header, "NMEAS",    "%d", 1, Nmeas_disk_new);
+  gfits_modify (&catalog[0].header, "NMISS",    "%d", 1, Nmiss_disk_new);
+  gfits_modify (&catalog[0].header, "NSECFILT", "%d", 1, Nsecfilt);
+  gfits_modify (&catalog[0].header, "EXTEND",   "%t", 1, TRUE);
+
+  /* in split mode, we can save only part of the data */ 
+
+  /*** Average Table ***/
+  if (catalog[0].average != NULL) {
+
+    first  = catalog[0].Naves_disk - catalog[0].Naves_off; // first row to write (memory)
+    start  = catalog[0].Naves_disk;                        // first row to write (disk)
+    Nrows  = catalog[0].Naverage - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= catalog[0].Naverage);
+    assert (catalog[0].Naves_disk >= catalog[0].Naves_off);
+
+    /* convert internal to external format */
+    if (!AverageToFtable (&ftable, &catalog[0].average[first], Nrows, catalog[0].catformat, primary)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    if (!dvo_catalog_save_subcat (catalog, &ftable, start, Nrows, catalog[0].Naves_disk, Naves_disk_new)) {
+      fprintf (stderr, "failure writing Average table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  } else {
+    // even if we do not save the average table, we need to keep the header in sync
+    /* rewind file pointers and truncate (file is still open) */
+    fseek (catalog[0].f, 0, SEEK_SET);
+
+    /* write table PHU header - always write this out */
+    /* XXX EAM : check if disk file size has changed */
+    if (!gfits_fwrite_header  (catalog[0].f, &catalog[0].header)) {
+      fprintf (stderr, "can't write primary header");
+      goto failure;
+    }
+  }
+
+  /*** Measure Table ***/
+  if (catalog[0].measure != NULL) {
+
+    first  = catalog[0].Nmeas_disk - catalog[0].Nmeas_off;  // first row in memory to write
+    start  = catalog[0].Nmeas_off; // first disk row to write
+    Nrows  = catalog[0].Nmeasure - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= catalog[0].Nmeasure);
+    assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off);
+
+    // convert to external table format
+    if (!MeasureToFtable (&ftable, &catalog[0].measure[first], Nrows, catalog[0].catformat)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Measure table
+    if (!dvo_catalog_save_subcat (catalog[0].measure_catalog, &ftable, start, Nrows, catalog[0].Nmeas_disk, Nmeas_disk_new)) {
+      fprintf (stderr, "trouble writing Measure table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /* missing table CANNOT be written unsorted, thus it is always written 
+     out in full */
+
+  /*** Missing Table ***/
+
+  if (catalog[0].missing != NULL) {
+
+    if (catalog[0].Nmiss_off != 0) {
+      fprintf (stderr, "inconsistency: Missing table cannot be written in segments\n");
+      goto failure;
+    }
+
+    // convert to external table format
+    if (!gfits_table_set_Missing (&ftable, catalog[0].missing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble converting format\n");
+      goto failure;
+    }
+
+    // write out Missing table (must write out entire table)
+    if (!dvo_catalog_save_subcat (catalog[0].missing_catalog, &ftable, 0, catalog[0].Nmissing, catalog[0].Nmissing, catalog[0].Nmissing)) {
+      fprintf (stderr, "trouble writing Missing Table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /*** Secfilt Table ***/
+  if (catalog[0].secfilt != NULL) {
+
+    first  = catalog[0].Nsecf_disk - catalog[0].Nsecf_off;  // first row in memory to write
+    start  = catalog[0].Nsecf_off; // first disk row to write
+    Nitems = catalog[0].Nsecf_mem;
+    Nrows  = Nitems - first;
+
+    assert (Nrows >= 0);
+    assert (first >= 0);
+    assert (first <= Nitems);
+    assert (catalog[0].Nmeas_disk >= catalog[0].Nmeas_off);
+
+    // convert to external table format
+    SecFiltToFtable (&ftable, &secfilt[first], Nrows, catalog[0].catformat);
+
+    // write out SecFilt table
+    if (!dvo_catalog_save_subcat (catalog[0].secfilt_catalog, &ftable, start, Nrows, catalog[0].Nsecf_disk, Nsecf_disk_new)) {
+      fprintf (stderr, "failure writing SecFilt table\n");
+      goto failure;
+    }
+    gfits_free_header (&header);
+    gfits_free_table (&ftable);
+  }
+
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+
+  return (TRUE);
+
+failure:
+  /* free temp storage */
+  if (primary != NULL) {
+    free (primary);
+    free (secfilt);
+  }
+  return (FALSE);
+}
+
+/* in split mode, extra files are linked to catalog->measure_catalog, etc.  Each
+   has a valid filename, f, header.  The primary catalog data pointers are set
+   to point at the corresponding entries from the elements on the chain. An
+   unloaded entry has a null pointer here.
+*/
+
+/* XXX EAM : this file needs work on the error exit conditions and memory leaks, esp under errors */
+
+/* XXX EAM : update is not efficient.  MeasureToFtable should only 
+   convert the new rows (Nmeas_disk to Nmeasure). the resulting
+   table represents the end rows of the ftable.  we need to define
+   the vtable based on the ftable, but with Ny = Nmeasure */  
+  
+
+
+    // * convert to an ftable
+    // * optionally write the PHU header/matrix
+    // * advance to the start of the output data block:
+    // ** Nx * catalog[0].Nmeas_off
+    // * write out the ftable data block
+    // * if Nmeas_off + Nmeasure >= Nmeas_disk, update padding
+    // ** start = Nmeas_off
+    // ** Nrows = Nmeasure
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert.c	(revision 16632)
@@ -0,0 +1,371 @@
+# include <dvo.h>
+
+/* The Ftable-TYPE conversion functions determine the format of table based on EXTNAME in header.
+   they convert the table to the internal format, and set 'format'.  
+
+   The TYPE-Ftable conversions functions create output tables in the format requested
+   by the 'format' function parameter.
+*/
+
+/** this file might be more readable if I use macros for the repetative
+    constructions below **/
+
+/*** Average / FTable conversion functions ***/
+
+Average *FtableToAverage (FTable *ftable, int *Naverage, int *format, SecFilt **primary) {
+
+  Average *average;
+  char extname[80];
+
+  /* in the Elixir and Loneos cases, we are supplied with an average magnitude in Average
+     in these cases, save these values in primary; otherwise set primary to NULL */
+  *primary = NULL;
+
+  /* convert to the internal format */
+  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
+    fprintf (stderr, "EXTNAME missing for average table\n");
+    return (FALSE);
+  }
+
+# define CONVERT_FORMAT(NAME, FORMAT, TYPE) \
+  if (!strcmp (extname, NAME)) { \
+    Average_##TYPE *tmpAverage; \
+    tmpAverage = gfits_table_get_Average_##TYPE (ftable, Naverage, NULL); \
+    average = Average_##TYPE##_ToInternal (tmpAverage, *Naverage, primary); \
+    free (tmpAverage); \
+    *format = DVO_FORMAT_##FORMAT; \
+    return (average); }
+
+  if (!strcmp (extname, "DVO_AVERAGE")) {
+    average = gfits_table_get_Average (ftable, Naverage, NULL);
+    *format = DVO_FORMAT_INTERNAL;
+    return (average);
+  }
+
+  CONVERT_FORMAT ("DVO_AVERAGE_ELIXIR", 	 ELIXIR, 	  Elixir);
+  CONVERT_FORMAT ("DVO_AVERAGE_LONEOS", 	 LONEOS, 	  Loneos);
+  CONVERT_FORMAT ("DVO_AVERAGE_PANSTARRS_DEV_0", PANSTARRS_DEV_0, Panstarrs_DEV_0);
+  CONVERT_FORMAT ("DVO_AVERAGE_PANSTARRS_DEV_1", PANSTARRS_DEV_1, Panstarrs_DEV_1);
+  CONVERT_FORMAT ("DVO_AVERAGE_PS1_DEV_1",       PS1_DEV_1,       PS1_DEV_1);
+# undef CONVERT_FORMAT
+
+  fprintf (stderr, "table format unknown: %s\n", extname);
+
+  *Naverage = 0;
+  return (NULL);
+}
+
+int AverageToFtable (FTable *ftable, Average *average, int Naverage, int format, SecFilt *primary) {
+
+# define FORMAT_CASE(FORMAT, TYPE) \
+    case DVO_FORMAT_##FORMAT: { \
+      Average_##TYPE *tmpAverage; \
+      tmpAverage = AverageInternalTo_##TYPE (average, Naverage, primary); \
+      gfits_table_set_Average_##TYPE (ftable, tmpAverage, Naverage); \
+      free (tmpAverage); \
+      break; }
+
+  /* convert from the internal format */
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      gfits_table_set_Average (ftable, average, Naverage);
+      break; }
+
+      FORMAT_CASE (ELIXIR, 	    Elixir);
+      FORMAT_CASE (LONEOS, 	    Loneos);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1,       PS1_DEV_1);
+# undef FORMAT_CASE
+
+    default:
+      fprintf (stderr, "table format unknown (average)\n");
+      return (FALSE);
+  }
+  return (TRUE);
+}
+
+/*** Measure / FTable conversion functions ***/
+
+Measure *FtableToMeasure (FTable *ftable, int *Nmeasure, int *format) {
+
+  Measure *measure;
+  char extname[80];
+
+  /* convert to the internal format */
+  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
+    fprintf (stderr, "EXTNAME missing for measure table\n");
+    return (FALSE);
+  }
+
+# define CONVERT_FORMAT(NAME, FORMAT, TYPE) \
+  if (!strcmp (extname, NAME)) { \
+    Measure_##TYPE *tmpMeasure; \
+    tmpMeasure = gfits_table_get_Measure_##TYPE (ftable, Nmeasure, NULL); \
+    measure = Measure_##TYPE##_ToInternal (tmpMeasure, *Nmeasure); \
+    free (tmpMeasure); \
+    *format = DVO_FORMAT_##FORMAT; \
+    return (measure); }
+
+  if (!strcmp (extname, "DVO_MEASURE")) {
+    measure = gfits_table_get_Measure (ftable, Nmeasure, NULL);
+    *format = DVO_FORMAT_INTERNAL;
+    return (measure);
+  }
+
+  CONVERT_FORMAT ("DVO_MEASURE_ELIXIR", 	 ELIXIR, 	  Elixir);
+  CONVERT_FORMAT ("DVO_MEASURE_LONEOS", 	 LONEOS,          Loneos);
+  CONVERT_FORMAT ("DVO_MEASURE_PANSTARRS_DEV_0", PANSTARRS_DEV_0, Panstarrs_DEV_0);
+  CONVERT_FORMAT ("DVO_MEASURE_PANSTARRS_DEV_1", PANSTARRS_DEV_1, Panstarrs_DEV_1);
+  CONVERT_FORMAT ("DVO_MEASURE_PS1_DEV_1",       PS1_DEV_1,       PS1_DEV_1);
+# undef CONVERT_FORMAT
+
+  fprintf (stderr, "table format unknown: %s\n", extname);
+
+  *Nmeasure = 0;
+  return (NULL);
+}
+
+int MeasureToFtable (FTable *ftable, Measure *measure, int Nmeasure, int format) {
+
+# define FORMAT_CASE(FORMAT, TYPE) \
+    case DVO_FORMAT_##FORMAT: { \
+      Measure_##TYPE *tmpMeasure; \
+      tmpMeasure = MeasureInternalTo_##TYPE (measure, Nmeasure); \
+      gfits_table_set_Measure_##TYPE (ftable, tmpMeasure, Nmeasure); \
+      free (tmpMeasure); \
+      break; }
+
+  /* convert from the internal format */
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      gfits_table_set_Measure (ftable, measure, Nmeasure);
+      break; }
+
+      FORMAT_CASE (ELIXIR, 	    Elixir);
+      FORMAT_CASE (LONEOS, 	    Loneos);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1,       PS1_DEV_1);
+# undef FORMAT_CASE
+
+    default:
+      fprintf (stderr, "table format unknown (measure)\n");
+      return (FALSE);
+  }
+  return (TRUE);
+}
+
+/*** SecFilt / FTable conversion functions ***/
+
+SecFilt *FtableToSecFilt (FTable *ftable, int *Nsecfilt, int *format) {
+
+  SecFilt *secfilt;
+  char extname[80];
+
+  /* convert to the internal format */
+  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
+    fprintf (stderr, "EXTNAME missing for secfilt table\n");
+    return (FALSE);
+  }
+
+# define CONVERT_FORMAT(NAME, FORMAT, TYPE) \
+  if (!strcmp (extname, NAME)) { \
+    SecFilt_##TYPE *tmpSecFilt; \
+    tmpSecFilt = gfits_table_get_SecFilt_##TYPE (ftable, Nsecfilt, NULL); \
+    secfilt = SecFilt_##TYPE##_ToInternal (tmpSecFilt, *Nsecfilt); \
+    free (tmpSecFilt); \
+    *format = DVO_FORMAT_##FORMAT; \
+    return (secfilt); }
+
+  if (!strcmp (extname, "DVO_SECFILT")) {
+    secfilt = gfits_table_get_SecFilt (ftable, Nsecfilt, NULL);
+    *format = DVO_FORMAT_INTERNAL;
+    return (secfilt);
+  }
+
+  CONVERT_FORMAT ("DVO_SECFILT_ELIXIR", 	 ELIXIR, 	  Elixir);
+  CONVERT_FORMAT ("DVO_SECFILT_LONEOS", 	 LONEOS, 	  Loneos);
+  CONVERT_FORMAT ("DVO_SECFILT_PANSTARRS_DEV_0", PANSTARRS_DEV_0, Panstarrs_DEV_0);
+  CONVERT_FORMAT ("DVO_SECFILT_PANSTARRS_DEV_1", PANSTARRS_DEV_1, Panstarrs_DEV_1);
+  CONVERT_FORMAT ("DVO_SECFILT_PS1_DEV_1",       PS1_DEV_1,       PS1_DEV_1);
+# undef CONVERT_FORMAT
+
+  fprintf (stderr, "table format unknown: %s\n", extname);
+
+  *Nsecfilt = 0;
+  return (NULL);
+}
+
+int SecFiltToFtable (FTable *ftable, SecFilt *secfilt, int Nsecfilt, int format) {
+
+# define FORMAT_CASE(FORMAT, TYPE) \
+    case DVO_FORMAT_##FORMAT: { \
+      SecFilt_##TYPE *tmpSecFilt; \
+      tmpSecFilt = SecFiltInternalTo_##TYPE (secfilt, Nsecfilt); \
+      gfits_table_set_SecFilt_##TYPE (ftable, tmpSecFilt, Nsecfilt); \
+      free (tmpSecFilt); \
+      break; }
+
+  /* convert from the internal format */
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      gfits_table_set_SecFilt (ftable, secfilt, Nsecfilt);
+      break; }
+
+      FORMAT_CASE (ELIXIR, 	    Elixir);
+      FORMAT_CASE (LONEOS, 	    Loneos);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1,       PS1_DEV_1);
+# undef FORMAT_CASE
+
+    default:
+      fprintf (stderr, "table format unknown (secfilt)\n");
+      return (FALSE);
+  }
+  return (TRUE);
+}
+
+/*** Image Conversions ***/
+
+int FtableToImage (FTable *ftable, Header *theader, int *format) {
+
+  int Nimage;
+  char extname[80];
+
+  /* extname may be set from outside if the source is RAW not MEF */
+  if (*format == DVO_FORMAT_ELIXIR) {		  // special case for ELIXIR
+    Image_Elixir *tmpimage;
+    tmpimage = gfits_table_get_Image_Elixir (ftable, &Nimage, NULL);
+    ftable[0].buffer = (char *) Image_Elixir_ToInternal (tmpimage, Nimage);
+    free (tmpimage);
+    gfits_free_header (theader);
+    gfits_table_mkheader_Image (theader);
+    gfits_modify (theader, "NAXIS2", "%d", 1, Nimage);
+    theader[0].Naxis[1] = Nimage;
+    ftable[0].size = gfits_data_size (theader);
+    return (TRUE);
+  }
+
+  /* convert to the internal format */
+  if (!gfits_scan (ftable[0].header, "EXTNAME", "%s", 1, extname)) {
+    fprintf (stderr, "EXTNAME missing for image table\n");
+    return (FALSE);
+  }
+
+# define CONVERT_FORMAT(NAME, FORMAT, TYPE) \
+  if (!strcmp (extname, NAME)) { \
+    Image_##TYPE *tmpimage; \
+    *format = DVO_FORMAT_##FORMAT; \
+    tmpimage = gfits_table_get_Image_##TYPE (ftable, &Nimage, NULL); \
+    ftable[0].buffer = (char *) Image_##TYPE##_ToInternal (tmpimage, Nimage); \
+    free (tmpimage); \
+    gfits_free_header (theader); \
+    gfits_table_mkheader_Image (theader); \
+    gfits_modify (theader, "NAXIS2", "%d", 1, Nimage); \
+    theader[0].Naxis[1] = Nimage; \
+    ftable[0].size = gfits_data_size (theader); \
+    return (TRUE); }
+
+  if (!strcmp (extname, "DVO_IMAGE")) {
+    Image *image;
+    image = gfits_table_get_Image (ftable, &Nimage, NULL);
+    *format = DVO_FORMAT_INTERNAL;
+    return (TRUE);
+  }
+
+  CONVERT_FORMAT ("DVO_IMAGE_ELIXIR", 	       ELIXIR,          Elixir);
+  CONVERT_FORMAT ("DVO_IMAGE_LONEOS", 	       LONEOS,          Loneos);
+  CONVERT_FORMAT ("DVO_IMAGE_PANSTARRS_DEV_0", PANSTARRS_DEV_0, Panstarrs_DEV_0);
+  CONVERT_FORMAT ("DVO_IMAGE_PANSTARRS_DEV_1", PANSTARRS_DEV_1, Panstarrs_DEV_1);
+  CONVERT_FORMAT ("DVO_IMAGE_PS1_DEV_1",       PS1_DEV_1,       PS1_DEV_1);
+# undef CONVERT_FORMAT
+
+  fprintf (stderr, "table format unknown: %s\n", extname);
+  return (FALSE);
+}
+
+int ImageToFtable (FTable *ftable, Header *theader, int format) {
+
+  int Nimage;
+
+  Nimage = theader[0].Naxis[1];
+
+# define FORMAT_CASE(FORMAT, TYPE) \
+    case DVO_FORMAT_##FORMAT: { \
+      Image_##TYPE *tmpImage; \
+      tmpImage = ImageInternalTo_##TYPE ((Image *) ftable[0].buffer, Nimage); \
+      free (ftable[0].buffer); \
+      gfits_table_set_Image_##TYPE (ftable, tmpImage, Nimage); \
+      free (tmpImage); \
+      break; }
+
+  /* convert from the internal format */
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      gfits_convert_Image ((Image *) ftable[0].buffer, sizeof(Image), Nimage);
+      break; }
+
+      FORMAT_CASE (ELIXIR, 	    Elixir);
+      FORMAT_CASE (LONEOS, 	    Loneos);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1,       PS1_DEV_1);
+# undef FORMAT_CASE
+
+    default:
+      fprintf (stderr, "table format unknown (image ftable)\n");
+      return (FALSE);
+  }
+  return (TRUE);
+}
+
+int ImageToVtable (VTable *vtable, Header *theader, int format) {
+
+  int i, Nrow, Nimage;
+
+  Nrow = vtable[0].Nrow;
+
+# define FORMAT_CASE(FORMAT, TYPE) \
+  case DVO_FORMAT_##FORMAT: { \
+      Image_##TYPE *tmpImage; \
+      /* convert table rows from internal to external format */ \
+      for (i = 0; i < Nrow; i++) { \
+	  tmpImage = ImageInternalTo_##TYPE ((Image *) vtable[0].buffer[i], 1); \
+	  gfits_convert_Image_##TYPE (tmpImage, sizeof(Image_##TYPE), 1); \
+	  free (vtable[0].buffer[i]); \
+	  vtable[0].buffer[i] = (char *) tmpImage; \
+      } \
+      /* convert header from old format to new format */ \
+      gfits_scan (theader, "NAXIS2", "%d", 1, &Nimage); \
+      gfits_free_header (theader); \
+      gfits_table_mkheader_Image_##TYPE (theader); \
+      gfits_modify (theader, "NAXIS2", "%d", 1, Nimage); \
+      theader[0].Naxis[1] = Nimage; \
+      vtable[0].size = gfits_data_size (theader); \
+      return (TRUE); }
+
+
+  /* convert from the internal format */
+  switch (format) {
+    case DVO_FORMAT_INTERNAL: {
+      for (i = 0; i < Nrow; i++) {
+	gfits_convert_Image ((Image *) vtable[0].buffer[i], sizeof(Image), 1);
+      }
+      return (TRUE); }
+
+      FORMAT_CASE (ELIXIR, 	    Elixir);
+      FORMAT_CASE (LONEOS, 	    Loneos);
+      FORMAT_CASE (PANSTARRS_DEV_0, Panstarrs_DEV_0);
+      FORMAT_CASE (PANSTARRS_DEV_1, Panstarrs_DEV_1);
+      FORMAT_CASE (PS1_DEV_1,       PS1_DEV_1);
+# undef FORMAT_CASE
+
+    default:
+      break;
+  }
+  fprintf (stderr, "table format unknown (image vtable)\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_PS1_DEV_1.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_PS1_DEV_1.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_PS1_DEV_1.c	(revision 16632)
@@ -0,0 +1,301 @@
+# include <dvo.h>
+
+// XXX these functions ahve to be adjusted to agree with the new definition of PS1_DEV_1
+
+/* convert panstarrs-format measures to internal measures */
+Measure *Measure_PS1_DEV_1_ToInternal (Measure_PS1_DEV_1 *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR         = in[i].dR;
+    out[i].dD         = in[i].dD;
+    out[i].M          = in[i].M;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].Mgal       = in[i].Mgal;
+    out[i].dM         = in[i].dM;
+    out[i].dt         = in[i].dt;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].detID      = in[i].detID;
+    out[i].imageID    = in[i].imageID;
+    out[i].qPSF       = in[i].qPSF;
+    out[i].psfProb    = in[i].psfProb;
+    out[i].crNsigma   = in[i].crNsigma;
+    out[i].extNsigma  = in[i].extNsigma;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].photcode   = in[i].photcode;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].dbFlags    = in[i].dbFlags;
+    out[i].photFlags  = in[i].photFlags;
+    out[i].stargal    = in[i].stargal;
+    out[i].dophot     = in[i].dophot;
+  }
+  return (out);
+}
+
+/* convert internal measures to panstarrs-format measures */
+Measure_PS1_DEV_1 *MeasureInternalTo_PS1_DEV_1 (Measure *in, int Nvalues) {
+
+  int i;
+  Measure_PS1_DEV_1 *out;
+
+  ALLOCATE (out, Measure_PS1_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR         = in[i].dR;
+    out[i].dD         = in[i].dD;
+    out[i].M          = in[i].M;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].Mgal       = in[i].Mgal;
+    out[i].dM         = in[i].dM;
+    out[i].dt         = in[i].dt;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].detID      = in[i].detID;
+    out[i].imageID    = in[i].imageID;
+    out[i].qPSF       = in[i].qPSF;
+    out[i].psfProb    = in[i].psfProb;
+    out[i].crNsigma   = in[i].crNsigma;
+    out[i].extNsigma  = in[i].extNsigma;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].photcode   = in[i].photcode;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].dbFlags    = in[i].dbFlags;
+    out[i].photFlags  = in[i].photFlags;
+    out[i].stargal    = in[i].stargal;
+    out[i].dophot     = in[i].dophot;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format averages to internal averages */
+// 'primary is needed to conform with the API for Loneos and Elixir, but is not used
+Average *Average_PS1_DEV_1_ToInternal (Average_PS1_DEV_1 *in, int Nvalues, SecFilt **primary) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R        = in[i].R;      
+    out[i].D        = in[i].D;      
+    out[i].Xp       = in[i].Xp;     
+    out[i].Nm       = in[i].Nm;     
+    out[i].Nn       = in[i].Nn;     
+    out[i].code     = in[i].code;   
+    out[i].offset   = in[i].offset; 
+    out[i].missing  = in[i].missing;
+    out[i].dR       = in[i].dR;
+    out[i].dD       = in[i].dD;
+    out[i].uR       = in[i].uR;
+    out[i].uD       = in[i].uD;
+    out[i].duR      = in[i].duR;
+    out[i].duD      = in[i].duD;
+    out[i].P        = in[i].P;
+    out[i].dP       = in[i].dP;
+    out[i].objID_hi = in[i].objID_hi;
+    out[i].objID_lo = in[i].objID_lo;
+  }
+  return (out);
+}
+
+/* convert internal averages to panstarrs-format averages */
+// 'primary is needed to conform with the API for Loneos and Elixir, but is not used
+Average_PS1_DEV_1 *AverageInternalTo_PS1_DEV_1 (Average *in, int Nvalues, SecFilt *primary) {
+
+  int i;
+  Average_PS1_DEV_1 *out;
+
+  ALLOCATE (out, Average_PS1_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R        = in[i].R;      
+    out[i].D        = in[i].D;      
+    out[i].Xp       = in[i].Xp;     
+    out[i].Nm       = in[i].Nm;     
+    out[i].Nn       = in[i].Nn;     
+    out[i].code     = in[i].code;   
+    out[i].offset   = in[i].offset; 
+    out[i].missing  = in[i].missing;
+    out[i].dR       = in[i].dR;
+    out[i].dD       = in[i].dD;
+    out[i].uR       = in[i].uR;
+    out[i].uD       = in[i].uD;
+    out[i].duR      = in[i].duR;
+    out[i].duD      = in[i].duD;
+    out[i].P        = in[i].P;
+    out[i].dP       = in[i].dP;
+    out[i].objID_hi = in[i].objID_hi;
+    out[i].objID_lo = in[i].objID_lo;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format secfilts to internal secfilts */
+SecFilt *SecFilt_PS1_DEV_1_ToInternal (SecFilt_PS1_DEV_1 *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = in[i].M;      
+    out[i].dM    = in[i].dM;      
+    out[i].Xm    = in[i].Xm;     
+    out[i].Ncode = in[i].Ncode;
+    out[i].Nused = in[i].Nused;
+ }
+  return (out);
+}
+
+/* convert internal secfilts to panstarrs-format secfilts */
+SecFilt_PS1_DEV_1 *SecFiltInternalTo_PS1_DEV_1 (SecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt_PS1_DEV_1 *out;
+
+  ALLOCATE (out, SecFilt_PS1_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = in[i].M;      
+    out[i].dM    = in[i].dM;      
+    out[i].Xm    = in[i].Xm;     
+    out[i].Ncode = in[i].Ncode;
+    out[i].Nused = in[i].Nused;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format images to internal images */
+Image *Image_PS1_DEV_1_ToInternal (Image_PS1_DEV_1 *in, int Nvalues) {
+
+  int i;
+  Image *out;
+
+  ALLOCATE (out, Image, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strcpy (out[i].name, in[i].name);
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].imageID	    = in[i].imageID;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
+
+/* convert internal images to panstarrs-format images */
+Image_PS1_DEV_1 *ImageInternalTo_PS1_DEV_1 (Image *in, int Nvalues) {
+
+  int i;
+  Image_PS1_DEV_1 *out;
+
+  ALLOCATE (out, Image_PS1_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strcpy (out[i].name, in[i].name);
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].imageID	    = in[i].imageID;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_elixir.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_elixir.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_elixir.c	(revision 16632)
@@ -0,0 +1,298 @@
+# include <dvo.h>
+
+/* convert elixir-format measures to internal measures */
+Measure *Measure_Elixir_ToInternal (Measure_Elixir *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR       = (in[i].dR      == NAN_S_SHORT) ? NAN : in[i].dR     * 0.01;
+    out[i].dD       = (in[i].dD      == NAN_S_SHORT) ? NAN : in[i].dD     * 0.01;
+    out[i].M        = (in[i].M       == NAN_S_SHORT) ? NAN : in[i].M      * 0.001;
+    out[i].dM       = (in[i].dM      == NAN_U_CHAR)  ? NAN : in[i].dM     * 0.001;
+    out[i].dt       = (in[i].dt      == NAN_S_SHORT) ? NAN : in[i].dt     * 0.001;
+    out[i].Mcal     = (in[i].Mcal    == NAN_S_SHORT) ? NAN : in[i].Mcal   * 0.001;
+    out[i].Mgal     = (in[i].Mgal    == NAN_S_SHORT) ? NAN : in[i].Mgal   * 0.001;
+    out[i].airmass  = (in[i].airmass == NAN_S_SHORT) ? NAN : in[i].airmass* 0.001;
+    out[i].FWx 	    = in[i].FWx;
+    out[i].FWy 	    = in[i].fwy * in[i].FWx * 0.01;
+    out[i].theta    = in[i].theta*(0x10000 / 0x100);
+    out[i].dophot   = in[i].dophot;
+    out[i].photcode = in[i].source;
+    out[i].t        = in[i].t;
+    out[i].averef   = in[i].averef;
+    out[i].dbFlags  = in[i].flags;
+    
+    /* these can be determined if needed / desired */
+    out[i].Xccd     = 0;
+    out[i].Yccd     = 0;
+    out[i].dXccd    = 0;
+    out[i].dYccd    = 0;
+
+    /* these do not have a corresponding value */
+    out[i].az        = 0;
+    out[i].stargal   = 0;
+    out[i].Sky       = 0;
+    out[i].dSky      = 0;
+    out[i].qPSF      = 0;
+    out[i].psfProb   = 0;
+    out[i].crNsigma  = 0;
+    out[i].extNsigma = 0;
+    out[i].photFlags = 0;
+
+    /* XXX add these later */
+    out[i].detID = 0;
+    out[i].imageID = 0;
+  }
+  return (out);
+}
+
+/* convert internal measures to elixir-format measures */
+Measure_Elixir *MeasureInternalTo_Elixir (Measure *in, int Nvalues) {
+
+  int i;
+  Measure_Elixir *out;
+
+  ALLOCATE (out, Measure_Elixir, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR       = isnan(in[i].dR     ) ? NAN_S_SHORT : in[i].dR      *  100.0;
+    out[i].dD       = isnan(in[i].dD     ) ? NAN_S_SHORT : in[i].dD      *  100.0;
+    out[i].M        = isnan(in[i].M      ) ? NAN_S_SHORT : in[i].M       * 1000.0;
+    out[i].dM       = isnan(in[i].dM     ) ? NAN_U_CHAR  : in[i].dM      * 1000.0;
+    out[i].dt       = isnan(in[i].dt     ) ? NAN_S_SHORT : in[i].dt      * 1000.0;
+    out[i].Mcal     = isnan(in[i].Mcal   ) ? NAN_S_SHORT : in[i].Mcal    * 1000.0;
+    out[i].Mgal     = isnan(in[i].Mgal   ) ? NAN_S_SHORT : in[i].Mgal    * 1000.0;
+    out[i].airmass  = isnan(in[i].airmass) ? NAN_S_SHORT : in[i].airmass * 1000.0;
+
+    if (out[i].M < 0) {
+	fprintf (stderr, ".");
+    }
+
+    out[i].FWx 	   = in[i].FWx;
+    out[i].fwy 	   = in[i].FWy * 100.0 / in[i].FWx;
+    out[i].theta   = in[i].theta*(0x100/ 0x10000);
+    out[i].dophot  = in[i].dophot;
+    out[i].source  = in[i].photcode;
+    out[i].t       = in[i].t;
+    out[i].averef  = in[i].averef;
+    out[i].flags   = in[i].dbFlags;
+  }
+  return (out);
+}
+
+/* convert elixir-format averages to internal averages */
+Average *Average_Elixir_ToInternal (Average_Elixir *in, int Nvalues, SecFilt **primary) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+  ALLOCATE (*primary, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R       = in[i].R;      
+    out[i].D       = in[i].D;      
+    out[i].Xp      = in[i].Xp;     
+    out[i].Nm      = in[i].Nm;     
+    out[i].Nn      = in[i].Nn;     
+    out[i].code    = in[i].code;   
+    out[i].offset  = in[i].offset; 
+    out[i].missing = in[i].missing;
+
+    /* these don't exist in Elixir */
+    out[i].dR      = 0;
+    out[i].dD      = 0;
+    out[i].uR      = 0;
+    out[i].uD      = 0;
+    out[i].duR     = 0;
+    out[i].duD     = 0;
+    out[i].P       = 0;
+    out[i].dP      = 0;
+
+    /* XXX add these later */
+    out[i].objID_hi = 0;
+    out[i].objID_lo = 0;
+
+    primary[0][i].M     = (in[i].M  == NAN_S_SHORT) ? NAN : in[i].M  * 0.001;      
+    primary[0][i].dM    = (in[i].dM == NAN_S_SHORT) ? NAN : in[i].dM * 0.001;      
+    primary[0][i].Xm    = in[i].Xm;     
+    primary[0][i].Ncode = 0;     
+    primary[0][i].Nused = 0;
+  }
+  return (out);
+}
+
+/* convert internal averages to elixir-format averages */
+Average_Elixir *AverageInternalTo_Elixir (Average *in, int Nvalues, SecFilt *primary) {
+
+  int i;
+  Average_Elixir *out;
+
+  ALLOCATE (out, Average_Elixir, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R       = in[i].R;      
+    out[i].D       = in[i].D;      
+    out[i].Xp      = in[i].Xp;     
+    out[i].Nm      = in[i].Nm;     
+    out[i].Nn      = in[i].Nn;     
+    out[i].code    = in[i].code;   
+    out[i].offset  = in[i].offset; 
+    out[i].missing = in[i].missing;
+
+    out[i].M       = isnan(primary[i].M)  ? NAN_S_SHORT : primary[i].M   * 1000.0;
+    out[i].dM      = isnan(primary[i].dM) ? NAN_S_SHORT : primary[i].dM  * 1000.0;
+    out[i].Xm      = primary[i].Xm;     
+  }
+  return (out);
+}
+
+/* convert elixir-format secfilts to internal secfilts */
+SecFilt *SecFilt_Elixir_ToInternal (SecFilt_Elixir *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = (in[i].M  == NAN_S_SHORT) ? NAN : in[i].M   * 0.001;
+    out[i].dM    = (in[i].dM == NAN_S_SHORT) ? NAN : in[i].dM  * 0.001;
+    out[i].Xm    = in[i].Xm;     
+    out[i].Ncode = 0;
+    out[i].Nused = 0;
+  }
+  return (out);
+}
+
+/* convert internal secfilts to elixir-format secfilts */
+SecFilt_Elixir *SecFiltInternalTo_Elixir (SecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt_Elixir *out;
+
+  ALLOCATE (out, SecFilt_Elixir, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = isnan(in[i].M)  ? NAN_S_SHORT : in[i].M   * 1000.0;
+    out[i].dM    = isnan(in[i].dM) ? NAN_S_SHORT : in[i].dM  * 1000.0;
+    out[i].Xm    = in[i].Xm;     
+  }
+  return (out);
+}
+
+/* convert elixir-format images to internal images */
+Image *Image_Elixir_ToInternal (Image_Elixir *in, int Nvalues) {
+
+  int i;
+  Image *out;
+
+  ALLOCATE (out, Image, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strcpy (out[i].name, in[i].name); // out[64], in[32]
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].secz    	    = (in[i].secz     == NAN_S_SHORT) ? NAN : in[i].secz     * 0.001;
+    out[i].apmifit  	    = (in[i].apmifit  == NAN_S_SHORT) ? NAN : in[i].apmifit  * 0.001;
+    out[i].dapmifit  	    = (in[i].dapmifit == NAN_S_SHORT) ? NAN : in[i].dapmifit * 0.001;
+    out[i].Mcal   	    = (in[i].Mcal     == NAN_S_SHORT) ? NAN : in[i].Mcal     * 0.001;
+    out[i].dMcal   	    = (in[i].dMcal    == NAN_S_SHORT) ? NAN : in[i].dMcal    * 0.001;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].source;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+
+    /* XXX add these later */
+    out[i].imageID = 0;
+
+    // not available in ELIXIR
+    out[i].sidtime  	    = NAN;
+    out[i].latitude  	    = NAN;
+  }
+  return (out);
+}
+
+/* convert internal images to elixir-format images */
+Image_Elixir *ImageInternalTo_Elixir (Image *in, int Nvalues) {
+
+  int i;
+  Image_Elixir *out;
+
+  ALLOCATE (out, Image_Elixir, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[64]
+    out[i].name[31] = 0; // force termination
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].secz    	    = isnan(in[i].secz    ) ? NAN_S_SHORT : in[i].secz     * 1000.0;
+    out[i].apmifit    	    = isnan(in[i].apmifit ) ? NAN_S_SHORT : in[i].apmifit  * 1000.0;
+    out[i].dapmifit    	    = isnan(in[i].dapmifit) ? NAN_S_SHORT : in[i].dapmifit * 1000.0;
+    out[i].Mcal    	    = isnan(in[i].Mcal    ) ? NAN_S_SHORT : in[i].Mcal     * 1000.0;
+    out[i].dMcal    	    = isnan(in[i].dMcal   ) ? NAN_S_SHORT : in[i].dMcal    * 1000.0;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].source   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_loneos.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_loneos.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_loneos.c	(revision 16632)
@@ -0,0 +1,286 @@
+# include <dvo.h>
+
+/* convert loneos-format measures to internal measures */
+Measure *Measure_Loneos_ToInternal (Measure_Loneos *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR        = (in[i].dR      == NAN_S_SHORT) ? NAN : in[i].dR     * 0.01;
+    out[i].dD        = (in[i].dD      == NAN_S_SHORT) ? NAN : in[i].dD     * 0.01;
+    out[i].M         = (in[i].M       == NAN_S_SHORT) ? NAN : in[i].M      * 0.001;
+    out[i].dM        = (in[i].dM      == NAN_U_CHAR)  ? NAN : in[i].dM     * 0.001;
+    out[i].Mcal      = (in[i].Mcal    == NAN_S_SHORT) ? NAN : in[i].Mcal   * 0.001;
+    out[i].dophot    = in[i].dophot;
+    out[i].photcode  = in[i].source;
+    out[i].t         = in[i].t;
+
+    /* flags and averef are now split */
+    out[i].averef    =  in[i].averef & 0x00ffffff;
+    out[i].dbFlags   = (in[i].averef & 0xff000000) >> 24;
+
+    /* these values don't exist in the Loneos format */
+    out[i].Mgal     = out[i].M;
+    out[i].dt       = 0;
+    out[i].airmass  = 0;
+    out[i].az       = 0;
+    out[i].FWx 	    = 0;
+    out[i].FWy 	    = 0;
+    out[i].theta    = 0;
+    out[i].stargal  = 0;
+    out[i].Sky      = 0;
+    out[i].dSky     = 0;
+    out[i].qPSF     = 0;
+    out[i].psfProb   = 0;
+    out[i].crNsigma  = 0;
+    out[i].extNsigma = 0;
+    out[i].photFlags = 0;
+
+    /* these can be determined if needed / desired */
+    out[i].Xccd     = 0;
+    out[i].Yccd     = 0;
+    out[i].dXccd    = 0;
+    out[i].dYccd    = 0;
+
+    /* XXX add these later */
+    out[i].detID = 0;
+    out[i].imageID = 0;
+  }
+  return (out);
+}
+
+/* convert internal measures to loneos-format measures */
+Measure_Loneos *MeasureInternalTo_Loneos (Measure *in, int Nvalues) {
+
+  int i;
+  Measure_Loneos *out;
+
+  ALLOCATE (out, Measure_Loneos, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR     = isnan(in[i].dR     ) ? NAN_S_SHORT : in[i].dR      *  100.0;
+    out[i].dD     = isnan(in[i].dD     ) ? NAN_S_SHORT : in[i].dD      *  100.0;
+    out[i].M      = isnan(in[i].M      ) ? NAN_S_SHORT : in[i].M       * 1000.0;
+    out[i].dM     = isnan(in[i].dM     ) ? NAN_U_CHAR  : in[i].dM      * 1000.0;
+    out[i].Mcal   = isnan(in[i].Mcal   ) ? NAN_S_SHORT : in[i].Mcal    * 1000.0;
+    out[i].dophot = in[i].dophot;
+    out[i].source = in[i].photcode;
+    out[i].t      = in[i].t;
+
+    /* flags and averef are merged in Loneos */
+    out[i].averef =  (in[i].averef & 0x00ffffff) | (in[i].dbFlags << 24);
+  }
+  return (out);
+}
+
+/* convert loneos-format averages to internal averages */
+Average *Average_Loneos_ToInternal (Average_Loneos *in, int Nvalues, SecFilt **primary) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+  ALLOCATE (*primary, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R       = in[i].R;      
+    out[i].D       = in[i].D;      
+    out[i].Xp      = in[i].Xp;     
+    out[i].Nm      = in[i].Nm;     
+    out[i].Nn      = in[i].Nn;     
+    out[i].code    = in[i].code;   
+    out[i].offset  = in[i].offset; 
+    out[i].missing = in[i].missing;
+
+    /* these don't exist in Loneos */
+    out[i].dR      = 0;
+    out[i].dD      = 0;
+    out[i].uR      = 0;
+    out[i].uD      = 0;
+    out[i].duR     = 0;
+    out[i].duD     = 0;
+    out[i].P       = 0;
+    out[i].dP      = 0;
+
+    /* XXX add these later */
+    out[i].objID_hi = 0;
+    out[i].objID_lo = 0;
+
+    primary[0][i].M  = (in[i].M  == NAN_S_SHORT) ? NAN : in[i].M  * 0.001;      
+    primary[0][i].Xm = in[i].Xm;     
+    primary[0][i].dM = NAN;
+    primary[0][i].Ncode = 0;     
+    primary[0][i].Nused = 0;
+  }
+  return (out);
+}
+
+/* convert internal averages to loneos-format averages */
+Average_Loneos *AverageInternalTo_Loneos (Average *in, int Nvalues, SecFilt *primary) {
+
+  int i;
+  Average_Loneos *out;
+
+  ALLOCATE (out, Average_Loneos, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R       = in[i].R;      
+    out[i].D       = in[i].D;      
+    out[i].Xp      = in[i].Xp;     
+    out[i].Nm      = in[i].Nm;     
+    out[i].Nn      = in[i].Nn;     
+    out[i].code    = in[i].code;   
+    out[i].offset  = in[i].offset; 
+    out[i].missing = in[i].missing;
+
+    out[i].M       = isnan(primary[i].M)  ? NAN_S_SHORT : primary[i].M   * 1000.0;
+    out[i].Xm      = primary[i].Xm;     
+  }
+  return (out);
+}
+
+/* convert loneos-format secfilts to internal secfilts */
+SecFilt *SecFilt_Loneos_ToInternal (SecFilt_Loneos *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = (in[i].M  == NAN_S_SHORT) ? NAN : in[i].M * 0.001;
+    out[i].Xm    = in[i].Xm;      
+    out[i].dM    = NAN;
+    out[i].Ncode = 0;
+    out[i].Nused = 0;
+  }
+  return (out);
+}
+
+/* convert internal secfilts to loneos-format secfilts */
+SecFilt_Loneos *SecFiltInternalTo_Loneos (SecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt_Loneos *out;
+
+  ALLOCATE (out, SecFilt_Loneos, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M    = isnan(in[i].M)  ? NAN_S_SHORT : in[i].M * 1000.0;
+    out[i].Xm   = in[i].Xm;      
+  }
+  return (out);
+}
+
+/* convert loneos-format images to internal images */
+Image *Image_Loneos_ToInternal (Image_Loneos *in, int Nvalues) {
+
+  int i;
+  Image *out;
+
+  ALLOCATE (out, Image, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strcpy (out[i].name, in[i].name); // out[64], in[32]
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+
+    out[i].secz    	    = (in[i].secz     == NAN_S_SHORT) ? NAN : in[i].secz     * 0.001;
+    out[i].apmifit  	    = (in[i].apmifit  == NAN_S_SHORT) ? NAN : in[i].apmifit  * 0.001;
+    out[i].dapmifit  	    = (in[i].dapmifit == NAN_S_SHORT) ? NAN : in[i].dapmifit * 0.001;
+    out[i].Mcal   	    = (in[i].Mcal     == NAN_S_SHORT) ? NAN : in[i].Mcal     * 0.001;
+    out[i].dMcal   	    = (in[i].dMcal    == NAN_S_SHORT) ? NAN : in[i].dMcal    * 0.001;
+
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].source;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+
+    /* XXX add these later */
+    out[i].imageID = 0;
+  }
+  return (out);
+}
+
+/* convert internal images to loneos-format images */
+Image_Loneos *ImageInternalTo_Loneos (Image *in, int Nvalues) {
+
+  int i;
+  Image_Loneos *out;
+
+  ALLOCATE (out, Image_Loneos, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[64]
+    out[i].name[31] = 0; // force termination
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+
+    out[i].secz    	    = isnan(in[i].secz    ) ? NAN_S_SHORT : in[i].secz     * 1000.0;
+    out[i].apmifit    	    = isnan(in[i].apmifit ) ? NAN_S_SHORT : in[i].apmifit  * 1000.0;
+    out[i].dapmifit    	    = isnan(in[i].dapmifit) ? NAN_S_SHORT : in[i].dapmifit * 1000.0;
+    out[i].Mcal    	    = isnan(in[i].Mcal    ) ? NAN_S_SHORT : in[i].Mcal     * 1000.0;
+    out[i].dMcal    	    = isnan(in[i].dMcal   ) ? NAN_S_SHORT : in[i].dMcal    * 1000.0;
+
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].source   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_panstarrs_DEV_0.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_panstarrs_DEV_0.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_panstarrs_DEV_0.c	(revision 16632)
@@ -0,0 +1,301 @@
+# include <dvo.h>
+
+/* convert panstarrs-format measures to internal measures */
+Measure *Measure_Panstarrs_DEV_0_ToInternal (Measure_Panstarrs_DEV_0 *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR         = in[i].dR;
+    out[i].dD         = in[i].dD;
+    out[i].M          = in[i].M;
+    out[i].dM         = in[i].dM;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].Mgal       = in[i].Mgal;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].dt         = in[i].dt;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].dophot     = in[i].dophot;
+    out[i].photcode   = in[i].photcode;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].dbFlags    = in[i].flags;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].stargal    = in[i].stargal;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].qPSF       = (in[i].qPSF == NAN_S_SHORT) ? NAN : in[i].qPSF;
+    out[i].detID      = in[i].detID_lo;
+    out[i].imageID    = in[i].imageID_lo;
+
+    // these don't have a correspondence
+    out[i].psfProb   = 0;
+    out[i].crNsigma  = 0;
+    out[i].extNsigma = 0;
+    out[i].photFlags = 0;
+  }
+  return (out);
+}
+
+/* convert internal measures to panstarrs-format measures */
+Measure_Panstarrs_DEV_0 *MeasureInternalTo_Panstarrs_DEV_0 (Measure *in, int Nvalues) {
+
+  int i;
+  Measure_Panstarrs_DEV_0 *out;
+
+  ALLOCATE (out, Measure_Panstarrs_DEV_0, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR         = in[i].dR;
+    out[i].dD         = in[i].dD;
+    out[i].M          = in[i].M;
+    out[i].dM         = in[i].dM;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].Mgal       = in[i].Mgal;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].dt         = in[i].dt;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].dophot     = in[i].dophot;
+    out[i].photcode   = in[i].photcode;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].flags      = in[i].dbFlags;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].stargal    = in[i].stargal;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].qPSF       = isnan(in[i].qPSF) ? NAN_S_SHORT : in[i].qPSF;
+    out[i].detID_hi   = 0;
+    out[i].detID_lo   = in[i].detID;
+    out[i].imageID_hi = 0;
+    out[i].imageID_lo = in[i].imageID;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format averages to internal averages */
+// 'primary is needed to conform with the API for Loneos and Elixir, but is not used
+Average *Average_Panstarrs_DEV_0_ToInternal (Average_Panstarrs_DEV_0 *in, int Nvalues, SecFilt **primary) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R        = in[i].R;      
+    out[i].D        = in[i].D;      
+    out[i].Xp       = in[i].Xp;     
+    out[i].Nm       = in[i].Nm;     
+    out[i].Nn       = in[i].Nn;     
+    out[i].code     = in[i].code;   
+    out[i].offset   = in[i].offset; 
+    out[i].missing  = in[i].missing;
+    out[i].dR       = in[i].dR;
+    out[i].dD       = in[i].dD;
+    out[i].uR       = in[i].uR;
+    out[i].uD       = in[i].uD;
+    out[i].duR      = in[i].duR;
+    out[i].duD      = in[i].duD;
+    out[i].P        = in[i].P;
+    out[i].dP       = in[i].dP;
+    out[i].objID_hi = in[i].objID_hi;
+    out[i].objID_lo = in[i].objID_lo;
+  }
+  return (out);
+}
+
+/* convert internal averages to panstarrs-format averages */
+// 'primary is needed to conform with the API for Loneos and Elixir, but is not used
+Average_Panstarrs_DEV_0 *AverageInternalTo_Panstarrs_DEV_0 (Average *in, int Nvalues, SecFilt *primary) {
+
+  int i;
+  Average_Panstarrs_DEV_0 *out;
+
+  ALLOCATE (out, Average_Panstarrs_DEV_0, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R        = in[i].R;      
+    out[i].D        = in[i].D;      
+    out[i].Xp       = in[i].Xp;     
+    out[i].Nm       = in[i].Nm;     
+    out[i].Nn       = in[i].Nn;     
+    out[i].code     = in[i].code;   
+    out[i].offset   = in[i].offset; 
+    out[i].missing  = in[i].missing;
+    out[i].dR       = in[i].dR;
+    out[i].dD       = in[i].dD;
+    out[i].uR       = in[i].uR;
+    out[i].uD       = in[i].uD;
+    out[i].duR      = in[i].duR;
+    out[i].duD      = in[i].duD;
+    out[i].P        = in[i].P;
+    out[i].dP       = in[i].dP;
+    out[i].objID_hi = in[i].objID_hi;
+    out[i].objID_lo = in[i].objID_lo;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format secfilts to internal secfilts */
+SecFilt *SecFilt_Panstarrs_DEV_0_ToInternal (SecFilt_Panstarrs_DEV_0 *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = in[i].M;      
+    out[i].dM    = in[i].dM;      
+    out[i].Xm    = in[i].Xm;     
+    out[i].Ncode = in[i].Ncode;
+    out[i].Nused = in[i].Nused;
+ }
+  return (out);
+}
+
+/* convert internal secfilts to panstarrs-format secfilts */
+SecFilt_Panstarrs_DEV_0 *SecFiltInternalTo_Panstarrs_DEV_0 (SecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt_Panstarrs_DEV_0 *out;
+
+  ALLOCATE (out, SecFilt_Panstarrs_DEV_0, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = in[i].M;      
+    out[i].dM    = in[i].dM;      
+    out[i].Xm    = in[i].Xm;     
+    out[i].Ncode = in[i].Ncode;
+    out[i].Nused = in[i].Nused;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format images to internal images */
+Image *Image_Panstarrs_DEV_0_ToInternal (Image_Panstarrs_DEV_0 *in, int Nvalues) {
+
+  int i;
+  Image *out;
+
+  ALLOCATE (out, Image, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strcpy (out[i].name, in[i].name); // out[64], in[32]
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].imageID	    = in[i].imageID_lo;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
+
+/* convert internal images to panstarrs-format images */
+Image_Panstarrs_DEV_0 *ImageInternalTo_Panstarrs_DEV_0 (Image *in, int Nvalues) {
+
+  int i;
+  Image_Panstarrs_DEV_0 *out;
+
+  ALLOCATE (out, Image_Panstarrs_DEV_0, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[64]
+    out[i].name[31] = 0; // force termination
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].imageID_hi	    = 0;
+    out[i].imageID_lo	    = in[i].imageID;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_panstarrs_DEV_1.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_panstarrs_DEV_1.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_convert_panstarrs_DEV_1.c	(revision 16632)
@@ -0,0 +1,300 @@
+# include <dvo.h>
+
+/* convert panstarrs-format measures to internal measures */
+Measure *Measure_Panstarrs_DEV_1_ToInternal (Measure_Panstarrs_DEV_1 *in, int Nvalues) {
+
+  int i;
+  Measure *out;
+
+  ALLOCATE (out, Measure, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR         = in[i].dR;
+    out[i].dD         = in[i].dD;
+    out[i].M          = in[i].M;
+    out[i].dM         = in[i].dM;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].Mgal       = in[i].Mgal;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].dt         = in[i].dt;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].dophot     = in[i].dophot;
+    out[i].photcode   = in[i].photcode;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].dbFlags    = in[i].flags;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].stargal    = in[i].stargal;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].qPSF       = (in[i].qPSF == NAN_S_SHORT) ? NAN : in[i].qPSF;
+    out[i].detID      = in[i].detID_lo;
+    out[i].imageID    = in[i].imageID_lo;
+
+    // these don't have a correspondence
+    out[i].psfProb   = 0;
+    out[i].crNsigma  = 0;
+    out[i].extNsigma = 0;
+    out[i].photFlags = 0;
+  }
+  return (out);
+}
+
+/* convert internal measures to panstarrs-format measures */
+Measure_Panstarrs_DEV_1 *MeasureInternalTo_Panstarrs_DEV_1 (Measure *in, int Nvalues) {
+
+  int i;
+  Measure_Panstarrs_DEV_1 *out;
+
+  ALLOCATE (out, Measure_Panstarrs_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].dR         = in[i].dR;
+    out[i].dD         = in[i].dD;
+    out[i].M          = in[i].M;
+    out[i].dM         = in[i].dM;
+    out[i].Mcal       = in[i].Mcal;
+    out[i].Mgal       = in[i].Mgal;
+    out[i].airmass    = in[i].airmass;
+    out[i].az         = in[i].az;
+    out[i].dt         = in[i].dt;
+    out[i].FWx 	      = in[i].FWx;
+    out[i].FWy 	      = in[i].FWy;
+    out[i].theta      = in[i].theta;
+    out[i].dophot     = in[i].dophot;
+    out[i].photcode   = in[i].photcode;
+    out[i].t          = in[i].t;
+    out[i].averef     = in[i].averef;
+    out[i].flags      = in[i].dbFlags;
+    out[i].Xccd       = in[i].Xccd;
+    out[i].Yccd       = in[i].Yccd;
+    out[i].dXccd      = in[i].dXccd;
+    out[i].dYccd      = in[i].dYccd;
+    out[i].stargal    = in[i].stargal;
+    out[i].Sky        = in[i].Sky;
+    out[i].dSky       = in[i].dSky;
+    out[i].qPSF       = isnan(in[i].qPSF) ? NAN_S_SHORT : in[i].qPSF;
+    out[i].detID_hi   = 0;
+    out[i].detID_lo   = in[i].detID;
+    out[i].imageID_hi = 0;
+    out[i].imageID_lo = in[i].imageID;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format averages to internal averages */
+// 'primary is needed to conform with the API for Loneos and Elixir, but is not used
+Average *Average_Panstarrs_DEV_1_ToInternal (Average_Panstarrs_DEV_1 *in, int Nvalues, SecFilt **primary) {
+
+  int i;
+  Average *out;
+
+  ALLOCATE (out, Average, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R        = in[i].R;      
+    out[i].D        = in[i].D;      
+    out[i].Xp       = in[i].Xp;     
+    out[i].Nm       = in[i].Nm;     
+    out[i].Nn       = in[i].Nn;     
+    out[i].code     = in[i].code;   
+    out[i].offset   = in[i].offset; 
+    out[i].missing  = in[i].missing;
+    out[i].dR       = in[i].dR;
+    out[i].dD       = in[i].dD;
+    out[i].uR       = in[i].uR;
+    out[i].uD       = in[i].uD;
+    out[i].duR      = in[i].duR;
+    out[i].duD      = in[i].duD;
+    out[i].P        = in[i].P;
+    out[i].dP       = in[i].dP;
+    out[i].objID_hi = in[i].objID_hi;
+    out[i].objID_lo = in[i].objID_lo;
+  }
+  return (out);
+}
+
+/* convert internal averages to panstarrs-format averages */
+// 'primary is needed to conform with the API for Loneos and Elixir, but is not used
+Average_Panstarrs_DEV_1 *AverageInternalTo_Panstarrs_DEV_1 (Average *in, int Nvalues, SecFilt *primary) {
+
+  int i;
+  Average_Panstarrs_DEV_1 *out;
+
+  ALLOCATE (out, Average_Panstarrs_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].R        = in[i].R;      
+    out[i].D        = in[i].D;      
+    out[i].Xp       = in[i].Xp;     
+    out[i].Nm       = in[i].Nm;     
+    out[i].Nn       = in[i].Nn;     
+    out[i].code     = in[i].code;   
+    out[i].offset   = in[i].offset; 
+    out[i].missing  = in[i].missing;
+    out[i].dR       = in[i].dR;
+    out[i].dD       = in[i].dD;
+    out[i].uR       = in[i].uR;
+    out[i].uD       = in[i].uD;
+    out[i].duR      = in[i].duR;
+    out[i].duD      = in[i].duD;
+    out[i].P        = in[i].P;
+    out[i].dP       = in[i].dP;
+    out[i].objID_hi = in[i].objID_hi;
+    out[i].objID_lo = in[i].objID_lo;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format secfilts to internal secfilts */
+SecFilt *SecFilt_Panstarrs_DEV_1_ToInternal (SecFilt_Panstarrs_DEV_1 *in, int Nvalues) {
+
+  int i;
+  SecFilt *out;
+
+  ALLOCATE (out, SecFilt, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = in[i].M;      
+    out[i].dM    = in[i].dM;      
+    out[i].Xm    = in[i].Xm;     
+    out[i].Ncode = in[i].Ncode;
+    out[i].Nused = in[i].Nused;
+ }
+  return (out);
+}
+
+/* convert internal secfilts to panstarrs-format secfilts */
+SecFilt_Panstarrs_DEV_1 *SecFiltInternalTo_Panstarrs_DEV_1 (SecFilt *in, int Nvalues) {
+
+  int i;
+  SecFilt_Panstarrs_DEV_1 *out;
+
+  ALLOCATE (out, SecFilt_Panstarrs_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    out[i].M     = in[i].M;      
+    out[i].dM    = in[i].dM;      
+    out[i].Xm    = in[i].Xm;     
+    out[i].Ncode = in[i].Ncode;
+    out[i].Nused = in[i].Nused;
+  }
+  return (out);
+}
+
+/* convert panstarrs-format images to internal images */
+Image *Image_Panstarrs_DEV_1_ToInternal (Image_Panstarrs_DEV_1 *in, int Nvalues) {
+
+  int i;
+  Image *out;
+
+  ALLOCATE (out, Image, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strcpy (out[i].name, in[i].name);
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].imageID	    = in[i].imageID_lo;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
+
+/* convert internal images to panstarrs-format images */
+Image_Panstarrs_DEV_1 *ImageInternalTo_Panstarrs_DEV_1 (Image *in, int Nvalues) {
+
+  int i;
+  Image_Panstarrs_DEV_1 *out;
+
+  ALLOCATE (out, Image_Panstarrs_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    memcpy (&out[i].coords, &in[i].coords, sizeof(Coords));
+    strcpy (out[i].name, in[i].name);
+
+    out[i].tzero    	    = in[i].tzero;
+    out[i].nstar    	    = in[i].nstar;
+    out[i].secz	    	    = in[i].secz;
+    out[i].NX	    	    = in[i].NX;
+    out[i].NY	    	    = in[i].NY;
+    out[i].apmifit  	    = in[i].apmifit;
+    out[i].dapmifit 	    = in[i].dapmifit;
+    out[i].Mcal	    	    = in[i].Mcal;
+    out[i].dMcal    	    = in[i].dMcal;
+    out[i].Xm	    	    = in[i].Xm;
+    out[i].photcode   	    = in[i].photcode;
+    out[i].exptime  	    = in[i].exptime;
+    out[i].sidtime  	    = in[i].sidtime;
+    out[i].latitude  	    = in[i].latitude;
+    out[i].detection_limit  = in[i].detection_limit;
+    out[i].saturation_limit = in[i].saturation_limit;
+    out[i].cerror	    = in[i].cerror;
+    out[i].fwhm_x	    = in[i].fwhm_x;
+    out[i].fwhm_y	    = in[i].fwhm_y;
+    out[i].trate	    = in[i].trate;
+    out[i].code		    = in[i].code;
+    out[i].ccdnum	    = in[i].ccdnum;
+    out[i].imageID_hi	    = 0;
+    out[i].imageID_lo	    = in[i].imageID;
+
+    out[i].order	    = in[i].order;
+    out[i].Mx		    = in[i].Mx;
+    out[i].My		    = in[i].My;
+    out[i].Mxx		    = in[i].Mxx;
+    out[i].Mxy		    = in[i].Mxy;
+    out[i].Myy		    = in[i].Myy;
+    out[i].Mxxx		    = in[i].Mxxx;
+    out[i].Mxxy		    = in[i].Mxxy;
+    out[i].Mxyy		    = in[i].Mxyy;
+    out[i].Myyy		    = in[i].Myyy;
+    out[i].Mxxxx	    = in[i].Mxxxx;
+    out[i].Mxxxy	    = in[i].Mxxxy;
+    out[i].Mxxyy	    = in[i].Mxxyy;
+    out[i].Mxyyy	    = in[i].Mxyyy;
+    out[i].Myyyy	    = in[i].Myyyy;
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_image.c	(revision 16632)
@@ -0,0 +1,198 @@
+# include <dvo.h>
+
+/* lock the image table */
+int dvo_image_lock (FITS_DB *db, char *filename, double timeout, int lockstate) {
+
+  /* lock the image catalog */
+  if (!check_file_access (filename, FALSE, TRUE)) return (FALSE);
+
+  db[0].lockstate = lockstate;
+  db[0].timeout   = timeout;
+  gfits_db_init (db);
+
+  if (!gfits_db_lock (db, filename)) {
+    fprintf (stderr, "can't lock image catalog\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int dvo_image_unlock (FITS_DB *db) {
+
+  mode_t mode;
+
+  gfits_db_close (db);
+
+  /* force permissions to 666 */
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (db[0].filename, mode);
+  return (TRUE);
+}
+
+/* determine db mode (RAW/MEF) and read the complete table */
+int dvo_image_load (FITS_DB *db, int VERBOSE, int FORCE_READ) {
+
+  int Naxis, Nread, status;
+  char buffer[241];
+
+  /* database name must be set first */
+  if (db == NULL) return (FALSE);
+  if (db[0].f == NULL) return (FALSE);
+
+  /* test for NAXIS == 2 in line 3 */
+  bzero (buffer, 241);
+  fseek (db[0].f, 0, SEEK_SET);
+  Nread = fread (buffer, 1, 240, db[0].f);
+  if (Nread != 240) {
+    if (VERBOSE) fprintf (stderr, "can't determine image db mode\n");
+    return (FALSE);
+  }
+  Nread = sscanf (&buffer[160], "NAXIS   = %d", &Naxis);
+  if (Nread != 1) {
+    if (VERBOSE) fprintf (stderr, "can't determine image db mode\n");
+    return (FALSE);
+  }
+  fseek (db[0].f, 0, SEEK_SET);
+
+  /* default values */
+  db[0].mode = DVO_MODE_MEF;
+  db[0].format = DVO_FORMAT_UNDEF;
+  if (Naxis == 2) db[0].mode = DVO_MODE_RAW; /* image table can only be RAW or MEF */
+
+  switch (db[0].mode) {
+    case DVO_MODE_MEF:
+      if (VERBOSE) fprintf (stderr, "reading images (mode DVO_MODE_MEF)\n");
+      status = gfits_db_load (db);
+      break;
+    case DVO_MODE_RAW:
+      if (VERBOSE) fprintf (stderr, "reading images (mode DVO_MODE_RAW)\n");
+      status = dvo_image_load_raw (db, VERBOSE, FORCE_READ);
+      break;
+    default:
+      fprintf (stderr, "error getting image mode\n");
+      exit (2);
+  }
+  if (!status) return (FALSE);
+  FtableToImage (&db[0].ftable, &db[0].theader, &db[0].format);
+  db[0].swapped = TRUE;  /* table has internal byte-order */
+  return (TRUE);
+}
+
+/* write the complete image table to disk in the requested mode */
+int dvo_image_save (FITS_DB *db, int VERBOSE) {
+
+  int status;
+
+  /* convert from internal to requested external format */
+  ImageToFtable (&db[0].ftable, &db[0].theader, db[0].format);
+  db[0].swapped = FALSE;
+
+  /* write data in appropriate mode */
+  switch (db[0].mode) {
+    case DVO_MODE_MEF:
+    case DVO_MODE_SPLIT:
+      status = gfits_db_save (db);
+      break;
+    case DVO_MODE_RAW:
+      status = dvo_image_save_raw (db, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "error writing image mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+int dvo_image_addrows (FITS_DB *db, Image *new, int Nnew) {
+
+  int Nimages;
+
+  /* adjust header */
+  Nimages = 0;
+  gfits_scan (&db[0].header, "NIMAGES", "%d", 1, &Nimages);
+  Nimages += Nnew;
+  gfits_modify (&db[0].header, "NIMAGES", "%d", 1, Nimages);
+
+  gfits_table_to_vtable (&db[0].ftable, &db[0].vtable, 0, 0);
+  gfits_vadd_rows (&db[0].vtable, (char *) new, Nnew, sizeof(Image));
+
+  /* check that primary header and table header agree */
+  if (Nimages != db[0].theader.Naxis[1]) {
+    fprintf (stderr, "header / table length mismatch!\n");
+  }
+  return (TRUE);
+}  
+
+/* write the vtable data to disk in the requested mode */
+int dvo_image_update (FITS_DB *db, int VERBOSE) {
+
+  int status;
+
+  /* convert from internal to requested external format */
+  /* theader is modified to match output format */
+  ImageToVtable (&db[0].vtable, &db[0].theader, db[0].format);
+  db[0].swapped = FALSE;
+
+  /* write data in appropriate mode */
+  switch (db[0].mode) {
+    case DVO_MODE_MEF:
+    case DVO_MODE_SPLIT:
+      status = gfits_db_update (db);
+      break;
+    case DVO_MODE_RAW:
+      status = dvo_image_update_raw (db, VERBOSE);
+      break;
+    default:
+      fprintf (stderr, "error writing image mode\n");
+      exit (2);
+  }
+  return (TRUE);
+}
+
+void dvo_image_create (FITS_DB *db, double ZeroPoint) {
+
+  /* create new header */
+  gfits_init_header (&db[0].header);
+
+  /* check the mode */
+  switch (db[0].mode) {
+    case DVO_MODE_RAW:
+      /* make header a fake image */
+      db[0].header.bitpix   = 16;
+      db[0].header.Naxes    = 2;
+      db[0].header.Naxis[0] = 1;
+      db[0].header.Naxis[1] = 1;
+      gfits_create_header (&db[0].header);
+      break;
+    case DVO_MODE_MEF:
+    case DVO_MODE_SPLIT:
+      db[0].header.extend   = TRUE;
+      gfits_create_header (&db[0].header);
+      db[0].mode = DVO_MODE_MEF;
+      break;
+    default:
+      fprintf (stderr, "invalid output catalog mode\n");
+      exit (1);
+  }
+
+  /* check the format */
+  if (db[0].format == DVO_FORMAT_UNDEF) {
+    fprintf (stderr, "invalid output catalog format\n");
+    exit (1);
+  }
+
+  gfits_create_matrix (&db[0].header, &db[0].matrix);
+  gfits_table_set_Image (&db[0].ftable, NULL, 0);
+
+  gfits_modify (&db[0].header, "NIMAGES", "%d", 1, 0);
+  gfits_modify (&db[0].header, "ZERO_PT", "%lf", 1, ZeroPoint);
+
+  if (db[0].format == DVO_FORMAT_INTERNAL)  	  gfits_modify (&db[0].header, "FORMAT", "%s", 1, "INTERNAL");
+  if (db[0].format == DVO_FORMAT_LONEOS)    	  gfits_modify (&db[0].header, "FORMAT", "%s", 1, "LONEOS");
+  if (db[0].format == DVO_FORMAT_ELIXIR)    	  gfits_modify (&db[0].header, "FORMAT", "%s", 1, "ELIXIR");
+  if (db[0].format == DVO_FORMAT_PANSTARRS_DEV_0) gfits_modify (&db[0].header, "FORMAT", "%s", 1, "PANSTARRS_DEV_0");
+  if (db[0].format == DVO_FORMAT_PANSTARRS_DEV_1) gfits_modify (&db[0].header, "FORMAT", "%s", 1, "PANSTARRS_DEV_1");
+  if (db[0].format == DVO_FORMAT_PS1_DEV_1)       gfits_modify (&db[0].header, "FORMAT", "%s", 1, "PS1_DEV_1");
+  
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_image_raw.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_image_raw.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_image_raw.c	(revision 16632)
@@ -0,0 +1,155 @@
+# include <dvo.h>
+
+/* the old Image.dat files used a fake FITS header defining a finite data block
+ * this function reads in the header and data, and creates an ftable and theader to match
+ */
+
+int dvo_image_load_raw (FITS_DB *db, int VERBOSE, int FORCE_READ) {
+
+  int Nimage, Ndata, size, ImageSize, nbytes, Nbytes;
+  struct stat filestatus;
+  char format[80], telescope[80];
+
+  /* read fits header from file - return FALSE on error */
+  if (!gfits_fread_header (db[0].f, &db[0].header)) {
+    fprintf (stderr, "can't read primary header\n"); 
+    return (FALSE);
+  }
+
+  /* determine image table format */
+  db[0].format = DVO_FORMAT_UNDEF;
+  if (gfits_scan (&db[0].header, "FORMAT",  "%s", 1, format)) {
+    db[0].format = dvo_catalog_catformat (format);
+    if (db[0].format != DVO_FORMAT_UNDEF) goto got_format;
+  }
+  if (gfits_scan (&db[0].header, "TELESCOP",  "%s", 1, telescope)) {
+    if (!strncmp (telescope, "LONEOS", strlen("LONEOS"))) {
+      db[0].format = DVO_FORMAT_LONEOS; // special case for LONEOS
+      goto got_format;
+    }
+    if (!strncmp (telescope, "1.3m McGraw-Hill", strlen("1.3m McGraw-Hill"))) {
+      db[0].format = DVO_FORMAT_ELIXIR; // special case for ELIXIR
+      goto got_format;
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "cannot determine image table format\n");
+  return (FALSE);
+
+got_format:
+  /* find number of images */
+  Nimage = 0;
+  gfits_scan (&db[0].header, "NIMAGES", "%d", 1, &Nimage);
+  if (stat (db[0].filename, &filestatus) == -1) {
+    if (VERBOSE) fprintf (stderr, "ERROR: failed to get status of image catalog\n");
+    exit (1);
+  }
+
+  /* get datatype size */
+  ImageSize = 0;
+  if (db[0].format == DVO_FORMAT_INTERNAL)  	  ImageSize = sizeof(Image);
+  if (db[0].format == DVO_FORMAT_LONEOS)    	  ImageSize = sizeof(Image_Loneos);
+  if (db[0].format == DVO_FORMAT_ELIXIR)    	  ImageSize = sizeof(Image_Elixir);
+  if (db[0].format == DVO_FORMAT_PANSTARRS_DEV_0) ImageSize = sizeof(Image_Panstarrs_DEV_0);
+  if (db[0].format == DVO_FORMAT_PANSTARRS_DEV_1) ImageSize = sizeof(Image_Panstarrs_DEV_1);
+  if (db[0].format == DVO_FORMAT_PS1_DEV_1)       ImageSize = sizeof(Image_PS1_DEV_1);
+
+  /* check that filesize makes sense */
+  size = Nimage*ImageSize + db[0].header.size;
+  if (size != filestatus.st_size) {
+    Ndata = (filestatus.st_size - db[0].header.size) / ImageSize;
+    if (VERBOSE) fprintf (stderr, "ERROR: image catalog has inconsistent size\n");
+    if (VERBOSE) fprintf (stderr, "header: %d, data: %d\n", Nimage, Ndata);
+    if (!FORCE_READ) exit (1);
+    Nimage = Ndata;
+  } 
+
+  /* create a dummy ftable, theader set for this data */
+  /* (original table has NAXIS = 2, change to 0) */
+  /* gfits_modify (&db[0].header, "NAXIS", "%d", 1, 0); */
+  gfits_create_matrix (&db[0].header, &db[0].matrix);
+  db[0].ftable.header = &db[0].theader;
+
+  if (db[0].format == DVO_FORMAT_INTERNAL)  	  gfits_table_mkheader_Image (&db[0].theader);
+  if (db[0].format == DVO_FORMAT_LONEOS)    	  gfits_table_mkheader_Image_Loneos (&db[0].theader);
+  if (db[0].format == DVO_FORMAT_ELIXIR)    	  gfits_table_mkheader_Image_Elixir (&db[0].theader);
+  if (db[0].format == DVO_FORMAT_PANSTARRS_DEV_0) gfits_table_mkheader_Image_Panstarrs_DEV_0 (&db[0].theader);
+  if (db[0].format == DVO_FORMAT_PANSTARRS_DEV_1) gfits_table_mkheader_Image_Panstarrs_DEV_1 (&db[0].theader);
+  if (db[0].format == DVO_FORMAT_PS1_DEV_1)       gfits_table_mkheader_Image_PS1_DEV_1 (&db[0].theader);
+    
+  /* read data from file */
+  Nbytes = ImageSize*Nimage;
+  ALLOCATE (db[0].ftable.buffer, char, Nbytes);
+  nbytes = fread (db[0].ftable.buffer, 1, Nbytes, db[0].f);
+  if (nbytes != Nbytes) {
+    if (VERBOSE) fprintf (stderr, "ERROR: problem loading image catalog\n");
+    exit (1);
+  } 
+
+  gfits_modify (&db[0].theader, "NAXIS2", "%d", 1, Nimage);
+  db[0].theader.Naxis[1] = Nimage;
+  db[0].ftable.size = gfits_data_size (&db[0].theader);
+  db[0].swapped = FALSE;  /* table does not have internal byte-order */
+  return (TRUE);
+}
+
+/* write out image db elements from vtable */
+int dvo_image_update_raw (FITS_DB *db, int VERBOSE) {
+
+  int i, Nx, Ny, Nrow, Nbytes;
+  int status, start, offset;
+  int *row;
+
+  if (VERBOSE) fprintf (stderr, "writing out %d images\n", db[0].vtable.Nrow);
+
+  /* position to start of file */
+  Fseek (db[0].f, 0, SEEK_SET);
+  
+  /* write out complete header (no check on disk size?) */
+  status = fwrite (db[0].header.buffer, 1, db[0].header.size, db[0].f);
+  if (status != db[0].header.size) {
+    fprintf (stderr, "ERROR: failed writing data to image header\n");
+    exit (1);
+  }
+
+  /** this code is identical to gfits_fwrite_vtable, except without padding */
+  Nrow = db[0].vtable.Nrow;
+  row = db[0].vtable.row;
+  gfits_scan (db[0].vtable.header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (db[0].vtable.header, "NAXIS2", "%d", 1, &Ny);
+
+  /* file pointer is at beginning of desired table data */
+  start = ftell (db[0].f);
+  
+  for (i = 0; i < Nrow; i++) {
+    offset = start + Nx*row[i];
+    fseek (db[0].f, offset, SEEK_SET);
+    Nbytes = fwrite (db[0].vtable.buffer[i], sizeof (char), Nx, db[0].f);
+    if (Nbytes != Nx) { return (FALSE); }
+  }
+  return (TRUE);
+}
+
+/* write out complete image db table from ftable */
+int dvo_image_save_raw (FITS_DB *db, int VERBOSE) {
+
+  int status, Nx, Ny, size, Nbytes;
+
+  if (VERBOSE) fprintf (stderr, "writing out %d images\n", db[0].theader.Naxis[1]);
+
+  /* position to start of file */
+  Fseek (db[0].f, 0, SEEK_SET);
+  
+  /* write out complete header (no check on disk size?) */
+  status = fwrite (db[0].header.buffer, 1, db[0].header.size, db[0].f);
+  if (status != db[0].header.size) {
+    fprintf (stderr, "ERROR: failed writing data to image header\n");
+    exit (1);
+  }
+
+  gfits_scan (db[0].ftable.header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (db[0].ftable.header, "NAXIS2", "%d", 1, &Ny);
+  size = Nx * Ny;
+  Nbytes = fwrite (db[0].ftable.buffer, sizeof(char), size, db[0].f);
+  if (Nbytes != size) return (FALSE);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_convert_elixir.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_convert_elixir.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_convert_elixir.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include <dvo.h>
+
+PhotCode_Elixir *PhotCode_Internal_To_Elixir (PhotCode *in, int Nvalues) {
+
+  int i;
+  PhotCode_Elixir *out;
+
+  ALLOCATE (out, PhotCode_Elixir, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+  }
+  return (out);
+}
+
+PhotCode *PhotCode_Elixir_To_Internal (PhotCode_Elixir *in, int Nvalues) {
+
+  int i;
+  PhotCode *out;
+
+  ALLOCATE (out, PhotCode, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    // not defined in Elixir:
+    out[i].astromScale = 1.0;
+    out[i].photSysErr = 1.0;
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_convert_ps1_dev_1.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_convert_ps1_dev_1.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_convert_ps1_dev_1.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include <dvo.h>
+
+PhotCode_PS1_DEV_1 *PhotCode_Internal_To_PS1_DEV_1 (PhotCode *in, int Nvalues) {
+
+  int i;
+  PhotCode_PS1_DEV_1 *out;
+
+  ALLOCATE (out, PhotCode_PS1_DEV_1, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    out[i].astromScale = in[i].astromScale;  
+    out[i].photSysErr = in[i].photSysErr;   
+  }
+  return (out);
+}
+
+PhotCode *PhotCode_PS1_DEV_1_To_Internal (PhotCode_PS1_DEV_1 *in, int Nvalues) {
+
+  int i;
+  PhotCode *out;
+
+  ALLOCATE (out, PhotCode, Nvalues);
+
+  for (i = 0; i < Nvalues; i++) {
+    strncpy (out[i].name, in[i].name, 31); // out[32], in[32]
+    out[i].name[31] = 0; // force termination
+
+    out[i].code = in[i].code;         
+    out[i].type = in[i].type;         
+    out[i].C = in[i].C;            
+    out[i].dC = in[i].dC;           
+    out[i].dX = in[i].dX;           
+    out[i].K = in[i].K;            
+    out[i].c1 = in[i].c1;           
+    out[i].c2 = in[i].c2;           
+    out[i].equiv = in[i].equiv;        
+    out[i].Nc = in[i].Nc;           
+    memcpy (out[i].X, in[i].X, 4*sizeof(float));            
+
+    out[i].astromScale = in[i].astromScale;  
+    out[i].photSysErr = in[i].photSysErr;   
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_ops.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_ops.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvo_photcode_ops.c	(revision 16632)
@@ -0,0 +1,527 @@
+# include <dvo.h>
+
+/* we use a static variable to save the pre-loaded the photcodes.
+   photcode conversion functions refer to this table for ref values */
+
+/* We have three indexes:
+
+   table[0].hashcode provides the table photcode sequence for a photcode value
+   table[0].hashNsec provides the Nsec sequence for a photcode value
+   table[0].codeNsec provides the photcode value for an Nsec sequence
+
+   given photcode = table[0].code[i] and code = photcode[0].code
+
+   hashcode[code] = i
+   hashNsec[code] = Nsec or -1 if not a PRI/SEC code
+   codeNsec[Nsec] = code
+*/
+
+static PhotCodeData *photcodes = NULL;
+
+PhotCodeData *GetPhotcodeTable () {
+
+  /* allocate space to photcode table, free existing data */
+  if (photcodes == NULL) {
+    ALLOCATE (photcodes, PhotCodeData, 1);
+    photcodes[0].code = NULL;
+  }
+  return photcodes;
+}
+
+/* the static ZERO_POINT is used by programs as an approximate nominal */
+static double ZERO_POINT = 0.0;
+
+void SetZeroPoint (double ZP) {
+  ZERO_POINT = ZP;
+}
+
+double GetZeroPoint () {
+  return ZERO_POINT;
+}
+
+# define SCALE 0.001
+
+/********** photcode lookup functions **********/
+
+/* return photcode for given name */
+PhotCode *GetPhotcodebyName (char *name) {
+  
+  int i;
+
+  if (name == NULL) return (NULL);
+  
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      return (&photcodes[0].code[i]);
+    }
+  }
+  return (NULL);
+}
+/* return photcode.code for given name */
+int GetPhotcodeCodebyName (char *name) {
+  
+  int i;
+  
+  if (name == NULL) return (0);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      return (photcodes[0].code[i].code);
+    }
+  }
+  return (0);
+}
+/* return equivalent photcode for given name */
+PhotCode *GetPhotcodeEquivbyName (char *name) {
+  
+  int i, equiv;
+  
+  if (name == NULL) return (NULL);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      if (photcodes[0].code[i].equiv == 0) return (NULL);
+      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
+      if (equiv == -1) return (NULL);
+      return (&photcodes[0].code[equiv]);
+    }
+  }
+  return (NULL);
+}
+/* return equivalent photcode.code for given name */
+int GetPhotcodeEquivCodebyName (char *name) {
+  
+  int i, equiv;
+  
+  if (name == NULL) return (0);
+
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (!strcmp (photcodes[0].code[i].name, name)) {
+      if (photcodes[0].code[i].equiv == 0) return (0);
+      equiv = photcodes[0].hashcode[photcodes[0].code[i].equiv];
+      if (equiv == -1) return (0);
+      return (photcodes[0].code[equiv].code);
+    }
+  }
+  return (0);
+}
+
+/* return photcode for given code */
+PhotCode *GetPhotcodebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  return (&photcodes[0].code[entry]);
+}
+/* return photcode.code for given code */
+char *GetPhotcodeNamebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  return (photcodes[0].code[entry].name);
+}
+/* return equivalent photcode for given code */
+PhotCode *GetPhotcodeEquivbyCode (int code) {
+  
+  int entry, equiv;
+  
+  if (code < 0) return (NULL);
+  if (code > 0x10000) return (NULL);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (NULL);
+
+  if (photcodes[0].code[entry].equiv == 0) return (NULL);
+  equiv = photcodes[0].hashcode[photcodes[0].code[entry].equiv];
+
+  if (equiv == -1) return (NULL);
+  return (&photcodes[0].code[equiv]);
+}
+/* return equivalent photcode.code for given code */
+int GetPhotcodeEquivCodebyCode (int code) {
+  
+  int entry;
+  
+  if (code < 0) return (0);
+  if (code > 0x10000) return (0);
+
+  entry = photcodes[0].hashcode[code];
+  if (entry == -1) return (0);
+  return (photcodes[0].code[entry].equiv);
+}
+
+int GetPhotcodeNsec (int code) {
+  
+  int Nsec;
+  
+  if (code < 0) return (-1);
+  if (code > 0x10000) return (-1);
+
+  Nsec = photcodes[0].hashNsec[code];
+  return (Nsec);
+}
+
+/* Nsec of 0 is PRI */
+PhotCode *GetPhotcodebyNsec (int Nsec) {
+  
+  int Ncode;
+  int Nseq;
+
+  if (Nsec > photcodes[0].Nsecfilt) return (NULL);
+  if (Nsec < 0) return (NULL);
+  
+  Ncode = photcodes[0].codeNsec[Nsec];
+  if (Ncode < 0) return (NULL);
+
+  Nseq = photcodes[0].hashcode[Ncode];
+  return (&photcodes[0].code[Nseq]);
+}
+
+int GetPhotcodeNsecfilt () {
+  return (photcodes[0].Nsecfilt);
+}
+
+/* ALLOCATE and return list of all photcodes
+   with photcode.equiv == code */
+int *GetPhotcodeEquivList (int code, int *nlist) {
+
+  int i, Nlist;
+  int *list;
+
+  ALLOCATE (list, int, MAX (1, photcodes[0].Ncode));
+  Nlist = 0;
+  for (i = 0; i < photcodes[0].Ncode; i++) {
+    if (photcodes[0].code[i].equiv != code) continue;
+    list[Nlist] = photcodes[0].code[i].code;
+    Nlist ++;
+  }
+  REALLOCATE (list, int, MAX (1, Nlist));
+
+  *nlist = Nlist;
+  return (list);
+}
+
+/******** photometry conversion functions *********/
+float PhotInst (Measure *measure) {
+
+  int Np;
+  float M;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NAN);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    M = measure[0].M;
+    return (M);
+  }
+
+  M = measure[0].M - measure[0].dt - ZERO_POINT;
+	  
+  return (M);
+
+}
+
+float PhotCat (Measure *measure) {
+
+  int Np;
+  float Mcat;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NAN);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mcat = measure[0].M;
+    return (Mcat);
+  }
+  code = &photcodes[0].code[Np];
+  Mcat = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + SCALE*code[0].C;
+  
+  return (Mcat);
+}
+
+float PhotSys (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  int i, Np;
+  float Mcat, Mcol, Msys, mc, Mc;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NAN);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Msys = measure[0].M;
+    return (Msys);
+  }
+  code = &photcodes[0].code[Np];
+  Mcat = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + SCALE*code[0].C;
+
+  /* for DEP, color must be made of PRI/SEC */
+  mc = PhotColorForCode (average, secfilt, NULL, code);
+  if (isnan(mc)) return (Mcat);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;
+  }
+  Msys = Mcat + Mcol;
+  return (Msys);
+}
+
+float PhotRel (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  int i, Np;
+  float Mcat, Mcol, Mrel, mc, Mc;
+  PhotCode *code;
+
+  Np = photcodes[0].hashcode[measure[0].photcode];
+  if (Np == -1) return (NAN);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mcat = measure[0].M;
+    return (Mcat);
+  }
+  code = &photcodes[0].code[Np];
+  Mrel = measure[0].M - ZERO_POINT + code[0].K*(measure[0].airmass - 1.000) + SCALE*code[0].C - measure[0].Mcal;
+
+  /* for DEP, color must be made of PRI/SEC */
+  mc = PhotColorForCode (average, secfilt, NULL, code);
+  if (isnan(mc)) return (Mrel);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Mrel += Mcol;
+  return (Mrel);
+}
+
+/* return calibrated magnitude from measure for given photcode */
+float PhotCal (Measure *thisone, Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
+
+  int i, Np; 
+  float Mcal, Mrel, Mcol, mc, Mc;
+
+  /* code must be the matching PRI/SEC code for this measurement or an equivalent ALT */
+  Np = photcodes[0].hashcode[thisone[0].photcode];
+  if (Np == -1) return (NAN);
+
+  if (photcodes[0].code[Np].type == PHOT_REF) {
+    Mrel = thisone[0].M;
+    return (Mrel);
+  }
+  if (code[0].code != photcodes[0].code[Np].equiv) return (NAN);
+
+  Mcal = PhotRel (thisone, average, secfilt) + SCALE*code[0].C;
+
+  mc = PhotColorForCode (average, secfilt, measure, code);
+  if (isnan(mc)) return (Mcal);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;
+  }
+  Mcal += Mcol;
+  return (Mcal);
+}
+
+/* color term may not use DEP magnitude */
+float PhotColorForCode (Average *average, SecFilt *secfilt, Measure *measure, PhotCode *code) {
+
+  int i, Ns1, Ns2, Ns;
+  float m1, m2, mc;
+  PhotCode *color;
+
+  m1 = m2 = NAN;
+
+  if (measure == NULL) {
+    Ns1 = photcodes[0].hashNsec[code[0].c1];
+    Ns2 = photcodes[0].hashNsec[code[0].c2];
+  
+    m1 = (Ns1 == -1) ? NAN : secfilt[Ns1].M;
+    m2 = (Ns2 == -1) ? NAN : secfilt[Ns2].M;
+    mc = (isnan(m1) || isnan(m2)) ? NAN : (m1 - m2);
+    return (mc);
+  }
+
+  /* find magnitude matching first color term */
+  color = GetPhotcodebyCode (code[0].c1);
+  if (color == NULL) return (NAN);
+  if (color[0].type == PHOT_REF) {
+    for (i = 0; (i < average[0].Nm) && (isnan(m1)); i++) {
+      if (measure[i].photcode == color[0].code) {
+	m1 = measure[i].M;
+      }
+    }
+  } else {
+    Ns = photcodes[0].hashNsec[color[0].code];
+    m1 = (Ns == -1) ? NAN : secfilt[Ns].M;
+  }	
+
+  /* find magnitude matching second color term */
+  color = GetPhotcodebyCode (code[0].c2);
+  if (color == NULL) return (NAN);
+  if (color[0].type == PHOT_REF) {
+    for (i = 0; (i < average[0].Nm) && (isnan(m2)); i++) {
+      if (measure[i].photcode == color[0].code) {
+	m2 = measure[i].M;
+      }
+    }
+  } else {
+    Ns = photcodes[0].hashNsec[color[0].code];
+    m2 = (Ns == -1) ? NAN : secfilt[Ns].M;
+  }	
+  mc = (isnan(m1) || isnan(m2)) ? NAN : (m1 - m2);
+  return (mc);
+}
+
+/* return calibrated magnitude from average/secfilt for given photcode */
+float PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
+
+  int i, Ns;
+  float Mave, Mref, Mcol, mc;
+  double Mc;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mave = (Ns == -1) ? NAN : secfilt[Ns].M;
+  Mref = Mave + SCALE*code[0].C;
+
+  mc = PhotColorForCode (average, secfilt, measure, code);
+  if (isnan(mc)) return (Mref);
+  mc = mc - SCALE*code[0].dX;
+
+  Mc = mc;
+  Mcol = 0;
+  for (i = 0; i < code[0].Nc; i++) {
+    Mcol += code[0].X[i]*Mc;
+    Mc *= mc;    /* the 0.001 is needed for higher order terms to keep the units mag = mag^n */
+  }
+  Mref += Mcol;
+  return (Mref);
+}
+
+/***/
+float PhotAve (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  float Mave;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mave = (Ns == -1) ? NAN : secfilt[Ns].M;
+  return (Mave);
+}
+
+float PhotdM (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  float dM;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  dM  = (Ns == -1) ? NAN : secfilt[Ns].dM;
+  return (dM);
+}
+
+// XXX return NAN or NAN_S_SHORT? (secfilt->Xm is short)
+float PhotXm (PhotCode *code, Average *average, SecFilt *secfilt) {
+
+  int Ns;
+  short Mi;
+  float Xm;
+
+  Ns = photcodes[0].hashNsec[code[0].code];
+  Mi = (Ns == -1) ? NAN : secfilt[Ns].Xm;
+  Xm = (isnan(Mi)) ? -1.0 : pow (10.0, 0.01*Mi);
+  return (Xm);
+}
+
+/* given a photcode pair c1 & c2, return the color of this star (NaN if not found) */
+int PhotColor (Average *average, SecFilt *secfilt, Measure *measure, int c1, int c2, double *color) {
+
+  int i, Ns;
+  double M1, M2, dM;
+  PhotCode *code;
+  
+  code = GetPhotcodebyCode (c1);
+  if (code == NULL) return (FALSE);
+  if (code[0].type == PHOT_REF) {
+    for (i = 0; i < average[0].Nm; i++) {
+      if (measure[i].photcode == c1) {
+	M1 = measure[i].M;
+	goto filter1;
+      }
+    }	
+    return (FALSE);
+  } else {
+    Ns = photcodes[0].hashNsec[code[0].code];
+    M1 = (Ns == -1) ? NAN : secfilt[Ns].M;
+  }	
+
+filter1:
+  code = GetPhotcodebyCode (c2);
+  if (code == NULL) return (FALSE);
+  if (code[0].type == PHOT_REF) {
+    for (i = 0; i < average[0].Nm; i++) {
+      if (measure[i].photcode == c2) {
+	M2 = measure[i].M;
+	goto filter2;
+      }
+    }	
+    return (FALSE);
+  } else {
+    Ns = photcodes[0].hashNsec[code[0].code];
+    M2 = (Ns == -1) ? NAN : secfilt[Ns].M;
+  }	
+  
+filter2:
+
+  dM = M1 - M2;
+  *color = dM;
+  
+  return (TRUE);
+}
+
+/* photcode table should have the following format: 
+
+# code name     type  zero  airmass  offset  c1 c2  slope  <color>  primary
+1    B        pri   24.0  0.15     -       -  -   -      -        -
+2    B        pri   24.0  0.15     -       -  -   -      -        -
+3    B1       sec   22.5  0.18     0.15    1  2   0.10   0.50     1
+1000 USNO_B   ref   -     -        -       -  -   -      -        -
+
+*/
+
+
+/*
+  Nc1 = photcodes[0].code[Np].c1;
+  Ns1 = photcodes[0].hashNsec[Nc1];
+
+  Nc2 = photcodes[0].code[Np].c2;
+  Ns2 = photcodes[0].hashNsec[Nc2];
+
+  Xlam = photcodes[0].code[Np].X[0];
+  Klam = photcodes[0].code[Np].K;
+  
+  m1 = (Ns1 == -1) ? average[0].M : secfilt[Ns1].M;
+  m2 = (Ns2 == -1) ? average[0].M : secfilt[Ns2].M;
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvosorts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvosorts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/dvosorts.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include <dvo.h>
+
+/* several dvo-specific sorting functions used in a number of locations */
+
+/* values are ave[i].R, ave[i].D, ave[i].M */
+void sortave (Average *ave, int N) {
+
+# define SWAPFUNC(A,B){ Average tmp; tmp = ave[A]; ave[A] = ave[B]; ave[B] = tmp; }
+# define COMPARE(A,B)(ave[A].R < ave[B].R)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+/* sort subset by image[subset[i]].tzero */
+void sort_image_subset (Image *image, int *subset, int N) {
+
+# define SWAPFUNC(A,B){ int tmp; tmp = subset[A]; subset[A] = subset[B]; subset[B] = tmp; }
+# define COMPARE(A,B)(image[subset[A]].tzero < image[subset[B]].tzero)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+/* sort a coordinate pair (X,Y) and the associated index (S) */
+void sort_coords_index (double *X, double *Y, int *S, int N) {
+  
+# define SWAPFUNC(A,B){ double dtmp; int itmp; \
+  dtmp = X[A]; X[A] = X[B]; X[B] = dtmp; \
+  dtmp = Y[A]; Y[A] = Y[B]; Y[B] = dtmp; \
+  itmp = S[A]; S[A] = S[B]; S[B] = itmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void sort_stars_ra (Stars *stars, int N) {
+
+# define SWAPFUNC(A,B){ Stars tmp; tmp = stars[A]; stars[A] = stars[B]; stars[B] = tmp; }
+# define COMPARE(A,B)(stars[A].R < stars[B].R)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void sort_regions (SkyRegion *region, int N) {
+
+# define SWAPFUNC(A,B){ SkyRegion tmp; tmp = region[A]; region[A] = region[B]; region[B] = tmp; }
+# define COMPARE(A,B)(region[A].Dmin < region[B].Dmin)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/fits_db.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/fits_db.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/fits_db.c	(revision 16632)
@@ -0,0 +1,234 @@
+# include <dvo.h>
+
+/* init the db structure */
+int gfits_db_init (FITS_DB *db) {
+
+  db[0].f             = NULL;
+  db[0].filename      = NULL;
+  db[0].header.buffer = NULL;
+  db[0].matrix.buffer = NULL;
+  db[0].theader.buffer = NULL;
+  db[0].ftable.buffer = NULL;
+  db[0].ftable.header = &db[0].theader;
+
+  db[0].vtable.header = NULL;
+  db[0].vtable.buffer = NULL;
+  db[0].vtable.row    = NULL;
+  return (TRUE);
+}
+
+/* create an empty db */
+int gfits_db_create (FITS_DB *db) {
+  gfits_init_header (&db[0].header);    
+  db[0].header.extend = TRUE;
+  gfits_create_header (&db[0].header);
+  gfits_create_matrix (&db[0].header, &db[0].matrix);
+  gfits_print (&db[0].header, "NEXTEND", "%d", 1, 1);
+  db[0].ftable.header = &db[0].theader;
+  return (TRUE);
+}
+
+int gfits_db_lock (FITS_DB *db, char *filename) {
+  
+  /* database name must be set first */
+  if (filename == NULL) {
+    fprintf (stderr, "db file is not set\n");
+    return (FALSE);
+  }
+
+  /* database handle must be set first */
+  if (db == NULL) {
+    fprintf (stderr, "db handle is not set\n");
+    return (FALSE);
+  }
+
+  /* lock & open database */
+  db[0].f = fsetlockfile (filename, db[0].timeout, db[0].lockstate, &db[0].dbstate);
+  if (db[0].f == NULL) {
+    if (db[0].dbstate == LCK_MISSING) {
+      fprintf (stderr, "no data in db %s\n", filename);
+    } else {
+      fprintf (stderr, "cannot set lock on db file %s\n", filename);
+    }
+    return (FALSE);
+  }
+  
+  db[0].filename = strcreate (filename);
+  return (TRUE);
+}
+
+/* load the complete db table into memory - load first extension, do not validate EXTNAME */
+int gfits_db_load (FITS_DB *db) {
+
+  /* database name must be set first */
+  if (db == NULL) {
+    fprintf (stderr, "db handle is not set\n");
+    return (FALSE);
+  }
+
+  /* init & load in FITS table data - return FALSE on error */
+  if (!gfits_fread_header (db[0].f, &db[0].header)) {
+    fprintf (stderr, "can't read primary header\n"); 
+    gfits_db_free (db);
+    return (FALSE);
+  }
+  if (!gfits_fread_matrix (db[0].f, &db[0].matrix, &db[0].header)) {
+    fprintf (stderr, "can't read primary matrix");
+    gfits_db_free (db);
+    return (FALSE);
+  }
+  if (!gfits_fread_header (db[0].f, &db[0].theader)) {
+    fprintf (stderr, "can't read table header");
+    gfits_db_free (db);
+    return (FALSE);
+  }
+  if (!gfits_fread_ftable_data (db[0].f, &db[0].ftable)) {
+    fprintf (stderr, "can't read table data");
+    gfits_db_free (db);
+    return (FALSE);
+  }
+  db[0].swapped = FALSE;  /* table does not have internal byte-order */
+  return (TRUE);
+}
+
+/* load the data from Nrows from table starting at start; load header, etc if needed */
+int gfits_db_load_segment (FITS_DB *db, int start, int Nrows) {
+
+  int Nskip;
+
+  /* database name must be set first */
+  if (db == NULL) {
+    fprintf (stderr, "db handle is not set\n");
+    return (FALSE);
+  }
+
+  /* database name must be opened */
+  if (db[0].f == NULL) {
+    fprintf (stderr, "db is not opened\n");
+    return (FALSE);
+  }
+
+  /* position to start of file */
+  Fseek (db[0].f, 0, SEEK_SET);
+
+  /* load or skip header */
+  if (db[0].header.buffer == NULL) {
+    if (!gfits_fread_header (db[0].f, &db[0].header)) {
+      fprintf (stderr, "can't read primary header\n"); 
+      return (FALSE);
+    }
+  } else {
+    Nskip = db[0].header.size;
+    Fseek (db[0].f, Nskip, SEEK_CUR);
+  }
+
+  /* load or skip matrix */
+  if (db[0].matrix.buffer == NULL) {
+    if (!gfits_fread_matrix (db[0].f, &db[0].matrix, &db[0].header)) {
+      fprintf (stderr, "can't read primary matrix");
+      return (FALSE);
+    }
+  } else {
+    Nskip = gfits_data_size (&db[0].header);
+    Fseek (db[0].f, Nskip, SEEK_CUR);
+  }
+
+  /* load or skip table header */
+  if (db[0].theader.buffer == NULL) {
+    if (!gfits_fread_header (db[0].f, &db[0].theader)) {
+      fprintf (stderr, "can't read table header");
+      return (FALSE);
+    }
+  } else {
+    Nskip = db[0].header.size;
+    Fseek (db[0].f, Nskip, SEEK_CUR);
+  }
+
+  /* read table segment into vtable */
+  if (!gfits_fread_vtable_range (db[0].f, &db[0].vtable, start, Nrows)) {
+    fprintf (stderr, "can't read table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* write complete db file */
+int gfits_db_save (FITS_DB *db) {
+
+  /* write all data to file */
+  make_backup (db[0].filename);
+  Fseek (db[0].f, 0, SEEK_SET);
+
+  if (!gfits_fwrite_header  (db[0].f, &db[0].header)) {
+    fprintf (stderr, "can't write primary header");
+    return (FALSE);
+  }
+  if (!gfits_fwrite_matrix  (db[0].f, &db[0].matrix)) {
+    fprintf (stderr, "can't write primary matrix");
+    return (FALSE);
+  }
+  if (!gfits_fwrite_Theader (db[0].f, &db[0].theader)) {
+    fprintf (stderr, "can't write table header");
+    return (FALSE);
+  }
+  if (!gfits_fwrite_table   (db[0].f, &db[0].ftable)) {
+    fprintf (stderr, "can't write table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* write vtable to db file (also appends rows to the end of the table) */
+int gfits_db_update (FITS_DB *db) {
+
+  /* this section is not valid if we have changed the size of header, matrix, theader */
+
+  /* write subset to file */
+  // make_backup (db[0].filename);  /*** drop this!!?? ***/
+  Fseek (db[0].f, 0, SEEK_SET);
+
+  /* do we revert to the old version if this fails? */
+  if (!gfits_fwrite_header   (db[0].f, &db[0].header))  {
+    fprintf (stderr, "can't update primary header");
+    return (FALSE);
+  }
+  if (!gfits_fwrite_matrix   (db[0].f, &db[0].matrix))  {
+    fprintf (stderr, "can't update primary matrix");
+    return (FALSE);
+  }
+  if (!gfits_fwrite_Theader  (db[0].f, &db[0].theader)) {
+    fprintf (stderr, "can't update table header");
+    return (FALSE);
+  }
+  if (!gfits_fwrite_vtable   (db[0].f, &db[0].vtable))  {
+    fprintf (stderr, "can't update table data");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* free memory associated with db handle */
+int gfits_db_free (FITS_DB *db) {
+  gfits_free_header (&db[0].header);
+  gfits_free_matrix (&db[0].matrix);
+  gfits_free_header (&db[0].theader);
+  gfits_free_table  (&db[0].ftable);
+  gfits_free_vtable (&db[0].vtable);
+  if (db[0].filename != NULL) {
+    free (db[0].filename);
+    db[0].filename = NULL;
+  }
+  return (TRUE);
+}
+
+/* close the db files (close open file & unlock) */
+int gfits_db_close (FITS_DB *db) {
+  if (db[0].f == NULL) return (TRUE);
+  fclearlockfile (db[0].filename, db[0].f, db[0].lockstate, &db[0].dbstate);
+  db[0].f = NULL;
+  return (TRUE);
+}  
+
+/* for this to be atomic, need to unlink before we unlock */
+/* unlink file here if resulting file is empty? */
+/* if (db[0].Nrow == 0) && (lockstate != LCK_SOFT)) unlink (dBFile); */
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/imreg_datatypes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/imreg_datatypes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/imreg_datatypes.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include <dvo.h>
+
+char typename[N_TYPE][32] = {"none", "object", "dark", "bias", "flat", "mask", "fringe", "scatter", "modes", "frpts", "any"};
+char typecode[N_TYPE]     = {'x',    'o',      'd',    'b',    'f',    'm',    'r',      's',       'M',     'F'};
+char modename[N_MODE][32] = {"none", "MEF", "SPLIT", "SINGLE", "CUBE", "SLICE", "MODES"};
+
+int get_image_type (char *name) {
+
+  int i;
+  
+  for (i = 0; i < N_TYPE; i++) {
+    if (!strncasecmp (name, typename[i], strlen(typename[i]))) {
+      return (i);
+    }
+  }
+
+  /* special cases */
+  if (!strncasecmp (name, "SKYFLAT", strlen("SKYFLAT"))) {
+    return (T_FLAT);
+  }
+
+  return (T_UNDEF);
+}
+
+char *get_type_name (int type) {
+
+  if (type < T_NONE) return ("undef");
+  if (type >= N_TYPE) return ("undef");
+  return (typename[type]);
+}
+
+int get_image_mode (char *name) {
+
+  int i;
+  
+  for (i = 0; i < N_MODE; i++) {
+    if (!strncasecmp (name, modename[i], strlen(modename[i]))) {
+      return (i);
+    }
+  }
+  return (M_UNDEF);
+}
+
+char *get_mode_name (int mode) {
+
+  if (mode < M_NONE) return ("undef");
+  if (mode >= N_MODE) return ("undef");
+  return (modename[mode]);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/mosaic_astrom.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/mosaic_astrom.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/mosaic_astrom.c	(revision 16632)
@@ -0,0 +1,131 @@
+# include <dvo.h>
+
+/* chip-match table: j = ChipMatch[i], images[j] is DIS for images[i] WRP */
+
+static int    iDIS = -1;      // DIS entry in ChipMatch[]
+static int    Ndis = 0;
+static int    *DISentry = NULL;
+static e_time *DIStzero = NULL;
+static int    *ChipMatch = NULL;
+
+/* what is the currently registered mosaic image? */
+int GetRegisteredMosaic () {
+  return (iDIS);
+}
+
+/* given an image array and a current entry of type WRP, find matching DIS & Register it */
+int FindMosaicForImage (Image *images, int Nimages, int entry) {
+
+  int status;
+
+  if (ChipMatch == NULL) {
+    status = FindMosaicForImage_TableSearch (images, Nimages, entry);
+    return (status);
+  }
+  status = FindMosaicForImage_MatchSearch (images, Nimages, entry);
+  return (status);
+}
+
+/* given an image array and a current entry of type WRP, find matching DIS & Register it */
+int FindMosaicForImage_TableSearch (Image *images, int Nimages, int entry) {
+
+  e_time tzero;
+  int i;
+
+  /* search backwards for image with same time and type DIS */
+
+  if (strcmp(&images[entry].coords.ctype[4], "-WRP")) {
+    /* not a wrp image, do nothing */
+    return (TRUE); /* error or not */
+  }
+
+  tzero = images[entry].tzero;
+  
+  for (i = entry - 1; i >= 0; i--) {
+    if (images[i].tzero != tzero) continue;
+    if (strcmp(&images[i].coords.ctype[4], "-DIS")) continue;
+
+    /* found a valid match */
+    RegisterMosaic (&images[i].coords);
+    iDIS = i;
+    return (TRUE);
+  }
+
+  for (i = entry + 1; i < Nimages; i++) {
+    if (images[i].tzero != tzero) continue;
+    if (strcmp(&images[i].coords.ctype[4], "-DIS")) continue;
+
+    /* found a valid match */
+    RegisterMosaic (&images[i].coords);
+    iDIS = i;
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/* given an image array and a current entry of type WRP, find matching DIS & Register it */
+int FindMosaicForImage_MatchSearch (Image *images, int Nimages, int entry) {
+
+  int N;
+
+  if (strcmp(&images[entry].coords.ctype[4], "-WRP")) {
+    /* not a wrp image, do nothing */
+    return (TRUE); /* error or not */
+  }
+
+  if (ChipMatch == NULL) return (FALSE);
+
+  N = ChipMatch[entry];
+  if (N < 0) return (FALSE);
+  if (N >= Nimages) return (FALSE);
+
+  RegisterMosaic (&images[N].coords);
+  iDIS = N;
+  return (TRUE);
+}
+
+int BuildChipMatch (Image *images, int Nimages) {
+
+  int i, j, NDIS;
+
+  if (DISentry != NULL) free (DISentry);
+  if (DIStzero != NULL) free (DIStzero);
+  if (ChipMatch != NULL) free (ChipMatch);
+
+  /* find all DIS images, save tzero (& instrument) */
+  Ndis = 0;
+  NDIS = 100;
+  ALLOCATE (DISentry, int, NDIS);
+  ALLOCATE (DIStzero, e_time, NDIS);
+
+  for (i = 0; i < Nimages; i++) {
+    if (strcmp(&images[i].coords.ctype[4], "-DIS")) continue;
+    DISentry[Ndis] = i;
+    DIStzero[Ndis] = images[i].tzero;
+    Ndis ++;
+    if (Ndis >= NDIS) {
+      NDIS += 100;
+      REALLOCATE (DISentry, int, NDIS);
+      REALLOCATE (DIStzero, e_time, NDIS);
+    }
+  }
+
+  /* find all matched WRP images */
+  ALLOCATE (ChipMatch, int, Nimages);
+  for (i = 0; i < Nimages; i++) {
+    ChipMatch[i] = -1;
+    if (strcmp(&images[i].coords.ctype[4], "-WRP")) continue;
+    for (j = 0; j < Ndis; j++) {
+      if (DIStzero[j] != images[i].tzero) continue;
+      ChipMatch[i] = DISentry[j];
+      goto got_match;
+    }
+
+    fprintf (stderr, "WARNING: can't find matching mosaic \n");
+    ChipMatch[i] = -2;
+
+  got_match:
+    continue;
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/photfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/photfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/photfits.c	(revision 16632)
@@ -0,0 +1,258 @@
+# include <dvo.h>
+# define MAX_ORDER 3
+
+/**** XXXX warning: these functions have not been corrected to handle 
+      the change of Mcal from millimags to mags
+      I don't think most functions are using the Mcal polynomial terms in 
+      any case... ****/
+
+/* all terms of order > 0 are stored as 16bit floats 
+   the zero-order term is stored as a short int (-32k,+32k) */
+
+/* convert double to low-precision short int */
+short int putMi (double value) {
+  
+  double T;
+  unsigned int I;
+
+  if (value > 0) {
+    T = 1000 * log10 (value);
+    I = MAX (MIN (T, 16383), -16382) + 0x3fff;
+    return (I);
+  }
+  if (value < 0) {
+    T = -value;
+    T = 1000 * log10 (T);
+    I = MAX (MIN (T, 16383), -16382) + 0xbfff;
+    return (I);
+  }
+  if (value == 0) {
+    I = 0;
+    return (0);
+  }
+  return (NAN_S_SHORT);
+}
+
+/* convert low-precision short int to double */
+double getMi (short int value) {
+  
+  double T, V, sign;
+  short int I;
+
+  if (value == 0) {
+    return (0.0);
+  }
+  if (value & 0x8000) {
+    sign = -1;
+    I = value & 0x7fff;
+  } else {
+    sign = +1;
+    I = value;
+  }
+    
+  T = (I - 0x3fff) / 1000.0;
+  V = sign * pow (10.0, T);
+  return (V);
+}
+
+/* convert image parameters to c[i] coeffs */
+void returnMcal (Image *image, double *c) {
+
+  switch (image[0].order) {
+  case 0:
+    c[0] = image[0].Mcal;
+    return;
+  case 1:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].My);
+    return;
+  case 2:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].Mxx);
+    c[3] = getMi (image[0].My);
+    c[4] = getMi (image[0].Mxy);
+    c[5] = getMi (image[0].Myy);
+    return;
+  case 3:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].Mxx);
+    c[3] = getMi (image[0].Mxxx);
+    c[4] = getMi (image[0].My);
+    c[5] = getMi (image[0].Mxy);
+    c[6] = getMi (image[0].Mxxy);
+    c[7] = getMi (image[0].Myy);
+    c[8] = getMi (image[0].Mxyy);
+    c[9] = getMi (image[0].Myyy);
+    return;
+  case 4:
+    c[0] = image[0].Mcal;
+    c[1] = getMi (image[0].Mx);
+    c[2] = getMi (image[0].Mxx);
+    c[3] = getMi (image[0].Mxxx);
+    c[4] = getMi (image[0].Mxxxx);
+    c[5] = getMi (image[0].My);
+    c[6] = getMi (image[0].Mxy);
+    c[7] = getMi (image[0].Mxxy);
+    c[8] = getMi (image[0].Mxxxy);
+    c[9] = getMi (image[0].Myy);
+    c[10] = getMi (image[0].Mxyy);
+    c[11] = getMi (image[0].Mxxyy);
+    c[12] = getMi (image[0].Myyy);
+    c[13] = getMi (image[0].Mxyyy);
+    c[14] = getMi (image[0].Myyyy);
+    return;
+  default:
+    c[0] = 0;
+    return;
+  }
+}
+
+void assignMcal (Image *image, double *c, int order) {
+
+  image[0].order = order;
+
+  switch (order) {
+  case 0:
+    image[0].Mcal = c[0];
+    return;
+  case 1:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].My    = putMi(c[2]);
+    return;
+  case 2:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].Mxx   = putMi(c[2]);
+    image[0].My    = putMi(c[3]);
+    image[0].Mxy   = putMi(c[4]);
+    image[0].Myy   = putMi(c[5]);
+    return;
+  case 3:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].Mxx   = putMi(c[2]);
+    image[0].Mxxx  = putMi(c[3]);
+    image[0].My    = putMi(c[4]);
+    image[0].Mxy   = putMi(c[5]);
+    image[0].Mxxy  = putMi(c[6]);
+    image[0].Myy   = putMi(c[7]);
+    image[0].Mxyy  = putMi(c[8]);
+    image[0].Myyy  = putMi(c[9]);
+    return;
+  case 4:
+    image[0].Mcal = c[0];
+    image[0].Mx    = putMi(c[1]);
+    image[0].Mxx   = putMi(c[2]);
+    image[0].Mxxx  = putMi(c[3]);
+    image[0].Mxxxx = putMi(c[4]);
+    image[0].My    = putMi(c[5]);
+    image[0].Mxy   = putMi(c[6]);
+    image[0].Mxxy  = putMi(c[7]);
+    image[0].Mxxxy = putMi(c[8]);
+    image[0].Myy   = putMi(c[9]);
+    image[0].Mxyy  = putMi(c[10]);
+    image[0].Mxxyy = putMi(c[11]);
+    image[0].Myyy  = putMi(c[12]);
+    image[0].Mxyyy = putMi(c[13]);
+    image[0].Myyyy = putMi(c[14]);
+    return;
+  default:
+    image[0].Mcal = 0.0;
+    image[0].order = 0;
+    return;
+  }
+}
+
+/* return value of image fit at x,y */
+double applyMcal (Image *image, double x, double y) {
+
+  double Mcal, c[15];
+
+  returnMcal (image, c);  /* convert image parameters to c[i] coeffs */
+  Mcal = 0.0;
+  switch (image[0].order) {
+  case 0:
+    Mcal = c[0];
+    break;
+  case 1:
+    Mcal = c[0] + x*c[1] + y*c[2];
+    break;
+  case 2:
+    Mcal = c[0] + x*(c[1] + x*c[2]) + y*(c[3] + x*c[4] + y*c[5]);
+    break;
+  case 3:
+    Mcal = c[0] + x*(c[1] + x*(c[2] + x*c[3])) + y*(c[4] + x*(c[5] + x*c[6]) + y*(c[7] + x*c[8] + y*c[9]));
+    break;
+  case 4:
+    Mcal = c[0] + x*(c[1] + x*(c[2] + x*(c[3] + x*c[4]))) + y*(c[5] + x*(c[6] + x*(c[7] + x*c[8])) + y*(c[9] + x*(c[10] + x*c[11]) + y*(c[12] + x*c[13] + y*c[14])));
+    break;
+  }
+  return (Mcal);
+}
+
+double findscatter (double *X, double *Y, double *M, double *dM, int N, double *c, int order) {
+  
+  int i;
+  double *x, *y, *m, *dm;
+  double S, S2, s, dS;
+
+  S2 = S = 0;
+  if (N < 2) {
+    return (0.0);
+  }
+  
+  x = X; y = Y; m = M; dm = dM;
+  switch (order) {
+  case 0:
+    for (i = 0; i < N; i++, m++, dm++) {
+      dS  = *m - c[0];
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 1:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*c[1] + *y*c[2];
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 2:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*(c[1] + *x*c[2]) + *y*(c[3] + *x*c[4] + *y*c[5]);
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 3:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*(c[1] + *x*(c[2] + *x*c[3])) + *y*(c[4] + *x*(c[5] + *x*c[6]) + *y*(c[7] + *x*c[8] + *y*c[9]));
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  case 4:
+    for (i = 0; i < N; i++, m++, x++, y++, dm++) {
+      s   = c[0] + *x*(c[1] + *x*(c[2] + *x*(c[3] + *x*c[4]))) + *y*(c[5] + *x*(c[6] + *x*(c[7] + *x*c[8])) + *y*(c[9] + *x*(c[10] + *x*c[11]) + *y*(c[12] + *x*c[13] + *y*c[14])));
+      dS  = *m - s;
+      *dm = dS;
+      S  += dS;
+      S2 += dS*dS;
+    }
+    break;
+  }
+  S = S / N;
+  S2 = sqrt (S2 / N - S*S);
+  return (S2);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/skydb.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/skydb.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/skydb.c	(revision 16632)
@@ -0,0 +1,400 @@
+
+typedef struct {
+  float r, d;
+} SkyCoord;
+
+/* each region is bounded on the sky by lines of constant RA & DEC.
+   the region represents a specified depth, and it may or may not have
+   children.  The start and end of the children in the array are childS and childE 
+   If the region at the given depth is populated with an object table, then 'object' is TRUE.
+   If the region at the given depth is populated with an image table, then 'image' is TRUE.
+*/   
+
+typedef struct {
+  char  name[16];
+  float Rmin, Rmax;
+  float Dmin, Dmax;
+  int   childS, childE;
+  char  depth, child;
+  char  object, image;
+} SkyRegion; /* 48 bytes */ 
+
+/* I have defined no accelerators other than the table hierarchy */
+
+/* find region which overlaps c at given depth (-1 : max depth) */
+SkyRegion *SkyFindPoint (SkyRegion *db, SkyCoord c, int depth) {
+  
+  Ns = 0;
+  Ne = 1;
+
+  while (1) {
+    No = -1;
+    for (i = Ns; (No == -1) && (i < Ne); i++) {
+      if (c.r < db[i].Rmin) continue;
+      if (c.r > db[i].Rmax) continue;
+      if (c.d < db[i].Dmin) continue;
+      if (c.d > db[i].Dmax) continue;
+      // got the needed region at this depth
+      No = i;
+    }
+    if (No == -1) return ((SkyRegion *) NULL);
+    if (depth == db[No].depth) return (&db[No]);
+    if ((depth > db[No].depth) && !db[No].child) return ((SkyRegion *) NULL);
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    Ns = db[No].childS;
+    Ne = db[No].childE;
+
+    if ((depth > db[No].depth) && db[No].child) continue;
+    return (&db[No]);
+  }
+}
+
+/* find regions at all levels which overlap c */
+SkyRegion **SkyFindLevels (SkyRegion *db, SkyCoord c, int *Nregion) {
+
+  SkyRegion **region;
+  
+  Ns = 0;
+  Ne = 1;
+
+  N = 0;
+  NREGION = 10;
+  ALLOCATE (region, SkyRegion *, NREGION);
+
+  while (1) {
+    No = -1;
+    for (i = Ns; (No == -1) && (i < Ne); i++) {
+      if (c.r < db[i].Rmin) continue;
+      if (c.r > db[i].Rmax) continue;
+      if (c.d < db[i].Dmin) continue;
+      if (c.d > db[i].Dmax) continue;
+      // got the needed region at this depth
+      No = i;
+    }
+    if (No == -1) return ((SkyRegion *) NULL);
+
+    region[N] = &db[No];
+    N++;
+    if (N == NREGION) {
+      NREGION += 10;
+      REALLOCATE (region, SkyRegion *, NREGION);
+    }      
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    if (db[No].child) {
+      Ns = db[No].childS;
+      Ne = db[No].childE;
+    } else {
+      *Nregion = N; 
+      return (region);
+    }
+  }
+}
+
+/* find regions contained within rectangular region  c1 - c2 */
+SkyRegion **SkyFindArea (SkyRegion *db, SkyCoord c1, SkyCoord c2, *nlist) {
+
+  int Nlist;
+  SkyRegion *list, *new, *sub;
+
+  while (c1.r > 360.0) c1.r -= 360.0;
+  while (c1.r <   0.0) c1.r += 360.0;
+  while (c2.r > 360.0) c2.r -= 360.0;
+  while (c2.r <   0.0) c2.r += 360.0;
+
+  /* check on c1.r > c2.r : cross boundary */
+  if (c1.r > c2.r) {
+    c0 = c2; c0.r = 360.0;
+    list1 = SkyFindArea (db, c1, c0, &Nlist1);
+    c0 = c1; c0.r = 0.0;
+    list2 = SkyFindArea (db, c0, c2, &Nlist2);
+    Nlist = Nlist1 + Nlist2;
+    ALLOCATE (list, SkyRegion *, Nlist);
+    memcpy (&list[0], list1, Nlist1*sizeof());
+    memcpy (&list[Nlist1], list2, Nlist2*sizeof());
+    free (list1);
+    free (list2);
+    *nlist = Nlist;
+    return (list);
+  }    
+
+  Nlist = 1;
+  ALLOCATE (list, SkyRegion *, 1);
+  list[0] = &db[0];
+  getchild = db[0].child;
+
+  while (getchild) {
+
+    getchild = FALSE;
+    Nnew = 0;
+    NNEW = Nlist + 100;
+    ALLOCATE (new, SkyRegion *, NNEW);
+
+    for (i = 0; i < Nlist; i++) {
+      if (list[i][0].child) {
+	sub = SkyFindAreaDB(db, list[i], c1, c2, &Nsub);
+	if (Nnew + Nsub == NNEW) {
+	  NNEW += 100;
+	  REALLOCATE (new, SkyRegion *, NNEW);
+	}
+	for (i = 0; i < Nsub; i++) {
+	  getchild |= sub[i][0].child;
+	  new[Nnew] = sub[i];
+	  Nnew++;
+	}
+	free (sub);
+      } else {
+	new[Nnew] = list[i];
+	Nnew ++;
+	if (Nnew == NNEW) {
+	  NNEW += 100;
+	  REALLOCATE (new, SkyRegion *, NNEW);
+	}
+      }
+    }
+
+    free (list);
+    list = new;
+    Nlist = Nnew;
+  }
+
+  return (list);
+  *nlist = Nlist;
+
+}
+
+/* ?? */
+SkyRegion *SkyFindAreaDB (SkyRegion *db, SkyRegion *ref, SkyCoord c1, SkyCoord c2, int *Nregion) {
+
+  SkyRegion **region;
+  
+  Ns = ref[0].childS;
+  Ne = ref[0].childE;
+
+  N = 0;
+  NREGION = 100;
+  ALLOCATE (region, SkyRegion *, NREGION);
+
+  /* c1 min, c2 max */
+
+  for (i = Ns; (No == -1) && (i < Ne); i++) {
+    if (c2.r < db[i].Rmin) continue;
+    if (c1.r > db[i].Rmax) continue;
+    if (c2.d < db[i].Dmin) continue;
+    if (c1.d > db[i].Dmax) continue;
+
+    region[N] = &db[i];
+    N++;
+    if (N == NREGION) {
+      NREGION += 100;
+      REALLOCATE (region, SkyRegion *, NREGION);
+    }      
+  }
+  *Nregion = N; 
+  return (region);
+}
+
+SkyRegion *SkyBuildTable (SkyRegion *seed, int Nseed, int level, int depth) {
+
+  /* given a table of Rmin, Dmin, Rmax, Dmax, name, at level 3, generate
+     all higher levels and 'depth' extra levels */
+
+  /* levels:
+     0 - fullsky.cpt
+     1 - n????.cpt / s????.cpt
+     2 - r????.cpt
+     3 - ????.cpt
+     4 - ????.??.cpt
+  */
+  
+  SkyRegion *db;
+
+  /* allocate at least 30 for levels 0 & 1 */
+  NREGION = 100;
+  ALLOCATE (db, SkyRegion, NREGION);
+
+  /* full sky */
+  strcpy (db[0].name, "fullsky.cpt");
+  db[0].Rmin =   0; db[0].Rmax = 360;
+  db[0].Dmin = -90; db[0].Dmax =  90;
+  db[0].depth = 0;
+  db[0].child = FALSE;
+  N = 1;
+
+  db[0].childS = N;
+  /* north dec bands */
+  for (dec = 0; dec < 90; dec += 7.5) {
+    sprintf (db[N].name, "n%04d.cpt", (int) 100*dec);
+    db[N].Rmin =   0; db[N].Rmax = 360;
+    db[N].Dmin = dec; db[N].Dmax = dec + 7.5;
+    db[N].depth = 1;
+    db[N].child = FALSE;
+    N++;
+  }
+  /* south dec bands */
+  for (dec = 0; dec > -90; dec -= 7.5) {
+    sprintf (db[N].name, "s%04d.cpt", (int) 100*dec);
+    db[N].Rmin =   0;       db[N].Rmax = 360;
+    db[N].Dmin = dec - 7.5; db[N].Dmax = dec;
+    db[N].depth = 1;
+    db[N].child = FALSE;
+    N++;
+  }
+  db[0].childE = N;
+
+  /* subdivide dec bands based on seed */
+  Rnumber = 0;
+  childS = db[0].childS;
+  childE = db[0].childE;
+  for (i = childS; i < childE; i++) {
+
+    Nnew = 0;
+    NNEW = 100;
+    ALLOCATE (new, SkyRegion, NNEW);
+
+    for (j = 0; j < Nseed; j++) {
+      if (seed[j].Rmin > db[i].Rmax) continue;
+      if (seed[j].Rmax < db[i].Rmin) continue;
+      if (seed[j].Dmin > db[i].Dmax) continue;
+      if (seed[j].Dmax < db[i].Dmin) continue;
+      
+      for (k = 0; k < Nnew; k++) {
+	if ((seed[j].Rmin == new[k].Rmin) && 
+	    (seed[j].Rmax == new[k].Rmax)) { 
+	  goto next_seed;
+	}
+	if ((seed[j].Rmin == new[k].Rmin) ^^ 
+	    (seed[j].Rmax != new[k].Rmax)) { 
+	  fprintf (stderr, "inconsistent blocks in seed file\n");
+	  return (NULL);
+	}
+      }	
+      new[Nnew].Rmin = seed[j].Rmin;
+      new[Nnew].Rmax = seed[j].Rmax;
+      new[Nnew].Dmin = db[i].Dmin;
+      new[Nnew].Dmax = db[i].Dmax;
+      new[Nnew].depth = 2;
+      new[Nnew].child = FALSE;
+      strncpy (root, db[i].name, 5); root[5] = 0;
+      sprintf (new[Nnew].name, "%s/r%04d.cpt", root, Rnumber);
+      Rnumber ++;      
+      Nnew ++;
+      if (Nnew == NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, SkyRegion, NNEW);
+      }
+    next_seed:
+    }
+    /* update db list */
+    db[i].childS = N;
+    db[i].childE = N + Nnew;
+    NREGION = N + Nnew + 100;
+    REALLOCATE (db, SkyRegion, NREGION);
+    memcpy (&db[N], new, Nnew*sizeof(SkyRegion));
+    free (new);
+    N += Nnew;
+  }
+
+  /* subdivide ra strips based on seed */
+  childS = db[db[0].childS].childS;
+  childE = db[db[0].childE - 1].childE;
+  nextS = N;
+  for (i = childS; i < childE; i++) {
+
+    Nnew = 0;
+    NNEW = 100;
+    ALLOCATE (new, SkyRegion, NNEW);
+
+    for (j = 0; j < Nseed; j++) {
+      if (seed[j].Rmin > db[i].Rmax) continue;
+      if (seed[j].Rmax < db[i].Rmin) continue;
+      if (seed[j].Dmin > db[i].Dmax) continue;
+      if (seed[j].Dmax < db[i].Dmin) continue;
+      
+      for (k = 0; k < Nnew; k++) {
+	if ((seed[j].Dmin == new[k].Dmin) && 
+	    (seed[j].Dmax == new[k].Dmax)) { 
+	  goto next_seed;
+	}
+	if ((seed[j].Dmin == new[k].Dmin) ^^ 
+	    (seed[j].Dmax != new[k].Dmax)) { 
+	  fprintf (stderr, "inconsistent blocks in seed file\n");
+	  return (NULL);
+	}
+      }	
+      new[Nnew].Dmin = seed[j].Dmin;
+      new[Nnew].Dmax = seed[j].Dmax;
+      new[Nnew].Rmin = db[i].Rmin;
+      new[Nnew].Rmax = db[i].Rmax;
+      new[Nnew].depth = 3;
+      new[Nnew].child = FALSE;
+      strcpy (new[Nnew].name, seed[j].name);
+      Nnew ++;
+      if (Nnew == NNEW) {
+	NNEW += 100;
+	REALLOCATE (new, SkyRegion, NNEW);
+      }
+    next_seed:
+    }
+    
+    /* update db list */
+    db[i].childS = N;
+    db[i].childE = N + Nnew;
+    NREGION = N + Nnew + 100;
+    REALLOCATE (db, SkyRegion, NREGION);
+    memcpy (&db[N], new, Nnew*sizeof(SkyRegion));
+    free (new);
+    N += Nnew;
+  }
+  nextE = N;
+
+  /* subdivide entries once more */
+  childS = nextS;
+  childE = nextE;
+  for (i = childS; i < childE; i++) {
+    Rnumber = 0;
+    db[i].childS = N;
+    dDec = (db[i].Dmax - db[i].Dmin) / 5.0;
+    dRa  = (db[i].Rmax - db[i].Rmin) / 5.0;
+    for (nx = 0; nx < 5; nx++) {
+      for (ny = 0; ny < 5; ny++) {
+	db[N].Dmin = db[i].Dmin + dDec * (nx + 0);
+	db[N].Dmax = db[i].Dmax + dDec * (nx + 1);
+	db[N].Rmin = db[i].Rmin + dDec * (nx + 0);
+	db[N].Rmax = db[i].Rmax + dDec * (nx + 1);
+	db[N].depth = 3;
+	db[N].child = FALSE;
+	strncpy (root, db[i].name, 10); root[10] = 0;
+	sprintf (db[N].name, "%s.%02d.cpt", root, Rnumber);
+	Rnumber ++;
+	N ++;
+	if (N == NREGION) {
+	  NREGION += 100;
+	  REALLOCATE (new, SkyRegion, NREGION);
+	}
+      }
+    }
+  }
+
+}
+
+/* region is pointer to entry in db */
+SkyRegion *SkyExtend (SkyRegion *db, SkyRegion *region) {
+
+}
+
+/* region is pointer to entry in db */
+SkyRegion *SkyContract (SkyRegion *db, SkyRegion *region) {
+
+}
+
+SkyRegion *SkyFindGCircle (SkyRegion *db, SkyCoord c1, SkyCoord c2) {
+
+}
+
+
+/* is entire db in memory, or do we load from disk for each operation? 
+   10,000 at level 3, 100,000 @ 4 : 0.5MB, 5MB */
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_gsc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_gsc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_gsc.c	(revision 16632)
@@ -0,0 +1,540 @@
+# include "dvo.h"
+# define NDECBANDS 24
+# define NDIV 4
+# define DEBUG 0
+
+static int DecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 25, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+static double DecMin[] = {0.0, +7.5, +15.0, +22.5, +30.0, +37.5, +45.0, +52.5, +60.0, +67.5, +75.0, +82.5, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, -52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+static double DecMax[] = {+7.5, +15.0, +22.5, +30.0, +37.5, +45.0, +52.5, +60.0, +67.5, +75.0, +82.5, +90.0, 0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, -52.5, -60.0, -67.5, -75.0, -82.5};
+static char *DecNames[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", "n5230", "n6000", "n6730", "n7500", "n8230", "s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", "s5230", "s6000", "s6730", "s7500", "s8230"};
+
+// L0 : full sky
+// L1 : Dec bands
+// L2 : RA segments
+// L3 : GSC regions
+// L4 : GSC subdivisions
+
+// a zone contains a set of L3 regions of the same size
+typedef struct {
+  int L1band;   // parent band
+  int L3start;  // start of zone in L1 band
+  int L3end;    // end of zone in L1 band (last + 1)
+  float dDec;   // height of L3 region in zone
+  float Rmin;
+  float Rmax;
+  float Dmin;
+  float Dmax;
+  int Nset;
+} SkyRegionZone;
+
+SkyTable *SkyRegionForDecBand (char *buffer, int Nregions, char *DecName, float Dmin, float Dmax);
+SkyRegionZone *SkyRegionFindZones (SkyTable *band, int *Nzones, int parent);
+void SkyTableL2fromZone (SkyTable *L2, SkyTable *L3, SkyTable *L4, SkyTable *band, SkyRegionZone *zone, int parent);
+void SkyTableL3fromL2 (SkyRegion *L2, SkyTable *L3, SkyTable *L4, SkyTable *band, int Ns, int Ne);
+void SkyTableL4fromL3 (SkyRegion *L3, SkyTable *L4);
+
+void SkyTableSort (SkyTable *table);
+void SkyTableAppend (SkyTable *old, SkyTable *new, int Nprev);
+int NsetForDecRange (float dDec);
+void SkyRegionPrint (SkyRegion *region);
+
+SkyTable *SkyTableFromGSC (char *filename, int depth, int VERBOSE) {
+
+  int i, j, skipLines, Nzones;
+
+  Header theader;
+  FTable ftable;
+  SkyTable *skytable;
+  SkyTable *band;
+  SkyTable L0, L1, L2, L3, L4;
+  SkyRegionZone *zones;
+
+  FILE *f;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    if (VERBOSE) fprintf (stderr, "can't find GSC Region file %s\n", filename);
+    return (NULL);
+  }
+
+/* load in table data */
+  ftable.header = &theader;
+  if (!gfits_fread_ftable (f, &ftable, "REGIONS")) {
+    if (VERBOSE) fprintf (stderr, "can't read GSC Region table\n");
+    fclose (f);
+    return (NULL);
+  }
+  gfits_free_header (&theader);
+
+/* generate the regions for each level independently. indices (parent,childE,childS) 
+   refer to the value within the independent group.  at the end, we combine and adjust
+   the indices */
+
+/* L0 : full sky */
+  L0.Nregions = 1;
+  ALLOCATE (L0.regions, SkyRegion, L0.Nregions);
+  L0.regions[0].Rmin 	=   0;
+  L0.regions[0].Rmax 	= 360;
+  L0.regions[0].Dmin 	= -90;
+  L0.regions[0].Dmax 	= +90;
+  L0.regions[0].index  	=  0;
+  L0.regions[0].depth  	=  0;
+  L0.regions[0].parent 	= -1;
+  L0.regions[0].child  	=  TRUE;
+  L0.regions[0].table  	= -1;
+  L0.regions[0].childS  =  0;
+  L0.regions[0].childE  =  NDECBANDS;
+  strcpy (L0.regions[0].name, "fullsky");
+  if (DEBUG) SkyRegionPrint (&L0.regions[0]);
+
+  /* allocate space for all levels */
+  L1.Nregions = L2.Nregions = L3.Nregions = L4.Nregions = 0;
+  ALLOCATE (L1.regions, SkyRegion, 1);
+  ALLOCATE (L2.regions, SkyRegion, 1);
+  ALLOCATE (L3.regions, SkyRegion, 1);
+  ALLOCATE (L4.regions, SkyRegion, 1);
+
+  // skipLines = 0;
+  // for (i = 0; i < 16; i++) skipLines += DecLines[i];
+  // for (i = 16; i < 17; i++) {
+
+  /* L1 : dec bands */
+  skipLines = 0;
+  for (i = 0; i < NDECBANDS; i++) {
+    L1.regions[i].Rmin     = 0;
+    L1.regions[i].Rmax     = 360;
+    L1.regions[i].Dmin     = DecMin[i];
+    L1.regions[i].Dmax     = DecMax[i];
+    L1.regions[i].index    = i;
+    L1.regions[i].depth    = 1;
+    L1.regions[i].parent   = 0;
+    L1.regions[i].child    = TRUE;
+    L1.regions[i].table    = -1;
+    strcpy (L1.regions[i].name, DecNames[i]);
+    if (DEBUG) SkyRegionPrint (&L1.regions[i]);
+
+    /* build the L2 regions for this L1 region (based on zones) */
+    L1.regions[i].childS   = L2.Nregions;
+
+    /* load all GSC Regions in this band */
+    band = SkyRegionForDecBand (&ftable.buffer[skipLines*48], DecLines[i], DecNames[i], L1.regions[i].Dmin, L1.regions[i].Dmax);
+    skipLines += DecLines[i];
+
+    /* sort the band regions by Rmin */
+    SkyTableSort (band);
+    
+    zones = SkyRegionFindZones (band, &Nzones, i);
+
+    /* subdivide each zone */
+    for (j = 0; j < Nzones; j++) {
+      if (DEBUG >= 1) fprintf (stderr, "zone: %d : %f - %f : %f - %f\n", j, zones[j].Rmin, zones[j].Rmax, zones[j].Dmin, zones[j].Dmax);
+      SkyTableL2fromZone (&L2, &L3, &L4, band, &zones[j], i);
+    }
+    free (zones);
+    SkyTableFree (band);
+
+    /* at end of loop, L2.Nregions has been updated to end of L2.regions for L1.region */
+    L1.regions[i].childE   = L2.Nregions;
+
+    L1.Nregions ++;
+    REALLOCATE (L1.regions, SkyRegion, L1.Nregions + 1);
+  }
+
+  /* merge L1 into L0 */
+  ALLOCATE (skytable, SkyTable, 1);
+  ALLOCATE (skytable[0].regions, SkyRegion, 1);
+  skytable[0].Nregions = 0;
+
+  SkyTableAppend (skytable, &L0, 0);
+  SkyTableAppend (skytable, &L1, skytable[0].Nregions - L0.Nregions);
+  SkyTableAppend (skytable, &L2, skytable[0].Nregions - L1.Nregions);
+  SkyTableAppend (skytable, &L3, skytable[0].Nregions - L2.Nregions);
+  SkyTableAppend (skytable, &L4, skytable[0].Nregions - L3.Nregions);
+
+  /* fix the depth elements and create the filename array */
+  ALLOCATE (skytable[0].filename, char *, skytable[0].Nregions);
+  for (i = 0; i < skytable[0].Nregions; i++) {
+    skytable[0].filename[i] = NULL;
+    skytable[0].regions[i].table = (skytable[0].regions[i].depth == depth);
+  }
+  return (skytable);
+}
+
+SkyTable *SkyRegionForDecBand (char *buffer, int Nregions, char *DecName, float DminBand, float DmaxBand) {
+
+  int i;
+  double Rmin, Rmax, Dmin, Dmax;
+  char temp[80], name[80];
+  SkyTable *band;
+  SkyRegion *regions;
+
+  ALLOCATE (band, SkyTable, 1);
+  ALLOCATE (regions, SkyRegion, Nregions);
+  for (i = 0; i < Nregions; i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hstgsc_hms_to_deg (&Rmin, &Rmax, &Dmin, &Dmax, &temp[7]);
+    if (Dmax < Dmin) SWAP (Dmin, Dmax);
+
+    /* check that we are in correct Dec band */
+    if ((Dmax < DminBand) || (Dmin > DmaxBand)) {
+      fprintf (stderr, "error with raw table: table mis-match\n");
+      fprintf (stderr, "line: %s\n", temp);
+      fprintf (stderr, "region %d: %f - %f vs %f - %f\n", i, Dmin, Dmax, DminBand, DmaxBand);
+      exit (2);
+    }
+
+    /* regions near 0,360 boundary have Rmax == 0.0 */
+    if (Rmax < Rmin) Rmax += 360.0;
+
+    regions[i].Dmin = Dmin;
+    regions[i].Dmax = Dmax;
+    regions[i].Rmin = Rmin;
+    regions[i].Rmax = Rmax;
+
+    temp[5] = 0;
+    sprintf (name, "%s/%s", DecName, &temp[1]);
+    strcpy (regions[i].name, name);
+  }
+  band[0].filename = NULL;
+  band[0].regions = regions;
+  band[0].Nregions = Nregions;
+  return (band);
+}
+
+/* sort skytable by Rmin */
+void SkyTableSort (SkyTable *table) {
+
+  SkyRegion *regions;
+  char **filename = NULL;
+
+  regions = table[0].regions;
+  filename = table[0].filename;
+
+# define SWAPFUNC(A,B){ \
+  if (table[0].filename) { \
+    char     *tempfile = filename[A]; filename[A] = filename[B]; filename[B] = tempfile; \
+  } \
+  SkyRegion tempregion = regions[A]; regions[A] = regions[B]; regions[B] = tempregion; \
+}
+# define COMPARE(A,B)(regions[A].Rmin < regions[B].Rmin)
+
+  OHANA_SORT (table[0].Nregions, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+}
+
+/* given a complete set of regions in a Dec band, subdivide into zones of equal-sized regions.
+ * this function assumes the DEC band is sliced first by lines of constant RA, then subdivided
+ * with lines of constant DEC.  Groups ('zones') of these smaller boxes have the same size in
+ * delta-Dec.  We are trying to fine the boundaries of these zones.  The initial assumption
+ * breaks down for the pole region (86.25 < DEC < 90), where the entire range is divided into a
+ * single circular patch.  we need to treat it differently.
+ */
+
+SkyRegionZone *SkyRegionFindZones (SkyTable *band, int *Nzones, int parent) {
+  
+  float Dmin, Dmax, dDec, dDecZone;
+  int i, j, Nz, NZ, Nregions, poleRegion;
+  SkyRegion *regions;
+  SkyRegion tempregion;
+  SkyRegionZone *zones;
+  char basename[64];
+  
+  regions = band[0].regions;
+  Nregions = band[0].Nregions;
+
+  NZ = 10;
+  ALLOCATE (zones, SkyRegionZone, NZ);
+ 
+  /* the pole regions need to be separately handled.  skip in analysis below */
+  poleRegion = 0;
+
+  /* search for transitions in the region dDec, find the max Dec range */
+  Nz = -1;
+  dDecZone = -1;
+  Dmin = +90;
+  Dmax = -90;
+  for (i = 0; i < Nregions; i++) {
+    if ((regions[i].Dmin >= +86.00) || (regions[i].Dmax <= -86.00)) {
+      /* drop the pole region (re-generated below) */
+      poleRegion = SIGN(regions[i].Dmin);
+      Nregions --;
+      tempregion = regions[i];
+      for (j = i; j < Nregions; j++) {
+	regions[j] = regions[j+1];
+      }
+      i--;
+      continue;
+    }
+    /* is this region in the current zone? */
+    Dmin = MIN (regions[i].Dmin, Dmin);
+    Dmax = MAX (regions[i].Dmax, Dmax);
+    dDec = regions[i].Dmax - regions[i].Dmin;
+    if (fabs(dDec - zones[Nz].dDec) > 0.001) {
+      /* we've found the end of the current zone; set the ending info */
+      if (Nz >= 0) {
+	zones[Nz].L3end = i;
+	zones[Nz].Rmax = regions[i-1].Rmax;
+      }
+
+      /* go to the next zone */
+      Nz++;
+      CHECK_REALLOCATE (zones, SkyRegionZone, NZ, Nz, 10);
+
+      /* start info for the new zone */
+      dDecZone = dDec;
+      zones[Nz].Rmin = regions[i].Rmin;
+      zones[Nz].dDec = dDecZone;
+      zones[Nz].L3start = i;
+      zones[Nz].L1band = parent;
+      zones[Nz].Nset = NsetForDecRange (zones[Nz].dDec);
+    }
+  }
+  zones[Nz].L3end = i;
+  zones[Nz].Rmax = regions[i-1].Rmax;
+  Nz ++;
+
+  for (i = 0; i < Nz; i++) {
+    zones[i].Dmin = Dmin;
+    zones[i].Dmax = Dmax;
+  }
+  
+  /* the pole region is mis-allocated in the gsc table to L3.  elevate it 
+     to L2 (zone) and subdivide */
+  if (poleRegion) {
+    CHECK_REALLOCATE (zones, SkyRegionZone, NZ, Nz, 10);
+    /* pole region @ L2 */
+    zones[Nz].Rmin = 0.0;
+    zones[Nz].Rmax = 360.0;
+    if (poleRegion > 0) {
+      zones[Nz].Dmin = +86.25;
+      zones[Nz].Dmax = +90.00;
+      strcpy (basename, "n8230/pole");
+    } else {
+      zones[Nz].Dmin = -90.00;
+      zones[Nz].Dmax = -86.25;
+      strcpy (basename, "s8230/pole");
+    }
+    zones[Nz].dDec = 90.00 - 86.25;
+    zones[Nz].L3start = Nregions;
+    zones[Nz].L3end = Nregions + 5;
+    zones[Nz].L1band = parent;
+
+    band[0].Nregions += 4;
+    REALLOCATE (band[0].regions, SkyRegion, band[0].Nregions);
+    for (i = 0; i < 4; i++) {
+      band[0].regions[Nregions + i].Rmin = i * 90.0;
+      band[0].regions[Nregions + i].Rmax = i * 90.0 + 90.0;
+      if (poleRegion > 0) {
+	band[0].regions[Nregions + i].Dmin = +86.250;
+	band[0].regions[Nregions + i].Dmax = +88.125;
+      } else {
+	band[0].regions[Nregions + i].Dmin = -88.125;
+	band[0].regions[Nregions + i].Dmax = -86.250;
+      }
+      sprintf (band[0].regions[Nregions + i].name, "%s.%d", basename, i);
+    }
+    band[0].regions[Nregions + i].Rmin = 0.0;
+    band[0].regions[Nregions + i].Rmax = 360.0;
+    if (poleRegion > 0) {
+      band[0].regions[Nregions + i].Dmin = +88.125;
+      band[0].regions[Nregions + i].Dmax = +90.000;
+    } else {
+      band[0].regions[Nregions + i].Dmin = -90.000;
+      band[0].regions[Nregions + i].Dmax = -88.125;
+    }
+    sprintf (band[0].regions[Nregions + i].name, "%s.%d", basename, i);
+
+    zones[0].Nset = 6;
+    zones[1].Nset = 5;
+
+    Nz ++;
+  }
+
+  *Nzones = Nz;
+  return (zones);
+}
+
+int NsetForDecRange (float dDec) {
+
+  int Ndiv, Nset;
+  
+  /* max segment size is ~7.5 x 15 degrees */
+  Ndiv = (int) (0.5 + 7.5 / dDec);
+  Nset = 2*Ndiv*Ndiv;
+  return (Nset);
+}
+  
+void SkyTableL2fromZone (SkyTable *L2, SkyTable *L3, SkyTable *L4, SkyTable *band, SkyRegionZone *zone, int parent) {
+
+  int i, Nr, Ns, Ne;
+  char *p, name[80];
+
+  Nr = L2[0].Nregions;
+  REALLOCATE (L2[0].regions, SkyRegion, Nr + 1);
+  
+  /* divide this zone into L2 regions with Nset L3 regions each (fewer on ends) */
+  for (i = zone[0].L3start; i < zone[0].L3end; i += zone[0].Nset) {
+    Ns = i; 
+    Ne = MIN (i + zone[0].Nset, zone[0].L3end);
+
+    L2[0].regions[Nr].Rmin = band[0].regions[Ns].Rmin;
+    L2[0].regions[Nr].Rmax = band[0].regions[Ne - 1].Rmax;
+    L2[0].regions[Nr].Dmin = zone[0].Dmin;
+    L2[0].regions[Nr].Dmax = zone[0].Dmax;
+    
+    L2[0].regions[Nr].index    =  Nr;
+    L2[0].regions[Nr].depth    =  2;
+    L2[0].regions[Nr].table    =  -1;
+    L2[0].regions[Nr].parent   =  parent;
+    L2[0].regions[Nr].child    =  FALSE;
+    L2[0].regions[Nr].childS   =  0;
+    L2[0].regions[Nr].childE   =  0;
+
+    /* define names for L2 regions */
+    p = strchr (band[0].regions[Ns].name, '/');
+    if (p == NULL) {
+      fprintf (stderr, "programming error in SkyTableL2fromZone\n");
+      exit (2);
+    }
+    *p = 0;
+    sprintf (name, "%s/z%03d", band[0].regions[Ns].name, Nr);
+    *p = '/';
+    strcpy (L2[0].regions[Nr].name, name);
+    if (DEBUG >= 2) SkyRegionPrint (&L2[0].regions[Nr]);
+
+    /* childS and childE are set in SkyTableL3fromL2 */
+    SkyTableL3fromL2 (&L2[0].regions[Nr], L3, L4, band, Ns, Ne);
+
+    Nr++;
+    REALLOCATE (L2[0].regions, SkyRegion, Nr + 1);
+  }
+  L2[0].Nregions = Nr;
+}
+
+void SkyTableL3fromL2 (SkyRegion *L2, SkyTable *L3, SkyTable *L4, SkyTable *band, int Ns, int Ne) {
+
+  int i, Nr;
+
+  Nr = L3[0].Nregions;
+  L3[0].Nregions += Ne - Ns;
+  REALLOCATE (L3[0].regions, SkyRegion, L3[0].Nregions);
+
+  L2[0].child  = TRUE;
+  L2[0].childS = Nr;
+  L2[0].childE = L3[0].Nregions;
+
+  /* copy the band entries corresponding to this region in the L3 table */
+  for (i = Ns; i < Ne; i++) {
+
+    L3[0].regions[Nr] = band[0].regions[i];
+    
+    L3[0].regions[Nr].index    =  Nr;
+    L3[0].regions[Nr].depth    =  3;
+    L3[0].regions[Nr].table    =  -1;
+    L3[0].regions[Nr].parent   =  L2[0].index;
+    L3[0].regions[Nr].child    =  FALSE;
+    L3[0].regions[Nr].childS   =  0;
+    L3[0].regions[Nr].childE   =  0;
+
+    if (DEBUG >= 3) SkyRegionPrint (&L3[0].regions[Nr]);
+    /* name is set for the band in SkyRegionForDecBand */
+
+    /* childS and childE are set in SkyTableL3fromL3 */
+    SkyTableL4fromL3 (&L3[0].regions[Nr], L4);
+    Nr++;
+  }
+
+  return;
+}
+
+void SkyTableL4fromL3 (SkyRegion *L3, SkyTable *L4) {
+
+  int nx, ny, Nr, Nbox;
+  double Rmin, Dmin, dR, dD;
+  char name[80];
+
+  Nr = L4[0].Nregions;
+  L4[0].Nregions += NDIV*NDIV;
+  REALLOCATE (L4[0].regions, SkyRegion, L4[0].Nregions);
+
+  L3[0].child  = TRUE;
+  L3[0].childS = Nr;
+  L3[0].childE = L4[0].Nregions;
+
+  // XXX handle the pole regions just a bit differently...
+
+  /* subdivide L3 into NDIV boxes */
+  Rmin = L3[0].Rmin;
+  Dmin = L3[0].Dmin;
+  dR = (L3[0].Rmax - L3[0].Rmin) / NDIV;
+  dD = (L3[0].Dmax - L3[0].Dmin) / NDIV;
+
+  Nbox = 0;
+  for (ny = 0; ny < NDIV; ny ++) {
+    for (nx = 0; nx < NDIV; nx ++) {
+      L4[0].regions[Nr].Rmin     = Rmin  + (nx + 0)*dR;
+      L4[0].regions[Nr].Rmax     = Rmin  + (nx + 1)*dR;
+      L4[0].regions[Nr].Dmin     = Dmin + (ny + 0)*dD;
+      L4[0].regions[Nr].Dmax     = Dmin + (ny + 1)*dD;
+
+      L4[0].regions[Nr].index    =  Nr;
+      L4[0].regions[Nr].depth    =  4;
+      L4[0].regions[Nr].table    =  -1;
+      L4[0].regions[Nr].parent   =  L3[0].index;
+      L4[0].regions[Nr].child    =  FALSE;
+      L4[0].regions[Nr].childS   =  0;
+      L4[0].regions[Nr].childE   =  0;
+
+      sprintf (name, "%s.%02d", L3[0].name, Nbox);
+      strcpy (L4[0].regions[Nr].name, name);
+      if (DEBUG >= 4) SkyRegionPrint (&L4[0].regions[Nr]);
+
+      Nr ++;
+      Nbox ++;
+    }
+  }
+  return;
+}
+
+void SkyTableAppend (SkyTable *old, SkyTable *new, int Nprev) {
+
+  int i, Nold;
+
+  Nold = old[0].Nregions;
+
+  old[0].Nregions += new[0].Nregions;
+  REALLOCATE (old[0].regions, SkyRegion, old[0].Nregions);
+
+  for (i = Nprev; i < Nold; i++) {
+    old[0].regions[i].childS += Nold;
+    old[0].regions[i].childE += Nold;
+  }
+
+  for (i = 0; i < new[0].Nregions; i++) {
+    old[0].regions[i + Nold] = new[0].regions[i];
+    old[0].regions[i + Nold].parent += Nprev;
+  }
+  return;
+}
+
+void SkyRegionPrint (SkyRegion *region) {
+
+  int i;
+
+  fprintf (stderr, "L%d:", region[0].depth);
+  for (i = 0; i < region[0].depth; i++) {
+    fprintf (stderr, " ");
+  } 
+  fprintf (stderr, "%s : %f - %f : %f - %f\n", region[0].name, region[0].Rmin, region[0].Rmax, region[0].Dmin, region[0].Dmax);
+  return;
+}
+
+/***
+    notes and questions:
+    1) is the regions.index value used?
+
+
+***/
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_io.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_io.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_io.c	(revision 16632)
@@ -0,0 +1,169 @@
+# include "dvo.h"
+
+SkyTable *SkyTableLoad (char *filename, int VERBOSE) {
+
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  SkyTable *skytable;
+  FILE *f;
+  int i;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    if (VERBOSE) fprintf (stderr, "can't find Sky Region file %s\n", filename);
+    return (NULL);
+  }
+
+  /* load in table data */
+  ftable.header = &theader;
+  if (!gfits_fread_header (f, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read Sky Region header\n");
+    fclose (f);
+    return (NULL);
+  }
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    if (VERBOSE) fprintf (stderr, "can't read Sky Region matrix\n");
+    gfits_free_header (&header);
+    fclose (f);
+    return (NULL);
+  }
+  if (!gfits_fread_ftable (f, &ftable, "SKY_REGION")) {
+    if (VERBOSE) fprintf (stderr, "can't read Sky Region table\n");
+    gfits_free_header (&header);
+    gfits_free_matrix (&matrix);
+    fclose (f);
+    return (NULL);
+  }
+
+  ALLOCATE (skytable, SkyTable, 1);
+  skytable[0].regions = gfits_table_get_SkyRegion (&ftable, &skytable[0].Nregions, NULL);
+  ALLOCATE (skytable[0].filename, char *, skytable[0].Nregions);
+  for (i = 0; i < skytable[0].Nregions; i++) {
+    skytable[0].filename[i] = NULL;
+  }
+  
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+  gfits_free_header (&theader);
+
+  return (skytable);
+}
+
+int SkyTableSave (SkyTable *skytable, char *filename) {
+
+  Header header;
+  Matrix matrix;
+  Header theader;
+  FTable ftable;
+  FILE *f;
+
+  /* make phu header (no matrix needed) */
+  ftable.header = &theader;
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  gfits_table_set_SkyRegion (&ftable, skytable[0].regions, skytable[0].Nregions);
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) { 
+    fprintf (stderr, "cannot open %s for output\n", filename);
+    return (FALSE);
+  }
+  
+  gfits_fwrite_header  (f, &header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table  (f, &ftable);
+  fclose (f);
+
+  return (TRUE);
+}
+
+SkyTable *SkyTableLoadOptimal (char *catdir, char *skyfile, char *gscfile, int depth, int verbose) {
+
+  char filename[256];
+  struct stat filestat;
+  SkyTable *sky;
+
+  /* first option: CATDIR/SkyTable.fits */
+  sprintf (filename, "%s/SkyTable.fits", catdir);
+  if (stat (filename, &filestat)) goto SKYFILE;
+  if (!check_file_access (filename, FALSE, verbose)) goto SKYFILE;
+  sky = SkyTableLoad (filename, verbose);
+  if (sky == NULL) {
+    fprintf (stderr, "error loading sky table\n");
+    exit (1);
+  }
+  return (sky);
+
+SKYFILE:
+  /* second option: SKYFILE */
+  if (skyfile == NULL) goto GSCFILE;
+  if (skyfile[0] != 0) goto GSCFILE;
+  if (stat (skyfile, &filestat)) goto GSCFILE;
+  if (!check_file_access (skyfile, FALSE, verbose)) goto GSCFILE;
+  sky = SkyTableLoad (skyfile, verbose);
+  if (sky == NULL) {
+    fprintf (stderr, "error loading sky table\n");
+    return (NULL);
+  }
+  /* set the depths to the default depth */
+  SkyTableSetDepth (sky, depth);
+
+  /* create CATDIR copy */
+  sprintf (filename, "%s/SkyTable.fits", catdir);
+  check_file_access (filename, FALSE, verbose);
+  if (!SkyTableSave (sky, filename)) return NULL;
+
+  gfits_convert_SkyRegion (sky[0].regions, sizeof (SkyTable), sky[0].Nregions);
+  return (sky);
+
+GSCFILE:
+  /* third option: GSCFILE */
+  sky = SkyTableFromGSC (gscfile, depth, verbose);
+  if (sky == NULL) {
+    fprintf (stderr, "error loading sky table\n");
+    return (NULL);
+  }
+
+  /* create CATDIR copy */
+  sprintf (filename, "%s/SkyTable.fits", catdir);
+  check_file_access (filename, FALSE, verbose);
+  if (!SkyTableSave (sky, filename)) return NULL;
+
+  gfits_convert_SkyRegion (sky[0].regions, sizeof (SkyRegion), sky[0].Nregions);
+  return (sky);
+}
+
+int SkyListSetFilenames (SkyList *list, char *path, char *ext) {
+
+  int i;
+  char line[256];
+
+  // this generates the names, be sure to free when not needed
+  for (i = 0; i < list[0].Nregions; i++) {
+    sprintf (line, "%s/%s.%s", path, list[0].regions[i][0].name, ext);
+    list[0].filename[i] = strcreate (line);
+  }
+
+  return (TRUE);
+}
+
+int SkyTableSetFilenames (SkyTable *sky, char *path, char *ext) {
+
+  int i;
+  char line[256];
+
+  // this generates the names, be sure to free when not needed
+  for (i = 0; i < sky[0].Nregions; i++) {
+    sprintf (line, "%s/%s.%s", path, sky[0].regions[i].name, ext);
+    sky[0].filename[i] = strcreate (line);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_ops.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_ops.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/skyregion_ops.c	(revision 16632)
@@ -0,0 +1,418 @@
+# include "dvo.h"
+
+/* each region is bounded on the sky by lines of constant RA & DEC.
+   the region represents a specified depth, and it may or may not have
+   children.  The start and end of the children in the array are childS and childE 
+   If the region at the given depth is populated with an object table, then 'object' is TRUE.
+   If the region at the given depth is populated with an image table, then 'image' is TRUE.
+   I have defined no accelerators other than the table hierarchy */
+
+/* find region which overlaps c at given depth (-1 : populated ) */
+SkyList *SkyRegionByPoint (SkyTable *table, int depth, double ra, double dec) {
+  
+  int i, Ns, Ne, No;
+  SkyRegion *region;
+  SkyList *list;
+
+  ALLOCATE (list, SkyList, 1);
+  ALLOCATE (list[0].regions,  SkyRegion *, 1);
+  ALLOCATE (list[0].filename,  char *, 1);
+  list[0].Nregions = 0;
+  list[0].ownElements = FALSE; // this list is only holding a view to the elements
+
+  region = table[0].regions;
+
+  Ns = 0;
+  Ne = 1;
+
+  while (1) {
+    No = -1;
+    for (i = Ns; (i < Ne) && (i < table[0].Nregions); i++) {
+      if (ra  < region[i].Rmin) continue;
+      if (ra  > region[i].Rmax) continue;
+      if (dec < region[i].Dmin) continue;
+      if (dec > region[i].Dmax) continue;
+      No = i;
+      break;
+    }
+    if (No == -1) return (list);
+    if ((depth == -1) && (region[No].table)) break;
+    if (depth == region[No].depth) break;
+    if ((depth > region[No].depth) && !region[No].child) return (list);
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    Ns = region[No].childS;
+    Ne = region[No].childE;
+  }
+
+  list[0].regions[0] = &region[No];
+  list[0].filename[0] = table[0].filename[No];
+  list[0].Nregions = 1;
+  return (list);
+}
+
+/* find regions at all levels which match name */
+/* XXX : need to add support for selected level / populated level */
+SkyList *SkyListByName (SkyTable *table, char *name) {
+
+  int i, Nchar, N, NREGIONS;
+  SkyList *list;
+  SkyRegion *region;
+  
+  N = 0;
+  NREGIONS = 10;
+  ALLOCATE (list, SkyList, 1);
+  ALLOCATE (list[0].regions, SkyRegion *, NREGIONS);
+  ALLOCATE (list[0].filename, char *, NREGIONS);
+  list[0].Nregions = N;
+  list[0].ownElements = FALSE; // this list is only holding a view to the elements
+
+  region = table[0].regions;
+
+  Nchar = strlen (name);
+
+  for (i = 0; i < table[0].Nregions; i++) {
+    if (strncasecmp (region[i].name, name, Nchar)) continue;
+
+    list[0].regions[N] = &region[i];
+    list[0].filename[N] = table[0].filename[i];
+    N++;
+    if (N >= NREGIONS) {
+	NREGIONS += 10;
+	REALLOCATE (list[0].regions, SkyRegion *, NREGIONS);
+	REALLOCATE (list[0].filename, char *, NREGIONS);
+    }
+  }
+  list[0].Nregions = N;
+  return (list);
+}
+
+/* find regions at all levels which overlap c */
+SkyList *SkyListByPoint (SkyTable *table, double ra, double dec) {
+
+  int i, Ns, Ne, No, N, NREGIONS;
+  SkyList *list;
+  SkyRegion *region;
+  
+  N = 0;
+  NREGIONS = 10;
+  ALLOCATE (list, SkyList, 1);
+  ALLOCATE (list[0].regions,  SkyRegion *, NREGIONS);
+  ALLOCATE (list[0].filename,  char *, NREGIONS);
+  list[0].Nregions = N;
+  list[0].ownElements = FALSE; // this list is only holding a view to the elements
+
+  region = table[0].regions;
+
+  Ns = 0;
+  Ne = 1;
+
+  while (1) {
+    No = -1;
+    for (i = Ns; (i < Ne) && (i < table[0].Nregions); i++) {
+      if (ra  < region[i].Rmin) continue;
+      if (ra  > region[i].Rmax) continue;
+      if (dec < region[i].Dmin) continue;
+      if (dec > region[i].Dmax) continue;
+      No = i;
+      break;
+    }
+    if (No == -1) return (list);
+
+    list[0].regions[N] = &region[No];
+    list[0].filename[N] = table[0].filename[No];
+    N++;
+    if (N >= NREGIONS) {
+	NREGIONS += 10;
+	REALLOCATE (list[0].regions, SkyRegion *, NREGIONS);
+	REALLOCATE (list[0].filename, char *, NREGIONS);
+    }
+    list[0].Nregions = N;
+
+    /* need to check Ns, Ne, or guarantee valid range */
+    if (region[No].child) {
+      Ns = region[No].childS;
+      Ne = region[No].childE;
+    } else {
+      return (list);
+    }
+  }
+}
+
+SkyList *SkyListByRadius (SkyTable *table, int depth, double RA, double DEC, double radius) {
+
+  double rad;
+  double Rmin, Rmax, Dmin, Dmax;
+  SkyList *list;
+
+  Dmin = DEC - radius;
+  Dmax = DEC + radius;
+
+  if ((Dmin <= -89) || (Dmax >= 89)) {
+    Rmin = 0;
+    Rmax = 360;
+  } else {
+    rad = MAX (radius / (cos(Dmin*RAD_DEG)), radius / (cos(Dmax*RAD_DEG)));
+    Rmin = RA - rad;
+    Rmax = RA + rad;
+  }
+
+  list = SkyListByBounds (table, depth, Rmin, Rmax, Dmin, Dmax);
+  return (list);
+}
+
+SkyList *SkyListByPatch (SkyTable *table, int depth, SkyRegion *patch) {
+
+  SkyList *list;
+
+  list = SkyListByBounds (table, depth, patch[0].Rmin, patch[0].Rmax, patch[0].Dmin, patch[0].Dmax);
+  return (list);
+}
+
+/* user must be careful about mosaic registration */
+SkyList *SkyListByImage (SkyTable *table, int depth, Image *image) {
+
+  int j;
+  SkyList *list;
+  double r, d, X[4], Y[4];
+  double Rmin, Rmax, Dmin, Dmax;
+  
+  // XXX EAM : image/mosaic MUST be registered (if WRP) 
+  SetImageCorners (X, Y, image);
+
+  Rmin = 360.0;
+  Rmax =   0.0;
+  Dmin = +90.0;
+  Dmax = -90.0;
+
+  /* does this work at 0,360 boundary? XY_to_RD must return 
+     coord offsets relative to CRVAL1,2 (ie, NOT renormalize) */
+  for (j = 0; j < 4; j++) {
+    /* XY_to_RD is two-level if ctype == WRP */
+    XY_to_RD (&r, &d, X[j], Y[j], &image[0].coords);
+    Rmin = MIN (Rmin, r);
+    Rmax = MAX (Rmax, r);
+    Dmin = MIN (Dmin, d);
+    Dmax = MAX (Dmax, d);
+  }
+
+  list = SkyListByBounds (table, depth, Rmin, Rmax, Dmin, Dmax);
+  return (list);
+}
+
+SkyList *SkyListByBounds (SkyTable *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax) {
+
+  int i, j, Ns;
+  SkyList *list, *extra;
+
+  /* rationalize Rmin, Rmax */
+  while (Rmin <   0.0) Rmin += 360;
+  while (Rmin > 360.0) Rmin -= 360;
+  while (Rmax <   0.0) Rmax += 360;
+  while (Rmax > 360.0) Rmax -= 360;
+
+  /* handle 0,360 boundary requests */
+  /* this is probably wrong: I will get duplicates for all Dec bands... */
+  if (Rmin > Rmax) {
+    list = SkyListChildrenByBounds (table, -1, depth, 0.0, Rmax, Dmin, Dmax);
+
+    extra = SkyListChildrenByBounds (table, -1, depth, Rmin, 360.0, Dmin, Dmax);
+    REALLOCATE (list[0].regions, SkyRegion *, list[0].Nregions + extra[0].Nregions);
+    REALLOCATE (list[0].filename, char *, list[0].Nregions + extra[0].Nregions);
+    Ns = list[0].Nregions;
+    for (i = 0; i < extra[0].Nregions; i++) {
+      // search for pre-existing match
+      for (j = 0; j < list[0].Nregions; j++) {
+	if (list[0].regions[j] == extra[0].regions[i]) {
+	  goto skip;
+	}
+      }
+      list[0].regions[Ns] = extra[0].regions[i];
+      list[0].filename[Ns] = extra[0].filename[i];
+      Ns ++;
+    skip:
+      continue;
+    }
+    list[0].Nregions = Ns;
+    SkyListFree (extra);
+  } else {
+    list = SkyListChildrenByBounds (table, -1, depth, Rmin, Rmax, Dmin, Dmax);
+  }
+
+  return (list);
+}
+
+SkyList *SkyListChildrenByBounds (SkyTable *table, int No, int depth, double Rmin, double Rmax, double Dmin, double Dmax) {
+
+  int i, j, Ns, Ne, Nnew, NNEW;
+  int append;
+  SkyList *children;
+  SkyList *list;
+  SkyRegion *region;
+
+  Nnew = 0;
+  NNEW = 50;
+  ALLOCATE (list, SkyList, 1);
+  ALLOCATE (list[0].regions, SkyRegion *, NNEW);
+  ALLOCATE (list[0].filename, char *, NNEW);
+  list[0].ownElements = FALSE; // this list is only holding a view to the elements
+
+  region = table[0].regions;
+
+  if (No == -1) {
+    Ns = 0;
+    Ne = 1;
+  } else {
+    Ns = region[No].childS;
+    Ne = region[No].childE;
+  }
+
+  for (i = Ns; (i < Ne) && (i < table[0].Nregions); i++) {
+    if (Rmax < region[i].Rmin) continue;
+    if (Rmin > region[i].Rmax) continue;
+    if (Dmax < region[i].Dmin) continue;
+    if (Dmin > region[i].Dmax) continue;
+
+    if ((depth > region[i].depth) && (region[i].child == FALSE)) continue;
+
+    append = FALSE;
+    append |= (depth > region[i].depth) && (region[i].child == TRUE);
+    append |= (depth ==             -1) && (region[i].table == FALSE);
+
+    if (append) {
+      /* append children to new */
+      children = SkyListChildrenByBounds (table, i, depth, Rmin, Rmax, Dmin, Dmax);
+      if (Nnew + children[0].Nregions >= NNEW) {
+	NNEW = Nnew + children[0].Nregions + 50;
+	REALLOCATE (list[0].regions, SkyRegion *, NNEW);
+	REALLOCATE (list[0].filename, char *, NNEW);
+      }
+      for (j = 0; j < children[0].Nregions; j++) {
+	list[0].regions[Nnew + j] = children[0].regions[j];
+	list[0].filename[Nnew + j] = children[0].filename[j];
+      }
+      Nnew += children[0].Nregions;
+      SkyListFree (children);
+    } else {
+      list[0].regions[Nnew] = &region[i];
+      list[0].filename[Nnew] = table[0].filename[i];
+      Nnew ++;
+      if (Nnew >= NNEW) {
+	  NNEW += 50;
+	  REALLOCATE (list[0].regions, SkyRegion *, NNEW);
+	  REALLOCATE (list[0].filename, char *, NNEW);
+      }
+    }
+  }
+
+  list[0].Nregions = Nnew;
+  return (list);
+}
+
+/* XXX EAM : this should go elsewhere (libdvo?) */
+void SetImageCorners (double *X, double *Y, Image *image) {
+
+  if (!strcmp(&image[0].coords.ctype[4], "-DIS")) {
+    X[0] = -0.5*image[0].NX; Y[0] = -0.5*image[0].NY;
+    X[1] = +0.5*image[0].NX; Y[1] = -0.5*image[0].NY;
+    X[2] = +0.5*image[0].NX; Y[2] = +0.5*image[0].NY;
+    X[3] = -0.5*image[0].NX; Y[3] = +0.5*image[0].NY;
+  } else {
+    X[0] = 0;           Y[0] = 0;
+    X[1] = image[0].NX; Y[1] = 0;
+    X[2] = image[0].NX; Y[2] = image[0].NY;
+    X[3] = 0;           Y[3] = image[0].NY;
+  }
+}
+
+int SkyTableSetDepth (SkyTable *sky, int depth) {
+
+  int i;
+
+  for (i = 0; i < sky[0].Nregions; i++) {
+    sky[0].regions[i].table = (sky[0].regions[i].depth == depth);
+  }
+  return (TRUE);
+}
+
+int SkyListFree (SkyList *list) {
+
+  int i;
+
+  /* XXX do we need to free the filename array as well? */
+  if (list == NULL) return (TRUE);
+  if (list[0].regions != NULL) {
+    if (list[0].ownElements) {
+      for (i = 0; i < list[0].Nregions; i++) {
+	if (list[0].filename[i] != NULL) {
+	  free (list[0].filename[i]);
+	}
+	free (list[0].regions[i]);
+      }
+    }
+    free (list[0].regions);
+  }
+  free (list);
+  list = NULL;
+  return (TRUE);
+}
+
+int SkyTableFree (SkyTable *table) {
+
+  int i;
+
+  if (table == NULL) return (TRUE);
+  if (table[0].filename != NULL) {
+    for (i = 0; i < table[0].Nregions; i++) {
+      if (table[0].filename[i] != NULL) {
+	free (table[0].filename[i]);
+      }
+    }
+    free (table[0].filename);
+  }
+  if (table[0].regions != NULL) {
+    free (table[0].regions);
+  }
+  free (table);
+  table = NULL;
+  return (TRUE);
+}
+
+int SkyListMerge (SkyList **outlist, SkyList *newlist) {
+
+    int i, j, skip, Nlist, Ntotal;
+    SkyList *list;
+    
+    if (*outlist == NULL) {
+	ALLOCATE (list, SkyList, 1);
+	ALLOCATE (list[0].regions, SkyRegion *, 1);
+	ALLOCATE (list[0].filename, char *, 1);
+	list[0].ownElements = FALSE; // this list is only holding a view to the elements
+	list[0].Nregions = 0;
+	*outlist = list;
+    } else {
+	list = *outlist;
+    }
+
+    Ntotal = list[0].Nregions + newlist[0].Nregions;
+    REALLOCATE (list[0].regions, SkyRegion *, Ntotal);
+    REALLOCATE (list[0].filename, char *, Ntotal);
+
+    Nlist = list[0].Nregions;
+    for (i = 0; i < newlist[0].Nregions; i++) {
+	/* check existing list to see if we already have this region */
+	skip = FALSE;
+	for (j = 0; j < list[0].Nregions; j++) {
+	    if (list[0].regions[j] == newlist[0].regions[i]) skip = TRUE;
+	}
+	if (skip) continue;
+	list[0].regions[Nlist] = newlist[0].regions[i];
+	list[0].filename[Nlist] = newlist[0].filename[i];
+	Nlist++;
+    }
+    list[0].Nregions = Nlist;
+    REALLOCATE (list[0].regions, SkyRegion *, Nlist);
+    REALLOCATE (list[0].filename, char *, Nlist);
+
+    return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/tabletest.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/tabletest.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/tabletest.c	(revision 16632)
@@ -0,0 +1,10 @@
+# include "dvo.h"
+
+int main (int argc, char **argv) {
+
+  SkyTable *table;
+
+  SkyTableFromGSC (argv[1], 2, TRUE);
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libdvo/src/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libdvo/src/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libdvo/src/version.c	(revision 16632)
@@ -0,0 +1,6 @@
+# include <dvo.h>
+static char *name = "$Name: not supported by cvs2svn $";
+
+char *libdvo_version () {
+  return (name);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/Makefile	(revision 16632)
@@ -0,0 +1,74 @@
+default: install
+help:
+	@echo "make options: install libfits man clean dist"
+
+include ../../Makefile.System
+HOME	=	$(ROOT)/src/libfits
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+HEAD	=	$(HOME)/header
+MATR	=	$(HOME)/matrix
+TABL	=	$(HOME)/table
+EXT	=	$(HOME)/extern
+INC	=	$(HOME)/include
+MAN	= 	$(HOME)/doc
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC -Wall -Werror
+FULL_CPPFLAGS = $(BASE_CPPFLAGS) -I$(EXT)
+FULL_LDFLAGS  = $(BASE_LDFLAGS) -lohana
+
+install: $(DESTLIB)/libFITS.a $(DESTLIB)/libFITS.$(DLLTYPE) $(DESTMAN)/fits.1
+libfits: $(LIB)/libFITS.$(ARCH).a $(LIB)/libFITS.$(ARCH).$(DLLTYPE)
+man: $(DESTMAN)/fits.1
+
+INCS = $(DESTINC)/gfitsio.h 
+
+HEADER_OBJ = \
+$(HEAD)/F_modify.$(ARCH).o			$(HEAD)/F_create_H.$(ARCH).o  \
+$(HEAD)/F_free_H.$(ARCH).o			$(HEAD)/F_H_field.$(ARCH).o   \
+$(HEAD)/F_read_H.$(ARCH).o			$(HEAD)/F_write_H.$(ARCH).o   \
+$(HEAD)/F_scan.$(ARCH).o			$(HEAD)/F_print.$(ARCH).o     \
+$(HEAD)/F_copy_H.$(ARCH).o			$(HEAD)/F_delete.$(ARCH).o    \
+$(HEAD)/F_read_XH.$(ARCH).o			$(HEAD)/F_init_H.$(ARCH).o    \
+$(HEAD)/F_convert_H.$(ARCH).o                   $(HEAD)/version.$(ARCH).o
+
+MATRIX_OBJ = \
+$(MATR)/F_add_M_value.$(ARCH).o 		$(MATR)/F_add_M.$(ARCH).o        \
+$(MATR)/F_create_M.$(ARCH).o 			$(MATR)/F_divide_M.$(ARCH).o     \
+$(MATR)/F_free_M.$(ARCH).o 			$(MATR)/F_copy_M.$(ARCH).o       \
+$(MATR)/F_write_M.$(ARCH).o 			$(MATR)/F_get_M_value.$(ARCH).o  \
+$(MATR)/F_multiply_M.$(ARCH).o 			$(MATR)/F_read_M.$(ARCH).o       \
+$(MATR)/F_insert_M.$(ARCH).o 			$(MATR)/F_set_M_value.$(ARCH).o  \
+$(MATR)/F_convert_format.$(ARCH).o              $(MATR)/F_read_segment.$(ARCH).o \
+$(MATR)/F_read_portion.$(ARCH).o		$(MATR)/F_load_M.$(ARCH).o	 \
+$(MATR)/F_matrix.$(ARCH).o                      $(MATR)/F_compress_M.$(ARCH).o   \
+$(MATR)/F_uncompress_data.$(ARCH).o
+
+TABLE_OBJ = \
+$(TABL)/F_create_T.$(ARCH).o 			$(TABL)/F_create_TH.$(ARCH).o    \
+$(TABL)/F_read_T.$(ARCH).o			$(TABL)/F_read_TH.$(ARCH).o      \
+$(TABL)/F_write_T.$(ARCH).o			$(TABL)/F_write_TH.$(ARCH).o     \
+$(TABL)/F_define_column.$(ARCH).o		$(TABL)/F_table_format.$(ARCH).o \
+$(TABL)/F_set_column.$(ARCH).o			$(TABL)/F_get_column.$(ARCH).o   \
+$(TABL)/F_table_row.$(ARCH).o			$(TABL)/F_free_T.$(ARCH).o       \
+$(TABL)/F_table_varlength.$(ARCH).o
+
+EXTERN_OBJ = \
+$(EXT)/fits_hcompress.$(ARCH).o \
+$(EXT)/fits_hdecompress.$(ARCH).o \
+$(EXT)/pliocomp.$(ARCH).o \
+$(EXT)/ricecomp.$(ARCH).o
+
+OBJS = $(HEADER_OBJ) $(MATRIX_OBJ) $(TABLE_OBJ) $(EXTERN_OBJ)
+
+extern: $(EXTERN_OBJ)
+
+$(OBJS): $(INCS)
+
+$(LIB)/libFITS.$(ARCH).a: $(OBJS)
+$(LIB)/libFITS.$(ARCH).$(DLLTYPE): $(OBJS)
+
+$(DESTLIB)/libFITS.a:  $(LIB)/libFITS.$(ARCH).a
+$(DESTLIB)/libFITS.$(DLLTYPE): $(LIB)/libFITS.$(ARCH).$(DLLTYPE)
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,41 @@
+
+- libfits 1.6 : 2006.08.23
+  * in order to allow compliation with cfitsio programs, I have changed the 
+    entire namespace to 'gfits' from 'fits'  (actually, only fits_copy_header 
+    was conflicting, but it is better to have a sufficiently different namespace).  
+    All ohana programs need to migrate to the new version of libfits.
+  * set buffer to NULL in gfits_init_header 
+
+- libfits 1.5
+  * cleaned up signed/unsigned inconsistencies
+
+libfits-1-4:
+  added dependency on libohana
+  make libfits work with ohana_allocate
+  removed internal fits.h include file, 
+  replaced with the common fitsio.h file
+
+2005.10.07
+
+	I was having some memory collision problems, and attempting to
+	use the ohana_allocate functions reminded me that the libFITS
+	functions were not supported under ohana_allocate.  This was
+	unhelpful.  I bit the bullet and split libohana into libohana
+	(base functions only, including ohana_allocate) and libdvo
+	(functions based on the libautocode structures).  Doing this
+	allowed me to make libFITS depend on libohana (including
+	ohana_allocate).  BUT, this forced me to change all LDFLAGS
+	entries in ohana to swap -lohana -lFITS for -lFITS -lohana,
+	and to add include <fitsio.h> in some cases.
+
+libfits-1-3:
+ added some additional vtable support, fixed minor iterpretation errors
+ in fits_modify.  
+
+libfits-1-1: 
+
+  F_scan now skips leading ' before parsing value : some bad FITS
+  writers add ' to float entries!
+
+libfits-1-0:
+  imported to CVS
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/README
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/README	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/README	(revision 16632)
@@ -0,0 +1,33 @@
+
+Installing gene's FITS C libraries.
+
+These FITS libraries are part of a larger package, but the rest of the
+package is not needed to make the libraries.  To install it for a
+specific system, the Makefile expects the environment variable ARCH to
+be defined to something appropriate to your machine (ie, sol for
+solaris, or linux for linux machines.  The resulting .o files then
+have machine specific names (ie, F_read_M.sol.o), making it easy to
+recompile for multiple machines.  The compiled library also has
+a machine specific names (libFITS.sol.a), and the installed version is
+then placed with a generic name in a machine specific locations (ie
+lib/sol/libFITS.a).  
+
+
+Edit the Configure file match your current system.  As it stands, the Makefile
+expects the fits directory to be $(ROOT)/src/fits.  The XINC and XLIB
+variables are not actually used by the fits libraries, so you can
+igore them.  
+
+BYTE_SWAP: byte swapping can be forced by placing a -DBYTE_SWAP option
+on the CC line in Configure (see commented out line).  Byte swapping
+is also enabled automatically if ARCH = linux.  (If you have other
+byte swapped machines, you can edit include/fits.h to enable them
+automatically as well).
+
+define an environment variable ARCH and run "make" or "make install"
+to install the library.
+
+good luck
+
+gene
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/VERSIONS
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/VERSIONS	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/VERSIONS	(revision 16632)
@@ -0,0 +1,5 @@
+
+tag names used by libfits:
+
+TAG         : Comment
+libfits-1-0 : first version under CVS
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.1
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.1	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.1	(revision 16632)
@@ -0,0 +1,256 @@
+.ad l
+.nh
+.TH FITS 1.0 "Sept 18, 1992" "Version 1.0"
+.SH NAME
+\fIFITS HEADER routines:\fP  fits_read_header, fits_write_header, 
+fits_header_field,  fits_scan, fits_print, fits_copy_header,
+fits_create_header, fits_free_header.
+
+\fIFITS MATRIX routines:\fP  fits_read_matrix, fits_write_matrix, 
+fits_get_matrix_value, fits_set_matrix_value, fits_create_matrix, 
+fits_free_matrix, fits_insert_array
+
+.SH SYNOPSIS
+.nf
+.ft B
+(compile with -lFITS)
+# include <fitsio.h>
+.LP
+\fI FITS Header Routines \fP
+.RS
+int   fits_read_header (filename, header)
+char      *filename;
+Header    *header;
+
+int   fits_write_header (filename, header)
+char      *filename;
+Header    *header;
+
+char *fits_header_field (header, field, N)
+Header    *header;
+char      *field;
+int        N;
+
+int   fits_scan   (header, field, mode, N, value)
+int   fits_print  (header, field, mode, N, value)
+int   fits_modify (header, field, mode, N, value)
+Header    *header;
+char      *field, *mode, *value;
+int        N;
+
+int   fits_create_header (header)
+Header    *header;
+
+int   fits_copy_header (header1, header2)
+Header    *header1;
+Header    *header2;
+
+int   fits_free_header (header)
+Header    *header;
+
+.RE
+.LP
+\fI FITS Matrix Routines \fP
+.RS 
+int   fits_read_matrix (filename, matrix)
+char      *filename;
+Matrix    *matrix;
+
+int   fits_write_matrix (filename, matrix)
+char      *filename;
+Matrix    *matrix;
+
+int   fits_get_matrix_value (matrix, x, y)
+Matrix    *matrix;
+int        x, y;
+
+void  fits_set_matrix_value (matrix, x, y, value)
+Matrix    *matrix;
+int        x, y;
+double     value;
+
+int   fits_create_matrix (header, matrix)
+Header    *header;
+Matrix    *matrix;
+
+int   fits_insert_array (matrix, array, x, y)
+Matrix    *matrix;
+Matrix    *array;
+int        x, y;
+
+int   fits_free_matrix (matrix)
+Matrix    *matrix;
+
+
+.SH DESCRIPTION
+.LP
+These functions allow for FITS I/O in a general C-like way.  There are
+several relavant structures defined in \fIfitsio.h\fP (see
+STRUCTURES below).  
+
+\fI FITS Header Routines \fP
+
+.RS 
+\fIfits_read_header\fP opens a file and reads the FITS header into
+a Header structure.  No error checking, except file existence is
+currently provided.  
+
+\fIfits_write_header\fP opens a file and write the Header structure
+into the file in FITS format.  It also puts a RETURN character (0x0a)
+into the N*80 bytes (the end of every header line).  This is not FITS
+standard, but it makes the header more readable.
+
+\fIfits_header_field\fP returns a pointer to the start of the Nth
+header line with the given keyword "field".  No error check is
+provided, except to note the lack of such a field (returns a NULL
+value).
+
+\fIfits_scan\fP, \fIfits_print\fP and \fIfits_modify\fP are modeled on
+\fIfscanf\fP and \fIfprintf\fP but act on a FITS header instead of a
+stream.  \fIfits_print\fP write a new entry, while \fIfits_modify\fP
+alters the value of an existing entry (wiping out the comment line).
+\fBdNote:\fP \fIfits_modify\fP will create a new entry, but \fIfits_print\fP 
+will \fInot\fP modify and existing entry!
+The following modes are supported:
+
+.RS
+.PD 0
+.TP
+%d 
+A signed decimal integer is expected.
+.TP
+%u 
+An unsigned decimal integer is expected.
+.TP
+%ld 
+A long decimal integer is expected.
+.TP
+%hd 
+A short decimal integer is expected.
+.TP
+%f 
+A float is expected.
+.TP 
+%lf 
+A double is expected.
+.TP
+%t 
+A boolean is expected.  The pointer should be of type \fIbool\fP.
+.TP
+%s 
+A string is expected.  The pointer should be of type \fIchar\fP.
+.TP
+%S A comment line string is expected.  The pointer should be of type \fIchar\fP.
+.RE
+
+\fIfits_create_header\fP creates a Header structure based on a partially filled 
+Header structure.  The mandatory structure values (simple, bitpix, Naxes, 
+Naxis[N], extend, unsign) must be set.  The buffer will be filled in 
+according to these values.
+
+\fIfits_copy_header\fP copies the header1 to header2;
+
+\fIfits_free_header\fP frees the allocated pointers associated with the 
+header.
+.RE
+
+\fI FITS Matrix Routines \fP
+
+.RS
+\fIfits_read_matrix\fP opens the given file and reads the matrix structure.
+There is, of course, no decent error checking.
+
+\fIfits_write_matrix\fP opens the given file and writes the matrix structure.
+The matrix is written to the end of the file, in the assumption that
+there is already a Header written to the file.  
+There is, of course, no decent error checking.
+
+\fIfits_get_matrix_value\fP returns the value of the pixel at the given (2-D) 
+coordinates.
+
+\fIfits_set_matrix_value\fP sets the value of the pixel at the given (2-D) 
+coordinates.
+
+\fIfits_create_matrix\fP creates a matrix which corresponds to the format
+described in the Header structure.
+
+\fIfits_copy_matrix\fP makes a duplicate copy of header1 in header2. 
+
+\fIfits_free_matrix\fP frees the allocated pointers associated with the
+Matrix.
+
+\fIfits_insert_array\fP set the values of the Matrix to those of the
+array (a small Matrix), using the x,y values as a relative offset.
+.RE
+
+.SH STRUCTURES
+.PP
+There are several important structures defined in \fIfitsio.h\fP
+which are described here.
+
+# define bool char
+
+# typedef struct {
+  bool                    simple;
+  bool                    unsign;
+  bool                    extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero, bscale;
+  char                   *buffer;
+ } Header;
+
+typedef struct {
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     bitpix;
+  bool                    unsign;
+  double                  bzero, bscale;
+  char                   *buffer;
+  int                     size;
+ } Matrix;
+
+REMINDER: data = (byte value) * bscale + bzero
+
+\fIbool\fP is defined to be a char.
+
+\fIHeader\fP is a structure for holding all header information.  It
+consists of values of the basic header fields required for a FITS file
+(SIMPLE, EXTEND, BITPIX, NAXIS, NAXIS1, NAXIS2...) as well as a
+pointer to the header data itself (\fIbuffer\fP) and the number of
+bytes in the header buffer (\fIsize\fP).  
+
+\fIMatrix\fP is a structure for holding the image matrix data.  It
+consists of the \fINaxes\fP, and \fINaxis[10]\fP entries as well
+as the \fIbuffer\fP and the \fIsize\fP entries.
+
+
+.SH COPYRIGHT
+Copyright 1991 Eugene Magnier
+.PP                                                
+Permission to use, copy, modify, distribute, and sell this software
+and its documentation for any purpose is hereby granted without fee,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of MIT not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.  MIT and the authors make
+no representations about the suitability of this software for any
+purpose.  It is provided "as is" without express or implied warranty.
+.PP
+MIT and the authors disclaim all warranties with regard to this
+software, including all implied warranties of merchantability and
+fitness, in no event shall MIT or the authors be liable for any
+special, indirect or consequential damages or any damages whatsoever
+resulting from loss of use, data or profits, whether in an action of
+contract, negligence or other tortious action, arising out of or in
+connection with the use or performance of this software.
+.SH ACKNOWLEDGEMENTS
+Walter H.G. Lewin for inspiration
+.PP
+NASA for lots of money
+.PP
+.SH AUTHOR
+Eugene Magnier.  MIT - CSR
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.tex
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.tex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.tex	(revision 16632)
@@ -0,0 +1,62 @@
+\documentstyle{AA}
+
+\title{FITS I/O Routine}
+\author{gene magnier}
+
+\begin{document}
+\maketitle
+
+        This file documents the C routines I have created for easy
+manipulation of FITS files.  For now, I will assume familiarity with C
+and the FITS format definitions.  (Maybe I will expand this text
+later).  This set of routines consists of a number of subroutines,
+each of which is contained within its own file.  The subroutines fall into
+three classes: those which manipulte headers, those which manipulate
+data matrices, and those which manipulate tables.  Every subroutine
+has a name which starts with the word {\tt fits}, and includes the word
+{\tt header, matrix,} or {\tt table}.  The file names use the letters
+F, H, M, and T as abbreviations for these words.  Below, I list all of
+the subroutines, and following this I describe them and their use.   
+
+\begin{center}
+\begin{tabular}{ll}
+\hline
+routine name               &   file name \\
+\hline
+fits\_read\_header         &   F\_read\_H.c            \\
+fits\_write\_header        &   F\_write\_H.c           \\
+fits\_header\_field        &   F\_H\_field.c           \\
+fits\_scan                 &   F\_scan.c               \\
+fits\_print                &   F\_print.c              \\
+fits\_modify               &   F\_modify.c             \\
+fits\_delete               &   F\_delete.c             \\
+fits\_create\_header       &   F\_create\_H.c          \\
+fits\_copy\_header         &   F\_copy\_H.c            \\
+fits\_free\_header         &   F\_free\_H.c            \\
+\hline
+fits\_read\_matrix         &   F\_read\_M.c            \\
+fits\_write\_matrix        &   F\_write\_M.c           \\
+fits\_get\_matrix\_value   &   F\_get\_M\_value.c      \\
+fits\_set\_matrix\_value   &   F\_set\_M\_value.c      \\
+fits\_add\_matrix\_value   &   F\_add\_M\_value.c      \\
+fits\_create\_matrix       &   F\_create\_M.c          \\
+fits\_copy\_matrix         &   F\_copy\_M.c            \\
+fits\_free\_matrix         &   F\_free\_M.c            \\
+fits\_add\_matrix          &   F\_add\_M.c             \\
+fits\_multiply\_matrix     &   F\_multiply\_M.c        \\
+fits\_divide\_matrix       &   F\_divide\_M.c          \\
+fits\_insert\_matrix       &   F\_insert\_M.c          \\
+fits\_insert\_array        &   F\_insert\_array.c      \\
+\hline
+fits\_read\_Theader        &   F\_read\_TH.c           \\
+fits\_write\_Theader       &   F\_write\_TH.c          \\
+fits\_create\_Theader      &   F\_create\_TH.c         \\
+fits\_read\_table          &   F\_read\_T.c            \\
+fits\_get\_table\_column   &   F\_get\_T\_column.c     \\
+fits\_get\_table\_value    &   F\_get\_T\_value.c      \\
+\hline
+\end{tabular}
+\end{center}
+
+\end{document}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/fits.txt	(revision 16632)
@@ -0,0 +1,253 @@
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+NAME
+     _F_I_T_S _H_E_A_D_E_R _r_o_u_t_i_n_e_s:  fits_read_header, fits_write_header,
+     fits_header_field,  fits_scan, fits_print, fits_copy_header,
+     fits_create_header, fits_free_header.
+
+     _F_I_T_S _M_A_T_R_I_X _r_o_u_t_i_n_e_s:  fits_read_matrix, fits_write_matrix,
+     fits_get_matrix_value, fits_set_matrix_value,
+     fits_create_matrix, fits_free_matrix, fits_insert_array
+
+SYNOPSIS
+     (compile with -lFITS)
+     # include <fitsio.h>
+
+      _F_I_T_S _H_e_a_d_e_r _R_o_u_t_i_n_e_s
+          int   fits_read_header (filename, header)
+          char      *filename;
+          Header    *header;
+
+          int   fits_write_header (filename, header)
+          char      *filename;
+          Header    *header;
+
+          char *fits_header_field (header, field, N)
+          Header    *header;
+          char      *field;
+          int        N;
+
+          int   fits_scan   (header, field, mode, value, N)
+          int   fits_print  (header, field, mode, value, N)
+          int   fits_modify (header, field, mode, value, N)
+          Header    *header;
+          char      *field, *mode, *value;
+          int        N;
+
+          int   fits_create_header (header)
+          Header    *header;
+
+          int   fits_copy_header (header1, header2)
+          Header    *header1;
+          Header    *header2;
+
+          int   fits_free_header (header)
+          Header    *header;
+
+      _F_I_T_S _M_a_t_r_i_x _R_o_u_t_i_n_e_s
+          int   fits_read_matrix (filename, matrix)
+          char      *filename;
+          Matrix    *matrix;
+
+          int   fits_write_matrix (filename, matrix)
+
+Version 1.0        Last change: Sept 18, 1992                   1
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          char      *filename;
+          Matrix    *matrix;
+
+          int   fits_get_matrix_value (matrix, x, y)
+          Matrix    *matrix;
+          int        x, y;
+
+          void  fits_set_matrix_value (matrix, x, y, value)
+          Matrix    *matrix;
+          int        x, y;
+          double     value;
+
+          int   fits_create_matrix (header, matrix)
+          Header    *header;
+          Matrix    *matrix;
+
+          int   fits_insert_array (matrix, array, x, y)
+          Matrix    *matrix;
+          Matrix    *array;
+          int        x, y;
+
+          int   fits_free_matrix (matrix)
+          Matrix    *matrix;
+
+DESCRIPTION
+     These functions allow for FITS I/O in a general C-like way.
+     There are several relavant structures defined in _f_i_t_s_i_o._h
+     (see STRUCTURES below).
+
+      _F_I_T_S _H_e_a_d_e_r _R_o_u_t_i_n_e_s
+
+          _f_i_t_s__r_e_a_d__h_e_a_d_e_r opens a file and reads the FITS header
+          into a Header structure.  No error checking, except
+          file existence is currently provided.
+
+          _f_i_t_s__w_r_i_t_e__h_e_a_d_e_r opens a file and write the Header
+          structure into the file in FITS format.  It also puts a
+          RETURN character (0x0a) into the N*80 bytes (the end of
+          every header line).  This is not FITS standard, but it
+          makes the header more readable.
+
+          _f_i_t_s__h_e_a_d_e_r__f_i_e_l_d returns a pointer to the start of the
+          Nth header line with the given keyword "field".  No
+          error check is provided, except to note the lack of
+          such a field (returns a NULL value).
+
+          _f_i_t_s__s_c_a_n, _f_i_t_s__p_r_i_n_t and _f_i_t_s__m_o_d_i_f_y are modeled on
+          _f_s_c_a_n_f and _f_p_r_i_n_t_f but act on a FITS header instead of
+          a stream.  _f_i_t_s__p_r_i_n_t write a new entry, while
+          _f_i_t_s__m_o_d_i_f_y alters the value of an existing entry
+
+Version 1.0        Last change: Sept 18, 1992                   2
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          (wiping out the comment line).  The following modes are
+          supported:
+
+               %d   A signed decimal integer is expected.
+               %u   An unsigned decimal integer is expected.
+               %ld  A long decimal integer is expected.
+               %hd  A short decimal integer is expected.
+               %f   A float is expected.
+               %lf  A double is expected.
+               %t   A boolean is expected.  The pointer should be
+                    of type _b_o_o_l.
+               %s   A string is expected.  The pointer should be
+                    of type _c_h_a_r.
+                    should be of type _c_h_a_r.
+               %S A comment line string is expected.  The pointer
+
+          _f_i_t_s__c_r_e_a_t_e__h_e_a_d_e_r creates a Header structure based on
+          a partially filled Header structure.  The mandatory
+          structure values (simple, bitpix, Naxes, Naxis[N],
+          extend, unsign) must be set.  The buffer will be filled
+          in according to these values.
+
+          _f_i_t_s__c_o_p_y__h_e_a_d_e_r copies the header1 to header2;
+
+          _f_i_t_s__f_r_e_e__h_e_a_d_e_r frees the allocated pointers
+          associated with the header.
+
+      _F_I_T_S _M_a_t_r_i_x _R_o_u_t_i_n_e_s
+
+          _f_i_t_s__r_e_a_d__m_a_t_r_i_x opens the given file and reads the
+          matrix structure.  There is, of course, no decent error
+          checking.
+
+          _f_i_t_s__w_r_i_t_e__m_a_t_r_i_x opens the given file and writes the
+          matrix structure.  The matrix is written to the end of
+          the file, in the assumption that there is already a
+          Header written to the file. There is, of course, no
+          decent error checking.
+
+          _f_i_t_s__g_e_t__m_a_t_r_i_x__v_a_l_u_e returns the value of the pixel at
+          the given (2-D) coordinates.
+
+          _f_i_t_s__s_e_t__m_a_t_r_i_x__v_a_l_u_e sets the value of the pixel at
+          the given (2-D) coordinates.
+
+          _f_i_t_s__c_r_e_a_t_e__m_a_t_r_i_x creates a matrix which corresponds
+          to the format described in the Header structure.
+
+          _f_i_t_s__c_o_p_y__m_a_t_r_i_x makes a duplicate copy of header1 in
+          header2.
+
+          _f_i_t_s__f_r_e_e__m_a_t_r_i_x frees the allocated pointers
+
+Version 1.0        Last change: Sept 18, 1992                   3
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+          associated with the Matrix.
+
+          _f_i_t_s__i_n_s_e_r_t__a_r_r_a_y set the values of the Matrix to those
+          of the array (a small Matrix), using the x,y values as
+          a relative offset.
+
+STRUCTURES
+     There are several important structures defined in _f_i_t_s_i_o._h
+     which are described here.
+
+     # define bool char
+
+     # typedef struct {
+       bool                    simple;
+       bool                    unsign;
+       bool                    extend;
+       int                     bitpix;
+       int                     Naxes;
+       int                     Naxis[FT_MAX_NAXES];
+       int                     size;
+       double                  bzero, bscale;
+       char                   *buffer;
+      } Header;
+
+     typedef struct {
+       int                     Naxes;
+       int                     Naxis[FT_MAX_NAXES];
+       int                     bitpix;
+       bool                    unsign;
+       double                  bzero, bscale;
+       char                   *buffer;
+       int                     size;
+      } Matrix;
+
+     REMINDER: data = (byte value) * bscale + bzero
+
+     _b_o_o_l is defined to be a char.
+
+     _H_e_a_d_e_r is a structure for holding all header information.
+     It consists of values of the basic header fields required
+     for a FITS file (SIMPLE, EXTEND, BITPIX, NAXIS, NAXIS1,
+     NAXIS2...) as well as a pointer to the header data itself
+     (_b_u_f_f_e_r) and the number of bytes in the header buffer
+     (_s_i_z_e).
+
+     _M_a_t_r_i_x is a structure for holding the image matrix data.  It
+     consists of the _N_a_x_e_s, and _N_a_x_i_s[_1_0] entries as well as the
+     _b_u_f_f_e_r and the _s_i_z_e entries.
+
+COPYRIGHT
+     Copyright 1991 Eugene Magnier
+
+Version 1.0        Last change: Sept 18, 1992                   4
+
+FITS(1.0)         MISC. REFERENCE MANUAL PAGES          FITS(1.0)
+
+     Permission to use, copy, modify, distribute, and sell this
+     software and its documentation for any purpose is hereby
+     granted without fee, provided that the above copyright
+     notice appear in all copies and that both that copyright
+     notice and this permission notice appear in supporting
+     documentation, and that the name of MIT not be used in
+     advertising or publicity pertaining to distribution of the
+     software without specific, written prior permission.  MIT
+     and the authors make no representations about the
+     suitability of this software for any purpose.  It is
+     provided "as is" without express or implied warranty.
+     MIT and the authors disclaim all warranties with regard to
+     this software, including all implied warranties of
+     merchantability and fitness, in no event shall MIT or the
+     authors be liable for any special, indirect or consequential
+     damages or any damages whatsoever resulting from loss of
+     use, data or profits, whether in an action of contract,
+     negligence or other tortious action, arising out of or in
+     connection with the use or performance of this software.
+ACKNOWLEDGEMENTS
+     Walter H.G. Lewin for inspiration
+     NASA for lots of money
+AUTHOR
+     Eugene Magnier.  MIT - CSR
+
+Version 1.0        Last change: Sept 18, 1992                   5
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes-compress.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes-compress.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes-compress.txt	(revision 16632)
@@ -0,0 +1,54 @@
+
+TFORMn : rPt(e_max)
+r is 0, 1, or absent
+P is literal
+t is datatype character for binary tables
+e_max is the largest record in the column
+
+data column actually contains: 2 32bit values:
+Length + Offset
+
+THEAP : offset from start of data to start of heap
+(note that the heap starts at NAXIS1 x NAXIS2, not Nx2880 bytes). 
+
+total size of heap segment (gap + heap data) is PCOUNT
+
+I need to implement (at least) support for read of compressed images.
+It might be a good plan to upgrade the gfits API set, or at least
+identify needed work.
+
+* PCOUNT / GCOUNT : these are currently ignored.  I need to at least
+  include them in the calculation of the fits data segment size.  I
+  might need to use them in the interpretation of the table data.
+
+* implement variable-length columns in FITS table support.  
+
+* add the I/O support directly to gfits_read/write_matrix, or define
+  low-level APIs to support read/write of a compressed image?
+
+  * we should start with the low-level APIs and add in the higher
+    level ones as needed.
+
+* possible needed APIs & upgrades:
+
+  - gfits_image_is_compressed (Header *header) 
+    does the specified header correspond to a compressed image?	
+    what about the PHU which implies a compressed image in the next
+    HDU?
+
+  - Matrix *gfits_uncompress_image (Header *header, Table *table)
+    convert the specified table into an image, modifying the header in
+    place
+
+  - Table *gfits_compress_image (Header *header, Matrix *matrix, Compression *options)
+    compress the given image returning the table data
+
+  o include PCOUNT in data area size (gfits_matrix_size)
+
+  o read heap when reading table (gfits_fread_table_data)
+
+  - void *gfits_varlength_column_pointer (FTable *ftable, VarLengthColumn *column, int row);
+
+  o int gfits_varlength_column_define (FTable *ftable, VarLengthColumn *def, int column);
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes.txt	(revision 16632)
@@ -0,0 +1,133 @@
+
+2002/09/19
+
+I am making some substantial upgrades to libfits.  My primary goal for
+the moment is the improve the table handling, but I am also making
+some minor cleanups in other areas.  A major concern is that no
+changes should be made to existing functions that will alter their
+behavior and break other programs.  Below I list functions that change
+and note if they risk causing any problems.
+
+header:
+
+fits_init_header:   new function (SAFE)
+fits_create_header: changed fits_print to fits_modify (SAFE)
+fits_fread_header:  new function, to eventually replace fits_load_header (SAFE)
+fits_fwrite_header: new function, to eventually replace fits_save_header (SAFE)
+fits_write_header:  cleaned (f == NULL) (SAFE)
+
+matrix:
+
+fits_create_matrix: if NAXIS==0, create 0 size matrix, allocate min 1 byte
+ - this is different, but now follows correct fits standard.
+ - does not affect any existing programs: all assume NAXIS > 0
+fits_fread_matrix:  new function, to eventually replace fits_load_matrix (SAFE)
+fits_load_matrix:   cleanup declaration format (SAFE)
+fits_fwrite_matrix: new function (SAFE)
+fits_write_matrix:  file ops only, wrapper to fwrite (SAFE)
+fits_matrix_size:   new function (SAFE)
+
+table: no changes
+
+---
+
+fits_write_header:  open / truncate file, write header first
+fits_fwrite_header: 
+
+
+
+current table functions: (9/2002)
+
+fits_read_Theader   (char *filename, Header *theader);
+fits_load_Theader   (FILE *f, Header *theader)
+fits_read_table     (char *filename, Table *table);
+fits_table_column   (Table *table, char *field, char *mode, varg array);
+fits_create_Theader (Header *header, char *type);
+
+new functions:
+
+fits_init_header (Header *header);
+ - set all values to defaults: 
+   bitpix = 8, Naxes = 0, bscale = 1, bzero = 0, extend = FALSE, unsign = FALSE;
+   
+fits_create_table_header (Header *header, char *type);
+ - create an empty table header: TFIELDS = 0, NAXIS1 = NAXIS2 = 0
+
+fits_define_table_column (Header *header, char *format, char *type, char *comment, char *unit);
+ - add a column definition to header
+ - add appropriate keywords
+ - update TFIELDS
+ - update NAXIS1
+
+fits_define_bintable_column (Header *header, char *format, char *type, char *comment, char *unit, double scale, double zero);
+ - add a column definition to header
+ - add appropriate keywords
+ - update TFIELDS
+ - update NAXIS1
+
+fits_get_table_column ()
+
+fits_table_column (Table *table, char *field, char *mode, void *result);
+
+
+
+
+typedef struct {
+  int                     simple;
+  int                     unsign;
+  int                     extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Header;
+
+typedef struct {
+  int                     unsign;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Matrix;
+
+typedef struct {
+  int                     bitpix;
+  int                     Nfields;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  char                   *buffer;
+  Header                  header;
+} Table;
+          
+typedef struct {
+  Header                 *header;
+  char                   *buffer;
+  int                     size;
+} FTable;
+
+typedef struct {
+  Header                 *header;
+  char                  **buffer;
+  int			  Nrow;
+  int                    *row;
+  int                     size;  /* total buffer size */
+  int			  pad;   /* bytes of padding at the end */
+} VTable;
+
+virtual table:
+
+a virtual table contains only part of the data on disk size is the
+total size of the table (disk + mem) buffer is a contiguous block of
+data in the table msize is the size of the memory block stored at
+buffer offset is the start of the memory block
+
+Nx is width of table,
+Ny is number of occupied rows
+size = Nx*Ny + pad;
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes2.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes2.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/notes2.txt	(revision 16632)
@@ -0,0 +1,51 @@
+
+complete list of FITS table APIs:
+
+int fits_create_table (Header *header, FTable *table) 
+int fits_create_Theader (Header *header, char *type)  - create empty extension header 
+int fits_create_table_header (Header *header, char *type, char *extname) - create valid table header
+
+int fits_define_bintable_column (Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero)
+int fits_define_table_column (Header *header, char *format, char *label, char *comment, char *unit) - 
+
+int fits_get_bintable_column (Header *header, FTable *table, char *label, void **data)
+int fits_get_table_column (Header *header, FTable *table, char *label, void **data)
+
+int fits_set_bintable_column (Header *header, FTable *table, char *label, void *data, int Nrow)
+int fits_set_table_column (Header *header, FTable *table, char *label, void *data, int Nrow)
+
+int fits_read_table (char *filename, Table *table)
+int fits_read_ftable (char *filename, FTable *table, char *extname)
+int fits_fread_ftable (FILE *f, FTable *table, char *extname)
+int fits_fread_vtable (FILE *f, VTable *table, char *extname, int Nrow, int *row)
+
+int fits_read_Theader (char *filename, Header *Theader)
+int fits_load_Theader (FILE *f, Header *Theader)
+int fits_fread_Theader (FILE *f, Header *Theader)
+
+int fits_bintable_format (char *format, char *type, int *Nval, int *Nbytes)
+int fits_table_format (char *format, char *type, int *Nval, int *Nbytes)
+
+  interpret table column format values.  
+  format - input column format value (TFORM), output C-style printing format
+  type   - char, int, float, double : use to case pointers
+  Nval   - number of entries 
+  Nbytes - bytes per entry
+
+int fits_table_to_vtable (FTable *ftable, VTable *vtable, int start, int Nkeep)
+
+int fits_add_rows (FTable *table, char *data, int Nrow, int Nbytes)
+int fits_vadd_rows (VTable *table, char *data, int Nrow, int Nbytes)
+int fits_delete_rows (FTable *table, int Nstart, int Nrow)
+
+int fits_write_table (char *filename, FTable *table)
+int fits_fwrite_table (FILE *f, FTable *table)
+int fits_fwrite_vtable (FILE *f, VTable *table)
+
+int fits_write_Theader (char *filename, Header *header)
+int fits_fwrite_Theader (FILE *f, Header *header)
+
+void fits_get_table_column (table, X, mode, values)  - REMOVED
+void fits_get_table_value (table, X, Y, mode, value) - REMOVED
+int fits_table_column (Table *table, char *field, char *mode,...) - REMOVED
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/sample.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/sample.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/sample.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define TRUE 1
+
+main () {
+
+  char filename[80];
+  int i, Nrow;
+  Header header, theader1, theader2;
+  Matrix matrix;
+  FTable table1, table2;
+  float zpobs[1000];
+  float zpref[1000];
+  unsigned long int time[1000];
+  char tchar[1000];
+  
+  strcpy (filename, "test.fits");
+  Nrow = 20;
+  for (i = 0; i < Nrow; i++) {
+    zpobs[i] = i + 5;
+    zpref[i] = i + 15;
+    time[i] = i + 300000;
+    sprintf (&tchar[8*i], "%8d", i);
+  }
+
+  /* create primary header */
+  gfits_init_header (&header);    header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_print (&header, "NEXTEND", "%d", 1, 2);
+
+  /* define bintable header & layout */
+  gfits_create_table_header (&theader1, "BINTABLE", "ZERO_POINTS");
+
+  gfits_define_bintable_column (&theader1, "E", "ZP_OBS", "measured zero point", "mag", 1.0, 0.0);
+  gfits_define_bintable_column (&theader1, "E", "ZP_REF", "measured zero point", "mag", 1.0, 0.0);
+  gfits_define_bintable_column (&theader1, "J", "TIME",   "time of data", "seconds since Jan 1, 1970 UT", 1.0, 0.0);
+  gfits_define_bintable_column (&theader1, "8A", "TCHAR",   "time of data", "seconds since Jan 1, 1970 UT", 1.0, 0.0);
+
+  /* create table, add data values */
+  gfits_create_table (&theader1, &table1);
+
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  gfits_set_bintable_column (&theader1, &table1, "ZP_OBS", zpobs, Nrow);
+  gfits_set_bintable_column (&theader1, &table1, "ZP_REF", zpref, Nrow);
+  gfits_set_bintable_column (&theader1, &table1, "TIME",   time,  Nrow);
+  gfits_set_bintable_column (&theader1, &table1, "TCHAR",  tchar,  Nrow);
+
+  /* define ASCII table header */
+  gfits_create_table_header (&theader2, "TABLE", "ASCII_PTS");
+
+  gfits_define_table_column (&theader2, "F5.2", "ZP_OBS", "measured zero point", "mag");
+  gfits_define_table_column (&theader2, "F5.2", "ZP_REF", "measured zero point", "mag");
+  gfits_define_table_column (&theader2, "I8", "TIME",    "time of data", "seconds");
+  gfits_define_table_column (&theader2, "A8", "TCHAR",   "time of data", "YYYYMMDD");
+
+  /* create table, add data values */
+  gfits_create_table (&theader2, &table2);
+
+  gfits_set_table_column (&theader2, &table2, "ZP_OBS", zpobs, Nrow);
+  gfits_set_table_column (&theader2, &table2, "ZP_REF", zpref, Nrow);
+  gfits_set_table_column (&theader2, &table2, "TIME",   time,  Nrow);
+  gfits_set_table_column (&theader2, &table2, "TCHAR",  tchar, Nrow);
+
+  /* write header, matrix, table1, table2 */
+  gfits_write_header  (filename, &header);
+  gfits_write_matrix  (filename, &matrix);
+  gfits_write_Theader (filename, &theader1);
+  gfits_write_table   (filename, &table1);
+  gfits_write_Theader (filename, &theader2);
+  gfits_write_table   (filename, &table2);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/doc/sample2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/doc/sample2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/doc/sample2.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <stdio.h>
+# define TRUE 1
+
+main () {
+
+  char filename[80];
+  int i, j, Nrow;
+  Header header, theader1, theader2;
+  Matrix matrix;
+  FTable table1, table2;
+  float *zpobs, *zpref;
+  unsigned long int *time;
+  char *tchar;
+  
+  table1.header = &theader1;
+  table2.header = &theader2;
+
+  strcpy (filename, "test.fits");
+  gfits_read_header  (filename, &header);
+  gfits_read_matrix  (filename, &matrix);
+  gfits_read_ftable  (filename, &table1, "ZERO_POINTS");
+  gfits_read_ftable  (filename, &table2, "ASCII_PTS");
+  
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  gfits_get_bintable_column (&theader1, &table1, "ZP_OBS", &zpobs);
+  gfits_get_bintable_column (&theader1, &table1, "ZP_REF", &zpref);
+  gfits_get_bintable_column (&theader1, &table1, "TIME",   &time);
+  gfits_get_bintable_column (&theader1, &table1, "TCHAR",  &tchar);
+  gfits_scan (&theader1, "NAXIS2", "%d", 1, &Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    fprintf (stderr, "%d %f %f %d   ", i, zpobs[i], zpref[i], time[i]);
+    for (j = 0; j < 8; j++) { fprintf (stderr, "%c", tchar[i*8 + j]); }
+    fprintf (stderr, "\n");
+  }
+
+  /* set table column based on array, extend NAXIS2 as needed/appropriate */
+  gfits_get_table_column (&theader2, &table2, "ZP_OBS", &zpobs);
+  gfits_get_table_column (&theader2, &table2, "ZP_REF", &zpref);
+  gfits_get_table_column (&theader2, &table2, "TIME",   &time);
+  gfits_get_table_column (&theader2, &table2, "TCHAR",  &tchar);
+  gfits_scan (&theader2, "NAXIS2", "%d", 1, &Nrow);
+
+  for (i = 0; i < Nrow; i++) {
+    fprintf (stderr, "%d %f %f %d   ", i, zpobs[i], zpref[i], time[i]);
+    for (j = 0; j < 8; j++) { fprintf (stderr, "%c", tchar[i*8 + j]); }
+    fprintf (stderr, "\n");
+  }
+
+
+}      
+
+/*
+  gfits_set_table_column (&theader2, &table2, "ZP_OBS", zpobs, Nrow);
+  gfits_set_table_column (&theader2, &table2, "ZP_REF", zpref, Nrow);
+  gfits_set_table_column (&theader2, &table2, "TIME",   time,  Nrow);
+  gfits_set_table_column (&theader2, &table2, "TCHAR",  tchar, Nrow);
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libfits/extern/fits_hcompress.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/extern/fits_hcompress.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/extern/fits_hcompress.c	(revision 16632)
@@ -0,0 +1,1688 @@
+/*  #########################################################################
+These routines to apply the H-compress compression algorithm to a 2-D Fits
+image were written by R. White at the STScI and were obtained from the STScI at
+http://www.stsci.edu/software/hcompress.html
+
+This source file is a concatination of the following sources files in the
+original distribution 
+ htrans.c 
+ digitize.c 
+ encode.c 
+ qwrite.c 
+ doencode.c 
+ bit_output.c 
+ qtree_encode.c
+
+The following modifications have been made to the original code:
+
+  - commented out redundant "include" statements
+  - added the noutchar global variable 
+  - changed all the 'extern' declarations to 'static', since all the routines are in
+    the same source file
+  - changed the first parameter in encode (and in lower level routines from a file stream
+    to a char array
+  - modifid the encode routine to return the size of the compressed array of bytes
+  - changed calls to printf and perror to call the CFITSIO ffpmsg routine
+  - modified the mywrite routine, and lower level byte writing routines,  to copy 
+    the output bytes to a char array, instead of writing them to a file stream
+  - replace "exit" statements with "return" statements
+  - changed the function declarations to the more modern ANSI C style
+
+ ############################################################################  */
+ 
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include <stdlib.h>
+
+// EAM : dropping fitsio prototypes
+# define LONGLONG long long
+# define DATA_COMPRESSION_ERR 413  /* error in imcompress routines */
+# define DATA_DECOMPRESSION_ERR 414 /* error in imcompress routines */
+
+static long noutchar;
+static long noutmax;
+
+static int htrans(int a[],int nx,int ny);
+static void digitize(int a[], int nx, int ny, int scale);
+static int encode(char *outfile, long *nlen, int a[], int nx, int ny, int scale);
+static void shuffle(int a[], int n, int n2, int tmp[]);
+
+static int htrans64(LONGLONG a[],int nx,int ny);
+static void digitize64(LONGLONG a[], int nx, int ny, int scale);
+static int encode64(char *outfile, long *nlen, LONGLONG a[], int nx, int ny, int scale);
+static void shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]);
+
+static  void writeint(char *outfile, int a);
+static  void writelonglong(char *outfile, LONGLONG a);
+static  int qwrite(char *outfile, char *a, int n); 
+static  int doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3]);
+static  int doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]);
+static int  mywrite(char *file, char buffer[], int n);
+
+static int qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes);
+static int qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes);
+static void start_outputing_bits();
+static void done_outputing_bits(char *outfile);
+static void output_nbits(char *outfile, int bits, int n);
+
+static void qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit);
+static void qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit);
+static void qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[]);
+static int  bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax);
+static void write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit);
+static void write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit);
+
+#define output_nybble(outfile,c)	output_nbits(outfile,c,4)
+#define output_huffman(outfile,c)	output_nbits(outfile,code[c],ncode[c])
+
+/* ---------------------------------------------------------------------- */
+int fits_hcompress(int *a, int ny, int nx, int scale, char *output, 
+                  long *nbytes, int *status)
+{
+  /* 
+     compress the input image using the H-compress algorithm
+  
+   a  - input image array
+   nx - size of X axis of image
+   ny - size of Y axis of image
+   scale - quantization scale factor. Larger values results in more (lossy) compression
+           scale = 0 does lossless compression
+   output - pre-allocated array to hold the output compressed stream of bytes
+   nbyts  - input value = size of the output buffer;
+            returned value = size of the compressed byte stream, in bytes
+
+ NOTE: the nx and ny dimensions as defined within this code are reversed from
+ the usual FITS notation.  ny is the fastest varying dimension, which is
+ usually considered the X axis in the FITS image display
+
+  */
+
+  int stat;
+  
+  if (*status > 0) return(*status);
+
+  /* H-transform */
+  stat = htrans(a, nx, ny);
+  if (stat) {
+     *status = stat;
+     return(*status);
+  }
+
+  /* digitize */
+  digitize(a, nx, ny, scale);
+
+  /* encode and write to output array */
+
+  noutmax = *nbytes;  /* input value is the allocated size of the array */
+  *nbytes = 0;  /* reset */
+
+  stat = encode(output, nbytes, a, nx, ny, scale);
+
+  *status = stat;
+  return(*status);
+}
+/* ---------------------------------------------------------------------- */
+int fits_hcompress64(LONGLONG *a, int ny, int nx, int scale, char *output, 
+                  long *nbytes, int *status)
+{
+  /* 
+     compress the input image using the H-compress algorithm
+  
+   a  - input image array
+   nx - size of X axis of image
+   ny - size of Y axis of image
+   scale - quantization scale factor. Larger values results in more (lossy) compression
+           scale = 0 does lossless compression
+   output - pre-allocated array to hold the output compressed stream of bytes
+   nbyts  - size of the compressed byte stream, in bytes
+
+ NOTE: the nx and ny dimensions as defined within this code are reversed from
+ the usual FITS notation.  ny is the fastest varying dimension, which is
+ usually considered the X axis in the FITS image display
+
+  */
+
+  int stat;
+  
+  if (*status > 0) return(*status);
+
+  /* H-transform */
+  stat = htrans64(a, nx, ny);
+  if (stat) {
+     *status = stat;
+     return(*status);
+  }
+
+  /* digitize */
+  digitize64(a, nx, ny, scale);
+
+  /* encode and write to output array */
+  noutmax = *nbytes;  /* input value is the allocated size of the array */
+  *nbytes = 0;  /* reset */
+
+  stat = encode64(output, nbytes, a, nx, ny, scale);
+
+  *status = stat;
+  return(*status);
+}
+
+ 
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* htrans.c   H-transform of NX x NY integer image
+ *
+ * Programmer: R. White		Date: 11 May 1992
+ */
+
+/* ######################################################################### */
+static int htrans(int a[],int nx,int ny)
+{
+int nmax, log2n, h0, hx, hy, hc, nxtop, nytop, i, j, k;
+int oddx, oddy;
+int shift, mask, mask2, prnd, prnd2, nrnd2;
+int s10, s00;
+int *tmp;
+
+	/*
+	 * log2n is log2 of max(nx,ny) rounded up to next power of 2
+	 */
+	nmax = (nx>ny) ? nx : ny;
+	log2n = (int) (log((float) nmax)/log(2.0)+0.5);
+	if ( nmax > (1<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */
+	tmp = (int *) malloc(((nmax+1)/2)*sizeof(int));
+	if(tmp == (int *) NULL) {
+	  // EAM : dropping Pence CFITSIO dependencies
+	  // XXX : add an error message function to gfits
+	  fprintf (stderr, "htrans: insufficient memory\n");
+	  return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * set up rounding and shifting masks
+	 */
+	shift = 0;
+	mask  = -2;
+	mask2 = mask << 1;
+	prnd  = 1;
+	prnd2 = prnd << 1;
+	nrnd2 = prnd2 - 1;
+	/*
+	 * do log2n reductions
+	 *
+	 * We're indexing a as a 2-D array with dimensions (nx,ny).
+	 */
+	nxtop = nx;
+	nytop = ny;
+	for (k = 0; k<log2n; k++) {
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = i*ny;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				/*
+				 * Divide h0,hx,hy,hc by 2 (1 the first time through).
+				 */
+				h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> shift;
+				hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift;
+				hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift;
+				hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift;
+				/*
+				 * Throw away the 2 bottom bits of h0, bottom bit of hx,hy.
+				 * To get rounding to be same for positive and negative
+				 * numbers, nrnd2 = prnd2 - 1.
+				 */
+				a[s10+1] = hc;
+				a[s10  ] = ( (hx>=0) ? (hx+prnd)  :  hx        ) & mask ;
+				a[s00+1] = ( (hy>=0) ? (hy+prnd)  :  hy        ) & mask ;
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+				s00 += 2;
+				s10 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do last element in row if row length is odd
+				 * s00+1, s10+1 are off edge
+				 */
+				h0 = (a[s10] + a[s00]) << (1-shift);
+				hx = (a[s10] - a[s00]) << (1-shift);
+				a[s10  ] = ( (hx>=0) ? (hx+prnd)  :  hx        ) & mask ;
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+				s00 += 1;
+				s10 += 1;
+			}
+		}
+		if (oddx) {
+			/*
+			 * do last row if column length is odd
+			 * s10, s10+1 are off edge
+			 */
+			s00 = i*ny;
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = (a[s00+1] + a[s00]) << (1-shift);
+				hy = (a[s00+1] - a[s00]) << (1-shift);
+				a[s00+1] = ( (hy>=0) ? (hy+prnd)  :  hy        ) & mask ;
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+				s00 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do corner element if both row and column lengths are odd
+				 * s00+1, s10, s10+1 are off edge
+				 */
+				h0 = a[s00] << (2-shift);
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+			}
+		}
+		/*
+		 * now shuffle in each dimension to group coefficients by order
+		 */
+		for (i = 0; i<nxtop; i++) {
+			shuffle(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			shuffle(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * image size reduced by 2 (round up if odd)
+		 */
+		nxtop = (nxtop+1)>>1;
+		nytop = (nytop+1)>>1;
+		/*
+		 * divisor doubles after first reduction
+		 */
+		shift = 1;
+		/*
+		 * masks, rounding values double after each iteration
+		 */
+		mask  = mask2;
+		prnd  = prnd2;
+		mask2 = mask2 << 1;
+		prnd2 = prnd2 << 1;
+		nrnd2 = prnd2 - 1;
+	}
+	free(tmp);
+	return(0);
+}
+/* ######################################################################### */
+
+static int htrans64(LONGLONG a[],int nx,int ny)
+{
+int nmax, log2n, nxtop, nytop, i, j, k;
+int oddx, oddy;
+int shift;
+int s10, s00;
+LONGLONG h0, hx, hy, hc, prnd, prnd2, nrnd2, mask, mask2;
+LONGLONG *tmp;
+
+	/*
+	 * log2n is log2 of max(nx,ny) rounded up to next power of 2
+	 */
+	nmax = (nx>ny) ? nx : ny;
+	log2n = (int) (log((float) nmax)/log(2.0)+0.5);
+	if ( nmax > (1<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */
+	tmp = (LONGLONG *) malloc(((nmax+1)/2)*sizeof(LONGLONG));
+	if(tmp == (LONGLONG *) NULL) {
+	  // EAM : dropping Pence CFITSIO dependencies
+	  // XXX : add an error message function to gfits
+	  fprintf (stderr, "htrans: insufficient memory\n"); 
+	  return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * set up rounding and shifting masks
+	 */
+	shift = 0;
+	mask  = (LONGLONG) -2;
+	mask2 = mask << 1;
+	prnd  = (LONGLONG) 1;
+	prnd2 = prnd << 1;
+	nrnd2 = prnd2 - 1;
+	/*
+	 * do log2n reductions
+	 *
+	 * We're indexing a as a 2-D array with dimensions (nx,ny).
+	 */
+	nxtop = nx;
+	nytop = ny;
+	for (k = 0; k<log2n; k++) {
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = i*ny;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				/*
+				 * Divide h0,hx,hy,hc by 2 (1 the first time through).
+				 */
+				h0 = (a[s10+1] + a[s10] + a[s00+1] + a[s00]) >> shift;
+				hx = (a[s10+1] + a[s10] - a[s00+1] - a[s00]) >> shift;
+				hy = (a[s10+1] - a[s10] + a[s00+1] - a[s00]) >> shift;
+				hc = (a[s10+1] - a[s10] - a[s00+1] + a[s00]) >> shift;
+				/*
+				 * Throw away the 2 bottom bits of h0, bottom bit of hx,hy.
+				 * To get rounding to be same for positive and negative
+				 * numbers, nrnd2 = prnd2 - 1.
+				 */
+				a[s10+1] = hc;
+				a[s10  ] = ( (hx>=0) ? (hx+prnd)  :  hx        ) & mask ;
+				a[s00+1] = ( (hy>=0) ? (hy+prnd)  :  hy        ) & mask ;
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+				s00 += 2;
+				s10 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do last element in row if row length is odd
+				 * s00+1, s10+1 are off edge
+				 */
+				h0 = (a[s10] + a[s00]) << (1-shift);
+				hx = (a[s10] - a[s00]) << (1-shift);
+				a[s10  ] = ( (hx>=0) ? (hx+prnd)  :  hx        ) & mask ;
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+				s00 += 1;
+				s10 += 1;
+			}
+		}
+		if (oddx) {
+			/*
+			 * do last row if column length is odd
+			 * s10, s10+1 are off edge
+			 */
+			s00 = i*ny;
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = (a[s00+1] + a[s00]) << (1-shift);
+				hy = (a[s00+1] - a[s00]) << (1-shift);
+				a[s00+1] = ( (hy>=0) ? (hy+prnd)  :  hy        ) & mask ;
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+				s00 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do corner element if both row and column lengths are odd
+				 * s00+1, s10, s10+1 are off edge
+				 */
+				h0 = a[s00] << (2-shift);
+				a[s00  ] = ( (h0>=0) ? (h0+prnd2) : (h0+nrnd2) ) & mask2;
+			}
+		}
+		/*
+		 * now shuffle in each dimension to group coefficients by order
+		 */
+		for (i = 0; i<nxtop; i++) {
+			shuffle64(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			shuffle64(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * image size reduced by 2 (round up if odd)
+		 */
+		nxtop = (nxtop+1)>>1;
+		nytop = (nytop+1)>>1;
+		/*
+		 * divisor doubles after first reduction
+		 */
+		shift = 1;
+		/*
+		 * masks, rounding values double after each iteration
+		 */
+		mask  = mask2;
+		prnd  = prnd2;
+		mask2 = mask2 << 1;
+		prnd2 = prnd2 << 1;
+		nrnd2 = prnd2 - 1;
+	}
+	free(tmp);
+	return(0);
+}
+
+/* ######################################################################### */
+static void
+shuffle(int a[], int n, int n2, int tmp[])
+{
+
+/* 
+int a[];	 array to shuffle					
+int n;		 number of elements to shuffle	
+int n2;		 second dimension					
+int tmp[];	 scratch storage					
+*/
+
+int i;
+int *p1, *p2, *pt;
+
+	/*
+	 * copy odd elements to tmp
+	 */
+	pt = tmp;
+	p1 = &a[n2];
+	for (i=1; i < n; i += 2) {
+		*pt = *p1;
+		pt += 1;
+		p1 += (n2+n2);
+	}
+	/*
+	 * compress even elements into first half of A
+	 */
+	p1 = &a[n2];
+	p2 = &a[n2+n2];
+	for (i=2; i<n; i += 2) {
+		*p1 = *p2;
+		p1 += n2;
+		p2 += (n2+n2);
+	}
+	/*
+	 * put odd elements into 2nd half
+	 */
+	pt = tmp;
+	for (i = 1; i<n; i += 2) {
+		*p1 = *pt;
+		p1 += n2;
+		pt += 1;
+	}
+}
+/* ######################################################################### */
+static void
+shuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[])
+{
+
+/* 
+LONGLONG a[];	 array to shuffle					
+int n;		 number of elements to shuffle	
+int n2;		 second dimension					
+LONGLONG tmp[];	 scratch storage					
+*/
+
+int i;
+LONGLONG *p1, *p2, *pt;
+
+	/*
+	 * copy odd elements to tmp
+	 */
+	pt = tmp;
+	p1 = &a[n2];
+	for (i=1; i < n; i += 2) {
+		*pt = *p1;
+		pt += 1;
+		p1 += (n2+n2);
+	}
+	/*
+	 * compress even elements into first half of A
+	 */
+	p1 = &a[n2];
+	p2 = &a[n2+n2];
+	for (i=2; i<n; i += 2) {
+		*p1 = *p2;
+		p1 += n2;
+		p2 += (n2+n2);
+	}
+	/*
+	 * put odd elements into 2nd half
+	 */
+	pt = tmp;
+	for (i = 1; i<n; i += 2) {
+		*p1 = *pt;
+		p1 += n2;
+		pt += 1;
+	}
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* digitize.c	digitize H-transform
+ *
+ * Programmer: R. White		Date: 11 March 1991
+ */
+
+/* ######################################################################### */
+static void  
+digitize(int a[], int nx, int ny, int scale)
+{
+int d, *p;
+
+	/*
+	 * round to multiple of scale
+	 */
+	if (scale <= 1) return;
+	d=(scale+1)/2-1;
+	for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*p+d) : (*p-d))/scale;
+}
+
+/* ######################################################################### */
+static void  
+digitize64(LONGLONG a[], int nx, int ny, int scale)
+{
+LONGLONG d, *p, scale64;
+
+	/*
+	 * round to multiple of scale
+	 */
+	if (scale <= 1) return;
+	d=(scale+1)/2-1;
+	scale64 = scale;  /* use a 64-bit int for efficiency in the big loop */
+
+	for (p=a; p <= &a[nx*ny-1]; p++) *p = ((*p>0) ? (*p+d) : (*p-d))/scale64;
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* encode.c		encode H-transform and write to outfile
+ *
+ * Programmer: R. White		Date: 2 February 1994
+ */
+
+static char code_magic[2] = { (char)0xDD, (char)0x99 };
+
+
+/* ######################################################################### */
+static int encode(char *outfile, long *nlength, int a[], int nx, int ny, int scale)
+{
+
+/* FILE *outfile;  - change outfile to a char array */  
+/*
+  long * nlength    returned length (in bytes) of the encoded array)
+  int a[];								 input H-transform array (nx,ny)
+  int nx,ny;								 size of H-transform array	
+  int scale;								 scale factor for digitization
+*/
+int nel, nx2, ny2, i, j, k, q, vmax[3], nsign, bits_to_go;
+unsigned char nbitplanes[3];
+unsigned char *signbits;
+int stat = 0;
+
+        noutchar = 0;  /* initialize the number of compressed bytes that have been written */
+	nel = nx*ny;
+	/*
+	 * write magic value
+	 */
+	qwrite(outfile, code_magic, sizeof(code_magic));
+	writeint(outfile, nx);			/* size of image */
+	writeint(outfile, ny);
+	writeint(outfile, scale);		/* scale factor for digitization */
+	/*
+	 * write first value of A (sum of all pixels -- the only value
+	 * which does not compress well)
+	 */
+	writelonglong(outfile, (LONGLONG) a[0]);
+
+	a[0] = 0;
+	/*
+	 * allocate array for sign bits and save values, 8 per byte
+	 */
+	signbits = (unsigned char *) malloc((nel+7)/8);
+	if (signbits == (unsigned char *) NULL) {
+	  // EAM : dropping Pence CFITSIO dependencies
+	  // XXX : add an error message function to gfits
+	  fprintf(stderr, "encode: insufficient memory\n"); 
+	  return(DATA_COMPRESSION_ERR);
+	}
+	nsign = 0;
+	bits_to_go = 8;
+	signbits[0] = 0;
+	for (i=0; i<nel; i++) {
+		if (a[i] > 0) {
+			/*
+			 * positive element, put zero at end of buffer
+			 */
+			signbits[nsign] <<= 1;
+			bits_to_go -= 1;
+		} else if (a[i] < 0) {
+			/*
+			 * negative element, shift in a one
+			 */
+			signbits[nsign] <<= 1;
+			signbits[nsign] |= 1;
+			bits_to_go -= 1;
+			/*
+			 * replace a by absolute value
+			 */
+			a[i] = -a[i];
+		}
+		if (bits_to_go == 0) {
+			/*
+			 * filled up this byte, go to the next one
+			 */
+			bits_to_go = 8;
+			nsign += 1;
+			signbits[nsign] = 0;
+		}
+	}
+	if (bits_to_go != 8) {
+		/*
+		 * some bits in last element
+		 * move bits in last byte to bottom and increment nsign
+		 */
+		signbits[nsign] <<= bits_to_go;
+		nsign += 1;
+	}
+
+	/*
+	 * calculate number of bit planes for 3 quadrants
+	 *
+	 * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, 
+	 */
+	for (q=0; q<3; q++) {
+		vmax[q] = 0;
+	}
+	/*
+	 * get maximum absolute value in each quadrant
+	 */
+	nx2 = (nx+1)/2;
+	ny2 = (ny+1)/2;
+	j=0;	/* column counter	*/
+	k=0;	/* row counter		*/
+	for (i=0; i<nel; i++) {
+		q = (j>=ny2) + (k>=nx2);
+		if (vmax[q] < a[i]) vmax[q] = a[i];
+		if (++j >= ny) {
+			j = 0;
+			k += 1;
+		}
+	}
+	/*
+	 * now calculate number of bits for each quadrant
+	 */
+	for (q = 0; q < 3; q++) {
+		nbitplanes[q] = (int) (log((float) (vmax[q]+1))/log(2.0)+0.5);
+		if ( (vmax[q]+1) > (1<<nbitplanes[q]) ) {
+			nbitplanes[q] += 1;
+		}
+	}
+	/*
+	 * write nbitplanes
+	 */
+	if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
+	        *nlength = noutchar;
+
+		fprintf (stderr, "encode: output buffer too small\n");
+		return (DATA_COMPRESSION_ERR);
+        }
+	 
+	/*
+	 * write coded array
+	 */
+	stat = doencode(outfile, a, nx, ny, nbitplanes);
+	/*
+	 * write sign bits
+	 */
+
+	if (nsign > 0) {
+
+	   if ( 0 == qwrite(outfile, (char *) signbits, nsign)) {
+	        free(signbits);
+	        *nlength = noutchar;
+		fprintf (stderr, "encode: output buffer too small");
+		return(DATA_COMPRESSION_ERR);
+          }
+	} 
+	
+	free(signbits);
+	*nlength = noutchar;
+
+        if (noutchar >= noutmax) {
+	  fprintf (stderr, "encode: output buffer too small");
+	  return(DATA_COMPRESSION_ERR);
+        }  
+	
+	return(stat); 
+}
+/* ######################################################################### */
+static int encode64(char *outfile, long *nlength, LONGLONG a[], int nx, int ny, int scale)
+{
+
+/* FILE *outfile;  - change outfile to a char array */  
+/*
+  long * nlength    returned length (in bytes) of the encoded array)
+  LONGLONG a[];								 input H-transform array (nx,ny)
+  int nx,ny;								 size of H-transform array	
+  int scale;								 scale factor for digitization
+*/
+int nel, nx2, ny2, i, j, k, q, nsign, bits_to_go;
+LONGLONG vmax[3];
+unsigned char nbitplanes[3];
+unsigned char *signbits;
+int stat = 0;
+
+        noutchar = 0;  /* initialize the number of compressed bytes that have been written */
+	nel = nx*ny;
+	/*
+	 * write magic value
+	 */
+	qwrite(outfile, code_magic, sizeof(code_magic));
+	writeint(outfile, nx);				/* size of image	*/
+	writeint(outfile, ny);
+	writeint(outfile, scale);			/* scale factor for digitization */
+	/*
+	 * write first value of A (sum of all pixels -- the only value
+	 * which does not compress well)
+	 */
+
+	writelonglong(outfile, a[0]);
+	a[0] = 0;
+	/*
+	 * allocate array for sign bits and save values, 8 per byte
+	 */
+	signbits = (unsigned char *) malloc((nel+7)/8);
+	if (signbits == (unsigned char *) NULL) {
+	  fprintf (stderr, "encode64: insufficient memory");
+	  return(DATA_COMPRESSION_ERR);
+	}
+	nsign = 0;
+	bits_to_go = 8;
+	signbits[0] = 0;
+	for (i=0; i<nel; i++) {
+		if (a[i] > 0) {
+			/*
+			 * positive element, put zero at end of buffer
+			 */
+			signbits[nsign] <<= 1;
+			bits_to_go -= 1;
+		} else if (a[i] < 0) {
+			/*
+			 * negative element, shift in a one
+			 */
+			signbits[nsign] <<= 1;
+			signbits[nsign] |= 1;
+			bits_to_go -= 1;
+			/*
+			 * replace a by absolute value
+			 */
+			a[i] = -a[i];
+		}
+		if (bits_to_go == 0) {
+			/*
+			 * filled up this byte, go to the next one
+			 */
+			bits_to_go = 8;
+			nsign += 1;
+			signbits[nsign] = 0;
+		}
+	}
+	if (bits_to_go != 8) {
+		/*
+		 * some bits in last element
+		 * move bits in last byte to bottom and increment nsign
+		 */
+		signbits[nsign] <<= bits_to_go;
+		nsign += 1;
+	}
+	/*
+	 * calculate number of bit planes for 3 quadrants
+	 *
+	 * quadrant 0=bottom left, 1=bottom right or top left, 2=top right, 
+	 */
+	for (q=0; q<3; q++) {
+		vmax[q] = 0;
+	}
+	/*
+	 * get maximum absolute value in each quadrant
+	 */
+	nx2 = (nx+1)/2;
+	ny2 = (ny+1)/2;
+
+        i = 0;
+        for (k=0; k<ny; k++) {
+            for (j=0; j<nx; j++) {
+                q = (j>=ny2) + (k>=nx2);
+                vmax[q] |= a[i];
+                i++;
+            }
+        } 
+
+	/*
+	 * now calculate number of bits for each quadrant
+	 */
+	 
+        /* this is a more efficient way to do this, */
+ 
+ 
+        for (q = 0; q < 3; q++) {
+            for (nbitplanes[q] = 0; vmax[q]>0; vmax[q] = vmax[q]>>1, nbitplanes[q]++) ; 
+        }
+
+
+/*
+	for (q = 0; q < 3; q++) {
+		nbitplanes[q] = log((float) (vmax[q]+1))/log(2.0)+0.5;
+		if ( (vmax[q]+1) > (((LONGLONG) 1)<<nbitplanes[q]) ) {
+			nbitplanes[q] += 1;
+		}
+	}
+*/
+
+	/*
+	 * write nbitplanes
+	 */
+
+	if (0 == qwrite(outfile, (char *) nbitplanes, sizeof(nbitplanes))) {
+	        *nlength = noutchar;
+		fprintf (stderr, "encode: output buffer too small");
+		return(DATA_COMPRESSION_ERR);
+        }
+	 
+	/*
+	 * write coded array
+	 */
+	stat = doencode64(outfile, a, nx, ny, nbitplanes);
+	/*
+	 * write sign bits
+	 */
+
+	if (nsign > 0) {
+
+	   if ( 0 == qwrite(outfile, (char *) signbits, nsign)) {
+	        free(signbits);
+	        *nlength = noutchar;
+		fprintf (stderr, "encode: output buffer too small");
+		return(DATA_COMPRESSION_ERR);
+          }
+	} 
+
+	free(signbits);
+	
+	*nlength = noutchar;
+
+        if (noutchar >= noutmax) {
+		fprintf (stderr, "encode64: output buffer too small");
+		return(DATA_COMPRESSION_ERR);
+        }
+		
+	return(stat); 
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* qwrite.c	Write binary data
+ *
+ * Programmer: R. White		Date: 11 March 1991
+ */
+
+/* ######################################################################### */
+static void
+writeint(char *outfile, int a)
+{
+int i;
+unsigned char b[4];
+
+	/* Write integer A one byte at a time to outfile.
+	 *
+	 * This is portable from Vax to Sun since it eliminates the
+	 * need for byte-swapping.
+	 */
+	for (i=3; i>=0; i--) {
+		b[i] = a & 0x000000ff;
+		a >>= 8;
+	}
+	for (i=0; i<4; i++) qwrite(outfile, (char *) &b[i],1);
+}
+
+/* ######################################################################### */
+static void
+writelonglong(char *outfile, LONGLONG a)
+{
+int i;
+unsigned char b[8];
+
+	/* Write integer A one byte at a time to outfile.
+	 *
+	 * This is portable from Vax to Sun since it eliminates the
+	 * need for byte-swapping.
+	 */
+	for (i=7; i>=0; i--) {
+		b[i] = (unsigned char) (a & 0x000000ff);
+		a >>= 8;
+	}
+	for (i=0; i<8; i++) qwrite(outfile, (char *) &b[i],1);
+}
+
+/* ######################################################################### */
+static int qwrite(char *outfile, char *a, int n)
+{
+int nwrite;
+
+	nwrite = mywrite(outfile, a, n);	
+	return(nwrite);      /* added by WDP to prevent compiler warning */
+}
+
+/* ######################################################################### */
+static int
+mywrite(char *file, char buffer[], int n)
+{
+    /*
+     * write n bytes from buffer into file
+     * returns number of bytes read (=n) if successful, <=0 if not
+     */
+
+     if (noutchar + n > noutmax) return(0);  /* buffer overflow */
+     
+     memcpy(&file[noutchar], buffer, n);
+     noutchar += n;
+
+     return(n);
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* doencode.c	Encode 2-D array and write stream of characters on outfile
+ *
+ * This version assumes that A is positive.
+ *
+ * Programmer: R. White		Date: 7 May 1991
+ */
+
+/* ######################################################################### */
+static int
+doencode(char *outfile, int a[], int nx, int ny, unsigned char nbitplanes[3])
+{
+/* char *outfile;						 output data stream
+int a[];							 Array of values to encode			
+int nx,ny;							 Array dimensions [nx][ny]			
+unsigned char nbitplanes[3];		 Number of bit planes in quadrants	
+*/
+
+int nx2, ny2, stat = 0;
+
+	nx2 = (nx+1)/2;
+	ny2 = (ny+1)/2;
+	/*
+	 * Initialize bit output
+	 */
+	start_outputing_bits();
+	/*
+	 * write out the bit planes for each quadrant
+	 */
+	stat = qtree_encode(outfile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
+
+        if (!stat)
+		stat = qtree_encode(outfile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
+
+        if (!stat)
+		stat = qtree_encode(outfile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
+
+        if (!stat)
+		stat = qtree_encode(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
+	/*
+	 * Add zero as an EOF symbol
+	 */
+	output_nybble(outfile, 0);
+	done_outputing_bits(outfile);
+	
+	return(stat);
+}
+/* ######################################################################### */
+static int
+doencode64(char *outfile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3])
+{
+/* char *outfile;						 output data stream
+LONGLONG a[];							 Array of values to encode			
+int nx,ny;							 Array dimensions [nx][ny]			
+unsigned char nbitplanes[3];		 Number of bit planes in quadrants	
+*/
+
+int nx2, ny2, stat = 0;
+
+	nx2 = (nx+1)/2;
+	ny2 = (ny+1)/2;
+	/*
+	 * Initialize bit output
+	 */
+	start_outputing_bits();
+	/*
+	 * write out the bit planes for each quadrant
+	 */
+	stat = qtree_encode64(outfile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
+
+        if (!stat)
+		stat = qtree_encode64(outfile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
+
+        if (!stat)
+		stat = qtree_encode64(outfile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
+
+        if (!stat)
+		stat = qtree_encode64(outfile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
+	/*
+	 * Add zero as an EOF symbol
+	 */
+	output_nybble(outfile, 0);
+	done_outputing_bits(outfile);
+	
+	return(stat);
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* BIT OUTPUT ROUTINES */
+
+
+static LONGLONG bitcount;
+
+/* THE BIT BUFFER */
+
+static int buffer2;			/* Bits buffered for output	*/
+static int bits_to_go2;			/* Number of bits free in buffer */
+
+
+/* ######################################################################### */
+/* INITIALIZE FOR BIT OUTPUT */
+
+static void
+start_outputing_bits()
+{
+	buffer2 = 0;			/* Buffer is empty to start	*/
+	bits_to_go2 = 8;		/* with				*/
+	bitcount = 0;
+}
+
+/* ######################################################################### */
+/* OUTPUT N BITS (N must be <= 8) */
+
+static void
+output_nbits(char *outfile, int bits, int n)
+{
+	/*
+	 * insert bits at end of buffer
+	 */
+	buffer2 <<= n;
+	buffer2 |= ( bits & ((1<<n)-1) );
+	bits_to_go2 -= n;
+	if (bits_to_go2 <= 0) {
+		/*
+		 * buffer2 full, put out top 8 bits
+		 */
+/*		putc((buffer2>>(-bits_to_go2)) & 0xff,outfile); */
+
+	        outfile[noutchar] = ((buffer2>>(-bits_to_go2)) & 0xff);
+
+		if (noutchar < noutmax) noutchar++;
+		
+		bits_to_go2 += 8;
+	}
+	bitcount += n;
+}
+
+
+/* ######################################################################### */
+/* FLUSH OUT THE LAST BITS */
+
+static void
+done_outputing_bits(char *outfile)
+{
+	if(bits_to_go2 < 8) {
+/*		putc(buffer2<<bits_to_go2,outfile); */
+
+	        outfile[noutchar] = (buffer2<<bits_to_go2);
+		if (noutchar < noutmax) noutchar++;
+
+		/* count the garbage bits too */
+		bitcount += bits_to_go2;
+	}
+}
+/* ######################################################################### */
+/* ######################################################################### */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* qtree_encode.c	Encode values in quadrant of 2-D array using binary
+ *					quadtree coding for each bit plane.  Assumes array is
+ *					positive.
+ *
+ * Programmer: R. White		Date: 15 May 1991
+ */
+
+/*
+ * Huffman code values and number of bits in each code
+ */
+static int code[16] =
+	{
+	0x3e, 0x00, 0x01, 0x08, 0x02, 0x09, 0x1a, 0x1b,
+	0x03, 0x1c, 0x0a, 0x1d, 0x0b, 0x1e, 0x3f, 0x0c
+	};
+static int ncode[16] =
+	{
+	6,    3,    3,    4,    3,    4,    5,    5,
+	3,    5,    4,    5,    4,    5,    6,    4
+	};
+
+/*
+ * variables for bit output to buffer when Huffman coding
+ */
+static int bitbuffer, bits_to_go3;
+
+/*
+ * macros to write out 4-bit nybble, Huffman code for this value
+ */
+
+
+/* ######################################################################### */
+static int
+qtree_encode(char *outfile, int a[], int n, int nqx, int nqy, int nbitplanes)
+{
+
+/*
+int a[];
+int n;								 physical dimension of row in a		
+int nqx;							 length of row			
+int nqy;							 length of column (<=n)				
+int nbitplanes;						 number of bit planes to output	
+*/
+	
+int log2n, i, k, bit, b, bmax, nqmax, nqx2, nqy2, nx, ny;
+unsigned char *scratch, *buffer;
+
+	/*
+	 * log2n is log2 of max(nqx,nqy) rounded up to next power of 2
+	 */
+	nqmax = (nqx>nqy) ? nqx : nqy;
+	log2n = (int) (log((float) nqmax)/log(2.0)+0.5);
+	if (nqmax > (1<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * initialize buffer point, max buffer size
+	 */
+	nqx2 = (nqx+1)/2;
+	nqy2 = (nqy+1)/2;
+	bmax = (nqx2*nqy2+1)/2;
+	/*
+	 * We're indexing A as a 2-D array with dimensions (nqx,nqy).
+	 * Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
+	 * Buffer is used to store string of codes for output.
+	 */
+	scratch = (unsigned char *) malloc(2*bmax);
+	buffer = (unsigned char *) malloc(bmax);
+	if ((scratch == (unsigned char *) NULL) ||
+		(buffer  == (unsigned char *) NULL)) {
+/*		fprintf(stderr, "qtree_encode: insufficient memory\n");
+		exit(-1);  */
+		
+		fprintf (stderr, "qtree_encode: insufficient memory");
+		return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * now encode each bit plane, starting with the top
+	 */
+	for (bit=nbitplanes-1; bit >= 0; bit--) {
+		/*
+		 * initial bit buffer
+		 */
+		b = 0;
+		bitbuffer = 0;
+		bits_to_go3 = 0;
+		/*
+		 * on first pass copy A to scratch array
+		 */
+		qtree_onebit(a,n,nqx,nqy,scratch,bit);
+		nx = (nqx+1)>>1;
+		ny = (nqy+1)>>1;
+		/*
+		 * copy non-zero values to output buffer, which will be written
+		 * in reverse order
+		 */
+		if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
+			/*
+			 * quadtree is expanding data,
+			 * change warning code and just fill buffer with bit-map
+			 */
+			write_bdirect(outfile,a,n,nqx,nqy,scratch,bit);
+			goto bitplane_done;
+		}
+		/*
+		 * do log2n reductions
+		 */
+		for (k = 1; k<log2n; k++) {
+			qtree_reduce(scratch,ny,nx,ny,scratch);
+			nx = (nx+1)>>1;
+			ny = (ny+1)>>1;
+			if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
+				write_bdirect(outfile,a,n,nqx,nqy,scratch,bit);
+				goto bitplane_done;
+			}
+		}
+		/*
+		 * OK, we've got the code in buffer
+		 * Write quadtree warning code, then write buffer in reverse order
+		 */
+		output_nybble(outfile,0xF);
+		if (b==0) {
+			if (bits_to_go3>0) {
+				/*
+				 * put out the last few bits
+				 */
+				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
+					bits_to_go3);
+			} else {
+				/*
+				 * have to write a zero nybble if there are no 1's in array
+				 */
+				output_huffman(outfile,0);
+			}
+		} else {
+			if (bits_to_go3>0) {
+				/*
+				 * put out the last few bits
+				 */
+				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
+					bits_to_go3);
+			}
+			for (i=b-1; i>=0; i--) {
+				output_nbits(outfile,buffer[i],8);
+			}
+		}
+		bitplane_done: ;
+	}
+	free(buffer);
+	free(scratch);
+	return(0);
+}
+/* ######################################################################### */
+static int
+qtree_encode64(char *outfile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes)
+{
+
+/*
+LONGLONG a[];
+int n;								 physical dimension of row in a		
+int nqx;							 length of row			
+int nqy;							 length of column (<=n)				
+int nbitplanes;						 number of bit planes to output	
+*/
+	
+int log2n, i, k, bit, b, nqmax, nqx2, nqy2, nx, ny;
+int bmax;  /* this potentially needs to be made a 64-bit int to support large arrays */
+unsigned char *scratch, *buffer;
+
+	/*
+	 * log2n is log2 of max(nqx,nqy) rounded up to next power of 2
+	 */
+	nqmax = (nqx>nqy) ? nqx : nqy;
+	log2n = (int) (log((float) nqmax)/log(2.0)+0.5);
+	if (nqmax > (1<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * initialize buffer point, max buffer size
+	 */
+	nqx2 = (nqx+1)/2;
+	nqy2 = (nqy+1)/2;
+	bmax = (( nqx2)* ( nqy2)+1)/2;
+	/*
+	 * We're indexing A as a 2-D array with dimensions (nqx,nqy).
+	 * Scratch is 2-D with dimensions (nqx/2,nqy/2) rounded up.
+	 * Buffer is used to store string of codes for output.
+	 */
+	scratch = (unsigned char *) malloc(2*bmax);
+	buffer = (unsigned char *) malloc(bmax);
+	if ((scratch == (unsigned char *) NULL) ||
+		(buffer  == (unsigned char *) NULL)) {
+/*		fprintf(stderr, "qtree_encode: insufficient memory\n");
+		exit(-1);  */
+		
+		fprintf (stderr, "qtree_encode64: insufficient memory");
+		return(DATA_COMPRESSION_ERR);
+	}
+	/*
+	 * now encode each bit plane, starting with the top
+	 */
+	for (bit=nbitplanes-1; bit >= 0; bit--) {
+		/*
+		 * initial bit buffer
+		 */
+		b = 0;
+		bitbuffer = 0;
+		bits_to_go3 = 0;
+		/*
+		 * on first pass copy A to scratch array
+		 */
+		qtree_onebit64(a,n,nqx,nqy,scratch,bit);
+		nx = (nqx+1)>>1;
+		ny = (nqy+1)>>1;
+		/*
+		 * copy non-zero values to output buffer, which will be written
+		 * in reverse order
+		 */
+		if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
+			/*
+			 * quadtree is expanding data,
+			 * change warning code and just fill buffer with bit-map
+			 */
+			write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit);
+			goto bitplane_done;
+		}
+		/*
+		 * do log2n reductions
+		 */
+		for (k = 1; k<log2n; k++) {
+			qtree_reduce(scratch,ny,nx,ny,scratch);
+			nx = (nx+1)>>1;
+			ny = (ny+1)>>1;
+			if (bufcopy(scratch,nx*ny,buffer,&b,bmax)) {
+				write_bdirect64(outfile,a,n,nqx,nqy,scratch,bit);
+				goto bitplane_done;
+			}
+		}
+		/*
+		 * OK, we've got the code in buffer
+		 * Write quadtree warning code, then write buffer in reverse order
+		 */
+		output_nybble(outfile,0xF);
+		if (b==0) {
+			if (bits_to_go3>0) {
+				/*
+				 * put out the last few bits
+				 */
+				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
+					bits_to_go3);
+			} else {
+				/*
+				 * have to write a zero nybble if there are no 1's in array
+				 */
+				output_huffman(outfile,0);
+			}
+		} else {
+			if (bits_to_go3>0) {
+				/*
+				 * put out the last few bits
+				 */
+				output_nbits(outfile, bitbuffer & ((1<<bits_to_go3)-1),
+					bits_to_go3);
+			}
+			for (i=b-1; i>=0; i--) {
+				output_nbits(outfile,buffer[i],8);
+			}
+		}
+		bitplane_done: ;
+	}
+	free(buffer);
+	free(scratch);
+	return(0);
+}
+
+/* ######################################################################### */
+/*
+ * copy non-zero codes from array to buffer
+ */
+static int
+bufcopy(unsigned char a[], int n, unsigned char buffer[], int *b, int bmax)
+{
+int i;
+
+	for (i = 0; i < n; i++) {
+		if (a[i] != 0) {
+			/*
+			 * add Huffman code for a[i] to buffer
+			 */
+			bitbuffer |= code[a[i]] << bits_to_go3;
+			bits_to_go3 += ncode[a[i]];
+			if (bits_to_go3 >= 8) {
+				buffer[*b] = bitbuffer & 0xFF;
+				*b += 1;
+				/*
+				 * return warning code if we fill buffer
+				 */
+				if (*b >= bmax) return(1);
+				bitbuffer >>= 8;
+				bits_to_go3 -= 8;
+			}
+		}
+	}
+	return(0);
+}
+
+/* ######################################################################### */
+/*
+ * Do first quadtree reduction step on bit BIT of array A.
+ * Results put into B.
+ * 
+ */
+static void
+qtree_onebit(int a[], int n, int nx, int ny, unsigned char b[], int bit)
+{
+int i, j, k;
+int b0, b1, b2, b3;
+int s10, s00;
+
+	/*
+	 * use selected bit to get amount to shift
+	 */
+	b0 = 1<<bit;
+	b1 = b0<<1;
+	b2 = b0<<2;
+	b3 = b0<<3;
+	k = 0;							/* k is index of b[i/2,j/2]	*/
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of a[i,j]	*/
+		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] = ( ( a[s10+1]     & b0)
+				   | ((a[s10  ]<<1) & b1)
+				   | ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> bit;
+			k += 1;
+			s00 += 2;
+			s10 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * row size is odd, do last element in row
+			 * s00+1,s10+1 are off edge
+			 */
+			b[k] = ( ((a[s10  ]<<1) & b1)
+				   | ((a[s00  ]<<3) & b3) ) >> bit;
+			k += 1;
+		}
+	}
+	if (i < nx) {
+		/*
+		 * column size is odd, do last row
+		 * s10,s10+1 are off edge
+		 */
+		s00 = n*i;
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] = ( ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> bit;
+			k += 1;
+			s00 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * both row and column size are odd, do corner element
+			 * s00+1, s10, s10+1 are off edge
+			 */
+			b[k] = ( ((a[s00  ]<<3) & b3) ) >> bit;
+			k += 1;
+		}
+	}
+}
+/* ######################################################################### */
+/*
+ * Do first quadtree reduction step on bit BIT of array A.
+ * Results put into B.
+ * 
+ */
+static void
+qtree_onebit64(LONGLONG a[], int n, int nx, int ny, unsigned char b[], int bit)
+{
+int i, j, k;
+LONGLONG b0, b1, b2, b3;
+int s10, s00;
+
+	/*
+	 * use selected bit to get amount to shift
+	 */
+	b0 = ((LONGLONG) 1)<<bit;
+	b1 = b0<<1;
+	b2 = b0<<2;
+	b3 = b0<<3;
+	k = 0;							/* k is index of b[i/2,j/2]	*/
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of a[i,j]	*/
+		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] = (unsigned char) (( ( a[s10+1]     & b0)
+				   | ((a[s10  ]<<1) & b1)
+				   | ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> bit);
+			k += 1;
+			s00 += 2;
+			s10 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * row size is odd, do last element in row
+			 * s00+1,s10+1 are off edge
+			 */
+			b[k] = (unsigned char) (( ((a[s10  ]<<1) & b1)
+				   | ((a[s00  ]<<3) & b3) ) >> bit);
+			k += 1;
+		}
+	}
+	if (i < nx) {
+		/*
+		 * column size is odd, do last row
+		 * s10,s10+1 are off edge
+		 */
+		s00 = n*i;
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] = (unsigned char) (( ((a[s00+1]<<2) & b2)
+				   | ((a[s00  ]<<3) & b3) ) >> bit);
+			k += 1;
+			s00 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * both row and column size are odd, do corner element
+			 * s00+1, s10, s10+1 are off edge
+			 */
+			b[k] = (unsigned char) (( ((a[s00  ]<<3) & b3) ) >> bit);
+			k += 1;
+		}
+	}
+}
+
+/* ######################################################################### */
+/*
+ * do one quadtree reduction step on array a
+ * results put into b (which may be the same as a)
+ */
+static void
+qtree_reduce(unsigned char a[], int n, int nx, int ny, unsigned char b[])
+{
+int i, j, k;
+int s10, s00;
+
+	k = 0;							/* k is index of b[i/2,j/2]	*/
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of a[i,j]	*/
+		s10 = s00+n;				/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] =	(a[s10+1] != 0)
+				| ( (a[s10  ] != 0) << 1)
+				| ( (a[s00+1] != 0) << 2)
+				| ( (a[s00  ] != 0) << 3);
+			k += 1;
+			s00 += 2;
+			s10 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * row size is odd, do last element in row
+			 * s00+1,s10+1 are off edge
+			 */
+			b[k] =  ( (a[s10  ] != 0) << 1)
+				  | ( (a[s00  ] != 0) << 3);
+			k += 1;
+		}
+	}
+	if (i < nx) {
+		/*
+		 * column size is odd, do last row
+		 * s10,s10+1 are off edge
+		 */
+		s00 = n*i;
+		for (j = 0; j<ny-1; j += 2) {
+			b[k] =  ( (a[s00+1] != 0) << 2)
+				  | ( (a[s00  ] != 0) << 3);
+			k += 1;
+			s00 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * both row and column size are odd, do corner element
+			 * s00+1, s10, s10+1 are off edge
+			 */
+			b[k] = ( (a[s00  ] != 0) << 3);
+			k += 1;
+		}
+	}
+}
+
+/* ######################################################################### */
+static void
+write_bdirect(char *outfile, int a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
+{
+int i;
+
+	/*
+	 * Write the direct bitmap warning code
+	 */
+	output_nybble(outfile,0x0);
+	/*
+	 * Copy A to scratch array (again!), packing 4 bits/nybble
+	 */
+	qtree_onebit(a,n,nqx,nqy,scratch,bit);
+	/*
+	 * write to outfile
+	 */
+	for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
+		output_nybble(outfile,scratch[i]);
+	}
+}
+/* ######################################################################### */
+static void
+write_bdirect64(char *outfile, LONGLONG a[], int n,int nqx, int nqy, unsigned char scratch[], int bit)
+{
+int i;
+
+	/*
+	 * Write the direct bitmap warning code
+	 */
+	output_nybble(outfile,0x0);
+	/*
+	 * Copy A to scratch array (again!), packing 4 bits/nybble
+	 */
+	qtree_onebit64(a,n,nqx,nqy,scratch,bit);
+	/*
+	 * write to outfile
+	 */
+	for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
+		output_nybble(outfile,scratch[i]);
+	}
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/extern/fits_hdecompress.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/extern/fits_hdecompress.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/extern/fits_hdecompress.c	(revision 16632)
@@ -0,0 +1,1974 @@
+/*  #########################################################################
+These routines to apply the H-compress decompression algorithm to a 2-D Fits
+image were written by R. White at the STScI and were obtained from the STScI at
+http://www.stsci.edu/software/hcompress.html
+
+This source file is a concatination of the following sources files in the
+original distribution 
+  hinv.c 
+  hsmooth.c 
+  undigitize.c 
+  decode.c 
+  dodecode.c 
+  qtree_decode.c 
+  qread.c 
+  bit_input.c
+
+
+The following modifications have been made to the original code:
+
+  - commented out redundant "include" statements
+  - added the nextchar global variable 
+  - changed all the 'extern' declarations to 'static', since all the routines are in
+    the same source file
+  - changed the first parameter in decode (and in lower level routines from a file stream
+    to a char array
+  - modified the myread routine, and lower level byte reading routines,  to copy 
+    the input bytes to a char array, instead of reading them from a file stream
+  - changed the function declarations to the more modern ANSI C style
+  - changed calls to printf and perror to call the CFITSIO ffpmsg routine
+  - replace "exit" statements with "return" statements
+
+ ############################################################################  */
+ 
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+// EAM : dropping fitsio prototypes
+# define LONGLONG long long
+# define DATA_COMPRESSION_ERR 413  /* error in imcompress routines */
+# define DATA_DECOMPRESSION_ERR 414 /* error in imcompress routines */
+
+/* WDP added test to see if min and max are already defined */
+#ifndef min
+#define min(a,b)        (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b)        (((a)>(b))?(a):(b))
+#endif
+
+#define input_nybble(infile)	input_nbits(infile,4)
+
+static long nextchar;
+
+static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale);
+static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale);
+static int hinv(int a[], int nx, int ny, int smooth ,int scale);
+static int hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale);
+static void undigitize(int a[], int nx, int ny, int scale);
+static void undigitize64(LONGLONG a[], int nx, int ny, int scale);
+static void unshuffle(int a[], int n, int n2, int tmp[]);
+static void unshuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[]);
+static void hsmooth(int a[], int nxtop, int nytop, int ny, int scale);
+static void hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale);
+static void qread(unsigned char *infile,char *a, int n);
+static int  readint(unsigned char *infile);
+static LONGLONG readlonglong(unsigned char *infile);
+static int dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3]);
+static int dodecode64(unsigned char *infile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3]);
+static int qtree_decode(unsigned char *infile, int a[], int n, int nqx, int nqy, int nbitplanes);
+static int qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes);
+static void start_inputing_bits();
+static int input_bit(unsigned char *infile);
+static int input_nbits(unsigned char *infile, int n);
+
+static void qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[]);
+static void qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit);
+static void qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit);
+static void qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n);
+static void read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit);
+static void read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit);
+static int  input_huffman(unsigned char *infile);
+static int  myread(unsigned char *file, char buffer[], int n);
+
+/* ---------------------------------------------------------------------- */
+int fits_hdecompress(unsigned char *input, int smooth, int *a, int *ny, int *nx, 
+                     int *scale, int *status)
+{
+  /* 
+     decompress the input byte stream using the H-compress algorithm
+  
+   input  - input array of compressed bytes
+   a - pre-allocated array to hold the output uncompressed image
+   nx - returned X axis size
+   ny - returned Y axis size
+
+ NOTE: the nx and ny dimensions as defined within this code are reversed from
+ the usual FITS notation.  ny is the fastest varying dimension, which is
+ usually considered the X axis in the FITS image display
+
+  */
+int stat;
+
+  if (*status > 0) return(*status);
+
+	/* decode the input array */
+
+	stat = decode(input, a, nx, ny, scale);
+        *status = stat;
+	if (stat) return(*status);
+	
+	/*
+	 * Un-Digitize
+	 */
+	undigitize(a, *nx, *ny, *scale);
+
+	/*
+	 * Inverse H-transform
+	 */
+	stat = hinv(a, *nx, *ny, smooth, *scale);
+        *status = stat;
+	
+  return(*status);
+}
+/* ---------------------------------------------------------------------- */
+int fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *ny, int *nx, 
+                     int *scale, int *status)
+{
+  /* 
+     decompress the input byte stream using the H-compress algorithm
+  
+   input  - input array of compressed bytes
+   a - pre-allocated array to hold the output uncompressed image
+   nx - returned X axis size
+   ny - returned Y axis size
+
+ NOTE: the nx and ny dimensions as defined within this code are reversed from
+ the usual FITS notation.  ny is the fastest varying dimension, which is
+ usually considered the X axis in the FITS image display
+
+  */
+  int stat, *iarray, ii, nval;
+
+  if (*status > 0) return(*status);
+
+	/* decode the input array */
+
+	stat = decode64(input, a, nx, ny, scale);
+        *status = stat;
+	if (stat) return(*status);
+	
+	/*
+	 * Un-Digitize
+	 */
+	undigitize64(a, *nx, *ny, *scale);
+
+	/*
+	 * Inverse H-transform
+	 */
+	stat = hinv64(a, *nx, *ny, smooth, *scale);
+
+        *status = stat;
+	
+         /* pack the I*8 values back into an I*4 array */
+        iarray = (int *) a;
+	nval = (*nx) * (*ny);
+
+	for (ii = 0; ii < nval; ii++)
+	   iarray[ii] = (int) a[ii];	
+
+  return(*status);
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* hinv.c   Inverse H-transform of NX x NY integer image
+ *
+ * Programmer: R. White		Date: 23 July 1993
+ */
+
+/*  ############################################################################  */
+static int 
+hinv(int a[], int nx, int ny, int smooth ,int scale)
+/*
+int smooth;    0 for no smoothing, else smooth during inversion 
+int scale;     used if smoothing is specified 
+*/
+{
+int nmax, log2n, i, j, k;
+int nxtop,nytop,nxf,nyf,c;
+int oddx,oddy;
+int shift, bit0, bit1, bit2, mask0, mask1, mask2,
+	prnd0, prnd1, prnd2, nrnd0, nrnd1, nrnd2, lowbit0, lowbit1;
+int h0, hx, hy, hc;
+int s10, s00;
+int *tmp;
+
+	/*
+	 * log2n is log2 of max(nx,ny) rounded up to next power of 2
+	 */
+	nmax = (nx>ny) ? nx : ny;
+	log2n = (int) (log((float) nmax)/log(2.0)+0.5);
+	if ( nmax > (1<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */  
+	tmp = (int *) malloc(((nmax+1)/2)*sizeof(int));
+	if (tmp == (int *) NULL) {
+	  fprintf (stderr, "hinv: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * set up masks, rounding parameters
+	 */
+	shift  = 1;
+	bit0   = 1 << (log2n - 1);
+	bit1   = bit0 << 1;
+	bit2   = bit0 << 2;
+	mask0  = -bit0;
+	mask1  = mask0 << 1;
+	mask2  = mask0 << 2;
+	prnd0  = bit0 >> 1;
+	prnd1  = bit1 >> 1;
+	prnd2  = bit2 >> 1;
+	nrnd0  = prnd0 - 1;
+	nrnd1  = prnd1 - 1;
+	nrnd2  = prnd2 - 1;
+	/*
+	 * round h0 to multiple of bit2
+	 */
+	a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2;
+	/*
+	 * do log2n expansions
+	 *
+	 * We're indexing a as a 2-D array with dimensions (nx,ny).
+	 */
+	nxtop = 1;
+	nytop = 1;
+	nxf = nx;
+	nyf = ny;
+	c = 1<<log2n;
+	for (k = log2n-1; k>=0; k--) {
+		/*
+		 * this somewhat cryptic code generates the sequence
+		 * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n
+		 */
+		c = c>>1;
+		nxtop = nxtop<<1;
+		nytop = nytop<<1;
+		if (nxf <= c) { nxtop -= 1; } else { nxf -= c; }
+		if (nyf <= c) { nytop -= 1; } else { nyf -= c; }
+		/*
+		 * double shift and fix nrnd0 (because prnd0=0) on last pass
+		 */
+		if (k == 0) {
+			nrnd0 = 0;
+			shift = 2;
+		}
+		/*
+		 * unshuffle in each dimension to interleave coefficients
+		 */
+		for (i = 0; i<nxtop; i++) {
+			unshuffle(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			unshuffle(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * smooth by interpolating coefficients if SMOOTH != 0
+		 */
+		if (smooth) hsmooth(a,nxtop,nytop,ny,scale);
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = ny*i;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hx = a[s10  ];
+				hy = a[s00+1];
+				hc = a[s10+1];
+				/*
+				 * round hx and hy to multiple of bit1, hc to multiple of bit0
+				 * h0 is already a multiple of bit2
+				 */
+				hx = (hx + ((hx >= 0) ? prnd1 : nrnd1)) & mask1;
+				hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1;
+				hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0;
+				/*
+				 * propagate bit0 of hc to hx,hy
+				 */
+				lowbit0 = hc & bit0;
+				hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0);
+				hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0);
+				/*
+				 * Propagate bits 0 and 1 of hc,hx,hy to h0.
+				 * This could be simplified if we assume h0>0, but then
+				 * the inversion would not be lossless for images with
+				 * negative pixels.
+				 */
+				lowbit1 = (hc ^ hx ^ hy) & bit1;
+				h0 = (h0 >= 0)
+					? (h0 + lowbit0 - lowbit1)
+					: (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1)));
+				/*
+				 * Divide sums by 2 (4 last time)
+				 */
+				a[s10+1] = (h0 + hx + hy + hc) >> shift;
+				a[s10  ] = (h0 + hx - hy - hc) >> shift;
+				a[s00+1] = (h0 - hx + hy - hc) >> shift;
+				a[s00  ] = (h0 - hx - hy + hc) >> shift;
+				s00 += 2;
+				s10 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do last element in row if row length is odd
+				 * s00+1, s10+1 are off edge
+				 */
+				h0 = a[s00  ];
+				hx = a[s10  ];
+				hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1;
+				lowbit1 = hx & bit1;
+				h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1);
+				a[s10  ] = (h0 + hx) >> shift;
+				a[s00  ] = (h0 - hx) >> shift;
+			}
+		}
+		if (oddx) {
+			/*
+			 * do last row if column length is odd
+			 * s10, s10+1 are off edge
+			 */
+			s00 = ny*i;
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hy = a[s00+1];
+				hy = ((hy >= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1;
+				lowbit1 = hy & bit1;
+				h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1);
+				a[s00+1] = (h0 + hy) >> shift;
+				a[s00  ] = (h0 - hy) >> shift;
+				s00 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do corner element if both row and column lengths are odd
+				 * s00+1, s10, s10+1 are off edge
+				 */
+				h0 = a[s00  ];
+				a[s00  ] = h0 >> shift;
+			}
+		}
+		/*
+		 * divide all the masks and rounding values by 2
+		 */
+		bit2 = bit1;
+		bit1 = bit0;
+		bit0 = bit0 >> 1;
+		mask1 = mask0;
+		mask0 = mask0 >> 1;
+		prnd1 = prnd0;
+		prnd0 = prnd0 >> 1;
+		nrnd1 = nrnd0;
+		nrnd0 = prnd0 - 1;
+	}
+	free(tmp);
+	return(0);
+}
+/*  ############################################################################  */
+static int 
+hinv64(LONGLONG a[], int nx, int ny, int smooth ,int scale)
+/*
+int smooth;    0 for no smoothing, else smooth during inversion 
+int scale;     used if smoothing is specified 
+*/
+{
+int nmax, log2n, i, j, k;
+int nxtop,nytop,nxf,nyf,c;
+int oddx,oddy;
+int shift;
+LONGLONG mask0, mask1, mask2, prnd0, prnd1, prnd2, bit0, bit1, bit2;
+LONGLONG  nrnd0, nrnd1, nrnd2, lowbit0, lowbit1;
+LONGLONG h0, hx, hy, hc;
+int s10, s00;
+LONGLONG *tmp;
+
+	/*
+	 * log2n is log2 of max(nx,ny) rounded up to next power of 2
+	 */
+	nmax = (nx>ny) ? nx : ny;
+	log2n = (int) (log((float) nmax)/log(2.0)+0.5);
+	if ( nmax > (1<<log2n) ) {
+		log2n += 1;
+	}
+	/*
+	 * get temporary storage for shuffling elements
+	 */  
+	tmp = (LONGLONG *) malloc(((nmax+1)/2)*sizeof(LONGLONG));
+	if (tmp == (LONGLONG *) NULL) {
+		fprintf (stderr, "hinv64: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * set up masks, rounding parameters
+	 */
+	shift  = 1;
+	bit0   = ((LONGLONG) 1) << (log2n - 1);
+	bit1   = bit0 << 1;
+	bit2   = bit0 << 2;
+	mask0  = -bit0;
+	mask1  = mask0 << 1;
+	mask2  = mask0 << 2;
+	prnd0  = bit0 >> 1;
+	prnd1  = bit1 >> 1;
+	prnd2  = bit2 >> 1;
+	nrnd0  = prnd0 - 1;
+	nrnd1  = prnd1 - 1;
+	nrnd2  = prnd2 - 1;
+	/*
+	 * round h0 to multiple of bit2
+	 */
+	a[0] = (a[0] + ((a[0] >= 0) ? prnd2 : nrnd2)) & mask2;
+	/*
+	 * do log2n expansions
+	 *
+	 * We're indexing a as a 2-D array with dimensions (nx,ny).
+	 */
+	nxtop = 1;
+	nytop = 1;
+	nxf = nx;
+	nyf = ny;
+	c = 1<<log2n;
+	for (k = log2n-1; k>=0; k--) {
+		/*
+		 * this somewhat cryptic code generates the sequence
+		 * ntop[k-1] = (ntop[k]+1)/2, where ntop[log2n] = n
+		 */
+		c = c>>1;
+		nxtop = nxtop<<1;
+		nytop = nytop<<1;
+		if (nxf <= c) { nxtop -= 1; } else { nxf -= c; }
+		if (nyf <= c) { nytop -= 1; } else { nyf -= c; }
+		/*
+		 * double shift and fix nrnd0 (because prnd0=0) on last pass
+		 */
+		if (k == 0) {
+			nrnd0 = 0;
+			shift = 2;
+		}
+		/*
+		 * unshuffle in each dimension to interleave coefficients
+		 */
+		for (i = 0; i<nxtop; i++) {
+			unshuffle64(&a[ny*i],nytop,1,tmp);
+		}
+		for (j = 0; j<nytop; j++) {
+			unshuffle64(&a[j],nxtop,ny,tmp);
+		}
+		/*
+		 * smooth by interpolating coefficients if SMOOTH != 0
+		 */
+		if (smooth) hsmooth64(a,nxtop,nytop,ny,scale);
+		oddx = nxtop % 2;
+		oddy = nytop % 2;
+		for (i = 0; i<nxtop-oddx; i += 2) {
+			s00 = ny*i;				/* s00 is index of a[i,j]	*/
+			s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hx = a[s10  ];
+				hy = a[s00+1];
+				hc = a[s10+1];
+				/*
+				 * round hx and hy to multiple of bit1, hc to multiple of bit0
+				 * h0 is already a multiple of bit2
+				 */
+				hx = (hx + ((hx >= 0) ? prnd1 : nrnd1)) & mask1;
+				hy = (hy + ((hy >= 0) ? prnd1 : nrnd1)) & mask1;
+				hc = (hc + ((hc >= 0) ? prnd0 : nrnd0)) & mask0;
+				/*
+				 * propagate bit0 of hc to hx,hy
+				 */
+				lowbit0 = hc & bit0;
+				hx = (hx >= 0) ? (hx - lowbit0) : (hx + lowbit0);
+				hy = (hy >= 0) ? (hy - lowbit0) : (hy + lowbit0);
+				/*
+				 * Propagate bits 0 and 1 of hc,hx,hy to h0.
+				 * This could be simplified if we assume h0>0, but then
+				 * the inversion would not be lossless for images with
+				 * negative pixels.
+				 */
+				lowbit1 = (hc ^ hx ^ hy) & bit1;
+				h0 = (h0 >= 0)
+					? (h0 + lowbit0 - lowbit1)
+					: (h0 + ((lowbit0 == 0) ? lowbit1 : (lowbit0-lowbit1)));
+				/*
+				 * Divide sums by 2 (4 last time)
+				 */
+				a[s10+1] = (h0 + hx + hy + hc) >> shift;
+				a[s10  ] = (h0 + hx - hy - hc) >> shift;
+				a[s00+1] = (h0 - hx + hy - hc) >> shift;
+				a[s00  ] = (h0 - hx - hy + hc) >> shift;
+				s00 += 2;
+				s10 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do last element in row if row length is odd
+				 * s00+1, s10+1 are off edge
+				 */
+				h0 = a[s00  ];
+				hx = a[s10  ];
+				hx = ((hx >= 0) ? (hx+prnd1) : (hx+nrnd1)) & mask1;
+				lowbit1 = hx & bit1;
+				h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1);
+				a[s10  ] = (h0 + hx) >> shift;
+				a[s00  ] = (h0 - hx) >> shift;
+			}
+		}
+		if (oddx) {
+			/*
+			 * do last row if column length is odd
+			 * s10, s10+1 are off edge
+			 */
+			s00 = ny*i;
+			for (j = 0; j<nytop-oddy; j += 2) {
+				h0 = a[s00  ];
+				hy = a[s00+1];
+				hy = ((hy >= 0) ? (hy+prnd1) : (hy+nrnd1)) & mask1;
+				lowbit1 = hy & bit1;
+				h0 = (h0 >= 0) ? (h0 - lowbit1) : (h0 + lowbit1);
+				a[s00+1] = (h0 + hy) >> shift;
+				a[s00  ] = (h0 - hy) >> shift;
+				s00 += 2;
+			}
+			if (oddy) {
+				/*
+				 * do corner element if both row and column lengths are odd
+				 * s00+1, s10, s10+1 are off edge
+				 */
+				h0 = a[s00  ];
+				a[s00  ] = h0 >> shift;
+			}
+		}
+		/*
+		 * divide all the masks and rounding values by 2
+		 */
+		bit2 = bit1;
+		bit1 = bit0;
+		bit0 = bit0 >> 1;
+		mask1 = mask0;
+		mask0 = mask0 >> 1;
+		prnd1 = prnd0;
+		prnd0 = prnd0 >> 1;
+		nrnd1 = nrnd0;
+		nrnd0 = prnd0 - 1;
+	}
+	free(tmp);
+	return(0);
+}
+
+/*  ############################################################################  */
+static void
+unshuffle(int a[], int n, int n2, int tmp[])
+/*
+int a[];	 array to shuffle					
+int n;		 number of elements to shuffle	
+int n2;		 second dimension					
+int tmp[];	 scratch storage					
+*/
+{
+int i;
+int nhalf;
+int *p1, *p2, *pt;
+ 
+	/*
+	 * copy 2nd half of array to tmp
+	 */
+	nhalf = (n+1)>>1;
+	pt = tmp;
+	p1 = &a[n2*nhalf];				/* pointer to a[i]			*/
+	for (i=nhalf; i<n; i++) {
+		*pt = *p1;
+		p1 += n2;
+		pt += 1;
+	}
+	/*
+	 * distribute 1st half of array to even elements
+	 */
+	p2 = &a[ n2*(nhalf-1) ];		/* pointer to a[i]			*/
+	p1 = &a[(n2*(nhalf-1))<<1];		/* pointer to a[2*i]		*/
+	for (i=nhalf-1; i >= 0; i--) {
+		*p1 = *p2;
+		p2 -= n2;
+		p1 -= (n2+n2);
+	}
+	/*
+	 * now distribute 2nd half of array (in tmp) to odd elements
+	 */
+	pt = tmp;
+	p1 = &a[n2];					/* pointer to a[i]			*/
+	for (i=1; i<n; i += 2) {
+		*p1 = *pt;
+		p1 += (n2+n2);
+		pt += 1;
+	}
+}
+/*  ############################################################################  */
+static void
+unshuffle64(LONGLONG a[], int n, int n2, LONGLONG tmp[])
+/*
+LONGLONG a[];	 array to shuffle					
+int n;		 number of elements to shuffle	
+int n2;		 second dimension					
+LONGLONG tmp[];	 scratch storage					
+*/
+{
+int i;
+int nhalf;
+LONGLONG *p1, *p2, *pt;
+ 
+	/*
+	 * copy 2nd half of array to tmp
+	 */
+	nhalf = (n+1)>>1;
+	pt = tmp;
+	p1 = &a[n2*nhalf];				/* pointer to a[i]			*/
+	for (i=nhalf; i<n; i++) {
+		*pt = *p1;
+		p1 += n2;
+		pt += 1;
+	}
+	/*
+	 * distribute 1st half of array to even elements
+	 */
+	p2 = &a[ n2*(nhalf-1) ];		/* pointer to a[i]			*/
+	p1 = &a[(n2*(nhalf-1))<<1];		/* pointer to a[2*i]		*/
+	for (i=nhalf-1; i >= 0; i--) {
+		*p1 = *p2;
+		p2 -= n2;
+		p1 -= (n2+n2);
+	}
+	/*
+	 * now distribute 2nd half of array (in tmp) to odd elements
+	 */
+	pt = tmp;
+	p1 = &a[n2];					/* pointer to a[i]			*/
+	for (i=1; i<n; i += 2) {
+		*p1 = *pt;
+		p1 += (n2+n2);
+		pt += 1;
+	}
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* hsmooth.c	Smooth H-transform image by adjusting coefficients toward
+ *				interpolated values
+ *
+ * Programmer: R. White		Date: 13 April 1992
+ */
+
+/*  ############################################################################  */
+static void 
+hsmooth(int a[], int nxtop, int nytop, int ny, int scale)
+/*
+int a[];			 array of H-transform coefficients		
+int nxtop,nytop;	 size of coefficient block to use			
+int ny;				 actual 1st dimension of array			
+int scale;			 truncation scale factor that was used	
+*/
+{
+int i, j;
+int ny2, s10, s00, diff, dmax, dmin, s, smax;
+int hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2;
+int m1,m2;
+
+	/*
+	 * Maximum change in coefficients is determined by scale factor.
+	 * Since we rounded during division (see digitize.c), the biggest
+	 * permitted change is scale/2.
+	 */
+	smax = (scale >> 1);
+	if (smax <= 0) return;
+	ny2 = ny << 1;
+	/*
+	 * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which
+	 * only (nxtop,nytop) are used.  The coefficients on the edge of the
+	 * array are not adjusted (which is why the loops below start at 2
+	 * instead of 0 and end at nxtop-2 instead of nxtop.)
+	 */
+	/*
+	 * Adjust x difference hx
+	 */
+	for (i = 2; i<nxtop-2; i += 2) {
+		s00 = ny*i;				/* s00 is index of a[i,j]	*/
+		s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<nytop; j += 2) {
+			/*
+			 * hp is h0 (mean value) in next x zone, hm is h0 in previous x zone
+			 */
+			hm = a[s00-ny2];
+			h0 = a[s00];
+			hp = a[s00+ny2];
+			/*
+			 * diff = 8 * hx slope that would match h0 in neighboring zones
+			 */
+			diff = hp-hm;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hx.
+			 * note dmax>=0, dmin<=0.
+			 */
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				/*
+				 * Compute change in slope limited to range +/- smax.
+				 * Careful with rounding negative numbers when using
+				 * shift for divide by 8.
+				 */
+				s = diff-(a[s10]<<3);
+				s = (s>=0) ? (s>>3) : ((s+7)>>3) ;
+				s = max( min(s, smax), -smax);
+				a[s10] = a[s10]+s;
+			}
+			s00 += 2;
+			s10 += 2;
+		}
+	}
+	/*
+	 * Adjust y difference hy
+	 */
+	for (i = 0; i<nxtop; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			hm = a[s00-2];
+			h0 = a[s00];
+			hp = a[s00+2];
+			diff = hp-hm;
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				s = diff-(a[s00+1]<<3);
+				s = (s>=0) ? (s>>3) : ((s+7)>>3) ;
+				s = max( min(s, smax), -smax);
+				a[s00+1] = a[s00+1]+s;
+			}
+			s00 += 2;
+			s10 += 2;
+		}
+	}
+	/*
+	 * Adjust curvature difference hc
+	 */
+	for (i = 2; i<nxtop-2; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			/*
+			 * ------------------    y
+			 * | hmp |    | hpp |    |
+			 * ------------------    |
+			 * |     | h0 |     |    |
+			 * ------------------    -------x
+			 * | hmm |    | hpm |
+			 * ------------------
+			 */
+			hmm = a[s00-ny2-2];
+			hpm = a[s00+ny2-2];
+			hmp = a[s00-ny2+2];
+			hpp = a[s00+ny2+2];
+			h0  = a[s00];
+			/*
+			 * diff = 64 * hc value that would match h0 in neighboring zones
+			 */
+			diff = hpp + hmm - hmp - hpm;
+			/*
+			 * 2 times x,y slopes in this zone
+			 */
+			hx2 = a[s10  ]<<1;
+			hy2 = a[s00+1]<<1;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			m1 = min(max(hpp-h0,0)-hx2-hy2, max(h0-hpm,0)+hx2-hy2);
+			m2 = min(max(h0-hmp,0)-hx2+hy2, max(hmm-h0,0)+hx2+hy2);
+			dmax = min(m1,m2) << 4;
+			m1 = max(min(hpp-h0,0)-hx2-hy2, min(h0-hpm,0)+hx2-hy2);
+			m2 = max(min(h0-hmp,0)-hx2+hy2, min(hmm-h0,0)+hx2+hy2);
+			dmin = max(m1,m2) << 4;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hc.
+			 * note dmax>=0, dmin<=0.
+			 */
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				/*
+				 * Compute change in slope limited to range +/- smax.
+				 * Careful with rounding negative numbers when using
+				 * shift for divide by 64.
+				 */
+				s = diff-(a[s10+1]<<6);
+				s = (s>=0) ? (s>>6) : ((s+63)>>6) ;
+				s = max( min(s, smax), -smax);
+				a[s10+1] = a[s10+1]+s;
+			}
+			s00 += 2;
+			s10 += 2;
+		}
+	}
+}
+/*  ############################################################################  */
+static void 
+hsmooth64(LONGLONG a[], int nxtop, int nytop, int ny, int scale)
+/*
+LONGLONG a[];			 array of H-transform coefficients		
+int nxtop,nytop;	 size of coefficient block to use			
+int ny;				 actual 1st dimension of array			
+int scale;			 truncation scale factor that was used	
+*/
+{
+int i, j;
+int ny2, s10, s00;
+LONGLONG hm, h0, hp, hmm, hpm, hmp, hpp, hx2, hy2, diff, dmax, dmin, s, smax, m1, m2;
+
+	/*
+	 * Maximum change in coefficients is determined by scale factor.
+	 * Since we rounded during division (see digitize.c), the biggest
+	 * permitted change is scale/2.
+	 */
+	smax = (scale >> 1);
+	if (smax <= 0) return;
+	ny2 = ny << 1;
+	/*
+	 * We're indexing a as a 2-D array with dimensions (nxtop,ny) of which
+	 * only (nxtop,nytop) are used.  The coefficients on the edge of the
+	 * array are not adjusted (which is why the loops below start at 2
+	 * instead of 0 and end at nxtop-2 instead of nxtop.)
+	 */
+	/*
+	 * Adjust x difference hx
+	 */
+	for (i = 2; i<nxtop-2; i += 2) {
+		s00 = ny*i;				/* s00 is index of a[i,j]	*/
+		s10 = s00+ny;			/* s10 is index of a[i+1,j]	*/
+		for (j = 0; j<nytop; j += 2) {
+			/*
+			 * hp is h0 (mean value) in next x zone, hm is h0 in previous x zone
+			 */
+			hm = a[s00-ny2];
+			h0 = a[s00];
+			hp = a[s00+ny2];
+			/*
+			 * diff = 8 * hx slope that would match h0 in neighboring zones
+			 */
+			diff = hp-hm;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hx.
+			 * note dmax>=0, dmin<=0.
+			 */
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				/*
+				 * Compute change in slope limited to range +/- smax.
+				 * Careful with rounding negative numbers when using
+				 * shift for divide by 8.
+				 */
+				s = diff-(a[s10]<<3);
+				s = (s>=0) ? (s>>3) : ((s+7)>>3) ;
+				s = max( min(s, smax), -smax);
+				a[s10] = a[s10]+s;
+			}
+			s00 += 2;
+			s10 += 2;
+		}
+	}
+	/*
+	 * Adjust y difference hy
+	 */
+	for (i = 0; i<nxtop; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			hm = a[s00-2];
+			h0 = a[s00];
+			hp = a[s00+2];
+			diff = hp-hm;
+			dmax = max( min( (hp-h0), (h0-hm) ), 0 ) << 2;
+			dmin = min( max( (hp-h0), (h0-hm) ), 0 ) << 2;
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				s = diff-(a[s00+1]<<3);
+				s = (s>=0) ? (s>>3) : ((s+7)>>3) ;
+				s = max( min(s, smax), -smax);
+				a[s00+1] = a[s00+1]+s;
+			}
+			s00 += 2;
+			s10 += 2;
+		}
+	}
+	/*
+	 * Adjust curvature difference hc
+	 */
+	for (i = 2; i<nxtop-2; i += 2) {
+		s00 = ny*i+2;
+		s10 = s00+ny;
+		for (j = 2; j<nytop-2; j += 2) {
+			/*
+			 * ------------------    y
+			 * | hmp |    | hpp |    |
+			 * ------------------    |
+			 * |     | h0 |     |    |
+			 * ------------------    -------x
+			 * | hmm |    | hpm |
+			 * ------------------
+			 */
+			hmm = a[s00-ny2-2];
+			hpm = a[s00+ny2-2];
+			hmp = a[s00-ny2+2];
+			hpp = a[s00+ny2+2];
+			h0  = a[s00];
+			/*
+			 * diff = 64 * hc value that would match h0 in neighboring zones
+			 */
+			diff = hpp + hmm - hmp - hpm;
+			/*
+			 * 2 times x,y slopes in this zone
+			 */
+			hx2 = a[s10  ]<<1;
+			hy2 = a[s00+1]<<1;
+			/*
+			 * monotonicity constraints on diff
+			 */
+			m1 = min(max(hpp-h0,0)-hx2-hy2, max(h0-hpm,0)+hx2-hy2);
+			m2 = min(max(h0-hmp,0)-hx2+hy2, max(hmm-h0,0)+hx2+hy2);
+			dmax = min(m1,m2) << 4;
+			m1 = max(min(hpp-h0,0)-hx2-hy2, min(h0-hpm,0)+hx2-hy2);
+			m2 = max(min(h0-hmp,0)-hx2+hy2, min(hmm-h0,0)+hx2+hy2);
+			dmin = max(m1,m2) << 4;
+			/*
+			 * if monotonicity would set slope = 0 then don't change hc.
+			 * note dmax>=0, dmin<=0.
+			 */
+			if (dmin < dmax) {
+				diff = max( min(diff, dmax), dmin);
+				/*
+				 * Compute change in slope limited to range +/- smax.
+				 * Careful with rounding negative numbers when using
+				 * shift for divide by 64.
+				 */
+				s = diff-(a[s10+1]<<6);
+				s = (s>=0) ? (s>>6) : ((s+63)>>6) ;
+				s = max( min(s, smax), -smax);
+				a[s10+1] = a[s10+1]+s;
+			}
+			s00 += 2;
+			s10 += 2;
+		}
+	}
+}
+
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* undigitize.c		undigitize H-transform
+ *
+ * Programmer: R. White		Date: 9 May 1991
+ */
+
+/*  ############################################################################  */
+static void
+undigitize(int a[], int nx, int ny, int scale)
+{
+int *p;
+
+	/*
+	 * multiply by scale
+	 */
+	if (scale <= 1) return;
+	for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale;
+}
+/*  ############################################################################  */
+static void
+undigitize64(LONGLONG a[], int nx, int ny, int scale)
+{
+LONGLONG *p, scale64;
+
+	/*
+	 * multiply by scale
+	 */
+	if (scale <= 1) return;
+	scale64 = (LONGLONG) scale;   /* use a 64-bit int for efficiency in the big loop */
+	
+	for (p=a; p <= &a[nx*ny-1]; p++) *p = (*p)*scale64;
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* decode.c		read codes from infile and construct array
+ *
+ * Programmer: R. White		Date: 2 February 1994
+ */
+
+
+static char code_magic[2] = { (char)0xDD, (char)0x99 };
+
+/*  ############################################################################  */
+static int decode(unsigned char *infile, int *a, int *nx, int *ny, int *scale)
+/*
+char *infile;				 input file							
+int  *a;				 address of output array [nx][ny]		
+int  *nx,*ny;				 size of output array					
+int  *scale;				 scale factor for digitization		
+*/
+{
+LONGLONG sumall;
+int nel, stat;
+unsigned char nbitplanes[3];
+char tmagic[2];
+
+	/* initialize the byte read position to the beginning of the array */;
+	nextchar = 0;
+	
+	/*
+	 * File starts either with special 2-byte magic code or with
+	 * FITS keyword "SIMPLE  ="
+	 */
+	qread(infile, tmagic, sizeof(tmagic));
+	/*
+	 * check for correct magic code value
+	 */
+	if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) {
+		fprintf (stderr, "bad file format");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	*nx =readint(infile);				/* x size of image			*/
+	*ny =readint(infile);				/* y size of image			*/
+	*scale=readint(infile);				/* scale factor for digitization	*/
+	
+	nel = (*nx) * (*ny);
+
+	/* sum of all pixels	*/
+	sumall=readlonglong(infile);
+	/* # bits in quadrants	*/
+
+	qread(infile, (char *) nbitplanes, sizeof(nbitplanes));
+
+	stat = dodecode(infile, a, *nx, *ny, nbitplanes);
+	/*
+	 * put sum of all pixels back into pixel 0
+	 */
+	a[0] = (int) sumall;
+	return(stat);
+}
+/*  ############################################################################  */
+static int decode64(unsigned char *infile, LONGLONG *a, int *nx, int *ny, int *scale)
+/*
+char *infile;				 input file							
+LONGLONG  *a;				 address of output array [nx][ny]		
+int  *nx,*ny;				 size of output array					
+int  *scale;				 scale factor for digitization		
+*/
+{
+int nel, stat;
+LONGLONG sumall;
+unsigned char nbitplanes[3];
+char tmagic[2];
+
+	/* initialize the byte read position to the beginning of the array */;
+	nextchar = 0;
+	
+	/*
+	 * File starts either with special 2-byte magic code or with
+	 * FITS keyword "SIMPLE  ="
+	 */
+	qread(infile, tmagic, sizeof(tmagic));
+	/*
+	 * check for correct magic code value
+	 */
+	if (memcmp(tmagic,code_magic,sizeof(code_magic)) != 0) {
+		fprintf (stderr, "bad file format");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	*nx =readint(infile);				/* x size of image			*/
+	*ny =readint(infile);				/* y size of image			*/
+	*scale=readint(infile);				/* scale factor for digitization	*/
+	
+	nel = (*nx) * (*ny);
+
+	/* sum of all pixels	*/
+	sumall=readlonglong(infile);
+	/* # bits in quadrants	*/
+
+	qread(infile, (char *) nbitplanes, sizeof(nbitplanes));
+
+	stat = dodecode64(infile, a, *nx, *ny, nbitplanes);
+	/*
+	 * put sum of all pixels back into pixel 0
+	 */
+	a[0] = sumall;
+
+	return(stat);
+}
+
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* dodecode.c	Decode stream of characters on infile and return array
+ *
+ * This version encodes the different quadrants separately
+ *
+ * Programmer: R. White		Date: 9 May 1991
+ */
+
+/*  ############################################################################  */
+static int
+dodecode(unsigned char *infile, int a[], int nx, int ny, unsigned char nbitplanes[3])
+
+/* int a[];					 			
+   int nx,ny;					 Array dimensions are [nx][ny]		
+   unsigned char nbitplanes[3];		 Number of bit planes in quadrants
+*/
+{
+int i, nel, nx2, ny2, stat;
+
+	nel = nx*ny;
+	nx2 = (nx+1)/2;
+	ny2 = (ny+1)/2;
+
+	/*
+	 * initialize a to zero
+	 */
+	for (i=0; i<nel; i++) a[i] = 0;
+	/*
+	 * Initialize bit input
+	 */
+	start_inputing_bits();
+	/*
+	 * read bit planes for each quadrant
+	 */
+	stat = qtree_decode(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
+        if (stat) return(stat);
+	
+	/*
+	 * make sure there is an EOF symbol (nybble=0) at end
+	 */
+	if (input_nybble(infile) != 0) {
+		fprintf (stderr, "dodecode: bad bit plane values");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now get the sign bits
+	 * Re-initialize bit input
+	 */
+	start_inputing_bits();
+	for (i=0; i<nel; i++) {
+		if (a[i] != 0) {
+			if (input_bit(infile) != 0) a[i] = -a[i];
+		}
+	}
+	return(0);
+}
+/*  ############################################################################  */
+static int
+dodecode64(unsigned char *infile, LONGLONG a[], int nx, int ny, unsigned char nbitplanes[3])
+
+/* LONGLONG a[];					 			
+   int nx,ny;					 Array dimensions are [nx][ny]		
+   unsigned char nbitplanes[3];		 Number of bit planes in quadrants
+*/
+{
+int i, nel, nx2, ny2, stat;
+
+	nel = nx*ny;
+	nx2 = (nx+1)/2;
+	ny2 = (ny+1)/2;
+
+	/*
+	 * initialize a to zero
+	 */
+	for (i=0; i<nel; i++) a[i] = 0;
+	/*
+	 * Initialize bit input
+	 */
+	start_inputing_bits();
+	/*
+	 * read bit planes for each quadrant
+	 */
+	stat = qtree_decode64(infile, &a[0],          ny, nx2,  ny2,  nbitplanes[0]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode64(infile, &a[ny2],        ny, nx2,  ny/2, nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode64(infile, &a[ny*nx2],     ny, nx/2, ny2,  nbitplanes[1]);
+        if (stat) return(stat);
+	
+	stat = qtree_decode64(infile, &a[ny*nx2+ny2], ny, nx/2, ny/2, nbitplanes[2]);
+        if (stat) return(stat);
+	
+	/*
+	 * make sure there is an EOF symbol (nybble=0) at end
+	 */
+	if (input_nybble(infile) != 0) {
+		fprintf (stderr, "dodecode64: bad bit plane values");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now get the sign bits
+	 * Re-initialize bit input
+	 */
+	start_inputing_bits();
+	for (i=0; i<nel; i++) {
+		if (a[i] != 0) {
+			if (input_bit(infile) != 0) a[i] = -a[i];
+		}
+	}
+	return(0);
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* qtree_decode.c	Read stream of codes from infile and construct bit planes
+ *					in quadrant of 2-D array using binary quadtree coding
+ *
+ * Programmer: R. White		Date: 7 May 1991
+ */
+
+/*  ############################################################################  */
+static int
+qtree_decode(unsigned char *infile, int a[], int n, int nqx, int nqy, int nbitplanes)
+
+/*
+char *infile;
+int a[];				 a is 2-D array with dimensions (n,n)	
+int n;					 length of full row in a				
+int nqx;				 partial length of row to decode		
+int nqy;				 partial length of column (<=n)		
+int nbitplanes;				 number of bitplanes to decode		
+*/
+{
+int log2n, k, bit, b, nqmax;
+int nx,ny,nfx,nfy,c;
+int nqx2, nqy2;
+unsigned char *scratch;
+
+	/*
+	 * log2n is log2 of max(nqx,nqy) rounded up to next power of 2
+	 */
+	nqmax = (nqx>nqy) ? nqx : nqy;
+	log2n = (int) (log((float) nqmax)/log(2.0)+0.5);
+	if (nqmax > (1<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * allocate scratch array for working space
+	 */
+	nqx2=(nqx+1)/2;
+	nqy2=(nqy+1)/2;
+	scratch = (unsigned char *) malloc(nqx2*nqy2);
+	if (scratch == (unsigned char *) NULL) {
+		fprintf (stderr, "qtree_decode: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now decode each bit plane, starting at the top
+	 * A is assumed to be initialized to zero
+	 */
+	for (bit = nbitplanes-1; bit >= 0; bit--) {
+		/*
+		 * Was bitplane was quadtree-coded or written directly?
+		 */
+		b = input_nybble(infile);
+
+		if(b == 0) {
+			/*
+			 * bit map was written directly
+			 */
+			read_bdirect(infile,a,n,nqx,nqy,scratch,bit);
+		} else if (b != 0xf) {
+			fprintf (stderr, "qtree_decode: bad format code");
+			return(DATA_DECOMPRESSION_ERR);
+		} else {
+			/*
+			 * bitmap was quadtree-coded, do log2n expansions
+			 *
+			 * read first code
+			 */
+			scratch[0] = input_huffman(infile);
+			/*
+			 * now do log2n expansions, reading codes from file as necessary
+			 */
+			nx = 1;
+			ny = 1;
+			nfx = nqx;
+			nfy = nqy;
+			c = 1<<log2n;
+			for (k = 1; k<log2n; k++) {
+				/*
+				 * this somewhat cryptic code generates the sequence
+				 * n[k-1] = (n[k]+1)/2 where n[log2n]=nqx or nqy
+				 */
+				c = c>>1;
+				nx = nx<<1;
+				ny = ny<<1;
+				if (nfx <= c) { nx -= 1; } else { nfx -= c; }
+				if (nfy <= c) { ny -= 1; } else { nfy -= c; }
+				qtree_expand(infile,scratch,nx,ny,scratch);
+			}
+			/*
+			 * now copy last set of 4-bit codes to bitplane bit of array a
+			 */
+			qtree_bitins(scratch,nqx,nqy,a,n,bit);
+		}
+	}
+	free(scratch);
+	return(0);
+}
+/*  ############################################################################  */
+static int
+qtree_decode64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, int nbitplanes)
+
+/*
+char *infile;
+LONGLONG a[];				 a is 2-D array with dimensions (n,n)	
+int n;					 length of full row in a				
+int nqx;				 partial length of row to decode		
+int nqy;				 partial length of column (<=n)		
+int nbitplanes;				 number of bitplanes to decode		
+*/
+{
+int log2n, k, bit, b, nqmax;
+int nx,ny,nfx,nfy,c;
+int nqx2, nqy2;
+unsigned char *scratch;
+
+	/*
+	 * log2n is log2 of max(nqx,nqy) rounded up to next power of 2
+	 */
+	nqmax = (nqx>nqy) ? nqx : nqy;
+	log2n = (int) (log((float) nqmax)/log(2.0)+0.5);
+	if (nqmax > (1<<log2n)) {
+		log2n += 1;
+	}
+	/*
+	 * allocate scratch array for working space
+	 */
+	nqx2=(nqx+1)/2;
+	nqy2=(nqy+1)/2;
+	scratch = (unsigned char *) malloc(nqx2*nqy2);
+	if (scratch == (unsigned char *) NULL) {
+		fprintf (stderr, "qtree_decode64: insufficient memory");
+		return(DATA_DECOMPRESSION_ERR);
+	}
+	/*
+	 * now decode each bit plane, starting at the top
+	 * A is assumed to be initialized to zero
+	 */
+	for (bit = nbitplanes-1; bit >= 0; bit--) {
+		/*
+		 * Was bitplane was quadtree-coded or written directly?
+		 */
+		b = input_nybble(infile);
+
+		if(b == 0) {
+			/*
+			 * bit map was written directly
+			 */
+			read_bdirect64(infile,a,n,nqx,nqy,scratch,bit);
+		} else if (b != 0xf) {
+			fprintf (stderr, "qtree_decode64: bad format code");
+			return(DATA_DECOMPRESSION_ERR);
+		} else {
+			/*
+			 * bitmap was quadtree-coded, do log2n expansions
+			 *
+			 * read first code
+			 */
+			scratch[0] = input_huffman(infile);
+			/*
+			 * now do log2n expansions, reading codes from file as necessary
+			 */
+			nx = 1;
+			ny = 1;
+			nfx = nqx;
+			nfy = nqy;
+			c = 1<<log2n;
+			for (k = 1; k<log2n; k++) {
+				/*
+				 * this somewhat cryptic code generates the sequence
+				 * n[k-1] = (n[k]+1)/2 where n[log2n]=nqx or nqy
+				 */
+				c = c>>1;
+				nx = nx<<1;
+				ny = ny<<1;
+				if (nfx <= c) { nx -= 1; } else { nfx -= c; }
+				if (nfy <= c) { ny -= 1; } else { nfy -= c; }
+				qtree_expand(infile,scratch,nx,ny,scratch);
+			}
+			/*
+			 * now copy last set of 4-bit codes to bitplane bit of array a
+			 */
+			qtree_bitins64(scratch,nqx,nqy,a,n,bit);
+		}
+	}
+	free(scratch);
+	return(0);
+}
+
+
+/*  ############################################################################  */
+/*
+ * do one quadtree expansion step on array a[(nqx+1)/2,(nqy+1)/2]
+ * results put into b[nqx,nqy] (which may be the same as a)
+ */
+static void
+qtree_expand(unsigned char *infile, unsigned char a[], int nx, int ny, unsigned char b[])
+{
+int i;
+
+	/*
+	 * first copy a to b, expanding each 4-bit value
+	 */
+	qtree_copy(a,nx,ny,b,ny);
+	/*
+	 * now read new 4-bit values into b for each non-zero element
+	 */
+	for (i = nx*ny-1; i >= 0; i--) {
+		if (b[i] != 0) b[i] = input_huffman(infile);
+	}
+}
+
+/*  ############################################################################  */
+/*
+ * copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding
+ * each value to 2x2 pixels
+ * a,b may be same array
+ */
+static void
+qtree_copy(unsigned char a[], int nx, int ny, unsigned char b[], int n)
+/*   int n;		declared y dimension of b */
+{
+int i, j, k, nx2, ny2;
+int s00, s10;
+
+	/*
+	 * first copy 4-bit values to b
+	 * start at end in case a,b are same array
+	 */
+	nx2 = (nx+1)/2;
+	ny2 = (ny+1)/2;
+	k = ny2*(nx2-1)+ny2-1;			/* k   is index of a[i,j]			*/
+	for (i = nx2-1; i >= 0; i--) {
+		s00 = 2*(n*i+ny2-1);		/* s00 is index of b[2*i,2*j]		*/
+		for (j = ny2-1; j >= 0; j--) {
+			b[s00] = a[k];
+			k -= 1;
+			s00 -= 2;
+		}
+	}
+	/*
+	 * now expand each 2x2 block
+	 */
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of b[i,j]	*/
+		s10 = s00+n;				/* s10 is index of b[i+1,j]	*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[s10+1] =  b[s00]     & 1;
+			b[s10  ] = (b[s00]>>1) & 1;
+			b[s00+1] = (b[s00]>>2) & 1;
+			b[s00  ] = (b[s00]>>3) & 1;
+			s00 += 2;
+			s10 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * row size is odd, do last element in row
+			 * s00+1, s10+1 are off edge
+			 */
+			b[s10  ] = (b[s00]>>1) & 1;
+			b[s00  ] = (b[s00]>>3) & 1;
+		}
+	}
+	if (i < nx) {
+		/*
+		 * column size is odd, do last row
+		 * s10, s10+1 are off edge
+		 */
+		s00 = n*i;
+		for (j = 0; j<ny-1; j += 2) {
+			b[s00+1] = (b[s00]>>2) & 1;
+			b[s00  ] = (b[s00]>>3) & 1;
+			s00 += 2;
+		}
+		if (j < ny) {
+			/*
+			 * both row and column size are odd, do corner element
+			 * s00+1, s10, s10+1 are off edge
+			 */
+			b[s00  ] = (b[s00]>>3) & 1;
+		}
+	}
+}
+
+/*  ############################################################################  */
+/*
+ * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding
+ * each value to 2x2 pixels and inserting into bitplane BIT of B.
+ * A,B may NOT be same array (it wouldn't make sense to be inserting
+ * bits into the same array anyway.)
+ */
+static void
+qtree_bitins(unsigned char a[], int nx, int ny, int b[], int n, int bit)
+/*
+   int n;		declared y dimension of b
+*/
+{
+int i, j, k;
+int s00, s10;
+
+	/*
+	 * expand each 2x2 block
+	 */
+	k = 0;							/* k   is index of a[i/2,j/2]	*/
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of b[i,j]		*/
+		s10 = s00+n;				/* s10 is index of b[i+1,j]		*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[s10+1] |= ( a[k]     & 1) << bit;
+			b[s10  ] |= ((a[k]>>1) & 1) << bit;
+			b[s00+1] |= ((a[k]>>2) & 1) << bit;
+			b[s00  ] |= ((a[k]>>3) & 1) << bit;
+			s00 += 2;
+			s10 += 2;
+			k += 1;
+		}
+		if (j < ny) {
+			/*
+			 * row size is odd, do last element in row
+			 * s00+1, s10+1 are off edge
+			 */
+			b[s10  ] |= ((a[k]>>1) & 1) << bit;
+			b[s00  ] |= ((a[k]>>3) & 1) << bit;
+			k += 1;
+		}
+	}
+	if (i < nx) {
+		/*
+		 * column size is odd, do last row
+		 * s10, s10+1 are off edge
+		 */
+		s00 = n*i;
+		for (j = 0; j<ny-1; j += 2) {
+			b[s00+1] |= ((a[k]>>2) & 1) << bit;
+			b[s00  ] |= ((a[k]>>3) & 1) << bit;
+			s00 += 2;
+			k += 1;
+		}
+		if (j < ny) {
+			/*
+			 * both row and column size are odd, do corner element
+			 * s00+1, s10, s10+1 are off edge
+			 */
+			b[s00  ] |= ((a[k]>>3) & 1) << bit;
+			k += 1;
+		}
+	}
+}
+/*  ############################################################################  */
+/*
+ * Copy 4-bit values from a[(nx+1)/2,(ny+1)/2] to b[nx,ny], expanding
+ * each value to 2x2 pixels and inserting into bitplane BIT of B.
+ * A,B may NOT be same array (it wouldn't make sense to be inserting
+ * bits into the same array anyway.)
+ */
+static void
+qtree_bitins64(unsigned char a[], int nx, int ny, LONGLONG b[], int n, int bit)
+/*
+   int n;		declared y dimension of b
+*/
+{
+int i, j, k;
+int s00, s10;
+
+	/*
+	 * expand each 2x2 block
+	 */
+	k = 0;							/* k   is index of a[i/2,j/2]	*/
+	for (i = 0; i<nx-1; i += 2) {
+		s00 = n*i;					/* s00 is index of b[i,j]		*/
+		s10 = s00+n;				/* s10 is index of b[i+1,j]		*/
+		for (j = 0; j<ny-1; j += 2) {
+			b[s10+1] |= ((LONGLONG) ( a[k]     & 1)) << bit;
+			b[s10  ] |= ((((LONGLONG)a[k])>>1) & 1) << bit;
+			b[s00+1] |= ((((LONGLONG)a[k])>>2) & 1) << bit;
+			b[s00  ] |= ((((LONGLONG)a[k])>>3) & 1) << bit;
+			s00 += 2;
+			s10 += 2;
+			k += 1;
+		}
+		if (j < ny) {
+			/*
+			 * row size is odd, do last element in row
+			 * s00+1, s10+1 are off edge
+			 */
+			b[s10  ] |= ((((LONGLONG)a[k])>>1) & 1) << bit;
+			b[s00  ] |= ((((LONGLONG)a[k])>>3) & 1) << bit;
+			k += 1;
+		}
+	}
+	if (i < nx) {
+		/*
+		 * column size is odd, do last row
+		 * s10, s10+1 are off edge
+		 */
+		s00 = n*i;
+		for (j = 0; j<ny-1; j += 2) {
+			b[s00+1] |= ((((LONGLONG)a[k])>>2) & 1) << bit;
+			b[s00  ] |= ((((LONGLONG)a[k])>>3) & 1) << bit;
+			s00 += 2;
+			k += 1;
+		}
+		if (j < ny) {
+			/*
+			 * both row and column size are odd, do corner element
+			 * s00+1, s10, s10+1 are off edge
+			 */
+			b[s00  ] |= ((((LONGLONG)a[k])>>3) & 1) << bit;
+			k += 1;
+		}
+	}
+}
+
+/*  ############################################################################  */
+static void
+read_bdirect(unsigned char *infile, int a[], int n, int nqx, int nqy, unsigned char scratch[], int bit)
+{
+int i;
+
+	/*
+	 * read bit image packed 4 pixels/nybble
+	 */
+	for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
+		scratch[i] = input_nybble(infile);
+	}
+	/*
+	 * insert in bitplane BIT of image A
+	 */
+	qtree_bitins(scratch,nqx,nqy,a,n,bit);
+}
+/*  ############################################################################  */
+static void
+read_bdirect64(unsigned char *infile, LONGLONG a[], int n, int nqx, int nqy, unsigned char scratch[], int bit)
+{
+int i;
+
+	/*
+	 * read bit image packed 4 pixels/nybble
+	 */
+	for (i = 0; i < ((nqx+1)/2) * ((nqy+1)/2); i++) {
+		scratch[i] = input_nybble(infile);
+	}
+	/*
+	 * insert in bitplane BIT of image A
+	 */
+	qtree_bitins64(scratch,nqx,nqy,a,n,bit);
+}
+
+/*  ############################################################################  */
+/*
+ * Huffman decoding for fixed codes
+ *
+ * Coded values range from 0-15
+ *
+ * Huffman code values (hex):
+ *
+ *	3e, 00, 01, 08, 02, 09, 1a, 1b,
+ *	03, 1c, 0a, 1d, 0b, 1e, 3f, 0c
+ *
+ * and number of bits in each code:
+ *
+ *	6,  3,  3,  4,  3,  4,  5,  5,
+ *	3,  5,  4,  5,  4,  5,  6,  4
+ */
+static int input_huffman(unsigned char *infile)
+{
+int c;
+
+	/*
+	 * get first 3 bits to start
+	 */
+	c = input_nbits(infile,3);
+	if (c < 4) {
+		/*
+		 * this is all we need
+		 * return 1,2,4,8 for c=0,1,2,3
+		 */
+		return(1<<c);
+	}
+	/*
+	 * get the next bit
+	 */
+	c = input_bit(infile) | (c<<1);
+	if (c < 13) {
+		/*
+		 * OK, 4 bits is enough
+		 */
+		switch (c) {
+			case  8 : return(3);
+			case  9 : return(5);
+			case 10 : return(10);
+			case 11 : return(12);
+			case 12 : return(15);
+		}
+	}
+	/*
+	 * get yet another bit
+	 */
+	c = input_bit(infile) | (c<<1);
+	if (c < 31) {
+		/*
+		 * OK, 5 bits is enough
+		 */
+		switch (c) {
+			case 26 : return(6);
+			case 27 : return(7);
+			case 28 : return(9);
+			case 29 : return(11);
+			case 30 : return(13);
+		}
+	}
+	/*
+	 * need the 6th bit
+	 */
+	c = input_bit(infile) | (c<<1);
+	if (c == 62) {
+		return(0);
+	} else {
+		return(14);
+	}
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research 
+ * in Astronomy. All rights reserved. Produced under National   
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+/* qread.c	Read binary data
+ *
+ * Programmer: R. White		Date: 11 March 1991
+ */
+
+static int readint(unsigned char *infile)
+{
+int a,i;
+unsigned char b[4];
+
+	/* Read integer A one byte at a time from infile.
+	 *
+	 * This is portable from Vax to Sun since it eliminates the
+	 * need for byte-swapping.
+	 */
+	for (i=0; i<4; i++) qread(infile,(char *) &b[i],1);
+	a = b[0];
+	for (i=1; i<4; i++) a = (a<<8) + b[i];
+	return(a);
+}
+
+/*  ############################################################################  */
+static LONGLONG readlonglong(unsigned char *infile)
+{
+int i;
+LONGLONG a;
+unsigned char b[8];
+
+	/* Read integer A one byte at a time from infile.
+	 *
+	 * This is portable from Vax to Sun since it eliminates the
+	 * need for byte-swapping.
+	 */
+	for (i=0; i<8; i++) qread(infile,(char *) &b[i],1);
+	a = b[0];
+	for (i=1; i<8; i++) a = (a<<8) + b[i];
+	return(a);
+}
+
+/*  ############################################################################  */
+static void qread(unsigned char *infile,char *a, int n)
+{
+/*
+	if(myread(infile, a, n) != n) {
+		perror("qread");
+		exit(-1);
+
+	}
+*/
+	myread(infile, a, n);
+}
+
+/*  ############################################################################  */
+static int myread(unsigned char *file, char buffer[], int n)
+{
+    /*
+     * read n bytes from file into buffer
+     * returns number of bytes read (=n) if successful, <=0 if not
+     *
+     * this version is for VMS C: each read may return
+     * fewer than n bytes, so multiple reads may be needed
+     * to fill the buffer.
+     *
+     * I think this is unnecessary for Sun Unix, but it won't hurt
+     * either, so I'll leave it in.
+     */
+/*    int nread, total;  */
+
+    /* keep reading until we've read n bytes */
+/*
+    total = 0;
+    while ( (nread = fread(&buffer[total], 1, n-total, file)) > 0) {
+	total += nread;
+	if (total==n) return(total);
+    }
+*/
+
+    memcpy(buffer, &file[nextchar], n);
+    nextchar += n;
+    
+    return(n);
+}
+
+/*  ############################################################################  */
+/*  ############################################################################  */
+/* Copyright (c) 1993 Association of Universities for Research
+ * in Astronomy. All rights reserved. Produced under National
+ * Aeronautics and Space Administration Contract No. NAS5-26555.
+ */
+
+/* BIT INPUT ROUTINES */
+
+/* THE BIT BUFFER */
+
+static int buffer2;			/* Bits waiting to be input	*/
+static int bits_to_go;			/* Number of bits still in buffer */
+
+
+/* INITIALIZE BIT INPUT */
+
+/*  ############################################################################  */
+static void start_inputing_bits()
+{
+	/*
+	 * Buffer starts out with no bits in it
+	 */
+	bits_to_go = 0;
+}
+
+
+/*  ############################################################################  */
+/* INPUT A BIT */
+
+static int input_bit(unsigned char *infile)
+{
+	if (bits_to_go == 0) {			/* Read the next byte if no	*/
+		/* buffer2 = getc(infile); */	/* bits are left in buffer	*/
+
+		buffer2 = infile[nextchar];
+		nextchar++;
+		
+	/*	if (buffer2 == EOF) {  */
+			/*
+			 * end of file is an error for this application
+			 */
+/*
+			fprintf(stderr, "input_bit: unexpected end-of-file\n");
+			exit(-1);
+		}
+*/
+		bits_to_go = 8;
+	}
+	/*
+	 * Return the next bit
+	 */
+	bits_to_go -= 1;
+	return((buffer2>>bits_to_go) & 1);
+}
+
+
+/*  ############################################################################  */
+/* INPUT N BITS (N must be <= 8) */
+
+static int input_nbits(unsigned char *infile, int n)
+{
+int c;
+
+	if (bits_to_go < n) {
+		/*
+		 * need another byte's worth of bits
+		 */
+		buffer2 <<= 8;
+
+/*		c = getc(infile);  */
+
+		c = infile[nextchar];
+		nextchar++;
+		
+/*		if (c == EOF) { */
+			/*
+			 * end of file is an error for this application
+			 */
+/*
+			fprintf(stderr, "input_nbits: unexpected end-of-file\n");
+			exit(-1);
+		}
+*/
+		buffer2 |= c;
+		bits_to_go += 8;
+	}
+	/*
+	 * now pick off the first n bits
+	 */
+	bits_to_go -= n;
+	return( (buffer2>>bits_to_go) & ((1<<n)-1) );
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/extern/pliocomp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/extern/pliocomp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/extern/pliocomp.c	(revision 16632)
@@ -0,0 +1,331 @@
+/* stdlib is needed for the abs function */
+#include <stdlib.h>
+/*
+   The following prototype code was provided by Doug Tody, NRAO, for
+   performing conversion between pixel arrays and line lists.  The
+   compression technique is used in IRAF.
+*/
+int pl_p2li (int *pxsrc, int xs, short *lldst, int npix);
+int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix);
+
+
+/*
+ * PL_P2L -- Convert a pixel array to a line list.  The length of the list is
+ * returned as the function value.
+ *
+ * Translated from the SPP version using xc -f, f2c.  8Sep99 DCT.
+ */
+
+#ifndef min
+#define min(a,b)        (((a)<(b))?(a):(b))
+#endif
+#ifndef max
+#define max(a,b)        (((a)>(b))?(a):(b))
+#endif
+
+int pl_p2li (int *pxsrc, int xs, short *lldst, int npix)
+/* int *pxsrc;                      input pixel array */
+/* int xs;                          starting index in pxsrc (?) */
+/* short *lldst;                    encoded line list */
+/* int npix;                        number of pixels to convert */
+{
+    /* System generated locals */
+    int ret_val, i__1, i__2, i__3;
+
+    /* Local variables */
+    static int zero, v, x1, hi, ip, dv, xe, np, op, iz, nv, pv, nz;
+
+    /* Parameter adjustments */
+    --lldst;
+    --pxsrc;
+
+    /* Function Body */
+    if (! (npix <= 0)) {
+        goto L110;
+    }
+    ret_val = 0;
+    goto L100;
+L110:
+    lldst[3] = -100;
+    lldst[2] = 7;
+    lldst[1] = 0;
+    lldst[6] = 0;
+    lldst[7] = 0;
+    xe = xs + npix - 1;
+    op = 8;
+    zero = 0;
+/* Computing MAX */
+    i__1 = zero, i__2 = pxsrc[xs];
+    pv = max(i__1,i__2);
+    x1 = xs;
+    iz = xs;
+    hi = 1;
+    i__1 = xe;
+    for (ip = xs; ip <= i__1; ++ip) {
+        if (! (ip < xe)) {
+            goto L130;
+        }
+/* Computing MAX */
+        i__2 = zero, i__3 = pxsrc[ip + 1];
+        nv = max(i__2,i__3);
+        if (! (nv == pv)) {
+            goto L140;
+        }
+        goto L120;
+L140:
+        if (! (pv == 0)) {
+            goto L150;
+        }
+        pv = nv;
+        x1 = ip + 1;
+        goto L120;
+L150:
+        goto L131;
+L130:
+        if (! (pv == 0)) {
+            goto L160;
+        }
+        x1 = xe + 1;
+L160:
+L131:
+        np = ip - x1 + 1;
+        nz = x1 - iz;
+        if (! (pv > 0)) {
+            goto L170;
+        }
+        dv = pv - hi;
+        if (! (dv != 0)) {
+            goto L180;
+        }
+        hi = pv;
+        if (! (abs(dv) > 4095)) {
+            goto L190;
+        }
+        lldst[op] = (short) ((pv & 4095) + 4096);
+        ++op;
+        lldst[op] = (short) (pv / 4096);
+        ++op;
+        goto L191;
+L190:
+        if (! (dv < 0)) {
+            goto L200;
+        }
+        lldst[op] = (short) (-dv + 12288);
+        goto L201;
+L200:
+        lldst[op] = (short) (dv + 8192);
+L201:
+        ++op;
+        if (! (np == 1 && nz == 0)) {
+            goto L210;
+        }
+        v = lldst[op - 1];
+        lldst[op - 1] = (short) (v | 16384);
+        goto L91;
+L210:
+L191:
+L180:
+L170:
+        if (! (nz > 0)) {
+            goto L220;
+        }
+L230:
+        if (! (nz > 0)) {
+            goto L232;
+        }
+        lldst[op] = (short) min(4095,nz);
+        ++op;
+/* L231: */
+        nz += -4095;
+        goto L230;
+L232:
+        if (! (np == 1 && pv > 0)) {
+            goto L240;
+        }
+        lldst[op - 1] = (short) (lldst[op - 1] + 20481);
+        goto L91;
+L240:
+L220:
+L250:
+        if (! (np > 0)) {
+            goto L252;
+        }
+        lldst[op] = (short) (min(4095,np) + 16384);
+        ++op;
+/* L251: */
+        np += -4095;
+        goto L250;
+L252:
+L91:
+        x1 = ip + 1;
+        iz = x1;
+        pv = nv;
+L120:
+        ;
+    }
+/* L121: */
+    lldst[4] = (short) ((op - 1) % 32768);
+    lldst[5] = (short) ((op - 1) / 32768);
+    ret_val = op - 1;
+    goto L100;
+L100:
+    return ret_val;
+} /* plp2li_ */
+
+/*
+ * PL_L2PI -- Translate a PLIO line list into an integer pixel array.
+ * The number of pixels output (always npix) is returned as the function
+ * value.
+ *
+ * Translated from the SPP version using xc -f, f2c.  8Sep99 DCT.
+ */
+
+int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix)
+/* short *ll_src;                   encoded line list */
+/* int xs;                          starting index in ll_src */
+/* int *px_dst;                    output pixel array */
+/* int npix;                       number of pixels to convert */
+{
+    /* System generated locals */
+    int ret_val, i__1, i__2;
+
+    /* Local variables */
+    static int data, sw0001, otop, i__, lllen, i1, i2, x1, x2, ip, xe, np,
+             op, pv, opcode, llfirt;
+    static int skipwd;
+
+    /* Parameter adjustments */
+    --px_dst;
+    --ll_src;
+
+    /* Function Body */
+    if (! (ll_src[3] > 0)) {
+        goto L110;
+    }
+    lllen = ll_src[3];
+    llfirt = 4;
+    goto L111;
+L110:
+    lllen = (ll_src[5] << 15) + ll_src[4];
+    llfirt = ll_src[2] + 1;
+L111:
+    if (! (npix <= 0 || lllen <= 0)) {
+        goto L120;
+    }
+    ret_val = 0;
+    goto L100;
+L120:
+    xe = xs + npix - 1;
+    skipwd = 0;
+    op = 1;
+    x1 = 1;
+    pv = 1;
+    i__1 = lllen;
+    for (ip = llfirt; ip <= i__1; ++ip) {
+        if (! skipwd) {
+            goto L140;
+        }
+        skipwd = 0;
+        goto L130;
+L140:
+        opcode = ll_src[ip] / 4096;
+        data = ll_src[ip] & 4095;
+        sw0001 = opcode;
+        goto L150;
+L160:
+        x2 = x1 + data - 1;
+        i1 = max(x1,xs);
+        i2 = min(x2,xe);
+        np = i2 - i1 + 1;
+        if (! (np > 0)) {
+            goto L170;
+        }
+        otop = op + np - 1;
+        if (! (opcode == 4)) {
+            goto L180;
+        }
+        i__2 = otop;
+        for (i__ = op; i__ <= i__2; ++i__) {
+            px_dst[i__] = pv;
+/* L190: */
+        }
+/* L191: */
+        goto L181;
+L180:
+        i__2 = otop;
+        for (i__ = op; i__ <= i__2; ++i__) {
+            px_dst[i__] = 0;
+/* L200: */
+        }
+/* L201: */
+        if (! (opcode == 5 && i2 == x2)) {
+            goto L210;
+        }
+        px_dst[otop] = pv;
+L210:
+L181:
+        op = otop + 1;
+L170:
+        x1 = x2 + 1;
+        goto L151;
+L220:
+        pv = (ll_src[ip + 1] << 12) + data;
+        skipwd = 1;
+        goto L151;
+L230:
+        pv += data;
+        goto L151;
+L240:
+        pv -= data;
+        goto L151;
+L250:
+        pv += data;
+        goto L91;
+L260:
+        pv -= data;
+L91:
+        if (! (x1 >= xs && x1 <= xe)) {
+            goto L270;
+        }
+        px_dst[op] = pv;
+        ++op;
+L270:
+        ++x1;
+        goto L151;
+L150:
+        ++sw0001;
+        if (sw0001 < 1 || sw0001 > 8) {
+            goto L151;
+        }
+        switch ((int)sw0001) {
+            case 1:  goto L160;
+            case 2:  goto L220;
+            case 3:  goto L230;
+            case 4:  goto L240;
+            case 5:  goto L160;
+            case 6:  goto L160;
+            case 7:  goto L250;
+            case 8:  goto L260;
+        }
+L151:
+        if (! (x1 > xe)) {
+            goto L280;
+        }
+        goto L131;
+L280:
+L130:
+        ;
+    }
+L131:
+    i__1 = npix;
+    for (i__ = op; i__ <= i__1; ++i__) {
+        px_dst[i__] = 0;
+/* L290: */
+    }
+/* L291: */
+    ret_val = npix;
+    goto L100;
+L100:
+    return ret_val;
+} /* pll2pi_ */
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/extern/ricecomp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/extern/ricecomp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/extern/ricecomp.c	(revision 16632)
@@ -0,0 +1,515 @@
+/*
+  The following code was written by Richard White at STScI and made
+  available for use in CFITSIO in July 1999.  These routines were
+  originally contained in 2 source files: rcomp.c and rdecomp.c,
+  and the 'include' file now called ricecomp.h was originally called buffer.h.
+*/
+
+/*----------------------------------------------------------*/
+/*                                                          */
+/*    START OF SOURCE FILE ORIGINALLY CALLED rcomp.c        */
+/*                                                          */
+/*----------------------------------------------------------*/
+/* @(#) rcomp.c 1.5 99/03/01 12:40:27 */
+/* rcomp.c	Compress image line using
+ *		(1) Difference of adjacent pixels
+ *		(2) Rice algorithm coding
+ *
+ * Returns number of bytes written to code buffer or
+ * -1 on failure
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "ricecomp.h"  /* originally included in rcomp.c file (WDP) */
+// #include "fitsio2.h"
+
+
+static void start_outputing_bits(Buffer *buffer);
+static int done_outputing_bits(Buffer *buffer);
+static int output_nbits(Buffer *buffer, int bits, int n);
+
+/* this routine used to be called 'rcomp'  (WDP)  */
+
+int fits_rcomp(int a[],		/* input array			*/
+	  int nx,		/* number of input pixels	*/
+	  unsigned char *c,	/* output buffer		*/
+	  int clen,		/* max length of output		*/
+	  int nblock)		/* coding block size		*/
+{
+Buffer bufmem, *buffer = &bufmem;
+int bsize, i, j, thisblock;
+int lastpix, nextpix, pdiff;
+int v, fs, fsmask, top, fsmax, fsbits, bbits;
+int lbitbuffer, lbits_to_go;
+unsigned int psum;
+double pixelsum, dpsum;
+unsigned int *diff;
+
+    /*
+     * Original size of each pixel (bsize, bytes) and coding block
+     * size (nblock, pixels)
+     * Could make bsize a parameter to allow more efficient
+     * compression of short & byte images.
+     */
+    bsize = 4;
+/*    nblock = 32; */
+    /*
+     * From bsize derive:
+     * FSBITS = # bits required to store FS
+     * FSMAX = maximum value for FS
+     * BBITS = bits/pixel for direct coding
+     */
+    switch (bsize) {
+    case 1:
+	fsbits = 3;
+	fsmax = 6;
+	break;
+    case 2:
+	fsbits = 4;
+	fsmax = 14;
+	break;
+    case 4:
+	fsbits = 5;
+	fsmax = 25;
+	break;
+    default:
+        fprintf (stderr, "rdecomp: bsize must be 1, 2, or 4 bytes");
+	return(-1);
+    }
+    bbits = 1<<fsbits;
+
+    /*
+     * Set up buffer pointers
+     */
+    buffer->start = c;
+    buffer->current = c;
+    buffer->end = c+clen;
+    buffer->bits_to_go = 8;
+    /*
+     * array for differences mapped to non-negative values
+     */
+    diff = (unsigned int *) malloc(nblock*sizeof(unsigned int));
+    if (diff == (unsigned int *) NULL) {
+        fprintf (stderr, "fits_rcomp: insufficient memory");
+	return(-1);
+    }
+    /*
+     * Code in blocks of nblock pixels
+     */
+    start_outputing_bits(buffer);
+
+    /* write out first int value to the first 4 bytes of the buffer */
+    if (output_nbits(buffer, a[0], 32) == EOF) {
+        fprintf (stderr, "rice_encode: end of buffer");
+        free(diff);
+        return(-1);
+    }
+
+    lastpix = a[0];  /* the first difference will always be zero */
+
+    thisblock = nblock;
+    for (i=0; i<nx; i += nblock) {
+	/* last block may be shorter */
+	if (nx-i < nblock) thisblock = nx-i;
+	/*
+	 * Compute differences of adjacent pixels and map them to unsigned values.
+	 * Note that this may overflow the integer variables -- that's
+	 * OK, because we can recover when decompressing.  If we were
+	 * compressing shorts or bytes, would want to do this arithmetic
+	 * with short/byte working variables (though diff will still be
+	 * passed as an int.)
+	 *
+	 * compute sum of mapped pixel values at same time
+	 * use double precision for sum to allow 32-bit integer inputs
+	 */
+	pixelsum = 0.0;
+	for (j=0; j<thisblock; j++) {
+	    nextpix = a[i+j];
+	    pdiff = nextpix - lastpix;
+	    diff[j] = (unsigned int) ((pdiff<0) ? ~(pdiff<<1) : (pdiff<<1));
+	    pixelsum += diff[j];
+	    lastpix = nextpix;
+	}
+	/*
+	 * compute number of bits to split from sum
+	 */
+	dpsum = (pixelsum - (thisblock/2) - 1)/thisblock;
+	if (dpsum < 0) dpsum = 0.0;
+	psum = ((unsigned int) dpsum ) >> 1;
+	for (fs = 0; psum>0; fs++) psum >>= 1;
+	/*
+	 * write the codes
+	 * fsbits ID bits used to indicate split level
+	 */
+	if (fs >= fsmax) {
+	    /* Special high entropy case when FS >= fsmax
+	     * Just write pixel difference values directly, no Rice coding at all.
+	     */
+	    if (output_nbits(buffer, fsmax+1, fsbits) == EOF) {
+                fprintf (stderr, "rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	    for (j=0; j<thisblock; j++) {
+		if (output_nbits(buffer, diff[j], bbits) == EOF) {
+                    fprintf (stderr, "rice_encode: end of buffer");
+                    free(diff);
+		    return(-1);
+		}
+	    }
+	} else if (fs == 0 && pixelsum == 0) {
+	    /*
+	     * special low entropy case when FS = 0 and pixelsum=0 (all
+	     * pixels in block are zero.)
+	     * Output a 0 and return
+	     */
+	    if (output_nbits(buffer, 0, fsbits) == EOF) {
+                fprintf (stderr, "rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	} else {
+	    /* normal case: not either very high or very low entropy */
+	    if (output_nbits(buffer, fs+1, fsbits) == EOF) {
+                fprintf (stderr, "rice_encode: end of buffer");
+                free(diff);
+		return(-1);
+	    }
+	    fsmask = (1<<fs) - 1;
+	    /*
+	     * local copies of bit buffer to improve optimization
+	     */
+	    lbitbuffer = buffer->bitbuffer;
+	    lbits_to_go = buffer->bits_to_go;
+	    for (j=0; j<thisblock; j++) {
+		v = diff[j];
+		top = v >> fs;
+		/*
+		 * top is coded by top zeros + 1
+		 */
+		if (lbits_to_go >= top+1) {
+		    lbitbuffer <<= top+1;
+		    lbitbuffer |= 1;
+		    lbits_to_go -= top+1;
+		} else {
+		    lbitbuffer <<= lbits_to_go;
+		    if (putcbuf(lbitbuffer & 0xff,buffer) == EOF) {
+                        fprintf (stderr, "rice_encode: end of buffer");
+                        free(diff);
+			return(-1);
+		    }
+		    for (top -= lbits_to_go; top>=8; top -= 8) {
+			if (putcbuf(0, buffer) == EOF) {
+                            fprintf (stderr, "rice_encode: end of buffer");
+                            free(diff);
+			    return(-1);
+			}
+		    }
+		    lbitbuffer = 1;
+		    lbits_to_go = 7-top;
+		}
+		/*
+		 * bottom FS bits are written without coding
+		 * code is output_nbits, moved into this routine to reduce overheads
+		 * This code potentially breaks if FS>24, so I am limiting
+		 * FS to 24 by choice of FSMAX above.
+		 */
+		if (fs > 0) {
+		    lbitbuffer <<= fs;
+		    lbitbuffer |= v & fsmask;
+		    lbits_to_go -= fs;
+		    while (lbits_to_go <= 0) {
+			if (putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer)==EOF) {
+                            fprintf (stderr, "rice_encode: end of buffer");
+                            free(diff);
+			    return(-1);
+			}
+			lbits_to_go += 8;
+		    }
+		}
+	    }
+	    buffer->bitbuffer = lbitbuffer;
+	    buffer->bits_to_go = lbits_to_go;
+	}
+    }
+    done_outputing_bits(buffer);
+    free(diff);
+    /*
+     * return number of bytes used
+     */
+    return(buffer->current - buffer->start);
+}
+/*---------------------------------------------------------------------------*/
+/* bit_output.c
+ *
+ * Bit output routines
+ * Procedures return zero on success, EOF on end-of-buffer
+ *
+ * Programmer: R. White     Date: 20 July 1998
+ */
+
+/* Initialize for bit output */
+
+static void start_outputing_bits(Buffer *buffer)
+{
+    /*
+     * Buffer is empty to start with
+     */
+    buffer->bitbuffer = 0;
+    buffer->bits_to_go = 8;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Output N bits (N must be <= 32) */
+
+static int output_nbits(Buffer *buffer, int bits, int n)
+{
+/* local copies */
+int lbitbuffer;
+int lbits_to_go;
+
+    /*
+     * insert bits at end of bitbuffer
+     */
+    lbitbuffer = buffer->bitbuffer;
+    lbits_to_go = buffer->bits_to_go;
+    if (lbits_to_go+n > 32) {
+	/*
+	 * special case for large n: put out the top lbits_to_go bits first
+	 * note that 0 < lbits_to_go <= 8
+	 */
+	lbitbuffer <<= lbits_to_go;
+	lbitbuffer |= (bits>>(n-lbits_to_go)) & ((1<<lbits_to_go)-1);
+	if (putcbuf(lbitbuffer & 0xff,buffer) == EOF) return(EOF);
+	n -= lbits_to_go;
+	lbits_to_go = 8;
+    }
+    lbitbuffer <<= n;
+    lbitbuffer |= ( bits & ((1<<n)-1) );
+    lbits_to_go -= n;
+    while (lbits_to_go <= 0) {
+	/*
+	 * bitbuffer full, put out top 8 bits
+	 */
+	if (putcbuf((lbitbuffer>>(-lbits_to_go)) & 0xff,buffer) == EOF)
+	    return(EOF);
+	lbits_to_go += 8;
+    }
+    buffer->bitbuffer = lbitbuffer;
+    buffer->bits_to_go = lbits_to_go;
+    return(0);
+}
+
+/*---------------------------------------------------------------------------*/
+/* Flush out the last bits */
+
+static int done_outputing_bits(Buffer *buffer)
+{
+    if(buffer->bits_to_go < 8) {
+	if (putcbuf(buffer->bitbuffer<<buffer->bits_to_go,buffer) == EOF)
+	    return(EOF);
+    }
+    return(0);
+}
+/*---------------------------------------------------------------------------*/
+/*----------------------------------------------------------*/
+/*                                                          */
+/*    START OF SOURCE FILE ORIGINALLY CALLED rdecomp.c      */
+/*                                                          */
+/*----------------------------------------------------------*/
+
+/* @(#) rdecomp.c 1.4 99/03/01 12:38:41 */
+/* rdecomp.c	Decompress image line using
+ *		(1) Difference of adjacent pixels
+ *		(2) Rice algorithm coding
+ *
+ * Returns 0 on success or 1 on failure
+ */
+
+/*    moved these 'includes' to the beginning of the file (WDP)
+#include <stdio.h>
+#include <stdlib.h>
+*/
+
+/* this routine used to be called 'rdecomp'  (WDP)  */
+
+int fits_rdecomp (unsigned char *c,		/* input buffer			*/
+	     int clen,			/* length of input		*/
+	     unsigned int array[],	/* output array			*/
+	     int nx,			/* number of output pixels	*/
+	     int nblock)		/* coding block size		*/
+{
+int bsize, i, k, imax;
+int nbits, nzero, fs;
+unsigned char *cend, bytevalue;
+unsigned int b, diff, lastpix;
+int fsmax, fsbits, bbits;
+static int *nonzero_count = (int *)NULL;
+
+   /*
+     * Original size of each pixel (bsize, bytes) and coding block
+     * size (nblock, pixels)
+     * Could make bsize a parameter to allow more efficient
+     * compression of short & byte images.
+     */
+    bsize = 4;
+/*    nblock = 32; */
+    /*
+     * From bsize derive:
+     * FSBITS = # bits required to store FS
+     * FSMAX = maximum value for FS
+     * BBITS = bits/pixel for direct coding
+     */
+    switch (bsize) {
+    case 1:
+	fsbits = 3;
+	fsmax = 6;
+	break;
+    case 2:
+	fsbits = 4;
+	fsmax = 14;
+	break;
+    case 4:
+	fsbits = 5;
+	fsmax = 25;
+	break;
+    default:
+        fprintf (stderr, "rdecomp: bsize must be 1, 2, or 4 bytes");
+	return 1;
+    }
+    bbits = 1<<fsbits;
+
+    // XXX EAM : sensible code would put this in an init function,
+    // with a provided cleanup function.  this is just generating
+    // the number of 1 bits for any 8bit value
+    if (nonzero_count == (int *) NULL) {
+	/*
+	 * nonzero_count is lookup table giving number of bits
+	 * in 8-bit values not including leading zeros
+	 */
+
+        /*  NOTE!!!  This memory never gets freed  */
+	nonzero_count = (int *) malloc(256*sizeof(int));
+	if (nonzero_count == (int *) NULL) {
+            fprintf (stderr, "rdecomp: insufficient memory");
+	    return 1;
+	}
+	nzero = 8;
+	k = 128;
+	for (i=255; i>=0; ) {
+	    for ( ; i>=k; i--) nonzero_count[i] = nzero;
+	    k = k/2;
+	    nzero--;
+	}
+    }
+    /*
+     * Decode in blocks of nblock pixels
+     */
+
+    /* first 4 bytes of input buffer contain the value of the first */
+    /* 4 byte integer value, without any encoding */
+    
+    // XXX EAM : wow! this is just doing { lastpix = *(int *)c; } without a cast (encoded value is big-endian)
+    
+    lastpix = 0;
+    bytevalue = c[0];
+    lastpix = lastpix | (bytevalue<<24);
+    bytevalue = c[1];
+    lastpix = lastpix | (bytevalue<<16);
+    bytevalue = c[2];
+    lastpix = lastpix | (bytevalue<<8);
+    bytevalue = c[3];
+    lastpix = lastpix | bytevalue;
+
+    c += 4;  
+    cend = c + clen - 4;
+
+    b = *c++;		    /* bit buffer			*/
+    nbits = 8;		    /* number of bits remaining in b	*/
+    for (i = 0; i<nx; ) {
+	/* get the FS value from first fsbits */
+	nbits -= fsbits;
+	while (nbits < 0) {
+	    b = (b<<8) | (*c++);
+	    nbits += 8;
+	}
+	fs = (b >> nbits) - 1;
+	b &= (1<<nbits)-1;
+	/* loop over the next block */
+	imax = i + nblock;
+	if (imax > nx) imax = nx;
+	if (fs<0) {
+	    /* low-entropy case, all zero differences */
+	    for ( ; i<imax; i++) array[i] = lastpix;
+	} else if (fs==fsmax) {
+	    /* high-entropy case, directly coded pixel values */
+	    for ( ; i<imax; i++) {
+		k = bbits - nbits;
+		diff = b<<k;
+		for (k -= 8; k >= 0; k -= 8) {
+		    b = *c++;
+		    diff |= b<<k;
+		}
+		if (nbits>0) {
+		    b = *c++;
+		    diff |= b>>(-k);
+		    b &= (1<<nbits)-1;
+		} else {
+		    b = 0;
+		}
+		/*
+		 * undo mapping and differencing
+		 * Note that some of these operations will overflow the
+		 * unsigned int arithmetic -- that's OK, it all works
+		 * out to give the right answers in the output file.
+		 */
+		if ((diff & 1) == 0) {
+		    diff = diff>>1;
+		} else {
+		    diff = ~(diff>>1);
+		}
+		array[i] = diff+lastpix;
+		lastpix = array[i];
+	    }
+	} else {
+	    /* normal case, Rice coding */
+	    for ( ; i<imax; i++) {
+		/* count number of leading zeros */
+		while (b == 0) {
+		    nbits += 8;
+		    b = *c++;
+		}
+		nzero = nbits - nonzero_count[b];
+		nbits -= nzero+1;
+		/* flip the leading one-bit */
+		b ^= 1<<nbits;
+		/* get the FS trailing bits */
+		nbits -= fs;
+		while (nbits < 0) {
+		    b = (b<<8) | (*c++);
+		    nbits += 8;
+		}
+		diff = (nzero<<fs) | (b>>nbits);
+		b &= (1<<nbits)-1;
+		/* undo mapping and differencing */
+		if ((diff & 1) == 0) {
+		    diff = diff>>1;
+		} else {
+		    diff = ~(diff>>1);
+		}
+		array[i] = diff+lastpix;
+		lastpix = array[i];
+	    }
+	}
+	if (c > cend) {
+            fprintf (stderr, "decompression error: hit end of compressed byte stream");
+	    return 1;
+	}
+    }
+    if (c < cend) {
+        fprintf (stderr, "decompression warning: unused bytes at end of compressed buffer");
+    }
+    return 0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/extern/ricecomp.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/extern/ricecomp.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/extern/ricecomp.h	(revision 16632)
@@ -0,0 +1,107 @@
+/* @(#) buffer.h 1.1 98/07/21 12:34:27 */
+/* buffer.h: structure for compression to buffer rather than to a file, including
+ *   bit I/O buffer
+ *
+ * R. White, 19 June 1998
+ */
+
+
+typedef unsigned char Buffer_t;
+
+typedef struct {
+	int bitbuffer;		/* bit buffer					*/
+	int bits_to_go;		/* bits to go in buffer			*/
+	Buffer_t *start;	/* start of buffer				*/
+	Buffer_t *current;	/* current position in buffer	*/
+	Buffer_t *end;		/* end of buffer				*/
+} Buffer;
+
+#define buffree(mf)		(free(mf->start), free(mf))
+#define bufused(mf)		(mf->current - mf->start)
+#define bufreset(mf)	(mf->current = mf->start)
+
+/*
+ * getcbuf, putcbuf macros for character IO to buffer
+ * putcbuf returns EOF on end of buffer, else returns 0
+ */
+#define getcbuf(mf) ((mf->current >= mf->end) ? EOF : *(mf->current)++)
+#define putcbuf(c,mf) \
+	((mf->current >= mf->end) ? \
+	EOF :\
+	((*(mf->current)++ = c), 0))
+
+/*
+ * bufalloc sets up buffer of length n
+ */
+
+/*  not needed by CFITSIO
+
+static Buffer *bufalloc(int n)
+{
+Buffer *mf;
+
+	mf = (Buffer *) malloc(sizeof(Buffer));
+	if (mf == (Buffer *)NULL) return((Buffer *)NULL);
+
+	mf->start = (Buffer_t *) malloc(n*sizeof(Buffer_t));
+	if (mf->start == (Buffer_t *)NULL) {
+		free(mf);
+		return((Buffer *)NULL);
+	}
+	mf->bits_to_go = 8;
+	mf->end = mf->start + n;
+	mf->current = mf->start;
+	return(mf);
+}
+*/
+
+/*
+ * bufrealloc extends buffer (or truncates it) by
+ * reallocating memory
+ */
+
+/* not needed by CFITSIO 
+static int bufrealloc(Buffer *mf, int n)
+{
+int len;
+
+	len = mf->current - mf->start;
+
+	* silently throw away data if buffer is already longer than n *
+	if (len>n) len = n;
+	if (len<0) len = 0;
+
+	mf->start = (Buffer_t *) realloc(mf->start, n*sizeof(Buffer_t));
+	if (mf->start == (Buffer_t *)NULL) return(0);
+
+	mf->end = mf->start + n;
+	mf->current = mf->start + len;
+	return(n);
+}
+*/
+
+/*
+ * bufdump dumps contents of buffer to outfile and resets
+ * it to be empty.  Returns number of bytes written.
+ *
+ * Note we don't write out the bit buffer -- you must call
+ * done_outputing_bits() first to ensure that the bit buffer
+ * is written out.  I do it this way to allow incremental
+ * buffer dumps while bit IO is still going on.
+ */
+
+/*  not needed by CFITSIO
+
+static int bufdump(FILE *outfile, Buffer *buffer)
+{
+int ndump;
+
+	ndump = bufused(buffer);
+	if (fwrite(buffer->start, 1, ndump, outfile) != ndump) {
+		fprintf(stderr, "bufdump: error in write\n");
+		exit(1);
+    }
+	bufreset(buffer);
+	return(ndump);
+}
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_H_field.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_H_field.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_H_field.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits header field ****************************/
+char *gfits_header_field (Header *header, char *field, int N) {
+
+  char *buf;
+  int i, Nwant, Nfound;
+  char keyword[10];
+
+  /* create a blank-padded keyword with exactly 8 characters */
+  strcpy (keyword, field);
+  for (i = strlen(field); i < 8; i++) keyword[i] = ' ';
+  keyword[8] = 0;
+
+  buf = header[0].buffer;
+
+  if (N > 0) {
+    /* find the Nth entry */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+	if (Nfound == N) return (buf);
+      }
+    }
+  }
+
+  if (N < 0) {
+    /* count the entries */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+      }
+    }
+
+    Nwant = Nfound + N + 1;
+    buf = header[0].buffer;
+
+    /* find the Nwant entry */
+    Nfound = 0;
+    for (i = 0; i < header[0].size; i+= FT_LINE_LENGTH, buf += FT_LINE_LENGTH) {
+      if (!strncmp (keyword, buf, 8)) {
+	Nfound ++;
+	if (Nwant == Nfound) return (buf);
+      }
+    }
+
+  }
+
+  return ((char *) NULL);
+
+}
+
+/* 
+
+   find the Nth entry of this keyword.
+   if N < 0, find the last - N - 1 word (ie, -1 = last)
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_convert_H.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_convert_H.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_convert_H.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_primary_to_extended (Header *header, char *exttype, char *comment) {
+
+  int Ns, No;
+  char line[81];
+
+  // XXX check for valid exttype, comment, output string
+  snprintf (line, 81, "%-8s= '%-18s' / %-s ", "XTENSION", exttype, comment);
+  Ns = strlen (line);
+  No = 80 - Ns;
+  strncpy (header->buffer, line, Ns);
+  memset (&header->buffer[Ns], ' ', No);
+
+  return (TRUE);
+}
+
+// don't require the current to have SIMPLE
+int gfits_modify_extended (Header *header, char *exttype, char *comment) {
+
+  int Ns, No;
+  char line[81];
+
+  // XXX check for valid exttype, comment, output string
+  snprintf (line, 81, "%-8s= '%-18s' / %-s ", "XTENSION", exttype, comment);
+  Ns = strlen (line);
+  No = 80 - Ns;
+  strncpy (header->buffer, line, Ns);
+  memset (&header->buffer[Ns], ' ', No);
+
+  return (TRUE);
+}
+
+int gfits_extended_to_primary (Header *header, int simple, char *comment) {
+
+  int Ns, No;
+  char line[81];
+
+  // XXX check for valid exttype, comment, output string
+  if (simple) {
+    snprintf (line, 81, "%-8s= %-18s T / %-s ", "SIMPLE", " ", comment);
+  } else {
+    snprintf (line, 81, "%-8s= %-18s F / %-s ", "SIMPLE", " ", comment);
+  }
+  Ns = strlen (line);
+  No = 80 - Ns;
+  strncpy (header->buffer, line, Ns);
+  memset (&header->buffer[Ns], ' ', No);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_copy_H.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_copy_H.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_copy_H.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits copy header ***********************************/
+int gfits_copy_header (Header *in, Header *out) {
+
+  int i;
+
+  out[0].simple = in[0].simple;
+  out[0].unsign = in[0].unsign;
+  out[0].extend = in[0].extend;
+  out[0].bitpix = in[0].bitpix;
+
+  out[0].Naxes  = in[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    out[0].Naxis[i] = in[0].Naxis[i];
+
+  out[0].size   = in[0].size;
+
+  out[0].pcount = in[0].pcount;
+  out[0].gcount = in[0].gcount;
+  out[0].bzero  = in[0].bzero;
+  out[0].bscale = in[0].bscale;
+
+  ALLOCATE (out[0].buffer, char, out[0].size);
+  
+  strncpy (out[0].buffer, in[0].buffer, out[0].size);
+
+  return (TRUE);
+}	
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_create_H.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_create_H.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_create_H.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define NBYTES 2880
+
+/******************** fits create header ***********************************/
+int gfits_create_header (Header *header) {
+
+  int i;
+  char axis[10];
+  
+  header[0].size = NBYTES;
+
+  ALLOCATE (header[0].buffer, char, NBYTES);
+
+  for (i = 0; i < NBYTES; i++) 
+    header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+
+  gfits_modify (header, "SIMPLE", "%t", 1, header[0].simple);
+  gfits_modify (header, "BITPIX", "%d", 1, header[0].bitpix);
+  gfits_modify (header, "NAXIS",  "%d", 1, header[0].Naxes);
+				       
+  for (i = 0; i < header[0].Naxes; i++) {
+    snprintf (axis, 10, "NAXIS%d", i + 1);
+    gfits_modify (header,  axis, "%d", 1, header[0].Naxis[i]);
+  }
+
+  gfits_modify (header, "PCOUNT", "%d",  1, header[0].pcount);
+  gfits_modify (header, "GCOUNT", "%d",  1, header[0].gcount);
+  gfits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+  gfits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  gfits_modify (header, "EXTEND", "%t",  1, header[0].extend);
+  return (TRUE);
+
+}	
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_delete.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits delete ****************************/
+int gfits_delete (Header *header, char *field, int N) {
+  
+  int i, Nbytes;
+  char *p1, *p2;
+  
+  p1 = gfits_header_field (header, field, N);
+  if (p1 == NULL) return (TRUE);
+
+  p2 = gfits_header_field (header, "END", 1);
+  if (p2 == NULL) return (FALSE); 
+
+  /* pull everything from p1 + FT_LINE_LENGTH to p2 + 79 back 80 chars */
+  Nbytes = (p2 - p1);
+  memmove (p1, p1 + FT_LINE_LENGTH, Nbytes);
+
+  for (i = 0; i < FT_LINE_LENGTH; i++) 
+    *(p2 + i) = ' ';
+
+  p2 = gfits_header_field (header, "END", 1);
+  if (header[0].size - (p2 - header[0].buffer + FT_LINE_LENGTH) > FT_RECORD_SIZE) {
+    header[0].size -= FT_RECORD_SIZE;
+    REALLOCATE (header[0].buffer, char, header[0].size);
+  }
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_free_H.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_free_H.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_free_H.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits free header ***********************************/
+void gfits_free_header (Header *header) {
+
+  if (header[0].buffer == (char *) NULL) return;
+  free (header[0].buffer);
+  header[0].buffer = (char *) NULL;
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_init_H.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_init_H.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_init_H.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include <ohana.h>
+# include <gfitsio.h>
+static int FT_UNSIGN_MODE = FALSE;
+
+/*********************** fits read header ***********************************/
+int gfits_init_header (Header *header) {
+
+  int i;
+
+  header[0].simple = TRUE;
+  header[0].extend = FALSE;
+  header[0].unsign = FALSE;
+  header[0].pcount = 0;
+  header[0].gcount = 1;
+  header[0].bscale = 1.0;
+  header[0].bzero  = 0.0;
+  header[0].bitpix = 8;
+  header[0].Naxes  = 0;
+  header[0].buffer = NULL;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+
+  return (TRUE);
+}
+
+int gfits_set_unsign_mode (int mode) {
+  int oldmode;
+  
+  oldmode = FT_UNSIGN_MODE;
+  FT_UNSIGN_MODE = mode;
+  return (oldmode);
+}
+
+int gfits_get_unsign_mode () {
+  return (FT_UNSIGN_MODE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_insert_array.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_insert_array.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_insert_array.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits insert array ***********************************/
+void gfits_insert_matrix (matrix, array, x, y) 
+Matrix *matrix, *array; 
+int x, y;
+{
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, start_m, Nbytes_m, Nbytes;
+
+  Nbytes = array[0].Naxis[0]*abs(array[0].bitpix) / 8;
+  Nbytes_m = matrix[0].Naxis[0]*abs(matrix[0].bitpix) / 8;
+  start_m = y*Nbytes_m + x*abs(matrix[0].bitpix) / 8;
+
+  for (i = 0; i < array[0].Naxis[1]; i++) {
+    bcopy (&array[0].buffer[i*Nbytes], 
+	   &matrix[0].buffer[start_m + i*Nbytes_m], Nbytes);
+  }
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_modify.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_modify.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_modify.c	(revision 16632)
@@ -0,0 +1,187 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+char *gfits_keyword_start (char *line);
+char *gfits_keyword_end (char *line);
+void pad_ending (char *line, char value, int Nbyte);
+
+int gfits_modify (Header *header, char *field, char *mode, int N,...) {
+  
+  /* this function expects one more argument, the value to be written */
+  /* this function is extremely similar to gfits_print, except it allows for changing an existing field. */
+
+  char comment[82], string[82], data[82];
+  char *p, *qs, *qe;
+  va_list argp;
+  
+  va_start (argp, N);
+  bzero (data, 82);
+  bzero (string, 82);
+  bzero (comment, 82);
+
+  if (mode[0] != '%') {
+    fprintf (stderr, "gfits_print: weird mode:  %s\n", mode);
+    return (FALSE);
+  }
+
+  /* find location of desired entry */
+  p = gfits_header_field (header, field, N);
+  if (p == NULL)  {
+    /* new entry, find the END of the header */
+    p = gfits_header_field (header, "END", 1);
+    if (p == NULL) return (FALSE); 
+    
+    /* is there enough space for 1 more line? */
+    if (header[0].size - (p - (header[0].buffer)) < 2*FT_LINE_LENGTH) {
+      header[0].size += FT_RECORD_SIZE;
+      REALLOCATE (header[0].buffer, char, header[0].size);
+      p = gfits_header_field (header, "END", 1);
+      if (p == NULL) return (FALSE); 
+      memset (p + FT_LINE_LENGTH, ' ', FT_RECORD_SIZE);
+    }
+    
+    /* push END line back 1 */
+    memmove ((p + FT_LINE_LENGTH), p, FT_LINE_LENGTH);
+    memset (p, ' ', FT_LINE_LENGTH);
+  } else {
+    /* old entry, save the comment region (is this skipping a character for non-strings?) */
+    qe = gfits_keyword_end (p);
+    qe += 3;
+    qe = MIN (p + 80, qe);
+    strncpy (comment, qe, p + 80 - qe);
+  }
+  pad_ending (comment, ' ', 82);  /* comment must contain spaces to the end */
+
+  /* write the numeric modes */
+  if (!strcmp (mode, "%d"))  snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, int),      comment);
+  if (!strcmp (mode, "%u"))  snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, unsigned), comment);
+  if (!strcmp (mode, "%ld")) snprintf (string, 81, "%-8s= %20ld / %-s ",    field, va_arg (argp, long),     comment);
+  if (!strcmp (mode, "%hd")) snprintf (string, 81, "%-8s= %20d / %-s ",     field, va_arg (argp, int),      comment);
+  if (!strcmp (mode, "%f"))  snprintf (string, 81, "%-8s= %20.10f / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%lf")) snprintf (string, 81, "%-8s= %20.10f / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%e"))  snprintf (string, 81, "%-8s= %20.10E / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%le")) snprintf (string, 81, "%-8s= %20.10E / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%g"))  snprintf (string, 81, "%-8s= %20.10G / %-s ",  field, va_arg (argp, double),   comment); 
+  if (!strcmp (mode, "%lg")) snprintf (string, 81, "%-8s= %20.10G / %-s ",  field, va_arg (argp, double),   comment); 
+
+  /* write the boolean mode */
+  if (!strcmp (mode, "%t")) {
+    if (va_arg (argp, int)) 
+      snprintf (string, 81, "%-8s= %18s T / %-s ", field, " ", comment);
+    else
+      snprintf (string, 81, "%-8s= %18s F / %-s ", field, " ", comment);
+  }
+
+  /* string value.  Quotes must be at least 18 chars apart */
+  if (!strcmp (mode, "%s")) {
+    strncpy (data, va_arg (argp, char *), 68);
+    snprintf (string, 81, "%-8s= '%-18s' / %-s ", field, data, comment);
+  }
+
+  /* comment type of value.  */
+  if (!strcmp (mode, "%S")) {
+    strncpy (data, va_arg (argp, char *), 71);
+    snprintf (string, 81, "%-8s %-71s", field, data);
+  }  
+
+  /* just a comment associated with a value.  this is assumes a fixed format position for the comment */
+  if (!strcmp (mode, "%C")) { 
+    qe = gfits_keyword_end (p);
+    qs = gfits_keyword_start (p);
+
+    /* keep ' on ends, if there */
+    if (qe[0]  == 0x27) qe ++;
+    if (qs[-1] == 0x27) qs --;
+
+    strncpy (data, qs, MAX (MIN (qe - qs, 71), 0));
+    strncpy (comment, va_arg (argp, char *), 80);
+    pad_ending (comment, ' ', 82);  /* comment must contain spaces to the end */
+    snprintf (string, 81, "%-8s= %s / %-s", field, data, comment);
+    /* this will keep the original line, but truncate the comment */
+  }
+
+  strncpy (p, string, 80);
+  va_end (argp);
+  return (TRUE);
+
+}
+
+/* given a FITS card line, return pointer to the start of the data area */
+char *gfits_keyword_start (char *line) {
+
+  char *c;
+
+  /* find the end of the existing data region */
+  c = line + 8;
+  if (*c != '=') return (c);  /* no data in COMMENT field */
+  
+  c += 2;
+  /* advance pointer over WHITESPACE */
+  while ((*c == ' ') && (c < line + 80)) { c++; }
+  
+  /* skip one quote mark */
+  if ((*c == 0x27) && (c < line + 80)) { c++; }
+
+  return (c);
+}
+
+/* given a FITS card line, return pointer to the end of the data area */
+char *gfits_keyword_end (char *line) {
+
+  int done;
+  char *c1, *c2;
+
+  /* find the end of the existing data region */
+  c1 = line + 8;
+  if (*c1 != '=') return (c1);  /* no data in COMMENT field */
+  c1 += 2;
+
+  /* advance pointer over WHITESPACE */
+  while ((*c1 == ' ') && (c1 < line + 80)) { c1++; }
+  
+  if (c1[0] == 0x27) { /* entry a string, skip over 'fred' */
+    for (done = FALSE, c2 = c1 + 1; !done && (c2 < line + 80); c2++) {
+      if ((c2[0] == 0x27) && (c2[1] == 0x27)) {
+	c2 += 2;
+	continue;
+      }
+      if (c2[0] == 0x27) {
+	c1 = c2;
+	done = TRUE;
+      }
+    }
+    if (!done) { /* error in line: mismatched ' chars, return fixed position */
+      c1 = line + 30;
+    }
+  } else {
+    while ((*c1 != ' ') && (c1 < line + 80)) c1++;
+  }
+  return (c1);
+}
+
+/* according to the FITS guidelines, a string is supposed to start with a single quote
+   on the 11th character.  I'll be generous and allow the string to start at the 10th.
+   I read the string into tmp then strip off the leading single quote and spaces.
+   a string of "  '  fred is here  '  " should become "fred is here".
+   a string of "  fred is here  " should also become "fred is here".
+   the remaining problem:
+   "'O''HARA'" should be kept as O''HARA.  need to test for double single quotes
+   d -- /(0x2f: comment)  (*(p + i + 10) != 0x2f) &&  && (*(p + i + 10) != 0x27)
+ */
+
+/* fill 'line' with Nbyte space from first NULL to last byte with value */
+void pad_ending (char *line, char value, int Nbyte) {
+  
+  char *p;
+  int N;
+
+  line[Nbyte-1] = 0;
+  
+  p = line + strlen (line);
+  N = MAX (Nbyte - strlen (line) - 1, 0);
+  memset (p, value, N);
+}
+
+
+/* in this routine, the value field will expand as needed, forcing out the comment
+   the total line is limited by snprintf to only 80 chars + EOL */
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_print.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_print.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_print.c	(revision 16632)
@@ -0,0 +1,100 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_print (Header *header, char *field, char *mode, int N,...) {
+  
+  /* this function expects one more argument, the value to be written */
+
+  static char blank[] = " ";
+  char string[82], line[80];
+  char *p, a;
+  va_list argp;  
+
+  va_start (argp, N);
+  
+  if (mode[0] != '%') {
+    fprintf (stderr, "gfits_print: weird mode:  %s\n", mode);
+    return (FALSE);
+  }
+
+  /* this is supposed to create a new field, not modify an old one.  */
+  p = gfits_header_field (header, field, N);
+  if (p != NULL) return (FALSE);
+
+  /* find the END of the header */
+  p = gfits_header_field (header, "END", 1);
+  if (p == NULL) return (FALSE); 
+
+  /* is there enough space for 1 more line? */
+  if (header[0].size - (p - (header[0].buffer)) < 2*FT_LINE_LENGTH) {
+    header[0].size += FT_RECORD_SIZE;
+    REALLOCATE (header[0].buffer, char, header[0].size);
+    /* re-find the "END" marker, in case new memory block is used */
+    p = gfits_header_field (header, "END", 1);
+    if (p == NULL) return (FALSE); 
+    memset (p + FT_LINE_LENGTH, ' ', FT_RECORD_SIZE);
+  }
+
+  /* push END line back 1 */
+  memmove ((p + FT_LINE_LENGTH), p, FT_LINE_LENGTH);
+  memset (p, ' ', FT_LINE_LENGTH);
+
+  /* write the new FITS card, setting the comment to be blank */
+  /* in these lines, the value field will expand as needed, forcing out the comment
+     the total line is limited by snprintf to only 80 chars + EOL */
+
+  /* write the numeric modes */
+  if (!strcmp (mode, "%d"))  { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, int),      blank); }
+  if (!strcmp (mode, "%u"))  { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, unsigned), blank); }
+  if (!strcmp (mode, "%ld")) { snprintf (string, 81, "%-8s= %20ld / %46s ",   field, va_arg (argp, long),     blank); }
+  if (!strcmp (mode, "%hd")) { snprintf (string, 81, "%-8s= %20d / %46s ",    field, va_arg (argp, int),      blank); }
+  if (!strcmp (mode, "%f"))  { snprintf (string, 81, "%-8s= %20.10f / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%lf")) { snprintf (string, 81, "%-8s= %20.10f / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%e"))  { snprintf (string, 81, "%-8s= %20.10E / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%le")) { snprintf (string, 81, "%-8s= %20.10E / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%g"))  { snprintf (string, 81, "%-8s= %20.10G / %46s ", field, va_arg (argp, double),   blank); }
+  if (!strcmp (mode, "%lg")) { snprintf (string, 81, "%-8s= %20.10G / %46s ", field, va_arg (argp, double),   blank); }
+
+  /* write the boolean mode */
+  if (!strcmp (mode, "%t")) {
+    a = va_arg (argp, int);
+    if (a == 1)
+      snprintf (string, 81, "%-8s= %18s T / %46s ", field, blank, blank);
+    else
+      snprintf (string, 81, "%-8s= %18s F / %46s ", field, blank, blank);
+  }
+
+  /* string value.  Quotes must be at least 18 chars apart.  Longer lines will this should be fixed to allow arbitrary string lengths, up to 69 chars */
+  if (!strcmp (mode, "%s")) {
+    strcpy (line, va_arg (argp, char *));
+    line[68] = 0;
+    snprintf (string, 81, "%-8s= '%-18s' / %46s ", field, line, blank);
+  }
+
+  /* comment type of value.  */
+  if (!strcmp (mode, "%S")) {
+    /* we are forcing the entry to be <= 69 char long */
+    strcpy (line, va_arg (argp, char *));
+    line[71] = 0;
+    snprintf (string, 81, "%-8s %-71s", field, line);
+  }  
+
+  /*
+maximal string line:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890 .
+KEYWORD = '01234567890123456789012345678901234567890123456789012345678901234567'
+
+maximal comment line:
+12345678901234567890123456789012345678901234567890123456789012345678901234567890 .
+KEYWORD  01234567890123456789012345678901234567890123456789012345678901234567890
+  */
+
+  /* can't write the comment in gfits_print - use gfits_modify */
+  if (!strcmp (mode, "%C")) return (FALSE);
+
+  strncpy (p, string, 80);
+  
+  va_end (argp);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_read_H.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_read_H.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_read_H.c	(revision 16632)
@@ -0,0 +1,99 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read header ***********************************/
+int gfits_read_header (char *filename, Header *header) {
+  
+  FILE *f;
+  
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    header[0].buffer = NULL;
+    return (FALSE);
+  }
+  if (!gfits_load_header (f, header)) {
+    fclose (f);
+    return (FALSE);
+  }
+
+  fclose (f);
+  return (TRUE);
+}	
+
+int gfits_load_header (FILE *f, Header *header) {
+
+  int i, done, Nbytes, t1, t2;
+  char *p;
+
+  header[0].size = 0;
+  done = FALSE;
+  ALLOCATE (header[0].buffer, char, 1);
+
+  for (i = 0; !done; i++) {
+    REALLOCATE (header[0].buffer, char, (i + 1)*FT_RECORD_SIZE);
+    Nbytes = fread (&header[0].buffer[i*FT_RECORD_SIZE], 
+		    sizeof(char), FT_RECORD_SIZE, f);
+    if (Nbytes != FT_RECORD_SIZE) {
+      if (feof(f)) return (FALSE);
+      perror ("gfits_load_header : failed to read all data");
+      return (FALSE);
+    }
+    
+    header[0].size += Nbytes;
+
+    if (i == 0) { 
+      /* on first block, verify it is a FITS table: SIMPLE .. or XTENSION ... */
+      t1 = strncmp (header[0].buffer, "SIMPLE", 6);
+      t2 = strncmp (header[0].buffer, "XTENSION", 8);
+      if (t1 && t2) return (FALSE);
+    }
+
+    p = gfits_header_field (header, "END", 1);
+    if (p != NULL)
+      done = TRUE;
+  }
+
+  header[0].unsign = gfits_get_unsign_mode();
+  header[0].bscale = 1;
+  header[0].bzero  = 0;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+
+  gfits_scan (header,  "SIMPLE", "%t",   1, &header[0].simple);
+  gfits_scan (header,  "BITPIX", "%d",   1, &header[0].bitpix);
+  gfits_scan (header,  "NAXIS",  "%d",   1, &header[0].Naxes);
+				                           
+  gfits_scan (header,  "EXTEND", "%t",   1, &header[0].extend);
+  gfits_scan (header,  "UNSIGN", "%t",   1, &header[0].unsign);
+  gfits_scan (header,  "BSCALE", "%lf",  1, &header[0].bscale);
+  gfits_scan (header,  "BZERO",  "%lf",  1, &header[0].bzero);
+				       
+  gfits_scan (header,  "NAXIS1", "%d", 1, &header[0].Naxis[0]);
+  gfits_scan (header,  "NAXIS2", "%d", 1, &header[0].Naxis[1]);
+  gfits_scan (header,  "NAXIS3", "%d", 1, &header[0].Naxis[2]);
+  gfits_scan (header,  "NAXIS4", "%d", 1, &header[0].Naxis[3]);
+  gfits_scan (header,  "NAXIS5", "%d", 1, &header[0].Naxis[4]);
+  gfits_scan (header,  "NAXIS6", "%d", 1, &header[0].Naxis[5]);
+  gfits_scan (header,  "NAXIS7", "%d", 1, &header[0].Naxis[6]);
+  gfits_scan (header,  "NAXIS8", "%d", 1, &header[0].Naxis[7]);
+  gfits_scan (header,  "NAXIS9", "%d", 1, &header[0].Naxis[8]);
+  gfits_scan (header, "NAXIS10", "%d", 1, &header[0].Naxis[9]);
+
+  if (!gfits_scan (header, "PCOUNT",  "%d", 1, &header[0].pcount)) {
+    header[0].pcount = 0;
+  }
+  if (!gfits_scan (header, "GCOUNT",  "%d", 1, &header[0].gcount)) {
+    header[0].gcount = 1;
+  }
+
+  return (TRUE);
+
+}
+
+int gfits_fread_header (FILE *f, Header *header) {
+
+  int status;
+  
+  status = gfits_load_header (f, header);
+  return (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_read_XH.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_read_XH.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_read_XH.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read header ***********************************/
+int gfits_read_Xheader (char *filename, Header *header, int N) {
+
+  int status;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    header[0].buffer = NULL;
+    fclose (f);
+    return (FALSE);
+  }
+
+  status = gfits_fread_Xheader (f, header, N);
+  if (!status) {
+    header[0].buffer = NULL;
+    fclose (f);
+    return (FALSE);
+  }
+
+  fclose (f);
+  return (status);
+
+}
+
+/*********************** fits read header ***********************************/
+int gfits_fread_Xheader (FILE *f, Header *header, int N) {
+  
+  /* read header for extension number N */
+
+  int j, Nmatrix, Nskip;
+  Header theader;
+  
+  /* set f to beginning of file */
+  fseek (f, 0, SEEK_SET);
+
+  Nskip = 0;
+  for (j = -1; j < N; j++) {
+    /* load data for this header */
+    if (!gfits_load_header (f, &theader)) {
+      return (FALSE);
+    }
+
+    Nmatrix = gfits_data_size (&theader);
+
+    /* skip to next header */
+    fseek (f, Nmatrix, SEEK_CUR);
+    Nskip += (Nmatrix + theader.size);
+    gfits_free_header (&theader);
+  }
+  
+  if (!gfits_load_header (f, header)) {
+    return (FALSE);
+  }
+  Nskip += header[0].size;
+  return (Nskip);
+}	
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_scan.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_scan.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_scan.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+char *gfits_keyword_start (char *line);
+char *gfits_keyword_end (char *line);
+
+int gfits_scan (Header *header, char *field, char *mode, int N,...) {
+
+  int status;
+  va_list argp;
+  
+  va_start (argp, N);
+  status = gfits_vscan (header, field, mode, N, argp);
+  va_end (argp);
+  return (status);
+}
+  
+int gfits_vscan (Header *header, char *field, char *mode, int N, va_list argp) {
+
+  char *p, *q, *s, tmp[81];
+  int Nchar;
+  double value;
+  
+  /* find the correct line with field */
+  p = gfits_header_field (header, field, N);
+  if (p == NULL) return (FALSE);
+
+  /* non-data entry (COMMENT, HISTORY) */
+  if (!strcmp (mode, "%S")) {
+    strncpy (va_arg (argp, char *), p + 8, FT_HISTORY_LENGTH);
+    return (TRUE);
+  }
+
+  /* all others require '=' in column 8 */
+  if (p[8] != '=') return (FALSE);
+
+  /* comment from data line */
+  if (!strcmp (mode, "%C")) {
+    q = gfits_keyword_end (p) + 3;
+    q = MIN (p + 80, q);
+    bzero (tmp, 81);
+    Nchar = MIN (80, p + 80 - q);
+    memcpy (tmp, q, Nchar);
+    stripwhite (tmp);
+    strcpy (va_arg (argp, char *), tmp);
+    return (TRUE);
+  }
+
+  /* extract data into char array (exclude containing ' chars) */
+  if (!strcmp (mode, "%s")) {
+    s = gfits_keyword_start (p); /* points at first char (not ') */
+    q = gfits_keyword_end (p); /* points at following space or ' */
+
+    Nchar = MAX (0, (q - s));
+    bzero (tmp, 81);
+    memcpy (tmp, s, Nchar);
+    stripwhite (tmp);
+    strcpy (va_arg (argp, char *), tmp);
+    return (TRUE);
+  }
+  
+  /* boolean data, requires int target */
+  if (!strcmp (mode, "%t")) {
+    s = gfits_keyword_start (p);
+    if (*s == 'T') {
+      *va_arg (argp, int *) = TRUE;
+      return (TRUE);
+    }
+    if (*s == 'F') {
+      *va_arg (argp, int *) = FALSE;   
+      return (TRUE);
+    }
+  }
+
+  /* remaining options are numerical data */
+  /* need to interpret 1.0d5 as 1.0e5 */
+  s = gfits_keyword_start (p); /* points at first char (not ') */
+  q = gfits_keyword_end (p); /* points at following space or ' */
+  value = strtod (s, &q);
+  if ((*q == 'd') || (*q == 'D')) 
+    value *= pow (10.0, atof (q + 1));
+
+  if (!strcmp (mode, "%d"))  { *va_arg (argp, int *)       = value; return (TRUE); }
+  if (!strcmp (mode, "%u"))  { *va_arg (argp, unsigned *)  = value; return (TRUE); }
+  if (!strcmp (mode, "%ld")) { *va_arg (argp, long *)      = value; return (TRUE); }
+  if (!strcmp (mode, "%hd")) { *va_arg (argp, short *)     = value; return (TRUE); }
+  if (!strcmp (mode, "%f"))  { *va_arg (argp, float *)     = value; return (TRUE); }
+  if (!strcmp (mode, "%lf")) { *va_arg (argp, double *)    = value; return (TRUE); }
+
+  /* no valid mode found */
+  return (FALSE);
+}
+
+/* if the variable argument stuff breaks on another system, look 
+at F_modify.c as it has the old code */
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/F_write_H.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/F_write_H.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/F_write_H.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write header ***********************************/
+int gfits_write_header (char *filename, Header *header) {
+
+  FILE *f;
+  int Nbytes, status;
+  
+  status = TRUE;
+
+  f = fopen (filename, "w");
+  if (f == (FILE *) NULL) return (FALSE);
+
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) {
+    status = FALSE;
+  }
+
+  fclose (f);
+
+  return (status);
+}	
+
+/*********************** fits write header ***********************************/
+int gfits_save_header (FILE *f, Header *header) {
+
+  int Nbytes, status;
+  
+  status = TRUE;
+
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) {
+    status = FALSE;
+  }
+
+  return (status);
+}	
+
+
+int gfits_fwrite_header (FILE *f, Header *header) {
+
+  int status;
+  status = gfits_save_header (f, header);
+  return (status);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/header/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/header/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/header/version.c	(revision 16632)
@@ -0,0 +1,7 @@
+# include <ohana.h>
+# include <gfitsio.h>
+static char *name = "$Name: not supported by cvs2svn $";
+
+char *gfits_version () {
+  return (name);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/include/cfuncs.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/include/cfuncs.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/include/cfuncs.h	(revision 16632)
@@ -0,0 +1,60 @@
+/*** random C-functions ***/
+
+void
+  bcopy
+  (char *b1,
+   char *b2,
+   int   length);
+
+void
+  bzero
+  (char *b,
+   int   length);
+
+# ifndef HAS_ANSI_PROTOTYPES
+int
+   fprintf 
+   (FILE *stream,
+    char *format,...);
+
+int
+   fscanf 
+   (FILE *stream,
+    char *format,...);
+
+int 
+  fread
+  (char *ptr,
+   int size, 
+   int nitems,
+   FILE *stream);
+
+/*
+char *
+  malloc
+  (unsigned size);
+
+char *
+  realloc
+  (char *ptr,
+   unsigned size);
+*/
+
+int 
+  fwrite
+  (char *ptr,
+   int size, 
+   int nitems,
+   FILE *stream);
+
+int
+  fseek 
+  (FILE *f,
+   int offset,
+   int from);
+
+int
+  fclose
+  (FILE *f);
+# endif /* HAS_ANSI_PROTOTYPES */
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/include/gfitsio.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/include/gfitsio.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/include/gfitsio.h	(revision 16632)
@@ -0,0 +1,211 @@
+/* FITS specific macros and structures */
+
+# include <assert.h>
+# include <errno.h>
+
+# ifndef GFITSIO
+# define GFITSIO
+
+/* also defined in libautocode/def/common.h */
+/* what about lin64 ?? - 'linux' might be defined automatically by linux */
+# ifndef BYTE_SWAP
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+# ifdef darwin_x86
+# define BYTE_SWAP
+# endif
+
+# ifdef dec
+# define BYTE_SWAP
+# endif
+# endif /* BYTE_SWAP */
+
+# ifndef NEWLINE
+# define NEWLINE                 10  /* UNIX RETURN character */
+# endif /* NEWLINE */
+
+/********** FITS Constants *********/
+# define FT_TEXT_LENGTH          18  /* max length text header field */
+# define FT_MAX_NAXES            10  /* max number of axes */
+# define FT_FIELD_LENGTH          8  /* max length header field */   
+# define FT_COMMENT_LENGTH       47  /* max length comment field */
+# define FT_HISTORY_LENGTH       72  /* max length history / comment */
+# define FT_LINE_LENGTH          80  /* FITS header line length */
+# define FT_RECORD_SIZE        2880  /* FITS block size */
+
+/* this structure defines the buffer which contains a header
+   and contains the minimum required keywords */
+
+typedef struct {
+  int                     simple;
+  int                     unsign;
+  int                     extend;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  int                     pcount;
+  int                     gcount;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Header;
+
+/* this structure defines the buffer which contains a matrix
+   and contains some relavant info */
+
+typedef struct {
+  int                     unsign;
+  int                     bitpix;
+  int                     Naxes;
+  int                     Naxis[FT_MAX_NAXES];
+  int                     size;
+  double                  bzero;
+  double                  bscale;
+  char                   *buffer;
+} Matrix;
+   
+/* the FTable represents a complete table on disk */          
+typedef struct {
+  Header                 *header;
+  char                   *buffer;
+  int                     size;
+} FTable;
+
+/* the VTable represents rows from a table on disk */          
+typedef struct {
+  Header                 *header;
+  char                  **buffer;
+  int                     Nrow;
+  int                    *row;
+  int                     size;  /* total buffer size */
+  int                     pad;   /* bytes of padding at the end */
+} VTable;
+
+typedef struct {
+  int  maxlen; 		      // max size of all table rows
+  int  nbytes;		      // number of bytes per column element
+  int  Nstart;		      // byte offset of this column
+  int  heap_start;	      // byte offset to start of HEAP
+  char format;		      // data format character (one of: XLABIJEDCM)
+} VarLengthColumn;
+
+# ifndef PROTO
+# define PROTO(A) A
+# endif
+
+char   *gfits_version                  PROTO((void));
+
+/******************************* Header functions *************/
+
+char   *gfits_header_field             PROTO((Header *header, char *field, int N)); 
+char   *gfits_keyword_end              PROTO((char *line));
+int     gfits_copy_header              PROTO((Header *in, Header *out)); 
+int     gfits_create_header            PROTO((Header *header)); 
+int     gfits_delete                   PROTO((Header *header, char *field, int N)); 
+int     gfits_fread_Xheader            PROTO((FILE *f, Header *header, int N));
+int     gfits_fread_header             PROTO((FILE *f, Header *header));
+void    gfits_free_header              PROTO((Header *header)); 
+int     gfits_fwrite_header            PROTO((FILE *f, Header *header)); 
+int     gfits_get_unsign_mode          PROTO((void));
+int     gfits_init_header              PROTO((Header *header));
+int     gfits_load_header              PROTO((FILE *f, Header *header));
+int     gfits_modify                   PROTO((Header *header, char *field, char *mode, int N,...)); 
+int     gfits_print                    PROTO((Header *header, char *field, char *mode, int N,...)); 
+int     gfits_read_Xheader             PROTO((char *filename, Header *header, int N));
+int     gfits_read_header              PROTO((char *filename, Header *header));
+int     gfits_save_header              PROTO((FILE *f, Header *header));
+int     gfits_scan                     PROTO((Header *header, char *field, char *mode, int N,...));
+int     gfits_set_unsign_mode          PROTO((int mode));
+int     gfits_stripwhite               PROTO((char *string));
+int     gfits_vscan                    PROTO((Header *header, char *field, char *mode, int N, va_list argp));
+int     gfits_write_header             PROTO((char *filename, Header *header)); 
+int     gfits_data_size                PROTO((Header *header));
+int     gfits_data_min_size            PROTO((Header *header));
+int 	gfits_extended_to_primary      PROTO((Header *header, int simple, char *comment));
+int 	gfits_primary_to_extended      PROTO((Header *header, char *exttype, char *comment));
+int 	gfits_modify_extended          PROTO((Header *header, char *exttype, char *comment));
+
+
+/******************************* Matrix functions *************/
+
+void   	gfits_add_matrix_value         PROTO((Matrix *matrix, int x, int y, double value)); 
+int    	gfits_convert_format           PROTO((Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int outUnsign));
+int     gfits_copy_matrix              PROTO((Matrix *in, Matrix *out)); 
+int     gfits_create_matrix            PROTO((Header *header, Matrix *matrix)); 
+int    	gfits_divide_matrix            PROTO((Matrix *M1, Matrix *M2, Matrix *M3)); 
+int    	gfits_fread_matrix             PROTO((FILE *f, Matrix *matrix, Header *header));
+int    	gfits_fread_matrix_segment     PROTO((FILE *f, Matrix *matrix, Header *header, char *region));
+void    gfits_free_matrix              PROTO((Matrix *matrix)); 
+int     gfits_fwrite_matrix            PROTO((FILE *f, Matrix *matrix));      
+double  gfits_get_matrix_value         PROTO((Matrix *matrix, int x, int y)); 
+void   	gfits_insert_array             PROTO((Matrix *matrix, Matrix *array, int x, int y)); 
+int    	gfits_load_matrix              PROTO((FILE *f, Matrix *matrix, Header *header));
+int    	gfits_multiply_matrix          PROTO((Matrix *M1, Matrix *M2, Matrix *M3)); 
+int     gfits_read_matrix              PROTO((char *filename, Matrix *matrix));      
+int    	gfits_read_matrix_segment      PROTO((char *filename, Matrix *matrix, char *region));
+int     gfits_read_portion             PROTO((char *filename, Matrix *matrix, int Nskip, int Npix));
+void   	gfits_set_matrix_value         PROTO((Matrix *matrix, int x, int y, double value)); 
+int     gfits_write_matrix             PROTO((char *filename, Matrix *matrix)); 
+int     gfits_uncompress_image 	       PROTO((Header *header, Matrix *matrix, FTable *ftable));
+int     gfits_uncompress_data  	       PROTO((char *zdata, int Nzdata, char *cmptype, char **optname, char **optvalue, int Nopt, char *outdata, int *Nout, int out_pixsize));
+int     gfits_distribute_data  	       PROTO((Matrix *matrix, int bitpix, char *data, int Ndata, int *otile, int *ztile, float zscale, float zzero));
+int     gfits_byteswap_zdata   	       PROTO((char *zdata, int Nzdata, int bitpix));
+int     gfits_extension_is_compressed  PROTO((Header *header));
+int     gfits_tile_size                PROTO((Matrix *matrix, int *otile, int *ztile));
+int     gfits_uncompressed_data_pixsize PROTO((char *cmptype, int out_bitpix));
+int     gfits_vartable_heap_pixsize    PROTO((char format));
+
+/******************************* Table functions *************/
+
+char   *gfits_table_print              PROTO((FTable *ftable,...));
+int     gfits_add_rows                 PROTO((FTable *ftable, char *data, int Nrow, int Nbytes));
+int     gfits_bintable_format          PROTO((char *format, char *type, int *Nval, int *Nbytes));
+int     gfits_create_table             PROTO((Header *header, FTable *ftable));
+int     gfits_create_table_header      PROTO((Header *header, char *type, char *extname));
+int     gfits_define_bintable_column   PROTO((Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero));
+int     gfits_define_table_column      PROTO((Header *header, char *format, char *label, char *comment, char *unit));
+int   	gfits_fread_ftable             PROTO((FILE *f, FTable *ftable, char *extname)); 
+int   	gfits_fread_ftable_data        PROTO((FILE *f, FTable *ftable));
+int   	gfits_fread_ftable_range       PROTO((FILE *f, FTable *ftable, int start, int Nrows));
+int   	gfits_fread_vtable             PROTO((FILE *f, VTable *vtable, char *extname, int Nrow, int *row));
+int   	gfits_fread_vtable_range       PROTO((FILE *f, VTable *vtable, int start, int Nrows));
+int     gfits_free_table               PROTO((FTable *ftable));
+int     gfits_free_vtable              PROTO((VTable *vtable));
+int     gfits_fwrite_table             PROTO((FILE *f, FTable *table));
+int     gfits_fwrite_vtable            PROTO((FILE *f, VTable *table));
+int     gfits_fwrite_ftable_range      PROTO((FILE *f, FTable *table, int start, int Nrows, int Ndisk, int Ntotal));
+int     gfits_get_bintable_column      PROTO((Header *header, FTable *table, char *label, void **data));
+int     gfits_get_bintable_column_type PROTO((Header *header, char *label, char *type, int *Nval));
+int     gfits_get_table_column         PROTO((Header *header, FTable *table, char *label, void **data));
+int     gfits_get_table_column_type    PROTO((Header *header, char *label, char *type));
+int     gfits_read_ftable              PROTO((char *filename, FTable *table, char *extname));
+int     gfits_read_table               PROTO((char *filename, FTable *ftable)); 
+int     gfits_set_bintable_column      PROTO((Header *header, FTable *table, char *label, void *data, int Nrow));
+int     gfits_set_table_column         PROTO((Header *header, FTable *table, char *label, void *data, int Nrow));
+int     gfits_table_column             PROTO((FTable *ftable, char *field, char *mode,...));
+int     gfits_table_format             PROTO((char *format, char *type, int *Nval, int *Nbytes));
+int     gfits_table_scale_data         PROTO((FTable *ftable));
+int     gfits_table_scale_storage      PROTO((FTable *ftable));
+int     gfits_table_to_vtable          PROTO((FTable *ftable, VTable *vtable, int start, int Nkeep));
+int     gfits_vadd_rows                PROTO((VTable *vtable, char *data, int Nrow, int Nbytes));
+int     gfits_vtable_from_ftable       PROTO((FTable *ftable, VTable *vtable, int *row, int Nrow));
+int     gfits_write_table              PROTO((char *filename, FTable *ftable)); 
+
+int     gfits_create_Theader           PROTO((Header *header, char *type));
+int     gfits_fread_Theader            PROTO((FILE *f, Header *header));
+int     gfits_fwrite_Theader           PROTO((FILE *f, Header *header));
+int     gfits_load_Theader             PROTO((FILE *f, Header *header));
+int     gfits_read_Theader             PROTO((char *filename, Header *header));     
+int     gfits_write_Theader            PROTO((char *filename, Header *header));
+
+int     gfits_varlength_column_define  PROTO((FTable *ftable, VarLengthColumn *def, int column));
+void   *gfits_varlength_column_pointer PROTO((FTable *ftable, VarLengthColumn *column, int row, int *length));
+
+#endif /* FITSIO */
Index: /branches/eam_branch_20080223/Ohana/src/libfits/lib/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/lib/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/lib/.cvsignore	(revision 16632)
@@ -0,0 +1,3 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.darwin.dylib
+*.darwin_x86.dylib
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_add_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_add_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_add_M.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits insert array ***********************************/
+void gfits_add_matrix (matrix, array, x, y) 
+Matrix *matrix, *array; 
+int x, y;
+{
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, j;
+  double V;
+
+  if ((x + array[0].Naxis[0] > matrix[0].Naxis[0]) ||
+      (y + array[0].Naxis[1] > matrix[0].Naxis[1])) {
+    fprintf (stderr, "can't add array here: (%d,%d) - (%d,%d) vs (%d,%d)\n",
+	     x, y, x + array[0].Naxis[0], y + array[0].Naxis[1],
+	     matrix[0].Naxis[0], matrix[0].Naxis[1]);
+    return;
+  }
+
+  for (i = 0; i < array[0].Naxis[0]; i++) {
+    for (j = 0; j < array[0].Naxis[1]; j++) {
+      V = gfits_get_matrix_value (array, i, j);
+      V += gfits_get_matrix_value (matrix, x + i, y + j);
+      gfits_set_matrix_value (matrix, x + i, y + j, V);
+    }
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_add_M_value.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_add_M_value.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_add_M_value.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***************** fits add matrix value ***********************************/
+void gfits_add_matrix_value (matrix, x, y, Value) 
+Matrix *matrix; 
+int x, y; 
+double Value;
+{
+
+  double value;
+
+  value = gfits_get_matrix_value (matrix, x, y);
+  value += Value;
+  gfits_set_matrix_value (matrix, x, y, value);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_compress_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_compress_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_compress_M.c	(revision 16632)
@@ -0,0 +1,472 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <zlib.h>
+
+# define MOD_KEYWORD(NAME,ZNAME,TYPE,IN,OUT) { \
+  gfits_scan (header, ZNAME, TYPE, 1, IN); \
+  gfits_delete (header, ZNAME, 1); \
+  gfits_print (header, NAME, TYPE, 1, OUT); }
+
+# define MOD_KEYWORD_REQUIRED(ZNAME,NAME,TYPE,IN,OUT) { \
+  if (!gfits_scan (header, ZNAME, TYPE, 1, IN)) ESCAPE; \
+  gfits_delete (header, ZNAME, 1); \
+  gfits_print (header, NAME, TYPE, 1, OUT); }
+
+# define ESCAPE { \
+  if (ztile != NULL) free (ztile); \
+  if (optname != NULL) { \
+    for (j = 0; j < Noptions; j++) { \
+      free (optname[j]); \
+      free (optvalue[j]); \
+    } \
+    free (optname); \
+    free (optvalue); \
+  } \
+  if (out != NULL) free (out); \
+  if (otile != NULL) free (otile); \
+  if (ntile != NULL) free (ntile); \
+  return (FALSE); }
+
+int gfits_uncompress_image (Header *header, Matrix *matrix, FTable *ftable) {
+
+  int i, j, status, zimage, zcol, Nzrows, Nout, Nzdata, max_tile_size;
+  char cmptype[80];
+  char zaxis[10], naxis[10], key[10], word[81], exttype[81], checksum[81], datasum[81];
+  int Noptions, NOPTIONS;
+  VarLengthColumn zdef;
+  float zscale, zzero;
+
+  int zdata_pixsize, odata_pixsize, idata_pixsize;
+
+  int *ztile = NULL;
+  int *otile = NULL;
+  int *ntile = NULL;
+  char **optname = NULL;
+  char **optvalue = NULL;
+  char *out = NULL;
+  char *zdata = NULL;
+
+  Noptions = 0;
+
+  // is ZIMAGE present?
+  status = gfits_scan (ftable->header, "ZIMAGE", "%t", 1, &zimage);
+  if (!status || !zimage) ESCAPE;
+
+  // copy original header to output header
+  gfits_copy_header (ftable->header, header);
+
+  // extract compression-specific keywords, update header as needed.
+  if (!gfits_scan (header, "ZCMPTYPE", "%s", 1, cmptype)) ESCAPE;
+  gfits_delete (header, "ZCMPTYPE", 1);
+
+  MOD_KEYWORD_REQUIRED ("ZBITPIX", "BITPIX", "%d", &header->bitpix, header->bitpix);
+  MOD_KEYWORD_REQUIRED ("ZNAXIS",  "NAXIS",  "%d", &header->Naxes,  header->Naxes);
+
+  for (i = 0; i < header->Naxes; i++) {
+    snprintf (zaxis, 10, "ZNAXIS%d", i + 1);
+    snprintf (naxis, 10, "NAXIS%d", i + 1);
+    MOD_KEYWORD_REQUIRED (zaxis,  naxis,  "%d", &header->Naxis[i],  header->Naxis[i]);
+  }    
+
+  // set up the tile sizes
+  ALLOCATE (ztile, int, header->Naxes);
+  if (!gfits_scan (header, "ZTILE1", "%d", 1, &ztile[0])) {
+    ztile[0] = header->Naxis[0];
+    for (i = 1; i < header->Naxes; i++) {
+      ztile[i] = 1;
+    }
+  } else {
+    for (i = 1; i < header->Naxes; i++) {
+      snprintf (key, 10, "ZTILE%d", i + 1);
+      if (!gfits_scan (header, key, "%d", 1, &ztile[i])) ESCAPE;
+      gfits_delete (header, key, 1);
+    }
+  }
+
+  // search for algorithm-specific keywords
+  NOPTIONS = 10;
+  ALLOCATE (optname, char *, NOPTIONS);
+  ALLOCATE (optvalue, char *, NOPTIONS);
+  for (Noptions = 0; TRUE; Noptions++) {
+    snprintf (key, 10, "ZNAME%d", Noptions + 1);
+    if (!gfits_scan (header, key, "%s", 1, word)) break;
+    gfits_delete (header, key, 1);
+    optname[Noptions] = strcreate (word);
+
+    snprintf (key, 10, "ZVAL%d", Noptions + 1);
+    if (!gfits_scan (header, key, "%s", 1, word)) ESCAPE;
+    gfits_delete (header, key, 1);
+    optvalue[Noptions] = strcreate (word);
+
+    if (Noptions == NOPTIONS - 1) {
+      NOPTIONS += 10;
+      REALLOCATE (optname, char *, NOPTIONS);
+      REALLOCATE (optvalue, char *, NOPTIONS);
+    }
+  }
+
+  // XXX is Noptions set to the correct value?
+  // XXX get ZMASKCMP 
+  int zsimple, have_zsimple;
+  int have_ztension;
+
+  have_zsimple  = gfits_scan (header, "ZSIMPLE", "%t", 1, &zsimple);
+  have_ztension = gfits_scan (header, "ZTENSION", "%s", 1, exttype);
+
+  if (!have_zsimple && !have_ztension) ESCAPE;
+  if ( have_zsimple &&  have_ztension) ESCAPE;
+
+  // have_zsimple : image comes from a PHU
+  if (have_zsimple) {
+    header->simple = zsimple;
+    gfits_delete (header, "ZSIMPLE", 1);
+    gfits_extended_to_primary (header, header->simple, "Image data");
+
+    MOD_KEYWORD ("ZEXTEND",  "EXTEND",   "%t", &header->extend, header->extend);
+    MOD_KEYWORD ("ZBLOCKED", "BLOCKED",  "%t", &header->extend, header->extend);
+  } else {
+    gfits_delete (header, "ZTENSION", 1);
+    gfits_modify_extended (header, exttype, "Image extension");
+    // XXX validate that exttype == 'IMAGE'?
+
+    MOD_KEYWORD ("ZPCOUNT",  "PCOUNT",   "%d", &header->pcount, header->pcount);
+    MOD_KEYWORD ("ZGCOUNT",  "GCOUNT",   "%d", &header->gcount, header->gcount);
+  }
+
+  MOD_KEYWORD ("ZHECKSUM", "ZHECKSUM", "%s", checksum,        checksum);
+  MOD_KEYWORD ("ZDATASUM", "DATASUM",  "%s", datasum,         datasum);
+
+  zscale = 1;
+  gfits_scan (header, "ZSCALE", "%lf", 1, &zscale);
+
+  zzero = 0;
+  gfits_scan (header, "ZZERO", "%lf", 1, &zzero);
+
+  // find the COMPRESSED_DATA column (format should be 1PB, 1PI, 1PJ)
+  for (i = 1; TRUE; i++) {
+    snprintf (key, 10, "TTYPE%d", i);
+    if (!gfits_scan (ftable->header, key, "%s", 1, word)) ESCAPE;
+    if (!strcmp (word, "COMPRESSED_DATA")) break;
+  }
+  zcol = i;
+
+  if (!gfits_varlength_column_define (ftable, &zdef, zcol)) ESCAPE;
+
+  // create the output image
+  gfits_create_matrix (header, matrix);
+
+  // counters for tile numbers
+  ALLOCATE (otile, int, matrix->Naxes);
+  ALLOCATE (ntile, int, matrix->Naxes);
+  max_tile_size = 1;
+  for (i = 0; i < matrix->Naxes; i++) {
+    otile[i] = 0;
+    ntile[i] = (matrix->Naxis[i] % ztile[i]) ? (matrix->Naxis[i] / ztile[i] + 1) : (matrix->Naxis[i] / ztile[i]);
+    max_tile_size *= ztile[i];
+  }
+
+  // this takes place in three major steps:
+  // 1) read the table data : zdef.format tells the size of the varlength heap element
+  // 2) uncompress the data : pixel size depends on compression method
+  // 3) distribute data to the tiles : output pixel size depends on header.bitpix
+
+  // heapdata -> zdata -> odata -> idata
+
+  // heapdata.pixsize : zdef.format
+  // zdata.pixsize : depends on compression
+  // odata.pixsize : depends on compression
+  // idata.pixsize : header.bitpix
+
+  // size of an element in the vartable heap section
+  zdata_pixsize = gfits_vartable_heap_pixsize (zdef.format);
+
+  // size of a pixel in the final image
+  idata_pixsize = abs(header[0].bitpix) / 8;
+
+  // size of a pixel in the output from the decompression routine
+  odata_pixsize = gfits_uncompressed_data_pixsize (cmptype, header[0].bitpix);
+  ALLOCATE (out, char, odata_pixsize*max_tile_size);
+
+  // uncompress the data
+  Nzrows = ftable->header->Naxis[1];
+  for (i = 0; i < Nzrows; i++) {
+
+    // expected output size for this tile
+    Nout = gfits_tile_size (matrix, otile, ztile);
+
+    zdata = gfits_varlength_column_pointer (ftable, &zdef, i, &Nzdata);
+    if (!zdata) return (FALSE);
+
+    // XXX not certain this is the correct place to do the swap (or if zdata_pixsize is
+    // the correct size to guide the swap)
+    if (!gfits_byteswap_zdata (zdata, Nzdata, zdata_pixsize)) return (FALSE);
+
+    // gfits_uncompress_data uncompresses from zdata to the temporary output buffer which must be allocated
+    if (!gfits_uncompress_data ((char *)zdata, Nzdata, cmptype, optname, optvalue, Noptions, out, &Nout, odata_pixsize)) return (FALSE);
+
+    // copy the uncompressed pixels into their correct locations 	    
+    if (!gfits_distribute_data (matrix, odata_pixsize, out, Nout, otile, ztile, zscale, zzero)) return (FALSE);
+
+    // update the tile counters, carrying to the next dimension if needed
+    for (j = 0; j < matrix->Naxes; j++) {
+      otile[j] ++;
+      if (otile[j] == ntile[j]) {
+	otile[j] = 0;
+      } else {
+	break;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+// gfits_varlength returns a pointer to a chunk of Nzdata of data elements starting at zdata.
+
+// XXX need to have an API to send the user data
+
+// XXX need to byte-swap the table column; this needs to be worked out more clearly
+// in the APIs: do the table read / column extract functions swap or not?.  we have
+// put the byte-swapping in gifts_varlength_column_pointer, but this is fairly weak.
+
+// XXX inconsistency between data element size between compressed data, uncompressed data, 
+// and output pixel data.....
+
+int gfits_tile_size (Matrix *matrix, int *otile, int *ztile) {
+
+  int i, Npixels, Ndimen;
+
+  // true sizes of this tile (in pixels)
+  Npixels = 1;
+  for (i = 0; i < matrix->Naxes; i++) {
+    Ndimen = MIN ((matrix->Naxis[i] - otile[i]*ztile[i]), ztile[i]);
+    Npixels *= Ndimen;
+  }
+  
+  return (Npixels);
+}
+
+// bitpix is the input data size/type
+int gfits_distribute_data (Matrix *matrix, int bitpix, char *data, int Ndata, int *otile, int *ztile, float zscale, float zzero) {
+
+  int i, j, start, offset, coord, Nline;
+  int *counter = NULL;
+  int *Ztile = NULL;
+
+  ALLOCATE (counter, int, matrix->Naxes);
+  ALLOCATE (Ztile, int, matrix->Naxes);
+
+  // counter for current row in tile to copy
+  // true sizes of this tile (in pixels)
+  for (i = 0; i < matrix->Naxes; i++) {
+    counter[i] = 0;
+    Ztile[i] = MIN ((matrix->Naxis[i] - otile[i]*ztile[i]), ztile[i]);
+  }
+
+  // number of lines in the tile (in pixels)
+  Nline = 1;
+  for (i = 1; i < matrix->Naxes; i++) {
+    Nline *= Ztile[i];
+  }
+
+  // double check reported size (needs the Isize)
+  assert (Ndata == Ztile[0]*Nline);
+
+  // set the starting point of the tile:
+  // start = otile[0]*ztile[0] + otile[1]*ztile[1]*Naxis[0] + otile[2]*ztile[2]*Naxis[0]*Naxis[1] + ...;
+  // start = otile[0]*ztile[0] + Naxis[0]*(otile[1]*ztile[1] + Naxis[1]*(otile[2]*ztile[2] + ...));
+  start = otile[matrix->Naxes-1]*ztile[matrix->Naxes-1];
+  for (i = matrix->Naxes - 2; i >= 0; i--) {
+    coord = otile[i]*ztile[i];
+    start = start*matrix->Naxis[i] + coord;
+  }
+  
+  // pixel offset in output array relative to tile start
+  offset = 0;
+
+  // we need to set up switches for all of the possible combinations:
+  // this macro is used at the inner switch to run the actual loop
+# define SCALE_AND_DIST(TYPE, SIZE) { \
+    TYPE *Optr = (TYPE *) &matrix->buffer[SIZE*(offset + start)]; \
+    for (j = 0; j < Ztile[0]; j++, Iptr++, Optr++) { \
+      *Optr = *Iptr * zscale + zzero; \
+    } }
+
+  // this macro sets up the outer switch and calls above macro with all output bitpix options
+# define SETUP_INSIZE(TYPE, SIZE) { \
+    TYPE *Iptr = (TYPE *) &data[i*SIZE*Ztile[0]]; \
+    switch (matrix->bitpix) { \
+      case 8: \
+	SCALE_AND_DIST (char, 1); \
+	break; \
+      case 16: \
+	SCALE_AND_DIST (short, 2); \
+	break; \
+      case 32: \
+	SCALE_AND_DIST (int, 4); \
+	break; \
+      case -32: \
+	SCALE_AND_DIST (float, 4); \
+	break; \
+      case -64: \
+	SCALE_AND_DIST (double, 8); \
+	break; \
+      default: \
+	abort(); \
+    } }
+
+  // loop over lines in the tile
+  for (i = 0; i < Nline; i++) {
+    switch (bitpix) {
+      case 1:
+	SETUP_INSIZE (char, 1);
+	break;
+      case 2: 
+	SETUP_INSIZE (short, 2);
+	break; 
+      case 4:
+	SETUP_INSIZE (int, 4);
+	break;
+      default:
+	abort();
+    }
+
+    // update the counters, carrying to the next dimension if needed
+    for (j = 1; j < matrix->Naxes; j++) {
+      counter[j] ++;
+      if (counter[j] == Ztile[j]) {
+	counter[j] = 0;
+      } else {
+	break;
+      }
+    }
+    if (j == matrix->Naxes) assert (i == Nline - 1); // we should be done here...
+
+    // Naxes = 3
+    // offset = counter[1]*matrix->Naxis[0] + counter[2]*matrix->Naxis[0]*matrix->Naxis[1] + 
+    // offset = matrix->Naxis[0]*(counter[1] + matrix->Naxis[1]*(counter[2] + matrix->Naxis[2]*...))
+
+    // determine the offset of the next line relative to the start position
+    offset = counter[matrix->Naxes - 1];
+    for (j = matrix->Naxes - 2; j >= 0; j--) {
+      offset = offset*matrix->Naxis[j] + counter[j];
+    }      
+  }
+
+  free (counter);
+  free (Ztile);
+  return (TRUE);
+}
+
+int gfits_byteswap_zdata (char *zdata, int Nzdata, int pixsize) {
+
+# ifdef BYTE_SWAP
+
+  int i;
+  char tmp;
+
+  switch (pixsize) {
+    case 1:
+      break;
+
+    case 2:
+      for (i = 0; i < Nzdata; i+=2) {
+	tmp = zdata[i];
+	zdata[i] = zdata[i+1];
+	zdata[i+1] = tmp;
+      }
+      break;
+
+    case 4:
+      for (i = 0; i < Nzdata; i+=4) {
+	tmp = zdata[i+1];
+	zdata[i+1] = zdata[i+2];
+	zdata[i+2] = tmp;
+	tmp = zdata[i];
+	zdata[i] = zdata[i+3];
+	zdata[i+3] = tmp;
+      }
+      break;
+
+    case 8:
+      for (i = 0; i < Nzdata; i+=8) {
+	tmp = zdata[i+0];
+	zdata[i+0] = zdata[i+7];
+	zdata[i+7] = tmp;
+	tmp = zdata[i+1];
+	zdata[i+1] = zdata[i+6];
+	zdata[i+6] = tmp;
+	tmp = zdata[i+2];
+	zdata[i+2] = zdata[i+5];
+	zdata[i+5] = tmp;
+	tmp = zdata[i+3];
+	zdata[i+3] = zdata[i+4];
+	zdata[i+4] = tmp;
+      }
+      break;
+  }
+# endif
+  return (TRUE);
+}
+
+int gfits_extension_is_compressed (Header *header) {
+
+    int has_extname, has_zimage, zimage;
+    char extname[80];
+
+    has_extname = gfits_scan (header, "EXTNAME", "%s", 1, extname);
+    has_zimage  = gfits_scan (header, "ZIMAGE", "%t", 1, &zimage);
+
+    if (has_zimage && zimage) return (TRUE);
+    if (has_extname) {
+	if (!strcmp (extname, "COMPRESSED_IMAGE")) return (TRUE);
+    }
+
+    return (FALSE);
+}
+
+int gfits_compressed_is_primary (Header *header) {
+
+    int has_ztension, has_zimage;
+    int ztension, zimage;
+
+    has_zimage   = gfits_scan (header, "ZIMAGE",   "%t", 1, &zimage);
+    has_ztension = gfits_scan (header, "ZTENSION", "%t", 1, &ztension);
+
+    if (has_zimage && zimage) return (TRUE);
+
+    return (FALSE);
+}
+
+int gfits_uncompressed_data_pixsize (char *cmptype, int out_bitpix) {
+
+  if (!strcasecmp(cmptype, "GZIP_1")) {
+    return (4);
+  }
+  if (!strcasecmp(cmptype, "RICE_1")) {
+    return (4);
+  }
+  if (!strcasecmp(cmptype, "PLIO_1")) {
+    return (1);
+  }
+  if (!strcasecmp(cmptype, "HCOMPRESS_1")) {
+    if (out_bitpix == 8)  return (4);
+    if (out_bitpix == 16) return (4);
+    return (8);
+  }
+  return (0);
+}
+
+int gfits_vartable_heap_pixsize (char format) {
+
+  if (format == 'B') {
+      return (1);
+  }
+  if (format == 'I') {
+      return (2);
+  }
+  if (format == 'J') {
+      return (4);
+  }
+  fprintf (stderr, "invalid size for compressed data: %c\n", format);  
+  abort ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_convert_format.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_convert_format.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_convert_format.c	(revision 16632)
@@ -0,0 +1,392 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+# define CONVERTDOWN \
+  inMode  *in; \
+  outMode *out; \
+  out = (outMode *) matrix[0].buffer; \
+  in  = (inMode  *) matrix[0].buffer; \
+  for (i = 0; i < Npixels; i++, out++, in++) \
+    *out = *in*A + B; \
+  REALLOCATE (matrix[0].buffer, char, matrix[0].size); 
+
+# define CONVERTSAME \
+  inMode  *in; \
+  outMode *out; \
+  out = (outMode *) matrix[0].buffer; \
+  in  = (inMode  *) matrix[0].buffer; \
+  for (i = 0; i < Npixels; i++, out++, in++) \
+    *out = *in*A + B; 
+
+# define CONVERTUP \
+  inMode  *in; \
+  outMode *out; \
+  REALLOCATE (matrix[0].buffer, char, matrix[0].size); \
+  out = (outMode *)matrix[0].buffer + Npixels - 1; \
+  in  = (inMode  *)matrix[0].buffer + Npixels - 1; \
+  for (i = 0; i < Npixels; i++, out--, in--) \
+    *out = *in*A + B;
+
+/*********************** fits convert format ***********************************/
+int gfits_convert_format (Header *header, Matrix *matrix, int outBitpix, double outScale, double outZero, int outUnsign) {
+
+  unsigned long i, nbytes, Npixels;
+  int    inBitpix, inUnsign;
+  double inScale, inZero;
+  double A, B;
+
+  inBitpix         = header[0].bitpix;
+  inScale          = header[0].bscale;
+  inZero           = header[0].bzero;
+  inUnsign         = header[0].unsign;
+
+  if ((inBitpix == outBitpix) && (inScale == outScale) && 
+      (inZero == outZero) && (inUnsign == outUnsign))
+    return (TRUE);
+
+  matrix[0].bitpix = header[0].bitpix = outBitpix;
+  matrix[0].bscale = header[0].bscale = outScale;
+  matrix[0].bzero  = header[0].bzero  = outZero;
+  matrix[0].unsign = header[0].unsign = outUnsign;
+  matrix[0].size   = gfits_data_size (header);
+  gfits_modify (header, "BITPIX", "%d", 1, outBitpix);
+  gfits_modify (header, "BSCALE", "%lf", 1, outScale);
+  gfits_modify (header, "BZERO",  "%lf", 1, outZero);
+  gfits_modify (header, "UNSIGN", "%t", 1, outUnsign);
+
+  Npixels          = header[0].Naxis[0]*header[0].Naxis[1];
+  nbytes           = Npixels * (abs(outBitpix) / 8);
+
+  A = inScale / outScale;
+  B = (inZero - outZero) / outScale;
+
+  if ((!outUnsign) && (!inUnsign)) {  /** BLOCK 1 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef unsigned char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTSAME; break; }
+	case 16:  { typedef short          outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short outMode; CONVERTUP;   break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTDOWN; break; }
+	case -32: { typedef float          outMode; CONVERTDOWN; break; }
+	case -64: { typedef double         outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((outUnsign) && (!inUnsign)) {  /** BLOCK 3 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef unsigned char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef          char   outMode; CONVERTSAME; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef          char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef          char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef          char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef          char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef          char   outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTDOWN; break; }
+	case -32: { typedef          float  outMode; CONVERTDOWN; break; }
+	case -64: { typedef          double outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((!outUnsign) && (inUnsign)) {  /** BLOCK 2 **/
+    switch (inBitpix) {
+    case 8: 
+      { typedef unsigned char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTSAME; break; }
+	case 16:  { typedef short          outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short outMode; CONVERTUP;   break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short outMode; CONVERTSAME; break; }
+	case 32:  { typedef int            outMode; CONVERTUP;   break; }
+	case -32: { typedef float          outMode; CONVERTUP;   break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef unsigned int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -32: 
+      { typedef float inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTSAME; break; }
+	case -32: { typedef float          outMode; CONVERTSAME; break; }
+	case -64: { typedef double         outMode; CONVERTUP;   break; }
+	}
+      }
+      break;
+    case -64: 
+      { typedef double inMode;
+	switch (outBitpix) {
+	case 8:   { typedef unsigned char  outMode; CONVERTDOWN; break; }
+	case 16:  { typedef short          outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short outMode; CONVERTDOWN; break; }
+	case 32:  { typedef int            outMode; CONVERTDOWN; break; }
+	case -32: { typedef float          outMode; CONVERTDOWN; break; }
+	case -64: { typedef double         outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+  if ((outUnsign) && (inUnsign)) {
+    switch (inBitpix) {
+    case 8: 
+      { typedef char inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char            outMode; CONVERTSAME; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTUP;   break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char            outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case -16: 
+      { typedef unsigned short inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char            outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTSAME; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTUP;   break; }
+	case -32: { typedef          float  outMode; CONVERTUP;   break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}
+      }
+      break;  
+    case 32: 
+      { typedef unsigned int inMode;
+	switch (outBitpix) {
+	case 8:   { typedef char            outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}				    
+      }					    
+      break;				    
+    case -32: 				    
+      { typedef float inMode;		    
+	switch (outBitpix) {		    
+	case 8:   { typedef char            outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTSAME; break; }
+	case -32: { typedef          float  outMode; CONVERTSAME; break; }
+	case -64: { typedef          double outMode; CONVERTUP;   break; }
+	}				    
+      }					    
+      break;				    
+    case -64: 				    
+      { typedef double inMode;		    
+	switch (outBitpix) {		    
+	case 8:   { typedef char            outMode; CONVERTDOWN; break; }
+	case 16:  { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case -16: { typedef unsigned short  outMode; CONVERTDOWN; break; }
+	case 32:  { typedef unsigned int    outMode; CONVERTDOWN; break; }
+	case -32: { typedef          float  outMode; CONVERTDOWN; break; }
+	case -64: { typedef          double outMode; CONVERTSAME; break; }
+	}
+      }
+    }
+  }
+
+  /* zero the padding region */
+  {
+    char *out;
+    int Nextra;
+    
+    out = (char *)matrix[0].buffer;
+    Nextra = matrix[0].size - nbytes;
+    bzero (&out[nbytes], Nextra);
+  }
+
+  return (TRUE);
+}
+ 
+/* WARNING --- this is STILL machine dependant.  It will now work on all 
+   machines, as long as char, int, short, float, double have sizes of 
+   8, 16, 32, 32, 64 bits resp.  However, the floating pt types are NOT
+   universal (or FITS standard), and so can't exchange from machine to 
+   machine. */
+
+/* NOTICE -- This file looks rather strange.  It is set this way to make 
+   all of the possible inter-conversions without too much excess code. 
+   The macros CONVERTUP and CONVERTDOWN need to be distinct.
+   Going to smaller or equal BITPIX, it is safe to run the array forward 
+   and allocate after the conversion.
+   Going to larger BITPIX, you need to reallocate first and run backwards 
+   to avoid wiping out the pixels.
+   OK, to deal with in and out UNSIGN, I have made four if blocks that are
+   almost identical. this looks silly.  any suggestions? 
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_copy_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_copy_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_copy_M.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits copy header ***********************************/
+int gfits_copy_matrix (Matrix *matrix1, Matrix *matrix2) {
+
+  int i;
+
+  matrix2[0].unsign = matrix1[0].unsign;
+  matrix2[0].bitpix = matrix1[0].bitpix;
+  matrix2[0].size   = matrix1[0].size;
+  matrix2[0].bzero  = matrix1[0].bzero;
+  matrix2[0].bscale = matrix1[0].bscale;
+  matrix2[0].Naxes  = matrix1[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    matrix2[0].Naxis[i] = matrix1[0].Naxis[i];
+
+  ALLOCATE (matrix2[0].buffer, char, matrix2[0].size);
+  
+  memcpy (matrix2[0].buffer, matrix1[0].buffer, matrix2[0].size);
+
+  return (TRUE);
+}	
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_create_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_create_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_create_M.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits create matrix *******************************/
+int gfits_create_matrix (header, matrix) 
+Header *header;
+Matrix *matrix;
+{
+
+  int i, Nbytes;
+
+  matrix[0].bitpix = header[0].bitpix;
+  matrix[0].unsign = header[0].unsign;
+  matrix[0].bscale = header[0].bscale;
+  matrix[0].bzero  = header[0].bzero;
+  matrix[0].Naxes  = header[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = header[0].Naxis[i];
+
+  Nbytes = gfits_data_size (header);
+  ALLOCATE (matrix[0].buffer, char, MAX (Nbytes, 1));
+  bzero (matrix[0].buffer, Nbytes);
+  
+  matrix[0].size = Nbytes;
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_divide_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_divide_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_divide_M.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/********************* fits divide matrix ***********************************/
+int gfits_divide_matrix (Matrix *M1, Matrix *M2, Matrix *M3) {
+
+  int i,j;
+  double value, val2;
+
+  if ((M1[0].Naxis[0] != M2[0].Naxis[0]) ||
+      (M1[0].Naxis[1] != M2[0].Naxis[1])) 
+    return (FALSE);
+
+  for (i = 0; i < M1[0].Naxis[0]; i++) {
+    for (j = 0; j < M1[0].Naxis[1]; j++) {
+      value = gfits_get_matrix_value (M1, i, j);
+      val2  = gfits_get_matrix_value (M2, i, j);
+      if (val2 != 0) 
+	value = value / val2;
+      else
+	value = 0.0;
+      gfits_set_matrix_value (M3, i, j, value);
+    }
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_free_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_free_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_free_M.c	(revision 16632)
@@ -0,0 +1,13 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits free matrix ***********************************/
+void gfits_free_matrix (Matrix *matrix) {
+
+  if (matrix[0].buffer == (char *) NULL) return;
+  free (matrix[0].buffer);
+  matrix[0].buffer = (char *) NULL;
+  
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_get_M_value.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_get_M_value.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_get_M_value.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***************** fits get matrix value ***********************************/
+double gfits_get_matrix_value (Matrix *matrix, int x, int y) {
+
+  double value;
+  int pixel;
+
+  if ((x < 0) || (x >= matrix[0].Naxis[0]) || (y < 0) || (y >= matrix[0].Naxis[1]))
+    return (0.0);
+  pixel = matrix[0].Naxis[0]*y + x;
+  value = HUGE_VAL;
+
+  if (matrix[0].unsign) {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((unsigned char  *) matrix[0].buffer + pixel);
+      break;
+    case 16:
+      value = *((unsigned short *) matrix[0].buffer + pixel);
+      break;
+    case 32:
+      value = *((unsigned int   *) matrix[0].buffer + pixel);
+      break;
+    case -32:
+      value = *((float          *) matrix[0].buffer + pixel);
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      break;
+    }
+  }
+  else {
+    switch (matrix[0].bitpix) {
+    case 8:
+      value = *((char  *) matrix[0].buffer + pixel);
+      break;
+    case 16:
+      value = *((short *) matrix[0].buffer + pixel);
+      break;
+    case 32:
+      value = *((int   *) matrix[0].buffer + pixel);
+      break;
+    case -32:
+      value = *((float          *) matrix[0].buffer + pixel);
+      break;
+    case -64:
+      value = *((double         *) matrix[0].buffer + pixel);
+      break;
+    }
+  }
+
+  value = matrix[0].bscale*value + matrix[0].bzero;
+  return (value);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_insert_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_insert_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_insert_M.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits insert array ***********************************/
+void gfits_insert_matrix (Matrix *matrix, Matrix *array, int x, int y) {
+
+  /* there is no check here to match BITPIX, BZERO, or BSCALE */
+
+  int i, start_m, Nbytes_m, Nbytes;
+
+  if ((x + array[0].Naxis[0] > matrix[0].Naxis[0]) ||
+      (y + array[0].Naxis[1] > matrix[0].Naxis[1])) {
+    fprintf (stderr, "can't insert array here: (%d,%d) - (%d,%d) vs (%d,%d)\n",
+	     x, y, x + array[0].Naxis[0], y + array[0].Naxis[1],
+	     matrix[0].Naxis[0], matrix[0].Naxis[1]);
+    return;
+  }
+
+  Nbytes = array[0].Naxis[0]*abs(array[0].bitpix) / 8;
+  Nbytes_m = matrix[0].Naxis[0]*abs(matrix[0].bitpix) / 8;
+  start_m = y*Nbytes_m + x*abs(matrix[0].bitpix) / 8;
+
+  for (i = 0; i < array[0].Naxis[1]; i++) {
+    memmove (&matrix[0].buffer[start_m + i*Nbytes_m], 
+	     &array[0].buffer[i*Nbytes], Nbytes);
+  }
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_load_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_load_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_load_M.c	(revision 16632)
@@ -0,0 +1,103 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_fread_matrix (FILE *f, Matrix *matrix, Header *header) {
+  
+  int status;
+  
+  status = gfits_load_matrix (f, matrix, header);
+  return (status);
+}
+
+/*********************** fits read matrix ***********************************/
+int gfits_load_matrix (FILE *f, Matrix *matrix, Header *header) {
+
+  int i, nbytes, Nbytes;
+
+  matrix[0].bitpix = header[0].bitpix;
+  matrix[0].unsign = header[0].unsign;
+  matrix[0].bscale = header[0].bscale;
+  matrix[0].bzero  = header[0].bzero;
+  matrix[0].Naxes  = header[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = header[0].Naxis[i];
+
+  Nbytes = gfits_data_size (header);
+  ALLOCATE (matrix[0].buffer, char, Nbytes);
+  matrix[0].size = Nbytes;
+
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    perror ("FITS file is short in ##__func__");
+    if (nbytes != gfits_data_min_size (header)) {
+      fprintf (stderr, "error: fits read error in %s", __func__);
+      return (FALSE);
+    }
+    fprintf (stderr, "warning: file missing pad\n");
+  }
+
+# ifdef BYTE_SWAP  
+ {
+  int perpix;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+
+  perpix = abs(header[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	tmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = tmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	tmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = tmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	tmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = tmp;
+	tmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = tmp;
+	tmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = tmp;
+	tmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = tmp;
+      }
+    }
+  }
+ }
+# endif
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file\n");
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in FITS file: (%d, %d)\n", nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_matrix.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_matrix.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_matrix.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_data_size (Header *header) {
+  
+  int i, Nrec, size;
+
+  if (header[0].Naxes == 0) return (0);
+
+  size = abs(header[0].bitpix / 8);
+
+  for (i = 0; i < header[0].Naxes; i++)
+    size *= header[0].Naxis[i];
+
+  // XXX do I multiply this times gcount?
+  size += header[0].pcount;
+
+  /* round up to next complete block */
+  if (size % FT_RECORD_SIZE) {
+    Nrec = 1 + (int) (size / FT_RECORD_SIZE);
+    size = FT_RECORD_SIZE * Nrec;
+  }
+
+  return (size);
+}
+
+int gfits_data_min_size (Header *header) {
+  
+  int i, size;
+
+  if (header[0].Naxes == 0) return (0);
+
+  size = abs(header[0].bitpix / 8);
+
+  for (i = 0; i < header[0].Naxes; i++)
+    size *= header[0].Naxis[i];
+
+  // XXX do I multiply this times gcount?
+  size += header[0].pcount;
+
+  return (size);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_multiply_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_multiply_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_multiply_M.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/******************* fits multiply matrix ***********************************/
+int gfits_multiply_matrix (Matrix *M1, Matrix *M2, Matrix *M3) {
+
+  int i,j;
+  double value;
+
+  if ((M1[0].Naxis[0] != M2[0].Naxis[0]) ||
+      (M1[0].Naxis[1] != M2[0].Naxis[1])) 
+    return (FALSE);
+
+  for (i = 0; i < M1[0].Naxis[0]; i++) {
+    for (j = 0; j < M1[0].Naxis[1]; j++) {
+      value = gfits_get_matrix_value (M1, i, j);
+      value *= gfits_get_matrix_value (M2, i, j);
+      gfits_set_matrix_value (M3, i, j, value);
+    }
+  }
+  
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_M.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read matrix ***********************************/
+int gfits_read_matrix (char *filename, Matrix *matrix) {
+
+  FILE *f;
+  Header header;
+  int status;
+
+  status = gfits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+
+  fseek (f, header.size, 0);
+  
+  status = gfits_load_matrix (f, matrix, &header);
+
+  fclose (f);
+
+  return (status);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_portion.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_portion.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_portion.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# ifndef SEEK_CUR 
+# define SEEK_SET 0   
+# define SEEK_CUR 1   
+# define SEEK_END 2
+# endif
+
+/*********************** fits read matrix ***********************************/
+/** the result of this function is a matrix with dimension Npix * 1 **/
+int gfits_read_portion (char *filename, Matrix *matrix, int Nskip, int Npix) {
+
+  FILE *f;
+  Header header;
+  int status, nbytes, Nbytes, Nrec;
+
+  status = gfits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  matrix[0].bitpix = header.bitpix;
+  matrix[0].unsign = header.unsign;
+  matrix[0].bscale = header.bscale;
+  matrix[0].bzero  = header.bzero;
+  matrix[0].Naxes  = 2;
+  matrix[0].Naxis[0] = Npix;
+  matrix[0].Naxis[1] = 1;
+
+  Nbytes = Npix  * abs (matrix[0].bitpix)/8;
+  Nskip  = Nskip * abs (matrix[0].bitpix)/8;
+
+  /* round up to next complete block */
+  if (Nbytes % FT_RECORD_SIZE) {
+    Nrec = 1 + (int) (Nbytes / FT_RECORD_SIZE);
+    Nbytes = FT_RECORD_SIZE * Nrec;
+  }
+  matrix[0].size = Nbytes;
+  ALLOCATE (matrix[0].buffer, char, Nbytes);
+
+  /* open file, read data, close file */
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+  fseek (f, header.size + Nskip, SEEK_SET);
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    perror ("fits matrix read error");
+  }
+
+  fclose (f);
+
+# ifdef BYTE_SWAP  
+ {
+  int i, perpix;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, ctmp;
+
+  perpix = abs(header.bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	ctmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = ctmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	ctmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = ctmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	ctmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = ctmp;
+	ctmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = ctmp;
+	ctmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = ctmp;
+      }
+    }
+  }
+ }
+# endif
+
+  gfits_free_header (&header);
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file %s (%d < %d - 2880)\n", filename, nbytes, Nbytes);
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in %s: (%d, %d)\n", filename, nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_segment.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_segment.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_read_segment.c	(revision 16632)
@@ -0,0 +1,159 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read matrix ***********************************/
+int gfits_read_matrix_segment (char *filename, Matrix *matrix, char *region) {
+
+  FILE *f;
+  Header header;
+  int status;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return (FALSE);
+  }
+
+  status = gfits_fread_header (f, &header);
+  if (!status) {
+    fclose (f);
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  status = gfits_fread_matrix_segment (f, matrix, &header, region);
+  if (!status) {
+    fclose (f);
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  fclose (f);
+  return (TRUE);
+}
+
+// read header before calling this function
+// file pointer should be at start of Matrix data segment
+int gfits_fread_matrix_segment (FILE *f, Matrix *matrix, Header *header, char *region) {
+
+  int status, i, nbytes, Nbytes, Nskip, NbytesData;
+  int wantaxis[FT_MAX_NAXES][2];
+  double tmp;
+
+  for (i = 0; i < FT_MAX_NAXES; i++) {
+    wantaxis[i][0] = wantaxis[i][1] = 0;
+  }
+
+  for (i = 0; i < header[0].Naxes; i++) {
+    status = dparse (&tmp, 2*i + 1, region);
+    if (!status || (tmp < 0))
+      wantaxis[i][0] = 0;
+    else 
+      wantaxis[i][0] = (tmp > header[0].Naxis[i] - 1) ? header[0].Naxis[i] - 1 : tmp;
+    status = dparse (&tmp, 2*i + 2, region);
+    if (!status || (tmp < 0))
+      wantaxis[i][1] = header[0].Naxis[i];
+    else 
+      wantaxis[i][1] = (tmp > header[0].Naxis[i]) ? header[0].Naxis[i] : tmp;
+  }
+
+  matrix[0].bitpix = header[0].bitpix;
+  matrix[0].unsign = header[0].unsign;
+  matrix[0].bscale = header[0].bscale;
+  matrix[0].bzero  = header[0].bzero;
+  matrix[0].Naxes  = header[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    matrix[0].Naxis[i] = wantaxis[i][1] - wantaxis[i][0];
+
+  matrix[0].size = abs (matrix[0].bitpix) / 8;
+  for (i = 0; i < matrix[0].Naxes; i++)
+    matrix[0].size *= matrix[0].Naxis[i];
+
+  Nskip = wantaxis[2][0]*matrix[0].Naxis[0]*matrix[0].Naxis[1]*abs(matrix[0].bitpix)/8;
+  NbytesData = Nskip + matrix[0].size;
+
+  if (NbytesData % FT_RECORD_SIZE) 
+    Nbytes = FT_RECORD_SIZE * ((int) (NbytesData / FT_RECORD_SIZE) + 1) - Nskip;
+  else 
+    Nbytes = FT_RECORD_SIZE * ((int) (NbytesData / FT_RECORD_SIZE)) - Nskip;
+
+  ALLOCATE (matrix[0].buffer, char, MAX (Nbytes, 1));
+
+# ifndef SEEK_CUR 
+# define SEEK_SET 0   
+# define SEEK_CUR 1   
+# define SEEK_END 2
+# endif
+
+  /* currently only good for reading in full planes in 3-D */
+  fseek (f, Nskip, SEEK_CUR);
+  nbytes = fread (matrix[0].buffer, sizeof(char), Nbytes, f);
+  if (nbytes != Nbytes) {
+    perror ("fits matrix read error");
+  }
+
+  matrix[0].size = Nbytes;
+
+# ifdef BYTE_SWAP  
+ {
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, ctmp;
+  int perpix;
+
+  perpix = abs(header[0].bitpix) / 8;
+  if (perpix > 1) {
+    byte0 = (unsigned char *) matrix[0].buffer;
+    byte1 = (unsigned char *) matrix[0].buffer + 1;
+    byte2 = (unsigned char *) matrix[0].buffer + 2;
+    byte3 = (unsigned char *) matrix[0].buffer + 3;
+    byte4 = (unsigned char *) matrix[0].buffer + 4;
+    byte5 = (unsigned char *) matrix[0].buffer + 5;
+    byte6 = (unsigned char *) matrix[0].buffer + 6;
+    byte7 = (unsigned char *) matrix[0].buffer + 7;
+    if (perpix == 2) {
+      for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	ctmp = *byte0;
+	*byte0 = *byte1;
+	*byte1 = ctmp;
+      }
+    }
+    if (perpix == 4) {
+      for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	ctmp = *byte0;
+	*byte0 = *byte3;
+	*byte3 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte2;
+	*byte2 = ctmp;
+      }
+    }
+    if (perpix == 8) {
+      for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	ctmp = *byte0;
+	*byte0 = *byte7;
+	*byte7 = ctmp;
+	ctmp = *byte1;
+	*byte1 = *byte6;
+	*byte6 = ctmp;
+	ctmp = *byte1;
+	*byte2 = *byte5;
+	*byte5 = ctmp;
+	ctmp = *byte1;
+	*byte3 = *byte4;
+	*byte4 = ctmp;
+      }
+    }
+  }
+ }
+# endif
+
+  if (nbytes < Nbytes - 2880) {  /* this is a bad FITS error: image is not OK */
+    fprintf (stderr, "error reading in matrix data from FITS file (%d < %d - 2880)\n", nbytes, Nbytes);
+    return (FALSE);
+  }
+  if (nbytes != Nbytes) {  /* this is a FITS error, but often the image is OK */
+    fprintf (stderr, "incomplete block in FITS file: (%d, %d)\n", nbytes, Nbytes);
+    return (TRUE); 
+  }
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_set_M_value.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_set_M_value.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_set_M_value.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/****************** fits set matrix value ***********************************/
+void gfits_set_matrix_value (Matrix *matrix, int x, int y, double Value) {
+
+  int pixel;
+  double value;
+
+  pixel = matrix[0].Naxis[0]*y + x;
+  value = (Value - matrix[0].bzero) / matrix[0].bscale;
+
+  if (matrix[0].unsign) {
+    switch (matrix[0].bitpix) {
+    case 8:
+      *((char  *) matrix[0].buffer + pixel) = value;
+      break;
+    case 16:
+      *((short *) matrix[0].buffer + pixel) = value;
+      break;
+    case 32:
+      *((int   *) matrix[0].buffer + pixel) = value;
+      break;
+    case -32:
+      *((float          *) matrix[0].buffer + pixel) = value;
+      break;
+    case -64:
+      *((double         *) matrix[0].buffer + pixel) = value;
+      break;
+    }
+  }
+  else {
+    switch (matrix[0].bitpix) {
+    case 8:
+      *((unsigned char  *) matrix[0].buffer + pixel) = value;
+      break;
+    case 16:
+      *((unsigned short *) matrix[0].buffer + pixel) = value;
+      break;
+    case 32:
+      *((unsigned int   *) matrix[0].buffer + pixel) = value;
+      break;
+    case -32:
+      *((float          *) matrix[0].buffer + pixel) = value;
+      break;
+    case -64:
+      *((double         *) matrix[0].buffer + pixel) = value;
+      break;
+    }
+  }
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_uncompress_data.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_uncompress_data.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_uncompress_data.c	(revision 16632)
@@ -0,0 +1,102 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# include <zlib.h>
+
+/* functions defined in ricecomp.c */
+int fits_rcomp(int a[], int nx,	unsigned char *c, int clen, int nblock);
+int fits_rdecomp (unsigned char *c, int clen, unsigned int array[], int nx, int nblock);
+
+/* functions defined in fits_hcompress.c */
+# define LONGLONG long long
+int fits_hcompress(int *a, int ny, int nx, int scale, char *output, long *nbytes, int *status);
+int fits_hcompress64(LONGLONG *a, int ny, int nx, int scale, char *output, long *nbytes, int *status);
+
+/* functions defined in fits_hdeccompress.c */
+int fits_hdecompress(unsigned char *input, int smooth, int *a, int *ny, int *nx, int *scale, int *status);
+int fits_hdecompress64(unsigned char *input, int smooth, LONGLONG *a, int *ny, int *nx, int *scale, int *status);
+
+/* functions defined in pliocomp.c */
+int pl_p2li (int *pxsrc, int xs, short *lldst, int npix);
+int pl_l2pi (short *ll_src, int xs, int *px_dst, int npix);
+
+int gfits_uncompress_data (char *zdata, int Nzdata, char *cmptype, char **optname, char **optvalue, int Nopt, char *outdata, int *Nout, int out_pixsize) {
+
+  int status;
+  static int Ninsum = 0;
+  static int Noutsum = 0;
+
+  if (!strcasecmp(cmptype, "GZIP_1")) {
+    unsigned long tNout = *Nout * out_pixsize;
+    // uncompress does not require us to know the expected number of pixel; it tells us the number
+    status = uncompress ((Bytef *) outdata, &tNout, (Bytef *) zdata, Nzdata);
+    if (status != Z_OK) {
+      fprintf (stderr, "error in uncompress (GZIP)\n");
+      return (FALSE);
+    }
+    *Nout = tNout;
+    return (TRUE);
+  }
+
+  if (!strcasecmp(cmptype, "RICE_1")) {
+    int i, blocksize;
+    // look for the BLOCKSIZE
+    blocksize = 32;
+    for (i = 0; i < Nopt; i++) {
+      if (!strcmp(optname[i], "BLOCKSIZE")) {
+	blocksize = atoi (optvalue[i]);
+	if ((blocksize != 16) && (blocksize != 32)) {
+	  fprintf (stderr, "RICE blocksize is not valid: %d (%s = %s)\n", blocksize, optname[i], optvalue[i]);
+	  return (FALSE);
+	}
+      }
+    }
+
+    int Npix;
+    // Npix = *Nout * (out_pixsize / 4.0);
+    Npix = *Nout;
+
+    Ninsum += Nzdata;
+    Noutsum += *Nout;
+    // fprintf (stderr, "%d comp bytes; %d uncomp 'pixels', totals: %d %d\n", Nzdata, Npix, Ninsum, Noutsum);
+
+    // rice decompression from the CFITSIO source tree : we need to tell it the expected number of pixels
+    // is also REQUIRES 4byte output, which is fairly stupid.
+    if (fits_rdecomp ((unsigned char *) zdata, Nzdata, (unsigned int *) outdata, Npix, blocksize)) {
+      fprintf (stderr, "error in rice decompression\n");
+      return (FALSE);
+    }
+    return (TRUE);
+  }
+  
+  if (!strcasecmp(cmptype, "PLIO_1")) {
+    int Npix;
+    Npix = pl_l2pi ((short *) zdata, 1, (int *) outdata, *Nout);
+    if (Npix != *Nout) {
+      fprintf (stderr, "error in plio decompression\n");
+      return (FALSE);
+    }
+    return (TRUE);
+  }
+
+  if (!strcasecmp(cmptype, "HCOMPRESS_1")) {
+    int Nx, Ny, scale;
+    status = 0;
+    // call hdecompress without smoothing
+    fits_hdecompress ((unsigned char *) zdata, FALSE, (int *) outdata, &Nx, &Ny, &scale, &status);
+    if (status) {
+      fprintf (stderr, "error in hdecompress\n");
+      return (FALSE);
+    }
+    // fprintf (stderr, "decompression yields image %d x %d (scale: %d)\n", Nx, Ny, scale);
+    
+    if (Nx * Ny != *Nout) {
+      fprintf (stderr, "error in hdecompress: mismatched output size\n");
+      return (FALSE);
+    }
+    return (TRUE);
+  }
+
+  fprintf (stderr, "unknown compression %s\n", cmptype);
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_write_M.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_write_M.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/matrix/F_write_M.c	(revision 16632)
@@ -0,0 +1,152 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write matrix ***********************************/
+int gfits_write_matrix (char *filename, Matrix *matrix) {
+
+  FILE *f;
+  int status;
+
+  f = fopen (filename, "a");
+  if (f == NULL) return (FALSE);
+  
+  fseek (f, 0, SEEK_END);  /* write matrix to end of file! */
+
+  status = gfits_fwrite_matrix (f, matrix);
+  fclose (f);
+  return (status);
+}
+
+/*********************** fits write matrix ***********************************/
+int gfits_fwrite_matrix (FILE *f, Matrix *matrix) {
+
+  int status, nbytes, Nbytes;
+
+  status = TRUE;
+
+  /* this is a bit dangerous: we are not realloc'ing the matrix.
+     if the size is wrong, it probably should simply pad the fwrite statement.
+     better policy should be defined (ie, matrix.size always correct blocking?)
+  */
+
+  if (matrix[0].size % FT_RECORD_SIZE) 
+    nbytes = FT_RECORD_SIZE * ((int) (matrix[0].size / FT_RECORD_SIZE) + 1);
+  else 
+    nbytes = FT_RECORD_SIZE * ((int) (matrix[0].size / FT_RECORD_SIZE));
+
+  /* this is a bit cumbersome: swap all words, write out file, then swap back... */
+# ifdef BYTE_SWAP  
+  { 
+    int i;
+    unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+    int perpix;
+
+    perpix = abs(matrix[0].bitpix) / 8;
+    if (perpix > 1) {
+      byte0 = (unsigned char *) matrix[0].buffer;
+      byte1 = (unsigned char *) matrix[0].buffer + 1;
+      byte2 = (unsigned char *) matrix[0].buffer + 2;
+      byte3 = (unsigned char *) matrix[0].buffer + 3;
+      byte4 = (unsigned char *) matrix[0].buffer + 4;
+      byte5 = (unsigned char *) matrix[0].buffer + 5;
+      byte6 = (unsigned char *) matrix[0].buffer + 6;
+      byte7 = (unsigned char *) matrix[0].buffer + 7;
+      if (perpix == 2) {
+	for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	  tmp = *byte0;
+	  *byte0 = *byte1;
+	  *byte1 = tmp;
+	}
+      }
+      if (perpix == 4) {
+	for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	  tmp = *byte0;
+	  *byte0 = *byte3;
+	  *byte3 = tmp;
+	  tmp = *byte1;
+	  *byte1 = *byte2;
+	  *byte2 = tmp;
+	}
+      }
+      if (perpix == 8) {
+	for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	  tmp = *byte0;
+	  *byte0 = *byte7;
+	  *byte7 = tmp;
+	  tmp = *byte1;
+	  *byte1 = *byte6;
+	  *byte6 = tmp;
+	  tmp = *byte1;
+	  *byte2 = *byte5;
+	  *byte5 = tmp;
+	  tmp = *byte1;
+	  *byte3 = *byte4;
+	  *byte4 = tmp;
+	}
+      }
+    }
+  }
+# endif
+
+  Nbytes = fwrite (matrix[0].buffer, sizeof(char), nbytes, f);
+  if (Nbytes != nbytes) {
+    status = FALSE;
+  }
+
+# ifdef BYTE_SWAP 
+  {
+    int i;
+    unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+    int perpix;
+
+    perpix = abs(matrix[0].bitpix) / 8;
+    if (perpix > 1) {
+      byte0 = (unsigned char *) matrix[0].buffer;
+      byte1 = (unsigned char *) matrix[0].buffer + 1;
+      byte2 = (unsigned char *) matrix[0].buffer + 2;
+      byte3 = (unsigned char *) matrix[0].buffer + 3;
+      byte4 = (unsigned char *) matrix[0].buffer + 4;
+      byte5 = (unsigned char *) matrix[0].buffer + 5;
+      byte6 = (unsigned char *) matrix[0].buffer + 6;
+      byte7 = (unsigned char *) matrix[0].buffer + 7;
+      if (perpix == 2) {
+	for (i = 0; i < nbytes; i+=2, byte0 += 2, byte1 += 2) {
+	  tmp = *byte0;
+	  *byte0 = *byte1;
+	  *byte1 = tmp;
+	}
+      }
+      if (perpix == 4) {
+	for (i = 0; i < nbytes; i+=4, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+	  tmp = *byte0;
+	  *byte0 = *byte3;
+	  *byte3 = tmp;
+	  tmp = *byte1;
+	  *byte1 = *byte2;
+	  *byte2 = tmp;
+	}
+      }
+      if (perpix == 8) {
+	for (i = 0; i < nbytes; i+=8, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+	  tmp = *byte0;
+	  *byte0 = *byte7;
+	  *byte7 = tmp;
+	  tmp = *byte1;
+	  *byte1 = *byte6;
+	  *byte6 = tmp;
+	  tmp = *byte1;
+	  *byte2 = *byte5;
+	  *byte5 = tmp;
+	  tmp = *byte1;
+	  *byte3 = *byte4;
+	  *byte4 = tmp;
+	}
+      }
+    }
+  }
+# endif
+
+  return (status);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_create_T.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_create_T.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_create_T.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits create table *******************************/
+int gfits_create_table (Header *header, FTable *table) {
+
+  int Nbytes;
+  char type[80];
+
+  gfits_scan (header, "XTENSION", "%s", 1, type);
+
+  table[0].header = header;
+  
+  Nbytes = gfits_data_size (header);
+  ALLOCATE (table[0].buffer, char, MAX (Nbytes, 1));
+  if (!strcmp (type, "TABLE")) {
+    memset (table[0].buffer, ' ', Nbytes);
+  } else {
+    memset (table[0].buffer, 0, Nbytes);
+  }
+  table[0].size = Nbytes;
+  return (TRUE);
+
+}
+
+/* init table structure, allocate space for data array (min 1 byte for 0 length) */
+
+/*********************** fits create table *******************************/
+int gfits_create_vtable (Header *header, VTable *table, int Nrow) {
+
+  int i, Nx, Ny;
+  char type[80];
+
+  gfits_scan (header, "XTENSION", "%s", 1, type);
+
+  table[0].header = header;
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[0];
+  table[0].size = gfits_data_size (header);
+  table[0].pad = table[0].size - Nx*Ny;
+ 
+  table[0].Nrow = Nrow;
+  ALLOCATE (table[0].buffer, char *, MAX (Nrow, 1));
+  ALLOCATE (table[0].row, int, MAX (Nrow, 1));
+  for (i = 0; i < Nrow; i++) {
+    ALLOCATE (table[0].buffer[i], char, Nx);
+  }
+  return (TRUE);
+}
+
+/* init table structure, allocate space for data array (min 1 byte for 0 length) */
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_create_TH.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_create_TH.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_create_TH.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define NBYTES 2880
+
+/* a basic table header (extension) is different from a primary header
+   in that it has the word XTENSION and a type for the first line,
+   instead of SIMPLE */
+
+/*********************** fits create Theader *********************************/
+int gfits_create_Theader (Header *header, char *type) {
+  
+  int i;
+  char axis[10];
+  
+  header[0].size = NBYTES;
+
+  ALLOCATE (header[0].buffer, char, NBYTES);
+  
+  for (i = 0; i < NBYTES; i++) 
+  header[0].buffer[i] = ' ';
+  strncpy (header[0].buffer, "END", 3);
+  
+  gfits_modify (header, "XTENSION", "%s", 1, type);
+  gfits_modify (header, "BITPIX",   "%d", 1, header[0].bitpix);
+  gfits_modify (header, "NAXIS",    "%d", 1, header[0].Naxes);
+  
+  for (i = 0; i < header[0].Naxes; i++) {
+    sprintf (axis, "NAXIS%d", i + 1);
+    gfits_modify (header,  axis, "%d", 1, header[0].Naxis[i], 1);
+  }
+  
+  gfits_modify (header, "PCOUNT", "%d", 1, header[0].pcount);
+  gfits_modify (header, "GCOUNT", "%d", 1, header[0].gcount);
+  if (!strcmp (type, "IMAGE")) {
+    gfits_modify (header, "BSCALE", "%lf", 1, header[0].bscale);
+    gfits_modify (header, "BZERO",  "%lf", 1, header[0].bzero);
+  }
+
+  return (TRUE);
+}	
+
+/*********************** fits create table header *********************************/
+int gfits_create_table_header (Header *header, char *type, char *extname) {
+  
+  int i, valid;
+
+  /* check valid table types */
+  valid = FALSE;
+  valid |= !strcmp (type, "TABLE");
+  valid |= !strcmp (type, "BINTABLE");
+  if (!valid) return (FALSE);
+
+  gfits_init_header (header);
+
+  header[0].simple = FALSE;
+  header[0].Naxes  = 2;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    header[0].Naxis[i] = 0;
+
+  gfits_create_Theader (header, type);
+
+  gfits_modify (header, "TFIELDS", "%d", 1, 0);
+  gfits_modify (header, "EXTNAME", "%s", 1, extname);
+  
+  return (TRUE);
+}	
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_define_column.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_define_column.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_define_column.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***********************/
+int gfits_define_bintable_column (Header *header, char *format, char *label, char *comment, char *unit, double bscale, double bzero) {
+
+  int Nfields, Nbytes, Nval, Naxis1;
+  char type[16], field[16];
+  
+  if (!gfits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  Nfields = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Naxis1);
+  Nfields ++;
+  Naxis1 += Nbytes*Nval;
+
+  sprintf (field, "TTYPE%d", Nfields);
+  gfits_modify (header, field, "%s", 1, label);
+  gfits_modify (header, field, "%C", 1, comment);
+  sprintf (field, "TUNIT%d", Nfields);
+  gfits_modify (header, field, "%s", 1, unit);
+  sprintf (field, "TFORM%d", Nfields);
+  gfits_modify (header, field, "%s", 1, format);
+  sprintf (field, "TSCAL%d", Nfields);
+  gfits_modify (header, field, "%lf", 1, bscale);
+  sprintf (field, "TZERO%d", Nfields);
+  gfits_modify (header, field, "%lf", 1, bzero);
+
+  /* update TFIELDS & NAXIS1 */
+  gfits_modify (header, "TFIELDS", "%d", 1, Nfields);
+  gfits_modify (header, "NAXIS1",  "%d", 1, Naxis1);
+  header[0].Naxis[0] = Naxis1;
+
+  return (TRUE);
+}
+
+/***********************/
+int gfits_define_table_column (Header *header, char *format, char *label, char *comment, char *unit) {
+
+  int Nstart, Nfields, Nbytes, Nval, Naxis1;
+  char type[16], field[16], cformat[16];
+
+  strcpy (cformat, format);
+  if (!gfits_table_format (cformat, type, &Nval, &Nbytes)) return (FALSE);
+
+  Nfields = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Naxis1);
+  Nstart = Naxis1 + 1;
+  Nfields ++;
+  Naxis1 += Nbytes*Nval;
+
+  sprintf (field, "TTYPE%d", Nfields);
+  gfits_modify (header, field, "%s", 1, label);
+  gfits_modify (header, field, "%C", 1, comment);
+  sprintf (field, "TUNIT%d", Nfields);
+  gfits_modify (header, field, "%s", 1, unit);
+  sprintf (field, "TFORM%d", Nfields);
+  gfits_modify (header, field, "%s", 1, format);
+
+  sprintf (field, "TBCOL%d", Nfields);
+  gfits_modify (header, field, "%d", 1, Nstart);
+
+  gfits_modify (header, "TFIELDS", "%d", 1, Nfields);
+  gfits_modify (header, "NAXIS1",  "%d", 1, Naxis1);
+  header[0].Naxis[0] = Naxis1;
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_free_T.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_free_T.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_free_T.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_free_table (FTable *table) {
+  
+  if (table[0].buffer == (char *) NULL) return (TRUE);
+  free (table[0].buffer);
+  table[0].buffer = (char *) NULL;
+  return (TRUE);
+}
+
+int gfits_free_vtable (VTable *table) {
+  
+  int i;
+
+  if (table[0].buffer == (char **) NULL) return (TRUE);
+
+  for (i = 0; i < table[0].Nrow; i++) {
+    free (table[0].buffer[i]);
+  }
+  free (table[0].buffer);
+  free (table[0].row);
+
+  table[0].buffer = NULL;
+  table[0].row    = NULL;
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_T_column.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_T_column.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_T_column.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits get table column *****************************/
+void gfits_get_table_column (table, X, mode, values) 
+Table *table; 
+int X; 
+char *mode, **values;
+{
+  
+  char Tform[100], field[100], tmp[100];
+  int  start, Nchar, i, N;
+  
+  int    *Ivalues;
+  long   *Lvalues;
+  short  *Svalues;
+  float  *Fvalues;
+  double *Dvalues;
+  char  **Cvalues;
+  
+  /* no error checking, all sorts of problems! */
+  /* should I count fields from 0 or from 1? */
+  
+  sprintf (field, "TBCOL%d\0", X);
+  gfits_scan (&table[0].header, field, "%d", &start, 1);
+  start --;
+  sprintf (field, "TFORM%d\0", X);
+  gfits_scan (&table[0].header, field, "%s", Tform, 1);
+  Nchar = atof (&Tform[1]);
+  
+  if (!strcmp (mode, "%d")) {
+    ALLOCATE (Ivalues, int, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      strncpy (tmp, &table[0].buffer[i*table[0].Naxis[0] + start], Nchar);
+      tmp[Nchar] = 0;
+      Ivalues[i] = atof (tmp);
+    }
+    values[0] = (char *) Ivalues;
+  }
+  if (!strcmp (mode, "%lf")) {
+    ALLOCATE (Dvalues, double, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      strncpy (tmp, &table[0].buffer[i*table[0].Naxis[0] + start], Nchar);
+      tmp[Nchar] = 0;
+      Dvalues[i] = atof (tmp);
+    }
+    values[0] = (char *) Dvalues;
+  }
+  if ((mode[0] == '%') && (mode[strlen(mode) - 1] == 'c')) {
+    mode[strlen(mode) - 1] = 0;
+    N = atof(&mode[1]);
+    ALLOCATE (Cvalues, char *, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      ALLOCATE (Cvalues[i], char, N + 1);
+      strncpy (Cvalues[i], &table[0].buffer[i*table[0].Naxis[0] + start], N);
+      Cvalues[i][N] = 0;
+    }
+    values[0] = (char *) Cvalues;
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_T_value.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_T_value.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_T_value.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits get table value ********************************/
+  
+void gfits_get_table_value (table, X, Y, mode, value)
+Table *table; 
+int X, Y; 
+char *mode, *value;
+{
+  
+  char Tform[100], field[100];
+  int  start, Nchar, byte;
+  char tmp[1000];
+  
+  /* no error checking, all sorts of problems! */
+  
+  sprintf (field, "TBCOL%d\0", X);
+  gfits_scan (&table[0].header, field, "%d", &start, 1);
+  start --;
+  
+  sprintf (field, "TFORM%d\0", X);
+  gfits_scan (&table[0].header, field, "%s", Tform, 1);
+  Nchar = atof (&Tform[1]);
+  
+  byte = Y*table[0].Naxis[0] + start;
+  strncpy (tmp, &table[0].buffer[byte], Nchar);
+  tmp[Nchar] = 0;
+
+  if (!strcmp (mode, "%d"))  *(int      *) value = (int)      atof (tmp);
+  if (!strcmp (mode, "%u"))  *(unsigned *) value = (unsigned) atof (tmp);
+  if (!strcmp (mode, "%ld")) *(long     *) value = (long)     atof (tmp);
+  if (!strcmp (mode, "%hd")) *(short    *) value = (short)    atof (tmp);
+  if (!strcmp (mode, "%f"))  *(float    *) value = (float)    atof (tmp);
+  if (!strcmp (mode, "%lf")) *(double   *) value = (double)   atof (tmp);
+
+  if (!strcmp (mode, "%s")) 
+    strcpy (value, tmp);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_column.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_column.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_get_column.c	(revision 16632)
@@ -0,0 +1,272 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define SWAP_BYTE { \
+  char tmp; \
+  tmp = Pin[0]; Pin[0] = Pin[1]; Pin[1] = tmp; }
+# define SWAP_WORD { \
+  char tmp; \
+  tmp = Pin[0]; Pin[0] = Pin[3]; Pin[3] = tmp; \
+  tmp = Pin[1]; Pin[1] = Pin[2]; Pin[2] = tmp; }
+# define SWAP_DBLE { \
+  char tmp; \
+  tmp = Pin[0]; Pin[0] = Pin[7]; Pin[7] = tmp; \
+  tmp = Pin[1]; Pin[1] = Pin[6]; Pin[6] = tmp; \
+  tmp = Pin[2]; Pin[2] = Pin[5]; Pin[5] = tmp; \
+  tmp = Pin[3]; Pin[3] = Pin[4]; Pin[4] = tmp; }
+
+/***********************/
+int gfits_get_bintable_column_type (Header *header, char *label, char *type, int *Nval) {
+
+  int i, N, Nfields, Nbytes;
+  char tlabel[80], field[80], format[80];
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_bintable_format (format, type, Nval, &Nbytes)) return (FALSE);
+  return (TRUE);
+}
+
+/***********************/
+int gfits_get_bintable_column (Header *header, FTable *table, char *label, void **data) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], type[16], tmpline[16];
+  char *Pin, *Pout, *array;
+  double Bscale, Bzero;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  Bscale = 1; 
+  Bzero  = 0;
+
+  /* interpret format */
+  sprintf (field, "TSCAL%d", N);
+  gfits_scan (header, field, "%lf", 1, &Bscale);
+  sprintf (field, "TZERO%d", N);
+  gfits_scan (header, field, "%lf", 1, &Bzero);
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_bintable_format (format, tmpline, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* extract bytes from table into temporary array */
+  ALLOCATE (array, char, Nbytes*Nval*Ny);
+  Pin  = table[0].buffer + Nstart;
+  Pout = array;
+  for (i = 0; i < Ny; i++, Pin += Nx, Pout += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  /* convert data in-situ with correct type, byte swap and Bzero/Bscale */
+  Pin  = array;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = *(char *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "short")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      SWAP_BYTE;
+# endif
+      *(short *)Pout = *(short *)Pin*Bscale + Bzero;
+    }  
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      SWAP_WORD;
+# endif
+      *(int *)Pout = *(int *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      SWAP_WORD;
+# endif
+      *(float *)Pout = *(float *)Pin*Bscale + Bzero;
+    }
+  }
+  if (!strcmp (type, "double")) {
+    for (i = 0; i < Nval*Ny; i++, Pin+=Nbytes, Pout+=Nbytes) {
+# ifdef BYTE_SWAP
+      SWAP_DBLE;
+# endif
+      *(double *)Pout = *(double *)Pin*Bscale + Bzero;
+    }
+  }
+
+  *data = array;
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var lenght array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+/***********************/
+int gfits_get_table_column_type (Header *header, char *label, char *type) {
+
+  int i, N, Nfields, Nval, Nbytes;
+  char tlabel[80], field[80], format[80];
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  return (TRUE);
+}
+
+/***********************/
+int gfits_get_table_column (Header *header, FTable *table, char *label, void **data) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], cformat[80], type[16], tmp[16];
+  char *array, *Pin, *Pout, *line;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+  array = NULL;
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  strcpy (cformat, format);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_table_format (format, tmp, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* allocate temporary line, init pointers */
+  ALLOCATE (line, char, Nval+1);
+  bzero (line, Nval+1);
+  Pin  = table[0].buffer + Nstart;
+
+  /* allocate output array, copy/scan line as needed */
+  if (!strcmp (type, "char")) {
+    ALLOCATE (array, char, Ny*Nval);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=Nval*Nbytes) {
+      memcpy (Pout, Pin, Nval*Nbytes);
+    }
+  }
+  if (!strcmp (type, "int")) {
+    ALLOCATE (array, char, Ny*4);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+      memcpy (line, Pin, Nval*Nbytes);
+      sscanf (line, "%d", (int *)Pout);
+    }
+  }
+  if (!strcmp (type, "float")) {
+    ALLOCATE (array, char, Ny*4);
+    Pout = array;
+    for (i = 0; i < Ny; i++, Pin+=Nx, Pout+=4) {
+      memcpy (line, Pin, Nval*Nbytes);
+      sscanf (line, "%f", (float *)Pout);
+    }
+  }
+  *data = array;
+  free (line);
+
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_read_T.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_read_T.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_read_T.c	(revision 16632)
@@ -0,0 +1,232 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read table ***********************************/
+int gfits_read_ftable (char *filename, FTable *table, char *extname) {
+
+  int status;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) return (FALSE);
+
+  status = gfits_fread_ftable (f, table, extname);
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits read table ***********************************/
+int gfits_fread_ftable (FILE *f, FTable *table, char *extname) {
+
+  int j, found, Nbytes;
+  Header *header;
+  char tname[80];
+
+  header = table[0].header;
+  fseek (f, 0, SEEK_SET);
+
+  found = FALSE;
+  for (j = -1; !found; j++) {
+    /* load data for this header */
+    if (!gfits_load_header (f, header)) return (FALSE);
+
+    /* check if this is the correct extension or not */
+    bzero (tname, 80);
+    gfits_scan (header, "EXTNAME", "%s", 1, tname);
+    if (!strcmp (tname, extname)) {
+      if (gfits_fread_ftable_data (f, table)) return (TRUE);
+      gfits_free_header (header);
+      return (FALSE);
+    }
+
+    /* skip to next header */
+    Nbytes = gfits_data_size (header);
+    fseek (f, Nbytes, SEEK_CUR);
+    gfits_free_header (header);
+  }
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fread_ftable_data (FILE *f, FTable *table) {
+
+  int Nbytes, Nread;
+  char string[128];
+
+  /* find buffer size */
+  Nbytes = gfits_data_size (table[0].header);
+  ALLOCATE (table[0].buffer, char, Nbytes);
+
+  Nread = fread (table[0].buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    snprintf (string, 128, "FITS file is short (%s)", __func__);
+    perror (string);
+    if (Nread < gfits_data_min_size (table[0].header)) {
+      fprintf (stderr, "error: fits read error in %s, read %d, need %d\n", __func__, Nread, gfits_data_min_size (table[0].header));
+      gfits_free_table  (table);
+      return (FALSE);
+    }
+    fprintf (stderr, "warning: file missing pad\n");
+  }
+  table[0].size = Nbytes;
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fread_ftable_range (FILE *f, FTable *table, int start, int Nrows) {
+
+  int Nbytes, Nread, Nskip, Nx, Ny;
+
+  /* find disk table size */
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[1];
+
+  // it is an error to ask for data starting out-of-bounds
+  if (start < 0) return (FALSE);
+  if (start >= Ny) return (FALSE);
+  
+  // if we request more data than is available, we will stop at the table end.
+  Nrows = MIN (Nrows, Ny - start);
+
+  Nskip = start * Nx;
+  Nbytes = Nrows * Nx;
+  ALLOCATE (table[0].buffer, char, MAX (Nbytes, 1));
+
+  fseek (f, Nskip, SEEK_CUR);
+
+  Nread = fread (table[0].buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    if (ferror (f)) {
+      perror ("fits read error");
+    } else {
+      fprintf (stderr, "unexpected eof\n");
+    }      
+    free (table[0].buffer);
+    return (FALSE);
+  }
+
+  /* modify structure and header to match actual read rows Ny */
+  table[0].header[0].Naxis[1] = Nrows;
+  gfits_modify (table[0].header, "NAXIS2",  "%d", 1, Nrows);
+  table[0].size = gfits_data_size (table[0].header);
+
+  return (TRUE);
+}	
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fread_vtable_range (FILE *f, VTable *table, int start, int Nrows) {
+
+  int i, Nbytes, Nread, Nskip, Nx, Ny;
+  char *buffer;
+
+  /* find buffer size */
+  Nx = table[0].header[0].Naxis[0];
+  Ny = table[0].header[0].Naxis[1];
+  table[0].size = gfits_data_size (table[0].header);
+  table[0].pad = table[0].size - Nx*Ny;
+
+  if (start < 0) return (FALSE);
+  if (start + Nrows >= Ny) return (FALSE);
+  
+  Nskip = start * Nx;
+  Nbytes = Nrows * Nx;
+  ALLOCATE (buffer, char, MAX (Nbytes, 1));
+
+  fseek (f, Nskip, SEEK_CUR);
+  Nread = fread (buffer, sizeof (char), Nbytes, f);
+  if (Nread != Nbytes) {
+    perror ("fits read error");
+    free (buffer);
+    return (FALSE);
+  }
+
+  ALLOCATE (table[0].row, int, MAX (Nrows, 1));
+  ALLOCATE (table[0].buffer, char *, MAX (Nrows, 1));
+  for (i = 0; i < Nrows; i++) {
+    ALLOCATE (table[0].buffer[i], char, MAX (Nx, 1));
+    memcpy (table[0].buffer[i], &buffer[i*Nx], Nx);
+    table[0].row[i] = start + i;
+  }
+  free (buffer);
+
+  return (TRUE);
+}	
+
+/*********************** fits read virtual table ***********************************/
+int gfits_fread_vtable (FILE *f, VTable *table, char *extname, int Nrow, int *row) {
+
+  int i, j, Nbytes, Nread;
+  int start, Nx, Ny, offset;
+  Header *header;
+  char tname[80];
+
+  header = table[0].header;
+  fseek (f, 0, SEEK_SET);
+
+  for (j = -1; TRUE; j++) {
+    /* load data for this header */
+    if (!gfits_load_header (f, header)) return (FALSE);
+
+    /* find buffer size */
+    Nbytes = gfits_data_size (header);
+
+    /* check if this is the correct extension or not */
+    bzero (tname, 80);
+    gfits_scan (header, "EXTNAME", "%s", 1, tname);
+    if (strcmp (tname, extname)) {
+      /* skip to next header */
+      fseek (f, Nbytes, SEEK_CUR);
+      gfits_free_header (header);
+      continue;
+    }
+
+    /* file pointer is at beginning of desired table data */
+    start = ftell (f);
+    gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+    gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+    for (i = 0; i < Nrow; i++) {
+      if (row[i] > Ny) { return (FALSE); }
+    }
+
+    ALLOCATE (table[0].buffer, char *, MAX (1, Nrow));
+    for (i = 0; i < Nrow; i++) {
+      ALLOCATE (table[0].buffer[i], char, MAX (1, Nx));
+      offset = start + Nx*row[i];
+      fseek (f, offset, SEEK_SET);
+      Nread = fread (table[0].buffer[i], sizeof (char), Nx, f);
+      if (Nread != Nx) { 
+	perror ("fits read error");
+	return (FALSE); 
+      }
+    }
+
+    table[0].Nrow  = Nrow;
+    ALLOCATE (table[0].row, int, MAX (1, Nrow));    
+    for (i = 0; i < Nrow; i++) table[0].row[i] = row[i];
+    table[0].size   = gfits_data_size (table[0].header);
+    table[0].pad    = table[0].size - Nx*Ny;
+    return (TRUE);
+  }
+}	
+
+int gfits_fread_header_extname (FILE *f, Header *header, char *extname) {
+
+  int Nbytes;
+  char current[80];
+
+  fseek (f, 0, SEEK_SET);
+  gfits_fread_header (f, header);
+
+  if (!strcasecmp (extname, "PHU")) return (TRUE);
+
+  Nbytes = gfits_data_size (header);
+  fseek (f, Nbytes, SEEK_CUR);
+
+  while (gfits_fread_header (f, header)) {
+    gfits_scan (header, "EXTNAME", "%s", 1, current);
+    if (!strcmp (current, extname)) return (TRUE);
+    Nbytes = gfits_data_size (header);
+    fseek (f, Nbytes, SEEK_CUR);
+  }
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_read_TH.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_read_TH.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_read_TH.c	(revision 16632)
@@ -0,0 +1,91 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits read Theader ***********************************/
+int gfits_read_Theader (char *filename, Header *Theader) {
+  
+  FILE *f;
+  Header header;
+  int status, Nbytes;
+  
+  status = gfits_read_header (filename, &header);
+  if (!status) {
+    fprintf (stderr, "error reading header of FITS file %s\n", filename);
+    return (FALSE);
+  }
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    Theader[0].buffer = NULL;
+    gfits_free_header (&header);
+    return (FALSE);
+  }
+
+  Nbytes = gfits_data_size (&header);
+  fseek (f, Nbytes, SEEK_SET);
+  gfits_free_header (&header);
+
+  status = gfits_load_Theader (f, Theader);
+  fclose (f);
+  return (status);
+}	
+
+/* load table from STREAM positioned at beginning of table header */
+/*********************** fits load Theader ***********************************/
+int gfits_load_Theader (FILE *f, Header *Theader) {
+  
+  char *p;
+  int i, done, status, Nbytes;
+  
+  Theader[0].size = 0;
+  done = FALSE;
+  ALLOCATE (Theader[0].buffer, char, 1);
+
+  for (i = 0; !done; i++) {
+    REALLOCATE (Theader[0].buffer, char, (i + 1)*FT_RECORD_SIZE);
+    Nbytes = fread (&Theader[0].buffer[i*FT_RECORD_SIZE], 
+		    sizeof(char), FT_RECORD_SIZE, f);
+    if (Nbytes != FT_RECORD_SIZE) {
+      perror ("fits matrix read error");
+    }
+
+    Theader[0].size += Nbytes;
+    if (Nbytes != FT_RECORD_SIZE) 
+      done = TRUE;
+    p = gfits_header_field (Theader, "END", 1);
+    if (p != NULL)
+      done = TRUE;
+  }
+
+  Theader[0].bscale = 0;
+  Theader[0].bzero  = 0;
+  for (i = 0; i < FT_MAX_NAXES; i++)
+    Theader[0].Naxis[i] = 0;
+
+  status = TRUE;
+  status &= gfits_scan (Theader,  "BITPIX", "%d", 1, &Theader[0].bitpix);
+  status &= gfits_scan (Theader,  "NAXIS",  "%d", 1, &Theader[0].Naxes);
+  if (!status) return (FALSE);
+				                           
+  gfits_scan (Theader,  "NAXIS1", "%d", 1, &Theader[0].Naxis[0]);
+  gfits_scan (Theader,  "NAXIS2", "%d", 1, &Theader[0].Naxis[1]);
+  gfits_scan (Theader,  "NAXIS3", "%d", 1, &Theader[0].Naxis[2]);
+  gfits_scan (Theader,  "NAXIS4", "%d", 1, &Theader[0].Naxis[3]);
+  gfits_scan (Theader,  "NAXIS5", "%d", 1, &Theader[0].Naxis[4]);
+  gfits_scan (Theader,  "NAXIS6", "%d", 1, &Theader[0].Naxis[5]);
+  gfits_scan (Theader,  "NAXIS7", "%d", 1, &Theader[0].Naxis[6]);
+  gfits_scan (Theader,  "NAXIS8", "%d", 1, &Theader[0].Naxis[7]);
+  gfits_scan (Theader,  "NAXIS9", "%d", 1, &Theader[0].Naxis[8]);
+  gfits_scan (Theader, "NAXIS10", "%d", 1, &Theader[0].Naxis[9]);
+
+  return (TRUE);
+}	
+
+/*********************** fits fread Theader ***********************************/
+int gfits_fread_Theader (FILE *f, Header *Theader) {
+  
+  int status;
+  
+  status = gfits_load_Theader (f, Theader);
+  return (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_set_column.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_set_column.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_set_column.c	(revision 16632)
@@ -0,0 +1,251 @@
+# include <ohana.h>
+# include <gfitsio.h>
+# define SWAP_BYTE { \
+  char tmp; \
+  tmp = Pout[0]; Pout[0] = Pout[1]; Pout[1] = tmp; }
+# define SWAP_WORD { \
+  char tmp; \
+  tmp = Pout[0]; Pout[0] = Pout[3]; Pout[3] = tmp; \
+  tmp = Pout[1]; Pout[1] = Pout[2]; Pout[2] = tmp; }
+# define SWAP_DBLE { \
+  char tmp; \
+  tmp = Pout[0]; Pout[0] = Pout[7]; Pout[7] = tmp; \
+  tmp = Pout[1]; Pout[1] = Pout[6]; Pout[6] = tmp; \
+  tmp = Pout[2]; Pout[2] = Pout[5]; Pout[5] = tmp; \
+  tmp = Pout[3]; Pout[3] = Pout[4]; Pout[4] = tmp; }
+
+/***********************/
+int gfits_set_bintable_column (Header *header, FTable *table, char *label, void *data, int Nrow) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, nbytes, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], type[16], tmpline[16];
+  char *Pin, *Pout, *array;
+  double Bscale, Bzero;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TSCAL%d", N);
+  gfits_scan (header, field, "%lf", 1, &Bscale);
+  sprintf (field, "TZERO%d", N);
+  gfits_scan (header, field, "%lf", 1, &Bzero);
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_bintable_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+  if (Ny == 0) { 
+    Ny = Nrow;
+    header[0].Naxis[1] = Ny;
+    gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+    nbytes = gfits_data_size (header);
+    REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+    bzero (table[0].buffer, nbytes);
+    table[0].size = nbytes;
+  }
+  if (Ny != Nrow) return (FALSE);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_bintable_format (format, tmpline, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* make duplicate of data with correct type
+     byte swap and Bzero/Bscale */
+  ALLOCATE (array, char, Nbytes*Nval*Nrow);
+  Pin = data;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(char *)Pout = (*(char *)Pin - Bzero) / Bscale;
+    }
+  }
+  if (!strcmp (type, "short")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(short *)Pout = (*(short *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_BYTE;
+# endif
+    }  
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(int *)Pout = (*(int *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(float *)Pout = (*(float *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_WORD;
+# endif
+    }
+  }
+  if (!strcmp (type, "double")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin+=Nbytes, Pout+=Nbytes) {
+      *(double *)Pout = (*(double *)Pin - Bzero) / Bscale;
+# ifdef BYTE_SWAP
+      SWAP_DBLE;
+# endif
+    }
+  }
+
+  /* check array space */
+  if (Nx*Ny < Nx*(Nrow - 1) + Nstart + Nval*Nbytes) {
+    fprintf (stderr, "mismatch in array sizes\n");
+    return (FALSE);
+  }
+
+  /* insert bytes from array into appropriate section of buffer */
+  Pout = table[0].buffer + Nstart;
+  Pin  = array;
+  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  free (array);
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var lenght array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+
+/***********************/
+int gfits_set_table_column (Header *header, FTable *table, char *label, void *data, int Nrow) {
+
+  int i, N, Nfields, Nval, Nbytes, Nx, Ny, nbytes, Nstart, Nv, Nb;
+  char tlabel[80], field[80], format[80], cformat[80], type[16], tmp[16];
+  char *array, *Pin, *Pout, *line;
+
+  if (label == (char *) NULL) return (FALSE);
+  if (label[0] == 0) return (FALSE);
+
+  /* find label in header */
+  tlabel[0] = 0;
+  gfits_scan (header, "TFIELDS", "%d", 1, &Nfields);
+  for (i = 1; strcmp (label, tlabel) && (i < Nfields + 1); i++) {
+    sprintf (field, "TTYPE%d", i);
+    gfits_scan (header, field, "%s", 1, tlabel);
+  }
+  if (strcmp (label, tlabel)) return (FALSE);
+  N = i - 1;
+
+  /* interpret format */
+  sprintf (field, "TFORM%d", N);
+  gfits_scan (header, field, "%s", 1, format);
+
+  if (!gfits_table_format (format, type, &Nval, &Nbytes)) return (FALSE);
+  strcpy (cformat, format);
+  
+  /* check existing table dimensions */
+  gfits_scan (header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2",  "%d", 1, &Ny);
+  if (Ny == 0) { 
+    Ny = Nrow;
+    header[0].Naxis[1] = Ny;
+    gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+    nbytes = gfits_data_size (header);
+    REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+    bzero (table[0].buffer, nbytes);
+    table[0].size = nbytes;
+  }
+  if (Ny != Nrow) return (FALSE);
+
+  /* scan columns to find insert point */
+  Nstart = 0;
+  for (i = 1; i < N; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (header, field, "%s", 1, format);
+    gfits_table_format (format, tmp, &Nv, &Nb);
+    Nstart += Nv*Nb;
+  }
+
+  /* print line with appropriate formatting */
+  ALLOCATE (array, char, Nbytes*Nval*Nrow);
+  ALLOCATE (line, char, Nval+1);
+  Pin = data;
+  Pout = array;
+  if (!strcmp (type, "char")) {
+    for (i = 0; i < Nval*Nrow; i++, Pin++, Pout++) {
+      *Pout = *Pin;
+    }
+  }
+  if (!strcmp (type, "int")) {
+    for (i = 0; i < Nrow; i++, Pin+=4, Pout+=Nval) {
+      snprintf (line, Nval + 1, cformat, *(int *)Pin);
+      memcpy (Pout, line, Nval);
+    }
+  }
+  if (!strcmp (type, "float")) {
+    for (i = 0; i < Nrow; i++, Pin+=4, Pout+=Nval) {
+      snprintf (line, Nval + 1, cformat, *(float *)Pin);
+      memcpy (Pout, line, Nval);
+    }
+  }
+
+  /* check array space */
+  if (Nx*Ny < Nx*(Nrow - 1) + Nstart + Nval*Nbytes) {
+    fprintf (stderr, "mismatch in array sizes\n");
+    return (FALSE);
+  }
+
+  /* insert bytes from array into appropriate section of buffer */
+  Pout = table[0].buffer + Nstart;
+  Pin  = array;
+  for (i = 0; i < Nrow; i++, Pout += Nx, Pin += Nval*Nbytes) {
+    memcpy (Pout, Pin, Nval*Nbytes);
+  }
+
+  free (line);
+  free (array);
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_column.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_column.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_column.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits table column ****************************/
+int gfits_table_column (Table *table, char *field, char *mode,...) {
+/* we expect one more field: the pointer to the array we read in */
+
+  char string[80], this_field[80], form[80], temp[80];
+  int i, j, N, start, end, width, M;
+  va_list argp;
+  double **D;
+  float  **F;
+  char   ***C;
+  int    **I;
+  
+  va_start (argp, mode);
+
+  /* find the correct field */
+  for (i = 0; i < table[0].Nfields; i++) {
+    sprintf (string, "TTYPE%d\0", i+1);
+    gfits_scan (&table[0].header, string, "%s", 1, this_field);
+    if (!strcmp (field, this_field)) {
+      break;
+    }
+  }
+  
+  if (i == table[0].Nfields) {
+    fprintf (stderr, "Table field %s does not exist\n", field);
+    return (FALSE);
+  }
+
+  N = i + 1;
+
+  sprintf (string, "TBCOL%d\0", N);
+  gfits_scan (&table[0].header, string, "%d", 1, &start);
+  sprintf (string, "TFORM%d\0", N);
+  gfits_scan (&table[0].header, string, "%s", 1, form);
+  /* we could use some error checking from the FITS table form, but
+     it is not immediately crucial */
+
+  if (N == table[0].Nfields) { 
+    end = table[0].Naxis[0];
+  } else {
+    sprintf (string, "TBCOL%d\0", N+1);
+    gfits_scan (&table[0].header, string, "%d", 1, &end);
+  }
+  width = end - start;
+  
+  if (!strcmp (mode, "%d")) {
+    I = va_arg (argp, int **);
+    ALLOCATE ((*I), int, table[0].Naxis[1]);
+    M = 0;
+  }
+  if (!strcmp (mode, "%f"))  {
+    F = va_arg (argp, float **);
+    ALLOCATE ((*F), float, table[0].Naxis[1]);
+    M = 1;
+  }
+  if (!strcmp (mode, "%lf")) {
+    D = va_arg (argp, double **);
+    ALLOCATE ((*D), double, table[0].Naxis[1]);
+    M = 2;
+  }
+  if (!strcmp (mode, "%s")) {
+    C = va_arg (argp, char ***);
+    ALLOCATE ((*C), char *, table[0].Naxis[1]);
+    for (i = 0; i < table[0].Naxis[1]; i++) {
+      ALLOCATE ((*C)[i], char, width + 1);
+    }
+    M = 3;
+  }
+
+  for (i = 0; i < table[0].Naxis[1]; i++) {
+    strncpy (temp, &table[0].buffer[i*table[0].Naxis[0] + start - 1], width);
+    temp[width] = 0;
+    switch (M) {
+    case 0:
+      (*I)[i] = (int) atof (temp);
+      break;
+    case 1:
+      (*F)[i] = atof (temp);
+      break;
+    case 2:
+      (*D)[i] = atof (temp);
+      break;
+    case 3:
+      strcpy ((*C)[i], temp);
+      break;
+    default:
+      fprintf (stderr, "unknown gfits_table_column mode: %s\n", mode);
+      return (FALSE);
+    }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_format.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_format.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_format.c	(revision 16632)
@@ -0,0 +1,329 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/***********************/
+int gfits_bintable_format (char *format, char *type, int *Nval, int *Nbytes) {
+
+  char *Lchar, *Fchar;
+  int Nv;
+
+  if (format == (char *) NULL) return (FALSE);
+  if (format[0] == 0) return (FALSE);
+  Lchar = &format[strlen(format) - 1];
+
+  Nv = strtol (format, &Fchar, 10);
+  if (Fchar != Lchar) return (FALSE);
+  if ((Nv == 0) && (Fchar == format)) Nv = 1;
+
+  *Nbytes = 0;
+  if (*Fchar == 'X') { *Nbytes = 1;  strcpy (type, "char");   *Nval = 1 + (int) Nv / 8; }
+  if (*Fchar == 'L') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'A') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'B') { *Nbytes = 1;  strcpy (type, "char");   *Nval = Nv;               }
+  if (*Fchar == 'I') { *Nbytes = 2;  strcpy (type, "short");  *Nval = Nv;               }
+  if (*Fchar == 'J') { *Nbytes = 4;  strcpy (type, "int");    *Nval = Nv;               }
+  if (*Fchar == 'E') { *Nbytes = 4;  strcpy (type, "float");  *Nval = Nv;               }
+  if (*Fchar == 'D') { *Nbytes = 8;  strcpy (type, "double"); *Nval = Nv;               }
+  if (*Fchar == 'P') { *Nbytes = 8;  strcpy (type, "var");    *Nval = 2*Nv;             }
+  if (*Fchar == 'C') { *Nbytes = 8;  strcpy (type, "float");  *Nval = 2*Nv;             }
+  if (*Fchar == 'M') { *Nbytes = 16; strcpy (type, "double"); *Nval = 2*Nv;             }
+  if (!*Nbytes) { return (FALSE); }
+
+  return (TRUE);
+}
+
+/* 
+   valid BINTABLE column formats:
+   L - logical
+   X - bit
+   I - 16 bit int
+   J - 32 bit int
+   A - char
+   E - float 
+   D - double
+   B - unsigned bytes
+   C - complex float
+   M - complex double
+   P - var length array descrpt (64 bit)
+   
+   all can be preceeded by integer N which specified number
+   of entries in array
+   
+*/
+
+/***********************/
+int gfits_table_format (char *format, char *type, int *Nval, int *Nbytes) {
+
+  char Fchar, Size[80], Type;
+  int Nv;
+
+  if (format == (char *) NULL) return (FALSE);
+  if (format[0] == 0) return (FALSE);
+  Fchar = format[0];
+
+  Nv = strtol (&format[1], (char **) NULL, 10);
+  if (Nv == 0) { 
+    Nv = 1;
+    strcpy (Size, "1");
+  } else {
+    strcpy (Size, &format[1]);
+  }
+  
+  Type = 'x';
+  if (Fchar == 'F') { *Nbytes = 1;  strcpy (type, "float");  Type = 'f'; *Nval = Nv; }
+  if (Fchar == 'I') { *Nbytes = 1;  strcpy (type, "int");    Type = 'd'; *Nval = Nv; }
+  if (Fchar == 'A') { *Nbytes = 1;  strcpy (type, "char");   Type = 's'; *Nval = Nv; }
+  if (!*Nbytes) { return (FALSE); }
+  
+  sprintf (format, "%%-%s%c", Size, Type);
+
+  return (TRUE);
+}
+
+/*
+  valid TABLE column formats:
+  FN.N  - floating point
+  INN   - integer
+  ANN   - NN char string
+  
+*/
+
+/** extract a table subset to a vtable ***/
+int gfits_table_to_vtable (FTable *ftable, VTable *vtable, int start, int Nkeep) {
+
+  /* gfits_table_to_vtable (f, v, 0, Ny - 1) - keep all of table
+     gfits_table_to_vtable (f, v, 0, 0)      - keep none of table 
+  */  
+
+  int i, Nx, Ny;
+
+  gfits_scan (ftable[0].header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (start + Nkeep > Ny) return (FALSE);
+  if (start < 0) return (FALSE);
+  if (Nkeep < 0) return (FALSE);
+
+  ALLOCATE (vtable[0].row, int, MAX (1, Nkeep));
+  ALLOCATE (vtable[0].buffer, char *, MAX (1, Nkeep));
+  for (i = 0; i < Nkeep; i++) {
+    ALLOCATE (vtable[0].buffer[i], char, MAX (1, Nx));
+    memcpy (vtable[0].buffer[i], &ftable[0].buffer[(i+start)*Nx], Nx);
+    vtable[0].row[i] = i + start;
+  }
+  
+  vtable[0].header = ftable[0].header;
+  vtable[0].size = ftable[0].size;
+  vtable[0].Nrow = Nkeep;
+  vtable[0].pad = vtable[0].size - Nx*Ny;
+
+  return (TRUE);
+}
+
+/** convert specified rows to vtable */
+int gfits_vtable_from_ftable (FTable *ftable, VTable *vtable, int *row, int Nrow) {
+
+  int i, N, Nx, Ny;
+
+  gfits_scan (ftable[0].header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2", "%d", 1, &Ny);
+
+  /* make empty vtable from table */
+  vtable[0].header = ftable[0].header;  /* make this a copy? */
+  vtable[0].size   = ftable[0].size;
+  vtable[0].pad    = vtable[0].size - Nx*Ny;
+  vtable[0].Nrow   = Ny;
+
+  /* insert selected rows in vtable (mask rows marked with -1) */ 
+  ALLOCATE (vtable[0].row, int, Nrow);
+  ALLOCATE (vtable[0].buffer, char *, Nrow);
+  for (N = i = 0; i < Nrow; i++) {
+    if (row[i] == -1) continue;
+    vtable[0].row[N] = row[i];
+    ALLOCATE (vtable[0].buffer[N], char, Nx);
+    memcpy (vtable[0].buffer[N], &ftable[0].buffer[Nx*row[i]], Nx);
+    N++;
+  }
+  vtable[0].Nrow = N;
+  return (TRUE);
+}
+
+/* use table def to format a complete string */
+char *gfits_table_print (FTable *table,...) { 
+  
+  int i, Nx, Nfields;
+  int off, Nchar, Nval, Nbytes;
+  char *line, format[64], field[16], type[16];
+  va_list argp;
+  
+  va_start (argp, table);
+
+  gfits_scan (table[0].header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (table[0].header, "TFIELDS", "%d", 1, &Nfields);
+
+  ALLOCATE (line, char, Nx + 1);
+  
+  off = 0;
+  for (i = 1; i <= Nfields; i++) {
+
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (table[0].header, field, "%s", 1, format);       /* get field format */
+    gfits_table_format (format, type, &Nval, &Nbytes); /* convert to c-style */
+    Nchar = Nval * Nbytes;
+    if (!strcmp (type, "int"))   { 
+      /* d = va_arg (argp, int); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, int)); 
+    }
+    if (!strcmp (type, "float")) { 
+      /* f = va_arg (argp, double); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, double)); 
+    }
+    if (!strcmp (type, "char"))  { 
+      /* c = va_arg (argp, char *); */
+      snprintf (&line[off], Nchar + 1, format, va_arg (argp, char *));
+    }
+    off += Nchar;
+  }
+  va_end (argp);
+  return (line);
+}
+
+// apply table tzero, tscal in situ (from storage to data)
+int gfits_table_scale_data (FTable *ftable) {
+
+  int i, j, n, Nx, Ny, Nfields;
+  int off, Nchar, Nval, Nbytes, status;
+  char format[64], field[16], type[16];
+  double tzero, tscale;
+  char *tmpChar;
+  short *tmpShort;
+  int *tmpInt;
+
+  off = 0;
+
+  gfits_scan (ftable[0].header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2",  "%d", 1, &Ny);
+  gfits_scan (ftable[0].header, "TFIELDS", "%d", 1, &Nfields);
+
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (ftable[0].header, field, "%s", 1, format);       /* get field format */
+    gfits_bintable_format (format, type, &Nval, &Nbytes); /* convert to c-style */
+    Nchar = Nval * Nbytes;
+
+    sprintf (field, "TZERO%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tzero);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+
+    sprintf (field, "TSCAL%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tscale);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+    if (tscale == 0.0) {
+	off += Nchar; 
+	continue;
+    }
+
+    if (!strcmp (type, "char"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpChar = (char *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpChar = *tmpChar * tscale + tzero;
+	}
+      }
+    }
+    if (!strcmp (type, "short"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpShort = (short *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpShort = *tmpShort * tscale + tzero;
+	}
+      }
+    }
+    if (!strcmp (type, "int"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpInt = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpInt = *tmpInt * tscale + tzero;
+	}
+      }
+    }
+    off += Nchar;
+  }
+  return (TRUE);
+}
+
+// apply table tzero, tscal in situ (from data to storage)
+int gfits_table_scale_storage (FTable *ftable) {
+
+  int i, j, n, Nx, Ny, Nfields;
+  int off, Nchar, Nval, Nbytes, status;
+  char format[64], field[16], type[16];
+  double tzero, tscale;
+  char *tmpChar;
+  short *tmpShort;
+  int *tmpInt;
+
+  off = 0;
+
+  gfits_scan (ftable[0].header, "NAXIS1",  "%d", 1, &Nx);
+  gfits_scan (ftable[0].header, "NAXIS2",  "%d", 1, &Ny);
+  gfits_scan (ftable[0].header, "TFIELDS", "%d", 1, &Nfields);
+
+  for (i = 1; i <= Nfields; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (ftable[0].header, field, "%s", 1, format);       /* get field format */
+    gfits_bintable_format (format, type, &Nval, &Nbytes); /* convert to c-style */
+    Nchar = Nval * Nbytes;
+
+    sprintf (field, "TZERO%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tzero);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+
+    sprintf (field, "TSCAL%d", i);
+    status = gfits_scan (ftable[0].header, field, "%lf", 1, &tscale);       /* get field format */
+    if (!status) {
+	off += Nchar; 
+	continue;
+    }
+    if (tscale == 0.0) {
+	off += Nchar; 
+	continue;
+    }
+
+    if (!strcmp (type, "char"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpChar = (char *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpChar = (*tmpChar - tzero) / tscale;
+	}
+      }
+    }
+    if (!strcmp (type, "short"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpShort = (short *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpShort = (*tmpShort - tzero) / tscale;
+	}
+      }
+    }
+    if (!strcmp (type, "int"))   { 
+      for (j = 0; j < Ny; j++) {
+	for (n = 0; n < Nval; n++) {
+	  tmpInt = (int *)&ftable[0].buffer[j*Nx + n*Nbytes + off];
+	  *tmpInt = (*tmpInt - tzero) / tscale;
+	}
+      }
+    }
+    off += Nchar;
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_row.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_row.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_row.c	(revision 16632)
@@ -0,0 +1,106 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits table column ****************************/
+int gfits_add_rows (FTable *table, char *data, int Nrow, int Nbytes) {
+
+  int Nx, Ny;
+  int nbytes, Nstart;
+  Header *header;
+
+  header = table[0].header;
+
+  gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (header[0].Naxis[0] != Nbytes) return (FALSE);
+  
+  Nstart = Nx*Ny;
+
+  /* update header y dimension */
+  Ny += Nrow;
+  header[0].Naxis[1] = Ny;
+  gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  nbytes = gfits_data_size (header);
+  REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+  table[0].size = nbytes;
+  
+  memcpy (&table[0].buffer[Nstart], data, Nbytes*Nrow);
+  memset (&table[0].buffer[Nx*Ny], ' ', nbytes - Nx*Ny);
+  return (TRUE);
+}
+
+/*********************** fits add (real) rows to virtual table ****************************/
+int gfits_vadd_rows (VTable *table, char *data, int Nrow, int Nbytes) {
+
+  int i, Nx, Ny;
+  int Nstart;
+  Header *header;
+
+  header = table[0].header;
+
+  gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (header[0].Naxis[0] != Nbytes) return (FALSE);
+  
+  /* Nstart is end of data in memory */
+  Nstart = table[0].Nrow;
+  table[0].Nrow += Nrow;
+  REALLOCATE (table[0].buffer, char *, table[0].Nrow);
+  REALLOCATE (table[0].row, int, table[0].Nrow);
+  for (i = 0; i < Nrow; i++) {
+    ALLOCATE (table[0].buffer[Nstart+i], char, MAX (1, Nx));
+    memcpy (table[0].buffer[Nstart+i], &data[i*Nx], Nx);
+    table[0].row[Nstart+i] = Ny + i;
+  }
+
+  /* update header y dimension */
+  Ny += Nrow;
+  header[0].Naxis[1] = Ny;
+  gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  table[0].size   = gfits_data_size (table[0].header);
+  table[0].pad    = table[0].size - Nx*Ny;
+
+  return (TRUE);
+}
+
+/*********************** fits table column ****************************/
+int gfits_delete_rows (FTable *table, int Nstart, int Nrow) {
+
+  int Nx, Ny, N0, N1, N2;
+  int nbytes;
+  Header *header;
+
+  header = table[0].header;
+
+  gfits_scan (header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (header, "NAXIS2", "%d", 1, &Ny);
+  
+  if (header[0].Naxis[1] != Ny) return (FALSE);
+  if (header[0].Naxis[0] != Nx) return (FALSE);
+  if (Ny > Nstart + Nrow) return (FALSE);
+  
+  /* shrink buffer by Nrow entries */
+  N0 = Nx*Nstart;
+  N1 = Nx*(Nstart + Nrow);
+  N2 = Nx*(Ny - Nstart - Nrow);
+  memmove (&table[0].buffer[N0], &table[0].buffer[N1], N2);
+
+  /* update header y dimension */
+  Ny -= Nrow;
+  header[0].Naxis[1] = Ny;
+  gfits_modify (header, "NAXIS2",  "%d", 1, Ny);
+
+  nbytes = gfits_data_size (header);
+  REALLOCATE (table[0].buffer, char, MAX (nbytes, 1));
+  table[0].size = nbytes;
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_varlength.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_varlength.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_table_varlength.c	(revision 16632)
@@ -0,0 +1,131 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int gfits_varlength_column_define (FTable *ftable, VarLengthColumn *def, int column) {
+
+  int i, Nv, Nb;
+  char *p1, *p2, *p3;
+  char field[81];
+  char format[81];
+  char tmpline[81];
+
+  // grab the value of TFORMn for this column
+  snprintf (field, 80, "TFORM%d", column);
+  if (!gfits_scan (ftable->header, field, "%s", 1, format)) return (FALSE);
+
+  // find and remove the max field length element
+  p1 = strchr (format, '(');
+  p2 = strchr (format, ')');
+
+  if (!p1 || !p2) return (FALSE); // not a valid varlength column -- missing (e_max)
+  if (p2 - p1 < 2) return (FALSE); // not a valid varlength column -- contains ()
+
+  def->maxlen = strtol (p1 + 1, &p3, 10);
+
+  if (p3 != p2) return (FALSE); // not a valid varlength column -- (e_max) contains extra chars
+  *p1 = 0; // make the format string end here for the rest of the function
+
+  // first char may optionally be 0, 1
+  p1 = format;
+  if ((*p1 == '0') || (*p1 == '1')) p1 ++;
+
+  // now p1 must be 'P';
+  if (*p1 == 0) return (FALSE);
+  if (*p1 != 'P') return (FALSE);
+
+  // next value is the actual varlength column format
+  p1 ++;
+  if (*p1 == 0) return (FALSE);
+  if (*p1 == 'P') { return (FALSE); }
+
+  def->nbytes = 0;
+  if (*p1 == 'X') { def->nbytes = 1;  def->format = *p1; }
+  if (*p1 == 'L') { def->nbytes = 1;  def->format = *p1; }
+  if (*p1 == 'A') { def->nbytes = 1;  def->format = *p1; }
+  if (*p1 == 'B') { def->nbytes = 1;  def->format = *p1; }
+  if (*p1 == 'I') { def->nbytes = 2;  def->format = *p1; }
+  if (*p1 == 'J') { def->nbytes = 4;  def->format = *p1; }
+  if (*p1 == 'E') { def->nbytes = 4;  def->format = *p1; }
+  if (*p1 == 'D') { def->nbytes = 8;  def->format = *p1; }
+  if (*p1 == 'C') { def->nbytes = 8;  def->format = *p1; }
+  if (*p1 == 'M') { def->nbytes = 16; def->format = *p1; }
+  if (!def->nbytes) { return (FALSE); }
+  
+  /* scan columns to find column offset */
+  def->Nstart = 0;
+  for (i = 1; i < column; i++) {
+    sprintf (field, "TFORM%d", i);
+    gfits_scan (ftable->header, field, "%s", 1, format);
+    gfits_bintable_format (format, tmpline, &Nv, &Nb);
+    def->Nstart += Nv*Nb;
+  }
+
+  if (!gfits_scan (ftable->header, "THEAP", "%d", 1, &def->heap_start)) {
+    def->heap_start = ftable->header->Naxis[0]*ftable->header->Naxis[1];
+  }
+
+  return TRUE;
+}
+
+void *gfits_varlength_column_pointer (FTable *ftable, VarLengthColumn *column, int row, int *length) {
+
+  int offset, Nx, *ptr;
+
+  // find the values for the specified row
+  // the values in the main table for this row and varlength column:
+  Nx = ftable->header->Naxis[0];
+
+# define SWAP_WORD \
+  tmp = pchar[0]; pchar[0] = pchar[3]; pchar[3] = tmp; \
+  tmp = pchar[1]; pchar[1] = pchar[2]; pchar[2] = tmp;
+
+# ifdef BYTE_SWAP
+  char *pchar, tmp;
+  pchar = &ftable->buffer[row*Nx + column->Nstart];
+  SWAP_WORD;
+  pchar = &ftable->buffer[row*Nx + column->Nstart + 4];
+  SWAP_WORD;
+# endif
+
+  ptr = (int *) &ftable->buffer[row*Nx + column->Nstart];
+  *length = ptr[0];
+  offset = ptr[1];
+
+  switch (column->format) {
+    case 'X':
+    case 'L':
+    case 'A':
+    case 'B': {
+      char *result;
+      result = (char *) ftable->buffer + column->heap_start + offset;
+      return result;
+    }
+    case 'I': {
+      short *result;
+      result = (short *) ftable->buffer + column->heap_start + offset;
+      return result;
+    }
+    case 'J': {
+      int *result;
+      result = (int *) ftable->buffer + column->heap_start + offset;
+      return result;
+    }
+    case 'E':
+    case 'C': {
+      float *result;
+      result = (float *) ftable->buffer + column->heap_start + offset;
+      return result;
+    }
+    case 'D':
+    case 'M': {
+      double *result;
+      result = (double *) ftable->buffer + column->heap_start + offset;
+      return result;
+    }
+    case 'P':
+    default:
+      abort();
+  }
+  abort();
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_write_T.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_write_T.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_write_T.c	(revision 16632)
@@ -0,0 +1,115 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write header *********************************/
+int gfits_write_table (char *filename, FTable *table) {
+  
+  FILE *f;
+  int status;
+  
+  status = TRUE;
+  
+  f = fopen (filename, "a+");
+  if (f == (FILE *) NULL) return (FALSE);
+  
+  status = fseek (f, 0, SEEK_END);  /* write table to end of file! */
+  status = gfits_fwrite_table (f, table);
+
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits write table *********************************/
+int gfits_fwrite_table (FILE *f, FTable *table) {
+  
+  int Nbytes;
+  
+  Nbytes = fwrite (table[0].buffer, sizeof(char), table[0].size, f);
+  
+  if (Nbytes != table[0].size) return (FALSE);
+  return (TRUE);
+}	
+
+/*********************** fits write virtual table *********************************/
+int gfits_fwrite_vtable (FILE *f, VTable *table) {
+  
+  int i, Nx, Ny, Npad, offset, start;
+  int Nbytes, *row, Nrow;
+  char *pad;
+
+  Nrow = table[0].Nrow;
+  row = table[0].row;
+  gfits_scan (table[0].header, "NAXIS1", "%d", 1, &Nx);
+  gfits_scan (table[0].header, "NAXIS2", "%d", 1, &Ny);
+
+  /* file pointer is at beginning of desired table data */
+  start = ftell (f);
+  
+  for (i = 0; i < Nrow; i++) {
+    offset = start + Nx*row[i];
+    fseek (f, offset, SEEK_SET);
+    Nbytes = fwrite (table[0].buffer[i], sizeof (char), Nx, f);
+    if (Nbytes != Nx) { return (FALSE); }
+  }
+  
+  Npad = table[0].size - Nx*Ny;
+  ALLOCATE (pad, char, Npad);
+  bzero (pad, Npad);
+
+  offset = start + Nx*Ny;
+  fseek (f, offset, SEEK_SET);
+  Nbytes = fwrite (pad, sizeof (char), Npad, f);
+  if (Nbytes != Npad) { return (FALSE); }
+  free (pad);
+
+  return (TRUE);
+}	
+
+
+/* this will add data beyond the end of the table in the file if needed,
+   filling intervening gap with 0 */
+
+/*********************** fits read ftable data ***********************************/
+int gfits_fwrite_ftable_range (FILE *f, FTable *ftable, int start, int Nrows, int Ndisk, int Ntotal) {
+
+  int Nbytes, Nwrite, Nskip, Nx, Npad;
+  char *pad;
+
+  if (start < 0) return (FALSE);
+  
+  /* modify vtable to represent full disk table */
+  gfits_modify (ftable[0].header, "NAXIS2", "%d", 1, Ntotal);
+  ftable[0].header[0].Naxis[1] = Ntotal;
+
+  Nx = ftable[0].header[0].Naxis[0]; // final output table size on disk 
+  ftable[0].size = gfits_data_size (ftable[0].header);
+
+  Nskip = start * Nx;
+  Nbytes = Nrows * Nx;
+
+  // cursor must be at start of the table header
+  if (!gfits_fwrite_Theader (f, ftable[0].header)) {
+    fprintf (stderr, "can't write table header");
+    return (FALSE);
+  }
+
+  // cursor must be at start of the table (after table header)
+  fseek (f, Nskip, SEEK_CUR);
+  Nwrite = fwrite (ftable[0].buffer, sizeof (char), Nbytes, f);
+  if (Nwrite != Nbytes) {
+    return (FALSE);
+  }
+
+  if (Ntotal >= Ndisk) {
+    Npad = ftable[0].size - Nx*Ntotal;
+    ALLOCATE (pad, char, Npad);
+    bzero (pad, Npad);
+    Nbytes = fwrite (pad, sizeof (char), Npad, f);
+    free (pad);
+
+    if (Nbytes != Npad) return (FALSE); 
+  }
+
+  return (TRUE);
+}	
+
Index: /branches/eam_branch_20080223/Ohana/src/libfits/table/F_write_TH.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libfits/table/F_write_TH.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libfits/table/F_write_TH.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+/*********************** fits write header *********************************/
+int gfits_write_Theader (char *filename, Header *header) {
+  
+  FILE *f;
+  int status;
+  
+  status = TRUE;
+  
+  f = fopen (filename, "a+");
+  if (f == (FILE *) NULL) return (FALSE);
+  
+  status = fseek (f, 0, SEEK_END);  /* write header to end of file! */
+  status = gfits_fwrite_Theader (f, header);
+
+  fclose (f);
+  return (status);
+}	
+
+/*********************** fits write header *********************************/
+int gfits_fwrite_Theader (FILE *f, Header *header) {
+  
+  int Nbytes;
+  
+  Nbytes = fwrite (header[0].buffer, sizeof(char), header[0].size, f);
+
+  if (Nbytes != header[0].size) return (FALSE);
+  return (TRUE);
+}	
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+lib
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/Makefile	(revision 16632)
@@ -0,0 +1,48 @@
+default: install
+help:
+	@echo "make options: install libkapa clean dist"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/libkapa
+LIB	= 	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	=	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS) -ldvo -lFITS -lohana
+
+install: $(DESTINC)/kapa.h $(DESTLIB)/libkapa.a $(DESTLIB)/libkapa.$(DLLTYPE)
+libkapa: $(LIB)/libkapa.$(ARCH).a $(LIB)/libkapa.$(ARCH).$(DLLTYPE)
+
+INCS = $(DESTINC)/kapa.h
+
+OBJS = \
+$(SRC)/IOfuncs.$(ARCH).o  \
+$(SRC)/KiiPicture.$(ARCH).o \
+$(SRC)/KiiOpen.$(ARCH).o \
+$(SRC)/KiiOverlay.$(ARCH).o \
+$(SRC)/KiiCursor.$(ARCH).o \
+$(SRC)/KiiConvert.$(ARCH).o \
+$(SRC)/KapaWindow.$(ARCH).o \
+$(SRC)/KapaColors.$(ARCH).o \
+$(SRC)/KapaOpen.$(ARCH).o
+
+DRAW = \
+$(SRC)/bDrawFuncs.$(ARCH).o     \
+$(SRC)/bDrawRotFont.$(ARCH).o   \
+$(SRC)/RotFont.$(ARCH).o        \
+$(SRC)/DrawRotString.$(ARCH).o  \
+$(SRC)/PSRotFont.$(ARCH).o
+
+$(OBJS): $(INCS)
+$(DRAW): $(INCS)
+
+$(LIB)/libkapa.$(ARCH).a: $(OBJS) $(DRAW)
+$(LIB)/libkapa.$(ARCH).$(DLLTYPE): $(OBJS) $(DRAW)
+
+$(DESTLIB)/libkapa.a:  $(LIB)/libkapa.$(ARCH).a  
+$(DESTLIB)/libkapa.$(DLLTYPE): $(LIB)/libkapa.$(ARCH).$(DLLTYPE)
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,12 @@
+
+- libkapa 1.2 : 2006.08.23
+  * added KapaInitGraph
+  * added KapaColorName
+  * added KapaPrepPlot
+  * added KapaPlotVector
+
+- libkapa 1.1
+  * added bDrawCircleSingle to fix circles with weight
+  * fixed format of textline data message
+
+
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/doc/api.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/doc/api.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/doc/api.txt	(revision 16632)
@@ -0,0 +1,37 @@
+
+COMM | Kapa Function  	| libkapa file  | libkapa API 
+-----------------------------------------------------
+DBOX | LoadFrame      	| KapaWindow.c  | KapaBox
+ERSP | ErasePlots       | KapaWindow.c  | KapaClearPlots
+ERSS | EraseSections    | KapaWindow.c  | KapaClearSections
+ERSI | EraseImage       | KapaWindow.c  | KapaClearImage
+ERSC | EraseCurrentPlot | KapaWindow.c  | KapaClearCurrentPlot
+LSEC | ListSection    	| KapaWindow.c  | KapaGetSection
+PNGF | PNGit          	| KiiConvert.c  | KapaPNG
+PPMF | PPMit          	| KiiConvert.c  | KapaPPM
+PLOT | LoadObject     	| KapaWindow.c  | KapaPrepPlot
+SSEC | SetSection     	| KapaWindow.c  | KapaSelectSection
+LABL | LoadLabels     	| KapaWindow.c  | KapaSendLabel
+PTXT | LoadTextlines  	| KapaWindow.c  | KapaSendTextline
+FONT | SetFont        	| KapaWindow.c  | KapaSetFont
+SLIM | SetLimits      	| KapaWindow.c  | KapaSetLimits
+DSEC | DefineSection  	| KapaWindow.c  | KapaSetSection
+MSEC | MoveSection  	| KapaWindow.c  | KapaMoveSection
+CENT | Center           | KapaWindow.c  | KiiCenter
+QUIT | Quit           	| KiiOpen.c     | KiiClose
+NCUR | !ACTIVE_CURSOR 	| KiiCursor.c   | KiiCursorOff
+CURS | +ACTIVE_CURSOR 	| KiiCursor.c   | KiiCursorOn
+ERSO | EraseOverlay     | KiiOverlay.c  | KiiEraseOverlay
+JPEG | JPEGit24         | KiiConvert.c  | KiiJPEG
+LOAD | LoadOverlay      | KiiOverlay.c  | KiiLoadOverlay
+READ | LoadPicture      | KiiPicture.c  | KiiNewPicture1D
+READ | LoadPicture      | KiiPicture.c  | KiiNewPicture2D
+PSIT | PScommand      	| KiiConvert.c  | KiiPS
+RSIZ | Resize         	| KapaWindow.c  | KiiResize
+SAVE | SaveOverlay      | KiiOverlay.c  | KiiSaveOverlay
+CSVE | CSaveOverlay     | KiiOverlay.c  | KiiSaveOverlay
+SLIM | GetLimits      	| KapaWindow.c  | KapaGetLimits
+SSTY | SetGraphData	| KapaWindow.c 	| KapaSetGraphData
+GSTY | GetGraphData	| KapaWindow.c 	| KapaGetGraphData
+SIMD | SetImageData	| KapaWindow.c 	| KapaSetImageData
+GIMD | GetImageData	| KapaWindow.c 	| KapaGetImageData
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/doc/notes.txt	(revision 16632)
@@ -0,0 +1,31 @@
+
+KII library functions:
+
+KiiOpen ()
+KiiClose ()
+KiiNewPicture ()
+KiiLoadOverlay ()
+KiiLoadTickmarks ()
+KiiEraseOverlay ()
+KiiSaveOverlay ()
+KiiPS
+KiiJPEG
+KiiResize 
+
+
+-----------------------
+
+KapaOpen ()
+KapaClose
+KapaPS
+KapaPNG
+KapaPPM
+KapaResize
+KapaLoadObject
+KapaSetLimits
+KapaLoadLabels
+KapaSetSection
+KapaLoadText
+KapaSetFont
+KapaErase
+KapaLoadBox
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/include/alphabet.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/include/alphabet.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/include/alphabet.h	(revision 16632)
@@ -0,0 +1,53 @@
+# include "../rotfont/times8.h"
+# include "../rotfont/times12.h"
+# include "../rotfont/times14.h"
+# include "../rotfont/times18.h"
+# include "../rotfont/times24.h"
+
+# include "../rotfont/courier8.h"
+# include "../rotfont/courier12.h"
+# include "../rotfont/courier14.h"
+# include "../rotfont/courier18.h"
+# include "../rotfont/courier24.h"
+
+# include "../rotfont/helvetica8.h"
+# include "../rotfont/helvetica12.h"
+# include "../rotfont/helvetica14.h"
+# include "../rotfont/helvetica18.h"
+# include "../rotfont/helvetica24.h"
+
+# include "../rotfont/symbol8.h"
+# include "../rotfont/symbol12.h"
+# include "../rotfont/symbol14.h"
+# include "../rotfont/symbol18.h"
+# include "../rotfont/symbol24.h"
+
+# define DEFFONT 1
+static FontSet HardwiredFonts[] = {
+  {times8font,  "times", 8},
+  {times12font, "times", 12},
+  {times14font, "times", 14},
+  {times18font, "times", 18},
+  {times24font, "times", 24},
+  
+  {courier8font,  "courier", 8},
+  {courier12font, "courier", 12},
+  {courier14font, "courier", 14},
+  {courier18font, "courier", 18},
+  {courier24font, "courier", 24},
+  
+  {helvetica8font,  "helvetica", 8},
+  {helvetica12font, "helvetica", 12},
+  {helvetica14font, "helvetica", 14},
+  {helvetica18font, "helvetica", 18},
+  {helvetica24font, "helvetica", 24},
+  
+  {symbol8font,  "symbol", 8},
+  {symbol12font, "symbol", 12},
+  {symbol14font, "symbol", 14},
+  {symbol18font, "symbol", 18},
+  {symbol24font, "symbol", 24}
+};
+
+/* put these as static in RotFont.c with accessor functions */
+# define NROT 256
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/include/kapa.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/include/kapa.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/include/kapa.h	(revision 16632)
@@ -0,0 +1,262 @@
+# ifndef KAPA_H
+# define KAPA_H
+
+/* linux is happy with this, not solaris */
+# include <netinet/ip.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+
+# include <sys/types.h>
+# include <sys/socket.h>
+# include <X11/Xlib.h>
+# include <png.h>
+# include <dvo.h>
+
+typedef struct sockaddr_in KapaSockAddress;
+
+typedef struct {
+  float *data1d;
+  float **data2d;
+  int Nx;
+  int Ny;
+} KiiImage;
+
+typedef struct {
+  float x;
+  float y;
+  float dx;
+  float dy;
+  float angle;
+  int type;
+} KiiOverlayBase;
+
+typedef struct {
+  float x;
+  float y;
+  float dx;
+  float dy;
+  float angle;
+  int type;
+  char *text;
+} KiiOverlay;
+
+typedef enum {
+  KII_OVERLAY_NONE, 
+  KII_OVERLAY_TEXT, 
+  KII_OVERLAY_BOX, 
+  KII_OVERLAY_LINE,
+  KII_OVERLAY_CIRCLE
+} KiiOverlayType;
+
+typedef enum {
+  KAPA_LABEL_XM,
+  KAPA_LABEL_YM,
+  KAPA_LABEL_XP,
+  KAPA_LABEL_YP,
+  KAPA_LABEL_UL,
+  KAPA_LABEL_UR,
+  KAPA_LABEL_LL,
+  KAPA_LABEL_LR,
+} KapaLabelType;
+
+typedef enum {
+  KAPA_PS_NEWPLOT,
+  KAPA_PS_NEWPAGE,
+  KAPA_PS_RAWPAGE
+} KapaPSmode;
+
+typedef struct {
+  char *name;
+  float x;
+  float y;
+  float dx;
+  float dy;
+} KapaSection;
+
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, ebar, color;
+  double lweight, size;
+  Coords coords;
+  int flipeast, flipnorth;
+  char axis[8], labels[8], ticks[8];
+} Graphdata;
+
+typedef struct {
+  int logflux;
+  double zero, range;
+  char name[1024];
+  char file[1024];
+} KapaImageData;
+
+typedef struct {
+  int dx, dy, ascent;
+  unsigned char *bits;
+} RotFont;
+
+typedef struct {
+  RotFont *font;
+  char name[64];
+  int size;
+} FontSet;
+
+typedef png_byte bDrawColor;
+
+typedef struct {
+  int Nx, Ny;
+  bDrawColor **pixels;
+} bDrawBuffer;
+
+/* IOfuncs.c */
+int KiiSendMessage (int device, char *format, ...);
+int KiiScanMessage (int device, char *format, ...);
+int KiiSendCommand (int device, int length, char *format, ...);
+int KiiSendCommandV (int device, int length, char *format, va_list argp);
+int KiiScanCommand (int device, int length, char *format, ...);
+int KiiSendData (int device, char *data, int Nbytes);
+char *KiiRecvData (int device);
+int KiiWaitAnswer (int device, char *expect);
+
+/* KiiOpen.c */
+int KiiOpen (char *kii_exec, char *name);
+int KiiClose (int socket);
+int KiiWait (char *sockpath);
+
+/* KiiPicture.c */
+int KiiSetChannel (int fd, int channel);
+int KiiSetColormap (int fd, char *colormap);
+int KiiNewPicture1D (int fd, KiiImage *image, KapaImageData *data, Coords *coords);
+int KiiNewPicture2D (int fd, KiiImage *image, KapaImageData *data, Coords *coords);
+
+int KapaSetImageCoords (int fd, Coords *coords);
+int KapaGetImageCoords (int fd, Coords *coords);
+int KapaGetImageRange (int fd, double *Xmin, double *Xmax, double *Ymin, double *Ymax);
+
+/* KiiOverlay.c */
+int KiiSelectOverlay (char *name, int *number);
+int KiiLoadOverlay (int fd, KiiOverlay *overlay, int Noverlay, char *name);
+int KiiEraseOverlay (int fd, char *name);
+int KiiSaveOverlay (int fd, int celestial, char *name, char *file);
+int KiiOverlayTypeByName (char *name);
+char *KiiOverlayTypeByNumber (int n);
+
+/* KiiConvert.c */
+int KiiPS (int fd, const char *filename, int scaleMode, int pageMode, char *pagename);
+int KiiJPEG (int fd, const char *filename);
+int KapaPNG (int fd, const char *filename);
+int KapaPPM (int fd, const char *filename);
+
+/* KiiCursor.c */
+int KiiCursorOn (int fd);
+int KiiCursorOff (int fd);
+int KiiCursorRead (int fd, double *x, double *y, double *z, double *r, double *d, char *key);
+
+/* KapaWindow.c */
+int KiiResize (int fd, int Nx, int Ny);
+int KiiCenter (int fd, double x, double y, int zoom);
+int KapaBox (int fd, Graphdata *graphdata);
+int KapaClearCurrentPlot (int fd);
+int KapaClearPlots (int fd);
+int KapaClearSections (int fd);
+int KapaClearImage (int fd);
+int KapaInitGraph (Graphdata *graphdata);
+int KapaPrepPlot (int fd, int Npts, Graphdata *graphmode);
+int KapaPlotVector (int fd, int Npts, float *values, char *type);
+int KapaSetFont (int fd, char *name, int size);
+int KapaSendLabel (int fd, char *string, int mode);
+int KapaSendTextline (int fd, char *string, float x, float y, float angle);
+int KapaSetLimits (int fd, Graphdata *graphmode);
+int KapaGetLimits (int fd, float *dx, float *dy);
+int KapaSetSection (int fd, KapaSection *section);
+int KapaSelectSection (int fd, char *name);
+int KapaGetSection (int fd, char *name);
+int KapaMoveSection (int fd, char *name, char *direction);
+int KapaSetGraphData (int fd, Graphdata *graphmode);
+int KapaGetGraphData (int fd, Graphdata *graphmode);
+int KapaSetImageData (int fd, KapaImageData *graphmode);
+int KapaGetImageData (int fd, KapaImageData *graphmode);
+int KapaSetToolbox (int fd, int location);
+
+/* KapaColors */
+int KapaColorByName (char *name);
+int KapaColormapSize ();
+char *KapaColorRGBString (int N);
+char *KapaColorName (int N);
+png_color *KapaPNGPalette (int *Npalette);
+unsigned long *KapaX11colors (Display *display, Colormap colormap, unsigned long default_color, int *Ncolors);
+
+/* RotFont.c */
+void InitRotFonts PROTO(());
+int SetRotFont PROTO((char *name, int size));
+char *GetRotFont PROTO((int *size));
+RotFont *GetRotFontData (double *scale);
+int RotStrlen PROTO((char *c));
+
+/* DrawRotString.c */
+int DrawRotText PROTO((int x, int y, char *string, int pos, double angle));
+int DrawRotBitmap PROTO((int x, int y, int dx, int dy, unsigned char *bitmap, int mode, double angle, double scale));
+int DrawRotTextInit (Display *display, Window window, GC gc, unsigned long fore, unsigned long back);
+
+
+/* PSRotFont.c */
+void PSRotText PROTO((FILE *f, int x, int y, char *string, int pos, double angle));
+void PSDumpRotSegment PROTO((FILE *f, char *segment, int *Nseg));
+void PSSetFont PROTO((FILE *f, char *name, int size));
+
+/* bDrawFuncs.c */
+bDrawBuffer *bDrawBufferCreate (int Nx, int Ny);
+void bDrawBufferFree (bDrawBuffer *buffer);
+void bDrawSetBuffer (bDrawBuffer *buffer);
+void bDrawSetStyle (bDrawColor color, int lw, int lt);
+void bDrawPoint (int x, int y);
+void bDrawPointf (float x, float y);
+
+void bDrawArc (double Xc, double Yc, double Xr, double Yr, double Ts, double Te);
+void bDrawCircle (double Xc, double Yc, double radius);
+void bDrawCircleFill (double xc, double yc, double radius);
+
+void bDrawLine (double x1, double y1, double x2, double y2);
+void bDrawLineWeight (int X1, int Y1, int X2, int Y2, int swapcoords);
+void bDrawLineBresen (int X1, int Y1, int X2, int Y2, int swapcoords);
+void bDrawLineHorizontal (int X1, int X2, int Y);
+void bDrawLineVertical (int X, int Y1, int Y2);
+
+void bDrawRectOpen (double x1, double y1, double x2, double y2);
+void bDrawRectFill (double x1, double y1, double x2, double y2);
+void bDrawTriOpen (double x1, double y1, double x2, double y2, double x3, double y3);
+void bDrawTriFill (double x1, double y1, double x2, double y2, double x3, double y3);
+
+/* bDrawRotFont.c */
+int bDrawRotText (int x, int y, char *string, int pos, double angle);
+int bDrawRotBitmap (int x, int y, int dx, int dy, unsigned char *bitmap, int mode, double angle, double scale);
+
+/* Kapa Socket functions */
+int KapaOpen (char *kapa_exec, char *kapa_name);
+int KapaServerInit (KapaSockAddress *Address);
+int KapaServerWait (int InitSocket, KapaSockAddress *Address);
+int KapaDefineValidIP (char *ipstring);
+int KapaClientSocket (char *hostname);
+int KapaOpenNamedSocket (char *kapa_exec, char *name);
+int KapaWaitNamedSocket (char *sockpath);
+
+/* define Kapa names for shared functions */
+// # define KapaOpen(p,n) KiiOpen(p,n)
+# define KapaResize(fd,Nx,Ny) KiiResize(fd,Nx,Ny)
+# define KapaCenter(fd,x,y,z) KiiResize(fd,x,y,z)
+# define KapaCursorOn(fd) KiiCursorOn(fd)
+# define KapaCursorOff(fd) KiiCursorOff(fd)
+# define KapaCursorRead(fd,x,y,k) KiiCursorRead(fd,x,y,k)
+# define KapaPS(fd,s,r,f) KiiPS(fd,s,r,f)
+
+# define KapaClose(socket) KiiClose(socket)
+# define KapaWait(sockpath) KiiWait(sockpath)
+# define KapaSendCommandV(device, length, format, argp) KiiSendCommandV(device, length, format, argp)
+# define KapaSendData(device, data, Nbytes) KiiSendData(device, data, Nbytes)
+# define KapaRecvData(device) KiiRecvData(device)
+
+/* these use varargs: is this safe, or should we make a stub function? */
+# define KapaSendMessage KiiSendMessage
+# define KapaSendCommand KiiSendCommand
+# define KapaScanMessage KiiScanMessage
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/include/kapa_internal.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/include/kapa_internal.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/include/kapa_internal.h	(revision 16632)
@@ -0,0 +1,18 @@
+# include <signal.h>
+# include <unistd.h>
+# include <sys/uio.h>
+# include <fcntl.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <sys/socket.h>
+# include <sys/un.h>
+# include <sys/time.h>
+# include <time.h>
+# include <errno.h>
+
+# include <ohana.h>
+# include <dvo.h>
+# include <kapa.h>
+
+/* do we need to move the Coords structure outside 
+   of libautocode? */
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/lib/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/lib/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/lib/.cvsignore	(revision 16632)
@@ -0,0 +1,3 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.darwin.dylib
+*.darwin_x86.dylib
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+fixfont
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/ReadMe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/ReadMe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/ReadMe	(revision 16632)
@@ -0,0 +1,10 @@
+start font server (as root): 
+ xfs &
+
+dump font to bdf file:
+
+fstobdf -s localhost:7100 -fn "-adobe-times-medium-r-*-*-12-*-*-*-*-*-*-*" > times12.bdf
+
+convert to .h file:
+ fixfont times12.bdf times12 > times12.h
+
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/alphabet.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/alphabet.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/alphabet.h	(revision 16632)
@@ -0,0 +1,69 @@
+typedef struct {
+  int dx, dy, ascent;
+  char *bits;
+} RotFont;
+
+typedef struct {
+  RotFont *font;
+  char name[64];
+  int size;
+} FontSet;
+
+# include "../rotfont/times8.h"
+# include "../rotfont/times12.h"
+# include "../rotfont/times14.h"
+# include "../rotfont/times18.h"
+# include "../rotfont/times24.h"
+
+# include "../rotfont/courier8.h"
+# include "../rotfont/courier12.h"
+# include "../rotfont/courier14.h"
+# include "../rotfont/courier18.h"
+# include "../rotfont/courier24.h"
+
+# include "../rotfont/helvetica8.h"
+# include "../rotfont/helvetica12.h"
+# include "../rotfont/helvetica14.h"
+# include "../rotfont/helvetica18.h"
+# include "../rotfont/helvetica24.h"
+
+# include "../rotfont/symbol8.h"
+# include "../rotfont/symbol12.h"
+# include "../rotfont/symbol14.h"
+# include "../rotfont/symbol18.h"
+# include "../rotfont/symbol24.h"
+
+# define DEFFONT 1
+static FontSet HardwiredFonts[] = {
+  {times8font,  "times", 8},
+  {times12font, "times", 12},
+  {times14font, "times", 14},
+  {times18font, "times", 18},
+  {times24font, "times", 24},
+  
+  {courier8font,  "courier", 8},
+  {courier12font, "courier", 12},
+  {courier14font, "courier", 14},
+  {courier18font, "courier", 18},
+  {courier24font, "courier", 24},
+  
+  {helvetica8font,  "helvetica", 8},
+  {helvetica12font, "helvetica", 12},
+  {helvetica14font, "helvetica", 14},
+  {helvetica18font, "helvetica", 18},
+  {helvetica24font, "helvetica", 24},
+  
+  {symbol8font,  "symbol", 8},
+  {symbol12font, "symbol", 12},
+  {symbol14font, "symbol", 14},
+  {symbol18font, "symbol", 18},
+  {symbol24font, "symbol", 24}
+};
+
+int Nallfonts;
+FontSet *AllFonts;
+RotFont *activefont;
+double activescale;
+
+char currentname[64];
+int  currentsize;
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/blank.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/blank.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/blank.h	(revision 16632)
@@ -0,0 +1,4 @@
+#define blank_width 5
+#define blank_height 1
+static unsigned char blank_bits[] = {
+   0x00};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier12.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier12.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier12.bdf	(revision 16632)
@@ -0,0 +1,2839 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -adobe-courier-medium-r-normal--12-116-75-75-m-70-iso8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 8 12 0 -2
+STARTPROPERTIES 25
+FOUNDRY "adobe"
+FAMILY_NAME "courier"
+WEIGHT_NAME "medium"
+SLANT "r"
+SETWIDTH_NAME "normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 116
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "m"
+AVERAGE_WIDTH 70
+CHARSET_REGISTRY "iso8859"
+CHARSET_ENCODING "1"
+FONT "-adobe-courier-medium-r-normal--12-116-75-75-m-70-iso8859-1"
+COPYRIGHT "Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation."
+RAW_PIXEL_SIZE 1000
+RAW_POINT_SIZE 964
+RAW_ASCENT 841
+RAW_DESCENT 288
+RAW_AVERAGE_WIDTH 6000
+FACE_NAME "Couriere."
+DEFAULT_CHAR 0
+FONT_ASCENT 10
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 190
+STARTCHAR space
+ENCODING 32
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 0 0 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 7 3 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+00
+40
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+50
+50
+50
+f8
+50
+f8
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+20
+60
+b8
+a8
+60
+38
+a8
+f0
+20
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+90
+6c
+70
+4c
+12
+1c
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+48
+40
+28
+e8
+90
+68
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 3 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+40
+80
+80
+80
+40
+40
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 9 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+40
+40
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 4 1 3
+ATTRIBUTES 0x0258
+BITMAP
+20
+f0
+20
+50
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 3 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 1 1 3
+ATTRIBUTES 0x0258
+BITMAP
+fc
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 2 3 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+08
+08
+10
+10
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+88
+88
+c8
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+08
+08
+10
+20
+48
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+10
+10
+30
+08
+08
+f0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+30
+50
+50
+f8
+10
+78
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+80
+f0
+88
+08
+08
+70
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+40
+b0
+c8
+88
+88
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+08
+10
+10
+10
+20
+20
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+78
+08
+10
+e0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 5 3 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+00
+c0
+40
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 6 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+60
+20
+00
+60
+40
+40
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+18
+20
+e0
+18
+04
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+fc
+00
+fc
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+10
+1c
+e0
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+88
+08
+10
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+9a
+aa
+aa
+7c
+3c
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+88
+88
+f8
+84
+84
+f8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+44
+80
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+44
+42
+42
+42
+44
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+44
+50
+70
+50
+40
+e0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+44
+80
+80
+8e
+42
+3e
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+44
+44
+7c
+44
+44
+ee
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+08
+08
+08
+88
+88
+f8
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+48
+50
+60
+50
+48
+c4
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+40
+40
+44
+44
+fc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c6
+6a
+6a
+6a
+52
+42
+e6
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+62
+52
+52
+4a
+4a
+e6
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+44
+44
+4c
+78
+40
+e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+82
+82
+82
+44
+38
+30
+2e
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+88
+98
+e0
+90
+88
+cc
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+88
+80
+70
+08
+88
+f0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+fe
+92
+92
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ee
+44
+64
+28
+28
+28
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c6
+52
+52
+6a
+6a
+6a
+44
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+6c
+28
+28
+10
+28
+44
+e6
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+48
+48
+50
+20
+20
+78
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+90
+90
+20
+48
+88
+f8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 9 4 -1
+ATTRIBUTES 0x0258
+BITMAP
+c0
+80
+80
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+20
+20
+20
+10
+10
+08
+08
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 1
+ATTRIBUTES 0x0258
+BITMAP
+20
+50
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 8 1 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+ff
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+7c
+42
+42
+42
+fc
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+84
+80
+80
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+1c
+04
+7c
+84
+84
+c4
+3e
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+40
+f8
+40
+40
+40
+f8
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+7e
+84
+84
+c4
+3c
+04
+38
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+7c
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 10 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+00
+f0
+10
+10
+10
+10
+10
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+4e
+58
+70
+48
+4e
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+fe
+92
+92
+92
+da
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+fc
+42
+42
+46
+7c
+40
+f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+7e
+c4
+84
+c4
+3c
+04
+0e
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fc
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+88
+f0
+c8
+b0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+f8
+40
+40
+40
+78
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e6
+44
+24
+28
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c6
+52
+6a
+6c
+24
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+66
+2c
+10
+6c
+c6
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+c6
+44
+24
+28
+10
+20
+f0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+10
+20
+48
+f8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 3 -1
+ATTRIBUTES 0x0258
+BITMAP
+60
+80
+80
+40
+80
+40
+40
+80
+60
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 1 10 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 9 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 2 1 3
+ATTRIBUTES 0x0258
+BITMAP
+68
+90
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 7 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+20
+78
+a8
+a0
+a0
+70
+20
+20
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+40
+40
+f8
+40
+40
+78
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+f8
+88
+88
+88
+f8
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+cc
+48
+50
+78
+78
+20
+78
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 1 10 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+48
+60
+90
+48
+38
+90
+f0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 1 2 6
+ATTRIBUTES 0x0258
+BITMAP
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+7c
+c6
+c2
+e6
+7c
+38
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+60
+e0
+e0
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+50
+a0
+50
+28
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+f8
+08
+08
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 1 2 3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+7c
+aa
+b2
+ba
+46
+38
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 1 2 6
+ATTRIBUTES 0x0258
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 3 2 4
+ATTRIBUTES 0x0258
+BITMAP
+e0
+90
+e0
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+f8
+20
+20
+00
+f8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+40
+e0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+60
+40
+20
+e0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 1 3 6
+ATTRIBUTES 0x0258
+BITMAP
+40
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+cc
+44
+44
+44
+7e
+40
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 8 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+a8
+a8
+68
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 2 2 3 3
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 3 2 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+60
+60
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 4 2 3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+e0
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+a0
+50
+28
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+02
+42
+46
+4c
+ea
+16
+26
+4e
+46
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+02
+46
+44
+4c
+fe
+1a
+22
+44
+4e
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+02
+62
+66
+24
+ea
+16
+26
+4e
+46
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+20
+c0
+80
+88
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+28
+10
+70
+28
+28
+28
+7c
+42
+c6
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3e
+12
+36
+3c
+74
+52
+de
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+7c
+8c
+80
+80
+80
+86
+78
+10
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+fc
+44
+50
+70
+50
+44
+fc
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+f8
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+44
+42
+f2
+42
+44
+f8
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+ee
+62
+52
+52
+4a
+4a
+e6
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 4 5 2 1
+ATTRIBUTES 0x0258
+BITMAP
+90
+70
+20
+d0
+90
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3a
+44
+8a
+92
+92
+64
+78
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+ee
+44
+44
+44
+44
+44
+38
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+cc
+48
+48
+50
+20
+20
+78
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+78
+4c
+44
+4c
+78
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+b0
+88
+88
+88
+b0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 8 1 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+70
+00
+70
+78
+88
+88
+fc
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+12
+7e
+90
+6e
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+7c
+84
+80
+80
+78
+20
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+78
+8c
+fc
+80
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+ATTRIBUTES 0x0258
+BITMAP
+50
+00
+60
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 8 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+28
+0c
+7e
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+fc
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3c
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+7c
+82
+82
+c6
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+f8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7e
+8a
+92
+e6
+9c
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+cc
+44
+44
+44
+3e
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+08
+00
+c6
+44
+24
+28
+10
+20
+f0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+7c
+42
+42
+46
+7c
+40
+f0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+28
+00
+c6
+44
+24
+28
+10
+20
+f0
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier12.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier12.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier12.h	(revision 16632)
@@ -0,0 +1,768 @@
+static unsigned char courier12_0_bits[] = {
+0x00};
+static unsigned char courier12_1_bits[] = {
+0x00};
+static unsigned char courier12_2_bits[] = {
+0x00};
+static unsigned char courier12_3_bits[] = {
+0x00};
+static unsigned char courier12_4_bits[] = {
+0x00};
+static unsigned char courier12_5_bits[] = {
+0x00};
+static unsigned char courier12_6_bits[] = {
+0x00};
+static unsigned char courier12_7_bits[] = {
+0x00};
+static unsigned char courier12_8_bits[] = {
+0x00};
+static unsigned char courier12_9_bits[] = {
+0x00};
+static unsigned char courier12_10_bits[] = {
+0x00};
+static unsigned char courier12_11_bits[] = {
+0x00};
+static unsigned char courier12_12_bits[] = {
+0x00};
+static unsigned char courier12_13_bits[] = {
+0x00};
+static unsigned char courier12_14_bits[] = {
+0x00};
+static unsigned char courier12_15_bits[] = {
+0x00};
+static unsigned char courier12_16_bits[] = {
+0x00};
+static unsigned char courier12_17_bits[] = {
+0x00};
+static unsigned char courier12_18_bits[] = {
+0x00};
+static unsigned char courier12_19_bits[] = {
+0x00};
+static unsigned char courier12_20_bits[] = {
+0x00};
+static unsigned char courier12_21_bits[] = {
+0x00};
+static unsigned char courier12_22_bits[] = {
+0x00};
+static unsigned char courier12_23_bits[] = {
+0x00};
+static unsigned char courier12_24_bits[] = {
+0x00};
+static unsigned char courier12_25_bits[] = {
+0x00};
+static unsigned char courier12_26_bits[] = {
+0x00};
+static unsigned char courier12_27_bits[] = {
+0x00};
+static unsigned char courier12_28_bits[] = {
+0x00};
+static unsigned char courier12_29_bits[] = {
+0x00};
+static unsigned char courier12_30_bits[] = {
+0x00};
+static unsigned char courier12_31_bits[] = {
+0x00};
+static unsigned char courier12_32_bits[] = {};
+static unsigned char courier12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02};
+static unsigned char courier12_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char courier12_35_bits[] = {
+0x0a, 0x0a, 0x0a, 0x1f, 0x0a, 0x1f, 0x0a, 0x0a, 0x0a};
+static unsigned char courier12_36_bits[] = {
+0x04, 0x06, 0x1d, 0x15, 0x06, 0x1c, 0x15, 0x0f, 0x04, 0x04};
+static unsigned char courier12_37_bits[] = {
+0x0e, 0x09, 0x36, 0x0e, 0x32, 0x48, 0x38};
+static unsigned char courier12_38_bits[] = {
+0x0c, 0x12, 0x02, 0x14, 0x17, 0x09, 0x16};
+static unsigned char courier12_39_bits[] = {
+0x02, 0x01, 0x01};
+static unsigned char courier12_40_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02};
+static unsigned char courier12_41_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char courier12_42_bits[] = {
+0x04, 0x0f, 0x04, 0x0a};
+static unsigned char courier12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char courier12_44_bits[] = {
+0x02, 0x01, 0x01};
+static unsigned char courier12_45_bits[] = {
+0x3f};
+static unsigned char courier12_46_bits[] = {
+0x03, 0x02};
+static unsigned char courier12_47_bits[] = {
+0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char courier12_48_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x13, 0x0e};
+static unsigned char courier12_49_bits[] = {
+0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_50_bits[] = {
+0x0f, 0x10, 0x10, 0x08, 0x04, 0x12, 0x1f};
+static unsigned char courier12_51_bits[] = {
+0x0f, 0x08, 0x08, 0x0c, 0x10, 0x10, 0x0f};
+static unsigned char courier12_52_bits[] = {
+0x08, 0x0c, 0x0a, 0x0a, 0x1f, 0x08, 0x1e};
+static unsigned char courier12_53_bits[] = {
+0x0f, 0x01, 0x0f, 0x11, 0x10, 0x10, 0x0e};
+static unsigned char courier12_54_bits[] = {
+0x1c, 0x02, 0x0d, 0x13, 0x11, 0x11, 0x0e};
+static unsigned char courier12_55_bits[] = {
+0x1f, 0x10, 0x08, 0x08, 0x08, 0x04, 0x04};
+static unsigned char courier12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier12_57_bits[] = {
+0x0e, 0x11, 0x11, 0x1e, 0x10, 0x08, 0x07};
+static unsigned char courier12_58_bits[] = {
+0x03, 0x02, 0x00, 0x03, 0x02};
+static unsigned char courier12_59_bits[] = {
+0x06, 0x04, 0x00, 0x06, 0x02, 0x02};
+static unsigned char courier12_60_bits[] = {
+0x18, 0x04, 0x07, 0x18, 0x20};
+static unsigned char courier12_61_bits[] = {
+0x3f, 0x00, 0x3f};
+static unsigned char courier12_62_bits[] = {
+0x06, 0x08, 0x38, 0x07, 0x01};
+static unsigned char courier12_63_bits[] = {
+0x0f, 0x11, 0x10, 0x08, 0x04, 0x00, 0x04};
+static unsigned char courier12_64_bits[] = {
+0x1c, 0x22, 0x59, 0x55, 0x55, 0x3e, 0x3c};
+static unsigned char courier12_65_bits[] = {
+0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_66_bits[] = {
+0x0f, 0x11, 0x11, 0x1f, 0x21, 0x21, 0x1f};
+static unsigned char courier12_67_bits[] = {
+0x3e, 0x22, 0x01, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char courier12_68_bits[] = {
+0x1f, 0x22, 0x42, 0x42, 0x42, 0x22, 0x1f};
+static unsigned char courier12_69_bits[] = {
+0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_70_bits[] = {
+0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x02, 0x07};
+static unsigned char courier12_71_bits[] = {
+0x3c, 0x22, 0x01, 0x01, 0x71, 0x42, 0x7c};
+static unsigned char courier12_72_bits[] = {
+0x77, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x77};
+static unsigned char courier12_73_bits[] = {
+0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_74_bits[] = {
+0x3e, 0x10, 0x10, 0x10, 0x11, 0x11, 0x1f};
+static unsigned char courier12_75_bits[] = {
+0x33, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x23};
+static unsigned char courier12_76_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x22, 0x22, 0x3f};
+static unsigned char courier12_77_bits[] = {
+0x63, 0x56, 0x56, 0x56, 0x4a, 0x42, 0x67};
+static unsigned char courier12_78_bits[] = {
+0x77, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x67};
+static unsigned char courier12_79_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_80_bits[] = {
+0x1f, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x07};
+static unsigned char courier12_81_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c, 0x0c, 0x74};
+static unsigned char courier12_82_bits[] = {
+0x0f, 0x11, 0x19, 0x07, 0x09, 0x11, 0x33};
+static unsigned char courier12_83_bits[] = {
+0x1e, 0x11, 0x01, 0x0e, 0x10, 0x11, 0x0f};
+static unsigned char courier12_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char courier12_85_bits[] = {
+0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_86_bits[] = {
+0x77, 0x22, 0x26, 0x14, 0x14, 0x14, 0x08};
+static unsigned char courier12_87_bits[] = {
+0x63, 0x4a, 0x4a, 0x56, 0x56, 0x56, 0x22};
+static unsigned char courier12_88_bits[] = {
+0x36, 0x14, 0x14, 0x08, 0x14, 0x22, 0x67};
+static unsigned char courier12_89_bits[] = {
+0x33, 0x12, 0x12, 0x0a, 0x04, 0x04, 0x1e};
+static unsigned char courier12_90_bits[] = {
+0x1f, 0x09, 0x09, 0x04, 0x12, 0x11, 0x1f};
+static unsigned char courier12_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char courier12_92_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10};
+static unsigned char courier12_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char courier12_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char courier12_95_bits[] = {
+0xff};
+static unsigned char courier12_96_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char courier12_97_bits[] = {
+0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_98_bits[] = {
+0x02, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3f};
+static unsigned char courier12_99_bits[] = {
+0x1e, 0x21, 0x01, 0x01, 0x1e};
+static unsigned char courier12_100_bits[] = {
+0x38, 0x20, 0x3e, 0x21, 0x21, 0x23, 0x7c};
+static unsigned char courier12_101_bits[] = {
+0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_102_bits[] = {
+0x3e, 0x02, 0x1f, 0x02, 0x02, 0x02, 0x1f};
+static unsigned char courier12_103_bits[] = {
+0x7e, 0x21, 0x21, 0x23, 0x3c, 0x20, 0x1c};
+static unsigned char courier12_104_bits[] = {
+0x02, 0x02, 0x3e, 0x22, 0x22, 0x22, 0x77};
+static unsigned char courier12_105_bits[] = {
+0x04, 0x00, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_106_bits[] = {
+0x08, 0x00, 0x00, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x07};
+static unsigned char courier12_107_bits[] = {
+0x02, 0x02, 0x72, 0x1a, 0x0e, 0x12, 0x72};
+static unsigned char courier12_108_bits[] = {
+0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_109_bits[] = {
+0x7f, 0x49, 0x49, 0x49, 0x5b};
+static unsigned char courier12_110_bits[] = {
+0x3f, 0x22, 0x22, 0x22, 0x77};
+static unsigned char courier12_111_bits[] = {
+0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_112_bits[] = {
+0x3f, 0x42, 0x42, 0x62, 0x3e, 0x02, 0x0f};
+static unsigned char courier12_113_bits[] = {
+0x7e, 0x23, 0x21, 0x23, 0x3c, 0x20, 0x70};
+static unsigned char courier12_114_bits[] = {
+0x3f, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char courier12_115_bits[] = {
+0x1e, 0x11, 0x0f, 0x13, 0x0d};
+static unsigned char courier12_116_bits[] = {
+0x02, 0x02, 0x1f, 0x02, 0x02, 0x02, 0x1e};
+static unsigned char courier12_117_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_118_bits[] = {
+0x67, 0x22, 0x24, 0x14, 0x08};
+static unsigned char courier12_119_bits[] = {
+0x63, 0x4a, 0x56, 0x36, 0x24};
+static unsigned char courier12_120_bits[] = {
+0x66, 0x34, 0x08, 0x36, 0x63};
+static unsigned char courier12_121_bits[] = {
+0x63, 0x22, 0x24, 0x14, 0x08, 0x04, 0x0f};
+static unsigned char courier12_122_bits[] = {
+0x1f, 0x08, 0x04, 0x12, 0x1f};
+static unsigned char courier12_123_bits[] = {
+0x06, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x06};
+static unsigned char courier12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier12_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier12_126_bits[] = {
+0x16, 0x09};
+static unsigned char courier12_127_bits[] = {
+0x00};
+static unsigned char courier12_128_bits[] = {
+0x00};
+static unsigned char courier12_129_bits[] = {
+0x00};
+static unsigned char courier12_130_bits[] = {
+0x00};
+static unsigned char courier12_131_bits[] = {
+0x00};
+static unsigned char courier12_132_bits[] = {
+0x00};
+static unsigned char courier12_133_bits[] = {
+0x00};
+static unsigned char courier12_134_bits[] = {
+0x00};
+static unsigned char courier12_135_bits[] = {
+0x00};
+static unsigned char courier12_136_bits[] = {
+0x00};
+static unsigned char courier12_137_bits[] = {
+0x00};
+static unsigned char courier12_138_bits[] = {
+0x00};
+static unsigned char courier12_139_bits[] = {
+0x00};
+static unsigned char courier12_140_bits[] = {
+0x00};
+static unsigned char courier12_141_bits[] = {
+0x00};
+static unsigned char courier12_142_bits[] = {
+0x00};
+static unsigned char courier12_143_bits[] = {
+0x00};
+static unsigned char courier12_144_bits[] = {
+0x00};
+static unsigned char courier12_145_bits[] = {
+0x00};
+static unsigned char courier12_146_bits[] = {
+0x00};
+static unsigned char courier12_147_bits[] = {
+0x00};
+static unsigned char courier12_148_bits[] = {
+0x00};
+static unsigned char courier12_149_bits[] = {
+0x00};
+static unsigned char courier12_150_bits[] = {
+0x00};
+static unsigned char courier12_151_bits[] = {
+0x00};
+static unsigned char courier12_152_bits[] = {
+0x00};
+static unsigned char courier12_153_bits[] = {
+0x00};
+static unsigned char courier12_154_bits[] = {
+0x00};
+static unsigned char courier12_155_bits[] = {
+0x00};
+static unsigned char courier12_156_bits[] = {
+0x00};
+static unsigned char courier12_157_bits[] = {
+0x00};
+static unsigned char courier12_158_bits[] = {
+0x00};
+static unsigned char courier12_159_bits[] = {
+0x00};
+static unsigned char courier12_160_bits[] = {
+0x00};
+static unsigned char courier12_161_bits[] = {
+0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier12_162_bits[] = {
+0x04, 0x1e, 0x15, 0x05, 0x05, 0x0e, 0x04, 0x04};
+static unsigned char courier12_163_bits[] = {
+0x1c, 0x02, 0x02, 0x1f, 0x02, 0x02, 0x1e};
+static unsigned char courier12_164_bits[] = {
+0x1f, 0x11, 0x11, 0x11, 0x1f};
+static unsigned char courier12_165_bits[] = {
+0x33, 0x12, 0x0a, 0x1e, 0x1e, 0x04, 0x1e};
+static unsigned char courier12_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier12_167_bits[] = {
+0x1e, 0x12, 0x06, 0x09, 0x12, 0x1c, 0x09, 0x0f};
+static unsigned char courier12_168_bits[] = {
+0x05};
+static unsigned char courier12_169_bits[] = {
+0x1c, 0x3e, 0x63, 0x43, 0x67, 0x3e, 0x1c};
+static unsigned char courier12_170_bits[] = {
+0x06, 0x07, 0x07, 0x07};
+static unsigned char courier12_171_bits[] = {
+0x14, 0x0a, 0x05, 0x0a, 0x14};
+static unsigned char courier12_172_bits[] = {
+0x1f, 0x10, 0x10};
+static unsigned char courier12_173_bits[] = {
+0x07};
+static unsigned char courier12_174_bits[] = {
+0x1c, 0x3e, 0x55, 0x4d, 0x5d, 0x62, 0x1c};
+static unsigned char courier12_175_bits[] = {
+0x0f};
+static unsigned char courier12_176_bits[] = {
+0x07, 0x09, 0x07};
+static unsigned char courier12_177_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, 0x1f};
+static unsigned char courier12_178_bits[] = {
+0x07, 0x04, 0x02, 0x07};
+static unsigned char courier12_179_bits[] = {
+0x06, 0x02, 0x04, 0x07};
+static unsigned char courier12_180_bits[] = {
+0x02};
+static unsigned char courier12_181_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x7e, 0x02, 0x02};
+static unsigned char courier12_182_bits[] = {
+0x1e, 0x15, 0x15, 0x16, 0x14, 0x14, 0x14, 0x14};
+static unsigned char courier12_183_bits[] = {
+0x03, 0x02};
+static unsigned char courier12_184_bits[] = {
+0x02, 0x06, 0x06};
+static unsigned char courier12_185_bits[] = {
+0x03, 0x02, 0x02, 0x07};
+static unsigned char courier12_186_bits[] = {
+0x07, 0x05, 0x07, 0x07};
+static unsigned char courier12_187_bits[] = {
+0x05, 0x0a, 0x14, 0x0a, 0x05};
+static unsigned char courier12_188_bits[] = {
+0x40, 0x42, 0x62, 0x32, 0x57, 0x68, 0x64, 0x72, 0x62};
+static unsigned char courier12_189_bits[] = {
+0x40, 0x62, 0x22, 0x32, 0x7f, 0x58, 0x44, 0x22, 0x72};
+static unsigned char courier12_190_bits[] = {
+0x40, 0x46, 0x66, 0x24, 0x57, 0x68, 0x64, 0x72, 0x62};
+static unsigned char courier12_191_bits[] = {
+0x08, 0x00, 0x04, 0x03, 0x01, 0x11, 0x1e};
+static unsigned char courier12_192_bits[] = {
+0x08, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_193_bits[] = {
+0x10, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_194_bits[] = {
+0x08, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_195_bits[] = {
+0x3c, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_196_bits[] = {
+0x14, 0x00, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_197_bits[] = {
+0x08, 0x14, 0x08, 0x0e, 0x14, 0x14, 0x14, 0x3e, 0x42, 0x63};
+static unsigned char courier12_198_bits[] = {
+0x7c, 0x48, 0x6c, 0x3c, 0x2e, 0x4a, 0x7b};
+static unsigned char courier12_199_bits[] = {
+0x3e, 0x31, 0x01, 0x01, 0x01, 0x61, 0x1e, 0x08, 0x0c};
+static unsigned char courier12_200_bits[] = {
+0x04, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_201_bits[] = {
+0x08, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_202_bits[] = {
+0x04, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_203_bits[] = {
+0x0a, 0x00, 0x3f, 0x22, 0x0a, 0x0e, 0x0a, 0x22, 0x3f};
+static unsigned char courier12_204_bits[] = {
+0x04, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_205_bits[] = {
+0x08, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_206_bits[] = {
+0x04, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_207_bits[] = {
+0x0a, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_208_bits[] = {
+0x1f, 0x22, 0x42, 0x4f, 0x42, 0x22, 0x1f};
+static unsigned char courier12_209_bits[] = {
+0x3c, 0x00, 0x77, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x67};
+static unsigned char courier12_210_bits[] = {
+0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_211_bits[] = {
+0x10, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_212_bits[] = {
+0x08, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_213_bits[] = {
+0x3c, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_214_bits[] = {
+0x14, 0x00, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier12_215_bits[] = {
+0x09, 0x0e, 0x04, 0x0b, 0x09};
+static unsigned char courier12_216_bits[] = {
+0x5c, 0x22, 0x51, 0x49, 0x49, 0x26, 0x1e};
+static unsigned char courier12_217_bits[] = {
+0x08, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_218_bits[] = {
+0x10, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_219_bits[] = {
+0x08, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_220_bits[] = {
+0x14, 0x00, 0x77, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c};
+static unsigned char courier12_221_bits[] = {
+0x08, 0x00, 0x33, 0x12, 0x12, 0x0a, 0x04, 0x04, 0x1e};
+static unsigned char courier12_222_bits[] = {
+0x07, 0x1e, 0x32, 0x22, 0x32, 0x1e, 0x07};
+static unsigned char courier12_223_bits[] = {
+0x0e, 0x11, 0x0d, 0x11, 0x11, 0x11, 0x0d};
+static unsigned char courier12_224_bits[] = {
+0x04, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_225_bits[] = {
+0x08, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_226_bits[] = {
+0x0e, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_227_bits[] = {
+0x1e, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_228_bits[] = {
+0x0a, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_229_bits[] = {
+0x0c, 0x0e, 0x00, 0x0e, 0x1e, 0x11, 0x11, 0x3f};
+static unsigned char courier12_230_bits[] = {
+0x3e, 0x48, 0x7e, 0x09, 0x76};
+static unsigned char courier12_231_bits[] = {
+0x3e, 0x21, 0x01, 0x01, 0x1e, 0x04, 0x0c};
+static unsigned char courier12_232_bits[] = {
+0x08, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_233_bits[] = {
+0x08, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_234_bits[] = {
+0x0e, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_235_bits[] = {
+0x0a, 0x00, 0x1e, 0x31, 0x3f, 0x01, 0x1e};
+static unsigned char courier12_236_bits[] = {
+0x04, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_237_bits[] = {
+0x08, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_238_bits[] = {
+0x0e, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_239_bits[] = {
+0x0a, 0x00, 0x06, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier12_240_bits[] = {
+0x0c, 0x14, 0x30, 0x7e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_241_bits[] = {
+0x3c, 0x00, 0x3f, 0x22, 0x22, 0x22, 0x77};
+static unsigned char courier12_242_bits[] = {
+0x08, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_243_bits[] = {
+0x10, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_244_bits[] = {
+0x1c, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_245_bits[] = {
+0x3c, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_246_bits[] = {
+0x14, 0x00, 0x3e, 0x41, 0x41, 0x63, 0x3c};
+static unsigned char courier12_247_bits[] = {
+0x04, 0x00, 0x1f, 0x00, 0x04};
+static unsigned char courier12_248_bits[] = {
+0x7e, 0x51, 0x49, 0x67, 0x39};
+static unsigned char courier12_249_bits[] = {
+0x08, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_250_bits[] = {
+0x10, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_251_bits[] = {
+0x1c, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_252_bits[] = {
+0x14, 0x00, 0x33, 0x22, 0x22, 0x22, 0x7c};
+static unsigned char courier12_253_bits[] = {
+0x10, 0x00, 0x63, 0x22, 0x24, 0x14, 0x08, 0x04, 0x0f};
+static unsigned char courier12_254_bits[] = {
+0x02, 0x02, 0x3e, 0x42, 0x42, 0x62, 0x3e, 0x02, 0x0f};
+static unsigned char courier12_255_bits[] = {
+0x14, 0x00, 0x63, 0x22, 0x24, 0x14, 0x08, 0x04, 0x0f};
+static RotFont courier12font[] = {
+{5, 1, 1, courier12_0_bits},
+{5, 1, 1, courier12_1_bits},
+{5, 1, 1, courier12_2_bits},
+{5, 1, 1, courier12_3_bits},
+{5, 1, 1, courier12_4_bits},
+{5, 1, 1, courier12_5_bits},
+{5, 1, 1, courier12_6_bits},
+{5, 1, 1, courier12_7_bits},
+{5, 1, 1, courier12_8_bits},
+{5, 1, 1, courier12_9_bits},
+{5, 1, 1, courier12_10_bits},
+{5, 1, 1, courier12_11_bits},
+{5, 1, 1, courier12_12_bits},
+{5, 1, 1, courier12_13_bits},
+{5, 1, 1, courier12_14_bits},
+{5, 1, 1, courier12_15_bits},
+{5, 1, 1, courier12_16_bits},
+{5, 1, 1, courier12_17_bits},
+{5, 1, 1, courier12_18_bits},
+{5, 1, 1, courier12_19_bits},
+{5, 1, 1, courier12_20_bits},
+{5, 1, 1, courier12_21_bits},
+{5, 1, 1, courier12_22_bits},
+{5, 1, 1, courier12_23_bits},
+{5, 1, 1, courier12_24_bits},
+{5, 1, 1, courier12_25_bits},
+{5, 1, 1, courier12_26_bits},
+{5, 1, 1, courier12_27_bits},
+{5, 1, 1, courier12_28_bits},
+{5, 1, 1, courier12_29_bits},
+{5, 1, 1, courier12_30_bits},
+{5, 1, 1, courier12_31_bits},
+{5, 0, 0, courier12_32_bits},
+{2, 7, 7, courier12_33_bits},
+{3, 3, 7, courier12_34_bits},
+{5, 9, 8, courier12_35_bits},
+{5, 10, 8, courier12_36_bits},
+{7, 7, 7, courier12_37_bits},
+{5, 7, 7, courier12_38_bits},
+{2, 3, 7, courier12_39_bits},
+{3, 9, 8, courier12_40_bits},
+{2, 9, 8, courier12_41_bits},
+{5, 4, 7, courier12_42_bits},
+{5, 5, 6, courier12_43_bits},
+{2, 3, 2, courier12_44_bits},
+{6, 1, 4, courier12_45_bits},
+{2, 2, 2, courier12_46_bits},
+{5, 10, 8, courier12_47_bits},
+{5, 7, 7, courier12_48_bits},
+{5, 7, 7, courier12_49_bits},
+{5, 7, 7, courier12_50_bits},
+{5, 7, 7, courier12_51_bits},
+{5, 7, 7, courier12_52_bits},
+{5, 7, 7, courier12_53_bits},
+{5, 7, 7, courier12_54_bits},
+{5, 7, 7, courier12_55_bits},
+{5, 7, 7, courier12_56_bits},
+{5, 7, 7, courier12_57_bits},
+{2, 5, 5, courier12_58_bits},
+{3, 6, 5, courier12_59_bits},
+{6, 5, 6, courier12_60_bits},
+{6, 3, 5, courier12_61_bits},
+{6, 5, 6, courier12_62_bits},
+{5, 7, 7, courier12_63_bits},
+{7, 7, 7, courier12_64_bits},
+{7, 7, 7, courier12_65_bits},
+{6, 7, 7, courier12_66_bits},
+{6, 7, 7, courier12_67_bits},
+{7, 7, 7, courier12_68_bits},
+{6, 7, 7, courier12_69_bits},
+{6, 7, 7, courier12_70_bits},
+{7, 7, 7, courier12_71_bits},
+{7, 7, 7, courier12_72_bits},
+{5, 7, 7, courier12_73_bits},
+{6, 7, 7, courier12_74_bits},
+{6, 7, 7, courier12_75_bits},
+{6, 7, 7, courier12_76_bits},
+{7, 7, 7, courier12_77_bits},
+{7, 7, 7, courier12_78_bits},
+{7, 7, 7, courier12_79_bits},
+{6, 7, 7, courier12_80_bits},
+{7, 9, 7, courier12_81_bits},
+{6, 7, 7, courier12_82_bits},
+{5, 7, 7, courier12_83_bits},
+{7, 7, 7, courier12_84_bits},
+{7, 7, 7, courier12_85_bits},
+{7, 7, 7, courier12_86_bits},
+{7, 7, 7, courier12_87_bits},
+{7, 7, 7, courier12_88_bits},
+{6, 7, 7, courier12_89_bits},
+{5, 7, 7, courier12_90_bits},
+{2, 9, 8, courier12_91_bits},
+{5, 10, 8, courier12_92_bits},
+{3, 9, 8, courier12_93_bits},
+{5, 6, 7, courier12_94_bits},
+{8, 1, -1, courier12_95_bits},
+{2, 3, 7, courier12_96_bits},
+{6, 5, 5, courier12_97_bits},
+{7, 7, 7, courier12_98_bits},
+{6, 5, 5, courier12_99_bits},
+{7, 7, 7, courier12_100_bits},
+{6, 5, 5, courier12_101_bits},
+{6, 7, 7, courier12_102_bits},
+{7, 7, 5, courier12_103_bits},
+{7, 7, 7, courier12_104_bits},
+{5, 8, 8, courier12_105_bits},
+{4, 10, 8, courier12_106_bits},
+{7, 7, 7, courier12_107_bits},
+{5, 7, 7, courier12_108_bits},
+{7, 5, 5, courier12_109_bits},
+{7, 5, 5, courier12_110_bits},
+{7, 5, 5, courier12_111_bits},
+{7, 7, 5, courier12_112_bits},
+{7, 7, 5, courier12_113_bits},
+{6, 5, 5, courier12_114_bits},
+{5, 5, 5, courier12_115_bits},
+{5, 7, 7, courier12_116_bits},
+{7, 5, 5, courier12_117_bits},
+{7, 5, 5, courier12_118_bits},
+{7, 5, 5, courier12_119_bits},
+{7, 5, 5, courier12_120_bits},
+{7, 7, 5, courier12_121_bits},
+{5, 5, 5, courier12_122_bits},
+{3, 9, 8, courier12_123_bits},
+{1, 10, 8, courier12_124_bits},
+{2, 9, 8, courier12_125_bits},
+{5, 2, 5, courier12_126_bits},
+{5, 1, 1, courier12_127_bits},
+{5, 1, 1, courier12_128_bits},
+{5, 1, 1, courier12_129_bits},
+{5, 1, 1, courier12_130_bits},
+{5, 1, 1, courier12_131_bits},
+{5, 1, 1, courier12_132_bits},
+{5, 1, 1, courier12_133_bits},
+{5, 1, 1, courier12_134_bits},
+{5, 1, 1, courier12_135_bits},
+{5, 1, 1, courier12_136_bits},
+{5, 1, 1, courier12_137_bits},
+{5, 1, 1, courier12_138_bits},
+{5, 1, 1, courier12_139_bits},
+{5, 1, 1, courier12_140_bits},
+{5, 1, 1, courier12_141_bits},
+{5, 1, 1, courier12_142_bits},
+{5, 1, 1, courier12_143_bits},
+{5, 1, 1, courier12_144_bits},
+{5, 1, 1, courier12_145_bits},
+{5, 1, 1, courier12_146_bits},
+{5, 1, 1, courier12_147_bits},
+{5, 1, 1, courier12_148_bits},
+{5, 1, 1, courier12_149_bits},
+{5, 1, 1, courier12_150_bits},
+{5, 1, 1, courier12_151_bits},
+{5, 1, 1, courier12_152_bits},
+{5, 1, 1, courier12_153_bits},
+{5, 1, 1, courier12_154_bits},
+{5, 1, 1, courier12_155_bits},
+{5, 1, 1, courier12_156_bits},
+{5, 1, 1, courier12_157_bits},
+{5, 1, 1, courier12_158_bits},
+{5, 1, 1, courier12_159_bits},
+{5, 1, 1, courier12_160_bits},
+{2, 7, 5, courier12_161_bits},
+{5, 8, 7, courier12_162_bits},
+{5, 7, 7, courier12_163_bits},
+{5, 5, 6, courier12_164_bits},
+{6, 7, 7, courier12_165_bits},
+{1, 10, 8, courier12_166_bits},
+{5, 8, 7, courier12_167_bits},
+{3, 1, 7, courier12_168_bits},
+{7, 7, 7, courier12_169_bits},
+{3, 4, 7, courier12_170_bits},
+{5, 5, 5, courier12_171_bits},
+{5, 3, 5, courier12_172_bits},
+{3, 1, 4, courier12_173_bits},
+{7, 7, 7, courier12_174_bits},
+{4, 1, 7, courier12_175_bits},
+{4, 3, 7, courier12_176_bits},
+{5, 7, 7, courier12_177_bits},
+{3, 4, 7, courier12_178_bits},
+{3, 4, 7, courier12_179_bits},
+{2, 1, 7, courier12_180_bits},
+{7, 7, 5, courier12_181_bits},
+{5, 8, 7, courier12_182_bits},
+{2, 2, 5, courier12_183_bits},
+{3, 3, 1, courier12_184_bits},
+{3, 4, 7, courier12_185_bits},
+{3, 4, 7, courier12_186_bits},
+{5, 5, 5, courier12_187_bits},
+{7, 9, 8, courier12_188_bits},
+{7, 9, 8, courier12_189_bits},
+{7, 9, 8, courier12_190_bits},
+{5, 7, 5, courier12_191_bits},
+{7, 9, 9, courier12_192_bits},
+{7, 9, 9, courier12_193_bits},
+{7, 9, 9, courier12_194_bits},
+{7, 9, 9, courier12_195_bits},
+{7, 9, 9, courier12_196_bits},
+{7, 10, 10, courier12_197_bits},
+{7, 7, 7, courier12_198_bits},
+{7, 9, 7, courier12_199_bits},
+{6, 9, 9, courier12_200_bits},
+{6, 9, 9, courier12_201_bits},
+{6, 9, 9, courier12_202_bits},
+{6, 9, 9, courier12_203_bits},
+{5, 9, 9, courier12_204_bits},
+{5, 9, 9, courier12_205_bits},
+{5, 9, 9, courier12_206_bits},
+{5, 9, 9, courier12_207_bits},
+{7, 7, 7, courier12_208_bits},
+{7, 9, 9, courier12_209_bits},
+{7, 9, 9, courier12_210_bits},
+{7, 9, 9, courier12_211_bits},
+{7, 9, 9, courier12_212_bits},
+{7, 9, 9, courier12_213_bits},
+{7, 9, 9, courier12_214_bits},
+{4, 5, 6, courier12_215_bits},
+{7, 7, 7, courier12_216_bits},
+{7, 9, 9, courier12_217_bits},
+{7, 9, 9, courier12_218_bits},
+{7, 9, 9, courier12_219_bits},
+{7, 9, 9, courier12_220_bits},
+{6, 9, 9, courier12_221_bits},
+{6, 7, 7, courier12_222_bits},
+{5, 7, 7, courier12_223_bits},
+{6, 7, 7, courier12_224_bits},
+{6, 7, 7, courier12_225_bits},
+{6, 7, 7, courier12_226_bits},
+{6, 7, 7, courier12_227_bits},
+{6, 7, 7, courier12_228_bits},
+{6, 8, 8, courier12_229_bits},
+{7, 5, 5, courier12_230_bits},
+{6, 7, 5, courier12_231_bits},
+{6, 7, 7, courier12_232_bits},
+{6, 7, 7, courier12_233_bits},
+{6, 7, 7, courier12_234_bits},
+{6, 7, 7, courier12_235_bits},
+{5, 7, 7, courier12_236_bits},
+{5, 7, 7, courier12_237_bits},
+{5, 7, 7, courier12_238_bits},
+{5, 7, 7, courier12_239_bits},
+{7, 8, 8, courier12_240_bits},
+{7, 7, 7, courier12_241_bits},
+{7, 7, 7, courier12_242_bits},
+{7, 7, 7, courier12_243_bits},
+{7, 7, 7, courier12_244_bits},
+{7, 7, 7, courier12_245_bits},
+{7, 7, 7, courier12_246_bits},
+{5, 5, 6, courier12_247_bits},
+{7, 5, 5, courier12_248_bits},
+{7, 7, 7, courier12_249_bits},
+{7, 7, 7, courier12_250_bits},
+{7, 7, 7, courier12_251_bits},
+{7, 7, 7, courier12_252_bits},
+{7, 9, 7, courier12_253_bits},
+{7, 9, 7, courier12_254_bits},
+{7, 9, 7, courier12_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier14.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier14.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier14.bdf	(revision 16632)
@@ -0,0 +1,3076 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Courier-Medium-R-Normal--14-100-100-100-M-90-ISO8859-1
+SIZE 10 100 100
+FONTBOUNDINGBOX 10 15 -1 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Courier"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 100
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "M"
+AVERAGE_WIDTH 90
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FACE_NAME "Courier"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Courier"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Courier"
+FONT "-Adobe-Courier-Medium-R-Normal--14-100-100-100-M-90-ISO8859-1"
+WEIGHT 10
+RESOLUTION 138
+QUAD_WIDTH 9
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 9 3 0
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 4 2 6
+BITMAP
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 -1
+BITMAP
+50
+50
+50
+f8
+50
+50
+f8
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 13 2 -2
+BITMAP
+20
+20
+78
+88
+80
+c0
+30
+08
+88
+f0
+20
+20
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+60
+90
+90
+73
+0c
+30
+cc
+12
+12
+0c
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 8 1 0
+BITMAP
+38
+40
+40
+40
+a8
+90
+98
+64
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 4 2 6
+BITMAP
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 3 -2
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 6 1 3
+BITMAP
+20
+20
+f8
+20
+50
+88
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 4 2 -2
+BITMAP
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 1 1 4
+BITMAP
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 2 2 3 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 11 1 -1
+BITMAP
+04
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+30
+48
+84
+84
+84
+84
+84
+84
+48
+30
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 1 0
+BITMAP
+20
+60
+a0
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 1 0
+BITMAP
+70
+88
+88
+08
+10
+20
+40
+80
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+38
+44
+04
+04
+18
+04
+04
+04
+84
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+18
+28
+28
+48
+48
+88
+88
+fc
+08
+1c
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+7c
+40
+40
+40
+78
+04
+04
+04
+84
+78
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+38
+40
+80
+80
+b8
+c4
+84
+84
+44
+38
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+fc
+84
+04
+08
+08
+08
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+70
+88
+88
+88
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 0
+BITMAP
+70
+88
+84
+84
+8c
+74
+04
+04
+08
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 2 7 3 0
+BITMAP
+c0
+c0
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 9 2 -2
+BITMAP
+60
+60
+00
+00
+00
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 0 1
+BITMAP
+06
+18
+60
+80
+60
+18
+06
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 3 1 3
+BITMAP
+fe
+00
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+c0
+30
+0c
+02
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+08
+30
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 -1
+BITMAP
+38
+44
+84
+9c
+a4
+a4
+9e
+80
+40
+38
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+fc
+42
+42
+42
+7c
+42
+42
+42
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3a
+46
+82
+80
+80
+80
+80
+42
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+42
+41
+41
+41
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+42
+42
+48
+78
+48
+40
+40
+f0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3a
+46
+82
+80
+80
+8f
+82
+42
+3c
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 0
+BITMAP
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3e
+08
+08
+08
+08
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ee
+44
+48
+50
+70
+48
+44
+44
+e3
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+f8
+20
+20
+20
+20
+21
+21
+21
+ff
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+6300
+5500
+5500
+4900
+4900
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+62
+52
+52
+4a
+4a
+46
+46
+e2
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fc
+42
+42
+42
+42
+7c
+40
+40
+f0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 0 -2
+BITMAP
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+31
+5e
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+42
+42
+42
+44
+78
+44
+42
+e1
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 9 1 0
+BITMAP
+74
+8c
+84
+80
+78
+04
+84
+c4
+b8
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+7c
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+4900
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+24
+24
+18
+24
+24
+42
+e7
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+ee
+44
+44
+28
+28
+10
+10
+10
+7c
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 9 1 0
+BITMAP
+fc
+84
+88
+10
+20
+20
+44
+84
+fc
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 3 -2
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 11 1 -1
+BITMAP
+80
+40
+40
+20
+20
+10
+10
+08
+08
+04
+04
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 5 2 4
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 1 0 -3
+BITMAP
+ff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 4 2 6
+BITMAP
+c0
+c0
+60
+20
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+78
+84
+04
+7c
+84
+84
+7a
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+c0
+40
+40
+5c
+62
+41
+41
+41
+62
+dc
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+3a
+46
+82
+80
+80
+42
+3c
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+06
+02
+02
+3a
+46
+82
+82
+82
+46
+3b
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+1e
+20
+20
+fc
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+3b
+46
+82
+82
+82
+46
+3a
+02
+04
+78
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+c0
+40
+40
+5c
+62
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+20
+20
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 13 1 -3
+BITMAP
+08
+08
+00
+f8
+08
+08
+08
+08
+08
+08
+08
+10
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+c0
+40
+40
+4e
+48
+50
+60
+50
+48
+ce
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+db00
+6d00
+4900
+4900
+4900
+4900
+ed80
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+dc
+62
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+dc
+62
+41
+41
+41
+62
+5c
+40
+40
+f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+3b
+46
+82
+82
+82
+46
+3a
+02
+02
+0f
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+cc
+52
+60
+40
+40
+40
+f8
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 7 1 0
+BITMAP
+7c
+84
+80
+78
+04
+84
+f8
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+20
+20
+fc
+20
+20
+20
+20
+22
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+e7
+42
+42
+24
+24
+18
+18
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+e380
+4100
+4900
+4900
+2a00
+3600
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 0 0
+BITMAP
+ee
+44
+28
+10
+28
+44
+ee
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+e7
+42
+42
+24
+24
+18
+08
+10
+10
+78
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 7 2 0
+BITMAP
+f8
+88
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+20
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 11 3 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 12 2 -2
+BITMAP
+80
+40
+40
+40
+40
+20
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 2 1 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 9 4 -2
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 0
+BITMAP
+20
+20
+78
+88
+80
+88
+70
+20
+20
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+18
+24
+20
+20
+78
+20
+20
+42
+fc
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 6 1 1
+BITMAP
+b4
+48
+84
+84
+48
+b4
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+ee
+44
+44
+28
+7c
+10
+7c
+10
+38
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 1 11 3 -2
+BITMAP
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 10 1 -1
+BITMAP
+3c
+44
+40
+f0
+88
+44
+3c
+08
+88
+f0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 1 2 8
+BITMAP
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+42
+99
+a5
+a1
+a5
+99
+42
+3c
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 3
+BITMAP
+c0
+20
+e0
+b0
+00
+f0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+11
+22
+44
+cc
+44
+22
+11
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 3 1 3
+BITMAP
+fe
+02
+02
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 1 1 4
+BITMAP
+fc
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+42
+b9
+a5
+b9
+a9
+a5
+42
+3c
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 1 2 8
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 4 2 6
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+fe
+10
+10
+00
+fe
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 4
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 4
+BITMAP
+60
+90
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 2 2 8
+BITMAP
+30
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 -3
+BITMAP
+c6
+42
+42
+42
+42
+46
+7b
+40
+40
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 -1
+BITMAP
+7e
+94
+94
+94
+74
+14
+14
+14
+14
+3e
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 2 2 3 3
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 3 2 -3
+BITMAP
+40
+20
+e0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 3 6 3 4
+BITMAP
+40
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 4 6 2 3
+BITMAP
+60
+90
+90
+60
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+88
+44
+22
+33
+22
+44
+88
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 10 10 -1 0
+BITMAP
+4000
+c100
+4200
+4400
+4480
+e980
+1280
+1480
+27c0
+4080
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 10 10 -1 0
+BITMAP
+4000
+c100
+4200
+4400
+4580
+ea40
+1040
+1080
+2100
+43c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 10 10 -1 0
+BITMAP
+6000
+9100
+6200
+1400
+9480
+6980
+1280
+1480
+27c0
+4080
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 -2
+BITMAP
+20
+20
+00
+20
+60
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+3000
+0c00
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0c00
+3000
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0800
+1400
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+1a00
+2c00
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+3600
+0000
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+1800
+2400
+1800
+3800
+0800
+1400
+1400
+2200
+3e00
+4100
+4100
+f780
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+1f80
+0c80
+1400
+1480
+2780
+3c80
+4400
+4480
+ef80
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+3a
+46
+82
+80
+80
+80
+80
+42
+3c
+10
+08
+38
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+60
+18
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+0c
+30
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+6c
+00
+fe
+42
+42
+48
+78
+48
+42
+42
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 12 2 0
+BITMAP
+c0
+30
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 12 2 0
+BITMAP
+18
+60
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 12 2 0
+BITMAP
+20
+50
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 11 2 0
+BITMAP
+d8
+00
+f8
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+42
+41
+41
+f1
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+1a
+2c
+00
+e7
+62
+52
+52
+4a
+4a
+46
+46
+e2
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+30
+0c
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+0c
+30
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+1a
+2c
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 0 0
+BITMAP
+66
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+1e80
+2100
+4280
+4480
+4880
+5080
+2080
+6100
+9e00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+30
+0c
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+0c
+30
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 0 0
+BITMAP
+66
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+0c
+30
+00
+ee
+44
+44
+28
+28
+10
+10
+10
+7c
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+e0
+40
+7c
+42
+42
+42
+7c
+40
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 0 0
+BITMAP
+38
+44
+44
+58
+44
+42
+42
+52
+cc
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+60
+18
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+18
+60
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+10
+28
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+34
+58
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+6c
+00
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+30
+48
+30
+78
+84
+04
+7c
+84
+8c
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+76
+89
+09
+7f
+88
+89
+76
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 -3
+BITMAP
+3a
+46
+82
+80
+80
+42
+3c
+10
+08
+38
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+60
+18
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+0c
+30
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+10
+28
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+6c
+00
+38
+44
+82
+fe
+80
+42
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+c0
+30
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+30
+c0
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 10 2 0
+BITMAP
+20
+50
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 5 9 2 0
+BITMAP
+d8
+00
+e0
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+02
+e4
+18
+28
+44
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+1a
+2c
+00
+dc
+62
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+30
+0c
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+0c
+30
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+10
+28
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+1a
+2c
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+6c
+00
+3c
+42
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 1
+BITMAP
+18
+18
+00
+ff
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+3d
+46
+89
+91
+a1
+42
+bc
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+30
+0c
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+0c
+30
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+10
+28
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+6c
+00
+c6
+42
+42
+42
+42
+46
+3b
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 13 0 -3
+BITMAP
+06
+18
+00
+e7
+42
+42
+24
+24
+18
+08
+10
+10
+78
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 -3
+BITMAP
+c0
+40
+5c
+62
+41
+41
+41
+62
+5c
+40
+40
+f0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 12 0 -3
+BITMAP
+36
+00
+e7
+42
+42
+24
+24
+18
+08
+10
+10
+78
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier14.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier14.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier14.h	(revision 16632)
@@ -0,0 +1,789 @@
+static unsigned char courier14_0_bits[] = {
+0x00};
+static unsigned char courier14_1_bits[] = {
+0x00};
+static unsigned char courier14_2_bits[] = {
+0x00};
+static unsigned char courier14_3_bits[] = {
+0x00};
+static unsigned char courier14_4_bits[] = {
+0x00};
+static unsigned char courier14_5_bits[] = {
+0x00};
+static unsigned char courier14_6_bits[] = {
+0x00};
+static unsigned char courier14_7_bits[] = {
+0x00};
+static unsigned char courier14_8_bits[] = {
+0x00};
+static unsigned char courier14_9_bits[] = {
+0x00};
+static unsigned char courier14_10_bits[] = {
+0x00};
+static unsigned char courier14_11_bits[] = {
+0x00};
+static unsigned char courier14_12_bits[] = {
+0x00};
+static unsigned char courier14_13_bits[] = {
+0x00};
+static unsigned char courier14_14_bits[] = {
+0x00};
+static unsigned char courier14_15_bits[] = {
+0x00};
+static unsigned char courier14_16_bits[] = {
+0x00};
+static unsigned char courier14_17_bits[] = {
+0x00};
+static unsigned char courier14_18_bits[] = {
+0x00};
+static unsigned char courier14_19_bits[] = {
+0x00};
+static unsigned char courier14_20_bits[] = {
+0x00};
+static unsigned char courier14_21_bits[] = {
+0x00};
+static unsigned char courier14_22_bits[] = {
+0x00};
+static unsigned char courier14_23_bits[] = {
+0x00};
+static unsigned char courier14_24_bits[] = {
+0x00};
+static unsigned char courier14_25_bits[] = {
+0x00};
+static unsigned char courier14_26_bits[] = {
+0x00};
+static unsigned char courier14_27_bits[] = {
+0x00};
+static unsigned char courier14_28_bits[] = {
+0x00};
+static unsigned char courier14_29_bits[] = {
+0x00};
+static unsigned char courier14_30_bits[] = {
+0x00};
+static unsigned char courier14_31_bits[] = {
+0x00};
+static unsigned char courier14_32_bits[] = {
+0x00};
+static unsigned char courier14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char courier14_34_bits[] = {
+0x09, 0x09, 0x09, 0x09};
+static unsigned char courier14_35_bits[] = {
+0x0a, 0x0a, 0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a, 0x0a, 0x0a};
+static unsigned char courier14_36_bits[] = {
+0x04, 0x04, 0x1e, 0x11, 0x01, 0x03, 0x0c, 0x10, 0x11, 0x0f, 0x04, 0x04, 
+0x04};
+static unsigned char courier14_37_bits[] = {
+0x06, 0x09, 0x09, 0xce, 0x30, 0x0c, 0x33, 0x48, 0x48, 0x30};
+static unsigned char courier14_38_bits[] = {
+0x1c, 0x02, 0x02, 0x02, 0x15, 0x09, 0x19, 0x26};
+static unsigned char courier14_39_bits[] = {
+0x06, 0x06, 0x03, 0x01};
+static unsigned char courier14_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char courier14_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char courier14_42_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x0a, 0x11};
+static unsigned char courier14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char courier14_44_bits[] = {
+0x06, 0x06, 0x03, 0x01};
+static unsigned char courier14_45_bits[] = {
+0x7f};
+static unsigned char courier14_46_bits[] = {
+0x03, 0x03};
+static unsigned char courier14_47_bits[] = {
+0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01};
+static unsigned char courier14_48_bits[] = {
+0x0c, 0x12, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x12, 0x0c};
+static unsigned char courier14_49_bits[] = {
+0x04, 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_50_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x02, 0x01, 0x11, 0x1f};
+static unsigned char courier14_51_bits[] = {
+0x1c, 0x22, 0x20, 0x20, 0x18, 0x20, 0x20, 0x20, 0x21, 0x1e};
+static unsigned char courier14_52_bits[] = {
+0x18, 0x14, 0x14, 0x12, 0x12, 0x11, 0x11, 0x3f, 0x10, 0x38};
+static unsigned char courier14_53_bits[] = {
+0x3e, 0x02, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x20, 0x21, 0x1e};
+static unsigned char courier14_54_bits[] = {
+0x1c, 0x02, 0x01, 0x01, 0x1d, 0x23, 0x21, 0x21, 0x22, 0x1c};
+static unsigned char courier14_55_bits[] = {
+0x3f, 0x21, 0x20, 0x10, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08};
+static unsigned char courier14_56_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char courier14_57_bits[] = {
+0x0e, 0x11, 0x21, 0x21, 0x31, 0x2e, 0x20, 0x20, 0x10, 0x0e};
+static unsigned char courier14_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char courier14_59_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x06, 0x06, 0x03, 0x01};
+static unsigned char courier14_60_bits[] = {
+0x60, 0x18, 0x06, 0x01, 0x06, 0x18, 0x60};
+static unsigned char courier14_61_bits[] = {
+0x7f, 0x00, 0x7f};
+static unsigned char courier14_62_bits[] = {
+0x03, 0x0c, 0x30, 0x40, 0x30, 0x0c, 0x03};
+static unsigned char courier14_63_bits[] = {
+0x0e, 0x11, 0x10, 0x10, 0x0c, 0x04, 0x00, 0x04, 0x04};
+static unsigned char courier14_64_bits[] = {
+0x1c, 0x22, 0x21, 0x39, 0x25, 0x25, 0x79, 0x01, 0x02, 0x1c};
+static unsigned char courier14_65_bits[] = {
+0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_66_bits[] = {
+0x3f, 0x42, 0x42, 0x42, 0x3e, 0x42, 0x42, 0x42, 0x3f};
+static unsigned char courier14_67_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c};
+static unsigned char courier14_68_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x82, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier14_69_bits[] = {
+0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_70_bits[] = {
+0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x02, 0x02, 0x0f};
+static unsigned char courier14_71_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0xf1, 0x41, 0x42, 0x3c};
+static unsigned char courier14_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_73_bits[] = {
+0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_74_bits[] = {
+0x7c, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char courier14_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x22, 0xc7};
+static unsigned char courier14_76_bits[] = {
+0x1f, 0x04, 0x04, 0x04, 0x04, 0x84, 0x84, 0x84, 0xff};
+static unsigned char courier14_77_bits[] = {
+0xc7, 0x01, 0xc6, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier14_78_bits[] = {
+0xe7, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x47};
+static unsigned char courier14_79_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_80_bits[] = {
+0x3f, 0x42, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x02, 0x0f};
+static unsigned char courier14_81_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x8c, 0x7a};
+static unsigned char courier14_82_bits[] = {
+0x3f, 0x42, 0x42, 0x42, 0x22, 0x1e, 0x22, 0x42, 0x87};
+static unsigned char courier14_83_bits[] = {
+0x2e, 0x31, 0x21, 0x01, 0x1e, 0x20, 0x21, 0x23, 0x1d};
+static unsigned char courier14_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e};
+static unsigned char courier14_85_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_86_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char courier14_87_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char courier14_88_bits[] = {
+0xe7, 0x42, 0x24, 0x24, 0x18, 0x24, 0x24, 0x42, 0xe7};
+static unsigned char courier14_89_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x3e};
+static unsigned char courier14_90_bits[] = {
+0x3f, 0x21, 0x11, 0x08, 0x04, 0x04, 0x22, 0x21, 0x3f};
+static unsigned char courier14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char courier14_92_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20};
+static unsigned char courier14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char courier14_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char courier14_95_bits[] = {
+0xff, 0x01};
+static unsigned char courier14_96_bits[] = {
+0x03, 0x03, 0x06, 0x04};
+static unsigned char courier14_97_bits[] = {
+0x1e, 0x21, 0x20, 0x3e, 0x21, 0x21, 0x5e};
+static unsigned char courier14_98_bits[] = {
+0x03, 0x02, 0x02, 0x3a, 0x46, 0x82, 0x82, 0x82, 0x46, 0x3b};
+static unsigned char courier14_99_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x42, 0x3c};
+static unsigned char courier14_100_bits[] = {
+0x60, 0x40, 0x40, 0x5c, 0x62, 0x41, 0x41, 0x41, 0x62, 0xdc};
+static unsigned char courier14_101_bits[] = {
+0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_102_bits[] = {
+0x78, 0x04, 0x04, 0x3f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_103_bits[] = {
+0xdc, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x20, 0x1e};
+static unsigned char courier14_104_bits[] = {
+0x03, 0x02, 0x02, 0x3a, 0x46, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_105_bits[] = {
+0x04, 0x04, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_106_bits[] = {
+0x10, 0x10, 0x00, 0x1f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x08, 
+0x07};
+static unsigned char courier14_107_bits[] = {
+0x03, 0x02, 0x02, 0x72, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x73};
+static unsigned char courier14_108_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_109_bits[] = {
+0xdb, 0x00, 0xb6, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0xb7, 0x01};
+static unsigned char courier14_110_bits[] = {
+0x3b, 0x46, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_111_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_112_bits[] = {
+0x3b, 0x46, 0x82, 0x82, 0x82, 0x46, 0x3a, 0x02, 0x02, 0x0f};
+static unsigned char courier14_113_bits[] = {
+0xdc, 0x62, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0xf0};
+static unsigned char courier14_114_bits[] = {
+0x33, 0x4a, 0x06, 0x02, 0x02, 0x02, 0x1f};
+static unsigned char courier14_115_bits[] = {
+0x3e, 0x21, 0x01, 0x1e, 0x20, 0x21, 0x1f};
+static unsigned char courier14_116_bits[] = {
+0x04, 0x04, 0x3f, 0x04, 0x04, 0x04, 0x04, 0x44, 0x38};
+static unsigned char courier14_117_bits[] = {
+0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_118_bits[] = {
+0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x18};
+static unsigned char courier14_119_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x92, 0x00, 0x92, 0x00, 0x54, 0x00, 0x6c, 0x00, 
+0x44, 0x00};
+static unsigned char courier14_120_bits[] = {
+0x77, 0x22, 0x14, 0x08, 0x14, 0x22, 0x77};
+static unsigned char courier14_121_bits[] = {
+0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x10, 0x08, 0x08, 0x1e};
+static unsigned char courier14_122_bits[] = {
+0x1f, 0x11, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char courier14_123_bits[] = {
+0x04, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x04};
+static unsigned char courier14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier14_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char courier14_126_bits[] = {
+0x26, 0x19};
+static unsigned char courier14_127_bits[] = {
+0x00};
+static unsigned char courier14_128_bits[] = {
+0x00};
+static unsigned char courier14_129_bits[] = {
+0x00};
+static unsigned char courier14_130_bits[] = {
+0x00};
+static unsigned char courier14_131_bits[] = {
+0x00};
+static unsigned char courier14_132_bits[] = {
+0x00};
+static unsigned char courier14_133_bits[] = {
+0x00};
+static unsigned char courier14_134_bits[] = {
+0x00};
+static unsigned char courier14_135_bits[] = {
+0x00};
+static unsigned char courier14_136_bits[] = {
+0x00};
+static unsigned char courier14_137_bits[] = {
+0x00};
+static unsigned char courier14_138_bits[] = {
+0x00};
+static unsigned char courier14_139_bits[] = {
+0x00};
+static unsigned char courier14_140_bits[] = {
+0x00};
+static unsigned char courier14_141_bits[] = {
+0x00};
+static unsigned char courier14_142_bits[] = {
+0x00};
+static unsigned char courier14_143_bits[] = {
+0x00};
+static unsigned char courier14_144_bits[] = {
+0x00};
+static unsigned char courier14_145_bits[] = {
+0x00};
+static unsigned char courier14_146_bits[] = {
+0x00};
+static unsigned char courier14_147_bits[] = {
+0x00};
+static unsigned char courier14_148_bits[] = {
+0x00};
+static unsigned char courier14_149_bits[] = {
+0x00};
+static unsigned char courier14_150_bits[] = {
+0x00};
+static unsigned char courier14_151_bits[] = {
+0x00};
+static unsigned char courier14_152_bits[] = {
+0x00};
+static unsigned char courier14_153_bits[] = {
+0x00};
+static unsigned char courier14_154_bits[] = {
+0x00};
+static unsigned char courier14_155_bits[] = {
+0x00};
+static unsigned char courier14_156_bits[] = {
+0x00};
+static unsigned char courier14_157_bits[] = {
+0x00};
+static unsigned char courier14_158_bits[] = {
+0x00};
+static unsigned char courier14_159_bits[] = {
+0x00};
+static unsigned char courier14_160_bits[] = {
+0x00};
+static unsigned char courier14_161_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier14_162_bits[] = {
+0x04, 0x04, 0x1e, 0x11, 0x01, 0x11, 0x0e, 0x04, 0x04};
+static unsigned char courier14_163_bits[] = {
+0x18, 0x24, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x42, 0x3f};
+static unsigned char courier14_164_bits[] = {
+0x2d, 0x12, 0x21, 0x21, 0x12, 0x2d};
+static unsigned char courier14_165_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x3e, 0x08, 0x3e, 0x08, 0x1c};
+static unsigned char courier14_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier14_167_bits[] = {
+0x3c, 0x22, 0x02, 0x0f, 0x11, 0x22, 0x3c, 0x10, 0x11, 0x0f};
+static unsigned char courier14_168_bits[] = {
+0x1b};
+static unsigned char courier14_169_bits[] = {
+0x3c, 0x42, 0x99, 0xa5, 0x85, 0xa5, 0x99, 0x42, 0x3c};
+static unsigned char courier14_170_bits[] = {
+0x03, 0x04, 0x07, 0x0d, 0x00, 0x0f};
+static unsigned char courier14_171_bits[] = {
+0x88, 0x44, 0x22, 0x33, 0x22, 0x44, 0x88};
+static unsigned char courier14_172_bits[] = {
+0x7f, 0x40, 0x40};
+static unsigned char courier14_173_bits[] = {
+0x3f};
+static unsigned char courier14_174_bits[] = {
+0x3c, 0x42, 0x9d, 0xa5, 0x9d, 0x95, 0xa5, 0x42, 0x3c};
+static unsigned char courier14_175_bits[] = {
+0x0f};
+static unsigned char courier14_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char courier14_177_bits[] = {
+0x08, 0x08, 0x7f, 0x08, 0x08, 0x00, 0x7f};
+static unsigned char courier14_178_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char courier14_179_bits[] = {
+0x06, 0x09, 0x06, 0x08, 0x09, 0x06};
+static unsigned char courier14_180_bits[] = {
+0x0c, 0x03};
+static unsigned char courier14_181_bits[] = {
+0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xde, 0x02, 0x02, 0x02};
+static unsigned char courier14_182_bits[] = {
+0x7e, 0x29, 0x29, 0x29, 0x2e, 0x28, 0x28, 0x28, 0x28, 0x7c};
+static unsigned char courier14_183_bits[] = {
+0x03, 0x03};
+static unsigned char courier14_184_bits[] = {
+0x02, 0x04, 0x07};
+static unsigned char courier14_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char courier14_186_bits[] = {
+0x06, 0x09, 0x09, 0x06, 0x00, 0x0f};
+static unsigned char courier14_187_bits[] = {
+0x11, 0x22, 0x44, 0xcc, 0x44, 0x22, 0x11};
+static unsigned char courier14_188_bits[] = {
+0x02, 0x00, 0x83, 0x00, 0x42, 0x00, 0x22, 0x00, 0x22, 0x01, 0x97, 0x01, 
+0x48, 0x01, 0x28, 0x01, 0xe4, 0x03, 0x02, 0x01};
+static unsigned char courier14_189_bits[] = {
+0x02, 0x00, 0x83, 0x00, 0x42, 0x00, 0x22, 0x00, 0xa2, 0x01, 0x57, 0x02, 
+0x08, 0x02, 0x08, 0x01, 0x84, 0x00, 0xc2, 0x03};
+static unsigned char courier14_190_bits[] = {
+0x06, 0x00, 0x89, 0x00, 0x46, 0x00, 0x28, 0x00, 0x29, 0x01, 0x96, 0x01, 
+0x48, 0x01, 0x28, 0x01, 0xe4, 0x03, 0x02, 0x01};
+static unsigned char courier14_191_bits[] = {
+0x04, 0x04, 0x00, 0x04, 0x06, 0x01, 0x01, 0x11, 0x0e};
+static unsigned char courier14_192_bits[] = {
+0x0c, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_193_bits[] = {
+0x30, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_194_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_195_bits[] = {
+0x58, 0x00, 0x34, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_196_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_197_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xef, 0x01};
+static unsigned char courier14_198_bits[] = {
+0xf8, 0x01, 0x30, 0x01, 0x28, 0x00, 0x28, 0x01, 0xe4, 0x01, 0x3c, 0x01, 
+0x22, 0x00, 0x22, 0x01, 0xf7, 0x01};
+static unsigned char courier14_199_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c, 0x08, 0x10, 0x1c};
+static unsigned char courier14_200_bits[] = {
+0x06, 0x18, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_201_bits[] = {
+0x30, 0x0c, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_202_bits[] = {
+0x08, 0x14, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_203_bits[] = {
+0x36, 0x00, 0x7f, 0x42, 0x42, 0x12, 0x1e, 0x12, 0x42, 0x42, 0x7f};
+static unsigned char courier14_204_bits[] = {
+0x03, 0x0c, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_205_bits[] = {
+0x18, 0x06, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_206_bits[] = {
+0x04, 0x0a, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_207_bits[] = {
+0x1b, 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_208_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x8f, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier14_209_bits[] = {
+0x58, 0x34, 0x00, 0xe7, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x47};
+static unsigned char courier14_210_bits[] = {
+0x0c, 0x30, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_211_bits[] = {
+0x30, 0x0c, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_212_bits[] = {
+0x08, 0x14, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_213_bits[] = {
+0x58, 0x34, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_214_bits[] = {
+0x66, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_215_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char courier14_216_bits[] = {
+0x78, 0x01, 0x84, 0x00, 0x42, 0x01, 0x22, 0x01, 0x12, 0x01, 0x0a, 0x01, 
+0x04, 0x01, 0x86, 0x00, 0x79, 0x00};
+static unsigned char courier14_217_bits[] = {
+0x0c, 0x30, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_218_bits[] = {
+0x30, 0x0c, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_219_bits[] = {
+0x08, 0x14, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_220_bits[] = {
+0x66, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c};
+static unsigned char courier14_221_bits[] = {
+0x30, 0x0c, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x08, 0x3e};
+static unsigned char courier14_222_bits[] = {
+0x07, 0x02, 0x3e, 0x42, 0x42, 0x42, 0x3e, 0x02, 0x07};
+static unsigned char courier14_223_bits[] = {
+0x1c, 0x22, 0x22, 0x1a, 0x22, 0x42, 0x42, 0x4a, 0x33};
+static unsigned char courier14_224_bits[] = {
+0x06, 0x18, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_225_bits[] = {
+0x18, 0x06, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_226_bits[] = {
+0x08, 0x14, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_227_bits[] = {
+0x2c, 0x1a, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_228_bits[] = {
+0x36, 0x00, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x1e, 0x21, 0x20, 0x3e, 0x21, 0x31, 0x6e};
+static unsigned char courier14_230_bits[] = {
+0x6e, 0x91, 0x90, 0xfe, 0x11, 0x91, 0x6e};
+static unsigned char courier14_231_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x01, 0x42, 0x3c, 0x08, 0x10, 0x1c};
+static unsigned char courier14_232_bits[] = {
+0x06, 0x18, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_233_bits[] = {
+0x30, 0x0c, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_234_bits[] = {
+0x08, 0x14, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_235_bits[] = {
+0x36, 0x00, 0x1c, 0x22, 0x41, 0x7f, 0x01, 0x42, 0x3c};
+static unsigned char courier14_236_bits[] = {
+0x03, 0x0c, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_237_bits[] = {
+0x0c, 0x03, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_238_bits[] = {
+0x04, 0x0a, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_239_bits[] = {
+0x1b, 0x00, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier14_240_bits[] = {
+0x40, 0x27, 0x18, 0x14, 0x22, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_241_bits[] = {
+0x58, 0x34, 0x00, 0x3b, 0x46, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char courier14_242_bits[] = {
+0x0c, 0x30, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_243_bits[] = {
+0x30, 0x0c, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_244_bits[] = {
+0x08, 0x14, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_245_bits[] = {
+0x58, 0x34, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_246_bits[] = {
+0x36, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier14_247_bits[] = {
+0x18, 0x18, 0x00, 0xff, 0x00, 0x18, 0x18};
+static unsigned char courier14_248_bits[] = {
+0xbc, 0x62, 0x91, 0x89, 0x85, 0x42, 0x3d};
+static unsigned char courier14_249_bits[] = {
+0x0c, 0x30, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_250_bits[] = {
+0x30, 0x0c, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_251_bits[] = {
+0x08, 0x14, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_252_bits[] = {
+0x36, 0x00, 0x63, 0x42, 0x42, 0x42, 0x42, 0x62, 0xdc};
+static unsigned char courier14_253_bits[] = {
+0x60, 0x18, 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x10, 0x08, 0x08, 
+0x1e};
+static unsigned char courier14_254_bits[] = {
+0x03, 0x02, 0x3a, 0x46, 0x82, 0x82, 0x82, 0x46, 0x3a, 0x02, 0x02, 0x0f};
+static unsigned char courier14_255_bits[] = {
+0x6c, 0x00, 0xe7, 0x42, 0x42, 0x24, 0x24, 0x18, 0x10, 0x08, 0x08, 0x1e};
+static RotFont courier14font[] = {
+{5, 1, 1, courier14_0_bits},
+{5, 1, 1, courier14_1_bits},
+{5, 1, 1, courier14_2_bits},
+{5, 1, 1, courier14_3_bits},
+{5, 1, 1, courier14_4_bits},
+{5, 1, 1, courier14_5_bits},
+{5, 1, 1, courier14_6_bits},
+{5, 1, 1, courier14_7_bits},
+{5, 1, 1, courier14_8_bits},
+{5, 1, 1, courier14_9_bits},
+{5, 1, 1, courier14_10_bits},
+{5, 1, 1, courier14_11_bits},
+{5, 1, 1, courier14_12_bits},
+{5, 1, 1, courier14_13_bits},
+{5, 1, 1, courier14_14_bits},
+{5, 1, 1, courier14_15_bits},
+{5, 1, 1, courier14_16_bits},
+{5, 1, 1, courier14_17_bits},
+{5, 1, 1, courier14_18_bits},
+{5, 1, 1, courier14_19_bits},
+{5, 1, 1, courier14_20_bits},
+{5, 1, 1, courier14_21_bits},
+{5, 1, 1, courier14_22_bits},
+{5, 1, 1, courier14_23_bits},
+{5, 1, 1, courier14_24_bits},
+{5, 1, 1, courier14_25_bits},
+{5, 1, 1, courier14_26_bits},
+{5, 1, 1, courier14_27_bits},
+{5, 1, 1, courier14_28_bits},
+{5, 1, 1, courier14_29_bits},
+{5, 1, 1, courier14_30_bits},
+{5, 1, 1, courier14_31_bits},
+{6, 1, 1, courier14_32_bits},
+{1, 9, 9, courier14_33_bits},
+{4, 4, 10, courier14_34_bits},
+{5, 10, 9, courier14_35_bits},
+{5, 13, 11, courier14_36_bits},
+{8, 10, 10, courier14_37_bits},
+{6, 8, 8, courier14_38_bits},
+{3, 4, 10, courier14_39_bits},
+{3, 12, 10, courier14_40_bits},
+{3, 12, 10, courier14_41_bits},
+{5, 6, 9, courier14_42_bits},
+{7, 7, 8, courier14_43_bits},
+{3, 4, 2, courier14_44_bits},
+{7, 1, 5, courier14_45_bits},
+{2, 2, 2, courier14_46_bits},
+{6, 11, 10, courier14_47_bits},
+{6, 10, 10, courier14_48_bits},
+{5, 10, 10, courier14_49_bits},
+{5, 10, 10, courier14_50_bits},
+{6, 10, 10, courier14_51_bits},
+{6, 10, 10, courier14_52_bits},
+{6, 10, 10, courier14_53_bits},
+{6, 10, 10, courier14_54_bits},
+{6, 10, 10, courier14_55_bits},
+{5, 10, 10, courier14_56_bits},
+{6, 10, 10, courier14_57_bits},
+{2, 7, 7, courier14_58_bits},
+{3, 9, 7, courier14_59_bits},
+{7, 7, 8, courier14_60_bits},
+{7, 3, 6, courier14_61_bits},
+{7, 7, 8, courier14_62_bits},
+{5, 9, 9, courier14_63_bits},
+{7, 10, 9, courier14_64_bits},
+{9, 9, 9, courier14_65_bits},
+{7, 9, 9, courier14_66_bits},
+{7, 9, 9, courier14_67_bits},
+{8, 9, 9, courier14_68_bits},
+{7, 9, 9, courier14_69_bits},
+{7, 9, 9, courier14_70_bits},
+{8, 9, 9, courier14_71_bits},
+{8, 9, 9, courier14_72_bits},
+{5, 9, 9, courier14_73_bits},
+{7, 9, 9, courier14_74_bits},
+{8, 9, 9, courier14_75_bits},
+{8, 9, 9, courier14_76_bits},
+{9, 9, 9, courier14_77_bits},
+{8, 9, 9, courier14_78_bits},
+{8, 9, 9, courier14_79_bits},
+{7, 9, 9, courier14_80_bits},
+{8, 11, 9, courier14_81_bits},
+{8, 9, 9, courier14_82_bits},
+{6, 9, 9, courier14_83_bits},
+{7, 9, 9, courier14_84_bits},
+{8, 9, 9, courier14_85_bits},
+{9, 9, 9, courier14_86_bits},
+{9, 9, 9, courier14_87_bits},
+{8, 9, 9, courier14_88_bits},
+{7, 9, 9, courier14_89_bits},
+{6, 9, 9, courier14_90_bits},
+{3, 12, 10, courier14_91_bits},
+{6, 11, 10, courier14_92_bits},
+{3, 12, 10, courier14_93_bits},
+{5, 5, 9, courier14_94_bits},
+{9, 1, -2, courier14_95_bits},
+{3, 4, 10, courier14_96_bits},
+{7, 7, 7, courier14_97_bits},
+{8, 10, 10, courier14_98_bits},
+{7, 7, 7, courier14_99_bits},
+{8, 10, 10, courier14_100_bits},
+{7, 7, 7, courier14_101_bits},
+{7, 10, 10, courier14_102_bits},
+{8, 10, 7, courier14_103_bits},
+{8, 10, 10, courier14_104_bits},
+{5, 10, 10, courier14_105_bits},
+{5, 13, 10, courier14_106_bits},
+{7, 10, 10, courier14_107_bits},
+{5, 10, 10, courier14_108_bits},
+{9, 7, 7, courier14_109_bits},
+{8, 7, 7, courier14_110_bits},
+{8, 7, 7, courier14_111_bits},
+{8, 10, 7, courier14_112_bits},
+{8, 10, 7, courier14_113_bits},
+{7, 7, 7, courier14_114_bits},
+{6, 7, 7, courier14_115_bits},
+{7, 9, 9, courier14_116_bits},
+{8, 7, 7, courier14_117_bits},
+{8, 7, 7, courier14_118_bits},
+{9, 7, 7, courier14_119_bits},
+{7, 7, 7, courier14_120_bits},
+{8, 10, 7, courier14_121_bits},
+{5, 7, 7, courier14_122_bits},
+{3, 12, 10, courier14_123_bits},
+{1, 11, 9, courier14_124_bits},
+{3, 12, 10, courier14_125_bits},
+{6, 2, 5, courier14_126_bits},
+{5, 1, 1, courier14_127_bits},
+{5, 1, 1, courier14_128_bits},
+{5, 1, 1, courier14_129_bits},
+{5, 1, 1, courier14_130_bits},
+{5, 1, 1, courier14_131_bits},
+{5, 1, 1, courier14_132_bits},
+{5, 1, 1, courier14_133_bits},
+{5, 1, 1, courier14_134_bits},
+{5, 1, 1, courier14_135_bits},
+{5, 1, 1, courier14_136_bits},
+{5, 1, 1, courier14_137_bits},
+{5, 1, 1, courier14_138_bits},
+{5, 1, 1, courier14_139_bits},
+{5, 1, 1, courier14_140_bits},
+{5, 1, 1, courier14_141_bits},
+{5, 1, 1, courier14_142_bits},
+{5, 1, 1, courier14_143_bits},
+{5, 1, 1, courier14_144_bits},
+{5, 1, 1, courier14_145_bits},
+{5, 1, 1, courier14_146_bits},
+{5, 1, 1, courier14_147_bits},
+{5, 1, 1, courier14_148_bits},
+{5, 1, 1, courier14_149_bits},
+{5, 1, 1, courier14_150_bits},
+{5, 1, 1, courier14_151_bits},
+{5, 1, 1, courier14_152_bits},
+{5, 1, 1, courier14_153_bits},
+{5, 1, 1, courier14_154_bits},
+{5, 1, 1, courier14_155_bits},
+{5, 1, 1, courier14_156_bits},
+{5, 1, 1, courier14_157_bits},
+{5, 1, 1, courier14_158_bits},
+{5, 1, 1, courier14_159_bits},
+{1, 1, 1, courier14_160_bits},
+{1, 9, 7, courier14_161_bits},
+{5, 9, 9, courier14_162_bits},
+{7, 9, 9, courier14_163_bits},
+{6, 6, 7, courier14_164_bits},
+{7, 9, 9, courier14_165_bits},
+{1, 11, 9, courier14_166_bits},
+{6, 10, 9, courier14_167_bits},
+{5, 1, 9, courier14_168_bits},
+{8, 9, 9, courier14_169_bits},
+{4, 6, 9, courier14_170_bits},
+{8, 7, 7, courier14_171_bits},
+{7, 3, 6, courier14_172_bits},
+{6, 1, 5, courier14_173_bits},
+{8, 9, 9, courier14_174_bits},
+{4, 1, 9, courier14_175_bits},
+{4, 4, 10, courier14_176_bits},
+{7, 7, 8, courier14_177_bits},
+{4, 6, 10, courier14_178_bits},
+{4, 6, 10, courier14_179_bits},
+{4, 2, 10, courier14_180_bits},
+{8, 10, 7, courier14_181_bits},
+{7, 10, 9, courier14_182_bits},
+{2, 2, 5, courier14_183_bits},
+{3, 3, 0, courier14_184_bits},
+{3, 6, 10, courier14_185_bits},
+{4, 6, 9, courier14_186_bits},
+{8, 7, 7, courier14_187_bits},
+{10, 10, 10, courier14_188_bits},
+{10, 10, 10, courier14_189_bits},
+{10, 10, 10, courier14_190_bits},
+{5, 9, 7, courier14_191_bits},
+{9, 12, 12, courier14_192_bits},
+{9, 12, 12, courier14_193_bits},
+{9, 12, 12, courier14_194_bits},
+{9, 12, 12, courier14_195_bits},
+{9, 11, 11, courier14_196_bits},
+{9, 12, 12, courier14_197_bits},
+{9, 9, 9, courier14_198_bits},
+{7, 12, 9, courier14_199_bits},
+{7, 12, 12, courier14_200_bits},
+{7, 12, 12, courier14_201_bits},
+{7, 12, 12, courier14_202_bits},
+{7, 11, 11, courier14_203_bits},
+{5, 12, 12, courier14_204_bits},
+{5, 12, 12, courier14_205_bits},
+{5, 12, 12, courier14_206_bits},
+{5, 11, 11, courier14_207_bits},
+{8, 9, 9, courier14_208_bits},
+{8, 12, 12, courier14_209_bits},
+{8, 12, 12, courier14_210_bits},
+{8, 12, 12, courier14_211_bits},
+{8, 12, 12, courier14_212_bits},
+{8, 12, 12, courier14_213_bits},
+{8, 11, 11, courier14_214_bits},
+{7, 7, 8, courier14_215_bits},
+{9, 9, 9, courier14_216_bits},
+{8, 12, 12, courier14_217_bits},
+{8, 12, 12, courier14_218_bits},
+{8, 12, 12, courier14_219_bits},
+{8, 11, 11, courier14_220_bits},
+{7, 12, 12, courier14_221_bits},
+{7, 9, 9, courier14_222_bits},
+{7, 9, 9, courier14_223_bits},
+{7, 10, 10, courier14_224_bits},
+{7, 10, 10, courier14_225_bits},
+{7, 10, 10, courier14_226_bits},
+{7, 10, 10, courier14_227_bits},
+{7, 9, 9, courier14_228_bits},
+{7, 10, 10, courier14_229_bits},
+{8, 7, 7, courier14_230_bits},
+{7, 10, 7, courier14_231_bits},
+{7, 10, 10, courier14_232_bits},
+{7, 10, 10, courier14_233_bits},
+{7, 10, 10, courier14_234_bits},
+{7, 9, 9, courier14_235_bits},
+{5, 10, 10, courier14_236_bits},
+{5, 10, 10, courier14_237_bits},
+{5, 10, 10, courier14_238_bits},
+{5, 9, 9, courier14_239_bits},
+{8, 12, 12, courier14_240_bits},
+{8, 10, 10, courier14_241_bits},
+{8, 10, 10, courier14_242_bits},
+{8, 10, 10, courier14_243_bits},
+{8, 10, 10, courier14_244_bits},
+{8, 10, 10, courier14_245_bits},
+{8, 9, 9, courier14_246_bits},
+{8, 7, 8, courier14_247_bits},
+{8, 7, 7, courier14_248_bits},
+{8, 10, 10, courier14_249_bits},
+{8, 10, 10, courier14_250_bits},
+{8, 10, 10, courier14_251_bits},
+{8, 9, 9, courier14_252_bits},
+{8, 13, 10, courier14_253_bits},
+{8, 12, 9, courier14_254_bits},
+{8, 12, 9, courier14_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier18.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier18.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier18.bdf	(revision 16632)
@@ -0,0 +1,3453 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Courier-Medium-R-Normal--18-180-75-75-M-110-ISO8859-1
+SIZE 18 75 75
+FONTBOUNDINGBOX 12 19 -1 -4
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Courier"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "M"
+AVERAGE_WIDTH 110
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 11
+X_HEIGHT 8
+FACE_NAME "Courier"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Courier"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Courier"
+FONT "-Adobe-Courier-Medium-R-Normal--18-180-75-75-M-110-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 11
+DEFAULT_CHAR 32
+FONT_ASCENT 14
+FONT_DESCENT 4
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 12 4 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 5 3 7
+BITMAP
+d8
+d8
+d8
+90
+90
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 -2
+BITMAP
+1200
+1200
+1200
+1200
+1200
+ff80
+2400
+2400
+2400
+ff00
+2400
+2400
+2400
+2400
+2400
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 -2
+BITMAP
+10
+10
+7a
+86
+82
+80
+70
+0c
+02
+82
+c2
+bc
+10
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+7000
+8800
+8800
+8800
+7180
+0e00
+3000
+ce00
+1100
+1100
+1100
+0e00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 10 2 0
+BITMAP
+38
+44
+40
+40
+20
+74
+88
+88
+98
+66
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 4 5 3 7
+BITMAP
+30
+30
+60
+60
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 14 5 -2
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 14 3 -2
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 8 2 4
+BITMAP
+10
+10
+10
+fe
+38
+28
+44
+44
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 1
+BITMAP
+0800
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 4 5 3 -3
+BITMAP
+30
+30
+60
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 1 1 5
+BITMAP
+ff80
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 2 4 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 16 1 -3
+BITMAP
+01
+01
+02
+02
+04
+04
+08
+08
+10
+10
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+38
+44
+82
+82
+82
+82
+82
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+30
+d0
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+1c
+22
+41
+41
+01
+02
+04
+08
+10
+20
+41
+ff
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+78
+84
+02
+02
+04
+38
+04
+02
+02
+02
+84
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+0c
+14
+14
+24
+24
+44
+44
+84
+fe
+04
+04
+1e
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+7e
+40
+40
+40
+5c
+62
+01
+01
+01
+01
+c2
+3c
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+1e
+20
+40
+40
+80
+b8
+c4
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 2 0
+BITMAP
+ff
+81
+02
+02
+04
+04
+04
+04
+08
+08
+08
+08
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+38
+44
+82
+82
+44
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+38
+44
+82
+82
+82
+46
+3a
+02
+02
+04
+08
+f0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 8 5 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 11 2 -3
+BITMAP
+18
+18
+00
+00
+00
+00
+30
+30
+60
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 1
+BITMAP
+00c0
+0300
+0c00
+3000
+c000
+3000
+0c00
+0300
+00c0
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 4 1 3
+BITMAP
+ff80
+0000
+0000
+ff80
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 1
+BITMAP
+c000
+3000
+0c00
+0300
+00c0
+0300
+0c00
+3000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+7c
+86
+82
+02
+04
+08
+30
+20
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 13 2 -1
+BITMAP
+3c
+42
+82
+82
+8e
+92
+92
+92
+8f
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+fe00
+4100
+4100
+4100
+4200
+7e00
+4100
+4080
+4080
+4100
+fe00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1e80
+6180
+4080
+8000
+8000
+8000
+8000
+8000
+4080
+6100
+1e00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+fc
+42
+41
+41
+41
+41
+41
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+ff
+41
+41
+41
+48
+78
+48
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 1 0
+BITMAP
+1e80
+6180
+4080
+8000
+8000
+8000
+83c0
+8080
+4080
+6100
+1e00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+4100
+4100
+4100
+7f00
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1f80
+0200
+0200
+0200
+0200
+0200
+8200
+8200
+8200
+4400
+3800
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 0 0
+BITMAP
+f3c0
+4100
+4200
+4400
+4800
+5800
+6400
+4200
+4200
+4100
+f1c0
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+f800
+2000
+2000
+2000
+2000
+2000
+2000
+2080
+2080
+2080
+ff80
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+4a40
+4a40
+4440
+4440
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e780
+6100
+5100
+5100
+4900
+4900
+4500
+4500
+4300
+4300
+f100
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+fe00
+4100
+4080
+4080
+4080
+4100
+7e00
+4000
+4000
+4000
+f800
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 -2
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+3880
+4700
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 1 0
+BITMAP
+fe00
+4100
+4100
+4100
+4200
+7c00
+4200
+4200
+4100
+4100
+f0c0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 2 0
+BITMAP
+3a
+46
+82
+80
+40
+3c
+02
+01
+81
+c2
+bc
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+ff80
+8880
+8880
+8880
+0800
+0800
+0800
+0800
+0800
+0800
+3e00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 0 0
+BITMAP
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+f1e0
+4040
+4040
+2080
+2080
+1100
+1100
+0a00
+0a00
+0400
+0400
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+f1e0
+4040
+4440
+4440
+4440
+2a80
+2a80
+2a80
+2a80
+1100
+1100
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+0800
+1400
+2200
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+0800
+0800
+3e00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+fe
+82
+84
+08
+08
+10
+20
+20
+42
+82
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 15 5 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 16 2 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+10
+10
+08
+08
+04
+04
+02
+02
+01
+01
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 15 3 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 4 2 8
+BITMAP
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 1 0 -4
+BITMAP
+ffe0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 4 5 3 7
+BITMAP
+c0
+c0
+60
+60
+30
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+c000
+4000
+4000
+4000
+5e00
+6100
+4080
+4080
+4080
+4080
+6100
+de00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3d
+43
+81
+80
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0300
+0100
+0100
+0100
+3d00
+4300
+8100
+8100
+8100
+8100
+4300
+3d80
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 2 0
+BITMAP
+0f
+10
+20
+20
+fe
+20
+20
+20
+20
+20
+20
+fe
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+3d80
+4300
+8100
+8100
+8100
+8100
+4300
+3d00
+0100
+0100
+0200
+7c00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+c000
+4000
+4000
+4000
+5e00
+6100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+10
+10
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 15 2 -4
+BITMAP
+08
+08
+00
+fc
+04
+04
+04
+04
+04
+04
+04
+04
+04
+08
+f0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+c000
+4000
+4000
+4000
+4f00
+4400
+4800
+7000
+4800
+4400
+4200
+c780
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+f0
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 8 0 0
+BITMAP
+d980
+6640
+4440
+4440
+4440
+4440
+4440
+e660
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+de00
+6100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+de00
+6100
+4080
+4080
+4080
+4080
+6100
+5e00
+4000
+4000
+4000
+f000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+3d80
+4300
+8100
+8100
+8100
+8100
+4300
+3d00
+0100
+0100
+0100
+0780
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+ee
+31
+20
+20
+20
+20
+20
+fe
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 8 2 0
+BITMAP
+7a
+86
+82
+70
+0c
+82
+c2
+bc
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 2 0
+BITMAP
+20
+20
+20
+fe
+20
+20
+20
+20
+20
+21
+1e
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+e380
+4100
+4900
+4900
+5500
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+e7
+42
+24
+18
+18
+24
+42
+e7
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+1000
+1000
+f800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 8 2 0
+BITMAP
+fe
+82
+84
+08
+10
+22
+42
+fe
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 15 3 -3
+BITMAP
+18
+20
+20
+20
+20
+20
+c0
+20
+20
+20
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 15 5 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 15 3 -3
+BITMAP
+c0
+20
+20
+20
+20
+20
+18
+20
+20
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 3 1 4
+BITMAP
+60
+99
+06
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 13 4 -4
+BITMAP
+c0
+c0
+00
+00
+80
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 12 2 0
+BITMAP
+10
+10
+10
+3c
+44
+84
+80
+80
+44
+38
+10
+10
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+1c
+22
+20
+20
+10
+fc
+10
+20
+21
+41
+7e
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 7 2 2
+BITMAP
+84
+78
+84
+84
+84
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+7f00
+0800
+7f00
+0800
+3e00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 1 15 5 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 13 2 -1
+BITMAP
+3e
+42
+42
+40
+70
+8c
+82
+62
+1c
+04
+84
+84
+f8
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 1 3 10
+BITMAP
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 11 0 0
+BITMAP
+1e00
+6180
+4e80
+9240
+a040
+a040
+a040
+9240
+4c80
+6180
+1e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 8 2 3
+BITMAP
+70
+08
+78
+88
+98
+ec
+00
+fc
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+0880
+3300
+6600
+cc00
+cc00
+6600
+3300
+0880
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 4 1 3
+BITMAP
+ff80
+0080
+0080
+0080
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 1 1 5
+BITMAP
+ff
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+1f00
+60c0
+5e40
+9120
+9120
+9e20
+9420
+9220
+51c0
+6080
+1f00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 1 3 9
+BITMAP
+f8
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 5 3 7
+BITMAP
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 1
+BITMAP
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0000
+ff80
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 7 3 5
+BITMAP
+70
+88
+08
+10
+20
+40
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 7 3 5
+BITMAP
+70
+88
+08
+30
+08
+88
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 3 4 9
+BITMAP
+20
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 -4
+BITMAP
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+7d80
+4000
+4000
+4000
+4000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 13 1 -1
+BITMAP
+3f
+4a
+8a
+8a
+8a
+4a
+3a
+0a
+0a
+0a
+0a
+0a
+3b
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 2 2 4 5
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 3 3 4 -3
+BITMAP
+40
+20
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 5 7 3 5
+BITMAP
+20
+e0
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 8 2 3
+BITMAP
+78
+84
+84
+84
+84
+78
+00
+fc
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+8800
+6600
+3300
+1980
+1980
+3300
+6600
+8800
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+2000
+e000
+2040
+2080
+2100
+2100
+fa40
+04c0
+0940
+0a40
+13e0
+2040
+00e0
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+2000
+e000
+2040
+2080
+2100
+2100
+fac0
+0520
+0920
+0840
+1080
+2100
+03e0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+7000
+8800
+0840
+3080
+0900
+8900
+7240
+04c0
+0940
+0a40
+13e0
+2040
+00e0
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 6 12 2 -3
+BITMAP
+18
+18
+00
+10
+10
+70
+80
+80
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+1000
+0800
+0400
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+0200
+0400
+0800
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+0400
+0a00
+1100
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 14 0 0
+BITMAP
+1900
+2600
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 14 0 0
+BITMAP
+1b00
+0000
+0000
+3c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 15 0 0
+BITMAP
+0c00
+1200
+1200
+0c00
+7c00
+0400
+0a00
+0a00
+1100
+1100
+2080
+3f80
+4040
+4040
+f1e0
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 -1 0
+BITMAP
+1fe0
+0620
+0a20
+0a00
+1240
+13c0
+3e40
+2200
+4220
+4220
+e7e0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -3
+BITMAP
+1e80
+6180
+4080
+8000
+8000
+8000
+8000
+8000
+4080
+6100
+1e00
+0800
+0400
+1800
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 15 1 0
+BITMAP
+20
+10
+08
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 15 1 0
+BITMAP
+04
+08
+10
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 15 1 0
+BITMAP
+18
+24
+42
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 14 1 0
+BITMAP
+66
+00
+00
+ff
+41
+41
+41
+48
+78
+48
+41
+41
+41
+ff
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 0
+BITMAP
+20
+10
+08
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 0
+BITMAP
+08
+10
+20
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 15 2 0
+BITMAP
+10
+28
+44
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 14 2 0
+BITMAP
+6c
+00
+00
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+fc
+42
+41
+41
+41
+f1
+41
+41
+41
+42
+fc
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1900
+2600
+0000
+e780
+6100
+5100
+5100
+4900
+4900
+4500
+4500
+4300
+4300
+f100
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+1000
+0800
+0400
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+0400
+0800
+1000
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+0800
+1400
+2200
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1900
+2600
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+3600
+0000
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 1
+BITMAP
+8080
+4100
+2200
+1400
+0800
+1400
+2200
+4100
+8080
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+0e20
+3140
+2080
+4140
+4240
+4440
+4840
+5040
+2080
+5180
+8e00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 15 0 0
+BITMAP
+1000
+0800
+0400
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 15 0 0
+BITMAP
+0200
+0400
+0800
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 15 0 0
+BITMAP
+0c00
+1200
+2100
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 14 0 0
+BITMAP
+3300
+0000
+0000
+f3c0
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+4080
+2100
+1e00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 0
+BITMAP
+0200
+0400
+0800
+0000
+e380
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+0800
+0800
+3e00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+e000
+4000
+7e00
+4100
+4080
+4080
+4100
+7e00
+4000
+4000
+e000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+1c
+22
+42
+42
+44
+4c
+42
+41
+41
+41
+49
+e6
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+2000
+1000
+0800
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0400
+0800
+1000
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1800
+2400
+4200
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+3200
+4c00
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+3600
+0000
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+1800
+2400
+2400
+1800
+0000
+3c00
+4200
+0200
+7e00
+8200
+8200
+8600
+7b80
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 8 0 0
+BITMAP
+7180
+8a40
+0420
+7fe0
+8400
+8400
+8a20
+71c0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 -3
+BITMAP
+3d
+43
+81
+80
+80
+80
+43
+3c
+10
+08
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+20
+10
+08
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+04
+08
+10
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+18
+24
+42
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+66
+00
+00
+3c
+42
+81
+ff
+80
+80
+43
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+40
+20
+10
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+08
+10
+20
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 12 2 0
+BITMAP
+10
+28
+44
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 11 2 0
+BITMAP
+6c
+00
+00
+70
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+73
+8c
+34
+42
+02
+3d
+43
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1900
+2600
+0000
+de00
+6100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+20
+10
+08
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+02
+04
+08
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 12 1 0
+BITMAP
+18
+24
+42
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+32
+4c
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 11 1 0
+BITMAP
+66
+00
+00
+3c
+42
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 9 1 1
+BITMAP
+18
+18
+00
+00
+ff
+00
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 8 1 0
+BITMAP
+3d
+42
+85
+89
+91
+a1
+42
+bc
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1000
+0800
+0400
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0400
+0800
+1000
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+0800
+1400
+2200
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+3600
+0000
+0000
+c300
+4100
+4100
+4100
+4100
+4100
+4300
+3d80
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 -4
+BITMAP
+0200
+0400
+0800
+0000
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+1000
+1000
+f800
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 -4
+BITMAP
+c000
+4000
+4000
+4000
+5e00
+6100
+4080
+4080
+4080
+4080
+6100
+5e00
+4000
+4000
+4000
+f000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 15 1 -4
+BITMAP
+3600
+0000
+0000
+e380
+4100
+4100
+2200
+2200
+1400
+1400
+0800
+0800
+1000
+1000
+f800
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier18.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier18.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier18.h	(revision 16632)
@@ -0,0 +1,906 @@
+static unsigned char courier18_0_bits[] = {
+0x00};
+static unsigned char courier18_1_bits[] = {
+0x00};
+static unsigned char courier18_2_bits[] = {
+0x00};
+static unsigned char courier18_3_bits[] = {
+0x00};
+static unsigned char courier18_4_bits[] = {
+0x00};
+static unsigned char courier18_5_bits[] = {
+0x00};
+static unsigned char courier18_6_bits[] = {
+0x00};
+static unsigned char courier18_7_bits[] = {
+0x00};
+static unsigned char courier18_8_bits[] = {
+0x00};
+static unsigned char courier18_9_bits[] = {
+0x00};
+static unsigned char courier18_10_bits[] = {
+0x00};
+static unsigned char courier18_11_bits[] = {
+0x00};
+static unsigned char courier18_12_bits[] = {
+0x00};
+static unsigned char courier18_13_bits[] = {
+0x00};
+static unsigned char courier18_14_bits[] = {
+0x00};
+static unsigned char courier18_15_bits[] = {
+0x00};
+static unsigned char courier18_16_bits[] = {
+0x00};
+static unsigned char courier18_17_bits[] = {
+0x00};
+static unsigned char courier18_18_bits[] = {
+0x00};
+static unsigned char courier18_19_bits[] = {
+0x00};
+static unsigned char courier18_20_bits[] = {
+0x00};
+static unsigned char courier18_21_bits[] = {
+0x00};
+static unsigned char courier18_22_bits[] = {
+0x00};
+static unsigned char courier18_23_bits[] = {
+0x00};
+static unsigned char courier18_24_bits[] = {
+0x00};
+static unsigned char courier18_25_bits[] = {
+0x00};
+static unsigned char courier18_26_bits[] = {
+0x00};
+static unsigned char courier18_27_bits[] = {
+0x00};
+static unsigned char courier18_28_bits[] = {
+0x00};
+static unsigned char courier18_29_bits[] = {
+0x00};
+static unsigned char courier18_30_bits[] = {
+0x00};
+static unsigned char courier18_31_bits[] = {
+0x00};
+static unsigned char courier18_32_bits[] = {
+0x00};
+static unsigned char courier18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x00, 0x03, 0x03};
+static unsigned char courier18_34_bits[] = {
+0x1b, 0x1b, 0x1b, 0x09, 0x09};
+static unsigned char courier18_35_bits[] = {
+0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0xff, 0x01, 
+0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 0xff, 0x00, 0x24, 0x00, 0x24, 0x00, 
+0x24, 0x00, 0x24, 0x00, 0x24, 0x00};
+static unsigned char courier18_36_bits[] = {
+0x08, 0x08, 0x5e, 0x61, 0x41, 0x01, 0x0e, 0x30, 0x40, 0x41, 0x43, 0x3d, 
+0x08, 0x08, 0x08};
+static unsigned char courier18_37_bits[] = {
+0x0e, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x8e, 0x01, 0x70, 0x00, 
+0x0c, 0x00, 0x73, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x70, 0x00};
+static unsigned char courier18_38_bits[] = {
+0x1c, 0x22, 0x02, 0x02, 0x04, 0x2e, 0x11, 0x11, 0x19, 0x66};
+static unsigned char courier18_39_bits[] = {
+0x0c, 0x0c, 0x06, 0x06, 0x03};
+static unsigned char courier18_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 
+0x02, 0x04};
+static unsigned char courier18_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 
+0x02, 0x01};
+static unsigned char courier18_42_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x1c, 0x14, 0x22, 0x22};
+static unsigned char courier18_43_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char courier18_44_bits[] = {
+0x0c, 0x0c, 0x06, 0x06, 0x03};
+static unsigned char courier18_45_bits[] = {
+0xff, 0x01};
+static unsigned char courier18_46_bits[] = {
+0x03, 0x03};
+static unsigned char courier18_47_bits[] = {
+0x80, 0x80, 0x40, 0x40, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 
+0x02, 0x02, 0x01, 0x01};
+static unsigned char courier18_48_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier18_49_bits[] = {
+0x0c, 0x0b, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_50_bits[] = {
+0x38, 0x44, 0x82, 0x82, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x82, 0xff};
+static unsigned char courier18_51_bits[] = {
+0x1e, 0x21, 0x40, 0x40, 0x20, 0x1c, 0x20, 0x40, 0x40, 0x40, 0x21, 0x1e};
+static unsigned char courier18_52_bits[] = {
+0x30, 0x28, 0x28, 0x24, 0x24, 0x22, 0x22, 0x21, 0x7f, 0x20, 0x20, 0x78};
+static unsigned char courier18_53_bits[] = {
+0x7e, 0x02, 0x02, 0x02, 0x3a, 0x46, 0x80, 0x80, 0x80, 0x80, 0x43, 0x3c};
+static unsigned char courier18_54_bits[] = {
+0x78, 0x04, 0x02, 0x02, 0x01, 0x1d, 0x23, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier18_55_bits[] = {
+0xff, 0x81, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x10, 0x10};
+static unsigned char courier18_56_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x22, 0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char courier18_57_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x62, 0x5c, 0x40, 0x40, 0x20, 0x10, 0x0f};
+static unsigned char courier18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char courier18_59_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x06, 0x06, 0x03};
+static unsigned char courier18_60_bits[] = {
+0x00, 0x03, 0xc0, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x0c, 0x00, 
+0x30, 0x00, 0xc0, 0x00, 0x00, 0x03};
+static unsigned char courier18_61_bits[] = {
+0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01};
+static unsigned char courier18_62_bits[] = {
+0x03, 0x00, 0x0c, 0x00, 0x30, 0x00, 0xc0, 0x00, 0x00, 0x03, 0xc0, 0x00, 
+0x30, 0x00, 0x0c, 0x00, 0x03, 0x00};
+static unsigned char courier18_63_bits[] = {
+0x3e, 0x61, 0x41, 0x40, 0x20, 0x10, 0x0c, 0x04, 0x00, 0x0c, 0x0c};
+static unsigned char courier18_64_bits[] = {
+0x3c, 0x42, 0x41, 0x41, 0x71, 0x49, 0x49, 0x49, 0xf1, 0x01, 0x01, 0xc2, 
+0x3c};
+static unsigned char courier18_65_bits[] = {
+0x3c, 0x00, 0x20, 0x00, 0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 
+0x04, 0x01, 0xfc, 0x01, 0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_66_bits[] = {
+0x7f, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x42, 0x00, 0x7e, 0x00, 
+0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 0x82, 0x00, 0x7f, 0x00};
+static unsigned char courier18_67_bits[] = {
+0x78, 0x01, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x86, 0x00, 0x78, 0x00};
+static unsigned char courier18_68_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier18_69_bits[] = {
+0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 0x82, 0x82, 0xff};
+static unsigned char courier18_70_bits[] = {
+0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char courier18_71_bits[] = {
+0x78, 0x01, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0xc1, 0x03, 0x01, 0x01, 0x02, 0x01, 0x86, 0x00, 0x78, 0x00};
+static unsigned char courier18_72_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xfe, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_73_bits[] = {
+0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_74_bits[] = {
+0xf8, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x22, 0x00, 0x1c, 0x00};
+static unsigned char courier18_75_bits[] = {
+0xcf, 0x03, 0x82, 0x00, 0x42, 0x00, 0x22, 0x00, 0x12, 0x00, 0x1a, 0x00, 
+0x26, 0x00, 0x42, 0x00, 0x42, 0x00, 0x82, 0x00, 0x8f, 0x03};
+static unsigned char courier18_76_bits[] = {
+0x1f, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0xff, 0x01};
+static unsigned char courier18_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0x52, 0x02, 0x52, 0x02, 
+0x22, 0x02, 0x22, 0x02, 0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_78_bits[] = {
+0xe7, 0x01, 0x86, 0x00, 0x8a, 0x00, 0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0xa2, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0xc2, 0x00, 0x8f, 0x00};
+static unsigned char courier18_79_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_80_bits[] = {
+0x7f, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x82, 0x00, 
+0x7e, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x1f, 0x00};
+static unsigned char courier18_81_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x38, 0x00, 0x1c, 0x01, 
+0xe2, 0x00};
+static unsigned char courier18_82_bits[] = {
+0x7f, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x42, 0x00, 0x3e, 0x00, 
+0x42, 0x00, 0x42, 0x00, 0x82, 0x00, 0x82, 0x00, 0x0f, 0x03};
+static unsigned char courier18_83_bits[] = {
+0x5c, 0x62, 0x41, 0x01, 0x02, 0x3c, 0x40, 0x80, 0x81, 0x43, 0x3d};
+static unsigned char courier18_84_bits[] = {
+0xff, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_85_bits[] = {
+0xcf, 0x03, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_86_bits[] = {
+0x8f, 0x07, 0x02, 0x02, 0x02, 0x02, 0x04, 0x01, 0x04, 0x01, 0x88, 0x00, 
+0x88, 0x00, 0x50, 0x00, 0x50, 0x00, 0x20, 0x00, 0x20, 0x00};
+static unsigned char courier18_87_bits[] = {
+0x8f, 0x07, 0x02, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x54, 0x01, 
+0x54, 0x01, 0x54, 0x01, 0x54, 0x01, 0x88, 0x00, 0x88, 0x00};
+static unsigned char courier18_88_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_89_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_90_bits[] = {
+0x7f, 0x41, 0x21, 0x10, 0x10, 0x08, 0x04, 0x04, 0x42, 0x41, 0x7f};
+static unsigned char courier18_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x07};
+static unsigned char courier18_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 
+0x40, 0x40, 0x80, 0x80};
+static unsigned char courier18_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x07};
+static unsigned char courier18_94_bits[] = {
+0x08, 0x14, 0x22, 0x41};
+static unsigned char courier18_95_bits[] = {
+0xff, 0x07};
+static unsigned char courier18_96_bits[] = {
+0x03, 0x03, 0x06, 0x06, 0x0c};
+static unsigned char courier18_97_bits[] = {
+0x3c, 0x00, 0x42, 0x00, 0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 
+0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_98_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x86, 0x00, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x86, 0x00, 0x7b, 0x00};
+static unsigned char courier18_99_bits[] = {
+0xbc, 0xc2, 0x81, 0x01, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_100_bits[] = {
+0xc0, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xbc, 0x00, 0xc2, 0x00, 
+0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_101_bits[] = {
+0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_102_bits[] = {
+0xf0, 0x08, 0x04, 0x04, 0x7f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7f};
+static unsigned char courier18_103_bits[] = {
+0xbc, 0x01, 0xc2, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0xc2, 0x00, 0xbc, 0x00, 0x80, 0x00, 0x80, 0x00, 0x40, 0x00, 0x3e, 0x00};
+static unsigned char courier18_104_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x86, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_105_bits[] = {
+0x08, 0x08, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_106_bits[] = {
+0x10, 0x10, 0x00, 0x3f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+0x20, 0x10, 0x0f};
+static unsigned char courier18_107_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xf2, 0x00, 0x22, 0x00, 
+0x12, 0x00, 0x0e, 0x00, 0x12, 0x00, 0x22, 0x00, 0x42, 0x00, 0xe3, 0x01};
+static unsigned char courier18_108_bits[] = {
+0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_109_bits[] = {
+0x9b, 0x01, 0x66, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 
+0x22, 0x02, 0x67, 0x06};
+static unsigned char courier18_110_bits[] = {
+0x7b, 0x00, 0x86, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_111_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_112_bits[] = {
+0x7b, 0x00, 0x86, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x86, 0x00, 0x7a, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x00};
+static unsigned char courier18_113_bits[] = {
+0xbc, 0x01, 0xc2, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0xc2, 0x00, 0xbc, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xe0, 0x01};
+static unsigned char courier18_114_bits[] = {
+0x77, 0x8c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x7f};
+static unsigned char courier18_115_bits[] = {
+0x5e, 0x61, 0x41, 0x0e, 0x30, 0x41, 0x43, 0x3d};
+static unsigned char courier18_116_bits[] = {
+0x04, 0x04, 0x04, 0x7f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x78};
+static unsigned char courier18_117_bits[] = {
+0xc3, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_118_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x10, 0x00, 0x10, 0x00};
+static unsigned char courier18_119_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00};
+static unsigned char courier18_120_bits[] = {
+0xe7, 0x42, 0x24, 0x18, 0x18, 0x24, 0x42, 0xe7};
+static unsigned char courier18_121_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1f, 0x00};
+static unsigned char courier18_122_bits[] = {
+0x7f, 0x41, 0x21, 0x10, 0x08, 0x44, 0x42, 0x7f};
+static unsigned char courier18_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x18};
+static unsigned char courier18_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char courier18_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x18, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x03};
+static unsigned char courier18_126_bits[] = {
+0x06, 0x99, 0x60};
+static unsigned char courier18_127_bits[] = {
+0x00};
+static unsigned char courier18_128_bits[] = {
+0x00};
+static unsigned char courier18_129_bits[] = {
+0x00};
+static unsigned char courier18_130_bits[] = {
+0x00};
+static unsigned char courier18_131_bits[] = {
+0x00};
+static unsigned char courier18_132_bits[] = {
+0x00};
+static unsigned char courier18_133_bits[] = {
+0x00};
+static unsigned char courier18_134_bits[] = {
+0x00};
+static unsigned char courier18_135_bits[] = {
+0x00};
+static unsigned char courier18_136_bits[] = {
+0x00};
+static unsigned char courier18_137_bits[] = {
+0x00};
+static unsigned char courier18_138_bits[] = {
+0x00};
+static unsigned char courier18_139_bits[] = {
+0x00};
+static unsigned char courier18_140_bits[] = {
+0x00};
+static unsigned char courier18_141_bits[] = {
+0x00};
+static unsigned char courier18_142_bits[] = {
+0x00};
+static unsigned char courier18_143_bits[] = {
+0x00};
+static unsigned char courier18_144_bits[] = {
+0x00};
+static unsigned char courier18_145_bits[] = {
+0x00};
+static unsigned char courier18_146_bits[] = {
+0x00};
+static unsigned char courier18_147_bits[] = {
+0x00};
+static unsigned char courier18_148_bits[] = {
+0x00};
+static unsigned char courier18_149_bits[] = {
+0x00};
+static unsigned char courier18_150_bits[] = {
+0x00};
+static unsigned char courier18_151_bits[] = {
+0x00};
+static unsigned char courier18_152_bits[] = {
+0x00};
+static unsigned char courier18_153_bits[] = {
+0x00};
+static unsigned char courier18_154_bits[] = {
+0x00};
+static unsigned char courier18_155_bits[] = {
+0x00};
+static unsigned char courier18_156_bits[] = {
+0x00};
+static unsigned char courier18_157_bits[] = {
+0x00};
+static unsigned char courier18_158_bits[] = {
+0x00};
+static unsigned char courier18_159_bits[] = {
+0x00};
+static unsigned char courier18_160_bits[] = {
+0x00};
+static unsigned char courier18_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char courier18_162_bits[] = {
+0x08, 0x08, 0x08, 0x3c, 0x22, 0x21, 0x01, 0x01, 0x22, 0x1c, 0x08, 0x08};
+static unsigned char courier18_163_bits[] = {
+0x38, 0x44, 0x04, 0x04, 0x08, 0x3f, 0x08, 0x04, 0x84, 0x82, 0x7e};
+static unsigned char courier18_164_bits[] = {
+0x21, 0x1e, 0x21, 0x21, 0x21, 0x1e, 0x21};
+static unsigned char courier18_165_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0xfe, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char courier18_167_bits[] = {
+0x7c, 0x42, 0x42, 0x02, 0x0e, 0x31, 0x41, 0x46, 0x38, 0x20, 0x21, 0x21, 
+0x1f};
+static unsigned char courier18_168_bits[] = {
+0x1b};
+static unsigned char courier18_169_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x72, 0x01, 0x49, 0x02, 0x05, 0x02, 0x05, 0x02, 
+0x05, 0x02, 0x49, 0x02, 0x32, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char courier18_170_bits[] = {
+0x0e, 0x10, 0x1e, 0x11, 0x19, 0x37, 0x00, 0x3f};
+static unsigned char courier18_171_bits[] = {
+0x10, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 0x66, 0x00, 
+0xcc, 0x00, 0x10, 0x01};
+static unsigned char courier18_172_bits[] = {
+0xff, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static unsigned char courier18_173_bits[] = {
+0xff};
+static unsigned char courier18_174_bits[] = {
+0xf8, 0x00, 0x06, 0x03, 0x7a, 0x02, 0x89, 0x04, 0x89, 0x04, 0x79, 0x04, 
+0x29, 0x04, 0x49, 0x04, 0x8a, 0x03, 0x06, 0x01, 0xf8, 0x00};
+static unsigned char courier18_175_bits[] = {
+0x1f};
+static unsigned char courier18_176_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char courier18_177_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x00, 0x00, 0xff, 0x01};
+static unsigned char courier18_178_bits[] = {
+0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x1f};
+static unsigned char courier18_179_bits[] = {
+0x0e, 0x11, 0x10, 0x0c, 0x10, 0x11, 0x0e};
+static unsigned char courier18_180_bits[] = {
+0x04, 0x02, 0x01};
+static unsigned char courier18_181_bits[] = {
+0xc3, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0xc2, 0x00, 0xbe, 0x01, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00};
+static unsigned char courier18_182_bits[] = {
+0xfc, 0x52, 0x51, 0x51, 0x51, 0x52, 0x5c, 0x50, 0x50, 0x50, 0x50, 0x50, 
+0xdc};
+static unsigned char courier18_183_bits[] = {
+0x03, 0x03};
+static unsigned char courier18_184_bits[] = {
+0x02, 0x04, 0x03};
+static unsigned char courier18_185_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char courier18_186_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x1e, 0x00, 0x3f};
+static unsigned char courier18_187_bits[] = {
+0x11, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x98, 0x01, 0xcc, 0x00, 
+0x66, 0x00, 0x11, 0x00};
+static unsigned char courier18_188_bits[] = {
+0x04, 0x00, 0x07, 0x00, 0x04, 0x02, 0x04, 0x01, 0x84, 0x00, 0x84, 0x00, 
+0x5f, 0x02, 0x20, 0x03, 0x90, 0x02, 0x50, 0x02, 0xc8, 0x07, 0x04, 0x02, 
+0x00, 0x07};
+static unsigned char courier18_189_bits[] = {
+0x04, 0x00, 0x07, 0x00, 0x04, 0x02, 0x04, 0x01, 0x84, 0x00, 0x84, 0x00, 
+0x5f, 0x03, 0xa0, 0x04, 0x90, 0x04, 0x10, 0x02, 0x08, 0x01, 0x84, 0x00, 
+0xc0, 0x07};
+static unsigned char courier18_190_bits[] = {
+0x0e, 0x00, 0x11, 0x00, 0x10, 0x02, 0x0c, 0x01, 0x90, 0x00, 0x91, 0x00, 
+0x4e, 0x02, 0x20, 0x03, 0x90, 0x02, 0x50, 0x02, 0xc8, 0x07, 0x04, 0x02, 
+0x00, 0x07};
+static unsigned char courier18_191_bits[] = {
+0x18, 0x18, 0x00, 0x08, 0x08, 0x0e, 0x01, 0x01, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char courier18_192_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_193_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_194_bits[] = {
+0x20, 0x00, 0x50, 0x00, 0x88, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_195_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 0x50, 0x00, 
+0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 0x02, 0x02, 
+0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_196_bits[] = {
+0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x20, 0x00, 0x50, 0x00, 
+0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 0x02, 0x02, 
+0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_197_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, 0x00, 0x3e, 0x00, 0x20, 0x00, 
+0x50, 0x00, 0x50, 0x00, 0x88, 0x00, 0x88, 0x00, 0x04, 0x01, 0xfc, 0x01, 
+0x02, 0x02, 0x02, 0x02, 0x8f, 0x07};
+static unsigned char courier18_198_bits[] = {
+0xf8, 0x07, 0x60, 0x04, 0x50, 0x04, 0x50, 0x00, 0x48, 0x02, 0xc8, 0x03, 
+0x7c, 0x02, 0x44, 0x00, 0x42, 0x04, 0x42, 0x04, 0xe7, 0x07};
+static unsigned char courier18_199_bits[] = {
+0x78, 0x01, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x02, 0x01, 0x86, 0x00, 0x78, 0x00, 0x10, 0x00, 
+0x20, 0x00, 0x18, 0x00};
+static unsigned char courier18_200_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 
+0x82, 0x82, 0xff};
+static unsigned char courier18_201_bits[] = {
+0x20, 0x10, 0x08, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 
+0x82, 0x82, 0xff};
+static unsigned char courier18_202_bits[] = {
+0x18, 0x24, 0x42, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 
+0x82, 0x82, 0xff};
+static unsigned char courier18_203_bits[] = {
+0x66, 0x00, 0x00, 0xff, 0x82, 0x82, 0x82, 0x12, 0x1e, 0x12, 0x82, 0x82, 
+0x82, 0xff};
+static unsigned char courier18_204_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x7f};
+static unsigned char courier18_205_bits[] = {
+0x10, 0x08, 0x04, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x7f};
+static unsigned char courier18_206_bits[] = {
+0x08, 0x14, 0x22, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x7f};
+static unsigned char courier18_207_bits[] = {
+0x36, 0x00, 0x00, 0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x7f};
+static unsigned char courier18_208_bits[] = {
+0x3f, 0x42, 0x82, 0x82, 0x82, 0x8f, 0x82, 0x82, 0x82, 0x42, 0x3f};
+static unsigned char courier18_209_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0xe7, 0x01, 0x86, 0x00, 0x8a, 0x00, 
+0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 0xa2, 0x00, 0xa2, 0x00, 0xc2, 0x00, 
+0xc2, 0x00, 0x8f, 0x00};
+static unsigned char courier18_210_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_211_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_212_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x44, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_213_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_214_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char courier18_215_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x82, 0x00, 0x01, 0x01};
+static unsigned char courier18_216_bits[] = {
+0x70, 0x04, 0x8c, 0x02, 0x04, 0x01, 0x82, 0x02, 0x42, 0x02, 0x22, 0x02, 
+0x12, 0x02, 0x0a, 0x02, 0x04, 0x01, 0x8a, 0x01, 0x71, 0x00};
+static unsigned char courier18_217_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_218_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_219_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_220_bits[] = {
+0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x03, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x84, 0x00, 0x78, 0x00};
+static unsigned char courier18_221_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x7c, 0x00};
+static unsigned char courier18_222_bits[] = {
+0x07, 0x00, 0x02, 0x00, 0x7e, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 
+0x82, 0x00, 0x7e, 0x00, 0x02, 0x00, 0x02, 0x00, 0x07, 0x00};
+static unsigned char courier18_223_bits[] = {
+0x38, 0x44, 0x42, 0x42, 0x22, 0x32, 0x42, 0x82, 0x82, 0x82, 0x92, 0x67};
+static unsigned char courier18_224_bits[] = {
+0x04, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 
+0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_225_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 
+0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_226_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x42, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 
+0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_227_bits[] = {
+0x4c, 0x00, 0x32, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x40, 0x00, 
+0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_228_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x42, 0x00, 0x40, 0x00, 
+0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 0xde, 0x01};
+static unsigned char courier18_229_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x18, 0x00, 0x00, 0x00, 0x3c, 0x00, 
+0x42, 0x00, 0x40, 0x00, 0x7e, 0x00, 0x41, 0x00, 0x41, 0x00, 0x61, 0x00, 
+0xde, 0x01};
+static unsigned char courier18_230_bits[] = {
+0x8e, 0x01, 0x51, 0x02, 0x20, 0x04, 0xfe, 0x07, 0x21, 0x00, 0x21, 0x00, 
+0x51, 0x04, 0x8e, 0x03};
+static unsigned char courier18_231_bits[] = {
+0xbc, 0xc2, 0x81, 0x01, 0x01, 0x01, 0xc2, 0x3c, 0x08, 0x10, 0x0c};
+static unsigned char courier18_232_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_233_bits[] = {
+0x20, 0x10, 0x08, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_234_bits[] = {
+0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_235_bits[] = {
+0x66, 0x00, 0x00, 0x3c, 0x42, 0x81, 0xff, 0x01, 0x01, 0xc2, 0x3c};
+static unsigned char courier18_236_bits[] = {
+0x02, 0x04, 0x08, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_237_bits[] = {
+0x10, 0x08, 0x04, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_238_bits[] = {
+0x08, 0x14, 0x22, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_239_bits[] = {
+0x36, 0x00, 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char courier18_240_bits[] = {
+0xce, 0x31, 0x2c, 0x42, 0x40, 0xbc, 0xc2, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_241_bits[] = {
+0x98, 0x00, 0x64, 0x00, 0x00, 0x00, 0x7b, 0x00, 0x86, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char courier18_242_bits[] = {
+0x04, 0x08, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_243_bits[] = {
+0x40, 0x20, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_244_bits[] = {
+0x18, 0x24, 0x42, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_245_bits[] = {
+0x4c, 0x32, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_246_bits[] = {
+0x66, 0x00, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char courier18_247_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x18, 0x18};
+static unsigned char courier18_248_bits[] = {
+0xbc, 0x42, 0xa1, 0x91, 0x89, 0x85, 0x42, 0x3d};
+static unsigned char courier18_249_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_250_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_251_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x44, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_252_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc2, 0x00, 0xbc, 0x01};
+static unsigned char courier18_253_bits[] = {
+0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 
+0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x08, 0x00, 0x08, 0x00, 0x1f, 0x00};
+static unsigned char courier18_254_bits[] = {
+0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7a, 0x00, 0x86, 0x00, 
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x86, 0x00, 0x7a, 0x00, 
+0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x0f, 0x00};
+static unsigned char courier18_255_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x1f, 0x00};
+static RotFont courier18font[] = {
+{5, 1, 1, courier18_0_bits},
+{5, 1, 1, courier18_1_bits},
+{5, 1, 1, courier18_2_bits},
+{5, 1, 1, courier18_3_bits},
+{5, 1, 1, courier18_4_bits},
+{5, 1, 1, courier18_5_bits},
+{5, 1, 1, courier18_6_bits},
+{5, 1, 1, courier18_7_bits},
+{5, 1, 1, courier18_8_bits},
+{5, 1, 1, courier18_9_bits},
+{5, 1, 1, courier18_10_bits},
+{5, 1, 1, courier18_11_bits},
+{5, 1, 1, courier18_12_bits},
+{5, 1, 1, courier18_13_bits},
+{5, 1, 1, courier18_14_bits},
+{5, 1, 1, courier18_15_bits},
+{5, 1, 1, courier18_16_bits},
+{5, 1, 1, courier18_17_bits},
+{5, 1, 1, courier18_18_bits},
+{5, 1, 1, courier18_19_bits},
+{5, 1, 1, courier18_20_bits},
+{5, 1, 1, courier18_21_bits},
+{5, 1, 1, courier18_22_bits},
+{5, 1, 1, courier18_23_bits},
+{5, 1, 1, courier18_24_bits},
+{5, 1, 1, courier18_25_bits},
+{5, 1, 1, courier18_26_bits},
+{5, 1, 1, courier18_27_bits},
+{5, 1, 1, courier18_28_bits},
+{5, 1, 1, courier18_29_bits},
+{5, 1, 1, courier18_30_bits},
+{5, 1, 1, courier18_31_bits},
+{7, 1, 1, courier18_32_bits},
+{2, 12, 12, courier18_33_bits},
+{5, 5, 12, courier18_34_bits},
+{9, 15, 13, courier18_35_bits},
+{7, 15, 13, courier18_36_bits},
+{9, 12, 12, courier18_37_bits},
+{7, 10, 10, courier18_38_bits},
+{4, 5, 12, courier18_39_bits},
+{3, 14, 12, courier18_40_bits},
+{3, 14, 12, courier18_41_bits},
+{7, 8, 12, courier18_42_bits},
+{9, 9, 10, courier18_43_bits},
+{4, 5, 2, courier18_44_bits},
+{9, 1, 6, courier18_45_bits},
+{2, 2, 2, courier18_46_bits},
+{8, 16, 13, courier18_47_bits},
+{7, 12, 12, courier18_48_bits},
+{7, 12, 12, courier18_49_bits},
+{8, 12, 12, courier18_50_bits},
+{7, 12, 12, courier18_51_bits},
+{7, 12, 12, courier18_52_bits},
+{8, 12, 12, courier18_53_bits},
+{7, 12, 12, courier18_54_bits},
+{8, 12, 12, courier18_55_bits},
+{7, 12, 12, courier18_56_bits},
+{7, 12, 12, courier18_57_bits},
+{2, 8, 8, courier18_58_bits},
+{5, 11, 8, courier18_59_bits},
+{10, 9, 10, courier18_60_bits},
+{9, 4, 7, courier18_61_bits},
+{10, 9, 10, courier18_62_bits},
+{7, 11, 11, courier18_63_bits},
+{8, 13, 12, courier18_64_bits},
+{11, 11, 11, courier18_65_bits},
+{9, 11, 11, courier18_66_bits},
+{9, 11, 11, courier18_67_bits},
+{8, 11, 11, courier18_68_bits},
+{8, 11, 11, courier18_69_bits},
+{8, 11, 11, courier18_70_bits},
+{10, 11, 11, courier18_71_bits},
+{9, 11, 11, courier18_72_bits},
+{7, 11, 11, courier18_73_bits},
+{9, 11, 11, courier18_74_bits},
+{10, 11, 11, courier18_75_bits},
+{9, 11, 11, courier18_76_bits},
+{11, 11, 11, courier18_77_bits},
+{9, 11, 11, courier18_78_bits},
+{9, 11, 11, courier18_79_bits},
+{9, 11, 11, courier18_80_bits},
+{9, 13, 11, courier18_81_bits},
+{10, 11, 11, courier18_82_bits},
+{8, 11, 11, courier18_83_bits},
+{9, 11, 11, courier18_84_bits},
+{10, 11, 11, courier18_85_bits},
+{11, 11, 11, courier18_86_bits},
+{11, 11, 11, courier18_87_bits},
+{9, 11, 11, courier18_88_bits},
+{9, 11, 11, courier18_89_bits},
+{7, 11, 11, courier18_90_bits},
+{3, 15, 12, courier18_91_bits},
+{8, 16, 13, courier18_92_bits},
+{3, 15, 12, courier18_93_bits},
+{7, 4, 12, courier18_94_bits},
+{11, 1, -3, courier18_95_bits},
+{4, 5, 12, courier18_96_bits},
+{9, 8, 8, courier18_97_bits},
+{9, 12, 12, courier18_98_bits},
+{8, 8, 8, courier18_99_bits},
+{9, 12, 12, courier18_100_bits},
+{8, 8, 8, courier18_101_bits},
+{8, 12, 12, courier18_102_bits},
+{9, 12, 8, courier18_103_bits},
+{9, 12, 12, courier18_104_bits},
+{7, 11, 11, courier18_105_bits},
+{6, 15, 11, courier18_106_bits},
+{9, 12, 12, courier18_107_bits},
+{7, 12, 12, courier18_108_bits},
+{11, 8, 8, courier18_109_bits},
+{9, 8, 8, courier18_110_bits},
+{8, 8, 8, courier18_111_bits},
+{9, 12, 8, courier18_112_bits},
+{9, 12, 8, courier18_113_bits},
+{8, 8, 8, courier18_114_bits},
+{7, 8, 8, courier18_115_bits},
+{8, 11, 11, courier18_116_bits},
+{9, 8, 8, courier18_117_bits},
+{9, 8, 8, courier18_118_bits},
+{9, 8, 8, courier18_119_bits},
+{8, 8, 8, courier18_120_bits},
+{9, 12, 8, courier18_121_bits},
+{7, 8, 8, courier18_122_bits},
+{5, 15, 12, courier18_123_bits},
+{1, 15, 12, courier18_124_bits},
+{5, 15, 12, courier18_125_bits},
+{8, 3, 7, courier18_126_bits},
+{5, 1, 1, courier18_127_bits},
+{5, 1, 1, courier18_128_bits},
+{5, 1, 1, courier18_129_bits},
+{5, 1, 1, courier18_130_bits},
+{5, 1, 1, courier18_131_bits},
+{5, 1, 1, courier18_132_bits},
+{5, 1, 1, courier18_133_bits},
+{5, 1, 1, courier18_134_bits},
+{5, 1, 1, courier18_135_bits},
+{5, 1, 1, courier18_136_bits},
+{5, 1, 1, courier18_137_bits},
+{5, 1, 1, courier18_138_bits},
+{5, 1, 1, courier18_139_bits},
+{5, 1, 1, courier18_140_bits},
+{5, 1, 1, courier18_141_bits},
+{5, 1, 1, courier18_142_bits},
+{5, 1, 1, courier18_143_bits},
+{5, 1, 1, courier18_144_bits},
+{5, 1, 1, courier18_145_bits},
+{5, 1, 1, courier18_146_bits},
+{5, 1, 1, courier18_147_bits},
+{5, 1, 1, courier18_148_bits},
+{5, 1, 1, courier18_149_bits},
+{5, 1, 1, courier18_150_bits},
+{5, 1, 1, courier18_151_bits},
+{5, 1, 1, courier18_152_bits},
+{5, 1, 1, courier18_153_bits},
+{5, 1, 1, courier18_154_bits},
+{5, 1, 1, courier18_155_bits},
+{5, 1, 1, courier18_156_bits},
+{5, 1, 1, courier18_157_bits},
+{5, 1, 1, courier18_158_bits},
+{5, 1, 1, courier18_159_bits},
+{1, 1, 1, courier18_160_bits},
+{2, 13, 9, courier18_161_bits},
+{6, 12, 12, courier18_162_bits},
+{8, 11, 11, courier18_163_bits},
+{6, 7, 9, courier18_164_bits},
+{9, 11, 11, courier18_165_bits},
+{1, 15, 12, courier18_166_bits},
+{7, 13, 12, courier18_167_bits},
+{5, 1, 11, courier18_168_bits},
+{10, 11, 11, courier18_169_bits},
+{6, 8, 11, courier18_170_bits},
+{9, 8, 8, courier18_171_bits},
+{9, 4, 7, courier18_172_bits},
+{8, 1, 6, courier18_173_bits},
+{11, 11, 11, courier18_174_bits},
+{5, 1, 10, courier18_175_bits},
+{5, 5, 12, courier18_176_bits},
+{9, 9, 10, courier18_177_bits},
+{5, 7, 12, courier18_178_bits},
+{5, 7, 12, courier18_179_bits},
+{3, 3, 12, courier18_180_bits},
+{9, 12, 8, courier18_181_bits},
+{8, 13, 12, courier18_182_bits},
+{2, 2, 7, courier18_183_bits},
+{3, 3, 0, courier18_184_bits},
+{5, 7, 12, courier18_185_bits},
+{6, 8, 11, courier18_186_bits},
+{9, 8, 8, courier18_187_bits},
+{11, 13, 13, courier18_188_bits},
+{11, 13, 13, courier18_189_bits},
+{11, 13, 13, courier18_190_bits},
+{6, 12, 9, courier18_191_bits},
+{11, 15, 15, courier18_192_bits},
+{11, 15, 15, courier18_193_bits},
+{11, 15, 15, courier18_194_bits},
+{11, 14, 14, courier18_195_bits},
+{11, 14, 14, courier18_196_bits},
+{11, 15, 15, courier18_197_bits},
+{11, 11, 11, courier18_198_bits},
+{9, 14, 11, courier18_199_bits},
+{8, 15, 15, courier18_200_bits},
+{8, 15, 15, courier18_201_bits},
+{8, 15, 15, courier18_202_bits},
+{8, 14, 14, courier18_203_bits},
+{7, 15, 15, courier18_204_bits},
+{7, 15, 15, courier18_205_bits},
+{7, 15, 15, courier18_206_bits},
+{7, 14, 14, courier18_207_bits},
+{8, 11, 11, courier18_208_bits},
+{9, 14, 14, courier18_209_bits},
+{9, 15, 15, courier18_210_bits},
+{9, 15, 15, courier18_211_bits},
+{9, 15, 15, courier18_212_bits},
+{9, 14, 14, courier18_213_bits},
+{9, 14, 14, courier18_214_bits},
+{9, 9, 10, courier18_215_bits},
+{11, 11, 11, courier18_216_bits},
+{10, 15, 15, courier18_217_bits},
+{10, 15, 15, courier18_218_bits},
+{10, 15, 15, courier18_219_bits},
+{10, 14, 14, courier18_220_bits},
+{9, 15, 15, courier18_221_bits},
+{9, 11, 11, courier18_222_bits},
+{8, 12, 12, courier18_223_bits},
+{9, 12, 12, courier18_224_bits},
+{9, 12, 12, courier18_225_bits},
+{9, 12, 12, courier18_226_bits},
+{9, 11, 11, courier18_227_bits},
+{9, 11, 11, courier18_228_bits},
+{9, 13, 13, courier18_229_bits},
+{11, 8, 8, courier18_230_bits},
+{8, 11, 8, courier18_231_bits},
+{8, 12, 12, courier18_232_bits},
+{8, 12, 12, courier18_233_bits},
+{8, 12, 12, courier18_234_bits},
+{8, 11, 11, courier18_235_bits},
+{7, 12, 12, courier18_236_bits},
+{7, 12, 12, courier18_237_bits},
+{7, 12, 12, courier18_238_bits},
+{7, 11, 11, courier18_239_bits},
+{8, 12, 12, courier18_240_bits},
+{9, 11, 11, courier18_241_bits},
+{8, 12, 12, courier18_242_bits},
+{8, 12, 12, courier18_243_bits},
+{8, 12, 12, courier18_244_bits},
+{8, 11, 11, courier18_245_bits},
+{8, 11, 11, courier18_246_bits},
+{8, 9, 10, courier18_247_bits},
+{8, 8, 8, courier18_248_bits},
+{9, 12, 12, courier18_249_bits},
+{9, 12, 12, courier18_250_bits},
+{9, 12, 12, courier18_251_bits},
+{9, 11, 11, courier18_252_bits},
+{9, 16, 12, courier18_253_bits},
+{9, 16, 12, courier18_254_bits},
+{9, 15, 11, courier18_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier24.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier24.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier24.bdf	(revision 16632)
@@ -0,0 +1,4150 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -adobe-courier-medium-r-normal--24-231-75-75-m-140-iso8859-1
+SIZE 23 75 75
+FONTBOUNDINGBOX 17 24 -1 -5
+STARTPROPERTIES 25
+FOUNDRY "adobe"
+FAMILY_NAME "courier"
+WEIGHT_NAME "medium"
+SLANT "r"
+SETWIDTH_NAME "normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 231
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "m"
+AVERAGE_WIDTH 140
+CHARSET_REGISTRY "iso8859"
+CHARSET_ENCODING "1"
+FONT "-adobe-courier-medium-r-normal--24-231-75-75-m-140-iso8859-1"
+COPYRIGHT "Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation."
+RAW_PIXEL_SIZE 1000
+RAW_POINT_SIZE 964
+RAW_ASCENT 841
+RAW_DESCENT 288
+RAW_AVERAGE_WIDTH 6000
+FACE_NAME "Couriere."
+DEFAULT_CHAR 0
+FONT_ASCENT 20
+FONT_DESCENT 7
+ENDPROPERTIES
+CHARS 190
+STARTCHAR space
+ENCODING 32
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 0 0 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 3 14 6 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+e0
+e0
+e0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 7 4 7
+ATTRIBUTES 0x0258
+BITMAP
+cc
+cc
+cc
+cc
+cc
+cc
+cc
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 17 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+1180
+1100
+1100
+1100
+1100
+1100
+ffe0
+2100
+2100
+2100
+2100
+ffe0
+2100
+2100
+2100
+2100
+2100
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 19 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0400
+0400
+1f80
+2580
+4480
+4480
+64c0
+3c00
+0f00
+0580
+c440
+4440
+6440
+7480
+7f00
+0400
+0400
+0400
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+3800
+4400
+8200
+8200
+8200
+4460
+39e0
+0f80
+7c00
+71c0
+0220
+0410
+0410
+0630
+01e0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 13 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3d00
+6200
+4000
+4000
+2000
+3000
+51c0
+c900
+8d00
+8600
+8600
+c700
+79c0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 6 4 8
+ATTRIBUTES 0x0258
+BITMAP
+30
+70
+60
+60
+c0
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 7 -2
+ATTRIBUTES 0x0258
+BITMAP
+10
+20
+20
+40
+40
+40
+80
+80
+80
+80
+80
+80
+c0
+40
+40
+20
+20
+10
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+60
+20
+20
+10
+10
+10
+10
+10
+10
+10
+10
+20
+20
+60
+40
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 9 3 5
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0800
+8880
+ff80
+3e00
+1c00
+3600
+6300
+2200
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 2
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0400
+0400
+0400
+0400
+ffe0
+0400
+0400
+0400
+0400
+0400
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 6 4 -3
+ATTRIBUTES 0x0258
+BITMAP
+30
+60
+60
+60
+c0
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 1 2 7
+ATTRIBUTES 0x0258
+BITMAP
+ffe0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 3 5 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+f0
+70
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 20 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+0040
+0080
+0080
+0180
+0100
+0300
+0200
+0200
+0400
+0400
+0800
+0800
+1000
+1000
+3000
+2000
+6000
+4000
+c000
+8000
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+4100
+8100
+8080
+8080
+8080
+8080
+8080
+8080
+8080
+8100
+4100
+6200
+3c00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+3c00
+6400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+7fc0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1e00
+2300
+4180
+4080
+0080
+0080
+0180
+0100
+0200
+0400
+0800
+1080
+6080
+8080
+ff80
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+4100
+0100
+0100
+0100
+0600
+0f00
+0100
+0080
+0080
+0080
+0080
+8300
+7e00
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0600
+0a00
+0a00
+1200
+1200
+2200
+4200
+4200
+8200
+ffc0
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+7f80
+4000
+4000
+4000
+4000
+4000
+5e00
+6180
+00c0
+0040
+0040
+0040
+0080
+c180
+7e00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 3 0
+ATTRIBUTES 0x0258
+BITMAP
+0f80
+3800
+6000
+4000
+c000
+8000
+bc00
+e200
+c300
+8100
+8100
+8100
+4100
+6200
+3c00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ffc0
+8040
+8080
+8080
+0080
+0100
+0100
+0300
+0200
+0200
+0600
+0400
+0c00
+0c00
+0800
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+c100
+8100
+8100
+8100
+6200
+3c00
+4300
+c100
+8080
+8080
+8080
+4300
+3e00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3c00
+6200
+4100
+8080
+8080
+8080
+c180
+6380
+3c80
+0080
+0100
+0100
+0200
+0400
+f800
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 9 5 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+f0
+70
+00
+00
+00
+60
+f0
+70
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 12 4 -3
+ATTRIBUTES 0x0258
+BITMAP
+30
+78
+38
+00
+00
+00
+30
+70
+60
+60
+40
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 11 1 2
+ATTRIBUTES 0x0258
+BITMAP
+0010
+0070
+0180
+0600
+3800
+e000
+3800
+0f00
+03e0
+0070
+0010
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 5 2 5
+ATTRIBUTES 0x0258
+BITMAP
+ffe0
+0000
+0000
+0000
+ffe0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 11 1 2
+ATTRIBUTES 0x0258
+BITMAP
+8000
+e000
+3800
+0600
+01c0
+0070
+03c0
+1f00
+fc00
+f000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 14 3 0
+ATTRIBUTES 0x0258
+BITMAP
+7c
+c2
+81
+81
+01
+01
+02
+1c
+10
+10
+00
+38
+38
+38
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 13 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0f80
+3060
+6010
+4698
+8d88
+8988
+9188
+9118
+9310
+dee0
+4400
+3070
+1fc0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff80
+20c0
+2020
+2020
+2020
+2060
+3f80
+2060
+2030
+2010
+2010
+2010
+2060
+ffc0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0f20
+30e0
+6060
+4060
+8020
+8000
+8000
+8000
+8000
+8000
+4000
+4030
+3060
+1f80
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff00
+20c0
+2060
+2020
+2010
+2010
+2010
+2010
+2010
+2010
+2030
+2020
+20c0
+ff80
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ffe0
+2020
+2020
+2020
+2020
+2100
+3f00
+2100
+2100
+2000
+2000
+2000
+2000
+fc00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0fa0
+30e0
+2060
+4020
+c020
+8000
+8000
+8000
+81f8
+8010
+4010
+6010
+3030
+0fc0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f0
+2020
+2020
+2020
+2020
+2020
+2020
+3fe0
+2020
+2020
+2020
+2020
+2020
+f8f0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0ff8
+0040
+0040
+0040
+0040
+0040
+0040
+0040
+4040
+4040
+4040
+4040
+6080
+1f80
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fcf8
+1020
+1040
+1080
+1100
+1200
+1400
+1e00
+1180
+1080
+1040
+1060
+1020
+fc38
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+fe00
+1000
+1000
+1000
+1000
+1000
+1000
+1000
+1010
+1010
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f03c
+2828
+2828
+2848
+2448
+2448
+2488
+2288
+2288
+2308
+2008
+2008
+2008
+f87c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0f8
+3810
+2810
+2810
+2410
+2410
+2210
+2210
+2110
+2110
+2090
+2090
+2050
+f870
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ff00
+21c0
+2040
+2020
+2020
+2020
+2060
+21c0
+3f80
+2000
+2000
+2000
+2000
+fc00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 17 1 -3
+ATTRIBUTES 0x0258
+BITMAP
+0f00
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+1f80
+0c00
+1f10
+10e0
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff80
+20c0
+2060
+2020
+2020
+2020
+20c0
+3f80
+2300
+2100
+2080
+2040
+2040
+f838
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 14 3 0
+ATTRIBUTES 0x0258
+BITMAP
+3c80
+4380
+8180
+8080
+8080
+8000
+6000
+3f00
+0180
+0080
+8080
+8080
+c100
+be00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7ff0
+4210
+4210
+4210
+4210
+c218
+0200
+0200
+0200
+0200
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f87c
+2010
+2010
+1010
+1020
+1020
+0820
+0840
+0c40
+04c0
+0480
+0280
+0380
+0300
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 15 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f83e
+6004
+6004
+6108
+2308
+2388
+2288
+2488
+24c8
+3458
+3850
+3830
+1830
+1030
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f0
+2040
+3040
+1880
+0900
+0500
+0600
+0600
+0d00
+0880
+10c0
+3060
+2020
+f8f8
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f8
+2020
+3060
+1040
+0880
+0c80
+0500
+0700
+0200
+0200
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+ff80
+8080
+8100
+8100
+8200
+0400
+0c00
+0800
+1000
+3040
+2040
+4040
+c040
+ffc0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 8 -2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 20 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+8000
+c000
+4000
+6000
+2000
+3000
+1000
+1000
+0800
+0800
+0400
+0400
+0200
+0200
+0300
+0100
+0180
+0080
+00c0
+0040
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 18 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 3
+ATTRIBUTES 0x0258
+BITMAP
+0e00
+0a00
+1a00
+1900
+1100
+3180
+2080
+60c0
+60c0
+c040
+c060
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 17 1 -1 -3
+ATTRIBUTES 0x0258
+BITMAP
+ffff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 6 4 8
+ATTRIBUTES 0x0258
+BITMAP
+30
+30
+60
+60
+e0
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e000
+2000
+2000
+2000
+2000
+27c0
+2c30
+3010
+3008
+3008
+3008
+3008
+3810
+3c30
+e7c0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1fe0
+60c0
+4040
+8000
+8000
+8000
+8000
+4020
+60c0
+1f00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+00e0
+0020
+0020
+0020
+0020
+1f20
+20e0
+4060
+8060
+8020
+8020
+8060
+4060
+31a0
+1f38
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0fc0
+1840
+1000
+1000
+1000
+ff80
+1000
+1000
+1000
+1000
+1000
+1000
+1000
+1000
+ff80
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+1f70
+61c0
+40c0
+8040
+8040
+8040
+c040
+40c0
+31c0
+1e40
+0040
+0040
+0080
+1f00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e000
+2000
+2000
+2000
+2000
+2f80
+3860
+2020
+2020
+2020
+2020
+2020
+2020
+2020
+f8f8
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 16 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+0c00
+0c00
+0000
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 20 2 -4
+ATTRIBUTES 0x0258
+BITMAP
+03
+03
+03
+00
+00
+00
+fe
+02
+02
+02
+02
+02
+02
+02
+02
+02
+02
+02
+84
+f8
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e000
+2000
+2000
+2000
+2000
+21f0
+2180
+2300
+2c00
+3c00
+2200
+2180
+20c0
+2060
+e0f8
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+7c00
+4400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 15 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+eef0
+3188
+2108
+2108
+2108
+2108
+2108
+2108
+2108
+f9ce
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ef80
+3040
+2020
+2020
+2020
+2020
+2020
+2020
+2020
+f9f8
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 0 -4
+ATTRIBUTES 0x0258
+BITMAP
+f7c0
+1c30
+1810
+1008
+1008
+1008
+1008
+1810
+1c20
+17c0
+1000
+1000
+1000
+fe00
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+1fb8
+60e0
+4060
+8020
+8020
+8020
+8020
+4060
+30a0
+1f20
+0020
+0020
+0020
+03f8
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+f3e0
+1620
+1800
+1000
+1000
+1000
+1000
+1000
+1000
+ff80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3e80
+4180
+4080
+6000
+3f00
+8380
+8040
+c040
+e0c0
+9f00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 14 3 0
+ATTRIBUTES 0x0258
+BITMAP
+4000
+4000
+4000
+4000
+ff00
+4000
+4000
+4000
+4000
+4000
+4000
+4000
+20c0
+1f00
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f8
+2020
+3040
+1040
+1080
+0880
+0980
+0500
+0700
+0600
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f03c
+4008
+4108
+2310
+2390
+2290
+1490
+1460
+1460
+0860
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 10 0 0
+ATTRIBUTES 0x0258
+BITMAP
+7c78
+1820
+0c40
+0680
+0300
+0780
+0cc0
+1860
+3030
+f87c
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+f078
+2020
+2020
+1040
+10c0
+0880
+0980
+0500
+0600
+0600
+0400
+0400
+0800
+fe00
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+7fc0
+4080
+4100
+0200
+0400
+0c00
+1800
+3040
+6040
+ffc0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 18 6 -2
+ATTRIBUTES 0x0258
+BITMAP
+18
+20
+40
+40
+40
+60
+20
+20
+60
+c0
+60
+20
+20
+60
+40
+40
+60
+38
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 1 21 7 -5
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 18 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+30
+10
+10
+10
+10
+10
+10
+18
+0c
+10
+10
+10
+10
+10
+10
+10
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 4 2 5
+ATTRIBUTES 0x0258
+BITMAP
+2040
+7cc0
+8780
+8000
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 3 13 6 -3
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+e0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 16 3 -1
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0800
+0800
+0800
+3e80
+4980
+8880
+8800
+8800
+8800
+4880
+6b00
+1c00
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0f00
+18c0
+3040
+2040
+2000
+2000
+3000
+ffc0
+1000
+1000
+1000
+1000
+2000
+3c20
+63c0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 1
+ATTRIBUTES 0x0258
+BITMAP
+8040
+5ec0
+3100
+6080
+4080
+4080
+4080
+2100
+5e80
+8040
+8040
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f8f8
+2060
+1040
+18c0
+0d80
+0700
+0200
+1fe0
+0200
+1fe0
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 1 21 7 -5
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 16 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+3f00
+6100
+4100
+4100
+3000
+f800
+8c00
+8600
+4100
+3080
+1980
+0f00
+0600
+8200
+8200
+fc00
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 3 5 12
+ATTRIBUTES 0x0258
+BITMAP
+d8
+d8
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+07c0
+1820
+2010
+4788
+4c4c
+9044
+9004
+9004
+9804
+4c44
+4788
+2010
+1820
+07c0
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 8 4 6
+ATTRIBUTES 0x0258
+BITMAP
+78
+08
+78
+88
+98
+7c
+00
+fc
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0440
+1980
+3300
+6600
+cc00
+cc00
+6200
+1100
+0cc0
+0440
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 6 2 4
+ATTRIBUTES 0x0258
+BITMAP
+ffc0
+0040
+0040
+0040
+0040
+0040
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 1 5 6
+ATTRIBUTES 0x0258
+BITMAP
+f8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+07c0
+1820
+2010
+4788
+c444
+84c4
+8704
+8484
+8484
+4f4c
+4008
+2010
+1820
+07c0
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 1 3 13
+ATTRIBUTES 0x0258
+BITMAP
+ff
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 7 7 4 8
+ATTRIBUTES 0x0258
+BITMAP
+38
+44
+82
+82
+82
+c4
+78
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 13 2 1
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0400
+0400
+0400
+0400
+ffe0
+0400
+0400
+0400
+0400
+0000
+0000
+ffe0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 9 4 6
+ATTRIBUTES 0x0258
+BITMAP
+78
+cc
+84
+04
+08
+10
+20
+44
+fc
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 9 4 6
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+08
+08
+38
+08
+04
+0c
+78
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 5 3 5 12
+ATTRIBUTES 0x0258
+BITMAP
+30
+60
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+30c0
+2ff0
+2000
+2000
+2000
+2000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 16 3 -2
+ATTRIBUTES 0x0258
+BITMAP
+3f80
+4900
+8900
+8900
+8900
+8900
+4900
+3900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+3b80
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 3 5 6
+ATTRIBUTES 0x0258
+BITMAP
+60
+f0
+70
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 4 4 5 -3
+ATTRIBUTES 0x0258
+BITMAP
+20
+30
+30
+f0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 9 4 6
+ATTRIBUTES 0x0258
+BITMAP
+30
+f0
+10
+10
+10
+10
+10
+10
+fc
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 6 8 4 6
+ATTRIBUTES 0x0258
+BITMAP
+78
+c4
+84
+84
+cc
+38
+00
+fc
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 10 2 0
+ATTRIBUTES 0x0258
+BITMAP
+8800
+6600
+3300
+1980
+0cc0
+0cc0
+1980
+2200
+cc00
+4400
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 17 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+6008
+a018
+2010
+2020
+2040
+2040
+2080
+2100
+f230
+0230
+0450
+0850
+1890
+1110
+21f8
+4010
+4078
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 17 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+3004
+5008
+1010
+1030
+1020
+1040
+10c0
+1080
+7938
+0244
+0604
+0404
+0808
+1018
+1030
+2044
+407c
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 17 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+700c
+8808
+0810
+1820
+3060
+0840
+0880
+0900
+f130
+0230
+0450
+0850
+0890
+1190
+21f8
+4010
+4078
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 8 13 3 -3
+ATTRIBUTES 0x0258
+BITMAP
+1c
+1c
+1c
+00
+08
+18
+60
+40
+80
+80
+81
+41
+3e
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0200
+0100
+0080
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0180
+0300
+0600
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0480
+0840
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0e20
+09c0
+0080
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 18 0 0
+ATTRIBUTES 0x0258
+BITMAP
+06c0
+06c0
+06c0
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 14 19 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0480
+0480
+0300
+0000
+3f00
+0300
+0780
+0680
+04c0
+0cc0
+0840
+1860
+1820
+1fe0
+3030
+2010
+6018
+f87c
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 14 0 0
+ATTRIBUTES 0x0258
+BITMAP
+0ff8
+0308
+0308
+0508
+0528
+0d20
+09e0
+0920
+1920
+1f20
+3108
+3108
+6108
+f9f8
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 17 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+1f20
+30e0
+4060
+4060
+8020
+8000
+8000
+8000
+8000
+8000
+c000
+4030
+20e0
+1f80
+0400
+0700
+0f00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0900
+1080
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+fff0
+1010
+1010
+1010
+1010
+1080
+1f80
+1080
+1080
+1000
+1010
+1010
+1010
+fff0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1200
+2100
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 18 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+ffc0
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+ff00
+20c0
+2060
+2020
+2010
+2010
+fe10
+2010
+2010
+2010
+2020
+2060
+20c0
+ff80
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+f0f8
+3810
+2810
+2810
+2410
+2410
+2210
+2210
+2110
+2110
+2090
+2090
+2050
+f870
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0900
+1080
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0f80
+30c0
+6060
+4020
+c010
+8010
+8010
+8010
+8010
+8010
+4020
+6020
+30c0
+0f80
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 9 9 3 3
+ATTRIBUTES 0x0258
+BITMAP
+4080
+c180
+6380
+3600
+1c00
+1c00
+3200
+4300
+8180
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 14 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0fa0
+30e0
+6060
+4070
+c090
+8110
+8310
+8210
+8410
+c810
+5820
+7020
+70c0
+5f80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0900
+1080
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+f9f8
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+4020
+6020
+6020
+3040
+1f80
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 18 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+f8f8
+2020
+3060
+1040
+0880
+0c80
+0500
+0700
+0200
+0200
+0200
+0200
+0200
+1fc0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 14 2 0
+ATTRIBUTES 0x0258
+BITMAP
+fc00
+2000
+2000
+3f80
+20c0
+2060
+2020
+2020
+2060
+20c0
+3f80
+2000
+2000
+fc00
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1e00
+3100
+6080
+4080
+4080
+4300
+4e00
+4180
+4080
+4040
+4040
+4040
+4040
+4880
+cf00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1600
+2100
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+3880
+2700
+0200
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0e00
+1200
+0e00
+0000
+0000
+3f00
+0180
+0080
+3f80
+4180
+8080
+8080
+8180
+c380
+7ce0
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+7fe0
+0230
+0210
+0210
+3ff0
+4200
+8200
+8200
+8700
+78f0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 13 2 -3
+ATTRIBUTES 0x0258
+BITMAP
+1f60
+60c0
+4040
+8000
+8000
+8000
+8000
+4020
+60c0
+1f00
+0400
+0600
+0e00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1600
+2100
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+0000
+1f00
+60c0
+c060
+8020
+ffe0
+8000
+8000
+4000
+6060
+1f80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0800
+0400
+0200
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0c00
+1800
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+1600
+2100
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 10 15 2 0
+ATTRIBUTES 0x0258
+BITMAP
+1b00
+1b00
+1b00
+0000
+0000
+7c00
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+0400
+ffc0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 17 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0200
+3c00
+0e00
+0b00
+1980
+00c0
+0060
+1fe0
+6070
+4030
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+0000
+ef80
+3040
+2020
+2020
+2020
+2020
+2020
+2020
+2020
+f9f8
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0b00
+1080
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1c40
+1380
+0100
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0000
+1f80
+6060
+4020
+8010
+8010
+8010
+8010
+4020
+3060
+1f80
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 11 11 2 2
+ATTRIBUTES 0x0258
+BITMAP
+0c00
+0c00
+0000
+0000
+0000
+ffe0
+0000
+0000
+0000
+0c00
+0c00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 10 1 0
+ATTRIBUTES 0x0258
+BITMAP
+1fa0
+6060
+40b0
+8110
+8210
+8c10
+d810
+7020
+7060
+df80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0400
+0200
+0100
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0600
+0b00
+1080
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 12 15 1 0
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0000
+e1c0
+2040
+2040
+2040
+2040
+2040
+2040
+2040
+31c0
+1f70
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 19 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+0300
+0600
+0c00
+0000
+0000
+f078
+2020
+2020
+1040
+10c0
+0880
+0980
+0500
+0600
+0600
+0400
+0400
+0800
+fe00
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 19 0 -4
+ATTRIBUTES 0x0258
+BITMAP
+f000
+1000
+1000
+1000
+1000
+17c0
+1c30
+1810
+1008
+1008
+1008
+1008
+1810
+1c20
+17c0
+1000
+1000
+1000
+fe00
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 584 0
+DWIDTH 14 0
+BBX 13 19 1 -4
+ATTRIBUTES 0x0258
+BITMAP
+0d80
+0d80
+0d80
+0000
+0000
+f078
+2020
+2020
+1040
+10c0
+0880
+0980
+0500
+0600
+0600
+0400
+0400
+0800
+fe00
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier24.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier24.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier24.h	(revision 16632)
@@ -0,0 +1,1068 @@
+static unsigned char courier24_0_bits[] = {
+0x00};
+static unsigned char courier24_1_bits[] = {
+0x00};
+static unsigned char courier24_2_bits[] = {
+0x00};
+static unsigned char courier24_3_bits[] = {
+0x00};
+static unsigned char courier24_4_bits[] = {
+0x00};
+static unsigned char courier24_5_bits[] = {
+0x00};
+static unsigned char courier24_6_bits[] = {
+0x00};
+static unsigned char courier24_7_bits[] = {
+0x00};
+static unsigned char courier24_8_bits[] = {
+0x00};
+static unsigned char courier24_9_bits[] = {
+0x00};
+static unsigned char courier24_10_bits[] = {
+0x00};
+static unsigned char courier24_11_bits[] = {
+0x00};
+static unsigned char courier24_12_bits[] = {
+0x00};
+static unsigned char courier24_13_bits[] = {
+0x00};
+static unsigned char courier24_14_bits[] = {
+0x00};
+static unsigned char courier24_15_bits[] = {
+0x00};
+static unsigned char courier24_16_bits[] = {
+0x00};
+static unsigned char courier24_17_bits[] = {
+0x00};
+static unsigned char courier24_18_bits[] = {
+0x00};
+static unsigned char courier24_19_bits[] = {
+0x00};
+static unsigned char courier24_20_bits[] = {
+0x00};
+static unsigned char courier24_21_bits[] = {
+0x00};
+static unsigned char courier24_22_bits[] = {
+0x00};
+static unsigned char courier24_23_bits[] = {
+0x00};
+static unsigned char courier24_24_bits[] = {
+0x00};
+static unsigned char courier24_25_bits[] = {
+0x00};
+static unsigned char courier24_26_bits[] = {
+0x00};
+static unsigned char courier24_27_bits[] = {
+0x00};
+static unsigned char courier24_28_bits[] = {
+0x00};
+static unsigned char courier24_29_bits[] = {
+0x00};
+static unsigned char courier24_30_bits[] = {
+0x00};
+static unsigned char courier24_31_bits[] = {
+0x00};
+static unsigned char courier24_32_bits[] = {
+0x00, 0x00};
+static unsigned char courier24_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x07, 
+0x07, 0x07};
+static unsigned char courier24_34_bits[] = {
+0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33};
+static unsigned char courier24_35_bits[] = {
+0x88, 0x01, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 
+0xff, 0x07, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0xff, 0x07, 
+0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00, 0x84, 0x00};
+static unsigned char courier24_36_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xf8, 0x01, 0xa4, 0x01, 0x22, 0x01, 
+0x22, 0x01, 0x26, 0x03, 0x3c, 0x00, 0xf0, 0x00, 0xa0, 0x01, 0x23, 0x02, 
+0x22, 0x02, 0x26, 0x02, 0x2e, 0x01, 0xfe, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00};
+static unsigned char courier24_37_bits[] = {
+0x1c, 0x00, 0x22, 0x00, 0x41, 0x00, 0x41, 0x00, 0x41, 0x00, 0x22, 0x06, 
+0x9c, 0x07, 0xf0, 0x01, 0x3e, 0x00, 0x8e, 0x03, 0x40, 0x04, 0x20, 0x08, 
+0x20, 0x08, 0x60, 0x0c, 0x80, 0x07};
+static unsigned char courier24_38_bits[] = {
+0xbc, 0x00, 0x46, 0x00, 0x02, 0x00, 0x02, 0x00, 0x04, 0x00, 0x0c, 0x00, 
+0x8a, 0x03, 0x93, 0x00, 0xb1, 0x00, 0x61, 0x00, 0x61, 0x00, 0xe3, 0x00, 
+0x9e, 0x03};
+static unsigned char courier24_39_bits[] = {
+0x0c, 0x0e, 0x06, 0x06, 0x03, 0x03};
+static unsigned char courier24_40_bits[] = {
+0x08, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x03, 0x02, 0x02, 0x04, 0x04, 0x08};
+static unsigned char courier24_41_bits[] = {
+0x02, 0x02, 0x06, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x04, 0x04, 0x06, 0x02, 0x03};
+static unsigned char courier24_42_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x11, 0x01, 0xff, 0x01, 0x7c, 0x00, 0x38, 0x00, 
+0x6c, 0x00, 0xc6, 0x00, 0x44, 0x00};
+static unsigned char courier24_43_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x07, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00};
+static unsigned char courier24_44_bits[] = {
+0x0c, 0x06, 0x06, 0x06, 0x03, 0x03};
+static unsigned char courier24_45_bits[] = {
+0xff, 0x07};
+static unsigned char courier24_46_bits[] = {
+0x06, 0x0f, 0x0e};
+static unsigned char courier24_47_bits[] = {
+0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0x80, 0x00, 0xc0, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 
+0x03, 0x00, 0x01, 0x00};
+static unsigned char courier24_48_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x82, 0x00, 0x81, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x81, 0x00, 
+0x82, 0x00, 0x46, 0x00, 0x3c, 0x00};
+static unsigned char courier24_49_bits[] = {
+0x30, 0x00, 0x3c, 0x00, 0x26, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xfe, 0x03};
+static unsigned char courier24_50_bits[] = {
+0x78, 0x00, 0xc4, 0x00, 0x82, 0x01, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 
+0x80, 0x01, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08, 0x01, 
+0x06, 0x01, 0x01, 0x01, 0xff, 0x01};
+static unsigned char courier24_51_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x82, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 
+0x60, 0x00, 0xf0, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 
+0x00, 0x01, 0xc1, 0x00, 0x7e, 0x00};
+static unsigned char courier24_52_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x50, 0x00, 0x50, 0x00, 0x48, 0x00, 0x48, 0x00, 
+0x44, 0x00, 0x42, 0x00, 0x42, 0x00, 0x41, 0x00, 0xff, 0x03, 0x40, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_53_bits[] = {
+0xfe, 0x01, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 
+0x7a, 0x00, 0x86, 0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x01, 0x83, 0x01, 0x7e, 0x00};
+static unsigned char courier24_54_bits[] = {
+0xf0, 0x01, 0x1c, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 
+0x3d, 0x00, 0x47, 0x00, 0xc3, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0x82, 0x00, 0x46, 0x00, 0x3c, 0x00};
+static unsigned char courier24_55_bits[] = {
+0xff, 0x03, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x80, 0x00, 
+0x80, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x10, 0x00};
+static unsigned char courier24_56_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x83, 0x00, 0x81, 0x00, 0x81, 0x00, 0x81, 0x00, 
+0x46, 0x00, 0x3c, 0x00, 0xc2, 0x00, 0x83, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0xc2, 0x00, 0x7c, 0x00};
+static unsigned char courier24_57_bits[] = {
+0x3c, 0x00, 0x46, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x83, 0x01, 0xc6, 0x01, 0x3c, 0x01, 0x00, 0x01, 0x80, 0x00, 0x80, 0x00, 
+0x40, 0x00, 0x20, 0x00, 0x1f, 0x00};
+static unsigned char courier24_58_bits[] = {
+0x06, 0x0f, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x0f, 0x0e};
+static unsigned char courier24_59_bits[] = {
+0x0c, 0x1e, 0x1c, 0x00, 0x00, 0x00, 0x0c, 0x0e, 0x06, 0x06, 0x02, 0x03};
+static unsigned char courier24_60_bits[] = {
+0x00, 0x08, 0x00, 0x0e, 0x80, 0x01, 0x60, 0x00, 0x1c, 0x00, 0x07, 0x00, 
+0x1c, 0x00, 0xf0, 0x00, 0xc0, 0x07, 0x00, 0x0e, 0x00, 0x08};
+static unsigned char courier24_61_bits[] = {
+0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07};
+static unsigned char courier24_62_bits[] = {
+0x01, 0x00, 0x07, 0x00, 0x1c, 0x00, 0x60, 0x00, 0x80, 0x03, 0x00, 0x0e, 
+0xc0, 0x03, 0xf8, 0x00, 0x3f, 0x00, 0x0f, 0x00, 0x03, 0x00};
+static unsigned char courier24_63_bits[] = {
+0x3e, 0x43, 0x81, 0x81, 0x80, 0x80, 0x40, 0x38, 0x08, 0x08, 0x00, 0x1c, 
+0x1c, 0x1c};
+static unsigned char courier24_64_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x06, 0x08, 0x62, 0x19, 0xb1, 0x11, 0x91, 0x11, 
+0x89, 0x11, 0x89, 0x18, 0xc9, 0x08, 0x7b, 0x07, 0x22, 0x00, 0x0c, 0x0e, 
+0xf8, 0x03};
+static unsigned char courier24_65_bits[] = {
+0xfc, 0x00, 0xc0, 0x00, 0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 
+0x10, 0x02, 0x18, 0x06, 0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 
+0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_66_bits[] = {
+0xff, 0x01, 0x04, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 
+0xfc, 0x01, 0x04, 0x06, 0x04, 0x0c, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 
+0x04, 0x06, 0xff, 0x03};
+static unsigned char courier24_67_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x02, 0x06, 0x01, 0x04, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x02, 0x0c, 
+0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_68_bits[] = {
+0xff, 0x00, 0x04, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x08, 0x04, 0x08, 
+0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x0c, 0x04, 0x04, 
+0x04, 0x03, 0xff, 0x01};
+static unsigned char courier24_69_bits[] = {
+0xff, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 
+0xf8, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_70_bits[] = {
+0xff, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x84, 0x00, 
+0xfc, 0x00, 0x84, 0x00, 0x84, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x3f, 0x00};
+static unsigned char courier24_71_bits[] = {
+0xf0, 0x05, 0x0c, 0x07, 0x04, 0x06, 0x02, 0x04, 0x03, 0x04, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x81, 0x1f, 0x01, 0x08, 0x02, 0x08, 0x06, 0x08, 
+0x0c, 0x0c, 0xf0, 0x03};
+static unsigned char courier24_72_bits[] = {
+0x1f, 0x0f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0xfc, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x1f, 0x0f};
+static unsigned char courier24_73_bits[] = {
+0xff, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_74_bits[] = {
+0xf0, 0x1f, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x06, 0x01, 0xf8, 0x01};
+static unsigned char courier24_75_bits[] = {
+0x3f, 0x1f, 0x08, 0x04, 0x08, 0x02, 0x08, 0x01, 0x88, 0x00, 0x48, 0x00, 
+0x28, 0x00, 0x78, 0x00, 0x88, 0x01, 0x08, 0x01, 0x08, 0x02, 0x08, 0x06, 
+0x08, 0x04, 0x3f, 0x1c};
+static unsigned char courier24_76_bits[] = {
+0x7f, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_77_bits[] = {
+0x0f, 0x3c, 0x14, 0x14, 0x14, 0x14, 0x14, 0x12, 0x24, 0x12, 0x24, 0x12, 
+0x24, 0x11, 0x44, 0x11, 0x44, 0x11, 0xc4, 0x10, 0x04, 0x10, 0x04, 0x10, 
+0x04, 0x10, 0x1f, 0x3e};
+static unsigned char courier24_78_bits[] = {
+0x0f, 0x1f, 0x1c, 0x08, 0x14, 0x08, 0x14, 0x08, 0x24, 0x08, 0x24, 0x08, 
+0x44, 0x08, 0x44, 0x08, 0x84, 0x08, 0x84, 0x08, 0x04, 0x09, 0x04, 0x09, 
+0x04, 0x0a, 0x1f, 0x0e};
+static unsigned char courier24_79_bits[] = {
+0xf0, 0x01, 0x0c, 0x03, 0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 
+0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_80_bits[] = {
+0xff, 0x00, 0x84, 0x03, 0x04, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x06, 0x84, 0x03, 0xfc, 0x01, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x3f, 0x00};
+static unsigned char courier24_81_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 
+0x0c, 0x03, 0xf8, 0x01, 0x30, 0x00, 0xf8, 0x08, 0x08, 0x07};
+static unsigned char courier24_82_bits[] = {
+0xff, 0x01, 0x04, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x03, 0xfc, 0x01, 0xc4, 0x00, 0x84, 0x00, 0x04, 0x01, 0x04, 0x02, 
+0x04, 0x02, 0x1f, 0x1c};
+static unsigned char courier24_83_bits[] = {
+0x3c, 0x01, 0xc2, 0x01, 0x81, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 
+0x06, 0x00, 0xfc, 0x00, 0x80, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x83, 0x00, 0x7d, 0x00};
+static unsigned char courier24_84_bits[] = {
+0xfe, 0x0f, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x42, 0x08, 0x43, 0x18, 
+0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_85_bits[] = {
+0x9f, 0x1f, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 
+0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_86_bits[] = {
+0x1f, 0x3e, 0x04, 0x08, 0x04, 0x08, 0x08, 0x08, 0x08, 0x04, 0x08, 0x04, 
+0x10, 0x04, 0x10, 0x02, 0x30, 0x02, 0x20, 0x03, 0x20, 0x01, 0x40, 0x01, 
+0xc0, 0x01, 0xc0, 0x00};
+static unsigned char courier24_87_bits[] = {
+0x1f, 0x7c, 0x06, 0x20, 0x06, 0x20, 0x86, 0x10, 0xc4, 0x10, 0xc4, 0x11, 
+0x44, 0x11, 0x24, 0x11, 0x24, 0x13, 0x2c, 0x1a, 0x1c, 0x0a, 0x1c, 0x0c, 
+0x18, 0x0c, 0x08, 0x0c};
+static unsigned char courier24_88_bits[] = {
+0x1f, 0x0f, 0x04, 0x02, 0x0c, 0x02, 0x18, 0x01, 0x90, 0x00, 0xa0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0xb0, 0x00, 0x10, 0x01, 0x08, 0x03, 0x0c, 0x06, 
+0x04, 0x04, 0x1f, 0x1f};
+static unsigned char courier24_89_bits[] = {
+0x1f, 0x1f, 0x04, 0x04, 0x0c, 0x06, 0x08, 0x02, 0x10, 0x01, 0x30, 0x01, 
+0xa0, 0x00, 0xe0, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_90_bits[] = {
+0xff, 0x01, 0x01, 0x01, 0x81, 0x00, 0x81, 0x00, 0x41, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x10, 0x00, 0x08, 0x00, 0x0c, 0x02, 0x04, 0x02, 0x02, 0x02, 
+0x03, 0x02, 0xff, 0x03};
+static unsigned char courier24_91_bits[] = {
+0x0f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x0f};
+static unsigned char courier24_92_bits[] = {
+0x01, 0x00, 0x03, 0x00, 0x02, 0x00, 0x06, 0x00, 0x04, 0x00, 0x0c, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x10, 0x00, 0x10, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0xc0, 0x00, 0x80, 0x00, 0x80, 0x01, 0x00, 0x01, 
+0x00, 0x03, 0x00, 0x02};
+static unsigned char courier24_93_bits[] = {
+0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x0f};
+static unsigned char courier24_94_bits[] = {
+0x70, 0x00, 0x50, 0x00, 0x58, 0x00, 0x98, 0x00, 0x88, 0x00, 0x8c, 0x01, 
+0x04, 0x01, 0x06, 0x03, 0x06, 0x03, 0x03, 0x02, 0x03, 0x06};
+static unsigned char courier24_95_bits[] = {
+0xff, 0xff, 0x01};
+static unsigned char courier24_96_bits[] = {
+0x0c, 0x0c, 0x06, 0x06, 0x07, 0x03};
+static unsigned char courier24_97_bits[] = {
+0xfc, 0x00, 0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_98_bits[] = {
+0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0xe4, 0x03, 
+0x34, 0x0c, 0x0c, 0x08, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x10, 
+0x1c, 0x08, 0x3c, 0x0c, 0xe7, 0x03};
+static unsigned char courier24_99_bits[] = {
+0xf8, 0x07, 0x06, 0x03, 0x02, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x04, 0x06, 0x03, 0xf8, 0x00};
+static unsigned char courier24_100_bits[] = {
+0x00, 0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xf8, 0x04, 
+0x04, 0x07, 0x02, 0x06, 0x01, 0x06, 0x01, 0x04, 0x01, 0x04, 0x01, 0x06, 
+0x02, 0x06, 0x8c, 0x05, 0xf8, 0x1c};
+static unsigned char courier24_101_bits[] = {
+0xf8, 0x00, 0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_102_bits[] = {
+0xf0, 0x03, 0x18, 0x02, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xff, 0x01, 
+0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0xff, 0x01};
+static unsigned char courier24_103_bits[] = {
+0xf8, 0x0e, 0x86, 0x03, 0x02, 0x03, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 
+0x03, 0x02, 0x02, 0x03, 0x8c, 0x03, 0x78, 0x02, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x01, 0xf8, 0x00};
+static unsigned char courier24_104_bits[] = {
+0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0xf4, 0x01, 
+0x1c, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04, 0x1f, 0x1f};
+static unsigned char courier24_105_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x3e, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_106_bits[] = {
+0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x7f, 0x40, 0x40, 0x40, 0x40, 0x40, 
+0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x21, 0x1f};
+static unsigned char courier24_107_bits[] = {
+0x07, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x84, 0x0f, 
+0x84, 0x01, 0xc4, 0x00, 0x34, 0x00, 0x3c, 0x00, 0x44, 0x00, 0x84, 0x01, 
+0x04, 0x03, 0x04, 0x06, 0x07, 0x1f};
+static unsigned char courier24_108_bits[] = {
+0x3e, 0x00, 0x22, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_109_bits[] = {
+0x77, 0x0f, 0x8c, 0x11, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 
+0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x9f, 0x73};
+static unsigned char courier24_110_bits[] = {
+0xf7, 0x01, 0x0c, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x9f, 0x1f};
+static unsigned char courier24_111_bits[] = {
+0xf8, 0x01, 0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_112_bits[] = {
+0xef, 0x03, 0x38, 0x0c, 0x18, 0x08, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 
+0x08, 0x10, 0x18, 0x08, 0x38, 0x04, 0xe8, 0x03, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x7f, 0x00};
+static unsigned char courier24_113_bits[] = {
+0xf8, 0x1d, 0x06, 0x07, 0x02, 0x06, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 
+0x01, 0x04, 0x02, 0x06, 0x0c, 0x05, 0xf8, 0x04, 0x00, 0x04, 0x00, 0x04, 
+0x00, 0x04, 0xc0, 0x1f};
+static unsigned char courier24_114_bits[] = {
+0xcf, 0x07, 0x68, 0x04, 0x18, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xff, 0x01};
+static unsigned char courier24_115_bits[] = {
+0x7c, 0x01, 0x82, 0x01, 0x02, 0x01, 0x06, 0x00, 0xfc, 0x00, 0xc1, 0x01, 
+0x01, 0x02, 0x03, 0x02, 0x07, 0x03, 0xf9, 0x00};
+static unsigned char courier24_116_bits[] = {
+0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0xff, 0x00, 0x02, 0x00, 
+0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 
+0x04, 0x03, 0xf8, 0x00};
+static unsigned char courier24_117_bits[] = {
+0x87, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_118_bits[] = {
+0x1f, 0x1f, 0x04, 0x04, 0x0c, 0x02, 0x08, 0x02, 0x08, 0x01, 0x10, 0x01, 
+0x90, 0x01, 0xa0, 0x00, 0xe0, 0x00, 0x60, 0x00};
+static unsigned char courier24_119_bits[] = {
+0x0f, 0x3c, 0x02, 0x10, 0x82, 0x10, 0xc4, 0x08, 0xc4, 0x09, 0x44, 0x09, 
+0x28, 0x09, 0x28, 0x06, 0x28, 0x06, 0x10, 0x06};
+static unsigned char courier24_120_bits[] = {
+0x3e, 0x1e, 0x18, 0x04, 0x30, 0x02, 0x60, 0x01, 0xc0, 0x00, 0xe0, 0x01, 
+0x30, 0x03, 0x18, 0x06, 0x0c, 0x0c, 0x1f, 0x3e};
+static unsigned char courier24_121_bits[] = {
+0x0f, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x08, 0x03, 0x10, 0x01, 
+0x90, 0x01, 0xa0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x10, 0x00, 0x7f, 0x00};
+static unsigned char courier24_122_bits[] = {
+0xfe, 0x03, 0x02, 0x01, 0x82, 0x00, 0x40, 0x00, 0x20, 0x00, 0x30, 0x00, 
+0x18, 0x00, 0x0c, 0x02, 0x06, 0x02, 0xff, 0x03};
+static unsigned char courier24_123_bits[] = {
+0x18, 0x04, 0x02, 0x02, 0x02, 0x06, 0x04, 0x04, 0x06, 0x03, 0x06, 0x04, 
+0x04, 0x06, 0x02, 0x02, 0x06, 0x1c};
+static unsigned char courier24_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier24_125_bits[] = {
+0x07, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x18, 0x30, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x07};
+static unsigned char courier24_126_bits[] = {
+0x04, 0x02, 0x3e, 0x03, 0xe1, 0x01, 0x01, 0x00};
+static unsigned char courier24_127_bits[] = {
+0x00};
+static unsigned char courier24_128_bits[] = {
+0x00};
+static unsigned char courier24_129_bits[] = {
+0x00};
+static unsigned char courier24_130_bits[] = {
+0x00};
+static unsigned char courier24_131_bits[] = {
+0x00};
+static unsigned char courier24_132_bits[] = {
+0x00};
+static unsigned char courier24_133_bits[] = {
+0x00};
+static unsigned char courier24_134_bits[] = {
+0x00};
+static unsigned char courier24_135_bits[] = {
+0x00};
+static unsigned char courier24_136_bits[] = {
+0x00};
+static unsigned char courier24_137_bits[] = {
+0x00};
+static unsigned char courier24_138_bits[] = {
+0x00};
+static unsigned char courier24_139_bits[] = {
+0x00};
+static unsigned char courier24_140_bits[] = {
+0x00};
+static unsigned char courier24_141_bits[] = {
+0x00};
+static unsigned char courier24_142_bits[] = {
+0x00};
+static unsigned char courier24_143_bits[] = {
+0x00};
+static unsigned char courier24_144_bits[] = {
+0x00};
+static unsigned char courier24_145_bits[] = {
+0x00};
+static unsigned char courier24_146_bits[] = {
+0x00};
+static unsigned char courier24_147_bits[] = {
+0x00};
+static unsigned char courier24_148_bits[] = {
+0x00};
+static unsigned char courier24_149_bits[] = {
+0x00};
+static unsigned char courier24_150_bits[] = {
+0x00};
+static unsigned char courier24_151_bits[] = {
+0x00};
+static unsigned char courier24_152_bits[] = {
+0x00};
+static unsigned char courier24_153_bits[] = {
+0x00};
+static unsigned char courier24_154_bits[] = {
+0x00};
+static unsigned char courier24_155_bits[] = {
+0x00};
+static unsigned char courier24_156_bits[] = {
+0x00};
+static unsigned char courier24_157_bits[] = {
+0x00};
+static unsigned char courier24_158_bits[] = {
+0x00};
+static unsigned char courier24_159_bits[] = {
+0x00};
+static unsigned char courier24_160_bits[] = {
+0x00};
+static unsigned char courier24_161_bits[] = {
+0x07, 0x07, 0x07, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06};
+static unsigned char courier24_162_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x01, 0x92, 0x01, 
+0x11, 0x01, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x12, 0x01, 0xd6, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char courier24_163_bits[] = {
+0xf0, 0x00, 0x18, 0x03, 0x0c, 0x02, 0x04, 0x02, 0x04, 0x00, 0x04, 0x00, 
+0x0c, 0x00, 0xff, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x04, 0x00, 0x3c, 0x04, 0xc6, 0x03};
+static unsigned char courier24_164_bits[] = {
+0x01, 0x02, 0x7a, 0x03, 0x8c, 0x00, 0x06, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x7a, 0x01, 0x01, 0x02, 0x01, 0x02};
+static unsigned char courier24_165_bits[] = {
+0x1f, 0x1f, 0x04, 0x06, 0x08, 0x02, 0x18, 0x03, 0xb0, 0x01, 0xe0, 0x00, 
+0x40, 0x00, 0xf8, 0x07, 0x40, 0x00, 0xf8, 0x07, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier24_167_bits[] = {
+0xfc, 0x00, 0x86, 0x00, 0x82, 0x00, 0x82, 0x00, 0x0c, 0x00, 0x1f, 0x00, 
+0x31, 0x00, 0x61, 0x00, 0x82, 0x00, 0x0c, 0x01, 0x98, 0x01, 0xf0, 0x00, 
+0x60, 0x00, 0x41, 0x00, 0x41, 0x00, 0x3f, 0x00};
+static unsigned char courier24_168_bits[] = {
+0x1b, 0x1b, 0x1b};
+static unsigned char courier24_169_bits[] = {
+0xe0, 0x03, 0x18, 0x04, 0x04, 0x08, 0xe2, 0x11, 0x32, 0x32, 0x09, 0x22, 
+0x09, 0x20, 0x09, 0x20, 0x19, 0x20, 0x32, 0x22, 0xe2, 0x11, 0x04, 0x08, 
+0x18, 0x04, 0xe0, 0x03};
+static unsigned char courier24_170_bits[] = {
+0x1e, 0x10, 0x1e, 0x11, 0x19, 0x3e, 0x00, 0x3f};
+static unsigned char courier24_171_bits[] = {
+0x20, 0x02, 0x98, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 
+0x46, 0x00, 0x88, 0x00, 0x30, 0x03, 0x20, 0x02};
+static unsigned char courier24_172_bits[] = {
+0xff, 0x03, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02, 0x00, 0x02};
+static unsigned char courier24_173_bits[] = {
+0x1f};
+static unsigned char courier24_174_bits[] = {
+0xe0, 0x03, 0x18, 0x04, 0x04, 0x08, 0xe2, 0x11, 0x23, 0x22, 0x21, 0x23, 
+0xe1, 0x20, 0x21, 0x21, 0x21, 0x21, 0xf2, 0x32, 0x02, 0x10, 0x04, 0x08, 
+0x18, 0x04, 0xe0, 0x03};
+static unsigned char courier24_175_bits[] = {
+0xff};
+static unsigned char courier24_176_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x23, 0x1e};
+static unsigned char courier24_177_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x07, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0xff, 0x07};
+static unsigned char courier24_178_bits[] = {
+0x1e, 0x33, 0x21, 0x20, 0x10, 0x08, 0x04, 0x22, 0x3f};
+static unsigned char courier24_179_bits[] = {
+0x0e, 0x11, 0x10, 0x10, 0x1c, 0x10, 0x20, 0x30, 0x1e};
+static unsigned char courier24_180_bits[] = {
+0x0c, 0x06, 0x03};
+static unsigned char courier24_181_bits[] = {
+0x87, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x04, 0x02, 0x0c, 0x03, 0xf4, 0x0f, 0x04, 0x00, 0x04, 0x00, 
+0x04, 0x00, 0x04, 0x00};
+static unsigned char courier24_182_bits[] = {
+0xfc, 0x01, 0x92, 0x00, 0x91, 0x00, 0x91, 0x00, 0x91, 0x00, 0x91, 0x00, 
+0x92, 0x00, 0x9c, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0xdc, 0x01};
+static unsigned char courier24_183_bits[] = {
+0x06, 0x0f, 0x0e};
+static unsigned char courier24_184_bits[] = {
+0x04, 0x0c, 0x0c, 0x0f};
+static unsigned char courier24_185_bits[] = {
+0x0c, 0x0f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3f};
+static unsigned char courier24_186_bits[] = {
+0x1e, 0x23, 0x21, 0x21, 0x33, 0x1c, 0x00, 0x3f};
+static unsigned char courier24_187_bits[] = {
+0x11, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x30, 0x03, 0x30, 0x03, 
+0x98, 0x01, 0x44, 0x00, 0x33, 0x00, 0x22, 0x00};
+static unsigned char courier24_188_bits[] = {
+0x06, 0x10, 0x05, 0x18, 0x04, 0x08, 0x04, 0x04, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x01, 0x84, 0x00, 0x4f, 0x0c, 0x40, 0x0c, 0x20, 0x0a, 0x10, 0x0a, 
+0x18, 0x09, 0x88, 0x08, 0x84, 0x1f, 0x02, 0x08, 0x02, 0x1e};
+static unsigned char courier24_189_bits[] = {
+0x0c, 0x20, 0x0a, 0x10, 0x08, 0x08, 0x08, 0x0c, 0x08, 0x04, 0x08, 0x02, 
+0x08, 0x03, 0x08, 0x01, 0x9e, 0x1c, 0x40, 0x22, 0x60, 0x20, 0x20, 0x20, 
+0x10, 0x10, 0x08, 0x18, 0x08, 0x0c, 0x04, 0x22, 0x02, 0x3e};
+static unsigned char courier24_190_bits[] = {
+0x0e, 0x30, 0x11, 0x10, 0x10, 0x08, 0x18, 0x04, 0x0c, 0x06, 0x10, 0x02, 
+0x10, 0x01, 0x90, 0x00, 0x8f, 0x0c, 0x40, 0x0c, 0x20, 0x0a, 0x10, 0x0a, 
+0x10, 0x09, 0x88, 0x09, 0x84, 0x1f, 0x02, 0x08, 0x02, 0x1e};
+static unsigned char courier24_191_bits[] = {
+0x38, 0x38, 0x38, 0x00, 0x10, 0x18, 0x06, 0x02, 0x01, 0x01, 0x81, 0x82, 
+0x7c};
+static unsigned char courier24_192_bits[] = {
+0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_193_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_194_bits[] = {
+0xc0, 0x00, 0x20, 0x01, 0x10, 0x02, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_195_bits[] = {
+0x70, 0x04, 0x90, 0x03, 0x00, 0x01, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_196_bits[] = {
+0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x00, 0x00, 0xfc, 0x00, 0xc0, 0x00, 
+0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 0x18, 0x06, 
+0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 0x1f, 0x3e};
+static unsigned char courier24_197_bits[] = {
+0xc0, 0x00, 0x20, 0x01, 0x20, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0xc0, 0x00, 0xe0, 0x01, 0x60, 0x01, 0x20, 0x03, 0x30, 0x03, 0x10, 0x02, 
+0x18, 0x06, 0x18, 0x04, 0xf8, 0x07, 0x0c, 0x0c, 0x04, 0x08, 0x06, 0x18, 
+0x1f, 0x3e};
+static unsigned char courier24_198_bits[] = {
+0xf0, 0x1f, 0xc0, 0x10, 0xc0, 0x10, 0xa0, 0x10, 0xa0, 0x14, 0xb0, 0x04, 
+0x90, 0x07, 0x90, 0x04, 0x98, 0x04, 0xf8, 0x04, 0x8c, 0x10, 0x8c, 0x10, 
+0x86, 0x10, 0x9f, 0x1f};
+static unsigned char courier24_199_bits[] = {
+0xf8, 0x04, 0x0c, 0x07, 0x02, 0x06, 0x02, 0x06, 0x01, 0x04, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x02, 0x0c, 
+0x04, 0x07, 0xf8, 0x01, 0x20, 0x00, 0xe0, 0x00, 0xf0, 0x00};
+static unsigned char courier24_200_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_201_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_202_bits[] = {
+0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_203_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0xff, 0x0f, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x01, 0xf8, 0x01, 0x08, 0x01, 
+0x08, 0x01, 0x08, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0xff, 0x0f};
+static unsigned char courier24_204_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_205_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_206_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_207_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0xff, 0x03, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_208_bits[] = {
+0xff, 0x00, 0x04, 0x03, 0x04, 0x06, 0x04, 0x04, 0x04, 0x08, 0x04, 0x08, 
+0x7f, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x08, 0x04, 0x04, 0x04, 0x06, 
+0x04, 0x03, 0xff, 0x01};
+static unsigned char courier24_209_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0x0f, 0x1f, 0x1c, 0x08, 
+0x14, 0x08, 0x14, 0x08, 0x24, 0x08, 0x24, 0x08, 0x44, 0x08, 0x44, 0x08, 
+0x84, 0x08, 0x84, 0x08, 0x04, 0x09, 0x04, 0x09, 0x04, 0x0a, 0x1f, 0x0e};
+static unsigned char courier24_210_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_211_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_212_bits[] = {
+0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_213_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_214_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0xf0, 0x01, 0x0c, 0x03, 
+0x06, 0x06, 0x02, 0x04, 0x03, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x06, 0x04, 0x0c, 0x03, 0xf0, 0x01};
+static unsigned char courier24_215_bits[] = {
+0x02, 0x01, 0x83, 0x01, 0xc6, 0x01, 0x6c, 0x00, 0x38, 0x00, 0x38, 0x00, 
+0x4c, 0x00, 0xc2, 0x00, 0x81, 0x01};
+static unsigned char courier24_216_bits[] = {
+0xf0, 0x05, 0x0c, 0x07, 0x06, 0x06, 0x02, 0x0e, 0x03, 0x09, 0x81, 0x08, 
+0xc1, 0x08, 0x41, 0x08, 0x21, 0x08, 0x13, 0x08, 0x1a, 0x04, 0x0e, 0x04, 
+0x0e, 0x03, 0xfa, 0x01};
+static unsigned char courier24_217_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_218_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_219_bits[] = {
+0x60, 0x00, 0x90, 0x00, 0x08, 0x01, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_220_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x9f, 0x1f, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 
+0x02, 0x04, 0x02, 0x04, 0x06, 0x04, 0x06, 0x04, 0x0c, 0x02, 0xf8, 0x01};
+static unsigned char courier24_221_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x1f, 0x04, 0x04, 
+0x0c, 0x06, 0x08, 0x02, 0x10, 0x01, 0x30, 0x01, 0xa0, 0x00, 0xe0, 0x00, 
+0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xf8, 0x03};
+static unsigned char courier24_222_bits[] = {
+0x3f, 0x00, 0x04, 0x00, 0x04, 0x00, 0xfc, 0x01, 0x04, 0x03, 0x04, 0x06, 
+0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x04, 0x03, 0xfc, 0x01, 0x04, 0x00, 
+0x04, 0x00, 0x3f, 0x00};
+static unsigned char courier24_223_bits[] = {
+0x78, 0x00, 0x8c, 0x00, 0x06, 0x01, 0x02, 0x01, 0x02, 0x01, 0xc2, 0x00, 
+0x72, 0x00, 0x82, 0x01, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x02, 0x12, 0x01, 0xf3, 0x00};
+static unsigned char courier24_224_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_225_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_226_bits[] = {
+0x30, 0x00, 0x68, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_227_bits[] = {
+0x1c, 0x01, 0xe4, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_228_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_229_bits[] = {
+0x70, 0x00, 0x48, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 
+0x80, 0x01, 0x00, 0x01, 0xfc, 0x01, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x81, 0x01, 0xc3, 0x01, 0x3e, 0x07};
+static unsigned char courier24_230_bits[] = {
+0xfe, 0x07, 0x40, 0x0c, 0x40, 0x08, 0x40, 0x08, 0xfc, 0x0f, 0x42, 0x00, 
+0x41, 0x00, 0x41, 0x00, 0xe1, 0x00, 0x1e, 0x0f};
+static unsigned char courier24_231_bits[] = {
+0xf8, 0x06, 0x06, 0x03, 0x02, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x04, 0x06, 0x03, 0xf8, 0x00, 0x20, 0x00, 0x60, 0x00, 
+0x70, 0x00};
+static unsigned char courier24_232_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_233_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_234_bits[] = {
+0x30, 0x00, 0x68, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_235_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0x06, 0x03, 0x03, 0x06, 0x01, 0x04, 0xff, 0x07, 0x01, 0x00, 0x01, 0x00, 
+0x02, 0x00, 0x06, 0x06, 0xf8, 0x01};
+static unsigned char courier24_236_bits[] = {
+0x10, 0x00, 0x20, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_237_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_238_bits[] = {
+0x30, 0x00, 0x68, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_239_bits[] = {
+0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0xff, 0x03};
+static unsigned char courier24_240_bits[] = {
+0x40, 0x00, 0x3c, 0x00, 0x70, 0x00, 0xd0, 0x00, 0x98, 0x01, 0x00, 0x03, 
+0x00, 0x06, 0xf8, 0x07, 0x06, 0x0e, 0x02, 0x0c, 0x01, 0x08, 0x01, 0x08, 
+0x01, 0x08, 0x01, 0x08, 0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_241_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf7, 0x01, 
+0x0c, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04, 0x9f, 0x1f};
+static unsigned char courier24_242_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_243_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_244_bits[] = {
+0x60, 0x00, 0xd0, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_245_bits[] = {
+0x38, 0x02, 0xc8, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_246_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 
+0x06, 0x06, 0x02, 0x04, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 0x01, 0x08, 
+0x02, 0x04, 0x0c, 0x06, 0xf8, 0x01};
+static unsigned char courier24_247_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00};
+static unsigned char courier24_248_bits[] = {
+0xf8, 0x05, 0x06, 0x06, 0x02, 0x0d, 0x81, 0x08, 0x41, 0x08, 0x31, 0x08, 
+0x1b, 0x08, 0x0e, 0x04, 0x0e, 0x06, 0xfb, 0x01};
+static unsigned char courier24_249_bits[] = {
+0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_250_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_251_bits[] = {
+0x60, 0x00, 0xd0, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_252_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 
+0x04, 0x02, 0x8c, 0x03, 0xf8, 0x0e};
+static unsigned char courier24_253_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x1e, 
+0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x08, 0x03, 0x10, 0x01, 0x90, 0x01, 
+0xa0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 
+0x7f, 0x00};
+static unsigned char courier24_254_bits[] = {
+0x0f, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xe8, 0x03, 
+0x38, 0x0c, 0x18, 0x08, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 0x08, 0x10, 
+0x18, 0x08, 0x38, 0x04, 0xe8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 
+0x7f, 0x00};
+static unsigned char courier24_255_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x1e, 
+0x04, 0x04, 0x04, 0x04, 0x08, 0x02, 0x08, 0x03, 0x10, 0x01, 0x90, 0x01, 
+0xa0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x10, 0x00, 
+0x7f, 0x00};
+static RotFont courier24font[] = {
+{5, 1, 1, courier24_0_bits},
+{5, 1, 1, courier24_1_bits},
+{5, 1, 1, courier24_2_bits},
+{5, 1, 1, courier24_3_bits},
+{5, 1, 1, courier24_4_bits},
+{5, 1, 1, courier24_5_bits},
+{5, 1, 1, courier24_6_bits},
+{5, 1, 1, courier24_7_bits},
+{5, 1, 1, courier24_8_bits},
+{5, 1, 1, courier24_9_bits},
+{5, 1, 1, courier24_10_bits},
+{5, 1, 1, courier24_11_bits},
+{5, 1, 1, courier24_12_bits},
+{5, 1, 1, courier24_13_bits},
+{5, 1, 1, courier24_14_bits},
+{5, 1, 1, courier24_15_bits},
+{5, 1, 1, courier24_16_bits},
+{5, 1, 1, courier24_17_bits},
+{5, 1, 1, courier24_18_bits},
+{5, 1, 1, courier24_19_bits},
+{5, 1, 1, courier24_20_bits},
+{5, 1, 1, courier24_21_bits},
+{5, 1, 1, courier24_22_bits},
+{5, 1, 1, courier24_23_bits},
+{5, 1, 1, courier24_24_bits},
+{5, 1, 1, courier24_25_bits},
+{5, 1, 1, courier24_26_bits},
+{5, 1, 1, courier24_27_bits},
+{5, 1, 1, courier24_28_bits},
+{5, 1, 1, courier24_29_bits},
+{5, 1, 1, courier24_30_bits},
+{5, 1, 1, courier24_31_bits},
+{10, 1, 1, courier24_32_bits},
+{3, 14, 14, courier24_33_bits},
+{6, 7, 14, courier24_34_bits},
+{11, 17, 16, courier24_35_bits},
+{10, 19, 16, courier24_36_bits},
+{12, 15, 15, courier24_37_bits},
+{10, 13, 13, courier24_38_bits},
+{4, 6, 14, courier24_39_bits},
+{4, 18, 16, courier24_40_bits},
+{4, 18, 16, courier24_41_bits},
+{9, 9, 14, courier24_42_bits},
+{11, 11, 13, courier24_43_bits},
+{4, 6, 3, courier24_44_bits},
+{11, 1, 8, courier24_45_bits},
+{4, 3, 3, courier24_46_bits},
+{10, 20, 17, courier24_47_bits},
+{9, 15, 15, courier24_48_bits},
+{10, 15, 15, courier24_49_bits},
+{9, 15, 15, courier24_50_bits},
+{9, 15, 15, courier24_51_bits},
+{10, 15, 15, courier24_52_bits},
+{10, 15, 15, courier24_53_bits},
+{9, 15, 15, courier24_54_bits},
+{10, 15, 15, courier24_55_bits},
+{9, 15, 15, courier24_56_bits},
+{9, 15, 15, courier24_57_bits},
+{4, 9, 9, courier24_58_bits},
+{5, 12, 9, courier24_59_bits},
+{12, 11, 13, courier24_60_bits},
+{11, 5, 10, courier24_61_bits},
+{12, 11, 13, courier24_62_bits},
+{8, 14, 14, courier24_63_bits},
+{13, 13, 13, courier24_64_bits},
+{14, 14, 14, courier24_65_bits},
+{12, 14, 14, courier24_66_bits},
+{12, 14, 14, courier24_67_bits},
+{12, 14, 14, courier24_68_bits},
+{12, 14, 14, courier24_69_bits},
+{11, 14, 14, courier24_70_bits},
+{13, 14, 14, courier24_71_bits},
+{12, 14, 14, courier24_72_bits},
+{10, 14, 14, courier24_73_bits},
+{13, 14, 14, courier24_74_bits},
+{13, 14, 14, courier24_75_bits},
+{12, 14, 14, courier24_76_bits},
+{14, 14, 14, courier24_77_bits},
+{13, 14, 14, courier24_78_bits},
+{12, 14, 14, courier24_79_bits},
+{11, 14, 14, courier24_80_bits},
+{12, 17, 14, courier24_81_bits},
+{13, 14, 14, courier24_82_bits},
+{9, 14, 14, courier24_83_bits},
+{13, 14, 14, courier24_84_bits},
+{13, 14, 14, courier24_85_bits},
+{14, 14, 14, courier24_86_bits},
+{15, 14, 14, courier24_87_bits},
+{13, 14, 14, courier24_88_bits},
+{13, 14, 14, courier24_89_bits},
+{10, 14, 14, courier24_90_bits},
+{4, 18, 16, courier24_91_bits},
+{10, 20, 17, courier24_92_bits},
+{4, 18, 16, courier24_93_bits},
+{11, 11, 14, courier24_94_bits},
+{17, 1, -2, courier24_95_bits},
+{4, 6, 14, courier24_96_bits},
+{11, 10, 10, courier24_97_bits},
+{13, 15, 15, courier24_98_bits},
+{11, 10, 10, courier24_99_bits},
+{13, 15, 15, courier24_100_bits},
+{11, 10, 10, courier24_101_bits},
+{10, 15, 15, courier24_102_bits},
+{12, 14, 10, courier24_103_bits},
+{13, 15, 15, courier24_104_bits},
+{10, 16, 16, courier24_105_bits},
+{8, 20, 16, courier24_106_bits},
+{13, 15, 15, courier24_107_bits},
+{10, 15, 15, courier24_108_bits},
+{15, 10, 10, courier24_109_bits},
+{13, 10, 10, courier24_110_bits},
+{12, 10, 10, courier24_111_bits},
+{13, 14, 10, courier24_112_bits},
+{13, 14, 10, courier24_113_bits},
+{12, 10, 10, courier24_114_bits},
+{10, 10, 10, courier24_115_bits},
+{10, 14, 14, courier24_116_bits},
+{12, 10, 10, courier24_117_bits},
+{13, 10, 10, courier24_118_bits},
+{14, 10, 10, courier24_119_bits},
+{14, 10, 10, courier24_120_bits},
+{13, 14, 10, courier24_121_bits},
+{10, 10, 10, courier24_122_bits},
+{5, 18, 16, courier24_123_bits},
+{1, 21, 16, courier24_124_bits},
+{6, 18, 16, courier24_125_bits},
+{10, 4, 9, courier24_126_bits},
+{5, 1, 1, courier24_127_bits},
+{5, 1, 1, courier24_128_bits},
+{5, 1, 1, courier24_129_bits},
+{5, 1, 1, courier24_130_bits},
+{5, 1, 1, courier24_131_bits},
+{5, 1, 1, courier24_132_bits},
+{5, 1, 1, courier24_133_bits},
+{5, 1, 1, courier24_134_bits},
+{5, 1, 1, courier24_135_bits},
+{5, 1, 1, courier24_136_bits},
+{5, 1, 1, courier24_137_bits},
+{5, 1, 1, courier24_138_bits},
+{5, 1, 1, courier24_139_bits},
+{5, 1, 1, courier24_140_bits},
+{5, 1, 1, courier24_141_bits},
+{5, 1, 1, courier24_142_bits},
+{5, 1, 1, courier24_143_bits},
+{5, 1, 1, courier24_144_bits},
+{5, 1, 1, courier24_145_bits},
+{5, 1, 1, courier24_146_bits},
+{5, 1, 1, courier24_147_bits},
+{5, 1, 1, courier24_148_bits},
+{5, 1, 1, courier24_149_bits},
+{5, 1, 1, courier24_150_bits},
+{5, 1, 1, courier24_151_bits},
+{5, 1, 1, courier24_152_bits},
+{5, 1, 1, courier24_153_bits},
+{5, 1, 1, courier24_154_bits},
+{5, 1, 1, courier24_155_bits},
+{5, 1, 1, courier24_156_bits},
+{5, 1, 1, courier24_157_bits},
+{5, 1, 1, courier24_158_bits},
+{5, 1, 1, courier24_159_bits},
+{5, 1, 1, courier24_160_bits},
+{3, 13, 10, courier24_161_bits},
+{9, 16, 15, courier24_162_bits},
+{11, 15, 15, courier24_163_bits},
+{11, 11, 12, courier24_164_bits},
+{13, 14, 14, courier24_165_bits},
+{1, 21, 16, courier24_166_bits},
+{9, 16, 14, courier24_167_bits},
+{5, 3, 15, courier24_168_bits},
+{14, 14, 14, courier24_169_bits},
+{6, 8, 14, courier24_170_bits},
+{10, 10, 10, courier24_171_bits},
+{10, 6, 10, courier24_172_bits},
+{5, 1, 7, courier24_173_bits},
+{14, 14, 14, courier24_174_bits},
+{8, 1, 14, courier24_175_bits},
+{7, 7, 15, courier24_176_bits},
+{11, 13, 14, courier24_177_bits},
+{6, 9, 15, courier24_178_bits},
+{6, 9, 15, courier24_179_bits},
+{5, 3, 15, courier24_180_bits},
+{12, 14, 10, courier24_181_bits},
+{9, 16, 14, courier24_182_bits},
+{4, 3, 9, courier24_183_bits},
+{4, 4, 1, courier24_184_bits},
+{6, 9, 15, courier24_185_bits},
+{6, 8, 14, courier24_186_bits},
+{10, 10, 10, courier24_187_bits},
+{13, 17, 15, courier24_188_bits},
+{14, 17, 15, courier24_189_bits},
+{14, 17, 15, courier24_190_bits},
+{8, 13, 10, courier24_191_bits},
+{14, 18, 18, courier24_192_bits},
+{14, 18, 18, courier24_193_bits},
+{14, 18, 18, courier24_194_bits},
+{14, 18, 18, courier24_195_bits},
+{14, 18, 18, courier24_196_bits},
+{14, 19, 19, courier24_197_bits},
+{13, 14, 14, courier24_198_bits},
+{12, 17, 14, courier24_199_bits},
+{12, 18, 18, courier24_200_bits},
+{12, 18, 18, courier24_201_bits},
+{12, 18, 18, courier24_202_bits},
+{12, 18, 18, courier24_203_bits},
+{10, 18, 18, courier24_204_bits},
+{10, 18, 18, courier24_205_bits},
+{10, 18, 18, courier24_206_bits},
+{10, 18, 18, courier24_207_bits},
+{12, 14, 14, courier24_208_bits},
+{13, 18, 18, courier24_209_bits},
+{12, 18, 18, courier24_210_bits},
+{12, 18, 18, courier24_211_bits},
+{12, 18, 18, courier24_212_bits},
+{12, 18, 18, courier24_213_bits},
+{12, 18, 18, courier24_214_bits},
+{9, 9, 12, courier24_215_bits},
+{12, 14, 14, courier24_216_bits},
+{13, 18, 18, courier24_217_bits},
+{13, 18, 18, courier24_218_bits},
+{13, 18, 18, courier24_219_bits},
+{13, 18, 18, courier24_220_bits},
+{13, 18, 18, courier24_221_bits},
+{11, 14, 14, courier24_222_bits},
+{10, 15, 15, courier24_223_bits},
+{11, 15, 15, courier24_224_bits},
+{11, 15, 15, courier24_225_bits},
+{11, 15, 15, courier24_226_bits},
+{11, 15, 15, courier24_227_bits},
+{11, 15, 15, courier24_228_bits},
+{11, 15, 15, courier24_229_bits},
+{13, 10, 10, courier24_230_bits},
+{11, 13, 10, courier24_231_bits},
+{11, 15, 15, courier24_232_bits},
+{11, 15, 15, courier24_233_bits},
+{11, 15, 15, courier24_234_bits},
+{11, 15, 15, courier24_235_bits},
+{10, 15, 15, courier24_236_bits},
+{10, 15, 15, courier24_237_bits},
+{10, 15, 15, courier24_238_bits},
+{10, 15, 15, courier24_239_bits},
+{12, 17, 17, courier24_240_bits},
+{13, 15, 15, courier24_241_bits},
+{12, 15, 15, courier24_242_bits},
+{12, 15, 15, courier24_243_bits},
+{12, 15, 15, courier24_244_bits},
+{12, 15, 15, courier24_245_bits},
+{12, 15, 15, courier24_246_bits},
+{11, 11, 13, courier24_247_bits},
+{12, 10, 10, courier24_248_bits},
+{12, 15, 15, courier24_249_bits},
+{12, 15, 15, courier24_250_bits},
+{12, 15, 15, courier24_251_bits},
+{12, 15, 15, courier24_252_bits},
+{13, 19, 15, courier24_253_bits},
+{13, 19, 15, courier24_254_bits},
+{13, 19, 15, courier24_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier8.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier8.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier8.bdf	(revision 16632)
@@ -0,0 +1,2404 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -adobe-courier-medium-r-normal--8-77-75-75-m-50-iso8859-1
+SIZE 8 75 75
+FONTBOUNDINGBOX 7 9 -1 -2
+STARTPROPERTIES 25
+FOUNDRY "adobe"
+FAMILY_NAME "courier"
+WEIGHT_NAME "medium"
+SLANT "r"
+SETWIDTH_NAME "normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 77
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "m"
+AVERAGE_WIDTH 50
+CHARSET_REGISTRY "iso8859"
+CHARSET_ENCODING "1"
+FONT "-adobe-courier-medium-r-normal--8-77-75-75-m-50-iso8859-1"
+COPYRIGHT "Copyright (c) IBM Corporation 1990,1991. IBM Courier is a Trademark of the IBM Corporation."
+RAW_PIXEL_SIZE 1000
+RAW_POINT_SIZE 964
+RAW_ASCENT 841
+RAW_DESCENT 288
+RAW_AVERAGE_WIDTH 6000
+FACE_NAME "Couriere."
+DEFAULT_CHAR 0
+FONT_ASCENT 7
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 190
+STARTCHAR space
+ENCODING 32
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 0 0 0 0
+ATTRIBUTES 0x0258
+BITMAP
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 4 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 2
+ATTRIBUTES 0x0258
+BITMAP
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+a0
+a0
+e0
+e0
+a0
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+c0
+e0
+e0
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+f8
+38
+38
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+a0
+e0
+e0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 6 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 6 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 1
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 1
+ATTRIBUTES 0x0258
+BITMAP
+40
+e0
+40
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 1 0 2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 1 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+a0
+a0
+a0
+c0
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+10
+30
+40
+f0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+60
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+60
+60
+f0
+30
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+80
+e0
+20
+e0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+80
+e0
+a0
+e0
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+10
+20
+20
+20
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+c0
+a0
+e0
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 3 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 4 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+40
+40
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+c0
+20
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+f0
+00
+f0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+40
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+a8
+e8
+f8
+70
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+70
+48
+f0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+80
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+48
+48
+f0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+e0
+80
+c0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+98
+78
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d0
+70
+50
+d0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+38
+10
+90
+f0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+60
+50
+c8
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+48
+f8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 6 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+dc
+d8
+a8
+d8
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+68
+68
+d8
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+90
+e0
+c0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+88
+70
+70
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+60
+50
+d8
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+c0
+20
+e0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+20
+20
+70
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+50
+50
+20
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+d8
+d8
+50
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d0
+20
+50
+d8
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+50
+20
+70
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+20
+50
+70
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+c0
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+ATTRIBUTES 0x0258
+BITMAP
+60
+e0
+90
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 6 1 -1 -1
+ATTRIBUTES 0x0258
+BITMAP
+fc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+90
+e8
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+f0
+88
+f0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+10
+f0
+90
+78
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+a8
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+80
+80
+e0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+70
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+70
+50
+d8
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 1 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+c0
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+70
+60
+d8
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+a8
+e8
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+50
+d8
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+f0
+48
+70
+40
+c0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+78
+90
+70
+10
+38
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+80
+e0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+70
+f0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+80
+80
+e0
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d0
+50
+70
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+d8
+50
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+a8
+b8
+50
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f0
+60
+d8
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+d0
+50
+20
+20
+e0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+e0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 7 2 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 7 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 1 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 4 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+e0
+c0
+f0
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+80
+e0
+80
+e0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+c0
+b0
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+50
+70
+70
+70
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 7 2 -2
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+80
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+c0
+e0
+20
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 1 1 4
+ATTRIBUTES 0x0258
+BITMAP
+c0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+e8
+88
+70
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+c0
+c0
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 1 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+f8
+f8
+70
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 1 1 4
+ATTRIBUTES 0x0258
+BITMAP
+e0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+40
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+20
+e0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+e0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 1 1 4
+ATTRIBUTES 0x0258
+BITMAP
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+d0
+50
+70
+40
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+60
+60
+60
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 1 2 2
+ATTRIBUTES 0x0258
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 2 2 -1
+ATTRIBUTES 0x0258
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 3 1 2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+c0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 2 1 2
+ATTRIBUTES 0x0258
+BITMAP
+e0
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+60
+60
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+c8
+50
+d8
+38
+58
+58
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+c8
+50
+f8
+28
+48
+98
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+c8
+50
+d0
+38
+58
+58
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 4 1 -1
+ATTRIBUTES 0x0258
+BITMAP
+40
+40
+80
+e0
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+60
+00
+70
+50
+70
+d8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+30
+78
+f8
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+80
+70
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+f8
+70
+40
+f8
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+e0
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+f8
+e8
+48
+f0
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+d8
+68
+68
+d8
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 3 1 1
+ATTRIBUTES 0x0258
+BITMAP
+a0
+60
+a0
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+a8
+a8
+f0
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d8
+90
+90
+f0
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+f8
+50
+20
+70
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+90
+e0
+c0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+e0
+a0
+e0
+a0
+e0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+90
+e8
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+70
+f8
+f8
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 4 0 -1
+ATTRIBUTES 0x0258
+BITMAP
+78
+80
+70
+20
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+a8
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+ATTRIBUTES 0x0258
+BITMAP
+c0
+00
+c0
+40
+e0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+ATTRIBUTES 0x0258
+BITMAP
+20
+20
+10
+f8
+88
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+f0
+50
+d8
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+30
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+70
+88
+70
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 4 2 0
+ATTRIBUTES 0x0258
+BITMAP
+80
+00
+00
+80
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 0
+ATTRIBUTES 0x0258
+BITMAP
+78
+e8
+b0
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+10
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d0
+50
+70
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+40
+00
+d0
+50
+20
+20
+e0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+c0
+40
+70
+48
+70
+40
+c0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 -2
+ATTRIBUTES 0x0258
+BITMAP
+60
+00
+d0
+50
+20
+20
+e0
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier8.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier8.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/courier8.h	(revision 16632)
@@ -0,0 +1,769 @@
+static unsigned char courier8_0_bits[] = {
+0x00};
+static unsigned char courier8_1_bits[] = {
+0x00};
+static unsigned char courier8_2_bits[] = {
+0x00};
+static unsigned char courier8_3_bits[] = {
+0x00};
+static unsigned char courier8_4_bits[] = {
+0x00};
+static unsigned char courier8_5_bits[] = {
+0x00};
+static unsigned char courier8_6_bits[] = {
+0x00};
+static unsigned char courier8_7_bits[] = {
+0x00};
+static unsigned char courier8_8_bits[] = {
+0x00};
+static unsigned char courier8_9_bits[] = {
+0x00};
+static unsigned char courier8_10_bits[] = {
+0x00};
+static unsigned char courier8_11_bits[] = {
+0x00};
+static unsigned char courier8_12_bits[] = {
+0x00};
+static unsigned char courier8_13_bits[] = {
+0x00};
+static unsigned char courier8_14_bits[] = {
+0x00};
+static unsigned char courier8_15_bits[] = {
+0x00};
+static unsigned char courier8_16_bits[] = {
+0x00};
+static unsigned char courier8_17_bits[] = {
+0x00};
+static unsigned char courier8_18_bits[] = {
+0x00};
+static unsigned char courier8_19_bits[] = {
+0x00};
+static unsigned char courier8_20_bits[] = {
+0x00};
+static unsigned char courier8_21_bits[] = {
+0x00};
+static unsigned char courier8_22_bits[] = {
+0x00};
+static unsigned char courier8_23_bits[] = {
+0x00};
+static unsigned char courier8_24_bits[] = {
+0x00};
+static unsigned char courier8_25_bits[] = {
+0x00};
+static unsigned char courier8_26_bits[] = {
+0x00};
+static unsigned char courier8_27_bits[] = {
+0x00};
+static unsigned char courier8_28_bits[] = {
+0x00};
+static unsigned char courier8_29_bits[] = {
+0x00};
+static unsigned char courier8_30_bits[] = {
+0x00};
+static unsigned char courier8_31_bits[] = {
+0x00};
+static unsigned char courier8_32_bits[] = {
+0x00};
+static unsigned char courier8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_34_bits[] = {
+0x05, 0x05};
+static unsigned char courier8_35_bits[] = {
+0x05, 0x05, 0x07, 0x07, 0x05};
+static unsigned char courier8_36_bits[] = {
+0x07, 0x07, 0x03, 0x07, 0x07, 0x02};
+static unsigned char courier8_37_bits[] = {
+0x07, 0x07, 0x1f, 0x1c, 0x1c};
+static unsigned char courier8_38_bits[] = {
+0x02, 0x01, 0x05, 0x07, 0x07};
+static unsigned char courier8_39_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_40_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char courier8_42_bits[] = {
+0x02, 0x02, 0x05};
+static unsigned char courier8_43_bits[] = {
+0x02, 0x07, 0x02};
+static unsigned char courier8_44_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_45_bits[] = {
+0x0f};
+static unsigned char courier8_46_bits[] = {
+0x01};
+static unsigned char courier8_47_bits[] = {
+0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 0x01};
+static unsigned char courier8_48_bits[] = {
+0x03, 0x05, 0x05, 0x05, 0x03};
+static unsigned char courier8_49_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char courier8_50_bits[] = {
+0x06, 0x08, 0x0c, 0x02, 0x0f};
+static unsigned char courier8_51_bits[] = {
+0x03, 0x02, 0x06, 0x04, 0x03};
+static unsigned char courier8_52_bits[] = {
+0x04, 0x06, 0x06, 0x0f, 0x0c};
+static unsigned char courier8_53_bits[] = {
+0x03, 0x01, 0x07, 0x04, 0x07};
+static unsigned char courier8_54_bits[] = {
+0x06, 0x01, 0x07, 0x05, 0x07};
+static unsigned char courier8_55_bits[] = {
+0x0f, 0x08, 0x04, 0x04, 0x04};
+static unsigned char courier8_56_bits[] = {
+0x07, 0x05, 0x03, 0x05, 0x07};
+static unsigned char courier8_57_bits[] = {
+0x06, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char courier8_58_bits[] = {
+0x01, 0x00, 0x01};
+static unsigned char courier8_59_bits[] = {
+0x02, 0x00, 0x02, 0x02};
+static unsigned char courier8_60_bits[] = {
+0x06, 0x03, 0x04};
+static unsigned char courier8_61_bits[] = {
+0x0f, 0x00, 0x0f};
+static unsigned char courier8_62_bits[] = {
+0x06, 0x0c, 0x03};
+static unsigned char courier8_63_bits[] = {
+0x07, 0x04, 0x02, 0x02};
+static unsigned char courier8_64_bits[] = {
+0x0e, 0x15, 0x17, 0x1f, 0x0e};
+static unsigned char courier8_65_bits[] = {
+0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_66_bits[] = {
+0x0f, 0x0e, 0x12, 0x0f};
+static unsigned char courier8_67_bits[] = {
+0x1e, 0x01, 0x01, 0x0e};
+static unsigned char courier8_68_bits[] = {
+0x1f, 0x12, 0x12, 0x0f};
+static unsigned char courier8_69_bits[] = {
+0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_70_bits[] = {
+0x0f, 0x07, 0x01, 0x03};
+static unsigned char courier8_71_bits[] = {
+0x1e, 0x01, 0x19, 0x1e};
+static unsigned char courier8_72_bits[] = {
+0x0b, 0x0e, 0x0a, 0x0b};
+static unsigned char courier8_73_bits[] = {
+0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_74_bits[] = {
+0x1c, 0x08, 0x09, 0x0f};
+static unsigned char courier8_75_bits[] = {
+0x1b, 0x06, 0x0a, 0x13};
+static unsigned char courier8_76_bits[] = {
+0x07, 0x02, 0x12, 0x1f};
+static unsigned char courier8_77_bits[] = {
+0x3b, 0x1b, 0x15, 0x1b};
+static unsigned char courier8_78_bits[] = {
+0x1b, 0x16, 0x16, 0x1b};
+static unsigned char courier8_79_bits[] = {
+0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_80_bits[] = {
+0x0f, 0x09, 0x07, 0x03};
+static unsigned char courier8_81_bits[] = {
+0x0e, 0x11, 0x11, 0x0e, 0x0e};
+static unsigned char courier8_82_bits[] = {
+0x0f, 0x06, 0x0a, 0x1b};
+static unsigned char courier8_83_bits[] = {
+0x0f, 0x03, 0x04, 0x07};
+static unsigned char courier8_84_bits[] = {
+0x1f, 0x04, 0x04, 0x0e};
+static unsigned char courier8_85_bits[] = {
+0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_86_bits[] = {
+0x1b, 0x0a, 0x0a, 0x04};
+static unsigned char courier8_87_bits[] = {
+0x1f, 0x1b, 0x1b, 0x0a};
+static unsigned char courier8_88_bits[] = {
+0x0b, 0x04, 0x0a, 0x1b};
+static unsigned char courier8_89_bits[] = {
+0x1f, 0x0a, 0x04, 0x0e};
+static unsigned char courier8_90_bits[] = {
+0x0f, 0x04, 0x0a, 0x0e};
+static unsigned char courier8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char courier8_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04};
+static unsigned char courier8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier8_94_bits[] = {
+0x06, 0x07, 0x09};
+static unsigned char courier8_95_bits[] = {
+0x3f};
+static unsigned char courier8_96_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_97_bits[] = {
+0x0e, 0x09, 0x17};
+static unsigned char courier8_98_bits[] = {
+0x01, 0x01, 0x0f, 0x11, 0x0f};
+static unsigned char courier8_99_bits[] = {
+0x1e, 0x01, 0x0e};
+static unsigned char courier8_100_bits[] = {
+0x0c, 0x08, 0x0f, 0x09, 0x1e};
+static unsigned char courier8_101_bits[] = {
+0x0e, 0x15, 0x1e};
+static unsigned char courier8_102_bits[] = {
+0x07, 0x07, 0x01, 0x01, 0x07};
+static unsigned char courier8_103_bits[] = {
+0x0e, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char courier8_104_bits[] = {
+0x03, 0x02, 0x0e, 0x0a, 0x1b};
+static unsigned char courier8_105_bits[] = {
+0x02, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_106_bits[] = {
+0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier8_107_bits[] = {
+0x03, 0x02, 0x0e, 0x06, 0x1b};
+static unsigned char courier8_108_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char courier8_109_bits[] = {
+0x1f, 0x15, 0x17};
+static unsigned char courier8_110_bits[] = {
+0x0f, 0x0a, 0x1b};
+static unsigned char courier8_111_bits[] = {
+0x0e, 0x11, 0x0e};
+static unsigned char courier8_112_bits[] = {
+0x0f, 0x12, 0x0e, 0x02, 0x03};
+static unsigned char courier8_113_bits[] = {
+0x1e, 0x09, 0x0e, 0x08, 0x1c};
+static unsigned char courier8_114_bits[] = {
+0x07, 0x01, 0x07};
+static unsigned char courier8_115_bits[] = {
+0x1e, 0x0e, 0x0f};
+static unsigned char courier8_116_bits[] = {
+0x07, 0x01, 0x01, 0x07};
+static unsigned char courier8_117_bits[] = {
+0x0b, 0x0a, 0x0e};
+static unsigned char courier8_118_bits[] = {
+0x1b, 0x0a, 0x04};
+static unsigned char courier8_119_bits[] = {
+0x15, 0x1d, 0x0a};
+static unsigned char courier8_120_bits[] = {
+0x0f, 0x06, 0x1b};
+static unsigned char courier8_121_bits[] = {
+0x0b, 0x0a, 0x04, 0x04, 0x07};
+static unsigned char courier8_122_bits[] = {
+0x07, 0x02, 0x07};
+static unsigned char courier8_123_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char courier8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char courier8_126_bits[] = {
+0x07};
+static unsigned char courier8_127_bits[] = {
+0x00};
+static unsigned char courier8_128_bits[] = {
+0x00};
+static unsigned char courier8_129_bits[] = {
+0x00};
+static unsigned char courier8_130_bits[] = {
+0x00};
+static unsigned char courier8_131_bits[] = {
+0x00};
+static unsigned char courier8_132_bits[] = {
+0x00};
+static unsigned char courier8_133_bits[] = {
+0x00};
+static unsigned char courier8_134_bits[] = {
+0x00};
+static unsigned char courier8_135_bits[] = {
+0x00};
+static unsigned char courier8_136_bits[] = {
+0x00};
+static unsigned char courier8_137_bits[] = {
+0x00};
+static unsigned char courier8_138_bits[] = {
+0x00};
+static unsigned char courier8_139_bits[] = {
+0x00};
+static unsigned char courier8_140_bits[] = {
+0x00};
+static unsigned char courier8_141_bits[] = {
+0x00};
+static unsigned char courier8_142_bits[] = {
+0x00};
+static unsigned char courier8_143_bits[] = {
+0x00};
+static unsigned char courier8_144_bits[] = {
+0x00};
+static unsigned char courier8_145_bits[] = {
+0x00};
+static unsigned char courier8_146_bits[] = {
+0x00};
+static unsigned char courier8_147_bits[] = {
+0x00};
+static unsigned char courier8_148_bits[] = {
+0x00};
+static unsigned char courier8_149_bits[] = {
+0x00};
+static unsigned char courier8_150_bits[] = {
+0x00};
+static unsigned char courier8_151_bits[] = {
+0x00};
+static unsigned char courier8_152_bits[] = {
+0x00};
+static unsigned char courier8_153_bits[] = {
+0x00};
+static unsigned char courier8_154_bits[] = {
+0x00};
+static unsigned char courier8_155_bits[] = {
+0x00};
+static unsigned char courier8_156_bits[] = {
+0x00};
+static unsigned char courier8_157_bits[] = {
+0x00};
+static unsigned char courier8_158_bits[] = {
+0x00};
+static unsigned char courier8_159_bits[] = {
+0x00};
+static unsigned char courier8_160_bits[] = {
+0x00};
+static unsigned char courier8_161_bits[] = {
+0x01, 0x01, 0x01, 0x01};
+static unsigned char courier8_162_bits[] = {
+0x02, 0x07, 0x03, 0x0f, 0x02};
+static unsigned char courier8_163_bits[] = {
+0x06, 0x01, 0x07, 0x01, 0x07};
+static unsigned char courier8_164_bits[] = {
+0x07, 0x05, 0x03, 0x0d};
+static unsigned char courier8_165_bits[] = {
+0x1f, 0x0a, 0x0e, 0x0e, 0x0e};
+static unsigned char courier8_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01};
+static unsigned char courier8_167_bits[] = {
+0x07, 0x03, 0x07, 0x04, 0x07};
+static unsigned char courier8_168_bits[] = {
+0x03};
+static unsigned char courier8_169_bits[] = {
+0x0e, 0x17, 0x11, 0x0e};
+static unsigned char courier8_170_bits[] = {
+0x03, 0x07};
+static unsigned char courier8_171_bits[] = {
+0x06, 0x03, 0x03};
+static unsigned char courier8_172_bits[] = {
+0x07, 0x04};
+static unsigned char courier8_173_bits[] = {
+0x03};
+static unsigned char courier8_174_bits[] = {
+0x1e, 0x1f, 0x1f, 0x0e};
+static unsigned char courier8_175_bits[] = {
+0x07};
+static unsigned char courier8_176_bits[] = {
+0x07, 0x05, 0x02};
+static unsigned char courier8_177_bits[] = {
+0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_178_bits[] = {
+0x07, 0x04, 0x07};
+static unsigned char courier8_179_bits[] = {
+0x03, 0x02, 0x07};
+static unsigned char courier8_180_bits[] = {
+0x01};
+static unsigned char courier8_181_bits[] = {
+0x0b, 0x0a, 0x0e, 0x02};
+static unsigned char courier8_182_bits[] = {
+0x07, 0x07, 0x06, 0x06, 0x06};
+static unsigned char courier8_183_bits[] = {
+0x01};
+static unsigned char courier8_184_bits[] = {
+0x01, 0x01};
+static unsigned char courier8_185_bits[] = {
+0x03, 0x02, 0x03};
+static unsigned char courier8_186_bits[] = {
+0x07, 0x07};
+static unsigned char courier8_187_bits[] = {
+0x03, 0x06, 0x06};
+static unsigned char courier8_188_bits[] = {
+0x13, 0x0a, 0x1b, 0x1c, 0x1a, 0x1a};
+static unsigned char courier8_189_bits[] = {
+0x13, 0x0a, 0x1f, 0x14, 0x12, 0x19};
+static unsigned char courier8_190_bits[] = {
+0x13, 0x0a, 0x0b, 0x1c, 0x1a, 0x1a};
+static unsigned char courier8_191_bits[] = {
+0x02, 0x02, 0x01, 0x07};
+static unsigned char courier8_192_bits[] = {
+0x08, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_193_bits[] = {
+0x02, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_194_bits[] = {
+0x06, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_195_bits[] = {
+0x0c, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_196_bits[] = {
+0x06, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_197_bits[] = {
+0x04, 0x06, 0x00, 0x0e, 0x0a, 0x0e, 0x1b};
+static unsigned char courier8_198_bits[] = {
+0x1e, 0x0c, 0x1e, 0x1f};
+static unsigned char courier8_199_bits[] = {
+0x1e, 0x01, 0x01, 0x0e, 0x0c};
+static unsigned char courier8_200_bits[] = {
+0x08, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_201_bits[] = {
+0x02, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_202_bits[] = {
+0x06, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_203_bits[] = {
+0x06, 0x00, 0x1f, 0x0e, 0x02, 0x1f};
+static unsigned char courier8_204_bits[] = {
+0x04, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_205_bits[] = {
+0x01, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_206_bits[] = {
+0x03, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_207_bits[] = {
+0x03, 0x00, 0x07, 0x02, 0x02, 0x07};
+static unsigned char courier8_208_bits[] = {
+0x1f, 0x17, 0x12, 0x0f};
+static unsigned char courier8_209_bits[] = {
+0x0c, 0x00, 0x1b, 0x16, 0x16, 0x1b};
+static unsigned char courier8_210_bits[] = {
+0x08, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_211_bits[] = {
+0x02, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_212_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_213_bits[] = {
+0x0c, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_214_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char courier8_215_bits[] = {
+0x05, 0x06, 0x05};
+static unsigned char courier8_216_bits[] = {
+0x1e, 0x15, 0x15, 0x0f};
+static unsigned char courier8_217_bits[] = {
+0x08, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_218_bits[] = {
+0x02, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_219_bits[] = {
+0x06, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_220_bits[] = {
+0x06, 0x00, 0x1b, 0x09, 0x09, 0x0f};
+static unsigned char courier8_221_bits[] = {
+0x02, 0x00, 0x1f, 0x0a, 0x04, 0x0e};
+static unsigned char courier8_222_bits[] = {
+0x07, 0x09, 0x07, 0x03};
+static unsigned char courier8_223_bits[] = {
+0x07, 0x05, 0x07, 0x05, 0x07};
+static unsigned char courier8_224_bits[] = {
+0x08, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_225_bits[] = {
+0x02, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_226_bits[] = {
+0x06, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_227_bits[] = {
+0x0c, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_228_bits[] = {
+0x06, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_229_bits[] = {
+0x06, 0x00, 0x0e, 0x09, 0x17};
+static unsigned char courier8_230_bits[] = {
+0x0e, 0x1f, 0x1f};
+static unsigned char courier8_231_bits[] = {
+0x1e, 0x01, 0x0e, 0x04};
+static unsigned char courier8_232_bits[] = {
+0x08, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_233_bits[] = {
+0x02, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_234_bits[] = {
+0x06, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_235_bits[] = {
+0x06, 0x00, 0x0e, 0x15, 0x1e};
+static unsigned char courier8_236_bits[] = {
+0x04, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_237_bits[] = {
+0x01, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_238_bits[] = {
+0x03, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_239_bits[] = {
+0x03, 0x00, 0x03, 0x02, 0x07};
+static unsigned char courier8_240_bits[] = {
+0x04, 0x04, 0x08, 0x1f, 0x11, 0x0e};
+static unsigned char courier8_241_bits[] = {
+0x0c, 0x00, 0x0f, 0x0a, 0x1b};
+static unsigned char courier8_242_bits[] = {
+0x08, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_243_bits[] = {
+0x02, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_244_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_245_bits[] = {
+0x0c, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_246_bits[] = {
+0x06, 0x00, 0x0e, 0x11, 0x0e};
+static unsigned char courier8_247_bits[] = {
+0x01, 0x00, 0x00, 0x01};
+static unsigned char courier8_248_bits[] = {
+0x1e, 0x17, 0x0d};
+static unsigned char courier8_249_bits[] = {
+0x08, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_250_bits[] = {
+0x02, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_251_bits[] = {
+0x06, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_252_bits[] = {
+0x06, 0x00, 0x0b, 0x0a, 0x0e};
+static unsigned char courier8_253_bits[] = {
+0x02, 0x00, 0x0b, 0x0a, 0x04, 0x04, 0x07};
+static unsigned char courier8_254_bits[] = {
+0x03, 0x02, 0x0e, 0x12, 0x0e, 0x02, 0x03};
+static unsigned char courier8_255_bits[] = {
+0x06, 0x00, 0x0b, 0x0a, 0x04, 0x04, 0x07};
+static RotFont courier8font[] = {
+{5, 1, 1, courier8_0_bits},
+{5, 1, 1, courier8_1_bits},
+{5, 1, 1, courier8_2_bits},
+{5, 1, 1, courier8_3_bits},
+{5, 1, 1, courier8_4_bits},
+{5, 1, 1, courier8_5_bits},
+{5, 1, 1, courier8_6_bits},
+{5, 1, 1, courier8_7_bits},
+{5, 1, 1, courier8_8_bits},
+{5, 1, 1, courier8_9_bits},
+{5, 1, 1, courier8_10_bits},
+{5, 1, 1, courier8_11_bits},
+{5, 1, 1, courier8_12_bits},
+{5, 1, 1, courier8_13_bits},
+{5, 1, 1, courier8_14_bits},
+{5, 1, 1, courier8_15_bits},
+{5, 1, 1, courier8_16_bits},
+{5, 1, 1, courier8_17_bits},
+{5, 1, 1, courier8_18_bits},
+{5, 1, 1, courier8_19_bits},
+{5, 1, 1, courier8_20_bits},
+{5, 1, 1, courier8_21_bits},
+{5, 1, 1, courier8_22_bits},
+{5, 1, 1, courier8_23_bits},
+{5, 1, 1, courier8_24_bits},
+{5, 1, 1, courier8_25_bits},
+{5, 1, 1, courier8_26_bits},
+{5, 1, 1, courier8_27_bits},
+{5, 1, 1, courier8_28_bits},
+{5, 1, 1, courier8_29_bits},
+{5, 1, 1, courier8_30_bits},
+{5, 1, 1, courier8_31_bits},
+{5, 1, 1, courier8_32_bits},
+{1, 4, 4, courier8_33_bits},
+{3, 2, 4, courier8_34_bits},
+{3, 5, 5, courier8_35_bits},
+{3, 6, 5, courier8_36_bits},
+{5, 5, 5, courier8_37_bits},
+{3, 5, 5, courier8_38_bits},
+{1, 2, 4, courier8_39_bits},
+{2, 6, 5, courier8_40_bits},
+{2, 6, 5, courier8_41_bits},
+{3, 3, 4, courier8_42_bits},
+{3, 3, 4, courier8_43_bits},
+{1, 2, 1, courier8_44_bits},
+{4, 1, 3, courier8_45_bits},
+{1, 1, 1, courier8_46_bits},
+{3, 7, 6, courier8_47_bits},
+{3, 5, 5, courier8_48_bits},
+{3, 5, 5, courier8_49_bits},
+{4, 5, 5, courier8_50_bits},
+{3, 5, 5, courier8_51_bits},
+{4, 5, 5, courier8_52_bits},
+{3, 5, 5, courier8_53_bits},
+{3, 5, 5, courier8_54_bits},
+{4, 5, 5, courier8_55_bits},
+{3, 5, 5, courier8_56_bits},
+{4, 5, 5, courier8_57_bits},
+{1, 3, 3, courier8_58_bits},
+{2, 4, 3, courier8_59_bits},
+{4, 3, 4, courier8_60_bits},
+{4, 3, 4, courier8_61_bits},
+{4, 3, 4, courier8_62_bits},
+{3, 4, 4, courier8_63_bits},
+{5, 5, 5, courier8_64_bits},
+{5, 4, 4, courier8_65_bits},
+{5, 4, 4, courier8_66_bits},
+{5, 4, 4, courier8_67_bits},
+{5, 4, 4, courier8_68_bits},
+{5, 4, 4, courier8_69_bits},
+{4, 4, 4, courier8_70_bits},
+{5, 4, 4, courier8_71_bits},
+{4, 4, 4, courier8_72_bits},
+{3, 4, 4, courier8_73_bits},
+{5, 4, 4, courier8_74_bits},
+{5, 4, 4, courier8_75_bits},
+{5, 4, 4, courier8_76_bits},
+{6, 4, 4, courier8_77_bits},
+{5, 4, 4, courier8_78_bits},
+{5, 4, 4, courier8_79_bits},
+{4, 4, 4, courier8_80_bits},
+{5, 5, 4, courier8_81_bits},
+{5, 4, 4, courier8_82_bits},
+{4, 4, 4, courier8_83_bits},
+{5, 4, 4, courier8_84_bits},
+{5, 4, 4, courier8_85_bits},
+{5, 4, 4, courier8_86_bits},
+{5, 4, 4, courier8_87_bits},
+{5, 4, 4, courier8_88_bits},
+{5, 4, 4, courier8_89_bits},
+{4, 4, 4, courier8_90_bits},
+{2, 7, 6, courier8_91_bits},
+{3, 7, 6, courier8_92_bits},
+{2, 7, 6, courier8_93_bits},
+{4, 3, 4, courier8_94_bits},
+{6, 1, 0, courier8_95_bits},
+{1, 2, 4, courier8_96_bits},
+{5, 3, 3, courier8_97_bits},
+{5, 5, 5, courier8_98_bits},
+{5, 3, 3, courier8_99_bits},
+{5, 5, 5, courier8_100_bits},
+{5, 3, 3, courier8_101_bits},
+{3, 5, 5, courier8_102_bits},
+{4, 5, 3, courier8_103_bits},
+{5, 5, 5, courier8_104_bits},
+{3, 5, 5, courier8_105_bits},
+{2, 7, 5, courier8_106_bits},
+{5, 5, 5, courier8_107_bits},
+{3, 5, 5, courier8_108_bits},
+{5, 3, 3, courier8_109_bits},
+{5, 3, 3, courier8_110_bits},
+{5, 3, 3, courier8_111_bits},
+{5, 5, 3, courier8_112_bits},
+{5, 5, 3, courier8_113_bits},
+{3, 3, 3, courier8_114_bits},
+{5, 3, 3, courier8_115_bits},
+{3, 4, 4, courier8_116_bits},
+{4, 3, 3, courier8_117_bits},
+{5, 3, 3, courier8_118_bits},
+{5, 3, 3, courier8_119_bits},
+{5, 3, 3, courier8_120_bits},
+{4, 5, 3, courier8_121_bits},
+{3, 3, 3, courier8_122_bits},
+{2, 7, 6, courier8_123_bits},
+{1, 7, 5, courier8_124_bits},
+{2, 7, 6, courier8_125_bits},
+{3, 1, 3, courier8_126_bits},
+{5, 1, 1, courier8_127_bits},
+{5, 1, 1, courier8_128_bits},
+{5, 1, 1, courier8_129_bits},
+{5, 1, 1, courier8_130_bits},
+{5, 1, 1, courier8_131_bits},
+{5, 1, 1, courier8_132_bits},
+{5, 1, 1, courier8_133_bits},
+{5, 1, 1, courier8_134_bits},
+{5, 1, 1, courier8_135_bits},
+{5, 1, 1, courier8_136_bits},
+{5, 1, 1, courier8_137_bits},
+{5, 1, 1, courier8_138_bits},
+{5, 1, 1, courier8_139_bits},
+{5, 1, 1, courier8_140_bits},
+{5, 1, 1, courier8_141_bits},
+{5, 1, 1, courier8_142_bits},
+{5, 1, 1, courier8_143_bits},
+{5, 1, 1, courier8_144_bits},
+{5, 1, 1, courier8_145_bits},
+{5, 1, 1, courier8_146_bits},
+{5, 1, 1, courier8_147_bits},
+{5, 1, 1, courier8_148_bits},
+{5, 1, 1, courier8_149_bits},
+{5, 1, 1, courier8_150_bits},
+{5, 1, 1, courier8_151_bits},
+{5, 1, 1, courier8_152_bits},
+{5, 1, 1, courier8_153_bits},
+{5, 1, 1, courier8_154_bits},
+{5, 1, 1, courier8_155_bits},
+{5, 1, 1, courier8_156_bits},
+{5, 1, 1, courier8_157_bits},
+{5, 1, 1, courier8_158_bits},
+{5, 1, 1, courier8_159_bits},
+{5, 1, 1, courier8_160_bits},
+{1, 4, 3, courier8_161_bits},
+{4, 5, 5, courier8_162_bits},
+{3, 5, 5, courier8_163_bits},
+{4, 4, 4, courier8_164_bits},
+{5, 5, 5, courier8_165_bits},
+{1, 7, 5, courier8_166_bits},
+{3, 5, 4, courier8_167_bits},
+{2, 1, 5, courier8_168_bits},
+{5, 4, 4, courier8_169_bits},
+{3, 2, 4, courier8_170_bits},
+{3, 3, 3, courier8_171_bits},
+{3, 2, 3, courier8_172_bits},
+{2, 1, 3, courier8_173_bits},
+{5, 4, 4, courier8_174_bits},
+{3, 1, 5, courier8_175_bits},
+{3, 3, 5, courier8_176_bits},
+{3, 4, 4, courier8_177_bits},
+{3, 3, 5, courier8_178_bits},
+{3, 3, 5, courier8_179_bits},
+{2, 1, 5, courier8_180_bits},
+{4, 4, 3, courier8_181_bits},
+{3, 5, 4, courier8_182_bits},
+{1, 1, 3, courier8_183_bits},
+{1, 2, 1, courier8_184_bits},
+{2, 3, 5, courier8_185_bits},
+{3, 2, 4, courier8_186_bits},
+{3, 3, 3, courier8_187_bits},
+{5, 6, 5, courier8_188_bits},
+{5, 6, 5, courier8_189_bits},
+{5, 6, 5, courier8_190_bits},
+{3, 4, 3, courier8_191_bits},
+{5, 6, 6, courier8_192_bits},
+{5, 6, 6, courier8_193_bits},
+{5, 6, 6, courier8_194_bits},
+{5, 6, 6, courier8_195_bits},
+{5, 6, 6, courier8_196_bits},
+{5, 7, 7, courier8_197_bits},
+{5, 4, 4, courier8_198_bits},
+{5, 5, 4, courier8_199_bits},
+{5, 6, 6, courier8_200_bits},
+{5, 6, 6, courier8_201_bits},
+{5, 6, 6, courier8_202_bits},
+{5, 6, 6, courier8_203_bits},
+{3, 6, 6, courier8_204_bits},
+{3, 6, 6, courier8_205_bits},
+{3, 6, 6, courier8_206_bits},
+{3, 6, 6, courier8_207_bits},
+{5, 4, 4, courier8_208_bits},
+{5, 6, 6, courier8_209_bits},
+{5, 6, 6, courier8_210_bits},
+{5, 6, 6, courier8_211_bits},
+{5, 6, 6, courier8_212_bits},
+{5, 6, 6, courier8_213_bits},
+{5, 6, 6, courier8_214_bits},
+{3, 3, 4, courier8_215_bits},
+{5, 4, 4, courier8_216_bits},
+{5, 6, 6, courier8_217_bits},
+{5, 6, 6, courier8_218_bits},
+{5, 6, 6, courier8_219_bits},
+{5, 6, 6, courier8_220_bits},
+{5, 6, 6, courier8_221_bits},
+{4, 4, 4, courier8_222_bits},
+{3, 5, 5, courier8_223_bits},
+{5, 5, 5, courier8_224_bits},
+{5, 5, 5, courier8_225_bits},
+{5, 5, 5, courier8_226_bits},
+{5, 5, 5, courier8_227_bits},
+{5, 5, 5, courier8_228_bits},
+{5, 5, 5, courier8_229_bits},
+{5, 3, 3, courier8_230_bits},
+{5, 4, 3, courier8_231_bits},
+{5, 5, 5, courier8_232_bits},
+{5, 5, 5, courier8_233_bits},
+{5, 5, 5, courier8_234_bits},
+{5, 5, 5, courier8_235_bits},
+{3, 5, 5, courier8_236_bits},
+{3, 5, 5, courier8_237_bits},
+{3, 5, 5, courier8_238_bits},
+{3, 5, 5, courier8_239_bits},
+{5, 6, 6, courier8_240_bits},
+{5, 5, 5, courier8_241_bits},
+{5, 5, 5, courier8_242_bits},
+{5, 5, 5, courier8_243_bits},
+{5, 5, 5, courier8_244_bits},
+{5, 5, 5, courier8_245_bits},
+{5, 5, 5, courier8_246_bits},
+{1, 4, 4, courier8_247_bits},
+{5, 3, 3, courier8_248_bits},
+{4, 5, 5, courier8_249_bits},
+{4, 5, 5, courier8_250_bits},
+{4, 5, 5, courier8_251_bits},
+{4, 5, 5, courier8_252_bits},
+{4, 7, 5, courier8_253_bits},
+{5, 7, 5, courier8_254_bits},
+{4, 7, 5, courier8_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/fixed.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/fixed.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/fixed.h	(revision 16632)
@@ -0,0 +1,765 @@
+static unsigned char fixed_0_bits[] = {};
+static unsigned char fixed_1_bits[] = {
+0x4, 0xe, 0xe, 0x1f, 0xe, 0xe, 0x04};
+static unsigned char fixed_2_bits[] = {
+0x15, 0xa, 0x15, 0xa, 0x15, 0xa, 0x15};
+static unsigned char fixed_3_bits[] = {
+0x9, 0x9, 0xf, 0x9, 0x9, 0x1e, 0x8, 0x8, 0x08};
+static unsigned char fixed_4_bits[] = {
+0x7, 0x1, 0x3, 0x1, 0x1d, 0x4, 0xc, 0x4, 0x04};
+static unsigned char fixed_5_bits[] = {
+0xe, 0x1, 0x1, 0xe, 0xe, 0x12, 0xe, 0x12, 0x12};
+static unsigned char fixed_6_bits[] = {
+0x1, 0x1, 0x1, 0xf, 0x1e, 0x2, 0xe, 0x2, 0x02};
+static unsigned char fixed_7_bits[] = {
+0x2, 0x5, 0x02};
+static unsigned char fixed_8_bits[] = {
+0x4, 0x4, 0x1f, 0x4, 0x4, 0x1f};
+static unsigned char fixed_9_bits[] = {
+0x9, 0xb, 0xb, 0xd, 0x9, 0x2, 0x2, 0x2, 0x1e};
+static unsigned char fixed_10_bits[] = {
+0x9, 0x9, 0x6, 0x2, 0x1e, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_11_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0x0f};
+static unsigned char fixed_12_bits[] = {
+0xf, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_13_bits[] = {
+0x7, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_14_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x07};
+static unsigned char fixed_15_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0x3f, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_16_bits[] = {
+0x3f};
+static unsigned char fixed_17_bits[] = {
+0x3f};
+static unsigned char fixed_18_bits[] = {
+0x3f};
+static unsigned char fixed_19_bits[] = {
+0x3f};
+static unsigned char fixed_20_bits[] = {
+0x3f};
+static unsigned char fixed_21_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x7, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_22_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0xf, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_23_bits[] = {
+0x8, 0x8, 0x8, 0x8, 0x3f};
+static unsigned char fixed_24_bits[] = {
+0x3f, 0x8, 0x8, 0x8, 0x8, 0x08};
+static unsigned char fixed_25_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_26_bits[] = {
+0x10, 0x8, 0x2, 0x1, 0x2, 0x8, 0x10, 0x1f};
+static unsigned char fixed_27_bits[] = {
+0x1, 0x2, 0x8, 0x10, 0x8, 0x2, 0x1, 0x1f};
+static unsigned char fixed_28_bits[] = {
+0x1f, 0xa, 0xa, 0xa, 0x0a};
+static unsigned char fixed_29_bits[] = {
+0x10, 0x8, 0x1f, 0x4, 0x1f, 0x2, 0x01};
+static unsigned char fixed_30_bits[] = {
+0xc, 0x12, 0x2, 0x7, 0x2, 0x12, 0x0d};
+static unsigned char fixed_31_bits[] = {
+0x01};
+static unsigned char fixed_32_bits[] = {};
+static unsigned char fixed_33_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x0, 0x01};
+static unsigned char fixed_34_bits[] = {
+0x5, 0x5, 0x05};
+static unsigned char fixed_35_bits[] = {
+0xa, 0xa, 0x1f, 0xa, 0x1f, 0xa, 0x0a};
+static unsigned char fixed_36_bits[] = {
+0x4, 0xe, 0x5, 0xe, 0x14, 0xe, 0x04};
+static unsigned char fixed_37_bits[] = {
+0x12, 0x15, 0xa, 0x4, 0xa, 0x15, 0x09};
+static unsigned char fixed_38_bits[] = {
+0x2, 0x5, 0x5, 0x2, 0x15, 0x9, 0x16};
+static unsigned char fixed_39_bits[] = {
+0x6, 0x2, 0x01};
+static unsigned char fixed_40_bits[] = {
+0x4, 0x2, 0x1, 0x1, 0x1, 0x2, 0x04};
+static unsigned char fixed_41_bits[] = {
+0x1, 0x2, 0x4, 0x4, 0x4, 0x2, 0x01};
+static unsigned char fixed_42_bits[] = {
+0x11, 0xa, 0x1f, 0xa, 0x11};
+static unsigned char fixed_43_bits[] = {
+0x4, 0x4, 0x1f, 0x4, 0x04};
+static unsigned char fixed_44_bits[] = {
+0x6, 0x2, 0x01};
+static unsigned char fixed_45_bits[] = {
+0x1f};
+static unsigned char fixed_46_bits[] = {
+0x2, 0x7, 0x02};
+static unsigned char fixed_47_bits[] = {
+0x10, 0x10, 0x8, 0x4, 0x2, 0x1, 0x01};
+static unsigned char fixed_48_bits[] = {
+0x4, 0xa, 0x11, 0x11, 0x11, 0xa, 0x04};
+static unsigned char fixed_49_bits[] = {
+0x4, 0x6, 0x5, 0x4, 0x4, 0x4, 0x1f};
+static unsigned char fixed_50_bits[] = {
+0xe, 0x11, 0x10, 0xc, 0x2, 0x1, 0x1f};
+static unsigned char fixed_51_bits[] = {
+0x1f, 0x10, 0x8, 0xc, 0x10, 0x11, 0x0e};
+static unsigned char fixed_52_bits[] = {
+0x8, 0xc, 0xa, 0x9, 0x1f, 0x8, 0x08};
+static unsigned char fixed_53_bits[] = {
+0x1f, 0x1, 0xd, 0x13, 0x10, 0x11, 0x0e};
+static unsigned char fixed_54_bits[] = {
+0xc, 0x2, 0x1, 0xd, 0x13, 0x11, 0x0e};
+static unsigned char fixed_55_bits[] = {
+0x1f, 0x10, 0x8, 0x8, 0x4, 0x2, 0x02};
+static unsigned char fixed_56_bits[] = {
+0xe, 0x11, 0x11, 0xe, 0x11, 0x11, 0x0e};
+static unsigned char fixed_57_bits[] = {
+0xe, 0x11, 0x19, 0x16, 0x10, 0x8, 0x06};
+static unsigned char fixed_58_bits[] = {
+0x2, 0x7, 0x2, 0x0, 0x2, 0x7, 0x02};
+static unsigned char fixed_59_bits[] = {
+0x2, 0x7, 0x2, 0x0, 0x6, 0x2, 0x01};
+static unsigned char fixed_60_bits[] = {
+0x8, 0x4, 0x2, 0x1, 0x2, 0x4, 0x08};
+static unsigned char fixed_61_bits[] = {
+0x1f, 0x0, 0x1f};
+static unsigned char fixed_62_bits[] = {
+0x1, 0x2, 0x4, 0x8, 0x4, 0x2, 0x01};
+static unsigned char fixed_63_bits[] = {
+0xe, 0x11, 0x8, 0x4, 0x4, 0x0, 0x04};
+static unsigned char fixed_64_bits[] = {
+0xe, 0x11, 0x19, 0x15, 0xd, 0x1, 0x0e};
+static unsigned char fixed_65_bits[] = {
+0x4, 0xa, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_66_bits[] = {
+0xf, 0x12, 0x12, 0xe, 0x12, 0x12, 0x0f};
+static unsigned char fixed_67_bits[] = {
+0xe, 0x11, 0x1, 0x1, 0x1, 0x11, 0x0e};
+static unsigned char fixed_68_bits[] = {
+0xf, 0x12, 0x12, 0x12, 0x12, 0x12, 0x0f};
+static unsigned char fixed_69_bits[] = {
+0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_70_bits[] = {
+0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x01};
+static unsigned char fixed_71_bits[] = {
+0xe, 0x11, 0x1, 0x1, 0x19, 0x11, 0x0e};
+static unsigned char fixed_72_bits[] = {
+0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11};
+static unsigned char fixed_73_bits[] = {
+0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_74_bits[] = {
+0x1c, 0x10, 0x10, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char fixed_75_bits[] = {
+0x11, 0x9, 0x5, 0x3, 0x5, 0x9, 0x11};
+static unsigned char fixed_76_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1f};
+static unsigned char fixed_77_bits[] = {
+0x11, 0x11, 0x1b, 0x15, 0x11, 0x11, 0x11};
+static unsigned char fixed_78_bits[] = {
+0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11};
+static unsigned char fixed_79_bits[] = {
+0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_80_bits[] = {
+0xf, 0x11, 0x11, 0xf, 0x1, 0x1, 0x01};
+static unsigned char fixed_81_bits[] = {
+0xe, 0x11, 0x11, 0x11, 0x11, 0x15, 0xe, 0x10};
+static unsigned char fixed_82_bits[] = {
+0xf, 0x11, 0x11, 0xf, 0x5, 0x9, 0x11};
+static unsigned char fixed_83_bits[] = {
+0xe, 0x11, 0x1, 0xe, 0x10, 0x11, 0x0e};
+static unsigned char fixed_84_bits[] = {
+0x1f, 0x4, 0x4, 0x4, 0x4, 0x4, 0x04};
+static unsigned char fixed_85_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_86_bits[] = {
+0x11, 0x11, 0x11, 0xa, 0xa, 0xa, 0x04};
+static unsigned char fixed_87_bits[] = {
+0x11, 0x11, 0x11, 0x15, 0x15, 0x1b, 0x11};
+static unsigned char fixed_88_bits[] = {
+0x11, 0x11, 0xa, 0x4, 0xa, 0x11, 0x11};
+static unsigned char fixed_89_bits[] = {
+0x11, 0x11, 0xa, 0x4, 0x4, 0x4, 0x04};
+static unsigned char fixed_90_bits[] = {
+0x1f, 0x10, 0x8, 0x4, 0x2, 0x1, 0x1f};
+static unsigned char fixed_91_bits[] = {
+0x7, 0x1, 0x1, 0x1, 0x1, 0x1, 0x07};
+static unsigned char fixed_92_bits[] = {
+0x1, 0x1, 0x2, 0x4, 0x8, 0x10, 0x10};
+static unsigned char fixed_93_bits[] = {
+0x7, 0x4, 0x4, 0x4, 0x4, 0x4, 0x07};
+static unsigned char fixed_94_bits[] = {
+0x4, 0xa, 0x11};
+static unsigned char fixed_95_bits[] = {
+0x1f};
+static unsigned char fixed_96_bits[] = {
+0x3, 0x2, 0x04};
+static unsigned char fixed_97_bits[] = {
+0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_98_bits[] = {
+0x1, 0x1, 0xd, 0x13, 0x11, 0x13, 0x0d};
+static unsigned char fixed_99_bits[] = {
+0xe, 0x11, 0x1, 0x11, 0x0e};
+static unsigned char fixed_100_bits[] = {
+0x10, 0x10, 0x16, 0x19, 0x11, 0x19, 0x16};
+static unsigned char fixed_101_bits[] = {
+0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_102_bits[] = {
+0xc, 0x12, 0x2, 0xf, 0x2, 0x2, 0x02};
+static unsigned char fixed_103_bits[] = {
+0x16, 0x9, 0x6, 0x1, 0xe, 0x11, 0x0e};
+static unsigned char fixed_104_bits[] = {
+0x1, 0x1, 0xd, 0x13, 0x11, 0x11, 0x11};
+static unsigned char fixed_105_bits[] = {
+0x2, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_106_bits[] = {
+0x8, 0x0, 0xc, 0x8, 0x8, 0x8, 0x9, 0x9, 0x06};
+static unsigned char fixed_107_bits[] = {
+0x1, 0x1, 0x11, 0x9, 0x7, 0x9, 0x11};
+static unsigned char fixed_108_bits[] = {
+0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_109_bits[] = {
+0xb, 0x15, 0x15, 0x15, 0x11};
+static unsigned char fixed_110_bits[] = {
+0xd, 0x13, 0x11, 0x11, 0x11};
+static unsigned char fixed_111_bits[] = {
+0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_112_bits[] = {
+0xd, 0x13, 0x13, 0xd, 0x1, 0x1, 0x01};
+static unsigned char fixed_113_bits[] = {
+0x16, 0x19, 0x19, 0x16, 0x10, 0x10, 0x10};
+static unsigned char fixed_114_bits[] = {
+0xd, 0x13, 0x1, 0x1, 0x01};
+static unsigned char fixed_115_bits[] = {
+0xe, 0x1, 0xe, 0x10, 0x0f};
+static unsigned char fixed_116_bits[] = {
+0x2, 0x2, 0xf, 0x2, 0x2, 0x12, 0x0c};
+static unsigned char fixed_117_bits[] = {
+0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_118_bits[] = {
+0x11, 0x11, 0xa, 0xa, 0x04};
+static unsigned char fixed_119_bits[] = {
+0x11, 0x11, 0x15, 0x15, 0x0a};
+static unsigned char fixed_120_bits[] = {
+0x11, 0xa, 0x4, 0xa, 0x11};
+static unsigned char fixed_121_bits[] = {
+0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static unsigned char fixed_122_bits[] = {
+0x1f, 0x8, 0x4, 0x2, 0x1f};
+static unsigned char fixed_123_bits[] = {
+0xc, 0x2, 0x4, 0x3, 0x4, 0x2, 0x0c};
+static unsigned char fixed_124_bits[] = {
+0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_125_bits[] = {
+0x3, 0x4, 0x2, 0xc, 0x2, 0x4, 0x03};
+static unsigned char fixed_126_bits[] = {
+0x12, 0x15, 0x09};
+static unsigned char fixed_127_bits[] = {};
+static unsigned char fixed_128_bits[] = {
+0x00};
+static unsigned char fixed_129_bits[] = {
+0x00};
+static unsigned char fixed_130_bits[] = {
+0x00};
+static unsigned char fixed_131_bits[] = {
+0x00};
+static unsigned char fixed_132_bits[] = {
+0x00};
+static unsigned char fixed_133_bits[] = {
+0x00};
+static unsigned char fixed_134_bits[] = {
+0x00};
+static unsigned char fixed_135_bits[] = {
+0x00};
+static unsigned char fixed_136_bits[] = {
+0x00};
+static unsigned char fixed_137_bits[] = {
+0x00};
+static unsigned char fixed_138_bits[] = {
+0x00};
+static unsigned char fixed_139_bits[] = {
+0x00};
+static unsigned char fixed_140_bits[] = {
+0x00};
+static unsigned char fixed_141_bits[] = {
+0x00};
+static unsigned char fixed_142_bits[] = {
+0x00};
+static unsigned char fixed_143_bits[] = {
+0x00};
+static unsigned char fixed_144_bits[] = {
+0x00};
+static unsigned char fixed_145_bits[] = {
+0x00};
+static unsigned char fixed_146_bits[] = {
+0x00};
+static unsigned char fixed_147_bits[] = {
+0x00};
+static unsigned char fixed_148_bits[] = {
+0x00};
+static unsigned char fixed_149_bits[] = {
+0x00};
+static unsigned char fixed_150_bits[] = {
+0x00};
+static unsigned char fixed_151_bits[] = {
+0x00};
+static unsigned char fixed_152_bits[] = {
+0x00};
+static unsigned char fixed_153_bits[] = {
+0x00};
+static unsigned char fixed_154_bits[] = {
+0x00};
+static unsigned char fixed_155_bits[] = {
+0x00};
+static unsigned char fixed_156_bits[] = {
+0x00};
+static unsigned char fixed_157_bits[] = {
+0x00};
+static unsigned char fixed_158_bits[] = {
+0x00};
+static unsigned char fixed_159_bits[] = {
+0x00};
+static unsigned char fixed_160_bits[] = {};
+static unsigned char fixed_161_bits[] = {
+0x1, 0x0, 0x1, 0x1, 0x1, 0x1, 0x01};
+static unsigned char fixed_162_bits[] = {
+0x4, 0x1e, 0x5, 0x5, 0x5, 0x1e, 0x04};
+static unsigned char fixed_163_bits[] = {
+0xc, 0x12, 0x2, 0x7, 0x2, 0x12, 0x0d};
+static unsigned char fixed_164_bits[] = {
+0x11, 0xe, 0xa, 0xe, 0x11};
+static unsigned char fixed_165_bits[] = {
+0x11, 0x11, 0xa, 0x4, 0x1f, 0x4, 0x4, 0x04};
+static unsigned char fixed_166_bits[] = {
+0x1, 0x1, 0x1, 0x0, 0x1, 0x1, 0x01};
+static unsigned char fixed_167_bits[] = {
+0xe, 0x1, 0x7, 0x9, 0x12, 0x1c, 0x10, 0x0e};
+static unsigned char fixed_168_bits[] = {
+0x05};
+static unsigned char fixed_169_bits[] = {
+0xe, 0x11, 0x15, 0x13, 0x15, 0x11, 0x0e};
+static unsigned char fixed_170_bits[] = {
+0xe, 0x9, 0xd, 0xa, 0x0, 0x0f};
+static unsigned char fixed_171_bits[] = {
+0x24, 0x12, 0x9, 0x12, 0x24};
+static unsigned char fixed_172_bits[] = {
+0xf, 0x08};
+static unsigned char fixed_173_bits[] = {
+0x1f};
+static unsigned char fixed_174_bits[] = {
+0xe, 0x11, 0x17, 0x13, 0x13, 0x11, 0x0e};
+static unsigned char fixed_175_bits[] = {
+0x1f};
+static unsigned char fixed_176_bits[] = {
+0x2, 0x5, 0x02};
+static unsigned char fixed_177_bits[] = {
+0x4, 0x4, 0x1f, 0x4, 0x4, 0x1f};
+static unsigned char fixed_178_bits[] = {
+0x6, 0x9, 0x4, 0x2, 0x0f};
+static unsigned char fixed_179_bits[] = {
+0x7, 0x8, 0x6, 0x8, 0x07};
+static unsigned char fixed_180_bits[] = {
+0x6, 0x03};
+static unsigned char fixed_181_bits[] = {
+0x11, 0x11, 0x11, 0x13, 0xd, 0x01};
+static unsigned char fixed_182_bits[] = {
+0x1e, 0x17, 0x17, 0x16, 0x14, 0x14, 0x14};
+static unsigned char fixed_183_bits[] = {
+0x01};
+static unsigned char fixed_184_bits[] = {
+0x2, 0x01};
+static unsigned char fixed_185_bits[] = {
+0x2, 0x3, 0x2, 0x2, 0x07};
+static unsigned char fixed_186_bits[] = {
+0x6, 0x9, 0x9, 0x6, 0x0, 0x0f};
+static unsigned char fixed_187_bits[] = {
+0x9, 0x12, 0x24, 0x12, 0x09};
+static unsigned char fixed_188_bits[] = {
+0x2, 0x3, 0x2, 0x2, 0x27, 0x30, 0x28, 0x3c, 0x20};
+static unsigned char fixed_189_bits[] = {
+0x2, 0x3, 0x2, 0x2, 0x17, 0x28, 0x20, 0x10, 0x38};
+static unsigned char fixed_190_bits[] = {
+0x3, 0x4, 0x2, 0x4, 0x13, 0x18, 0x14, 0x1e, 0x10};
+static unsigned char fixed_191_bits[] = {
+0x4, 0x0, 0x4, 0x4, 0x2, 0x11, 0x0e};
+static unsigned char fixed_192_bits[] = {
+0x2, 0x4, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_193_bits[] = {
+0x8, 0x4, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_194_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_195_bits[] = {
+0x12, 0xd, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_196_bits[] = {
+0xa, 0x0, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_197_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x11, 0x1f, 0x11, 0x11};
+static unsigned char fixed_198_bits[] = {
+0x3c, 0xa, 0x9, 0x39, 0xf, 0x9, 0x39};
+static unsigned char fixed_199_bits[] = {
+0xe, 0x11, 0x1, 0x1, 0x1, 0x11, 0xe, 0x4, 0x02};
+static unsigned char fixed_200_bits[] = {
+0x2, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_201_bits[] = {
+0x8, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_202_bits[] = {
+0x4, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_203_bits[] = {
+0xa, 0x1f, 0x1, 0x1, 0xf, 0x1, 0x1, 0x1f};
+static unsigned char fixed_204_bits[] = {
+0x1, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_205_bits[] = {
+0x4, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_206_bits[] = {
+0x2, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_207_bits[] = {
+0x5, 0x7, 0x2, 0x2, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_208_bits[] = {
+0xf, 0x12, 0x12, 0x17, 0x12, 0x12, 0x0f};
+static unsigned char fixed_209_bits[] = {
+0xc, 0x11, 0x11, 0x13, 0x15, 0x19, 0x11, 0x11};
+static unsigned char fixed_210_bits[] = {
+0x2, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_211_bits[] = {
+0x8, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_212_bits[] = {
+0x4, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_213_bits[] = {
+0xe, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_214_bits[] = {
+0xa, 0xe, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_215_bits[] = {
+0x11, 0xa, 0x4, 0xa, 0x11};
+static unsigned char fixed_216_bits[] = {
+0xe, 0x19, 0x19, 0x15, 0x13, 0x13, 0x0e};
+static unsigned char fixed_217_bits[] = {
+0x2, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_218_bits[] = {
+0x8, 0x15, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_219_bits[] = {
+0x4, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_220_bits[] = {
+0xa, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_221_bits[] = {
+0x8, 0x15, 0x11, 0xa, 0x4, 0x4, 0x4, 0x04};
+static unsigned char fixed_222_bits[] = {
+0x1, 0xf, 0x11, 0xf, 0x1, 0x1, 0x01};
+static unsigned char fixed_223_bits[] = {
+0xe, 0x11, 0x11, 0xf, 0x11, 0x11, 0xf, 0x01};
+static unsigned char fixed_224_bits[] = {
+0x2, 0x4, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_225_bits[] = {
+0x8, 0x4, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_226_bits[] = {
+0x4, 0xa, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_227_bits[] = {
+0x14, 0xa, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_228_bits[] = {
+0xa, 0x0, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_229_bits[] = {
+0x4, 0xa, 0x4, 0xe, 0x10, 0x1e, 0x11, 0x1e};
+static unsigned char fixed_230_bits[] = {
+0x1e, 0x28, 0x3e, 0x9, 0x3e};
+static unsigned char fixed_231_bits[] = {
+0xe, 0x11, 0x1, 0x11, 0xe, 0x4, 0x02};
+static unsigned char fixed_232_bits[] = {
+0x2, 0x4, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_233_bits[] = {
+0x8, 0x4, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_234_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_235_bits[] = {
+0xa, 0x0, 0xe, 0x11, 0x1f, 0x1, 0x0e};
+static unsigned char fixed_236_bits[] = {
+0x1, 0x2, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_237_bits[] = {
+0x2, 0x1, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_238_bits[] = {
+0x2, 0x5, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_239_bits[] = {
+0x5, 0x0, 0x3, 0x2, 0x2, 0x2, 0x07};
+static unsigned char fixed_240_bits[] = {
+0x3, 0xc, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_241_bits[] = {
+0x14, 0xa, 0xd, 0x13, 0x11, 0x11, 0x11};
+static unsigned char fixed_242_bits[] = {
+0x2, 0x4, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_243_bits[] = {
+0x8, 0x4, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_244_bits[] = {
+0x4, 0xa, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_245_bits[] = {
+0x14, 0xa, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_246_bits[] = {
+0xa, 0x0, 0xe, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char fixed_247_bits[] = {
+0x4, 0x0, 0x1f, 0x0, 0x04};
+static unsigned char fixed_248_bits[] = {
+0x1e, 0x19, 0x15, 0x13, 0x0f};
+static unsigned char fixed_249_bits[] = {
+0x2, 0x4, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_250_bits[] = {
+0x8, 0x4, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_251_bits[] = {
+0x4, 0xa, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_252_bits[] = {
+0xa, 0x0, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char fixed_253_bits[] = {
+0x8, 0x4, 0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static unsigned char fixed_254_bits[] = {
+0x1, 0xf, 0x11, 0x11, 0x11, 0xf, 0x1, 0x01};
+static unsigned char fixed_255_bits[] = {
+0xa, 0x0, 0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static RotFont fixedfont[] = {
+{0, 0, 0, fixed_0_bits},
+{5, 7, 7, fixed_1_bits},
+{5, 7, 7, fixed_2_bits},
+{5, 9, 7, fixed_3_bits},
+{5, 9, 7, fixed_4_bits},
+{5, 9, 7, fixed_5_bits},
+{5, 9, 7, fixed_6_bits},
+{3, 3, 7, fixed_7_bits},
+{5, 6, 6, fixed_8_bits},
+{5, 9, 7, fixed_9_bits},
+{5, 9, 7, fixed_10_bits},
+{4, 5, 8, fixed_11_bits},
+{4, 6, 4, fixed_12_bits},
+{3, 6, 4, fixed_13_bits},
+{3, 5, 8, fixed_14_bits},
+{6, 10, 8, fixed_15_bits},
+{6, 1, 8, fixed_16_bits},
+{6, 1, 6, fixed_17_bits},
+{6, 1, 4, fixed_18_bits},
+{6, 1, 2, fixed_19_bits},
+{6, 1, 0, fixed_20_bits},
+{3, 10, 8, fixed_21_bits},
+{4, 10, 8, fixed_22_bits},
+{6, 5, 8, fixed_23_bits},
+{6, 6, 4, fixed_24_bits},
+{1, 10, 8, fixed_25_bits},
+{5, 8, 7, fixed_26_bits},
+{5, 8, 7, fixed_27_bits},
+{5, 5, 5, fixed_28_bits},
+{5, 7, 7, fixed_29_bits},
+{5, 7, 7, fixed_30_bits},
+{1, 1, 4, fixed_31_bits},
+{0, 0, 0, fixed_32_bits},
+{1, 7, 7, fixed_33_bits},
+{3, 3, 7, fixed_34_bits},
+{5, 7, 7, fixed_35_bits},
+{5, 7, 7, fixed_36_bits},
+{5, 7, 7, fixed_37_bits},
+{5, 7, 7, fixed_38_bits},
+{3, 3, 7, fixed_39_bits},
+{3, 7, 7, fixed_40_bits},
+{3, 7, 7, fixed_41_bits},
+{5, 5, 6, fixed_42_bits},
+{5, 5, 6, fixed_43_bits},
+{3, 3, 2, fixed_44_bits},
+{5, 1, 4, fixed_45_bits},
+{3, 3, 2, fixed_46_bits},
+{5, 7, 7, fixed_47_bits},
+{5, 7, 7, fixed_48_bits},
+{5, 7, 7, fixed_49_bits},
+{5, 7, 7, fixed_50_bits},
+{5, 7, 7, fixed_51_bits},
+{5, 7, 7, fixed_52_bits},
+{5, 7, 7, fixed_53_bits},
+{5, 7, 7, fixed_54_bits},
+{5, 7, 7, fixed_55_bits},
+{5, 7, 7, fixed_56_bits},
+{5, 7, 7, fixed_57_bits},
+{3, 7, 6, fixed_58_bits},
+{3, 7, 6, fixed_59_bits},
+{4, 7, 7, fixed_60_bits},
+{5, 3, 5, fixed_61_bits},
+{4, 7, 7, fixed_62_bits},
+{5, 7, 7, fixed_63_bits},
+{5, 7, 7, fixed_64_bits},
+{5, 7, 7, fixed_65_bits},
+{5, 7, 7, fixed_66_bits},
+{5, 7, 7, fixed_67_bits},
+{5, 7, 7, fixed_68_bits},
+{5, 7, 7, fixed_69_bits},
+{5, 7, 7, fixed_70_bits},
+{5, 7, 7, fixed_71_bits},
+{5, 7, 7, fixed_72_bits},
+{3, 7, 7, fixed_73_bits},
+{5, 7, 7, fixed_74_bits},
+{5, 7, 7, fixed_75_bits},
+{5, 7, 7, fixed_76_bits},
+{5, 7, 7, fixed_77_bits},
+{5, 7, 7, fixed_78_bits},
+{5, 7, 7, fixed_79_bits},
+{5, 7, 7, fixed_80_bits},
+{5, 8, 7, fixed_81_bits},
+{5, 7, 7, fixed_82_bits},
+{5, 7, 7, fixed_83_bits},
+{5, 7, 7, fixed_84_bits},
+{5, 7, 7, fixed_85_bits},
+{5, 7, 7, fixed_86_bits},
+{5, 7, 7, fixed_87_bits},
+{5, 7, 7, fixed_88_bits},
+{5, 7, 7, fixed_89_bits},
+{5, 7, 7, fixed_90_bits},
+{3, 7, 7, fixed_91_bits},
+{5, 7, 7, fixed_92_bits},
+{3, 7, 7, fixed_93_bits},
+{5, 3, 7, fixed_94_bits},
+{5, 1, 0, fixed_95_bits},
+{3, 3, 7, fixed_96_bits},
+{5, 5, 5, fixed_97_bits},
+{5, 7, 7, fixed_98_bits},
+{5, 5, 5, fixed_99_bits},
+{5, 7, 7, fixed_100_bits},
+{5, 5, 5, fixed_101_bits},
+{5, 7, 7, fixed_102_bits},
+{5, 7, 5, fixed_103_bits},
+{5, 7, 7, fixed_104_bits},
+{3, 7, 7, fixed_105_bits},
+{4, 9, 7, fixed_106_bits},
+{5, 7, 7, fixed_107_bits},
+{3, 7, 7, fixed_108_bits},
+{5, 5, 5, fixed_109_bits},
+{5, 5, 5, fixed_110_bits},
+{5, 5, 5, fixed_111_bits},
+{5, 7, 5, fixed_112_bits},
+{5, 7, 5, fixed_113_bits},
+{5, 5, 5, fixed_114_bits},
+{5, 5, 5, fixed_115_bits},
+{5, 7, 7, fixed_116_bits},
+{5, 5, 5, fixed_117_bits},
+{5, 5, 5, fixed_118_bits},
+{5, 5, 5, fixed_119_bits},
+{5, 5, 5, fixed_120_bits},
+{5, 7, 5, fixed_121_bits},
+{5, 5, 5, fixed_122_bits},
+{4, 7, 7, fixed_123_bits},
+{1, 7, 7, fixed_124_bits},
+{4, 7, 7, fixed_125_bits},
+{5, 3, 7, fixed_126_bits},
+{0, 0, 0, fixed_127_bits},
+{5, 1, 1, fixed_128_bits},
+{5, 1, 1, fixed_129_bits},
+{5, 1, 1, fixed_130_bits},
+{5, 1, 1, fixed_131_bits},
+{5, 1, 1, fixed_132_bits},
+{5, 1, 1, fixed_133_bits},
+{5, 1, 1, fixed_134_bits},
+{5, 1, 1, fixed_135_bits},
+{5, 1, 1, fixed_136_bits},
+{5, 1, 1, fixed_137_bits},
+{5, 1, 1, fixed_138_bits},
+{5, 1, 1, fixed_139_bits},
+{5, 1, 1, fixed_140_bits},
+{5, 1, 1, fixed_141_bits},
+{5, 1, 1, fixed_142_bits},
+{5, 1, 1, fixed_143_bits},
+{5, 1, 1, fixed_144_bits},
+{5, 1, 1, fixed_145_bits},
+{5, 1, 1, fixed_146_bits},
+{5, 1, 1, fixed_147_bits},
+{5, 1, 1, fixed_148_bits},
+{5, 1, 1, fixed_149_bits},
+{5, 1, 1, fixed_150_bits},
+{5, 1, 1, fixed_151_bits},
+{5, 1, 1, fixed_152_bits},
+{5, 1, 1, fixed_153_bits},
+{5, 1, 1, fixed_154_bits},
+{5, 1, 1, fixed_155_bits},
+{5, 1, 1, fixed_156_bits},
+{5, 1, 1, fixed_157_bits},
+{5, 1, 1, fixed_158_bits},
+{5, 1, 1, fixed_159_bits},
+{0, 0, 0, fixed_160_bits},
+{1, 7, 7, fixed_161_bits},
+{5, 7, 6, fixed_162_bits},
+{5, 7, 7, fixed_163_bits},
+{5, 5, 5, fixed_164_bits},
+{5, 8, 7, fixed_165_bits},
+{1, 7, 7, fixed_166_bits},
+{5, 8, 7, fixed_167_bits},
+{3, 1, 8, fixed_168_bits},
+{5, 7, 7, fixed_169_bits},
+{4, 6, 7, fixed_170_bits},
+{6, 5, 5, fixed_171_bits},
+{4, 2, 4, fixed_172_bits},
+{5, 1, 4, fixed_173_bits},
+{5, 7, 7, fixed_174_bits},
+{5, 1, 8, fixed_175_bits},
+{3, 3, 7, fixed_176_bits},
+{5, 6, 6, fixed_177_bits},
+{4, 5, 8, fixed_178_bits},
+{4, 5, 8, fixed_179_bits},
+{3, 2, 8, fixed_180_bits},
+{5, 6, 5, fixed_181_bits},
+{5, 7, 7, fixed_182_bits},
+{1, 1, 4, fixed_183_bits},
+{2, 2, 0, fixed_184_bits},
+{3, 5, 8, fixed_185_bits},
+{4, 6, 7, fixed_186_bits},
+{6, 5, 5, fixed_187_bits},
+{6, 9, 8, fixed_188_bits},
+{6, 9, 8, fixed_189_bits},
+{5, 9, 8, fixed_190_bits},
+{5, 7, 7, fixed_191_bits},
+{5, 8, 8, fixed_192_bits},
+{5, 8, 8, fixed_193_bits},
+{5, 8, 8, fixed_194_bits},
+{5, 8, 8, fixed_195_bits},
+{5, 8, 8, fixed_196_bits},
+{5, 8, 8, fixed_197_bits},
+{6, 7, 7, fixed_198_bits},
+{5, 9, 7, fixed_199_bits},
+{5, 8, 8, fixed_200_bits},
+{5, 8, 8, fixed_201_bits},
+{5, 8, 8, fixed_202_bits},
+{5, 8, 8, fixed_203_bits},
+{3, 8, 8, fixed_204_bits},
+{3, 8, 8, fixed_205_bits},
+{3, 8, 8, fixed_206_bits},
+{3, 8, 8, fixed_207_bits},
+{5, 7, 7, fixed_208_bits},
+{5, 8, 8, fixed_209_bits},
+{5, 8, 8, fixed_210_bits},
+{5, 8, 8, fixed_211_bits},
+{5, 8, 8, fixed_212_bits},
+{5, 8, 8, fixed_213_bits},
+{5, 8, 8, fixed_214_bits},
+{5, 5, 5, fixed_215_bits},
+{5, 7, 7, fixed_216_bits},
+{5, 8, 8, fixed_217_bits},
+{5, 8, 8, fixed_218_bits},
+{5, 8, 8, fixed_219_bits},
+{5, 8, 8, fixed_220_bits},
+{5, 8, 8, fixed_221_bits},
+{5, 7, 7, fixed_222_bits},
+{5, 8, 7, fixed_223_bits},
+{5, 7, 7, fixed_224_bits},
+{5, 7, 7, fixed_225_bits},
+{5, 7, 7, fixed_226_bits},
+{5, 7, 7, fixed_227_bits},
+{5, 7, 7, fixed_228_bits},
+{5, 8, 8, fixed_229_bits},
+{6, 5, 5, fixed_230_bits},
+{5, 7, 5, fixed_231_bits},
+{5, 7, 7, fixed_232_bits},
+{5, 7, 7, fixed_233_bits},
+{5, 7, 7, fixed_234_bits},
+{5, 7, 7, fixed_235_bits},
+{3, 8, 8, fixed_236_bits},
+{3, 8, 8, fixed_237_bits},
+{3, 8, 8, fixed_238_bits},
+{3, 7, 7, fixed_239_bits},
+{5, 7, 7, fixed_240_bits},
+{5, 7, 7, fixed_241_bits},
+{5, 7, 7, fixed_242_bits},
+{5, 7, 7, fixed_243_bits},
+{5, 7, 7, fixed_244_bits},
+{5, 7, 7, fixed_245_bits},
+{5, 7, 7, fixed_246_bits},
+{5, 5, 6, fixed_247_bits},
+{5, 5, 5, fixed_248_bits},
+{5, 7, 7, fixed_249_bits},
+{5, 7, 7, fixed_250_bits},
+{5, 7, 7, fixed_251_bits},
+{5, 7, 7, fixed_252_bits},
+{5, 9, 7, fixed_253_bits},
+{5, 8, 6, fixed_254_bits},
+{5, 9, 7, fixed_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/fixfont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/fixfont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/fixfont.c	(revision 16632)
@@ -0,0 +1,180 @@
+# include <stdio.h>
+# include <math.h>
+# define TRUE 1
+# define FALSE 0
+
+# 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); \
+    }
+
+#define blank_width 5
+#define blank_height 1
+static unsigned char blank_bits[] = {0x00};
+
+typedef struct {
+  int dx, dy, ascent, Nb;
+  unsigned char *bits;
+  char name[64];
+} RotFont;
+
+char flip_bits (char a);
+int scan_line (FILE *f, char *line);
+
+main (int argc, char **argv) {
+
+  int BitMap, Nvalue, code;
+  unsigned int bits;
+  int i, j, dx, dy, ddx, ddy;
+  char buffer[1000], name[1000], glyph[1000];
+  unsigned char value[1000], bitchar[3];
+  RotFont font[256];
+  
+  FILE *f;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: fixfont (file.bdf) (name)\n");
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open file %s\n", argv[1]);
+    exit (0);
+  }
+
+  for (i = 0; i < 256; i++) {
+    font[i].bits = 0;
+  }
+
+  BitMap = FALSE;
+  Nvalue = 0;
+  while (scan_line (f, buffer) != EOF) {
+    sscanf (buffer, "%s", name);
+    if (!strcmp (name, "ENDCHAR")) {
+      BitMap = FALSE;
+      if ((code >= 0) && (code < 256)) {
+	font[code].dx = dx;
+	font[code].dy = dy;
+	font[code].ascent = dy + ddy;
+	font[code].Nb = Nvalue;
+	ALLOCATE (font[code].bits, unsigned char, Nvalue);
+	strcpy (font[code].name, glyph);
+	for (i = 0; i < Nvalue; i++) { 
+	  font[code].bits[i] = value[i];
+	}
+      }
+      fprintf (stderr, "found %s\n", glyph);
+    }
+    if (BitMap) {
+      bitchar[2] = 0;
+      for (j = 0; buffer[j] != 0; j+=2) {
+	bitchar[0] = buffer[j];
+	bitchar[1] = buffer[j+1];
+	sscanf (bitchar, "%x", &bits);
+	value[Nvalue] = flip_bits (bits);
+	Nvalue ++;
+      }
+      continue;
+    } 
+    if (!strcmp (name, "STARTCHAR")) {
+      sscanf (buffer, "%*s %s", glyph);
+    }
+    if (!strcmp (name, "ENCODING")) {
+      sscanf (buffer, "%*s %d", &code);
+    }
+    if (!strcmp (name, "BBX")) {
+      sscanf (buffer, "%*s %d %d %d %d", &dx, &dy, &ddx, &ddy);
+    }
+    if (!strcmp (name, "BITMAP")) {
+      BitMap = TRUE;
+      Nvalue = 0;
+    }
+  }    
+
+  for (i = 0; i < 256; i++) {
+    if (font[i].bits  == 0) {
+      font[i].bits = blank_bits;
+      font[i].dx = blank_width;
+      font[i].dy = blank_height;
+      font[i].Nb = 1;
+      font[i].ascent = blank_height;
+      strcpy (font[i].name, "blank");
+    }
+    fprintf (stdout, "static unsigned char %s_%d_bits[] = {", argv[2], i);
+    for (j = 0; j < font[i].Nb; j++) {
+      if (!(j % 12)) fprintf (stdout, "\n");
+      if (j == font[i].Nb - 1) fprintf (stdout, "0x%02x", font[i].bits[j]);
+      else fprintf (stdout, "0x%02x, ", font[i].bits[j]);
+    }
+    fprintf (stdout, "};\n");
+  }
+  
+  fprintf (stdout, "static RotFont %sfont[] = {\n", argv[2]);
+  for (i = 0; i < 255; i++) {
+    fprintf (stdout, "{%d, %d, %d, %s_%d_bits},\n", 
+	     font[i].dx, font[i].dy, font[i].ascent, argv[2], i);
+  }
+  fprintf (stdout, "{%d, %d, %d, %s_%d_bits}};\n", 
+	   font[i].dx, font[i].dy, font[i].ascent, argv[2], i);
+
+      
+}
+
+int scan_line (FILE *f, char *line) {
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
+char flip_bits (char a) {
+
+  char b, c;
+  
+  c = 0;
+  b = (a & 0x01) << 7;
+  c = c | b;
+  b = (a & 0x02) << 5;
+  c = c | b;
+  b = (a & 0x04) << 3;
+  c = c | b;
+  b = (a & 0x08) << 1;
+  c = c | b;
+  b = (a & 0x10) >> 1;
+  c = c | b;
+  b = (a & 0x20) >> 3;
+  c = c | b;
+  b = (a & 0x40) >> 5;
+  c = c | b;
+  b = (a & 0x80) >> 7;
+  c = c | b;
+
+  return (c);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica12.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica12.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica12.bdf	(revision 16632)
@@ -0,0 +1,3020 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 11 15 0 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 67
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 7
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--12-120-75-75-P-67-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 7
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+28
+28
+fc
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -1
+BITMAP
+20
+70
+a8
+a0
+70
+28
+a8
+a8
+70
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+6200
+9400
+9400
+6800
+0800
+1300
+1480
+1480
+2300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+30
+48
+48
+30
+50
+8a
+84
+8c
+72
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 1 6
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+a0
+40
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 3 1 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 5 1 1 3
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+10
+10
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 3 9 1 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+10
+20
+40
+80
+80
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+08
+30
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+08
+18
+28
+28
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+f8
+80
+80
+f0
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+80
+b0
+c8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+f8
+08
+10
+10
+20
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+78
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 6 1 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+f8
+00
+f8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+10
+10
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 10 10 1 -1
+BITMAP
+1f00
+6080
+4d40
+9240
+a240
+a240
+a680
+9b00
+4000
+3e00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+10
+28
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f8
+84
+84
+84
+f8
+84
+84
+84
+f8
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3c
+42
+80
+80
+80
+80
+80
+42
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+f8
+84
+82
+82
+82
+82
+82
+84
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+fc
+80
+80
+80
+f8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+3c
+42
+80
+80
+8e
+82
+82
+46
+3a
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+82
+82
+fe
+82
+82
+82
+82
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+08
+08
+08
+08
+88
+88
+70
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 1 0
+BITMAP
+84
+88
+90
+a0
+e0
+90
+88
+84
+82
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+f8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8080
+c180
+c180
+a280
+a280
+9480
+9480
+8880
+8880
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+c2
+a2
+a2
+92
+8a
+8a
+86
+82
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f8
+84
+84
+84
+f8
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3c
+42
+81
+81
+81
+89
+85
+42
+3d
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f8
+84
+84
+84
+f8
+88
+84
+84
+84
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+84
+80
+60
+18
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fe
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+44
+28
+28
+10
+10
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+8880
+8880
+8880
+4900
+5500
+5500
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+44
+44
+28
+10
+28
+44
+44
+82
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+fe
+02
+04
+08
+10
+20
+40
+80
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 1 -3
+BITMAP
+c0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 9 0 0
+BITMAP
+80
+80
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 3 0 5
+BITMAP
+20
+50
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 1 0 -2
+BITMAP
+fe
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 0 6
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+b0
+c8
+88
+88
+88
+c8
+b0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+08
+08
+68
+98
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 4 9 0 0
+BITMAP
+30
+40
+e0
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+88
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+b0
+c8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+80
+80
+90
+a0
+c0
+c0
+a0
+90
+88
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 7 1 0
+BITMAP
+a4
+da
+92
+92
+92
+92
+92
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+b0
+c8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+b0
+c8
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+68
+98
+88
+88
+88
+98
+68
+08
+08
+08
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+a0
+c0
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+60
+90
+80
+60
+10
+90
+60
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+40
+e0
+40
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+88
+88
+88
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 7 0 0
+BITMAP
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+84
+48
+30
+30
+48
+84
+84
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+f0
+10
+20
+40
+40
+80
+f0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+30
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 12 0 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 2 0 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 10 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -1
+BITMAP
+10
+70
+a8
+a0
+a0
+a0
+c8
+70
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+30
+48
+40
+40
+f0
+20
+20
+48
+b0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 6 0 1
+BITMAP
+84
+78
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+88
+88
+50
+20
+f8
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 11 1 -2
+BITMAP
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+70
+88
+80
+60
+90
+88
+88
+48
+30
+08
+88
+70
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 1 0 8
+BITMAP
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3e00
+4100
+9c80
+a280
+a080
+a280
+9c80
+4100
+3e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+e0
+20
+a0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+28
+50
+a0
+50
+28
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 4 1 2
+BITMAP
+fc
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 1 0 3
+BITMAP
+f0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+3e00
+4100
+9c80
+9480
+9880
+9480
+9480
+4100
+3e00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 4
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+f8
+20
+20
+00
+f8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 5 0 3
+BITMAP
+60
+90
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 5 0 3
+BITMAP
+e0
+20
+40
+20
+c0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 160 0
+DWIDTH 2 0
+BBX 2 2 0 8
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+88
+88
+88
+88
+88
+98
+e8
+80
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+3c
+68
+e8
+e8
+e8
+68
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 4 0 -3
+BITMAP
+40
+20
+20
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 5 1 3
+BITMAP
+40
+c0
+40
+40
+40
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 5 1 4
+BITMAP
+e0
+a0
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+a0
+50
+28
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+c200
+4400
+4400
+4900
+1300
+1500
+2780
+4100
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4100
+c200
+4400
+4800
+4b00
+1480
+1100
+2200
+4780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+e100
+2200
+4400
+2400
+c900
+0b00
+1500
+1780
+2100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+20
+00
+20
+20
+40
+40
+88
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+20
+10
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+28
+00
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+10
+28
+10
+10
+10
+28
+44
+44
+7c
+82
+82
+82
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+1f80
+2800
+2800
+4800
+4f80
+7800
+8800
+8800
+8f80
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 -3
+BITMAP
+3c
+42
+80
+80
+80
+80
+80
+42
+3c
+08
+08
+30
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+28
+00
+fc
+80
+80
+80
+fc
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 12 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+7c
+42
+41
+41
+f1
+41
+41
+42
+7c
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+14
+28
+00
+82
+c2
+a2
+a2
+92
+8a
+8a
+86
+82
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+10
+08
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+04
+08
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+08
+14
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+14
+28
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+24
+00
+3c
+42
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 10 11 0 -1
+BITMAP
+0040
+1e80
+2100
+4280
+4480
+4480
+4880
+5080
+2100
+5e00
+8000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+20
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+08
+10
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 12 1 0
+BITMAP
+10
+28
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+00
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+08
+10
+00
+82
+82
+44
+44
+28
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+80
+80
+f8
+84
+84
+84
+f8
+80
+80
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+b0
+88
+88
+88
+b0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+10
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 1 0
+BITMAP
+50
+00
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+30
+48
+30
+70
+88
+08
+78
+88
+88
+74
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+7700
+8880
+0880
+7f80
+8800
+8880
+7700
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 -3
+BITMAP
+70
+88
+80
+80
+80
+88
+70
+20
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+f8
+80
+88
+70
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 10 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 10 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+68
+30
+50
+08
+78
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+b0
+c8
+88
+88
+88
+88
+88
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+00
+f8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+3a
+44
+4c
+54
+64
+44
+b8
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+50
+00
+88
+88
+88
+88
+88
+98
+68
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+10
+20
+00
+88
+88
+88
+90
+50
+50
+20
+20
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+80
+80
+b0
+c8
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 12 1 -3
+BITMAP
+50
+00
+88
+88
+48
+50
+50
+30
+20
+20
+20
+c0
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica12.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica12.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica12.h	(revision 16632)
@@ -0,0 +1,783 @@
+static unsigned char helvetica12_0_bits[] = {
+0x00};
+static unsigned char helvetica12_1_bits[] = {
+0x00};
+static unsigned char helvetica12_2_bits[] = {
+0x00};
+static unsigned char helvetica12_3_bits[] = {
+0x00};
+static unsigned char helvetica12_4_bits[] = {
+0x00};
+static unsigned char helvetica12_5_bits[] = {
+0x00};
+static unsigned char helvetica12_6_bits[] = {
+0x00};
+static unsigned char helvetica12_7_bits[] = {
+0x00};
+static unsigned char helvetica12_8_bits[] = {
+0x00};
+static unsigned char helvetica12_9_bits[] = {
+0x00};
+static unsigned char helvetica12_10_bits[] = {
+0x00};
+static unsigned char helvetica12_11_bits[] = {
+0x00};
+static unsigned char helvetica12_12_bits[] = {
+0x00};
+static unsigned char helvetica12_13_bits[] = {
+0x00};
+static unsigned char helvetica12_14_bits[] = {
+0x00};
+static unsigned char helvetica12_15_bits[] = {
+0x00};
+static unsigned char helvetica12_16_bits[] = {
+0x00};
+static unsigned char helvetica12_17_bits[] = {
+0x00};
+static unsigned char helvetica12_18_bits[] = {
+0x00};
+static unsigned char helvetica12_19_bits[] = {
+0x00};
+static unsigned char helvetica12_20_bits[] = {
+0x00};
+static unsigned char helvetica12_21_bits[] = {
+0x00};
+static unsigned char helvetica12_22_bits[] = {
+0x00};
+static unsigned char helvetica12_23_bits[] = {
+0x00};
+static unsigned char helvetica12_24_bits[] = {
+0x00};
+static unsigned char helvetica12_25_bits[] = {
+0x00};
+static unsigned char helvetica12_26_bits[] = {
+0x00};
+static unsigned char helvetica12_27_bits[] = {
+0x00};
+static unsigned char helvetica12_28_bits[] = {
+0x00};
+static unsigned char helvetica12_29_bits[] = {
+0x00};
+static unsigned char helvetica12_30_bits[] = {
+0x00};
+static unsigned char helvetica12_31_bits[] = {
+0x00};
+static unsigned char helvetica12_32_bits[] = {
+0x00};
+static unsigned char helvetica12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char helvetica12_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char helvetica12_35_bits[] = {
+0x14, 0x14, 0x3f, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char helvetica12_36_bits[] = {
+0x04, 0x0e, 0x15, 0x05, 0x0e, 0x14, 0x15, 0x15, 0x0e, 0x04};
+static unsigned char helvetica12_37_bits[] = {
+0x46, 0x00, 0x29, 0x00, 0x29, 0x00, 0x16, 0x00, 0x10, 0x00, 0xc8, 0x00, 
+0x28, 0x01, 0x28, 0x01, 0xc4, 0x00};
+static unsigned char helvetica12_38_bits[] = {
+0x0c, 0x12, 0x12, 0x0c, 0x0a, 0x51, 0x21, 0x31, 0x4e};
+static unsigned char helvetica12_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char helvetica12_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char helvetica12_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char helvetica12_42_bits[] = {
+0x05, 0x02, 0x05};
+static unsigned char helvetica12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char helvetica12_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char helvetica12_45_bits[] = {
+0x1f};
+static unsigned char helvetica12_46_bits[] = {
+0x01};
+static unsigned char helvetica12_47_bits[] = {
+0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char helvetica12_48_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char helvetica12_50_bits[] = {
+0x0e, 0x11, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x1f};
+static unsigned char helvetica12_51_bits[] = {
+0x0e, 0x11, 0x10, 0x0c, 0x10, 0x10, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_52_bits[] = {
+0x10, 0x18, 0x14, 0x14, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char helvetica12_53_bits[] = {
+0x1f, 0x01, 0x01, 0x0f, 0x10, 0x10, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_54_bits[] = {
+0x0e, 0x11, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_55_bits[] = {
+0x1f, 0x10, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02};
+static unsigned char helvetica12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_57_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x1e, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char helvetica12_58_bits[] = {
+0x01, 0x00, 0x00, 0x00, 0x00, 0x01};
+static unsigned char helvetica12_59_bits[] = {
+0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char helvetica12_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char helvetica12_61_bits[] = {
+0x1f, 0x00, 0x1f};
+static unsigned char helvetica12_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char helvetica12_63_bits[] = {
+0x0e, 0x11, 0x11, 0x08, 0x08, 0x04, 0x04, 0x00, 0x04};
+static unsigned char helvetica12_64_bits[] = {
+0xf8, 0x00, 0x06, 0x01, 0xb2, 0x02, 0x49, 0x02, 0x45, 0x02, 0x45, 0x02, 
+0x65, 0x01, 0xd9, 0x00, 0x02, 0x00, 0x7c, 0x00};
+static unsigned char helvetica12_65_bits[] = {
+0x08, 0x14, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_66_bits[] = {
+0x1f, 0x21, 0x21, 0x21, 0x1f, 0x21, 0x21, 0x21, 0x1f};
+static unsigned char helvetica12_67_bits[] = {
+0x3c, 0x42, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c};
+static unsigned char helvetica12_68_bits[] = {
+0x1f, 0x21, 0x41, 0x41, 0x41, 0x41, 0x41, 0x21, 0x1f};
+static unsigned char helvetica12_69_bits[] = {
+0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_70_bits[] = {
+0x3f, 0x01, 0x01, 0x01, 0x1f, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_71_bits[] = {
+0x3c, 0x42, 0x01, 0x01, 0x71, 0x41, 0x41, 0x62, 0x5c};
+static unsigned char helvetica12_72_bits[] = {
+0x41, 0x41, 0x41, 0x41, 0x7f, 0x41, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_73_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_74_bits[] = {
+0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_75_bits[] = {
+0x21, 0x11, 0x09, 0x05, 0x07, 0x09, 0x11, 0x21, 0x41};
+static unsigned char helvetica12_76_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f};
+static unsigned char helvetica12_77_bits[] = {
+0x01, 0x01, 0x83, 0x01, 0x83, 0x01, 0x45, 0x01, 0x45, 0x01, 0x29, 0x01, 
+0x29, 0x01, 0x11, 0x01, 0x11, 0x01};
+static unsigned char helvetica12_78_bits[] = {
+0x41, 0x43, 0x45, 0x45, 0x49, 0x51, 0x51, 0x61, 0x41};
+static unsigned char helvetica12_79_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_80_bits[] = {
+0x1f, 0x21, 0x21, 0x21, 0x1f, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_81_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x91, 0xa1, 0x42, 0xbc};
+static unsigned char helvetica12_82_bits[] = {
+0x1f, 0x21, 0x21, 0x21, 0x1f, 0x11, 0x21, 0x21, 0x21};
+static unsigned char helvetica12_83_bits[] = {
+0x1e, 0x21, 0x01, 0x06, 0x18, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_84_bits[] = {
+0x7f, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char helvetica12_85_bits[] = {
+0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_86_bits[] = {
+0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08};
+static unsigned char helvetica12_87_bits[] = {
+0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x92, 0x00, 0xaa, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char helvetica12_88_bits[] = {
+0x41, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x41};
+static unsigned char helvetica12_89_bits[] = {
+0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08};
+static unsigned char helvetica12_90_bits[] = {
+0x7f, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x7f};
+static unsigned char helvetica12_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char helvetica12_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08};
+static unsigned char helvetica12_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char helvetica12_94_bits[] = {
+0x04, 0x0a, 0x11};
+static unsigned char helvetica12_95_bits[] = {
+0x7f};
+static unsigned char helvetica12_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char helvetica12_97_bits[] = {
+0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_98_bits[] = {
+0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x13, 0x0d};
+static unsigned char helvetica12_99_bits[] = {
+0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_100_bits[] = {
+0x10, 0x10, 0x16, 0x19, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_101_bits[] = {
+0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_102_bits[] = {
+0x0c, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_103_bits[] = {
+0x16, 0x19, 0x11, 0x11, 0x11, 0x19, 0x16, 0x10, 0x11, 0x0e};
+static unsigned char helvetica12_104_bits[] = {
+0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11};
+static unsigned char helvetica12_105_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_106_bits[] = {
+0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica12_107_bits[] = {
+0x01, 0x01, 0x09, 0x05, 0x03, 0x03, 0x05, 0x09, 0x11};
+static unsigned char helvetica12_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_109_bits[] = {
+0x25, 0x5b, 0x49, 0x49, 0x49, 0x49, 0x49};
+static unsigned char helvetica12_110_bits[] = {
+0x0d, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11};
+static unsigned char helvetica12_111_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_112_bits[] = {
+0x0d, 0x13, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_113_bits[] = {
+0x16, 0x19, 0x11, 0x11, 0x11, 0x19, 0x16, 0x10, 0x10, 0x10};
+static unsigned char helvetica12_114_bits[] = {
+0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_115_bits[] = {
+0x06, 0x09, 0x01, 0x06, 0x08, 0x09, 0x06};
+static unsigned char helvetica12_116_bits[] = {
+0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x06};
+static unsigned char helvetica12_117_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_118_bits[] = {
+0x11, 0x11, 0x11, 0x0a, 0x0a, 0x04, 0x04};
+static unsigned char helvetica12_119_bits[] = {
+0x11, 0x01, 0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 0x44, 0x00, 
+0x44, 0x00};
+static unsigned char helvetica12_120_bits[] = {
+0x21, 0x12, 0x0c, 0x0c, 0x12, 0x21, 0x21};
+static unsigned char helvetica12_121_bits[] = {
+0x11, 0x11, 0x11, 0x09, 0x0a, 0x0a, 0x04, 0x04, 0x02, 0x01};
+static unsigned char helvetica12_122_bits[] = {
+0x0f, 0x08, 0x04, 0x02, 0x02, 0x01, 0x0f};
+static unsigned char helvetica12_123_bits[] = {
+0x0c, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char helvetica12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03};
+static unsigned char helvetica12_126_bits[] = {
+0x26, 0x19};
+static unsigned char helvetica12_127_bits[] = {
+0x00};
+static unsigned char helvetica12_128_bits[] = {
+0x00};
+static unsigned char helvetica12_129_bits[] = {
+0x00};
+static unsigned char helvetica12_130_bits[] = {
+0x00};
+static unsigned char helvetica12_131_bits[] = {
+0x00};
+static unsigned char helvetica12_132_bits[] = {
+0x00};
+static unsigned char helvetica12_133_bits[] = {
+0x00};
+static unsigned char helvetica12_134_bits[] = {
+0x00};
+static unsigned char helvetica12_135_bits[] = {
+0x00};
+static unsigned char helvetica12_136_bits[] = {
+0x00};
+static unsigned char helvetica12_137_bits[] = {
+0x00};
+static unsigned char helvetica12_138_bits[] = {
+0x00};
+static unsigned char helvetica12_139_bits[] = {
+0x00};
+static unsigned char helvetica12_140_bits[] = {
+0x00};
+static unsigned char helvetica12_141_bits[] = {
+0x00};
+static unsigned char helvetica12_142_bits[] = {
+0x00};
+static unsigned char helvetica12_143_bits[] = {
+0x00};
+static unsigned char helvetica12_144_bits[] = {
+0x00};
+static unsigned char helvetica12_145_bits[] = {
+0x00};
+static unsigned char helvetica12_146_bits[] = {
+0x00};
+static unsigned char helvetica12_147_bits[] = {
+0x00};
+static unsigned char helvetica12_148_bits[] = {
+0x00};
+static unsigned char helvetica12_149_bits[] = {
+0x00};
+static unsigned char helvetica12_150_bits[] = {
+0x00};
+static unsigned char helvetica12_151_bits[] = {
+0x00};
+static unsigned char helvetica12_152_bits[] = {
+0x00};
+static unsigned char helvetica12_153_bits[] = {
+0x00};
+static unsigned char helvetica12_154_bits[] = {
+0x00};
+static unsigned char helvetica12_155_bits[] = {
+0x00};
+static unsigned char helvetica12_156_bits[] = {
+0x00};
+static unsigned char helvetica12_157_bits[] = {
+0x00};
+static unsigned char helvetica12_158_bits[] = {
+0x00};
+static unsigned char helvetica12_159_bits[] = {
+0x00};
+static unsigned char helvetica12_160_bits[] = {
+0x00};
+static unsigned char helvetica12_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_162_bits[] = {
+0x08, 0x0e, 0x15, 0x05, 0x05, 0x05, 0x13, 0x0e, 0x02};
+static unsigned char helvetica12_163_bits[] = {
+0x0c, 0x12, 0x02, 0x02, 0x0f, 0x04, 0x04, 0x12, 0x0d};
+static unsigned char helvetica12_164_bits[] = {
+0x21, 0x1e, 0x12, 0x12, 0x1e, 0x21};
+static unsigned char helvetica12_165_bits[] = {
+0x11, 0x11, 0x0a, 0x04, 0x1f, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char helvetica12_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_167_bits[] = {
+0x0e, 0x11, 0x01, 0x06, 0x09, 0x11, 0x11, 0x12, 0x0c, 0x10, 0x11, 0x0e};
+static unsigned char helvetica12_168_bits[] = {
+0x05};
+static unsigned char helvetica12_169_bits[] = {
+0x7c, 0x00, 0x82, 0x00, 0x39, 0x01, 0x45, 0x01, 0x05, 0x01, 0x45, 0x01, 
+0x39, 0x01, 0x82, 0x00, 0x7c, 0x00};
+static unsigned char helvetica12_170_bits[] = {
+0x07, 0x04, 0x05, 0x00, 0x07};
+static unsigned char helvetica12_171_bits[] = {
+0x14, 0x0a, 0x05, 0x0a, 0x14};
+static unsigned char helvetica12_172_bits[] = {
+0x3f, 0x20, 0x20, 0x20};
+static unsigned char helvetica12_173_bits[] = {
+0x0f};
+static unsigned char helvetica12_174_bits[] = {
+0x7c, 0x00, 0x82, 0x00, 0x39, 0x01, 0x29, 0x01, 0x19, 0x01, 0x29, 0x01, 
+0x29, 0x01, 0x82, 0x00, 0x7c, 0x00};
+static unsigned char helvetica12_175_bits[] = {
+0x0f};
+static unsigned char helvetica12_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char helvetica12_177_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, 0x1f};
+static unsigned char helvetica12_178_bits[] = {
+0x06, 0x09, 0x04, 0x02, 0x0f};
+static unsigned char helvetica12_179_bits[] = {
+0x07, 0x04, 0x02, 0x04, 0x03};
+static unsigned char helvetica12_180_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica12_181_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x17, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_182_bits[] = {
+0x3c, 0x16, 0x17, 0x17, 0x17, 0x16, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14};
+static unsigned char helvetica12_183_bits[] = {
+0x01};
+static unsigned char helvetica12_184_bits[] = {
+0x02, 0x04, 0x04, 0x03};
+static unsigned char helvetica12_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_186_bits[] = {
+0x07, 0x05, 0x07, 0x00, 0x07};
+static unsigned char helvetica12_187_bits[] = {
+0x05, 0x0a, 0x14, 0x0a, 0x05};
+static unsigned char helvetica12_188_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x22, 0x00, 0x22, 0x00, 0x92, 0x00, 0xc8, 0x00, 
+0xa8, 0x00, 0xe4, 0x01, 0x82, 0x00};
+static unsigned char helvetica12_189_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x22, 0x00, 0x12, 0x00, 0xd2, 0x00, 0x28, 0x01, 
+0x88, 0x00, 0x44, 0x00, 0xe2, 0x01};
+static unsigned char helvetica12_190_bits[] = {
+0x87, 0x00, 0x44, 0x00, 0x22, 0x00, 0x24, 0x00, 0x93, 0x00, 0xd0, 0x00, 
+0xa8, 0x00, 0xe8, 0x01, 0x84, 0x00};
+static unsigned char helvetica12_191_bits[] = {
+0x04, 0x00, 0x04, 0x04, 0x02, 0x02, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_192_bits[] = {
+0x04, 0x08, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_193_bits[] = {
+0x10, 0x08, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_194_bits[] = {
+0x08, 0x14, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_195_bits[] = {
+0x28, 0x14, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_196_bits[] = {
+0x14, 0x00, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_197_bits[] = {
+0x08, 0x14, 0x08, 0x08, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x41, 0x41, 0x41};
+static unsigned char helvetica12_198_bits[] = {
+0xf8, 0x01, 0x14, 0x00, 0x14, 0x00, 0x12, 0x00, 0xf2, 0x01, 0x1e, 0x00, 
+0x11, 0x00, 0x11, 0x00, 0xf1, 0x01};
+static unsigned char helvetica12_199_bits[] = {
+0x3c, 0x42, 0x01, 0x01, 0x01, 0x01, 0x01, 0x42, 0x3c, 0x10, 0x10, 0x0c};
+static unsigned char helvetica12_200_bits[] = {
+0x04, 0x08, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_201_bits[] = {
+0x10, 0x08, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_202_bits[] = {
+0x08, 0x14, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_203_bits[] = {
+0x14, 0x00, 0x3f, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica12_204_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_205_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_206_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_207_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_208_bits[] = {
+0x3e, 0x42, 0x82, 0x82, 0x8f, 0x82, 0x82, 0x42, 0x3e};
+static unsigned char helvetica12_209_bits[] = {
+0x28, 0x14, 0x00, 0x41, 0x43, 0x45, 0x45, 0x49, 0x51, 0x51, 0x61, 0x41};
+static unsigned char helvetica12_210_bits[] = {
+0x08, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_211_bits[] = {
+0x20, 0x10, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_212_bits[] = {
+0x10, 0x28, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_213_bits[] = {
+0x28, 0x14, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_214_bits[] = {
+0x24, 0x00, 0x3c, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica12_215_bits[] = {
+0x11, 0x0a, 0x04, 0x0a, 0x11};
+static unsigned char helvetica12_216_bits[] = {
+0x00, 0x02, 0x78, 0x01, 0x84, 0x00, 0x42, 0x01, 0x22, 0x01, 0x22, 0x01, 
+0x12, 0x01, 0x0a, 0x01, 0x84, 0x00, 0x7a, 0x00, 0x01, 0x00};
+static unsigned char helvetica12_217_bits[] = {
+0x04, 0x08, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_218_bits[] = {
+0x10, 0x08, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_219_bits[] = {
+0x08, 0x14, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_220_bits[] = {
+0x12, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica12_221_bits[] = {
+0x10, 0x08, 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08};
+static unsigned char helvetica12_222_bits[] = {
+0x01, 0x01, 0x1f, 0x21, 0x21, 0x21, 0x1f, 0x01, 0x01};
+static unsigned char helvetica12_223_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0d, 0x11, 0x11, 0x11, 0x0d};
+static unsigned char helvetica12_224_bits[] = {
+0x04, 0x08, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_225_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_226_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_227_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_228_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x0e, 0x11, 0x10, 0x1e, 0x11, 0x11, 0x2e};
+static unsigned char helvetica12_230_bits[] = {
+0xee, 0x00, 0x11, 0x01, 0x10, 0x01, 0xfe, 0x01, 0x11, 0x00, 0x11, 0x01, 
+0xee, 0x00};
+static unsigned char helvetica12_231_bits[] = {
+0x0e, 0x11, 0x01, 0x01, 0x01, 0x11, 0x0e, 0x04, 0x08, 0x06};
+static unsigned char helvetica12_232_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_233_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_234_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_235_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x1f, 0x01, 0x11, 0x0e};
+static unsigned char helvetica12_236_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_238_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_239_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica12_240_bits[] = {
+0x16, 0x0c, 0x0a, 0x10, 0x1e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_241_bits[] = {
+0x14, 0x0a, 0x00, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x11, 0x11};
+static unsigned char helvetica12_242_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_243_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_244_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_245_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_246_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica12_247_bits[] = {
+0x04, 0x00, 0x1f, 0x00, 0x04};
+static unsigned char helvetica12_248_bits[] = {
+0x5c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x1d};
+static unsigned char helvetica12_249_bits[] = {
+0x02, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_250_bits[] = {
+0x08, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_251_bits[] = {
+0x04, 0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_252_bits[] = {
+0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x19, 0x16};
+static unsigned char helvetica12_253_bits[] = {
+0x08, 0x04, 0x00, 0x11, 0x11, 0x11, 0x09, 0x0a, 0x0a, 0x04, 0x04, 0x02, 
+0x01};
+static unsigned char helvetica12_254_bits[] = {
+0x01, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 0x01};
+static unsigned char helvetica12_255_bits[] = {
+0x0a, 0x00, 0x11, 0x11, 0x12, 0x0a, 0x0a, 0x0c, 0x04, 0x04, 0x04, 0x03};
+static RotFont helvetica12font[] = {
+{5, 1, 1, helvetica12_0_bits},
+{5, 1, 1, helvetica12_1_bits},
+{5, 1, 1, helvetica12_2_bits},
+{5, 1, 1, helvetica12_3_bits},
+{5, 1, 1, helvetica12_4_bits},
+{5, 1, 1, helvetica12_5_bits},
+{5, 1, 1, helvetica12_6_bits},
+{5, 1, 1, helvetica12_7_bits},
+{5, 1, 1, helvetica12_8_bits},
+{5, 1, 1, helvetica12_9_bits},
+{5, 1, 1, helvetica12_10_bits},
+{5, 1, 1, helvetica12_11_bits},
+{5, 1, 1, helvetica12_12_bits},
+{5, 1, 1, helvetica12_13_bits},
+{5, 1, 1, helvetica12_14_bits},
+{5, 1, 1, helvetica12_15_bits},
+{5, 1, 1, helvetica12_16_bits},
+{5, 1, 1, helvetica12_17_bits},
+{5, 1, 1, helvetica12_18_bits},
+{5, 1, 1, helvetica12_19_bits},
+{5, 1, 1, helvetica12_20_bits},
+{5, 1, 1, helvetica12_21_bits},
+{5, 1, 1, helvetica12_22_bits},
+{5, 1, 1, helvetica12_23_bits},
+{5, 1, 1, helvetica12_24_bits},
+{5, 1, 1, helvetica12_25_bits},
+{5, 1, 1, helvetica12_26_bits},
+{5, 1, 1, helvetica12_27_bits},
+{5, 1, 1, helvetica12_28_bits},
+{5, 1, 1, helvetica12_29_bits},
+{5, 1, 1, helvetica12_30_bits},
+{5, 1, 1, helvetica12_31_bits},
+{6, 1, 1, helvetica12_32_bits},
+{1, 9, 9, helvetica12_33_bits},
+{3, 3, 9, helvetica12_34_bits},
+{6, 8, 8, helvetica12_35_bits},
+{5, 10, 9, helvetica12_36_bits},
+{9, 9, 9, helvetica12_37_bits},
+{7, 9, 9, helvetica12_38_bits},
+{2, 3, 9, helvetica12_39_bits},
+{3, 12, 9, helvetica12_40_bits},
+{3, 12, 9, helvetica12_41_bits},
+{3, 3, 9, helvetica12_42_bits},
+{5, 5, 6, helvetica12_43_bits},
+{2, 3, 1, helvetica12_44_bits},
+{5, 1, 4, helvetica12_45_bits},
+{1, 1, 1, helvetica12_46_bits},
+{4, 9, 9, helvetica12_47_bits},
+{5, 9, 9, helvetica12_48_bits},
+{3, 9, 9, helvetica12_49_bits},
+{5, 9, 9, helvetica12_50_bits},
+{5, 9, 9, helvetica12_51_bits},
+{6, 9, 9, helvetica12_52_bits},
+{5, 9, 9, helvetica12_53_bits},
+{5, 9, 9, helvetica12_54_bits},
+{5, 9, 9, helvetica12_55_bits},
+{5, 9, 9, helvetica12_56_bits},
+{5, 9, 9, helvetica12_57_bits},
+{1, 6, 6, helvetica12_58_bits},
+{2, 8, 6, helvetica12_59_bits},
+{6, 5, 6, helvetica12_60_bits},
+{5, 3, 5, helvetica12_61_bits},
+{6, 5, 6, helvetica12_62_bits},
+{5, 9, 9, helvetica12_63_bits},
+{10, 10, 9, helvetica12_64_bits},
+{7, 9, 9, helvetica12_65_bits},
+{6, 9, 9, helvetica12_66_bits},
+{7, 9, 9, helvetica12_67_bits},
+{7, 9, 9, helvetica12_68_bits},
+{6, 9, 9, helvetica12_69_bits},
+{6, 9, 9, helvetica12_70_bits},
+{7, 9, 9, helvetica12_71_bits},
+{7, 9, 9, helvetica12_72_bits},
+{1, 9, 9, helvetica12_73_bits},
+{5, 9, 9, helvetica12_74_bits},
+{7, 9, 9, helvetica12_75_bits},
+{5, 9, 9, helvetica12_76_bits},
+{9, 9, 9, helvetica12_77_bits},
+{7, 9, 9, helvetica12_78_bits},
+{8, 9, 9, helvetica12_79_bits},
+{6, 9, 9, helvetica12_80_bits},
+{8, 9, 9, helvetica12_81_bits},
+{6, 9, 9, helvetica12_82_bits},
+{6, 9, 9, helvetica12_83_bits},
+{7, 9, 9, helvetica12_84_bits},
+{6, 9, 9, helvetica12_85_bits},
+{7, 9, 9, helvetica12_86_bits},
+{9, 9, 9, helvetica12_87_bits},
+{7, 9, 9, helvetica12_88_bits},
+{7, 9, 9, helvetica12_89_bits},
+{7, 9, 9, helvetica12_90_bits},
+{2, 12, 9, helvetica12_91_bits},
+{4, 9, 9, helvetica12_92_bits},
+{2, 12, 9, helvetica12_93_bits},
+{5, 3, 8, helvetica12_94_bits},
+{7, 1, -1, helvetica12_95_bits},
+{2, 3, 9, helvetica12_96_bits},
+{6, 7, 7, helvetica12_97_bits},
+{5, 9, 9, helvetica12_98_bits},
+{5, 7, 7, helvetica12_99_bits},
+{5, 9, 9, helvetica12_100_bits},
+{5, 7, 7, helvetica12_101_bits},
+{4, 9, 9, helvetica12_102_bits},
+{5, 10, 7, helvetica12_103_bits},
+{5, 9, 9, helvetica12_104_bits},
+{1, 9, 9, helvetica12_105_bits},
+{2, 12, 9, helvetica12_106_bits},
+{5, 9, 9, helvetica12_107_bits},
+{1, 9, 9, helvetica12_108_bits},
+{7, 7, 7, helvetica12_109_bits},
+{5, 7, 7, helvetica12_110_bits},
+{5, 7, 7, helvetica12_111_bits},
+{5, 10, 7, helvetica12_112_bits},
+{5, 10, 7, helvetica12_113_bits},
+{3, 7, 7, helvetica12_114_bits},
+{4, 7, 7, helvetica12_115_bits},
+{3, 9, 9, helvetica12_116_bits},
+{5, 7, 7, helvetica12_117_bits},
+{5, 7, 7, helvetica12_118_bits},
+{9, 7, 7, helvetica12_119_bits},
+{6, 7, 7, helvetica12_120_bits},
+{5, 10, 7, helvetica12_121_bits},
+{4, 7, 7, helvetica12_122_bits},
+{4, 12, 9, helvetica12_123_bits},
+{1, 12, 9, helvetica12_124_bits},
+{4, 12, 9, helvetica12_125_bits},
+{6, 2, 5, helvetica12_126_bits},
+{5, 1, 1, helvetica12_127_bits},
+{5, 1, 1, helvetica12_128_bits},
+{5, 1, 1, helvetica12_129_bits},
+{5, 1, 1, helvetica12_130_bits},
+{5, 1, 1, helvetica12_131_bits},
+{5, 1, 1, helvetica12_132_bits},
+{5, 1, 1, helvetica12_133_bits},
+{5, 1, 1, helvetica12_134_bits},
+{5, 1, 1, helvetica12_135_bits},
+{5, 1, 1, helvetica12_136_bits},
+{5, 1, 1, helvetica12_137_bits},
+{5, 1, 1, helvetica12_138_bits},
+{5, 1, 1, helvetica12_139_bits},
+{5, 1, 1, helvetica12_140_bits},
+{5, 1, 1, helvetica12_141_bits},
+{5, 1, 1, helvetica12_142_bits},
+{5, 1, 1, helvetica12_143_bits},
+{5, 1, 1, helvetica12_144_bits},
+{5, 1, 1, helvetica12_145_bits},
+{5, 1, 1, helvetica12_146_bits},
+{5, 1, 1, helvetica12_147_bits},
+{5, 1, 1, helvetica12_148_bits},
+{5, 1, 1, helvetica12_149_bits},
+{5, 1, 1, helvetica12_150_bits},
+{5, 1, 1, helvetica12_151_bits},
+{5, 1, 1, helvetica12_152_bits},
+{5, 1, 1, helvetica12_153_bits},
+{5, 1, 1, helvetica12_154_bits},
+{5, 1, 1, helvetica12_155_bits},
+{5, 1, 1, helvetica12_156_bits},
+{5, 1, 1, helvetica12_157_bits},
+{5, 1, 1, helvetica12_158_bits},
+{5, 1, 1, helvetica12_159_bits},
+{1, 1, 1, helvetica12_160_bits},
+{1, 10, 7, helvetica12_161_bits},
+{5, 9, 8, helvetica12_162_bits},
+{5, 9, 9, helvetica12_163_bits},
+{6, 6, 7, helvetica12_164_bits},
+{5, 9, 9, helvetica12_165_bits},
+{1, 11, 9, helvetica12_166_bits},
+{5, 12, 9, helvetica12_167_bits},
+{3, 1, 9, helvetica12_168_bits},
+{9, 9, 9, helvetica12_169_bits},
+{3, 5, 9, helvetica12_170_bits},
+{5, 5, 6, helvetica12_171_bits},
+{6, 4, 6, helvetica12_172_bits},
+{4, 1, 4, helvetica12_173_bits},
+{9, 9, 9, helvetica12_174_bits},
+{4, 1, 9, helvetica12_175_bits},
+{4, 4, 8, helvetica12_176_bits},
+{5, 7, 7, helvetica12_177_bits},
+{4, 5, 8, helvetica12_178_bits},
+{3, 5, 8, helvetica12_179_bits},
+{2, 2, 10, helvetica12_180_bits},
+{5, 10, 7, helvetica12_181_bits},
+{6, 12, 9, helvetica12_182_bits},
+{1, 1, 4, helvetica12_183_bits},
+{3, 4, 1, helvetica12_184_bits},
+{2, 5, 8, helvetica12_185_bits},
+{3, 5, 9, helvetica12_186_bits},
+{5, 5, 6, helvetica12_187_bits},
+{9, 9, 9, helvetica12_188_bits},
+{9, 9, 9, helvetica12_189_bits},
+{9, 9, 9, helvetica12_190_bits},
+{5, 9, 6, helvetica12_191_bits},
+{7, 12, 12, helvetica12_192_bits},
+{7, 12, 12, helvetica12_193_bits},
+{7, 12, 12, helvetica12_194_bits},
+{7, 12, 12, helvetica12_195_bits},
+{7, 11, 11, helvetica12_196_bits},
+{7, 12, 12, helvetica12_197_bits},
+{9, 9, 9, helvetica12_198_bits},
+{7, 12, 9, helvetica12_199_bits},
+{6, 12, 12, helvetica12_200_bits},
+{6, 12, 12, helvetica12_201_bits},
+{6, 12, 12, helvetica12_202_bits},
+{6, 11, 11, helvetica12_203_bits},
+{2, 12, 12, helvetica12_204_bits},
+{2, 12, 12, helvetica12_205_bits},
+{3, 12, 12, helvetica12_206_bits},
+{3, 11, 11, helvetica12_207_bits},
+{8, 9, 9, helvetica12_208_bits},
+{7, 12, 12, helvetica12_209_bits},
+{8, 12, 12, helvetica12_210_bits},
+{8, 12, 12, helvetica12_211_bits},
+{8, 12, 12, helvetica12_212_bits},
+{8, 12, 12, helvetica12_213_bits},
+{8, 11, 11, helvetica12_214_bits},
+{5, 5, 6, helvetica12_215_bits},
+{10, 11, 10, helvetica12_216_bits},
+{6, 12, 12, helvetica12_217_bits},
+{6, 12, 12, helvetica12_218_bits},
+{6, 12, 12, helvetica12_219_bits},
+{6, 11, 11, helvetica12_220_bits},
+{7, 12, 12, helvetica12_221_bits},
+{6, 9, 9, helvetica12_222_bits},
+{5, 9, 9, helvetica12_223_bits},
+{6, 10, 10, helvetica12_224_bits},
+{6, 10, 10, helvetica12_225_bits},
+{6, 10, 10, helvetica12_226_bits},
+{6, 10, 10, helvetica12_227_bits},
+{6, 9, 9, helvetica12_228_bits},
+{6, 10, 10, helvetica12_229_bits},
+{9, 7, 7, helvetica12_230_bits},
+{5, 10, 7, helvetica12_231_bits},
+{5, 10, 10, helvetica12_232_bits},
+{5, 10, 10, helvetica12_233_bits},
+{5, 10, 10, helvetica12_234_bits},
+{5, 9, 9, helvetica12_235_bits},
+{2, 10, 10, helvetica12_236_bits},
+{2, 10, 10, helvetica12_237_bits},
+{3, 10, 10, helvetica12_238_bits},
+{3, 9, 9, helvetica12_239_bits},
+{5, 10, 10, helvetica12_240_bits},
+{5, 10, 10, helvetica12_241_bits},
+{5, 10, 10, helvetica12_242_bits},
+{5, 10, 10, helvetica12_243_bits},
+{5, 10, 10, helvetica12_244_bits},
+{5, 10, 10, helvetica12_245_bits},
+{5, 9, 9, helvetica12_246_bits},
+{5, 5, 6, helvetica12_247_bits},
+{7, 7, 7, helvetica12_248_bits},
+{5, 10, 10, helvetica12_249_bits},
+{5, 10, 10, helvetica12_250_bits},
+{5, 10, 10, helvetica12_251_bits},
+{5, 9, 9, helvetica12_252_bits},
+{5, 13, 10, helvetica12_253_bits},
+{5, 12, 9, helvetica12_254_bits},
+{5, 12, 9, helvetica12_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica14.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica14.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica14.bdf	(revision 16632)
@@ -0,0 +1,3309 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--14-100-100-100-P-76-ISO8859-1
+SIZE 10 100 100
+FONTBOUNDINGBOX 14 17 -1 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 100
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "P"
+AVERAGE_WIDTH 76
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 11
+X_HEIGHT 8
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--14-100-100-100-P-76-ISO8859-1"
+WEIGHT 10
+RESOLUTION 138
+QUAD_WIDTH 8
+DEFAULT_CHAR 32
+FONT_ASCENT 13
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 11 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 3 1 8
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 10 0 0
+BITMAP
+14
+14
+14
+7e
+28
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 14 0 -2
+BITMAP
+10
+7c
+92
+92
+90
+50
+38
+14
+12
+92
+92
+7c
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+7080
+8900
+8900
+7200
+0200
+0400
+0800
+09c0
+1220
+1220
+21c0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+30
+48
+48
+30
+20
+52
+8a
+84
+8a
+71
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 3 1 8
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 5 1 6
+BITMAP
+20
+a8
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 4 0 -2
+BITMAP
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 1 1 4
+BITMAP
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 2 1 0
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 11 0 0
+BITMAP
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+84
+84
+84
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 3 11 2 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+04
+08
+10
+20
+40
+80
+80
+fc
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+04
+04
+38
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+04
+0c
+14
+24
+44
+84
+84
+fe
+04
+04
+04
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+fc
+80
+80
+80
+f8
+04
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+80
+80
+b8
+c4
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+fc
+04
+08
+08
+10
+10
+20
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+84
+84
+78
+84
+84
+84
+84
+78
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+78
+84
+84
+84
+84
+7c
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 8 1 0
+BITMAP
+80
+80
+00
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 10 0 -2
+BITMAP
+40
+40
+00
+00
+00
+00
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 3 1 3
+BITMAP
+fc
+00
+fc
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+cc
+84
+84
+04
+08
+10
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 12 1 -1
+BITMAP
+0f00
+30c0
+4020
+46a0
+8920
+9120
+9120
+9340
+8d80
+4000
+6080
+1f00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fc
+86
+82
+82
+84
+f8
+84
+82
+82
+86
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+1c
+63
+41
+80
+80
+80
+80
+80
+41
+63
+1c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+f8
+86
+82
+81
+81
+81
+81
+81
+82
+86
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1e00
+6180
+4080
+8000
+8000
+8780
+8080
+8080
+4080
+6380
+1c80
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+81
+81
+81
+81
+81
+ff
+81
+81
+81
+81
+81
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 11 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+04
+04
+04
+04
+04
+04
+04
+04
+84
+84
+78
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 8 11 1 0
+BITMAP
+82
+84
+88
+90
+a0
+e0
+90
+88
+84
+82
+81
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+fc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+8020
+c060
+c060
+a0a0
+a0a0
+9120
+9120
+8a20
+8a20
+8420
+8420
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+c1
+a1
+a1
+91
+91
+89
+89
+85
+85
+83
+83
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fc
+86
+82
+82
+86
+fc
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 11 1 0
+BITMAP
+1c00
+6300
+4100
+8080
+8080
+8080
+8880
+8480
+4300
+6300
+1c80
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+fe
+83
+81
+81
+82
+fc
+82
+81
+81
+81
+81
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+38
+c6
+82
+80
+60
+18
+06
+02
+82
+c6
+38
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+ff80
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+8080
+8080
+4100
+4100
+6300
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 13 11 0 0
+BITMAP
+8208
+8208
+8508
+4510
+4510
+4510
+28a0
+28a0
+28a0
+1040
+1040
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+8080
+4100
+2200
+1400
+0800
+0800
+1400
+2200
+4100
+4100
+8080
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+8080
+c180
+4100
+2200
+2200
+1400
+1c00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+fe
+02
+04
+08
+18
+10
+20
+60
+40
+80
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 14 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 11 0 0
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+20
+10
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 14 0 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 5 1 6
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 8 1 0 -3
+BITMAP
+ff
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 3 0 8
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 8 1 0
+BITMAP
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+80
+80
+80
+b8
+cc
+84
+84
+84
+84
+cc
+b8
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+78
+cc
+80
+80
+80
+84
+cc
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+04
+04
+04
+74
+cc
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 8 1 0
+BITMAP
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 11 0 0
+BITMAP
+30
+40
+40
+e0
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+74
+cc
+84
+84
+84
+84
+cc
+74
+04
+cc
+78
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+80
+80
+80
+b8
+cc
+84
+84
+84
+84
+84
+84
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 11 1 0
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 14 -1 -3
+BITMAP
+20
+20
+00
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+80
+80
+80
+88
+90
+a0
+c0
+a0
+90
+88
+84
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 11 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 8 1 0
+BITMAP
+b300
+cc80
+8880
+8880
+8880
+8880
+8880
+8880
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 8 1 0
+BITMAP
+b8
+cc
+84
+84
+84
+84
+84
+84
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 8 1 0
+BITMAP
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+b8
+cc
+84
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+74
+cc
+84
+84
+84
+84
+cc
+74
+04
+04
+04
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+b0
+c0
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 8 1 0
+BITMAP
+70
+88
+c0
+70
+18
+08
+88
+70
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+40
+40
+e0
+40
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 8 1 0
+BITMAP
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+82
+82
+44
+44
+44
+28
+28
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 8 0 0
+BITMAP
+8880
+8880
+8880
+4900
+4900
+5500
+2200
+2200
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 8 0 0
+BITMAP
+c6
+44
+28
+10
+10
+28
+44
+c6
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 -3
+BITMAP
+82
+c2
+44
+44
+24
+28
+18
+10
+10
+30
+60
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 8 0 0
+BITMAP
+fc
+04
+08
+10
+20
+40
+80
+fc
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 14 0 -3
+BITMAP
+18
+20
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 14 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 14 0 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 3 1 3
+BITMAP
+64
+b4
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 -1
+BITMAP
+04
+78
+cc
+90
+90
+a0
+a4
+cc
+78
+80
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 0 0
+BITMAP
+38
+44
+40
+40
+f8
+20
+20
+20
+40
+62
+dc
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 6 1 2
+BITMAP
+84
+78
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+82
+82
+82
+44
+44
+28
+fe
+10
+fe
+10
+10
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 14 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 5 14 2 -3
+BITMAP
+70
+d8
+88
+c0
+70
+98
+88
+88
+c8
+70
+18
+88
+d8
+70
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 1 0 9
+BITMAP
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+1e00
+6180
+5c80
+a2c0
+a240
+a040
+a240
+9c40
+4080
+6180
+1e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 7 1 4
+BITMAP
+e0
+10
+70
+90
+d0
+00
+f0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+24
+48
+90
+48
+24
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 4 1 2
+BITMAP
+fe
+02
+02
+02
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 1 0 4
+BITMAP
+e0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+1e00
+6180
+5c80
+9240
+9240
+9c40
+9240
+9240
+4080
+6180
+1e00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 1 0 9
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 4 1 7
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 9 1 0
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+00
+fe
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 6 0 5
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 6 0 5
+BITMAP
+60
+90
+20
+10
+90
+60
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 2 2 2 9
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+84
+84
+84
+84
+84
+84
+cc
+b4
+80
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 14 0 -3
+BITMAP
+3e
+74
+f4
+f4
+f4
+74
+34
+14
+14
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 1 1 4
+BITMAP
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 3 0 -3
+BITMAP
+20
+90
+60
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 2 6 1 5
+BITMAP
+40
+c0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 7 1 4
+BITMAP
+60
+90
+90
+90
+60
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 5 1 2
+BITMAP
+90
+48
+24
+48
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+4200
+c200
+4400
+4400
+4800
+4880
+0980
+1280
+1480
+27c0
+2080
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 9 11 1 0
+BITMAP
+4200
+c200
+4400
+4400
+4800
+4b00
+1480
+1080
+1100
+2200
+2780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+6100
+9100
+2200
+1200
+9400
+6440
+04c0
+0940
+0a40
+13e0
+1040
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+10
+10
+00
+10
+20
+40
+80
+84
+84
+cc
+30
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+1000
+0800
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0400
+0800
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0c00
+1200
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+1a00
+2c00
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+3600
+0000
+0800
+1c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0c00
+1200
+1200
+0c00
+0c00
+1400
+1400
+2200
+2200
+4100
+7f00
+4100
+8080
+8080
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 1008 0
+DWIDTH 14 0
+BBX 12 11 1 0
+BITMAP
+1ff0
+1200
+1200
+2200
+2200
+23f0
+7e00
+4200
+4200
+8200
+83f0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 -3
+BITMAP
+1c
+63
+41
+80
+80
+80
+80
+80
+41
+63
+1c
+08
+24
+18
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+20
+10
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+08
+10
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+18
+24
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+6c
+00
+fe
+80
+80
+80
+80
+fc
+80
+80
+80
+80
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 14 1 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 14 2 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 14 1 0
+BITMAP
+60
+90
+00
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 5 13 0 0
+BITMAP
+d8
+00
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 11 0 0
+BITMAP
+7c00
+4300
+4100
+4080
+4080
+f080
+4080
+4080
+4100
+4300
+7c00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+1a
+2c
+00
+c1
+a1
+a1
+91
+91
+89
+89
+85
+85
+83
+83
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1000
+0800
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0400
+0800
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0c00
+1200
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1a00
+2c00
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+3300
+0000
+1c00
+6300
+4100
+8080
+8080
+8080
+8080
+8080
+4100
+6300
+1c00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 11 11 0 0
+BITMAP
+0e20
+31c0
+2080
+4140
+4240
+4440
+4840
+5040
+2080
+7180
+8e00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+10
+08
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+04
+08
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+18
+24
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+66
+00
+81
+81
+81
+81
+81
+81
+81
+81
+81
+42
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0400
+0800
+0000
+8080
+c180
+4100
+2200
+2200
+1400
+1c00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 11 1 0
+BITMAP
+80
+80
+fc
+86
+82
+82
+86
+fc
+80
+80
+80
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+70
+88
+88
+88
+b0
+90
+88
+88
+88
+88
+b0
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+20
+10
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+10
+20
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+30
+48
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+34
+58
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 11 1 0
+BITMAP
+48
+48
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+30
+48
+30
+00
+78
+cc
+04
+7c
+c4
+84
+cc
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 8 1 0
+BITMAP
+7bc0
+c660
+0420
+7fe0
+c400
+8400
+ce60
+7bc0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 -3
+BITMAP
+78
+cc
+80
+80
+80
+84
+cc
+78
+10
+48
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+10
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+10
+20
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+48
+00
+78
+cc
+84
+fc
+80
+80
+cc
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 11 1 0
+BITMAP
+80
+40
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 2 11 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 4 11 0 0
+BITMAP
+60
+90
+00
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+a0
+a0
+00
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+d8
+70
+90
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+68
+b0
+00
+b8
+cc
+84
+84
+84
+84
+84
+84
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+10
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+10
+20
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+68
+b0
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+48
+00
+78
+cc
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 7 1 1
+BITMAP
+10
+10
+00
+fe
+00
+10
+10
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 8 8 0 0
+BITMAP
+3d
+62
+46
+4a
+52
+62
+46
+bc
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+20
+10
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+10
+20
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 11 1 0
+BITMAP
+48
+48
+00
+84
+84
+84
+84
+84
+84
+cc
+74
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 14 0 -3
+BITMAP
+08
+10
+00
+82
+c2
+44
+44
+24
+28
+18
+10
+10
+30
+60
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 14 1 -3
+BITMAP
+80
+80
+80
+b8
+cc
+84
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 14 0 -3
+BITMAP
+24
+24
+00
+82
+c2
+44
+44
+24
+28
+18
+10
+10
+30
+60
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica14.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica14.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica14.h	(revision 16632)
@@ -0,0 +1,845 @@
+static unsigned char helvetica14_0_bits[] = {
+0x00};
+static unsigned char helvetica14_1_bits[] = {
+0x00};
+static unsigned char helvetica14_2_bits[] = {
+0x00};
+static unsigned char helvetica14_3_bits[] = {
+0x00};
+static unsigned char helvetica14_4_bits[] = {
+0x00};
+static unsigned char helvetica14_5_bits[] = {
+0x00};
+static unsigned char helvetica14_6_bits[] = {
+0x00};
+static unsigned char helvetica14_7_bits[] = {
+0x00};
+static unsigned char helvetica14_8_bits[] = {
+0x00};
+static unsigned char helvetica14_9_bits[] = {
+0x00};
+static unsigned char helvetica14_10_bits[] = {
+0x00};
+static unsigned char helvetica14_11_bits[] = {
+0x00};
+static unsigned char helvetica14_12_bits[] = {
+0x00};
+static unsigned char helvetica14_13_bits[] = {
+0x00};
+static unsigned char helvetica14_14_bits[] = {
+0x00};
+static unsigned char helvetica14_15_bits[] = {
+0x00};
+static unsigned char helvetica14_16_bits[] = {
+0x00};
+static unsigned char helvetica14_17_bits[] = {
+0x00};
+static unsigned char helvetica14_18_bits[] = {
+0x00};
+static unsigned char helvetica14_19_bits[] = {
+0x00};
+static unsigned char helvetica14_20_bits[] = {
+0x00};
+static unsigned char helvetica14_21_bits[] = {
+0x00};
+static unsigned char helvetica14_22_bits[] = {
+0x00};
+static unsigned char helvetica14_23_bits[] = {
+0x00};
+static unsigned char helvetica14_24_bits[] = {
+0x00};
+static unsigned char helvetica14_25_bits[] = {
+0x00};
+static unsigned char helvetica14_26_bits[] = {
+0x00};
+static unsigned char helvetica14_27_bits[] = {
+0x00};
+static unsigned char helvetica14_28_bits[] = {
+0x00};
+static unsigned char helvetica14_29_bits[] = {
+0x00};
+static unsigned char helvetica14_30_bits[] = {
+0x00};
+static unsigned char helvetica14_31_bits[] = {
+0x00};
+static unsigned char helvetica14_32_bits[] = {
+0x00};
+static unsigned char helvetica14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char helvetica14_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char helvetica14_35_bits[] = {
+0x28, 0x28, 0x28, 0x7e, 0x14, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char helvetica14_36_bits[] = {
+0x08, 0x3e, 0x49, 0x49, 0x09, 0x0a, 0x1c, 0x28, 0x48, 0x49, 0x49, 0x3e, 
+0x08, 0x08};
+static unsigned char helvetica14_37_bits[] = {
+0x0e, 0x01, 0x91, 0x00, 0x91, 0x00, 0x4e, 0x00, 0x40, 0x00, 0x20, 0x00, 
+0x10, 0x00, 0x90, 0x03, 0x48, 0x04, 0x48, 0x04, 0x84, 0x03};
+static unsigned char helvetica14_38_bits[] = {
+0x0c, 0x12, 0x12, 0x0c, 0x04, 0x4a, 0x51, 0x21, 0x51, 0x8e};
+static unsigned char helvetica14_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char helvetica14_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 
+0x02, 0x04};
+static unsigned char helvetica14_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 
+0x02, 0x01};
+static unsigned char helvetica14_42_bits[] = {
+0x04, 0x15, 0x0e, 0x15, 0x04};
+static unsigned char helvetica14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char helvetica14_44_bits[] = {
+0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica14_45_bits[] = {
+0x7f};
+static unsigned char helvetica14_46_bits[] = {
+0x01, 0x01};
+static unsigned char helvetica14_47_bits[] = {
+0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_48_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char helvetica14_50_bits[] = {
+0x1e, 0x21, 0x21, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x01, 0x3f};
+static unsigned char helvetica14_51_bits[] = {
+0x1e, 0x21, 0x21, 0x20, 0x20, 0x1c, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_52_bits[] = {
+0x20, 0x30, 0x28, 0x24, 0x22, 0x21, 0x21, 0x7f, 0x20, 0x20, 0x20};
+static unsigned char helvetica14_53_bits[] = {
+0x3f, 0x01, 0x01, 0x01, 0x1f, 0x20, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_54_bits[] = {
+0x1e, 0x21, 0x01, 0x01, 0x1d, 0x23, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_55_bits[] = {
+0x3f, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_56_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x1e, 0x21, 0x21, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_57_bits[] = {
+0x1e, 0x21, 0x21, 0x21, 0x21, 0x3e, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_58_bits[] = {
+0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char helvetica14_59_bits[] = {
+0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica14_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char helvetica14_61_bits[] = {
+0x3f, 0x00, 0x3f};
+static unsigned char helvetica14_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char helvetica14_63_bits[] = {
+0x0c, 0x33, 0x21, 0x21, 0x20, 0x10, 0x08, 0x04, 0x00, 0x04, 0x04};
+static unsigned char helvetica14_64_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x02, 0x04, 0x62, 0x05, 0x91, 0x04, 0x89, 0x04, 
+0x89, 0x04, 0xc9, 0x02, 0xb1, 0x01, 0x02, 0x00, 0x06, 0x01, 0xf8, 0x00};
+static unsigned char helvetica14_65_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_66_bits[] = {
+0x3f, 0x61, 0x41, 0x41, 0x21, 0x1f, 0x21, 0x41, 0x41, 0x61, 0x3f};
+static unsigned char helvetica14_67_bits[] = {
+0x38, 0xc6, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0xc6, 0x38};
+static unsigned char helvetica14_68_bits[] = {
+0x1f, 0x61, 0x41, 0x81, 0x81, 0x81, 0x81, 0x81, 0x41, 0x61, 0x1f};
+static unsigned char helvetica14_69_bits[] = {
+0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x01, 0x7f};
+static unsigned char helvetica14_70_bits[] = {
+0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_71_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x02, 0x01, 0x01, 0x00, 0x01, 0x00, 0xe1, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0xc6, 0x01, 0x38, 0x01};
+static unsigned char helvetica14_72_bits[] = {
+0x81, 0x81, 0x81, 0x81, 0x81, 0xff, 0x81, 0x81, 0x81, 0x81, 0x81};
+static unsigned char helvetica14_73_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_74_bits[] = {
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x1e};
+static unsigned char helvetica14_75_bits[] = {
+0x41, 0x21, 0x11, 0x09, 0x05, 0x07, 0x09, 0x11, 0x21, 0x41, 0x81};
+static unsigned char helvetica14_76_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3f};
+static unsigned char helvetica14_77_bits[] = {
+0x01, 0x04, 0x03, 0x06, 0x03, 0x06, 0x05, 0x05, 0x05, 0x05, 0x89, 0x04, 
+0x89, 0x04, 0x51, 0x04, 0x51, 0x04, 0x21, 0x04, 0x21, 0x04};
+static unsigned char helvetica14_78_bits[] = {
+0x83, 0x85, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 0xc1, 0xc1};
+static unsigned char helvetica14_79_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_80_bits[] = {
+0x3f, 0x61, 0x41, 0x41, 0x61, 0x3f, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_81_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x11, 0x01, 0x21, 0x01, 0xc2, 0x00, 0xc6, 0x00, 0x38, 0x01};
+static unsigned char helvetica14_82_bits[] = {
+0x7f, 0xc1, 0x81, 0x81, 0x41, 0x3f, 0x41, 0x81, 0x81, 0x81, 0x81};
+static unsigned char helvetica14_83_bits[] = {
+0x1c, 0x63, 0x41, 0x01, 0x06, 0x18, 0x60, 0x40, 0x41, 0x63, 0x1c};
+static unsigned char helvetica14_84_bits[] = {
+0xff, 0x01, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_85_bits[] = {
+0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 0x3c};
+static unsigned char helvetica14_86_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0x82, 0x00, 0xc6, 0x00, 0x44, 0x00, 
+0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_87_bits[] = {
+0x41, 0x10, 0x41, 0x10, 0xa1, 0x10, 0xa2, 0x08, 0xa2, 0x08, 0xa2, 0x08, 
+0x14, 0x05, 0x14, 0x05, 0x14, 0x05, 0x08, 0x02, 0x08, 0x02};
+static unsigned char helvetica14_88_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x82, 0x00, 0x82, 0x00, 0x01, 0x01};
+static unsigned char helvetica14_89_bits[] = {
+0x01, 0x01, 0x83, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_90_bits[] = {
+0x7f, 0x40, 0x20, 0x10, 0x18, 0x08, 0x04, 0x06, 0x02, 0x01, 0x7f};
+static unsigned char helvetica14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x07};
+static unsigned char helvetica14_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08};
+static unsigned char helvetica14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x07};
+static unsigned char helvetica14_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char helvetica14_95_bits[] = {
+0xff};
+static unsigned char helvetica14_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char helvetica14_97_bits[] = {
+0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_98_bits[] = {
+0x01, 0x01, 0x01, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1d};
+static unsigned char helvetica14_99_bits[] = {
+0x1e, 0x33, 0x01, 0x01, 0x01, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_100_bits[] = {
+0x20, 0x20, 0x20, 0x2e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_101_bits[] = {
+0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_102_bits[] = {
+0x0c, 0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_103_bits[] = {
+0x2e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e, 0x20, 0x33, 0x1e};
+static unsigned char helvetica14_104_bits[] = {
+0x01, 0x01, 0x01, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21};
+static unsigned char helvetica14_105_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_106_bits[] = {
+0x04, 0x04, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x03};
+static unsigned char helvetica14_107_bits[] = {
+0x01, 0x01, 0x01, 0x11, 0x09, 0x05, 0x03, 0x05, 0x09, 0x11, 0x21};
+static unsigned char helvetica14_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_109_bits[] = {
+0xcd, 0x00, 0x33, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 
+0x11, 0x01, 0x11, 0x01};
+static unsigned char helvetica14_110_bits[] = {
+0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21};
+static unsigned char helvetica14_111_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_112_bits[] = {
+0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_113_bits[] = {
+0x2e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e, 0x20, 0x20, 0x20};
+static unsigned char helvetica14_114_bits[] = {
+0x0d, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_115_bits[] = {
+0x0e, 0x11, 0x03, 0x0e, 0x18, 0x10, 0x11, 0x0e};
+static unsigned char helvetica14_116_bits[] = {
+0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char helvetica14_117_bits[] = {
+0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_118_bits[] = {
+0x41, 0x41, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08};
+static unsigned char helvetica14_119_bits[] = {
+0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0xaa, 0x00, 
+0x44, 0x00, 0x44, 0x00};
+static unsigned char helvetica14_120_bits[] = {
+0x63, 0x22, 0x14, 0x08, 0x08, 0x14, 0x22, 0x63};
+static unsigned char helvetica14_121_bits[] = {
+0x41, 0x43, 0x22, 0x22, 0x24, 0x14, 0x18, 0x08, 0x08, 0x0c, 0x06};
+static unsigned char helvetica14_122_bits[] = {
+0x3f, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x3f};
+static unsigned char helvetica14_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x18};
+static unsigned char helvetica14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x03};
+static unsigned char helvetica14_126_bits[] = {
+0x26, 0x2d, 0x19};
+static unsigned char helvetica14_127_bits[] = {
+0x00};
+static unsigned char helvetica14_128_bits[] = {
+0x00};
+static unsigned char helvetica14_129_bits[] = {
+0x00};
+static unsigned char helvetica14_130_bits[] = {
+0x00};
+static unsigned char helvetica14_131_bits[] = {
+0x00};
+static unsigned char helvetica14_132_bits[] = {
+0x00};
+static unsigned char helvetica14_133_bits[] = {
+0x00};
+static unsigned char helvetica14_134_bits[] = {
+0x00};
+static unsigned char helvetica14_135_bits[] = {
+0x00};
+static unsigned char helvetica14_136_bits[] = {
+0x00};
+static unsigned char helvetica14_137_bits[] = {
+0x00};
+static unsigned char helvetica14_138_bits[] = {
+0x00};
+static unsigned char helvetica14_139_bits[] = {
+0x00};
+static unsigned char helvetica14_140_bits[] = {
+0x00};
+static unsigned char helvetica14_141_bits[] = {
+0x00};
+static unsigned char helvetica14_142_bits[] = {
+0x00};
+static unsigned char helvetica14_143_bits[] = {
+0x00};
+static unsigned char helvetica14_144_bits[] = {
+0x00};
+static unsigned char helvetica14_145_bits[] = {
+0x00};
+static unsigned char helvetica14_146_bits[] = {
+0x00};
+static unsigned char helvetica14_147_bits[] = {
+0x00};
+static unsigned char helvetica14_148_bits[] = {
+0x00};
+static unsigned char helvetica14_149_bits[] = {
+0x00};
+static unsigned char helvetica14_150_bits[] = {
+0x00};
+static unsigned char helvetica14_151_bits[] = {
+0x00};
+static unsigned char helvetica14_152_bits[] = {
+0x00};
+static unsigned char helvetica14_153_bits[] = {
+0x00};
+static unsigned char helvetica14_154_bits[] = {
+0x00};
+static unsigned char helvetica14_155_bits[] = {
+0x00};
+static unsigned char helvetica14_156_bits[] = {
+0x00};
+static unsigned char helvetica14_157_bits[] = {
+0x00};
+static unsigned char helvetica14_158_bits[] = {
+0x00};
+static unsigned char helvetica14_159_bits[] = {
+0x00};
+static unsigned char helvetica14_160_bits[] = {
+0x00};
+static unsigned char helvetica14_161_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_162_bits[] = {
+0x20, 0x1e, 0x33, 0x09, 0x09, 0x05, 0x25, 0x33, 0x1e, 0x01};
+static unsigned char helvetica14_163_bits[] = {
+0x1c, 0x22, 0x02, 0x02, 0x1f, 0x04, 0x04, 0x04, 0x02, 0x46, 0x3b};
+static unsigned char helvetica14_164_bits[] = {
+0x21, 0x1e, 0x12, 0x12, 0x1e, 0x21};
+static unsigned char helvetica14_165_bits[] = {
+0x41, 0x41, 0x41, 0x22, 0x22, 0x14, 0x7f, 0x08, 0x7f, 0x08, 0x08};
+static unsigned char helvetica14_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_167_bits[] = {
+0x0e, 0x1b, 0x11, 0x03, 0x0e, 0x19, 0x11, 0x11, 0x13, 0x0e, 0x18, 0x11, 
+0x1b, 0x0e};
+static unsigned char helvetica14_168_bits[] = {
+0x1b};
+static unsigned char helvetica14_169_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x3a, 0x01, 0x45, 0x03, 0x45, 0x02, 0x05, 0x02, 
+0x45, 0x02, 0x39, 0x02, 0x02, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char helvetica14_170_bits[] = {
+0x07, 0x08, 0x0e, 0x09, 0x0b, 0x00, 0x0f};
+static unsigned char helvetica14_171_bits[] = {
+0x24, 0x12, 0x09, 0x12, 0x24};
+static unsigned char helvetica14_172_bits[] = {
+0x7f, 0x40, 0x40, 0x40};
+static unsigned char helvetica14_173_bits[] = {
+0x07};
+static unsigned char helvetica14_174_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x3a, 0x01, 0x49, 0x02, 0x49, 0x02, 0x39, 0x02, 
+0x49, 0x02, 0x49, 0x02, 0x02, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char helvetica14_175_bits[] = {
+0x0f};
+static unsigned char helvetica14_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char helvetica14_177_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08, 0x00, 0x7f};
+static unsigned char helvetica14_178_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char helvetica14_179_bits[] = {
+0x06, 0x09, 0x04, 0x08, 0x09, 0x06};
+static unsigned char helvetica14_180_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica14_181_bits[] = {
+0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2d, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_182_bits[] = {
+0x7c, 0x2e, 0x2f, 0x2f, 0x2f, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x28, 
+0x28, 0x28};
+static unsigned char helvetica14_183_bits[] = {
+0x03};
+static unsigned char helvetica14_184_bits[] = {
+0x04, 0x09, 0x06};
+static unsigned char helvetica14_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_186_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x06, 0x00, 0x0f};
+static unsigned char helvetica14_187_bits[] = {
+0x09, 0x12, 0x24, 0x12, 0x09};
+static unsigned char helvetica14_188_bits[] = {
+0x42, 0x00, 0x43, 0x00, 0x22, 0x00, 0x22, 0x00, 0x12, 0x00, 0x12, 0x01, 
+0x90, 0x01, 0x48, 0x01, 0x28, 0x01, 0xe4, 0x03, 0x04, 0x01};
+static unsigned char helvetica14_189_bits[] = {
+0x42, 0x00, 0x43, 0x00, 0x22, 0x00, 0x22, 0x00, 0x12, 0x00, 0xd2, 0x00, 
+0x28, 0x01, 0x08, 0x01, 0x88, 0x00, 0x44, 0x00, 0xe4, 0x01};
+static unsigned char helvetica14_190_bits[] = {
+0x86, 0x00, 0x89, 0x00, 0x44, 0x00, 0x48, 0x00, 0x29, 0x00, 0x26, 0x02, 
+0x20, 0x03, 0x90, 0x02, 0x50, 0x02, 0xc8, 0x07, 0x08, 0x02};
+static unsigned char helvetica14_191_bits[] = {
+0x08, 0x08, 0x00, 0x08, 0x04, 0x02, 0x01, 0x21, 0x21, 0x33, 0x0c};
+static unsigned char helvetica14_192_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_193_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_194_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_195_bits[] = {
+0x58, 0x00, 0x34, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_196_bits[] = {
+0x6c, 0x00, 0x00, 0x00, 0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_197_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, 0x00, 0x30, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_198_bits[] = {
+0xf8, 0x0f, 0x48, 0x00, 0x48, 0x00, 0x44, 0x00, 0x44, 0x00, 0xc4, 0x0f, 
+0x7e, 0x00, 0x42, 0x00, 0x42, 0x00, 0x41, 0x00, 0xc1, 0x0f};
+static unsigned char helvetica14_199_bits[] = {
+0x38, 0xc6, 0x82, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0xc6, 0x38, 0x10, 
+0x24, 0x18};
+static unsigned char helvetica14_200_bits[] = {
+0x04, 0x08, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 
+0x01, 0x7f};
+static unsigned char helvetica14_201_bits[] = {
+0x10, 0x08, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 
+0x01, 0x7f};
+static unsigned char helvetica14_202_bits[] = {
+0x18, 0x24, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 
+0x01, 0x7f};
+static unsigned char helvetica14_203_bits[] = {
+0x36, 0x00, 0x7f, 0x01, 0x01, 0x01, 0x01, 0x3f, 0x01, 0x01, 0x01, 0x01, 
+0x7f};
+static unsigned char helvetica14_204_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x02};
+static unsigned char helvetica14_205_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_206_bits[] = {
+0x06, 0x09, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x02};
+static unsigned char helvetica14_207_bits[] = {
+0x1b, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04};
+static unsigned char helvetica14_208_bits[] = {
+0x3e, 0x00, 0xc2, 0x00, 0x82, 0x00, 0x02, 0x01, 0x02, 0x01, 0x0f, 0x01, 
+0x02, 0x01, 0x02, 0x01, 0x82, 0x00, 0xc2, 0x00, 0x3e, 0x00};
+static unsigned char helvetica14_209_bits[] = {
+0x58, 0x34, 0x00, 0x83, 0x85, 0x85, 0x89, 0x89, 0x91, 0x91, 0xa1, 0xa1, 
+0xc1, 0xc1};
+static unsigned char helvetica14_210_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_211_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_212_bits[] = {
+0x30, 0x00, 0x48, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_213_bits[] = {
+0x58, 0x00, 0x34, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 
+0xc6, 0x00, 0x38, 0x00};
+static unsigned char helvetica14_214_bits[] = {
+0xcc, 0x00, 0x00, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x82, 0x00, 0xc6, 0x00, 
+0x38, 0x00};
+static unsigned char helvetica14_215_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char helvetica14_216_bits[] = {
+0x70, 0x04, 0x8c, 0x03, 0x04, 0x01, 0x82, 0x02, 0x42, 0x02, 0x22, 0x02, 
+0x12, 0x02, 0x0a, 0x02, 0x04, 0x01, 0x8e, 0x01, 0x71, 0x00};
+static unsigned char helvetica14_217_bits[] = {
+0x08, 0x10, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 
+0x42, 0x3c};
+static unsigned char helvetica14_218_bits[] = {
+0x20, 0x10, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 
+0x42, 0x3c};
+static unsigned char helvetica14_219_bits[] = {
+0x18, 0x24, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 
+0x42, 0x3c};
+static unsigned char helvetica14_220_bits[] = {
+0x66, 0x00, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x3c};
+static unsigned char helvetica14_221_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x01, 0x01, 0x83, 0x01, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica14_222_bits[] = {
+0x01, 0x01, 0x3f, 0x61, 0x41, 0x41, 0x61, 0x3f, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_223_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0d, 0x09, 0x11, 0x11, 0x11, 0x11, 0x0d};
+static unsigned char helvetica14_224_bits[] = {
+0x04, 0x08, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_225_bits[] = {
+0x08, 0x04, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_226_bits[] = {
+0x0c, 0x12, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_227_bits[] = {
+0x2c, 0x1a, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_228_bits[] = {
+0x12, 0x12, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x00, 0x1e, 0x33, 0x20, 0x3e, 0x23, 0x21, 0x33, 0x6e};
+static unsigned char helvetica14_230_bits[] = {
+0xde, 0x03, 0x63, 0x06, 0x20, 0x04, 0xfe, 0x07, 0x23, 0x00, 0x21, 0x00, 
+0x73, 0x06, 0xde, 0x03};
+static unsigned char helvetica14_231_bits[] = {
+0x1e, 0x33, 0x01, 0x01, 0x01, 0x21, 0x33, 0x1e, 0x08, 0x12, 0x0c};
+static unsigned char helvetica14_232_bits[] = {
+0x04, 0x08, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_233_bits[] = {
+0x08, 0x04, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_234_bits[] = {
+0x0c, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_235_bits[] = {
+0x12, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x3f, 0x01, 0x01, 0x33, 0x1e};
+static unsigned char helvetica14_236_bits[] = {
+0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica14_238_bits[] = {
+0x06, 0x09, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_239_bits[] = {
+0x05, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica14_240_bits[] = {
+0x1b, 0x0e, 0x09, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_241_bits[] = {
+0x16, 0x0d, 0x00, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21};
+static unsigned char helvetica14_242_bits[] = {
+0x04, 0x08, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_243_bits[] = {
+0x08, 0x04, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_244_bits[] = {
+0x0c, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_245_bits[] = {
+0x16, 0x0d, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_246_bits[] = {
+0x12, 0x12, 0x00, 0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char helvetica14_247_bits[] = {
+0x08, 0x08, 0x00, 0x7f, 0x00, 0x08, 0x08};
+static unsigned char helvetica14_248_bits[] = {
+0xbc, 0x46, 0x62, 0x52, 0x4a, 0x46, 0x62, 0x3d};
+static unsigned char helvetica14_249_bits[] = {
+0x04, 0x08, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_250_bits[] = {
+0x08, 0x04, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_251_bits[] = {
+0x0c, 0x12, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_252_bits[] = {
+0x12, 0x12, 0x00, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x2e};
+static unsigned char helvetica14_253_bits[] = {
+0x10, 0x08, 0x00, 0x41, 0x43, 0x22, 0x22, 0x24, 0x14, 0x18, 0x08, 0x08, 
+0x0c, 0x06};
+static unsigned char helvetica14_254_bits[] = {
+0x01, 0x01, 0x01, 0x1d, 0x33, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 
+0x01, 0x01};
+static unsigned char helvetica14_255_bits[] = {
+0x24, 0x24, 0x00, 0x41, 0x43, 0x22, 0x22, 0x24, 0x14, 0x18, 0x08, 0x08, 
+0x0c, 0x06};
+static RotFont helvetica14font[] = {
+{5, 1, 1, helvetica14_0_bits},
+{5, 1, 1, helvetica14_1_bits},
+{5, 1, 1, helvetica14_2_bits},
+{5, 1, 1, helvetica14_3_bits},
+{5, 1, 1, helvetica14_4_bits},
+{5, 1, 1, helvetica14_5_bits},
+{5, 1, 1, helvetica14_6_bits},
+{5, 1, 1, helvetica14_7_bits},
+{5, 1, 1, helvetica14_8_bits},
+{5, 1, 1, helvetica14_9_bits},
+{5, 1, 1, helvetica14_10_bits},
+{5, 1, 1, helvetica14_11_bits},
+{5, 1, 1, helvetica14_12_bits},
+{5, 1, 1, helvetica14_13_bits},
+{5, 1, 1, helvetica14_14_bits},
+{5, 1, 1, helvetica14_15_bits},
+{5, 1, 1, helvetica14_16_bits},
+{5, 1, 1, helvetica14_17_bits},
+{5, 1, 1, helvetica14_18_bits},
+{5, 1, 1, helvetica14_19_bits},
+{5, 1, 1, helvetica14_20_bits},
+{5, 1, 1, helvetica14_21_bits},
+{5, 1, 1, helvetica14_22_bits},
+{5, 1, 1, helvetica14_23_bits},
+{5, 1, 1, helvetica14_24_bits},
+{5, 1, 1, helvetica14_25_bits},
+{5, 1, 1, helvetica14_26_bits},
+{5, 1, 1, helvetica14_27_bits},
+{5, 1, 1, helvetica14_28_bits},
+{5, 1, 1, helvetica14_29_bits},
+{5, 1, 1, helvetica14_30_bits},
+{5, 1, 1, helvetica14_31_bits},
+{7, 1, 1, helvetica14_32_bits},
+{1, 11, 11, helvetica14_33_bits},
+{3, 3, 11, helvetica14_34_bits},
+{7, 10, 10, helvetica14_35_bits},
+{7, 14, 12, helvetica14_36_bits},
+{11, 11, 11, helvetica14_37_bits},
+{8, 10, 10, helvetica14_38_bits},
+{2, 3, 11, helvetica14_39_bits},
+{3, 14, 11, helvetica14_40_bits},
+{3, 14, 11, helvetica14_41_bits},
+{5, 5, 11, helvetica14_42_bits},
+{7, 7, 8, helvetica14_43_bits},
+{2, 4, 2, helvetica14_44_bits},
+{7, 1, 5, helvetica14_45_bits},
+{1, 2, 2, helvetica14_46_bits},
+{4, 11, 11, helvetica14_47_bits},
+{6, 11, 11, helvetica14_48_bits},
+{3, 11, 11, helvetica14_49_bits},
+{6, 11, 11, helvetica14_50_bits},
+{6, 11, 11, helvetica14_51_bits},
+{7, 11, 11, helvetica14_52_bits},
+{6, 11, 11, helvetica14_53_bits},
+{6, 11, 11, helvetica14_54_bits},
+{6, 11, 11, helvetica14_55_bits},
+{6, 11, 11, helvetica14_56_bits},
+{6, 11, 11, helvetica14_57_bits},
+{1, 8, 8, helvetica14_58_bits},
+{2, 10, 8, helvetica14_59_bits},
+{6, 5, 7, helvetica14_60_bits},
+{6, 3, 6, helvetica14_61_bits},
+{6, 5, 7, helvetica14_62_bits},
+{6, 11, 11, helvetica14_63_bits},
+{11, 12, 11, helvetica14_64_bits},
+{9, 11, 11, helvetica14_65_bits},
+{7, 11, 11, helvetica14_66_bits},
+{8, 11, 11, helvetica14_67_bits},
+{8, 11, 11, helvetica14_68_bits},
+{7, 11, 11, helvetica14_69_bits},
+{7, 11, 11, helvetica14_70_bits},
+{9, 11, 11, helvetica14_71_bits},
+{8, 11, 11, helvetica14_72_bits},
+{1, 11, 11, helvetica14_73_bits},
+{6, 11, 11, helvetica14_74_bits},
+{8, 11, 11, helvetica14_75_bits},
+{6, 11, 11, helvetica14_76_bits},
+{11, 11, 11, helvetica14_77_bits},
+{8, 11, 11, helvetica14_78_bits},
+{9, 11, 11, helvetica14_79_bits},
+{7, 11, 11, helvetica14_80_bits},
+{9, 11, 11, helvetica14_81_bits},
+{8, 11, 11, helvetica14_82_bits},
+{7, 11, 11, helvetica14_83_bits},
+{9, 11, 11, helvetica14_84_bits},
+{8, 11, 11, helvetica14_85_bits},
+{9, 11, 11, helvetica14_86_bits},
+{13, 11, 11, helvetica14_87_bits},
+{9, 11, 11, helvetica14_88_bits},
+{9, 11, 11, helvetica14_89_bits},
+{7, 11, 11, helvetica14_90_bits},
+{3, 14, 11, helvetica14_91_bits},
+{4, 11, 11, helvetica14_92_bits},
+{3, 14, 11, helvetica14_93_bits},
+{5, 5, 11, helvetica14_94_bits},
+{8, 1, -2, helvetica14_95_bits},
+{2, 3, 11, helvetica14_96_bits},
+{7, 8, 8, helvetica14_97_bits},
+{6, 11, 11, helvetica14_98_bits},
+{6, 8, 8, helvetica14_99_bits},
+{6, 11, 11, helvetica14_100_bits},
+{6, 8, 8, helvetica14_101_bits},
+{4, 11, 11, helvetica14_102_bits},
+{6, 11, 8, helvetica14_103_bits},
+{6, 11, 11, helvetica14_104_bits},
+{1, 11, 11, helvetica14_105_bits},
+{3, 14, 11, helvetica14_106_bits},
+{6, 11, 11, helvetica14_107_bits},
+{1, 11, 11, helvetica14_108_bits},
+{9, 8, 8, helvetica14_109_bits},
+{6, 8, 8, helvetica14_110_bits},
+{6, 8, 8, helvetica14_111_bits},
+{6, 11, 8, helvetica14_112_bits},
+{6, 11, 8, helvetica14_113_bits},
+{4, 8, 8, helvetica14_114_bits},
+{5, 8, 8, helvetica14_115_bits},
+{4, 10, 10, helvetica14_116_bits},
+{6, 8, 8, helvetica14_117_bits},
+{7, 8, 8, helvetica14_118_bits},
+{9, 8, 8, helvetica14_119_bits},
+{7, 8, 8, helvetica14_120_bits},
+{7, 11, 8, helvetica14_121_bits},
+{6, 8, 8, helvetica14_122_bits},
+{5, 14, 11, helvetica14_123_bits},
+{1, 14, 11, helvetica14_124_bits},
+{5, 14, 11, helvetica14_125_bits},
+{6, 3, 6, helvetica14_126_bits},
+{5, 1, 1, helvetica14_127_bits},
+{5, 1, 1, helvetica14_128_bits},
+{5, 1, 1, helvetica14_129_bits},
+{5, 1, 1, helvetica14_130_bits},
+{5, 1, 1, helvetica14_131_bits},
+{5, 1, 1, helvetica14_132_bits},
+{5, 1, 1, helvetica14_133_bits},
+{5, 1, 1, helvetica14_134_bits},
+{5, 1, 1, helvetica14_135_bits},
+{5, 1, 1, helvetica14_136_bits},
+{5, 1, 1, helvetica14_137_bits},
+{5, 1, 1, helvetica14_138_bits},
+{5, 1, 1, helvetica14_139_bits},
+{5, 1, 1, helvetica14_140_bits},
+{5, 1, 1, helvetica14_141_bits},
+{5, 1, 1, helvetica14_142_bits},
+{5, 1, 1, helvetica14_143_bits},
+{5, 1, 1, helvetica14_144_bits},
+{5, 1, 1, helvetica14_145_bits},
+{5, 1, 1, helvetica14_146_bits},
+{5, 1, 1, helvetica14_147_bits},
+{5, 1, 1, helvetica14_148_bits},
+{5, 1, 1, helvetica14_149_bits},
+{5, 1, 1, helvetica14_150_bits},
+{5, 1, 1, helvetica14_151_bits},
+{5, 1, 1, helvetica14_152_bits},
+{5, 1, 1, helvetica14_153_bits},
+{5, 1, 1, helvetica14_154_bits},
+{5, 1, 1, helvetica14_155_bits},
+{5, 1, 1, helvetica14_156_bits},
+{5, 1, 1, helvetica14_157_bits},
+{5, 1, 1, helvetica14_158_bits},
+{5, 1, 1, helvetica14_159_bits},
+{1, 1, 1, helvetica14_160_bits},
+{1, 11, 8, helvetica14_161_bits},
+{6, 10, 9, helvetica14_162_bits},
+{7, 11, 11, helvetica14_163_bits},
+{6, 6, 8, helvetica14_164_bits},
+{7, 11, 11, helvetica14_165_bits},
+{1, 14, 11, helvetica14_166_bits},
+{5, 14, 11, helvetica14_167_bits},
+{5, 1, 10, helvetica14_168_bits},
+{10, 11, 11, helvetica14_169_bits},
+{4, 7, 11, helvetica14_170_bits},
+{6, 5, 7, helvetica14_171_bits},
+{7, 4, 6, helvetica14_172_bits},
+{3, 1, 5, helvetica14_173_bits},
+{10, 11, 11, helvetica14_174_bits},
+{4, 1, 10, helvetica14_175_bits},
+{4, 4, 11, helvetica14_176_bits},
+{7, 9, 9, helvetica14_177_bits},
+{4, 6, 11, helvetica14_178_bits},
+{4, 6, 11, helvetica14_179_bits},
+{2, 2, 11, helvetica14_180_bits},
+{6, 11, 8, helvetica14_181_bits},
+{7, 14, 11, helvetica14_182_bits},
+{2, 1, 5, helvetica14_183_bits},
+{4, 3, 0, helvetica14_184_bits},
+{2, 6, 11, helvetica14_185_bits},
+{4, 7, 11, helvetica14_186_bits},
+{6, 5, 7, helvetica14_187_bits},
+{10, 11, 11, helvetica14_188_bits},
+{9, 11, 11, helvetica14_189_bits},
+{11, 11, 11, helvetica14_190_bits},
+{6, 11, 8, helvetica14_191_bits},
+{9, 14, 14, helvetica14_192_bits},
+{9, 14, 14, helvetica14_193_bits},
+{9, 14, 14, helvetica14_194_bits},
+{9, 14, 14, helvetica14_195_bits},
+{9, 13, 13, helvetica14_196_bits},
+{9, 14, 14, helvetica14_197_bits},
+{12, 11, 11, helvetica14_198_bits},
+{8, 14, 11, helvetica14_199_bits},
+{7, 14, 14, helvetica14_200_bits},
+{7, 14, 14, helvetica14_201_bits},
+{7, 14, 14, helvetica14_202_bits},
+{7, 13, 13, helvetica14_203_bits},
+{2, 14, 14, helvetica14_204_bits},
+{2, 14, 14, helvetica14_205_bits},
+{4, 14, 14, helvetica14_206_bits},
+{5, 13, 13, helvetica14_207_bits},
+{9, 11, 11, helvetica14_208_bits},
+{8, 14, 14, helvetica14_209_bits},
+{9, 14, 14, helvetica14_210_bits},
+{9, 14, 14, helvetica14_211_bits},
+{9, 14, 14, helvetica14_212_bits},
+{9, 14, 14, helvetica14_213_bits},
+{9, 13, 13, helvetica14_214_bits},
+{7, 7, 8, helvetica14_215_bits},
+{11, 11, 11, helvetica14_216_bits},
+{8, 14, 14, helvetica14_217_bits},
+{8, 14, 14, helvetica14_218_bits},
+{8, 14, 14, helvetica14_219_bits},
+{8, 13, 13, helvetica14_220_bits},
+{9, 14, 14, helvetica14_221_bits},
+{7, 11, 11, helvetica14_222_bits},
+{5, 11, 11, helvetica14_223_bits},
+{7, 11, 11, helvetica14_224_bits},
+{7, 11, 11, helvetica14_225_bits},
+{7, 11, 11, helvetica14_226_bits},
+{7, 11, 11, helvetica14_227_bits},
+{7, 11, 11, helvetica14_228_bits},
+{7, 12, 12, helvetica14_229_bits},
+{11, 8, 8, helvetica14_230_bits},
+{6, 11, 8, helvetica14_231_bits},
+{6, 11, 11, helvetica14_232_bits},
+{6, 11, 11, helvetica14_233_bits},
+{6, 11, 11, helvetica14_234_bits},
+{6, 11, 11, helvetica14_235_bits},
+{2, 11, 11, helvetica14_236_bits},
+{2, 11, 11, helvetica14_237_bits},
+{4, 11, 11, helvetica14_238_bits},
+{3, 11, 11, helvetica14_239_bits},
+{6, 11, 11, helvetica14_240_bits},
+{6, 11, 11, helvetica14_241_bits},
+{6, 11, 11, helvetica14_242_bits},
+{6, 11, 11, helvetica14_243_bits},
+{6, 11, 11, helvetica14_244_bits},
+{6, 11, 11, helvetica14_245_bits},
+{6, 11, 11, helvetica14_246_bits},
+{7, 7, 8, helvetica14_247_bits},
+{8, 8, 8, helvetica14_248_bits},
+{6, 11, 11, helvetica14_249_bits},
+{6, 11, 11, helvetica14_250_bits},
+{6, 11, 11, helvetica14_251_bits},
+{6, 11, 11, helvetica14_252_bits},
+{7, 14, 11, helvetica14_253_bits},
+{6, 14, 11, helvetica14_254_bits},
+{7, 14, 11, helvetica14_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica18.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica18.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica18.bdf	(revision 16632)
@@ -0,0 +1,3830 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--18-180-75-75-P-98-ISO8859-1
+SIZE 18 75 75
+FONTBOUNDINGBOX 18 22 -1 -4
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 98
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 14
+X_HEIGHT 10
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 11-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--18-180-75-75-P-98-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 11
+DEFAULT_CHAR 32
+FONT_ASCENT 16
+FONT_DESCENT 5
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 14 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+80
+80
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 5 0 9
+BITMAP
+d8
+d8
+d8
+90
+90
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 13 0 0
+BITMAP
+0900
+0900
+0900
+7fc0
+7fc0
+1200
+1200
+1200
+ff80
+ff80
+2400
+2400
+2400
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 16 1 -2
+BITMAP
+0800
+3e00
+7f00
+cb00
+c800
+e800
+7800
+3e00
+0f00
+0980
+c980
+eb80
+7f00
+3e00
+0800
+0800
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+7860
+fcc0
+ccc0
+cd80
+fd80
+7b00
+0300
+0678
+06fc
+0ccc
+0ccc
+18fc
+1878
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 1 0
+BITMAP
+3c00
+7e00
+6600
+6600
+3c00
+7c00
+eec0
+c6c0
+c3c0
+c380
+e7c0
+7ee0
+3c70
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 5 1 9
+BITMAP
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 1 -4
+BITMAP
+10
+30
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+30
+10
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 1 -4
+BITMAP
+80
+c0
+60
+60
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 6 1 8
+BITMAP
+20
+20
+f8
+70
+70
+88
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+18
+18
+18
+18
+ff
+ff
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 5 1 -3
+BITMAP
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 8 2 1 4
+BITMAP
+ff
+ff
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 2 1 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 14 0 0
+BITMAP
+18
+18
+10
+10
+30
+30
+20
+20
+60
+60
+40
+40
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+66
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+66
+7e
+3c
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 5 13 2 0
+BITMAP
+18
+f8
+f8
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+fe
+c3
+03
+07
+0e
+1c
+38
+70
+e0
+c0
+ff
+ff
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+c3
+c3
+06
+1c
+1e
+07
+03
+c3
+c7
+7e
+3c
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 1 0
+BITMAP
+0300
+0700
+0f00
+1b00
+3300
+3300
+6300
+c300
+ff80
+ff80
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+fe
+fe
+c0
+c0
+fc
+fe
+c7
+03
+03
+c3
+c7
+fe
+7c
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7f
+63
+c0
+c0
+dc
+fe
+c3
+c3
+c3
+e3
+7e
+3c
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+ff
+ff
+03
+06
+0c
+0c
+18
+18
+30
+30
+30
+60
+60
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+e7
+c3
+c3
+66
+7e
+66
+c3
+c3
+e7
+7e
+3c
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+7e
+c7
+c3
+c3
+c3
+7f
+3b
+03
+03
+c6
+fe
+7c
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 10 1 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 13 1 -3
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+03
+0f
+3c
+70
+c0
+70
+3c
+0f
+03
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 7 6 2 2
+BITMAP
+fe
+fe
+00
+00
+fe
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+c0
+f0
+3c
+0e
+03
+0e
+3c
+f0
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 7 14 1 0
+BITMAP
+7c
+fe
+c6
+c6
+0e
+1c
+38
+30
+30
+30
+00
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 17 1 -3
+BITMAP
+03f0
+0ffc
+1c0e
+3006
+63b3
+6773
+c633
+cc63
+cc66
+cc66
+cccc
+cff8
+6770
+7000
+3800
+1ff0
+07e0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 14 0 0
+BITMAP
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c180
+ff80
+ffc0
+c0e0
+c060
+c060
+c0e0
+ffc0
+ff80
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+0f80
+3fe0
+7070
+6030
+e000
+c000
+c000
+c000
+c000
+e000
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c060
+c060
+c060
+c060
+c060
+c060
+c0c0
+c1c0
+ff80
+ff00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+0f80
+3fe0
+7070
+6030
+e030
+c000
+c000
+c1f0
+c1f0
+e030
+6030
+7070
+3ff0
+0fb0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+c060
+c060
+c060
+c060
+c060
+ffe0
+ffe0
+c060
+c060
+c060
+c060
+c060
+c060
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 14 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+03
+03
+03
+03
+03
+03
+03
+03
+03
+c3
+c3
+e7
+7e
+3c
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 14 1 0
+BITMAP
+c0e0
+c1c0
+c380
+c700
+ce00
+dc00
+f800
+fc00
+ce00
+c700
+c380
+c1c0
+c0e0
+c070
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ff
+ff
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 14 1 0
+BITMAP
+c00c
+c00c
+e01c
+e01c
+f03c
+f03c
+d86c
+d86c
+cccc
+cccc
+c48c
+c78c
+c30c
+c30c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+e060
+f060
+f060
+d860
+cc60
+cc60
+c660
+c660
+c360
+c1e0
+c1e0
+c0e0
+c060
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 14 1 0
+BITMAP
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c1c0
+ff80
+ff00
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 15 1 -1
+BITMAP
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e1b8
+61b0
+70f0
+3fe0
+0fb0
+0030
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c1c0
+ff80
+ff00
+c180
+c180
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+1f00
+7fc0
+e0e0
+c060
+e000
+7c00
+1f00
+03c0
+00e0
+0060
+c060
+e0e0
+7fc0
+3f00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ffc0
+ffc0
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+c030
+c030
+6060
+6060
+6060
+30c0
+30c0
+30c0
+1980
+1980
+1980
+0f00
+0f00
+0600
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 14 1 0
+BITMAP
+c183
+c183
+c183
+c3c3
+63c6
+6246
+6666
+6666
+366c
+366c
+342c
+1c38
+1818
+1818
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+e0e0
+60c0
+71c0
+3180
+1b00
+0e00
+0e00
+1b00
+3180
+71c0
+60c0
+e0e0
+c060
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 14 1 0
+BITMAP
+c030
+c030
+6060
+6060
+30c0
+30c0
+1980
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ffc0
+ffc0
+00c0
+0180
+0300
+0600
+0c00
+1c00
+1800
+3000
+6000
+c000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 18 1 -4
+BITMAP
+f0
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 14 0 0
+BITMAP
+c0
+c0
+40
+40
+60
+60
+20
+20
+30
+30
+10
+10
+18
+18
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 18 0 -4
+BITMAP
+f0
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 5 1 8
+BITMAP
+10
+38
+6c
+c6
+82
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 2 0 -4
+BITMAP
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 5 1 9
+BITMAP
+40
+80
+80
+c0
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+c000
+c000
+c000
+c000
+de00
+ff00
+e300
+c180
+c180
+c180
+c180
+e300
+ff00
+de00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3e
+7f
+63
+c0
+c0
+c0
+c0
+63
+7f
+3e
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0180
+0180
+0180
+0180
+3d80
+7f80
+6380
+c180
+c180
+c180
+c180
+6380
+7f80
+3d80
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 14 0 0
+BITMAP
+1c
+3c
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -4
+BITMAP
+3d80
+7f80
+6180
+c180
+c180
+c180
+c180
+6380
+7f80
+3d80
+0180
+6300
+7f00
+1c00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+ce
+df
+e3
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 14 1 0
+BITMAP
+c0
+c0
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 18 -1 -4
+BITMAP
+30
+30
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c6
+cc
+d8
+f0
+f8
+d8
+cc
+ce
+c6
+c7
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 14 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 10 1 0
+BITMAP
+cc60
+def0
+e730
+c630
+c630
+c630
+c630
+c630
+c630
+c630
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+ce
+df
+e3
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -4
+BITMAP
+de00
+ff00
+e300
+c180
+c180
+c180
+c180
+e300
+ff00
+de00
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 -4
+BITMAP
+3d80
+7f80
+6380
+c180
+c180
+c180
+c180
+6380
+7f80
+3d80
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 10 1 0
+BITMAP
+d8
+d8
+e0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+3c
+7e
+c6
+c0
+fc
+3e
+06
+c6
+fc
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 13 0 0
+BITMAP
+30
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+38
+18
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 10 1 0
+BITMAP
+c630
+c630
+c630
+6660
+6660
+6960
+2940
+39c0
+1980
+1980
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+c3
+e7
+66
+3c
+18
+18
+3c
+66
+e7
+c3
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -4
+BITMAP
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+18
+18
+70
+70
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+fe
+06
+0c
+18
+30
+60
+c0
+fe
+fe
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 18 0 -4
+BITMAP
+0c
+18
+30
+30
+30
+30
+30
+60
+c0
+60
+30
+30
+30
+30
+30
+30
+18
+0c
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 18 1 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 18 0 -4
+BITMAP
+c0
+60
+30
+30
+30
+30
+30
+18
+0c
+18
+30
+30
+30
+30
+30
+30
+60
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 3 1 4
+BITMAP
+33
+7e
+cc
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 14 2 -4
+BITMAP
+c0
+c0
+00
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -2
+BITMAP
+04
+04
+3e
+7f
+6b
+c8
+c8
+c8
+c8
+6b
+7f
+3e
+10
+10
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 0 0
+BITMAP
+1e00
+3f00
+6180
+6180
+6000
+3000
+7e00
+1800
+1800
+3000
+6080
+ff80
+df00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 3
+BITMAP
+c3
+ff
+66
+66
+66
+ff
+c3
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+c3
+c3
+66
+66
+66
+3c
+ff
+18
+ff
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 17 1 -3
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+3c
+7e
+c3
+c3
+f0
+7c
+6e
+c7
+c3
+e3
+73
+3e
+0e
+07
+c3
+c3
+7e
+3c
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 2 0 11
+BITMAP
+d8
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+4710
+8888
+9008
+9008
+9008
+8888
+4710
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 8 1 6
+BITMAP
+70
+c8
+38
+48
+d8
+68
+00
+f8
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 8 1 1
+BITMAP
+12
+36
+6c
+d8
+d8
+6c
+36
+12
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 5 1 3
+BITMAP
+ff80
+ff80
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 2 1 4
+BITMAP
+f8
+f8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+4f90
+8848
+8848
+8f88
+8908
+8888
+4850
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 1 0 12
+BITMAP
+f8
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 5 1 8
+BITMAP
+70
+d8
+88
+d8
+70
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+18
+18
+18
+ff
+ff
+18
+18
+18
+00
+ff
+ff
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 8 0 5
+BITMAP
+70
+f8
+98
+18
+30
+60
+f8
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 8 0 5
+BITMAP
+70
+f8
+98
+30
+30
+98
+f8
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 3 0 11
+BITMAP
+30
+60
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -4
+BITMAP
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+e7
+ff
+db
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+3f
+72
+f2
+f2
+f2
+f2
+72
+32
+12
+12
+12
+12
+12
+12
+12
+12
+12
+12
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 4
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 5 0 -4
+BITMAP
+60
+70
+18
+d8
+f0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 3 8 1 5
+BITMAP
+60
+e0
+e0
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 8 1 6
+BITMAP
+70
+d8
+88
+88
+d8
+70
+00
+f8
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 8 1 1
+BITMAP
+90
+d8
+6c
+36
+36
+6c
+d8
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+6060
+e060
+e0c0
+6180
+6180
+6310
+6230
+6670
+0cf0
+0db0
+19f8
+3030
+3030
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+6060
+e060
+e0c0
+6180
+6180
+6370
+62f8
+6698
+0c18
+0c30
+1860
+30f8
+30f8
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 13 0 0
+BITMAP
+7030
+f830
+9860
+30c0
+30c0
+9988
+f918
+7338
+0678
+06d8
+0cfc
+1818
+1818
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 7 14 1 -4
+BITMAP
+18
+18
+00
+00
+18
+18
+18
+38
+70
+e0
+c6
+c6
+fe
+7c
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+1800
+0c00
+0600
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0180
+0300
+0600
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0600
+0f00
+1980
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0c80
+1680
+1300
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 17 0 0
+BITMAP
+1980
+1980
+0000
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 18 0 0
+BITMAP
+0f00
+1980
+1980
+0f00
+0600
+0600
+0f00
+0f00
+1980
+1980
+30c0
+30c0
+3fc0
+7fe0
+6060
+6060
+c030
+c030
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 14 1 0
+BITMAP
+07ff
+07ff
+0d80
+0d80
+1980
+1980
+31fe
+31fe
+3f80
+7f80
+6180
+6180
+c1ff
+c1ff
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 18 1 -4
+BITMAP
+0f80
+3fe0
+7070
+6030
+e000
+c000
+c000
+c000
+c000
+e000
+6030
+7070
+3fe0
+0f80
+0e00
+0300
+1b00
+1e00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 0
+BITMAP
+3000
+1800
+0c00
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 0
+BITMAP
+0300
+0600
+0c00
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 0
+BITMAP
+0c00
+1e00
+3300
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+3300
+3300
+0000
+ff80
+ff80
+c000
+c000
+c000
+c000
+ff00
+ff00
+c000
+c000
+c000
+c000
+ff80
+ff80
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 0 0
+BITMAP
+c0
+60
+30
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 18 2 0
+BITMAP
+30
+60
+c0
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 18 0 0
+BITMAP
+30
+78
+cc
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 17 0 0
+BITMAP
+cc
+cc
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 14 0 0
+BITMAP
+7f80
+7fc0
+60e0
+6060
+6030
+6030
+fc30
+fc30
+6030
+6030
+6060
+60e0
+7fc0
+7f80
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0c80
+1680
+1300
+0000
+e060
+e060
+f060
+d860
+d860
+cc60
+cc60
+c660
+c660
+c360
+c1e0
+c1e0
+c0e0
+c060
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+0c00
+0600
+0300
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+00c0
+0180
+0300
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+0300
+0780
+0cc0
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 18 1 0
+BITMAP
+0640
+0b40
+0980
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0d80
+0d80
+0000
+0f80
+3fe0
+7070
+6030
+e038
+c018
+c018
+c018
+c018
+e038
+6030
+7070
+3fe0
+0f80
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+c0c0
+6180
+3300
+1e00
+0c00
+1e00
+3300
+6180
+c0c0
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 14 0 0
+BITMAP
+07cc
+1ffc
+3838
+3078
+70dc
+61cc
+638c
+670c
+6e0c
+6c1c
+3818
+7838
+fff0
+c7c0
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1800
+0c00
+0600
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0300
+0600
+0c00
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0600
+0f00
+1980
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+1980
+1980
+0000
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 18 1 0
+BITMAP
+0180
+0300
+0600
+0000
+c030
+c030
+6060
+6060
+30c0
+30c0
+1980
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+c000
+c000
+c000
+ff00
+ff80
+c1c0
+c0c0
+c0c0
+c1c0
+ff80
+ff00
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+38
+7c
+c6
+c6
+c6
+c6
+dc
+dc
+c6
+c6
+c6
+c6
+de
+dc
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+60
+30
+18
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+0c
+18
+30
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+18
+3c
+66
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+32
+5a
+4c
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+6c
+6c
+00
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+38
+6c
+6c
+38
+7c
+ee
+c6
+0e
+7e
+e6
+c6
+c6
+ee
+76
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 10 1 0
+BITMAP
+7de0
+eff0
+c618
+0e18
+7ff8
+e600
+c600
+c718
+eff8
+75e0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 -4
+BITMAP
+3e
+7f
+63
+c0
+c0
+c0
+c0
+63
+7f
+3e
+38
+0c
+6c
+78
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+60
+30
+18
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+06
+0c
+18
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+18
+3c
+66
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+36
+36
+00
+3c
+7e
+c3
+c3
+ff
+c0
+c0
+e3
+7f
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 14 0 0
+BITMAP
+c0
+60
+30
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 14 0 0
+BITMAP
+30
+60
+c0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 6 14 -1 0
+BITMAP
+30
+78
+cc
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 5 13 0 0
+BITMAP
+d8
+d8
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+6000
+3600
+3800
+4c00
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+32
+5a
+4c
+00
+ce
+df
+e3
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+3000
+1800
+0c00
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0600
+0c00
+1800
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0c00
+1e00
+3300
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1900
+2d00
+2600
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+3600
+3600
+0000
+3e00
+7f00
+6300
+c180
+c180
+c180
+c180
+6300
+7f00
+3e00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+18
+18
+00
+ff
+ff
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 10 0 0
+BITMAP
+0e60
+3fc0
+3180
+63c0
+66c0
+6cc0
+78c0
+3180
+7f80
+ce00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+30
+18
+0c
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+06
+0c
+18
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+18
+3c
+66
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+66
+66
+00
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+c7
+fb
+73
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+06
+0c
+18
+00
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+18
+18
+70
+70
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 18 1 -4
+BITMAP
+c000
+c000
+c000
+c000
+de00
+ff00
+e300
+c180
+c180
+c180
+c180
+e300
+ff00
+de00
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 17 1 -4
+BITMAP
+66
+66
+00
+c3
+c3
+c3
+66
+66
+66
+24
+3c
+18
+18
+18
+18
+70
+70
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica18.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica18.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica18.h	(revision 16632)
@@ -0,0 +1,988 @@
+static unsigned char helvetica18_0_bits[] = {
+0x00};
+static unsigned char helvetica18_1_bits[] = {
+0x00};
+static unsigned char helvetica18_2_bits[] = {
+0x00};
+static unsigned char helvetica18_3_bits[] = {
+0x00};
+static unsigned char helvetica18_4_bits[] = {
+0x00};
+static unsigned char helvetica18_5_bits[] = {
+0x00};
+static unsigned char helvetica18_6_bits[] = {
+0x00};
+static unsigned char helvetica18_7_bits[] = {
+0x00};
+static unsigned char helvetica18_8_bits[] = {
+0x00};
+static unsigned char helvetica18_9_bits[] = {
+0x00};
+static unsigned char helvetica18_10_bits[] = {
+0x00};
+static unsigned char helvetica18_11_bits[] = {
+0x00};
+static unsigned char helvetica18_12_bits[] = {
+0x00};
+static unsigned char helvetica18_13_bits[] = {
+0x00};
+static unsigned char helvetica18_14_bits[] = {
+0x00};
+static unsigned char helvetica18_15_bits[] = {
+0x00};
+static unsigned char helvetica18_16_bits[] = {
+0x00};
+static unsigned char helvetica18_17_bits[] = {
+0x00};
+static unsigned char helvetica18_18_bits[] = {
+0x00};
+static unsigned char helvetica18_19_bits[] = {
+0x00};
+static unsigned char helvetica18_20_bits[] = {
+0x00};
+static unsigned char helvetica18_21_bits[] = {
+0x00};
+static unsigned char helvetica18_22_bits[] = {
+0x00};
+static unsigned char helvetica18_23_bits[] = {
+0x00};
+static unsigned char helvetica18_24_bits[] = {
+0x00};
+static unsigned char helvetica18_25_bits[] = {
+0x00};
+static unsigned char helvetica18_26_bits[] = {
+0x00};
+static unsigned char helvetica18_27_bits[] = {
+0x00};
+static unsigned char helvetica18_28_bits[] = {
+0x00};
+static unsigned char helvetica18_29_bits[] = {
+0x00};
+static unsigned char helvetica18_30_bits[] = {
+0x00};
+static unsigned char helvetica18_31_bits[] = {
+0x00};
+static unsigned char helvetica18_32_bits[] = {
+0x00};
+static unsigned char helvetica18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 
+0x03, 0x03};
+static unsigned char helvetica18_34_bits[] = {
+0x1b, 0x1b, 0x1b, 0x09, 0x09};
+static unsigned char helvetica18_35_bits[] = {
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0xfe, 0x03, 0xfe, 0x03, 0x48, 0x00, 
+0x48, 0x00, 0x48, 0x00, 0xff, 0x01, 0xff, 0x01, 0x24, 0x00, 0x24, 0x00, 
+0x24, 0x00};
+static unsigned char helvetica18_36_bits[] = {
+0x10, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xd3, 0x00, 0x13, 0x00, 0x17, 0x00, 
+0x1e, 0x00, 0x7c, 0x00, 0xf0, 0x00, 0x90, 0x01, 0x93, 0x01, 0xd7, 0x01, 
+0xfe, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char helvetica18_37_bits[] = {
+0x1e, 0x06, 0x3f, 0x03, 0x33, 0x03, 0xb3, 0x01, 0xbf, 0x01, 0xde, 0x00, 
+0xc0, 0x00, 0x60, 0x1e, 0x60, 0x3f, 0x30, 0x33, 0x30, 0x33, 0x18, 0x3f, 
+0x18, 0x1e};
+static unsigned char helvetica18_38_bits[] = {
+0x3c, 0x00, 0x7e, 0x00, 0x66, 0x00, 0x66, 0x00, 0x3c, 0x00, 0x3e, 0x00, 
+0x77, 0x03, 0x63, 0x03, 0xc3, 0x03, 0xc3, 0x01, 0xe7, 0x03, 0x7e, 0x07, 
+0x3c, 0x0e};
+static unsigned char helvetica18_39_bits[] = {
+0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica18_40_bits[] = {
+0x08, 0x0c, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x08};
+static unsigned char helvetica18_41_bits[] = {
+0x01, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x06, 0x06, 0x03, 0x01};
+static unsigned char helvetica18_42_bits[] = {
+0x04, 0x04, 0x1f, 0x0e, 0x0e, 0x11};
+static unsigned char helvetica18_43_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica18_44_bits[] = {
+0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica18_45_bits[] = {
+0xff, 0xff};
+static unsigned char helvetica18_46_bits[] = {
+0x03, 0x03};
+static unsigned char helvetica18_47_bits[] = {
+0x18, 0x18, 0x08, 0x08, 0x0c, 0x0c, 0x04, 0x04, 0x06, 0x06, 0x02, 0x02, 
+0x03, 0x03};
+static unsigned char helvetica18_48_bits[] = {
+0x3c, 0x7e, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x7e, 
+0x3c};
+static unsigned char helvetica18_49_bits[] = {
+0x18, 0x1f, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char helvetica18_50_bits[] = {
+0x3c, 0x7f, 0xc3, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x07, 0x03, 0xff, 
+0xff};
+static unsigned char helvetica18_51_bits[] = {
+0x3c, 0x7e, 0xc3, 0xc3, 0x60, 0x38, 0x78, 0xe0, 0xc0, 0xc3, 0xe3, 0x7e, 
+0x3c};
+static unsigned char helvetica18_52_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xd8, 0x00, 0xcc, 0x00, 0xcc, 0x00, 
+0xc6, 0x00, 0xc3, 0x00, 0xff, 0x01, 0xff, 0x01, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char helvetica18_53_bits[] = {
+0x7f, 0x7f, 0x03, 0x03, 0x3f, 0x7f, 0xe3, 0xc0, 0xc0, 0xc3, 0xe3, 0x7f, 
+0x3e};
+static unsigned char helvetica18_54_bits[] = {
+0x3c, 0xfe, 0xc6, 0x03, 0x03, 0x3b, 0x7f, 0xc3, 0xc3, 0xc3, 0xc7, 0x7e, 
+0x3c};
+static unsigned char helvetica18_55_bits[] = {
+0xff, 0xff, 0xc0, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 
+0x06};
+static unsigned char helvetica18_56_bits[] = {
+0x3c, 0x7e, 0xe7, 0xc3, 0xc3, 0x66, 0x7e, 0x66, 0xc3, 0xc3, 0xe7, 0x7e, 
+0x3c};
+static unsigned char helvetica18_57_bits[] = {
+0x3c, 0x7e, 0xe3, 0xc3, 0xc3, 0xc3, 0xfe, 0xdc, 0xc0, 0xc0, 0x63, 0x7f, 
+0x3e};
+static unsigned char helvetica18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char helvetica18_59_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02, 0x02, 
+0x01};
+static unsigned char helvetica18_60_bits[] = {
+0xc0, 0xf0, 0x3c, 0x0e, 0x03, 0x0e, 0x3c, 0xf0, 0xc0};
+static unsigned char helvetica18_61_bits[] = {
+0x7f, 0x7f, 0x00, 0x00, 0x7f, 0x7f};
+static unsigned char helvetica18_62_bits[] = {
+0x03, 0x0f, 0x3c, 0x70, 0xc0, 0x70, 0x3c, 0x0f, 0x03};
+static unsigned char helvetica18_63_bits[] = {
+0x3e, 0x7f, 0x63, 0x63, 0x70, 0x38, 0x1c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 
+0x0c, 0x0c};
+static unsigned char helvetica18_64_bits[] = {
+0xc0, 0x0f, 0xf0, 0x3f, 0x38, 0x70, 0x0c, 0x60, 0xc6, 0xcd, 0xe6, 0xce, 
+0x63, 0xcc, 0x33, 0xc6, 0x33, 0x66, 0x33, 0x66, 0x33, 0x33, 0xf3, 0x1f, 
+0xe6, 0x0e, 0x0e, 0x00, 0x1c, 0x00, 0xf8, 0x0f, 0xe0, 0x07};
+static unsigned char helvetica18_65_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 
+0x0c, 0x03, 0x0c, 0x03, 0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 
+0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_66_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x01, 
+0xff, 0x01, 0xff, 0x03, 0x03, 0x07, 0x03, 0x06, 0x03, 0x06, 0x03, 0x07, 
+0xff, 0x03, 0xff, 0x01};
+static unsigned char helvetica18_67_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_68_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xff, 0x00};
+static unsigned char helvetica18_69_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x00, 0xff, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_70_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x00, 0xff, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_71_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x0c, 0x03, 0x00, 
+0x03, 0x00, 0x83, 0x0f, 0x83, 0x0f, 0x07, 0x0c, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x0f, 0xf0, 0x0d};
+static unsigned char helvetica18_72_bits[] = {
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0xff, 0x07, 0xff, 0x07, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06};
+static unsigned char helvetica18_73_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_74_bits[] = {
+0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc3, 0xc3, 0xe7, 
+0x7e, 0x3c};
+static unsigned char helvetica18_75_bits[] = {
+0x03, 0x07, 0x83, 0x03, 0xc3, 0x01, 0xe3, 0x00, 0x73, 0x00, 0x3b, 0x00, 
+0x1f, 0x00, 0x3f, 0x00, 0x73, 0x00, 0xe3, 0x00, 0xc3, 0x01, 0x83, 0x03, 
+0x03, 0x07, 0x03, 0x0e};
+static unsigned char helvetica18_76_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0xff, 0xff};
+static unsigned char helvetica18_77_bits[] = {
+0x03, 0x30, 0x03, 0x30, 0x07, 0x38, 0x07, 0x38, 0x0f, 0x3c, 0x0f, 0x3c, 
+0x1b, 0x36, 0x1b, 0x36, 0x33, 0x33, 0x33, 0x33, 0x23, 0x31, 0xe3, 0x31, 
+0xc3, 0x30, 0xc3, 0x30};
+static unsigned char helvetica18_78_bits[] = {
+0x03, 0x06, 0x07, 0x06, 0x0f, 0x06, 0x0f, 0x06, 0x1b, 0x06, 0x33, 0x06, 
+0x33, 0x06, 0x63, 0x06, 0x63, 0x06, 0xc3, 0x06, 0x83, 0x07, 0x83, 0x07, 
+0x03, 0x07, 0x03, 0x06};
+static unsigned char helvetica18_79_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_80_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xff, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_81_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x87, 0x1d, 0x86, 0x0d, 0x0e, 0x0f, 
+0xfc, 0x07, 0xf0, 0x0d, 0x00, 0x0c};
+static unsigned char helvetica18_82_bits[] = {
+0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xff, 0x00, 0x83, 0x01, 0x83, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_83_bits[] = {
+0xf8, 0x00, 0xfe, 0x03, 0x07, 0x07, 0x03, 0x06, 0x07, 0x00, 0x3e, 0x00, 
+0xf8, 0x00, 0xc0, 0x03, 0x00, 0x07, 0x00, 0x06, 0x03, 0x06, 0x07, 0x07, 
+0xfe, 0x03, 0xfc, 0x00};
+static unsigned char helvetica18_84_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00};
+static unsigned char helvetica18_85_bits[] = {
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 
+0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_86_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 
+0x0c, 0x03, 0x0c, 0x03, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0xf0, 0x00, 
+0xf0, 0x00, 0x60, 0x00};
+static unsigned char helvetica18_87_bits[] = {
+0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0xc3, 0xc3, 0xc6, 0x63, 0x46, 0x62, 
+0x66, 0x66, 0x66, 0x66, 0x6c, 0x36, 0x6c, 0x36, 0x2c, 0x34, 0x38, 0x1c, 
+0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica18_88_bits[] = {
+0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8e, 0x03, 0x8c, 0x01, 0xd8, 0x00, 
+0x70, 0x00, 0x70, 0x00, 0xd8, 0x00, 0x8c, 0x01, 0x8e, 0x03, 0x06, 0x03, 
+0x07, 0x07, 0x03, 0x06};
+static unsigned char helvetica18_89_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0x0c, 0x03, 
+0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica18_90_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x38, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 
+0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica18_91_bits[] = {
+0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f};
+static unsigned char helvetica18_92_bits[] = {
+0x03, 0x03, 0x02, 0x02, 0x06, 0x06, 0x04, 0x04, 0x0c, 0x0c, 0x08, 0x08, 
+0x18, 0x18};
+static unsigned char helvetica18_93_bits[] = {
+0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f};
+static unsigned char helvetica18_94_bits[] = {
+0x08, 0x1c, 0x36, 0x63, 0x41};
+static unsigned char helvetica18_95_bits[] = {
+0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica18_96_bits[] = {
+0x02, 0x01, 0x01, 0x03, 0x03};
+static unsigned char helvetica18_97_bits[] = {
+0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 0x77, 0x6e};
+static unsigned char helvetica18_98_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x7b, 0x00, 0xff, 0x00, 
+0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc7, 0x00, 
+0xff, 0x00, 0x7b, 0x00};
+static unsigned char helvetica18_99_bits[] = {
+0x7c, 0xfe, 0xc6, 0x03, 0x03, 0x03, 0x03, 0xc6, 0xfe, 0x7c};
+static unsigned char helvetica18_100_bits[] = {
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xbc, 0x01, 0xfe, 0x01, 
+0xc6, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x01, 
+0xfe, 0x01, 0xbc, 0x01};
+static unsigned char helvetica18_101_bits[] = {
+0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 0xfe, 0x3c};
+static unsigned char helvetica18_102_bits[] = {
+0x38, 0x3c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c};
+static unsigned char helvetica18_103_bits[] = {
+0xbc, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc6, 0x01, 0xfe, 0x01, 0xbc, 0x01, 0x80, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x38, 0x00};
+static unsigned char helvetica18_104_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x73, 0xfb, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 
+0xc3, 0xc3};
+static unsigned char helvetica18_105_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_106_bits[] = {
+0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x07};
+static unsigned char helvetica18_107_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x63, 0x33, 0x1b, 0x0f, 0x1f, 0x1b, 0x33, 0x73, 
+0x63, 0xe3};
+static unsigned char helvetica18_108_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_109_bits[] = {
+0x33, 0x06, 0x7b, 0x0f, 0xe7, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c};
+static unsigned char helvetica18_110_bits[] = {
+0x73, 0xfb, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3};
+static unsigned char helvetica18_111_bits[] = {
+0x7c, 0x00, 0xfe, 0x00, 0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc6, 0x00, 0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_112_bits[] = {
+0x7b, 0x00, 0xff, 0x00, 0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc7, 0x00, 0xff, 0x00, 0x7b, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_113_bits[] = {
+0xbc, 0x01, 0xfe, 0x01, 0xc6, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0xc6, 0x01, 0xfe, 0x01, 0xbc, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01};
+static unsigned char helvetica18_114_bits[] = {
+0x1b, 0x1b, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_115_bits[] = {
+0x3c, 0x7e, 0x63, 0x03, 0x3f, 0x7c, 0x60, 0x63, 0x3f, 0x1e};
+static unsigned char helvetica18_116_bits[] = {
+0x0c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1c, 
+0x18};
+static unsigned char helvetica18_117_bits[] = {
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 0xdf, 0xce};
+static unsigned char helvetica18_118_bits[] = {
+0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18};
+static unsigned char helvetica18_119_bits[] = {
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x66, 0x06, 0x66, 0x06, 0x96, 0x06, 
+0x94, 0x02, 0x9c, 0x03, 0x98, 0x01, 0x98, 0x01};
+static unsigned char helvetica18_120_bits[] = {
+0xc3, 0xe7, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x66, 0xe7, 0xc3};
+static unsigned char helvetica18_121_bits[] = {
+0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 0x18, 0x18, 0x18, 
+0x0e, 0x0e};
+static unsigned char helvetica18_122_bits[] = {
+0x7f, 0x7f, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x7f, 0x7f};
+static unsigned char helvetica18_123_bits[] = {
+0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30};
+static unsigned char helvetica18_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_125_bits[] = {
+0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x18, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03};
+static unsigned char helvetica18_126_bits[] = {
+0xcc, 0x7e, 0x33};
+static unsigned char helvetica18_127_bits[] = {
+0x00};
+static unsigned char helvetica18_128_bits[] = {
+0x00};
+static unsigned char helvetica18_129_bits[] = {
+0x00};
+static unsigned char helvetica18_130_bits[] = {
+0x00};
+static unsigned char helvetica18_131_bits[] = {
+0x00};
+static unsigned char helvetica18_132_bits[] = {
+0x00};
+static unsigned char helvetica18_133_bits[] = {
+0x00};
+static unsigned char helvetica18_134_bits[] = {
+0x00};
+static unsigned char helvetica18_135_bits[] = {
+0x00};
+static unsigned char helvetica18_136_bits[] = {
+0x00};
+static unsigned char helvetica18_137_bits[] = {
+0x00};
+static unsigned char helvetica18_138_bits[] = {
+0x00};
+static unsigned char helvetica18_139_bits[] = {
+0x00};
+static unsigned char helvetica18_140_bits[] = {
+0x00};
+static unsigned char helvetica18_141_bits[] = {
+0x00};
+static unsigned char helvetica18_142_bits[] = {
+0x00};
+static unsigned char helvetica18_143_bits[] = {
+0x00};
+static unsigned char helvetica18_144_bits[] = {
+0x00};
+static unsigned char helvetica18_145_bits[] = {
+0x00};
+static unsigned char helvetica18_146_bits[] = {
+0x00};
+static unsigned char helvetica18_147_bits[] = {
+0x00};
+static unsigned char helvetica18_148_bits[] = {
+0x00};
+static unsigned char helvetica18_149_bits[] = {
+0x00};
+static unsigned char helvetica18_150_bits[] = {
+0x00};
+static unsigned char helvetica18_151_bits[] = {
+0x00};
+static unsigned char helvetica18_152_bits[] = {
+0x00};
+static unsigned char helvetica18_153_bits[] = {
+0x00};
+static unsigned char helvetica18_154_bits[] = {
+0x00};
+static unsigned char helvetica18_155_bits[] = {
+0x00};
+static unsigned char helvetica18_156_bits[] = {
+0x00};
+static unsigned char helvetica18_157_bits[] = {
+0x00};
+static unsigned char helvetica18_158_bits[] = {
+0x00};
+static unsigned char helvetica18_159_bits[] = {
+0x00};
+static unsigned char helvetica18_160_bits[] = {
+0x00};
+static unsigned char helvetica18_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_162_bits[] = {
+0x20, 0x20, 0x7c, 0xfe, 0xd6, 0x13, 0x13, 0x13, 0x13, 0xd6, 0xfe, 0x7c, 
+0x08, 0x08};
+static unsigned char helvetica18_163_bits[] = {
+0x78, 0x00, 0xfc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x06, 0x00, 0x0c, 0x00, 
+0x7e, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x01, 0xff, 0x01, 
+0xfb, 0x00};
+static unsigned char helvetica18_164_bits[] = {
+0xc3, 0xff, 0x66, 0x66, 0x66, 0xff, 0xc3};
+static unsigned char helvetica18_165_bits[] = {
+0xc3, 0xc3, 0x66, 0x66, 0x66, 0x3c, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char helvetica18_166_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_167_bits[] = {
+0x3c, 0x7e, 0xc3, 0xc3, 0x0f, 0x3e, 0x76, 0xe3, 0xc3, 0xc7, 0xce, 0x7c, 
+0x70, 0xe0, 0xc3, 0xc3, 0x7e, 0x3c};
+static unsigned char helvetica18_168_bits[] = {
+0x1b, 0x1b};
+static unsigned char helvetica18_169_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xe2, 0x08, 0x11, 0x11, 0x09, 0x10, 
+0x09, 0x10, 0x09, 0x10, 0x11, 0x11, 0xe2, 0x08, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char helvetica18_170_bits[] = {
+0x0e, 0x13, 0x1c, 0x12, 0x1b, 0x16, 0x00, 0x1f};
+static unsigned char helvetica18_171_bits[] = {
+0x48, 0x6c, 0x36, 0x1b, 0x1b, 0x36, 0x6c, 0x48};
+static unsigned char helvetica18_172_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
+static unsigned char helvetica18_173_bits[] = {
+0x1f, 0x1f};
+static unsigned char helvetica18_174_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xf2, 0x09, 0x11, 0x12, 0x11, 0x12, 
+0xf1, 0x11, 0x91, 0x10, 0x11, 0x11, 0x12, 0x0a, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char helvetica18_175_bits[] = {
+0x1f};
+static unsigned char helvetica18_176_bits[] = {
+0x0e, 0x1b, 0x11, 0x1b, 0x0e};
+static unsigned char helvetica18_177_bits[] = {
+0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18, 0x00, 0xff, 0xff};
+static unsigned char helvetica18_178_bits[] = {
+0x0e, 0x1f, 0x19, 0x18, 0x0c, 0x06, 0x1f, 0x1f};
+static unsigned char helvetica18_179_bits[] = {
+0x0e, 0x1f, 0x19, 0x0c, 0x0c, 0x19, 0x1f, 0x0e};
+static unsigned char helvetica18_180_bits[] = {
+0x0c, 0x06, 0x03};
+static unsigned char helvetica18_181_bits[] = {
+0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe7, 0xff, 0xdb, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica18_182_bits[] = {
+0xfc, 0x4e, 0x4f, 0x4f, 0x4f, 0x4f, 0x4e, 0x4c, 0x48, 0x48, 0x48, 0x48, 
+0x48, 0x48, 0x48, 0x48, 0x48, 0x48};
+static unsigned char helvetica18_183_bits[] = {
+0x03, 0x03};
+static unsigned char helvetica18_184_bits[] = {
+0x06, 0x0e, 0x18, 0x1b, 0x0f};
+static unsigned char helvetica18_185_bits[] = {
+0x06, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06};
+static unsigned char helvetica18_186_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1b, 0x0e, 0x00, 0x1f};
+static unsigned char helvetica18_187_bits[] = {
+0x09, 0x1b, 0x36, 0x6c, 0x6c, 0x36, 0x1b, 0x09};
+static unsigned char helvetica18_188_bits[] = {
+0x06, 0x06, 0x07, 0x06, 0x07, 0x03, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x08, 
+0x46, 0x0c, 0x66, 0x0e, 0x30, 0x0f, 0xb0, 0x0d, 0x98, 0x1f, 0x0c, 0x0c, 
+0x0c, 0x0c};
+static unsigned char helvetica18_189_bits[] = {
+0x06, 0x06, 0x07, 0x06, 0x07, 0x03, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x0e, 
+0x46, 0x1f, 0x66, 0x19, 0x30, 0x18, 0x30, 0x0c, 0x18, 0x06, 0x0c, 0x1f, 
+0x0c, 0x1f};
+static unsigned char helvetica18_190_bits[] = {
+0x0e, 0x0c, 0x1f, 0x0c, 0x19, 0x06, 0x0c, 0x03, 0x0c, 0x03, 0x99, 0x11, 
+0x9f, 0x18, 0xce, 0x1c, 0x60, 0x1e, 0x60, 0x1b, 0x30, 0x3f, 0x18, 0x18, 
+0x18, 0x18};
+static unsigned char helvetica18_191_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x18, 0x1c, 0x0e, 0x07, 0x63, 0x63, 
+0x7f, 0x3e};
+static unsigned char helvetica18_192_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_193_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_194_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_195_bits[] = {
+0x30, 0x01, 0x68, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_196_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x00, 
+0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 0xfc, 0x03, 
+0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_197_bits[] = {
+0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x0c, 0x03, 0x0c, 0x03, 
+0xfc, 0x03, 0xfe, 0x07, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char helvetica18_198_bits[] = {
+0xe0, 0xff, 0xe0, 0xff, 0xb0, 0x01, 0xb0, 0x01, 0x98, 0x01, 0x98, 0x01, 
+0x8c, 0x7f, 0x8c, 0x7f, 0xfc, 0x01, 0xfe, 0x01, 0x86, 0x01, 0x86, 0x01, 
+0x83, 0xff, 0x83, 0xff};
+static unsigned char helvetica18_199_bits[] = {
+0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x06, 0x0c, 0x0e, 0x0e, 
+0xfc, 0x07, 0xf0, 0x01, 0x70, 0x00, 0xc0, 0x00, 0xd8, 0x00, 0x78, 0x00};
+static unsigned char helvetica18_200_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_201_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_202_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_203_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01};
+static unsigned char helvetica18_204_bits[] = {
+0x03, 0x06, 0x0c, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica18_205_bits[] = {
+0x0c, 0x06, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica18_206_bits[] = {
+0x0c, 0x1e, 0x33, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica18_207_bits[] = {
+0x33, 0x33, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica18_208_bits[] = {
+0xfe, 0x01, 0xfe, 0x03, 0x06, 0x07, 0x06, 0x06, 0x06, 0x0c, 0x06, 0x0c, 
+0x3f, 0x0c, 0x3f, 0x0c, 0x06, 0x0c, 0x06, 0x0c, 0x06, 0x06, 0x06, 0x07, 
+0xfe, 0x03, 0xfe, 0x01};
+static unsigned char helvetica18_209_bits[] = {
+0x30, 0x01, 0x68, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x07, 0x06, 0x07, 0x06, 
+0x0f, 0x06, 0x1b, 0x06, 0x1b, 0x06, 0x33, 0x06, 0x33, 0x06, 0x63, 0x06, 
+0x63, 0x06, 0xc3, 0x06, 0x83, 0x07, 0x83, 0x07, 0x03, 0x07, 0x03, 0x06};
+static unsigned char helvetica18_210_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_211_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_212_bits[] = {
+0xc0, 0x00, 0xe0, 0x01, 0x30, 0x03, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_213_bits[] = {
+0x60, 0x02, 0xd0, 0x02, 0x90, 0x01, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 
+0x0e, 0x0e, 0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_214_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0xf0, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 
+0x06, 0x0c, 0x07, 0x1c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x07, 0x1c, 0x06, 0x0c, 0x0e, 0x0e, 0xfc, 0x07, 0xf0, 0x01};
+static unsigned char helvetica18_215_bits[] = {
+0x03, 0x03, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x78, 0x00, 
+0xcc, 0x00, 0x86, 0x01, 0x03, 0x03};
+static unsigned char helvetica18_216_bits[] = {
+0xe0, 0x33, 0xf8, 0x3f, 0x1c, 0x1c, 0x0c, 0x1e, 0x0e, 0x3b, 0x86, 0x33, 
+0xc6, 0x31, 0xe6, 0x30, 0x76, 0x30, 0x36, 0x38, 0x1c, 0x18, 0x1e, 0x1c, 
+0xff, 0x0f, 0xe3, 0x03};
+static unsigned char helvetica18_217_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_218_bits[] = {
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_219_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_220_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica18_221_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0x0c, 0x03, 0x98, 0x01, 0xf0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica18_222_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x00, 0xff, 0x01, 0x83, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xff, 0x01, 0xff, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_223_bits[] = {
+0x1c, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3b, 0x3b, 0x63, 0x63, 0x63, 0x63, 
+0x7b, 0x3b};
+static unsigned char helvetica18_224_bits[] = {
+0x06, 0x0c, 0x18, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_225_bits[] = {
+0x30, 0x18, 0x0c, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_226_bits[] = {
+0x18, 0x3c, 0x66, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_227_bits[] = {
+0x4c, 0x5a, 0x32, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_228_bits[] = {
+0x36, 0x36, 0x00, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 0x77, 
+0x6e};
+static unsigned char helvetica18_229_bits[] = {
+0x1c, 0x36, 0x36, 0x1c, 0x3e, 0x77, 0x63, 0x70, 0x7e, 0x67, 0x63, 0x63, 
+0x77, 0x6e};
+static unsigned char helvetica18_230_bits[] = {
+0xbe, 0x07, 0xf7, 0x0f, 0x63, 0x18, 0x70, 0x18, 0xfe, 0x1f, 0x67, 0x00, 
+0x63, 0x00, 0xe3, 0x18, 0xf7, 0x1f, 0xae, 0x07};
+static unsigned char helvetica18_231_bits[] = {
+0x7c, 0xfe, 0xc6, 0x03, 0x03, 0x03, 0x03, 0xc6, 0xfe, 0x7c, 0x1c, 0x30, 
+0x36, 0x1e};
+static unsigned char helvetica18_232_bits[] = {
+0x06, 0x0c, 0x18, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 
+0xfe, 0x3c};
+static unsigned char helvetica18_233_bits[] = {
+0x60, 0x30, 0x18, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 
+0xfe, 0x3c};
+static unsigned char helvetica18_234_bits[] = {
+0x18, 0x3c, 0x66, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 
+0xfe, 0x3c};
+static unsigned char helvetica18_235_bits[] = {
+0x6c, 0x6c, 0x00, 0x3c, 0x7e, 0xc3, 0xc3, 0xff, 0x03, 0x03, 0xc7, 0xfe, 
+0x3c};
+static unsigned char helvetica18_236_bits[] = {
+0x03, 0x06, 0x0c, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06};
+static unsigned char helvetica18_237_bits[] = {
+0x0c, 0x06, 0x03, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06};
+static unsigned char helvetica18_238_bits[] = {
+0x0c, 0x1e, 0x33, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c};
+static unsigned char helvetica18_239_bits[] = {
+0x1b, 0x1b, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06};
+static unsigned char helvetica18_240_bits[] = {
+0x06, 0x00, 0x6c, 0x00, 0x1c, 0x00, 0x32, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_241_bits[] = {
+0x4c, 0x5a, 0x32, 0x00, 0x73, 0xfb, 0xc7, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 
+0xc3, 0xc3};
+static unsigned char helvetica18_242_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_243_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_244_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_245_bits[] = {
+0x98, 0x00, 0xb4, 0x00, 0x64, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xc6, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 
+0xfe, 0x00, 0x7c, 0x00};
+static unsigned char helvetica18_246_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xc6, 0x00, 
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc6, 0x00, 0xfe, 0x00, 
+0x7c, 0x00};
+static unsigned char helvetica18_247_bits[] = {
+0x18, 0x18, 0x00, 0xff, 0xff, 0x00, 0x18, 0x18};
+static unsigned char helvetica18_248_bits[] = {
+0x70, 0x06, 0xfc, 0x03, 0x8c, 0x01, 0xc6, 0x03, 0x66, 0x03, 0x36, 0x03, 
+0x1e, 0x03, 0x8c, 0x01, 0xfe, 0x01, 0x73, 0x00};
+static unsigned char helvetica18_249_bits[] = {
+0x0c, 0x18, 0x30, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 
+0xdf, 0xce};
+static unsigned char helvetica18_250_bits[] = {
+0x60, 0x30, 0x18, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 
+0xdf, 0xce};
+static unsigned char helvetica18_251_bits[] = {
+0x18, 0x3c, 0x66, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 
+0xdf, 0xce};
+static unsigned char helvetica18_252_bits[] = {
+0x66, 0x66, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xe3, 0xdf, 
+0xce};
+static unsigned char helvetica18_253_bits[] = {
+0x60, 0x30, 0x18, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 
+0x18, 0x18, 0x18, 0x18, 0x0e, 0x0e};
+static unsigned char helvetica18_254_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x7b, 0x00, 0xff, 0x00, 
+0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc7, 0x00, 
+0xff, 0x00, 0x7b, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica18_255_bits[] = {
+0x66, 0x66, 0x00, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 0x66, 0x24, 0x3c, 0x18, 
+0x18, 0x18, 0x18, 0x0e, 0x0e};
+static RotFont helvetica18font[] = {
+{5, 1, 1, helvetica18_0_bits},
+{5, 1, 1, helvetica18_1_bits},
+{5, 1, 1, helvetica18_2_bits},
+{5, 1, 1, helvetica18_3_bits},
+{5, 1, 1, helvetica18_4_bits},
+{5, 1, 1, helvetica18_5_bits},
+{5, 1, 1, helvetica18_6_bits},
+{5, 1, 1, helvetica18_7_bits},
+{5, 1, 1, helvetica18_8_bits},
+{5, 1, 1, helvetica18_9_bits},
+{5, 1, 1, helvetica18_10_bits},
+{5, 1, 1, helvetica18_11_bits},
+{5, 1, 1, helvetica18_12_bits},
+{5, 1, 1, helvetica18_13_bits},
+{5, 1, 1, helvetica18_14_bits},
+{5, 1, 1, helvetica18_15_bits},
+{5, 1, 1, helvetica18_16_bits},
+{5, 1, 1, helvetica18_17_bits},
+{5, 1, 1, helvetica18_18_bits},
+{5, 1, 1, helvetica18_19_bits},
+{5, 1, 1, helvetica18_20_bits},
+{5, 1, 1, helvetica18_21_bits},
+{5, 1, 1, helvetica18_22_bits},
+{5, 1, 1, helvetica18_23_bits},
+{5, 1, 1, helvetica18_24_bits},
+{5, 1, 1, helvetica18_25_bits},
+{5, 1, 1, helvetica18_26_bits},
+{5, 1, 1, helvetica18_27_bits},
+{5, 1, 1, helvetica18_28_bits},
+{5, 1, 1, helvetica18_29_bits},
+{5, 1, 1, helvetica18_30_bits},
+{5, 1, 1, helvetica18_31_bits},
+{9, 1, 1, helvetica18_32_bits},
+{2, 14, 14, helvetica18_33_bits},
+{5, 5, 14, helvetica18_34_bits},
+{10, 13, 13, helvetica18_35_bits},
+{9, 16, 14, helvetica18_36_bits},
+{14, 13, 13, helvetica18_37_bits},
+{12, 13, 13, helvetica18_38_bits},
+{2, 5, 14, helvetica18_39_bits},
+{4, 18, 14, helvetica18_40_bits},
+{4, 18, 14, helvetica18_41_bits},
+{5, 6, 14, helvetica18_42_bits},
+{8, 10, 10, helvetica18_43_bits},
+{2, 5, 2, helvetica18_44_bits},
+{8, 2, 6, helvetica18_45_bits},
+{2, 2, 2, helvetica18_46_bits},
+{5, 14, 14, helvetica18_47_bits},
+{8, 13, 13, helvetica18_48_bits},
+{5, 13, 13, helvetica18_49_bits},
+{8, 13, 13, helvetica18_50_bits},
+{8, 13, 13, helvetica18_51_bits},
+{9, 13, 13, helvetica18_52_bits},
+{8, 13, 13, helvetica18_53_bits},
+{8, 13, 13, helvetica18_54_bits},
+{8, 13, 13, helvetica18_55_bits},
+{8, 13, 13, helvetica18_56_bits},
+{8, 13, 13, helvetica18_57_bits},
+{2, 10, 10, helvetica18_58_bits},
+{2, 13, 10, helvetica18_59_bits},
+{8, 9, 9, helvetica18_60_bits},
+{7, 6, 8, helvetica18_61_bits},
+{8, 9, 9, helvetica18_62_bits},
+{7, 14, 14, helvetica18_63_bits},
+{16, 17, 14, helvetica18_64_bits},
+{12, 14, 14, helvetica18_65_bits},
+{11, 14, 14, helvetica18_66_bits},
+{12, 14, 14, helvetica18_67_bits},
+{11, 14, 14, helvetica18_68_bits},
+{9, 14, 14, helvetica18_69_bits},
+{9, 14, 14, helvetica18_70_bits},
+{12, 14, 14, helvetica18_71_bits},
+{11, 14, 14, helvetica18_72_bits},
+{2, 14, 14, helvetica18_73_bits},
+{8, 14, 14, helvetica18_74_bits},
+{12, 14, 14, helvetica18_75_bits},
+{8, 14, 14, helvetica18_76_bits},
+{14, 14, 14, helvetica18_77_bits},
+{11, 14, 14, helvetica18_78_bits},
+{13, 14, 14, helvetica18_79_bits},
+{10, 14, 14, helvetica18_80_bits},
+{13, 15, 14, helvetica18_81_bits},
+{10, 14, 14, helvetica18_82_bits},
+{11, 14, 14, helvetica18_83_bits},
+{10, 14, 14, helvetica18_84_bits},
+{11, 14, 14, helvetica18_85_bits},
+{12, 14, 14, helvetica18_86_bits},
+{16, 14, 14, helvetica18_87_bits},
+{11, 14, 14, helvetica18_88_bits},
+{12, 14, 14, helvetica18_89_bits},
+{10, 14, 14, helvetica18_90_bits},
+{4, 18, 14, helvetica18_91_bits},
+{5, 14, 14, helvetica18_92_bits},
+{4, 18, 14, helvetica18_93_bits},
+{7, 5, 13, helvetica18_94_bits},
+{10, 2, -2, helvetica18_95_bits},
+{2, 5, 14, helvetica18_96_bits},
+{7, 10, 10, helvetica18_97_bits},
+{9, 14, 14, helvetica18_98_bits},
+{8, 10, 10, helvetica18_99_bits},
+{9, 14, 14, helvetica18_100_bits},
+{8, 10, 10, helvetica18_101_bits},
+{6, 14, 14, helvetica18_102_bits},
+{9, 14, 10, helvetica18_103_bits},
+{8, 14, 14, helvetica18_104_bits},
+{2, 14, 14, helvetica18_105_bits},
+{4, 18, 14, helvetica18_106_bits},
+{8, 14, 14, helvetica18_107_bits},
+{2, 14, 14, helvetica18_108_bits},
+{12, 10, 10, helvetica18_109_bits},
+{8, 10, 10, helvetica18_110_bits},
+{9, 10, 10, helvetica18_111_bits},
+{9, 14, 10, helvetica18_112_bits},
+{9, 14, 10, helvetica18_113_bits},
+{5, 10, 10, helvetica18_114_bits},
+{7, 10, 10, helvetica18_115_bits},
+{6, 13, 13, helvetica18_116_bits},
+{8, 10, 10, helvetica18_117_bits},
+{8, 10, 10, helvetica18_118_bits},
+{12, 10, 10, helvetica18_119_bits},
+{8, 10, 10, helvetica18_120_bits},
+{8, 14, 10, helvetica18_121_bits},
+{7, 10, 10, helvetica18_122_bits},
+{6, 18, 14, helvetica18_123_bits},
+{2, 18, 14, helvetica18_124_bits},
+{6, 18, 14, helvetica18_125_bits},
+{8, 3, 7, helvetica18_126_bits},
+{5, 1, 1, helvetica18_127_bits},
+{5, 1, 1, helvetica18_128_bits},
+{5, 1, 1, helvetica18_129_bits},
+{5, 1, 1, helvetica18_130_bits},
+{5, 1, 1, helvetica18_131_bits},
+{5, 1, 1, helvetica18_132_bits},
+{5, 1, 1, helvetica18_133_bits},
+{5, 1, 1, helvetica18_134_bits},
+{5, 1, 1, helvetica18_135_bits},
+{5, 1, 1, helvetica18_136_bits},
+{5, 1, 1, helvetica18_137_bits},
+{5, 1, 1, helvetica18_138_bits},
+{5, 1, 1, helvetica18_139_bits},
+{5, 1, 1, helvetica18_140_bits},
+{5, 1, 1, helvetica18_141_bits},
+{5, 1, 1, helvetica18_142_bits},
+{5, 1, 1, helvetica18_143_bits},
+{5, 1, 1, helvetica18_144_bits},
+{5, 1, 1, helvetica18_145_bits},
+{5, 1, 1, helvetica18_146_bits},
+{5, 1, 1, helvetica18_147_bits},
+{5, 1, 1, helvetica18_148_bits},
+{5, 1, 1, helvetica18_149_bits},
+{5, 1, 1, helvetica18_150_bits},
+{5, 1, 1, helvetica18_151_bits},
+{5, 1, 1, helvetica18_152_bits},
+{5, 1, 1, helvetica18_153_bits},
+{5, 1, 1, helvetica18_154_bits},
+{5, 1, 1, helvetica18_155_bits},
+{5, 1, 1, helvetica18_156_bits},
+{5, 1, 1, helvetica18_157_bits},
+{5, 1, 1, helvetica18_158_bits},
+{5, 1, 1, helvetica18_159_bits},
+{1, 1, 1, helvetica18_160_bits},
+{2, 14, 10, helvetica18_161_bits},
+{8, 14, 12, helvetica18_162_bits},
+{9, 13, 13, helvetica18_163_bits},
+{8, 7, 10, helvetica18_164_bits},
+{8, 13, 13, helvetica18_165_bits},
+{2, 17, 14, helvetica18_166_bits},
+{8, 18, 14, helvetica18_167_bits},
+{5, 2, 13, helvetica18_168_bits},
+{13, 13, 13, helvetica18_169_bits},
+{5, 8, 14, helvetica18_170_bits},
+{7, 8, 9, helvetica18_171_bits},
+{9, 5, 8, helvetica18_172_bits},
+{5, 2, 6, helvetica18_173_bits},
+{13, 13, 13, helvetica18_174_bits},
+{5, 1, 13, helvetica18_175_bits},
+{5, 5, 13, helvetica18_176_bits},
+{8, 11, 11, helvetica18_177_bits},
+{5, 8, 13, helvetica18_178_bits},
+{5, 8, 13, helvetica18_179_bits},
+{4, 3, 14, helvetica18_180_bits},
+{8, 14, 10, helvetica18_181_bits},
+{8, 18, 14, helvetica18_182_bits},
+{2, 2, 6, helvetica18_183_bits},
+{5, 5, 1, helvetica18_184_bits},
+{3, 8, 13, helvetica18_185_bits},
+{5, 8, 14, helvetica18_186_bits},
+{7, 8, 9, helvetica18_187_bits},
+{13, 13, 13, helvetica18_188_bits},
+{13, 13, 13, helvetica18_189_bits},
+{14, 13, 13, helvetica18_190_bits},
+{7, 14, 10, helvetica18_191_bits},
+{12, 18, 18, helvetica18_192_bits},
+{12, 18, 18, helvetica18_193_bits},
+{12, 18, 18, helvetica18_194_bits},
+{12, 18, 18, helvetica18_195_bits},
+{12, 17, 17, helvetica18_196_bits},
+{12, 18, 18, helvetica18_197_bits},
+{16, 14, 14, helvetica18_198_bits},
+{12, 18, 14, helvetica18_199_bits},
+{9, 18, 18, helvetica18_200_bits},
+{9, 18, 18, helvetica18_201_bits},
+{9, 18, 18, helvetica18_202_bits},
+{9, 17, 17, helvetica18_203_bits},
+{4, 18, 18, helvetica18_204_bits},
+{4, 18, 18, helvetica18_205_bits},
+{6, 18, 18, helvetica18_206_bits},
+{6, 17, 17, helvetica18_207_bits},
+{12, 14, 14, helvetica18_208_bits},
+{11, 18, 18, helvetica18_209_bits},
+{13, 18, 18, helvetica18_210_bits},
+{13, 18, 18, helvetica18_211_bits},
+{13, 18, 18, helvetica18_212_bits},
+{13, 18, 18, helvetica18_213_bits},
+{13, 17, 17, helvetica18_214_bits},
+{10, 9, 9, helvetica18_215_bits},
+{14, 14, 14, helvetica18_216_bits},
+{11, 18, 18, helvetica18_217_bits},
+{11, 18, 18, helvetica18_218_bits},
+{11, 18, 18, helvetica18_219_bits},
+{11, 17, 17, helvetica18_220_bits},
+{12, 18, 18, helvetica18_221_bits},
+{10, 14, 14, helvetica18_222_bits},
+{7, 14, 14, helvetica18_223_bits},
+{7, 14, 14, helvetica18_224_bits},
+{7, 14, 14, helvetica18_225_bits},
+{7, 14, 14, helvetica18_226_bits},
+{7, 14, 14, helvetica18_227_bits},
+{7, 13, 13, helvetica18_228_bits},
+{7, 14, 14, helvetica18_229_bits},
+{13, 10, 10, helvetica18_230_bits},
+{8, 14, 10, helvetica18_231_bits},
+{8, 14, 14, helvetica18_232_bits},
+{8, 14, 14, helvetica18_233_bits},
+{8, 14, 14, helvetica18_234_bits},
+{8, 13, 13, helvetica18_235_bits},
+{4, 14, 14, helvetica18_236_bits},
+{4, 14, 14, helvetica18_237_bits},
+{6, 14, 14, helvetica18_238_bits},
+{5, 13, 13, helvetica18_239_bits},
+{9, 14, 14, helvetica18_240_bits},
+{8, 14, 14, helvetica18_241_bits},
+{9, 14, 14, helvetica18_242_bits},
+{9, 14, 14, helvetica18_243_bits},
+{9, 14, 14, helvetica18_244_bits},
+{9, 14, 14, helvetica18_245_bits},
+{9, 13, 13, helvetica18_246_bits},
+{8, 8, 9, helvetica18_247_bits},
+{11, 10, 10, helvetica18_248_bits},
+{8, 14, 14, helvetica18_249_bits},
+{8, 14, 14, helvetica18_250_bits},
+{8, 14, 14, helvetica18_251_bits},
+{8, 13, 13, helvetica18_252_bits},
+{8, 18, 14, helvetica18_253_bits},
+{9, 18, 14, helvetica18_254_bits},
+{8, 17, 13, helvetica18_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica24.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica24.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica24.bdf	(revision 16632)
@@ -0,0 +1,4679 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--24-240-75-75-P-130-ISO8859-1
+SIZE 24 75 75
+FONTBOUNDINGBOX 25 29 -1 -5
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 240
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 130
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 19
+X_HEIGHT 14
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--24-240-75-75-P-130-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 15
+DEFAULT_CHAR 32
+FONT_ASCENT 22
+FONT_DESCENT 5
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+80
+80
+00
+00
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 6 1 13
+BITMAP
+cc
+cc
+cc
+cc
+cc
+44
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 17 2 0
+BITMAP
+0cc0
+0cc0
+0cc0
+1980
+ffe0
+ffe0
+1980
+1980
+3300
+3300
+ffe0
+ffe0
+3300
+3300
+6600
+6600
+6600
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 21 1 -2
+BITMAP
+0600
+0600
+3f80
+7fc0
+e6e0
+c660
+c600
+e600
+7600
+3e00
+0f80
+07c0
+06e0
+0660
+c660
+c660
+e6e0
+7fc0
+3f80
+0600
+0600
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 19 18 1 0
+BITMAP
+000600
+3c0c00
+7e0c00
+c31800
+c31800
+c33000
+c33000
+7e6000
+3c6000
+00c000
+00c780
+018fc0
+019860
+031860
+031860
+061860
+060fc0
+040780
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 14 18 1 0
+BITMAP
+0f00
+1f80
+39c0
+30c0
+30c0
+30c0
+1980
+0f00
+1e00
+3f18
+7398
+61d8
+c0f0
+c060
+c0f0
+e1d8
+7f9c
+1e00
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 6 2 13
+BITMAP
+c0
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 2 -5
+BITMAP
+18
+18
+30
+30
+60
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+60
+30
+30
+18
+18
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 1 -5
+BITMAP
+c0
+c0
+60
+60
+30
+30
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+30
+30
+30
+60
+60
+c0
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 7 1 12
+BITMAP
+10
+10
+d6
+7c
+38
+6c
+44
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 12 1 1
+BITMAP
+0600
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 6 2 -3
+BITMAP
+c0
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 11 2 2 6
+BITMAP
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 0
+BITMAP
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 19 0 0
+BITMAP
+06
+06
+06
+0c
+0c
+0c
+18
+18
+18
+18
+30
+30
+30
+60
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1f00
+3f80
+71c0
+60c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 6 18 2 0
+BITMAP
+0c
+0c
+1c
+fc
+fc
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1e00
+7f80
+61c0
+c0c0
+c060
+c060
+0060
+00c0
+01c0
+0380
+0f00
+1c00
+3800
+7000
+e000
+c000
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1f00
+7f80
+6180
+c0c0
+c0c0
+c0c0
+00c0
+0180
+0f00
+0fc0
+00c0
+0060
+0060
+c060
+c0c0
+61c0
+7f80
+1f00
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0180
+0380
+0380
+0780
+0f80
+0d80
+1980
+3980
+3180
+6180
+e180
+c180
+ffe0
+ffe0
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+7fc0
+7fc0
+6000
+6000
+6000
+6000
+6e00
+7f80
+71c0
+00c0
+0060
+0060
+0060
+c060
+c0c0
+e1c0
+7f80
+1e00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0f00
+3fc0
+70c0
+6060
+e060
+c000
+c000
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+e060
+60c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+ffe0
+ffe0
+00e0
+00c0
+0180
+0180
+0300
+0300
+0600
+0600
+0c00
+0c00
+1c00
+1800
+1800
+3800
+3000
+3000
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+0e00
+3f80
+3180
+60c0
+60c0
+60c0
+60c0
+3180
+1f00
+3f80
+60c0
+e0e0
+c060
+c060
+c060
+71c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1f00
+7fc0
+71c0
+e0c0
+c060
+c060
+c060
+c060
+e0e0
+71e0
+7f60
+1e60
+0060
+00e0
+c0c0
+e1c0
+7f80
+1e00
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 14 2 0
+BITMAP
+c0
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 17 2 -3
+BITMAP
+c0
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 12 1 1
+BITMAP
+0030
+00f0
+03c0
+0f00
+3c00
+e000
+e000
+3c00
+0f00
+03c0
+00f0
+0030
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 10 6 2 5
+BITMAP
+ffc0
+ffc0
+0000
+0000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 12 1 1
+BITMAP
+c000
+f000
+3c00
+0f00
+03c0
+0070
+0070
+03c0
+0f00
+3c00
+f000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 0
+BITMAP
+1f00
+7f80
+71c0
+e0c0
+c0c0
+c1c0
+0180
+0380
+0700
+0600
+0c00
+0c00
+0c00
+0c00
+0000
+0000
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 22 23 2 -4
+BITMAP
+00ff00
+03ffc0
+0f01e0
+1c0070
+380018
+300018
+60730c
+60fb0c
+c1c70c
+c3860c
+c3060c
+c6060c
+c60c1c
+c60c18
+c60c38
+e71c70
+63f7e0
+71e380
+380000
+1c0000
+0f0300
+07ff00
+00fc00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 19 1 0
+BITMAP
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 14 19 2 0
+BITMAP
+ffc0
+fff0
+c070
+c018
+c018
+c018
+c018
+c030
+ffe0
+fff0
+c018
+c00c
+c00c
+c00c
+c00c
+c01c
+c038
+fff0
+ffc0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e006
+c000
+c000
+c000
+c000
+c000
+c000
+c003
+e003
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 15 19 2 0
+BITMAP
+ffc0
+fff0
+c078
+c01c
+c00c
+c00e
+c006
+c006
+c006
+c006
+c006
+c006
+c006
+c00e
+c00c
+c01c
+c078
+fff0
+ffc0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 19 2 0
+BITMAP
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 0
+BITMAP
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ffc0
+ffc0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e006
+c000
+c000
+c000
+c07f
+c07f
+c003
+c003
+e003
+6007
+700f
+3c3f
+1ffb
+07e3
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 19 2 0
+BITMAP
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+fffc
+fffc
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 2 19 3 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 10 19 1 0
+BITMAP
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+00c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7f80
+3f00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 15 19 2 0
+BITMAP
+c038
+c070
+c0e0
+c1c0
+c380
+c700
+ce00
+dc00
+fc00
+fe00
+e700
+c380
+c1c0
+c0e0
+c070
+c038
+c01c
+c00e
+c006
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 840 0
+DWIDTH 21 0
+BBX 17 19 2 0
+BITMAP
+c00180
+e00380
+e00380
+f00780
+f00780
+d80d80
+d80d80
+d80d80
+cc1980
+cc1980
+cc1980
+c63180
+c63180
+c63180
+c36180
+c36180
+c36180
+c1c180
+c1c180
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 19 2 0
+BITMAP
+e00c
+f00c
+f00c
+d80c
+dc0c
+cc0c
+ce0c
+c60c
+c70c
+c30c
+c38c
+c18c
+c1cc
+c0cc
+c0ec
+c06c
+c03c
+c03c
+c01c
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 13 19 2 0
+BITMAP
+ffe0
+fff0
+c030
+c018
+c018
+c018
+c018
+c030
+fff0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 0
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+60e6
+707e
+3c1c
+1ffe
+07e7
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 13 19 2 0
+BITMAP
+ffe0
+fff0
+c030
+c018
+c018
+c018
+c018
+c030
+fff0
+ffe0
+c070
+c030
+c018
+c018
+c018
+c018
+c018
+c018
+c018
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 0
+BITMAP
+07c0
+1ff0
+3838
+7018
+6018
+6000
+7000
+3e00
+0fc0
+01f0
+0078
+001c
+000c
+c00c
+c00c
+e01c
+7838
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 0
+BITMAP
+fffc
+fffc
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 19 2 0
+BITMAP
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 19 1 0
+BITMAP
+c006
+c006
+e00e
+600c
+701c
+3018
+3018
+3838
+1830
+1830
+1c70
+0c60
+0c60
+0ee0
+06c0
+06c0
+0380
+0380
+0380
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 20 19 1 0
+BITMAP
+c06030
+c06030
+c06030
+c0f030
+60f060
+619860
+619860
+619860
+619860
+3198c0
+330cc0
+330cc0
+330cc0
+1b0d80
+1b0d80
+1e0780
+0e0700
+0c0300
+0c0300
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 19 1 0
+BITMAP
+c006
+e00e
+701c
+3018
+1830
+1c70
+0ee0
+07c0
+0380
+0380
+07c0
+0ee0
+0c60
+1c70
+3838
+3018
+600c
+e00e
+c006
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 0
+BITMAP
+c00c
+e01c
+6018
+7038
+3030
+3870
+1860
+1ce0
+0cc0
+0fc0
+0780
+0780
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 19 1 0
+BITMAP
+fff8
+fff8
+0038
+0070
+00e0
+01c0
+01c0
+0380
+0700
+0700
+0e00
+1c00
+1c00
+3800
+7000
+7000
+e000
+fff8
+fff8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 4 24 2 -5
+BITMAP
+f0
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 19 0 0
+BITMAP
+c0
+c0
+c0
+60
+60
+60
+30
+30
+30
+30
+18
+18
+18
+0c
+0c
+0c
+06
+06
+06
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 4 24 1 -5
+BITMAP
+f0
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 9 1 10
+BITMAP
+0c00
+0c00
+1e00
+1200
+3300
+6180
+6180
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 2 0 -5
+BITMAP
+fffc
+fffc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 6 2 13
+BITMAP
+40
+80
+80
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+c060
+c060
+c060
+e0c0
+f1c0
+df80
+cf00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+1f00
+3f80
+71c0
+60c0
+c000
+c000
+c000
+c000
+c000
+c000
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 1 0
+BITMAP
+0060
+0060
+0060
+0060
+0060
+1e60
+3f60
+71e0
+60e0
+c060
+c060
+c060
+c060
+c060
+c060
+60e0
+71e0
+3f60
+1e60
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 19 1 0
+BITMAP
+1c
+3c
+30
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 1 -5
+BITMAP
+1e60
+3f60
+71e0
+60e0
+c060
+c060
+c060
+c060
+c060
+c060
+60e0
+71e0
+3f60
+1e60
+0060
+c060
+e0c0
+7fc0
+1f00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 10 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+ce00
+df80
+f180
+e0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 0
+BITMAP
+c0
+c0
+c0
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 24 0 -5
+BITMAP
+30
+30
+30
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+e0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+c000
+c180
+c380
+c700
+ce00
+dc00
+f800
+fc00
+ce00
+c600
+c700
+c380
+c180
+c1c0
+c0c0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 16 14 2 0
+BITMAP
+ce3c
+ff7e
+e3c7
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+c183
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 14 2 0
+BITMAP
+ce00
+df80
+f180
+e0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 2 -5
+BITMAP
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+c060
+c060
+c060
+e0c0
+f1c0
+df80
+cf00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 19 1 -5
+BITMAP
+1e60
+3f60
+71e0
+60e0
+c060
+c060
+c060
+c060
+c060
+c060
+60e0
+71e0
+3f60
+1e60
+0060
+0060
+0060
+0060
+0060
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 6 14 2 0
+BITMAP
+cc
+dc
+fc
+e0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+3e00
+7f80
+e1c0
+c0c0
+c000
+f800
+7f00
+0f80
+01c0
+00c0
+c0c0
+c1c0
+ff80
+3f00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 18 1 0
+BITMAP
+30
+30
+30
+30
+fc
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+3c
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 14 2 0
+BITMAP
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 14 1 0
+BITMAP
+c060
+c060
+c060
+60c0
+60c0
+71c0
+3180
+3180
+1b00
+1b00
+1b00
+0e00
+0e00
+0e00
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 18 14 0 0
+BITMAP
+c0c0c0
+c0c0c0
+61e180
+61e180
+61e180
+312300
+333300
+333300
+1b3600
+1a1600
+1e1e00
+0e1c00
+0c0c00
+0c0c00
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+c0c0
+e1c0
+6180
+3300
+3f00
+1e00
+0c00
+1e00
+1e00
+3300
+7380
+6180
+e1c0
+c0c0
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 19 0 -5
+BITMAP
+c030
+c030
+6030
+7060
+3060
+38e0
+18c0
+18c0
+0d80
+0d80
+0780
+0700
+0300
+0300
+0600
+0600
+0c00
+3c00
+3800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+ffc0
+ffc0
+0180
+0300
+0700
+0e00
+0c00
+1c00
+3800
+3000
+6000
+e000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 24 1 -5
+BITMAP
+0c
+18
+30
+30
+30
+30
+30
+30
+30
+30
+60
+c0
+c0
+60
+30
+30
+30
+30
+30
+30
+30
+30
+18
+0c
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 24 2 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 24 1 -5
+BITMAP
+c0
+60
+30
+30
+30
+30
+30
+30
+30
+30
+18
+0c
+0c
+18
+30
+30
+30
+30
+30
+30
+30
+30
+60
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 4 2 5
+BITMAP
+70c0
+fcc0
+cfc0
+c380
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 19 2 -5
+BITMAP
+c0
+c0
+c0
+00
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 10 18 1 -2
+BITMAP
+0180
+0180
+1f00
+3f80
+73c0
+66c0
+c600
+cc00
+cc00
+cc00
+d800
+d800
+d8c0
+71c0
+7f80
+3f00
+6000
+6000
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 1 0
+BITMAP
+1f80
+3fe0
+7070
+6030
+6000
+7000
+3000
+1800
+ff80
+ff80
+1800
+1800
+1800
+3000
+3000
+6730
+fff0
+f0e0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 3
+BITMAP
+c060
+eee0
+7fc0
+3180
+60c0
+60c0
+60c0
+60c0
+3180
+7fc0
+eee0
+c060
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 18 0 0
+BITMAP
+e01c
+6018
+7038
+3030
+3870
+1860
+1ce0
+0cc0
+3ff0
+3ff0
+0300
+3ff0
+3ff0
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 23 2 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 24 1 -5
+BITMAP
+1f00
+3f80
+71c0
+60c0
+70c0
+3800
+1c00
+7e00
+e700
+c380
+c1c0
+c0c0
+6060
+7060
+3860
+1cc0
+0f80
+0700
+0380
+61c0
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 16
+BITMAP
+cc
+cc
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+600300
+43e100
+c63180
+8c1080
+880080
+880080
+880080
+8c1080
+c63180
+43e100
+600300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 12 1 7
+BITMAP
+78
+cc
+cc
+0c
+7c
+cc
+cc
+dc
+76
+00
+fe
+fe
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 9 8 2 3
+BITMAP
+1980
+3300
+6600
+cc00
+cc00
+6600
+3300
+1980
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 8 1 3
+BITMAP
+fff8
+fff8
+0018
+0018
+0018
+0018
+0018
+0018
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 6
+BITMAP
+fc
+fc
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+600300
+43e100
+c21180
+821080
+821080
+83e080
+824080
+822080
+c22180
+421100
+600300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 16
+BITMAP
+fc
+fc
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 8 7 0 11
+BITMAP
+3c
+66
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 10 0 8
+BITMAP
+3c
+7e
+c6
+06
+0c
+18
+30
+60
+fe
+fe
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 10 0 8
+BITMAP
+7c
+fe
+c6
+06
+3c
+3c
+06
+c6
+fe
+7c
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 5 4 1 15
+BITMAP
+18
+30
+60
+c0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 -5
+BITMAP
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+e3c0
+fec0
+dcc0
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 23 1 -4
+BITMAP
+1fc0
+7fc0
+7980
+f980
+f980
+f980
+f980
+f980
+f980
+7980
+7980
+3980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 6
+BITMAP
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 5 6 1 -5
+BITMAP
+60
+70
+18
+18
+f8
+70
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 4 10 1 8
+BITMAP
+30
+30
+f0
+f0
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 12 1 7
+BITMAP
+38
+6c
+c6
+c6
+c6
+c6
+c6
+6c
+38
+00
+fe
+fe
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 9 8 3 3
+BITMAP
+cc00
+6600
+3300
+1980
+1980
+3300
+6600
+cc00
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 18 18 1 0
+BITMAP
+301800
+301800
+f03000
+f03000
+306000
+306000
+30c000
+30c000
+318300
+318700
+030f00
+030f00
+061b00
+063300
+0c7fc0
+0c7fc0
+180300
+180300
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 18 18 1 0
+BITMAP
+301800
+301800
+f03000
+f03000
+306000
+306000
+30c000
+30c000
+318780
+318fc0
+0318c0
+0300c0
+060180
+060300
+0c0600
+0c0c00
+181fc0
+181fc0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 19 18 0 0
+BITMAP
+7c0c00
+fe0c00
+c61800
+061800
+3c3000
+3c3000
+066000
+c66000
+fec180
+7cc380
+018780
+018780
+030d80
+031980
+063fe0
+063fe0
+0c0180
+0c0180
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 -5
+BITMAP
+0c00
+0c00
+0c00
+0000
+0000
+0c00
+0c00
+0c00
+0c00
+1800
+3800
+7000
+6000
+e0c0
+c0c0
+c1c0
+e380
+7f80
+3e00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0c00
+0600
+0300
+0180
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0060
+00c0
+0180
+0300
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0180
+03c0
+0660
+0c30
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 23 1 0
+BITMAP
+0710
+0db0
+08e0
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 23 1 0
+BITMAP
+0c60
+0c60
+0000
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 24 1 0
+BITMAP
+0380
+06c0
+06c0
+0380
+0000
+0380
+0380
+06c0
+06c0
+0c40
+0c60
+0c60
+1830
+1830
+1830
+3018
+3ff8
+3ff8
+600c
+600c
+600c
+c006
+c006
+c006
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 920 0
+DWIDTH 23 0
+BBX 21 19 1 0
+BITMAP
+03fff8
+03fff8
+066000
+066000
+0c6000
+0c6000
+0c6000
+186000
+187ff8
+187ff8
+306000
+3fe000
+3fe000
+606000
+606000
+606000
+c06000
+c07ff8
+c07ff8
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 -5
+BITMAP
+07e0
+1ff8
+3c3c
+700e
+6006
+e006
+c000
+c000
+c000
+c000
+c000
+c000
+c003
+e003
+6006
+700e
+3c3c
+1ff8
+07e0
+0380
+00c0
+00c0
+07c0
+0380
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 24 2 0
+BITMAP
+3000
+1800
+0c00
+0600
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 24 2 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 24 2 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 23 2 0
+BITMAP
+1980
+1980
+0000
+0000
+fff0
+fff0
+c000
+c000
+c000
+c000
+c000
+c000
+ffe0
+ffe0
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+fff0
+fff0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 1 0
+BITMAP
+c0
+60
+30
+18
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 24 2 0
+BITMAP
+18
+30
+60
+c0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 8 24 0 0
+BITMAP
+18
+3c
+66
+c3
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 23 1 0
+BITMAP
+cc
+cc
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 19 0 0
+BITMAP
+3ff000
+3ffc00
+301e00
+300700
+300300
+300380
+300180
+300180
+ff0180
+ff0180
+300180
+300180
+300180
+300380
+300300
+300700
+301e00
+3ffc00
+3ff000
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 23 2 0
+BITMAP
+0710
+0db0
+08e0
+0000
+e00c
+f00c
+f00c
+d80c
+dc0c
+cc0c
+ce0c
+c60c
+c70c
+c30c
+c38c
+c18c
+c1cc
+c0cc
+c0ec
+c06c
+c03c
+c03c
+c01c
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 0
+BITMAP
+0600
+0300
+0180
+00c0
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 0
+BITMAP
+0030
+0060
+00c0
+0180
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 24 1 0
+BITMAP
+0180
+03c0
+0660
+0c30
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 23 1 0
+BITMAP
+0710
+0db0
+08e0
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 23 1 0
+BITMAP
+0660
+0660
+0000
+0000
+07e0
+1ff8
+3c3c
+700e
+6006
+e007
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+e007
+6006
+700e
+3c3c
+1ff8
+07e0
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 12 0 1
+BITMAP
+c018
+6030
+3060
+18c0
+0d80
+0700
+0700
+0d80
+18c0
+3060
+6030
+c018
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 18 19 0 0
+BITMAP
+03f040
+0ffcc0
+1e1f80
+380700
+300700
+700d80
+601980
+603180
+606180
+60c180
+618180
+630180
+660180
+6c0380
+380300
+380700
+7e1e00
+cffc00
+83f000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 24 2 0
+BITMAP
+0c00
+0600
+0300
+0180
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 24 2 0
+BITMAP
+0060
+00c0
+0180
+0300
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 24 2 0
+BITMAP
+0300
+0780
+0cc0
+1860
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 23 2 0
+BITMAP
+0cc0
+0cc0
+0000
+0000
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+c00c
+6018
+7038
+3ff0
+0fc0
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 24 1 0
+BITMAP
+0060
+00c0
+0180
+0300
+0000
+c00c
+e01c
+6018
+7038
+3030
+3870
+1860
+1ce0
+0cc0
+0fc0
+0780
+0780
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 13 19 2 0
+BITMAP
+c000
+c000
+c000
+c000
+ffe0
+fff0
+c030
+c018
+c018
+c018
+c018
+c030
+fff0
+ffe0
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 10 19 3 0
+BITMAP
+1c00
+7f00
+e300
+c180
+c180
+c180
+c300
+c700
+ce00
+cf00
+c380
+c180
+c0c0
+c0c0
+c0c0
+c180
+c380
+cf00
+ce00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1800
+0c00
+0600
+0300
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1c40
+36c0
+2380
+0000
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1980
+1980
+0000
+0000
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0e00
+1b00
+1100
+1b00
+0e00
+1f00
+3f80
+61c0
+60c0
+00c0
+07c0
+3fc0
+78c0
+e0c0
+c0c0
+c1c0
+e3c0
+7ee0
+3c60
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 840 0
+DWIDTH 21 0
+BBX 19 14 1 0
+BITMAP
+1f0e00
+3fbf80
+61f1c0
+60e0c0
+00c060
+07c060
+3fffe0
+78ffe0
+e0c000
+c0c000
+c1e060
+e3f0e0
+7e3fc0
+3c0f00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 -5
+BITMAP
+1f00
+3f80
+71c0
+60c0
+c000
+c000
+c000
+c000
+c000
+c000
+60c0
+71c0
+3f80
+1f00
+1c00
+0600
+0600
+3e00
+1c00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1800
+0c00
+0600
+0300
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1980
+1980
+0000
+0000
+0e00
+3f80
+71c0
+60c0
+c060
+c060
+ffe0
+ffe0
+c000
+c000
+6060
+70e0
+3fc0
+0f00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 19 0 0
+BITMAP
+c0
+60
+30
+18
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 19 1 0
+BITMAP
+18
+30
+60
+c0
+00
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 8 19 -1 0
+BITMAP
+18
+3c
+66
+c3
+00
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 6 18 0 0
+BITMAP
+cc
+cc
+00
+00
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+e000
+7180
+1e00
+3c00
+c600
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 18 2 0
+BITMAP
+3880
+6d80
+4700
+0000
+ce00
+df80
+f180
+e0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+1800
+0c00
+0600
+0300
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 19 1 0
+BITMAP
+0600
+0f00
+1980
+30c0
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+1c40
+36c0
+2380
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 18 1 0
+BITMAP
+3180
+3180
+0000
+0000
+1f00
+3f80
+71c0
+60c0
+c060
+c060
+c060
+c060
+c060
+c060
+60c0
+71c0
+3f80
+1f00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 12 1 1
+BITMAP
+0600
+0600
+0600
+0000
+0000
+fff0
+fff0
+0000
+0000
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 14 0 0
+BITMAP
+0f98
+1ff0
+38e0
+3060
+60f0
+61b0
+6330
+6630
+6630
+6c30
+3860
+30e0
+7fc0
+cf80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 0
+BITMAP
+3000
+1800
+0c00
+0600
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 0
+BITMAP
+0180
+0300
+0600
+0c00
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 19 2 0
+BITMAP
+0c00
+1e00
+3300
+6180
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 18 2 0
+BITMAP
+3300
+3300
+0000
+0000
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+63c0
+7ec0
+1cc0
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 24 0 -5
+BITMAP
+00c0
+0180
+0300
+0600
+0000
+c030
+c030
+6030
+7060
+3060
+38e0
+18c0
+18c0
+0d80
+0d80
+0780
+0700
+0300
+0300
+0600
+0600
+0c00
+3c00
+3800
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 11 24 2 -5
+BITMAP
+c000
+c000
+c000
+c000
+c000
+cf00
+df80
+f1c0
+e0c0
+c060
+c060
+c060
+c060
+c060
+c060
+e0c0
+f1c0
+df80
+cf00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 23 0 -5
+BITMAP
+1980
+1980
+0000
+0000
+c030
+c030
+6030
+7060
+3060
+38e0
+18c0
+18c0
+0d80
+0d80
+0780
+0700
+0300
+0300
+0600
+0600
+0c00
+3c00
+3800
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica24.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica24.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica24.h	(revision 16632)
@@ -0,0 +1,1170 @@
+static unsigned char helvetica24_0_bits[] = {
+0x00};
+static unsigned char helvetica24_1_bits[] = {
+0x00};
+static unsigned char helvetica24_2_bits[] = {
+0x00};
+static unsigned char helvetica24_3_bits[] = {
+0x00};
+static unsigned char helvetica24_4_bits[] = {
+0x00};
+static unsigned char helvetica24_5_bits[] = {
+0x00};
+static unsigned char helvetica24_6_bits[] = {
+0x00};
+static unsigned char helvetica24_7_bits[] = {
+0x00};
+static unsigned char helvetica24_8_bits[] = {
+0x00};
+static unsigned char helvetica24_9_bits[] = {
+0x00};
+static unsigned char helvetica24_10_bits[] = {
+0x00};
+static unsigned char helvetica24_11_bits[] = {
+0x00};
+static unsigned char helvetica24_12_bits[] = {
+0x00};
+static unsigned char helvetica24_13_bits[] = {
+0x00};
+static unsigned char helvetica24_14_bits[] = {
+0x00};
+static unsigned char helvetica24_15_bits[] = {
+0x00};
+static unsigned char helvetica24_16_bits[] = {
+0x00};
+static unsigned char helvetica24_17_bits[] = {
+0x00};
+static unsigned char helvetica24_18_bits[] = {
+0x00};
+static unsigned char helvetica24_19_bits[] = {
+0x00};
+static unsigned char helvetica24_20_bits[] = {
+0x00};
+static unsigned char helvetica24_21_bits[] = {
+0x00};
+static unsigned char helvetica24_22_bits[] = {
+0x00};
+static unsigned char helvetica24_23_bits[] = {
+0x00};
+static unsigned char helvetica24_24_bits[] = {
+0x00};
+static unsigned char helvetica24_25_bits[] = {
+0x00};
+static unsigned char helvetica24_26_bits[] = {
+0x00};
+static unsigned char helvetica24_27_bits[] = {
+0x00};
+static unsigned char helvetica24_28_bits[] = {
+0x00};
+static unsigned char helvetica24_29_bits[] = {
+0x00};
+static unsigned char helvetica24_30_bits[] = {
+0x00};
+static unsigned char helvetica24_31_bits[] = {
+0x00, 0x00};
+static unsigned char helvetica24_32_bits[] = {
+0x00, 0x00};
+static unsigned char helvetica24_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x01, 0x01, 0x00, 0x00, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_34_bits[] = {
+0x33, 0x33, 0x33, 0x33, 0x33, 0x22};
+static unsigned char helvetica24_35_bits[] = {
+0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x98, 0x01, 0xff, 0x07, 0xff, 0x07, 
+0x98, 0x01, 0x98, 0x01, 0xcc, 0x00, 0xcc, 0x00, 0xff, 0x07, 0xff, 0x07, 
+0xcc, 0x00, 0xcc, 0x00, 0x66, 0x00, 0x66, 0x00, 0x66, 0x00};
+static unsigned char helvetica24_36_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0xfc, 0x01, 0xfe, 0x03, 0x67, 0x07, 0x63, 0x06, 
+0x63, 0x00, 0x67, 0x00, 0x6e, 0x00, 0x7c, 0x00, 0xf0, 0x01, 0xe0, 0x03, 
+0x60, 0x07, 0x60, 0x06, 0x63, 0x06, 0x63, 0x06, 0x67, 0x07, 0xfe, 0x03, 
+0xfc, 0x01, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica24_37_bits[] = {
+0x00, 0x60, 0x00, 0x3c, 0x30, 0x00, 0x7e, 0x30, 0x00, 0xc3, 0x18, 0x00, 
+0xc3, 0x18, 0x00, 0xc3, 0x0c, 0x00, 0xc3, 0x0c, 0x00, 0x7e, 0x06, 0x00, 
+0x3c, 0x06, 0x00, 0x00, 0x03, 0x00, 0x00, 0xe3, 0x01, 0x80, 0xf1, 0x03, 
+0x80, 0x19, 0x06, 0xc0, 0x18, 0x06, 0xc0, 0x18, 0x06, 0x60, 0x18, 0x06, 
+0x60, 0xf0, 0x03, 0x20, 0xe0, 0x01};
+static unsigned char helvetica24_38_bits[] = {
+0xf0, 0x00, 0xf8, 0x01, 0x9c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 
+0x98, 0x01, 0xf0, 0x00, 0x78, 0x00, 0xfc, 0x18, 0xce, 0x19, 0x86, 0x1b, 
+0x03, 0x0f, 0x03, 0x06, 0x03, 0x0f, 0x87, 0x1b, 0xfe, 0x39, 0x78, 0x00};
+static unsigned char helvetica24_39_bits[] = {
+0x03, 0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica24_40_bits[] = {
+0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18};
+static unsigned char helvetica24_41_bits[] = {
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03};
+static unsigned char helvetica24_42_bits[] = {
+0x08, 0x08, 0x6b, 0x3e, 0x1c, 0x36, 0x22};
+static unsigned char helvetica24_43_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica24_44_bits[] = {
+0x03, 0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica24_45_bits[] = {
+0xff, 0x07, 0xff, 0x07};
+static unsigned char helvetica24_46_bits[] = {
+0x03, 0x03, 0x03};
+static unsigned char helvetica24_47_bits[] = {
+0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x0c, 
+0x0c, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_48_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_49_bits[] = {
+0x30, 0x30, 0x38, 0x3f, 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x30, 0x30, 0x30, 0x30};
+static unsigned char helvetica24_50_bits[] = {
+0x78, 0x00, 0xfe, 0x01, 0x86, 0x03, 0x03, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x00, 0x06, 0x00, 0x03, 0x80, 0x03, 0xc0, 0x01, 0xf0, 0x00, 0x38, 0x00, 
+0x1c, 0x00, 0x0e, 0x00, 0x07, 0x00, 0x03, 0x00, 0xff, 0x07, 0xff, 0x07};
+static unsigned char helvetica24_51_bits[] = {
+0xf8, 0x00, 0xfe, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x00, 0x03, 0x80, 0x01, 0xf0, 0x00, 0xf0, 0x03, 0x00, 0x03, 0x00, 0x06, 
+0x00, 0x06, 0x03, 0x06, 0x03, 0x03, 0x86, 0x03, 0xfe, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_52_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x01, 0xf0, 0x01, 0xb0, 0x01, 
+0x98, 0x01, 0x9c, 0x01, 0x8c, 0x01, 0x86, 0x01, 0x87, 0x01, 0x83, 0x01, 
+0xff, 0x07, 0xff, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
+static unsigned char helvetica24_53_bits[] = {
+0xfe, 0x03, 0xfe, 0x03, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x76, 0x00, 0xfe, 0x01, 0x8e, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06, 0x03, 0x06, 0x03, 0x03, 0x87, 0x03, 0xfe, 0x01, 0x78, 0x00};
+static unsigned char helvetica24_54_bits[] = {
+0xf0, 0x00, 0xfc, 0x03, 0x0e, 0x03, 0x06, 0x06, 0x07, 0x06, 0x03, 0x00, 
+0x03, 0x00, 0xf3, 0x00, 0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x07, 0x06, 0x06, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica24_55_bits[] = {
+0xff, 0x07, 0xff, 0x07, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0x80, 0x01, 
+0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x38, 0x00, 0x18, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0c, 0x00};
+static unsigned char helvetica24_56_bits[] = {
+0x70, 0x00, 0xfc, 0x01, 0x8c, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x8c, 0x01, 0xf8, 0x00, 0xfc, 0x01, 0x06, 0x03, 0x07, 0x07, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x8e, 0x03, 0xfe, 0x03, 0xf8, 0x00};
+static unsigned char helvetica24_57_bits[] = {
+0xf8, 0x00, 0xfe, 0x03, 0x8e, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x8e, 0x07, 0xfe, 0x06, 0x78, 0x06, 
+0x00, 0x06, 0x00, 0x07, 0x03, 0x03, 0x87, 0x03, 0xfe, 0x01, 0x78, 0x00};
+static unsigned char helvetica24_58_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_59_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 
+0x03, 0x03, 0x02, 0x02, 0x01};
+static unsigned char helvetica24_60_bits[] = {
+0x00, 0x0c, 0x00, 0x0f, 0xc0, 0x03, 0xf0, 0x00, 0x3c, 0x00, 0x07, 0x00, 
+0x07, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0xc0, 0x03, 0x00, 0x0f, 0x00, 0x0c};
+static unsigned char helvetica24_61_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica24_62_bits[] = {
+0x03, 0x00, 0x0f, 0x00, 0x3c, 0x00, 0xf0, 0x00, 0xc0, 0x03, 0x00, 0x0e, 
+0x00, 0x0e, 0xc0, 0x03, 0xf0, 0x00, 0x3c, 0x00, 0x0f, 0x00, 0x03, 0x00};
+static unsigned char helvetica24_63_bits[] = {
+0xf8, 0x00, 0xfe, 0x01, 0x8e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0x80, 0x01, 0xc0, 0x01, 0xe0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00};
+static unsigned char helvetica24_64_bits[] = {
+0x00, 0xff, 0x00, 0xc0, 0xff, 0x03, 0xf0, 0x80, 0x07, 0x38, 0x00, 0x0e, 
+0x1c, 0x00, 0x18, 0x0c, 0x00, 0x18, 0x06, 0xce, 0x30, 0x06, 0xdf, 0x30, 
+0x83, 0xe3, 0x30, 0xc3, 0x61, 0x30, 0xc3, 0x60, 0x30, 0x63, 0x60, 0x30, 
+0x63, 0x30, 0x38, 0x63, 0x30, 0x18, 0x63, 0x30, 0x1c, 0xe7, 0x38, 0x0e, 
+0xc6, 0xef, 0x07, 0x8e, 0xc7, 0x01, 0x1c, 0x00, 0x00, 0x38, 0x00, 0x00, 
+0xf0, 0xc0, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x3f, 0x00};
+static unsigned char helvetica24_65_bits[] = {
+0xc0, 0x01, 0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 
+0x30, 0x06, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 
+0xfc, 0x1f, 0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 
+0x03, 0x60};
+static unsigned char helvetica24_66_bits[] = {
+0xff, 0x03, 0xff, 0x0f, 0x03, 0x0e, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x0c, 0xff, 0x07, 0xff, 0x0f, 0x03, 0x18, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x38, 0x03, 0x1c, 0xff, 0x0f, 
+0xff, 0x03};
+static unsigned char helvetica24_67_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0x60, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0xc0, 0x07, 0xc0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 
+0xe0, 0x07};
+static unsigned char helvetica24_68_bits[] = {
+0xff, 0x03, 0xff, 0x0f, 0x03, 0x1e, 0x03, 0x38, 0x03, 0x30, 0x03, 0x70, 
+0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60, 
+0x03, 0x60, 0x03, 0x70, 0x03, 0x30, 0x03, 0x38, 0x03, 0x1e, 0xff, 0x0f, 
+0xff, 0x03};
+static unsigned char helvetica24_69_bits[] = {
+0xff, 0x0f, 0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 
+0xff, 0x0f};
+static unsigned char helvetica24_70_bits[] = {
+0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x03, 0xff, 0x03, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_71_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0x60, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xfe, 0x03, 0xfe, 0x03, 0xc0, 
+0x03, 0xc0, 0x07, 0xc0, 0x06, 0xe0, 0x0e, 0xf0, 0x3c, 0xfc, 0xf8, 0xdf, 
+0xe0, 0xc7};
+static unsigned char helvetica24_72_bits[] = {
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0xff, 0x3f, 0xff, 0x3f, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30};
+static unsigned char helvetica24_73_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_74_bits[] = {
+0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 
+0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xfe, 0x01, 
+0xfc, 0x00};
+static unsigned char helvetica24_75_bits[] = {
+0x03, 0x1c, 0x03, 0x0e, 0x03, 0x07, 0x83, 0x03, 0xc3, 0x01, 0xe3, 0x00, 
+0x73, 0x00, 0x3b, 0x00, 0x3f, 0x00, 0x7f, 0x00, 0xe7, 0x00, 0xc3, 0x01, 
+0x83, 0x03, 0x03, 0x07, 0x03, 0x0e, 0x03, 0x1c, 0x03, 0x38, 0x03, 0x70, 
+0x03, 0x60};
+static unsigned char helvetica24_76_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x07, 
+0xff, 0x07};
+static unsigned char helvetica24_77_bits[] = {
+0x03, 0x80, 0x01, 0x07, 0xc0, 0x01, 0x07, 0xc0, 0x01, 0x0f, 0xe0, 0x01, 
+0x0f, 0xe0, 0x01, 0x1b, 0xb0, 0x01, 0x1b, 0xb0, 0x01, 0x1b, 0xb0, 0x01, 
+0x33, 0x98, 0x01, 0x33, 0x98, 0x01, 0x33, 0x98, 0x01, 0x63, 0x8c, 0x01, 
+0x63, 0x8c, 0x01, 0x63, 0x8c, 0x01, 0xc3, 0x86, 0x01, 0xc3, 0x86, 0x01, 
+0xc3, 0x86, 0x01, 0x83, 0x83, 0x01, 0x83, 0x83, 0x01};
+static unsigned char helvetica24_78_bits[] = {
+0x07, 0x30, 0x0f, 0x30, 0x0f, 0x30, 0x1b, 0x30, 0x3b, 0x30, 0x33, 0x30, 
+0x73, 0x30, 0x63, 0x30, 0xe3, 0x30, 0xc3, 0x30, 0xc3, 0x31, 0x83, 0x31, 
+0x83, 0x33, 0x03, 0x33, 0x03, 0x37, 0x03, 0x36, 0x03, 0x3c, 0x03, 0x3c, 
+0x03, 0x38};
+static unsigned char helvetica24_79_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 
+0xe0, 0x07};
+static unsigned char helvetica24_80_bits[] = {
+0xff, 0x07, 0xff, 0x0f, 0x03, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x0c, 0xff, 0x0f, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_81_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x07, 0xe0, 0x06, 0x67, 0x0e, 0x7e, 0x3c, 0x38, 0xf8, 0x7f, 
+0xe0, 0xe7};
+static unsigned char helvetica24_82_bits[] = {
+0xff, 0x07, 0xff, 0x0f, 0x03, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x03, 0x0c, 0xff, 0x0f, 0xff, 0x07, 0x03, 0x0e, 0x03, 0x0c, 
+0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18};
+static unsigned char helvetica24_83_bits[] = {
+0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x0e, 0x18, 0x06, 0x18, 0x06, 0x00, 
+0x0e, 0x00, 0x7c, 0x00, 0xf0, 0x03, 0x80, 0x0f, 0x00, 0x1e, 0x00, 0x38, 
+0x00, 0x30, 0x03, 0x30, 0x03, 0x30, 0x07, 0x38, 0x1e, 0x1c, 0xfc, 0x0f, 
+0xf0, 0x03};
+static unsigned char helvetica24_84_bits[] = {
+0xff, 0x3f, 0xff, 0x3f, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char helvetica24_85_bits[] = {
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 
+0xf0, 0x03};
+static unsigned char helvetica24_86_bits[] = {
+0x03, 0x60, 0x03, 0x60, 0x07, 0x70, 0x06, 0x30, 0x0e, 0x38, 0x0c, 0x18, 
+0x0c, 0x18, 0x1c, 0x1c, 0x18, 0x0c, 0x18, 0x0c, 0x38, 0x0e, 0x30, 0x06, 
+0x30, 0x06, 0x70, 0x07, 0x60, 0x03, 0x60, 0x03, 0xc0, 0x01, 0xc0, 0x01, 
+0xc0, 0x01};
+static unsigned char helvetica24_87_bits[] = {
+0x03, 0x06, 0x0c, 0x03, 0x06, 0x0c, 0x03, 0x06, 0x0c, 0x03, 0x0f, 0x0c, 
+0x06, 0x0f, 0x06, 0x86, 0x19, 0x06, 0x86, 0x19, 0x06, 0x86, 0x19, 0x06, 
+0x86, 0x19, 0x06, 0x8c, 0x19, 0x03, 0xcc, 0x30, 0x03, 0xcc, 0x30, 0x03, 
+0xcc, 0x30, 0x03, 0xd8, 0xb0, 0x01, 0xd8, 0xb0, 0x01, 0x78, 0xe0, 0x01, 
+0x70, 0xe0, 0x00, 0x30, 0xc0, 0x00, 0x30, 0xc0, 0x00};
+static unsigned char helvetica24_88_bits[] = {
+0x03, 0x60, 0x07, 0x70, 0x0e, 0x38, 0x0c, 0x18, 0x18, 0x0c, 0x38, 0x0e, 
+0x70, 0x07, 0xe0, 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0x70, 0x07, 
+0x30, 0x06, 0x38, 0x0e, 0x1c, 0x1c, 0x0c, 0x18, 0x06, 0x30, 0x07, 0x70, 
+0x03, 0x60};
+static unsigned char helvetica24_89_bits[] = {
+0x03, 0x30, 0x07, 0x38, 0x06, 0x18, 0x0e, 0x1c, 0x0c, 0x0c, 0x1c, 0x0e, 
+0x18, 0x06, 0x38, 0x07, 0x30, 0x03, 0xf0, 0x03, 0xe0, 0x01, 0xe0, 0x01, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char helvetica24_90_bits[] = {
+0xff, 0x1f, 0xff, 0x1f, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 
+0x80, 0x03, 0xc0, 0x01, 0xe0, 0x00, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 
+0x38, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x07, 0x00, 0xff, 0x1f, 
+0xff, 0x1f};
+static unsigned char helvetica24_91_bits[] = {
+0x0f, 0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f};
+static unsigned char helvetica24_92_bits[] = {
+0x03, 0x03, 0x03, 0x06, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x18, 
+0x18, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60};
+static unsigned char helvetica24_93_bits[] = {
+0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x0f};
+static unsigned char helvetica24_94_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0xcc, 0x00, 0x86, 0x01, 
+0x86, 0x01, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_95_bits[] = {
+0xff, 0x3f, 0xff, 0x3f};
+static unsigned char helvetica24_96_bits[] = {
+0x02, 0x01, 0x01, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_97_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 
+0xfc, 0x03, 0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 
+0x7e, 0x07, 0x3c, 0x06};
+static unsigned char helvetica24_98_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xf3, 0x00, 
+0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x03, 0x8f, 0x03, 0xfb, 0x01, 
+0xf3, 0x00};
+static unsigned char helvetica24_99_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x03, 0x8e, 0x03, 
+0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_100_bits[] = {
+0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x78, 0x06, 
+0xfc, 0x06, 0x8e, 0x07, 0x06, 0x07, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x07, 0x8e, 0x07, 0xfc, 0x06, 
+0x78, 0x06};
+static unsigned char helvetica24_101_bits[] = {
+0x70, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 
+0xfc, 0x03, 0xf0, 0x00};
+static unsigned char helvetica24_102_bits[] = {
+0x38, 0x3c, 0x0c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_103_bits[] = {
+0x78, 0x06, 0xfc, 0x06, 0x8e, 0x07, 0x06, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x07, 0x8e, 0x07, 
+0xfc, 0x06, 0x78, 0x06, 0x00, 0x06, 0x03, 0x06, 0x07, 0x03, 0xfe, 0x03, 
+0xf8, 0x00};
+static unsigned char helvetica24_104_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x73, 0x00, 
+0xfb, 0x01, 0x8f, 0x01, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_105_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_106_bits[] = {
+0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0f, 0x07};
+static unsigned char helvetica24_107_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x83, 0x01, 
+0xc3, 0x01, 0xe3, 0x00, 0x73, 0x00, 0x3b, 0x00, 0x1f, 0x00, 0x3f, 0x00, 
+0x73, 0x00, 0x63, 0x00, 0xe3, 0x00, 0xc3, 0x01, 0x83, 0x01, 0x83, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_108_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_109_bits[] = {
+0x73, 0x3c, 0xff, 0x7e, 0xc7, 0xe3, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 
+0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 
+0x83, 0xc1, 0x83, 0xc1};
+static unsigned char helvetica24_110_bits[] = {
+0x73, 0x00, 0xfb, 0x01, 0x8f, 0x01, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_111_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 
+0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_112_bits[] = {
+0xf3, 0x00, 0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x03, 0x8f, 0x03, 
+0xfb, 0x01, 0xf3, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_113_bits[] = {
+0x78, 0x06, 0xfc, 0x06, 0x8e, 0x07, 0x06, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x07, 0x8e, 0x07, 
+0xfc, 0x06, 0x78, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06};
+static unsigned char helvetica24_114_bits[] = {
+0x33, 0x3b, 0x3f, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char helvetica24_115_bits[] = {
+0x7c, 0x00, 0xfe, 0x01, 0x87, 0x03, 0x03, 0x03, 0x03, 0x00, 0x1f, 0x00, 
+0xfe, 0x00, 0xf0, 0x01, 0x80, 0x03, 0x00, 0x03, 0x03, 0x03, 0x83, 0x03, 
+0xff, 0x01, 0xfc, 0x00};
+static unsigned char helvetica24_116_bits[] = {
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x38};
+static unsigned char helvetica24_117_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 
+0x7e, 0x03, 0x38, 0x03};
+static unsigned char helvetica24_118_bits[] = {
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 
+0x8c, 0x01, 0x8c, 0x01, 0xd8, 0x00, 0xd8, 0x00, 0xd8, 0x00, 0x70, 0x00, 
+0x70, 0x00, 0x70, 0x00};
+static unsigned char helvetica24_119_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x87, 0x01, 0x86, 0x87, 0x01, 
+0x86, 0x87, 0x01, 0x8c, 0xc4, 0x00, 0xcc, 0xcc, 0x00, 0xcc, 0xcc, 0x00, 
+0xd8, 0x6c, 0x00, 0x58, 0x68, 0x00, 0x78, 0x78, 0x00, 0x70, 0x38, 0x00, 
+0x30, 0x30, 0x00, 0x30, 0x30, 0x00};
+static unsigned char helvetica24_120_bits[] = {
+0x03, 0x03, 0x87, 0x03, 0x86, 0x01, 0xcc, 0x00, 0xfc, 0x00, 0x78, 0x00, 
+0x30, 0x00, 0x78, 0x00, 0x78, 0x00, 0xcc, 0x00, 0xce, 0x01, 0x86, 0x01, 
+0x87, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_121_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x06, 0x0c, 0x0e, 0x06, 0x0c, 0x06, 0x1c, 0x07, 
+0x18, 0x03, 0x18, 0x03, 0xb0, 0x01, 0xb0, 0x01, 0xe0, 0x01, 0xe0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x3c, 0x00, 
+0x1c, 0x00};
+static unsigned char helvetica24_122_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x80, 0x01, 0xc0, 0x00, 0xe0, 0x00, 0x70, 0x00, 
+0x30, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x07, 0x00, 
+0xff, 0x03, 0xff, 0x03};
+static unsigned char helvetica24_123_bits[] = {
+0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 
+0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30};
+static unsigned char helvetica24_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_125_bits[] = {
+0x03, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 
+0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03};
+static unsigned char helvetica24_126_bits[] = {
+0x0e, 0x03, 0x3f, 0x03, 0xf3, 0x03, 0xc3, 0x01};
+static unsigned char helvetica24_127_bits[] = {
+0x00};
+static unsigned char helvetica24_128_bits[] = {
+0x00};
+static unsigned char helvetica24_129_bits[] = {
+0x00};
+static unsigned char helvetica24_130_bits[] = {
+0x00};
+static unsigned char helvetica24_131_bits[] = {
+0x00};
+static unsigned char helvetica24_132_bits[] = {
+0x00};
+static unsigned char helvetica24_133_bits[] = {
+0x00};
+static unsigned char helvetica24_134_bits[] = {
+0x00};
+static unsigned char helvetica24_135_bits[] = {
+0x00};
+static unsigned char helvetica24_136_bits[] = {
+0x00};
+static unsigned char helvetica24_137_bits[] = {
+0x00};
+static unsigned char helvetica24_138_bits[] = {
+0x00};
+static unsigned char helvetica24_139_bits[] = {
+0x00};
+static unsigned char helvetica24_140_bits[] = {
+0x00};
+static unsigned char helvetica24_141_bits[] = {
+0x00};
+static unsigned char helvetica24_142_bits[] = {
+0x00};
+static unsigned char helvetica24_143_bits[] = {
+0x00};
+static unsigned char helvetica24_144_bits[] = {
+0x00};
+static unsigned char helvetica24_145_bits[] = {
+0x00};
+static unsigned char helvetica24_146_bits[] = {
+0x00};
+static unsigned char helvetica24_147_bits[] = {
+0x00};
+static unsigned char helvetica24_148_bits[] = {
+0x00};
+static unsigned char helvetica24_149_bits[] = {
+0x00};
+static unsigned char helvetica24_150_bits[] = {
+0x00};
+static unsigned char helvetica24_151_bits[] = {
+0x00};
+static unsigned char helvetica24_152_bits[] = {
+0x00};
+static unsigned char helvetica24_153_bits[] = {
+0x00};
+static unsigned char helvetica24_154_bits[] = {
+0x00};
+static unsigned char helvetica24_155_bits[] = {
+0x00};
+static unsigned char helvetica24_156_bits[] = {
+0x00};
+static unsigned char helvetica24_157_bits[] = {
+0x00};
+static unsigned char helvetica24_158_bits[] = {
+0x00};
+static unsigned char helvetica24_159_bits[] = {
+0x00};
+static unsigned char helvetica24_160_bits[] = {
+0x00};
+static unsigned char helvetica24_161_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_162_bits[] = {
+0x80, 0x01, 0x80, 0x01, 0xf8, 0x00, 0xfc, 0x01, 0xce, 0x03, 0x66, 0x03, 
+0x63, 0x00, 0x33, 0x00, 0x33, 0x00, 0x33, 0x00, 0x1b, 0x00, 0x1b, 0x00, 
+0x1b, 0x03, 0x8e, 0x03, 0xfe, 0x01, 0xfc, 0x00, 0x06, 0x00, 0x06, 0x00};
+static unsigned char helvetica24_163_bits[] = {
+0xf8, 0x01, 0xfc, 0x07, 0x0e, 0x0e, 0x06, 0x0c, 0x06, 0x00, 0x0e, 0x00, 
+0x0c, 0x00, 0x18, 0x00, 0xff, 0x01, 0xff, 0x01, 0x18, 0x00, 0x18, 0x00, 
+0x18, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xe6, 0x0c, 0xff, 0x0f, 0x0f, 0x07};
+static unsigned char helvetica24_164_bits[] = {
+0x03, 0x06, 0x77, 0x07, 0xfe, 0x03, 0x8c, 0x01, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8c, 0x01, 0xfe, 0x03, 0x77, 0x07, 0x03, 0x06};
+static unsigned char helvetica24_165_bits[] = {
+0x07, 0x38, 0x06, 0x18, 0x0e, 0x1c, 0x0c, 0x0c, 0x1c, 0x0e, 0x18, 0x06, 
+0x38, 0x07, 0x30, 0x03, 0xfc, 0x0f, 0xfc, 0x0f, 0xc0, 0x00, 0xfc, 0x0f, 
+0xfc, 0x0f, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char helvetica24_166_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_167_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x0e, 0x03, 0x1c, 0x00, 
+0x38, 0x00, 0x7e, 0x00, 0xe7, 0x00, 0xc3, 0x01, 0x83, 0x03, 0x03, 0x03, 
+0x06, 0x06, 0x0e, 0x06, 0x1c, 0x06, 0x38, 0x03, 0xf0, 0x01, 0xe0, 0x00, 
+0xc0, 0x01, 0x86, 0x03, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_168_bits[] = {
+0x33, 0x33};
+static unsigned char helvetica24_169_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0x06, 0xc0, 0x00, 
+0xc2, 0x87, 0x00, 0x63, 0x8c, 0x01, 0x31, 0x08, 0x01, 0x11, 0x00, 0x01, 
+0x11, 0x00, 0x01, 0x11, 0x00, 0x01, 0x31, 0x08, 0x01, 0x63, 0x8c, 0x01, 
+0xc2, 0x87, 0x00, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char helvetica24_170_bits[] = {
+0x1e, 0x33, 0x33, 0x30, 0x3e, 0x33, 0x33, 0x3b, 0x6e, 0x00, 0x7f, 0x7f};
+static unsigned char helvetica24_171_bits[] = {
+0x98, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 0x66, 0x00, 
+0xcc, 0x00, 0x98, 0x01};
+static unsigned char helvetica24_172_bits[] = {
+0xff, 0x1f, 0xff, 0x1f, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 
+0x00, 0x18, 0x00, 0x18};
+static unsigned char helvetica24_173_bits[] = {
+0x3f, 0x3f};
+static unsigned char helvetica24_174_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0x06, 0xc0, 0x00, 
+0xc2, 0x87, 0x00, 0x43, 0x88, 0x01, 0x41, 0x08, 0x01, 0x41, 0x08, 0x01, 
+0xc1, 0x07, 0x01, 0x41, 0x02, 0x01, 0x41, 0x04, 0x01, 0x43, 0x84, 0x01, 
+0x42, 0x88, 0x00, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char helvetica24_175_bits[] = {
+0x3f, 0x3f};
+static unsigned char helvetica24_176_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char helvetica24_177_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 0xff, 0x0f, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f};
+static unsigned char helvetica24_178_bits[] = {
+0x3c, 0x7e, 0x63, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x7f, 0x7f};
+static unsigned char helvetica24_179_bits[] = {
+0x3e, 0x7f, 0x63, 0x60, 0x3c, 0x3c, 0x60, 0x63, 0x7f, 0x3e};
+static unsigned char helvetica24_180_bits[] = {
+0x18, 0x0c, 0x06, 0x03};
+static unsigned char helvetica24_181_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 
+0x7f, 0x03, 0x3b, 0x03, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_182_bits[] = {
+0xf8, 0x03, 0xfe, 0x03, 0x9e, 0x01, 0x9f, 0x01, 0x9f, 0x01, 0x9f, 0x01, 
+0x9f, 0x01, 0x9f, 0x01, 0x9f, 0x01, 0x9e, 0x01, 0x9e, 0x01, 0x9c, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01};
+static unsigned char helvetica24_183_bits[] = {
+0x03, 0x03, 0x03};
+static unsigned char helvetica24_184_bits[] = {
+0x06, 0x0e, 0x18, 0x18, 0x1f, 0x0e};
+static unsigned char helvetica24_185_bits[] = {
+0x0c, 0x0c, 0x0f, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_186_bits[] = {
+0x1c, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1c, 0x00, 0x7f, 0x7f};
+static unsigned char helvetica24_187_bits[] = {
+0x33, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x98, 0x01, 0xcc, 0x00, 
+0x66, 0x00, 0x33, 0x00};
+static unsigned char helvetica24_188_bits[] = {
+0x0c, 0x18, 0x00, 0x0c, 0x18, 0x00, 0x0f, 0x0c, 0x00, 0x0f, 0x0c, 0x00, 
+0x0c, 0x06, 0x00, 0x0c, 0x06, 0x00, 0x0c, 0x03, 0x00, 0x0c, 0x03, 0x00, 
+0x8c, 0xc1, 0x00, 0x8c, 0xe1, 0x00, 0xc0, 0xf0, 0x00, 0xc0, 0xf0, 0x00, 
+0x60, 0xd8, 0x00, 0x60, 0xcc, 0x00, 0x30, 0xfe, 0x03, 0x30, 0xfe, 0x03, 
+0x18, 0xc0, 0x00, 0x18, 0xc0, 0x00};
+static unsigned char helvetica24_189_bits[] = {
+0x0c, 0x18, 0x00, 0x0c, 0x18, 0x00, 0x0f, 0x0c, 0x00, 0x0f, 0x0c, 0x00, 
+0x0c, 0x06, 0x00, 0x0c, 0x06, 0x00, 0x0c, 0x03, 0x00, 0x0c, 0x03, 0x00, 
+0x8c, 0xe1, 0x01, 0x8c, 0xf1, 0x03, 0xc0, 0x18, 0x03, 0xc0, 0x00, 0x03, 
+0x60, 0x80, 0x01, 0x60, 0xc0, 0x00, 0x30, 0x60, 0x00, 0x30, 0x30, 0x00, 
+0x18, 0xf8, 0x03, 0x18, 0xf8, 0x03};
+static unsigned char helvetica24_190_bits[] = {
+0x3e, 0x30, 0x00, 0x7f, 0x30, 0x00, 0x63, 0x18, 0x00, 0x60, 0x18, 0x00, 
+0x3c, 0x0c, 0x00, 0x3c, 0x0c, 0x00, 0x60, 0x06, 0x00, 0x63, 0x06, 0x00, 
+0x7f, 0x83, 0x01, 0x3e, 0xc3, 0x01, 0x80, 0xe1, 0x01, 0x80, 0xe1, 0x01, 
+0xc0, 0xb0, 0x01, 0xc0, 0x98, 0x01, 0x60, 0xfc, 0x07, 0x60, 0xfc, 0x07, 
+0x30, 0x80, 0x01, 0x30, 0x80, 0x01};
+static unsigned char helvetica24_191_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0e, 0x00, 
+0x06, 0x00, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x01, 0xfe, 0x01, 
+0x7c, 0x00};
+static unsigned char helvetica24_192_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_193_bits[] = {
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_194_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x30, 0x0c, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_195_bits[] = {
+0xe0, 0x08, 0xb0, 0x0d, 0x10, 0x07, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x01, 
+0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 0x18, 0x0c, 
+0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 0x06, 0x30, 
+0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_196_bits[] = {
+0x30, 0x06, 0x30, 0x06, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0xc0, 0x01, 
+0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 0x18, 0x0c, 
+0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 0x06, 0x30, 
+0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_197_bits[] = {
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 
+0xc0, 0x01, 0x60, 0x03, 0x60, 0x03, 0x30, 0x02, 0x30, 0x06, 0x30, 0x06, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x18, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x06, 0x30, 0x06, 0x30, 0x06, 0x30, 0x03, 0x60, 0x03, 0x60, 0x03, 0x60};
+static unsigned char helvetica24_198_bits[] = {
+0xc0, 0xff, 0x1f, 0xc0, 0xff, 0x1f, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 
+0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x30, 0x06, 0x00, 0x18, 0x06, 0x00, 
+0x18, 0xfe, 0x1f, 0x18, 0xfe, 0x1f, 0x0c, 0x06, 0x00, 0xfc, 0x07, 0x00, 
+0xfc, 0x07, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 0x06, 0x06, 0x00, 
+0x03, 0x06, 0x00, 0x03, 0xfe, 0x1f, 0x03, 0xfe, 0x1f};
+static unsigned char helvetica24_199_bits[] = {
+0xe0, 0x07, 0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0x60, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0xc0, 0x07, 0xc0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 
+0xe0, 0x07, 0xc0, 0x01, 0x00, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xc0, 0x01};
+static unsigned char helvetica24_200_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_201_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_202_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_203_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0xff, 0x07, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char helvetica24_204_bits[] = {
+0x03, 0x06, 0x0c, 0x18, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_205_bits[] = {
+0x18, 0x0c, 0x06, 0x03, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06};
+static unsigned char helvetica24_206_bits[] = {
+0x18, 0x3c, 0x66, 0xc3, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica24_207_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_208_bits[] = {
+0xfc, 0x0f, 0x00, 0xfc, 0x3f, 0x00, 0x0c, 0x78, 0x00, 0x0c, 0xe0, 0x00, 
+0x0c, 0xc0, 0x00, 0x0c, 0xc0, 0x01, 0x0c, 0x80, 0x01, 0x0c, 0x80, 0x01, 
+0xff, 0x80, 0x01, 0xff, 0x80, 0x01, 0x0c, 0x80, 0x01, 0x0c, 0x80, 0x01, 
+0x0c, 0x80, 0x01, 0x0c, 0xc0, 0x01, 0x0c, 0xc0, 0x00, 0x0c, 0xe0, 0x00, 
+0x0c, 0x78, 0x00, 0xfc, 0x3f, 0x00, 0xfc, 0x0f, 0x00};
+static unsigned char helvetica24_209_bits[] = {
+0xe0, 0x08, 0xb0, 0x0d, 0x10, 0x07, 0x00, 0x00, 0x07, 0x30, 0x0f, 0x30, 
+0x0f, 0x30, 0x1b, 0x30, 0x3b, 0x30, 0x33, 0x30, 0x73, 0x30, 0x63, 0x30, 
+0xe3, 0x30, 0xc3, 0x30, 0xc3, 0x31, 0x83, 0x31, 0x83, 0x33, 0x03, 0x33, 
+0x03, 0x37, 0x03, 0x36, 0x03, 0x3c, 0x03, 0x3c, 0x03, 0x38};
+static unsigned char helvetica24_210_bits[] = {
+0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x03, 0x00, 0x00, 0xe0, 0x07, 
+0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_211_bits[] = {
+0x00, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0x00, 0x00, 0xe0, 0x07, 
+0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_212_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x30, 0x0c, 0x00, 0x00, 0xe0, 0x07, 
+0xf8, 0x1f, 0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x07, 0xe0, 0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_213_bits[] = {
+0xe0, 0x08, 0xb0, 0x0d, 0x10, 0x07, 0x00, 0x00, 0xe0, 0x07, 0xf8, 0x1f, 
+0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, 
+0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_214_bits[] = {
+0x60, 0x06, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0xf8, 0x1f, 
+0x3c, 0x3c, 0x0e, 0x70, 0x06, 0x60, 0x07, 0xe0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, 
+0x06, 0x60, 0x0e, 0x70, 0x3c, 0x3c, 0xf8, 0x1f, 0xe0, 0x07};
+static unsigned char helvetica24_215_bits[] = {
+0x03, 0x18, 0x06, 0x0c, 0x0c, 0x06, 0x18, 0x03, 0xb0, 0x01, 0xe0, 0x00, 
+0xe0, 0x00, 0xb0, 0x01, 0x18, 0x03, 0x0c, 0x06, 0x06, 0x0c, 0x03, 0x18};
+static unsigned char helvetica24_216_bits[] = {
+0xc0, 0x0f, 0x02, 0xf0, 0x3f, 0x03, 0x78, 0xf8, 0x01, 0x1c, 0xe0, 0x00, 
+0x0c, 0xe0, 0x00, 0x0e, 0xb0, 0x01, 0x06, 0x98, 0x01, 0x06, 0x8c, 0x01, 
+0x06, 0x86, 0x01, 0x06, 0x83, 0x01, 0x86, 0x81, 0x01, 0xc6, 0x80, 0x01, 
+0x66, 0x80, 0x01, 0x36, 0xc0, 0x01, 0x1c, 0xc0, 0x00, 0x1c, 0xe0, 0x00, 
+0x7e, 0x78, 0x00, 0xf3, 0x3f, 0x00, 0xc1, 0x0f, 0x00};
+static unsigned char helvetica24_217_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x00, 0x00, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_218_bits[] = {
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_219_bits[] = {
+0xc0, 0x00, 0xe0, 0x01, 0x30, 0x03, 0x18, 0x06, 0x00, 0x00, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_220_bits[] = {
+0x30, 0x03, 0x30, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 0x03, 0x30, 
+0x03, 0x30, 0x06, 0x18, 0x0e, 0x1c, 0xfc, 0x0f, 0xf0, 0x03};
+static unsigned char helvetica24_221_bits[] = {
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x03, 0x30, 
+0x07, 0x38, 0x06, 0x18, 0x0e, 0x1c, 0x0c, 0x0c, 0x1c, 0x0e, 0x18, 0x06, 
+0x38, 0x07, 0x30, 0x03, 0xf0, 0x03, 0xe0, 0x01, 0xe0, 0x01, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char helvetica24_222_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x07, 0xff, 0x0f, 
+0x03, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x0c, 
+0xff, 0x0f, 0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char helvetica24_223_bits[] = {
+0x38, 0x00, 0xfe, 0x00, 0xc7, 0x00, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0xc3, 0x00, 0xe3, 0x00, 0x73, 0x00, 0xf3, 0x00, 0xc3, 0x01, 0x83, 0x01, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x01, 0xc3, 0x01, 0xf3, 0x00, 
+0x73, 0x00};
+static unsigned char helvetica24_224_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_225_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_226_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_227_bits[] = {
+0x38, 0x02, 0x6c, 0x03, 0xc4, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_228_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x01, 
+0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 0x1e, 0x03, 
+0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 0x3c, 0x06};
+static unsigned char helvetica24_229_bits[] = {
+0x70, 0x00, 0xd8, 0x00, 0x88, 0x00, 0xd8, 0x00, 0x70, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x86, 0x03, 0x06, 0x03, 0x00, 0x03, 0xe0, 0x03, 0xfc, 0x03, 
+0x1e, 0x03, 0x07, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc7, 0x03, 0x7e, 0x07, 
+0x3c, 0x06};
+static unsigned char helvetica24_230_bits[] = {
+0xf8, 0x70, 0x00, 0xfc, 0xfd, 0x01, 0x86, 0x8f, 0x03, 0x06, 0x07, 0x03, 
+0x00, 0x03, 0x06, 0xe0, 0x03, 0x06, 0xfc, 0xff, 0x07, 0x1e, 0xff, 0x07, 
+0x07, 0x03, 0x00, 0x03, 0x03, 0x00, 0x83, 0x07, 0x06, 0xc7, 0x0f, 0x07, 
+0x7e, 0xfc, 0x03, 0x3c, 0xf0, 0x00};
+static unsigned char helvetica24_231_bits[] = {
+0xf8, 0x00, 0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x03, 0x8e, 0x03, 
+0xfc, 0x01, 0xf8, 0x00, 0x38, 0x00, 0x60, 0x00, 0x60, 0x00, 0x7c, 0x00, 
+0x38, 0x00};
+static unsigned char helvetica24_232_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x70, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 
+0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 
+0xf0, 0x00};
+static unsigned char helvetica24_233_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 
+0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 
+0xf0, 0x00};
+static unsigned char helvetica24_234_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0x70, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 
+0xff, 0x07, 0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 
+0xf0, 0x00};
+static unsigned char helvetica24_235_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xfc, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0xff, 0x07, 0xff, 0x07, 
+0x03, 0x00, 0x03, 0x00, 0x06, 0x06, 0x0e, 0x07, 0xfc, 0x03, 0xf0, 0x00};
+static unsigned char helvetica24_236_bits[] = {
+0x03, 0x06, 0x0c, 0x18, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_237_bits[] = {
+0x18, 0x0c, 0x06, 0x03, 0x00, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06};
+static unsigned char helvetica24_238_bits[] = {
+0x18, 0x3c, 0x66, 0xc3, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char helvetica24_239_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c};
+static unsigned char helvetica24_240_bits[] = {
+0x07, 0x00, 0x8e, 0x01, 0x78, 0x00, 0x3c, 0x00, 0x63, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_241_bits[] = {
+0x1c, 0x01, 0xb6, 0x01, 0xe2, 0x00, 0x00, 0x00, 0x73, 0x00, 0xfb, 0x01, 
+0x8f, 0x01, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char helvetica24_242_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_243_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_244_bits[] = {
+0x60, 0x00, 0xf0, 0x00, 0x98, 0x01, 0x0c, 0x03, 0x00, 0x00, 0xf8, 0x00, 
+0xfc, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 
+0xf8, 0x00};
+static unsigned char helvetica24_245_bits[] = {
+0x38, 0x02, 0x6c, 0x03, 0xc4, 0x01, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_246_bits[] = {
+0x8c, 0x01, 0x8c, 0x01, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfc, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x06, 0x03, 0x8e, 0x03, 0xfc, 0x01, 0xf8, 0x00};
+static unsigned char helvetica24_247_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char helvetica24_248_bits[] = {
+0xf0, 0x19, 0xf8, 0x0f, 0x1c, 0x07, 0x0c, 0x06, 0x06, 0x0f, 0x86, 0x0d, 
+0xc6, 0x0c, 0x66, 0x0c, 0x66, 0x0c, 0x36, 0x0c, 0x1c, 0x06, 0x0c, 0x07, 
+0xfe, 0x03, 0xf3, 0x01};
+static unsigned char helvetica24_249_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 
+0x38, 0x03};
+static unsigned char helvetica24_250_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 
+0x38, 0x03};
+static unsigned char helvetica24_251_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 
+0x38, 0x03};
+static unsigned char helvetica24_252_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x03, 0x7e, 0x03, 0x38, 0x03};
+static unsigned char helvetica24_253_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x00, 0x00, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x0c, 0x0e, 0x06, 0x0c, 0x06, 0x1c, 0x07, 0x18, 0x03, 
+0x18, 0x03, 0xb0, 0x01, 0xb0, 0x01, 0xe0, 0x01, 0xe0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x1c, 0x00};
+static unsigned char helvetica24_254_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xf3, 0x00, 
+0xfb, 0x01, 0x8f, 0x03, 0x07, 0x03, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x03, 0x8f, 0x03, 0xfb, 0x01, 
+0xf3, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char helvetica24_255_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x0c, 0x0e, 0x06, 0x0c, 0x06, 0x1c, 0x07, 0x18, 0x03, 0x18, 0x03, 
+0xb0, 0x01, 0xb0, 0x01, 0xe0, 0x01, 0xe0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x3c, 0x00, 0x1c, 0x00};
+static RotFont helvetica24font[] = {
+{5, 1, 1, helvetica24_0_bits},
+{5, 1, 1, helvetica24_1_bits},
+{5, 1, 1, helvetica24_2_bits},
+{5, 1, 1, helvetica24_3_bits},
+{5, 1, 1, helvetica24_4_bits},
+{5, 1, 1, helvetica24_5_bits},
+{5, 1, 1, helvetica24_6_bits},
+{5, 1, 1, helvetica24_7_bits},
+{5, 1, 1, helvetica24_8_bits},
+{5, 1, 1, helvetica24_9_bits},
+{5, 1, 1, helvetica24_10_bits},
+{5, 1, 1, helvetica24_11_bits},
+{5, 1, 1, helvetica24_12_bits},
+{5, 1, 1, helvetica24_13_bits},
+{5, 1, 1, helvetica24_14_bits},
+{5, 1, 1, helvetica24_15_bits},
+{5, 1, 1, helvetica24_16_bits},
+{5, 1, 1, helvetica24_17_bits},
+{5, 1, 1, helvetica24_18_bits},
+{5, 1, 1, helvetica24_19_bits},
+{5, 1, 1, helvetica24_20_bits},
+{5, 1, 1, helvetica24_21_bits},
+{5, 1, 1, helvetica24_22_bits},
+{5, 1, 1, helvetica24_23_bits},
+{5, 1, 1, helvetica24_24_bits},
+{5, 1, 1, helvetica24_25_bits},
+{5, 1, 1, helvetica24_26_bits},
+{5, 1, 1, helvetica24_27_bits},
+{5, 1, 1, helvetica24_28_bits},
+{5, 1, 1, helvetica24_29_bits},
+{5, 1, 1, helvetica24_30_bits},
+{5, 1, 1, helvetica24_31_bits},
+{10, 1, 1, helvetica24_32_bits},
+{2, 19, 19, helvetica24_33_bits},
+{6, 6, 19, helvetica24_34_bits},
+{11, 17, 17, helvetica24_35_bits},
+{11, 21, 19, helvetica24_36_bits},
+{19, 18, 18, helvetica24_37_bits},
+{14, 18, 18, helvetica24_38_bits},
+{2, 6, 19, helvetica24_39_bits},
+{5, 24, 19, helvetica24_40_bits},
+{5, 24, 19, helvetica24_41_bits},
+{7, 7, 19, helvetica24_42_bits},
+{12, 12, 13, helvetica24_43_bits},
+{2, 6, 3, helvetica24_44_bits},
+{11, 2, 8, helvetica24_45_bits},
+{2, 3, 3, helvetica24_46_bits},
+{7, 19, 19, helvetica24_47_bits},
+{11, 18, 18, helvetica24_48_bits},
+{6, 18, 18, helvetica24_49_bits},
+{11, 18, 18, helvetica24_50_bits},
+{11, 18, 18, helvetica24_51_bits},
+{11, 18, 18, helvetica24_52_bits},
+{11, 18, 18, helvetica24_53_bits},
+{11, 18, 18, helvetica24_54_bits},
+{11, 18, 18, helvetica24_55_bits},
+{11, 18, 18, helvetica24_56_bits},
+{11, 18, 18, helvetica24_57_bits},
+{2, 14, 14, helvetica24_58_bits},
+{2, 17, 14, helvetica24_59_bits},
+{12, 12, 13, helvetica24_60_bits},
+{10, 6, 11, helvetica24_61_bits},
+{12, 12, 13, helvetica24_62_bits},
+{10, 19, 19, helvetica24_63_bits},
+{22, 23, 19, helvetica24_64_bits},
+{15, 19, 19, helvetica24_65_bits},
+{14, 19, 19, helvetica24_66_bits},
+{16, 19, 19, helvetica24_67_bits},
+{15, 19, 19, helvetica24_68_bits},
+{12, 19, 19, helvetica24_69_bits},
+{11, 19, 19, helvetica24_70_bits},
+{16, 19, 19, helvetica24_71_bits},
+{14, 19, 19, helvetica24_72_bits},
+{2, 19, 19, helvetica24_73_bits},
+{10, 19, 19, helvetica24_74_bits},
+{15, 19, 19, helvetica24_75_bits},
+{11, 19, 19, helvetica24_76_bits},
+{17, 19, 19, helvetica24_77_bits},
+{14, 19, 19, helvetica24_78_bits},
+{16, 19, 19, helvetica24_79_bits},
+{13, 19, 19, helvetica24_80_bits},
+{16, 19, 19, helvetica24_81_bits},
+{13, 19, 19, helvetica24_82_bits},
+{14, 19, 19, helvetica24_83_bits},
+{14, 19, 19, helvetica24_84_bits},
+{14, 19, 19, helvetica24_85_bits},
+{15, 19, 19, helvetica24_86_bits},
+{20, 19, 19, helvetica24_87_bits},
+{15, 19, 19, helvetica24_88_bits},
+{14, 19, 19, helvetica24_89_bits},
+{13, 19, 19, helvetica24_90_bits},
+{4, 24, 19, helvetica24_91_bits},
+{7, 19, 19, helvetica24_92_bits},
+{4, 24, 19, helvetica24_93_bits},
+{10, 9, 19, helvetica24_94_bits},
+{14, 2, -3, helvetica24_95_bits},
+{2, 6, 19, helvetica24_96_bits},
+{11, 14, 14, helvetica24_97_bits},
+{11, 19, 19, helvetica24_98_bits},
+{10, 14, 14, helvetica24_99_bits},
+{11, 19, 19, helvetica24_100_bits},
+{11, 14, 14, helvetica24_101_bits},
+{6, 19, 19, helvetica24_102_bits},
+{11, 19, 14, helvetica24_103_bits},
+{10, 19, 19, helvetica24_104_bits},
+{2, 19, 19, helvetica24_105_bits},
+{4, 24, 19, helvetica24_106_bits},
+{10, 19, 19, helvetica24_107_bits},
+{2, 19, 19, helvetica24_108_bits},
+{16, 14, 14, helvetica24_109_bits},
+{10, 14, 14, helvetica24_110_bits},
+{11, 14, 14, helvetica24_111_bits},
+{11, 19, 14, helvetica24_112_bits},
+{11, 19, 14, helvetica24_113_bits},
+{6, 14, 14, helvetica24_114_bits},
+{10, 14, 14, helvetica24_115_bits},
+{6, 18, 18, helvetica24_116_bits},
+{10, 14, 14, helvetica24_117_bits},
+{11, 14, 14, helvetica24_118_bits},
+{18, 14, 14, helvetica24_119_bits},
+{10, 14, 14, helvetica24_120_bits},
+{12, 19, 14, helvetica24_121_bits},
+{10, 14, 14, helvetica24_122_bits},
+{6, 24, 19, helvetica24_123_bits},
+{2, 24, 19, helvetica24_124_bits},
+{6, 24, 19, helvetica24_125_bits},
+{10, 4, 9, helvetica24_126_bits},
+{5, 1, 1, helvetica24_127_bits},
+{5, 1, 1, helvetica24_128_bits},
+{5, 1, 1, helvetica24_129_bits},
+{5, 1, 1, helvetica24_130_bits},
+{5, 1, 1, helvetica24_131_bits},
+{5, 1, 1, helvetica24_132_bits},
+{5, 1, 1, helvetica24_133_bits},
+{5, 1, 1, helvetica24_134_bits},
+{5, 1, 1, helvetica24_135_bits},
+{5, 1, 1, helvetica24_136_bits},
+{5, 1, 1, helvetica24_137_bits},
+{5, 1, 1, helvetica24_138_bits},
+{5, 1, 1, helvetica24_139_bits},
+{5, 1, 1, helvetica24_140_bits},
+{5, 1, 1, helvetica24_141_bits},
+{5, 1, 1, helvetica24_142_bits},
+{5, 1, 1, helvetica24_143_bits},
+{5, 1, 1, helvetica24_144_bits},
+{5, 1, 1, helvetica24_145_bits},
+{5, 1, 1, helvetica24_146_bits},
+{5, 1, 1, helvetica24_147_bits},
+{5, 1, 1, helvetica24_148_bits},
+{5, 1, 1, helvetica24_149_bits},
+{5, 1, 1, helvetica24_150_bits},
+{5, 1, 1, helvetica24_151_bits},
+{5, 1, 1, helvetica24_152_bits},
+{5, 1, 1, helvetica24_153_bits},
+{5, 1, 1, helvetica24_154_bits},
+{5, 1, 1, helvetica24_155_bits},
+{5, 1, 1, helvetica24_156_bits},
+{5, 1, 1, helvetica24_157_bits},
+{5, 1, 1, helvetica24_158_bits},
+{5, 1, 1, helvetica24_159_bits},
+{1, 1, 1, helvetica24_160_bits},
+{2, 19, 14, helvetica24_161_bits},
+{10, 18, 16, helvetica24_162_bits},
+{12, 18, 18, helvetica24_163_bits},
+{11, 12, 15, helvetica24_164_bits},
+{14, 18, 18, helvetica24_165_bits},
+{2, 23, 19, helvetica24_166_bits},
+{11, 24, 19, helvetica24_167_bits},
+{6, 2, 18, helvetica24_168_bits},
+{17, 17, 17, helvetica24_169_bits},
+{7, 12, 19, helvetica24_170_bits},
+{9, 8, 11, helvetica24_171_bits},
+{13, 8, 11, helvetica24_172_bits},
+{6, 2, 8, helvetica24_173_bits},
+{17, 17, 17, helvetica24_174_bits},
+{6, 2, 18, helvetica24_175_bits},
+{8, 7, 18, helvetica24_176_bits},
+{12, 13, 13, helvetica24_177_bits},
+{7, 10, 18, helvetica24_178_bits},
+{7, 10, 18, helvetica24_179_bits},
+{5, 4, 19, helvetica24_180_bits},
+{10, 19, 14, helvetica24_181_bits},
+{10, 23, 19, helvetica24_182_bits},
+{2, 3, 9, helvetica24_183_bits},
+{5, 6, 1, helvetica24_184_bits},
+{4, 10, 18, helvetica24_185_bits},
+{7, 12, 19, helvetica24_186_bits},
+{9, 8, 11, helvetica24_187_bits},
+{18, 18, 18, helvetica24_188_bits},
+{18, 18, 18, helvetica24_189_bits},
+{19, 18, 18, helvetica24_190_bits},
+{10, 19, 14, helvetica24_191_bits},
+{15, 24, 24, helvetica24_192_bits},
+{15, 24, 24, helvetica24_193_bits},
+{15, 24, 24, helvetica24_194_bits},
+{15, 23, 23, helvetica24_195_bits},
+{15, 23, 23, helvetica24_196_bits},
+{15, 24, 24, helvetica24_197_bits},
+{21, 19, 19, helvetica24_198_bits},
+{16, 24, 19, helvetica24_199_bits},
+{12, 24, 24, helvetica24_200_bits},
+{12, 24, 24, helvetica24_201_bits},
+{12, 24, 24, helvetica24_202_bits},
+{12, 23, 23, helvetica24_203_bits},
+{5, 24, 24, helvetica24_204_bits},
+{5, 24, 24, helvetica24_205_bits},
+{8, 24, 24, helvetica24_206_bits},
+{6, 23, 23, helvetica24_207_bits},
+{17, 19, 19, helvetica24_208_bits},
+{14, 23, 23, helvetica24_209_bits},
+{16, 24, 24, helvetica24_210_bits},
+{16, 24, 24, helvetica24_211_bits},
+{16, 24, 24, helvetica24_212_bits},
+{16, 23, 23, helvetica24_213_bits},
+{16, 23, 23, helvetica24_214_bits},
+{13, 12, 13, helvetica24_215_bits},
+{18, 19, 19, helvetica24_216_bits},
+{14, 24, 24, helvetica24_217_bits},
+{14, 24, 24, helvetica24_218_bits},
+{14, 24, 24, helvetica24_219_bits},
+{14, 23, 23, helvetica24_220_bits},
+{14, 24, 24, helvetica24_221_bits},
+{13, 19, 19, helvetica24_222_bits},
+{10, 19, 19, helvetica24_223_bits},
+{11, 19, 19, helvetica24_224_bits},
+{11, 19, 19, helvetica24_225_bits},
+{11, 19, 19, helvetica24_226_bits},
+{11, 19, 19, helvetica24_227_bits},
+{11, 18, 18, helvetica24_228_bits},
+{11, 19, 19, helvetica24_229_bits},
+{19, 14, 14, helvetica24_230_bits},
+{10, 19, 14, helvetica24_231_bits},
+{11, 19, 19, helvetica24_232_bits},
+{11, 19, 19, helvetica24_233_bits},
+{11, 19, 19, helvetica24_234_bits},
+{11, 18, 18, helvetica24_235_bits},
+{5, 19, 19, helvetica24_236_bits},
+{5, 19, 19, helvetica24_237_bits},
+{8, 19, 19, helvetica24_238_bits},
+{6, 18, 18, helvetica24_239_bits},
+{11, 19, 19, helvetica24_240_bits},
+{10, 18, 18, helvetica24_241_bits},
+{11, 19, 19, helvetica24_242_bits},
+{11, 19, 19, helvetica24_243_bits},
+{11, 19, 19, helvetica24_244_bits},
+{11, 18, 18, helvetica24_245_bits},
+{11, 18, 18, helvetica24_246_bits},
+{12, 12, 13, helvetica24_247_bits},
+{13, 14, 14, helvetica24_248_bits},
+{10, 19, 19, helvetica24_249_bits},
+{10, 19, 19, helvetica24_250_bits},
+{10, 19, 19, helvetica24_251_bits},
+{10, 18, 18, helvetica24_252_bits},
+{12, 24, 19, helvetica24_253_bits},
+{11, 24, 19, helvetica24_254_bits},
+{12, 23, 18, helvetica24_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica8.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica8.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica8.bdf	(revision 16632)
@@ -0,0 +1,2572 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Helvetica-Medium-R-Normal--8-80-75-75-P-46-ISO8859-1
+SIZE 8 75 75
+FONTBOUNDINGBOX 9 11 0 -2
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Helvetica"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 46
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 6
+X_HEIGHT 5
+FACE_NAME "Helvetica"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Helvetica is a trademark of Linotype-Hell AG and/or its subsidiaries.  "
+_DEC_DEVICE_FONTNAMES "PS=Helvetica"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 04-Dec-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Helvetica"
+FONT "-Adobe-Helvetica-Medium-R-Normal--8-80-75-75-P-46-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 5
+DEFAULT_CHAR 32
+FONT_ASCENT 8
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 1 3
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+50
+f8
+50
+f8
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 -1
+BITMAP
+20
+70
+80
+60
+10
+e0
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 6 1 0
+BITMAP
+e8
+a8
+d0
+2c
+54
+5c
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+40
+a0
+48
+a8
+b0
+58
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 3 1 3
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 1 -1
+BITMAP
+40
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 1 -1
+BITMAP
+80
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 1 2
+BITMAP
+40
+e0
+40
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 1 0
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 1 2 2
+BITMAP
+f0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 1 -1
+BITMAP
+40
+40
+40
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 2 6 2 0
+BITMAP
+40
+c0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 2 0
+BITMAP
+c0
+20
+c0
+20
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+20
+20
+60
+f0
+20
+20
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 2 0
+BITMAP
+e0
+80
+c0
+20
+20
+c0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+70
+80
+e0
+90
+90
+60
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+f0
+10
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 4 1 0
+BITMAP
+80
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 -2
+BITMAP
+40
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+BITMAP
+20
+40
+80
+40
+20
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 1 1
+BITMAP
+e0
+00
+e0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 2 0
+BITMAP
+80
+40
+20
+40
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 2 0
+BITMAP
+c0
+20
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 1080 0
+DWIDTH 9 0
+BBX 8 7 1 -1
+BITMAP
+3e
+41
+99
+a5
+9e
+80
+78
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+e0
+90
+e0
+90
+90
+e0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+80
+80
+88
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+f0
+88
+88
+88
+88
+f0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 2 0
+BITMAP
+f0
+80
+e0
+80
+80
+80
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+80
+98
+88
+88
+70
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+88
+88
+f8
+88
+88
+88
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 1 0
+BITMAP
+20
+20
+20
+20
+a0
+40
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+90
+a0
+c0
+e0
+90
+90
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 6 2 0
+BITMAP
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 6 2 0
+BITMAP
+88
+d8
+a8
+a8
+a8
+a8
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+88
+c8
+a8
+a8
+98
+88
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+e0
+90
+90
+e0
+80
+80
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 -2
+BITMAP
+70
+88
+88
+88
+88
+70
+20
+10
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+e0
+90
+90
+e0
+90
+90
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+70
+80
+e0
+10
+10
+e0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+90
+90
+90
+90
+a0
+40
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 6 1 0
+BITMAP
+92
+92
+92
+6c
+48
+48
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+90
+90
+60
+60
+90
+90
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+c8
+48
+48
+30
+20
+20
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 2 0
+BITMAP
+f0
+10
+20
+40
+80
+f0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 1 -1
+BITMAP
+c0
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+80
+80
+80
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+c0
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 3 0 2
+BITMAP
+20
+50
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 1 0 -1
+BITMAP
+f8
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 3 1 3
+BITMAP
+80
+80
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 1 0
+BITMAP
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+80
+80
+e0
+90
+90
+90
+e0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+60
+80
+80
+80
+60
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+10
+10
+70
+90
+90
+90
+70
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 1 0
+BITMAP
+20
+40
+e0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+70
+90
+90
+70
+10
+60
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+80
+80
+e0
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 0
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 9 0 -2
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+80
+80
+a0
+c0
+c0
+a0
+a0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+f0
+a8
+a8
+a8
+a8
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+e0
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+e0
+90
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+70
+90
+90
+90
+70
+10
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 1 0
+BITMAP
+a0
+c0
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+60
+80
+60
+20
+c0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 1 0
+BITMAP
+40
+40
+e0
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+90
+90
+90
+a0
+40
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+a8
+a8
+a8
+50
+50
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+90
+90
+60
+90
+90
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 1 -1
+BITMAP
+90
+90
+90
+60
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+e0
+20
+40
+80
+e0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+20
+40
+40
+c0
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+80
+40
+40
+60
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 2 1 2
+BITMAP
+48
+b0
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 -2
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 7 1 -1
+BITMAP
+40
+40
+a0
+80
+a0
+40
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 0
+BITMAP
+30
+40
+e0
+40
+40
+f0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 5 0 0
+BITMAP
+88
+70
+50
+70
+88
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+88
+50
+f8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 1 -1
+BITMAP
+80
+80
+80
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 -2
+BITMAP
+70
+80
+60
+90
+60
+30
+10
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 4 1 0 5
+BITMAP
+90
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+84
+b4
+a4
+b4
+84
+78
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 1
+BITMAP
+c0
+20
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 1 1
+BITMAP
+50
+a0
+50
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 3 1 1
+BITMAP
+f0
+10
+10
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 1 0 2
+BITMAP
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+84
+b4
+b4
+ac
+84
+78
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 1 0 5
+BITMAP
+e0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 1 3
+BITMAP
+40
+a0
+40
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+20
+f0
+20
+00
+f0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 1 2
+BITMAP
+80
+40
+80
+c0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 4 0 2
+BITMAP
+e0
+60
+20
+c0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 0 4
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 1 -2
+BITMAP
+a0
+a0
+a0
+e0
+80
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 8 0 -2
+BITMAP
+78
+d0
+d0
+d0
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 2 1 1
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 0 -2
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 0 2
+BITMAP
+40
+c0
+40
+40
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 1
+BITMAP
+e0
+a0
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 1 1
+BITMAP
+a0
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 7 0 -1
+BITMAP
+40
+c4
+48
+54
+2c
+5e
+04
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 7 0 -1
+BITMAP
+40
+c4
+48
+5c
+22
+44
+0e
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 7 0 -1
+BITMAP
+e0
+64
+28
+d4
+2c
+5e
+04
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 1 -1
+BITMAP
+20
+00
+20
+40
+90
+60
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+28
+50
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+20
+20
+20
+50
+70
+88
+88
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 6 1 0
+BITMAP
+3e
+30
+50
+7c
+90
+9e
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 -2
+BITMAP
+70
+88
+88
+80
+88
+70
+40
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 9 2 0
+BITMAP
+40
+20
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 9 2 0
+BITMAP
+20
+40
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 9 2 0
+BITMAP
+40
+a0
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 8 2 0
+BITMAP
+a0
+00
+f0
+80
+e0
+80
+80
+f0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 9 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 9 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 9 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 8 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+48
+e8
+48
+48
+70
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+28
+50
+00
+88
+c8
+a8
+a8
+98
+88
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 1 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 -1
+BITMAP
+08
+78
+88
+98
+a8
+c8
+f0
+80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+08
+10
+00
+c8
+48
+48
+30
+20
+20
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+80
+f0
+88
+88
+f0
+80
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 7 2 -1
+BITMAP
+60
+90
+a0
+90
+90
+a0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+80
+40
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+20
+40
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+40
+a0
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 8 0 0
+BITMAP
+68
+b0
+00
+60
+10
+70
+50
+68
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 1 0
+BITMAP
+a0
+00
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 0
+BITMAP
+40
+a0
+40
+c0
+20
+e0
+a0
+d0
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 1 0
+BITMAP
+d0
+28
+f8
+a0
+d8
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 -2
+BITMAP
+60
+80
+80
+80
+60
+40
+80
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+40
+20
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+20
+40
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+40
+a0
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+a0
+00
+40
+a0
+e0
+80
+60
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 0
+BITMAP
+80
+40
+00
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 1 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 8 0 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+90
+60
+a0
+70
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+50
+a0
+00
+e0
+90
+90
+90
+90
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+40
+20
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+10
+20
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+40
+a0
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 1 0
+BITMAP
+50
+a0
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 0
+BITMAP
+90
+00
+60
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+20
+00
+f0
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 7 7 0 -1
+BITMAP
+02
+3c
+48
+58
+68
+70
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+80
+40
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+20
+40
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 1 0
+BITMAP
+40
+a0
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 1 0
+BITMAP
+a0
+00
+a0
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 9 1 -1
+BITMAP
+10
+20
+00
+90
+90
+90
+60
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 1 -1
+BITMAP
+80
+e0
+90
+90
+90
+e0
+80
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 1 -1
+BITMAP
+50
+00
+90
+90
+90
+60
+40
+80
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica8.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica8.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/helvetica8.h	(revision 16632)
@@ -0,0 +1,769 @@
+static unsigned char helvetica8_0_bits[] = {
+0x00};
+static unsigned char helvetica8_1_bits[] = {
+0x00};
+static unsigned char helvetica8_2_bits[] = {
+0x00};
+static unsigned char helvetica8_3_bits[] = {
+0x00};
+static unsigned char helvetica8_4_bits[] = {
+0x00};
+static unsigned char helvetica8_5_bits[] = {
+0x00};
+static unsigned char helvetica8_6_bits[] = {
+0x00};
+static unsigned char helvetica8_7_bits[] = {
+0x00};
+static unsigned char helvetica8_8_bits[] = {
+0x00};
+static unsigned char helvetica8_9_bits[] = {
+0x00};
+static unsigned char helvetica8_10_bits[] = {
+0x00};
+static unsigned char helvetica8_11_bits[] = {
+0x00};
+static unsigned char helvetica8_12_bits[] = {
+0x00};
+static unsigned char helvetica8_13_bits[] = {
+0x00};
+static unsigned char helvetica8_14_bits[] = {
+0x00};
+static unsigned char helvetica8_15_bits[] = {
+0x00};
+static unsigned char helvetica8_16_bits[] = {
+0x00};
+static unsigned char helvetica8_17_bits[] = {
+0x00};
+static unsigned char helvetica8_18_bits[] = {
+0x00};
+static unsigned char helvetica8_19_bits[] = {
+0x00};
+static unsigned char helvetica8_20_bits[] = {
+0x00};
+static unsigned char helvetica8_21_bits[] = {
+0x00};
+static unsigned char helvetica8_22_bits[] = {
+0x00};
+static unsigned char helvetica8_23_bits[] = {
+0x00};
+static unsigned char helvetica8_24_bits[] = {
+0x00};
+static unsigned char helvetica8_25_bits[] = {
+0x00};
+static unsigned char helvetica8_26_bits[] = {
+0x00};
+static unsigned char helvetica8_27_bits[] = {
+0x00};
+static unsigned char helvetica8_28_bits[] = {
+0x00};
+static unsigned char helvetica8_29_bits[] = {
+0x00};
+static unsigned char helvetica8_30_bits[] = {
+0x00};
+static unsigned char helvetica8_31_bits[] = {
+0x00};
+static unsigned char helvetica8_32_bits[] = {
+0x00};
+static unsigned char helvetica8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char helvetica8_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char helvetica8_35_bits[] = {
+0x0a, 0x1f, 0x0a, 0x1f, 0x0a};
+static unsigned char helvetica8_36_bits[] = {
+0x04, 0x0e, 0x01, 0x06, 0x08, 0x07, 0x02};
+static unsigned char helvetica8_37_bits[] = {
+0x17, 0x15, 0x0b, 0x34, 0x2a, 0x3a};
+static unsigned char helvetica8_38_bits[] = {
+0x02, 0x05, 0x12, 0x15, 0x0d, 0x1a};
+static unsigned char helvetica8_39_bits[] = {
+0x01, 0x01, 0x01};
+static unsigned char helvetica8_40_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char helvetica8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_42_bits[] = {
+0x02, 0x07, 0x02};
+static unsigned char helvetica8_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char helvetica8_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char helvetica8_45_bits[] = {
+0x0f};
+static unsigned char helvetica8_46_bits[] = {
+0x01};
+static unsigned char helvetica8_47_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_48_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_50_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char helvetica8_51_bits[] = {
+0x03, 0x04, 0x03, 0x04, 0x04, 0x03};
+static unsigned char helvetica8_52_bits[] = {
+0x04, 0x04, 0x06, 0x0f, 0x04, 0x04};
+static unsigned char helvetica8_53_bits[] = {
+0x07, 0x01, 0x03, 0x04, 0x04, 0x03};
+static unsigned char helvetica8_54_bits[] = {
+0x0e, 0x01, 0x07, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_55_bits[] = {
+0x0f, 0x08, 0x04, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_56_bits[] = {
+0x06, 0x09, 0x06, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_57_bits[] = {
+0x06, 0x09, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char helvetica8_58_bits[] = {
+0x01, 0x00, 0x00, 0x01};
+static unsigned char helvetica8_59_bits[] = {
+0x02, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_60_bits[] = {
+0x04, 0x02, 0x01, 0x02, 0x04};
+static unsigned char helvetica8_61_bits[] = {
+0x07, 0x00, 0x07};
+static unsigned char helvetica8_62_bits[] = {
+0x01, 0x02, 0x04, 0x02, 0x01};
+static unsigned char helvetica8_63_bits[] = {
+0x03, 0x04, 0x02, 0x00, 0x02};
+static unsigned char helvetica8_64_bits[] = {
+0x7c, 0x82, 0x99, 0xa5, 0x79, 0x01, 0x1e};
+static unsigned char helvetica8_65_bits[] = {
+0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_66_bits[] = {
+0x07, 0x09, 0x07, 0x09, 0x09, 0x07};
+static unsigned char helvetica8_67_bits[] = {
+0x0e, 0x11, 0x01, 0x01, 0x11, 0x0e};
+static unsigned char helvetica8_68_bits[] = {
+0x0f, 0x11, 0x11, 0x11, 0x11, 0x0f};
+static unsigned char helvetica8_69_bits[] = {
+0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_70_bits[] = {
+0x0f, 0x01, 0x07, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_71_bits[] = {
+0x0e, 0x01, 0x19, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_72_bits[] = {
+0x11, 0x11, 0x1f, 0x11, 0x11, 0x11};
+static unsigned char helvetica8_73_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_74_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x05, 0x02};
+static unsigned char helvetica8_75_bits[] = {
+0x09, 0x05, 0x03, 0x07, 0x09, 0x09};
+static unsigned char helvetica8_76_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char helvetica8_77_bits[] = {
+0x11, 0x1b, 0x15, 0x15, 0x15, 0x15};
+static unsigned char helvetica8_78_bits[] = {
+0x11, 0x13, 0x15, 0x15, 0x19, 0x11};
+static unsigned char helvetica8_79_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_80_bits[] = {
+0x07, 0x09, 0x09, 0x07, 0x01, 0x01};
+static unsigned char helvetica8_81_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e, 0x04, 0x08};
+static unsigned char helvetica8_82_bits[] = {
+0x07, 0x09, 0x09, 0x07, 0x09, 0x09};
+static unsigned char helvetica8_83_bits[] = {
+0x0e, 0x01, 0x07, 0x08, 0x08, 0x07};
+static unsigned char helvetica8_84_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_85_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_86_bits[] = {
+0x09, 0x09, 0x09, 0x09, 0x05, 0x02};
+static unsigned char helvetica8_87_bits[] = {
+0x49, 0x49, 0x49, 0x36, 0x12, 0x12};
+static unsigned char helvetica8_88_bits[] = {
+0x09, 0x09, 0x06, 0x06, 0x09, 0x09};
+static unsigned char helvetica8_89_bits[] = {
+0x13, 0x12, 0x12, 0x0c, 0x04, 0x04};
+static unsigned char helvetica8_90_bits[] = {
+0x0f, 0x08, 0x04, 0x02, 0x01, 0x0f};
+static unsigned char helvetica8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char helvetica8_92_bits[] = {
+0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char helvetica8_94_bits[] = {
+0x04, 0x0a, 0x11};
+static unsigned char helvetica8_95_bits[] = {
+0x1f};
+static unsigned char helvetica8_96_bits[] = {
+0x01, 0x01, 0x01};
+static unsigned char helvetica8_97_bits[] = {
+0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_98_bits[] = {
+0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x07};
+static unsigned char helvetica8_99_bits[] = {
+0x06, 0x01, 0x01, 0x01, 0x06};
+static unsigned char helvetica8_100_bits[] = {
+0x08, 0x08, 0x0e, 0x09, 0x09, 0x09, 0x0e};
+static unsigned char helvetica8_101_bits[] = {
+0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_102_bits[] = {
+0x04, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_103_bits[] = {
+0x0e, 0x09, 0x09, 0x0e, 0x08, 0x06};
+static unsigned char helvetica8_104_bits[] = {
+0x01, 0x01, 0x07, 0x09, 0x09, 0x09, 0x09};
+static unsigned char helvetica8_105_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_106_bits[] = {
+0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_107_bits[] = {
+0x01, 0x01, 0x05, 0x03, 0x03, 0x05, 0x05};
+static unsigned char helvetica8_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_109_bits[] = {
+0x0f, 0x15, 0x15, 0x15, 0x15};
+static unsigned char helvetica8_110_bits[] = {
+0x07, 0x09, 0x09, 0x09, 0x09};
+static unsigned char helvetica8_111_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_112_bits[] = {
+0x07, 0x09, 0x09, 0x09, 0x07, 0x01};
+static unsigned char helvetica8_113_bits[] = {
+0x0e, 0x09, 0x09, 0x09, 0x0e, 0x08};
+static unsigned char helvetica8_114_bits[] = {
+0x05, 0x03, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_115_bits[] = {
+0x06, 0x01, 0x06, 0x04, 0x03};
+static unsigned char helvetica8_116_bits[] = {
+0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_117_bits[] = {
+0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_118_bits[] = {
+0x09, 0x09, 0x09, 0x05, 0x02};
+static unsigned char helvetica8_119_bits[] = {
+0x15, 0x15, 0x15, 0x0a, 0x0a};
+static unsigned char helvetica8_120_bits[] = {
+0x09, 0x09, 0x06, 0x09, 0x09};
+static unsigned char helvetica8_121_bits[] = {
+0x09, 0x09, 0x09, 0x06, 0x02, 0x01};
+static unsigned char helvetica8_122_bits[] = {
+0x07, 0x04, 0x02, 0x01, 0x07};
+static unsigned char helvetica8_123_bits[] = {
+0x04, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04};
+static unsigned char helvetica8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_125_bits[] = {
+0x01, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01};
+static unsigned char helvetica8_126_bits[] = {
+0x12, 0x0d};
+static unsigned char helvetica8_127_bits[] = {
+0x00};
+static unsigned char helvetica8_128_bits[] = {
+0x00};
+static unsigned char helvetica8_129_bits[] = {
+0x00};
+static unsigned char helvetica8_130_bits[] = {
+0x00};
+static unsigned char helvetica8_131_bits[] = {
+0x00};
+static unsigned char helvetica8_132_bits[] = {
+0x00};
+static unsigned char helvetica8_133_bits[] = {
+0x00};
+static unsigned char helvetica8_134_bits[] = {
+0x00};
+static unsigned char helvetica8_135_bits[] = {
+0x00};
+static unsigned char helvetica8_136_bits[] = {
+0x00};
+static unsigned char helvetica8_137_bits[] = {
+0x00};
+static unsigned char helvetica8_138_bits[] = {
+0x00};
+static unsigned char helvetica8_139_bits[] = {
+0x00};
+static unsigned char helvetica8_140_bits[] = {
+0x00};
+static unsigned char helvetica8_141_bits[] = {
+0x00};
+static unsigned char helvetica8_142_bits[] = {
+0x00};
+static unsigned char helvetica8_143_bits[] = {
+0x00};
+static unsigned char helvetica8_144_bits[] = {
+0x00};
+static unsigned char helvetica8_145_bits[] = {
+0x00};
+static unsigned char helvetica8_146_bits[] = {
+0x00};
+static unsigned char helvetica8_147_bits[] = {
+0x00};
+static unsigned char helvetica8_148_bits[] = {
+0x00};
+static unsigned char helvetica8_149_bits[] = {
+0x00};
+static unsigned char helvetica8_150_bits[] = {
+0x00};
+static unsigned char helvetica8_151_bits[] = {
+0x00};
+static unsigned char helvetica8_152_bits[] = {
+0x00};
+static unsigned char helvetica8_153_bits[] = {
+0x00};
+static unsigned char helvetica8_154_bits[] = {
+0x00};
+static unsigned char helvetica8_155_bits[] = {
+0x00};
+static unsigned char helvetica8_156_bits[] = {
+0x00};
+static unsigned char helvetica8_157_bits[] = {
+0x00};
+static unsigned char helvetica8_158_bits[] = {
+0x00};
+static unsigned char helvetica8_159_bits[] = {
+0x00};
+static unsigned char helvetica8_160_bits[] = {
+0x00};
+static unsigned char helvetica8_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_162_bits[] = {
+0x02, 0x02, 0x05, 0x01, 0x05, 0x02, 0x02};
+static unsigned char helvetica8_163_bits[] = {
+0x0c, 0x02, 0x07, 0x02, 0x02, 0x0f};
+static unsigned char helvetica8_164_bits[] = {
+0x11, 0x0e, 0x0a, 0x0e, 0x11};
+static unsigned char helvetica8_165_bits[] = {
+0x11, 0x0a, 0x1f, 0x04, 0x04};
+static unsigned char helvetica8_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_167_bits[] = {
+0x0e, 0x01, 0x06, 0x09, 0x06, 0x0c, 0x08, 0x07};
+static unsigned char helvetica8_168_bits[] = {
+0x09};
+static unsigned char helvetica8_169_bits[] = {
+0x1e, 0x21, 0x2d, 0x25, 0x2d, 0x21, 0x1e};
+static unsigned char helvetica8_170_bits[] = {
+0x03, 0x04, 0x07, 0x00, 0x07};
+static unsigned char helvetica8_171_bits[] = {
+0x0a, 0x05, 0x0a};
+static unsigned char helvetica8_172_bits[] = {
+0x0f, 0x08, 0x08};
+static unsigned char helvetica8_173_bits[] = {
+0x03};
+static unsigned char helvetica8_174_bits[] = {
+0x1e, 0x21, 0x2d, 0x2d, 0x35, 0x21, 0x1e};
+static unsigned char helvetica8_175_bits[] = {
+0x07};
+static unsigned char helvetica8_176_bits[] = {
+0x02, 0x05, 0x02};
+static unsigned char helvetica8_177_bits[] = {
+0x04, 0x0f, 0x04, 0x00, 0x0f};
+static unsigned char helvetica8_178_bits[] = {
+0x01, 0x02, 0x01, 0x03};
+static unsigned char helvetica8_179_bits[] = {
+0x07, 0x06, 0x04, 0x03};
+static unsigned char helvetica8_180_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica8_181_bits[] = {
+0x05, 0x05, 0x05, 0x07, 0x01, 0x01};
+static unsigned char helvetica8_182_bits[] = {
+0x1e, 0x0b, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char helvetica8_183_bits[] = {
+0x01, 0x01};
+static unsigned char helvetica8_184_bits[] = {
+0x02, 0x01};
+static unsigned char helvetica8_185_bits[] = {
+0x02, 0x03, 0x02, 0x02};
+static unsigned char helvetica8_186_bits[] = {
+0x07, 0x05, 0x07, 0x00, 0x07};
+static unsigned char helvetica8_187_bits[] = {
+0x05, 0x0a, 0x05};
+static unsigned char helvetica8_188_bits[] = {
+0x02, 0x23, 0x12, 0x2a, 0x34, 0x7a, 0x20};
+static unsigned char helvetica8_189_bits[] = {
+0x02, 0x23, 0x12, 0x3a, 0x44, 0x22, 0x70};
+static unsigned char helvetica8_190_bits[] = {
+0x07, 0x26, 0x14, 0x2b, 0x34, 0x7a, 0x20};
+static unsigned char helvetica8_191_bits[] = {
+0x04, 0x00, 0x04, 0x02, 0x09, 0x06};
+static unsigned char helvetica8_192_bits[] = {
+0x02, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_193_bits[] = {
+0x08, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_194_bits[] = {
+0x04, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_195_bits[] = {
+0x14, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_196_bits[] = {
+0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_197_bits[] = {
+0x04, 0x0a, 0x04, 0x04, 0x04, 0x0a, 0x0e, 0x11, 0x11};
+static unsigned char helvetica8_198_bits[] = {
+0x7c, 0x0c, 0x0a, 0x3e, 0x09, 0x79};
+static unsigned char helvetica8_199_bits[] = {
+0x0e, 0x11, 0x11, 0x01, 0x11, 0x0e, 0x02, 0x01};
+static unsigned char helvetica8_200_bits[] = {
+0x02, 0x04, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_201_bits[] = {
+0x04, 0x02, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_202_bits[] = {
+0x02, 0x05, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_203_bits[] = {
+0x05, 0x00, 0x0f, 0x01, 0x07, 0x01, 0x01, 0x0f};
+static unsigned char helvetica8_204_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_205_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_206_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_207_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_208_bits[] = {
+0x0e, 0x12, 0x17, 0x12, 0x12, 0x0e};
+static unsigned char helvetica8_209_bits[] = {
+0x14, 0x0a, 0x00, 0x11, 0x13, 0x15, 0x15, 0x19, 0x11};
+static unsigned char helvetica8_210_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_211_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_212_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_213_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_214_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_215_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char helvetica8_216_bits[] = {
+0x10, 0x1e, 0x11, 0x19, 0x15, 0x13, 0x0f, 0x01};
+static unsigned char helvetica8_217_bits[] = {
+0x02, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_218_bits[] = {
+0x08, 0x04, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_219_bits[] = {
+0x04, 0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_220_bits[] = {
+0x0a, 0x00, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char helvetica8_221_bits[] = {
+0x10, 0x08, 0x00, 0x13, 0x12, 0x12, 0x0c, 0x04, 0x04};
+static unsigned char helvetica8_222_bits[] = {
+0x01, 0x0f, 0x11, 0x11, 0x0f, 0x01};
+static unsigned char helvetica8_223_bits[] = {
+0x06, 0x09, 0x05, 0x09, 0x09, 0x05, 0x01};
+static unsigned char helvetica8_224_bits[] = {
+0x01, 0x02, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_225_bits[] = {
+0x04, 0x02, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_226_bits[] = {
+0x02, 0x05, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_227_bits[] = {
+0x16, 0x0d, 0x00, 0x06, 0x08, 0x0e, 0x0a, 0x16};
+static unsigned char helvetica8_228_bits[] = {
+0x05, 0x00, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_229_bits[] = {
+0x02, 0x05, 0x02, 0x03, 0x04, 0x07, 0x05, 0x0b};
+static unsigned char helvetica8_230_bits[] = {
+0x0b, 0x14, 0x1f, 0x05, 0x1b};
+static unsigned char helvetica8_231_bits[] = {
+0x06, 0x01, 0x01, 0x01, 0x06, 0x02, 0x01};
+static unsigned char helvetica8_232_bits[] = {
+0x02, 0x04, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_233_bits[] = {
+0x04, 0x02, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_234_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_235_bits[] = {
+0x05, 0x00, 0x02, 0x05, 0x07, 0x01, 0x06};
+static unsigned char helvetica8_236_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char helvetica8_238_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_239_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char helvetica8_240_bits[] = {
+0x09, 0x06, 0x05, 0x0e, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_241_bits[] = {
+0x0a, 0x05, 0x00, 0x07, 0x09, 0x09, 0x09, 0x09};
+static unsigned char helvetica8_242_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_243_bits[] = {
+0x08, 0x04, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_244_bits[] = {
+0x02, 0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_245_bits[] = {
+0x0a, 0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_246_bits[] = {
+0x09, 0x00, 0x06, 0x09, 0x09, 0x09, 0x06};
+static unsigned char helvetica8_247_bits[] = {
+0x04, 0x00, 0x0f, 0x00, 0x04};
+static unsigned char helvetica8_248_bits[] = {
+0x40, 0x3c, 0x12, 0x1a, 0x16, 0x0e, 0x01};
+static unsigned char helvetica8_249_bits[] = {
+0x01, 0x02, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_250_bits[] = {
+0x04, 0x02, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_251_bits[] = {
+0x02, 0x05, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_252_bits[] = {
+0x05, 0x00, 0x05, 0x05, 0x05, 0x05, 0x06};
+static unsigned char helvetica8_253_bits[] = {
+0x08, 0x04, 0x00, 0x09, 0x09, 0x09, 0x06, 0x02, 0x01};
+static unsigned char helvetica8_254_bits[] = {
+0x01, 0x07, 0x09, 0x09, 0x09, 0x07, 0x01};
+static unsigned char helvetica8_255_bits[] = {
+0x0a, 0x00, 0x09, 0x09, 0x09, 0x06, 0x02, 0x01};
+static RotFont helvetica8font[] = {
+{5, 1, 1, helvetica8_0_bits},
+{5, 1, 1, helvetica8_1_bits},
+{5, 1, 1, helvetica8_2_bits},
+{5, 1, 1, helvetica8_3_bits},
+{5, 1, 1, helvetica8_4_bits},
+{5, 1, 1, helvetica8_5_bits},
+{5, 1, 1, helvetica8_6_bits},
+{5, 1, 1, helvetica8_7_bits},
+{5, 1, 1, helvetica8_8_bits},
+{5, 1, 1, helvetica8_9_bits},
+{5, 1, 1, helvetica8_10_bits},
+{5, 1, 1, helvetica8_11_bits},
+{5, 1, 1, helvetica8_12_bits},
+{5, 1, 1, helvetica8_13_bits},
+{5, 1, 1, helvetica8_14_bits},
+{5, 1, 1, helvetica8_15_bits},
+{5, 1, 1, helvetica8_16_bits},
+{5, 1, 1, helvetica8_17_bits},
+{5, 1, 1, helvetica8_18_bits},
+{5, 1, 1, helvetica8_19_bits},
+{5, 1, 1, helvetica8_20_bits},
+{5, 1, 1, helvetica8_21_bits},
+{5, 1, 1, helvetica8_22_bits},
+{5, 1, 1, helvetica8_23_bits},
+{5, 1, 1, helvetica8_24_bits},
+{5, 1, 1, helvetica8_25_bits},
+{5, 1, 1, helvetica8_26_bits},
+{5, 1, 1, helvetica8_27_bits},
+{5, 1, 1, helvetica8_28_bits},
+{5, 1, 1, helvetica8_29_bits},
+{5, 1, 1, helvetica8_30_bits},
+{5, 1, 1, helvetica8_31_bits},
+{4, 1, 1, helvetica8_32_bits},
+{1, 6, 6, helvetica8_33_bits},
+{3, 3, 6, helvetica8_34_bits},
+{5, 5, 5, helvetica8_35_bits},
+{4, 7, 6, helvetica8_36_bits},
+{6, 6, 6, helvetica8_37_bits},
+{5, 6, 6, helvetica8_38_bits},
+{1, 3, 6, helvetica8_39_bits},
+{2, 7, 6, helvetica8_40_bits},
+{2, 7, 6, helvetica8_41_bits},
+{3, 3, 5, helvetica8_42_bits},
+{5, 5, 5, helvetica8_43_bits},
+{2, 3, 1, helvetica8_44_bits},
+{4, 1, 3, helvetica8_45_bits},
+{1, 1, 1, helvetica8_46_bits},
+{2, 7, 6, helvetica8_47_bits},
+{4, 6, 6, helvetica8_48_bits},
+{2, 6, 6, helvetica8_49_bits},
+{4, 6, 6, helvetica8_50_bits},
+{3, 6, 6, helvetica8_51_bits},
+{4, 6, 6, helvetica8_52_bits},
+{3, 6, 6, helvetica8_53_bits},
+{4, 6, 6, helvetica8_54_bits},
+{4, 6, 6, helvetica8_55_bits},
+{4, 6, 6, helvetica8_56_bits},
+{4, 6, 6, helvetica8_57_bits},
+{1, 4, 4, helvetica8_58_bits},
+{2, 6, 4, helvetica8_59_bits},
+{3, 5, 5, helvetica8_60_bits},
+{3, 3, 4, helvetica8_61_bits},
+{3, 5, 5, helvetica8_62_bits},
+{3, 5, 5, helvetica8_63_bits},
+{8, 7, 6, helvetica8_64_bits},
+{5, 6, 6, helvetica8_65_bits},
+{4, 6, 6, helvetica8_66_bits},
+{5, 6, 6, helvetica8_67_bits},
+{5, 6, 6, helvetica8_68_bits},
+{4, 6, 6, helvetica8_69_bits},
+{4, 6, 6, helvetica8_70_bits},
+{5, 6, 6, helvetica8_71_bits},
+{5, 6, 6, helvetica8_72_bits},
+{1, 6, 6, helvetica8_73_bits},
+{3, 6, 6, helvetica8_74_bits},
+{4, 6, 6, helvetica8_75_bits},
+{3, 6, 6, helvetica8_76_bits},
+{5, 6, 6, helvetica8_77_bits},
+{5, 6, 6, helvetica8_78_bits},
+{5, 6, 6, helvetica8_79_bits},
+{4, 6, 6, helvetica8_80_bits},
+{5, 8, 6, helvetica8_81_bits},
+{4, 6, 6, helvetica8_82_bits},
+{4, 6, 6, helvetica8_83_bits},
+{3, 6, 6, helvetica8_84_bits},
+{5, 6, 6, helvetica8_85_bits},
+{4, 6, 6, helvetica8_86_bits},
+{7, 6, 6, helvetica8_87_bits},
+{4, 6, 6, helvetica8_88_bits},
+{5, 6, 6, helvetica8_89_bits},
+{4, 6, 6, helvetica8_90_bits},
+{2, 7, 6, helvetica8_91_bits},
+{2, 7, 6, helvetica8_92_bits},
+{2, 7, 6, helvetica8_93_bits},
+{5, 3, 5, helvetica8_94_bits},
+{5, 1, 0, helvetica8_95_bits},
+{1, 3, 6, helvetica8_96_bits},
+{4, 5, 5, helvetica8_97_bits},
+{4, 7, 7, helvetica8_98_bits},
+{3, 5, 5, helvetica8_99_bits},
+{4, 7, 7, helvetica8_100_bits},
+{3, 5, 5, helvetica8_101_bits},
+{3, 7, 7, helvetica8_102_bits},
+{4, 6, 5, helvetica8_103_bits},
+{4, 7, 7, helvetica8_104_bits},
+{1, 7, 7, helvetica8_105_bits},
+{2, 9, 7, helvetica8_106_bits},
+{3, 7, 7, helvetica8_107_bits},
+{1, 7, 7, helvetica8_108_bits},
+{5, 5, 5, helvetica8_109_bits},
+{4, 5, 5, helvetica8_110_bits},
+{4, 5, 5, helvetica8_111_bits},
+{4, 6, 5, helvetica8_112_bits},
+{4, 6, 5, helvetica8_113_bits},
+{3, 5, 5, helvetica8_114_bits},
+{3, 5, 5, helvetica8_115_bits},
+{3, 7, 7, helvetica8_116_bits},
+{3, 5, 5, helvetica8_117_bits},
+{4, 5, 5, helvetica8_118_bits},
+{5, 5, 5, helvetica8_119_bits},
+{4, 5, 5, helvetica8_120_bits},
+{4, 6, 5, helvetica8_121_bits},
+{3, 5, 5, helvetica8_122_bits},
+{3, 7, 6, helvetica8_123_bits},
+{1, 7, 6, helvetica8_124_bits},
+{3, 7, 6, helvetica8_125_bits},
+{5, 2, 4, helvetica8_126_bits},
+{5, 1, 1, helvetica8_127_bits},
+{5, 1, 1, helvetica8_128_bits},
+{5, 1, 1, helvetica8_129_bits},
+{5, 1, 1, helvetica8_130_bits},
+{5, 1, 1, helvetica8_131_bits},
+{5, 1, 1, helvetica8_132_bits},
+{5, 1, 1, helvetica8_133_bits},
+{5, 1, 1, helvetica8_134_bits},
+{5, 1, 1, helvetica8_135_bits},
+{5, 1, 1, helvetica8_136_bits},
+{5, 1, 1, helvetica8_137_bits},
+{5, 1, 1, helvetica8_138_bits},
+{5, 1, 1, helvetica8_139_bits},
+{5, 1, 1, helvetica8_140_bits},
+{5, 1, 1, helvetica8_141_bits},
+{5, 1, 1, helvetica8_142_bits},
+{5, 1, 1, helvetica8_143_bits},
+{5, 1, 1, helvetica8_144_bits},
+{5, 1, 1, helvetica8_145_bits},
+{5, 1, 1, helvetica8_146_bits},
+{5, 1, 1, helvetica8_147_bits},
+{5, 1, 1, helvetica8_148_bits},
+{5, 1, 1, helvetica8_149_bits},
+{5, 1, 1, helvetica8_150_bits},
+{5, 1, 1, helvetica8_151_bits},
+{5, 1, 1, helvetica8_152_bits},
+{5, 1, 1, helvetica8_153_bits},
+{5, 1, 1, helvetica8_154_bits},
+{5, 1, 1, helvetica8_155_bits},
+{5, 1, 1, helvetica8_156_bits},
+{5, 1, 1, helvetica8_157_bits},
+{5, 1, 1, helvetica8_158_bits},
+{5, 1, 1, helvetica8_159_bits},
+{1, 1, 1, helvetica8_160_bits},
+{1, 7, 5, helvetica8_161_bits},
+{3, 7, 6, helvetica8_162_bits},
+{4, 6, 6, helvetica8_163_bits},
+{5, 5, 5, helvetica8_164_bits},
+{5, 5, 5, helvetica8_165_bits},
+{1, 7, 6, helvetica8_166_bits},
+{4, 8, 6, helvetica8_167_bits},
+{4, 1, 6, helvetica8_168_bits},
+{6, 7, 6, helvetica8_169_bits},
+{3, 5, 6, helvetica8_170_bits},
+{4, 3, 4, helvetica8_171_bits},
+{4, 3, 4, helvetica8_172_bits},
+{2, 1, 3, helvetica8_173_bits},
+{6, 7, 6, helvetica8_174_bits},
+{3, 1, 6, helvetica8_175_bits},
+{3, 3, 6, helvetica8_176_bits},
+{4, 5, 5, helvetica8_177_bits},
+{2, 4, 6, helvetica8_178_bits},
+{3, 4, 6, helvetica8_179_bits},
+{2, 2, 6, helvetica8_180_bits},
+{3, 6, 4, helvetica8_181_bits},
+{5, 8, 6, helvetica8_182_bits},
+{1, 2, 3, helvetica8_183_bits},
+{2, 2, 0, helvetica8_184_bits},
+{2, 4, 6, helvetica8_185_bits},
+{3, 5, 6, helvetica8_186_bits},
+{4, 3, 4, helvetica8_187_bits},
+{7, 7, 6, helvetica8_188_bits},
+{7, 7, 6, helvetica8_189_bits},
+{7, 7, 6, helvetica8_190_bits},
+{4, 6, 5, helvetica8_191_bits},
+{5, 9, 9, helvetica8_192_bits},
+{5, 9, 9, helvetica8_193_bits},
+{5, 9, 9, helvetica8_194_bits},
+{5, 9, 9, helvetica8_195_bits},
+{5, 8, 8, helvetica8_196_bits},
+{5, 9, 9, helvetica8_197_bits},
+{7, 6, 6, helvetica8_198_bits},
+{5, 8, 6, helvetica8_199_bits},
+{4, 9, 9, helvetica8_200_bits},
+{4, 9, 9, helvetica8_201_bits},
+{4, 9, 9, helvetica8_202_bits},
+{4, 8, 8, helvetica8_203_bits},
+{2, 9, 9, helvetica8_204_bits},
+{2, 9, 9, helvetica8_205_bits},
+{3, 9, 9, helvetica8_206_bits},
+{3, 8, 8, helvetica8_207_bits},
+{5, 6, 6, helvetica8_208_bits},
+{5, 9, 9, helvetica8_209_bits},
+{5, 9, 9, helvetica8_210_bits},
+{5, 9, 9, helvetica8_211_bits},
+{5, 9, 9, helvetica8_212_bits},
+{5, 9, 9, helvetica8_213_bits},
+{5, 8, 8, helvetica8_214_bits},
+{4, 4, 4, helvetica8_215_bits},
+{5, 8, 7, helvetica8_216_bits},
+{5, 9, 9, helvetica8_217_bits},
+{5, 9, 9, helvetica8_218_bits},
+{5, 9, 9, helvetica8_219_bits},
+{5, 8, 8, helvetica8_220_bits},
+{5, 9, 9, helvetica8_221_bits},
+{5, 6, 6, helvetica8_222_bits},
+{4, 7, 6, helvetica8_223_bits},
+{4, 8, 8, helvetica8_224_bits},
+{4, 8, 8, helvetica8_225_bits},
+{4, 8, 8, helvetica8_226_bits},
+{5, 8, 8, helvetica8_227_bits},
+{4, 7, 7, helvetica8_228_bits},
+{4, 8, 8, helvetica8_229_bits},
+{5, 5, 5, helvetica8_230_bits},
+{3, 7, 5, helvetica8_231_bits},
+{3, 8, 8, helvetica8_232_bits},
+{3, 8, 8, helvetica8_233_bits},
+{3, 8, 8, helvetica8_234_bits},
+{3, 7, 7, helvetica8_235_bits},
+{2, 8, 8, helvetica8_236_bits},
+{2, 8, 8, helvetica8_237_bits},
+{3, 8, 8, helvetica8_238_bits},
+{3, 7, 7, helvetica8_239_bits},
+{4, 8, 8, helvetica8_240_bits},
+{4, 8, 8, helvetica8_241_bits},
+{4, 8, 8, helvetica8_242_bits},
+{4, 8, 8, helvetica8_243_bits},
+{4, 8, 8, helvetica8_244_bits},
+{4, 8, 8, helvetica8_245_bits},
+{4, 7, 7, helvetica8_246_bits},
+{4, 5, 5, helvetica8_247_bits},
+{7, 7, 6, helvetica8_248_bits},
+{3, 8, 8, helvetica8_249_bits},
+{3, 8, 8, helvetica8_250_bits},
+{3, 8, 8, helvetica8_251_bits},
+{3, 7, 7, helvetica8_252_bits},
+{4, 9, 8, helvetica8_253_bits},
+{4, 7, 6, helvetica8_254_bits},
+{4, 8, 7, helvetica8_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol12.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol12.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol12.bdf	(revision 16632)
@@ -0,0 +1,3022 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--12-120-75-75-P-74-Adobe-FontSpecific
+SIZE 12 75 75
+FONTBOUNDINGBOX 14 16 -1 -4
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 74
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 9
+X_HEIGHT 6
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--12-120-75-75-P-74-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 8
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+8080
+4100
+4100
+3e00
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+28
+28
+28
+fc
+50
+f8
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+f8
+08
+08
+08
+f8
+08
+08
+08
+f8
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+7900
+9700
+9200
+6400
+0800
+1300
+1480
+2480
+6300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+3000
+4800
+4800
+3700
+7200
+9a00
+8c00
+8c80
+7300
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+e0
+10
+f0
+10
+10
+e0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 5 0 2
+BITMAP
+20
+a8
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 1 1 3
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+88
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 9 1 0
+BITMAP
+40
+c0
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+08
+30
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+18
+28
+28
+48
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+78
+40
+80
+f0
+18
+08
+08
+88
+f0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+38
+40
+80
+b0
+c8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+f8
+88
+10
+10
+20
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+c8
+70
+98
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+88
+78
+10
+10
+20
+40
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 6 2 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+f8
+00
+f8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+20
+00
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+68
+b0
+00
+f8
+00
+f8
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+0800
+1c00
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+46
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+24
+18
+18
+24
+24
+42
+e7
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+10
+10
+28
+28
+44
+44
+44
+82
+fe
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+1c00
+0800
+7f00
+c980
+8880
+c980
+7f00
+0800
+1c00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 9 0 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+04
+0a
+0a
+66
+a3
+22
+22
+26
+1c
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ee
+44
+48
+50
+70
+48
+44
+42
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+0800
+0800
+1400
+1400
+2200
+2200
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 9 0 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+5140
+4a40
+4a40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+62
+52
+52
+4a
+4a
+46
+46
+e2
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ff
+42
+42
+42
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+42
+a5
+bd
+a5
+42
+66
+3c
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+f8
+4c
+44
+4c
+78
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fc
+84
+c0
+60
+30
+20
+40
+82
+fe
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+78
+80
+80
+80
+c0
+70
+08
+48
+70
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+1e00
+3300
+2100
+4080
+4080
+4080
+2100
+9240
+f3c0
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+7e
+42
+00
+24
+3c
+24
+00
+81
+ff
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+dd80
+4900
+4900
+6b00
+3e00
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+fc
+84
+08
+10
+20
+20
+40
+84
+fc
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 6 1 0
+BITMAP
+10
+10
+00
+00
+82
+82
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 0 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+fe
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 1 0 -3
+BITMAP
+fc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 7 1 0 11
+BITMAP
+fe
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 6 1 0
+BITMAP
+74
+d4
+88
+88
+d4
+66
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+70
+88
+88
+88
+b0
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 -3
+BITMAP
+c6
+ac
+28
+18
+30
+28
+68
+4a
+c6
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+98
+80
+40
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+70
+80
+e0
+80
+90
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 11 0 -3
+BITMAP
+10
+10
+38
+54
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 -3
+BITMAP
+c4
+a4
+24
+24
+28
+18
+10
+30
+20
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 -3
+BITMAP
+6c
+b2
+22
+22
+22
+22
+02
+02
+02
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 6 0 0
+BITMAP
+c0
+40
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 -3
+BITMAP
+18
+54
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 6 0 0
+BITMAP
+4c
+d4
+60
+70
+58
+4c
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+60
+50
+10
+30
+28
+48
+48
+8a
+86
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 1 -3
+BITMAP
+88
+88
+88
+88
+9a
+ec
+80
+80
+c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 6 0 0
+BITMAP
+cc
+44
+44
+28
+28
+30
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+70
+88
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+7e
+a4
+24
+24
+26
+64
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 0
+BITMAP
+70
+88
+88
+88
+f8
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 9 1 -3
+BITMAP
+70
+88
+88
+88
+c8
+b0
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+7c
+90
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+78
+a0
+20
+20
+28
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 6 0 0
+BITMAP
+64
+a2
+22
+22
+26
+1c
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+7f
+a2
+49
+49
+49
+49
+36
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 6 1 0
+BITMAP
+44
+92
+92
+92
+92
+6c
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 14 1 -3
+BITMAP
+40
+80
+70
+c0
+80
+f0
+40
+80
+80
+c0
+70
+08
+48
+70
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 -3
+BITMAP
+8880
+4900
+4900
+4900
+6b00
+3e00
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 13 1 -3
+BITMAP
+40
+98
+70
+40
+80
+80
+80
+80
+c0
+70
+08
+48
+70
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+18
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 12 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+c0
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 3 0 2
+BITMAP
+62
+92
+8c
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 3 1 6
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 5 9 -1 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 4 0 1
+BITMAP
+0000
+0000
+0000
+c600
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+28
+10
+10
+10
+10
+10
+38
+20
+40
+80
+0c
+30
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 7 1 -1
+BITMAP
+c0
+30
+0c
+00
+fc
+08
+10
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+10
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 6 1 0
+BITMAP
+80
+76
+00
+98
+80
+8c
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 7 1 -1
+BITMAP
+80
+76
+00
+0c
+14
+10
+7c
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 11 5 1 1
+BITMAP
+1000
+1020
+2020
+a0c0
+3820
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 12 5 0 1
+BITMAP
+d6f0
+d610
+1020
+70f0
+f870
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 16 1 -4
+BITMAP
+20
+68
+f8
+f8
+78
+38
+10
+10
+38
+78
+f8
+d0
+10
+10
+20
+80
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 12 5 0 1
+BITMAP
+4040
+ffe0
+4040
+2080
+2000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 15 1 -3
+BITMAP
+40
+00
+f8
+f0
+40
+00
+20
+00
+20
+70
+a8
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 5
+BITMAP
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+20
+20
+20
+00
+40
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 5 3 0 6
+BITMAP
+00
+20
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 0 0
+BITMAP
+f0
+00
+20
+00
+40
+20
+20
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 4 0 1
+BITMAP
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+20
+a8
+70
+20
+60
+90
+90
+60
+20
+20
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 4 1 1
+BITMAP
+f0
+20
+20
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+f8
+28
+50
+a0
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+30
+08
+30
+c0
+00
+f8
+88
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+50
+20
+50
+88
+70
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+88
+88
+74
+60
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 1 1 0
+BITMAP
+0800
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 1 16 3 -4
+BITMAP
+00
+80
+80
+80
+80
+00
+00
+80
+80
+00
+00
+00
+80
+00
+00
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 13 1 0 3
+BITMAP
+10f8
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 8 0 0
+BITMAP
+20
+f8
+40
+80
+f8
+00
+f8
+00
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 7 9 1 0
+BITMAP
+f8
+64
+98
+00
+64
+98
+88
+80
+80
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+8080
+8080
+ff80
+0200
+0200
+0200
+fe00
+8880
+6600
+d480
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 11 1 -3
+BITMAP
+4c
+66
+e2
+3f
+61
+42
+64
+0c
+06
+03
+01
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+6180
+1c00
+0080
+0080
+0080
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+0000
+0080
+8000
+2600
+9180
+ab80
+6480
+9000
+1c00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+6300
+6300
+9480
+8880
+9480
+6300
+6300
+1c00
+1c00
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 6 1 0
+BITMAP
+63
+00
+49
+00
+88
+80
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 6 1 0
+BITMAP
+be
+80
+88
+80
+49
+00
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 6 1 0
+BITMAP
+63
+00
+1c
+00
+1c
+80
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 8 1 -2
+BITMAP
+63
+00
+43
+00
+84
+80
+88
+80
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 8 0 -1
+BITMAP
+90
+80
+61
+00
+63
+00
+9c
+00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 6 0 0
+BITMAP
+3c
+42
+81
+81
+81
+81
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 8 0 -2
+BITMAP
+81
+81
+81
+81
+42
+3c
+fc
+02
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+00
+00
+00
+fc
+fc
+00
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 8 1 -1
+BITMAP
+00
+00
+00
+fc
+00
+fc
+00
+3c
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+4480
+8800
+3f00
+3f00
+8080
+4000
+3f00
+8080
+4000
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+00
+ff
+7c
+80
+fc
+80
+80
+7c
+04
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+7c
+88
+fc
+90
+a0
+7c
+40
+00
+80
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+01
+00
+02
+00
+04
+00
+08
+00
+10
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 6 0 3
+BITMAP
+0020
+0040
+00e0
+80e0
+8140
+4220
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 11 0 -1
+BITMAP
+2400
+1800
+3c00
+f980
+b980
+ed00
+3c00
+4280
+a980
+a580
+4200
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 12 0 0
+BITMAP
+fa
+80
+aa
+80
+24
+40
+24
+40
+24
+40
+76
+60
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 1 1 3
+BITMAP
+c0
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 7 4 1 0
+BITMAP
+80
+40
+00
+40
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+00
+40
+00
+40
+00
+40
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 6 1 0
+BITMAP
+00
+40
+00
+40
+00
+40
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1040 0
+DWIDTH 13 0
+BBX 11 5 1 1
+BITMAP
+0040
+00e0
+8000
+0200
+0400
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 11 5 0 1
+BITMAP
+0460
+a820
+2800
+10c0
+fe00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 5 12 1 -1
+BITMAP
+00
+00
+30
+30
+48
+48
+80
+80
+80
+80
+48
+48
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 11 5 1 1
+BITMAP
+3020
+2080
+7fc0
+c060
+7fc0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 5 12 1 0
+BITMAP
+20
+80
+20
+00
+78
+e0
+c0
+00
+78
+e0
+20
+00
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+20
+70
+d8
+50
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 11 0 -1
+BITMAP
+50
+50
+50
+00
+80
+f0
+c0
+00
+60
+f0
+c0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+00
+80
+50
+50
+50
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+50
+50
+d8
+70
+20
+30
+30
+48
+84
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 10 6 0 3
+BITMAP
+8440
+4800
+3000
+2000
+4040
+8040
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 -1
+BITMAP
+40
+20
+20
+10
+3c
+42
+b9
+a5
+b9
+a5
+a5
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 1 -4
+BITMAP
+40
+30
+30
+40
+90
+a0
+a0
+a0
+90
+40
+30
+f0
+80
+20
+80
+20
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 1 -4
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+80
+80
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 1 -4
+BITMAP
+80
+f0
+10
+20
+20
+40
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 16 1 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 1 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 15 1 -3
+BITMAP
+20
+00
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 2 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 0 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 15 2 -3
+BITMAP
+80
+e0
+60
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 1 16 2 -4
+BITMAP
+80
+80
+80
+00
+00
+00
+00
+00
+00
+00
+80
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 12 0 -2
+BITMAP
+20
+20
+20
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 5 15 0 -3
+BITMAP
+80
+80
+80
+80
+80
+60
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 5 16 4 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+40
+40
+20
+20
+10
+10
+20
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 1 16 1 -4
+BITMAP
+00
+00
+00
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 5 15 0 -3
+BITMAP
+20
+a0
+c0
+38
+58
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 0 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 3 -4
+BITMAP
+80
+80
+80
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 16 0 -4
+BITMAP
+00
+d0
+e0
+80
+40
+40
+20
+20
+20
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 16 1 -4
+BITMAP
+00
+00
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 1 16 3 -4
+BITMAP
+80
+80
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 15 1 -3
+BITMAP
+40
+40
+80
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 0 -4
+BITMAP
+20
+20
+20
+20
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 16 2 -4
+BITMAP
+80
+80
+80
+80
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 3 15 0 -3
+BITMAP
+20
+20
+e0
+c0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol12.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol12.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol12.h	(revision 16632)
@@ -0,0 +1,815 @@
+static unsigned char symbol12_0_bits[] = {
+0x00};
+static unsigned char symbol12_1_bits[] = {
+0x00};
+static unsigned char symbol12_2_bits[] = {
+0x00};
+static unsigned char symbol12_3_bits[] = {
+0x00};
+static unsigned char symbol12_4_bits[] = {
+0x00};
+static unsigned char symbol12_5_bits[] = {
+0x00};
+static unsigned char symbol12_6_bits[] = {
+0x00};
+static unsigned char symbol12_7_bits[] = {
+0x00};
+static unsigned char symbol12_8_bits[] = {
+0x00};
+static unsigned char symbol12_9_bits[] = {
+0x00};
+static unsigned char symbol12_10_bits[] = {
+0x00};
+static unsigned char symbol12_11_bits[] = {
+0x00};
+static unsigned char symbol12_12_bits[] = {
+0x00};
+static unsigned char symbol12_13_bits[] = {
+0x00};
+static unsigned char symbol12_14_bits[] = {
+0x00};
+static unsigned char symbol12_15_bits[] = {
+0x00};
+static unsigned char symbol12_16_bits[] = {
+0x00};
+static unsigned char symbol12_17_bits[] = {
+0x00};
+static unsigned char symbol12_18_bits[] = {
+0x00};
+static unsigned char symbol12_19_bits[] = {
+0x00};
+static unsigned char symbol12_20_bits[] = {
+0x00};
+static unsigned char symbol12_21_bits[] = {
+0x00};
+static unsigned char symbol12_22_bits[] = {
+0x00};
+static unsigned char symbol12_23_bits[] = {
+0x00};
+static unsigned char symbol12_24_bits[] = {
+0x00};
+static unsigned char symbol12_25_bits[] = {
+0x00};
+static unsigned char symbol12_26_bits[] = {
+0x00};
+static unsigned char symbol12_27_bits[] = {
+0x00};
+static unsigned char symbol12_28_bits[] = {
+0x00};
+static unsigned char symbol12_29_bits[] = {
+0x00};
+static unsigned char symbol12_30_bits[] = {
+0x00};
+static unsigned char symbol12_31_bits[] = {
+0x00};
+static unsigned char symbol12_32_bits[] = {
+0x00};
+static unsigned char symbol12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char symbol12_34_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x82, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol12_35_bits[] = {
+0x14, 0x14, 0x14, 0x3f, 0x0a, 0x1f, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol12_36_bits[] = {
+0x1f, 0x10, 0x10, 0x10, 0x1f, 0x10, 0x10, 0x10, 0x1f};
+static unsigned char symbol12_37_bits[] = {
+0x9e, 0x00, 0xe9, 0x00, 0x49, 0x00, 0x26, 0x00, 0x10, 0x00, 0xc8, 0x00, 
+0x28, 0x01, 0x24, 0x01, 0xc6, 0x00};
+static unsigned char symbol12_38_bits[] = {
+0x0c, 0x00, 0x12, 0x00, 0x12, 0x00, 0xec, 0x00, 0x4e, 0x00, 0x59, 0x00, 
+0x31, 0x00, 0x31, 0x01, 0xce, 0x00};
+static unsigned char symbol12_39_bits[] = {
+0x07, 0x08, 0x0f, 0x08, 0x08, 0x07};
+static unsigned char symbol12_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char symbol12_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char symbol12_42_bits[] = {
+0x04, 0x15, 0x0e, 0x15, 0x04};
+static unsigned char symbol12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char symbol12_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char symbol12_45_bits[] = {
+0x1f};
+static unsigned char symbol12_46_bits[] = {
+0x01};
+static unsigned char symbol12_47_bits[] = {
+0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char symbol12_48_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_50_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char symbol12_51_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x0c, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char symbol12_52_bits[] = {
+0x18, 0x14, 0x14, 0x12, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char symbol12_53_bits[] = {
+0x1e, 0x02, 0x01, 0x0f, 0x18, 0x10, 0x10, 0x11, 0x0f};
+static unsigned char symbol12_54_bits[] = {
+0x1c, 0x02, 0x01, 0x0d, 0x13, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_55_bits[] = {
+0x1f, 0x11, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02};
+static unsigned char symbol12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x13, 0x0e, 0x19, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_57_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x1e, 0x08, 0x08, 0x04, 0x02};
+static unsigned char symbol12_58_bits[] = {
+0x01, 0x00, 0x00, 0x00, 0x00, 0x01};
+static unsigned char symbol12_59_bits[] = {
+0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char symbol12_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char symbol12_61_bits[] = {
+0x1f, 0x00, 0x1f};
+static unsigned char symbol12_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char symbol12_63_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x04, 0x00, 0x04};
+static unsigned char symbol12_64_bits[] = {
+0x16, 0x0d, 0x00, 0x1f, 0x00, 0x1f};
+static unsigned char symbol12_65_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 
+0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol12_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x62, 0x42, 0x62, 0x3f};
+static unsigned char symbol12_67_bits[] = {
+0xe7, 0x42, 0x24, 0x18, 0x18, 0x24, 0x24, 0x42, 0xe7};
+static unsigned char symbol12_68_bits[] = {
+0x08, 0x08, 0x14, 0x14, 0x22, 0x22, 0x22, 0x41, 0x7f};
+static unsigned char symbol12_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char symbol12_70_bits[] = {
+0x38, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x93, 0x01, 0x11, 0x01, 0x93, 0x01, 
+0xfe, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol12_71_bits[] = {
+0x7f, 0x42, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char symbol12_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_74_bits[] = {
+0x20, 0x50, 0x50, 0x66, 0xc5, 0x44, 0x44, 0x64, 0x38};
+static unsigned char symbol12_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x42, 0xe7};
+static unsigned char symbol12_76_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol12_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0x8a, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char symbol12_78_bits[] = {
+0xe7, 0x46, 0x4a, 0x4a, 0x52, 0x52, 0x62, 0x62, 0x47};
+static unsigned char symbol12_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char symbol12_80_bits[] = {
+0xff, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char symbol12_81_bits[] = {
+0x3c, 0x66, 0x42, 0xa5, 0xbd, 0xa5, 0x42, 0x66, 0x3c};
+static unsigned char symbol12_82_bits[] = {
+0x1f, 0x32, 0x22, 0x32, 0x1e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol12_83_bits[] = {
+0x3f, 0x21, 0x03, 0x06, 0x0c, 0x04, 0x02, 0x41, 0x7f};
+static unsigned char symbol12_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char symbol12_85_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol12_86_bits[] = {
+0x1e, 0x01, 0x01, 0x01, 0x03, 0x0e, 0x10, 0x12, 0x0e};
+static unsigned char symbol12_87_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x84, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x84, 0x00, 0x49, 0x02, 0xcf, 0x03};
+static unsigned char symbol12_88_bits[] = {
+0x7e, 0x42, 0x00, 0x24, 0x3c, 0x24, 0x00, 0x81, 0xff};
+static unsigned char symbol12_89_bits[] = {
+0xbb, 0x01, 0x92, 0x00, 0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol12_90_bits[] = {
+0x3f, 0x21, 0x10, 0x08, 0x04, 0x04, 0x02, 0x21, 0x3f};
+static unsigned char symbol12_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char symbol12_92_bits[] = {
+0x08, 0x08, 0x00, 0x00, 0x41, 0x41};
+static unsigned char symbol12_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char symbol12_94_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x7f};
+static unsigned char symbol12_95_bits[] = {
+0x3f};
+static unsigned char symbol12_96_bits[] = {
+0x7f};
+static unsigned char symbol12_97_bits[] = {
+0x2e, 0x2b, 0x11, 0x11, 0x2b, 0x66};
+static unsigned char symbol12_98_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0d, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 
+0x01};
+static unsigned char symbol12_99_bits[] = {
+0x63, 0x35, 0x14, 0x18, 0x0c, 0x14, 0x16, 0x52, 0x63};
+static unsigned char symbol12_100_bits[] = {
+0x0e, 0x19, 0x01, 0x02, 0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_101_bits[] = {
+0x0e, 0x01, 0x07, 0x01, 0x09, 0x0e};
+static unsigned char symbol12_102_bits[] = {
+0x08, 0x08, 0x1c, 0x2a, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 0x08};
+static unsigned char symbol12_103_bits[] = {
+0x23, 0x25, 0x24, 0x24, 0x14, 0x18, 0x08, 0x0c, 0x04};
+static unsigned char symbol12_104_bits[] = {
+0x36, 0x4d, 0x44, 0x44, 0x44, 0x44, 0x40, 0x40, 0x40};
+static unsigned char symbol12_105_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x06};
+static unsigned char symbol12_106_bits[] = {
+0x18, 0x2a, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 0x08};
+static unsigned char symbol12_107_bits[] = {
+0x32, 0x2b, 0x06, 0x0e, 0x1a, 0x32};
+static unsigned char symbol12_108_bits[] = {
+0x06, 0x0a, 0x08, 0x0c, 0x14, 0x12, 0x12, 0x51, 0x61};
+static unsigned char symbol12_109_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x59, 0x37, 0x01, 0x01, 0x03};
+static unsigned char symbol12_110_bits[] = {
+0x33, 0x22, 0x22, 0x14, 0x14, 0x0c};
+static unsigned char symbol12_111_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_112_bits[] = {
+0x7e, 0x25, 0x24, 0x24, 0x64, 0x26};
+static unsigned char symbol12_113_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_114_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x13, 0x0d, 0x01, 0x01, 0x01};
+static unsigned char symbol12_115_bits[] = {
+0x3e, 0x09, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char symbol12_116_bits[] = {
+0x1e, 0x05, 0x04, 0x04, 0x14, 0x0c};
+static unsigned char symbol12_117_bits[] = {
+0x26, 0x45, 0x44, 0x44, 0x64, 0x38};
+static unsigned char symbol12_118_bits[] = {
+0xfe, 0x45, 0x92, 0x92, 0x92, 0x92, 0x6c};
+static unsigned char symbol12_119_bits[] = {
+0x22, 0x49, 0x49, 0x49, 0x49, 0x36};
+static unsigned char symbol12_120_bits[] = {
+0x02, 0x01, 0x0e, 0x03, 0x01, 0x0f, 0x02, 0x01, 0x01, 0x03, 0x0e, 0x10, 
+0x12, 0x0e};
+static unsigned char symbol12_121_bits[] = {
+0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol12_122_bits[] = {
+0x02, 0x19, 0x0e, 0x02, 0x01, 0x01, 0x01, 0x01, 0x03, 0x0e, 0x10, 0x12, 
+0x0e};
+static unsigned char symbol12_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 0x18};
+static unsigned char symbol12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 0x03};
+static unsigned char symbol12_126_bits[] = {
+0x46, 0x49, 0x31};
+static unsigned char symbol12_127_bits[] = {
+0x00};
+static unsigned char symbol12_128_bits[] = {
+0x00};
+static unsigned char symbol12_129_bits[] = {
+0x00};
+static unsigned char symbol12_130_bits[] = {
+0x00};
+static unsigned char symbol12_131_bits[] = {
+0x00};
+static unsigned char symbol12_132_bits[] = {
+0x00};
+static unsigned char symbol12_133_bits[] = {
+0x00};
+static unsigned char symbol12_134_bits[] = {
+0x00};
+static unsigned char symbol12_135_bits[] = {
+0x00};
+static unsigned char symbol12_136_bits[] = {
+0x00};
+static unsigned char symbol12_137_bits[] = {
+0x00};
+static unsigned char symbol12_138_bits[] = {
+0x00};
+static unsigned char symbol12_139_bits[] = {
+0x00};
+static unsigned char symbol12_140_bits[] = {
+0x00};
+static unsigned char symbol12_141_bits[] = {
+0x00};
+static unsigned char symbol12_142_bits[] = {
+0x00};
+static unsigned char symbol12_143_bits[] = {
+0x00};
+static unsigned char symbol12_144_bits[] = {
+0x00};
+static unsigned char symbol12_145_bits[] = {
+0x00};
+static unsigned char symbol12_146_bits[] = {
+0x00};
+static unsigned char symbol12_147_bits[] = {
+0x00};
+static unsigned char symbol12_148_bits[] = {
+0x00};
+static unsigned char symbol12_149_bits[] = {
+0x00};
+static unsigned char symbol12_150_bits[] = {
+0x00};
+static unsigned char symbol12_151_bits[] = {
+0x00};
+static unsigned char symbol12_152_bits[] = {
+0x00};
+static unsigned char symbol12_153_bits[] = {
+0x00};
+static unsigned char symbol12_154_bits[] = {
+0x00};
+static unsigned char symbol12_155_bits[] = {
+0x00};
+static unsigned char symbol12_156_bits[] = {
+0x00};
+static unsigned char symbol12_157_bits[] = {
+0x00};
+static unsigned char symbol12_158_bits[] = {
+0x00};
+static unsigned char symbol12_159_bits[] = {
+0x00};
+static unsigned char symbol12_160_bits[] = {
+0x00};
+static unsigned char symbol12_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_162_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol12_163_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_164_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_165_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x00};
+static unsigned char symbol12_166_bits[] = {
+0x14, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x04, 0x02, 0x01, 0x30, 0x0c};
+static unsigned char symbol12_167_bits[] = {
+0x03, 0x0c, 0x30, 0x00, 0x3f, 0x10, 0x08};
+static unsigned char symbol12_168_bits[] = {
+0x08, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char symbol12_169_bits[] = {
+0x01, 0x6e, 0x00, 0x19, 0x01, 0x31};
+static unsigned char symbol12_170_bits[] = {
+0x01, 0x6e, 0x00, 0x30, 0x28, 0x08, 0x3e};
+static unsigned char symbol12_171_bits[] = {
+0x08, 0x00, 0x08, 0x04, 0x04, 0x04, 0x05, 0x03, 0x1c, 0x04};
+static unsigned char symbol12_172_bits[] = {
+0x6b, 0x0f, 0x6b, 0x08, 0x08, 0x04, 0x0e, 0x0f, 0x1f, 0x0e};
+static unsigned char symbol12_173_bits[] = {
+0x04, 0x16, 0x1f, 0x1f, 0x1e, 0x1c, 0x08, 0x08, 0x1c, 0x1e, 0x1f, 0x0b, 
+0x08, 0x08, 0x04, 0x01};
+static unsigned char symbol12_174_bits[] = {
+0x02, 0x02, 0xff, 0x07, 0x02, 0x02, 0x04, 0x01, 0x04, 0x00};
+static unsigned char symbol12_175_bits[] = {
+0x02, 0x00, 0x1f, 0x0f, 0x02, 0x00, 0x04, 0x00, 0x04, 0x0e, 0x15, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol12_176_bits[] = {
+0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_177_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x02};
+static unsigned char symbol12_178_bits[] = {
+0x00, 0x04, 0x1f};
+static unsigned char symbol12_179_bits[] = {
+0x0f, 0x00, 0x04, 0x00, 0x02, 0x04, 0x04};
+static unsigned char symbol12_180_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_181_bits[] = {
+0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_182_bits[] = {
+0x04, 0x15, 0x0e, 0x04, 0x06, 0x09, 0x09, 0x06, 0x04, 0x04};
+static unsigned char symbol12_183_bits[] = {
+0x0f, 0x04, 0x04, 0x00};
+static unsigned char symbol12_184_bits[] = {
+0x1f, 0x14, 0x0a, 0x05, 0x03};
+static unsigned char symbol12_185_bits[] = {
+0x0c, 0x10, 0x0c, 0x03, 0x00, 0x1f, 0x11};
+static unsigned char symbol12_186_bits[] = {
+0x0a, 0x04, 0x0a, 0x11, 0x0e};
+static unsigned char symbol12_187_bits[] = {
+0x11, 0x11, 0x2e, 0x06, 0x09};
+static unsigned char symbol12_188_bits[] = {
+0x10, 0x00};
+static unsigned char symbol12_189_bits[] = {
+0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 
+0x01, 0x00, 0x00, 0x00};
+static unsigned char symbol12_190_bits[] = {
+0x08, 0x1f};
+static unsigned char symbol12_191_bits[] = {
+0x04, 0x1f, 0x02, 0x01, 0x1f, 0x00, 0x1f, 0x00};
+static unsigned char symbol12_192_bits[] = {
+0x1f, 0x26, 0x19, 0x00, 0x26, 0x19, 0x11, 0x01, 0x01};
+static unsigned char symbol12_193_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_194_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0xff, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x7f, 0x00, 0x11, 0x01, 0x66, 0x00, 0x2b, 0x01};
+static unsigned char symbol12_195_bits[] = {
+0x32, 0x66, 0x47, 0xfc, 0x86, 0x42, 0x26, 0x30, 0x60, 0xc0, 0x80};
+static unsigned char symbol12_196_bits[] = {
+0x86, 0x01, 0x38, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_197_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x64, 0x00, 0x89, 0x01, 0xd5, 0x01, 
+0x26, 0x01, 0x09, 0x00, 0x38, 0x00};
+static unsigned char symbol12_198_bits[] = {
+0xc6, 0x00, 0xc6, 0x00, 0x29, 0x01, 0x11, 0x01, 0x29, 0x01, 0xc6, 0x00, 
+0xc6, 0x00, 0x38, 0x00, 0x38, 0x00};
+static unsigned char symbol12_199_bits[] = {
+0xc6, 0x00, 0x92, 0x00, 0x11, 0x01};
+static unsigned char symbol12_200_bits[] = {
+0x7d, 0x01, 0x11, 0x01, 0x92, 0x00};
+static unsigned char symbol12_201_bits[] = {
+0xc6, 0x00, 0x38, 0x00, 0x38, 0x01};
+static unsigned char symbol12_202_bits[] = {
+0xc6, 0x00, 0xc2, 0x00, 0x21, 0x01, 0x11, 0x01};
+static unsigned char symbol12_203_bits[] = {
+0x09, 0x01, 0x86, 0x00, 0xc6, 0x00, 0x39, 0x00};
+static unsigned char symbol12_204_bits[] = {
+0x3c, 0x42, 0x81, 0x81, 0x81, 0x81};
+static unsigned char symbol12_205_bits[] = {
+0x81, 0x81, 0x81, 0x81, 0x42, 0x3c, 0x3f, 0x40};
+static unsigned char symbol12_206_bits[] = {
+0x00, 0x00, 0x00, 0x3f, 0x3f, 0x00};
+static unsigned char symbol12_207_bits[] = {
+0x00, 0x00, 0x00, 0x3f, 0x00, 0x3f, 0x00, 0x3c};
+static unsigned char symbol12_208_bits[] = {
+0x22, 0x01, 0x11, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0x01, 0x01, 0x02, 0x00, 
+0xfc, 0x00, 0x01, 0x01, 0x02, 0x00};
+static unsigned char symbol12_209_bits[] = {
+0x00, 0xff, 0x3e, 0x01, 0x3f, 0x01, 0x01, 0x3e, 0x20};
+static unsigned char symbol12_210_bits[] = {
+0x3e, 0x11, 0x3f, 0x09, 0x05, 0x3e, 0x02, 0x00, 0x01};
+static unsigned char symbol12_211_bits[] = {
+0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0x10, 0x00, 0x08};
+static unsigned char symbol12_212_bits[] = {
+0x00, 0x04, 0x00, 0x02, 0x00, 0x07, 0x01, 0x07, 0x81, 0x02, 0x42, 0x04};
+static unsigned char symbol12_213_bits[] = {
+0x24, 0x00, 0x18, 0x00, 0x3c, 0x00, 0x9f, 0x01, 0x9d, 0x01, 0xb7, 0x00, 
+0x3c, 0x00, 0x42, 0x01, 0x95, 0x01, 0xa5, 0x01, 0x42, 0x00};
+static unsigned char symbol12_214_bits[] = {
+0x5f, 0x01, 0x55, 0x01, 0x24, 0x02, 0x24, 0x02, 0x24, 0x02, 0x6e, 0x06};
+static unsigned char symbol12_215_bits[] = {
+0x03};
+static unsigned char symbol12_216_bits[] = {
+0x01, 0x02, 0x00, 0x02};
+static unsigned char symbol12_217_bits[] = {
+0x00, 0x02, 0x00, 0x02, 0x00, 0x02};
+static unsigned char symbol12_218_bits[] = {
+0x00, 0x02, 0x00, 0x02, 0x00, 0x02};
+static unsigned char symbol12_219_bits[] = {
+0x00, 0x02, 0x00, 0x07, 0x01, 0x00, 0x40, 0x00, 0x20, 0x00};
+static unsigned char symbol12_220_bits[] = {
+0x20, 0x06, 0x15, 0x04, 0x14, 0x00, 0x08, 0x03, 0x7f, 0x00};
+static unsigned char symbol12_221_bits[] = {
+0x00, 0x00, 0x0c, 0x0c, 0x12, 0x12, 0x01, 0x01, 0x01, 0x01, 0x12, 0x12};
+static unsigned char symbol12_222_bits[] = {
+0x0c, 0x04, 0x04, 0x01, 0xfe, 0x03, 0x03, 0x06, 0xfe, 0x03};
+static unsigned char symbol12_223_bits[] = {
+0x04, 0x01, 0x04, 0x00, 0x1e, 0x07, 0x03, 0x00, 0x1e, 0x07, 0x04, 0x00};
+static unsigned char symbol12_224_bits[] = {
+0x04, 0x0e, 0x1b, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol12_225_bits[] = {
+0x0a, 0x0a, 0x0a, 0x00, 0x01, 0x0f, 0x03, 0x00, 0x06, 0x0f, 0x03};
+static unsigned char symbol12_226_bits[] = {
+0x00, 0x01, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol12_227_bits[] = {
+0x0a, 0x0a, 0x1b, 0x0e, 0x04, 0x0c, 0x0c, 0x12, 0x21};
+static unsigned char symbol12_228_bits[] = {
+0x21, 0x02, 0x12, 0x00, 0x0c, 0x00, 0x04, 0x00, 0x02, 0x02, 0x01, 0x02};
+static unsigned char symbol12_229_bits[] = {
+0x02, 0x04, 0x04, 0x08, 0x3c, 0x42, 0x9d, 0xa5, 0x9d, 0xa5, 0xa5};
+static unsigned char symbol12_230_bits[] = {
+0x02, 0x0c, 0x0c, 0x02, 0x09, 0x05, 0x05, 0x05, 0x09, 0x02, 0x0c, 0x0f, 
+0x01, 0x04, 0x01, 0x04};
+static unsigned char symbol12_231_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_232_bits[] = {
+0x01, 0x0f, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_233_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_234_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_235_bits[] = {
+0x04, 0x00, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_236_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_237_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_238_bits[] = {
+0x01, 0x07, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_239_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_240_bits[] = {
+0x00};
+static unsigned char symbol12_241_bits[] = {
+0x04, 0x04, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_242_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_243_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x02, 0x04, 
+0x04, 0x08, 0x08, 0x04};
+static unsigned char symbol12_244_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_245_bits[] = {
+0x04, 0x05, 0x03, 0x1c, 0x1a, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01};
+static unsigned char symbol12_246_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_247_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_248_bits[] = {
+0x00, 0x0b, 0x07, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol12_249_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_250_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol12_251_bits[] = {
+0x02, 0x02, 0x01, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol12_252_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol12_253_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol12_254_bits[] = {
+0x04, 0x04, 0x07, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol12_255_bits[] = {
+0x00};
+static RotFont symbol12font[] = {
+{5, 1, 1, symbol12_0_bits},
+{5, 1, 1, symbol12_1_bits},
+{5, 1, 1, symbol12_2_bits},
+{5, 1, 1, symbol12_3_bits},
+{5, 1, 1, symbol12_4_bits},
+{5, 1, 1, symbol12_5_bits},
+{5, 1, 1, symbol12_6_bits},
+{5, 1, 1, symbol12_7_bits},
+{5, 1, 1, symbol12_8_bits},
+{5, 1, 1, symbol12_9_bits},
+{5, 1, 1, symbol12_10_bits},
+{5, 1, 1, symbol12_11_bits},
+{5, 1, 1, symbol12_12_bits},
+{5, 1, 1, symbol12_13_bits},
+{5, 1, 1, symbol12_14_bits},
+{5, 1, 1, symbol12_15_bits},
+{5, 1, 1, symbol12_16_bits},
+{5, 1, 1, symbol12_17_bits},
+{5, 1, 1, symbol12_18_bits},
+{5, 1, 1, symbol12_19_bits},
+{5, 1, 1, symbol12_20_bits},
+{5, 1, 1, symbol12_21_bits},
+{5, 1, 1, symbol12_22_bits},
+{5, 1, 1, symbol12_23_bits},
+{5, 1, 1, symbol12_24_bits},
+{5, 1, 1, symbol12_25_bits},
+{5, 1, 1, symbol12_26_bits},
+{5, 1, 1, symbol12_27_bits},
+{5, 1, 1, symbol12_28_bits},
+{5, 1, 1, symbol12_29_bits},
+{5, 1, 1, symbol12_30_bits},
+{5, 1, 1, symbol12_31_bits},
+{1, 1, 1, symbol12_32_bits},
+{1, 9, 9, symbol12_33_bits},
+{9, 9, 9, symbol12_34_bits},
+{6, 9, 9, symbol12_35_bits},
+{5, 9, 9, symbol12_36_bits},
+{9, 9, 9, symbol12_37_bits},
+{9, 9, 9, symbol12_38_bits},
+{4, 6, 6, symbol12_39_bits},
+{3, 12, 9, symbol12_40_bits},
+{3, 12, 9, symbol12_41_bits},
+{5, 5, 7, symbol12_42_bits},
+{5, 5, 6, symbol12_43_bits},
+{2, 3, 1, symbol12_44_bits},
+{5, 1, 4, symbol12_45_bits},
+{1, 1, 1, symbol12_46_bits},
+{3, 9, 9, symbol12_47_bits},
+{5, 9, 9, symbol12_48_bits},
+{3, 9, 9, symbol12_49_bits},
+{5, 9, 9, symbol12_50_bits},
+{5, 9, 9, symbol12_51_bits},
+{6, 9, 9, symbol12_52_bits},
+{5, 9, 9, symbol12_53_bits},
+{5, 9, 9, symbol12_54_bits},
+{5, 9, 9, symbol12_55_bits},
+{5, 9, 9, symbol12_56_bits},
+{5, 9, 9, symbol12_57_bits},
+{1, 6, 6, symbol12_58_bits},
+{2, 8, 6, symbol12_59_bits},
+{6, 5, 6, symbol12_60_bits},
+{5, 3, 5, symbol12_61_bits},
+{6, 5, 6, symbol12_62_bits},
+{5, 9, 9, symbol12_63_bits},
+{5, 6, 6, symbol12_64_bits},
+{9, 9, 9, symbol12_65_bits},
+{7, 9, 9, symbol12_66_bits},
+{8, 9, 9, symbol12_67_bits},
+{7, 9, 9, symbol12_68_bits},
+{7, 9, 9, symbol12_69_bits},
+{9, 9, 9, symbol12_70_bits},
+{7, 9, 9, symbol12_71_bits},
+{8, 9, 9, symbol12_72_bits},
+{3, 9, 9, symbol12_73_bits},
+{8, 9, 9, symbol12_74_bits},
+{8, 9, 9, symbol12_75_bits},
+{9, 9, 9, symbol12_76_bits},
+{11, 9, 9, symbol12_77_bits},
+{8, 9, 9, symbol12_78_bits},
+{8, 9, 9, symbol12_79_bits},
+{8, 9, 9, symbol12_80_bits},
+{8, 9, 9, symbol12_81_bits},
+{6, 9, 9, symbol12_82_bits},
+{7, 9, 9, symbol12_83_bits},
+{7, 9, 9, symbol12_84_bits},
+{9, 9, 9, symbol12_85_bits},
+{5, 9, 6, symbol12_86_bits},
+{10, 9, 9, symbol12_87_bits},
+{8, 9, 9, symbol12_88_bits},
+{9, 9, 9, symbol12_89_bits},
+{6, 9, 9, symbol12_90_bits},
+{3, 12, 9, symbol12_91_bits},
+{7, 6, 6, symbol12_92_bits},
+{3, 12, 9, symbol12_93_bits},
+{7, 9, 9, symbol12_94_bits},
+{6, 1, -2, symbol12_95_bits},
+{7, 1, 12, symbol12_96_bits},
+{7, 6, 6, symbol12_97_bits},
+{5, 13, 10, symbol12_98_bits},
+{7, 9, 6, symbol12_99_bits},
+{5, 10, 10, symbol12_100_bits},
+{4, 6, 6, symbol12_101_bits},
+{7, 11, 8, symbol12_102_bits},
+{6, 9, 6, symbol12_103_bits},
+{7, 9, 6, symbol12_104_bits},
+{3, 6, 6, symbol12_105_bits},
+{7, 9, 6, symbol12_106_bits},
+{6, 6, 6, symbol12_107_bits},
+{7, 9, 9, symbol12_108_bits},
+{7, 9, 6, symbol12_109_bits},
+{6, 6, 6, symbol12_110_bits},
+{5, 6, 6, symbol12_111_bits},
+{7, 6, 6, symbol12_112_bits},
+{5, 9, 9, symbol12_113_bits},
+{5, 9, 6, symbol12_114_bits},
+{6, 6, 6, symbol12_115_bits},
+{5, 6, 6, symbol12_116_bits},
+{7, 6, 6, symbol12_117_bits},
+{8, 7, 7, symbol12_118_bits},
+{7, 6, 6, symbol12_119_bits},
+{5, 14, 11, symbol12_120_bits},
+{9, 9, 6, symbol12_121_bits},
+{5, 13, 10, symbol12_122_bits},
+{5, 12, 9, symbol12_123_bits},
+{1, 12, 9, symbol12_124_bits},
+{5, 12, 9, symbol12_125_bits},
+{7, 3, 5, symbol12_126_bits},
+{5, 1, 1, symbol12_127_bits},
+{5, 1, 1, symbol12_128_bits},
+{5, 1, 1, symbol12_129_bits},
+{5, 1, 1, symbol12_130_bits},
+{5, 1, 1, symbol12_131_bits},
+{5, 1, 1, symbol12_132_bits},
+{5, 1, 1, symbol12_133_bits},
+{5, 1, 1, symbol12_134_bits},
+{5, 1, 1, symbol12_135_bits},
+{5, 1, 1, symbol12_136_bits},
+{5, 1, 1, symbol12_137_bits},
+{5, 1, 1, symbol12_138_bits},
+{5, 1, 1, symbol12_139_bits},
+{5, 1, 1, symbol12_140_bits},
+{5, 1, 1, symbol12_141_bits},
+{5, 1, 1, symbol12_142_bits},
+{5, 1, 1, symbol12_143_bits},
+{5, 1, 1, symbol12_144_bits},
+{5, 1, 1, symbol12_145_bits},
+{5, 1, 1, symbol12_146_bits},
+{5, 1, 1, symbol12_147_bits},
+{5, 1, 1, symbol12_148_bits},
+{5, 1, 1, symbol12_149_bits},
+{5, 1, 1, symbol12_150_bits},
+{5, 1, 1, symbol12_151_bits},
+{5, 1, 1, symbol12_152_bits},
+{5, 1, 1, symbol12_153_bits},
+{5, 1, 1, symbol12_154_bits},
+{5, 1, 1, symbol12_155_bits},
+{5, 1, 1, symbol12_156_bits},
+{5, 1, 1, symbol12_157_bits},
+{5, 1, 1, symbol12_158_bits},
+{5, 1, 1, symbol12_159_bits},
+{5, 1, 1, symbol12_160_bits},
+{8, 9, 9, symbol12_161_bits},
+{3, 3, 9, symbol12_162_bits},
+{6, 7, 7, symbol12_163_bits},
+{5, 9, 9, symbol12_164_bits},
+{9, 4, 5, symbol12_165_bits},
+{6, 12, 9, symbol12_166_bits},
+{7, 7, 6, symbol12_167_bits},
+{5, 6, 6, symbol12_168_bits},
+{7, 6, 6, symbol12_169_bits},
+{7, 7, 6, symbol12_170_bits},
+{11, 5, 6, symbol12_171_bits},
+{12, 5, 6, symbol12_172_bits},
+{5, 16, 12, symbol12_173_bits},
+{12, 5, 6, symbol12_174_bits},
+{5, 15, 12, symbol12_175_bits},
+{4, 4, 9, symbol12_176_bits},
+{5, 7, 7, symbol12_177_bits},
+{5, 3, 9, symbol12_178_bits},
+{6, 7, 7, symbol12_179_bits},
+{5, 5, 6, symbol12_180_bits},
+{8, 4, 5, symbol12_181_bits},
+{5, 10, 10, symbol12_182_bits},
+{4, 4, 5, symbol12_183_bits},
+{5, 5, 6, symbol12_184_bits},
+{5, 7, 7, symbol12_185_bits},
+{5, 5, 6, symbol12_186_bits},
+{6, 5, 6, symbol12_187_bits},
+{9, 1, 1, symbol12_188_bits},
+{1, 16, 12, symbol12_189_bits},
+{13, 1, 4, symbol12_190_bits},
+{7, 8, 8, symbol12_191_bits},
+{7, 9, 9, symbol12_192_bits},
+{8, 11, 10, symbol12_193_bits},
+{9, 10, 10, symbol12_194_bits},
+{8, 11, 8, symbol12_195_bits},
+{9, 9, 9, symbol12_196_bits},
+{9, 9, 9, symbol12_197_bits},
+{9, 9, 9, symbol12_198_bits},
+{8, 6, 6, symbol12_199_bits},
+{8, 6, 6, symbol12_200_bits},
+{8, 6, 6, symbol12_201_bits},
+{8, 8, 6, symbol12_202_bits},
+{8, 8, 7, symbol12_203_bits},
+{8, 6, 6, symbol12_204_bits},
+{8, 8, 6, symbol12_205_bits},
+{6, 6, 6, symbol12_206_bits},
+{6, 8, 7, symbol12_207_bits},
+{9, 9, 9, symbol12_208_bits},
+{8, 9, 9, symbol12_209_bits},
+{8, 9, 9, symbol12_210_bits},
+{8, 9, 9, symbol12_211_bits},
+{11, 6, 9, symbol12_212_bits},
+{9, 11, 10, symbol12_213_bits},
+{7, 12, 12, symbol12_214_bits},
+{2, 1, 4, symbol12_215_bits},
+{7, 4, 4, symbol12_216_bits},
+{6, 6, 6, symbol12_217_bits},
+{6, 6, 6, symbol12_218_bits},
+{11, 5, 6, symbol12_219_bits},
+{11, 5, 6, symbol12_220_bits},
+{5, 12, 11, symbol12_221_bits},
+{11, 5, 6, symbol12_222_bits},
+{5, 12, 12, symbol12_223_bits},
+{6, 9, 9, symbol12_224_bits},
+{4, 11, 10, symbol12_225_bits},
+{8, 9, 9, symbol12_226_bits},
+{8, 9, 9, symbol12_227_bits},
+{10, 6, 9, symbol12_228_bits},
+{8, 11, 10, symbol12_229_bits},
+{4, 16, 12, symbol12_230_bits},
+{1, 16, 12, symbol12_231_bits},
+{4, 16, 12, symbol12_232_bits},
+{3, 16, 12, symbol12_233_bits},
+{1, 16, 12, symbol12_234_bits},
+{3, 15, 12, symbol12_235_bits},
+{3, 16, 12, symbol12_236_bits},
+{3, 16, 12, symbol12_237_bits},
+{3, 15, 12, symbol12_238_bits},
+{1, 16, 12, symbol12_239_bits},
+{5, 1, 1, symbol12_240_bits},
+{4, 12, 10, symbol12_241_bits},
+{5, 15, 12, symbol12_242_bits},
+{5, 16, 12, symbol12_243_bits},
+{1, 16, 12, symbol12_244_bits},
+{5, 15, 12, symbol12_245_bits},
+{4, 16, 12, symbol12_246_bits},
+{1, 16, 12, symbol12_247_bits},
+{4, 16, 12, symbol12_248_bits},
+{3, 16, 12, symbol12_249_bits},
+{1, 16, 12, symbol12_250_bits},
+{3, 15, 12, symbol12_251_bits},
+{3, 16, 12, symbol12_252_bits},
+{3, 16, 12, symbol12_253_bits},
+{3, 15, 12, symbol12_254_bits},
+{5, 1, 1, symbol12_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol14.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol14.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol14.bdf	(revision 16632)
@@ -0,0 +1,3274 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--14-140-75-75-P-85-Adobe-FontSpecific
+SIZE 14 75 75
+FONTBOUNDINGBOX 16 20 -1 -6
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 140
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 85
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 10
+X_HEIGHT 7
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--14-140-75-75-P-85-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 9
+DEFAULT_CHAR 32
+FONT_ASCENT 12
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 1 10 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+8080
+4100
+4100
+3e00
+2200
+2200
+1400
+1400
+0800
+0800
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+14
+14
+14
+7e
+28
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+fc
+04
+04
+04
+fc
+04
+04
+04
+04
+fc
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 9 10 1 0
+BITMAP
+7980
+9700
+9200
+9400
+6c00
+1b00
+1480
+2480
+4480
+c300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+3000
+4800
+4800
+7000
+2700
+7200
+ca00
+8400
+ce80
+7b00
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+e0
+10
+08
+78
+08
+10
+e0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 6 1 2
+BITMAP
+20
+a8
+70
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 205 0
+DWIDTH 3 0
+BBX 2 4 0 -2
+BITMAP
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 1 0 3
+BITMAP
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 205 0
+DWIDTH 3 0
+BBX 1 2 1 0
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+cc
+84
+84
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+70
+d8
+88
+08
+18
+10
+20
+40
+c4
+fc
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+cc
+84
+0c
+38
+0c
+04
+04
+cc
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+08
+18
+18
+28
+68
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+78
+40
+80
+e0
+30
+18
+08
+08
+90
+e0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+1c
+30
+40
+40
+f8
+8c
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+fc
+84
+08
+08
+10
+10
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+d8
+88
+88
+70
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+cc
+84
+84
+c4
+78
+18
+10
+60
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 1 7 2 0
+BITMAP
+80
+80
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+40
+40
+00
+00
+00
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+02
+0c
+30
+c0
+30
+0c
+02
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 3 0 2
+BITMAP
+fe
+00
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+80
+60
+18
+06
+18
+60
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+72
+9c
+00
+fe
+00
+00
+fe
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+0800
+1c00
+1400
+1400
+2200
+2200
+3e00
+6300
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fc
+46
+42
+46
+7c
+46
+42
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+4100
+2200
+3600
+1c00
+1400
+2200
+6300
+4100
+e380
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+10
+10
+28
+28
+28
+44
+44
+44
+82
+fe
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+1c00
+0800
+7f00
+c980
+8880
+8880
+c980
+7f00
+0800
+1c00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+4100
+4100
+4100
+7f00
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 10 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+0c
+0a
+0a
+66
+a3
+22
+22
+22
+36
+1c
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+ee
+44
+48
+50
+70
+50
+48
+44
+42
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+0800
+0800
+1400
+3600
+2200
+2200
+6300
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 891 0
+DWIDTH 13 0
+BBX 11 10 1 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+5b40
+4a40
+4a40
+4e40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+6100
+5100
+5900
+4900
+4d00
+4500
+4700
+4300
+e100
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+ff80
+4100
+4100
+4100
+4100
+4100
+4100
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+66
+42
+a5
+bd
+a5
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+f8
+4c
+44
+44
+4c
+78
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 10 1 0
+BITMAP
+fe
+c2
+60
+30
+18
+10
+20
+40
+c1
+ff
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+38
+c0
+80
+80
+80
+60
+38
+04
+24
+38
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 10 10 0 0
+BITMAP
+0c00
+3300
+2100
+4080
+4080
+4080
+4080
+2100
+9240
+f3c0
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+7f00
+4100
+0000
+2200
+3e00
+2200
+0000
+0000
+8080
+ff80
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 11 10 0 0
+BITMAP
+ce60
+64c0
+2480
+2480
+1f00
+0400
+0400
+0400
+0400
+0e00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+82
+04
+08
+10
+10
+20
+40
+82
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 7 1 0
+BITMAP
+18
+18
+00
+00
+00
+c3
+c3
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+0800
+ff80
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+fe
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 8 1 0 13
+BITMAP
+ff
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 7 1 0
+BITMAP
+76
+d4
+88
+88
+88
+d5
+66
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 14 1 -3
+BITMAP
+78
+cc
+84
+8c
+98
+8c
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 10 0 -3
+BITMAP
+c3
+a6
+24
+3c
+18
+38
+28
+64
+45
+c3
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+70
+98
+80
+40
+70
+98
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 7 1 0
+BITMAP
+78
+c8
+80
+60
+80
+c8
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 13 1 -3
+BITMAP
+10
+10
+10
+38
+54
+92
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 6 10 0 -3
+BITMAP
+c4
+a4
+24
+28
+28
+18
+18
+10
+30
+30
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 10 0 -3
+BITMAP
+6c
+b2
+22
+22
+22
+22
+22
+02
+02
+02
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+60
+a0
+20
+20
+20
+28
+30
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 10 1 -3
+BITMAP
+18
+54
+d2
+92
+92
+54
+38
+10
+10
+10
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+46
+ca
+50
+70
+58
+4c
+46
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 10 1 0
+BITMAP
+60
+50
+10
+10
+28
+28
+48
+44
+85
+83
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 1 -2
+BITMAP
+88
+88
+88
+88
+88
+9a
+f6
+80
+c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+c6
+42
+22
+22
+14
+14
+08
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 7 1 0
+BITMAP
+78
+cc
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 7 0 0
+BITMAP
+7e
+a4
+24
+24
+24
+25
+66
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+d8
+88
+88
+f8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 6 10 1 -3
+BITMAP
+78
+cc
+84
+84
+84
+cc
+b8
+80
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+7e
+c8
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+78
+a0
+20
+20
+20
+28
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+64
+a2
+22
+22
+22
+26
+1c
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 10 8 0 0
+BITMAP
+7fc0
+a080
+4440
+4440
+4440
+4440
+64c0
+3b80
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+6300
+8880
+8880
+8880
+8880
+c980
+7700
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 15 1 -3
+BITMAP
+20
+40
+38
+20
+40
+78
+20
+40
+80
+80
+c0
+78
+04
+24
+38
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 9 10 0 -3
+BITMAP
+8880
+4900
+4900
+4900
+6b00
+3e00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 14 1 -3
+BITMAP
+20
+44
+3c
+10
+20
+40
+40
+80
+80
+c0
+78
+04
+24
+38
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+18
+20
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 205 0
+DWIDTH 3 0
+BBX 1 13 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 3 1 2
+BITMAP
+62
+92
+8c
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 10 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 4 3 0 7
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 5 10 -1 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 4 0 2
+BITMAP
+0000
+c600
+2b00
+1000
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 13 0 -3
+BITMAP
+10
+10
+10
+38
+30
+60
+80
+02
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 8 1 -1
+BITMAP
+0200
+fe00
+0800
+1000
+2000
+4080
+8000
+0080
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 7 7 2 0
+BITMAP
+80
+8c
+80
+76
+00
+06
+0a
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 7 7 2 0
+BITMAP
+08
+08
+3c
+10
+10
+10
+20
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 8 1 -1
+BITMAP
+2000
+a080
+1c00
+1c00
+1c00
+eb80
+ff80
+eb80
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1028 0
+DWIDTH 15 0
+BBX 13 7 1 0
+BITMAP
+0800
+0800
+1038
+7cf8
+7c38
+1068
+fef8
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 14 7 0 0
+BITMAP
+fe7c
+3810
+0800
+1c00
+3e00
+7f00
+ff80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 20 1 -6
+BITMAP
+6a
+00
+08
+00
+08
+00
+10
+40
+20
+20
+40
+10
+fe
+f8
+40
+10
+20
+20
+10
+40
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 14 7 0 0
+BITMAP
+1000
+2000
+4000
+fffc
+4000
+2000
+1000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 17 1 -3
+BITMAP
+10
+38
+54
+92
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 4 1 6
+BITMAP
+10
+10
+10
+00
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+20
+00
+10
+00
+08
+fe
+fc
+00
+08
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 7 3 -1 7
+BITMAP
+00
+10
+00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+20
+10
+10
+10
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+10
+10
+10
+92
+54
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 4 0 2
+BITMAP
+38
+10
+60
+90
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 6 11 0 0
+BITMAP
+90
+60
+10
+10
+10
+fc
+10
+10
+10
+00
+fc
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+30
+68
+90
+80
+60
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+18
+06
+18
+60
+80
+00
+fe
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 5 0 1
+BITMAP
+76
+88
+88
+76
+70
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 7 5 0 1
+BITMAP
+88
+04
+04
+04
+74
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 891 0
+DWIDTH 13 0
+BBX 9 2 2 0
+BITMAP
+cc80
+8480
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 1 20 4 -6
+BITMAP
+00
+00
+80
+80
+80
+00
+00
+00
+00
+80
+00
+00
+00
+00
+00
+80
+00
+80
+00
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1028 0
+DWIDTH 15 0
+BBX 15 1 0 3
+BITMAP
+fe00
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 9 0 0
+BITMAP
+fe
+00
+fe
+72
+9c
+00
+72
+9c
+88
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 8 10 2 0
+BITMAP
+80
+88
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 8 12 1 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 11 1 0
+BITMAP
+80c0
+fe00
+0100
+0100
+0140
+ff40
+88c0
+6600
+7480
+8c40
+63c0
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 9 12 1 -3
+BITMAP
+3f00
+4200
+2400
+0300
+6180
+1a00
+7300
+9d80
+8980
+8b00
+ce00
+6a00
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+2900
+0900
+0900
+6900
+b080
+1000
+2300
+4580
+8880
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+9080
+d480
+6900
+6b00
+b600
+9000
+9000
+6000
+1c00
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+6300
+6300
+9480
+8880
+9480
+6300
+6300
+1c00
+1c00
+6300
+4900
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 10 7 0 0
+BITMAP
+8880
+be80
+8880
+4900
+6300
+1c00
+1f00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 10 7 0 0
+BITMAP
+60c0
+40c0
+8100
+8200
+8400
+8800
+9000
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 7 0 0
+BITMAP
+6000
+6080
+9f00
+1e00
+6180
+4080
+8000
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 9 1 -2
+BITMAP
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+4080
+6180
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 9 0 -1
+BITMAP
+1e00
+fe00
+0100
+0080
+0080
+0080
+0100
+fe00
+fe00
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 7 1 0
+BITMAP
+0100
+0080
+0080
+0080
+0100
+fe00
+0000
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 9 0 -2
+BITMAP
+ff80
+0100
+3f80
+4200
+8200
+8400
+8400
+4800
+3f80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 7 7 1 0
+BITMAP
+10
+00
+3e
+80
+40
+00
+80
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 7 9 0 -1
+BITMAP
+00
+80
+00
+80
+00
+40
+00
+3e
+80
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 11 10 0 0
+BITMAP
+3f80
+4000
+8000
+8000
+8000
+4000
+3f80
+0000
+ff80
+3e40
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 11 0 0
+BITMAP
+8080
+8000
+3e00
+3e00
+9080
+9000
+3e00
+0000
+0080
+0100
+0200
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+0400
+0800
+1000
+2000
+4000
+ffc0
+ff80
+8080
+4100
+4100
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+2200
+2200
+2200
+1400
+1400
+0800
+0800
+1e00
+2100
+7c80
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 11 6 0 4
+BITMAP
+9240
+9240
+9c40
+9240
+7980
+2100
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 12 1 -1
+BITMAP
+1e00
+1e00
+2100
+4e80
+9240
+9040
+9040
+9240
+4c80
+2100
+1e00
+fa80
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 548 0
+DWIDTH 8 0
+BBX 8 14 0 0
+BITMAP
+aa
+80
+26
+c0
+25
+40
+25
+40
+76
+e0
+ff
+c0
+40
+80
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 1 2 1 3
+BITMAP
+00
+80
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 5 0 0
+BITMAP
+4080
+4080
+4080
+4080
+4080
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+40
+80
+40
+80
+40
+80
+e1
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 8 7 0 0
+BITMAP
+c0
+01
+01
+01
+02
+02
+02
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1028 0
+DWIDTH 15 0
+BBX 13 7 1 0
+BITMAP
+0260
+a420
+1410
+0808
+8080
+ff80
+0080
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 13 7 0 0
+BITMAP
+0080
+0080
+0080
+1818
+2420
+4240
+8180
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+42
+42
+24
+24
+18
+18
+10
+40
+20
+20
+7e
+f0
+c0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 14 0
+BBX 13 7 1 0
+BITMAP
+1878
+f020
+2010
+4010
+0020
+0078
+f8c0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 617 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+00
+7e
+f8
+20
+00
+10
+00
+10
+38
+6c
+aa
+28
+28
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+28
+28
+28
+28
+28
+28
+28
+00
+40
+00
+20
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 4 15 0 -4
+BITMAP
+f0
+f0
+00
+10
+f0
+f0
+00
+20
+00
+40
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+2800
+2800
+aa40
+3800
+1000
+2840
+4480
+4440
+2800
+1000
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 822 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+2000
+4040
+4080
+8080
+4040
+4000
+2000
+1e00
+2100
+5c80
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 754 0
+DWIDTH 11 0
+BBX 10 6 0 4
+BITMAP
+9240
+9240
+9c40
+9240
+5280
+2100
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 9 12 0 -1
+BITMAP
+1e00
+1e00
+2100
+4c80
+9200
+9000
+9000
+9200
+4c80
+2100
+1e00
+fa80
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+20
+80
+20
+c0
+20
+40
+20
+40
+20
+40
+f0
+00
+80
+00
+40
+00
+20
+00
+10
+00
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 1 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+80
+80
+00
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+00
+00
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 17 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 20 3 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 3 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+20
+40
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 17 3 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+20
+20
+20
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 1 20 3 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 342 0
+DWIDTH 5 0
+BBX 4 15 1 -4
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+40
+30
+80
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 274 0
+DWIDTH 4 0
+BBX 5 13 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 5 20 5 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+00
+80
+40
+40
+20
+20
+20
+10
+10
+10
+20
+20
+20
+40
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 1 20 1 -6
+BITMAP
+00
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+00
+00
+00
+80
+80
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 685 0
+DWIDTH 10 0
+BBX 5 17 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+00
+00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 4 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 20 1 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+10
+10
+10
+10
+10
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 1 20 4 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 411 0
+DWIDTH 6 0
+BBX 4 17 1 -3
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+80
+80
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 20 0 -6
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+10
+10
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 3 20 3 -6
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+e0
+c0
+20
+00
+00
+00
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 7 0
+BBX 4 17 0 -3
+BITMAP
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+10
+80
+80
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol14.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol14.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol14.h	(revision 16632)
@@ -0,0 +1,859 @@
+static unsigned char symbol14_0_bits[] = {
+0x00};
+static unsigned char symbol14_1_bits[] = {
+0x00};
+static unsigned char symbol14_2_bits[] = {
+0x00};
+static unsigned char symbol14_3_bits[] = {
+0x00};
+static unsigned char symbol14_4_bits[] = {
+0x00};
+static unsigned char symbol14_5_bits[] = {
+0x00};
+static unsigned char symbol14_6_bits[] = {
+0x00};
+static unsigned char symbol14_7_bits[] = {
+0x00};
+static unsigned char symbol14_8_bits[] = {
+0x00};
+static unsigned char symbol14_9_bits[] = {
+0x00};
+static unsigned char symbol14_10_bits[] = {
+0x00};
+static unsigned char symbol14_11_bits[] = {
+0x00};
+static unsigned char symbol14_12_bits[] = {
+0x00};
+static unsigned char symbol14_13_bits[] = {
+0x00};
+static unsigned char symbol14_14_bits[] = {
+0x00};
+static unsigned char symbol14_15_bits[] = {
+0x00};
+static unsigned char symbol14_16_bits[] = {
+0x00};
+static unsigned char symbol14_17_bits[] = {
+0x00};
+static unsigned char symbol14_18_bits[] = {
+0x00};
+static unsigned char symbol14_19_bits[] = {
+0x00};
+static unsigned char symbol14_20_bits[] = {
+0x00};
+static unsigned char symbol14_21_bits[] = {
+0x00};
+static unsigned char symbol14_22_bits[] = {
+0x00};
+static unsigned char symbol14_23_bits[] = {
+0x00};
+static unsigned char symbol14_24_bits[] = {
+0x00};
+static unsigned char symbol14_25_bits[] = {
+0x00};
+static unsigned char symbol14_26_bits[] = {
+0x00};
+static unsigned char symbol14_27_bits[] = {
+0x00};
+static unsigned char symbol14_28_bits[] = {
+0x00};
+static unsigned char symbol14_29_bits[] = {
+0x00};
+static unsigned char symbol14_30_bits[] = {
+0x00};
+static unsigned char symbol14_31_bits[] = {
+0x00};
+static unsigned char symbol14_32_bits[] = {
+0x00};
+static unsigned char symbol14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char symbol14_34_bits[] = {
+0x01, 0x01, 0x82, 0x00, 0x82, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol14_35_bits[] = {
+0x28, 0x28, 0x28, 0x7e, 0x14, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char symbol14_36_bits[] = {
+0x3f, 0x20, 0x20, 0x20, 0x3f, 0x20, 0x20, 0x20, 0x20, 0x3f};
+static unsigned char symbol14_37_bits[] = {
+0x9e, 0x01, 0xe9, 0x00, 0x49, 0x00, 0x29, 0x00, 0x36, 0x00, 0xd8, 0x00, 
+0x28, 0x01, 0x24, 0x01, 0x22, 0x01, 0xc3, 0x00};
+static unsigned char symbol14_38_bits[] = {
+0x0c, 0x00, 0x12, 0x00, 0x12, 0x00, 0x0e, 0x00, 0xe4, 0x00, 0x4e, 0x00, 
+0x53, 0x00, 0x21, 0x00, 0x73, 0x01, 0xde, 0x00};
+static unsigned char symbol14_39_bits[] = {
+0x07, 0x08, 0x10, 0x1e, 0x10, 0x08, 0x07};
+static unsigned char symbol14_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 
+0x04};
+static unsigned char symbol14_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 
+0x01};
+static unsigned char symbol14_42_bits[] = {
+0x04, 0x15, 0x0e, 0x0e, 0x15, 0x04};
+static unsigned char symbol14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char symbol14_44_bits[] = {
+0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol14_45_bits[] = {
+0x7f};
+static unsigned char symbol14_46_bits[] = {
+0x01, 0x01};
+static unsigned char symbol14_47_bits[] = {
+0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char symbol14_48_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char symbol14_50_bits[] = {
+0x0e, 0x1b, 0x11, 0x10, 0x18, 0x08, 0x04, 0x02, 0x23, 0x3f};
+static unsigned char symbol14_51_bits[] = {
+0x1e, 0x33, 0x21, 0x30, 0x1c, 0x30, 0x20, 0x20, 0x33, 0x1e};
+static unsigned char symbol14_52_bits[] = {
+0x10, 0x18, 0x18, 0x14, 0x16, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char symbol14_53_bits[] = {
+0x1e, 0x02, 0x01, 0x07, 0x0c, 0x18, 0x10, 0x10, 0x09, 0x07};
+static unsigned char symbol14_54_bits[] = {
+0x38, 0x0c, 0x02, 0x02, 0x1f, 0x31, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_55_bits[] = {
+0x3f, 0x21, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02};
+static unsigned char symbol14_56_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x0e, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol14_57_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x23, 0x1e, 0x18, 0x08, 0x06, 0x03};
+static unsigned char symbol14_58_bits[] = {
+0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char symbol14_59_bits[] = {
+0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol14_60_bits[] = {
+0x40, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x40};
+static unsigned char symbol14_61_bits[] = {
+0x7f, 0x00, 0x7f};
+static unsigned char symbol14_62_bits[] = {
+0x01, 0x06, 0x18, 0x60, 0x18, 0x06, 0x01};
+static unsigned char symbol14_63_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x04, 0x00, 0x04, 0x04};
+static unsigned char symbol14_64_bits[] = {
+0x4e, 0x39, 0x00, 0x7f, 0x00, 0x00, 0x7f};
+static unsigned char symbol14_65_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x7c, 0x00, 0xc6, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x62, 0x42, 0x42, 0x62, 0x3f};
+static unsigned char symbol14_67_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0xc6, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_68_bits[] = {
+0x08, 0x08, 0x14, 0x14, 0x14, 0x22, 0x22, 0x22, 0x41, 0x7f};
+static unsigned char symbol14_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x42, 0x7f};
+static unsigned char symbol14_70_bits[] = {
+0x38, 0x00, 0x10, 0x00, 0xfe, 0x00, 0x93, 0x01, 0x11, 0x01, 0x11, 0x01, 
+0x93, 0x01, 0xfe, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol14_71_bits[] = {
+0x7f, 0x42, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol14_72_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xfe, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol14_74_bits[] = {
+0x30, 0x50, 0x50, 0x66, 0xc5, 0x44, 0x44, 0x44, 0x6c, 0x38};
+static unsigned char symbol14_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x0a, 0x12, 0x22, 0x42, 0xe7};
+static unsigned char symbol14_76_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x6c, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0xc6, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0xda, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x72, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char symbol14_78_bits[] = {
+0xc7, 0x01, 0x86, 0x00, 0x8a, 0x00, 0x9a, 0x00, 0x92, 0x00, 0xb2, 0x00, 
+0xa2, 0x00, 0xe2, 0x00, 0xc2, 0x00, 0x87, 0x00};
+static unsigned char symbol14_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char symbol14_80_bits[] = {
+0xff, 0x01, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char symbol14_81_bits[] = {
+0x3c, 0x66, 0x42, 0xa5, 0xbd, 0xa5, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char symbol14_82_bits[] = {
+0x1f, 0x32, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol14_83_bits[] = {
+0x7f, 0x43, 0x06, 0x0c, 0x18, 0x08, 0x04, 0x02, 0x83, 0xff};
+static unsigned char symbol14_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char symbol14_85_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char symbol14_86_bits[] = {
+0x1c, 0x03, 0x01, 0x01, 0x01, 0x06, 0x1c, 0x20, 0x24, 0x1c};
+static unsigned char symbol14_87_bits[] = {
+0x30, 0x00, 0xcc, 0x00, 0x84, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 
+0x02, 0x01, 0x84, 0x00, 0x49, 0x02, 0xcf, 0x03};
+static unsigned char symbol14_88_bits[] = {
+0xfe, 0x00, 0x82, 0x00, 0x00, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff, 0x01};
+static unsigned char symbol14_89_bits[] = {
+0x73, 0x06, 0x26, 0x03, 0x24, 0x01, 0x24, 0x01, 0xf8, 0x00, 0x20, 0x00, 
+0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x70, 0x00};
+static unsigned char symbol14_90_bits[] = {
+0x7f, 0x41, 0x20, 0x10, 0x08, 0x08, 0x04, 0x02, 0x41, 0x7f};
+static unsigned char symbol14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x07};
+static unsigned char symbol14_92_bits[] = {
+0x18, 0x18, 0x00, 0x00, 0x00, 0xc3, 0xc3};
+static unsigned char symbol14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x07};
+static unsigned char symbol14_94_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01};
+static unsigned char symbol14_95_bits[] = {
+0x7f};
+static unsigned char symbol14_96_bits[] = {
+0xff};
+static unsigned char symbol14_97_bits[] = {
+0x6e, 0x2b, 0x11, 0x11, 0x11, 0xab, 0x66};
+static unsigned char symbol14_98_bits[] = {
+0x1e, 0x33, 0x21, 0x31, 0x19, 0x31, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 
+0x01, 0x01};
+static unsigned char symbol14_99_bits[] = {
+0xc3, 0x65, 0x24, 0x3c, 0x18, 0x1c, 0x14, 0x26, 0xa2, 0xc3};
+static unsigned char symbol14_100_bits[] = {
+0x0e, 0x19, 0x01, 0x02, 0x0e, 0x19, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol14_101_bits[] = {
+0x1e, 0x13, 0x01, 0x06, 0x01, 0x13, 0x0e};
+static unsigned char symbol14_102_bits[] = {
+0x08, 0x08, 0x08, 0x1c, 0x2a, 0x49, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 
+0x08};
+static unsigned char symbol14_103_bits[] = {
+0x23, 0x25, 0x24, 0x14, 0x14, 0x18, 0x18, 0x08, 0x0c, 0x0c};
+static unsigned char symbol14_104_bits[] = {
+0x36, 0x4d, 0x44, 0x44, 0x44, 0x44, 0x44, 0x40, 0x40, 0x40};
+static unsigned char symbol14_105_bits[] = {
+0x06, 0x05, 0x04, 0x04, 0x04, 0x14, 0x0c};
+static unsigned char symbol14_106_bits[] = {
+0x18, 0x2a, 0x4b, 0x49, 0x49, 0x2a, 0x1c, 0x08, 0x08, 0x08};
+static unsigned char symbol14_107_bits[] = {
+0x62, 0x53, 0x0a, 0x0e, 0x1a, 0x32, 0x62};
+static unsigned char symbol14_108_bits[] = {
+0x06, 0x0a, 0x08, 0x08, 0x14, 0x14, 0x12, 0x22, 0xa1, 0xc1};
+static unsigned char symbol14_109_bits[] = {
+0x11, 0x11, 0x11, 0x11, 0x11, 0x59, 0x6f, 0x01, 0x03};
+static unsigned char symbol14_110_bits[] = {
+0x63, 0x42, 0x44, 0x44, 0x28, 0x28, 0x10};
+static unsigned char symbol14_111_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_112_bits[] = {
+0x7e, 0x25, 0x24, 0x24, 0x24, 0xa4, 0x66};
+static unsigned char symbol14_113_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1f, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol14_114_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x33, 0x1d, 0x01, 0x01, 0x01};
+static unsigned char symbol14_115_bits[] = {
+0x7e, 0x13, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char symbol14_116_bits[] = {
+0x1e, 0x05, 0x04, 0x04, 0x04, 0x14, 0x0c};
+static unsigned char symbol14_117_bits[] = {
+0x26, 0x45, 0x44, 0x44, 0x44, 0x64, 0x38};
+static unsigned char symbol14_118_bits[] = {
+0xfe, 0x03, 0x05, 0x01, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 
+0x26, 0x03, 0xdc, 0x01};
+static unsigned char symbol14_119_bits[] = {
+0xc6, 0x00, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x11, 0x01, 0x93, 0x01, 
+0xee, 0x00};
+static unsigned char symbol14_120_bits[] = {
+0x04, 0x02, 0x1c, 0x04, 0x02, 0x1e, 0x04, 0x02, 0x01, 0x01, 0x03, 0x1e, 
+0x20, 0x24, 0x1c};
+static unsigned char symbol14_121_bits[] = {
+0x11, 0x01, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol14_122_bits[] = {
+0x04, 0x22, 0x3c, 0x08, 0x04, 0x02, 0x02, 0x01, 0x01, 0x03, 0x1e, 0x20, 
+0x24, 0x1c};
+static unsigned char symbol14_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 
+0x18};
+static unsigned char symbol14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char symbol14_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 
+0x03};
+static unsigned char symbol14_126_bits[] = {
+0x46, 0x49, 0x31};
+static unsigned char symbol14_127_bits[] = {
+0x00};
+static unsigned char symbol14_128_bits[] = {
+0x00};
+static unsigned char symbol14_129_bits[] = {
+0x00};
+static unsigned char symbol14_130_bits[] = {
+0x00};
+static unsigned char symbol14_131_bits[] = {
+0x00};
+static unsigned char symbol14_132_bits[] = {
+0x00};
+static unsigned char symbol14_133_bits[] = {
+0x00};
+static unsigned char symbol14_134_bits[] = {
+0x00};
+static unsigned char symbol14_135_bits[] = {
+0x00};
+static unsigned char symbol14_136_bits[] = {
+0x00};
+static unsigned char symbol14_137_bits[] = {
+0x00};
+static unsigned char symbol14_138_bits[] = {
+0x00};
+static unsigned char symbol14_139_bits[] = {
+0x00};
+static unsigned char symbol14_140_bits[] = {
+0x00};
+static unsigned char symbol14_141_bits[] = {
+0x00};
+static unsigned char symbol14_142_bits[] = {
+0x00};
+static unsigned char symbol14_143_bits[] = {
+0x00};
+static unsigned char symbol14_144_bits[] = {
+0x00};
+static unsigned char symbol14_145_bits[] = {
+0x00};
+static unsigned char symbol14_146_bits[] = {
+0x00};
+static unsigned char symbol14_147_bits[] = {
+0x00};
+static unsigned char symbol14_148_bits[] = {
+0x00};
+static unsigned char symbol14_149_bits[] = {
+0x00};
+static unsigned char symbol14_150_bits[] = {
+0x00};
+static unsigned char symbol14_151_bits[] = {
+0x00};
+static unsigned char symbol14_152_bits[] = {
+0x00};
+static unsigned char symbol14_153_bits[] = {
+0x00};
+static unsigned char symbol14_154_bits[] = {
+0x00};
+static unsigned char symbol14_155_bits[] = {
+0x00};
+static unsigned char symbol14_156_bits[] = {
+0x00};
+static unsigned char symbol14_157_bits[] = {
+0x00};
+static unsigned char symbol14_158_bits[] = {
+0x00};
+static unsigned char symbol14_159_bits[] = {
+0x00};
+static unsigned char symbol14_160_bits[] = {
+0x00};
+static unsigned char symbol14_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_162_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol14_163_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_164_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_165_bits[] = {
+0x00, 0x00, 0x63, 0x00, 0xd4, 0x00, 0x08, 0x00};
+static unsigned char symbol14_166_bits[] = {
+0x08, 0x08, 0x08, 0x1c, 0x0c, 0x06, 0x01, 0x40, 0x30, 0x0c, 0x03, 0x0c, 
+0x30};
+static unsigned char symbol14_167_bits[] = {
+0x40, 0x00, 0x7f, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x01, 
+0x01, 0x00, 0x00, 0x01};
+static unsigned char symbol14_168_bits[] = {
+0x01, 0x31, 0x01, 0x6e, 0x00, 0x60, 0x50};
+static unsigned char symbol14_169_bits[] = {
+0x10, 0x10, 0x3c, 0x08, 0x08, 0x08, 0x04};
+static unsigned char symbol14_170_bits[] = {
+0x04, 0x00, 0x05, 0x01, 0x38, 0x00, 0x38, 0x00, 0x38, 0x00, 0xd7, 0x01, 
+0xff, 0x01, 0xd7, 0x01};
+static unsigned char symbol14_171_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x08, 0x1c, 0x3e, 0x1f, 0x3e, 0x1c, 0x08, 0x16, 
+0x7f, 0x1f};
+static unsigned char symbol14_172_bits[] = {
+0x7f, 0x3e, 0x1c, 0x08, 0x10, 0x00, 0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 
+0xff, 0x01};
+static unsigned char symbol14_173_bits[] = {
+0x56, 0x00, 0x10, 0x00, 0x10, 0x00, 0x08, 0x02, 0x04, 0x04, 0x02, 0x08, 
+0x7f, 0x1f, 0x02, 0x08, 0x04, 0x04, 0x08, 0x02};
+static unsigned char symbol14_174_bits[] = {
+0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0xff, 0x3f, 0x02, 0x00, 0x04, 0x00, 
+0x08, 0x00};
+static unsigned char symbol14_175_bits[] = {
+0x08, 0x1c, 0x2a, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol14_176_bits[] = {
+0x08, 0x08, 0x08, 0x00};
+static unsigned char symbol14_177_bits[] = {
+0x04, 0x00, 0x08, 0x00, 0x10, 0x7f, 0x3f, 0x00, 0x10};
+static unsigned char symbol14_178_bits[] = {
+0x00, 0x08, 0x00};
+static unsigned char symbol14_179_bits[] = {
+0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol14_180_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x49, 0x2a};
+static unsigned char symbol14_181_bits[] = {
+0x1c, 0x08, 0x06, 0x09};
+static unsigned char symbol14_182_bits[] = {
+0x09, 0x06, 0x08, 0x08, 0x08, 0x3f, 0x08, 0x08, 0x08, 0x00, 0x3f};
+static unsigned char symbol14_183_bits[] = {
+0x0c, 0x16, 0x09, 0x01, 0x06};
+static unsigned char symbol14_184_bits[] = {
+0x18, 0x60, 0x18, 0x06, 0x01, 0x00, 0x7f};
+static unsigned char symbol14_185_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char symbol14_186_bits[] = {
+0x6e, 0x11, 0x11, 0x6e, 0x0e};
+static unsigned char symbol14_187_bits[] = {
+0x11, 0x20, 0x20, 0x20, 0x2e};
+static unsigned char symbol14_188_bits[] = {
+0x33, 0x01, 0x21, 0x01};
+static unsigned char symbol14_189_bits[] = {
+0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00};
+static unsigned char symbol14_190_bits[] = {
+0x7f, 0x00};
+static unsigned char symbol14_191_bits[] = {
+0x7f, 0x00, 0x7f, 0x4e, 0x39, 0x00, 0x4e, 0x39, 0x11};
+static unsigned char symbol14_192_bits[] = {
+0x01, 0x11, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_193_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_194_bits[] = {
+0x01, 0x03, 0x7f, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x02, 0xff, 0x02, 
+0x11, 0x03, 0x66, 0x00, 0x2e, 0x01, 0x31, 0x02, 0xc6, 0x03};
+static unsigned char symbol14_195_bits[] = {
+0xfc, 0x00, 0x42, 0x00, 0x24, 0x00, 0xc0, 0x00, 0x86, 0x01, 0x58, 0x00, 
+0xce, 0x00, 0xb9, 0x01, 0x91, 0x01, 0xd1, 0x00, 0x73, 0x00, 0x56, 0x00};
+static unsigned char symbol14_196_bits[] = {
+0x94, 0x00, 0x90, 0x00, 0x90, 0x00, 0x96, 0x00, 0x0d, 0x01, 0x08, 0x00, 
+0xc4, 0x00, 0xa2, 0x01, 0x11, 0x01};
+static unsigned char symbol14_197_bits[] = {
+0x09, 0x01, 0x2b, 0x01, 0x96, 0x00, 0xd6, 0x00, 0x6d, 0x00, 0x09, 0x00, 
+0x09, 0x00, 0x06, 0x00, 0x38, 0x00};
+static unsigned char symbol14_198_bits[] = {
+0xc6, 0x00, 0xc6, 0x00, 0x29, 0x01, 0x11, 0x01, 0x29, 0x01, 0xc6, 0x00, 
+0xc6, 0x00, 0x38, 0x00, 0x38, 0x00, 0xc6, 0x00, 0x92, 0x00};
+static unsigned char symbol14_199_bits[] = {
+0x11, 0x01, 0x7d, 0x01, 0x11, 0x01, 0x92, 0x00, 0xc6, 0x00, 0x38, 0x00, 
+0xf8, 0x00};
+static unsigned char symbol14_200_bits[] = {
+0x06, 0x03, 0x02, 0x03, 0x81, 0x00, 0x41, 0x00, 0x21, 0x00, 0x11, 0x00, 
+0x09, 0x00};
+static unsigned char symbol14_201_bits[] = {
+0x06, 0x00, 0x06, 0x01, 0xf9, 0x00, 0x78, 0x00, 0x86, 0x01, 0x02, 0x01, 
+0x01, 0x00};
+static unsigned char symbol14_202_bits[] = {
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x02, 0x01, 0x86, 0x01};
+static unsigned char symbol14_203_bits[] = {
+0x78, 0x00, 0x7f, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 
+0x80, 0x00, 0x7f, 0x00, 0x7f, 0x00};
+static unsigned char symbol14_204_bits[] = {
+0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x00, 0x7f, 0x00, 
+0x00, 0x00};
+static unsigned char symbol14_205_bits[] = {
+0xff, 0x01, 0x80, 0x00, 0xfc, 0x01, 0x42, 0x00, 0x41, 0x00, 0x21, 0x00, 
+0x21, 0x00, 0x12, 0x00, 0xfc, 0x01};
+static unsigned char symbol14_206_bits[] = {
+0x08, 0x00, 0x7c, 0x01, 0x02, 0x00, 0x01};
+static unsigned char symbol14_207_bits[] = {
+0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 0x7c, 0x01};
+static unsigned char symbol14_208_bits[] = {
+0xfc, 0x01, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x02, 0x00, 
+0xfc, 0x01, 0x00, 0x00, 0xff, 0x01, 0x7c, 0x02};
+static unsigned char symbol14_209_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x09, 0x01, 0x09, 0x00, 
+0x7c, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00};
+static unsigned char symbol14_210_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0xff, 0x03, 
+0xff, 0x01, 0x01, 0x01, 0x82, 0x00, 0x82, 0x00};
+static unsigned char symbol14_211_bits[] = {
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x78, 0x00, 0x84, 0x00, 0x3e, 0x01};
+static unsigned char symbol14_212_bits[] = {
+0x49, 0x02, 0x49, 0x02, 0x39, 0x02, 0x49, 0x02, 0x9e, 0x01, 0x84, 0x00};
+static unsigned char symbol14_213_bits[] = {
+0x78, 0x00, 0x78, 0x00, 0x84, 0x00, 0x72, 0x01, 0x49, 0x02, 0x09, 0x02, 
+0x09, 0x02, 0x49, 0x02, 0x32, 0x01, 0x84, 0x00, 0x78, 0x00, 0x5f, 0x01};
+static unsigned char symbol14_214_bits[] = {
+0x55, 0x01, 0x64, 0x03, 0xa4, 0x02, 0xa4, 0x02, 0x6e, 0x07, 0xff, 0x03, 
+0x02, 0x01};
+static unsigned char symbol14_215_bits[] = {
+0x00, 0x01};
+static unsigned char symbol14_216_bits[] = {
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01};
+static unsigned char symbol14_217_bits[] = {
+0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x87};
+static unsigned char symbol14_218_bits[] = {
+0x03, 0x80, 0x80, 0x80, 0x40, 0x40, 0x40};
+static unsigned char symbol14_219_bits[] = {
+0x40, 0x06, 0x25, 0x04, 0x28, 0x08, 0x10, 0x10, 0x01, 0x01, 0xff, 0x01, 
+0x00, 0x01};
+static unsigned char symbol14_220_bits[] = {
+0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x18, 0x18, 0x24, 0x04, 0x42, 0x02, 
+0x81, 0x01};
+static unsigned char symbol14_221_bits[] = {
+0x42, 0x42, 0x24, 0x24, 0x18, 0x18, 0x08, 0x02, 0x04, 0x04, 0x7e, 0x0f, 
+0x03};
+static unsigned char symbol14_222_bits[] = {
+0x18, 0x1e, 0x0f, 0x04, 0x04, 0x08, 0x02, 0x08, 0x00, 0x04, 0x00, 0x1e, 
+0x1f, 0x03};
+static unsigned char symbol14_223_bits[] = {
+0x00, 0x7e, 0x1f, 0x04, 0x00, 0x08, 0x00, 0x08, 0x1c, 0x36, 0x55, 0x14, 
+0x14};
+static unsigned char symbol14_224_bits[] = {
+0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x02, 0x00, 0x04};
+static unsigned char symbol14_225_bits[] = {
+0x0f, 0x0f, 0x00, 0x08, 0x0f, 0x0f, 0x00, 0x04, 0x00, 0x02, 0x04, 0x04, 
+0x04, 0x04, 0x04};
+static unsigned char symbol14_226_bits[] = {
+0x14, 0x00, 0x14, 0x00, 0x55, 0x02, 0x1c, 0x00, 0x08, 0x00, 0x14, 0x02, 
+0x22, 0x01, 0x22, 0x02, 0x14, 0x00, 0x08, 0x00};
+static unsigned char symbol14_227_bits[] = {
+0x04, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 
+0x04, 0x00, 0x78, 0x00, 0x84, 0x00, 0x3a, 0x01};
+static unsigned char symbol14_228_bits[] = {
+0x49, 0x02, 0x49, 0x02, 0x39, 0x02, 0x49, 0x02, 0x4a, 0x01, 0x84, 0x00};
+static unsigned char symbol14_229_bits[] = {
+0x78, 0x00, 0x78, 0x00, 0x84, 0x00, 0x32, 0x01, 0x49, 0x00, 0x09, 0x00, 
+0x09, 0x00, 0x49, 0x00, 0x32, 0x01, 0x84, 0x00, 0x78, 0x00, 0x5f, 0x01};
+static unsigned char symbol14_230_bits[] = {
+0x04, 0x01, 0x04, 0x03, 0x04, 0x02, 0x04, 0x02, 0x04, 0x02, 0x0f, 0x00, 
+0x01, 0x00, 0x02, 0x00, 0x04, 0x00, 0x08, 0x00};
+static unsigned char symbol14_231_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 
+0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char symbol14_232_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_233_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_234_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 
+0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_235_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_236_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_237_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x07, 0x04, 0x02, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_238_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x04, 0x04, 0x04};
+static unsigned char symbol14_239_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01};
+static unsigned char symbol14_240_bits[] = {
+0x00};
+static unsigned char symbol14_241_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x02, 0x0c, 0x01};
+static unsigned char symbol14_242_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char symbol14_243_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x02, 0x04, 0x04, 
+0x04, 0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02};
+static unsigned char symbol14_244_bits[] = {
+0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01};
+static unsigned char symbol14_245_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_246_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00};
+static unsigned char symbol14_247_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_248_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol14_249_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x08, 0x08, 0x08, 0x08, 0x08};
+static unsigned char symbol14_250_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol14_251_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x01, 0x01};
+static unsigned char symbol14_252_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08};
+static unsigned char symbol14_253_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x07, 0x03, 0x04, 0x00, 0x00, 0x00};
+static unsigned char symbol14_254_bits[] = {
+0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 
+0x08, 0x08, 0x08, 0x01, 0x01};
+static unsigned char symbol14_255_bits[] = {
+0x00};
+static RotFont symbol14font[] = {
+{5, 1, 1, symbol14_0_bits},
+{5, 1, 1, symbol14_1_bits},
+{5, 1, 1, symbol14_2_bits},
+{5, 1, 1, symbol14_3_bits},
+{5, 1, 1, symbol14_4_bits},
+{5, 1, 1, symbol14_5_bits},
+{5, 1, 1, symbol14_6_bits},
+{5, 1, 1, symbol14_7_bits},
+{5, 1, 1, symbol14_8_bits},
+{5, 1, 1, symbol14_9_bits},
+{5, 1, 1, symbol14_10_bits},
+{5, 1, 1, symbol14_11_bits},
+{5, 1, 1, symbol14_12_bits},
+{5, 1, 1, symbol14_13_bits},
+{5, 1, 1, symbol14_14_bits},
+{5, 1, 1, symbol14_15_bits},
+{5, 1, 1, symbol14_16_bits},
+{5, 1, 1, symbol14_17_bits},
+{5, 1, 1, symbol14_18_bits},
+{5, 1, 1, symbol14_19_bits},
+{5, 1, 1, symbol14_20_bits},
+{5, 1, 1, symbol14_21_bits},
+{5, 1, 1, symbol14_22_bits},
+{5, 1, 1, symbol14_23_bits},
+{5, 1, 1, symbol14_24_bits},
+{5, 1, 1, symbol14_25_bits},
+{5, 1, 1, symbol14_26_bits},
+{5, 1, 1, symbol14_27_bits},
+{5, 1, 1, symbol14_28_bits},
+{5, 1, 1, symbol14_29_bits},
+{5, 1, 1, symbol14_30_bits},
+{5, 1, 1, symbol14_31_bits},
+{1, 1, 1, symbol14_32_bits},
+{1, 10, 10, symbol14_33_bits},
+{9, 10, 10, symbol14_34_bits},
+{7, 10, 10, symbol14_35_bits},
+{6, 10, 10, symbol14_36_bits},
+{9, 10, 10, symbol14_37_bits},
+{9, 10, 10, symbol14_38_bits},
+{5, 7, 7, symbol14_39_bits},
+{3, 13, 10, symbol14_40_bits},
+{3, 13, 10, symbol14_41_bits},
+{5, 6, 8, symbol14_42_bits},
+{7, 7, 7, symbol14_43_bits},
+{2, 4, 2, symbol14_44_bits},
+{7, 1, 4, symbol14_45_bits},
+{1, 2, 2, symbol14_46_bits},
+{4, 10, 10, symbol14_47_bits},
+{6, 10, 10, symbol14_48_bits},
+{5, 10, 10, symbol14_49_bits},
+{6, 10, 10, symbol14_50_bits},
+{6, 10, 10, symbol14_51_bits},
+{6, 10, 10, symbol14_52_bits},
+{5, 10, 10, symbol14_53_bits},
+{6, 10, 10, symbol14_54_bits},
+{6, 10, 10, symbol14_55_bits},
+{5, 10, 10, symbol14_56_bits},
+{6, 10, 10, symbol14_57_bits},
+{1, 7, 7, symbol14_58_bits},
+{2, 9, 7, symbol14_59_bits},
+{7, 7, 7, symbol14_60_bits},
+{7, 3, 5, symbol14_61_bits},
+{7, 7, 7, symbol14_62_bits},
+{5, 10, 10, symbol14_63_bits},
+{7, 7, 7, symbol14_64_bits},
+{9, 10, 10, symbol14_65_bits},
+{7, 10, 10, symbol14_66_bits},
+{9, 10, 10, symbol14_67_bits},
+{7, 10, 10, symbol14_68_bits},
+{7, 10, 10, symbol14_69_bits},
+{9, 10, 10, symbol14_70_bits},
+{7, 10, 10, symbol14_71_bits},
+{9, 10, 10, symbol14_72_bits},
+{3, 10, 10, symbol14_73_bits},
+{8, 10, 10, symbol14_74_bits},
+{8, 10, 10, symbol14_75_bits},
+{9, 10, 10, symbol14_76_bits},
+{11, 10, 10, symbol14_77_bits},
+{9, 10, 10, symbol14_78_bits},
+{8, 10, 10, symbol14_79_bits},
+{9, 10, 10, symbol14_80_bits},
+{8, 10, 10, symbol14_81_bits},
+{6, 10, 10, symbol14_82_bits},
+{8, 10, 10, symbol14_83_bits},
+{7, 10, 10, symbol14_84_bits},
+{9, 10, 10, symbol14_85_bits},
+{6, 10, 7, symbol14_86_bits},
+{10, 10, 10, symbol14_87_bits},
+{9, 10, 10, symbol14_88_bits},
+{11, 10, 10, symbol14_89_bits},
+{7, 10, 10, symbol14_90_bits},
+{3, 13, 10, symbol14_91_bits},
+{8, 7, 7, symbol14_92_bits},
+{3, 13, 10, symbol14_93_bits},
+{9, 10, 10, symbol14_94_bits},
+{7, 1, -2, symbol14_95_bits},
+{8, 1, 14, symbol14_96_bits},
+{8, 7, 7, symbol14_97_bits},
+{6, 14, 11, symbol14_98_bits},
+{8, 10, 7, symbol14_99_bits},
+{5, 11, 11, symbol14_100_bits},
+{5, 7, 7, symbol14_101_bits},
+{7, 13, 10, symbol14_102_bits},
+{6, 10, 7, symbol14_103_bits},
+{7, 10, 7, symbol14_104_bits},
+{5, 7, 7, symbol14_105_bits},
+{7, 10, 7, symbol14_106_bits},
+{7, 7, 7, symbol14_107_bits},
+{8, 10, 10, symbol14_108_bits},
+{7, 9, 7, symbol14_109_bits},
+{7, 7, 7, symbol14_110_bits},
+{6, 7, 7, symbol14_111_bits},
+{8, 7, 7, symbol14_112_bits},
+{5, 10, 10, symbol14_113_bits},
+{6, 10, 7, symbol14_114_bits},
+{7, 7, 7, symbol14_115_bits},
+{5, 7, 7, symbol14_116_bits},
+{7, 7, 7, symbol14_117_bits},
+{10, 8, 8, symbol14_118_bits},
+{9, 7, 7, symbol14_119_bits},
+{6, 15, 12, symbol14_120_bits},
+{9, 10, 7, symbol14_121_bits},
+{6, 14, 11, symbol14_122_bits},
+{5, 13, 10, symbol14_123_bits},
+{1, 13, 10, symbol14_124_bits},
+{5, 13, 10, symbol14_125_bits},
+{7, 3, 5, symbol14_126_bits},
+{5, 1, 1, symbol14_127_bits},
+{5, 1, 1, symbol14_128_bits},
+{5, 1, 1, symbol14_129_bits},
+{5, 1, 1, symbol14_130_bits},
+{5, 1, 1, symbol14_131_bits},
+{5, 1, 1, symbol14_132_bits},
+{5, 1, 1, symbol14_133_bits},
+{5, 1, 1, symbol14_134_bits},
+{5, 1, 1, symbol14_135_bits},
+{5, 1, 1, symbol14_136_bits},
+{5, 1, 1, symbol14_137_bits},
+{5, 1, 1, symbol14_138_bits},
+{5, 1, 1, symbol14_139_bits},
+{5, 1, 1, symbol14_140_bits},
+{5, 1, 1, symbol14_141_bits},
+{5, 1, 1, symbol14_142_bits},
+{5, 1, 1, symbol14_143_bits},
+{5, 1, 1, symbol14_144_bits},
+{5, 1, 1, symbol14_145_bits},
+{5, 1, 1, symbol14_146_bits},
+{5, 1, 1, symbol14_147_bits},
+{5, 1, 1, symbol14_148_bits},
+{5, 1, 1, symbol14_149_bits},
+{5, 1, 1, symbol14_150_bits},
+{5, 1, 1, symbol14_151_bits},
+{5, 1, 1, symbol14_152_bits},
+{5, 1, 1, symbol14_153_bits},
+{5, 1, 1, symbol14_154_bits},
+{5, 1, 1, symbol14_155_bits},
+{5, 1, 1, symbol14_156_bits},
+{5, 1, 1, symbol14_157_bits},
+{5, 1, 1, symbol14_158_bits},
+{5, 1, 1, symbol14_159_bits},
+{5, 1, 1, symbol14_160_bits},
+{8, 10, 10, symbol14_161_bits},
+{4, 3, 10, symbol14_162_bits},
+{7, 9, 9, symbol14_163_bits},
+{5, 10, 10, symbol14_164_bits},
+{9, 4, 6, symbol14_165_bits},
+{7, 13, 10, symbol14_166_bits},
+{9, 8, 7, symbol14_167_bits},
+{7, 7, 7, symbol14_168_bits},
+{7, 7, 7, symbol14_169_bits},
+{9, 8, 7, symbol14_170_bits},
+{13, 7, 7, symbol14_171_bits},
+{14, 7, 7, symbol14_172_bits},
+{7, 20, 14, symbol14_173_bits},
+{14, 7, 7, symbol14_174_bits},
+{7, 17, 14, symbol14_175_bits},
+{4, 4, 10, symbol14_176_bits},
+{7, 9, 9, symbol14_177_bits},
+{7, 3, 10, symbol14_178_bits},
+{7, 9, 9, symbol14_179_bits},
+{7, 7, 7, symbol14_180_bits},
+{8, 4, 6, symbol14_181_bits},
+{6, 11, 11, symbol14_182_bits},
+{5, 5, 6, symbol14_183_bits},
+{7, 7, 7, symbol14_184_bits},
+{7, 7, 7, symbol14_185_bits},
+{7, 5, 6, symbol14_186_bits},
+{7, 5, 6, symbol14_187_bits},
+{9, 2, 2, symbol14_188_bits},
+{1, 20, 14, symbol14_189_bits},
+{15, 1, 4, symbol14_190_bits},
+{8, 9, 9, symbol14_191_bits},
+{8, 10, 10, symbol14_192_bits},
+{8, 12, 11, symbol14_193_bits},
+{10, 11, 11, symbol14_194_bits},
+{9, 12, 9, symbol14_195_bits},
+{9, 9, 9, symbol14_196_bits},
+{9, 9, 9, symbol14_197_bits},
+{11, 11, 11, symbol14_198_bits},
+{10, 7, 7, symbol14_199_bits},
+{10, 7, 7, symbol14_200_bits},
+{9, 7, 7, symbol14_201_bits},
+{9, 9, 7, symbol14_202_bits},
+{9, 9, 8, symbol14_203_bits},
+{9, 7, 7, symbol14_204_bits},
+{9, 9, 7, symbol14_205_bits},
+{7, 7, 7, symbol14_206_bits},
+{7, 9, 8, symbol14_207_bits},
+{11, 10, 10, symbol14_208_bits},
+{9, 11, 11, symbol14_209_bits},
+{10, 10, 10, symbol14_210_bits},
+{10, 10, 10, symbol14_211_bits},
+{11, 6, 10, symbol14_212_bits},
+{10, 12, 11, symbol14_213_bits},
+{8, 14, 14, symbol14_214_bits},
+{1, 2, 5, symbol14_215_bits},
+{9, 5, 5, symbol14_216_bits},
+{8, 7, 7, symbol14_217_bits},
+{8, 7, 7, symbol14_218_bits},
+{13, 7, 7, symbol14_219_bits},
+{13, 7, 7, symbol14_220_bits},
+{7, 13, 13, symbol14_221_bits},
+{13, 7, 7, symbol14_222_bits},
+{7, 13, 13, symbol14_223_bits},
+{7, 11, 11, symbol14_224_bits},
+{4, 15, 11, symbol14_225_bits},
+{10, 10, 10, symbol14_226_bits},
+{10, 10, 10, symbol14_227_bits},
+{10, 6, 10, symbol14_228_bits},
+{9, 12, 11, symbol14_229_bits},
+{4, 20, 14, symbol14_230_bits},
+{1, 20, 14, symbol14_231_bits},
+{4, 20, 14, symbol14_232_bits},
+{4, 20, 14, symbol14_233_bits},
+{1, 20, 14, symbol14_234_bits},
+{4, 17, 14, symbol14_235_bits},
+{4, 20, 14, symbol14_236_bits},
+{3, 20, 14, symbol14_237_bits},
+{4, 17, 14, symbol14_238_bits},
+{1, 20, 14, symbol14_239_bits},
+{5, 1, 1, symbol14_240_bits},
+{4, 15, 11, symbol14_241_bits},
+{5, 13, 12, symbol14_242_bits},
+{5, 20, 14, symbol14_243_bits},
+{1, 20, 14, symbol14_244_bits},
+{5, 17, 14, symbol14_245_bits},
+{4, 20, 14, symbol14_246_bits},
+{1, 20, 14, symbol14_247_bits},
+{4, 20, 14, symbol14_248_bits},
+{4, 20, 14, symbol14_249_bits},
+{1, 20, 14, symbol14_250_bits},
+{4, 17, 14, symbol14_251_bits},
+{4, 20, 14, symbol14_252_bits},
+{3, 20, 14, symbol14_253_bits},
+{4, 17, 14, symbol14_254_bits},
+{5, 1, 1, symbol14_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol18.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol18.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol18.bdf	(revision 16632)
@@ -0,0 +1,3822 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--18-180-75-75-P-107-Adobe-FontSpecific
+SIZE 18 75 75
+FONTBOUNDINGBOX 20 25 -1 -7
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 107
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 13
+X_HEIGHT 9
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--18-180-75-75-P-107-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 11
+DEFAULT_CHAR 32
+FONT_ASCENT 16
+FONT_DESCENT 4
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 2 13 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 0 0
+BITMAP
+c018
+c018
+6030
+6030
+3fe0
+3060
+18c0
+18c0
+0880
+0d80
+0500
+0700
+0200
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 10 13 -1 0
+BITMAP
+0900
+0900
+0900
+0900
+7fc0
+1200
+1200
+1200
+ff80
+2400
+2400
+2400
+2400
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+ff
+03
+03
+03
+03
+03
+7f
+03
+03
+03
+03
+03
+ff
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+3860
+67e0
+c4c0
+c580
+e980
+7300
+0600
+0670
+0cc8
+1988
+1988
+31d0
+30e0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 1 0
+BITMAP
+1c00
+3600
+2200
+2600
+3c00
+39e0
+7cc0
+ee80
+c780
+c300
+c390
+67f0
+3ce0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+f0
+38
+1c
+0c
+7c
+0c
+1c
+38
+f0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+10
+30
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+30
+10
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+80
+c0
+60
+60
+30
+30
+30
+30
+30
+30
+30
+30
+30
+60
+60
+c0
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 7 1 3
+BITMAP
+10
+d6
+7c
+38
+7c
+d6
+10
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+18
+18
+18
+ff
+ff
+18
+18
+18
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 5 1 -3
+BITMAP
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 2 1 4
+BITMAP
+fe
+fe
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 13 0 0
+BITMAP
+18
+18
+18
+30
+30
+30
+60
+60
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+66
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+66
+66
+3c
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 6 13 1 0
+BITMAP
+10
+30
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+3c
+7e
+ce
+86
+06
+06
+0c
+18
+30
+60
+c2
+fe
+fe
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7c
+ce
+86
+06
+0c
+38
+1c
+0e
+06
+06
+06
+cc
+f8
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+06
+0e
+0e
+1e
+36
+36
+66
+c6
+c6
+ff
+06
+06
+06
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7e
+7c
+c0
+c0
+f0
+3c
+0c
+0e
+06
+06
+0c
+dc
+f0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+0e
+38
+30
+60
+60
+fc
+c6
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+7f
+ff
+86
+06
+0c
+0c
+0c
+18
+18
+18
+30
+30
+30
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+62
+62
+76
+3c
+3e
+67
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+6e
+c7
+c3
+c3
+c3
+e3
+7f
+3a
+06
+0c
+38
+e0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 2 9 2 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+60
+60
+00
+00
+00
+00
+00
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+0380
+0f00
+3c00
+f000
+c000
+f000
+3c00
+0f00
+0380
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 6 1 2
+BITMAP
+ff
+ff
+00
+00
+ff
+ff
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+e000
+7800
+1e00
+0780
+0180
+0780
+1e00
+7800
+e000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 0
+BITMAP
+78
+dc
+cc
+cc
+0c
+0c
+18
+30
+20
+20
+00
+60
+60
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+73
+ff
+ce
+00
+ff
+ff
+00
+ff
+ff
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0400
+0e00
+0e00
+0b00
+1b00
+1300
+1180
+3180
+3fc0
+20c0
+60c0
+60e0
+f1f0
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+fc00
+6600
+6300
+6300
+6300
+6600
+7e00
+6300
+6180
+6180
+6180
+6380
+ff00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+f070
+7060
+38c0
+18c0
+1d80
+0f00
+0600
+0f00
+1b80
+3180
+31c0
+60e0
+e0f0
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 11 13 0 0
+BITMAP
+0400
+0600
+0e00
+0b00
+1300
+1300
+1180
+2180
+21c0
+40c0
+40c0
+8060
+ffe0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0f00
+0600
+1f80
+6660
+c630
+c630
+c630
+c630
+c630
+6660
+1f80
+0600
+0f00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 0 0
+BITMAP
+ffc0
+70c0
+3040
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+7800
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f1e0
+60c0
+60c0
+60c0
+60c0
+60c0
+7fc0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 13 1 0
+BITMAP
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 1 0
+BITMAP
+0600
+0b00
+0980
+0580
+6380
+f180
+b1c0
+31a0
+3180
+3180
+3180
+3b00
+1e00
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 11 13 2 0
+BITMAP
+f3c0
+6180
+6300
+6600
+6c00
+7800
+7800
+6c00
+6600
+6300
+6380
+61c0
+f1e0
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 0
+BITMAP
+0600
+0600
+0f00
+0b00
+0b00
+1980
+1180
+1180
+30c0
+20c0
+2060
+6060
+f0f0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+e01c
+7038
+7038
+5878
+5858
+58d8
+4c98
+4c98
+4d98
+4718
+4718
+4318
+e23c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+e0e0
+7040
+7040
+5840
+4c40
+4c40
+4640
+4340
+43c0
+41c0
+40c0
+40c0
+e040
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+0e00
+3180
+60c0
+e0e0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60c0
+3180
+0e00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+ffe0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+0e00
+3180
+60c0
+e0e0
+c060
+d160
+df60
+d160
+c060
+e0e0
+60c0
+3180
+0e00
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+fe
+67
+63
+63
+63
+67
+7e
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 1 0
+BITMAP
+ff80
+c180
+6080
+3000
+1800
+0c00
+0c00
+0800
+1000
+2040
+40c0
+ff80
+ff80
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+ffc0
+ccc0
+8c40
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+1e00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 0
+BITMAP
+f8f0
+7060
+30c0
+18c0
+1d80
+0f00
+0f00
+0600
+0600
+0600
+0600
+0600
+0f00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 -4
+BITMAP
+3c
+7c
+c0
+80
+80
+80
+c0
+78
+3c
+04
+04
+3c
+38
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+0700
+18c0
+3060
+7070
+6030
+6030
+6030
+6030
+3060
+18c0
+8888
+f8f8
+f8f8
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+7f80
+7f80
+4080
+0000
+2100
+3f00
+3f00
+2100
+0000
+8040
+8040
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 13 0 0
+BITMAP
+c78c
+6318
+6318
+6318
+6318
+3330
+1fe0
+0300
+0300
+0300
+0300
+0300
+0780
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+c380
+8300
+0700
+0600
+0e00
+1c00
+1800
+3800
+7000
+6080
+e180
+ff80
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 10 9 2 0
+BITMAP
+0c00
+0c00
+0000
+0000
+0000
+0000
+0000
+c0c0
+c0c0
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 -4
+BITMAP
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 2 0 -4
+BITMAP
+ff80
+ff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 10 1 0 16
+BITMAP
+ffc0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 9 1 0
+BITMAP
+3cc0
+6580
+c300
+c300
+c300
+c300
+c300
+6520
+38c0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 18 1 -4
+BITMAP
+3c
+46
+c6
+c6
+c6
+cc
+c6
+c3
+c3
+c3
+c3
+c3
+e6
+dc
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 13 0 -4
+BITMAP
+60c0
+f1c0
+9180
+1300
+1700
+0e00
+0c00
+1c00
+1a00
+3200
+6240
+e3c0
+c180
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+38
+4c
+40
+60
+30
+38
+6c
+c6
+c6
+c6
+c6
+c6
+6c
+38
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 9 1 0
+BITMAP
+78
+ec
+cc
+c0
+70
+c0
+c0
+e4
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 -4
+BITMAP
+0800
+0800
+0800
+3e00
+6b00
+c980
+c980
+c980
+c980
+c980
+6b00
+3e00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 13 0 -4
+BITMAP
+c3
+e3
+a3
+26
+26
+16
+14
+1c
+0c
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 -4
+BITMAP
+6700
+e980
+b180
+3180
+3180
+3180
+3180
+3180
+3180
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+60
+e0
+60
+60
+60
+60
+60
+68
+70
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 -4
+BITMAP
+6600
+cf00
+c980
+c980
+c980
+c980
+4900
+6b00
+3e00
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+6380
+e580
+6800
+7800
+7c00
+6e00
+6700
+6380
+6180
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 14 0 0
+BITMAP
+3000
+7800
+4800
+0800
+0800
+0800
+1c00
+1c00
+3400
+3400
+6600
+6240
+c3c0
+c180
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 2 -4
+BITMAP
+4200
+c600
+c600
+c600
+c600
+c600
+c680
+fb80
+7b00
+4000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+c3
+c3
+61
+62
+32
+34
+1c
+18
+08
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+7f80
+ff80
+9200
+1200
+1200
+1200
+3280
+7380
+6300
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3c
+66
+c3
+c3
+c3
+c3
+ff
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 -4
+BITMAP
+3c
+46
+c3
+c3
+c3
+c3
+c3
+e6
+dc
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 1 0
+BITMAP
+1fc0
+7fc0
+6600
+c300
+c300
+c300
+c300
+6600
+3c00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+7e
+fe
+90
+10
+10
+10
+12
+1e
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+6300
+f180
+b180
+3180
+3180
+3180
+3180
+3b00
+1e00
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 11 0 0
+BITMAP
+3fe0
+7fe0
+9980
+30c0
+2040
+6660
+6660
+6660
+6660
+36c0
+39c0
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 9 1 0
+BITMAP
+3300
+6180
+4080
+ccc0
+ccc0
+ccc0
+ccc0
+6d80
+7380
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 19 1 -4
+BITMAP
+60
+8e
+fc
+20
+40
+40
+7c
+78
+c0
+80
+80
+80
+c0
+fc
+7e
+02
+02
+1e
+1c
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 0 -4
+BITMAP
+e238
+7270
+3260
+3260
+3260
+3260
+1ac0
+1ac0
+0f80
+0200
+0200
+0200
+0200
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 19 1 -4
+BITMAP
+60
+86
+9e
+78
+60
+40
+80
+80
+80
+80
+80
+80
+c0
+fc
+7e
+02
+02
+1e
+1c
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+0e
+18
+30
+30
+30
+30
+30
+60
+c0
+60
+30
+30
+30
+30
+30
+18
+0e
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 17 1 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+0c
+06
+0c
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 3 1 4
+BITMAP
+73
+ff
+ce
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 0 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 5 1 9
+BITMAP
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 12 0 0
+BITMAP
+0000
+0080
+c000
+2000
+6000
+6000
+0000
+0000
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 8 13 -1 0
+BITMAP
+00
+0c
+00
+1e
+00
+30
+70
+60
+c0
+80
+03
+80
+0f
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 5 0 3
+BITMAP
+0030
+00f0
+00c0
+00f0
+0030
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 17 0 -4
+BITMAP
+0000
+0000
+8000
+0080
+8080
+8000
+0600
+0c00
+1800
+3000
+6000
+c080
+7980
+cf00
+8600
+cf00
+7980
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 10 9 2 0
+BITMAP
+0380
+0580
+0c00
+0c00
+0c00
+7f00
+1800
+1800
+1800
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 9 9 2 0
+BITMAP
+1800
+1800
+1800
+1800
+1800
+1800
+d000
+e000
+0c00
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 9 9 2 0
+BITMAP
+1e00
+1e00
+1e00
+6d80
+ff80
+ff80
+6d80
+0c00
+0800
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 10 9 2 0
+BITMAP
+1c00
+3e00
+7f00
+ff80
+7f00
+3e00
+1c00
+0800
+6300
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1013 0
+DWIDTH 19 0
+BBX 17 8 1 1
+BITMAP
+f78080
+80ff80
+7f0000
+003e00
+1c0000
+000c00
+1e0000
+007f80
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 8 0 1
+BITMAP
+ffc0c0
+c06d80
+0c0000
+001800
+003000
+006000
+00ffc0
+80ffc0
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 25 1 -7
+BITMAP
+80
+60
+03
+00
+30
+06
+00
+18
+0c
+00
+18
+00
+00
+30
+00
+00
+60
+00
+00
+ff
+ff
+c0
+ff
+ff
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 8 0 1
+BITMAP
+600000
+300000
+180000
+183c40
+db9900
+181800
+181800
+181800
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 22 1 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+00
+06
+00
+00
+03
+00
+00
+01
+80
+ff
+ff
+c0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 6 1 7
+BITMAP
+f8
+f8
+c0
+00
+00
+80
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 11 1 0
+BITMAP
+00
+03
+00
+00
+06
+00
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 5 0 9
+BITMAP
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 12 0 0
+BITMAP
+1800
+1800
+1800
+1880
+db00
+3c00
+7080
+8880
+d800
+1800
+1880
+ff00
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 9 0 0
+BITMAP
+1800
+00c0
+ff00
+7740
+cc80
+e000
+7800
+1e00
+0780
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 5 0 3
+BITMAP
+0180
+0780
+1e00
+7800
+e000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+00
+00
+fe
+80
+fe
+80
+e0
+c0
+72
+80
+32
+00
+1e
+00
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 6 2 2
+BITMAP
+08
+00
+18
+00
+30
+00
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+73
+80
+e1
+c0
+79
+e0
+cf
+00
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+86
+00
+cf
+00
+79
+e0
+78
+cc
+86
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 8 1 1
+BITMAP
+06
+06
+06
+3e
+66
+c6
+c6
+c6
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 2
+BITMAP
+c4
+ec
+78
+70
+f8
+f8
+f8
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 14 2 2 0
+BITMAP
+f870
+1818
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 2 25 4 -7
+BITMAP
+00
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+00
+c0
+c0
+00
+00
+c0
+c0
+00
+c0
+c0
+00
+c0
+c0
+40
+c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1013 0
+DWIDTH 19 0
+BBX 19 2 0 4
+BITMAP
+ce0060
+ffcec0
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 9 12 1 0
+BITMAP
+0c80
+0c80
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+c0c0
+c0c0
+ffe0
+e0e0
+ffe0
+0180
+0180
+0180
+0180
+0180
+0180
+2180
+6180
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 10 15 1 -1
+BITMAP
+ff80
+ff80
+6000
+2000
+c200
+e3c0
+71c0
+38c0
+3980
+7d00
+cf00
+c700
+e300
+7380
+31c0
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 14 1 0
+BITMAP
+70c0
+f040
+1fc0
+3fc0
+6080
+4100
+4200
+2200
+1300
+0380
+01c0
+00c0
+00c0
+70c0
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 15 1 -4
+BITMAP
+f880
+1f00
+0e00
+79c0
+fee0
+8e70
+8630
+c660
+7680
+3640
+2660
+0660
+0660
+0660
+0660
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+6c70
+b830
+0c00
+1800
+31e0
+6730
+cc30
+d830
+d630
+f660
+64e0
+77c0
+b380
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+9800
+9800
+d800
+7000
+1f80
+39c0
+6060
+d9b0
+ddb0
+8f10
+8610
+8f10
+dbb0
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+d9b0
+6060
+39c0
+1f80
+1f80
+39c0
+6660
+c630
+c630
+bfd0
+bfd0
+8610
+c630
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 9 1 0
+BITMAP
+c630
+6060
+39c0
+1f80
+1fb0
+39f0
+6060
+c0f0
+c1b0
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 9 1 0
+BITMAP
+8310
+8610
+8c10
+d830
+f030
+6060
+f9c0
+df80
+1f80
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 9 1 0
+BITMAP
+39c0
+6060
+e070
+c030
+c030
+c030
+c030
+c030
+c030
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 12 0 -3
+BITMAP
+c030
+c030
+c030
+c030
+e070
+6060
+39c0
+1f80
+ff80
+ffe0
+0060
+0030
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 -2
+BITMAP
+0030
+0030
+0060
+ffe0
+ff80
+ff80
+ffe0
+0060
+0030
+0030
+0030
+0060
+ffe0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 9 0 0
+BITMAP
+ff80
+0000
+fff0
+fff0
+0060
+00c0
+1ff0
+7ff0
+6180
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 12 0 -3
+BITMAP
+c300
+c300
+c600
+6600
+7ff0
+1ff0
+1800
+3000
+1ff0
+7ff0
+6000
+c000
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 9 9 1 0
+BITMAP
+c000
+c000
+6000
+7f80
+1f80
+1f80
+7f80
+6000
+c000
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 11 1 -1
+BITMAP
+c000
+c000
+6000
+7fc0
+1fc0
+0000
+ffc0
+ffc0
+1f80
+7f80
+e000
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+c000
+ff80
+c000
+e000
+7f80
+1f80
+0080
+1fc0
+7fc0
+e200
+c400
+ff80
+c800
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 1 0
+BITMAP
+f000
+7fc0
+3fc0
+4000
+0010
+0030
+0060
+00c0
+0180
+0300
+0600
+0c00
+1800
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+3000
+6000
+c000
+fff8
+fff0
+e020
+6060
+6040
+70c0
+3080
+3080
+3980
+1900
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+1b00
+0e00
+0e00
+0400
+1fc0
+38e0
+6030
+df18
+cd98
+cd98
+cd98
+cf18
+cd98
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 8 1 5
+BITMAP
+dcd8
+6030
+38e0
+1fc0
+1fc0
+38e0
+6030
+c798
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 16 0 -2
+BITMAP
+cd98
+cc98
+cc18
+cc18
+cc98
+c718
+6030
+38e0
+1fc0
+ff1c
+ab18
+2318
+22a8
+22a8
+22a8
+2248
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 10 17 0 0
+BITMAP
+7740
+ffc0
+7000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fcc0
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 4
+BITMAP
+00
+40
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 6 1 0
+BITMAP
+0040
+0040
+0080
+0080
+0080
+0080
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+3080
+7100
+d900
+1900
+1900
+0d00
+0d00
+0600
+0600
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+0600
+c0c0
+ffc0
+ffc0
+0040
+0040
+0040
+0040
+0c00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 9 0 0
+BITMAP
+0c0000
+003300
+330040
+806180
+c0c0c0
+c0c0c0
+c0c040
+806180
+330000
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 9 1 0
+BITMAP
+001e
+000c
+000c
+0008
+0400
+1806
+003f
+ff00
+7fff
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+8080
+0180
+7f80
+8000
+ff00
+1800
+0000
+0400
+0800
+1800
+3f80
+7f80
+e000
+7f80
+3f80
+1800
+0800
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 16 9 1 0
+BITMAP
+0800
+1c00
+3600
+7700
+f780
+3600
+3600
+3600
+3600
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+0000
+0000
+ff80
+ff80
+0000
+ff80
+ff80
+0000
+0000
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+3600
+f780
+7700
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 17 0 -3
+BITMAP
+30
+00
+18
+00
+08
+00
+08
+00
+18
+00
+30
+00
+30
+00
+60
+00
+60
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+00c0
+80c0
+8060
+0060
+0030
+0030
+0018
+0008
+0018
+1830
+3060
+60c0
+c080
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+c0c0
+6060
+3030
+1818
+1fc0
+38e0
+6030
+cf18
+cd98
+cd98
+cf18
+cd98
+cd98
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 8 1 5
+BITMAP
+cd98
+6030
+38e0
+1fc0
+1fc0
+38e0
+6030
+c718
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 16 0 -2
+BITMAP
+cc90
+cc10
+cc10
+cc10
+cc90
+c710
+6030
+38e0
+1fc0
+fb10
+2310
+2310
+22a0
+22a0
+22a0
+2240
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 1 -7
+BITMAP
+20
+48
+fc
+e0
+e0
+60
+70
+20
+38
+00
+1c
+00
+0c
+00
+04
+00
+00
+00
+04
+00
+0c
+00
+18
+00
+30
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 1 -7
+BITMAP
+00
+40
+00
+c0
+00
+c0
+c0
+c0
+c0
+00
+00
+00
+00
+00
+00
+40
+40
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+e0
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 1 -7
+BITMAP
+40
+40
+40
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 22 1 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 4 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f8
+38
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 22 4 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+30
+e0
+e0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 2 25 4 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 17 0 -3
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+38
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 22 0 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+c0
+c0
+60
+60
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 7 25 5 -7
+BITMAP
+30
+30
+18
+18
+08
+18
+18
+30
+30
+60
+60
+c0
+c0
+1c
+1c
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 2 25 0 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 7 22 0 -4
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 0 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+04
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 4 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+40
+80
+c0
+40
+40
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 25 0 -7
+BITMAP
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+08
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 2 25 4 -7
+BITMAP
+00
+00
+00
+00
+00
+00
+40
+40
+c0
+80
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 22 1 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 1 -7
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 25 4 -7
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+f8
+e0
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 5 22 1 -4
+BITMAP
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol18.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol18.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol18.h	(revision 16632)
@@ -0,0 +1,1000 @@
+static unsigned char symbol18_0_bits[] = {
+0x00};
+static unsigned char symbol18_1_bits[] = {
+0x00};
+static unsigned char symbol18_2_bits[] = {
+0x00};
+static unsigned char symbol18_3_bits[] = {
+0x00};
+static unsigned char symbol18_4_bits[] = {
+0x00};
+static unsigned char symbol18_5_bits[] = {
+0x00};
+static unsigned char symbol18_6_bits[] = {
+0x00};
+static unsigned char symbol18_7_bits[] = {
+0x00};
+static unsigned char symbol18_8_bits[] = {
+0x00};
+static unsigned char symbol18_9_bits[] = {
+0x00};
+static unsigned char symbol18_10_bits[] = {
+0x00};
+static unsigned char symbol18_11_bits[] = {
+0x00};
+static unsigned char symbol18_12_bits[] = {
+0x00};
+static unsigned char symbol18_13_bits[] = {
+0x00};
+static unsigned char symbol18_14_bits[] = {
+0x00};
+static unsigned char symbol18_15_bits[] = {
+0x00};
+static unsigned char symbol18_16_bits[] = {
+0x00};
+static unsigned char symbol18_17_bits[] = {
+0x00};
+static unsigned char symbol18_18_bits[] = {
+0x00};
+static unsigned char symbol18_19_bits[] = {
+0x00};
+static unsigned char symbol18_20_bits[] = {
+0x00};
+static unsigned char symbol18_21_bits[] = {
+0x00};
+static unsigned char symbol18_22_bits[] = {
+0x00};
+static unsigned char symbol18_23_bits[] = {
+0x00};
+static unsigned char symbol18_24_bits[] = {
+0x00};
+static unsigned char symbol18_25_bits[] = {
+0x00};
+static unsigned char symbol18_26_bits[] = {
+0x00};
+static unsigned char symbol18_27_bits[] = {
+0x00};
+static unsigned char symbol18_28_bits[] = {
+0x00};
+static unsigned char symbol18_29_bits[] = {
+0x00};
+static unsigned char symbol18_30_bits[] = {
+0x00};
+static unsigned char symbol18_31_bits[] = {
+0x00};
+static unsigned char symbol18_32_bits[] = {
+0x00};
+static unsigned char symbol18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x00, 0x00, 0x03, 
+0x03};
+static unsigned char symbol18_34_bits[] = {
+0x03, 0x18, 0x03, 0x18, 0x06, 0x0c, 0x06, 0x0c, 0xfc, 0x07, 0x0c, 0x06, 
+0x18, 0x03, 0x18, 0x03, 0x10, 0x01, 0xb0, 0x01, 0xa0, 0x00, 0xe0, 0x00, 
+0x40, 0x00};
+static unsigned char symbol18_35_bits[] = {
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0xfe, 0x03, 0x48, 0x00, 
+0x48, 0x00, 0x48, 0x00, 0xff, 0x01, 0x24, 0x00, 0x24, 0x00, 0x24, 0x00, 
+0x24, 0x00};
+static unsigned char symbol18_36_bits[] = {
+0xff, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 
+0xff};
+static unsigned char symbol18_37_bits[] = {
+0x1c, 0x06, 0xe6, 0x07, 0x23, 0x03, 0xa3, 0x01, 0x97, 0x01, 0xce, 0x00, 
+0x60, 0x00, 0x60, 0x0e, 0x30, 0x13, 0x98, 0x11, 0x98, 0x11, 0x8c, 0x0b, 
+0x0c, 0x07};
+static unsigned char symbol18_38_bits[] = {
+0x38, 0x00, 0x6c, 0x00, 0x44, 0x00, 0x64, 0x00, 0x3c, 0x00, 0x9c, 0x07, 
+0x3e, 0x03, 0x77, 0x01, 0xe3, 0x01, 0xc3, 0x00, 0xc3, 0x09, 0xe6, 0x0f, 
+0x3c, 0x07};
+static unsigned char symbol18_39_bits[] = {
+0x0f, 0x1c, 0x38, 0x30, 0x3e, 0x30, 0x38, 0x1c, 0x0f};
+static unsigned char symbol18_40_bits[] = {
+0x08, 0x0c, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x06, 0x06, 0x0c, 0x08};
+static unsigned char symbol18_41_bits[] = {
+0x01, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x06, 0x06, 0x03, 0x01};
+static unsigned char symbol18_42_bits[] = {
+0x08, 0x6b, 0x3e, 0x1c, 0x3e, 0x6b, 0x08};
+static unsigned char symbol18_43_bits[] = {
+0x18, 0x18, 0x18, 0xff, 0xff, 0x18, 0x18, 0x18};
+static unsigned char symbol18_44_bits[] = {
+0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char symbol18_45_bits[] = {
+0x7f, 0x7f};
+static unsigned char symbol18_46_bits[] = {
+0x03, 0x03};
+static unsigned char symbol18_47_bits[] = {
+0x18, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_48_bits[] = {
+0x3c, 0x66, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x66, 
+0x3c};
+static unsigned char symbol18_49_bits[] = {
+0x08, 0x0c, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x3f};
+static unsigned char symbol18_50_bits[] = {
+0x3c, 0x7e, 0x73, 0x61, 0x60, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x43, 0x7f, 
+0x7f};
+static unsigned char symbol18_51_bits[] = {
+0x3e, 0x73, 0x61, 0x60, 0x30, 0x1c, 0x38, 0x70, 0x60, 0x60, 0x60, 0x33, 
+0x1f};
+static unsigned char symbol18_52_bits[] = {
+0x60, 0x70, 0x70, 0x78, 0x6c, 0x6c, 0x66, 0x63, 0x63, 0xff, 0x60, 0x60, 
+0x60};
+static unsigned char symbol18_53_bits[] = {
+0x7e, 0x3e, 0x03, 0x03, 0x0f, 0x3c, 0x30, 0x70, 0x60, 0x60, 0x30, 0x3b, 
+0x0f};
+static unsigned char symbol18_54_bits[] = {
+0x70, 0x1c, 0x0c, 0x06, 0x06, 0x3f, 0x63, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char symbol18_55_bits[] = {
+0xfe, 0xff, 0x61, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x18, 0x0c, 0x0c, 
+0x0c};
+static unsigned char symbol18_56_bits[] = {
+0x3c, 0x66, 0x46, 0x46, 0x6e, 0x3c, 0x7c, 0xe6, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char symbol18_57_bits[] = {
+0x3c, 0x76, 0xe3, 0xc3, 0xc3, 0xc3, 0xc7, 0xfe, 0x5c, 0x60, 0x30, 0x1c, 
+0x07};
+static unsigned char symbol18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char symbol18_59_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char symbol18_60_bits[] = {
+0xc0, 0x01, 0xf0, 0x00, 0x3c, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x0f, 0x00, 
+0x3c, 0x00, 0xf0, 0x00, 0xc0, 0x01};
+static unsigned char symbol18_61_bits[] = {
+0xff, 0xff, 0x00, 0x00, 0xff, 0xff};
+static unsigned char symbol18_62_bits[] = {
+0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 0x80, 0x01, 0xe0, 0x01, 
+0x78, 0x00, 0x1e, 0x00, 0x07, 0x00};
+static unsigned char symbol18_63_bits[] = {
+0x1e, 0x3b, 0x33, 0x33, 0x30, 0x30, 0x18, 0x0c, 0x04, 0x04, 0x00, 0x06, 
+0x06};
+static unsigned char symbol18_64_bits[] = {
+0xce, 0xff, 0x73, 0x00, 0xff, 0xff, 0x00, 0xff, 0xff};
+static unsigned char symbol18_65_bits[] = {
+0x20, 0x00, 0x70, 0x00, 0x70, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xc8, 0x00, 
+0x88, 0x01, 0x8c, 0x01, 0xfc, 0x03, 0x04, 0x03, 0x06, 0x03, 0x06, 0x07, 
+0x8f, 0x0f};
+static unsigned char symbol18_66_bits[] = {
+0x3f, 0x00, 0x66, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0x66, 0x00, 
+0x7e, 0x00, 0xc6, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x01, 
+0xff, 0x00};
+static unsigned char symbol18_67_bits[] = {
+0x0f, 0x0e, 0x0e, 0x06, 0x1c, 0x03, 0x18, 0x03, 0xb8, 0x01, 0xf0, 0x00, 
+0x60, 0x00, 0xf0, 0x00, 0xd8, 0x01, 0x8c, 0x01, 0x8c, 0x03, 0x06, 0x07, 
+0x07, 0x0f};
+static unsigned char symbol18_68_bits[] = {
+0x20, 0x00, 0x60, 0x00, 0x70, 0x00, 0xd0, 0x00, 0xc8, 0x00, 0xc8, 0x00, 
+0x88, 0x01, 0x84, 0x01, 0x84, 0x03, 0x02, 0x03, 0x02, 0x03, 0x01, 0x06, 
+0xff, 0x07};
+static unsigned char symbol18_69_bits[] = {
+0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 
+0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 
+0xff, 0x01};
+static unsigned char symbol18_70_bits[] = {
+0xf0, 0x00, 0x60, 0x00, 0xf8, 0x01, 0x66, 0x06, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x66, 0x06, 0xf8, 0x01, 0x60, 0x00, 
+0xf0, 0x00};
+static unsigned char symbol18_71_bits[] = {
+0xff, 0x03, 0x0e, 0x03, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x1e, 0x00};
+static unsigned char symbol18_72_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0xfe, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x8f, 0x07};
+static unsigned char symbol18_73_bits[] = {
+0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char symbol18_74_bits[] = {
+0x60, 0x00, 0xd0, 0x00, 0x90, 0x01, 0xa0, 0x01, 0xc6, 0x01, 0x8f, 0x01, 
+0x8d, 0x03, 0x8c, 0x05, 0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0xdc, 0x00, 
+0x78, 0x00};
+static unsigned char symbol18_75_bits[] = {
+0xcf, 0x03, 0x86, 0x01, 0xc6, 0x00, 0x66, 0x00, 0x36, 0x00, 0x1e, 0x00, 
+0x1e, 0x00, 0x36, 0x00, 0x66, 0x00, 0xc6, 0x00, 0xc6, 0x01, 0x86, 0x03, 
+0x8f, 0x07};
+static unsigned char symbol18_76_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x98, 0x01, 
+0x88, 0x01, 0x88, 0x01, 0x0c, 0x03, 0x04, 0x03, 0x04, 0x06, 0x06, 0x06, 
+0x0f, 0x0f};
+static unsigned char symbol18_77_bits[] = {
+0x07, 0x38, 0x0e, 0x1c, 0x0e, 0x1c, 0x1a, 0x1e, 0x1a, 0x1a, 0x1a, 0x1b, 
+0x32, 0x19, 0x32, 0x19, 0xb2, 0x19, 0xe2, 0x18, 0xe2, 0x18, 0xc2, 0x18, 
+0x47, 0x3c};
+static unsigned char symbol18_78_bits[] = {
+0x07, 0x07, 0x0e, 0x02, 0x0e, 0x02, 0x1a, 0x02, 0x32, 0x02, 0x32, 0x02, 
+0x62, 0x02, 0xc2, 0x02, 0xc2, 0x03, 0x82, 0x03, 0x02, 0x03, 0x02, 0x03, 
+0x07, 0x02};
+static unsigned char symbol18_79_bits[] = {
+0x70, 0x00, 0x8c, 0x01, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8c, 0x01, 
+0x70, 0x00};
+static unsigned char symbol18_80_bits[] = {
+0xff, 0x07, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x8f, 0x07};
+static unsigned char symbol18_81_bits[] = {
+0x70, 0x00, 0x8c, 0x01, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x8b, 0x06, 
+0xfb, 0x06, 0x8b, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8c, 0x01, 
+0x70, 0x00};
+static unsigned char symbol18_82_bits[] = {
+0x7f, 0xe6, 0xc6, 0xc6, 0xc6, 0xe6, 0x7e, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char symbol18_83_bits[] = {
+0xff, 0x01, 0x83, 0x01, 0x06, 0x01, 0x0c, 0x00, 0x18, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x10, 0x00, 0x08, 0x00, 0x04, 0x02, 0x02, 0x03, 0xff, 0x01, 
+0xff, 0x01};
+static unsigned char symbol18_84_bits[] = {
+0xff, 0x03, 0x33, 0x03, 0x31, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x78, 0x00};
+static unsigned char symbol18_85_bits[] = {
+0x1f, 0x0f, 0x0e, 0x06, 0x0c, 0x03, 0x18, 0x03, 0xb8, 0x01, 0xf0, 0x00, 
+0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00};
+static unsigned char symbol18_86_bits[] = {
+0x3c, 0x3e, 0x03, 0x01, 0x01, 0x01, 0x03, 0x1e, 0x3c, 0x20, 0x20, 0x3c, 
+0x1c};
+static unsigned char symbol18_87_bits[] = {
+0xe0, 0x00, 0x18, 0x03, 0x0c, 0x06, 0x0e, 0x0e, 0x06, 0x0c, 0x06, 0x0c, 
+0x06, 0x0c, 0x06, 0x0c, 0x0c, 0x06, 0x18, 0x03, 0x11, 0x11, 0x1f, 0x1f, 
+0x1f, 0x1f};
+static unsigned char symbol18_88_bits[] = {
+0xfe, 0x01, 0xfe, 0x01, 0x02, 0x01, 0x00, 0x00, 0x84, 0x00, 0xfc, 0x00, 
+0xfc, 0x00, 0x84, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x02, 0xff, 0x03, 
+0xff, 0x03};
+static unsigned char symbol18_89_bits[] = {
+0xe3, 0x31, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0x18, 0xcc, 0x0c, 
+0xf8, 0x07, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xe0, 0x01};
+static unsigned char symbol18_90_bits[] = {
+0xff, 0x01, 0xc3, 0x01, 0xc1, 0x00, 0xe0, 0x00, 0x60, 0x00, 0x70, 0x00, 
+0x38, 0x00, 0x18, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x06, 0x01, 0x87, 0x01, 
+0xff, 0x01};
+static unsigned char symbol18_91_bits[] = {
+0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x0f};
+static unsigned char symbol18_92_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_93_bits[] = {
+0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0f};
+static unsigned char symbol18_94_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xff, 0x03, 
+0xff, 0x03};
+static unsigned char symbol18_95_bits[] = {
+0xff, 0x01, 0xff, 0x01};
+static unsigned char symbol18_96_bits[] = {
+0xff, 0x03};
+static unsigned char symbol18_97_bits[] = {
+0x3c, 0x03, 0xa6, 0x01, 0xc3, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0xa6, 0x04, 0x1c, 0x03};
+static unsigned char symbol18_98_bits[] = {
+0x3c, 0x62, 0x63, 0x63, 0x63, 0x33, 0x63, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 
+0x67, 0x3b, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_99_bits[] = {
+0x06, 0x03, 0x8f, 0x03, 0x89, 0x01, 0xc8, 0x00, 0xe8, 0x00, 0x70, 0x00, 
+0x30, 0x00, 0x38, 0x00, 0x58, 0x00, 0x4c, 0x00, 0x46, 0x02, 0xc7, 0x03, 
+0x83, 0x01};
+static unsigned char symbol18_100_bits[] = {
+0x1c, 0x32, 0x02, 0x06, 0x0c, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x63, 0x63, 
+0x36, 0x1c};
+static unsigned char symbol18_101_bits[] = {
+0x1e, 0x37, 0x33, 0x03, 0x0e, 0x03, 0x03, 0x27, 0x1e};
+static unsigned char symbol18_102_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x7c, 0x00, 0xd6, 0x00, 0x93, 0x01, 
+0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 0xd6, 0x00, 0x7c, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char symbol18_103_bits[] = {
+0xc3, 0xc7, 0xc5, 0x64, 0x64, 0x68, 0x28, 0x38, 0x30, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char symbol18_104_bits[] = {
+0xe6, 0x00, 0x97, 0x01, 0x8d, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 
+0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01};
+static unsigned char symbol18_105_bits[] = {
+0x06, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x16, 0x0e};
+static unsigned char symbol18_106_bits[] = {
+0x66, 0x00, 0xf3, 0x00, 0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 0x93, 0x01, 
+0x92, 0x00, 0xd6, 0x00, 0x7c, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00};
+static unsigned char symbol18_107_bits[] = {
+0xc6, 0x01, 0xa7, 0x01, 0x16, 0x00, 0x1e, 0x00, 0x3e, 0x00, 0x76, 0x00, 
+0xe6, 0x00, 0xc6, 0x01, 0x86, 0x01};
+static unsigned char symbol18_108_bits[] = {
+0x0c, 0x00, 0x1e, 0x00, 0x12, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x38, 0x00, 0x38, 0x00, 0x2c, 0x00, 0x2c, 0x00, 0x66, 0x00, 0x46, 0x02, 
+0xc3, 0x03, 0x83, 0x01};
+static unsigned char symbol18_109_bits[] = {
+0x42, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 0x63, 0x00, 
+0x63, 0x01, 0xdf, 0x01, 0xde, 0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char symbol18_110_bits[] = {
+0xc3, 0xc3, 0x86, 0x46, 0x4c, 0x2c, 0x38, 0x18, 0x10};
+static unsigned char symbol18_111_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char symbol18_112_bits[] = {
+0xfe, 0x01, 0xff, 0x01, 0x49, 0x00, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 
+0x4c, 0x01, 0xce, 0x01, 0xc6, 0x00};
+static unsigned char symbol18_113_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xff, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char symbol18_114_bits[] = {
+0x3c, 0x62, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x67, 0x3b, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_115_bits[] = {
+0xf8, 0x03, 0xfe, 0x03, 0x66, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0x66, 0x00, 0x3c, 0x00};
+static unsigned char symbol18_116_bits[] = {
+0x7e, 0x7f, 0x09, 0x08, 0x08, 0x08, 0x48, 0x78, 0x38};
+static unsigned char symbol18_117_bits[] = {
+0xc6, 0x00, 0x8f, 0x01, 0x8d, 0x01, 0x8c, 0x01, 0x8c, 0x01, 0x8c, 0x01, 
+0x8c, 0x01, 0xdc, 0x00, 0x78, 0x00};
+static unsigned char symbol18_118_bits[] = {
+0xfc, 0x07, 0xfe, 0x07, 0x99, 0x01, 0x0c, 0x03, 0x04, 0x02, 0x66, 0x06, 
+0x66, 0x06, 0x66, 0x06, 0x66, 0x06, 0x6c, 0x03, 0x9c, 0x03};
+static unsigned char symbol18_119_bits[] = {
+0xcc, 0x00, 0x86, 0x01, 0x02, 0x01, 0x33, 0x03, 0x33, 0x03, 0x33, 0x03, 
+0x33, 0x03, 0xb6, 0x01, 0xce, 0x01};
+static unsigned char symbol18_120_bits[] = {
+0x06, 0x71, 0x3f, 0x04, 0x02, 0x02, 0x3e, 0x1e, 0x03, 0x01, 0x01, 0x01, 
+0x03, 0x3f, 0x7e, 0x40, 0x40, 0x78, 0x38};
+static unsigned char symbol18_121_bits[] = {
+0x47, 0x1c, 0x4e, 0x0e, 0x4c, 0x06, 0x4c, 0x06, 0x4c, 0x06, 0x4c, 0x06, 
+0x58, 0x03, 0x58, 0x03, 0xf0, 0x01, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 
+0x40, 0x00};
+static unsigned char symbol18_122_bits[] = {
+0x06, 0x61, 0x79, 0x1e, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x03, 0x3f, 0x7e, 0x40, 0x40, 0x78, 0x38};
+static unsigned char symbol18_123_bits[] = {
+0x70, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x18, 0x70};
+static unsigned char symbol18_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x30, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char symbol18_126_bits[] = {
+0xce, 0xff, 0x73};
+static unsigned char symbol18_127_bits[] = {
+0x00};
+static unsigned char symbol18_128_bits[] = {
+0x00};
+static unsigned char symbol18_129_bits[] = {
+0x00};
+static unsigned char symbol18_130_bits[] = {
+0x00};
+static unsigned char symbol18_131_bits[] = {
+0x00};
+static unsigned char symbol18_132_bits[] = {
+0x00};
+static unsigned char symbol18_133_bits[] = {
+0x00};
+static unsigned char symbol18_134_bits[] = {
+0x00};
+static unsigned char symbol18_135_bits[] = {
+0x00};
+static unsigned char symbol18_136_bits[] = {
+0x00};
+static unsigned char symbol18_137_bits[] = {
+0x00};
+static unsigned char symbol18_138_bits[] = {
+0x00};
+static unsigned char symbol18_139_bits[] = {
+0x00};
+static unsigned char symbol18_140_bits[] = {
+0x00};
+static unsigned char symbol18_141_bits[] = {
+0x00};
+static unsigned char symbol18_142_bits[] = {
+0x00};
+static unsigned char symbol18_143_bits[] = {
+0x00};
+static unsigned char symbol18_144_bits[] = {
+0x00};
+static unsigned char symbol18_145_bits[] = {
+0x00};
+static unsigned char symbol18_146_bits[] = {
+0x00};
+static unsigned char symbol18_147_bits[] = {
+0x00};
+static unsigned char symbol18_148_bits[] = {
+0x00};
+static unsigned char symbol18_149_bits[] = {
+0x00};
+static unsigned char symbol18_150_bits[] = {
+0x00};
+static unsigned char symbol18_151_bits[] = {
+0x00};
+static unsigned char symbol18_152_bits[] = {
+0x00};
+static unsigned char symbol18_153_bits[] = {
+0x00};
+static unsigned char symbol18_154_bits[] = {
+0x00};
+static unsigned char symbol18_155_bits[] = {
+0x00};
+static unsigned char symbol18_156_bits[] = {
+0x00};
+static unsigned char symbol18_157_bits[] = {
+0x00};
+static unsigned char symbol18_158_bits[] = {
+0x00};
+static unsigned char symbol18_159_bits[] = {
+0x00};
+static unsigned char symbol18_160_bits[] = {
+0x00};
+static unsigned char symbol18_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00};
+static unsigned char symbol18_162_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol18_163_bits[] = {
+0x00, 0x00, 0x00, 0x01, 0x03, 0x00, 0x04, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol18_164_bits[] = {
+0x00, 0x30, 0x00, 0x78, 0x00, 0x0c, 0x0e, 0x06, 0x03, 0x01, 0xc0, 0x01, 
+0xf0};
+static unsigned char symbol18_165_bits[] = {
+0x00, 0x0c, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x0c};
+static unsigned char symbol18_166_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 
+0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x01, 
+0x9e, 0x01, 0xf3, 0x00, 0x61, 0x00, 0xf3, 0x00, 0x9e, 0x01};
+static unsigned char symbol18_167_bits[] = {
+0xc0, 0x01, 0xa0, 0x01, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xfe, 0x00, 
+0x18, 0x00, 0x18, 0x00, 0x18, 0x00};
+static unsigned char symbol18_168_bits[] = {
+0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 
+0x0b, 0x00, 0x07, 0x00, 0x30, 0x00};
+static unsigned char symbol18_169_bits[] = {
+0x78, 0x00, 0x78, 0x00, 0x78, 0x00, 0xb6, 0x01, 0xff, 0x01, 0xff, 0x01, 
+0xb6, 0x01, 0x30, 0x00, 0x10, 0x00};
+static unsigned char symbol18_170_bits[] = {
+0x38, 0x00, 0x7c, 0x00, 0xfe, 0x00, 0xff, 0x01, 0xfe, 0x00, 0x7c, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0xc6, 0x00};
+static unsigned char symbol18_171_bits[] = {
+0xef, 0x01, 0x01, 0x01, 0xff, 0x01, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0x38, 0x00, 0x00, 0x00, 0x30, 0x00, 0x78, 0x00, 0x00, 0x00, 0xfe, 0x01};
+static unsigned char symbol18_172_bits[] = {
+0xff, 0x03, 0x03, 0x03, 0xb6, 0x01, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0xff, 0x03, 0x01, 0xff, 0x03};
+static unsigned char symbol18_173_bits[] = {
+0x01, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x18, 0x30, 0x00, 0x18, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0xff, 0xff, 0x03, 0xff, 0xff, 
+0x03};
+static unsigned char symbol18_174_bits[] = {
+0x06, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x3c, 0x02, 
+0xdb, 0x99, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00};
+static unsigned char symbol18_175_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x60, 
+0x00, 0x00, 0xc0, 0x00, 0x00, 0x80, 0x01, 0xff, 0xff, 0x03};
+static unsigned char symbol18_176_bits[] = {
+0x1f, 0x1f, 0x03, 0x00, 0x00, 0x01};
+static unsigned char symbol18_177_bits[] = {
+0x00, 0xc0, 0x00, 0x00, 0x60, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol18_178_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol18_179_bits[] = {
+0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x01, 0xdb, 0x00, 0x3c, 0x00, 
+0x0e, 0x01, 0x11, 0x01, 0x1b, 0x00, 0x18, 0x00, 0x18, 0x01, 0xff, 0x00};
+static unsigned char symbol18_180_bits[] = {
+0x18, 0x00, 0x00, 0x03, 0xff, 0x00, 0xee, 0x02, 0x33, 0x01, 0x07, 0x00, 
+0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01};
+static unsigned char symbol18_181_bits[] = {
+0x80, 0x01, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0x07, 0x00};
+static unsigned char symbol18_182_bits[] = {
+0x00, 0x00, 0x7f, 0x01, 0x7f, 0x01, 0x07, 0x03, 0x4e, 0x01, 0x4c, 0x00, 
+0x78, 0x00};
+static unsigned char symbol18_183_bits[] = {
+0x10, 0x00, 0x18, 0x00, 0x0c, 0x00};
+static unsigned char symbol18_184_bits[] = {
+0xce, 0x01, 0x87, 0x03, 0x9e, 0x07, 0xf3, 0x00};
+static unsigned char symbol18_185_bits[] = {
+0x61, 0x00, 0xf3, 0x00, 0x9e, 0x07, 0x1e, 0x33, 0x61};
+static unsigned char symbol18_186_bits[] = {
+0x60, 0x60, 0x60, 0x7c, 0x66, 0x63, 0x63, 0x63};
+static unsigned char symbol18_187_bits[] = {
+0x23, 0x37, 0x1e, 0x0e, 0x1f, 0x1f, 0x1f};
+static unsigned char symbol18_188_bits[] = {
+0x1f, 0x0e, 0x18, 0x18};
+static unsigned char symbol18_189_bits[] = {
+0x00, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 
+0x03, 0x00, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x00, 0x03, 0x03, 0x02, 
+0x03};
+static unsigned char symbol18_190_bits[] = {
+0x73, 0x00, 0x06, 0xff, 0x73, 0x03};
+static unsigned char symbol18_191_bits[] = {
+0x30, 0x01, 0x30, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01};
+static unsigned char symbol18_192_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0xff, 0x07, 0x07, 0x07, 0xff, 0x07, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x84, 0x01, 
+0x86, 0x01};
+static unsigned char symbol18_193_bits[] = {
+0xff, 0x01, 0xff, 0x01, 0x06, 0x00, 0x04, 0x00, 0x43, 0x00, 0xc7, 0x03, 
+0x8e, 0x03, 0x1c, 0x03, 0x9c, 0x01, 0xbe, 0x00, 0xf3, 0x00, 0xe3, 0x00, 
+0xc7, 0x00, 0xce, 0x01, 0x8c, 0x03};
+static unsigned char symbol18_194_bits[] = {
+0x0e, 0x03, 0x0f, 0x02, 0xf8, 0x03, 0xfc, 0x03, 0x06, 0x01, 0x82, 0x00, 
+0x42, 0x00, 0x44, 0x00, 0xc8, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x03, 
+0x00, 0x03, 0x0e, 0x03};
+static unsigned char symbol18_195_bits[] = {
+0x1f, 0x01, 0xf8, 0x00, 0x70, 0x00, 0x9e, 0x03, 0x7f, 0x07, 0x71, 0x0e, 
+0x61, 0x0c, 0x63, 0x06, 0x6e, 0x01, 0x6c, 0x02, 0x64, 0x06, 0x60, 0x06, 
+0x60, 0x06, 0x60, 0x06, 0x60, 0x06};
+static unsigned char symbol18_196_bits[] = {
+0x36, 0x0e, 0x1d, 0x0c, 0x30, 0x00, 0x18, 0x00, 0x8c, 0x07, 0xe6, 0x0c, 
+0x33, 0x0c, 0x1b, 0x0c, 0x6b, 0x0c, 0x6f, 0x06, 0x26, 0x07, 0xee, 0x03, 
+0xcd, 0x01};
+static unsigned char symbol18_197_bits[] = {
+0x19, 0x00, 0x19, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0xf8, 0x01, 0x9c, 0x03, 
+0x06, 0x06, 0x9b, 0x0d, 0xbb, 0x0d, 0xf1, 0x08, 0x61, 0x08, 0xf1, 0x08, 
+0xdb, 0x0d};
+static unsigned char symbol18_198_bits[] = {
+0x9b, 0x0d, 0x06, 0x06, 0x9c, 0x03, 0xf8, 0x01, 0xf8, 0x01, 0x9c, 0x03, 
+0x66, 0x06, 0x63, 0x0c, 0x63, 0x0c, 0xfd, 0x0b, 0xfd, 0x0b, 0x61, 0x08, 
+0x63, 0x0c};
+static unsigned char symbol18_199_bits[] = {
+0x63, 0x0c, 0x06, 0x06, 0x9c, 0x03, 0xf8, 0x01, 0xf8, 0x0d, 0x9c, 0x0f, 
+0x06, 0x06, 0x03, 0x0f, 0x83, 0x0d};
+static unsigned char symbol18_200_bits[] = {
+0xc1, 0x08, 0x61, 0x08, 0x31, 0x08, 0x1b, 0x0c, 0x0f, 0x0c, 0x06, 0x06, 
+0x9f, 0x03, 0xfb, 0x01, 0xf8, 0x01};
+static unsigned char symbol18_201_bits[] = {
+0x9c, 0x03, 0x06, 0x06, 0x07, 0x0e, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char symbol18_202_bits[] = {
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x07, 0x0e, 0x06, 0x06, 
+0x9c, 0x03, 0xf8, 0x01, 0xff, 0x01, 0xff, 0x07, 0x00, 0x06, 0x00, 0x0c};
+static unsigned char symbol18_203_bits[] = {
+0x00, 0x0c, 0x00, 0x0c, 0x00, 0x06, 0xff, 0x07, 0xff, 0x01, 0xff, 0x01, 
+0xff, 0x07, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x06, 
+0xff, 0x07};
+static unsigned char symbol18_204_bits[] = {
+0xff, 0x01, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0x00, 0x06, 0x00, 0x03, 
+0xf8, 0x0f, 0xfe, 0x0f, 0x86, 0x01};
+static unsigned char symbol18_205_bits[] = {
+0xc3, 0x00, 0xc3, 0x00, 0x63, 0x00, 0x66, 0x00, 0xfe, 0x0f, 0xf8, 0x0f, 
+0x18, 0x00, 0x0c, 0x00, 0xf8, 0x0f, 0xfe, 0x0f, 0x06, 0x00, 0x03, 0x00};
+static unsigned char symbol18_206_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x01, 0xf8, 0x01, 0xf8, 0x01, 
+0xfe, 0x01, 0x06, 0x00, 0x03, 0x00};
+static unsigned char symbol18_207_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x03, 0xf8, 0x03, 0x00, 0x00, 
+0xff, 0x03, 0xff, 0x03, 0xf8, 0x01, 0xfe, 0x01, 0x07, 0x00};
+static unsigned char symbol18_208_bits[] = {
+0x03, 0x00, 0xff, 0x01, 0x03, 0x00, 0x07, 0x00, 0xfe, 0x01, 0xf8, 0x01, 
+0x00, 0x01, 0xf8, 0x03, 0xfe, 0x03, 0x47, 0x00, 0x23, 0x00, 0xff, 0x01, 
+0x13, 0x00};
+static unsigned char symbol18_209_bits[] = {
+0x0f, 0x00, 0xfe, 0x03, 0xfc, 0x03, 0x02, 0x00, 0x00, 0x08, 0x00, 0x0c, 
+0x00, 0x06, 0x00, 0x03, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 
+0x18, 0x00};
+static unsigned char symbol18_210_bits[] = {
+0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x1f, 0xff, 0x0f, 0x07, 0x04, 
+0x06, 0x06, 0x06, 0x02, 0x0e, 0x03, 0x0c, 0x01, 0x0c, 0x01, 0x9c, 0x01, 
+0x98, 0x00};
+static unsigned char symbol18_211_bits[] = {
+0xd8, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xfb, 0x18, 0xb3, 0x19, 0xb3, 0x19, 0xb3, 0x19, 0xf3, 0x18, 
+0xb3, 0x19};
+static unsigned char symbol18_212_bits[] = {
+0x3b, 0x1b, 0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xe3, 0x19};
+static unsigned char symbol18_213_bits[] = {
+0xb3, 0x19, 0x33, 0x19, 0x33, 0x18, 0x33, 0x18, 0x33, 0x19, 0xe3, 0x18, 
+0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xff, 0x38, 0xd5, 0x18, 0xc4, 0x18, 
+0x44, 0x15, 0x44, 0x15, 0x44, 0x15, 0x44, 0x12};
+static unsigned char symbol18_214_bits[] = {
+0xee, 0x02, 0xff, 0x03, 0x0e, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x03};
+static unsigned char symbol18_215_bits[] = {
+0x00, 0x02};
+static unsigned char symbol18_216_bits[] = {
+0x00, 0x02, 0x00, 0x02, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static unsigned char symbol18_217_bits[] = {
+0x0c, 0x01, 0x8e, 0x00, 0x9b, 0x00, 0x98, 0x00, 0x98, 0x00, 0xb0, 0x00, 
+0xb0, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol18_218_bits[] = {
+0x60, 0x00, 0x03, 0x03, 0xff, 0x03, 0xff, 0x03, 0x00, 0x02, 0x00, 0x02, 
+0x00, 0x02, 0x00, 0x02, 0x30, 0x00};
+static unsigned char symbol18_219_bits[] = {
+0x30, 0x00, 0x00, 0x00, 0xcc, 0x00, 0xcc, 0x00, 0x02, 0x01, 0x86, 0x01, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x01, 0x86, 0x01, 
+0xcc, 0x00, 0x00};
+static unsigned char symbol18_220_bits[] = {
+0x00, 0x78, 0x00, 0x30, 0x00, 0x30, 0x00, 0x10, 0x20, 0x00, 0x18, 0x60, 
+0x00, 0xfc, 0xff, 0x00, 0xfe, 0xff};
+static unsigned char symbol18_221_bits[] = {
+0x01, 0x01, 0x80, 0x01, 0xfe, 0x01, 0x01, 0x00, 0xff, 0x00, 0x18, 0x00, 
+0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x18, 0x00, 0xfc, 0x01, 0xfe, 0x01, 
+0x07, 0x00, 0xfe, 0x01, 0xfc, 0x01, 0x18, 0x00, 0x10, 0x00};
+static unsigned char symbol18_222_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x6c, 0x00, 0xee, 0x00, 0xef, 0x01, 0x6c, 0x00, 
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00};
+static unsigned char symbol18_223_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 
+0x00, 0x00, 0xff, 0x01, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol18_224_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0xef, 0x01, 0xee, 0x00};
+static unsigned char symbol18_225_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x10, 0x00, 0x10, 0x00, 0x18, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x06, 0x00, 0x06};
+static unsigned char symbol18_226_bits[] = {
+0x00, 0x03, 0x01, 0x03, 0x01, 0x06, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x0c, 
+0x00, 0x18, 0x00, 0x10, 0x00, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 
+0x03, 0x01};
+static unsigned char symbol18_227_bits[] = {
+0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xf3, 0x18, 0xb3, 0x19, 0xb3, 0x19, 0xf3, 0x18, 0xb3, 0x19, 
+0xb3, 0x19};
+static unsigned char symbol18_228_bits[] = {
+0xb3, 0x19, 0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xf8, 0x03, 0x1c, 0x07, 
+0x06, 0x0c, 0xe3, 0x18};
+static unsigned char symbol18_229_bits[] = {
+0x33, 0x09, 0x33, 0x08, 0x33, 0x08, 0x33, 0x08, 0x33, 0x09, 0xe3, 0x08, 
+0x06, 0x0c, 0x1c, 0x07, 0xf8, 0x03, 0xdf, 0x08, 0xc4, 0x08, 0xc4, 0x08, 
+0x44, 0x05, 0x44, 0x05, 0x44, 0x05, 0x44, 0x02};
+static unsigned char symbol18_230_bits[] = {
+0x04, 0x12, 0x3f, 0x07, 0x07, 0x06, 0x0e, 0x04, 0x1c, 0x00, 0x38, 0x00, 
+0x30, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x18, 0x00, 
+0x0c};
+static unsigned char symbol18_231_bits[] = {
+0x00, 0x02, 0x00, 0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_232_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_233_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x07};
+static unsigned char symbol18_234_bits[] = {
+0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_235_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_236_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_237_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x1f, 0x1c, 0x06, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_238_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07, 0x07};
+static unsigned char symbol18_239_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_240_bits[] = {
+0x00};
+static unsigned char symbol18_241_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x1c, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_242_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x03, 0x03, 0x06, 0x06};
+static unsigned char symbol18_243_bits[] = {
+0x0c, 0x0c, 0x18, 0x18, 0x10, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 
+0x03, 0x38, 0x38, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c};
+static unsigned char symbol18_244_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x00, 0x02, 
+0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_245_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_246_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 
+0x20};
+static unsigned char symbol18_247_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02, 0x01, 0x03, 
+0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00};
+static unsigned char symbol18_248_bits[] = {
+0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char symbol18_249_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x10, 0x10, 
+0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 
+0x10};
+static unsigned char symbol18_250_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x01, 0x03, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00};
+static unsigned char symbol18_251_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol18_252_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char symbol18_253_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x07, 0x0c, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18};
+static unsigned char symbol18_254_bits[] = {
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06};
+static unsigned char symbol18_255_bits[] = {
+0x00};
+static RotFont symbol18font[] = {
+{5, 1, 1, symbol18_0_bits},
+{5, 1, 1, symbol18_1_bits},
+{5, 1, 1, symbol18_2_bits},
+{5, 1, 1, symbol18_3_bits},
+{5, 1, 1, symbol18_4_bits},
+{5, 1, 1, symbol18_5_bits},
+{5, 1, 1, symbol18_6_bits},
+{5, 1, 1, symbol18_7_bits},
+{5, 1, 1, symbol18_8_bits},
+{5, 1, 1, symbol18_9_bits},
+{5, 1, 1, symbol18_10_bits},
+{5, 1, 1, symbol18_11_bits},
+{5, 1, 1, symbol18_12_bits},
+{5, 1, 1, symbol18_13_bits},
+{5, 1, 1, symbol18_14_bits},
+{5, 1, 1, symbol18_15_bits},
+{5, 1, 1, symbol18_16_bits},
+{5, 1, 1, symbol18_17_bits},
+{5, 1, 1, symbol18_18_bits},
+{5, 1, 1, symbol18_19_bits},
+{5, 1, 1, symbol18_20_bits},
+{5, 1, 1, symbol18_21_bits},
+{5, 1, 1, symbol18_22_bits},
+{5, 1, 1, symbol18_23_bits},
+{5, 1, 1, symbol18_24_bits},
+{5, 1, 1, symbol18_25_bits},
+{5, 1, 1, symbol18_26_bits},
+{5, 1, 1, symbol18_27_bits},
+{5, 1, 1, symbol18_28_bits},
+{5, 1, 1, symbol18_29_bits},
+{5, 1, 1, symbol18_30_bits},
+{5, 1, 1, symbol18_31_bits},
+{1, 1, 1, symbol18_32_bits},
+{2, 13, 13, symbol18_33_bits},
+{13, 13, 13, symbol18_34_bits},
+{10, 13, 13, symbol18_35_bits},
+{8, 13, 13, symbol18_36_bits},
+{13, 13, 13, symbol18_37_bits},
+{12, 13, 13, symbol18_38_bits},
+{6, 9, 9, symbol18_39_bits},
+{4, 17, 13, symbol18_40_bits},
+{4, 17, 13, symbol18_41_bits},
+{7, 7, 10, symbol18_42_bits},
+{8, 8, 9, symbol18_43_bits},
+{3, 5, 2, symbol18_44_bits},
+{7, 2, 6, symbol18_45_bits},
+{2, 2, 2, symbol18_46_bits},
+{5, 13, 13, symbol18_47_bits},
+{8, 13, 13, symbol18_48_bits},
+{6, 13, 13, symbol18_49_bits},
+{7, 13, 13, symbol18_50_bits},
+{7, 13, 13, symbol18_51_bits},
+{8, 13, 13, symbol18_52_bits},
+{7, 13, 13, symbol18_53_bits},
+{8, 13, 13, symbol18_54_bits},
+{8, 13, 13, symbol18_55_bits},
+{8, 13, 13, symbol18_56_bits},
+{8, 13, 13, symbol18_57_bits},
+{2, 9, 9, symbol18_58_bits},
+{3, 12, 9, symbol18_59_bits},
+{9, 9, 9, symbol18_60_bits},
+{8, 6, 8, symbol18_61_bits},
+{9, 9, 9, symbol18_62_bits},
+{6, 13, 13, symbol18_63_bits},
+{8, 9, 9, symbol18_64_bits},
+{12, 13, 13, symbol18_65_bits},
+{9, 13, 13, symbol18_66_bits},
+{12, 13, 13, symbol18_67_bits},
+{11, 13, 13, symbol18_68_bits},
+{9, 13, 13, symbol18_69_bits},
+{12, 13, 13, symbol18_70_bits},
+{10, 13, 13, symbol18_71_bits},
+{11, 13, 13, symbol18_72_bits},
+{4, 13, 13, symbol18_73_bits},
+{11, 13, 13, symbol18_74_bits},
+{11, 13, 13, symbol18_75_bits},
+{12, 13, 13, symbol18_76_bits},
+{14, 13, 13, symbol18_77_bits},
+{11, 13, 13, symbol18_78_bits},
+{11, 13, 13, symbol18_79_bits},
+{11, 13, 13, symbol18_80_bits},
+{11, 13, 13, symbol18_81_bits},
+{8, 13, 13, symbol18_82_bits},
+{10, 13, 13, symbol18_83_bits},
+{10, 13, 13, symbol18_84_bits},
+{12, 13, 13, symbol18_85_bits},
+{6, 13, 9, symbol18_86_bits},
+{13, 13, 13, symbol18_87_bits},
+{10, 13, 13, symbol18_88_bits},
+{14, 13, 13, symbol18_89_bits},
+{9, 13, 13, symbol18_90_bits},
+{4, 17, 13, symbol18_91_bits},
+{10, 9, 9, symbol18_92_bits},
+{4, 17, 13, symbol18_93_bits},
+{10, 13, 13, symbol18_94_bits},
+{9, 2, -2, symbol18_95_bits},
+{10, 1, 17, symbol18_96_bits},
+{11, 9, 9, symbol18_97_bits},
+{8, 18, 14, symbol18_98_bits},
+{10, 13, 9, symbol18_99_bits},
+{7, 14, 14, symbol18_100_bits},
+{6, 9, 9, symbol18_101_bits},
+{9, 16, 12, symbol18_102_bits},
+{8, 13, 9, symbol18_103_bits},
+{9, 13, 9, symbol18_104_bits},
+{5, 9, 9, symbol18_105_bits},
+{9, 13, 9, symbol18_106_bits},
+{9, 9, 9, symbol18_107_bits},
+{10, 14, 14, symbol18_108_bits},
+{9, 13, 9, symbol18_109_bits},
+{8, 9, 9, symbol18_110_bits},
+{8, 9, 9, symbol18_111_bits},
+{9, 9, 9, symbol18_112_bits},
+{8, 13, 13, symbol18_113_bits},
+{8, 13, 9, symbol18_114_bits},
+{10, 9, 9, symbol18_115_bits},
+{7, 9, 9, symbol18_116_bits},
+{9, 9, 9, symbol18_117_bits},
+{11, 11, 11, symbol18_118_bits},
+{10, 9, 9, symbol18_119_bits},
+{7, 19, 15, symbol18_120_bits},
+{13, 13, 9, symbol18_121_bits},
+{7, 19, 15, symbol18_122_bits},
+{7, 17, 13, symbol18_123_bits},
+{2, 17, 13, symbol18_124_bits},
+{7, 17, 13, symbol18_125_bits},
+{8, 3, 7, symbol18_126_bits},
+{5, 1, 1, symbol18_127_bits},
+{5, 1, 1, symbol18_128_bits},
+{5, 1, 1, symbol18_129_bits},
+{5, 1, 1, symbol18_130_bits},
+{5, 1, 1, symbol18_131_bits},
+{5, 1, 1, symbol18_132_bits},
+{5, 1, 1, symbol18_133_bits},
+{5, 1, 1, symbol18_134_bits},
+{5, 1, 1, symbol18_135_bits},
+{5, 1, 1, symbol18_136_bits},
+{5, 1, 1, symbol18_137_bits},
+{5, 1, 1, symbol18_138_bits},
+{5, 1, 1, symbol18_139_bits},
+{5, 1, 1, symbol18_140_bits},
+{5, 1, 1, symbol18_141_bits},
+{5, 1, 1, symbol18_142_bits},
+{5, 1, 1, symbol18_143_bits},
+{5, 1, 1, symbol18_144_bits},
+{5, 1, 1, symbol18_145_bits},
+{5, 1, 1, symbol18_146_bits},
+{5, 1, 1, symbol18_147_bits},
+{5, 1, 1, symbol18_148_bits},
+{5, 1, 1, symbol18_149_bits},
+{5, 1, 1, symbol18_150_bits},
+{5, 1, 1, symbol18_151_bits},
+{5, 1, 1, symbol18_152_bits},
+{5, 1, 1, symbol18_153_bits},
+{5, 1, 1, symbol18_154_bits},
+{5, 1, 1, symbol18_155_bits},
+{5, 1, 1, symbol18_156_bits},
+{5, 1, 1, symbol18_157_bits},
+{5, 1, 1, symbol18_158_bits},
+{5, 1, 1, symbol18_159_bits},
+{5, 1, 1, symbol18_160_bits},
+{11, 13, 13, symbol18_161_bits},
+{4, 5, 14, symbol18_162_bits},
+{9, 12, 12, symbol18_163_bits},
+{8, 13, 13, symbol18_164_bits},
+{12, 5, 8, symbol18_165_bits},
+{9, 17, 13, symbol18_166_bits},
+{10, 9, 9, symbol18_167_bits},
+{9, 9, 9, symbol18_168_bits},
+{9, 9, 9, symbol18_169_bits},
+{10, 9, 9, symbol18_170_bits},
+{17, 8, 9, symbol18_171_bits},
+{18, 8, 9, symbol18_172_bits},
+{8, 25, 18, symbol18_173_bits},
+{18, 8, 9, symbol18_174_bits},
+{8, 22, 18, symbol18_175_bits},
+{5, 6, 13, symbol18_176_bits},
+{8, 11, 11, symbol18_177_bits},
+{8, 5, 14, symbol18_178_bits},
+{9, 12, 12, symbol18_179_bits},
+{10, 9, 9, symbol18_180_bits},
+{11, 5, 8, symbol18_181_bits},
+{7, 14, 14, symbol18_182_bits},
+{5, 6, 8, symbol18_183_bits},
+{8, 8, 9, symbol18_184_bits},
+{8, 9, 9, symbol18_185_bits},
+{8, 8, 9, symbol18_186_bits},
+{8, 7, 9, symbol18_187_bits},
+{14, 2, 2, symbol18_188_bits},
+{2, 25, 18, symbol18_189_bits},
+{19, 2, 6, symbol18_190_bits},
+{9, 12, 12, symbol18_191_bits},
+{11, 13, 13, symbol18_192_bits},
+{10, 15, 14, symbol18_193_bits},
+{13, 14, 14, symbol18_194_bits},
+{12, 15, 11, symbol18_195_bits},
+{12, 13, 13, symbol18_196_bits},
+{12, 13, 13, symbol18_197_bits},
+{12, 13, 13, symbol18_198_bits},
+{12, 9, 9, symbol18_199_bits},
+{12, 9, 9, symbol18_200_bits},
+{12, 9, 9, symbol18_201_bits},
+{12, 12, 9, symbol18_202_bits},
+{12, 13, 11, symbol18_203_bits},
+{12, 9, 9, symbol18_204_bits},
+{12, 12, 9, symbol18_205_bits},
+{9, 9, 9, symbol18_206_bits},
+{10, 11, 10, symbol18_207_bits},
+{13, 13, 13, symbol18_208_bits},
+{12, 13, 13, symbol18_209_bits},
+{13, 13, 13, symbol18_210_bits},
+{13, 13, 13, symbol18_211_bits},
+{14, 8, 13, symbol18_212_bits},
+{14, 16, 14, symbol18_213_bits},
+{10, 17, 17, symbol18_214_bits},
+{2, 2, 6, symbol18_215_bits},
+{11, 6, 6, symbol18_216_bits},
+{10, 9, 9, symbol18_217_bits},
+{10, 9, 9, symbol18_218_bits},
+{18, 9, 9, symbol18_219_bits},
+{16, 9, 9, symbol18_220_bits},
+{9, 17, 17, symbol18_221_bits},
+{16, 9, 9, symbol18_222_bits},
+{9, 17, 17, symbol18_223_bits},
+{9, 14, 14, symbol18_224_bits},
+{5, 17, 14, symbol18_225_bits},
+{13, 13, 13, symbol18_226_bits},
+{13, 13, 13, symbol18_227_bits},
+{13, 8, 13, symbol18_228_bits},
+{12, 16, 14, symbol18_229_bits},
+{6, 25, 18, symbol18_230_bits},
+{2, 25, 18, symbol18_231_bits},
+{6, 25, 18, symbol18_232_bits},
+{5, 25, 18, symbol18_233_bits},
+{2, 25, 18, symbol18_234_bits},
+{5, 22, 18, symbol18_235_bits},
+{5, 25, 18, symbol18_236_bits},
+{5, 25, 18, symbol18_237_bits},
+{5, 22, 18, symbol18_238_bits},
+{2, 25, 18, symbol18_239_bits},
+{5, 1, 1, symbol18_240_bits},
+{5, 17, 14, symbol18_241_bits},
+{6, 22, 18, symbol18_242_bits},
+{7, 25, 18, symbol18_243_bits},
+{2, 25, 18, symbol18_244_bits},
+{7, 22, 18, symbol18_245_bits},
+{6, 25, 18, symbol18_246_bits},
+{2, 25, 18, symbol18_247_bits},
+{6, 25, 18, symbol18_248_bits},
+{5, 25, 18, symbol18_249_bits},
+{2, 25, 18, symbol18_250_bits},
+{5, 22, 18, symbol18_251_bits},
+{5, 25, 18, symbol18_252_bits},
+{5, 25, 18, symbol18_253_bits},
+{5, 22, 18, symbol18_254_bits},
+{5, 1, 1, symbol18_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol24.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol24.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol24.bdf	(revision 16632)
@@ -0,0 +1,4576 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--24-240-75-75-P-142-Adobe-FontSpecific
+SIZE 24 75 75
+FONTBOUNDINGBOX 26 32 -1 -8
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 240
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 142
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 17
+X_HEIGHT 13
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--24-240-75-75-P-142-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 15
+DEFAULT_CHAR 32
+FONT_ASCENT 20
+FONT_DESCENT 5
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 17 2 0
+BITMAP
+40
+e0
+e0
+e0
+e0
+e0
+e0
+e0
+40
+40
+40
+40
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+c006
+c006
+600c
+600c
+3ff8
+3ff8
+3018
+1830
+1830
+0c60
+0c60
+0c60
+06c0
+06c0
+0380
+0380
+0380
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0880
+0880
+0880
+0880
+0880
+0880
+7fe0
+1100
+1100
+1100
+ffc0
+2200
+2200
+2200
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+ffe0
+ffe0
+0060
+0060
+0060
+0060
+0060
+ffe0
+ffe0
+0060
+0060
+0060
+0060
+0060
+0060
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 17 1 0
+BITMAP
+1f0600
+39fe00
+710c00
+611800
+e31800
+c23000
+c66000
+cc6000
+78c780
+018ec0
+019c40
+033840
+0630c0
+063080
+0c3180
+183300
+181e00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+0780
+0cc0
+1840
+1840
+18c0
+1d80
+0f3e
+1e1c
+3e18
+6730
+c3a0
+c1e0
+c0c0
+c1e0
+e372
+7e3e
+3c1c
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 13 2 0
+BITMAP
+f0
+3c
+0e
+07
+03
+03
+7f
+03
+03
+07
+0e
+3c
+f0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+0c
+18
+30
+20
+60
+60
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+60
+60
+20
+30
+18
+0c
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+c0
+60
+30
+10
+18
+18
+08
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+08
+18
+18
+10
+30
+60
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 10 2 7
+BITMAP
+18
+18
+c3
+e7
+18
+18
+e7
+c3
+18
+18
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 10 1 2
+BITMAP
+0c00
+0c00
+0c00
+0c00
+ffc0
+ffc0
+0c00
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 3 6 1 -4
+BITMAP
+60
+60
+20
+60
+c0
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 2 1 6
+BITMAP
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 0
+BITMAP
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 17 0 0
+BITMAP
+06
+06
+06
+0c
+0c
+0c
+18
+18
+30
+30
+30
+60
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+6180
+3300
+1e00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 6 17 3 0
+BITMAP
+30
+70
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1c00
+7f00
+6700
+8380
+8180
+0180
+0180
+0380
+0300
+0700
+0c00
+0c00
+1800
+3000
+6040
+ffc0
+ff80
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 17 1 0
+BITMAP
+1c00
+7e00
+4700
+8300
+8300
+0600
+0c00
+1e00
+0700
+0300
+0180
+0180
+0180
+0300
+c700
+fe00
+7800
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0300
+0700
+0700
+0f00
+0b00
+1b00
+1300
+3300
+2300
+6300
+4300
+ffc0
+ffc0
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 17 1 0
+BITMAP
+3f80
+3f00
+6000
+4000
+c000
+f000
+fc00
+1e00
+0700
+0380
+0180
+0180
+0180
+0180
+c300
+fe00
+7c00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+03c0
+0e00
+3800
+7000
+6000
+e000
+cf00
+f380
+e180
+c0c0
+c0c0
+c0c0
+c0c0
+e0c0
+61c0
+7380
+1f00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+7fc0
+ffc0
+c0c0
+8180
+0180
+0300
+0300
+0300
+0600
+0600
+0600
+0c00
+0c00
+0c00
+1800
+1800
+1800
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+6180
+7300
+3e00
+1c00
+3f00
+6380
+c1c0
+c0c0
+c0c0
+c0c0
+c1c0
+6380
+3e00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+61c0
+73c0
+1ec0
+0180
+0380
+0700
+0e00
+3c00
+f000
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 11 2 0
+BITMAP
+c0
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 3 15 1 -4
+BITMAP
+60
+60
+60
+00
+00
+00
+00
+00
+00
+60
+60
+20
+60
+c0
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 12 0 1
+BITMAP
+0070
+01e0
+0780
+1e00
+7800
+e000
+e000
+7800
+1e00
+0780
+01e0
+0070
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 6 1 4
+BITMAP
+ffc0
+ffc0
+0000
+0000
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 12 12 0 1
+BITMAP
+e000
+7800
+1e00
+0780
+01e0
+0070
+0070
+01e0
+0780
+1e00
+7800
+e000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 17 2 0
+BITMAP
+7c
+c6
+83
+c3
+c7
+06
+0e
+0c
+18
+18
+10
+10
+10
+00
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 1
+BITMAP
+3820
+7c60
+c7c0
+8380
+0000
+0000
+ffe0
+ffe0
+0000
+0000
+ffe0
+ffe0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 17 0 0
+BITMAP
+008000
+01c000
+01c000
+014000
+036000
+026000
+023000
+063000
+043000
+0c1800
+081800
+0ffc00
+180c00
+100c00
+300600
+300600
+f80f80
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+ffc0
+30e0
+3070
+3030
+3030
+3030
+3030
+3060
+3fc0
+3070
+3038
+3018
+3018
+3018
+3038
+3070
+ffc0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 17 1 0
+BITMAP
+f81f80
+700e00
+380c00
+1c1800
+0c3000
+066000
+07c000
+038000
+018000
+03c000
+06e000
+0c7000
+083800
+181800
+301c00
+700e00
+f81f80
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 16 17 0 0
+BITMAP
+0300
+0300
+0780
+0480
+04c0
+0cc0
+0860
+0860
+1830
+1030
+3018
+2018
+200c
+600c
+4006
+c006
+ffff
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff0
+3030
+3010
+3000
+3000
+3000
+3020
+3020
+3fe0
+3020
+3020
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 16 17 1 0
+BITMAP
+07e0
+0180
+0180
+0ff0
+399c
+6186
+e187
+c183
+c183
+c183
+e187
+6186
+399c
+0ff0
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff8
+3018
+3008
+3008
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+fc3f
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+3ffc
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+fc3f
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 17 1 0
+BITMAP
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+03c0
+06e0
+0460
+0660
+0330
+71b0
+f8f0
+983c
+1830
+1830
+3030
+3030
+3030
+3060
+3860
+1cc0
+0f80
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+fc7c
+3030
+3060
+30c0
+3180
+3300
+3600
+3e00
+3f00
+3380
+3180
+31c0
+30e0
+3070
+3038
+301c
+fc3e
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+0300
+0300
+0780
+0480
+04c0
+04c0
+0cc0
+0860
+0860
+1860
+1030
+1030
+3030
+2018
+2018
+601c
+f83e
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 20 17 1 0
+BITMAP
+f001f0
+3801c0
+3803c0
+3c02c0
+2c02c0
+2e06c0
+2604c0
+270cc0
+2308c0
+2388c0
+2198c0
+21d0c0
+20d0c0
+20f0c0
+2060c0
+2060c0
+f803f0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+f01f
+3804
+3804
+2c04
+2e04
+2604
+2304
+2304
+2184
+21c4
+20c4
+2064
+2064
+2034
+203c
+201c
+f80c
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+300c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+300c
+1c38
+07e0
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+ffff
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+300c
+fc3f
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+300c
+6006
+6006
+c813
+c813
+cff3
+cff3
+c813
+c813
+c003
+4002
+6006
+300c
+1c38
+07e0
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+ff80
+30e0
+3060
+3030
+3030
+3030
+3060
+30e0
+3f80
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+fff0
+e030
+7010
+3800
+1c00
+0e00
+0700
+0380
+0300
+0600
+0c00
+1800
+3010
+6010
+c030
+fff0
+fff0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+fffc
+c30c
+8304
+8304
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0fc0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 16 17 0 0
+BITMAP
+f81f
+700e
+300c
+1818
+1c10
+0c30
+0e60
+0660
+03c0
+03c0
+0180
+0180
+0180
+0180
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 18 1 -5
+BITMAP
+1f80
+3f80
+6000
+6000
+c000
+c000
+c000
+c000
+c000
+c000
+6000
+7f00
+1f80
+0080
+0080
+0180
+0f00
+0e00
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+300c
+6006
+6006
+c003
+c003
+c003
+c003
+e007
+6006
+300c
+1818
+8c31
+8421
+fc3f
+fc3f
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+7ff8
+7ff8
+6018
+4008
+0000
+1020
+1020
+1fe0
+1fe0
+1020
+1020
+0000
+8004
+8004
+c00c
+fffc
+fffc
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 17 1 0
+BITMAP
+e3f1c0
+70c380
+30c300
+30c300
+38c700
+38c700
+18c600
+1cce00
+07f800
+00c000
+00c000
+00c000
+00c000
+00c000
+00c000
+00c000
+03f000
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 17 1 0
+BITMAP
+fff0
+c070
+8060
+00e0
+01c0
+0180
+0380
+0700
+0600
+0e00
+1c00
+3800
+3800
+7000
+6010
+e030
+fff0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 22 2 -5
+BITMAP
+f8
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f8
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 12 10 3 0
+BITMAP
+0600
+0600
+0600
+0000
+0000
+0000
+0000
+c030
+c030
+c030
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 22 1 -5
+BITMAP
+f8
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+f8
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+fffc
+fffc
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 2 0 -5
+BITMAP
+fff8
+fff8
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 2 0 21
+BITMAP
+fff8
+fff8
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+1f18
+71b8
+60b0
+e0f0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60e4
+71fc
+1f38
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 24 1 -5
+BITMAP
+3e00
+6700
+c380
+c180
+c180
+c380
+c300
+ce00
+cf00
+c380
+c180
+c1c0
+c0c0
+c0c0
+c0c0
+c1c0
+e180
+f380
+df00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 1 -5
+BITMAP
+7060
+f860
+d8c0
+88c0
+0980
+0980
+0b00
+0700
+0600
+0600
+0e00
+0e00
+1900
+1900
+3110
+31b0
+61f0
+60e0
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 18 1 0
+BITMAP
+1f00
+3380
+2180
+3000
+3800
+1c00
+0e00
+3f00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+3e00
+7300
+e300
+c300
+e000
+6000
+3c00
+6000
+e000
+c000
+e080
+7180
+3f00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 22 1 -5
+BITMAP
+0600
+0600
+0600
+0600
+1f80
+36c0
+6660
+e670
+c630
+c630
+c630
+c630
+c630
+e670
+6660
+36c0
+1f80
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 18 0 -5
+BITMAP
+7060
+f860
+9860
+98c0
+18c0
+0cc0
+0d80
+0d80
+0580
+0700
+0700
+0300
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 12 18 1 -5
+BITMAP
+71c0
+fbe0
+9e30
+1c30
+1830
+1830
+1830
+1830
+1830
+1830
+1830
+1830
+1830
+0030
+0030
+0030
+0030
+0030
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 13 1 0
+BITMAP
+30
+70
+f0
+30
+30
+30
+30
+30
+30
+30
+32
+3e
+1c
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 1 -5
+BITMAP
+3380
+73c0
+6660
+c670
+c630
+c630
+c630
+c630
+c630
+e670
+6660
+36c0
+1f80
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+3070
+70f0
+f1b0
+3300
+3600
+3c00
+3c00
+3e00
+3700
+3380
+31c0
+30e0
+31f0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 19 1 0
+BITMAP
+7000
+f800
+8800
+0800
+0800
+0c00
+0c00
+0c00
+1c00
+1e00
+1a00
+3200
+3200
+3300
+6100
+6100
+6190
+c1f0
+c0e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 18 2 -5
+BITMAP
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+c180
+e390
+fff0
+de60
+c000
+c000
+e000
+e000
+e000
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+c0e0
+c0e0
+c060
+6040
+60c0
+6080
+3180
+3100
+3300
+1a00
+1a00
+0e00
+0c00
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+1f00
+71c0
+60c0
+e0e0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60c0
+71c0
+1f00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+7ff8
+fff8
+98c0
+18c0
+18c0
+18c0
+18c0
+18c0
+18c0
+18c0
+18c8
+38f8
+30f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+ffc0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+6180
+3300
+1e00
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 18 1 -5
+BITMAP
+3e00
+6380
+c180
+c1c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c1c0
+c180
+e380
+de00
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 14 13 1 0
+BITMAP
+1ffc
+71fc
+60c0
+e0e0
+c060
+c060
+c060
+c060
+c060
+e0e0
+60c0
+71c0
+1f00
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 10 13 0 0
+BITMAP
+3fc0
+7fc0
+cc00
+8c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c80
+0f80
+0700
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 13 0 0
+BITMAP
+30e0
+7830
+d818
+9818
+1818
+1818
+1818
+1818
+1818
+1830
+0c30
+0ee0
+07c0
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 14 1 0
+BITMAP
+7fff
+ffff
+9818
+300c
+318c
+6186
+6186
+6186
+6186
+6186
+6186
+318c
+3bdc
+1e78
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+1860
+3030
+6018
+6318
+c30c
+c30c
+c30c
+c30c
+c30c
+c30c
+6318
+77b8
+3cf0
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 24 1 -5
+BITMAP
+3000
+6380
+6780
+3f00
+3000
+2000
+3780
+1f80
+3000
+6000
+c000
+8000
+8000
+8000
+c000
+f000
+7c00
+3f80
+0fc0
+00c0
+0040
+00c0
+0f80
+0f00
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 18 1 -5
+BITMAP
+c183
+718e
+318c
+399c
+399c
+399c
+399c
+399c
+399c
+1998
+1998
+0db0
+07e0
+0180
+0180
+0180
+0180
+0180
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 24 1 -5
+BITMAP
+3000
+6380
+6780
+3f00
+1800
+3000
+2000
+6000
+4000
+c000
+8000
+8000
+8000
+8000
+c000
+f000
+7c00
+3f80
+0fc0
+00c0
+0040
+00c0
+0f80
+0f00
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+07
+0c
+18
+18
+18
+18
+18
+10
+30
+20
+c0
+20
+30
+10
+18
+18
+18
+18
+18
+18
+0c
+07
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 160 0
+DWIDTH 4 0
+BBX 2 22 1 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+08
+0c
+04
+03
+04
+0c
+08
+18
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 4 1 5
+BITMAP
+3820
+7c60
+c7c0
+8380
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 6 1 12
+BITMAP
+e0
+70
+70
+d8
+38
+b8
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 15 0 0
+BITMAP
+1b30
+0e00
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+1f80
+1830
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 160 0
+DWIDTH 4 0
+BBX 8 17 -1 0
+BITMAP
+70
+60
+c0
+80
+00
+70
+01
+e0
+07
+80
+1e
+00
+78
+00
+e0
+00
+e0
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 7 1 4
+BITMAP
+0078
+001e
+0002
+c000
+f000
+3000
+00fe
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 22 0 -5
+BITMAP
+f0f8
+f000
+0300
+0608
+0c18
+1818
+3030
+6060
+60c0
+c0c0
+3838
+7e78
+c7c0
+c380
+c6c0
+7c78
+3838
+00f0
+0198
+0198
+0300
+0300
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 13 2 0
+BITMAP
+0300
+1fe0
+0300
+0300
+0300
+0600
+0600
+0600
+0600
+0600
+0600
+0c00
+0c00
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 10 13 4 0
+BITMAP
+cc00
+cc00
+d800
+7000
+0780
+0fc0
+0fc0
+0fc0
+0fc0
+7780
+fb40
+ffc0
+ffc0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 12 13 3 0
+BITMAP
+fb70
+7330
+0300
+0780
+0c00
+0c00
+1e00
+3f00
+3f00
+7f80
+ffc0
+7f80
+3f00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 12 13 3 0
+BITMAP
+3f00
+1e00
+0c00
+0c00
+70e0
+f9f0
+f9f0
+fff0
+fff0
+fff0
+7fe0
+7fe0
+3fc0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 1040 0
+DWIDTH 26 0
+BBX 24 12 1 1
+BITMAP
+1f800f
+000f00
+060006
+000600
+0f001f
+803fc0
+7fe07f
+e0fff0
+fff0f6
+f06660
+06000f
+000600
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 25 12 0 1
+BITMAP
+600c0000
+18001800
+000c6000
+06ffff80
+ffffff00
+00063000
+0c180000
+0c003000
+00600600
+00000c00
+00001800
+00003000
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 31 1 -8
+BITMAP
+0000
+6000
+0000
+fff0
+ff80
+fff0
+ff80
+6000
+0000
+3000
+0000
+1800
+0000
+0c00
+0000
+0600
+0000
+0600
+0f00
+1f80
+36c0
+6660
+c630
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 25 12 0 1
+BITMAP
+06000600
+06000600
+06000600
+06000600
+06000600
+06000600
+06000600
+06000600
+06000000
+30000000
+18000000
+0c000000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 29 1 -5
+BITMAP
+0600
+0000
+0300
+fff0
+ff80
+fff0
+ff80
+0000
+0300
+0000
+0600
+0000
+0c00
+0000
+1800
+0000
+3000
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 7 1 10
+BITMAP
+06
+00
+06
+00
+06
+00
+06
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+00c0
+3040
+6000
+c000
+8000
+0000
+0000
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 6 1 12
+BITMAP
+6c80
+8280
+6c00
+0c00
+0c00
+0c00
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 15 0 0
+BITMAP
+0c00
+ffc0
+ffc0
+0c00
+0c00
+0c00
+0c00
+0000
+0000
+ffc0
+ffc0
+1980
+3b80
+7700
+6600
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 10 1 2
+BITMAP
+cc00
+8800
+e000
+7800
+1e00
+0780
+01e0
+0060
+0060
+01e0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 7 1 4
+BITMAP
+0780
+3e00
+f000
+c000
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 19 1 0
+BITMAP
+c040
+60c0
+3180
+1b00
+0e00
+0e00
+1b00
+3180
+60c0
+c040
+3800
+7c40
+c6c0
+c380
+c7c0
+7c40
+3800
+3e00
+6300
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 8 2 3
+BITMAP
+c1
+80
+01
+80
+00
+c0
+00
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 8 1 3
+BITMAP
+00c0
+00c0
+1ec0
+73c0
+61c0
+c0c0
+c0c0
+c180
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 13 2 0
+BITMAP
+c180
+c180
+c300
+6700
+3c00
+3c40
+ffc0
+ffc0
+7e00
+0c00
+0c00
+0000
+ffc0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 8 1 3
+BITMAP
+ffc0
+0000
+0c00
+0c00
+0180
+0180
+0300
+0300
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 8 1 3
+BITMAP
+ffc0
+ffc0
+0c00
+ffc0
+ffc0
+3000
+3000
+6000
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 960 0
+DWIDTH 24 0
+BBX 18 3 3 0
+BITMAP
+6000c0
+e0ffc0
+0000c0
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 2 32 6 -8
+BITMAP
+c0
+c0
+c0
+00
+00
+c0
+c0
+c0
+c0
+00
+00
+40
+40
+c0
+c0
+80
+80
+00
+00
+40
+40
+c0
+c0
+80
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 25 2 0 6
+BITMAP
+c0c0c080
+c0c0c080
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 16 1 0
+BITMAP
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+fffc
+ff80
+fffc
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 16 1 0
+BITMAP
+ff80
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+2000
+6000
+fff0
+fff0
+6000
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 19 1 -1
+BITMAP
+2000
+8180
+c300
+e3f0
+71f0
+3860
+1cc0
+3c80
+6e80
+c780
+c380
+e380
+f1c0
+70e0
+3070
+7030
+e010
+0f80
+3ffc
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 18 1 0
+BITMAP
+70f800
+304000
+40c000
+c03080
+1c7000
+380000
+001c00
+1c0000
+300c00
+0cde00
+0ff000
+c01e00
+003f00
+006380
+00c180
+008180
+00c180
+00e180
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 15 20 2 -5
+BITMAP
+0070
+b800
+39b0
+0018
+9800
+1198
+0000
+9800
+019c
+0000
+8c00
+018c
+0018
+8680
+3f06
+804e
+0700
+0600
+0c00
+183c
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+30fe
+3186
+6306
+6606
+6c06
+680c
+799c
+7398
+7230
+7a70
+5be0
+dd80
+8c00
+8c00
+8c00
+d800
+7000
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1e78
+381c
+6006
+6816
+cc33
+c663
+c3c3
+c183
+c3c3
+c663
+cc33
+6816
+6006
+381c
+1e78
+07e0
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 17 1 0
+BITMAP
+07e000
+783800
+618640
+86c180
+c183c0
+fbdfc0
+c183c0
+83c180
+618640
+063800
+1e7800
+e003c0
+c00fc0
+801c00
+003000
+003000
+006000
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 13 1 0
+BITMAP
+8060
+3180
+6061
+8060
+c180
+6181
+8063
+0180
+6601
+803c
+0300
+3803
+003c
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 13 1 0
+BITMAP
+0e00
+6ffc
+00c3
+f000
+07e0
+1ff8
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 12 1 0
+BITMAP
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+c002
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 15 1 -3
+BITMAP
+6006
+6006
+381c
+1ff8
+07e0
+ffe0
+fff8
+001c
+000c
+0006
+0006
+0006
+0006
+000c
+001c
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 16 1 -2
+BITMAP
+fff8
+ffe0
+ffe0
+fff8
+001c
+000c
+0006
+0006
+0006
+0006
+000c
+001c
+fff8
+ffe0
+0000
+fffe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 12 1 0
+BITMAP
+fffe
+000c
+000c
+0ffe
+3ffe
+7030
+6030
+c060
+c060
+c0c0
+c0c0
+6180
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 15 1 -3
+BITMAP
+7180
+3ffe
+0ffe
+0600
+0600
+0ffe
+3ffe
+7000
+6000
+c000
+c000
+c000
+c000
+6000
+7000
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 13 2 0
+BITMAP
+3ff0
+0ff0
+0ff0
+3ff0
+7000
+6000
+c000
+c000
+c000
+c000
+6000
+7000
+3ff0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 12 17 2 -2
+BITMAP
+0ff0
+0000
+fff0
+fff0
+1ff0
+7ff0
+6000
+c000
+c000
+fff0
+fff0
+c000
+c000
+c000
+6000
+7ff0
+1ff0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 16 1 0
+BITMAP
+00c000
+c01f80
+7ff000
+80c180
+c30080
+f0ff80
+c60080
+00cc00
+6c0000
+f01f80
+180000
+000000
+800000
+000000
+000000
+000000
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 18 1 0
+BITMAP
+0000
+3000
+0060
+0000
+c000
+0180
+0003
+0000
+0600
+000c
+0000
+1800
+0030
+0000
+7fff
+80ff
+ff80
+ffff
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+c003
+c002
+6006
+6004
+300c
+3008
+3018
+1810
+1830
+0c20
+0c20
+0660
+0640
+03c0
+03c0
+0180
+0180
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1e78
+381c
+6006
+6fe6
+c673
+c633
+c673
+c7e3
+c6c3
+c663
+c633
+6f3e
+6006
+381c
+1e78
+07e0
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 20 10 1 7
+BITMAP
+07e010
+783810
+600660
+c6c660
+cc23c0
+03cc00
+cc03c0
+23c660
+63c660
+063810
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 21 1 -3
+BITMAP
+1e7800
+e0ff80
+709900
+601800
+e01800
+e01800
+601800
+601800
+601800
+601800
+603c80
+f0ff80
+803000
+003000
+003000
+003000
+003000
+003000
+003000
+003000
+003000
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 23 0 0
+BITMAP
+0030
+0600
+3004
+0030
+0600
+3004
+0030
+0600
+3004
+0030
+0600
+3004
+0030
+0600
+3004
+00fc
+1f80
+0004
+0004
+0004
+000c
+000c
+0008
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 3 2 6
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 8 1 0
+BITMAP
+0800
+1830
+1870
+10d8
+1018
+100c
+300c
+3006
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 12 1 0
+BITMAP
+2000
+2000
+2000
+6000
+c000
+c000
+c000
+c0c0
+c0c0
+fff8
+fff8
+0000
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 12 1 0
+BITMAP
+0000
+0000
+0000
+0000
+0000
+0700
+0700
+0d80
+0d80
+18c0
+18c0
+3060
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 23 12 1 0
+BITMAP
+306060
+306030
+c018c0
+18c018
+c01860
+306030
+306030
+6018c0
+18c00c
+800d80
+070006
+000600
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 23 12 1 0
+BITMAP
+c00c00
+601800
+303ffe
+f87ffe
+fce000
+0ee000
+0e7ffe
+fc3ffe
+f81800
+300c00
+600600
+c00600
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 23 1 0
+BITMAP
+0000
+0000
+1800
+0030
+fff0
+7ff0
+fee0
+0000
+e000
+0070
+fff0
+3ff0
+fe10
+0000
+0c00
+0000
+0000
+0600
+0f00
+1f80
+39c0
+79e0
+d9b0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 1000 0
+DWIDTH 25 0
+BBX 23 12 1 0
+BITMAP
+198018
+801980
+198018
+801980
+198018
+801980
+198018
+801980
+198018
+801980
+198018
+800000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 23 1 0
+BITMAP
+c000
+0060
+0000
+30f0
+fff0
+fff0
+fc00
+0000
+0000
+0ef0
+fff0
+fff0
+f800
+0030
+0000
+6000
+00c0
+1980
+1980
+1980
+1980
+1980
+1980
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 18 1 0
+BITMAP
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+1980
+d980
+79c0
+39c0
+1f80
+0f00
+0600
+0c00
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 22 0 -5
+BITMAP
+0c
+00
+1e
+00
+32
+00
+32
+00
+60
+80
+60
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+80
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+6180
+3300
+3300
+1e00
+0c00
+0c00
+0606
+0c0c
+1818
+3030
+6060
+c0c0
+6060
+3030
+1818
+0c0c
+0606
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1e78
+381c
+6006
+67e6
+c633
+c633
+c633
+c7e3
+c663
+c633
+c633
+6632
+6006
+381c
+1e78
+07e0
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 10 1 7
+BITMAP
+07e000
+783800
+600640
+c6c7c0
+ce63c0
+03cc00
+cc03c0
+63c7c0
+63c640
+063800
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 14 20 2 -2
+BITMAP
+1e78
+07e0
+fec0
+c018
+c0c0
+18e0
+c018
+e1c0
+18f0
+c018
+d2c0
+18dc
+c018
+ccc0
+18cc
+c018
+ccc0
+fff8
+e018
+7008
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 31 1 -8
+BITMAP
+3800
+1c00
+0e00
+0700
+0380
+0180
+0080
+0180
+0300
+0600
+0c00
+1800
+3000
+6000
+c000
+ff80
+ff80
+0180
+0300
+0600
+0c00
+1800
+1800
+3000
+3000
+6000
+6000
+6000
+6000
+c000
+c000
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 1 -8
+BITMAP
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 32 1 -8
+BITMAP
+c000
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 31 1 -8
+BITMAP
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+c0
+00
+60
+00
+60
+00
+60
+00
+60
+00
+30
+00
+30
+00
+18
+00
+18
+00
+0c
+00
+06
+00
+02
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 1 -8
+BITMAP
+00
+00
+80
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 29 1 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 31 5 -8
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 5 32 2 -8
+BITMAP
+c0
+c0
+f8
+18
+30
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 29 5 -5
+BITMAP
+c0
+c0
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+10
+30
+60
+c0
+60
+30
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 2 32 5 -8
+BITMAP
+00
+00
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 22 1 -5
+BITMAP
+30
+1e
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 8 28 0 -5
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+c0
+c0
+60
+60
+30
+30
+18
+18
+0c
+0c
+06
+06
+0c
+0c
+18
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 8 31 8 -8
+BITMAP
+18
+30
+30
+60
+60
+c0
+c0
+07
+0f
+1b
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 2 32 2 -8
+BITMAP
+00
+c0
+c0
+c0
+00
+00
+00
+00
+40
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 8 26 2 -2
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 31 0 -8
+BITMAP
+c080
+c080
+c080
+c080
+c000
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0200
+cc80
+7080
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+0000
+8000
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 7 -8
+BITMAP
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 9 32 0 -8
+BITMAP
+8000
+8080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c080
+c000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+8000
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 31 2 -8
+BITMAP
+80
+00
+80
+00
+80
+00
+80
+00
+80
+00
+80
+02
+00
+02
+00
+02
+00
+02
+00
+06
+00
+06
+00
+0c
+00
+0c
+00
+18
+00
+30
+00
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 2 32 7 -8
+BITMAP
+40
+00
+c0
+00
+c0
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 7 29 2 -5
+BITMAP
+06
+06
+06
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 31 0 -8
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+06
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 5 32 5 -8
+BITMAP
+00
+00
+00
+f8
+f0
+18
+08
+08
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 7 29 0 -5
+BITMAP
+06
+06
+06
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+60
+30
+18
+30
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol24.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol24.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol24.h	(revision 16632)
@@ -0,0 +1,1127 @@
+static unsigned char symbol24_0_bits[] = {
+0x00};
+static unsigned char symbol24_1_bits[] = {
+0x00};
+static unsigned char symbol24_2_bits[] = {
+0x00};
+static unsigned char symbol24_3_bits[] = {
+0x00};
+static unsigned char symbol24_4_bits[] = {
+0x00};
+static unsigned char symbol24_5_bits[] = {
+0x00};
+static unsigned char symbol24_6_bits[] = {
+0x00};
+static unsigned char symbol24_7_bits[] = {
+0x00};
+static unsigned char symbol24_8_bits[] = {
+0x00};
+static unsigned char symbol24_9_bits[] = {
+0x00};
+static unsigned char symbol24_10_bits[] = {
+0x00};
+static unsigned char symbol24_11_bits[] = {
+0x00};
+static unsigned char symbol24_12_bits[] = {
+0x00};
+static unsigned char symbol24_13_bits[] = {
+0x00};
+static unsigned char symbol24_14_bits[] = {
+0x00};
+static unsigned char symbol24_15_bits[] = {
+0x00};
+static unsigned char symbol24_16_bits[] = {
+0x00};
+static unsigned char symbol24_17_bits[] = {
+0x00};
+static unsigned char symbol24_18_bits[] = {
+0x00};
+static unsigned char symbol24_19_bits[] = {
+0x00};
+static unsigned char symbol24_20_bits[] = {
+0x00};
+static unsigned char symbol24_21_bits[] = {
+0x00};
+static unsigned char symbol24_22_bits[] = {
+0x00};
+static unsigned char symbol24_23_bits[] = {
+0x00};
+static unsigned char symbol24_24_bits[] = {
+0x00};
+static unsigned char symbol24_25_bits[] = {
+0x00};
+static unsigned char symbol24_26_bits[] = {
+0x00};
+static unsigned char symbol24_27_bits[] = {
+0x00};
+static unsigned char symbol24_28_bits[] = {
+0x00};
+static unsigned char symbol24_29_bits[] = {
+0x00};
+static unsigned char symbol24_30_bits[] = {
+0x00};
+static unsigned char symbol24_31_bits[] = {
+0x00};
+static unsigned char symbol24_32_bits[] = {
+0x00};
+static unsigned char symbol24_33_bits[] = {
+0x02, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x02, 0x02, 0x02, 0x02, 
+0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char symbol24_34_bits[] = {
+0x03, 0x60, 0x03, 0x60, 0x06, 0x30, 0x06, 0x30, 0xfc, 0x1f, 0xfc, 0x1f, 
+0x0c, 0x18, 0x18, 0x0c, 0x18, 0x0c, 0x30, 0x06, 0x30, 0x06, 0x30, 0x06, 
+0x60, 0x03, 0x60, 0x03, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01};
+static unsigned char symbol24_35_bits[] = {
+0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 
+0xfe, 0x07, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xff, 0x03, 0x44, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char symbol24_36_bits[] = {
+0xff, 0x07, 0xff, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06, 0xff, 0x07, 0xff, 0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 
+0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0xff, 0x07, 0xff, 0x07};
+static unsigned char symbol24_37_bits[] = {
+0xf8, 0x60, 0x00, 0x9c, 0x7f, 0x00, 0x8e, 0x30, 0x00, 0x86, 0x18, 0x00, 
+0xc7, 0x18, 0x00, 0x43, 0x0c, 0x00, 0x63, 0x06, 0x00, 0x33, 0x06, 0x00, 
+0x1e, 0xe3, 0x01, 0x80, 0x71, 0x03, 0x80, 0x39, 0x02, 0xc0, 0x1c, 0x02, 
+0x60, 0x0c, 0x03, 0x60, 0x0c, 0x01, 0x30, 0x8c, 0x01, 0x18, 0xcc, 0x00, 
+0x18, 0x78, 0x00};
+static unsigned char symbol24_38_bits[] = {
+0xe0, 0x01, 0x30, 0x03, 0x18, 0x02, 0x18, 0x02, 0x18, 0x03, 0xb8, 0x01, 
+0xf0, 0x7c, 0x78, 0x38, 0x7c, 0x18, 0xe6, 0x0c, 0xc3, 0x05, 0x83, 0x07, 
+0x03, 0x03, 0x83, 0x07, 0xc7, 0x4e, 0x7e, 0x7c, 0x3c, 0x38};
+static unsigned char symbol24_39_bits[] = {
+0x0f, 0x3c, 0x70, 0xe0, 0xc0, 0xc0, 0xfe, 0xc0, 0xc0, 0xe0, 0x70, 0x3c, 
+0x0f};
+static unsigned char symbol24_40_bits[] = {
+0x30, 0x18, 0x0c, 0x04, 0x06, 0x06, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x02, 0x06, 0x06, 0x04, 0x0c, 0x18, 0x30};
+static unsigned char symbol24_41_bits[] = {
+0x03, 0x06, 0x0c, 0x08, 0x18, 0x18, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x30, 0x10, 0x18, 0x18, 0x08, 0x0c, 0x06, 0x03};
+static unsigned char symbol24_42_bits[] = {
+0x18, 0x18, 0xc3, 0xe7, 0x18, 0x18, 0xe7, 0xc3, 0x18, 0x18};
+static unsigned char symbol24_43_bits[] = {
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0xff, 0x03, 0xff, 0x03, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00};
+static unsigned char symbol24_44_bits[] = {
+0x06, 0x06, 0x04, 0x06, 0x03, 0x01};
+static unsigned char symbol24_45_bits[] = {
+0xff, 0x07, 0xff, 0x07};
+static unsigned char symbol24_46_bits[] = {
+0x03, 0x03, 0x03};
+static unsigned char symbol24_47_bits[] = {
+0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 
+0x06, 0x06, 0x03, 0x03, 0x03};
+static unsigned char symbol24_48_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00};
+static unsigned char symbol24_49_bits[] = {
+0x0c, 0x0e, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char symbol24_50_bits[] = {
+0x38, 0x00, 0xfe, 0x00, 0xe6, 0x00, 0xc1, 0x01, 0x81, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0xe0, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x18, 0x00, 0x0c, 0x00, 0x06, 0x02, 0xff, 0x03, 0xff, 0x01};
+static unsigned char symbol24_51_bits[] = {
+0x38, 0x00, 0x7e, 0x00, 0xe2, 0x00, 0xc1, 0x00, 0xc1, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x78, 0x00, 0xe0, 0x00, 0xc0, 0x00, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0xc0, 0x00, 0xe3, 0x00, 0x7f, 0x00, 0x1e, 0x00};
+static unsigned char symbol24_52_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd8, 0x00, 
+0xc8, 0x00, 0xcc, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xc2, 0x00, 0xff, 0x03, 
+0xff, 0x03, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char symbol24_53_bits[] = {
+0xfc, 0x01, 0xfc, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x0f, 0x00, 
+0x3f, 0x00, 0x78, 0x00, 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0xc3, 0x00, 0x7f, 0x00, 0x3e, 0x00};
+static unsigned char symbol24_54_bits[] = {
+0xc0, 0x03, 0x70, 0x00, 0x1c, 0x00, 0x0e, 0x00, 0x06, 0x00, 0x07, 0x00, 
+0xf3, 0x00, 0xcf, 0x01, 0x87, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x07, 0x03, 0x86, 0x03, 0xce, 0x01, 0xf8, 0x00};
+static unsigned char symbol24_55_bits[] = {
+0xfe, 0x03, 0xff, 0x03, 0x03, 0x03, 0x81, 0x01, 0x80, 0x01, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00};
+static unsigned char symbol24_56_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xce, 0x00, 
+0x7c, 0x00, 0x38, 0x00, 0xfc, 0x00, 0xc6, 0x01, 0x83, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0xc6, 0x01, 0x7c, 0x00};
+static unsigned char symbol24_57_bits[] = {
+0x78, 0x00, 0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x03, 0xce, 0x03, 0x78, 0x03, 0x80, 0x01, 
+0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x3c, 0x00, 0x0f, 0x00};
+static unsigned char symbol24_58_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03};
+static unsigned char symbol24_59_bits[] = {
+0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 
+0x06, 0x03, 0x01};
+static unsigned char symbol24_60_bits[] = {
+0x00, 0x0e, 0x80, 0x07, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0x07, 0x00, 
+0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x0e};
+static unsigned char symbol24_61_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03};
+static unsigned char symbol24_62_bits[] = {
+0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 0x80, 0x07, 0x00, 0x0e, 
+0x00, 0x0e, 0x80, 0x07, 0xe0, 0x01, 0x78, 0x00, 0x1e, 0x00, 0x07, 0x00};
+static unsigned char symbol24_63_bits[] = {
+0x3e, 0x63, 0xc1, 0xc3, 0xe3, 0x60, 0x70, 0x30, 0x18, 0x18, 0x08, 0x08, 
+0x08, 0x00, 0x00, 0x0c, 0x0c};
+static unsigned char symbol24_64_bits[] = {
+0x1c, 0x04, 0x3e, 0x06, 0xe3, 0x03, 0xc1, 0x01, 0x00, 0x00, 0x00, 0x00, 
+0xff, 0x07, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0xff, 0x07};
+static unsigned char symbol24_65_bits[] = {
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x02, 0x00, 
+0xc0, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x30, 0x18, 0x00, 0x10, 0x18, 0x00, 0xf0, 0x3f, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x1f, 0xf0, 0x01};
+static unsigned char symbol24_66_bits[] = {
+0xff, 0x03, 0x0c, 0x07, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x06, 0xfc, 0x03, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x18, 
+0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x1c, 0x0c, 0x0e, 0xff, 0x03};
+static unsigned char symbol24_67_bits[] = {
+0x1f, 0xf8, 0x01, 0x0e, 0x70, 0x00, 0x1c, 0x30, 0x00, 0x38, 0x18, 0x00, 
+0x30, 0x0c, 0x00, 0x60, 0x06, 0x00, 0xe0, 0x03, 0x00, 0xc0, 0x01, 0x00, 
+0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0x60, 0x07, 0x00, 0x30, 0x0e, 0x00, 
+0x10, 0x1c, 0x00, 0x18, 0x18, 0x00, 0x0c, 0x38, 0x00, 0x0e, 0x70, 0x00, 
+0x1f, 0xf8, 0x01};
+static unsigned char symbol24_68_bits[] = {
+0xc0, 0x00, 0xc0, 0x00, 0xe0, 0x01, 0x20, 0x01, 0x20, 0x03, 0x30, 0x03, 
+0x10, 0x06, 0x10, 0x06, 0x18, 0x0c, 0x08, 0x0c, 0x0c, 0x18, 0x04, 0x18, 
+0x04, 0x30, 0x06, 0x30, 0x02, 0x60, 0x03, 0x60, 0xff, 0xff};
+static unsigned char symbol24_69_bits[] = {
+0xff, 0x0f, 0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x04, 0x0c, 0x04, 0xfc, 0x07, 0x0c, 0x04, 0x0c, 0x04, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char symbol24_70_bits[] = {
+0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f, 0x9c, 0x39, 0x86, 0x61, 
+0x87, 0xe1, 0x83, 0xc1, 0x83, 0xc1, 0x83, 0xc1, 0x87, 0xe1, 0x86, 0x61, 
+0x9c, 0x39, 0xf0, 0x0f, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char symbol24_71_bits[] = {
+0xff, 0x1f, 0x0c, 0x18, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char symbol24_72_bits[] = {
+0x3f, 0xfc, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0xfc, 0x3f, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x3f, 0xfc};
+static unsigned char symbol24_73_bits[] = {
+0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char symbol24_74_bits[] = {
+0xc0, 0x03, 0x60, 0x07, 0x20, 0x06, 0x60, 0x06, 0xc0, 0x0c, 0x8e, 0x0d, 
+0x1f, 0x0f, 0x19, 0x3c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x06, 0x1c, 0x06, 0x38, 0x03, 0xf0, 0x01};
+static unsigned char symbol24_75_bits[] = {
+0x3f, 0x3e, 0x0c, 0x0c, 0x0c, 0x06, 0x0c, 0x03, 0x8c, 0x01, 0xcc, 0x00, 
+0x6c, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xcc, 0x01, 0x8c, 0x01, 0x8c, 0x03, 
+0x0c, 0x07, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x38, 0x3f, 0x7c};
+static unsigned char symbol24_76_bits[] = {
+0xc0, 0x00, 0xc0, 0x00, 0xe0, 0x01, 0x20, 0x01, 0x20, 0x03, 0x20, 0x03, 
+0x30, 0x03, 0x10, 0x06, 0x10, 0x06, 0x18, 0x06, 0x08, 0x0c, 0x08, 0x0c, 
+0x0c, 0x0c, 0x04, 0x18, 0x04, 0x18, 0x06, 0x38, 0x1f, 0x7c};
+static unsigned char symbol24_77_bits[] = {
+0x0f, 0x80, 0x0f, 0x1c, 0x80, 0x03, 0x1c, 0xc0, 0x03, 0x3c, 0x40, 0x03, 
+0x34, 0x40, 0x03, 0x74, 0x60, 0x03, 0x64, 0x20, 0x03, 0xe4, 0x30, 0x03, 
+0xc4, 0x10, 0x03, 0xc4, 0x11, 0x03, 0x84, 0x19, 0x03, 0x84, 0x0b, 0x03, 
+0x04, 0x0b, 0x03, 0x04, 0x0f, 0x03, 0x04, 0x06, 0x03, 0x04, 0x06, 0x03, 
+0x1f, 0xc0, 0x0f};
+static unsigned char symbol24_78_bits[] = {
+0x0f, 0xf8, 0x1c, 0x20, 0x1c, 0x20, 0x34, 0x20, 0x74, 0x20, 0x64, 0x20, 
+0xc4, 0x20, 0xc4, 0x20, 0x84, 0x21, 0x84, 0x23, 0x04, 0x23, 0x04, 0x26, 
+0x04, 0x26, 0x04, 0x2c, 0x04, 0x3c, 0x04, 0x38, 0x1f, 0x30};
+static unsigned char symbol24_79_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x0c, 0x30, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x06, 0x60, 0x06, 0x60, 0x0c, 0x30, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char symbol24_80_bits[] = {
+0xff, 0xff, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x30, 0x3f, 0xfc};
+static unsigned char symbol24_81_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x0c, 0x30, 0x06, 0x60, 0x06, 0x60, 0x13, 0xc8, 
+0x13, 0xc8, 0xf3, 0xcf, 0xf3, 0xcf, 0x13, 0xc8, 0x13, 0xc8, 0x03, 0xc0, 
+0x02, 0x40, 0x06, 0x60, 0x0c, 0x30, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char symbol24_82_bits[] = {
+0xff, 0x01, 0x0c, 0x07, 0x0c, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x06, 0x0c, 0x07, 0xfc, 0x01, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char symbol24_83_bits[] = {
+0xff, 0x0f, 0x07, 0x0c, 0x0e, 0x08, 0x1c, 0x00, 0x38, 0x00, 0x70, 0x00, 
+0xe0, 0x00, 0xc0, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 
+0x0c, 0x08, 0x06, 0x08, 0x03, 0x0c, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char symbol24_84_bits[] = {
+0xff, 0x3f, 0xc3, 0x30, 0xc1, 0x20, 0xc1, 0x20, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x03};
+static unsigned char symbol24_85_bits[] = {
+0x1f, 0xf8, 0x0e, 0x70, 0x0c, 0x30, 0x18, 0x18, 0x38, 0x08, 0x30, 0x0c, 
+0x70, 0x06, 0x60, 0x06, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char symbol24_86_bits[] = {
+0xf8, 0x01, 0xfc, 0x01, 0x06, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x00, 
+0xf8, 0x01, 0x00, 0x01, 0x00, 0x01, 0x80, 0x01, 0xf0, 0x00, 0x70, 0x00};
+static unsigned char symbol24_87_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x0c, 0x30, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x07, 0xe0, 0x06, 0x60, 0x0c, 0x30, 
+0x18, 0x18, 0x31, 0x8c, 0x21, 0x84, 0x3f, 0xfc, 0x3f, 0xfc};
+static unsigned char symbol24_88_bits[] = {
+0xfe, 0x1f, 0xfe, 0x1f, 0x06, 0x18, 0x02, 0x10, 0x00, 0x00, 0x08, 0x04, 
+0x08, 0x04, 0xf8, 0x07, 0xf8, 0x07, 0x08, 0x04, 0x08, 0x04, 0x00, 0x00, 
+0x01, 0x20, 0x01, 0x20, 0x03, 0x30, 0xff, 0x3f, 0xff, 0x3f};
+static unsigned char symbol24_89_bits[] = {
+0xc7, 0x8f, 0x03, 0x0e, 0xc3, 0x01, 0x0c, 0xc3, 0x00, 0x0c, 0xc3, 0x00, 
+0x1c, 0xe3, 0x00, 0x1c, 0xe3, 0x00, 0x18, 0x63, 0x00, 0x38, 0x73, 0x00, 
+0xe0, 0x1f, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 
+0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 
+0xc0, 0x0f, 0x00};
+static unsigned char symbol24_90_bits[] = {
+0xff, 0x0f, 0x03, 0x0e, 0x01, 0x06, 0x00, 0x07, 0x80, 0x03, 0x80, 0x01, 
+0xc0, 0x01, 0xe0, 0x00, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00, 
+0x1c, 0x00, 0x0e, 0x00, 0x06, 0x08, 0x07, 0x0c, 0xff, 0x0f};
+static unsigned char symbol24_91_bits[] = {
+0x1f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x1f};
+static unsigned char symbol24_92_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c};
+static unsigned char symbol24_93_bits[] = {
+0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f};
+static unsigned char symbol24_94_bits[] = {
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xff, 0x3f, 0xff, 0x3f};
+static unsigned char symbol24_95_bits[] = {
+0xff, 0x1f, 0xff, 0x1f};
+static unsigned char symbol24_96_bits[] = {
+0xff, 0x1f, 0xff, 0x1f};
+static unsigned char symbol24_97_bits[] = {
+0xf8, 0x18, 0x8e, 0x1d, 0x06, 0x0d, 0x07, 0x0f, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x27, 0x8e, 0x3f, 
+0xf8, 0x1c};
+static unsigned char symbol24_98_bits[] = {
+0x7c, 0x00, 0xe6, 0x00, 0xc3, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc3, 0x01, 
+0xc3, 0x00, 0x73, 0x00, 0xf3, 0x00, 0xc3, 0x01, 0x83, 0x01, 0x83, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0x87, 0x01, 0xcf, 0x01, 
+0xfb, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_99_bits[] = {
+0x0e, 0x06, 0x1f, 0x06, 0x1b, 0x03, 0x11, 0x03, 0x90, 0x01, 0x90, 0x01, 
+0xd0, 0x00, 0xe0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x70, 0x00, 0x70, 0x00, 
+0x98, 0x00, 0x98, 0x00, 0x8c, 0x08, 0x8c, 0x0d, 0x86, 0x0f, 0x06, 0x07};
+static unsigned char symbol24_100_bits[] = {
+0xf8, 0x00, 0xcc, 0x01, 0x84, 0x01, 0x0c, 0x00, 0x1c, 0x00, 0x38, 0x00, 
+0x70, 0x00, 0xfc, 0x00, 0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char symbol24_101_bits[] = {
+0x7c, 0x00, 0xce, 0x00, 0xc7, 0x00, 0xc3, 0x00, 0x07, 0x00, 0x06, 0x00, 
+0x3c, 0x00, 0x06, 0x00, 0x07, 0x00, 0x03, 0x00, 0x07, 0x01, 0x8e, 0x01, 
+0xfc, 0x00};
+static unsigned char symbol24_102_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf8, 0x01, 0x6c, 0x03, 
+0x66, 0x06, 0x67, 0x0e, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x67, 0x0e, 0x66, 0x06, 0x6c, 0x03, 0xf8, 0x01, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_103_bits[] = {
+0x0e, 0x06, 0x1f, 0x06, 0x19, 0x06, 0x19, 0x03, 0x18, 0x03, 0x30, 0x03, 
+0xb0, 0x01, 0xb0, 0x01, 0xa0, 0x01, 0xe0, 0x00, 0xe0, 0x00, 0xc0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_104_bits[] = {
+0x8e, 0x03, 0xdf, 0x07, 0x79, 0x0c, 0x38, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 
+0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 
+0x18, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c};
+static unsigned char symbol24_105_bits[] = {
+0x0c, 0x0e, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x4c, 0x7c, 
+0x38};
+static unsigned char symbol24_106_bits[] = {
+0xcc, 0x01, 0xce, 0x03, 0x66, 0x06, 0x63, 0x0e, 0x63, 0x0c, 0x63, 0x0c, 
+0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x67, 0x0e, 0x66, 0x06, 0x6c, 0x03, 
+0xf8, 0x01, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_107_bits[] = {
+0x0c, 0x0e, 0x0e, 0x0f, 0x8f, 0x0d, 0xcc, 0x00, 0x6c, 0x00, 0x3c, 0x00, 
+0x3c, 0x00, 0x7c, 0x00, 0xec, 0x00, 0xcc, 0x01, 0x8c, 0x03, 0x0c, 0x07, 
+0x8c, 0x0f};
+static unsigned char symbol24_108_bits[] = {
+0x0e, 0x00, 0x1f, 0x00, 0x11, 0x00, 0x10, 0x00, 0x10, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x38, 0x00, 0x78, 0x00, 0x58, 0x00, 0x4c, 0x00, 
+0x4c, 0x00, 0xcc, 0x00, 0x86, 0x00, 0x86, 0x00, 0x86, 0x09, 0x83, 0x0f, 
+0x03, 0x07};
+static unsigned char symbol24_109_bits[] = {
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0xc7, 0x09, 0xff, 0x0f, 
+0x7b, 0x06, 0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00};
+static unsigned char symbol24_110_bits[] = {
+0x03, 0x07, 0x03, 0x07, 0x03, 0x06, 0x06, 0x02, 0x06, 0x03, 0x06, 0x01, 
+0x8c, 0x01, 0x8c, 0x00, 0xcc, 0x00, 0x58, 0x00, 0x58, 0x00, 0x70, 0x00, 
+0x30, 0x00};
+static unsigned char symbol24_111_bits[] = {
+0xf8, 0x00, 0x8e, 0x03, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8e, 0x03, 
+0xf8, 0x00};
+static unsigned char symbol24_112_bits[] = {
+0xfe, 0x1f, 0xff, 0x1f, 0x19, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 
+0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 0x13, 0x1c, 0x1f, 
+0x0c, 0x0f};
+static unsigned char symbol24_113_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0xff, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00};
+static unsigned char symbol24_114_bits[] = {
+0x7c, 0x00, 0xc6, 0x01, 0x83, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x03, 0x83, 0x01, 0xc7, 0x01, 
+0x7b, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_115_bits[] = {
+0xf8, 0x3f, 0x8e, 0x3f, 0x06, 0x03, 0x07, 0x07, 0x03, 0x06, 0x03, 0x06, 
+0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x07, 0x07, 0x06, 0x03, 0x8e, 0x03, 
+0xf8, 0x00};
+static unsigned char symbol24_116_bits[] = {
+0xfc, 0x03, 0xfe, 0x03, 0x33, 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x01, 0xf0, 0x01, 
+0xe0, 0x00};
+static unsigned char symbol24_117_bits[] = {
+0x0c, 0x07, 0x1e, 0x0c, 0x1b, 0x18, 0x19, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x30, 0x0c, 0x70, 0x07, 
+0xe0, 0x03};
+static unsigned char symbol24_118_bits[] = {
+0xfe, 0xff, 0xff, 0xff, 0x19, 0x18, 0x0c, 0x30, 0x8c, 0x31, 0x86, 0x61, 
+0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x86, 0x61, 0x8c, 0x31, 
+0xdc, 0x3b, 0x78, 0x1e};
+static unsigned char symbol24_119_bits[] = {
+0x18, 0x06, 0x0c, 0x0c, 0x06, 0x18, 0xc6, 0x18, 0xc3, 0x30, 0xc3, 0x30, 
+0xc3, 0x30, 0xc3, 0x30, 0xc3, 0x30, 0xc3, 0x30, 0xc6, 0x18, 0xee, 0x1d, 
+0x3c, 0x0f};
+static unsigned char symbol24_120_bits[] = {
+0x0c, 0x00, 0xc6, 0x01, 0xe6, 0x01, 0xfc, 0x00, 0x0c, 0x00, 0x04, 0x00, 
+0xec, 0x01, 0xf8, 0x01, 0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0xfc, 0x01, 
+0xf0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0xf0, 0x01, 0xf0, 0x00};
+static unsigned char symbol24_121_bits[] = {
+0x83, 0xc1, 0x8e, 0x71, 0x8c, 0x31, 0x9c, 0x39, 0x9c, 0x39, 0x9c, 0x39, 
+0x9c, 0x39, 0x9c, 0x39, 0x9c, 0x39, 0x98, 0x19, 0x98, 0x19, 0xb0, 0x0d, 
+0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01};
+static unsigned char symbol24_122_bits[] = {
+0x0c, 0x00, 0xc6, 0x01, 0xe6, 0x01, 0xfc, 0x00, 0x18, 0x00, 0x0c, 0x00, 
+0x04, 0x00, 0x06, 0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x03, 0x00, 0x0f, 0x00, 0x3e, 0x00, 0xfc, 0x01, 
+0xf0, 0x03, 0x00, 0x03, 0x00, 0x02, 0x00, 0x03, 0xf0, 0x01, 0xf0, 0x00};
+static unsigned char symbol24_123_bits[] = {
+0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x0c, 0x04, 0x03, 0x04, 
+0x0c, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0};
+static unsigned char symbol24_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x30, 0x20, 0xc0, 0x20, 
+0x30, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char symbol24_126_bits[] = {
+0x1c, 0x04, 0x3e, 0x06, 0xe3, 0x03, 0xc1, 0x01};
+static unsigned char symbol24_127_bits[] = {
+0x00};
+static unsigned char symbol24_128_bits[] = {
+0x00};
+static unsigned char symbol24_129_bits[] = {
+0x00};
+static unsigned char symbol24_130_bits[] = {
+0x00};
+static unsigned char symbol24_131_bits[] = {
+0x00};
+static unsigned char symbol24_132_bits[] = {
+0x00};
+static unsigned char symbol24_133_bits[] = {
+0x00};
+static unsigned char symbol24_134_bits[] = {
+0x00};
+static unsigned char symbol24_135_bits[] = {
+0x00};
+static unsigned char symbol24_136_bits[] = {
+0x00};
+static unsigned char symbol24_137_bits[] = {
+0x00};
+static unsigned char symbol24_138_bits[] = {
+0x00};
+static unsigned char symbol24_139_bits[] = {
+0x00};
+static unsigned char symbol24_140_bits[] = {
+0x00};
+static unsigned char symbol24_141_bits[] = {
+0x00};
+static unsigned char symbol24_142_bits[] = {
+0x00};
+static unsigned char symbol24_143_bits[] = {
+0x00};
+static unsigned char symbol24_144_bits[] = {
+0x00};
+static unsigned char symbol24_145_bits[] = {
+0x00};
+static unsigned char symbol24_146_bits[] = {
+0x00};
+static unsigned char symbol24_147_bits[] = {
+0x00};
+static unsigned char symbol24_148_bits[] = {
+0x00};
+static unsigned char symbol24_149_bits[] = {
+0x00};
+static unsigned char symbol24_150_bits[] = {
+0x00};
+static unsigned char symbol24_151_bits[] = {
+0x00};
+static unsigned char symbol24_152_bits[] = {
+0x00};
+static unsigned char symbol24_153_bits[] = {
+0x00};
+static unsigned char symbol24_154_bits[] = {
+0x00};
+static unsigned char symbol24_155_bits[] = {
+0x00};
+static unsigned char symbol24_156_bits[] = {
+0x00};
+static unsigned char symbol24_157_bits[] = {
+0x00};
+static unsigned char symbol24_158_bits[] = {
+0x00};
+static unsigned char symbol24_159_bits[] = {
+0x00};
+static unsigned char symbol24_160_bits[] = {
+0x00};
+static unsigned char symbol24_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_162_bits[] = {
+0x07, 0x0e, 0x0e, 0x1b, 0x1c, 0x1d};
+static unsigned char symbol24_163_bits[] = {
+0xd8, 0x0c, 0x70, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0xf8, 0x01, 0x18, 0x0c};
+static unsigned char symbol24_164_bits[] = {
+0x0e, 0x06, 0x03, 0x01, 0x00, 0x0e, 0x80, 0x07, 0xe0, 0x01, 0x78, 0x00, 
+0x1e, 0x00, 0x07, 0x00, 0x07};
+static unsigned char symbol24_165_bits[] = {
+0x00, 0x1e, 0x00, 0x78, 0x00, 0x40, 0x03, 0x00, 0x0f, 0x00, 0x0c, 0x00, 
+0x00, 0x7f};
+static unsigned char symbol24_166_bits[] = {
+0x0f, 0x1f, 0x0f, 0x00, 0xc0, 0x00, 0x60, 0x10, 0x30, 0x18, 0x18, 0x18, 
+0x0c, 0x0c, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03, 0x1c, 0x1c, 0x7e, 0x1e, 
+0xe3, 0x03, 0xc3, 0x01, 0x63, 0x03, 0x3e, 0x1e, 0x1c, 0x1c, 0x00, 0x0f, 
+0x80, 0x19, 0x80, 0x19, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char symbol24_167_bits[] = {
+0xc0, 0x00, 0xf8, 0x07, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 
+0x30, 0x00};
+static unsigned char symbol24_168_bits[] = {
+0x33, 0x00, 0x33, 0x00, 0x1b, 0x00, 0x0e, 0x00, 0xe0, 0x01, 0xf0, 0x03, 
+0xf0, 0x03, 0xf0, 0x03, 0xf0, 0x03, 0xee, 0x01, 0xdf, 0x02, 0xff, 0x03, 
+0xff, 0x03};
+static unsigned char symbol24_169_bits[] = {
+0xdf, 0x0e, 0xce, 0x0c, 0xc0, 0x00, 0xe0, 0x01, 0x30, 0x00, 0x30, 0x00, 
+0x78, 0x00, 0xfc, 0x00, 0xfc, 0x00, 0xfe, 0x01, 0xff, 0x03, 0xfe, 0x01, 
+0xfc, 0x00};
+static unsigned char symbol24_170_bits[] = {
+0xfc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x30, 0x00, 0x0e, 0x07, 0x9f, 0x0f, 
+0x9f, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 0xfe, 0x07, 0xfe, 0x07, 
+0xfc, 0x03};
+static unsigned char symbol24_171_bits[] = {
+0xf8, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf8, 0x01, 0xfc, 0x03, 0xfe, 0x07, 0xfe, 0x07, 0xff, 0x0f, 
+0xff, 0x0f, 0x6f, 0x0f, 0x66, 0x06, 0x60, 0x00, 0xf0, 0x00, 0x60, 0x00};
+static unsigned char symbol24_172_bits[] = {
+0x06, 0x30, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x30, 0x06, 0x00, 
+0x60, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0x00, 0x60, 0x0c, 0x00, 
+0x30, 0x18, 0x00, 0x00, 0x30, 0x00, 0x0c, 0x00, 0x00, 0x06, 0x60, 0x00, 
+0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00};
+static unsigned char symbol24_173_bits[] = {
+0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x01, 0xff, 0x0f, 
+0xff, 0x01, 0x06, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 
+0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf8, 0x01, 0x6c, 0x03, 0x66, 0x06, 0x63, 0x0c, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00};
+static unsigned char symbol24_174_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 
+0x0c, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00};
+static unsigned char symbol24_175_bits[] = {
+0x60, 0x00, 0x00, 0x00, 0xc0, 0x00, 0xff, 0x0f, 0xff, 0x01, 0xff, 0x0f, 
+0xff, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 
+0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_176_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60};
+static unsigned char symbol24_177_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x03, 0x0c, 0x02, 0x06, 0x00, 0x03, 0x00, 0x01, 0x00, 
+0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_178_bits[] = {
+0x36, 0x01, 0x41, 0x01, 0x36, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00};
+static unsigned char symbol24_179_bits[] = {
+0x30, 0x00, 0xff, 0x03, 0xff, 0x03, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0xff, 0x03, 0x98, 0x01, 
+0xdc, 0x01, 0xee, 0x00, 0x66, 0x00};
+static unsigned char symbol24_180_bits[] = {
+0x33, 0x00, 0x11, 0x00, 0x07, 0x00, 0x1e, 0x00, 0x78, 0x00, 0xe0, 0x01, 
+0x80, 0x07, 0x00, 0x06, 0x00, 0x06, 0x80, 0x07};
+static unsigned char symbol24_181_bits[] = {
+0xe0, 0x01, 0x7c, 0x00, 0x0f, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0xff, 0x0f};
+static unsigned char symbol24_182_bits[] = {
+0x03, 0x02, 0x06, 0x03, 0x8c, 0x01, 0xd8, 0x00, 0x70, 0x00, 0x70, 0x00, 
+0xd8, 0x00, 0x8c, 0x01, 0x06, 0x03, 0x03, 0x02, 0x1c, 0x00, 0x3e, 0x02, 
+0x63, 0x03, 0xc3, 0x01, 0xe3, 0x03, 0x3e, 0x02, 0x1c, 0x00, 0x7c, 0x00, 
+0xc6, 0x00};
+static unsigned char symbol24_183_bits[] = {
+0x83, 0x01, 0x80, 0x01, 0x00, 0x03, 0x00, 0x03};
+static unsigned char symbol24_184_bits[] = {
+0x00, 0x03, 0x00, 0x03, 0x78, 0x03, 0xce, 0x03, 0x86, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x83, 0x01};
+static unsigned char symbol24_185_bits[] = {
+0x83, 0x01, 0x83, 0x01, 0xc3, 0x00, 0xe6, 0x00, 0x3c, 0x00, 0x3c, 0x02, 
+0xff, 0x03, 0xff, 0x03, 0x7e, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 
+0xff, 0x03};
+static unsigned char symbol24_186_bits[] = {
+0xff, 0x03, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x80, 0x01, 0x80, 0x01, 
+0xc0, 0x00, 0xc0, 0x00};
+static unsigned char symbol24_187_bits[] = {
+0xff, 0x03, 0xff, 0x03, 0x30, 0x00, 0xff, 0x03, 0xff, 0x03, 0x0c, 0x00, 
+0x0c, 0x00, 0x06, 0x00};
+static unsigned char symbol24_188_bits[] = {
+0x06, 0x00, 0x03, 0x07, 0xff, 0x03, 0x00, 0x00, 0x03};
+static unsigned char symbol24_189_bits[] = {
+0x03, 0x03, 0x03, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x02, 
+0x02, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 0x01, 
+0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_190_bits[] = {
+0x03, 0x03, 0x03, 0x01, 0x03, 0x03, 0x03, 0x01};
+static unsigned char symbol24_191_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0xff, 0x3f, 0xff, 0x01, 0xff, 0x3f};
+static unsigned char symbol24_192_bits[] = {
+0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 
+0x06, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0x06, 0x00};
+static unsigned char symbol24_193_bits[] = {
+0x04, 0x00, 0x81, 0x01, 0xc3, 0x00, 0xc7, 0x0f, 0x8e, 0x0f, 0x1c, 0x06, 
+0x38, 0x03, 0x3c, 0x01, 0x76, 0x01, 0xe3, 0x01, 0xc3, 0x01, 0xc7, 0x01, 
+0x8f, 0x03, 0x0e, 0x07, 0x0c, 0x0e, 0x0e, 0x0c, 0x07, 0x08, 0xf0, 0x01, 
+0xfc, 0x3f};
+static unsigned char symbol24_194_bits[] = {
+0x0e, 0x1f, 0x00, 0x0c, 0x02, 0x00, 0x02, 0x03, 0x00, 0x03, 0x0c, 0x01, 
+0x38, 0x0e, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x38, 0x00, 0x38, 0x00, 0x00, 
+0x0c, 0x30, 0x00, 0x30, 0x7b, 0x00, 0xf0, 0x0f, 0x00, 0x03, 0x78, 0x00, 
+0x00, 0xfc, 0x00, 0x00, 0xc6, 0x01, 0x00, 0x83, 0x01, 0x00, 0x81, 0x01, 
+0x00, 0x83, 0x01, 0x00, 0x87, 0x01};
+static unsigned char symbol24_195_bits[] = {
+0x00, 0x0e, 0x1d, 0x00, 0x9c, 0x0d, 0x00, 0x18, 0x19, 0x00, 0x88, 0x19, 
+0x00, 0x00, 0x19, 0x00, 0x80, 0x39, 0x00, 0x00, 0x31, 0x00, 0x80, 0x31, 
+0x00, 0x18, 0x61, 0x01, 0xfc, 0x60, 0x01, 0x72, 0xe0, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x18, 0x3c};
+static unsigned char symbol24_196_bits[] = {
+0x0c, 0x7f, 0x8c, 0x61, 0xc6, 0x60, 0x66, 0x60, 0x36, 0x60, 0x16, 0x30, 
+0x9e, 0x39, 0xce, 0x19, 0x4e, 0x0c, 0x5e, 0x0e, 0xda, 0x07, 0xbb, 0x01, 
+0x31, 0x00, 0x31, 0x00, 0x31, 0x00, 0x1b, 0x00, 0x0e, 0x00};
+static unsigned char symbol24_197_bits[] = {
+0xe0, 0x07, 0x78, 0x1e, 0x1c, 0x38, 0x06, 0x60, 0x16, 0x68, 0x33, 0xcc, 
+0x63, 0xc6, 0xc3, 0xc3, 0x83, 0xc1, 0xc3, 0xc3, 0x63, 0xc6, 0x33, 0xcc, 
+0x16, 0x68, 0x06, 0x60, 0x1c, 0x38, 0x78, 0x1e, 0xe0, 0x07};
+static unsigned char symbol24_198_bits[] = {
+0xe0, 0x07, 0x00, 0x1e, 0x1c, 0x00, 0x86, 0x61, 0x02, 0x61, 0x83, 0x01, 
+0x83, 0xc1, 0x03, 0xdf, 0xfb, 0x03, 0x83, 0xc1, 0x03, 0xc1, 0x83, 0x01, 
+0x86, 0x61, 0x02, 0x60, 0x1c, 0x00, 0x78, 0x1e, 0x00, 0x07, 0xc0, 0x03, 
+0x03, 0xf0, 0x03, 0x01, 0x38, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 
+0x00, 0x06, 0x00};
+static unsigned char symbol24_199_bits[] = {
+0x01, 0x06, 0x8c, 0x01, 0x06, 0x86, 0x01, 0x06, 0x83, 0x01, 0x86, 0x81, 
+0x01, 0xc6, 0x80, 0x01, 0x66, 0x80, 0x01, 0x3c, 0xc0, 0x00, 0x1c, 0xc0, 
+0x00, 0x3c};
+static unsigned char symbol24_200_bits[] = {
+0x70, 0x00, 0xf6, 0x3f, 0x00, 0xc3, 0x0f, 0x00, 0xe0, 0x07, 0xf8, 0x1f, 
+0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0};
+static unsigned char symbol24_201_bits[] = {
+0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 
+0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40, 0x03, 0x40};
+static unsigned char symbol24_202_bits[] = {
+0x06, 0x60, 0x06, 0x60, 0x1c, 0x38, 0xf8, 0x1f, 0xe0, 0x07, 0xff, 0x07, 
+0xff, 0x1f, 0x00, 0x38, 0x00, 0x30, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 
+0x00, 0x60, 0x00, 0x30, 0x00, 0x38};
+static unsigned char symbol24_203_bits[] = {
+0xff, 0x1f, 0xff, 0x07, 0xff, 0x07, 0xff, 0x1f, 0x00, 0x38, 0x00, 0x30, 
+0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 0x00, 0x38, 
+0xff, 0x1f, 0xff, 0x07, 0x00, 0x00, 0xff, 0x7f};
+static unsigned char symbol24_204_bits[] = {
+0xff, 0x7f, 0x00, 0x30, 0x00, 0x30, 0xf0, 0x7f, 0xfc, 0x7f, 0x0e, 0x0c, 
+0x06, 0x0c, 0x03, 0x06, 0x03, 0x06, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01};
+static unsigned char symbol24_205_bits[] = {
+0x8e, 0x01, 0xfc, 0x7f, 0xf0, 0x7f, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x7f, 
+0xfc, 0x7f, 0x0e, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x06, 0x00, 0x0e, 0x00};
+static unsigned char symbol24_206_bits[] = {
+0xfc, 0x0f, 0xf0, 0x0f, 0xf0, 0x0f, 0xfc, 0x0f, 0x0e, 0x00, 0x06, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x0e, 0x00, 
+0xfc, 0x0f};
+static unsigned char symbol24_207_bits[] = {
+0xf0, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0xf8, 0x0f, 0xfe, 0x0f, 
+0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 0xff, 0x0f, 0xff, 0x0f, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0xfe, 0x0f, 0xf8, 0x0f};
+static unsigned char symbol24_208_bits[] = {
+0x00, 0x03, 0x00, 0x03, 0xf8, 0x01, 0xfe, 0x0f, 0x00, 0x01, 0x83, 0x01, 
+0xc3, 0x00, 0x01, 0x0f, 0xff, 0x01, 0x63, 0x00, 0x01, 0x00, 0x33, 0x00, 
+0x36, 0x00, 0x00, 0x0f, 0xf8, 0x01, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_209_bits[] = {
+0x00, 0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x00, 0x80, 0x01, 
+0x00, 0xc0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x30, 0x00, 0x00, 0x18, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x01, 0xff, 0xff};
+static unsigned char symbol24_210_bits[] = {
+0x03, 0xc0, 0x03, 0x40, 0x06, 0x60, 0x06, 0x20, 0x0c, 0x30, 0x0c, 0x10, 
+0x0c, 0x18, 0x18, 0x08, 0x18, 0x0c, 0x30, 0x04, 0x30, 0x04, 0x60, 0x06, 
+0x60, 0x02, 0xc0, 0x03, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01};
+static unsigned char symbol24_211_bits[] = {
+0xe0, 0x07, 0x78, 0x1e, 0x1c, 0x38, 0x06, 0x60, 0xf6, 0x67, 0x63, 0xce, 
+0x63, 0xcc, 0x63, 0xce, 0xe3, 0xc7, 0x63, 0xc3, 0x63, 0xc6, 0x63, 0xcc, 
+0xf6, 0x7c, 0x06, 0x60, 0x1c, 0x38, 0x78, 0x1e, 0xe0, 0x07};
+static unsigned char symbol24_212_bits[] = {
+0xe0, 0x07, 0x08, 0x1e, 0x1c, 0x08, 0x06, 0x60, 0x06, 0x63, 0x63, 0x06, 
+0x33, 0xc4, 0x03, 0xc0, 0x33, 0x00, 0x33, 0xc0, 0x03, 0xc4, 0x63, 0x06, 
+0xc6, 0x63, 0x06, 0x60, 0x1c, 0x08};
+static unsigned char symbol24_213_bits[] = {
+0x78, 0x1e, 0x00, 0x07, 0xff, 0x01, 0x0e, 0x99, 0x00, 0x06, 0x18, 0x00, 
+0x07, 0x18, 0x00, 0x07, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 
+0x06, 0x18, 0x00, 0x06, 0x18, 0x00, 0x06, 0x3c, 0x01, 0x0f, 0xff, 0x01, 
+0x01, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 
+0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c, 0x00, 
+0x00, 0x0c, 0x00};
+static unsigned char symbol24_214_bits[] = {
+0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 
+0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 
+0x00, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x3f, 0xf8, 0x01, 0x00, 0x20, 
+0x00, 0x20, 0x00, 0x20, 0x00, 0x30, 0x00, 0x30, 0x00, 0x10};
+static unsigned char symbol24_215_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol24_216_bits[] = {
+0x10, 0x00, 0x18, 0x0c, 0x18, 0x0e, 0x08, 0x1b, 0x08, 0x18, 0x08, 0x30, 
+0x0c, 0x30, 0x0c, 0x60};
+static unsigned char symbol24_217_bits[] = {
+0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x03, 0x03, 0x03, 0xff, 0x1f, 0xff, 0x1f, 0x00, 0x00};
+static unsigned char symbol24_218_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xb0, 0x01, 0xb0, 0x01, 0x18, 0x03, 0x18, 0x03, 0x0c, 0x06};
+static unsigned char symbol24_219_bits[] = {
+0x0c, 0x06, 0x06, 0x0c, 0x06, 0x0c, 0x03, 0x18, 0x03, 0x18, 0x03, 0x18, 
+0x03, 0x18, 0x06, 0x0c, 0x06, 0x0c, 0x0c, 0x06, 0x0c, 0x06, 0x18, 0x03, 
+0x18, 0x03, 0x30, 0x01, 0xb0, 0x01, 0xe0, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char symbol24_220_bits[] = {
+0x03, 0x30, 0x00, 0x06, 0x18, 0x00, 0x0c, 0xfc, 0x7f, 0x1f, 0xfe, 0x7f, 
+0x3f, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0xfe, 0x7f, 0x3f, 0xfc, 0x7f, 
+0x1f, 0x18, 0x00, 0x0c, 0x30, 0x00, 0x06, 0x60, 0x00, 0x03, 0x60, 0x00};
+static unsigned char symbol24_221_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x0c, 0xff, 0x0f, 0xfe, 0x0f, 
+0x7f, 0x07, 0x00, 0x00, 0x07, 0x00, 0x00, 0x0e, 0xff, 0x0f, 0xfc, 0x0f, 
+0x7f, 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 
+0xf0, 0x00, 0xf8, 0x01, 0x9c, 0x03, 0x9e, 0x07, 0x9b, 0x0d};
+static unsigned char symbol24_222_bits[] = {
+0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x18, 0x01, 0x98, 0x01, 0x98, 0x01, 0x18, 0x01, 0x00, 0x00};
+static unsigned char symbol24_223_bits[] = {
+0x03, 0x00, 0x00, 0x06, 0x00, 0x00, 0x0c, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 
+0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x0f, 0xff, 0x0f, 0xff, 0x0f, 
+0x1f, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x06, 0x00, 0x00, 0x03, 0x98, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01};
+static unsigned char symbol24_224_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 
+0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x98, 0x01, 0x9b, 0x01, 
+0x9e, 0x03, 0x9c, 0x03, 0xf8, 0x01, 0xf0, 0x00, 0x60, 0x00, 0x30, 0x00};
+static unsigned char symbol24_225_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x06, 0x01, 0x06, 0x01, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x01};
+static unsigned char symbol24_226_bits[] = {
+0x86, 0x01, 0xcc, 0x00, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03, 
+0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 0x60};
+static unsigned char symbol24_227_bits[] = {
+0xe0, 0x07, 0x78, 0x1e, 0x1c, 0x38, 0x06, 0x60, 0xe6, 0x67, 0x63, 0xcc, 
+0x63, 0xcc, 0x63, 0xcc, 0xe3, 0xc7, 0x63, 0xc6, 0x63, 0xcc, 0x63, 0xcc, 
+0x66, 0x4c, 0x06, 0x60, 0x1c, 0x38, 0x78, 0x1e, 0xe0, 0x07};
+static unsigned char symbol24_228_bits[] = {
+0xe0, 0x07, 0x00, 0x1e, 0x1c, 0x00, 0x06, 0x60, 0x02, 0x63, 0xe3, 0x03, 
+0x73, 0xc6, 0x03, 0xc0, 0x33, 0x00, 0x33, 0xc0, 0x03, 0xc6, 0xe3, 0x03, 
+0xc6, 0x63, 0x02, 0x60, 0x1c, 0x00};
+static unsigned char symbol24_229_bits[] = {
+0x78, 0x1e, 0xe0, 0x07, 0x7f, 0x03, 0x03, 0x18, 0x03, 0x03, 0x18, 0x07, 
+0x03, 0x18, 0x87, 0x03, 0x18, 0x0f, 0x03, 0x18, 0x4b, 0x03, 0x18, 0x3b, 
+0x03, 0x18, 0x33, 0x03, 0x18, 0x33, 0x03, 0x18, 0x33, 0x03, 0xff, 0x1f, 
+0x07, 0x18, 0x0e, 0x10};
+static unsigned char symbol24_230_bits[] = {
+0x1c, 0x00, 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x01, 
+0x00, 0x01, 0x80, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 
+0x0c, 0x00, 0x06, 0x00, 0x03, 0x00, 0xff, 0x01, 0xff, 0x01, 0x80, 0x01, 
+0xc0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x03, 0x00, 
+0x03, 0x00};
+static unsigned char symbol24_231_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_232_bits[] = {
+0x03, 0x00, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00};
+static unsigned char symbol24_233_bits[] = {
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x18, 0x00, 
+0x18, 0x00, 0x30, 0x00, 0x60, 0x00, 0x40};
+static unsigned char symbol24_234_bits[] = {
+0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_235_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_236_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_237_bits[] = {
+0x03, 0x03, 0x1f, 0x18, 0x0c, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_238_bits[] = {
+0x03, 0x03, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x08, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol24_239_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02};
+static unsigned char symbol24_240_bits[] = {
+0x00};
+static unsigned char symbol24_241_bits[] = {
+0x0c, 0x78, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_242_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x00, 0x03, 0x03, 0x06, 0x06, 0x0c, 0x0c, 0x18, 0x18, 0x30, 0x30, 0x60, 
+0x60, 0x30, 0x30, 0x18};
+static unsigned char symbol24_243_bits[] = {
+0x18, 0x0c, 0x0c, 0x06, 0x06, 0x03, 0x03, 0xe0, 0xf0, 0xd8, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18};
+static unsigned char symbol24_244_bits[] = {
+0x00, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_245_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03};
+static unsigned char symbol24_246_bits[] = {
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x33, 0x01, 0x0e, 0x01, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x01, 0x00};
+static unsigned char symbol24_247_bits[] = {
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00};
+static unsigned char symbol24_248_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 
+0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x01, 0x03, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 
+0x01, 0x00, 0x01, 0x00};
+static unsigned char symbol24_249_bits[] = {
+0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x40, 
+0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x30, 
+0x00, 0x30, 0x00, 0x18, 0x00, 0x0c, 0x00};
+static unsigned char symbol24_250_bits[] = {
+0x02, 0x00, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_251_bits[] = {
+0x60, 0x60, 0x60, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_252_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 
+0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 
+0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60};
+static unsigned char symbol24_253_bits[] = {
+0x00, 0x00, 0x00, 0x1f, 0x0f, 0x18, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol24_254_bits[] = {
+0x60, 0x60, 0x60, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x02, 0x06, 0x0c, 0x18, 0x0c, 0x06, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char symbol24_255_bits[] = {
+0x00};
+static RotFont symbol24font[] = {
+{5, 1, 1, symbol24_0_bits},
+{5, 1, 1, symbol24_1_bits},
+{5, 1, 1, symbol24_2_bits},
+{5, 1, 1, symbol24_3_bits},
+{5, 1, 1, symbol24_4_bits},
+{5, 1, 1, symbol24_5_bits},
+{5, 1, 1, symbol24_6_bits},
+{5, 1, 1, symbol24_7_bits},
+{5, 1, 1, symbol24_8_bits},
+{5, 1, 1, symbol24_9_bits},
+{5, 1, 1, symbol24_10_bits},
+{5, 1, 1, symbol24_11_bits},
+{5, 1, 1, symbol24_12_bits},
+{5, 1, 1, symbol24_13_bits},
+{5, 1, 1, symbol24_14_bits},
+{5, 1, 1, symbol24_15_bits},
+{5, 1, 1, symbol24_16_bits},
+{5, 1, 1, symbol24_17_bits},
+{5, 1, 1, symbol24_18_bits},
+{5, 1, 1, symbol24_19_bits},
+{5, 1, 1, symbol24_20_bits},
+{5, 1, 1, symbol24_21_bits},
+{5, 1, 1, symbol24_22_bits},
+{5, 1, 1, symbol24_23_bits},
+{5, 1, 1, symbol24_24_bits},
+{5, 1, 1, symbol24_25_bits},
+{5, 1, 1, symbol24_26_bits},
+{5, 1, 1, symbol24_27_bits},
+{5, 1, 1, symbol24_28_bits},
+{5, 1, 1, symbol24_29_bits},
+{5, 1, 1, symbol24_30_bits},
+{5, 1, 1, symbol24_31_bits},
+{1, 1, 1, symbol24_32_bits},
+{3, 17, 17, symbol24_33_bits},
+{15, 17, 17, symbol24_34_bits},
+{11, 17, 17, symbol24_35_bits},
+{11, 17, 17, symbol24_36_bits},
+{18, 17, 17, symbol24_37_bits},
+{15, 17, 17, symbol24_38_bits},
+{8, 13, 13, symbol24_39_bits},
+{6, 22, 17, symbol24_40_bits},
+{6, 22, 17, symbol24_41_bits},
+{8, 10, 17, symbol24_42_bits},
+{10, 10, 12, symbol24_43_bits},
+{3, 6, 2, symbol24_44_bits},
+{11, 2, 8, symbol24_45_bits},
+{2, 3, 3, symbol24_46_bits},
+{7, 17, 17, symbol24_47_bits},
+{10, 17, 17, symbol24_48_bits},
+{6, 17, 17, symbol24_49_bits},
+{10, 17, 17, symbol24_50_bits},
+{9, 17, 17, symbol24_51_bits},
+{10, 17, 17, symbol24_52_bits},
+{9, 17, 17, symbol24_53_bits},
+{10, 17, 17, symbol24_54_bits},
+{10, 17, 17, symbol24_55_bits},
+{10, 17, 17, symbol24_56_bits},
+{10, 17, 17, symbol24_57_bits},
+{2, 11, 11, symbol24_58_bits},
+{3, 15, 11, symbol24_59_bits},
+{12, 12, 13, symbol24_60_bits},
+{10, 6, 10, symbol24_61_bits},
+{12, 12, 13, symbol24_62_bits},
+{8, 17, 17, symbol24_63_bits},
+{11, 12, 13, symbol24_64_bits},
+{17, 17, 17, symbol24_65_bits},
+{13, 17, 17, symbol24_66_bits},
+{17, 17, 17, symbol24_67_bits},
+{16, 17, 17, symbol24_68_bits},
+{13, 17, 17, symbol24_69_bits},
+{16, 17, 17, symbol24_70_bits},
+{13, 17, 17, symbol24_71_bits},
+{16, 17, 17, symbol24_72_bits},
+{6, 17, 17, symbol24_73_bits},
+{14, 17, 17, symbol24_74_bits},
+{15, 17, 17, symbol24_75_bits},
+{15, 17, 17, symbol24_76_bits},
+{20, 17, 17, symbol24_77_bits},
+{16, 17, 17, symbol24_78_bits},
+{16, 17, 17, symbol24_79_bits},
+{16, 17, 17, symbol24_80_bits},
+{16, 17, 17, symbol24_81_bits},
+{12, 17, 17, symbol24_82_bits},
+{12, 17, 17, symbol24_83_bits},
+{14, 17, 17, symbol24_84_bits},
+{16, 17, 17, symbol24_85_bits},
+{9, 18, 13, symbol24_86_bits},
+{16, 17, 17, symbol24_87_bits},
+{14, 17, 17, symbol24_88_bits},
+{18, 17, 17, symbol24_89_bits},
+{12, 17, 17, symbol24_90_bits},
+{5, 22, 17, symbol24_91_bits},
+{12, 10, 10, symbol24_92_bits},
+{5, 22, 17, symbol24_93_bits},
+{14, 17, 17, symbol24_94_bits},
+{13, 2, -3, symbol24_95_bits},
+{13, 2, 23, symbol24_96_bits},
+{14, 13, 13, symbol24_97_bits},
+{10, 24, 19, symbol24_98_bits},
+{12, 18, 13, symbol24_99_bits},
+{10, 18, 18, symbol24_100_bits},
+{9, 13, 13, symbol24_101_bits},
+{12, 22, 17, symbol24_102_bits},
+{11, 18, 13, symbol24_103_bits},
+{12, 18, 13, symbol24_104_bits},
+{7, 13, 13, symbol24_105_bits},
+{12, 18, 13, symbol24_106_bits},
+{12, 13, 13, symbol24_107_bits},
+{12, 19, 19, symbol24_108_bits},
+{12, 18, 13, symbol24_109_bits},
+{11, 13, 13, symbol24_110_bits},
+{11, 13, 13, symbol24_111_bits},
+{13, 13, 13, symbol24_112_bits},
+{10, 17, 17, symbol24_113_bits},
+{10, 18, 13, symbol24_114_bits},
+{14, 13, 13, symbol24_115_bits},
+{10, 13, 13, symbol24_116_bits},
+{13, 13, 13, symbol24_117_bits},
+{16, 14, 14, symbol24_118_bits},
+{14, 13, 13, symbol24_119_bits},
+{10, 24, 19, symbol24_120_bits},
+{16, 18, 13, symbol24_121_bits},
+{10, 24, 19, symbol24_122_bits},
+{8, 22, 17, symbol24_123_bits},
+{2, 22, 17, symbol24_124_bits},
+{8, 22, 17, symbol24_125_bits},
+{11, 4, 9, symbol24_126_bits},
+{5, 1, 1, symbol24_127_bits},
+{5, 1, 1, symbol24_128_bits},
+{5, 1, 1, symbol24_129_bits},
+{5, 1, 1, symbol24_130_bits},
+{5, 1, 1, symbol24_131_bits},
+{5, 1, 1, symbol24_132_bits},
+{5, 1, 1, symbol24_133_bits},
+{5, 1, 1, symbol24_134_bits},
+{5, 1, 1, symbol24_135_bits},
+{5, 1, 1, symbol24_136_bits},
+{5, 1, 1, symbol24_137_bits},
+{5, 1, 1, symbol24_138_bits},
+{5, 1, 1, symbol24_139_bits},
+{5, 1, 1, symbol24_140_bits},
+{5, 1, 1, symbol24_141_bits},
+{5, 1, 1, symbol24_142_bits},
+{5, 1, 1, symbol24_143_bits},
+{5, 1, 1, symbol24_144_bits},
+{5, 1, 1, symbol24_145_bits},
+{5, 1, 1, symbol24_146_bits},
+{5, 1, 1, symbol24_147_bits},
+{5, 1, 1, symbol24_148_bits},
+{5, 1, 1, symbol24_149_bits},
+{5, 1, 1, symbol24_150_bits},
+{5, 1, 1, symbol24_151_bits},
+{5, 1, 1, symbol24_152_bits},
+{5, 1, 1, symbol24_153_bits},
+{5, 1, 1, symbol24_154_bits},
+{5, 1, 1, symbol24_155_bits},
+{5, 1, 1, symbol24_156_bits},
+{5, 1, 1, symbol24_157_bits},
+{5, 1, 1, symbol24_158_bits},
+{5, 1, 1, symbol24_159_bits},
+{5, 1, 1, symbol24_160_bits},
+{13, 17, 17, symbol24_161_bits},
+{5, 6, 18, symbol24_162_bits},
+{12, 15, 15, symbol24_163_bits},
+{8, 17, 17, symbol24_164_bits},
+{15, 7, 11, symbol24_165_bits},
+{13, 22, 17, symbol24_166_bits},
+{14, 13, 13, symbol24_167_bits},
+{10, 13, 13, symbol24_168_bits},
+{12, 13, 13, symbol24_169_bits},
+{12, 13, 13, symbol24_170_bits},
+{24, 12, 13, symbol24_171_bits},
+{25, 12, 13, symbol24_172_bits},
+{12, 31, 23, symbol24_173_bits},
+{25, 12, 13, symbol24_174_bits},
+{12, 29, 24, symbol24_175_bits},
+{7, 7, 17, symbol24_176_bits},
+{10, 14, 14, symbol24_177_bits},
+{9, 6, 18, symbol24_178_bits},
+{12, 15, 15, symbol24_179_bits},
+{11, 10, 12, symbol24_180_bits},
+{14, 7, 11, symbol24_181_bits},
+{10, 19, 19, symbol24_182_bits},
+{8, 8, 11, symbol24_183_bits},
+{10, 8, 11, symbol24_184_bits},
+{10, 13, 13, symbol24_185_bits},
+{11, 8, 11, symbol24_186_bits},
+{11, 8, 11, symbol24_187_bits},
+{18, 3, 3, symbol24_188_bits},
+{2, 32, 24, symbol24_189_bits},
+{25, 2, 8, symbol24_190_bits},
+{14, 16, 16, symbol24_191_bits},
+{12, 16, 16, symbol24_192_bits},
+{14, 19, 18, symbol24_193_bits},
+{17, 18, 18, symbol24_194_bits},
+{15, 20, 15, symbol24_195_bits},
+{16, 17, 17, symbol24_196_bits},
+{16, 17, 17, symbol24_197_bits},
+{18, 17, 17, symbol24_198_bits},
+{16, 13, 13, symbol24_199_bits},
+{16, 13, 13, symbol24_200_bits},
+{15, 12, 12, symbol24_201_bits},
+{15, 15, 12, symbol24_202_bits},
+{15, 16, 14, symbol24_203_bits},
+{15, 12, 12, symbol24_204_bits},
+{15, 15, 12, symbol24_205_bits},
+{12, 13, 13, symbol24_206_bits},
+{12, 17, 15, symbol24_207_bits},
+{17, 16, 16, symbol24_208_bits},
+{16, 18, 18, symbol24_209_bits},
+{16, 17, 17, symbol24_210_bits},
+{16, 17, 17, symbol24_211_bits},
+{20, 10, 17, symbol24_212_bits},
+{17, 21, 18, symbol24_213_bits},
+{14, 23, 23, symbol24_214_bits},
+{2, 3, 9, symbol24_215_bits},
+{15, 8, 8, symbol24_216_bits},
+{13, 12, 12, symbol24_217_bits},
+{13, 12, 12, symbol24_218_bits},
+{23, 12, 12, symbol24_219_bits},
+{23, 12, 12, symbol24_220_bits},
+{12, 23, 23, symbol24_221_bits},
+{23, 12, 12, symbol24_222_bits},
+{12, 23, 23, symbol24_223_bits},
+{10, 18, 18, symbol24_224_bits},
+{7, 22, 17, symbol24_225_bits},
+{16, 17, 17, symbol24_226_bits},
+{16, 17, 17, symbol24_227_bits},
+{18, 10, 17, symbol24_228_bits},
+{14, 20, 18, symbol24_229_bits},
+{9, 31, 23, symbol24_230_bits},
+{2, 32, 24, symbol24_231_bits},
+{9, 32, 24, symbol24_232_bits},
+{7, 31, 23, symbol24_233_bits},
+{2, 32, 24, symbol24_234_bits},
+{7, 29, 24, symbol24_235_bits},
+{7, 31, 23, symbol24_236_bits},
+{5, 32, 24, symbol24_237_bits},
+{7, 29, 24, symbol24_238_bits},
+{2, 32, 24, symbol24_239_bits},
+{5, 1, 1, symbol24_240_bits},
+{7, 22, 17, symbol24_241_bits},
+{8, 28, 23, symbol24_242_bits},
+{8, 31, 23, symbol24_243_bits},
+{2, 32, 24, symbol24_244_bits},
+{8, 26, 24, symbol24_245_bits},
+{9, 31, 23, symbol24_246_bits},
+{2, 32, 24, symbol24_247_bits},
+{9, 32, 24, symbol24_248_bits},
+{7, 31, 23, symbol24_249_bits},
+{2, 32, 24, symbol24_250_bits},
+{7, 29, 24, symbol24_251_bits},
+{7, 31, 23, symbol24_252_bits},
+{5, 32, 24, symbol24_253_bits},
+{7, 29, 24, symbol24_254_bits},
+{5, 1, 1, symbol24_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol8.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol8.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol8.bdf	(revision 16632)
@@ -0,0 +1,2537 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Symbol-Medium-R-Normal--8-80-75-75-P-51-Adobe-FontSpecific
+SIZE 8 75 75
+FONTBOUNDINGBOX 9 11 -1 -3
+STARTPROPERTIES 31
+FOUNDRY "Adobe"
+FAMILY_NAME "Symbol"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 51
+CHARSET_REGISTRY "Adobe"
+CHARSET_ENCODING "FontSpecific"
+CAP_HEIGHT 6
+X_HEIGHT 4
+FACE_NAME "Symbol"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "No mark"
+_DEC_DEVICE_FONTNAMES "PS=Symbol"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 18-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+FULL_NAME "Symbol"
+FONT "-Adobe-Symbol-Medium-R-Normal--8-80-75-75-P-51-Adobe-FontSpecific"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 5
+DEFAULT_CHAR 32
+FONT_ASCENT 8
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 188
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+88
+88
+70
+50
+20
+20
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 6 -1 0
+BITMAP
+50
+f8
+50
+50
+f8
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+10
+10
+70
+10
+f0
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+c8
+d0
+20
+58
+98
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+60
+50
+20
+f8
+a0
+58
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+c0
+60
+20
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+80
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 8 1 -2
+BITMAP
+80
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 1 2
+BITMAP
+40
+e0
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 1 0 2
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 0
+BITMAP
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+a0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+20
+40
+80
+e0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+20
+60
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 0 0
+BITMAP
+20
+60
+a0
+f0
+20
+20
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+e0
+80
+c0
+20
+20
+c0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+60
+80
+c0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+e0
+a0
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+a0
+e0
+20
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 4 1 0
+BITMAP
+80
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 -2
+BITMAP
+40
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+18
+60
+c0
+60
+18
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+BITMAP
+f0
+00
+f0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+c0
+30
+18
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+20
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+50
+a0
+00
+f0
+00
+f0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+70
+50
+70
+50
+d8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+e0
+50
+60
+50
+50
+e0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+88
+50
+20
+20
+50
+88
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+50
+50
+88
+88
+f8
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+40
+70
+40
+40
+f0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+70
+20
+a8
+a8
+20
+70
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+50
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+48
+78
+48
+48
+d8
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 6 0 0
+BITMAP
+c0
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+60
+50
+38
+d0
+50
+60
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+50
+60
+60
+50
+d8
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+20
+30
+48
+48
+48
+cc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 6 0 0
+BITMAP
+c6
+44
+6c
+54
+54
+d6
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+48
+68
+78
+58
+c8
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+d8
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+fc
+48
+48
+48
+48
+d8
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+d8
+a8
+a8
+d8
+70
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+e0
+50
+50
+60
+40
+e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+90
+40
+40
+90
+f0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+50
+40
+40
+40
+60
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+d8
+48
+50
+20
+20
+70
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+60
+80
+80
+40
+20
+40
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 6 1 0
+BITMAP
+20
+50
+88
+88
+50
+d8
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+70
+00
+70
+00
+88
+f8
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 7 6 0 0
+BITMAP
+d6
+54
+54
+7c
+10
+38
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+f0
+90
+20
+40
+90
+f0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 -2
+BITMAP
+c0
+80
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 4 1 0
+BITMAP
+40
+00
+00
+90
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 1 -2
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+40
+40
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 1 0 -2
+BITMAP
+f0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 5 1 0 7
+BITMAP
+f8
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 4 0 0
+BITMAP
+50
+b0
+a0
+50
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+40
+a0
+a0
+c0
+a0
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+b0
+a0
+40
+40
+a0
+b0
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+80
+40
+a0
+a0
+c0
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+60
+e0
+80
+60
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 -2
+BITMAP
+40
+40
+60
+d0
+d0
+60
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+50
+d0
+60
+20
+40
+40
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+60
+d0
+50
+50
+10
+10
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 4 0 0
+BITMAP
+c0
+40
+40
+40
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+a0
+d0
+d0
+60
+40
+40
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+50
+f0
+60
+50
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+80
+c0
+40
+20
+60
+90
+98
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 -2
+BITMAP
+a0
+a0
+a0
+d0
+80
+c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+90
+90
+e0
+40
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+f0
+50
+50
+d0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+40
+a0
+e0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+40
+a0
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+70
+a0
+a0
+40
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+e0
+40
+40
+60
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+50
+d0
+50
+60
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+f8
+a8
+a8
+a8
+58
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+88
+a8
+a8
+58
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+80
+e0
+40
+60
+80
+80
+40
+20
+60
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -2
+BITMAP
+a8
+a8
+a8
+70
+20
+20
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+80
+e0
+40
+80
+80
+80
+40
+20
+60
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 1 -2
+BITMAP
+20
+40
+40
+40
+80
+40
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 8 0 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 1 -2
+BITMAP
+80
+40
+40
+40
+20
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 2 0 1
+BITMAP
+50
+a0
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 3 0 4
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 4 7 -1 0
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 3 0 1
+BITMAP
+00
+00
+00
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 8 0 -2
+BITMAP
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 -1
+BITMAP
+00
+90
+a0
+40
+40
+40
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 -1
+BITMAP
+40
+40
+40
+80
+30
+40
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 1 -1
+BITMAP
+80
+70
+00
+f0
+10
+20
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+20
+40
+40
+40
+80
+50
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+a8
+50
+30
+40
+e0
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 11 0 -3
+BITMAP
+60
+60
+f0
+f0
+40
+40
+20
+70
+f8
+f0
+60
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+40
+48
+d8
+f8
+f0
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 10 0 -2
+BITMAP
+60
+40
+20
+60
+f0
+f0
+50
+40
+20
+40
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 0 3
+BITMAP
+e0
+40
+20
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 6 0 0
+BITMAP
+20
+40
+f8
+40
+20
+20
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 4 3 0 4
+BITMAP
+70
+a0
+20
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 6 0 0
+BITMAP
+20
+20
+20
+20
+20
+20
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+20
+00
+00
+f0
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 3 0 1
+BITMAP
+00
+00
+20
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+20
+20
+20
+20
+20
+a0
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 0 1
+BITMAP
+60
+20
+40
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+a0
+40
+20
+20
+f0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 -2
+BITMAP
+20
+20
+f0
+50
+50
+a0
+c0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+20
+10
+e0
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+90
+60
+60
+90
+50
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 1 1 0
+BITMAP
+a0
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 1 11 2 -3
+BITMAP
+00
+00
+80
+00
+00
+80
+80
+00
+00
+80
+00
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 1 0 2
+BITMAP
+60
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+00
+f0
+00
+60
+20
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+f0
+20
+f0
+40
+40
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+f0
+00
+f0
+00
+f0
+50
+a0
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+00
+50
+a0
+a8
+80
+80
+80
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 5 7 1 -2
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+80
+f8
+08
+08
+48
+f8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+40
+d8
+48
+68
+78
+d8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 -1
+BITMAP
+c8
+78
+88
+90
+10
+08
+c8
+78
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+58
+a0
+a0
+38
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+28
+68
+c8
+40
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+98
+a8
+c8
+70
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -2
+BITMAP
+c0
+40
+70
+d8
+a8
+a8
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -1
+BITMAP
+d8
+70
+70
+a8
+f8
+a8
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+a8
+70
+08
+70
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 -2
+BITMAP
+98
+a8
+a8
+c8
+70
+80
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 4 1 0
+BITMAP
+70
+80
+80
+80
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 6 1 -1
+BITMAP
+80
+80
+80
+70
+f0
+00
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+08
+f0
+f0
+08
+08
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+f0
+00
+f8
+08
+78
+90
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+a0
+78
+40
+78
+80
+80
+78
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+78
+80
+80
+78
+00
+f8
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 4 0 2
+BITMAP
+f0
+80
+70
+20
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 8 0 -1
+BITMAP
+70
+f0
+c0
+70
+40
+08
+10
+20
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 8 0 0
+BITMAP
+40
+f8
+f8
+88
+88
+50
+70
+20
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 2
+BITMAP
+00
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 3 0 0
+BITMAP
+c8
+b8
+b0
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+a0
+c0
+70
+70
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+80
+b0
+a0
+b0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 1080 0
+DWIDTH 9 0
+BBX 8 4 0 0
+BITMAP
+88
+70
+fc
+5a
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 4 0 0
+BITMAP
+5a
+5a
+fc
+48
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+40
+40
+40
+40
+40
+c0
+00
+00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 4 0 0
+BITMAP
+10
+10
+a0
+a0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+40
+40
+80
+f0
+00
+00
+20
+50
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+90
+90
+90
+90
+a0
+40
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 -2
+BITMAP
+00
+40
+c0
+00
+00
+c0
+40
+00
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+40
+60
+f0
+60
+60
+60
+60
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+60
+08
+f8
+f8
+08
+60
+60
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 4 0 2
+BITMAP
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 -1
+BITMAP
+60
+40
+20
+50
+c8
+c8
+50
+20
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 1 -3
+BITMAP
+40
+40
+80
+80
+80
+80
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+80
+00
+00
+80
+80
+80
+80
+80
+00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 1 -3
+BITMAP
+c0
+40
+40
+40
+c0
+80
+40
+40
+00
+40
+80
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 11 1 -3
+BITMAP
+e0
+40
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 1 -3
+BITMAP
+40
+c0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 1 11 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 0 -2
+BITMAP
+80
+40
+40
+40
+40
+80
+40
+40
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 11 1 -3
+BITMAP
+40
+40
+40
+40
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 3 11 1 -3
+BITMAP
+80
+80
+80
+40
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 1 11 -1 -3
+BITMAP
+80
+80
+80
+80
+00
+80
+80
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 3 11 -1 -3
+BITMAP
+80
+80
+20
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+40
+80
+40
+40
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+00
+00
+00
+00
+00
+00
+00
+00
+00
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+c0
+c0
+80
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 11 1 -3
+BITMAP
+00
+00
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 0 -3
+BITMAP
+40
+80
+c0
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 1 -3
+BITMAP
+40
+40
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 11 0 -3
+BITMAP
+80
+80
+40
+40
+40
+40
+40
+40
+40
+40
+40
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol8.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol8.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/symbol8.h	(revision 16632)
@@ -0,0 +1,769 @@
+static unsigned char symbol8_0_bits[] = {
+0x00};
+static unsigned char symbol8_1_bits[] = {
+0x00};
+static unsigned char symbol8_2_bits[] = {
+0x00};
+static unsigned char symbol8_3_bits[] = {
+0x00};
+static unsigned char symbol8_4_bits[] = {
+0x00};
+static unsigned char symbol8_5_bits[] = {
+0x00};
+static unsigned char symbol8_6_bits[] = {
+0x00};
+static unsigned char symbol8_7_bits[] = {
+0x00};
+static unsigned char symbol8_8_bits[] = {
+0x00};
+static unsigned char symbol8_9_bits[] = {
+0x00};
+static unsigned char symbol8_10_bits[] = {
+0x00};
+static unsigned char symbol8_11_bits[] = {
+0x00};
+static unsigned char symbol8_12_bits[] = {
+0x00};
+static unsigned char symbol8_13_bits[] = {
+0x00};
+static unsigned char symbol8_14_bits[] = {
+0x00};
+static unsigned char symbol8_15_bits[] = {
+0x00};
+static unsigned char symbol8_16_bits[] = {
+0x00};
+static unsigned char symbol8_17_bits[] = {
+0x00};
+static unsigned char symbol8_18_bits[] = {
+0x00};
+static unsigned char symbol8_19_bits[] = {
+0x00};
+static unsigned char symbol8_20_bits[] = {
+0x00};
+static unsigned char symbol8_21_bits[] = {
+0x00};
+static unsigned char symbol8_22_bits[] = {
+0x00};
+static unsigned char symbol8_23_bits[] = {
+0x00};
+static unsigned char symbol8_24_bits[] = {
+0x00};
+static unsigned char symbol8_25_bits[] = {
+0x00};
+static unsigned char symbol8_26_bits[] = {
+0x00};
+static unsigned char symbol8_27_bits[] = {
+0x00};
+static unsigned char symbol8_28_bits[] = {
+0x00};
+static unsigned char symbol8_29_bits[] = {
+0x00};
+static unsigned char symbol8_30_bits[] = {
+0x00};
+static unsigned char symbol8_31_bits[] = {
+0x00};
+static unsigned char symbol8_32_bits[] = {
+0x00};
+static unsigned char symbol8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char symbol8_34_bits[] = {
+0x11, 0x11, 0x0e, 0x0a, 0x04, 0x04};
+static unsigned char symbol8_35_bits[] = {
+0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a};
+static unsigned char symbol8_36_bits[] = {
+0x0f, 0x08, 0x08, 0x0e, 0x08, 0x0f};
+static unsigned char symbol8_37_bits[] = {
+0x13, 0x0b, 0x04, 0x1a, 0x19};
+static unsigned char symbol8_38_bits[] = {
+0x06, 0x0a, 0x04, 0x1f, 0x05, 0x1a};
+static unsigned char symbol8_39_bits[] = {
+0x03, 0x06, 0x04, 0x03};
+static unsigned char symbol8_40_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char symbol8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol8_42_bits[] = {
+0x02, 0x07, 0x05};
+static unsigned char symbol8_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char symbol8_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char symbol8_45_bits[] = {
+0x1f};
+static unsigned char symbol8_46_bits[] = {
+0x01};
+static unsigned char symbol8_47_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char symbol8_48_bits[] = {
+0x02, 0x05, 0x05, 0x05, 0x05, 0x02};
+static unsigned char symbol8_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char symbol8_50_bits[] = {
+0x02, 0x05, 0x04, 0x02, 0x01, 0x07};
+static unsigned char symbol8_51_bits[] = {
+0x02, 0x05, 0x04, 0x06, 0x04, 0x03};
+static unsigned char symbol8_52_bits[] = {
+0x04, 0x06, 0x05, 0x0f, 0x04, 0x04};
+static unsigned char symbol8_53_bits[] = {
+0x07, 0x01, 0x03, 0x04, 0x04, 0x03};
+static unsigned char symbol8_54_bits[] = {
+0x06, 0x01, 0x03, 0x05, 0x05, 0x02};
+static unsigned char symbol8_55_bits[] = {
+0x07, 0x05, 0x04, 0x02, 0x02, 0x02};
+static unsigned char symbol8_56_bits[] = {
+0x02, 0x05, 0x02, 0x05, 0x05, 0x02};
+static unsigned char symbol8_57_bits[] = {
+0x02, 0x05, 0x05, 0x07, 0x04, 0x03};
+static unsigned char symbol8_58_bits[] = {
+0x01, 0x00, 0x00, 0x01};
+static unsigned char symbol8_59_bits[] = {
+0x02, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char symbol8_60_bits[] = {
+0x18, 0x06, 0x03, 0x06, 0x18};
+static unsigned char symbol8_61_bits[] = {
+0x0f, 0x00, 0x0f};
+static unsigned char symbol8_62_bits[] = {
+0x03, 0x0c, 0x18, 0x0c, 0x03};
+static unsigned char symbol8_63_bits[] = {
+0x02, 0x05, 0x04, 0x02, 0x00, 0x02};
+static unsigned char symbol8_64_bits[] = {
+0x0a, 0x05, 0x00, 0x0f, 0x00, 0x0f};
+static unsigned char symbol8_65_bits[] = {
+0x04, 0x0e, 0x0a, 0x0e, 0x0a, 0x1b};
+static unsigned char symbol8_66_bits[] = {
+0x07, 0x0a, 0x06, 0x0a, 0x0a, 0x07};
+static unsigned char symbol8_67_bits[] = {
+0x11, 0x0a, 0x04, 0x04, 0x0a, 0x11};
+static unsigned char symbol8_68_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11, 0x1f};
+static unsigned char symbol8_69_bits[] = {
+0x0f, 0x02, 0x0e, 0x02, 0x02, 0x0f};
+static unsigned char symbol8_70_bits[] = {
+0x0e, 0x04, 0x15, 0x15, 0x04, 0x0e};
+static unsigned char symbol8_71_bits[] = {
+0x0f, 0x0a, 0x02, 0x02, 0x02, 0x03};
+static unsigned char symbol8_72_bits[] = {
+0x1b, 0x12, 0x1e, 0x12, 0x12, 0x1b};
+static unsigned char symbol8_73_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char symbol8_74_bits[] = {
+0x06, 0x0a, 0x1c, 0x0b, 0x0a, 0x06};
+static unsigned char symbol8_75_bits[] = {
+0x1b, 0x0a, 0x06, 0x06, 0x0a, 0x1b};
+static unsigned char symbol8_76_bits[] = {
+0x04, 0x0c, 0x12, 0x12, 0x12, 0x33};
+static unsigned char symbol8_77_bits[] = {
+0x63, 0x22, 0x36, 0x2a, 0x2a, 0x6b};
+static unsigned char symbol8_78_bits[] = {
+0x1b, 0x12, 0x16, 0x1e, 0x1a, 0x13};
+static unsigned char symbol8_79_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char symbol8_80_bits[] = {
+0x3f, 0x12, 0x12, 0x12, 0x12, 0x1b};
+static unsigned char symbol8_81_bits[] = {
+0x0e, 0x1b, 0x15, 0x15, 0x1b, 0x0e};
+static unsigned char symbol8_82_bits[] = {
+0x07, 0x0a, 0x0a, 0x06, 0x02, 0x07};
+static unsigned char symbol8_83_bits[] = {
+0x0f, 0x09, 0x02, 0x02, 0x09, 0x0f};
+static unsigned char symbol8_84_bits[] = {
+0x0f, 0x0a, 0x02, 0x02, 0x02, 0x06};
+static unsigned char symbol8_85_bits[] = {
+0x1b, 0x12, 0x0a, 0x04, 0x04, 0x0e};
+static unsigned char symbol8_86_bits[] = {
+0x06, 0x01, 0x01, 0x02, 0x04, 0x02};
+static unsigned char symbol8_87_bits[] = {
+0x04, 0x0a, 0x11, 0x11, 0x0a, 0x1b};
+static unsigned char symbol8_88_bits[] = {
+0x0e, 0x00, 0x0e, 0x00, 0x11, 0x1f};
+static unsigned char symbol8_89_bits[] = {
+0x6b, 0x2a, 0x2a, 0x3e, 0x08, 0x1c};
+static unsigned char symbol8_90_bits[] = {
+0x0f, 0x09, 0x04, 0x02, 0x09, 0x0f};
+static unsigned char symbol8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char symbol8_92_bits[] = {
+0x02, 0x00, 0x00, 0x09};
+static unsigned char symbol8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char symbol8_94_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char symbol8_95_bits[] = {
+0x0f};
+static unsigned char symbol8_96_bits[] = {
+0x1f};
+static unsigned char symbol8_97_bits[] = {
+0x0a, 0x0d, 0x05, 0x0a};
+static unsigned char symbol8_98_bits[] = {
+0x02, 0x05, 0x05, 0x03, 0x05, 0x05, 0x03, 0x01, 0x01};
+static unsigned char symbol8_99_bits[] = {
+0x0d, 0x05, 0x02, 0x02, 0x05, 0x0d};
+static unsigned char symbol8_100_bits[] = {
+0x02, 0x05, 0x01, 0x02, 0x05, 0x05, 0x03};
+static unsigned char symbol8_101_bits[] = {
+0x06, 0x07, 0x01, 0x06};
+static unsigned char symbol8_102_bits[] = {
+0x02, 0x02, 0x06, 0x0b, 0x0b, 0x06, 0x02, 0x02};
+static unsigned char symbol8_103_bits[] = {
+0x0a, 0x0b, 0x06, 0x04, 0x02, 0x02};
+static unsigned char symbol8_104_bits[] = {
+0x06, 0x0b, 0x0a, 0x0a, 0x08, 0x08};
+static unsigned char symbol8_105_bits[] = {
+0x03, 0x02, 0x02, 0x02};
+static unsigned char symbol8_106_bits[] = {
+0x05, 0x0b, 0x0b, 0x06, 0x02, 0x02};
+static unsigned char symbol8_107_bits[] = {
+0x0a, 0x0f, 0x06, 0x0a};
+static unsigned char symbol8_108_bits[] = {
+0x01, 0x03, 0x02, 0x04, 0x06, 0x09, 0x19};
+static unsigned char symbol8_109_bits[] = {
+0x05, 0x05, 0x05, 0x0b, 0x01, 0x03};
+static unsigned char symbol8_110_bits[] = {
+0x09, 0x09, 0x07, 0x02};
+static unsigned char symbol8_111_bits[] = {
+0x02, 0x05, 0x05, 0x02};
+static unsigned char symbol8_112_bits[] = {
+0x0f, 0x0a, 0x0a, 0x0b};
+static unsigned char symbol8_113_bits[] = {
+0x02, 0x05, 0x07, 0x05, 0x05, 0x02};
+static unsigned char symbol8_114_bits[] = {
+0x02, 0x05, 0x05, 0x03, 0x01, 0x01};
+static unsigned char symbol8_115_bits[] = {
+0x0e, 0x05, 0x05, 0x02};
+static unsigned char symbol8_116_bits[] = {
+0x07, 0x02, 0x02, 0x06};
+static unsigned char symbol8_117_bits[] = {
+0x0a, 0x0b, 0x0a, 0x06};
+static unsigned char symbol8_118_bits[] = {
+0x1f, 0x15, 0x15, 0x15, 0x1a};
+static unsigned char symbol8_119_bits[] = {
+0x11, 0x15, 0x15, 0x1a};
+static unsigned char symbol8_120_bits[] = {
+0x01, 0x07, 0x02, 0x06, 0x01, 0x01, 0x02, 0x04, 0x06};
+static unsigned char symbol8_121_bits[] = {
+0x15, 0x15, 0x15, 0x0e, 0x04, 0x04};
+static unsigned char symbol8_122_bits[] = {
+0x01, 0x07, 0x02, 0x01, 0x01, 0x01, 0x02, 0x04, 0x06};
+static unsigned char symbol8_123_bits[] = {
+0x04, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x04};
+static unsigned char symbol8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_125_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x04, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol8_126_bits[] = {
+0x0a, 0x05};
+static unsigned char symbol8_127_bits[] = {
+0x00};
+static unsigned char symbol8_128_bits[] = {
+0x00};
+static unsigned char symbol8_129_bits[] = {
+0x00};
+static unsigned char symbol8_130_bits[] = {
+0x00};
+static unsigned char symbol8_131_bits[] = {
+0x00};
+static unsigned char symbol8_132_bits[] = {
+0x00};
+static unsigned char symbol8_133_bits[] = {
+0x00};
+static unsigned char symbol8_134_bits[] = {
+0x00};
+static unsigned char symbol8_135_bits[] = {
+0x00};
+static unsigned char symbol8_136_bits[] = {
+0x00};
+static unsigned char symbol8_137_bits[] = {
+0x00};
+static unsigned char symbol8_138_bits[] = {
+0x00};
+static unsigned char symbol8_139_bits[] = {
+0x00};
+static unsigned char symbol8_140_bits[] = {
+0x00};
+static unsigned char symbol8_141_bits[] = {
+0x00};
+static unsigned char symbol8_142_bits[] = {
+0x00};
+static unsigned char symbol8_143_bits[] = {
+0x00};
+static unsigned char symbol8_144_bits[] = {
+0x00};
+static unsigned char symbol8_145_bits[] = {
+0x00};
+static unsigned char symbol8_146_bits[] = {
+0x00};
+static unsigned char symbol8_147_bits[] = {
+0x00};
+static unsigned char symbol8_148_bits[] = {
+0x00};
+static unsigned char symbol8_149_bits[] = {
+0x00};
+static unsigned char symbol8_150_bits[] = {
+0x00};
+static unsigned char symbol8_151_bits[] = {
+0x00};
+static unsigned char symbol8_152_bits[] = {
+0x00};
+static unsigned char symbol8_153_bits[] = {
+0x00};
+static unsigned char symbol8_154_bits[] = {
+0x00};
+static unsigned char symbol8_155_bits[] = {
+0x00};
+static unsigned char symbol8_156_bits[] = {
+0x00};
+static unsigned char symbol8_157_bits[] = {
+0x00};
+static unsigned char symbol8_158_bits[] = {
+0x00};
+static unsigned char symbol8_159_bits[] = {
+0x00};
+static unsigned char symbol8_160_bits[] = {
+0x00};
+static unsigned char symbol8_161_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_162_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol8_163_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_164_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_165_bits[] = {
+0x00, 0x00, 0x00};
+static unsigned char symbol8_166_bits[] = {
+0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_167_bits[] = {
+0x00, 0x09, 0x05, 0x02, 0x02, 0x02};
+static unsigned char symbol8_168_bits[] = {
+0x02, 0x02, 0x02, 0x01, 0x0c, 0x02};
+static unsigned char symbol8_169_bits[] = {
+0x01, 0x0e, 0x00, 0x0f, 0x08, 0x04};
+static unsigned char symbol8_170_bits[] = {
+0x04, 0x02, 0x02, 0x02, 0x01, 0x0a};
+static unsigned char symbol8_171_bits[] = {
+0x15, 0x0a, 0x0c, 0x02, 0x07};
+static unsigned char symbol8_172_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char symbol8_173_bits[] = {
+0x06, 0x06, 0x0f, 0x0f, 0x02, 0x02, 0x04, 0x0e, 0x1f, 0x0f, 0x06};
+static unsigned char symbol8_174_bits[] = {
+0x02, 0x12, 0x1b, 0x1f, 0x0f};
+static unsigned char symbol8_175_bits[] = {
+0x06, 0x02, 0x04, 0x06, 0x0f, 0x0f, 0x0a, 0x02, 0x04, 0x02};
+static unsigned char symbol8_176_bits[] = {
+0x07, 0x02, 0x04};
+static unsigned char symbol8_177_bits[] = {
+0x04, 0x02, 0x1f, 0x02, 0x04, 0x04};
+static unsigned char symbol8_178_bits[] = {
+0x0e, 0x05, 0x04};
+static unsigned char symbol8_179_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04, 0x04};
+static unsigned char symbol8_180_bits[] = {
+0x04, 0x00, 0x00, 0x0f};
+static unsigned char symbol8_181_bits[] = {
+0x00, 0x00, 0x04};
+static unsigned char symbol8_182_bits[] = {
+0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05};
+static unsigned char symbol8_183_bits[] = {
+0x06, 0x04, 0x02};
+static unsigned char symbol8_184_bits[] = {
+0x05, 0x02, 0x04, 0x04, 0x0f};
+static unsigned char symbol8_185_bits[] = {
+0x04, 0x04, 0x0f, 0x0a, 0x0a, 0x05, 0x03};
+static unsigned char symbol8_186_bits[] = {
+0x04, 0x08, 0x07, 0x00, 0x0f};
+static unsigned char symbol8_187_bits[] = {
+0x09, 0x06, 0x06, 0x09, 0x0a};
+static unsigned char symbol8_188_bits[] = {
+0x05};
+static unsigned char symbol8_189_bits[] = {
+0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00};
+static unsigned char symbol8_190_bits[] = {
+0x06};
+static unsigned char symbol8_191_bits[] = {
+0x00, 0x0f, 0x00, 0x06, 0x04};
+static unsigned char symbol8_192_bits[] = {
+0x04, 0x0f, 0x04, 0x0f, 0x02, 0x02};
+static unsigned char symbol8_193_bits[] = {
+0x0f, 0x00, 0x0f, 0x00, 0x0f, 0x0a, 0x05};
+static unsigned char symbol8_194_bits[] = {
+0x00, 0x0a, 0x05, 0x15, 0x01, 0x01, 0x01};
+static unsigned char symbol8_195_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_196_bits[] = {
+0x01, 0x1f, 0x10, 0x10, 0x12, 0x1f};
+static unsigned char symbol8_197_bits[] = {
+0x02, 0x1b, 0x12, 0x16, 0x1e, 0x1b};
+static unsigned char symbol8_198_bits[] = {
+0x13, 0x1e, 0x11, 0x09, 0x08, 0x10, 0x13, 0x1e};
+static unsigned char symbol8_199_bits[] = {
+0x1a, 0x05, 0x05, 0x1c};
+static unsigned char symbol8_200_bits[] = {
+0x14, 0x16, 0x13, 0x02};
+static unsigned char symbol8_201_bits[] = {
+0x19, 0x15, 0x13, 0x0e};
+static unsigned char symbol8_202_bits[] = {
+0x03, 0x02, 0x0e, 0x1b, 0x15, 0x15};
+static unsigned char symbol8_203_bits[] = {
+0x1b, 0x0e, 0x0e, 0x15, 0x1f, 0x15};
+static unsigned char symbol8_204_bits[] = {
+0x15, 0x0e, 0x10, 0x0e};
+static unsigned char symbol8_205_bits[] = {
+0x19, 0x15, 0x15, 0x13, 0x0e, 0x01};
+static unsigned char symbol8_206_bits[] = {
+0x0e, 0x01, 0x01, 0x01};
+static unsigned char symbol8_207_bits[] = {
+0x01, 0x01, 0x01, 0x0e, 0x0f, 0x00};
+static unsigned char symbol8_208_bits[] = {
+0x10, 0x0f, 0x0f, 0x10, 0x10};
+static unsigned char symbol8_209_bits[] = {
+0x0f, 0x00, 0x1f, 0x10, 0x1e, 0x09};
+static unsigned char symbol8_210_bits[] = {
+0x05, 0x1e, 0x02, 0x1e, 0x01, 0x01, 0x1e};
+static unsigned char symbol8_211_bits[] = {
+0x1e, 0x01, 0x01, 0x1e, 0x00, 0x1f, 0x0e};
+static unsigned char symbol8_212_bits[] = {
+0x0f, 0x01, 0x0e, 0x04};
+static unsigned char symbol8_213_bits[] = {
+0x0e, 0x0f, 0x03, 0x0e, 0x02, 0x10, 0x08, 0x04};
+static unsigned char symbol8_214_bits[] = {
+0x02, 0x1f, 0x1f, 0x11, 0x11, 0x0a, 0x0e, 0x04};
+static unsigned char symbol8_215_bits[] = {
+0x00};
+static unsigned char symbol8_216_bits[] = {
+0x13, 0x1d, 0x0d};
+static unsigned char symbol8_217_bits[] = {
+0x05, 0x03, 0x0e, 0x0e};
+static unsigned char symbol8_218_bits[] = {
+0x01, 0x0d, 0x05, 0x0d};
+static unsigned char symbol8_219_bits[] = {
+0x11, 0x0e, 0x3f, 0x5a};
+static unsigned char symbol8_220_bits[] = {
+0x5a, 0x5a, 0x3f, 0x12};
+static unsigned char symbol8_221_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00};
+static unsigned char symbol8_222_bits[] = {
+0x08, 0x08, 0x05, 0x05};
+static unsigned char symbol8_223_bits[] = {
+0x02, 0x02, 0x01, 0x0f, 0x00, 0x00, 0x04, 0x0a};
+static unsigned char symbol8_224_bits[] = {
+0x09, 0x09, 0x09, 0x09, 0x05, 0x02};
+static unsigned char symbol8_225_bits[] = {
+0x00, 0x02, 0x03, 0x00, 0x00, 0x03, 0x02, 0x00};
+static unsigned char symbol8_226_bits[] = {
+0x02, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x06};
+static unsigned char symbol8_227_bits[] = {
+0x06, 0x10, 0x1f, 0x1f, 0x10, 0x06, 0x06};
+static unsigned char symbol8_228_bits[] = {
+0x06, 0x06, 0x06, 0x0f};
+static unsigned char symbol8_229_bits[] = {
+0x06, 0x02, 0x04, 0x0a, 0x13, 0x13, 0x0a, 0x04};
+static unsigned char symbol8_230_bits[] = {
+0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char symbol8_231_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00};
+static unsigned char symbol8_232_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01};
+static unsigned char symbol8_233_bits[] = {
+0x07, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_234_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_235_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_236_bits[] = {
+0x02, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_237_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_238_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_239_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_240_bits[] = {
+0x00};
+static unsigned char symbol8_241_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02};
+static unsigned char symbol8_242_bits[] = {
+0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_243_bits[] = {
+0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_244_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_245_bits[] = {
+0x01, 0x01, 0x04, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_246_bits[] = {
+0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_247_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_248_bits[] = {
+0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+static unsigned char symbol8_249_bits[] = {
+0x03, 0x03, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_250_bits[] = {
+0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_251_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_252_bits[] = {
+0x02, 0x01, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_253_bits[] = {
+0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char symbol8_254_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char symbol8_255_bits[] = {
+0x00};
+static RotFont symbol8font[] = {
+{5, 1, 1, symbol8_0_bits},
+{5, 1, 1, symbol8_1_bits},
+{5, 1, 1, symbol8_2_bits},
+{5, 1, 1, symbol8_3_bits},
+{5, 1, 1, symbol8_4_bits},
+{5, 1, 1, symbol8_5_bits},
+{5, 1, 1, symbol8_6_bits},
+{5, 1, 1, symbol8_7_bits},
+{5, 1, 1, symbol8_8_bits},
+{5, 1, 1, symbol8_9_bits},
+{5, 1, 1, symbol8_10_bits},
+{5, 1, 1, symbol8_11_bits},
+{5, 1, 1, symbol8_12_bits},
+{5, 1, 1, symbol8_13_bits},
+{5, 1, 1, symbol8_14_bits},
+{5, 1, 1, symbol8_15_bits},
+{5, 1, 1, symbol8_16_bits},
+{5, 1, 1, symbol8_17_bits},
+{5, 1, 1, symbol8_18_bits},
+{5, 1, 1, symbol8_19_bits},
+{5, 1, 1, symbol8_20_bits},
+{5, 1, 1, symbol8_21_bits},
+{5, 1, 1, symbol8_22_bits},
+{5, 1, 1, symbol8_23_bits},
+{5, 1, 1, symbol8_24_bits},
+{5, 1, 1, symbol8_25_bits},
+{5, 1, 1, symbol8_26_bits},
+{5, 1, 1, symbol8_27_bits},
+{5, 1, 1, symbol8_28_bits},
+{5, 1, 1, symbol8_29_bits},
+{5, 1, 1, symbol8_30_bits},
+{5, 1, 1, symbol8_31_bits},
+{1, 1, 1, symbol8_32_bits},
+{1, 6, 6, symbol8_33_bits},
+{5, 6, 6, symbol8_34_bits},
+{5, 6, 6, symbol8_35_bits},
+{4, 6, 6, symbol8_36_bits},
+{5, 5, 5, symbol8_37_bits},
+{5, 6, 6, symbol8_38_bits},
+{3, 4, 4, symbol8_39_bits},
+{2, 8, 6, symbol8_40_bits},
+{2, 8, 6, symbol8_41_bits},
+{3, 3, 5, symbol8_42_bits},
+{5, 5, 5, symbol8_43_bits},
+{2, 3, 1, symbol8_44_bits},
+{5, 1, 3, symbol8_45_bits},
+{1, 1, 1, symbol8_46_bits},
+{2, 6, 6, symbol8_47_bits},
+{3, 6, 6, symbol8_48_bits},
+{3, 6, 6, symbol8_49_bits},
+{3, 6, 6, symbol8_50_bits},
+{3, 6, 6, symbol8_51_bits},
+{4, 6, 6, symbol8_52_bits},
+{3, 6, 6, symbol8_53_bits},
+{3, 6, 6, symbol8_54_bits},
+{3, 6, 6, symbol8_55_bits},
+{3, 6, 6, symbol8_56_bits},
+{3, 6, 6, symbol8_57_bits},
+{1, 4, 4, symbol8_58_bits},
+{2, 6, 4, symbol8_59_bits},
+{5, 5, 5, symbol8_60_bits},
+{4, 3, 4, symbol8_61_bits},
+{5, 5, 5, symbol8_62_bits},
+{3, 6, 6, symbol8_63_bits},
+{4, 6, 6, symbol8_64_bits},
+{5, 6, 6, symbol8_65_bits},
+{4, 6, 6, symbol8_66_bits},
+{5, 6, 6, symbol8_67_bits},
+{5, 6, 6, symbol8_68_bits},
+{4, 6, 6, symbol8_69_bits},
+{5, 6, 6, symbol8_70_bits},
+{4, 6, 6, symbol8_71_bits},
+{5, 6, 6, symbol8_72_bits},
+{2, 6, 6, symbol8_73_bits},
+{5, 6, 6, symbol8_74_bits},
+{5, 6, 6, symbol8_75_bits},
+{6, 6, 6, symbol8_76_bits},
+{7, 6, 6, symbol8_77_bits},
+{5, 6, 6, symbol8_78_bits},
+{5, 6, 6, symbol8_79_bits},
+{6, 6, 6, symbol8_80_bits},
+{5, 6, 6, symbol8_81_bits},
+{4, 6, 6, symbol8_82_bits},
+{4, 6, 6, symbol8_83_bits},
+{4, 6, 6, symbol8_84_bits},
+{5, 6, 6, symbol8_85_bits},
+{3, 6, 4, symbol8_86_bits},
+{5, 6, 6, symbol8_87_bits},
+{5, 6, 6, symbol8_88_bits},
+{7, 6, 6, symbol8_89_bits},
+{4, 6, 6, symbol8_90_bits},
+{2, 8, 6, symbol8_91_bits},
+{4, 4, 4, symbol8_92_bits},
+{2, 8, 6, symbol8_93_bits},
+{4, 6, 6, symbol8_94_bits},
+{4, 1, -1, symbol8_95_bits},
+{5, 1, 8, symbol8_96_bits},
+{4, 4, 4, symbol8_97_bits},
+{3, 9, 7, symbol8_98_bits},
+{4, 6, 4, symbol8_99_bits},
+{3, 7, 7, symbol8_100_bits},
+{3, 4, 4, symbol8_101_bits},
+{4, 8, 6, symbol8_102_bits},
+{4, 6, 4, symbol8_103_bits},
+{4, 6, 4, symbol8_104_bits},
+{2, 4, 4, symbol8_105_bits},
+{4, 6, 4, symbol8_106_bits},
+{4, 4, 4, symbol8_107_bits},
+{5, 7, 7, symbol8_108_bits},
+{4, 6, 4, symbol8_109_bits},
+{4, 4, 4, symbol8_110_bits},
+{3, 4, 4, symbol8_111_bits},
+{4, 4, 4, symbol8_112_bits},
+{3, 6, 6, symbol8_113_bits},
+{3, 6, 4, symbol8_114_bits},
+{4, 4, 4, symbol8_115_bits},
+{3, 4, 4, symbol8_116_bits},
+{4, 4, 4, symbol8_117_bits},
+{5, 5, 5, symbol8_118_bits},
+{5, 4, 4, symbol8_119_bits},
+{3, 9, 7, symbol8_120_bits},
+{5, 6, 4, symbol8_121_bits},
+{3, 9, 7, symbol8_122_bits},
+{3, 9, 7, symbol8_123_bits},
+{1, 8, 6, symbol8_124_bits},
+{3, 9, 7, symbol8_125_bits},
+{4, 2, 3, symbol8_126_bits},
+{5, 1, 1, symbol8_127_bits},
+{5, 1, 1, symbol8_128_bits},
+{5, 1, 1, symbol8_129_bits},
+{5, 1, 1, symbol8_130_bits},
+{5, 1, 1, symbol8_131_bits},
+{5, 1, 1, symbol8_132_bits},
+{5, 1, 1, symbol8_133_bits},
+{5, 1, 1, symbol8_134_bits},
+{5, 1, 1, symbol8_135_bits},
+{5, 1, 1, symbol8_136_bits},
+{5, 1, 1, symbol8_137_bits},
+{5, 1, 1, symbol8_138_bits},
+{5, 1, 1, symbol8_139_bits},
+{5, 1, 1, symbol8_140_bits},
+{5, 1, 1, symbol8_141_bits},
+{5, 1, 1, symbol8_142_bits},
+{5, 1, 1, symbol8_143_bits},
+{5, 1, 1, symbol8_144_bits},
+{5, 1, 1, symbol8_145_bits},
+{5, 1, 1, symbol8_146_bits},
+{5, 1, 1, symbol8_147_bits},
+{5, 1, 1, symbol8_148_bits},
+{5, 1, 1, symbol8_149_bits},
+{5, 1, 1, symbol8_150_bits},
+{5, 1, 1, symbol8_151_bits},
+{5, 1, 1, symbol8_152_bits},
+{5, 1, 1, symbol8_153_bits},
+{5, 1, 1, symbol8_154_bits},
+{5, 1, 1, symbol8_155_bits},
+{5, 1, 1, symbol8_156_bits},
+{5, 1, 1, symbol8_157_bits},
+{5, 1, 1, symbol8_158_bits},
+{5, 1, 1, symbol8_159_bits},
+{5, 1, 1, symbol8_160_bits},
+{5, 6, 6, symbol8_161_bits},
+{2, 3, 7, symbol8_162_bits},
+{4, 6, 6, symbol8_163_bits},
+{4, 7, 7, symbol8_164_bits},
+{5, 3, 4, symbol8_165_bits},
+{4, 8, 6, symbol8_166_bits},
+{4, 6, 5, symbol8_167_bits},
+{5, 6, 5, symbol8_168_bits},
+{5, 6, 5, symbol8_169_bits},
+{4, 6, 6, symbol8_170_bits},
+{8, 5, 5, symbol8_171_bits},
+{8, 5, 5, symbol8_172_bits},
+{5, 11, 8, symbol8_173_bits},
+{8, 5, 5, symbol8_174_bits},
+{5, 10, 8, symbol8_175_bits},
+{3, 3, 6, symbol8_176_bits},
+{5, 6, 6, symbol8_177_bits},
+{4, 3, 7, symbol8_178_bits},
+{4, 6, 6, symbol8_179_bits},
+{4, 4, 4, symbol8_180_bits},
+{5, 3, 4, symbol8_181_bits},
+{3, 7, 7, symbol8_182_bits},
+{3, 3, 4, symbol8_183_bits},
+{4, 5, 5, symbol8_184_bits},
+{4, 7, 5, symbol8_185_bits},
+{4, 5, 5, symbol8_186_bits},
+{4, 5, 5, symbol8_187_bits},
+{5, 1, 1, symbol8_188_bits},
+{1, 11, 8, symbol8_189_bits},
+{8, 1, 3, symbol8_190_bits},
+{5, 5, 5, symbol8_191_bits},
+{5, 6, 6, symbol8_192_bits},
+{5, 7, 7, symbol8_193_bits},
+{6, 7, 7, symbol8_194_bits},
+{5, 7, 5, symbol8_195_bits},
+{5, 6, 6, symbol8_196_bits},
+{5, 6, 6, symbol8_197_bits},
+{5, 8, 7, symbol8_198_bits},
+{5, 4, 4, symbol8_199_bits},
+{5, 4, 4, symbol8_200_bits},
+{5, 4, 4, symbol8_201_bits},
+{5, 6, 4, symbol8_202_bits},
+{5, 6, 5, symbol8_203_bits},
+{5, 4, 4, symbol8_204_bits},
+{5, 6, 4, symbol8_205_bits},
+{4, 4, 4, symbol8_206_bits},
+{4, 6, 5, symbol8_207_bits},
+{5, 5, 5, symbol8_208_bits},
+{5, 6, 6, symbol8_209_bits},
+{5, 7, 6, symbol8_210_bits},
+{5, 7, 6, symbol8_211_bits},
+{8, 4, 6, symbol8_212_bits},
+{6, 8, 7, symbol8_213_bits},
+{5, 8, 8, symbol8_214_bits},
+{1, 1, 3, symbol8_215_bits},
+{5, 3, 3, symbol8_216_bits},
+{4, 4, 4, symbol8_217_bits},
+{4, 4, 4, symbol8_218_bits},
+{8, 4, 4, symbol8_219_bits},
+{7, 4, 4, symbol8_220_bits},
+{4, 8, 8, symbol8_221_bits},
+{7, 4, 4, symbol8_222_bits},
+{4, 8, 8, symbol8_223_bits},
+{5, 6, 6, symbol8_224_bits},
+{2, 8, 6, symbol8_225_bits},
+{5, 7, 6, symbol8_226_bits},
+{5, 7, 6, symbol8_227_bits},
+{6, 4, 6, symbol8_228_bits},
+{5, 8, 7, symbol8_229_bits},
+{2, 11, 8, symbol8_230_bits},
+{1, 11, 8, symbol8_231_bits},
+{2, 11, 8, symbol8_232_bits},
+{3, 11, 8, symbol8_233_bits},
+{1, 11, 8, symbol8_234_bits},
+{2, 11, 8, symbol8_235_bits},
+{2, 11, 8, symbol8_236_bits},
+{2, 11, 8, symbol8_237_bits},
+{2, 11, 8, symbol8_238_bits},
+{1, 11, 8, symbol8_239_bits},
+{5, 1, 1, symbol8_240_bits},
+{2, 8, 6, symbol8_241_bits},
+{3, 11, 8, symbol8_242_bits},
+{3, 11, 8, symbol8_243_bits},
+{1, 11, 8, symbol8_244_bits},
+{3, 11, 8, symbol8_245_bits},
+{2, 11, 8, symbol8_246_bits},
+{1, 11, 8, symbol8_247_bits},
+{2, 11, 8, symbol8_248_bits},
+{2, 11, 8, symbol8_249_bits},
+{1, 11, 8, symbol8_250_bits},
+{2, 11, 8, symbol8_251_bits},
+{2, 11, 8, symbol8_252_bits},
+{2, 11, 8, symbol8_253_bits},
+{2, 11, 8, symbol8_254_bits},
+{5, 1, 1, symbol8_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times12.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times12.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times12.bdf	(revision 16632)
@@ -0,0 +1,2973 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--12-120-75-75-P-64-ISO8859-1
+SIZE 12 75 75
+FONTBOUNDINGBOX 12 15 0 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 12
+POINT_SIZE 120
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 64
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 9
+X_HEIGHT 6
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--12-120-75-75-P-64-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 7
+DEFAULT_CHAR 32
+FONT_ASCENT 11
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 3 1 6
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+50
+50
+f8
+50
+50
+f8
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 11 0 -1
+BITMAP
+20
+70
+a8
+a0
+60
+30
+28
+28
+a8
+70
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 8 9 1 0
+BITMAP
+63
+9e
+94
+68
+10
+36
+29
+49
+46
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+1800
+2400
+2400
+1b80
+7900
+ce00
+8400
+ce80
+7b00
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 1 -3
+BITMAP
+20
+40
+40
+80
+80
+80
+80
+80
+80
+40
+40
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 12 0 -3
+BITMAP
+80
+40
+40
+20
+20
+20
+20
+20
+20
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 5 0 4
+BITMAP
+20
+a8
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+20
+f8
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 3 0 -2
+BITMAP
+40
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 1 1 3
+BITMAP
+f8
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+d8
+88
+88
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 0 0
+BITMAP
+20
+60
+a0
+20
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+08
+08
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+08
+10
+70
+08
+08
+88
+70
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+10
+30
+30
+50
+50
+90
+f8
+10
+10
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+38
+40
+40
+70
+18
+08
+08
+98
+70
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+18
+60
+40
+f0
+98
+88
+88
+c8
+70
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+f8
+88
+10
+10
+20
+20
+40
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+88
+88
+c8
+70
+98
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+70
+98
+88
+88
+c8
+78
+10
+30
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 6 1 0
+BITMAP
+80
+00
+00
+00
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 8 0 -2
+BITMAP
+40
+00
+00
+00
+00
+40
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 0 1
+BITMAP
+0c
+30
+c0
+30
+0c
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 3 1 2
+BITMAP
+f8
+00
+f8
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 5 1 1
+BITMAP
+c0
+30
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 0 0
+BITMAP
+60
+90
+10
+20
+40
+40
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 10 11 1 -2
+BITMAP
+0f00
+3080
+6040
+4d40
+9240
+a240
+a480
+a480
+9b00
+4000
+3e00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+42
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+3a
+66
+42
+80
+80
+80
+42
+66
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+fc
+46
+42
+41
+41
+41
+42
+46
+fc
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+40
+f0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3a
+66
+42
+80
+87
+82
+42
+66
+3c
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 9 0 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 1 0
+BITMAP
+70
+20
+20
+20
+20
+20
+20
+a0
+c0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+ee
+44
+48
+50
+70
+58
+4c
+46
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+44
+fc
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 11 9 0 0
+BITMAP
+c060
+60c0
+60c0
+5140
+5140
+4a40
+4a40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+c380
+6100
+6100
+5100
+4900
+4900
+4500
+4300
+e100
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 -2
+BITMAP
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+0c
+03
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+fc
+46
+42
+46
+7c
+48
+44
+42
+e3
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+74
+8c
+84
+60
+38
+0c
+84
+cc
+b8
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+fe
+92
+10
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+1400
+1c00
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 12 0
+BBX 12 9 0 0
+BITMAP
+ee70
+4420
+6620
+2240
+3740
+1540
+1980
+0880
+0880
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 1 0
+BITMAP
+e7
+42
+24
+38
+18
+2c
+24
+42
+e7
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+4100
+2200
+1200
+1c00
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+86
+0c
+18
+30
+60
+c0
+82
+fe
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+80
+80
+80
+40
+40
+40
+20
+20
+20
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 5 0 4
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 1 0 -3
+BITMAP
+fc
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 3 1 6
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+c0
+40
+40
+70
+48
+48
+48
+48
+70
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+80
+80
+90
+60
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+30
+10
+10
+70
+90
+90
+90
+90
+68
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 9 0 0
+BITMAP
+20
+40
+40
+e0
+40
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 -3
+BITMAP
+78
+90
+90
+e0
+40
+70
+88
+88
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+c0
+40
+40
+70
+48
+48
+48
+48
+ec
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+00
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 2 12 0 -3
+BITMAP
+40
+00
+00
+c0
+40
+40
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+c0
+40
+40
+48
+50
+60
+50
+48
+4c
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 6 0 0
+BITMAP
+b600
+4900
+4900
+4900
+4900
+ed80
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+b0
+48
+48
+48
+48
+ec
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 -3
+BITMAP
+f0
+48
+48
+48
+48
+70
+40
+40
+e0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 -3
+BITMAP
+70
+90
+90
+90
+90
+70
+10
+10
+38
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 6 0 0
+BITMAP
+b0
+60
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+70
+90
+c0
+30
+90
+e0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 7 0 0
+BITMAP
+40
+f0
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 6 0 0
+BITMAP
+cc
+48
+58
+50
+30
+20
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 6 0 0
+BITMAP
+ed80
+4900
+6b00
+2a00
+3400
+2400
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 6 1 0
+BITMAP
+d8
+50
+20
+20
+50
+d8
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 -3
+BITMAP
+cc
+48
+58
+50
+30
+20
+20
+40
+c0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 6 1 0
+BITMAP
+f0
+90
+20
+40
+90
+f0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+30
+40
+40
+40
+40
+80
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 12 0 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+20
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 2 0 3
+BITMAP
+64
+98
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 1 9 1 -3
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 1 -1
+BITMAP
+08
+70
+98
+a0
+a0
+c8
+70
+80
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+30
+48
+40
+40
+f0
+40
+40
+e8
+d8
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 7 1 1
+BITMAP
+84
+78
+48
+48
+48
+78
+84
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 0 0
+BITMAP
+88
+88
+50
+50
+f8
+20
+f8
+20
+70
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 9 1 0
+BITMAP
+80
+80
+80
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 12 1 -3
+BITMAP
+70
+90
+c0
+60
+b0
+90
+90
+d0
+60
+30
+90
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 1 0 7
+BITMAP
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 800 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+1c00
+6300
+5d00
+a480
+a080
+a480
+5d00
+6300
+1c00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 6 1 3
+BITMAP
+c0
+20
+e0
+a0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 0
+BITMAP
+28
+50
+a0
+50
+28
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 6 4 1 1
+BITMAP
+fc
+04
+04
+04
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 1 0 3
+BITMAP
+f0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+1c00
+6300
+5d00
+9280
+9c80
+9480
+d500
+6300
+3c00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 1 0 7
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 4 0 5
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+20
+20
+f8
+20
+20
+00
+f8
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 4 5 0 4
+BITMAP
+60
+90
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 5 0 4
+BITMAP
+e0
+20
+40
+20
+c0
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 2 2 1 7
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 -3
+BITMAP
+d8
+48
+48
+48
+48
+74
+40
+40
+60
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 6 12 0 -3
+BITMAP
+7c
+e8
+e8
+e8
+e8
+68
+28
+28
+28
+28
+28
+28
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 1 1 1 3
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 3 0 -3
+BITMAP
+40
+20
+e0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 5 0 4
+BITMAP
+40
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 3 6 1 3
+BITMAP
+40
+a0
+a0
+40
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 0 0
+BITMAP
+a0
+50
+28
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+4200
+c400
+4400
+4800
+e900
+1300
+1500
+2780
+2100
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+4200
+c400
+4400
+4800
+eb00
+1480
+1100
+2200
+2780
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e200
+2400
+4400
+2800
+c900
+1300
+1500
+2780
+2100
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 0 -3
+BITMAP
+20
+00
+20
+20
+20
+40
+80
+90
+60
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+1000
+0800
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0400
+0800
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0800
+1400
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0a00
+1400
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 11 0 0
+BITMAP
+1400
+0000
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0800
+1400
+0800
+0800
+0800
+1400
+1400
+2200
+3e00
+2200
+4100
+e380
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 880 0
+DWIDTH 11 0
+BBX 10 9 0 0
+BITMAP
+3fc0
+1840
+2800
+2880
+4f80
+7880
+4800
+8840
+cfc0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 -3
+BITMAP
+3a
+66
+42
+80
+80
+80
+42
+66
+3c
+10
+08
+38
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+20
+10
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+08
+10
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+10
+28
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 7 11 0 0
+BITMAP
+28
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+80
+40
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+20
+40
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 12 0 0
+BITMAP
+40
+a0
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 4 0
+BBX 3 11 0 0
+BITMAP
+a0
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+fc
+46
+42
+41
+e1
+41
+42
+46
+fc
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0a00
+1400
+0000
+c380
+6100
+6100
+5100
+4900
+4900
+4500
+4300
+e100
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+20
+10
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+04
+08
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+14
+28
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 11 0 0
+BITMAP
+24
+00
+3c
+66
+42
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+88
+50
+20
+50
+88
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+0080
+3d00
+6600
+4600
+8900
+8900
+9100
+6200
+6600
+bc00
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+10
+08
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+04
+08
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 12 0 0
+BITMAP
+10
+28
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 640 0
+DWIDTH 8 0
+BBX 8 11 0 0
+BITMAP
+24
+00
+e7
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+0400
+0800
+0000
+e380
+4100
+2200
+1200
+1c00
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 7 9 0 0
+BITMAP
+e0
+40
+7c
+46
+42
+46
+7c
+40
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+30
+48
+48
+50
+70
+48
+44
+44
+d8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+10
+20
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+50
+a0
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+20
+60
+90
+70
+90
+90
+68
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 720 0
+DWIDTH 9 0
+BBX 8 6 1 0
+BITMAP
+6c
+92
+7e
+90
+99
+6e
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 400 0
+DWIDTH 5 0
+BBX 4 9 1 -3
+BITMAP
+60
+90
+80
+80
+90
+60
+40
+20
+e0
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+40
+20
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+40
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 9 1 0
+BITMAP
+20
+50
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 8 1 0
+BITMAP
+50
+00
+60
+90
+f0
+80
+c8
+70
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+80
+40
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+80
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 9 0 0
+BITMAP
+40
+a0
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+a0
+00
+c0
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+40
+70
+a0
+70
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+28
+50
+00
+b0
+48
+48
+48
+48
+ec
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+40
+20
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+20
+40
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+20
+50
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 9 1 0
+BITMAP
+50
+a0
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 4 8 1 0
+BITMAP
+a0
+00
+60
+90
+90
+90
+90
+60
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 7 0
+BBX 5 5 1 1
+BITMAP
+20
+00
+f8
+00
+20
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+34
+48
+48
+48
+48
+70
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+20
+10
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+10
+20
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 9 0 0
+BITMAP
+20
+50
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+50
+00
+d8
+48
+48
+48
+48
+34
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 12 0 -3
+BITMAP
+08
+10
+00
+cc
+48
+58
+50
+30
+20
+20
+40
+c0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 5 12 0 -3
+BITMAP
+c0
+40
+40
+70
+48
+48
+48
+48
+70
+40
+40
+e0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 6 0
+BBX 6 11 0 -3
+BITMAP
+48
+00
+cc
+48
+58
+50
+30
+20
+20
+40
+c0
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times12.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times12.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times12.h	(revision 16632)
@@ -0,0 +1,792 @@
+static unsigned char times12_0_bits[] = {
+0x00};
+static unsigned char times12_1_bits[] = {
+0x00};
+static unsigned char times12_2_bits[] = {
+0x00};
+static unsigned char times12_3_bits[] = {
+0x00};
+static unsigned char times12_4_bits[] = {
+0x00};
+static unsigned char times12_5_bits[] = {
+0x00};
+static unsigned char times12_6_bits[] = {
+0x00};
+static unsigned char times12_7_bits[] = {
+0x00};
+static unsigned char times12_8_bits[] = {
+0x00};
+static unsigned char times12_9_bits[] = {
+0x00};
+static unsigned char times12_10_bits[] = {
+0x00};
+static unsigned char times12_11_bits[] = {
+0x00};
+static unsigned char times12_12_bits[] = {
+0x00};
+static unsigned char times12_13_bits[] = {
+0x00};
+static unsigned char times12_14_bits[] = {
+0x00};
+static unsigned char times12_15_bits[] = {
+0x00};
+static unsigned char times12_16_bits[] = {
+0x00};
+static unsigned char times12_17_bits[] = {
+0x00};
+static unsigned char times12_18_bits[] = {
+0x00};
+static unsigned char times12_19_bits[] = {
+0x00};
+static unsigned char times12_20_bits[] = {
+0x00};
+static unsigned char times12_21_bits[] = {
+0x00};
+static unsigned char times12_22_bits[] = {
+0x00};
+static unsigned char times12_23_bits[] = {
+0x00};
+static unsigned char times12_24_bits[] = {
+0x00};
+static unsigned char times12_25_bits[] = {
+0x00};
+static unsigned char times12_26_bits[] = {
+0x00};
+static unsigned char times12_27_bits[] = {
+0x00};
+static unsigned char times12_28_bits[] = {
+0x00};
+static unsigned char times12_29_bits[] = {
+0x00};
+static unsigned char times12_30_bits[] = {
+0x00};
+static unsigned char times12_31_bits[] = {
+0x00};
+static unsigned char times12_32_bits[] = {
+0x00};
+static unsigned char times12_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char times12_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char times12_35_bits[] = {
+0x0a, 0x0a, 0x1f, 0x0a, 0x0a, 0x1f, 0x0a, 0x0a};
+static unsigned char times12_36_bits[] = {
+0x04, 0x0e, 0x15, 0x05, 0x06, 0x0c, 0x14, 0x14, 0x15, 0x0e, 0x04};
+static unsigned char times12_37_bits[] = {
+0xc6, 0x79, 0x29, 0x16, 0x08, 0x6c, 0x94, 0x92, 0x62};
+static unsigned char times12_38_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0xd8, 0x01, 0x9e, 0x00, 0x73, 0x00, 
+0x21, 0x00, 0x73, 0x01, 0xde, 0x00};
+static unsigned char times12_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char times12_40_bits[] = {
+0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04};
+static unsigned char times12_41_bits[] = {
+0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01};
+static unsigned char times12_42_bits[] = {
+0x04, 0x15, 0x0e, 0x15, 0x04};
+static unsigned char times12_43_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04};
+static unsigned char times12_44_bits[] = {
+0x02, 0x02, 0x01};
+static unsigned char times12_45_bits[] = {
+0x1f};
+static unsigned char times12_46_bits[] = {
+0x01};
+static unsigned char times12_47_bits[] = {
+0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char times12_48_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times12_49_bits[] = {
+0x04, 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e};
+static unsigned char times12_50_bits[] = {
+0x0e, 0x11, 0x10, 0x10, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char times12_51_bits[] = {
+0x0e, 0x11, 0x10, 0x08, 0x0e, 0x10, 0x10, 0x11, 0x0e};
+static unsigned char times12_52_bits[] = {
+0x08, 0x0c, 0x0c, 0x0a, 0x0a, 0x09, 0x1f, 0x08, 0x08};
+static unsigned char times12_53_bits[] = {
+0x1c, 0x02, 0x02, 0x0e, 0x18, 0x10, 0x10, 0x19, 0x0e};
+static unsigned char times12_54_bits[] = {
+0x18, 0x06, 0x02, 0x0f, 0x19, 0x11, 0x11, 0x13, 0x0e};
+static unsigned char times12_55_bits[] = {
+0x1f, 0x11, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x02};
+static unsigned char times12_56_bits[] = {
+0x0e, 0x11, 0x11, 0x13, 0x0e, 0x19, 0x11, 0x11, 0x0e};
+static unsigned char times12_57_bits[] = {
+0x0e, 0x19, 0x11, 0x11, 0x13, 0x1e, 0x08, 0x0c, 0x03};
+static unsigned char times12_58_bits[] = {
+0x01, 0x00, 0x00, 0x00, 0x00, 0x01};
+static unsigned char times12_59_bits[] = {
+0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01};
+static unsigned char times12_60_bits[] = {
+0x30, 0x0c, 0x03, 0x0c, 0x30};
+static unsigned char times12_61_bits[] = {
+0x1f, 0x00, 0x1f};
+static unsigned char times12_62_bits[] = {
+0x03, 0x0c, 0x30, 0x0c, 0x03};
+static unsigned char times12_63_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x02, 0x02, 0x00, 0x02};
+static unsigned char times12_64_bits[] = {
+0xf0, 0x00, 0x0c, 0x01, 0x06, 0x02, 0xb2, 0x02, 0x49, 0x02, 0x45, 0x02, 
+0x25, 0x01, 0x25, 0x01, 0xd9, 0x00, 0x02, 0x00, 0x7c, 0x00};
+static unsigned char times12_65_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 
+0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x42, 0x42, 0x62, 0x3f};
+static unsigned char times12_67_bits[] = {
+0x5c, 0x66, 0x42, 0x01, 0x01, 0x01, 0x42, 0x66, 0x3c};
+static unsigned char times12_68_bits[] = {
+0x3f, 0x62, 0x42, 0x82, 0x82, 0x82, 0x42, 0x62, 0x3f};
+static unsigned char times12_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_70_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x02, 0x0f};
+static unsigned char times12_71_bits[] = {
+0x5c, 0x66, 0x42, 0x01, 0xe1, 0x41, 0x42, 0x66, 0x3c};
+static unsigned char times12_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char times12_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_74_bits[] = {
+0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x03};
+static unsigned char times12_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x1a, 0x32, 0x62, 0xe7};
+static unsigned char times12_76_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x22, 0x3f};
+static unsigned char times12_77_bits[] = {
+0x03, 0x06, 0x06, 0x03, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char times12_78_bits[] = {
+0xc3, 0x01, 0x86, 0x00, 0x86, 0x00, 0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 
+0xa2, 0x00, 0xc2, 0x00, 0x87, 0x00};
+static unsigned char times12_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_80_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_81_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c, 0x30, 0xc0};
+static unsigned char times12_82_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x12, 0x22, 0x42, 0xc7};
+static unsigned char times12_83_bits[] = {
+0x2e, 0x31, 0x21, 0x06, 0x1c, 0x30, 0x21, 0x33, 0x1d};
+static unsigned char times12_84_bits[] = {
+0x7f, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char times12_85_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_86_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times12_87_bits[] = {
+0x77, 0x0e, 0x22, 0x04, 0x66, 0x04, 0x44, 0x02, 0xec, 0x02, 0xa8, 0x02, 
+0x98, 0x01, 0x10, 0x01, 0x10, 0x01};
+static unsigned char times12_88_bits[] = {
+0xe7, 0x42, 0x24, 0x1c, 0x18, 0x34, 0x24, 0x42, 0xe7};
+static unsigned char times12_89_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x48, 0x00, 0x38, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char times12_90_bits[] = {
+0x7f, 0x61, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x41, 0x7f};
+static unsigned char times12_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x07};
+static unsigned char times12_92_bits[] = {
+0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04};
+static unsigned char times12_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x07};
+static unsigned char times12_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char times12_95_bits[] = {
+0x3f};
+static unsigned char times12_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char times12_97_bits[] = {
+0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_98_bits[] = {
+0x03, 0x02, 0x02, 0x0e, 0x12, 0x12, 0x12, 0x12, 0x0e};
+static unsigned char times12_99_bits[] = {
+0x06, 0x09, 0x01, 0x01, 0x09, 0x06};
+static unsigned char times12_100_bits[] = {
+0x0c, 0x08, 0x08, 0x0e, 0x09, 0x09, 0x09, 0x09, 0x16};
+static unsigned char times12_101_bits[] = {
+0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_102_bits[] = {
+0x04, 0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02};
+static unsigned char times12_103_bits[] = {
+0x1e, 0x09, 0x09, 0x07, 0x02, 0x0e, 0x11, 0x11, 0x0e};
+static unsigned char times12_104_bits[] = {
+0x03, 0x02, 0x02, 0x0e, 0x12, 0x12, 0x12, 0x12, 0x37};
+static unsigned char times12_105_bits[] = {
+0x02, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_106_bits[] = {
+0x02, 0x00, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times12_107_bits[] = {
+0x03, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x32};
+static unsigned char times12_108_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_109_bits[] = {
+0x6d, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0x92, 0x00, 0xb7, 0x01};
+static unsigned char times12_110_bits[] = {
+0x0d, 0x12, 0x12, 0x12, 0x12, 0x37};
+static unsigned char times12_111_bits[] = {
+0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_112_bits[] = {
+0x0f, 0x12, 0x12, 0x12, 0x12, 0x0e, 0x02, 0x02, 0x07};
+static unsigned char times12_113_bits[] = {
+0x0e, 0x09, 0x09, 0x09, 0x09, 0x0e, 0x08, 0x08, 0x1c};
+static unsigned char times12_114_bits[] = {
+0x0d, 0x06, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_115_bits[] = {
+0x0e, 0x09, 0x03, 0x0c, 0x09, 0x07};
+static unsigned char times12_116_bits[] = {
+0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char times12_117_bits[] = {
+0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_118_bits[] = {
+0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04};
+static unsigned char times12_119_bits[] = {
+0xb7, 0x01, 0x92, 0x00, 0xd6, 0x00, 0x54, 0x00, 0x2c, 0x00, 0x24, 0x00};
+static unsigned char times12_120_bits[] = {
+0x1b, 0x0a, 0x04, 0x04, 0x0a, 0x1b};
+static unsigned char times12_121_bits[] = {
+0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04, 0x04, 0x02, 0x03};
+static unsigned char times12_122_bits[] = {
+0x0f, 0x09, 0x04, 0x02, 0x09, 0x0f};
+static unsigned char times12_123_bits[] = {
+0x0c, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char times12_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times12_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03};
+static unsigned char times12_126_bits[] = {
+0x26, 0x19};
+static unsigned char times12_127_bits[] = {
+0x00};
+static unsigned char times12_128_bits[] = {
+0x00};
+static unsigned char times12_129_bits[] = {
+0x00};
+static unsigned char times12_130_bits[] = {
+0x00};
+static unsigned char times12_131_bits[] = {
+0x00};
+static unsigned char times12_132_bits[] = {
+0x00};
+static unsigned char times12_133_bits[] = {
+0x00};
+static unsigned char times12_134_bits[] = {
+0x00};
+static unsigned char times12_135_bits[] = {
+0x00};
+static unsigned char times12_136_bits[] = {
+0x00};
+static unsigned char times12_137_bits[] = {
+0x00};
+static unsigned char times12_138_bits[] = {
+0x00};
+static unsigned char times12_139_bits[] = {
+0x00};
+static unsigned char times12_140_bits[] = {
+0x00};
+static unsigned char times12_141_bits[] = {
+0x00};
+static unsigned char times12_142_bits[] = {
+0x00};
+static unsigned char times12_143_bits[] = {
+0x00};
+static unsigned char times12_144_bits[] = {
+0x00};
+static unsigned char times12_145_bits[] = {
+0x00};
+static unsigned char times12_146_bits[] = {
+0x00};
+static unsigned char times12_147_bits[] = {
+0x00};
+static unsigned char times12_148_bits[] = {
+0x00};
+static unsigned char times12_149_bits[] = {
+0x00};
+static unsigned char times12_150_bits[] = {
+0x00};
+static unsigned char times12_151_bits[] = {
+0x00};
+static unsigned char times12_152_bits[] = {
+0x00};
+static unsigned char times12_153_bits[] = {
+0x00};
+static unsigned char times12_154_bits[] = {
+0x00};
+static unsigned char times12_155_bits[] = {
+0x00};
+static unsigned char times12_156_bits[] = {
+0x00};
+static unsigned char times12_157_bits[] = {
+0x00};
+static unsigned char times12_158_bits[] = {
+0x00};
+static unsigned char times12_159_bits[] = {
+0x00};
+static unsigned char times12_160_bits[] = {
+0x00};
+static unsigned char times12_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times12_162_bits[] = {
+0x10, 0x0e, 0x19, 0x05, 0x05, 0x13, 0x0e, 0x01};
+static unsigned char times12_163_bits[] = {
+0x0c, 0x12, 0x02, 0x02, 0x0f, 0x02, 0x02, 0x17, 0x1b};
+static unsigned char times12_164_bits[] = {
+0x21, 0x1e, 0x12, 0x12, 0x12, 0x1e, 0x21};
+static unsigned char times12_165_bits[] = {
+0x11, 0x11, 0x0a, 0x0a, 0x1f, 0x04, 0x1f, 0x04, 0x0e};
+static unsigned char times12_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times12_167_bits[] = {
+0x0e, 0x09, 0x03, 0x06, 0x0d, 0x09, 0x09, 0x0b, 0x06, 0x0c, 0x09, 0x07};
+static unsigned char times12_168_bits[] = {
+0x05};
+static unsigned char times12_169_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0xba, 0x00, 0x25, 0x01, 0x05, 0x01, 0x25, 0x01, 
+0xba, 0x00, 0xc6, 0x00, 0x38, 0x00};
+static unsigned char times12_170_bits[] = {
+0x03, 0x04, 0x07, 0x05, 0x00, 0x07};
+static unsigned char times12_171_bits[] = {
+0x14, 0x0a, 0x05, 0x0a, 0x14};
+static unsigned char times12_172_bits[] = {
+0x3f, 0x20, 0x20, 0x20};
+static unsigned char times12_173_bits[] = {
+0x0f};
+static unsigned char times12_174_bits[] = {
+0x38, 0x00, 0xc6, 0x00, 0xba, 0x00, 0x49, 0x01, 0x39, 0x01, 0x29, 0x01, 
+0xab, 0x00, 0xc6, 0x00, 0x3c, 0x00};
+static unsigned char times12_175_bits[] = {
+0x0f};
+static unsigned char times12_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char times12_177_bits[] = {
+0x04, 0x04, 0x1f, 0x04, 0x04, 0x00, 0x1f};
+static unsigned char times12_178_bits[] = {
+0x06, 0x09, 0x04, 0x02, 0x0f};
+static unsigned char times12_179_bits[] = {
+0x07, 0x04, 0x02, 0x04, 0x03};
+static unsigned char times12_180_bits[] = {
+0x02, 0x01};
+static unsigned char times12_181_bits[] = {
+0x1b, 0x12, 0x12, 0x12, 0x12, 0x2e, 0x02, 0x02, 0x06};
+static unsigned char times12_182_bits[] = {
+0x3e, 0x17, 0x17, 0x17, 0x17, 0x16, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14};
+static unsigned char times12_183_bits[] = {
+0x01};
+static unsigned char times12_184_bits[] = {
+0x02, 0x04, 0x07};
+static unsigned char times12_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x07};
+static unsigned char times12_186_bits[] = {
+0x02, 0x05, 0x05, 0x02, 0x00, 0x07};
+static unsigned char times12_187_bits[] = {
+0x05, 0x0a, 0x14, 0x0a, 0x05};
+static unsigned char times12_188_bits[] = {
+0x42, 0x00, 0x23, 0x00, 0x22, 0x00, 0x12, 0x00, 0x97, 0x00, 0xc8, 0x00, 
+0xa8, 0x00, 0xe4, 0x01, 0x84, 0x00};
+static unsigned char times12_189_bits[] = {
+0x42, 0x00, 0x23, 0x00, 0x22, 0x00, 0x12, 0x00, 0xd7, 0x00, 0x28, 0x01, 
+0x88, 0x00, 0x44, 0x00, 0xe4, 0x01};
+static unsigned char times12_190_bits[] = {
+0x47, 0x00, 0x24, 0x00, 0x22, 0x00, 0x14, 0x00, 0x93, 0x00, 0xc8, 0x00, 
+0xa8, 0x00, 0xe4, 0x01, 0x84, 0x00};
+static unsigned char times12_191_bits[] = {
+0x04, 0x00, 0x04, 0x04, 0x04, 0x02, 0x01, 0x09, 0x06};
+static unsigned char times12_192_bits[] = {
+0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_193_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_194_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_195_bits[] = {
+0x50, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_196_bits[] = {
+0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 
+0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_197_bits[] = {
+0x10, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x44, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times12_198_bits[] = {
+0xfc, 0x03, 0x18, 0x02, 0x14, 0x00, 0x14, 0x01, 0xf2, 0x01, 0x1e, 0x01, 
+0x12, 0x00, 0x11, 0x02, 0xf3, 0x03};
+static unsigned char times12_199_bits[] = {
+0x5c, 0x66, 0x42, 0x01, 0x01, 0x01, 0x42, 0x66, 0x3c, 0x08, 0x10, 0x1c};
+static unsigned char times12_200_bits[] = {
+0x04, 0x08, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_201_bits[] = {
+0x10, 0x08, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_202_bits[] = {
+0x08, 0x14, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_203_bits[] = {
+0x14, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x7f};
+static unsigned char times12_204_bits[] = {
+0x01, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_205_bits[] = {
+0x04, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_206_bits[] = {
+0x02, 0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_207_bits[] = {
+0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_208_bits[] = {
+0x3f, 0x62, 0x42, 0x82, 0x87, 0x82, 0x42, 0x62, 0x3f};
+static unsigned char times12_209_bits[] = {
+0x50, 0x00, 0x28, 0x00, 0x00, 0x00, 0xc3, 0x01, 0x86, 0x00, 0x86, 0x00, 
+0x8a, 0x00, 0x92, 0x00, 0x92, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0x87, 0x00};
+static unsigned char times12_210_bits[] = {
+0x04, 0x08, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_211_bits[] = {
+0x20, 0x10, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_212_bits[] = {
+0x08, 0x14, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_213_bits[] = {
+0x28, 0x14, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_214_bits[] = {
+0x24, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times12_215_bits[] = {
+0x11, 0x0a, 0x04, 0x0a, 0x11};
+static unsigned char times12_216_bits[] = {
+0x00, 0x01, 0xbc, 0x00, 0x66, 0x00, 0x62, 0x00, 0x91, 0x00, 0x91, 0x00, 
+0x89, 0x00, 0x46, 0x00, 0x66, 0x00, 0x3d, 0x00};
+static unsigned char times12_217_bits[] = {
+0x08, 0x10, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_218_bits[] = {
+0x20, 0x10, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_219_bits[] = {
+0x08, 0x14, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_220_bits[] = {
+0x24, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times12_221_bits[] = {
+0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 
+0x48, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char times12_222_bits[] = {
+0x07, 0x02, 0x3e, 0x62, 0x42, 0x62, 0x3e, 0x02, 0x07};
+static unsigned char times12_223_bits[] = {
+0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x12, 0x22, 0x22, 0x1b};
+static unsigned char times12_224_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_225_bits[] = {
+0x08, 0x04, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_226_bits[] = {
+0x04, 0x0a, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_227_bits[] = {
+0x0a, 0x05, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_228_bits[] = {
+0x0a, 0x00, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_229_bits[] = {
+0x04, 0x0a, 0x04, 0x06, 0x09, 0x0e, 0x09, 0x09, 0x16};
+static unsigned char times12_230_bits[] = {
+0x36, 0x49, 0x7e, 0x09, 0x99, 0x76};
+static unsigned char times12_231_bits[] = {
+0x06, 0x09, 0x01, 0x01, 0x09, 0x06, 0x02, 0x04, 0x07};
+static unsigned char times12_232_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_233_bits[] = {
+0x04, 0x02, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_234_bits[] = {
+0x04, 0x0a, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_235_bits[] = {
+0x0a, 0x00, 0x06, 0x09, 0x0f, 0x01, 0x13, 0x0e};
+static unsigned char times12_236_bits[] = {
+0x01, 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_237_bits[] = {
+0x02, 0x01, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_238_bits[] = {
+0x02, 0x05, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_239_bits[] = {
+0x05, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times12_240_bits[] = {
+0x02, 0x0e, 0x05, 0x0e, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_241_bits[] = {
+0x14, 0x0a, 0x00, 0x0d, 0x12, 0x12, 0x12, 0x12, 0x37};
+static unsigned char times12_242_bits[] = {
+0x02, 0x04, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_243_bits[] = {
+0x04, 0x02, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_244_bits[] = {
+0x04, 0x0a, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_245_bits[] = {
+0x0a, 0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_246_bits[] = {
+0x05, 0x00, 0x06, 0x09, 0x09, 0x09, 0x09, 0x06};
+static unsigned char times12_247_bits[] = {
+0x04, 0x00, 0x1f, 0x00, 0x04};
+static unsigned char times12_248_bits[] = {
+0x2c, 0x12, 0x12, 0x12, 0x12, 0x0e, 0x01};
+static unsigned char times12_249_bits[] = {
+0x04, 0x08, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_250_bits[] = {
+0x08, 0x04, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_251_bits[] = {
+0x04, 0x0a, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_252_bits[] = {
+0x0a, 0x00, 0x1b, 0x12, 0x12, 0x12, 0x12, 0x2c};
+static unsigned char times12_253_bits[] = {
+0x10, 0x08, 0x00, 0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04, 0x04, 0x02, 0x03};
+static unsigned char times12_254_bits[] = {
+0x03, 0x02, 0x02, 0x0e, 0x12, 0x12, 0x12, 0x12, 0x0e, 0x02, 0x02, 0x07};
+static unsigned char times12_255_bits[] = {
+0x12, 0x00, 0x33, 0x12, 0x1a, 0x0a, 0x0c, 0x04, 0x04, 0x02, 0x03};
+static RotFont times12font[] = {
+{5, 1, 1, times12_0_bits},
+{5, 1, 1, times12_1_bits},
+{5, 1, 1, times12_2_bits},
+{5, 1, 1, times12_3_bits},
+{5, 1, 1, times12_4_bits},
+{5, 1, 1, times12_5_bits},
+{5, 1, 1, times12_6_bits},
+{5, 1, 1, times12_7_bits},
+{5, 1, 1, times12_8_bits},
+{5, 1, 1, times12_9_bits},
+{5, 1, 1, times12_10_bits},
+{5, 1, 1, times12_11_bits},
+{5, 1, 1, times12_12_bits},
+{5, 1, 1, times12_13_bits},
+{5, 1, 1, times12_14_bits},
+{5, 1, 1, times12_15_bits},
+{5, 1, 1, times12_16_bits},
+{5, 1, 1, times12_17_bits},
+{5, 1, 1, times12_18_bits},
+{5, 1, 1, times12_19_bits},
+{5, 1, 1, times12_20_bits},
+{5, 1, 1, times12_21_bits},
+{5, 1, 1, times12_22_bits},
+{5, 1, 1, times12_23_bits},
+{5, 1, 1, times12_24_bits},
+{5, 1, 1, times12_25_bits},
+{5, 1, 1, times12_26_bits},
+{5, 1, 1, times12_27_bits},
+{5, 1, 1, times12_28_bits},
+{5, 1, 1, times12_29_bits},
+{5, 1, 1, times12_30_bits},
+{5, 1, 1, times12_31_bits},
+{5, 1, 1, times12_32_bits},
+{1, 9, 9, times12_33_bits},
+{3, 3, 9, times12_34_bits},
+{5, 8, 8, times12_35_bits},
+{5, 11, 10, times12_36_bits},
+{8, 9, 9, times12_37_bits},
+{9, 9, 9, times12_38_bits},
+{2, 3, 9, times12_39_bits},
+{3, 12, 9, times12_40_bits},
+{3, 12, 9, times12_41_bits},
+{5, 5, 9, times12_42_bits},
+{5, 5, 6, times12_43_bits},
+{2, 3, 1, times12_44_bits},
+{5, 1, 4, times12_45_bits},
+{1, 1, 1, times12_46_bits},
+{3, 9, 9, times12_47_bits},
+{5, 9, 9, times12_48_bits},
+{4, 9, 9, times12_49_bits},
+{5, 9, 9, times12_50_bits},
+{5, 9, 9, times12_51_bits},
+{5, 9, 9, times12_52_bits},
+{5, 9, 9, times12_53_bits},
+{5, 9, 9, times12_54_bits},
+{5, 9, 9, times12_55_bits},
+{5, 9, 9, times12_56_bits},
+{5, 9, 9, times12_57_bits},
+{1, 6, 6, times12_58_bits},
+{2, 8, 6, times12_59_bits},
+{6, 5, 6, times12_60_bits},
+{5, 3, 5, times12_61_bits},
+{6, 5, 6, times12_62_bits},
+{4, 9, 9, times12_63_bits},
+{10, 11, 9, times12_64_bits},
+{9, 9, 9, times12_65_bits},
+{7, 9, 9, times12_66_bits},
+{7, 9, 9, times12_67_bits},
+{8, 9, 9, times12_68_bits},
+{7, 9, 9, times12_69_bits},
+{7, 9, 9, times12_70_bits},
+{8, 9, 9, times12_71_bits},
+{8, 9, 9, times12_72_bits},
+{3, 9, 9, times12_73_bits},
+{4, 9, 9, times12_74_bits},
+{8, 9, 9, times12_75_bits},
+{6, 9, 9, times12_76_bits},
+{11, 9, 9, times12_77_bits},
+{9, 9, 9, times12_78_bits},
+{8, 9, 9, times12_79_bits},
+{7, 9, 9, times12_80_bits},
+{8, 11, 9, times12_81_bits},
+{8, 9, 9, times12_82_bits},
+{6, 9, 9, times12_83_bits},
+{7, 9, 9, times12_84_bits},
+{8, 9, 9, times12_85_bits},
+{9, 9, 9, times12_86_bits},
+{12, 9, 9, times12_87_bits},
+{8, 9, 9, times12_88_bits},
+{9, 9, 9, times12_89_bits},
+{7, 9, 9, times12_90_bits},
+{3, 12, 9, times12_91_bits},
+{3, 9, 9, times12_92_bits},
+{3, 12, 9, times12_93_bits},
+{5, 5, 9, times12_94_bits},
+{6, 1, -2, times12_95_bits},
+{2, 3, 9, times12_96_bits},
+{5, 6, 6, times12_97_bits},
+{5, 9, 9, times12_98_bits},
+{4, 6, 6, times12_99_bits},
+{5, 9, 9, times12_100_bits},
+{5, 6, 6, times12_101_bits},
+{3, 9, 9, times12_102_bits},
+{5, 9, 6, times12_103_bits},
+{6, 9, 9, times12_104_bits},
+{3, 9, 9, times12_105_bits},
+{2, 12, 9, times12_106_bits},
+{6, 9, 9, times12_107_bits},
+{3, 9, 9, times12_108_bits},
+{9, 6, 6, times12_109_bits},
+{6, 6, 6, times12_110_bits},
+{4, 6, 6, times12_111_bits},
+{5, 9, 6, times12_112_bits},
+{5, 9, 6, times12_113_bits},
+{4, 6, 6, times12_114_bits},
+{4, 6, 6, times12_115_bits},
+{4, 7, 7, times12_116_bits},
+{6, 6, 6, times12_117_bits},
+{6, 6, 6, times12_118_bits},
+{9, 6, 6, times12_119_bits},
+{5, 6, 6, times12_120_bits},
+{6, 9, 6, times12_121_bits},
+{4, 6, 6, times12_122_bits},
+{4, 12, 9, times12_123_bits},
+{1, 9, 9, times12_124_bits},
+{4, 12, 9, times12_125_bits},
+{6, 2, 5, times12_126_bits},
+{5, 1, 1, times12_127_bits},
+{5, 1, 1, times12_128_bits},
+{5, 1, 1, times12_129_bits},
+{5, 1, 1, times12_130_bits},
+{5, 1, 1, times12_131_bits},
+{5, 1, 1, times12_132_bits},
+{5, 1, 1, times12_133_bits},
+{5, 1, 1, times12_134_bits},
+{5, 1, 1, times12_135_bits},
+{5, 1, 1, times12_136_bits},
+{5, 1, 1, times12_137_bits},
+{5, 1, 1, times12_138_bits},
+{5, 1, 1, times12_139_bits},
+{5, 1, 1, times12_140_bits},
+{5, 1, 1, times12_141_bits},
+{5, 1, 1, times12_142_bits},
+{5, 1, 1, times12_143_bits},
+{5, 1, 1, times12_144_bits},
+{5, 1, 1, times12_145_bits},
+{5, 1, 1, times12_146_bits},
+{5, 1, 1, times12_147_bits},
+{5, 1, 1, times12_148_bits},
+{5, 1, 1, times12_149_bits},
+{5, 1, 1, times12_150_bits},
+{5, 1, 1, times12_151_bits},
+{5, 1, 1, times12_152_bits},
+{5, 1, 1, times12_153_bits},
+{5, 1, 1, times12_154_bits},
+{5, 1, 1, times12_155_bits},
+{5, 1, 1, times12_156_bits},
+{5, 1, 1, times12_157_bits},
+{5, 1, 1, times12_158_bits},
+{5, 1, 1, times12_159_bits},
+{1, 1, 1, times12_160_bits},
+{1, 9, 6, times12_161_bits},
+{5, 8, 7, times12_162_bits},
+{5, 9, 9, times12_163_bits},
+{6, 7, 8, times12_164_bits},
+{5, 9, 9, times12_165_bits},
+{1, 9, 9, times12_166_bits},
+{4, 12, 9, times12_167_bits},
+{3, 1, 8, times12_168_bits},
+{9, 9, 9, times12_169_bits},
+{3, 6, 9, times12_170_bits},
+{5, 5, 5, times12_171_bits},
+{6, 4, 5, times12_172_bits},
+{4, 1, 4, times12_173_bits},
+{9, 9, 9, times12_174_bits},
+{4, 1, 8, times12_175_bits},
+{4, 4, 9, times12_176_bits},
+{5, 7, 7, times12_177_bits},
+{4, 5, 9, times12_178_bits},
+{3, 5, 9, times12_179_bits},
+{2, 2, 9, times12_180_bits},
+{6, 9, 6, times12_181_bits},
+{6, 12, 9, times12_182_bits},
+{1, 1, 4, times12_183_bits},
+{3, 3, 0, times12_184_bits},
+{3, 5, 9, times12_185_bits},
+{3, 6, 9, times12_186_bits},
+{5, 5, 5, times12_187_bits},
+{9, 9, 9, times12_188_bits},
+{9, 9, 9, times12_189_bits},
+{9, 9, 9, times12_190_bits},
+{4, 9, 6, times12_191_bits},
+{9, 12, 12, times12_192_bits},
+{9, 12, 12, times12_193_bits},
+{9, 12, 12, times12_194_bits},
+{9, 12, 12, times12_195_bits},
+{9, 11, 11, times12_196_bits},
+{9, 12, 12, times12_197_bits},
+{10, 9, 9, times12_198_bits},
+{7, 12, 9, times12_199_bits},
+{7, 12, 12, times12_200_bits},
+{7, 12, 12, times12_201_bits},
+{7, 12, 12, times12_202_bits},
+{7, 11, 11, times12_203_bits},
+{3, 12, 12, times12_204_bits},
+{3, 12, 12, times12_205_bits},
+{3, 12, 12, times12_206_bits},
+{3, 11, 11, times12_207_bits},
+{8, 9, 9, times12_208_bits},
+{9, 12, 12, times12_209_bits},
+{8, 12, 12, times12_210_bits},
+{8, 12, 12, times12_211_bits},
+{8, 12, 12, times12_212_bits},
+{8, 12, 12, times12_213_bits},
+{8, 11, 11, times12_214_bits},
+{5, 5, 6, times12_215_bits},
+{9, 10, 10, times12_216_bits},
+{8, 12, 12, times12_217_bits},
+{8, 12, 12, times12_218_bits},
+{8, 12, 12, times12_219_bits},
+{8, 11, 11, times12_220_bits},
+{9, 12, 12, times12_221_bits},
+{7, 9, 9, times12_222_bits},
+{6, 9, 9, times12_223_bits},
+{5, 9, 9, times12_224_bits},
+{5, 9, 9, times12_225_bits},
+{5, 9, 9, times12_226_bits},
+{5, 9, 9, times12_227_bits},
+{5, 8, 8, times12_228_bits},
+{5, 9, 9, times12_229_bits},
+{8, 6, 6, times12_230_bits},
+{4, 9, 6, times12_231_bits},
+{5, 9, 9, times12_232_bits},
+{5, 9, 9, times12_233_bits},
+{5, 9, 9, times12_234_bits},
+{5, 8, 8, times12_235_bits},
+{3, 9, 9, times12_236_bits},
+{3, 9, 9, times12_237_bits},
+{3, 9, 9, times12_238_bits},
+{3, 8, 8, times12_239_bits},
+{4, 9, 9, times12_240_bits},
+{6, 9, 9, times12_241_bits},
+{4, 9, 9, times12_242_bits},
+{4, 9, 9, times12_243_bits},
+{4, 9, 9, times12_244_bits},
+{4, 9, 9, times12_245_bits},
+{4, 8, 8, times12_246_bits},
+{5, 5, 6, times12_247_bits},
+{6, 7, 6, times12_248_bits},
+{6, 9, 9, times12_249_bits},
+{6, 9, 9, times12_250_bits},
+{6, 9, 9, times12_251_bits},
+{6, 8, 8, times12_252_bits},
+{6, 12, 9, times12_253_bits},
+{5, 12, 9, times12_254_bits},
+{6, 11, 8, times12_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times14.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times14.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times14.bdf	(revision 16632)
@@ -0,0 +1,3205 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--14-100-100-100-P-74-ISO8859-1
+SIZE 10 100 100
+FONTBOUNDINGBOX 14 17 -1 -3
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 14
+POINT_SIZE 100
+RESOLUTION_X 100
+RESOLUTION_Y 100
+SPACING "P"
+AVERAGE_WIDTH 74
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 10
+X_HEIGHT 7
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--14-100-100-100-P-74-ISO8859-1"
+WEIGHT 10
+RESOLUTION 138
+QUAD_WIDTH 8
+DEFAULT_CHAR 32
+FONT_ASCENT 12
+FONT_DESCENT 3
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 1 10 2 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+00
+80
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 3 3 1 7
+BITMAP
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+14
+14
+7e
+28
+28
+28
+fc
+50
+50
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 12 1 -1
+BITMAP
+20
+78
+a8
+a0
+a0
+70
+28
+28
+28
+a8
+f0
+20
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 9 10 1 0
+BITMAP
+7180
+df00
+9200
+9400
+6800
+0b00
+1680
+2480
+4480
+4300
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 10 10 1 0
+BITMAP
+1800
+2400
+2400
+3800
+1380
+7900
+ca00
+8400
+ce40
+7380
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 3 1 7
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+20
+20
+40
+40
+80
+80
+80
+80
+80
+40
+40
+20
+20
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+80
+80
+40
+40
+20
+20
+20
+20
+20
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 6 1 4
+BITMAP
+20
+a8
+70
+70
+a8
+20
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+10
+fe
+10
+10
+10
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 3 1 -2
+BITMAP
+c0
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 6 1 1 3
+BITMAP
+fc
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 1 1 0
+BITMAP
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 12 0 -2
+BITMAP
+10
+10
+10
+20
+20
+20
+40
+40
+40
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+78
+cc
+84
+84
+84
+84
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+20
+e0
+20
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+d8
+88
+08
+18
+10
+20
+40
+88
+f8
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+78
+8c
+04
+08
+30
+38
+04
+04
+cc
+78
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+08
+18
+18
+28
+68
+48
+88
+fc
+08
+08
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+78
+40
+80
+e0
+30
+18
+08
+08
+90
+e0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+0c
+10
+20
+40
+78
+cc
+84
+84
+cc
+78
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+fc
+84
+08
+08
+10
+10
+20
+20
+40
+40
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+70
+98
+88
+c8
+70
+98
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+78
+cc
+84
+84
+cc
+78
+08
+10
+20
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 7 1 0
+BITMAP
+c0
+00
+00
+00
+00
+00
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 9 1 -2
+BITMAP
+c0
+00
+00
+00
+00
+00
+c0
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+06
+18
+60
+c0
+60
+18
+06
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 3 0 2
+BITMAP
+fe
+00
+fe
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+c0
+30
+0c
+06
+0c
+30
+c0
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 5 10 0 0
+BITMAP
+70
+88
+88
+08
+10
+20
+20
+00
+20
+20
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 12 12 0 -2
+BITMAP
+0f80
+3060
+6020
+4690
+8910
+9110
+9110
+9320
+cdc0
+4000
+30c0
+0f00
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fc
+46
+42
+46
+7c
+46
+42
+42
+46
+fc
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3d
+63
+41
+81
+80
+80
+80
+c1
+62
+3c
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+fe00
+2300
+2100
+2080
+2080
+2080
+2080
+2100
+2300
+fe00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 10 1 0
+BITMAP
+fe
+42
+40
+44
+7c
+44
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+3d00
+6300
+4100
+8100
+8000
+8780
+8100
+c100
+6300
+3e00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+e7
+42
+42
+42
+7e
+42
+42
+42
+42
+e7
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 10 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 10 1 0
+BITMAP
+70
+20
+20
+20
+20
+20
+20
+20
+a0
+c0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+ee
+44
+48
+50
+70
+50
+48
+44
+46
+e7
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+e0
+40
+40
+40
+40
+40
+40
+40
+42
+fe
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 10 1 0
+BITMAP
+e0e0
+60c0
+5140
+5140
+5b40
+4a40
+4a40
+4e40
+4440
+e4e0
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 10 1 0
+BITMAP
+e380
+6100
+5100
+5900
+4900
+4d00
+4500
+4500
+4300
+e300
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+f8
+4c
+44
+44
+4c
+78
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 -3
+BITMAP
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+08
+06
+03
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+fc00
+2600
+2200
+2200
+2600
+3c00
+2400
+2200
+2300
+f180
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+74
+cc
+84
+c0
+70
+18
+04
+84
+cc
+b8
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 10 1 0
+BITMAP
+fe
+92
+92
+10
+10
+10
+10
+10
+10
+38
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 10 1 0
+BITMAP
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+e380
+4100
+6300
+2200
+2200
+3600
+1400
+1c00
+0800
+0800
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 13 10 0 0
+BITMAP
+e738
+4210
+6230
+2220
+2520
+3560
+1540
+18c0
+0880
+0880
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+7380
+2100
+1200
+1200
+0c00
+0c00
+1200
+2100
+6180
+f3c0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 10 0 0
+BITMAP
+e380
+4100
+2200
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 8 10 0 0
+BITMAP
+7f
+43
+02
+04
+08
+10
+20
+40
+c1
+ff
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+e0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 10 0 0
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+20
+10
+10
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 -3
+BITMAP
+e0
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+20
+e0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 5 1 5
+BITMAP
+20
+50
+50
+88
+88
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 1 0 -3
+BITMAP
+fe
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 2 3 1 7
+BITMAP
+40
+80
+c0
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+c0
+40
+40
+58
+6c
+44
+44
+44
+4c
+78
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+78
+cc
+80
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+18
+08
+08
+78
+c8
+88
+88
+88
+d8
+74
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 7 1 0
+BITMAP
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 5 10 0 0
+BITMAP
+38
+60
+40
+f8
+40
+40
+40
+40
+40
+f0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+78
+d0
+88
+c8
+70
+40
+78
+84
+cc
+70
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+c0
+40
+40
+58
+6c
+44
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+40
+40
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 13 0 -3
+BITMAP
+20
+20
+00
+60
+20
+20
+20
+20
+20
+20
+20
+a0
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+c0
+40
+40
+4c
+48
+70
+50
+48
+4c
+e6
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+c0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 11 7 0 0
+BITMAP
+db80
+6ec0
+4440
+4440
+4440
+4440
+eee0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+d8
+6c
+44
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 7 1 0
+BITMAP
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 -3
+BITMAP
+d8
+6c
+44
+44
+44
+6c
+58
+40
+40
+e0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+78
+c8
+88
+88
+88
+d8
+68
+08
+08
+1c
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 7 0 0
+BITMAP
+b8
+60
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 7 1 0
+BITMAP
+70
+90
+c0
+60
+30
+90
+e0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 8 0 0
+BITMAP
+40
+f0
+40
+40
+40
+40
+40
+30
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+ee
+44
+44
+28
+28
+10
+10
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 11 7 0 0
+BITMAP
+eee0
+4440
+4440
+2480
+3b80
+1100
+1100
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 7 0 0
+BITMAP
+ee
+44
+38
+10
+38
+44
+ee
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 -3
+BITMAP
+ee
+44
+44
+28
+28
+10
+30
+20
+a0
+c0
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+fc
+88
+18
+30
+60
+c4
+fc
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+18
+20
+20
+20
+20
+40
+80
+40
+20
+20
+20
+20
+18
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+c0
+20
+20
+20
+20
+10
+08
+10
+20
+20
+20
+20
+c0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 2 0 3
+BITMAP
+62
+9c
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 1 10 2 -3
+BITMAP
+80
+80
+00
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 9 0 -1
+BITMAP
+04
+7c
+cc
+90
+90
+a0
+e4
+78
+80
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 10 0 0
+BITMAP
+1c
+34
+20
+20
+f8
+20
+20
+20
+e2
+bc
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 7 1 1
+BITMAP
+88
+70
+88
+88
+88
+70
+88
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+ee
+44
+6c
+28
+7c
+10
+7c
+10
+10
+38
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 1 10 1 0
+BITMAP
+80
+80
+80
+80
+00
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 13 1 -3
+BITMAP
+38
+58
+40
+60
+70
+98
+88
+c8
+70
+30
+10
+d0
+e0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 2 1 8
+BITMAP
+a0
+a0
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+1e00
+6180
+4e80
+9240
+9040
+9040
+9240
+4c80
+6180
+1e00
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 6 0 4
+BITMAP
+e0
+20
+a0
+e0
+00
+e0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 6 0 0
+BITMAP
+24
+48
+90
+90
+48
+24
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 4 1 2
+BITMAP
+fe
+02
+02
+02
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 1 0 3
+BITMAP
+e0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 864 0
+DWIDTH 12 0
+BBX 10 10 1 0
+BITMAP
+1e00
+6180
+5c80
+9240
+9c40
+9440
+9240
+5280
+6180
+1e00
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 1 0 8
+BITMAP
+f0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 4 4 1 6
+BITMAP
+60
+90
+90
+60
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 0 0
+BITMAP
+10
+10
+fe
+10
+10
+00
+fe
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 6 0 4
+BITMAP
+60
+90
+10
+20
+40
+f0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 4 6 0 4
+BITMAP
+60
+90
+20
+10
+90
+60
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 3 1 8
+BITMAP
+20
+60
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 -3
+BITMAP
+cc
+44
+44
+44
+44
+6c
+76
+40
+40
+60
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 13 0 -3
+BITMAP
+3e
+74
+f4
+f4
+f4
+74
+34
+14
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 1 2 2 3
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 3 1 -3
+BITMAP
+40
+20
+c0
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 288 0
+DWIDTH 4 0
+BBX 3 6 0 4
+BITMAP
+40
+c0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 4 6 0 4
+BITMAP
+60
+90
+90
+60
+00
+f0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 6 1 0
+BITMAP
+90
+48
+24
+24
+48
+90
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+4100
+c200
+4200
+4400
+4480
+e980
+0a80
+1480
+17c0
+2080
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+4100
+c200
+4200
+4400
+4580
+ea40
+0840
+1080
+1100
+23c0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 10 10 0 0
+BITMAP
+6100
+9200
+2200
+1400
+9480
+6980
+0a80
+1480
+17c0
+2080
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 432 0
+DWIDTH 6 0
+BBX 5 10 0 -3
+BITMAP
+20
+20
+00
+20
+20
+40
+80
+88
+88
+70
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1000
+1800
+0400
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0400
+0c00
+1000
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+0800
+1c00
+2200
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1200
+2a00
+2400
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+2400
+2400
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1800
+2400
+1800
+0000
+0800
+0800
+1400
+1400
+2200
+2200
+3e00
+4100
+4100
+e380
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 936 0
+DWIDTH 13 0
+BBX 11 10 1 0
+BITMAP
+1fe0
+0c20
+1400
+1440
+27c0
+2440
+3c00
+4420
+4420
+efe0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 -3
+BITMAP
+3d
+63
+41
+81
+80
+80
+80
+c1
+62
+3c
+08
+04
+18
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+20
+30
+08
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+04
+0c
+10
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 14 1 0
+BITMAP
+10
+38
+44
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+24
+24
+00
+fe
+42
+40
+44
+7c
+44
+40
+42
+42
+fe
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 0
+BITMAP
+80
+c0
+20
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 14 1 0
+BITMAP
+20
+60
+80
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 5 14 0 0
+BITMAP
+20
+70
+88
+00
+70
+20
+20
+20
+20
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 360 0
+DWIDTH 5 0
+BBX 3 13 1 0
+BITMAP
+a0
+a0
+00
+e0
+40
+40
+40
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 10 0 0
+BITMAP
+fe00
+2300
+2100
+2080
+f880
+2080
+2080
+2100
+2300
+fe00
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 14 1 0
+BITMAP
+1200
+2a00
+2400
+0000
+e380
+6100
+5100
+5900
+4900
+4d00
+4500
+4500
+4300
+e300
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+20
+30
+08
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+04
+0c
+10
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+10
+38
+44
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+24
+54
+48
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+24
+24
+00
+3c
+66
+42
+81
+81
+81
+81
+42
+66
+3c
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+82
+44
+28
+10
+28
+44
+82
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 9 12 0 -1
+BITMAP
+0080
+1f00
+3100
+2300
+4480
+4c80
+4880
+5080
+3100
+6300
+5e00
+8000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+20
+30
+08
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+04
+0c
+10
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 14 1 0
+BITMAP
+10
+38
+44
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+24
+24
+00
+e7
+42
+42
+42
+42
+42
+42
+42
+66
+3c
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 648 0
+DWIDTH 9 0
+BBX 9 14 0 0
+BITMAP
+0200
+0600
+0800
+0000
+e380
+4100
+2200
+2200
+1400
+0800
+0800
+0800
+0800
+1c00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 6 10 1 0
+BITMAP
+e0
+40
+78
+4c
+44
+44
+4c
+78
+40
+e0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 0 0
+BITMAP
+38
+6c
+44
+48
+70
+58
+4c
+44
+54
+d8
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+40
+60
+10
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+08
+18
+20
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+20
+70
+88
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+48
+a8
+90
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+50
+50
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+30
+48
+30
+00
+70
+c8
+18
+68
+88
+c8
+74
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 792 0
+DWIDTH 11 0
+BBX 9 7 1 0
+BITMAP
+7f00
+c980
+1f00
+6800
+8800
+cc80
+7700
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 -3
+BITMAP
+70
+c8
+80
+80
+80
+c4
+78
+20
+10
+60
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+40
+60
+10
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+08
+18
+20
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 11 1 0
+BITMAP
+20
+70
+88
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 10 1 0
+BITMAP
+50
+50
+00
+70
+88
+f8
+80
+80
+c4
+78
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+80
+c0
+20
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 11 0 0
+BITMAP
+20
+60
+80
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 5 11 -1 0
+BITMAP
+20
+70
+88
+00
+60
+20
+20
+20
+20
+20
+70
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 216 0
+DWIDTH 3 0
+BBX 3 10 0 0
+BITMAP
+a0
+a0
+00
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+d8
+60
+90
+78
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+24
+54
+48
+00
+d8
+6c
+44
+44
+44
+44
+ee
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+40
+60
+10
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+10
+30
+40
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+20
+70
+88
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 11 1 0
+BITMAP
+48
+a8
+90
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 5 10 1 0
+BITMAP
+50
+50
+00
+70
+d8
+88
+88
+88
+d8
+70
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 576 0
+DWIDTH 8 0
+BBX 7 7 1 0
+BITMAP
+10
+10
+00
+fe
+00
+10
+10
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 9 0 -1
+BITMAP
+02
+3c
+6c
+44
+44
+44
+6c
+78
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+20
+30
+08
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+08
+18
+20
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 11 0 0
+BITMAP
+10
+38
+44
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 10 0 0
+BITMAP
+28
+28
+00
+cc
+44
+44
+44
+44
+6c
+36
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 14 0 -3
+BITMAP
+04
+0c
+10
+00
+ee
+44
+44
+28
+28
+10
+30
+20
+a0
+c0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 6 13 0 -3
+BITMAP
+c0
+40
+40
+58
+6c
+44
+44
+44
+6c
+58
+40
+40
+e0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 504 0
+DWIDTH 7 0
+BBX 7 13 0 -3
+BITMAP
+28
+28
+00
+ee
+44
+44
+28
+28
+10
+30
+20
+a0
+c0
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times14.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times14.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times14.h	(revision 16632)
@@ -0,0 +1,840 @@
+static unsigned char times14_0_bits[] = {
+0x00};
+static unsigned char times14_1_bits[] = {
+0x00};
+static unsigned char times14_2_bits[] = {
+0x00};
+static unsigned char times14_3_bits[] = {
+0x00};
+static unsigned char times14_4_bits[] = {
+0x00};
+static unsigned char times14_5_bits[] = {
+0x00};
+static unsigned char times14_6_bits[] = {
+0x00};
+static unsigned char times14_7_bits[] = {
+0x00};
+static unsigned char times14_8_bits[] = {
+0x00};
+static unsigned char times14_9_bits[] = {
+0x00};
+static unsigned char times14_10_bits[] = {
+0x00};
+static unsigned char times14_11_bits[] = {
+0x00};
+static unsigned char times14_12_bits[] = {
+0x00};
+static unsigned char times14_13_bits[] = {
+0x00};
+static unsigned char times14_14_bits[] = {
+0x00};
+static unsigned char times14_15_bits[] = {
+0x00};
+static unsigned char times14_16_bits[] = {
+0x00};
+static unsigned char times14_17_bits[] = {
+0x00};
+static unsigned char times14_18_bits[] = {
+0x00};
+static unsigned char times14_19_bits[] = {
+0x00};
+static unsigned char times14_20_bits[] = {
+0x00};
+static unsigned char times14_21_bits[] = {
+0x00};
+static unsigned char times14_22_bits[] = {
+0x00};
+static unsigned char times14_23_bits[] = {
+0x00};
+static unsigned char times14_24_bits[] = {
+0x00};
+static unsigned char times14_25_bits[] = {
+0x00};
+static unsigned char times14_26_bits[] = {
+0x00};
+static unsigned char times14_27_bits[] = {
+0x00};
+static unsigned char times14_28_bits[] = {
+0x00};
+static unsigned char times14_29_bits[] = {
+0x00};
+static unsigned char times14_30_bits[] = {
+0x00};
+static unsigned char times14_31_bits[] = {
+0x00};
+static unsigned char times14_32_bits[] = {
+0x00};
+static unsigned char times14_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01};
+static unsigned char times14_34_bits[] = {
+0x05, 0x05, 0x05};
+static unsigned char times14_35_bits[] = {
+0x28, 0x28, 0x7e, 0x14, 0x14, 0x14, 0x3f, 0x0a, 0x0a, 0x0a};
+static unsigned char times14_36_bits[] = {
+0x04, 0x1e, 0x15, 0x05, 0x05, 0x0e, 0x14, 0x14, 0x14, 0x15, 0x0f, 0x04};
+static unsigned char times14_37_bits[] = {
+0x8e, 0x01, 0xfb, 0x00, 0x49, 0x00, 0x29, 0x00, 0x16, 0x00, 0xd0, 0x00, 
+0x68, 0x01, 0x24, 0x01, 0x22, 0x01, 0xc2, 0x00};
+static unsigned char times14_38_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x24, 0x00, 0x1c, 0x00, 0xc8, 0x01, 0x9e, 0x00, 
+0x53, 0x00, 0x21, 0x00, 0x73, 0x02, 0xce, 0x01};
+static unsigned char times14_39_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char times14_40_bits[] = {
+0x04, 0x04, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04, 
+0x04};
+static unsigned char times14_41_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x04, 0x04, 0x04, 0x02, 0x02, 0x01, 
+0x01};
+static unsigned char times14_42_bits[] = {
+0x04, 0x15, 0x0e, 0x0e, 0x15, 0x04};
+static unsigned char times14_43_bits[] = {
+0x08, 0x08, 0x08, 0x7f, 0x08, 0x08, 0x08};
+static unsigned char times14_44_bits[] = {
+0x03, 0x02, 0x01};
+static unsigned char times14_45_bits[] = {
+0x3f};
+static unsigned char times14_46_bits[] = {
+0x03};
+static unsigned char times14_47_bits[] = {
+0x08, 0x08, 0x08, 0x04, 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01};
+static unsigned char times14_48_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char times14_49_bits[] = {
+0x04, 0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char times14_50_bits[] = {
+0x0e, 0x1b, 0x11, 0x10, 0x18, 0x08, 0x04, 0x02, 0x11, 0x1f};
+static unsigned char times14_51_bits[] = {
+0x1e, 0x31, 0x20, 0x10, 0x0c, 0x1c, 0x20, 0x20, 0x33, 0x1e};
+static unsigned char times14_52_bits[] = {
+0x10, 0x18, 0x18, 0x14, 0x16, 0x12, 0x11, 0x3f, 0x10, 0x10};
+static unsigned char times14_53_bits[] = {
+0x1e, 0x02, 0x01, 0x07, 0x0c, 0x18, 0x10, 0x10, 0x09, 0x07};
+static unsigned char times14_54_bits[] = {
+0x30, 0x08, 0x04, 0x02, 0x1e, 0x33, 0x21, 0x21, 0x33, 0x1e};
+static unsigned char times14_55_bits[] = {
+0x3f, 0x21, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02};
+static unsigned char times14_56_bits[] = {
+0x0e, 0x19, 0x11, 0x13, 0x0e, 0x19, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times14_57_bits[] = {
+0x1e, 0x33, 0x21, 0x21, 0x33, 0x1e, 0x10, 0x08, 0x04, 0x03};
+static unsigned char times14_58_bits[] = {
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03};
+static unsigned char times14_59_bits[] = {
+0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01};
+static unsigned char times14_60_bits[] = {
+0x60, 0x18, 0x06, 0x03, 0x06, 0x18, 0x60};
+static unsigned char times14_61_bits[] = {
+0x7f, 0x00, 0x7f};
+static unsigned char times14_62_bits[] = {
+0x03, 0x0c, 0x30, 0x60, 0x30, 0x0c, 0x03};
+static unsigned char times14_63_bits[] = {
+0x0e, 0x11, 0x11, 0x10, 0x08, 0x04, 0x04, 0x00, 0x04, 0x04};
+static unsigned char times14_64_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x06, 0x04, 0x62, 0x09, 0x91, 0x08, 0x89, 0x08, 
+0x89, 0x08, 0xc9, 0x04, 0xb3, 0x03, 0x02, 0x00, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times14_65_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 
+0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_66_bits[] = {
+0x3f, 0x62, 0x42, 0x62, 0x3e, 0x62, 0x42, 0x42, 0x62, 0x3f};
+static unsigned char times14_67_bits[] = {
+0xbc, 0xc6, 0x82, 0x81, 0x01, 0x01, 0x01, 0x83, 0x46, 0x3c};
+static unsigned char times14_68_bits[] = {
+0x7f, 0x00, 0xc4, 0x00, 0x84, 0x00, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 
+0x04, 0x01, 0x84, 0x00, 0xc4, 0x00, 0x7f, 0x00};
+static unsigned char times14_69_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x42, 0x7f};
+static unsigned char times14_70_bits[] = {
+0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_71_bits[] = {
+0xbc, 0x00, 0xc6, 0x00, 0x82, 0x00, 0x81, 0x00, 0x01, 0x00, 0xe1, 0x01, 
+0x81, 0x00, 0x83, 0x00, 0xc6, 0x00, 0x7c, 0x00};
+static unsigned char times14_72_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42, 0x42, 0xe7};
+static unsigned char times14_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_74_bits[] = {
+0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x03};
+static unsigned char times14_75_bits[] = {
+0x77, 0x22, 0x12, 0x0a, 0x0e, 0x0a, 0x12, 0x22, 0x62, 0xe7};
+static unsigned char times14_76_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x42, 0x7f};
+static unsigned char times14_77_bits[] = {
+0x07, 0x07, 0x06, 0x03, 0x8a, 0x02, 0x8a, 0x02, 0xda, 0x02, 0x52, 0x02, 
+0x52, 0x02, 0x72, 0x02, 0x22, 0x02, 0x27, 0x07};
+static unsigned char times14_78_bits[] = {
+0xc7, 0x01, 0x86, 0x00, 0x8a, 0x00, 0x9a, 0x00, 0x92, 0x00, 0xb2, 0x00, 
+0xa2, 0x00, 0xa2, 0x00, 0xc2, 0x00, 0xc7, 0x00};
+static unsigned char times14_79_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c};
+static unsigned char times14_80_bits[] = {
+0x1f, 0x32, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_81_bits[] = {
+0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 0x3c, 0x10, 0x60, 
+0xc0};
+static unsigned char times14_82_bits[] = {
+0x3f, 0x00, 0x64, 0x00, 0x44, 0x00, 0x44, 0x00, 0x64, 0x00, 0x3c, 0x00, 
+0x24, 0x00, 0x44, 0x00, 0xc4, 0x00, 0x8f, 0x01};
+static unsigned char times14_83_bits[] = {
+0x2e, 0x33, 0x21, 0x03, 0x0e, 0x18, 0x20, 0x21, 0x33, 0x1d};
+static unsigned char times14_84_bits[] = {
+0x7f, 0x49, 0x49, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c};
+static unsigned char times14_85_bits[] = {
+0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 0x3c};
+static unsigned char times14_86_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0xc6, 0x00, 0x44, 0x00, 0x44, 0x00, 0x6c, 0x00, 
+0x28, 0x00, 0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times14_87_bits[] = {
+0xe7, 0x1c, 0x42, 0x08, 0x46, 0x0c, 0x44, 0x04, 0xa4, 0x04, 0xac, 0x06, 
+0xa8, 0x02, 0x18, 0x03, 0x10, 0x01, 0x10, 0x01};
+static unsigned char times14_88_bits[] = {
+0xce, 0x01, 0x84, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x48, 0x00, 0x84, 0x00, 0x86, 0x01, 0xcf, 0x03};
+static unsigned char times14_89_bits[] = {
+0xc7, 0x01, 0x82, 0x00, 0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x38, 0x00};
+static unsigned char times14_90_bits[] = {
+0xfe, 0xc2, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x83, 0xff};
+static unsigned char times14_91_bits[] = {
+0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x07};
+static unsigned char times14_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04, 0x04, 0x08, 0x08};
+static unsigned char times14_93_bits[] = {
+0x07, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x07};
+static unsigned char times14_94_bits[] = {
+0x04, 0x0a, 0x0a, 0x11, 0x11};
+static unsigned char times14_95_bits[] = {
+0x7f};
+static unsigned char times14_96_bits[] = {
+0x02, 0x01, 0x03};
+static unsigned char times14_97_bits[] = {
+0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_98_bits[] = {
+0x03, 0x02, 0x02, 0x1a, 0x36, 0x22, 0x22, 0x22, 0x32, 0x1e};
+static unsigned char times14_99_bits[] = {
+0x1e, 0x33, 0x01, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_100_bits[] = {
+0x18, 0x10, 0x10, 0x1e, 0x13, 0x11, 0x11, 0x11, 0x1b, 0x2e};
+static unsigned char times14_101_bits[] = {
+0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_102_bits[] = {
+0x1c, 0x06, 0x02, 0x1f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0f};
+static unsigned char times14_103_bits[] = {
+0x1e, 0x0b, 0x11, 0x13, 0x0e, 0x02, 0x1e, 0x21, 0x33, 0x0e};
+static unsigned char times14_104_bits[] = {
+0x03, 0x02, 0x02, 0x1a, 0x36, 0x22, 0x22, 0x22, 0x22, 0x77};
+static unsigned char times14_105_bits[] = {
+0x02, 0x02, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_106_bits[] = {
+0x04, 0x04, 0x00, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 
+0x03};
+static unsigned char times14_107_bits[] = {
+0x03, 0x02, 0x02, 0x32, 0x12, 0x0e, 0x0a, 0x12, 0x32, 0x67};
+static unsigned char times14_108_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_109_bits[] = {
+0xdb, 0x01, 0x76, 0x03, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 0x22, 0x02, 
+0x77, 0x07};
+static unsigned char times14_110_bits[] = {
+0x1b, 0x36, 0x22, 0x22, 0x22, 0x22, 0x77};
+static unsigned char times14_111_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_112_bits[] = {
+0x1b, 0x36, 0x22, 0x22, 0x22, 0x36, 0x1a, 0x02, 0x02, 0x07};
+static unsigned char times14_113_bits[] = {
+0x1e, 0x13, 0x11, 0x11, 0x11, 0x1b, 0x16, 0x10, 0x10, 0x38};
+static unsigned char times14_114_bits[] = {
+0x1d, 0x06, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_115_bits[] = {
+0x0e, 0x09, 0x03, 0x06, 0x0c, 0x09, 0x07};
+static unsigned char times14_116_bits[] = {
+0x02, 0x0f, 0x02, 0x02, 0x02, 0x02, 0x02, 0x0c};
+static unsigned char times14_117_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_118_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08};
+static unsigned char times14_119_bits[] = {
+0x77, 0x07, 0x22, 0x02, 0x22, 0x02, 0x24, 0x01, 0xdc, 0x01, 0x88, 0x00, 
+0x88, 0x00};
+static unsigned char times14_120_bits[] = {
+0x77, 0x22, 0x1c, 0x08, 0x1c, 0x22, 0x77};
+static unsigned char times14_121_bits[] = {
+0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x0c, 0x04, 0x05, 0x03};
+static unsigned char times14_122_bits[] = {
+0x3f, 0x11, 0x18, 0x0c, 0x06, 0x23, 0x3f};
+static unsigned char times14_123_bits[] = {
+0x18, 0x04, 0x04, 0x04, 0x04, 0x02, 0x01, 0x02, 0x04, 0x04, 0x04, 0x04, 
+0x18};
+static unsigned char times14_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times14_125_bits[] = {
+0x03, 0x04, 0x04, 0x04, 0x04, 0x08, 0x10, 0x08, 0x04, 0x04, 0x04, 0x04, 
+0x03};
+static unsigned char times14_126_bits[] = {
+0x46, 0x39};
+static unsigned char times14_127_bits[] = {
+0x00};
+static unsigned char times14_128_bits[] = {
+0x00};
+static unsigned char times14_129_bits[] = {
+0x00};
+static unsigned char times14_130_bits[] = {
+0x00};
+static unsigned char times14_131_bits[] = {
+0x00};
+static unsigned char times14_132_bits[] = {
+0x00};
+static unsigned char times14_133_bits[] = {
+0x00};
+static unsigned char times14_134_bits[] = {
+0x00};
+static unsigned char times14_135_bits[] = {
+0x00};
+static unsigned char times14_136_bits[] = {
+0x00};
+static unsigned char times14_137_bits[] = {
+0x00};
+static unsigned char times14_138_bits[] = {
+0x00};
+static unsigned char times14_139_bits[] = {
+0x00};
+static unsigned char times14_140_bits[] = {
+0x00};
+static unsigned char times14_141_bits[] = {
+0x00};
+static unsigned char times14_142_bits[] = {
+0x00};
+static unsigned char times14_143_bits[] = {
+0x00};
+static unsigned char times14_144_bits[] = {
+0x00};
+static unsigned char times14_145_bits[] = {
+0x00};
+static unsigned char times14_146_bits[] = {
+0x00};
+static unsigned char times14_147_bits[] = {
+0x00};
+static unsigned char times14_148_bits[] = {
+0x00};
+static unsigned char times14_149_bits[] = {
+0x00};
+static unsigned char times14_150_bits[] = {
+0x00};
+static unsigned char times14_151_bits[] = {
+0x00};
+static unsigned char times14_152_bits[] = {
+0x00};
+static unsigned char times14_153_bits[] = {
+0x00};
+static unsigned char times14_154_bits[] = {
+0x00};
+static unsigned char times14_155_bits[] = {
+0x00};
+static unsigned char times14_156_bits[] = {
+0x00};
+static unsigned char times14_157_bits[] = {
+0x00};
+static unsigned char times14_158_bits[] = {
+0x00};
+static unsigned char times14_159_bits[] = {
+0x00};
+static unsigned char times14_160_bits[] = {
+0x00};
+static unsigned char times14_161_bits[] = {
+0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times14_162_bits[] = {
+0x20, 0x3e, 0x33, 0x09, 0x09, 0x05, 0x27, 0x1e, 0x01};
+static unsigned char times14_163_bits[] = {
+0x38, 0x2c, 0x04, 0x04, 0x1f, 0x04, 0x04, 0x04, 0x47, 0x3d};
+static unsigned char times14_164_bits[] = {
+0x11, 0x0e, 0x11, 0x11, 0x11, 0x0e, 0x11};
+static unsigned char times14_165_bits[] = {
+0x77, 0x22, 0x36, 0x14, 0x3e, 0x08, 0x3e, 0x08, 0x08, 0x1c};
+static unsigned char times14_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times14_167_bits[] = {
+0x1c, 0x1a, 0x02, 0x06, 0x0e, 0x19, 0x11, 0x13, 0x0e, 0x0c, 0x08, 0x0b, 
+0x07};
+static unsigned char times14_168_bits[] = {
+0x05, 0x05};
+static unsigned char times14_169_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x72, 0x01, 0x49, 0x02, 0x09, 0x02, 0x09, 0x02, 
+0x49, 0x02, 0x32, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char times14_170_bits[] = {
+0x07, 0x04, 0x05, 0x07, 0x00, 0x07};
+static unsigned char times14_171_bits[] = {
+0x24, 0x12, 0x09, 0x09, 0x12, 0x24};
+static unsigned char times14_172_bits[] = {
+0x7f, 0x40, 0x40, 0x40};
+static unsigned char times14_173_bits[] = {
+0x07};
+static unsigned char times14_174_bits[] = {
+0x78, 0x00, 0x86, 0x01, 0x3a, 0x01, 0x49, 0x02, 0x39, 0x02, 0x29, 0x02, 
+0x49, 0x02, 0x4a, 0x01, 0x86, 0x01, 0x78, 0x00};
+static unsigned char times14_175_bits[] = {
+0x0f};
+static unsigned char times14_176_bits[] = {
+0x06, 0x09, 0x09, 0x06};
+static unsigned char times14_177_bits[] = {
+0x08, 0x08, 0x7f, 0x08, 0x08, 0x00, 0x7f};
+static unsigned char times14_178_bits[] = {
+0x06, 0x09, 0x08, 0x04, 0x02, 0x0f};
+static unsigned char times14_179_bits[] = {
+0x06, 0x09, 0x04, 0x08, 0x09, 0x06};
+static unsigned char times14_180_bits[] = {
+0x04, 0x06, 0x01};
+static unsigned char times14_181_bits[] = {
+0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6e, 0x02, 0x02, 0x06};
+static unsigned char times14_182_bits[] = {
+0x7c, 0x2e, 0x2f, 0x2f, 0x2f, 0x2e, 0x2c, 0x28, 0x28, 0x28, 0x28, 0x28, 
+0x28};
+static unsigned char times14_183_bits[] = {
+0x01, 0x01};
+static unsigned char times14_184_bits[] = {
+0x02, 0x04, 0x03};
+static unsigned char times14_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_186_bits[] = {
+0x06, 0x09, 0x09, 0x06, 0x00, 0x0f};
+static unsigned char times14_187_bits[] = {
+0x09, 0x12, 0x24, 0x24, 0x12, 0x09};
+static unsigned char times14_188_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x42, 0x00, 0x22, 0x00, 0x22, 0x01, 0x97, 0x01, 
+0x50, 0x01, 0x28, 0x01, 0xe8, 0x03, 0x04, 0x01};
+static unsigned char times14_189_bits[] = {
+0x82, 0x00, 0x43, 0x00, 0x42, 0x00, 0x22, 0x00, 0xa2, 0x01, 0x57, 0x02, 
+0x10, 0x02, 0x08, 0x01, 0x88, 0x00, 0xc4, 0x03};
+static unsigned char times14_190_bits[] = {
+0x86, 0x00, 0x49, 0x00, 0x44, 0x00, 0x28, 0x00, 0x29, 0x01, 0x96, 0x01, 
+0x50, 0x01, 0x28, 0x01, 0xe8, 0x03, 0x04, 0x01};
+static unsigned char times14_191_bits[] = {
+0x04, 0x04, 0x00, 0x04, 0x04, 0x02, 0x01, 0x11, 0x11, 0x0e};
+static unsigned char times14_192_bits[] = {
+0x08, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_193_bits[] = {
+0x20, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_194_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x44, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_195_bits[] = {
+0x48, 0x00, 0x54, 0x00, 0x24, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_196_bits[] = {
+0x24, 0x00, 0x24, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x28, 0x00, 
+0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 0x82, 0x00, 
+0xc7, 0x01};
+static unsigned char times14_197_bits[] = {
+0x18, 0x00, 0x24, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x28, 0x00, 0x28, 0x00, 0x44, 0x00, 0x44, 0x00, 0x7c, 0x00, 0x82, 0x00, 
+0x82, 0x00, 0xc7, 0x01};
+static unsigned char times14_198_bits[] = {
+0xf8, 0x07, 0x30, 0x04, 0x28, 0x00, 0x28, 0x02, 0xe4, 0x03, 0x24, 0x02, 
+0x3c, 0x00, 0x22, 0x04, 0x22, 0x04, 0xf7, 0x07};
+static unsigned char times14_199_bits[] = {
+0xbc, 0xc6, 0x82, 0x81, 0x01, 0x01, 0x01, 0x83, 0x46, 0x3c, 0x10, 0x20, 
+0x18};
+static unsigned char times14_200_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 
+0x42, 0x7f};
+static unsigned char times14_201_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 
+0x42, 0x7f};
+static unsigned char times14_202_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 
+0x42, 0x7f};
+static unsigned char times14_203_bits[] = {
+0x24, 0x24, 0x00, 0x7f, 0x42, 0x02, 0x22, 0x3e, 0x22, 0x02, 0x42, 0x42, 
+0x7f};
+static unsigned char times14_204_bits[] = {
+0x01, 0x03, 0x04, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x07};
+static unsigned char times14_205_bits[] = {
+0x04, 0x06, 0x01, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x02, 0x07};
+static unsigned char times14_206_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 
+0x04, 0x0e};
+static unsigned char times14_207_bits[] = {
+0x05, 0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 
+0x07};
+static unsigned char times14_208_bits[] = {
+0x7f, 0x00, 0xc4, 0x00, 0x84, 0x00, 0x04, 0x01, 0x1f, 0x01, 0x04, 0x01, 
+0x04, 0x01, 0x84, 0x00, 0xc4, 0x00, 0x7f, 0x00};
+static unsigned char times14_209_bits[] = {
+0x48, 0x00, 0x54, 0x00, 0x24, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x86, 0x00, 
+0x8a, 0x00, 0x9a, 0x00, 0x92, 0x00, 0xb2, 0x00, 0xa2, 0x00, 0xa2, 0x00, 
+0xc2, 0x00, 0xc7, 0x00};
+static unsigned char times14_210_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_211_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_212_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_213_bits[] = {
+0x24, 0x2a, 0x12, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_214_bits[] = {
+0x24, 0x24, 0x00, 0x3c, 0x66, 0x42, 0x81, 0x81, 0x81, 0x81, 0x42, 0x66, 
+0x3c};
+static unsigned char times14_215_bits[] = {
+0x41, 0x22, 0x14, 0x08, 0x14, 0x22, 0x41};
+static unsigned char times14_216_bits[] = {
+0x00, 0x01, 0xf8, 0x00, 0x8c, 0x00, 0xc4, 0x00, 0x22, 0x01, 0x32, 0x01, 
+0x12, 0x01, 0x0a, 0x01, 0x8c, 0x00, 0xc6, 0x00, 0x7a, 0x00, 0x01, 0x00};
+static unsigned char times14_217_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_218_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_219_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 
+0x66, 0x3c};
+static unsigned char times14_220_bits[] = {
+0x24, 0x24, 0x00, 0xe7, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x66, 
+0x3c};
+static unsigned char times14_221_bits[] = {
+0x40, 0x00, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0xc7, 0x01, 0x82, 0x00, 
+0x44, 0x00, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 
+0x10, 0x00, 0x38, 0x00};
+static unsigned char times14_222_bits[] = {
+0x07, 0x02, 0x1e, 0x32, 0x22, 0x22, 0x32, 0x1e, 0x02, 0x07};
+static unsigned char times14_223_bits[] = {
+0x1c, 0x36, 0x22, 0x12, 0x0e, 0x1a, 0x32, 0x22, 0x2a, 0x1b};
+static unsigned char times14_224_bits[] = {
+0x02, 0x06, 0x08, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_225_bits[] = {
+0x10, 0x18, 0x04, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_226_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_227_bits[] = {
+0x12, 0x15, 0x09, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_228_bits[] = {
+0x0a, 0x0a, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_229_bits[] = {
+0x0c, 0x12, 0x0c, 0x00, 0x0e, 0x13, 0x18, 0x16, 0x11, 0x13, 0x2e};
+static unsigned char times14_230_bits[] = {
+0xfe, 0x00, 0x93, 0x01, 0xf8, 0x00, 0x16, 0x00, 0x11, 0x00, 0x33, 0x01, 
+0xee, 0x00};
+static unsigned char times14_231_bits[] = {
+0x0e, 0x13, 0x01, 0x01, 0x01, 0x23, 0x1e, 0x04, 0x08, 0x06};
+static unsigned char times14_232_bits[] = {
+0x02, 0x06, 0x08, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_233_bits[] = {
+0x10, 0x18, 0x04, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_234_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_235_bits[] = {
+0x0a, 0x0a, 0x00, 0x0e, 0x11, 0x1f, 0x01, 0x01, 0x23, 0x1e};
+static unsigned char times14_236_bits[] = {
+0x01, 0x03, 0x04, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_237_bits[] = {
+0x04, 0x06, 0x01, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_238_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x06, 0x04, 0x04, 0x04, 0x04, 0x04, 0x0e};
+static unsigned char times14_239_bits[] = {
+0x05, 0x05, 0x00, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times14_240_bits[] = {
+0x1b, 0x06, 0x09, 0x1e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_241_bits[] = {
+0x24, 0x2a, 0x12, 0x00, 0x1b, 0x36, 0x22, 0x22, 0x22, 0x22, 0x77};
+static unsigned char times14_242_bits[] = {
+0x02, 0x06, 0x08, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_243_bits[] = {
+0x08, 0x0c, 0x02, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_244_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_245_bits[] = {
+0x12, 0x15, 0x09, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_246_bits[] = {
+0x0a, 0x0a, 0x00, 0x0e, 0x1b, 0x11, 0x11, 0x11, 0x1b, 0x0e};
+static unsigned char times14_247_bits[] = {
+0x08, 0x08, 0x00, 0x7f, 0x00, 0x08, 0x08};
+static unsigned char times14_248_bits[] = {
+0x40, 0x3c, 0x36, 0x22, 0x22, 0x22, 0x36, 0x1e, 0x01};
+static unsigned char times14_249_bits[] = {
+0x04, 0x0c, 0x10, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_250_bits[] = {
+0x10, 0x18, 0x04, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_251_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_252_bits[] = {
+0x14, 0x14, 0x00, 0x33, 0x22, 0x22, 0x22, 0x22, 0x36, 0x6c};
+static unsigned char times14_253_bits[] = {
+0x20, 0x30, 0x08, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x0c, 0x04, 
+0x05, 0x03};
+static unsigned char times14_254_bits[] = {
+0x03, 0x02, 0x02, 0x1a, 0x36, 0x22, 0x22, 0x22, 0x36, 0x1a, 0x02, 0x02, 
+0x07};
+static unsigned char times14_255_bits[] = {
+0x14, 0x14, 0x00, 0x77, 0x22, 0x22, 0x14, 0x14, 0x08, 0x0c, 0x04, 0x05, 
+0x03};
+static RotFont times14font[] = {
+{5, 1, 1, times14_0_bits},
+{5, 1, 1, times14_1_bits},
+{5, 1, 1, times14_2_bits},
+{5, 1, 1, times14_3_bits},
+{5, 1, 1, times14_4_bits},
+{5, 1, 1, times14_5_bits},
+{5, 1, 1, times14_6_bits},
+{5, 1, 1, times14_7_bits},
+{5, 1, 1, times14_8_bits},
+{5, 1, 1, times14_9_bits},
+{5, 1, 1, times14_10_bits},
+{5, 1, 1, times14_11_bits},
+{5, 1, 1, times14_12_bits},
+{5, 1, 1, times14_13_bits},
+{5, 1, 1, times14_14_bits},
+{5, 1, 1, times14_15_bits},
+{5, 1, 1, times14_16_bits},
+{5, 1, 1, times14_17_bits},
+{5, 1, 1, times14_18_bits},
+{5, 1, 1, times14_19_bits},
+{5, 1, 1, times14_20_bits},
+{5, 1, 1, times14_21_bits},
+{5, 1, 1, times14_22_bits},
+{5, 1, 1, times14_23_bits},
+{5, 1, 1, times14_24_bits},
+{5, 1, 1, times14_25_bits},
+{5, 1, 1, times14_26_bits},
+{5, 1, 1, times14_27_bits},
+{5, 1, 1, times14_28_bits},
+{5, 1, 1, times14_29_bits},
+{5, 1, 1, times14_30_bits},
+{5, 1, 1, times14_31_bits},
+{6, 1, 1, times14_32_bits},
+{1, 10, 10, times14_33_bits},
+{3, 3, 10, times14_34_bits},
+{7, 10, 10, times14_35_bits},
+{5, 12, 11, times14_36_bits},
+{9, 10, 10, times14_37_bits},
+{10, 10, 10, times14_38_bits},
+{2, 3, 10, times14_39_bits},
+{3, 13, 10, times14_40_bits},
+{3, 13, 10, times14_41_bits},
+{5, 6, 10, times14_42_bits},
+{7, 7, 7, times14_43_bits},
+{2, 3, 1, times14_44_bits},
+{6, 1, 4, times14_45_bits},
+{2, 1, 1, times14_46_bits},
+{4, 12, 10, times14_47_bits},
+{6, 10, 10, times14_48_bits},
+{5, 10, 10, times14_49_bits},
+{5, 10, 10, times14_50_bits},
+{6, 10, 10, times14_51_bits},
+{6, 10, 10, times14_52_bits},
+{5, 10, 10, times14_53_bits},
+{6, 10, 10, times14_54_bits},
+{6, 10, 10, times14_55_bits},
+{5, 10, 10, times14_56_bits},
+{6, 10, 10, times14_57_bits},
+{2, 7, 7, times14_58_bits},
+{2, 9, 7, times14_59_bits},
+{7, 7, 7, times14_60_bits},
+{7, 3, 5, times14_61_bits},
+{7, 7, 7, times14_62_bits},
+{5, 10, 10, times14_63_bits},
+{12, 12, 10, times14_64_bits},
+{9, 10, 10, times14_65_bits},
+{7, 10, 10, times14_66_bits},
+{8, 10, 10, times14_67_bits},
+{9, 10, 10, times14_68_bits},
+{7, 10, 10, times14_69_bits},
+{7, 10, 10, times14_70_bits},
+{9, 10, 10, times14_71_bits},
+{8, 10, 10, times14_72_bits},
+{3, 10, 10, times14_73_bits},
+{4, 10, 10, times14_74_bits},
+{8, 10, 10, times14_75_bits},
+{7, 10, 10, times14_76_bits},
+{11, 10, 10, times14_77_bits},
+{9, 10, 10, times14_78_bits},
+{8, 10, 10, times14_79_bits},
+{6, 10, 10, times14_80_bits},
+{8, 13, 10, times14_81_bits},
+{9, 10, 10, times14_82_bits},
+{6, 10, 10, times14_83_bits},
+{7, 10, 10, times14_84_bits},
+{8, 10, 10, times14_85_bits},
+{9, 10, 10, times14_86_bits},
+{13, 10, 10, times14_87_bits},
+{10, 10, 10, times14_88_bits},
+{9, 10, 10, times14_89_bits},
+{8, 10, 10, times14_90_bits},
+{3, 13, 10, times14_91_bits},
+{4, 10, 10, times14_92_bits},
+{3, 13, 10, times14_93_bits},
+{5, 5, 10, times14_94_bits},
+{7, 1, -2, times14_95_bits},
+{2, 3, 10, times14_96_bits},
+{6, 7, 7, times14_97_bits},
+{6, 10, 10, times14_98_bits},
+{6, 7, 7, times14_99_bits},
+{6, 10, 10, times14_100_bits},
+{6, 7, 7, times14_101_bits},
+{5, 10, 10, times14_102_bits},
+{6, 10, 7, times14_103_bits},
+{7, 10, 10, times14_104_bits},
+{3, 10, 10, times14_105_bits},
+{3, 13, 10, times14_106_bits},
+{7, 10, 10, times14_107_bits},
+{3, 10, 10, times14_108_bits},
+{11, 7, 7, times14_109_bits},
+{7, 7, 7, times14_110_bits},
+{5, 7, 7, times14_111_bits},
+{6, 10, 7, times14_112_bits},
+{6, 10, 7, times14_113_bits},
+{5, 7, 7, times14_114_bits},
+{4, 7, 7, times14_115_bits},
+{4, 8, 8, times14_116_bits},
+{7, 7, 7, times14_117_bits},
+{7, 7, 7, times14_118_bits},
+{11, 7, 7, times14_119_bits},
+{7, 7, 7, times14_120_bits},
+{7, 10, 7, times14_121_bits},
+{6, 7, 7, times14_122_bits},
+{5, 13, 10, times14_123_bits},
+{1, 10, 10, times14_124_bits},
+{5, 13, 10, times14_125_bits},
+{7, 2, 5, times14_126_bits},
+{5, 1, 1, times14_127_bits},
+{5, 1, 1, times14_128_bits},
+{5, 1, 1, times14_129_bits},
+{5, 1, 1, times14_130_bits},
+{5, 1, 1, times14_131_bits},
+{5, 1, 1, times14_132_bits},
+{5, 1, 1, times14_133_bits},
+{5, 1, 1, times14_134_bits},
+{5, 1, 1, times14_135_bits},
+{5, 1, 1, times14_136_bits},
+{5, 1, 1, times14_137_bits},
+{5, 1, 1, times14_138_bits},
+{5, 1, 1, times14_139_bits},
+{5, 1, 1, times14_140_bits},
+{5, 1, 1, times14_141_bits},
+{5, 1, 1, times14_142_bits},
+{5, 1, 1, times14_143_bits},
+{5, 1, 1, times14_144_bits},
+{5, 1, 1, times14_145_bits},
+{5, 1, 1, times14_146_bits},
+{5, 1, 1, times14_147_bits},
+{5, 1, 1, times14_148_bits},
+{5, 1, 1, times14_149_bits},
+{5, 1, 1, times14_150_bits},
+{5, 1, 1, times14_151_bits},
+{5, 1, 1, times14_152_bits},
+{5, 1, 1, times14_153_bits},
+{5, 1, 1, times14_154_bits},
+{5, 1, 1, times14_155_bits},
+{5, 1, 1, times14_156_bits},
+{5, 1, 1, times14_157_bits},
+{5, 1, 1, times14_158_bits},
+{5, 1, 1, times14_159_bits},
+{1, 1, 1, times14_160_bits},
+{1, 10, 7, times14_161_bits},
+{6, 9, 8, times14_162_bits},
+{7, 10, 10, times14_163_bits},
+{5, 7, 8, times14_164_bits},
+{7, 10, 10, times14_165_bits},
+{1, 10, 10, times14_166_bits},
+{5, 13, 10, times14_167_bits},
+{3, 2, 10, times14_168_bits},
+{10, 10, 10, times14_169_bits},
+{3, 6, 10, times14_170_bits},
+{6, 6, 6, times14_171_bits},
+{7, 4, 6, times14_172_bits},
+{3, 1, 4, times14_173_bits},
+{10, 10, 10, times14_174_bits},
+{4, 1, 9, times14_175_bits},
+{4, 4, 10, times14_176_bits},
+{7, 7, 7, times14_177_bits},
+{4, 6, 10, times14_178_bits},
+{4, 6, 10, times14_179_bits},
+{3, 3, 11, times14_180_bits},
+{7, 10, 7, times14_181_bits},
+{7, 13, 10, times14_182_bits},
+{1, 2, 5, times14_183_bits},
+{3, 3, 0, times14_184_bits},
+{3, 6, 10, times14_185_bits},
+{4, 6, 10, times14_186_bits},
+{6, 6, 6, times14_187_bits},
+{10, 10, 10, times14_188_bits},
+{10, 10, 10, times14_189_bits},
+{10, 10, 10, times14_190_bits},
+{5, 10, 7, times14_191_bits},
+{9, 14, 14, times14_192_bits},
+{9, 14, 14, times14_193_bits},
+{9, 14, 14, times14_194_bits},
+{9, 14, 14, times14_195_bits},
+{9, 13, 13, times14_196_bits},
+{9, 14, 14, times14_197_bits},
+{11, 10, 10, times14_198_bits},
+{8, 13, 10, times14_199_bits},
+{7, 14, 14, times14_200_bits},
+{7, 14, 14, times14_201_bits},
+{7, 14, 14, times14_202_bits},
+{7, 13, 13, times14_203_bits},
+{3, 14, 14, times14_204_bits},
+{3, 14, 14, times14_205_bits},
+{5, 14, 14, times14_206_bits},
+{3, 13, 13, times14_207_bits},
+{9, 10, 10, times14_208_bits},
+{9, 14, 14, times14_209_bits},
+{8, 14, 14, times14_210_bits},
+{8, 14, 14, times14_211_bits},
+{8, 14, 14, times14_212_bits},
+{8, 14, 14, times14_213_bits},
+{8, 13, 13, times14_214_bits},
+{7, 7, 7, times14_215_bits},
+{9, 12, 11, times14_216_bits},
+{8, 14, 14, times14_217_bits},
+{8, 14, 14, times14_218_bits},
+{8, 14, 14, times14_219_bits},
+{8, 13, 13, times14_220_bits},
+{9, 14, 14, times14_221_bits},
+{6, 10, 10, times14_222_bits},
+{6, 10, 10, times14_223_bits},
+{6, 11, 11, times14_224_bits},
+{6, 11, 11, times14_225_bits},
+{6, 11, 11, times14_226_bits},
+{6, 11, 11, times14_227_bits},
+{6, 10, 10, times14_228_bits},
+{6, 11, 11, times14_229_bits},
+{9, 7, 7, times14_230_bits},
+{6, 10, 7, times14_231_bits},
+{6, 11, 11, times14_232_bits},
+{6, 11, 11, times14_233_bits},
+{6, 11, 11, times14_234_bits},
+{6, 10, 10, times14_235_bits},
+{3, 11, 11, times14_236_bits},
+{3, 11, 11, times14_237_bits},
+{5, 11, 11, times14_238_bits},
+{3, 10, 10, times14_239_bits},
+{5, 10, 10, times14_240_bits},
+{7, 11, 11, times14_241_bits},
+{5, 11, 11, times14_242_bits},
+{5, 11, 11, times14_243_bits},
+{5, 11, 11, times14_244_bits},
+{5, 11, 11, times14_245_bits},
+{5, 10, 10, times14_246_bits},
+{7, 7, 7, times14_247_bits},
+{7, 9, 8, times14_248_bits},
+{7, 11, 11, times14_249_bits},
+{7, 11, 11, times14_250_bits},
+{7, 11, 11, times14_251_bits},
+{7, 10, 10, times14_252_bits},
+{7, 14, 11, times14_253_bits},
+{6, 13, 10, times14_254_bits},
+{7, 13, 10, times14_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times18.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times18.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times18.bdf	(revision 16632)
@@ -0,0 +1,3675 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--18-180-75-75-P-94-ISO8859-1
+SIZE 18 75 75
+FONTBOUNDINGBOX 19 21 -1 -4
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 18
+POINT_SIZE 180
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 94
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 13
+X_HEIGHT 9
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 22-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--18-180-75-75-P-94-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 10
+DEFAULT_CHAR 32
+FONT_ASCENT 15
+FONT_DESCENT 4
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 13 1 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+40
+40
+40
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 4 1 9
+BITMAP
+cc
+cc
+cc
+88
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 11 13 -1 0
+BITMAP
+0d80
+0d80
+0d80
+0d80
+7fe0
+1b00
+1b00
+1b00
+ffc0
+3600
+3600
+3600
+3600
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 16 1 -2
+BITMAP
+10
+7c
+d6
+d2
+d0
+f0
+78
+3c
+1c
+16
+16
+96
+d6
+7c
+10
+10
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+3830
+6fe0
+c440
+c480
+cd80
+fb00
+7270
+06d8
+0d88
+0988
+1998
+31f0
+20e0
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+1c00
+3200
+3200
+3200
+3400
+19e0
+38c0
+6d80
+cf00
+c700
+c780
+edf0
+78e0
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 4 1 9
+BITMAP
+c0
+e0
+20
+40
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 17 1 -4
+BITMAP
+18
+30
+60
+60
+40
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+40
+60
+60
+30
+18
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 17 1 -4
+BITMAP
+c0
+60
+30
+30
+10
+18
+18
+18
+18
+18
+18
+18
+10
+30
+30
+60
+c0
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 8 1 6
+BITMAP
+10
+10
+d6
+54
+38
+d6
+92
+10
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 1 0
+BITMAP
+0800
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0800
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 3 5 0 -3
+BITMAP
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 1 1 4
+BITMAP
+ff
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 15 0 -2
+BITMAP
+08
+08
+18
+10
+10
+30
+20
+20
+60
+40
+40
+c0
+80
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+42
+c3
+c3
+c3
+c3
+c3
+c3
+c3
+42
+66
+3c
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 6 13 2 0
+BITMAP
+30
+70
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+78
+fc
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+3c
+7e
+ce
+86
+06
+06
+0c
+0c
+18
+30
+62
+fe
+fe
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7c
+ce
+86
+06
+0c
+38
+3c
+0e
+06
+06
+06
+cc
+f8
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+06
+0e
+0e
+16
+26
+66
+46
+86
+ff
+ff
+06
+06
+06
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+7e
+7c
+c0
+c0
+f0
+3c
+0c
+0e
+06
+06
+0c
+dc
+f0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+07
+1c
+30
+60
+60
+fc
+c6
+c3
+c3
+c3
+e3
+76
+3c
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+fe
+fe
+84
+0c
+08
+18
+18
+10
+30
+30
+20
+60
+60
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+66
+62
+62
+74
+3c
+3c
+6e
+c7
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+3c
+6e
+c6
+c3
+c3
+c3
+e3
+7f
+06
+06
+0c
+38
+e0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 9 1 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 3 12 0 -3
+BITMAP
+60
+60
+00
+00
+00
+00
+00
+60
+60
+20
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+0180
+0700
+1c00
+7000
+c000
+7000
+1c00
+0700
+0180
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 3 1 3
+BITMAP
+ff
+00
+ff
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 9 1 0
+BITMAP
+c000
+7000
+1c00
+0700
+0180
+0700
+1c00
+7000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 0
+BITMAP
+78
+8c
+c4
+cc
+0c
+18
+18
+30
+20
+20
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 906 0
+DWIDTH 17 0
+BBX 14 16 1 -3
+BITMAP
+07e0
+0e30
+3818
+3008
+63ec
+67e4
+c664
+cc64
+cccc
+ccc8
+cdd8
+6770
+6000
+3000
+1c30
+07e0
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+ff00
+6380
+6180
+6180
+6180
+6300
+7f80
+61c0
+60c0
+60c0
+60c0
+6180
+ff00
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 1 0
+BITMAP
+0f20
+30e0
+6060
+6020
+c000
+c000
+c000
+c000
+c000
+6000
+6060
+38c0
+0f00
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+ff00
+6380
+60c0
+60c0
+6060
+6060
+6060
+6060
+6060
+60c0
+60c0
+6380
+ff00
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 13 1 0
+BITMAP
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0f20
+30e0
+6060
+6020
+c000
+c000
+c0f0
+c060
+c060
+6060
+6060
+39c0
+0f00
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f1e0
+60c0
+60c0
+60c0
+60c0
+60c0
+7fc0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 13 1 0
+BITMAP
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 13 0 0
+BITMAP
+3c
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+d8
+f0
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f3c0
+6180
+6300
+6600
+6c00
+7800
+7800
+6c00
+6600
+6300
+6380
+61c0
+f0e0
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 1 0
+BITMAP
+f000
+6000
+6000
+6000
+6000
+6000
+6000
+6000
+6000
+6000
+6040
+60c0
+ffc0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 853 0
+DWIDTH 16 0
+BBX 14 13 1 0
+BITMAP
+e01c
+7038
+7038
+7878
+5858
+58d8
+5cd8
+4c98
+4d98
+4718
+4718
+4218
+e23c
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+e0e0
+6040
+7040
+7840
+5840
+4c40
+4e40
+4740
+4340
+41c0
+41c0
+40c0
+e040
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 13 1 0
+BITMAP
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 1 0
+BITMAP
+ff00
+6380
+6180
+6180
+6180
+6300
+7e00
+6000
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 -4
+BITMAP
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+0600
+0300
+01c0
+00f0
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 13 1 0
+BITMAP
+ff00
+6380
+6180
+6180
+6180
+6300
+7e00
+6600
+6300
+6180
+6180
+60c0
+f0e0
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 13 1 0
+BITMAP
+3a
+66
+c2
+c0
+e0
+78
+3c
+0e
+07
+03
+83
+c6
+bc
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+ffc0
+ccc0
+8c40
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+0c00
+1e00
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 0 0
+BITMAP
+f878
+7030
+3020
+3820
+1860
+1840
+1c40
+0cc0
+0e80
+0680
+0780
+0300
+0300
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 18 0
+BBX 18 13 0 0
+BITMAP
+f9e3c0
+30c180
+30c100
+18c100
+186300
+186200
+1ce200
+0ca600
+0cb400
+0d3400
+073c00
+061800
+061800
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 13 0 0
+BITMAP
+f070
+7060
+38c0
+1980
+0d00
+0e00
+0600
+0f00
+1b00
+1180
+31c0
+60e0
+f0f0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 13 0 0
+BITMAP
+f0f0
+7060
+30c0
+1880
+1900
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+0f00
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 10 13 1 0
+BITMAP
+7fc0
+61c0
+4180
+0380
+0700
+0600
+0e00
+1c00
+3800
+3000
+7040
+e0c0
+ffc0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 16 2 -3
+BITMAP
+f0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 13 0 0
+BITMAP
+80
+80
+c0
+40
+60
+60
+20
+30
+30
+10
+18
+08
+08
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 16 0 -3
+BITMAP
+f0
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+f0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 7 1 6
+BITMAP
+10
+38
+28
+6c
+44
+c6
+82
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 1 0 -4
+BITMAP
+ff80
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 4 1 9
+BITMAP
+40
+80
+e0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+78
+cc
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+e0
+60
+60
+60
+6e
+77
+63
+63
+63
+63
+63
+76
+3c
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+3c
+66
+c6
+c0
+c0
+c0
+c0
+62
+3c
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+0e
+06
+06
+06
+3e
+66
+c6
+c6
+c6
+c6
+c6
+66
+3f
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+c3
+ff
+c0
+c0
+e1
+76
+3c
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 13 0 0
+BITMAP
+1c
+34
+20
+60
+f8
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 13 0 -4
+BITMAP
+3e
+cc
+c4
+c4
+cc
+78
+40
+7c
+7f
+83
+c1
+e2
+7c
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 0 0
+BITMAP
+e000
+6000
+6000
+6000
+6600
+6f00
+7300
+6300
+6300
+6300
+6300
+6300
+f380
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+60
+60
+00
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 17 -1 -4
+BITMAP
+30
+30
+00
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+e0
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+e000
+6000
+6000
+6000
+6700
+6200
+6400
+6800
+7800
+6c00
+6600
+6300
+e380
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 14 9 0 0
+BITMAP
+e630
+6f78
+7398
+6318
+6318
+6318
+6318
+6318
+f7bc
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 9 0 0
+BITMAP
+e600
+6f00
+7300
+6300
+6300
+6300
+6300
+6300
+f380
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 9 0 0
+BITMAP
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 -4
+BITMAP
+ee
+77
+63
+63
+63
+63
+63
+76
+6c
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 -4
+BITMAP
+3e
+66
+c6
+c6
+c6
+c6
+c6
+66
+3e
+06
+06
+06
+0f
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 6 9 0 0
+BITMAP
+ec
+6c
+70
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 9 0 0
+BITMAP
+68
+d8
+c8
+e0
+70
+38
+98
+d8
+b0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 11 0 0
+BITMAP
+20
+60
+f8
+60
+60
+60
+60
+60
+60
+74
+38
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 9 -1 0
+BITMAP
+f380
+6300
+6200
+3200
+3600
+1400
+1c00
+0800
+0800
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 13 9 -1 0
+BITMAP
+e738
+6630
+6260
+3660
+3760
+1d40
+1dc0
+0880
+0880
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 9 0 0
+BITMAP
+e380
+6300
+3600
+1c00
+0c00
+1c00
+3600
+6300
+e380
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 9 13 -1 -4
+BITMAP
+f380
+6100
+7300
+3200
+3600
+1c00
+1c00
+0c00
+1800
+1800
+1000
+f000
+e000
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 9 0 0
+BITMAP
+fe
+ce
+8c
+18
+30
+30
+62
+e6
+fe
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+0e
+18
+30
+30
+30
+30
+30
+60
+c0
+60
+30
+30
+30
+30
+30
+18
+0e
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 160 0
+DWIDTH 3 0
+BBX 1 13 1 0
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 17 1 -4
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+0c
+06
+0c
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 2 1 4
+BITMAP
+7980
+cf00
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 1 1 1 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 13 1 -4
+BITMAP
+c0
+c0
+00
+00
+80
+80
+80
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 1 -2
+BITMAP
+06
+04
+3e
+6b
+cb
+c8
+d8
+d0
+d0
+72
+7c
+40
+c0
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 10 13 0 0
+BITMAP
+0f00
+1980
+1980
+1800
+1800
+1800
+7e00
+1800
+1800
+1000
+7840
+bfc0
+e780
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 7 1 3
+BITMAP
+dd80
+f780
+6300
+4100
+6300
+f780
+dd80
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+f7
+62
+62
+76
+34
+34
+7e
+18
+7e
+18
+18
+18
+7e
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 160 0
+DWIDTH 3 0
+BBX 1 13 1 0
+BITMAP
+80
+80
+80
+80
+80
+00
+00
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 16 1 -3
+BITMAP
+3c
+66
+66
+70
+38
+7c
+8e
+c7
+e3
+71
+3e
+1c
+0e
+66
+66
+3c
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 2 0 10
+BITMAP
+d8
+d8
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+4790
+8888
+9008
+9008
+9008
+8888
+4710
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 8 0 5
+BITMAP
+60
+90
+10
+70
+90
+e8
+00
+f8
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+11
+33
+66
+cc
+66
+33
+11
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 5 1 1
+BITMAP
+ff80
+0080
+0080
+0080
+0080
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 2 0 4
+BITMAP
+f8
+f8
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 13 1 0
+BITMAP
+0f80
+3060
+4010
+5f10
+8888
+8888
+8f08
+8908
+8888
+5cd0
+4010
+3060
+0f80
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 1 0 11
+BITMAP
+f8
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 373 0
+DWIDTH 7 0
+BBX 5 5 1 8
+BITMAP
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 10 1 0
+BITMAP
+0800
+0800
+0800
+0800
+ff80
+0800
+0800
+0800
+0000
+ff80
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 8 0 5
+BITMAP
+70
+98
+18
+10
+20
+20
+40
+f8
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 8 0 5
+BITMAP
+70
+88
+18
+70
+18
+08
+88
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 4 3 0 10
+BITMAP
+30
+60
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 -4
+BITMAP
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+7b80
+4000
+4000
+6000
+6000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 17 1 -4
+BITMAP
+3e
+74
+f4
+f4
+f4
+f4
+f4
+74
+14
+14
+14
+14
+14
+14
+14
+14
+14
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 213 0
+DWIDTH 4 0
+BBX 2 2 1 4
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 5 1 -4
+BITMAP
+20
+20
+10
+b0
+60
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 3 8 1 5
+BITMAP
+40
+c0
+40
+40
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 8 0 5
+BITMAP
+70
+d8
+88
+88
+d8
+70
+00
+f8
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+88
+cc
+66
+33
+66
+cc
+88
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+4080
+c180
+4100
+4300
+4600
+4440
+4cc0
+e940
+1b40
+3240
+27e0
+6040
+4040
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 13 1 0
+BITMAP
+4080
+c180
+4100
+4300
+4600
+45c0
+4e60
+e860
+1840
+3080
+2080
+6100
+43e0
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 13 13 -1 0
+BITMAP
+7020
+8860
+1840
+70c0
+1980
+0910
+8b30
+7250
+06d0
+0c90
+09f8
+1810
+1010
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 6 13 1 -4
+BITMAP
+30
+30
+00
+10
+10
+30
+60
+60
+c0
+cc
+8c
+c4
+78
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0c00
+0600
+0100
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+00c0
+0180
+0200
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0200
+0700
+0880
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 16 1 0
+BITMAP
+0740
+0b80
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 16 1 0
+BITMAP
+0d80
+0d80
+0000
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 800 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+0300
+0480
+0480
+0300
+0200
+0700
+0700
+0500
+0d80
+0980
+19c0
+10c0
+1fc0
+30e0
+2060
+6070
+f0f8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 906 0
+DWIDTH 17 0
+BBX 15 13 1 0
+BITMAP
+0ffc
+078c
+0584
+0580
+0d80
+0988
+19f8
+1f88
+1180
+3180
+2182
+6186
+f7fe
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 17 1 -4
+BITMAP
+0f20
+30e0
+6060
+6020
+c000
+c000
+c000
+c000
+c000
+6000
+6060
+38c0
+0f00
+0400
+0200
+1600
+0c00
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+3000
+1800
+0400
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0600
+0c00
+1000
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0800
+1c00
+2200
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 586 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+3300
+3300
+0000
+ff80
+6180
+6080
+6000
+6000
+6100
+7f00
+6100
+6000
+6000
+6080
+6180
+ff80
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+c0
+60
+10
+00
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+30
+60
+80
+00
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 5 17 1 0
+BITMAP
+20
+70
+88
+00
+f0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 6 0
+BBX 6 16 0 0
+BITMAP
+cc
+cc
+00
+78
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 12 13 0 0
+BITMAP
+7f80
+31c0
+3060
+3060
+3030
+3030
+fc30
+3030
+3030
+3060
+3060
+31c0
+7f80
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+0e80
+1700
+0000
+e0e0
+6040
+7040
+7840
+5840
+4c40
+4e40
+4740
+4340
+41c0
+41c0
+40c0
+e040
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+1800
+0c00
+0200
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+00c0
+0180
+0200
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+0200
+0700
+0880
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 16 1 0
+BITMAP
+0e80
+1700
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 16 1 0
+BITMAP
+1980
+1980
+0000
+0f00
+30c0
+6060
+6060
+c030
+c030
+c030
+c030
+c030
+6060
+6060
+30c0
+0f00
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+c3
+66
+3c
+18
+3c
+66
+c3
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 746 0
+DWIDTH 14 0
+BBX 12 15 1 -1
+BITMAP
+0030
+0f60
+30c0
+60e0
+61a0
+c330
+c330
+c630
+cc30
+cc30
+5860
+7060
+30c0
+6f00
+c000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+1800
+0c00
+0200
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0180
+0300
+0400
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0400
+0e00
+1100
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 693 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+1980
+1980
+0000
+f0e0
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+6040
+70c0
+3980
+1f00
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 12 17 0 0
+BITMAP
+0180
+0300
+0400
+0000
+f0f0
+7060
+30c0
+1880
+1900
+0f00
+0600
+0600
+0600
+0600
+0600
+0600
+0f00
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 13 1 0
+BITMAP
+f000
+6000
+6000
+7f00
+6380
+6180
+6180
+6180
+6300
+7e00
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+1c
+36
+23
+63
+63
+66
+7c
+66
+63
+63
+6b
+6b
+ee
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+c0
+60
+10
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+0c
+18
+20
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+10
+38
+44
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+34
+58
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 12 1 0
+BITMAP
+6c
+6c
+00
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 7 13 1 0
+BITMAP
+30
+48
+48
+30
+78
+c8
+cc
+1c
+6c
+cc
+cc
+fc
+66
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 12 0
+BBX 11 9 0 0
+BITMAP
+7bc0
+ce60
+cc20
+1fe0
+6c00
+cc00
+cc00
+fe60
+63c0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 -4
+BITMAP
+3c
+66
+c0
+c0
+c0
+c0
+c0
+66
+3c
+10
+08
+58
+30
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 0
+BITMAP
+60
+30
+08
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 0
+BITMAP
+06
+0c
+10
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 13 0 0
+BITMAP
+10
+38
+44
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 7 12 0 0
+BITMAP
+6c
+6c
+00
+3c
+66
+c2
+fe
+c0
+c0
+c0
+66
+3c
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+c0
+60
+10
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 4 13 0 0
+BITMAP
+30
+60
+80
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 13 0 0
+BITMAP
+20
+70
+88
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 266 0
+DWIDTH 5 0
+BBX 5 12 0 0
+BITMAP
+d8
+d8
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+60
+36
+38
+4c
+3e
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 9 12 0 0
+BITMAP
+3a00
+5c00
+0000
+e600
+6f00
+7300
+6300
+6300
+6300
+6300
+6300
+f380
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+60
+30
+08
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+06
+0c
+10
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 13 0 0
+BITMAP
+10
+38
+44
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+1a
+2c
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 12 0 0
+BITMAP
+6c
+6c
+00
+3c
+66
+c3
+c3
+c3
+c3
+c3
+66
+3c
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 533 0
+DWIDTH 10 0
+BBX 8 7 1 1
+BITMAP
+18
+18
+00
+ff
+00
+18
+18
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 11 0 -1
+BITMAP
+01
+3f
+66
+cf
+cb
+db
+d3
+f3
+66
+7c
+c0
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+3000
+1800
+0400
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+0600
+0c00
+1000
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 13 0 0
+BITMAP
+0800
+1c00
+2200
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 9 12 0 0
+BITMAP
+3600
+3600
+0000
+e700
+6300
+6300
+6300
+6300
+6300
+6300
+7700
+3b80
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 17 -1 -4
+BITMAP
+03
+06
+08
+00
+f3
+63
+72
+32
+36
+1c
+1c
+0c
+08
+18
+10
+f0
+e0
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 9 0
+BBX 8 17 0 -4
+BITMAP
+e0
+60
+60
+60
+6e
+77
+63
+63
+63
+63
+63
+76
+7c
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 426 0
+DWIDTH 8 0
+BBX 8 16 -1 -4
+BITMAP
+36
+36
+00
+f3
+63
+72
+32
+36
+1c
+1c
+0c
+08
+18
+10
+f0
+e0
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times18.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times18.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times18.h	(revision 16632)
@@ -0,0 +1,980 @@
+static unsigned char times18_0_bits[] = {
+0x00};
+static unsigned char times18_1_bits[] = {
+0x00};
+static unsigned char times18_2_bits[] = {
+0x00};
+static unsigned char times18_3_bits[] = {
+0x00};
+static unsigned char times18_4_bits[] = {
+0x00};
+static unsigned char times18_5_bits[] = {
+0x00};
+static unsigned char times18_6_bits[] = {
+0x00};
+static unsigned char times18_7_bits[] = {
+0x00};
+static unsigned char times18_8_bits[] = {
+0x00};
+static unsigned char times18_9_bits[] = {
+0x00};
+static unsigned char times18_10_bits[] = {
+0x00};
+static unsigned char times18_11_bits[] = {
+0x00};
+static unsigned char times18_12_bits[] = {
+0x00};
+static unsigned char times18_13_bits[] = {
+0x00};
+static unsigned char times18_14_bits[] = {
+0x00};
+static unsigned char times18_15_bits[] = {
+0x00};
+static unsigned char times18_16_bits[] = {
+0x00};
+static unsigned char times18_17_bits[] = {
+0x00};
+static unsigned char times18_18_bits[] = {
+0x00};
+static unsigned char times18_19_bits[] = {
+0x00};
+static unsigned char times18_20_bits[] = {
+0x00};
+static unsigned char times18_21_bits[] = {
+0x00};
+static unsigned char times18_22_bits[] = {
+0x00};
+static unsigned char times18_23_bits[] = {
+0x00};
+static unsigned char times18_24_bits[] = {
+0x00};
+static unsigned char times18_25_bits[] = {
+0x00};
+static unsigned char times18_26_bits[] = {
+0x00};
+static unsigned char times18_27_bits[] = {
+0x00};
+static unsigned char times18_28_bits[] = {
+0x00};
+static unsigned char times18_29_bits[] = {
+0x00};
+static unsigned char times18_30_bits[] = {
+0x00};
+static unsigned char times18_31_bits[] = {
+0x00};
+static unsigned char times18_32_bits[] = {
+0x00};
+static unsigned char times18_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x00, 0x00, 0x03, 
+0x03};
+static unsigned char times18_34_bits[] = {
+0x33, 0x33, 0x33, 0x11};
+static unsigned char times18_35_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0xb0, 0x01, 0xfe, 0x07, 0xd8, 0x00, 
+0xd8, 0x00, 0xd8, 0x00, 0xff, 0x03, 0x6c, 0x00, 0x6c, 0x00, 0x6c, 0x00, 
+0x6c, 0x00};
+static unsigned char times18_36_bits[] = {
+0x08, 0x3e, 0x6b, 0x4b, 0x0b, 0x0f, 0x1e, 0x3c, 0x38, 0x68, 0x68, 0x69, 
+0x6b, 0x3e, 0x08, 0x08};
+static unsigned char times18_37_bits[] = {
+0x1c, 0x0c, 0xf6, 0x07, 0x23, 0x02, 0x23, 0x01, 0xb3, 0x01, 0xdf, 0x00, 
+0x4e, 0x0e, 0x60, 0x1b, 0xb0, 0x11, 0x90, 0x11, 0x98, 0x19, 0x8c, 0x0f, 
+0x04, 0x07};
+static unsigned char times18_38_bits[] = {
+0x38, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x4c, 0x00, 0x2c, 0x00, 0x98, 0x07, 
+0x1c, 0x03, 0xb6, 0x01, 0xf3, 0x00, 0xe3, 0x00, 0xe3, 0x01, 0xb7, 0x0f, 
+0x1e, 0x07};
+static unsigned char times18_39_bits[] = {
+0x03, 0x07, 0x04, 0x02};
+static unsigned char times18_40_bits[] = {
+0x18, 0x0c, 0x06, 0x06, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x02, 0x06, 0x06, 0x0c, 0x18};
+static unsigned char times18_41_bits[] = {
+0x03, 0x06, 0x0c, 0x0c, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x08, 0x0c, 0x0c, 0x06, 0x03};
+static unsigned char times18_42_bits[] = {
+0x08, 0x08, 0x6b, 0x2a, 0x1c, 0x6b, 0x49, 0x08};
+static unsigned char times18_43_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times18_44_bits[] = {
+0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char times18_45_bits[] = {
+0xff};
+static unsigned char times18_46_bits[] = {
+0x03, 0x03};
+static unsigned char times18_47_bits[] = {
+0x10, 0x10, 0x18, 0x08, 0x08, 0x0c, 0x04, 0x04, 0x06, 0x02, 0x02, 0x03, 
+0x01, 0x01, 0x01};
+static unsigned char times18_48_bits[] = {
+0x3c, 0x66, 0x42, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x42, 0x66, 
+0x3c};
+static unsigned char times18_49_bits[] = {
+0x0c, 0x0e, 0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x1e, 
+0x3f};
+static unsigned char times18_50_bits[] = {
+0x3c, 0x7e, 0x73, 0x61, 0x60, 0x60, 0x30, 0x30, 0x18, 0x0c, 0x46, 0x7f, 
+0x7f};
+static unsigned char times18_51_bits[] = {
+0x3e, 0x73, 0x61, 0x60, 0x30, 0x1c, 0x3c, 0x70, 0x60, 0x60, 0x60, 0x33, 
+0x1f};
+static unsigned char times18_52_bits[] = {
+0x60, 0x70, 0x70, 0x68, 0x64, 0x66, 0x62, 0x61, 0xff, 0xff, 0x60, 0x60, 
+0x60};
+static unsigned char times18_53_bits[] = {
+0x7e, 0x3e, 0x03, 0x03, 0x0f, 0x3c, 0x30, 0x70, 0x60, 0x60, 0x30, 0x3b, 
+0x0f};
+static unsigned char times18_54_bits[] = {
+0xe0, 0x38, 0x0c, 0x06, 0x06, 0x3f, 0x63, 0xc3, 0xc3, 0xc3, 0xc7, 0x6e, 
+0x3c};
+static unsigned char times18_55_bits[] = {
+0x7f, 0x7f, 0x21, 0x30, 0x10, 0x18, 0x18, 0x08, 0x0c, 0x0c, 0x04, 0x06, 
+0x06};
+static unsigned char times18_56_bits[] = {
+0x3c, 0x66, 0x46, 0x46, 0x2e, 0x3c, 0x3c, 0x76, 0xe3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_57_bits[] = {
+0x3c, 0x76, 0x63, 0xc3, 0xc3, 0xc3, 0xc7, 0xfe, 0x60, 0x60, 0x30, 0x1c, 
+0x07};
+static unsigned char times18_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char times18_59_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x04, 0x06, 0x03};
+static unsigned char times18_60_bits[] = {
+0x80, 0x01, 0xe0, 0x00, 0x38, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x0e, 0x00, 
+0x38, 0x00, 0xe0, 0x00, 0x80, 0x01};
+static unsigned char times18_61_bits[] = {
+0xff, 0x00, 0xff};
+static unsigned char times18_62_bits[] = {
+0x03, 0x00, 0x0e, 0x00, 0x38, 0x00, 0xe0, 0x00, 0x80, 0x01, 0xe0, 0x00, 
+0x38, 0x00, 0x0e, 0x00, 0x03, 0x00};
+static unsigned char times18_63_bits[] = {
+0x1e, 0x31, 0x23, 0x33, 0x30, 0x18, 0x18, 0x0c, 0x04, 0x04, 0x00, 0x0c, 
+0x0c};
+static unsigned char times18_64_bits[] = {
+0xe0, 0x07, 0x70, 0x0c, 0x1c, 0x18, 0x0c, 0x10, 0xc6, 0x37, 0xe6, 0x27, 
+0x63, 0x26, 0x33, 0x26, 0x33, 0x33, 0x33, 0x13, 0xb3, 0x1b, 0xe6, 0x0e, 
+0x06, 0x00, 0x0c, 0x00, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times18_65_bits[] = {
+0x40, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 
+0x98, 0x03, 0x08, 0x03, 0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 
+0x0f, 0x1f};
+static unsigned char times18_66_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 
+0xfe, 0x01, 0x86, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 
+0xff, 0x00};
+static unsigned char times18_67_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x06, 0x04, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x1c, 0x03, 
+0xf0, 0x00};
+static unsigned char times18_68_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x03, 0x06, 0x03, 0xc6, 0x01, 
+0xff, 0x00};
+static unsigned char times18_69_bits[] = {
+0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 
+0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 
+0xff, 0x01};
+static unsigned char times18_70_bits[] = {
+0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 
+0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x0f, 0x00};
+static unsigned char times18_71_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x06, 0x04, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x0f, 0x03, 0x06, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x9c, 0x03, 
+0xf0, 0x00};
+static unsigned char times18_72_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0xfe, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x8f, 0x07};
+static unsigned char times18_73_bits[] = {
+0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_74_bits[] = {
+0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 
+0x0f};
+static unsigned char times18_75_bits[] = {
+0xcf, 0x03, 0x86, 0x01, 0xc6, 0x00, 0x66, 0x00, 0x36, 0x00, 0x1e, 0x00, 
+0x1e, 0x00, 0x36, 0x00, 0x66, 0x00, 0xc6, 0x00, 0xc6, 0x01, 0x86, 0x03, 
+0x0f, 0x07};
+static unsigned char times18_76_bits[] = {
+0x0f, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x02, 0x06, 0x03, 
+0xff, 0x03};
+static unsigned char times18_77_bits[] = {
+0x07, 0x38, 0x0e, 0x1c, 0x0e, 0x1c, 0x1e, 0x1e, 0x1a, 0x1a, 0x1a, 0x1b, 
+0x3a, 0x1b, 0x32, 0x19, 0xb2, 0x19, 0xe2, 0x18, 0xe2, 0x18, 0x42, 0x18, 
+0x47, 0x3c};
+static unsigned char times18_78_bits[] = {
+0x07, 0x07, 0x06, 0x02, 0x0e, 0x02, 0x1e, 0x02, 0x1a, 0x02, 0x32, 0x02, 
+0x72, 0x02, 0xe2, 0x02, 0xc2, 0x02, 0x82, 0x03, 0x82, 0x03, 0x02, 0x03, 
+0x07, 0x02};
+static unsigned char times18_79_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 
+0xf0, 0x00};
+static unsigned char times18_80_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 
+0x7e, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x0f, 0x00};
+static unsigned char times18_81_bits[] = {
+0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 
+0xf0, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x03, 0x00, 0x0f};
+static unsigned char times18_82_bits[] = {
+0xff, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 
+0x7e, 0x00, 0x66, 0x00, 0xc6, 0x00, 0x86, 0x01, 0x86, 0x01, 0x06, 0x03, 
+0x0f, 0x07};
+static unsigned char times18_83_bits[] = {
+0x5c, 0x66, 0x43, 0x03, 0x07, 0x1e, 0x3c, 0x70, 0xe0, 0xc0, 0xc1, 0x63, 
+0x3d};
+static unsigned char times18_84_bits[] = {
+0xff, 0x03, 0x33, 0x03, 0x31, 0x02, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 
+0x78, 0x00};
+static unsigned char times18_85_bits[] = {
+0x0f, 0x07, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 
+0xf8, 0x00};
+static unsigned char times18_86_bits[] = {
+0x1f, 0x1e, 0x0e, 0x0c, 0x0c, 0x04, 0x1c, 0x04, 0x18, 0x06, 0x18, 0x02, 
+0x38, 0x02, 0x30, 0x03, 0x70, 0x01, 0x60, 0x01, 0xe0, 0x01, 0xc0, 0x00, 
+0xc0, 0x00};
+static unsigned char times18_87_bits[] = {
+0x9f, 0xc7, 0x03, 0x0c, 0x83, 0x01, 0x0c, 0x83, 0x00, 0x18, 0x83, 0x00, 
+0x18, 0xc6, 0x00, 0x18, 0x46, 0x00, 0x38, 0x47, 0x00, 0x30, 0x65, 0x00, 
+0x30, 0x2d, 0x00, 0xb0, 0x2c, 0x00, 0xe0, 0x3c, 0x00, 0x60, 0x18, 0x00, 
+0x60, 0x18, 0x00};
+static unsigned char times18_88_bits[] = {
+0x0f, 0x0e, 0x0e, 0x06, 0x1c, 0x03, 0x98, 0x01, 0xb0, 0x00, 0x70, 0x00, 
+0x60, 0x00, 0xf0, 0x00, 0xd8, 0x00, 0x88, 0x01, 0x8c, 0x03, 0x06, 0x07, 
+0x0f, 0x0f};
+static unsigned char times18_89_bits[] = {
+0x0f, 0x0f, 0x0e, 0x06, 0x0c, 0x03, 0x18, 0x01, 0x98, 0x00, 0xf0, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0xf0, 0x00};
+static unsigned char times18_90_bits[] = {
+0xfe, 0x03, 0x86, 0x03, 0x82, 0x01, 0xc0, 0x01, 0xe0, 0x00, 0x60, 0x00, 
+0x70, 0x00, 0x38, 0x00, 0x1c, 0x00, 0x0c, 0x00, 0x0e, 0x02, 0x07, 0x03, 
+0xff, 0x03};
+static unsigned char times18_91_bits[] = {
+0x0f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x0f};
+static unsigned char times18_92_bits[] = {
+0x01, 0x01, 0x03, 0x02, 0x06, 0x06, 0x04, 0x0c, 0x0c, 0x08, 0x18, 0x10, 
+0x10};
+static unsigned char times18_93_bits[] = {
+0x0f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0f};
+static unsigned char times18_94_bits[] = {
+0x08, 0x1c, 0x14, 0x36, 0x22, 0x63, 0x41};
+static unsigned char times18_95_bits[] = {
+0xff, 0x01};
+static unsigned char times18_96_bits[] = {
+0x02, 0x01, 0x07, 0x06};
+static unsigned char times18_97_bits[] = {
+0x1e, 0x33, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 0x66};
+static unsigned char times18_98_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x76, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 
+0x3c};
+static unsigned char times18_99_bits[] = {
+0x3c, 0x66, 0x63, 0x03, 0x03, 0x03, 0x03, 0x46, 0x3c};
+static unsigned char times18_100_bits[] = {
+0x70, 0x60, 0x60, 0x60, 0x7c, 0x66, 0x63, 0x63, 0x63, 0x63, 0x63, 0x66, 
+0xfc};
+static unsigned char times18_101_bits[] = {
+0x3c, 0x66, 0xc3, 0xff, 0x03, 0x03, 0x87, 0x6e, 0x3c};
+static unsigned char times18_102_bits[] = {
+0x38, 0x2c, 0x04, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_103_bits[] = {
+0x7c, 0x33, 0x23, 0x23, 0x33, 0x1e, 0x02, 0x3e, 0xfe, 0xc1, 0x83, 0x47, 
+0x3e};
+static unsigned char times18_104_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x66, 0x00, 0xf6, 0x00, 
+0xce, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xcf, 0x01};
+static unsigned char times18_105_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_106_bits[] = {
+0x0c, 0x0c, 0x00, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x07, 0x03};
+static unsigned char times18_107_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe6, 0x00, 0x46, 0x00, 
+0x26, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x36, 0x00, 0x66, 0x00, 0xc6, 0x00, 
+0xc7, 0x01};
+static unsigned char times18_108_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_109_bits[] = {
+0x67, 0x0c, 0xf6, 0x1e, 0xce, 0x19, 0xc6, 0x18, 0xc6, 0x18, 0xc6, 0x18, 
+0xc6, 0x18, 0xc6, 0x18, 0xef, 0x3d};
+static unsigned char times18_110_bits[] = {
+0x67, 0x00, 0xf6, 0x00, 0xce, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xcf, 0x01};
+static unsigned char times18_111_bits[] = {
+0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char times18_112_bits[] = {
+0x77, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 0x36, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_113_bits[] = {
+0x7c, 0x66, 0x63, 0x63, 0x63, 0x63, 0x63, 0x66, 0x7c, 0x60, 0x60, 0x60, 
+0xf0};
+static unsigned char times18_114_bits[] = {
+0x37, 0x36, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_115_bits[] = {
+0x16, 0x1b, 0x13, 0x07, 0x0e, 0x1c, 0x19, 0x1b, 0x0d};
+static unsigned char times18_116_bits[] = {
+0x04, 0x06, 0x1f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x2e, 0x1c};
+static unsigned char times18_117_bits[] = {
+0xe7, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xee, 0x00, 0xdc, 0x01};
+static unsigned char times18_118_bits[] = {
+0xcf, 0x01, 0xc6, 0x00, 0x46, 0x00, 0x4c, 0x00, 0x6c, 0x00, 0x28, 0x00, 
+0x38, 0x00, 0x10, 0x00, 0x10, 0x00};
+static unsigned char times18_119_bits[] = {
+0xe7, 0x1c, 0x66, 0x0c, 0x46, 0x06, 0x6c, 0x06, 0xec, 0x06, 0xb8, 0x02, 
+0xb8, 0x03, 0x10, 0x01, 0x10, 0x01};
+static unsigned char times18_120_bits[] = {
+0xc7, 0x01, 0xc6, 0x00, 0x6c, 0x00, 0x38, 0x00, 0x30, 0x00, 0x38, 0x00, 
+0x6c, 0x00, 0xc6, 0x00, 0xc7, 0x01};
+static unsigned char times18_121_bits[] = {
+0xcf, 0x01, 0x86, 0x00, 0xce, 0x00, 0x4c, 0x00, 0x6c, 0x00, 0x38, 0x00, 
+0x38, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00, 0x0f, 0x00, 
+0x07, 0x00};
+static unsigned char times18_122_bits[] = {
+0x7f, 0x73, 0x31, 0x18, 0x0c, 0x0c, 0x46, 0x67, 0x7f};
+static unsigned char times18_123_bits[] = {
+0x70, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x03, 0x06, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x18, 0x70};
+static unsigned char times18_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char times18_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0x60, 0x30, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char times18_126_bits[] = {
+0x9e, 0x01, 0xf3, 0x00};
+static unsigned char times18_127_bits[] = {
+0x00};
+static unsigned char times18_128_bits[] = {
+0x00};
+static unsigned char times18_129_bits[] = {
+0x00};
+static unsigned char times18_130_bits[] = {
+0x00};
+static unsigned char times18_131_bits[] = {
+0x00};
+static unsigned char times18_132_bits[] = {
+0x00};
+static unsigned char times18_133_bits[] = {
+0x00};
+static unsigned char times18_134_bits[] = {
+0x00};
+static unsigned char times18_135_bits[] = {
+0x00};
+static unsigned char times18_136_bits[] = {
+0x00};
+static unsigned char times18_137_bits[] = {
+0x00};
+static unsigned char times18_138_bits[] = {
+0x00};
+static unsigned char times18_139_bits[] = {
+0x00};
+static unsigned char times18_140_bits[] = {
+0x00};
+static unsigned char times18_141_bits[] = {
+0x00};
+static unsigned char times18_142_bits[] = {
+0x00};
+static unsigned char times18_143_bits[] = {
+0x00};
+static unsigned char times18_144_bits[] = {
+0x00};
+static unsigned char times18_145_bits[] = {
+0x00};
+static unsigned char times18_146_bits[] = {
+0x00};
+static unsigned char times18_147_bits[] = {
+0x00};
+static unsigned char times18_148_bits[] = {
+0x00};
+static unsigned char times18_149_bits[] = {
+0x00};
+static unsigned char times18_150_bits[] = {
+0x00};
+static unsigned char times18_151_bits[] = {
+0x00};
+static unsigned char times18_152_bits[] = {
+0x00};
+static unsigned char times18_153_bits[] = {
+0x00};
+static unsigned char times18_154_bits[] = {
+0x00};
+static unsigned char times18_155_bits[] = {
+0x00};
+static unsigned char times18_156_bits[] = {
+0x00};
+static unsigned char times18_157_bits[] = {
+0x00};
+static unsigned char times18_158_bits[] = {
+0x00};
+static unsigned char times18_159_bits[] = {
+0x00};
+static unsigned char times18_160_bits[] = {
+0x00};
+static unsigned char times18_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03};
+static unsigned char times18_162_bits[] = {
+0x60, 0x20, 0x7c, 0xd6, 0xd3, 0x13, 0x1b, 0x0b, 0x0b, 0x4e, 0x3e, 0x02, 
+0x03};
+static unsigned char times18_163_bits[] = {
+0xf0, 0x00, 0x98, 0x01, 0x98, 0x01, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 
+0x7e, 0x00, 0x18, 0x00, 0x18, 0x00, 0x08, 0x00, 0x1e, 0x02, 0xfd, 0x03, 
+0xe7, 0x01};
+static unsigned char times18_164_bits[] = {
+0xbb, 0x01, 0xef, 0x01, 0xc6, 0x00, 0x82, 0x00, 0xc6, 0x00, 0xef, 0x01, 
+0xbb, 0x01};
+static unsigned char times18_165_bits[] = {
+0xef, 0x46, 0x46, 0x6e, 0x2c, 0x2c, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 
+0x7e};
+static unsigned char times18_166_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 
+0x01};
+static unsigned char times18_167_bits[] = {
+0x3c, 0x66, 0x66, 0x0e, 0x1c, 0x3e, 0x71, 0xe3, 0xc7, 0x8e, 0x7c, 0x38, 
+0x70, 0x66, 0x66, 0x3c};
+static unsigned char times18_168_bits[] = {
+0x1b, 0x1b};
+static unsigned char times18_169_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xe2, 0x09, 0x11, 0x11, 0x09, 0x10, 
+0x09, 0x10, 0x09, 0x10, 0x11, 0x11, 0xe2, 0x08, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char times18_170_bits[] = {
+0x06, 0x09, 0x08, 0x0e, 0x09, 0x17, 0x00, 0x1f};
+static unsigned char times18_171_bits[] = {
+0x88, 0xcc, 0x66, 0x33, 0x66, 0xcc, 0x88};
+static unsigned char times18_172_bits[] = {
+0xff, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
+static unsigned char times18_173_bits[] = {
+0x1f, 0x1f};
+static unsigned char times18_174_bits[] = {
+0xf0, 0x01, 0x0c, 0x06, 0x02, 0x08, 0xfa, 0x08, 0x11, 0x11, 0x11, 0x11, 
+0xf1, 0x10, 0x91, 0x10, 0x11, 0x11, 0x3a, 0x0b, 0x02, 0x08, 0x0c, 0x06, 
+0xf0, 0x01};
+static unsigned char times18_175_bits[] = {
+0x1f};
+static unsigned char times18_176_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times18_177_bits[] = {
+0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0x10, 0x00, 0xff, 0x01, 0x10, 0x00, 
+0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0xff, 0x01};
+static unsigned char times18_178_bits[] = {
+0x0e, 0x19, 0x18, 0x08, 0x04, 0x04, 0x02, 0x1f};
+static unsigned char times18_179_bits[] = {
+0x0e, 0x11, 0x18, 0x0e, 0x18, 0x10, 0x11, 0x0e};
+static unsigned char times18_180_bits[] = {
+0x0c, 0x06, 0x01};
+static unsigned char times18_181_bits[] = {
+0xe7, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xee, 0x00, 0xde, 0x01, 0x02, 0x00, 0x02, 0x00, 0x06, 0x00, 
+0x06, 0x00};
+static unsigned char times18_182_bits[] = {
+0x7c, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2e, 0x28, 0x28, 0x28, 0x28, 
+0x28, 0x28, 0x28, 0x28, 0x28};
+static unsigned char times18_183_bits[] = {
+0x03, 0x03};
+static unsigned char times18_184_bits[] = {
+0x04, 0x04, 0x08, 0x0d, 0x06};
+static unsigned char times18_185_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times18_186_bits[] = {
+0x0e, 0x1b, 0x11, 0x11, 0x1b, 0x0e, 0x00, 0x1f};
+static unsigned char times18_187_bits[] = {
+0x11, 0x33, 0x66, 0xcc, 0x66, 0x33, 0x11};
+static unsigned char times18_188_bits[] = {
+0x02, 0x01, 0x83, 0x01, 0x82, 0x00, 0xc2, 0x00, 0x62, 0x00, 0x22, 0x02, 
+0x32, 0x03, 0x97, 0x02, 0xd8, 0x02, 0x4c, 0x02, 0xe4, 0x07, 0x06, 0x02, 
+0x02, 0x02};
+static unsigned char times18_189_bits[] = {
+0x02, 0x01, 0x83, 0x01, 0x82, 0x00, 0xc2, 0x00, 0x62, 0x00, 0xa2, 0x03, 
+0x72, 0x06, 0x17, 0x06, 0x18, 0x02, 0x0c, 0x01, 0x04, 0x01, 0x86, 0x00, 
+0xc2, 0x07};
+static unsigned char times18_190_bits[] = {
+0x0e, 0x04, 0x11, 0x06, 0x18, 0x02, 0x0e, 0x03, 0x98, 0x01, 0x90, 0x08, 
+0xd1, 0x0c, 0x4e, 0x0a, 0x60, 0x0b, 0x30, 0x09, 0x90, 0x1f, 0x18, 0x08, 
+0x08, 0x08};
+static unsigned char times18_191_bits[] = {
+0x0c, 0x0c, 0x00, 0x08, 0x08, 0x0c, 0x06, 0x06, 0x03, 0x33, 0x31, 0x23, 
+0x1e};
+static unsigned char times18_192_bits[] = {
+0x30, 0x00, 0x60, 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_193_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_194_bits[] = {
+0x40, 0x00, 0xe0, 0x00, 0x10, 0x01, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_195_bits[] = {
+0xe0, 0x02, 0xd0, 0x01, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 0xe0, 0x00, 
+0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 0xf8, 0x03, 
+0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_196_bits[] = {
+0xb0, 0x01, 0xb0, 0x01, 0x00, 0x00, 0x40, 0x00, 0xe0, 0x00, 0xe0, 0x00, 
+0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 0xf8, 0x03, 
+0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_197_bits[] = {
+0xc0, 0x00, 0x20, 0x01, 0x20, 0x01, 0xc0, 0x00, 0x40, 0x00, 0xe0, 0x00, 
+0xe0, 0x00, 0xa0, 0x00, 0xb0, 0x01, 0x90, 0x01, 0x98, 0x03, 0x08, 0x03, 
+0xf8, 0x03, 0x0c, 0x07, 0x04, 0x06, 0x06, 0x0e, 0x0f, 0x1f};
+static unsigned char times18_198_bits[] = {
+0xf0, 0x3f, 0xe0, 0x31, 0xa0, 0x21, 0xa0, 0x01, 0xb0, 0x01, 0x90, 0x11, 
+0x98, 0x1f, 0xf8, 0x11, 0x88, 0x01, 0x8c, 0x01, 0x84, 0x41, 0x86, 0x61, 
+0xef, 0x7f};
+static unsigned char times18_199_bits[] = {
+0xf0, 0x04, 0x0c, 0x07, 0x06, 0x06, 0x06, 0x04, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x06, 0x1c, 0x03, 
+0xf0, 0x00, 0x20, 0x00, 0x40, 0x00, 0x68, 0x00, 0x30, 0x00};
+static unsigned char times18_200_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 
+0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_201_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 
+0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_202_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x44, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 
+0x06, 0x01, 0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_203_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0xff, 0x01, 0x86, 0x01, 0x06, 0x01, 
+0x06, 0x00, 0x06, 0x00, 0x86, 0x00, 0xfe, 0x00, 0x86, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x01, 0x86, 0x01, 0xff, 0x01};
+static unsigned char times18_204_bits[] = {
+0x03, 0x06, 0x08, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_205_bits[] = {
+0x0c, 0x06, 0x01, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_206_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_207_bits[] = {
+0x33, 0x33, 0x00, 0x1e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times18_208_bits[] = {
+0xfe, 0x01, 0x8c, 0x03, 0x0c, 0x06, 0x0c, 0x06, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x06, 0x0c, 0x06, 0x8c, 0x03, 
+0xfe, 0x01};
+static unsigned char times18_209_bits[] = {
+0x70, 0x01, 0xe8, 0x00, 0x00, 0x00, 0x07, 0x07, 0x06, 0x02, 0x0e, 0x02, 
+0x1e, 0x02, 0x1a, 0x02, 0x32, 0x02, 0x72, 0x02, 0xe2, 0x02, 0xc2, 0x02, 
+0x82, 0x03, 0x82, 0x03, 0x02, 0x03, 0x07, 0x02};
+static unsigned char times18_210_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 
+0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_211_bits[] = {
+0x00, 0x03, 0x80, 0x01, 0x40, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 
+0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_212_bits[] = {
+0x40, 0x00, 0xe0, 0x00, 0x10, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 
+0x06, 0x06, 0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x03, 0x0c, 0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_213_bits[] = {
+0x70, 0x01, 0xe8, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 
+0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_214_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0xf0, 0x00, 0x0c, 0x03, 0x06, 0x06, 
+0x06, 0x06, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 0x03, 0x0c, 
+0x06, 0x06, 0x06, 0x06, 0x0c, 0x03, 0xf0, 0x00};
+static unsigned char times18_215_bits[] = {
+0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3};
+static unsigned char times18_216_bits[] = {
+0x00, 0x0c, 0xf0, 0x06, 0x0c, 0x03, 0x06, 0x07, 0x86, 0x05, 0xc3, 0x0c, 
+0xc3, 0x0c, 0x63, 0x0c, 0x33, 0x0c, 0x33, 0x0c, 0x1a, 0x06, 0x0e, 0x06, 
+0x0c, 0x03, 0xf6, 0x00, 0x03, 0x00};
+static unsigned char times18_217_bits[] = {
+0x18, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_218_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_219_bits[] = {
+0x20, 0x00, 0x70, 0x00, 0x88, 0x00, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_220_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x0f, 0x07, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 0x06, 0x02, 
+0x06, 0x02, 0x0e, 0x03, 0x9c, 0x01, 0xf8, 0x00};
+static unsigned char times18_221_bits[] = {
+0x80, 0x01, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0e, 0x06, 
+0x0c, 0x03, 0x18, 0x01, 0x98, 0x00, 0xf0, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xf0, 0x00};
+static unsigned char times18_222_bits[] = {
+0x0f, 0x00, 0x06, 0x00, 0x06, 0x00, 0xfe, 0x00, 0xc6, 0x01, 0x86, 0x01, 
+0x86, 0x01, 0x86, 0x01, 0xc6, 0x00, 0x7e, 0x00, 0x06, 0x00, 0x06, 0x00, 
+0x0f, 0x00};
+static unsigned char times18_223_bits[] = {
+0x38, 0x6c, 0xc4, 0xc6, 0xc6, 0x66, 0x3e, 0x66, 0xc6, 0xc6, 0xd6, 0xd6, 
+0x77};
+static unsigned char times18_224_bits[] = {
+0x03, 0x06, 0x08, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_225_bits[] = {
+0x30, 0x18, 0x04, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_226_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_227_bits[] = {
+0x2c, 0x1a, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 0x66};
+static unsigned char times18_228_bits[] = {
+0x36, 0x36, 0x00, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 0x66};
+static unsigned char times18_229_bits[] = {
+0x0c, 0x12, 0x12, 0x0c, 0x1e, 0x13, 0x33, 0x38, 0x36, 0x33, 0x33, 0x3f, 
+0x66};
+static unsigned char times18_230_bits[] = {
+0xde, 0x03, 0x73, 0x06, 0x33, 0x04, 0xf8, 0x07, 0x36, 0x00, 0x33, 0x00, 
+0x33, 0x00, 0x7f, 0x06, 0xc6, 0x03};
+static unsigned char times18_231_bits[] = {
+0x3c, 0x66, 0x03, 0x03, 0x03, 0x03, 0x03, 0x66, 0x3c, 0x08, 0x10, 0x1a, 
+0x0c};
+static unsigned char times18_232_bits[] = {
+0x06, 0x0c, 0x10, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 
+0x3c};
+static unsigned char times18_233_bits[] = {
+0x60, 0x30, 0x08, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 
+0x3c};
+static unsigned char times18_234_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 
+0x3c};
+static unsigned char times18_235_bits[] = {
+0x36, 0x36, 0x00, 0x3c, 0x66, 0x43, 0x7f, 0x03, 0x03, 0x03, 0x66, 0x3c};
+static unsigned char times18_236_bits[] = {
+0x03, 0x06, 0x08, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_237_bits[] = {
+0x0c, 0x06, 0x01, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_238_bits[] = {
+0x04, 0x0e, 0x11, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x0f};
+static unsigned char times18_239_bits[] = {
+0x1b, 0x1b, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_240_bits[] = {
+0x06, 0x6c, 0x1c, 0x32, 0x7c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_241_bits[] = {
+0x5c, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x67, 0x00, 0xf6, 0x00, 0xce, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xcf, 0x01};
+static unsigned char times18_242_bits[] = {
+0x06, 0x0c, 0x10, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_243_bits[] = {
+0x60, 0x30, 0x08, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_244_bits[] = {
+0x08, 0x1c, 0x22, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 
+0x3c};
+static unsigned char times18_245_bits[] = {
+0x58, 0x34, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char times18_246_bits[] = {
+0x36, 0x36, 0x00, 0x3c, 0x66, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c};
+static unsigned char times18_247_bits[] = {
+0x18, 0x18, 0x00, 0xff, 0x00, 0x18, 0x18};
+static unsigned char times18_248_bits[] = {
+0x80, 0xfc, 0x66, 0xf3, 0xd3, 0xdb, 0xcb, 0xcf, 0x66, 0x3e, 0x03};
+static unsigned char times18_249_bits[] = {
+0x0c, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 
+0xdc, 0x01};
+static unsigned char times18_250_bits[] = {
+0x60, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 
+0xdc, 0x01};
+static unsigned char times18_251_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x44, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 
+0xdc, 0x01};
+static unsigned char times18_252_bits[] = {
+0x6c, 0x00, 0x6c, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xc6, 0x00, 0xc6, 0x00, 
+0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xee, 0x00, 0xdc, 0x01};
+static unsigned char times18_253_bits[] = {
+0xc0, 0x60, 0x10, 0x00, 0xcf, 0xc6, 0x4e, 0x4c, 0x6c, 0x38, 0x38, 0x30, 
+0x10, 0x18, 0x08, 0x0f, 0x07};
+static unsigned char times18_254_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x76, 0xee, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x6e, 
+0x3e, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times18_255_bits[] = {
+0x6c, 0x6c, 0x00, 0xcf, 0xc6, 0x4e, 0x4c, 0x6c, 0x38, 0x38, 0x30, 0x10, 
+0x18, 0x08, 0x0f, 0x07};
+static RotFont times18font[] = {
+{5, 1, 1, times18_0_bits},
+{5, 1, 1, times18_1_bits},
+{5, 1, 1, times18_2_bits},
+{5, 1, 1, times18_3_bits},
+{5, 1, 1, times18_4_bits},
+{5, 1, 1, times18_5_bits},
+{5, 1, 1, times18_6_bits},
+{5, 1, 1, times18_7_bits},
+{5, 1, 1, times18_8_bits},
+{5, 1, 1, times18_9_bits},
+{5, 1, 1, times18_10_bits},
+{5, 1, 1, times18_11_bits},
+{5, 1, 1, times18_12_bits},
+{5, 1, 1, times18_13_bits},
+{5, 1, 1, times18_14_bits},
+{5, 1, 1, times18_15_bits},
+{5, 1, 1, times18_16_bits},
+{5, 1, 1, times18_17_bits},
+{5, 1, 1, times18_18_bits},
+{5, 1, 1, times18_19_bits},
+{5, 1, 1, times18_20_bits},
+{5, 1, 1, times18_21_bits},
+{5, 1, 1, times18_22_bits},
+{5, 1, 1, times18_23_bits},
+{5, 1, 1, times18_24_bits},
+{5, 1, 1, times18_25_bits},
+{5, 1, 1, times18_26_bits},
+{5, 1, 1, times18_27_bits},
+{5, 1, 1, times18_28_bits},
+{5, 1, 1, times18_29_bits},
+{5, 1, 1, times18_30_bits},
+{5, 1, 1, times18_31_bits},
+{8, 1, 1, times18_32_bits},
+{2, 13, 13, times18_33_bits},
+{6, 4, 13, times18_34_bits},
+{11, 13, 13, times18_35_bits},
+{7, 16, 14, times18_36_bits},
+{13, 13, 13, times18_37_bits},
+{12, 13, 13, times18_38_bits},
+{3, 4, 13, times18_39_bits},
+{5, 17, 13, times18_40_bits},
+{5, 17, 13, times18_41_bits},
+{7, 8, 14, times18_42_bits},
+{9, 9, 9, times18_43_bits},
+{3, 5, 2, times18_44_bits},
+{8, 1, 5, times18_45_bits},
+{2, 2, 2, times18_46_bits},
+{5, 15, 13, times18_47_bits},
+{8, 13, 13, times18_48_bits},
+{6, 13, 13, times18_49_bits},
+{7, 13, 13, times18_50_bits},
+{7, 13, 13, times18_51_bits},
+{8, 13, 13, times18_52_bits},
+{7, 13, 13, times18_53_bits},
+{8, 13, 13, times18_54_bits},
+{7, 13, 13, times18_55_bits},
+{8, 13, 13, times18_56_bits},
+{8, 13, 13, times18_57_bits},
+{2, 9, 9, times18_58_bits},
+{3, 12, 9, times18_59_bits},
+{9, 9, 9, times18_60_bits},
+{8, 3, 6, times18_61_bits},
+{9, 9, 9, times18_62_bits},
+{6, 13, 13, times18_63_bits},
+{14, 16, 13, times18_64_bits},
+{13, 13, 13, times18_65_bits},
+{10, 13, 13, times18_66_bits},
+{11, 13, 13, times18_67_bits},
+{11, 13, 13, times18_68_bits},
+{9, 13, 13, times18_69_bits},
+{9, 13, 13, times18_70_bits},
+{12, 13, 13, times18_71_bits},
+{11, 13, 13, times18_72_bits},
+{4, 13, 13, times18_73_bits},
+{6, 13, 13, times18_74_bits},
+{11, 13, 13, times18_75_bits},
+{10, 13, 13, times18_76_bits},
+{14, 13, 13, times18_77_bits},
+{11, 13, 13, times18_78_bits},
+{12, 13, 13, times18_79_bits},
+{9, 13, 13, times18_80_bits},
+{12, 17, 13, times18_81_bits},
+{11, 13, 13, times18_82_bits},
+{8, 13, 13, times18_83_bits},
+{10, 13, 13, times18_84_bits},
+{11, 13, 13, times18_85_bits},
+{13, 13, 13, times18_86_bits},
+{18, 13, 13, times18_87_bits},
+{12, 13, 13, times18_88_bits},
+{12, 13, 13, times18_89_bits},
+{10, 13, 13, times18_90_bits},
+{4, 16, 13, times18_91_bits},
+{5, 13, 13, times18_92_bits},
+{4, 16, 13, times18_93_bits},
+{7, 7, 13, times18_94_bits},
+{9, 1, -3, times18_95_bits},
+{3, 4, 13, times18_96_bits},
+{7, 9, 9, times18_97_bits},
+{8, 13, 13, times18_98_bits},
+{7, 9, 9, times18_99_bits},
+{8, 13, 13, times18_100_bits},
+{8, 9, 9, times18_101_bits},
+{6, 13, 13, times18_102_bits},
+{8, 13, 9, times18_103_bits},
+{9, 13, 13, times18_104_bits},
+{4, 13, 13, times18_105_bits},
+{4, 17, 13, times18_106_bits},
+{9, 13, 13, times18_107_bits},
+{4, 13, 13, times18_108_bits},
+{14, 9, 9, times18_109_bits},
+{9, 9, 9, times18_110_bits},
+{8, 9, 9, times18_111_bits},
+{8, 13, 9, times18_112_bits},
+{8, 13, 9, times18_113_bits},
+{6, 9, 9, times18_114_bits},
+{5, 9, 9, times18_115_bits},
+{6, 11, 11, times18_116_bits},
+{9, 9, 9, times18_117_bits},
+{9, 9, 9, times18_118_bits},
+{13, 9, 9, times18_119_bits},
+{9, 9, 9, times18_120_bits},
+{9, 13, 9, times18_121_bits},
+{7, 9, 9, times18_122_bits},
+{7, 17, 13, times18_123_bits},
+{1, 13, 13, times18_124_bits},
+{7, 17, 13, times18_125_bits},
+{9, 2, 6, times18_126_bits},
+{5, 1, 1, times18_127_bits},
+{5, 1, 1, times18_128_bits},
+{5, 1, 1, times18_129_bits},
+{5, 1, 1, times18_130_bits},
+{5, 1, 1, times18_131_bits},
+{5, 1, 1, times18_132_bits},
+{5, 1, 1, times18_133_bits},
+{5, 1, 1, times18_134_bits},
+{5, 1, 1, times18_135_bits},
+{5, 1, 1, times18_136_bits},
+{5, 1, 1, times18_137_bits},
+{5, 1, 1, times18_138_bits},
+{5, 1, 1, times18_139_bits},
+{5, 1, 1, times18_140_bits},
+{5, 1, 1, times18_141_bits},
+{5, 1, 1, times18_142_bits},
+{5, 1, 1, times18_143_bits},
+{5, 1, 1, times18_144_bits},
+{5, 1, 1, times18_145_bits},
+{5, 1, 1, times18_146_bits},
+{5, 1, 1, times18_147_bits},
+{5, 1, 1, times18_148_bits},
+{5, 1, 1, times18_149_bits},
+{5, 1, 1, times18_150_bits},
+{5, 1, 1, times18_151_bits},
+{5, 1, 1, times18_152_bits},
+{5, 1, 1, times18_153_bits},
+{5, 1, 1, times18_154_bits},
+{5, 1, 1, times18_155_bits},
+{5, 1, 1, times18_156_bits},
+{5, 1, 1, times18_157_bits},
+{5, 1, 1, times18_158_bits},
+{5, 1, 1, times18_159_bits},
+{1, 1, 1, times18_160_bits},
+{2, 13, 9, times18_161_bits},
+{8, 13, 11, times18_162_bits},
+{10, 13, 13, times18_163_bits},
+{9, 7, 10, times18_164_bits},
+{8, 13, 13, times18_165_bits},
+{1, 13, 13, times18_166_bits},
+{8, 16, 13, times18_167_bits},
+{5, 2, 12, times18_168_bits},
+{13, 13, 13, times18_169_bits},
+{5, 8, 13, times18_170_bits},
+{8, 7, 8, times18_171_bits},
+{9, 5, 6, times18_172_bits},
+{5, 2, 6, times18_173_bits},
+{13, 13, 13, times18_174_bits},
+{5, 1, 12, times18_175_bits},
+{5, 5, 13, times18_176_bits},
+{9, 10, 10, times18_177_bits},
+{5, 8, 13, times18_178_bits},
+{5, 8, 13, times18_179_bits},
+{4, 3, 13, times18_180_bits},
+{9, 13, 9, times18_181_bits},
+{7, 17, 13, times18_182_bits},
+{2, 2, 6, times18_183_bits},
+{4, 5, 1, times18_184_bits},
+{3, 8, 13, times18_185_bits},
+{5, 8, 13, times18_186_bits},
+{8, 7, 8, times18_187_bits},
+{11, 13, 13, times18_188_bits},
+{11, 13, 13, times18_189_bits},
+{13, 13, 13, times18_190_bits},
+{6, 13, 9, times18_191_bits},
+{13, 17, 17, times18_192_bits},
+{13, 17, 17, times18_193_bits},
+{13, 17, 17, times18_194_bits},
+{13, 16, 16, times18_195_bits},
+{13, 16, 16, times18_196_bits},
+{13, 17, 17, times18_197_bits},
+{15, 13, 13, times18_198_bits},
+{11, 17, 13, times18_199_bits},
+{9, 17, 17, times18_200_bits},
+{9, 17, 17, times18_201_bits},
+{9, 17, 17, times18_202_bits},
+{9, 16, 16, times18_203_bits},
+{4, 17, 17, times18_204_bits},
+{4, 17, 17, times18_205_bits},
+{5, 17, 17, times18_206_bits},
+{6, 16, 16, times18_207_bits},
+{12, 13, 13, times18_208_bits},
+{11, 16, 16, times18_209_bits},
+{12, 17, 17, times18_210_bits},
+{12, 17, 17, times18_211_bits},
+{12, 17, 17, times18_212_bits},
+{12, 16, 16, times18_213_bits},
+{12, 16, 16, times18_214_bits},
+{8, 7, 8, times18_215_bits},
+{12, 15, 14, times18_216_bits},
+{11, 17, 17, times18_217_bits},
+{11, 17, 17, times18_218_bits},
+{11, 17, 17, times18_219_bits},
+{11, 16, 16, times18_220_bits},
+{12, 17, 17, times18_221_bits},
+{9, 13, 13, times18_222_bits},
+{8, 13, 13, times18_223_bits},
+{7, 13, 13, times18_224_bits},
+{7, 13, 13, times18_225_bits},
+{7, 13, 13, times18_226_bits},
+{7, 12, 12, times18_227_bits},
+{7, 12, 12, times18_228_bits},
+{7, 13, 13, times18_229_bits},
+{11, 9, 9, times18_230_bits},
+{7, 13, 9, times18_231_bits},
+{7, 13, 13, times18_232_bits},
+{7, 13, 13, times18_233_bits},
+{7, 13, 13, times18_234_bits},
+{7, 12, 12, times18_235_bits},
+{4, 13, 13, times18_236_bits},
+{4, 13, 13, times18_237_bits},
+{5, 13, 13, times18_238_bits},
+{5, 12, 12, times18_239_bits},
+{8, 13, 13, times18_240_bits},
+{9, 12, 12, times18_241_bits},
+{8, 13, 13, times18_242_bits},
+{8, 13, 13, times18_243_bits},
+{8, 13, 13, times18_244_bits},
+{8, 12, 12, times18_245_bits},
+{8, 12, 12, times18_246_bits},
+{8, 7, 8, times18_247_bits},
+{8, 11, 10, times18_248_bits},
+{9, 13, 13, times18_249_bits},
+{9, 13, 13, times18_250_bits},
+{9, 13, 13, times18_251_bits},
+{9, 12, 12, times18_252_bits},
+{8, 17, 13, times18_253_bits},
+{8, 17, 13, times18_254_bits},
+{8, 16, 12, times18_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times24.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times24.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times24.bdf	(revision 16632)
@@ -0,0 +1,4377 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--24-240-75-75-P-124-ISO8859-1
+SIZE 24 75 75
+FONTBOUNDINGBOX 24 28 -1 -6
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 24
+POINT_SIZE 240
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 124
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 17
+X_HEIGHT 12
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2-1, 22-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--24-240-75-75-P-124-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 14
+DEFAULT_CHAR 32
+FONT_ASCENT 20
+FONT_DESCENT 6
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 2 17 3 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 6 5 1 12
+BITMAP
+cc
+cc
+cc
+cc
+88
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0880
+0880
+0880
+0880
+0880
+7fe0
+7fe0
+1100
+1100
+1100
+ffc0
+ffc0
+2200
+2200
+2200
+2200
+2200
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 11 21 0 -2
+BITMAP
+0400
+0400
+1f80
+34e0
+6460
+6420
+6400
+7400
+3c00
+1e00
+0780
+07c0
+04e0
+0460
+8460
+8460
+c4c0
+e5c0
+3f00
+0400
+0400
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 16 1 0
+BITMAP
+1e0c00
+33fc00
+611800
+c11000
+c13000
+c26000
+e44000
+78c000
+018f00
+011980
+033080
+066080
+046080
+0c6100
+187200
+303c00
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+0780
+0cc0
+1840
+1840
+18c0
+1d80
+0f00
+0e3e
+1e18
+3710
+6320
+c1a0
+c1c0
+c0c0
+e1e1
+7f7e
+3c3c
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 3 5 3 12
+BITMAP
+c0
+e0
+20
+60
+c0
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+04
+08
+10
+30
+20
+60
+60
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+60
+60
+20
+30
+10
+08
+04
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 -5
+BITMAP
+80
+40
+20
+30
+10
+18
+18
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+0c
+18
+18
+10
+30
+20
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 9 2 8
+BITMAP
+0800
+1c00
+c980
+eb80
+1c00
+eb80
+c980
+1c00
+0800
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 12 1 1
+BITMAP
+0600
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0600
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 5 2 -3
+BITMAP
+c0
+e0
+20
+60
+c0
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 2 1 6
+BITMAP
+fff0
+fff0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 2 2 0
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 8 20 -1 -3
+BITMAP
+03
+03
+03
+06
+06
+04
+0c
+0c
+08
+18
+18
+10
+30
+30
+20
+60
+60
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+e1c0
+6180
+6180
+3300
+1e00
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 17 2 0
+BITMAP
+08
+18
+78
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+ff
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1c00
+7f00
+4380
+8180
+8180
+0180
+0180
+0300
+0300
+0600
+0400
+0c00
+1800
+3000
+6040
+ffc0
+ff80
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 17 1 0
+BITMAP
+1c00
+7e00
+4700
+8300
+8300
+0600
+0c00
+1e00
+0700
+0380
+0180
+0180
+0180
+0100
+c300
+e600
+7800
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0300
+0700
+0700
+0b00
+1b00
+1300
+3300
+2300
+6300
+4300
+c300
+ffc0
+ffc0
+0300
+0300
+0300
+0300
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1fc0
+1f80
+2000
+2000
+6000
+7800
+7e00
+0f80
+0380
+01c0
+00c0
+00c0
+00c0
+00c0
+c180
+e380
+7e00
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+03c0
+0e00
+1800
+3000
+7000
+6000
+ee00
+f380
+c180
+c0c0
+c0c0
+c0c0
+c0c0
+e0c0
+6180
+7b80
+1e00
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+7fc0
+ffc0
+c0c0
+8180
+0180
+0100
+0300
+0300
+0200
+0600
+0600
+0400
+0c00
+0c00
+0c00
+1800
+1800
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+6180
+3300
+1e00
+1e00
+3700
+6180
+41c0
+c0c0
+c0c0
+c0c0
+e180
+7380
+1e00
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+7780
+6180
+c1c0
+c0c0
+c0c0
+c0c0
+c0c0
+61c0
+73c0
+1d80
+0180
+0380
+0300
+0600
+1c00
+f000
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 11 2 0
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+c0
+c0
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 14 2 -3
+BITMAP
+c0
+c0
+00
+00
+00
+00
+00
+00
+00
+c0
+e0
+20
+60
+c0
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 11 1 1
+BITMAP
+0060
+01c0
+0700
+1c00
+7000
+c000
+7000
+1c00
+0700
+01c0
+0060
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 6 1 4
+BITMAP
+fff0
+fff0
+0000
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 11 1 1
+BITMAP
+c000
+7000
+1c00
+0700
+01c0
+0060
+01c0
+0700
+1c00
+7000
+c000
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 17 2 0
+BITMAP
+7c
+c6
+83
+c3
+c3
+07
+0e
+0c
+18
+18
+10
+10
+10
+00
+00
+30
+30
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 18 20 2 -3
+BITMAP
+03f800
+0f0e00
+1c0300
+380180
+700080
+60ecc0
+e1fc40
+c38c40
+c30c40
+c60c40
+c61840
+c618c0
+c61880
+c63980
+637b00
+61de00
+300000
+180000
+0e0c00
+03f000
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 17 0 0
+BITMAP
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+ffc0
+3070
+3030
+3018
+3018
+3018
+3030
+3040
+3fe0
+3038
+3018
+300c
+300c
+300c
+3018
+3078
+ffe0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+07e4
+1c3c
+380c
+6004
+6004
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+6000
+6004
+3808
+1e38
+07e0
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 15 17 1 0
+BITMAP
+ffc0
+3070
+3038
+300c
+300c
+3006
+3006
+3006
+3006
+3006
+3006
+3006
+300c
+300c
+3038
+3070
+ffc0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 17 1 0
+BITMAP
+fff0
+3030
+3010
+3010
+3000
+3000
+3020
+3020
+3fe0
+3020
+3020
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e4
+1c3c
+380c
+6004
+6004
+c000
+c000
+c000
+c000
+c03f
+c00c
+c00c
+600c
+600c
+381c
+1e38
+07e0
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+fc1f80
+300600
+300600
+300600
+300600
+300600
+300600
+300600
+3ffe00
+300600
+300600
+300600
+300600
+300600
+300600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 17 1 0
+BITMAP
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+1f80
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+0600
+c600
+cc00
+7800
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 16 17 1 0
+BITMAP
+fc7e
+3018
+3030
+3060
+30c0
+3180
+3300
+3e00
+3f00
+3380
+31c0
+30e0
+3070
+3038
+301c
+300e
+fc1f
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 13 17 1 0
+BITMAP
+fc00
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 880 0
+DWIDTH 22 0
+BBX 21 17 1 0
+BITMAP
+f000f8
+3000e0
+380160
+380160
+2c0260
+2c0260
+260260
+260460
+230460
+230860
+218860
+218860
+20d060
+20d060
+206060
+206060
+f821f8
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+f01f
+3004
+3804
+3804
+2c04
+2604
+2604
+2304
+2184
+2184
+20c4
+2064
+2064
+2034
+201c
+201c
+f80c
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+ffc0
+3070
+3030
+3018
+3018
+3018
+3030
+3070
+3fc0
+3000
+3000
+3000
+3000
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 -5
+BITMAP
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+01c0
+00e0
+0070
+0038
+000f
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 15 17 1 0
+BITMAP
+ffc0
+3070
+3030
+3038
+3018
+3038
+3030
+3070
+3fc0
+3380
+31c0
+30c0
+3060
+3070
+3038
+301c
+fc1e
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+1e40
+63c0
+c0c0
+c040
+c040
+e000
+7800
+1e00
+0f80
+03c0
+00e0
+0060
+8060
+8060
+c0c0
+f180
+9e00
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 17 1 0
+BITMAP
+fffc
+c30c
+8304
+8304
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0300
+0fc0
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 17 0 0
+BITMAP
+fc1f80
+300600
+300400
+180c00
+180800
+180800
+0c1800
+0c1000
+063000
+062000
+062000
+036000
+034000
+03c000
+018000
+018000
+018000
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 920 0
+DWIDTH 23 0
+BBX 23 17 0 0
+BITMAP
+fc7e7e
+301818
+301810
+181810
+181830
+182c20
+0c2c20
+0c2c60
+064c60
+064c40
+064640
+0346c0
+034680
+038780
+018380
+018300
+018300
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 18 17 0 0
+BITMAP
+7e0f80
+1c0600
+0e0c00
+060800
+031000
+03a000
+01c000
+00c000
+00e000
+017000
+023800
+061800
+040c00
+080e00
+180700
+300380
+fc0fc0
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 16 17 0 0
+BITMAP
+fc3f
+300c
+3808
+1818
+1c10
+0c30
+0620
+0660
+0340
+03c0
+0180
+0180
+0180
+0180
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fff0
+c070
+80e0
+80c0
+01c0
+0380
+0300
+0700
+0600
+0e00
+1c00
+1800
+3800
+3008
+7008
+e018
+fff8
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 21 2 -4
+BITMAP
+f8
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+f8
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 17 0 0
+BITMAP
+c0
+c0
+40
+60
+60
+20
+30
+30
+10
+18
+18
+08
+0c
+0c
+04
+06
+06
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 21 1 -4
+BITMAP
+f8
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+f8
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 9 1 8
+BITMAP
+0800
+1c00
+1400
+3600
+2200
+6300
+4100
+c180
+8080
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 13 2 0 -5
+BITMAP
+fff8
+fff8
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 3 5 2 12
+BITMAP
+60
+c0
+80
+e0
+60
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+e000
+6000
+6000
+6000
+6000
+6e00
+7380
+6180
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+6180
+7380
+5e00
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1f00
+6380
+4180
+c000
+c000
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0380
+0180
+0180
+0180
+0180
+1d80
+7380
+6180
+c180
+c180
+c180
+c180
+c180
+c180
+6180
+7380
+1ec0
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 12 1 0
+BITMAP
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 17 0 0
+BITMAP
+0e
+16
+30
+30
+30
+fe
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 11 17 1 -5
+BITMAP
+1fc0
+3300
+6180
+6180
+6180
+6180
+3300
+3e00
+3000
+6000
+7f00
+3fc0
+6060
+c020
+c060
+f1c0
+3f00
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+e000
+6000
+6000
+6000
+6000
+6700
+6f80
+71c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+60
+60
+00
+00
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 22 0 -5
+BITMAP
+30
+30
+00
+00
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+e0
+c0
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 11 17 1 0
+BITMAP
+e000
+6000
+6000
+6000
+6000
+67c0
+6300
+6600
+6400
+6800
+7800
+6c00
+6e00
+6700
+6380
+61c0
+f3e0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 4 17 1 0
+BITMAP
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 800 0
+DWIDTH 20 0
+BBX 18 12 1 0
+BITMAP
+e70e00
+6f9f00
+71e380
+60c180
+60c180
+60c180
+60c180
+60c180
+60c180
+60c180
+60c180
+f1e3c0
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 0
+BITMAP
+e700
+6f80
+71c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 12 1 0
+BITMAP
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 -5
+BITMAP
+ee00
+7380
+6180
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+6180
+7380
+6e00
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 -5
+BITMAP
+1d80
+7380
+6180
+c180
+c180
+c180
+c180
+c180
+c180
+6180
+7380
+1d80
+0180
+0180
+0180
+0180
+03c0
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 12 1 0
+BITMAP
+e6
+6e
+76
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+3e
+66
+c2
+e0
+70
+7c
+1e
+07
+03
+83
+c6
+f8
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 7 15 0 0
+BITMAP
+10
+30
+70
+fe
+30
+30
+30
+30
+30
+30
+30
+30
+30
+32
+1c
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 0
+BITMAP
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 12 0 0
+BITMAP
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 12 0 0
+BITMAP
+f1e780
+60c300
+60c200
+30c200
+30c200
+316400
+196400
+1a6400
+1a2800
+0e3800
+0e3800
+041000
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 0
+BITMAP
+f1e0
+60c0
+3180
+3900
+1a00
+0c00
+0e00
+1b00
+3380
+2180
+60c0
+f1e0
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 17 0 -5
+BITMAP
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+0c00
+0800
+1800
+f000
+e000
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 12 1 0
+BITMAP
+ff
+c3
+86
+0e
+1c
+18
+38
+30
+70
+61
+c3
+ff
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+07
+0c
+18
+18
+18
+18
+18
+10
+30
+20
+c0
+20
+30
+10
+18
+18
+18
+18
+18
+18
+0c
+07
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 17 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 400 0
+DWIDTH 10 0
+BBX 8 22 1 -5
+BITMAP
+e0
+30
+18
+18
+18
+18
+18
+08
+0c
+04
+03
+04
+0c
+08
+18
+18
+18
+18
+18
+18
+30
+e0
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 4 1 5
+BITMAP
+3820
+7c60
+c7c0
+8380
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 2 17 4 -5
+BITMAP
+c0
+c0
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 16 1 -2
+BITMAP
+0100
+0100
+1f00
+6380
+4380
+c400
+c400
+c800
+c800
+c800
+d000
+7080
+7f00
+3e00
+4000
+4000
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0f00
+1980
+3180
+3000
+3000
+3000
+3000
+fc00
+3000
+3000
+3000
+3000
+3000
+3000
+7840
+bec0
+e780
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 12 1 3
+BITMAP
+c060
+eee0
+7fc0
+3180
+60c0
+60c0
+60c0
+60c0
+3180
+7fc0
+eee0
+c060
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 14 17 0 0
+BITMAP
+f87c
+7030
+3020
+1860
+1840
+0cc0
+0c80
+0780
+0300
+1fe0
+0300
+1fe0
+0300
+0300
+0300
+0300
+0fc0
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 17 2 0
+BITMAP
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+00
+00
+00
+c0
+c0
+c0
+c0
+c0
+c0
+c0
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 8 20 2 -2
+BITMAP
+1c
+26
+46
+60
+70
+38
+3c
+4e
+87
+83
+c3
+e2
+74
+38
+1c
+0e
+06
+62
+64
+38
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 14
+BITMAP
+cc
+cc
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+61e300
+473100
+c41980
+8c0080
+880080
+880080
+880080
+8c0080
+c41980
+477100
+61c300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 7 9 0 8
+BITMAP
+78
+cc
+0c
+7c
+cc
+cc
+76
+00
+7e
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 9 10 2 1
+BITMAP
+0880
+1980
+3300
+6600
+cc00
+cc00
+6600
+3300
+1980
+0880
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 7 1 3
+BITMAP
+fff0
+fff0
+0030
+0030
+0030
+0030
+0030
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 2 1 5
+BITMAP
+fe
+fe
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 760 0
+DWIDTH 19 0
+BBX 17 17 1 0
+BITMAP
+07f000
+1c1c00
+300600
+67e300
+423100
+c21180
+821080
+823080
+83e080
+824080
+822080
+c23180
+471900
+600300
+300600
+1c1c00
+07f000
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 2 1 14
+BITMAP
+fc
+fc
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 9 0
+BBX 7 7 1 10
+BITMAP
+38
+44
+82
+82
+82
+44
+38
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 15 1 0
+BITMAP
+0600
+0600
+0600
+0600
+0600
+fff0
+fff0
+0600
+0600
+0600
+0600
+0600
+0000
+fff0
+fff0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 6 10 0 7
+BITMAP
+38
+4c
+8c
+0c
+08
+10
+30
+20
+44
+fc
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 6 10 0 7
+BITMAP
+38
+4c
+8c
+08
+30
+08
+0c
+8c
+88
+70
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 5 4 2 13
+BITMAP
+18
+38
+60
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 -5
+BITMAP
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+7ec0
+5ce0
+4000
+4000
+c000
+e000
+4000
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 22 1 -5
+BITMAP
+1f80
+3900
+7900
+7900
+f900
+f900
+f900
+7900
+7900
+3900
+1900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+0900
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 2 2 2 6
+BITMAP
+c0
+c0
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 6 1 -6
+BITMAP
+10
+30
+3c
+0c
+cc
+78
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 280 0
+DWIDTH 7 0
+BBX 5 10 1 7
+BITMAP
+20
+60
+a0
+20
+20
+20
+20
+20
+20
+f8
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 9 1 8
+BITMAP
+78
+cc
+cc
+cc
+cc
+cc
+78
+00
+fc
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 9 10 2 1
+BITMAP
+8800
+cc00
+6600
+3300
+1980
+1980
+3300
+6600
+cc00
+8800
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 17 1 0
+BITMAP
+2008
+6018
+a030
+2020
+2060
+2040
+20c0
+2184
+210c
+fb1c
+0214
+0624
+0c64
+0844
+18ff
+1004
+3004
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 15 17 1 0
+BITMAP
+2008
+6018
+a030
+2020
+2060
+2040
+20c0
+219c
+2126
+fb46
+0206
+0604
+0c08
+0818
+1810
+1022
+307e
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 17 17 0 0
+BITMAP
+380400
+4c0c00
+8c1800
+081000
+303000
+082000
+0c6000
+8cc200
+888600
+718e00
+010a00
+031200
+063200
+042200
+0c7f80
+080200
+180200
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 8 17 1 -5
+BITMAP
+0c
+0c
+00
+00
+08
+08
+18
+18
+38
+30
+70
+e0
+c3
+c3
+c1
+63
+3e
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 22 0 0
+BITMAP
+030000
+038000
+00c000
+002000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 22 0 0
+BITMAP
+003000
+007000
+00c000
+010000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 22 0 0
+BITMAP
+018000
+03c000
+066000
+081000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 21 0 0
+BITMAP
+039000
+04e000
+000000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300700
+fc1f80
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 21 0 0
+BITMAP
+063000
+063000
+000000
+000000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 17 21 0 0
+BITMAP
+01c000
+022000
+022000
+01c000
+008000
+01c000
+01c000
+016000
+026000
+023000
+063000
+043000
+041800
+0c1800
+0ff800
+080c00
+180c00
+100c00
+100600
+300600
+fc1f80
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 840 0
+DWIDTH 21 0
+BBX 20 17 0 0
+BITMAP
+03ffe0
+01e060
+016020
+016020
+026000
+026000
+066080
+046080
+047f80
+0c6080
+0fe080
+086000
+186000
+106010
+106010
+306030
+f9fff0
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 23 1 -6
+BITMAP
+07e4
+1c3c
+380c
+6004
+6004
+c000
+c000
+c000
+c000
+c000
+c000
+c000
+6000
+6004
+3808
+1e38
+07e0
+0100
+0300
+03c0
+00c0
+0cc0
+0780
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 22 1 0
+BITMAP
+1800
+1c00
+0600
+0100
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 22 1 0
+BITMAP
+00c0
+01c0
+0300
+0400
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 22 1 0
+BITMAP
+0300
+0780
+0cc0
+1020
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 21 1 0
+BITMAP
+1980
+1980
+0000
+0000
+fff0
+3030
+3010
+3010
+3000
+3000
+3040
+3040
+3fc0
+3040
+3040
+3000
+3000
+3008
+3008
+3018
+fff8
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 0
+BITMAP
+c0
+e0
+30
+08
+00
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 22 1 0
+BITMAP
+0c
+1c
+30
+40
+00
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 8 22 1 0
+BITMAP
+18
+3c
+66
+81
+00
+7e
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+18
+7e
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 320 0
+DWIDTH 8 0
+BBX 6 21 1 0
+BITMAP
+cc
+cc
+00
+00
+fc
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+fc
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 680 0
+DWIDTH 17 0
+BBX 16 17 0 0
+BITMAP
+7fe0
+1838
+181c
+1806
+1806
+1803
+1803
+1803
+ff03
+1803
+1803
+1803
+1806
+1806
+181c
+1838
+7fe0
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0390
+04e0
+0000
+0000
+f01f
+3004
+3804
+3804
+2c04
+2604
+2604
+2304
+2184
+2184
+20c4
+2064
+2064
+2034
+201c
+201c
+f80c
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0600
+0700
+0180
+0040
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0030
+0070
+00c0
+0100
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0180
+03c0
+0660
+0810
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0390
+04e0
+0000
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0660
+0660
+0000
+0000
+07e0
+1c38
+381c
+6006
+6006
+c003
+c003
+c003
+c003
+c003
+c003
+c003
+6006
+6006
+381c
+1c38
+07e0
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 10 11 2 1
+BITMAP
+8040
+c0c0
+6180
+3300
+1e00
+0c00
+1e00
+3300
+6180
+c0c0
+8040
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 19 1 -1
+BITMAP
+0004
+07e4
+1c38
+381c
+6026
+6046
+c043
+c083
+c083
+c103
+c103
+c203
+c203
+6406
+6806
+381c
+1c38
+27e0
+2000
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0600
+0700
+0180
+0040
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0030
+0070
+00c0
+0100
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 22 1 0
+BITMAP
+0180
+03c0
+0660
+0810
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 18 0
+BBX 16 21 1 0
+BITMAP
+0630
+0630
+0000
+0000
+fc1f
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3004
+3008
+1808
+1c30
+07e0
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 16 22 0 0
+BITMAP
+0030
+0070
+00c0
+0100
+0000
+fc3f
+300c
+3808
+1818
+1c10
+0c30
+0620
+0660
+0340
+03c0
+0180
+0180
+0180
+0180
+0180
+0180
+07e0
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 15 0
+BBX 13 17 1 0
+BITMAP
+fc00
+3000
+3000
+3000
+3fc0
+3070
+3030
+3018
+3018
+3018
+3030
+3070
+3fc0
+3000
+3000
+3000
+fc00
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+1e00
+3300
+6180
+6180
+6180
+6180
+6300
+6c00
+6700
+6380
+6180
+61c0
+60c0
+60c0
+6cc0
+6c80
+e700
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+6000
+7000
+1800
+0400
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0300
+0700
+0c00
+1000
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+1800
+3c00
+2400
+4200
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+3a00
+5c00
+0000
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+6600
+6600
+0000
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+1c00
+2200
+2200
+1c00
+0000
+3e00
+6700
+6300
+0300
+0f00
+3b00
+6300
+c300
+c300
+c700
+fb00
+7180
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 640 0
+DWIDTH 16 0
+BBX 14 12 1 0
+BITMAP
+3cf0
+6798
+630c
+030c
+0ffc
+3b00
+6300
+c300
+c300
+c784
+fbf8
+70f0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 18 1 -6
+BITMAP
+1f00
+6380
+4180
+c000
+c000
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+0800
+1800
+1e00
+0600
+6600
+3c00
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+6000
+7000
+1800
+0400
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0300
+0700
+0c00
+1000
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 17 1 0
+BITMAP
+0c00
+1e00
+1200
+2100
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 9 16 1 0
+BITMAP
+3300
+3300
+0000
+0000
+1e00
+6300
+4180
+c180
+ff80
+c000
+c000
+c000
+e000
+7080
+7f00
+1e00
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 17 0 0
+BITMAP
+c0
+e0
+30
+08
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 5 17 1 0
+BITMAP
+18
+38
+60
+80
+00
+e0
+60
+60
+60
+60
+60
+60
+60
+60
+60
+60
+f0
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 6 17 0 0
+BITMAP
+30
+78
+48
+84
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 6 0
+BBX 6 16 0 0
+BITMAP
+cc
+cc
+00
+00
+70
+30
+30
+30
+30
+30
+30
+30
+30
+30
+30
+78
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+c000
+7180
+1e00
+3c00
+c600
+1f00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+1c80
+2700
+0000
+0000
+e700
+6f80
+71c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+f1e0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+3000
+3800
+0c00
+0200
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0180
+0380
+0600
+0800
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 17 1 0
+BITMAP
+0c00
+1e00
+1200
+2100
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 16 1 0
+BITMAP
+1c80
+2700
+0000
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 16 1 0
+BITMAP
+3300
+3300
+0000
+0000
+1e00
+7380
+6180
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+c0c0
+6180
+7380
+1e00
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 560 0
+DWIDTH 14 0
+BBX 12 10 1 2
+BITMAP
+0600
+0600
+0000
+0000
+fff0
+fff0
+0000
+0000
+0600
+0600
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 14 1 -1
+BITMAP
+00c0
+1ec0
+7380
+6380
+c6c0
+c4c0
+ccc0
+c8c0
+d8c0
+d0c0
+7180
+7380
+de00
+c000
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+3000
+3800
+0c00
+0200
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0180
+0380
+0600
+0800
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 17 1 0
+BITMAP
+0c00
+1e00
+1200
+2100
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 520 0
+DWIDTH 13 0
+BBX 11 16 1 0
+BITMAP
+3300
+3300
+0000
+0000
+e1c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+71c0
+3ec0
+1ce0
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 22 0 -5
+BITMAP
+0180
+0380
+0600
+0800
+0000
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+0c00
+0800
+1800
+f000
+e000
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 12 0
+BBX 10 22 1 -5
+BITMAP
+e000
+6000
+6000
+6000
+6000
+6e00
+7380
+6180
+60c0
+60c0
+60c0
+60c0
+60c0
+60c0
+6180
+7380
+6e00
+6000
+6000
+6000
+6000
+f000
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 440 0
+DWIDTH 11 0
+BBX 11 21 0 -5
+BITMAP
+3300
+3300
+0000
+0000
+f1e0
+60c0
+6080
+3080
+3080
+3100
+1900
+1900
+1a00
+0e00
+0e00
+0400
+0c00
+0800
+1800
+f000
+e000
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times24.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times24.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times24.h	(revision 16632)
@@ -0,0 +1,1110 @@
+static unsigned char times24_0_bits[] = {
+0x00};
+static unsigned char times24_1_bits[] = {
+0x00};
+static unsigned char times24_2_bits[] = {
+0x00};
+static unsigned char times24_3_bits[] = {
+0x00};
+static unsigned char times24_4_bits[] = {
+0x00};
+static unsigned char times24_5_bits[] = {
+0x00};
+static unsigned char times24_6_bits[] = {
+0x00};
+static unsigned char times24_7_bits[] = {
+0x00};
+static unsigned char times24_8_bits[] = {
+0x00};
+static unsigned char times24_9_bits[] = {
+0x00};
+static unsigned char times24_10_bits[] = {
+0x00};
+static unsigned char times24_11_bits[] = {
+0x00};
+static unsigned char times24_12_bits[] = {
+0x00};
+static unsigned char times24_13_bits[] = {
+0x00};
+static unsigned char times24_14_bits[] = {
+0x00};
+static unsigned char times24_15_bits[] = {
+0x00};
+static unsigned char times24_16_bits[] = {
+0x00};
+static unsigned char times24_17_bits[] = {
+0x00};
+static unsigned char times24_18_bits[] = {
+0x00};
+static unsigned char times24_19_bits[] = {
+0x00};
+static unsigned char times24_20_bits[] = {
+0x00};
+static unsigned char times24_21_bits[] = {
+0x00};
+static unsigned char times24_22_bits[] = {
+0x00};
+static unsigned char times24_23_bits[] = {
+0x00};
+static unsigned char times24_24_bits[] = {
+0x00};
+static unsigned char times24_25_bits[] = {
+0x00};
+static unsigned char times24_26_bits[] = {
+0x00};
+static unsigned char times24_27_bits[] = {
+0x00};
+static unsigned char times24_28_bits[] = {
+0x00};
+static unsigned char times24_29_bits[] = {
+0x00};
+static unsigned char times24_30_bits[] = {
+0x00};
+static unsigned char times24_31_bits[] = {
+0x00};
+static unsigned char times24_32_bits[] = {
+0x00};
+static unsigned char times24_33_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char times24_34_bits[] = {
+0x33, 0x33, 0x33, 0x33, 0x11};
+static unsigned char times24_35_bits[] = {
+0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xfe, 0x07, 
+0xfe, 0x07, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xff, 0x03, 0xff, 0x03, 
+0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00, 0x44, 0x00};
+static unsigned char times24_36_bits[] = {
+0x20, 0x00, 0x20, 0x00, 0xf8, 0x01, 0x2c, 0x07, 0x26, 0x06, 0x26, 0x04, 
+0x26, 0x00, 0x2e, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xe0, 0x01, 0xe0, 0x03, 
+0x20, 0x07, 0x20, 0x06, 0x21, 0x06, 0x21, 0x06, 0x23, 0x03, 0xa7, 0x03, 
+0xfc, 0x00, 0x20, 0x00, 0x20, 0x00};
+static unsigned char times24_37_bits[] = {
+0x78, 0x30, 0x00, 0xcc, 0x3f, 0x00, 0x86, 0x18, 0x00, 0x83, 0x08, 0x00, 
+0x83, 0x0c, 0x00, 0x43, 0x06, 0x00, 0x27, 0x02, 0x00, 0x1e, 0x03, 0x00, 
+0x80, 0xf1, 0x00, 0x80, 0x98, 0x01, 0xc0, 0x0c, 0x01, 0x60, 0x06, 0x01, 
+0x20, 0x06, 0x01, 0x30, 0x86, 0x00, 0x18, 0x4e, 0x00, 0x0c, 0x3c, 0x00};
+static unsigned char times24_38_bits[] = {
+0xe0, 0x01, 0x30, 0x03, 0x18, 0x02, 0x18, 0x02, 0x18, 0x03, 0xb8, 0x01, 
+0xf0, 0x00, 0x70, 0x7c, 0x78, 0x18, 0xec, 0x08, 0xc6, 0x04, 0x83, 0x05, 
+0x83, 0x03, 0x03, 0x03, 0x87, 0x87, 0xfe, 0x7e, 0x3c, 0x3c};
+static unsigned char times24_39_bits[] = {
+0x03, 0x07, 0x04, 0x06, 0x03};
+static unsigned char times24_40_bits[] = {
+0x20, 0x10, 0x08, 0x0c, 0x04, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x06, 0x06, 0x04, 0x0c, 0x08, 0x10, 0x20};
+static unsigned char times24_41_bits[] = {
+0x01, 0x02, 0x04, 0x0c, 0x08, 0x18, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 
+0x30, 0x30, 0x30, 0x18, 0x18, 0x08, 0x0c, 0x04, 0x02, 0x01};
+static unsigned char times24_42_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x93, 0x01, 0xd7, 0x01, 0x38, 0x00, 0xd7, 0x01, 
+0x93, 0x01, 0x38, 0x00, 0x10, 0x00};
+static unsigned char times24_43_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char times24_44_bits[] = {
+0x03, 0x07, 0x04, 0x06, 0x03};
+static unsigned char times24_45_bits[] = {
+0xff, 0x0f, 0xff, 0x0f};
+static unsigned char times24_46_bits[] = {
+0x03, 0x03};
+static unsigned char times24_47_bits[] = {
+0xc0, 0xc0, 0xc0, 0x60, 0x60, 0x20, 0x30, 0x30, 0x10, 0x18, 0x18, 0x08, 
+0x0c, 0x0c, 0x04, 0x06, 0x06, 0x03, 0x03, 0x03};
+static unsigned char times24_48_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x87, 0x03, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00};
+static unsigned char times24_49_bits[] = {
+0x10, 0x18, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0xff};
+static unsigned char times24_50_bits[] = {
+0x38, 0x00, 0xfe, 0x00, 0xc2, 0x01, 0x81, 0x01, 0x81, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0xc0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x20, 0x00, 0x30, 0x00, 
+0x18, 0x00, 0x0c, 0x00, 0x06, 0x02, 0xff, 0x03, 0xff, 0x01};
+static unsigned char times24_51_bits[] = {
+0x38, 0x00, 0x7e, 0x00, 0xe2, 0x00, 0xc1, 0x00, 0xc1, 0x00, 0x60, 0x00, 
+0x30, 0x00, 0x78, 0x00, 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x00, 0xc3, 0x00, 0x67, 0x00, 0x1e, 0x00};
+static unsigned char times24_52_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xd8, 0x00, 0xc8, 0x00, 
+0xcc, 0x00, 0xc4, 0x00, 0xc6, 0x00, 0xc2, 0x00, 0xc3, 0x00, 0xff, 0x03, 
+0xff, 0x03, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00};
+static unsigned char times24_53_bits[] = {
+0xf8, 0x03, 0xf8, 0x01, 0x04, 0x00, 0x04, 0x00, 0x06, 0x00, 0x1e, 0x00, 
+0x7e, 0x00, 0xf0, 0x01, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x03, 0x00, 0x03, 
+0x00, 0x03, 0x00, 0x03, 0x83, 0x01, 0xc7, 0x01, 0x7e, 0x00};
+static unsigned char times24_54_bits[] = {
+0xc0, 0x03, 0x70, 0x00, 0x18, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x06, 0x00, 
+0x77, 0x00, 0xcf, 0x01, 0x83, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x07, 0x03, 0x86, 0x01, 0xde, 0x01, 0x78, 0x00};
+static unsigned char times24_55_bits[] = {
+0xfe, 0x03, 0xff, 0x03, 0x03, 0x03, 0x81, 0x01, 0x80, 0x01, 0x80, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0x40, 0x00, 0x60, 0x00, 0x60, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x30, 0x00, 0x30, 0x00, 0x18, 0x00, 0x18, 0x00};
+static unsigned char times24_56_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0xcc, 0x00, 
+0x78, 0x00, 0x78, 0x00, 0xec, 0x00, 0x86, 0x01, 0x82, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x87, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_57_bits[] = {
+0x78, 0x00, 0xee, 0x01, 0x86, 0x01, 0x83, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x03, 0xce, 0x03, 0xb8, 0x01, 0x80, 0x01, 
+0xc0, 0x01, 0xc0, 0x00, 0x60, 0x00, 0x38, 0x00, 0x0f, 0x00};
+static unsigned char times24_58_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03};
+static unsigned char times24_59_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x04, 
+0x06, 0x03};
+static unsigned char times24_60_bits[] = {
+0x00, 0x06, 0x80, 0x03, 0xe0, 0x00, 0x38, 0x00, 0x0e, 0x00, 0x03, 0x00, 
+0x0e, 0x00, 0x38, 0x00, 0xe0, 0x00, 0x80, 0x03, 0x00, 0x06};
+static unsigned char times24_61_bits[] = {
+0xff, 0x0f, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char times24_62_bits[] = {
+0x03, 0x00, 0x0e, 0x00, 0x38, 0x00, 0xe0, 0x00, 0x80, 0x03, 0x00, 0x06, 
+0x80, 0x03, 0xe0, 0x00, 0x38, 0x00, 0x0e, 0x00, 0x03, 0x00};
+static unsigned char times24_63_bits[] = {
+0x3e, 0x63, 0xc1, 0xc3, 0xc3, 0xe0, 0x70, 0x30, 0x18, 0x18, 0x08, 0x08, 
+0x08, 0x00, 0x00, 0x0c, 0x0c};
+static unsigned char times24_64_bits[] = {
+0xc0, 0x1f, 0x00, 0xf0, 0x70, 0x00, 0x38, 0xc0, 0x00, 0x1c, 0x80, 0x01, 
+0x0e, 0x00, 0x01, 0x06, 0x37, 0x03, 0x87, 0x3f, 0x02, 0xc3, 0x31, 0x02, 
+0xc3, 0x30, 0x02, 0x63, 0x30, 0x02, 0x63, 0x18, 0x02, 0x63, 0x18, 0x03, 
+0x63, 0x18, 0x01, 0x63, 0x9c, 0x01, 0xc6, 0xde, 0x00, 0x86, 0x7b, 0x00, 
+0x0c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x70, 0x30, 0x00, 0xc0, 0x0f, 0x00};
+static unsigned char times24_65_bits[] = {
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_66_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 
+0x0c, 0x0c, 0x0c, 0x02, 0xfc, 0x07, 0x0c, 0x1c, 0x0c, 0x18, 0x0c, 0x30, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x18, 0x0c, 0x1e, 0xff, 0x07};
+static unsigned char times24_67_bits[] = {
+0xe0, 0x27, 0x38, 0x3c, 0x1c, 0x30, 0x06, 0x20, 0x06, 0x20, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x06, 0x00, 0x06, 0x20, 0x1c, 0x10, 0x78, 0x1c, 0xe0, 0x07};
+static unsigned char times24_68_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x60, 
+0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 0x0c, 0x60, 
+0x0c, 0x30, 0x0c, 0x30, 0x0c, 0x1c, 0x0c, 0x0e, 0xff, 0x03};
+static unsigned char times24_69_bits[] = {
+0xff, 0x0f, 0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x02, 0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_70_bits[] = {
+0xff, 0x0f, 0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x04, 0x0c, 0x04, 0xfc, 0x07, 0x0c, 0x04, 0x0c, 0x04, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char times24_71_bits[] = {
+0xe0, 0x27, 0x38, 0x3c, 0x1c, 0x30, 0x06, 0x20, 0x06, 0x20, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0xfc, 0x03, 0x30, 0x03, 0x30, 
+0x06, 0x30, 0x06, 0x30, 0x1c, 0x38, 0x78, 0x1c, 0xe0, 0x07};
+static unsigned char times24_72_bits[] = {
+0x3f, 0xf8, 0x01, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0xfc, 0x7f, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_73_bits[] = {
+0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_74_bits[] = {
+0xf8, 0x01, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x60, 0x00, 0x60, 0x00, 0x63, 0x00, 0x33, 0x00, 0x1e, 0x00};
+static unsigned char times24_75_bits[] = {
+0x3f, 0x7e, 0x0c, 0x18, 0x0c, 0x0c, 0x0c, 0x06, 0x0c, 0x03, 0x8c, 0x01, 
+0xcc, 0x00, 0x7c, 0x00, 0xfc, 0x00, 0xcc, 0x01, 0x8c, 0x03, 0x0c, 0x07, 
+0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x38, 0x0c, 0x70, 0x3f, 0xf8};
+static unsigned char times24_76_bits[] = {
+0x3f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_77_bits[] = {
+0x0f, 0x00, 0x1f, 0x0c, 0x00, 0x07, 0x1c, 0x80, 0x06, 0x1c, 0x80, 0x06, 
+0x34, 0x40, 0x06, 0x34, 0x40, 0x06, 0x64, 0x40, 0x06, 0x64, 0x20, 0x06, 
+0xc4, 0x20, 0x06, 0xc4, 0x10, 0x06, 0x84, 0x11, 0x06, 0x84, 0x11, 0x06, 
+0x04, 0x0b, 0x06, 0x04, 0x0b, 0x06, 0x04, 0x06, 0x06, 0x04, 0x06, 0x06, 
+0x1f, 0x84, 0x1f};
+static unsigned char times24_78_bits[] = {
+0x0f, 0xf8, 0x0c, 0x20, 0x1c, 0x20, 0x1c, 0x20, 0x34, 0x20, 0x64, 0x20, 
+0x64, 0x20, 0xc4, 0x20, 0x84, 0x21, 0x84, 0x21, 0x04, 0x23, 0x04, 0x26, 
+0x04, 0x26, 0x04, 0x2c, 0x04, 0x38, 0x04, 0x38, 0x1f, 0x30};
+static unsigned char times24_79_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x06, 0x60, 0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_80_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 
+0x0c, 0x0c, 0x0c, 0x0e, 0xfc, 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char times24_81_bits[] = {
+0xe0, 0x07, 0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x06, 0x60, 0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07, 0x80, 0x03, 
+0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0xf0};
+static unsigned char times24_82_bits[] = {
+0xff, 0x03, 0x0c, 0x0e, 0x0c, 0x0c, 0x0c, 0x1c, 0x0c, 0x18, 0x0c, 0x1c, 
+0x0c, 0x0c, 0x0c, 0x0e, 0xfc, 0x03, 0xcc, 0x01, 0x8c, 0x03, 0x0c, 0x03, 
+0x0c, 0x06, 0x0c, 0x0e, 0x0c, 0x1c, 0x0c, 0x38, 0x3f, 0x78};
+static unsigned char times24_83_bits[] = {
+0x78, 0x02, 0xc6, 0x03, 0x03, 0x03, 0x03, 0x02, 0x03, 0x02, 0x07, 0x00, 
+0x1e, 0x00, 0x78, 0x00, 0xf0, 0x01, 0xc0, 0x03, 0x00, 0x07, 0x00, 0x06, 
+0x01, 0x06, 0x01, 0x06, 0x03, 0x03, 0x8f, 0x01, 0x79, 0x00};
+static unsigned char times24_84_bits[] = {
+0xff, 0x3f, 0xc3, 0x30, 0xc1, 0x20, 0xc1, 0x20, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x03};
+static unsigned char times24_85_bits[] = {
+0x3f, 0xf8, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_86_bits[] = {
+0x3f, 0xf8, 0x01, 0x0c, 0x60, 0x00, 0x0c, 0x20, 0x00, 0x18, 0x30, 0x00, 
+0x18, 0x10, 0x00, 0x18, 0x10, 0x00, 0x30, 0x18, 0x00, 0x30, 0x08, 0x00, 
+0x60, 0x0c, 0x00, 0x60, 0x04, 0x00, 0x60, 0x04, 0x00, 0xc0, 0x06, 0x00, 
+0xc0, 0x02, 0x00, 0xc0, 0x03, 0x00, 0x80, 0x01, 0x00, 0x80, 0x01, 0x00, 
+0x80, 0x01, 0x00};
+static unsigned char times24_87_bits[] = {
+0x3f, 0x7e, 0x7e, 0x0c, 0x18, 0x18, 0x0c, 0x18, 0x08, 0x18, 0x18, 0x08, 
+0x18, 0x18, 0x0c, 0x18, 0x34, 0x04, 0x30, 0x34, 0x04, 0x30, 0x34, 0x06, 
+0x60, 0x32, 0x06, 0x60, 0x32, 0x02, 0x60, 0x62, 0x02, 0xc0, 0x62, 0x03, 
+0xc0, 0x62, 0x01, 0xc0, 0xe1, 0x01, 0x80, 0xc1, 0x01, 0x80, 0xc1, 0x00, 
+0x80, 0xc1, 0x00};
+static unsigned char times24_88_bits[] = {
+0x7e, 0xf0, 0x01, 0x38, 0x60, 0x00, 0x70, 0x30, 0x00, 0x60, 0x10, 0x00, 
+0xc0, 0x08, 0x00, 0xc0, 0x05, 0x00, 0x80, 0x03, 0x00, 0x00, 0x03, 0x00, 
+0x00, 0x07, 0x00, 0x80, 0x0e, 0x00, 0x40, 0x1c, 0x00, 0x60, 0x18, 0x00, 
+0x20, 0x30, 0x00, 0x10, 0x70, 0x00, 0x18, 0xe0, 0x00, 0x0c, 0xc0, 0x01, 
+0x3f, 0xf0, 0x03};
+static unsigned char times24_89_bits[] = {
+0x3f, 0xfc, 0x0c, 0x30, 0x1c, 0x10, 0x18, 0x18, 0x38, 0x08, 0x30, 0x0c, 
+0x60, 0x04, 0x60, 0x06, 0xc0, 0x02, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char times24_90_bits[] = {
+0xff, 0x0f, 0x03, 0x0e, 0x01, 0x07, 0x01, 0x03, 0x80, 0x03, 0xc0, 0x01, 
+0xc0, 0x00, 0xe0, 0x00, 0x60, 0x00, 0x70, 0x00, 0x38, 0x00, 0x18, 0x00, 
+0x1c, 0x00, 0x0c, 0x10, 0x0e, 0x10, 0x07, 0x18, 0xff, 0x1f};
+static unsigned char times24_91_bits[] = {
+0x1f, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x1f};
+static unsigned char times24_92_bits[] = {
+0x03, 0x03, 0x02, 0x06, 0x06, 0x04, 0x0c, 0x0c, 0x08, 0x18, 0x18, 0x10, 
+0x30, 0x30, 0x20, 0x60, 0x60};
+static unsigned char times24_93_bits[] = {
+0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f};
+static unsigned char times24_94_bits[] = {
+0x10, 0x00, 0x38, 0x00, 0x28, 0x00, 0x6c, 0x00, 0x44, 0x00, 0xc6, 0x00, 
+0x82, 0x00, 0x83, 0x01, 0x01, 0x01};
+static unsigned char times24_95_bits[] = {
+0xff, 0x1f, 0xff, 0x1f};
+static unsigned char times24_96_bits[] = {
+0x06, 0x03, 0x01, 0x07, 0x06};
+static unsigned char times24_97_bits[] = {
+0x7c, 0x00, 0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 
+0xc6, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_98_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x76, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 0xce, 0x01, 0x7a, 0x00};
+static unsigned char times24_99_bits[] = {
+0xf8, 0x00, 0xc6, 0x01, 0x82, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_100_bits[] = {
+0xc0, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xb8, 0x01, 
+0xce, 0x01, 0x86, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0x83, 0x01, 0x86, 0x01, 0xce, 0x01, 0x78, 0x03};
+static unsigned char times24_101_bits[] = {
+0x78, 0x00, 0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_102_bits[] = {
+0x70, 0x68, 0x0c, 0x0c, 0x0c, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_103_bits[] = {
+0xf8, 0x03, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 
+0xcc, 0x00, 0x7c, 0x00, 0x0c, 0x00, 0x06, 0x00, 0xfe, 0x00, 0xfc, 0x03, 
+0x06, 0x06, 0x03, 0x04, 0x03, 0x06, 0x8f, 0x03, 0xfc, 0x00};
+static unsigned char times24_104_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe6, 0x00, 
+0xf6, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_105_bits[] = {
+0x06, 0x06, 0x00, 0x00, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_106_bits[] = {
+0x0c, 0x0c, 0x00, 0x00, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x07, 0x03};
+static unsigned char times24_107_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0xe6, 0x03, 
+0xc6, 0x00, 0x66, 0x00, 0x26, 0x00, 0x16, 0x00, 0x1e, 0x00, 0x36, 0x00, 
+0x76, 0x00, 0xe6, 0x00, 0xc6, 0x01, 0x86, 0x03, 0xcf, 0x07};
+static unsigned char times24_108_bits[] = {
+0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_109_bits[] = {
+0xe7, 0x70, 0x00, 0xf6, 0xf9, 0x00, 0x8e, 0xc7, 0x01, 0x06, 0x83, 0x01, 
+0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 
+0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x06, 0x83, 0x01, 0x8f, 0xc7, 0x03};
+static unsigned char times24_110_bits[] = {
+0xe7, 0x00, 0xf6, 0x01, 0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_111_bits[] = {
+0x78, 0x00, 0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_112_bits[] = {
+0x77, 0x00, 0xce, 0x01, 0x86, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 0xce, 0x01, 0x76, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0f, 0x00};
+static unsigned char times24_113_bits[] = {
+0xb8, 0x01, 0xce, 0x01, 0x86, 0x01, 0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 
+0x83, 0x01, 0x83, 0x01, 0x83, 0x01, 0x86, 0x01, 0xce, 0x01, 0xb8, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xc0, 0x03};
+static unsigned char times24_114_bits[] = {
+0x67, 0x76, 0x6e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_115_bits[] = {
+0x7c, 0x66, 0x43, 0x07, 0x0e, 0x3e, 0x78, 0xe0, 0xc0, 0xc1, 0x63, 0x1f};
+static unsigned char times24_116_bits[] = {
+0x08, 0x0c, 0x0e, 0x7f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x4c, 0x38};
+static unsigned char times24_117_bits[] = {
+0x87, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_118_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 
+0x98, 0x00, 0x98, 0x00, 0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00};
+static unsigned char times24_119_bits[] = {
+0x8f, 0xe7, 0x01, 0x06, 0xc3, 0x00, 0x06, 0x43, 0x00, 0x0c, 0x43, 0x00, 
+0x0c, 0x43, 0x00, 0x8c, 0x26, 0x00, 0x98, 0x26, 0x00, 0x58, 0x26, 0x00, 
+0x58, 0x14, 0x00, 0x70, 0x1c, 0x00, 0x70, 0x1c, 0x00, 0x20, 0x08, 0x00};
+static unsigned char times24_120_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x8c, 0x01, 0x9c, 0x00, 0x58, 0x00, 0x30, 0x00, 
+0x70, 0x00, 0xd8, 0x00, 0xcc, 0x01, 0x84, 0x01, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_121_bits[] = {
+0x8f, 0x07, 0x06, 0x03, 0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 
+0x98, 0x00, 0x98, 0x00, 0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 
+0x30, 0x00, 0x10, 0x00, 0x18, 0x00, 0x0f, 0x00, 0x07, 0x00};
+static unsigned char times24_122_bits[] = {
+0xff, 0xc3, 0x61, 0x70, 0x38, 0x18, 0x1c, 0x0c, 0x0e, 0x86, 0xc3, 0xff};
+static unsigned char times24_123_bits[] = {
+0xe0, 0x30, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x0c, 0x04, 0x03, 0x04, 
+0x0c, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x30, 0xe0};
+static unsigned char times24_124_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char times24_125_bits[] = {
+0x07, 0x0c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x30, 0x20, 0xc0, 0x20, 
+0x30, 0x10, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0c, 0x07};
+static unsigned char times24_126_bits[] = {
+0x1c, 0x04, 0x3e, 0x06, 0xe3, 0x03, 0xc1, 0x01};
+static unsigned char times24_127_bits[] = {
+0x00};
+static unsigned char times24_128_bits[] = {
+0x00};
+static unsigned char times24_129_bits[] = {
+0x00};
+static unsigned char times24_130_bits[] = {
+0x00};
+static unsigned char times24_131_bits[] = {
+0x00};
+static unsigned char times24_132_bits[] = {
+0x00};
+static unsigned char times24_133_bits[] = {
+0x00};
+static unsigned char times24_134_bits[] = {
+0x00};
+static unsigned char times24_135_bits[] = {
+0x00};
+static unsigned char times24_136_bits[] = {
+0x00};
+static unsigned char times24_137_bits[] = {
+0x00};
+static unsigned char times24_138_bits[] = {
+0x00};
+static unsigned char times24_139_bits[] = {
+0x00};
+static unsigned char times24_140_bits[] = {
+0x00};
+static unsigned char times24_141_bits[] = {
+0x00};
+static unsigned char times24_142_bits[] = {
+0x00};
+static unsigned char times24_143_bits[] = {
+0x00};
+static unsigned char times24_144_bits[] = {
+0x00};
+static unsigned char times24_145_bits[] = {
+0x00};
+static unsigned char times24_146_bits[] = {
+0x00};
+static unsigned char times24_147_bits[] = {
+0x00};
+static unsigned char times24_148_bits[] = {
+0x00};
+static unsigned char times24_149_bits[] = {
+0x00};
+static unsigned char times24_150_bits[] = {
+0x00};
+static unsigned char times24_151_bits[] = {
+0x00};
+static unsigned char times24_152_bits[] = {
+0x00};
+static unsigned char times24_153_bits[] = {
+0x00};
+static unsigned char times24_154_bits[] = {
+0x00};
+static unsigned char times24_155_bits[] = {
+0x00};
+static unsigned char times24_156_bits[] = {
+0x00};
+static unsigned char times24_157_bits[] = {
+0x00};
+static unsigned char times24_158_bits[] = {
+0x00};
+static unsigned char times24_159_bits[] = {
+0x00};
+static unsigned char times24_160_bits[] = {
+0x00};
+static unsigned char times24_161_bits[] = {
+0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char times24_162_bits[] = {
+0x80, 0x00, 0x80, 0x00, 0xf8, 0x00, 0xc6, 0x01, 0xc2, 0x01, 0x23, 0x00, 
+0x23, 0x00, 0x13, 0x00, 0x13, 0x00, 0x13, 0x00, 0x0b, 0x00, 0x0e, 0x01, 
+0xfe, 0x00, 0x7c, 0x00, 0x02, 0x00, 0x02, 0x00};
+static unsigned char times24_163_bits[] = {
+0xf0, 0x00, 0x98, 0x01, 0x8c, 0x01, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x3f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x00, 0x0c, 0x00, 0x1e, 0x02, 0x7d, 0x03, 0xe7, 0x01};
+static unsigned char times24_164_bits[] = {
+0x03, 0x06, 0x77, 0x07, 0xfe, 0x03, 0x8c, 0x01, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8c, 0x01, 0xfe, 0x03, 0x77, 0x07, 0x03, 0x06};
+static unsigned char times24_165_bits[] = {
+0x1f, 0x3e, 0x0e, 0x0c, 0x0c, 0x04, 0x18, 0x06, 0x18, 0x02, 0x30, 0x03, 
+0x30, 0x01, 0xe0, 0x01, 0xc0, 0x00, 0xf8, 0x07, 0xc0, 0x00, 0xf8, 0x07, 
+0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xc0, 0x00, 0xf0, 0x03};
+static unsigned char times24_166_bits[] = {
+0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x03};
+static unsigned char times24_167_bits[] = {
+0x38, 0x64, 0x62, 0x06, 0x0e, 0x1c, 0x3c, 0x72, 0xe1, 0xc1, 0xc3, 0x47, 
+0x2e, 0x1c, 0x38, 0x70, 0x60, 0x46, 0x26, 0x1c};
+static unsigned char times24_168_bits[] = {
+0x33, 0x33};
+static unsigned char times24_169_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0x86, 0xc7, 0x00, 
+0xe2, 0x8c, 0x00, 0x23, 0x98, 0x01, 0x31, 0x00, 0x01, 0x11, 0x00, 0x01, 
+0x11, 0x00, 0x01, 0x11, 0x00, 0x01, 0x31, 0x00, 0x01, 0x23, 0x98, 0x01, 
+0xe2, 0x8e, 0x00, 0x86, 0xc3, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char times24_170_bits[] = {
+0x1e, 0x33, 0x30, 0x3e, 0x33, 0x33, 0x6e, 0x00, 0x7e};
+static unsigned char times24_171_bits[] = {
+0x10, 0x01, 0x98, 0x01, 0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x33, 0x00, 
+0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x10, 0x01};
+static unsigned char times24_172_bits[] = {
+0xff, 0x0f, 0xff, 0x0f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 
+0x00, 0x0c};
+static unsigned char times24_173_bits[] = {
+0x7f, 0x7f};
+static unsigned char times24_174_bits[] = {
+0xe0, 0x0f, 0x00, 0x38, 0x38, 0x00, 0x0c, 0x60, 0x00, 0xe6, 0xc7, 0x00, 
+0x42, 0x8c, 0x00, 0x43, 0x88, 0x01, 0x41, 0x08, 0x01, 0x41, 0x0c, 0x01, 
+0xc1, 0x07, 0x01, 0x41, 0x02, 0x01, 0x41, 0x04, 0x01, 0x43, 0x8c, 0x01, 
+0xe2, 0x98, 0x00, 0x06, 0xc0, 0x00, 0x0c, 0x60, 0x00, 0x38, 0x38, 0x00, 
+0xe0, 0x0f, 0x00};
+static unsigned char times24_175_bits[] = {
+0x3f, 0x3f};
+static unsigned char times24_176_bits[] = {
+0x1c, 0x22, 0x41, 0x41, 0x41, 0x22, 0x1c};
+static unsigned char times24_177_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0xff, 0x0f, 
+0xff, 0x0f, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 0x60, 0x00, 
+0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f};
+static unsigned char times24_178_bits[] = {
+0x1c, 0x32, 0x31, 0x30, 0x10, 0x08, 0x0c, 0x04, 0x22, 0x3f};
+static unsigned char times24_179_bits[] = {
+0x1c, 0x32, 0x31, 0x10, 0x0c, 0x10, 0x30, 0x31, 0x11, 0x0e};
+static unsigned char times24_180_bits[] = {
+0x18, 0x1c, 0x06, 0x01};
+static unsigned char times24_181_bits[] = {
+0x87, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7e, 0x03, 0x3a, 0x07, 
+0x02, 0x00, 0x02, 0x00, 0x03, 0x00, 0x07, 0x00, 0x02, 0x00};
+static unsigned char times24_182_bits[] = {
+0xf8, 0x01, 0x9c, 0x00, 0x9e, 0x00, 0x9e, 0x00, 0x9f, 0x00, 0x9f, 0x00, 
+0x9f, 0x00, 0x9e, 0x00, 0x9e, 0x00, 0x9c, 0x00, 0x98, 0x00, 0x90, 0x00, 
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 
+0x90, 0x00, 0x90, 0x00, 0x90, 0x00, 0x90, 0x00};
+static unsigned char times24_183_bits[] = {
+0x03, 0x03};
+static unsigned char times24_184_bits[] = {
+0x08, 0x0c, 0x3c, 0x30, 0x33, 0x1e};
+static unsigned char times24_185_bits[] = {
+0x04, 0x06, 0x05, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x1f};
+static unsigned char times24_186_bits[] = {
+0x1e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x1e, 0x00, 0x3f};
+static unsigned char times24_187_bits[] = {
+0x11, 0x00, 0x33, 0x00, 0x66, 0x00, 0xcc, 0x00, 0x98, 0x01, 0x98, 0x01, 
+0xcc, 0x00, 0x66, 0x00, 0x33, 0x00, 0x11, 0x00};
+static unsigned char times24_188_bits[] = {
+0x04, 0x10, 0x06, 0x18, 0x05, 0x0c, 0x04, 0x04, 0x04, 0x06, 0x04, 0x02, 
+0x04, 0x03, 0x84, 0x21, 0x84, 0x30, 0xdf, 0x38, 0x40, 0x28, 0x60, 0x24, 
+0x30, 0x26, 0x10, 0x22, 0x18, 0xff, 0x08, 0x20, 0x0c, 0x20};
+static unsigned char times24_189_bits[] = {
+0x04, 0x10, 0x06, 0x18, 0x05, 0x0c, 0x04, 0x04, 0x04, 0x06, 0x04, 0x02, 
+0x04, 0x03, 0x84, 0x39, 0x84, 0x64, 0xdf, 0x62, 0x40, 0x60, 0x60, 0x20, 
+0x30, 0x10, 0x10, 0x18, 0x18, 0x08, 0x08, 0x44, 0x0c, 0x7e};
+static unsigned char times24_190_bits[] = {
+0x1c, 0x20, 0x00, 0x32, 0x30, 0x00, 0x31, 0x18, 0x00, 0x10, 0x08, 0x00, 
+0x0c, 0x0c, 0x00, 0x10, 0x04, 0x00, 0x30, 0x06, 0x00, 0x31, 0x43, 0x00, 
+0x11, 0x61, 0x00, 0x8e, 0x71, 0x00, 0x80, 0x50, 0x00, 0xc0, 0x48, 0x00, 
+0x60, 0x4c, 0x00, 0x20, 0x44, 0x00, 0x30, 0xfe, 0x01, 0x10, 0x40, 0x00, 
+0x18, 0x40, 0x00};
+static unsigned char times24_191_bits[] = {
+0x30, 0x30, 0x00, 0x00, 0x10, 0x10, 0x18, 0x18, 0x1c, 0x0c, 0x0e, 0x07, 
+0xc3, 0xc3, 0x83, 0xc6, 0x7c};
+static unsigned char times24_192_bits[] = {
+0xc0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 
+0x80, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 
+0x10, 0x30, 0x00, 0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x3f, 0xf8, 0x01};
+static unsigned char times24_193_bits[] = {
+0x00, 0x0c, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 
+0x80, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 
+0x10, 0x30, 0x00, 0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x3f, 0xf8, 0x01};
+static unsigned char times24_194_bits[] = {
+0x80, 0x01, 0x00, 0xc0, 0x03, 0x00, 0x60, 0x06, 0x00, 0x10, 0x08, 0x00, 
+0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 
+0x80, 0x06, 0x00, 0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 
+0x20, 0x0c, 0x00, 0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 
+0x10, 0x30, 0x00, 0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 
+0x0c, 0x60, 0x00, 0x3f, 0xf8, 0x01};
+static unsigned char times24_195_bits[] = {
+0xc0, 0x09, 0x00, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0xe0, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_196_bits[] = {
+0x60, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_197_bits[] = {
+0x80, 0x03, 0x00, 0x40, 0x04, 0x00, 0x40, 0x04, 0x00, 0x80, 0x03, 0x00, 
+0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x80, 0x03, 0x00, 0x80, 0x06, 0x00, 
+0x40, 0x06, 0x00, 0x40, 0x0c, 0x00, 0x60, 0x0c, 0x00, 0x20, 0x0c, 0x00, 
+0x20, 0x18, 0x00, 0x30, 0x18, 0x00, 0xf0, 0x1f, 0x00, 0x10, 0x30, 0x00, 
+0x18, 0x30, 0x00, 0x08, 0x30, 0x00, 0x08, 0x60, 0x00, 0x0c, 0x60, 0x00, 
+0x3f, 0xf8, 0x01};
+static unsigned char times24_198_bits[] = {
+0xc0, 0xff, 0x07, 0x80, 0x07, 0x06, 0x80, 0x06, 0x04, 0x80, 0x06, 0x04, 
+0x40, 0x06, 0x00, 0x40, 0x06, 0x00, 0x60, 0x06, 0x01, 0x20, 0x06, 0x01, 
+0x20, 0xfe, 0x01, 0x30, 0x06, 0x01, 0xf0, 0x07, 0x01, 0x10, 0x06, 0x00, 
+0x18, 0x06, 0x00, 0x08, 0x06, 0x08, 0x08, 0x06, 0x08, 0x0c, 0x06, 0x0c, 
+0x9f, 0xff, 0x0f};
+static unsigned char times24_199_bits[] = {
+0xe0, 0x27, 0x38, 0x3c, 0x1c, 0x30, 0x06, 0x20, 0x06, 0x20, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x06, 0x00, 0x06, 0x20, 0x1c, 0x10, 0x78, 0x1c, 0xe0, 0x07, 0x80, 0x00, 
+0xc0, 0x00, 0xc0, 0x03, 0x00, 0x03, 0x30, 0x03, 0xe0, 0x01};
+static unsigned char times24_200_bits[] = {
+0x18, 0x00, 0x38, 0x00, 0x60, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 
+0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_201_bits[] = {
+0x00, 0x03, 0x80, 0x03, 0xc0, 0x00, 0x20, 0x00, 0x00, 0x00, 0xff, 0x0f, 
+0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 
+0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_202_bits[] = {
+0xc0, 0x00, 0xe0, 0x01, 0x30, 0x03, 0x08, 0x04, 0x00, 0x00, 0xff, 0x0f, 
+0x0c, 0x0c, 0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 
+0x0c, 0x02, 0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 
+0x0c, 0x10, 0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_203_bits[] = {
+0x98, 0x01, 0x98, 0x01, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x0c, 0x0c, 
+0x0c, 0x08, 0x0c, 0x08, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x02, 0x0c, 0x02, 
+0xfc, 0x03, 0x0c, 0x02, 0x0c, 0x02, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x10, 
+0x0c, 0x10, 0x0c, 0x18, 0xff, 0x1f};
+static unsigned char times24_204_bits[] = {
+0x03, 0x07, 0x0c, 0x10, 0x00, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_205_bits[] = {
+0x30, 0x38, 0x0c, 0x02, 0x00, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_206_bits[] = {
+0x18, 0x3c, 0x66, 0x81, 0x00, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 
+0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e};
+static unsigned char times24_207_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3f};
+static unsigned char times24_208_bits[] = {
+0xfe, 0x07, 0x18, 0x1c, 0x18, 0x38, 0x18, 0x60, 0x18, 0x60, 0x18, 0xc0, 
+0x18, 0xc0, 0x18, 0xc0, 0xff, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 0x18, 0xc0, 
+0x18, 0x60, 0x18, 0x60, 0x18, 0x38, 0x18, 0x1c, 0xfe, 0x07};
+static unsigned char times24_209_bits[] = {
+0xc0, 0x09, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf8, 0x0c, 0x20, 
+0x1c, 0x20, 0x1c, 0x20, 0x34, 0x20, 0x64, 0x20, 0x64, 0x20, 0xc4, 0x20, 
+0x84, 0x21, 0x84, 0x21, 0x04, 0x23, 0x04, 0x26, 0x04, 0x26, 0x04, 0x2c, 
+0x04, 0x38, 0x04, 0x38, 0x1f, 0x30};
+static unsigned char times24_210_bits[] = {
+0x60, 0x00, 0xe0, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x00, 0xe0, 0x07, 
+0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 
+0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_211_bits[] = {
+0x00, 0x0c, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x07, 
+0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 
+0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_212_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x10, 0x08, 0x00, 0x00, 0xe0, 0x07, 
+0x38, 0x1c, 0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 
+0x06, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_213_bits[] = {
+0xc0, 0x09, 0x20, 0x07, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x38, 0x1c, 
+0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 0x06, 0x60, 
+0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_214_bits[] = {
+0x60, 0x06, 0x60, 0x06, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x38, 0x1c, 
+0x1c, 0x38, 0x06, 0x60, 0x06, 0x60, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 
+0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x03, 0xc0, 0x06, 0x60, 0x06, 0x60, 
+0x1c, 0x38, 0x38, 0x1c, 0xe0, 0x07};
+static unsigned char times24_215_bits[] = {
+0x01, 0x02, 0x03, 0x03, 0x86, 0x01, 0xcc, 0x00, 0x78, 0x00, 0x30, 0x00, 
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x03, 0x03, 0x01, 0x02};
+static unsigned char times24_216_bits[] = {
+0x00, 0x20, 0xe0, 0x27, 0x38, 0x1c, 0x1c, 0x38, 0x06, 0x64, 0x06, 0x62, 
+0x03, 0xc2, 0x03, 0xc1, 0x03, 0xc1, 0x83, 0xc0, 0x83, 0xc0, 0x43, 0xc0, 
+0x43, 0xc0, 0x26, 0x60, 0x16, 0x60, 0x1c, 0x38, 0x38, 0x1c, 0xe4, 0x07, 
+0x04, 0x00};
+static unsigned char times24_217_bits[] = {
+0x60, 0x00, 0xe0, 0x00, 0x80, 0x01, 0x00, 0x02, 0x00, 0x00, 0x3f, 0xf8, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_218_bits[] = {
+0x00, 0x0c, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xf8, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_219_bits[] = {
+0x80, 0x01, 0xc0, 0x03, 0x60, 0x06, 0x10, 0x08, 0x00, 0x00, 0x3f, 0xf8, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x10, 0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_220_bits[] = {
+0x60, 0x0c, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xf8, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 
+0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x20, 0x0c, 0x10, 
+0x18, 0x10, 0x38, 0x0c, 0xe0, 0x07};
+static unsigned char times24_221_bits[] = {
+0x00, 0x0c, 0x00, 0x0e, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x3f, 0xfc, 
+0x0c, 0x30, 0x1c, 0x10, 0x18, 0x18, 0x38, 0x08, 0x30, 0x0c, 0x60, 0x04, 
+0x60, 0x06, 0xc0, 0x02, 0xc0, 0x03, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 
+0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xe0, 0x07};
+static unsigned char times24_222_bits[] = {
+0x3f, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0xfc, 0x03, 0x0c, 0x0e, 
+0x0c, 0x0c, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x18, 0x0c, 0x0c, 0x0c, 0x0e, 
+0xfc, 0x03, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x00, 0x3f, 0x00};
+static unsigned char times24_223_bits[] = {
+0x78, 0x00, 0xcc, 0x00, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 0x86, 0x01, 
+0xc6, 0x00, 0x36, 0x00, 0xe6, 0x00, 0xc6, 0x01, 0x86, 0x01, 0x86, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x36, 0x03, 0x36, 0x01, 0xe7, 0x00};
+static unsigned char times24_224_bits[] = {
+0x06, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_225_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_226_bits[] = {
+0x18, 0x00, 0x3c, 0x00, 0x24, 0x00, 0x42, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_227_bits[] = {
+0x5c, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xe6, 0x00, 
+0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_228_bits[] = {
+0x66, 0x00, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00, 0xe6, 0x00, 
+0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 0xc3, 0x00, 
+0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_229_bits[] = {
+0x38, 0x00, 0x44, 0x00, 0x44, 0x00, 0x38, 0x00, 0x00, 0x00, 0x7c, 0x00, 
+0xe6, 0x00, 0xc6, 0x00, 0xc0, 0x00, 0xf0, 0x00, 0xdc, 0x00, 0xc6, 0x00, 
+0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x00, 0xdf, 0x00, 0x8e, 0x01};
+static unsigned char times24_230_bits[] = {
+0x3c, 0x0f, 0xe6, 0x19, 0xc6, 0x30, 0xc0, 0x30, 0xf0, 0x3f, 0xdc, 0x00, 
+0xc6, 0x00, 0xc3, 0x00, 0xc3, 0x00, 0xe3, 0x21, 0xdf, 0x1f, 0x0e, 0x0f};
+static unsigned char times24_231_bits[] = {
+0xf8, 0x00, 0xc6, 0x01, 0x82, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00, 
+0x10, 0x00, 0x18, 0x00, 0x78, 0x00, 0x60, 0x00, 0x66, 0x00, 0x3c, 0x00};
+static unsigned char times24_232_bits[] = {
+0x06, 0x00, 0x0e, 0x00, 0x18, 0x00, 0x20, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_233_bits[] = {
+0xc0, 0x00, 0xe0, 0x00, 0x30, 0x00, 0x08, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_234_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xc6, 0x00, 0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 
+0x03, 0x00, 0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_235_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xc6, 0x00, 
+0x82, 0x01, 0x83, 0x01, 0xff, 0x01, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 
+0x07, 0x00, 0x0e, 0x01, 0xfe, 0x00, 0x78, 0x00};
+static unsigned char times24_236_bits[] = {
+0x03, 0x07, 0x0c, 0x10, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_237_bits[] = {
+0x18, 0x1c, 0x06, 0x01, 0x00, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 
+0x06, 0x06, 0x06, 0x06, 0x0f};
+static unsigned char times24_238_bits[] = {
+0x0c, 0x1e, 0x12, 0x21, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_239_bits[] = {
+0x33, 0x33, 0x00, 0x00, 0x0e, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 
+0x0c, 0x0c, 0x0c, 0x1e};
+static unsigned char times24_240_bits[] = {
+0x03, 0x00, 0x8e, 0x01, 0x78, 0x00, 0x3c, 0x00, 0x63, 0x00, 0xf8, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_241_bits[] = {
+0x38, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x00, 0xf6, 0x01, 
+0x8e, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x8f, 0x07};
+static unsigned char times24_242_bits[] = {
+0x0c, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_243_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_244_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0x78, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_245_bits[] = {
+0x38, 0x01, 0xe4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xce, 0x01, 
+0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_246_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xce, 0x01, 
+0x86, 0x01, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 
+0x03, 0x03, 0x86, 0x01, 0xce, 0x01, 0x78, 0x00};
+static unsigned char times24_247_bits[] = {
+0x60, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xff, 0x0f, 
+0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x00};
+static unsigned char times24_248_bits[] = {
+0x00, 0x03, 0x78, 0x03, 0xce, 0x01, 0xc6, 0x01, 0x63, 0x03, 0x23, 0x03, 
+0x33, 0x03, 0x13, 0x03, 0x1b, 0x03, 0x0b, 0x03, 0x8e, 0x01, 0xce, 0x01, 
+0x7b, 0x00, 0x03, 0x00};
+static unsigned char times24_249_bits[] = {
+0x0c, 0x00, 0x1c, 0x00, 0x30, 0x00, 0x40, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_250_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_251_bits[] = {
+0x30, 0x00, 0x78, 0x00, 0x48, 0x00, 0x84, 0x00, 0x00, 0x00, 0x87, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_252_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x8e, 0x03, 0x7c, 0x03, 0x38, 0x07};
+static unsigned char times24_253_bits[] = {
+0x80, 0x01, 0xc0, 0x01, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x8f, 0x07, 
+0x06, 0x03, 0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 0x98, 0x00, 
+0x98, 0x00, 0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0x30, 0x00, 
+0x10, 0x00, 0x18, 0x00, 0x0f, 0x00, 0x07, 0x00};
+static unsigned char times24_254_bits[] = {
+0x07, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x76, 0x00, 
+0xce, 0x01, 0x86, 0x01, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 0x06, 0x03, 
+0x06, 0x03, 0x06, 0x03, 0x86, 0x01, 0xce, 0x01, 0x76, 0x00, 0x06, 0x00, 
+0x06, 0x00, 0x06, 0x00, 0x06, 0x00, 0x0f, 0x00};
+static unsigned char times24_255_bits[] = {
+0xcc, 0x00, 0xcc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x07, 0x06, 0x03, 
+0x06, 0x01, 0x0c, 0x01, 0x0c, 0x01, 0x8c, 0x00, 0x98, 0x00, 0x98, 0x00, 
+0x58, 0x00, 0x70, 0x00, 0x70, 0x00, 0x20, 0x00, 0x30, 0x00, 0x10, 0x00, 
+0x18, 0x00, 0x0f, 0x00, 0x07, 0x00};
+static RotFont times24font[] = {
+{5, 1, 1, times24_0_bits},
+{5, 1, 1, times24_1_bits},
+{5, 1, 1, times24_2_bits},
+{5, 1, 1, times24_3_bits},
+{5, 1, 1, times24_4_bits},
+{5, 1, 1, times24_5_bits},
+{5, 1, 1, times24_6_bits},
+{5, 1, 1, times24_7_bits},
+{5, 1, 1, times24_8_bits},
+{5, 1, 1, times24_9_bits},
+{5, 1, 1, times24_10_bits},
+{5, 1, 1, times24_11_bits},
+{5, 1, 1, times24_12_bits},
+{5, 1, 1, times24_13_bits},
+{5, 1, 1, times24_14_bits},
+{5, 1, 1, times24_15_bits},
+{5, 1, 1, times24_16_bits},
+{5, 1, 1, times24_17_bits},
+{5, 1, 1, times24_18_bits},
+{5, 1, 1, times24_19_bits},
+{5, 1, 1, times24_20_bits},
+{5, 1, 1, times24_21_bits},
+{5, 1, 1, times24_22_bits},
+{5, 1, 1, times24_23_bits},
+{5, 1, 1, times24_24_bits},
+{5, 1, 1, times24_25_bits},
+{5, 1, 1, times24_26_bits},
+{5, 1, 1, times24_27_bits},
+{5, 1, 1, times24_28_bits},
+{5, 1, 1, times24_29_bits},
+{5, 1, 1, times24_30_bits},
+{5, 1, 1, times24_31_bits},
+{10, 1, 1, times24_32_bits},
+{2, 17, 17, times24_33_bits},
+{6, 5, 17, times24_34_bits},
+{11, 17, 17, times24_35_bits},
+{11, 21, 19, times24_36_bits},
+{17, 16, 16, times24_37_bits},
+{16, 17, 17, times24_38_bits},
+{3, 5, 17, times24_39_bits},
+{6, 22, 17, times24_40_bits},
+{6, 22, 17, times24_41_bits},
+{9, 9, 17, times24_42_bits},
+{12, 12, 13, times24_43_bits},
+{3, 5, 2, times24_44_bits},
+{12, 2, 8, times24_45_bits},
+{2, 2, 2, times24_46_bits},
+{8, 20, 17, times24_47_bits},
+{10, 17, 17, times24_48_bits},
+{8, 17, 17, times24_49_bits},
+{10, 17, 17, times24_50_bits},
+{9, 17, 17, times24_51_bits},
+{10, 17, 17, times24_52_bits},
+{10, 17, 17, times24_53_bits},
+{10, 17, 17, times24_54_bits},
+{10, 17, 17, times24_55_bits},
+{10, 17, 17, times24_56_bits},
+{10, 17, 17, times24_57_bits},
+{2, 11, 11, times24_58_bits},
+{3, 14, 11, times24_59_bits},
+{11, 11, 12, times24_60_bits},
+{12, 6, 10, times24_61_bits},
+{11, 11, 12, times24_62_bits},
+{8, 17, 17, times24_63_bits},
+{18, 20, 17, times24_64_bits},
+{17, 17, 17, times24_65_bits},
+{14, 17, 17, times24_66_bits},
+{14, 17, 17, times24_67_bits},
+{15, 17, 17, times24_68_bits},
+{13, 17, 17, times24_69_bits},
+{12, 17, 17, times24_70_bits},
+{16, 17, 17, times24_71_bits},
+{17, 17, 17, times24_72_bits},
+{6, 17, 17, times24_73_bits},
+{9, 17, 17, times24_74_bits},
+{16, 17, 17, times24_75_bits},
+{13, 17, 17, times24_76_bits},
+{21, 17, 17, times24_77_bits},
+{16, 17, 17, times24_78_bits},
+{16, 17, 17, times24_79_bits},
+{13, 17, 17, times24_80_bits},
+{16, 22, 17, times24_81_bits},
+{15, 17, 17, times24_82_bits},
+{11, 17, 17, times24_83_bits},
+{14, 17, 17, times24_84_bits},
+{16, 17, 17, times24_85_bits},
+{17, 17, 17, times24_86_bits},
+{23, 17, 17, times24_87_bits},
+{18, 17, 17, times24_88_bits},
+{16, 17, 17, times24_89_bits},
+{13, 17, 17, times24_90_bits},
+{5, 21, 17, times24_91_bits},
+{7, 17, 17, times24_92_bits},
+{5, 21, 17, times24_93_bits},
+{9, 9, 17, times24_94_bits},
+{13, 2, -3, times24_95_bits},
+{3, 5, 17, times24_96_bits},
+{9, 12, 12, times24_97_bits},
+{10, 17, 17, times24_98_bits},
+{9, 12, 12, times24_99_bits},
+{10, 17, 17, times24_100_bits},
+{9, 12, 12, times24_101_bits},
+{7, 17, 17, times24_102_bits},
+{11, 17, 12, times24_103_bits},
+{11, 17, 17, times24_104_bits},
+{4, 17, 17, times24_105_bits},
+{4, 22, 17, times24_106_bits},
+{11, 17, 17, times24_107_bits},
+{4, 17, 17, times24_108_bits},
+{18, 12, 12, times24_109_bits},
+{11, 12, 12, times24_110_bits},
+{10, 12, 12, times24_111_bits},
+{10, 17, 12, times24_112_bits},
+{10, 17, 12, times24_113_bits},
+{7, 12, 12, times24_114_bits},
+{8, 12, 12, times24_115_bits},
+{7, 15, 15, times24_116_bits},
+{11, 12, 12, times24_117_bits},
+{11, 12, 12, times24_118_bits},
+{17, 12, 12, times24_119_bits},
+{11, 12, 12, times24_120_bits},
+{11, 17, 12, times24_121_bits},
+{8, 12, 12, times24_122_bits},
+{8, 22, 17, times24_123_bits},
+{2, 17, 17, times24_124_bits},
+{8, 22, 17, times24_125_bits},
+{11, 4, 9, times24_126_bits},
+{5, 1, 1, times24_127_bits},
+{5, 1, 1, times24_128_bits},
+{5, 1, 1, times24_129_bits},
+{5, 1, 1, times24_130_bits},
+{5, 1, 1, times24_131_bits},
+{5, 1, 1, times24_132_bits},
+{5, 1, 1, times24_133_bits},
+{5, 1, 1, times24_134_bits},
+{5, 1, 1, times24_135_bits},
+{5, 1, 1, times24_136_bits},
+{5, 1, 1, times24_137_bits},
+{5, 1, 1, times24_138_bits},
+{5, 1, 1, times24_139_bits},
+{5, 1, 1, times24_140_bits},
+{5, 1, 1, times24_141_bits},
+{5, 1, 1, times24_142_bits},
+{5, 1, 1, times24_143_bits},
+{5, 1, 1, times24_144_bits},
+{5, 1, 1, times24_145_bits},
+{5, 1, 1, times24_146_bits},
+{5, 1, 1, times24_147_bits},
+{5, 1, 1, times24_148_bits},
+{5, 1, 1, times24_149_bits},
+{5, 1, 1, times24_150_bits},
+{5, 1, 1, times24_151_bits},
+{5, 1, 1, times24_152_bits},
+{5, 1, 1, times24_153_bits},
+{5, 1, 1, times24_154_bits},
+{5, 1, 1, times24_155_bits},
+{5, 1, 1, times24_156_bits},
+{5, 1, 1, times24_157_bits},
+{5, 1, 1, times24_158_bits},
+{5, 1, 1, times24_159_bits},
+{1, 1, 1, times24_160_bits},
+{2, 17, 12, times24_161_bits},
+{9, 16, 14, times24_162_bits},
+{10, 17, 17, times24_163_bits},
+{11, 12, 15, times24_164_bits},
+{14, 17, 17, times24_165_bits},
+{2, 17, 17, times24_166_bits},
+{8, 20, 18, times24_167_bits},
+{6, 2, 16, times24_168_bits},
+{17, 17, 17, times24_169_bits},
+{7, 9, 17, times24_170_bits},
+{9, 10, 11, times24_171_bits},
+{12, 7, 10, times24_172_bits},
+{7, 2, 7, times24_173_bits},
+{17, 17, 17, times24_174_bits},
+{6, 2, 16, times24_175_bits},
+{7, 7, 17, times24_176_bits},
+{12, 15, 15, times24_177_bits},
+{6, 10, 17, times24_178_bits},
+{6, 10, 17, times24_179_bits},
+{5, 4, 17, times24_180_bits},
+{11, 17, 12, times24_181_bits},
+{9, 22, 17, times24_182_bits},
+{2, 2, 8, times24_183_bits},
+{6, 6, 0, times24_184_bits},
+{5, 10, 17, times24_185_bits},
+{6, 9, 17, times24_186_bits},
+{9, 10, 11, times24_187_bits},
+{16, 17, 17, times24_188_bits},
+{15, 17, 17, times24_189_bits},
+{17, 17, 17, times24_190_bits},
+{8, 17, 12, times24_191_bits},
+{17, 22, 22, times24_192_bits},
+{17, 22, 22, times24_193_bits},
+{17, 22, 22, times24_194_bits},
+{17, 21, 21, times24_195_bits},
+{17, 21, 21, times24_196_bits},
+{17, 21, 21, times24_197_bits},
+{20, 17, 17, times24_198_bits},
+{14, 23, 17, times24_199_bits},
+{13, 22, 22, times24_200_bits},
+{13, 22, 22, times24_201_bits},
+{13, 22, 22, times24_202_bits},
+{13, 21, 21, times24_203_bits},
+{6, 22, 22, times24_204_bits},
+{6, 22, 22, times24_205_bits},
+{8, 22, 22, times24_206_bits},
+{6, 21, 21, times24_207_bits},
+{16, 17, 17, times24_208_bits},
+{16, 21, 21, times24_209_bits},
+{16, 22, 22, times24_210_bits},
+{16, 22, 22, times24_211_bits},
+{16, 22, 22, times24_212_bits},
+{16, 21, 21, times24_213_bits},
+{16, 21, 21, times24_214_bits},
+{10, 11, 12, times24_215_bits},
+{16, 19, 18, times24_216_bits},
+{16, 22, 22, times24_217_bits},
+{16, 22, 22, times24_218_bits},
+{16, 22, 22, times24_219_bits},
+{16, 21, 21, times24_220_bits},
+{16, 22, 22, times24_221_bits},
+{13, 17, 17, times24_222_bits},
+{10, 17, 17, times24_223_bits},
+{9, 17, 17, times24_224_bits},
+{9, 17, 17, times24_225_bits},
+{9, 17, 17, times24_226_bits},
+{9, 16, 16, times24_227_bits},
+{9, 16, 16, times24_228_bits},
+{9, 17, 17, times24_229_bits},
+{14, 12, 12, times24_230_bits},
+{9, 18, 12, times24_231_bits},
+{9, 17, 17, times24_232_bits},
+{9, 17, 17, times24_233_bits},
+{9, 17, 17, times24_234_bits},
+{9, 16, 16, times24_235_bits},
+{5, 17, 17, times24_236_bits},
+{5, 17, 17, times24_237_bits},
+{6, 17, 17, times24_238_bits},
+{6, 16, 16, times24_239_bits},
+{10, 17, 17, times24_240_bits},
+{11, 16, 16, times24_241_bits},
+{10, 17, 17, times24_242_bits},
+{10, 17, 17, times24_243_bits},
+{10, 17, 17, times24_244_bits},
+{10, 16, 16, times24_245_bits},
+{10, 16, 16, times24_246_bits},
+{12, 10, 12, times24_247_bits},
+{10, 14, 13, times24_248_bits},
+{11, 17, 17, times24_249_bits},
+{11, 17, 17, times24_250_bits},
+{11, 17, 17, times24_251_bits},
+{11, 16, 16, times24_252_bits},
+{11, 22, 17, times24_253_bits},
+{10, 22, 17, times24_254_bits},
+{11, 21, 16, times24_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times8.bdf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times8.bdf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times8.bdf	(revision 16632)
@@ -0,0 +1,2435 @@
+STARTFONT 2.1
+COMMENT  
+COMMENT  Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved.
+COMMENT  
+COMMENT  WARNING:  This bdf file was generated from a font server using
+COMMENT  fstobdf.  The resulting font is subject to the same copyright,
+COMMENT  license, and trademark restrictions as the original font.  The
+COMMENT  authors and distributors of fstobdf disclaim all liability for
+COMMENT  misuse of the program or its output.
+COMMENT  
+FONT -Adobe-Times-Medium-R-Normal--8-80-75-75-P-44-ISO8859-1
+SIZE 8 75 75
+FONTBOUNDINGBOX 9 10 -1 -2
+STARTPROPERTIES 32
+FOUNDRY "Adobe"
+FAMILY_NAME "Times"
+WEIGHT_NAME "Medium"
+SLANT "R"
+SETWIDTH_NAME "Normal"
+ADD_STYLE_NAME ""
+PIXEL_SIZE 8
+POINT_SIZE 80
+RESOLUTION_X 75
+RESOLUTION_Y 75
+SPACING "P"
+AVERAGE_WIDTH 44
+CHARSET_REGISTRY "ISO8859"
+CHARSET_ENCODING "1"
+CAP_HEIGHT 5
+X_HEIGHT 4
+FACE_NAME "Times Roman"
+COPYRIGHT "Copyright (c) 1984, 1987 Adobe Systems Incorporated. All Rights Reserved. Copyright (c) 1988, 1991 Digital Equipment Corporation. All Rights Reserved."
+NOTICE "Times is a trademark of Linotype-Hell AG and/or its subsidiaries."
+_DEC_DEVICE_FONTNAMES "PS=Times-Roman"
+_DEC_PRODUCTINFO "DECwindows Fonts V2.2, 07-Nov-1991"
+RELATIVE_SETWIDTH 50
+RELATIVE_WEIGHT 50
+CHARSET_COLLECTIONS "ASCII ISO8859-1 ADOBE-STANDARD"
+FULL_NAME "Times Roman"
+FONT "-Adobe-Times-Medium-R-Normal--8-80-75-75-P-44-ISO8859-1"
+WEIGHT 10
+RESOLUTION 103
+QUAD_WIDTH 5
+DEFAULT_CHAR 32
+FONT_ASCENT 7
+FONT_DESCENT 2
+ENDPROPERTIES
+CHARS 191
+STARTCHAR space
+ENCODING 32
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclam
+ENCODING 33
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 1 0
+BITMAP
+80
+80
+80
+80
+00
+80
+ENDCHAR
+STARTCHAR quotedbl
+ENCODING 34
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 2 0 3
+BITMAP
+a0
+a0
+ENDCHAR
+STARTCHAR numbersign
+ENCODING 35
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+50
+f0
+50
+f0
+50
+ENDCHAR
+STARTCHAR dollar
+ENCODING 36
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 -1
+BITMAP
+40
+60
+80
+60
+a0
+c0
+40
+ENDCHAR
+STARTCHAR percent
+ENCODING 37
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+c8
+d0
+20
+58
+98
+ENDCHAR
+STARTCHAR ampersand
+ENCODING 38
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 6 0 0
+BITMAP
+20
+50
+60
+a8
+90
+78
+ENDCHAR
+STARTCHAR apostrophe
+ENCODING 39
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 2 1 4
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR parenleft
+ENCODING 40
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 1 -1
+BITMAP
+40
+80
+80
+80
+80
+80
+40
+ENDCHAR
+STARTCHAR parenright
+ENCODING 41
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 0 -1
+BITMAP
+80
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR asterisk
+ENCODING 42
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 3 1 2
+BITMAP
+a0
+40
+a0
+ENDCHAR
+STARTCHAR plus
+ENCODING 43
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+20
+20
+f0
+20
+20
+ENDCHAR
+STARTCHAR comma
+ENCODING 44
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 1 -1
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR minus
+ENCODING 45
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 1 1 2
+BITMAP
+f0
+ENDCHAR
+STARTCHAR period
+ENCODING 46
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 1 0
+BITMAP
+80
+ENDCHAR
+STARTCHAR slash
+ENCODING 47
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+20
+20
+40
+40
+40
+80
+80
+ENDCHAR
+STARTCHAR 0
+ENCODING 48
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+a0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR 1
+ENCODING 49
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR 2
+ENCODING 50
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+c0
+20
+40
+80
+e0
+ENDCHAR
+STARTCHAR 3
+ENCODING 51
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+c0
+20
+40
+20
+c0
+ENDCHAR
+STARTCHAR 4
+ENCODING 52
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+20
+60
+a0
+f0
+20
+ENDCHAR
+STARTCHAR 5
+ENCODING 53
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+e0
+80
+60
+20
+c0
+ENDCHAR
+STARTCHAR 6
+ENCODING 54
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+60
+80
+c0
+a0
+40
+ENDCHAR
+STARTCHAR 7
+ENCODING 55
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+e0
+20
+40
+80
+80
+ENDCHAR
+STARTCHAR 8
+ENCODING 56
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+a0
+40
+a0
+40
+ENDCHAR
+STARTCHAR 9
+ENCODING 57
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+a0
+60
+20
+c0
+ENDCHAR
+STARTCHAR colon
+ENCODING 58
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 3 1 0
+BITMAP
+80
+00
+80
+ENDCHAR
+STARTCHAR semicolon
+ENCODING 59
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 1 -1
+BITMAP
+40
+00
+40
+80
+ENDCHAR
+STARTCHAR less
+ENCODING 60
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+20
+40
+80
+40
+20
+ENDCHAR
+STARTCHAR equal
+ENCODING 61
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 3 0 1
+BITMAP
+f0
+00
+f0
+ENDCHAR
+STARTCHAR greater
+ENCODING 62
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 1 0
+BITMAP
+80
+40
+20
+40
+80
+ENDCHAR
+STARTCHAR question
+ENCODING 63
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 0
+BITMAP
+c0
+20
+40
+00
+40
+ENDCHAR
+STARTCHAR at
+ENCODING 64
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 0 -1
+BITMAP
+78
+84
+9c
+a4
+bc
+80
+78
+ENDCHAR
+STARTCHAR A
+ENCODING 65
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+20
+50
+70
+50
+d8
+ENDCHAR
+STARTCHAR B
+ENCODING 66
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+e0
+50
+60
+50
+e0
+ENDCHAR
+STARTCHAR C
+ENCODING 67
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+88
+80
+88
+70
+ENDCHAR
+STARTCHAR D
+ENCODING 68
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+f0
+48
+48
+48
+f0
+ENDCHAR
+STARTCHAR E
+ENCODING 69
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR F
+ENCODING 70
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+f0
+40
+70
+40
+c0
+ENDCHAR
+STARTCHAR G
+ENCODING 71
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+80
+b8
+88
+70
+ENDCHAR
+STARTCHAR H
+ENCODING 72
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+48
+78
+48
+cc
+ENDCHAR
+STARTCHAR I
+ENCODING 73
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 0
+BITMAP
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR J
+ENCODING 74
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 5 0 0
+BITMAP
+c0
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR K
+ENCODING 75
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+c8
+50
+60
+50
+d8
+ENDCHAR
+STARTCHAR L
+ENCODING 76
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+e0
+40
+40
+50
+f0
+ENDCHAR
+STARTCHAR M
+ENCODING 77
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 7 5 0 0
+BITMAP
+ee
+6c
+54
+54
+c6
+ENDCHAR
+STARTCHAR N
+ENCODING 78
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+68
+68
+58
+c8
+ENDCHAR
+STARTCHAR O
+ENCODING 79
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR P
+ENCODING 80
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+f0
+48
+70
+40
+c0
+ENDCHAR
+STARTCHAR Q
+ENCODING 81
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -2
+BITMAP
+70
+88
+88
+88
+70
+20
+10
+ENDCHAR
+STARTCHAR R
+ENCODING 82
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+e0
+50
+60
+50
+d8
+ENDCHAR
+STARTCHAR S
+ENCODING 83
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+70
+80
+60
+10
+e0
+ENDCHAR
+STARTCHAR T
+ENCODING 84
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 5 0 0
+BITMAP
+f8
+a8
+20
+20
+70
+ENDCHAR
+STARTCHAR U
+ENCODING 85
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR V
+ENCODING 86
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+d8
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR W
+ENCODING 87
+SWIDTH 960 0
+DWIDTH 8 0
+BBX 8 5 0 0
+BITMAP
+d3
+52
+4a
+5a
+2c
+ENDCHAR
+STARTCHAR X
+ENCODING 88
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+cc
+30
+30
+48
+cc
+ENDCHAR
+STARTCHAR Y
+ENCODING 89
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+d8
+50
+20
+20
+70
+ENDCHAR
+STARTCHAR Z
+ENCODING 90
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 1 0
+BITMAP
+f0
+a0
+40
+90
+f0
+ENDCHAR
+STARTCHAR bracketleft
+ENCODING 91
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+c0
+80
+80
+80
+80
+80
+c0
+ENDCHAR
+STARTCHAR backslash
+ENCODING 92
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 0 -1
+BITMAP
+80
+80
+40
+40
+40
+20
+20
+ENDCHAR
+STARTCHAR bracketright
+ENCODING 93
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 -1
+BITMAP
+c0
+40
+40
+40
+40
+40
+c0
+ENDCHAR
+STARTCHAR asciicircum
+ENCODING 94
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 2 1 4
+BITMAP
+40
+a0
+ENDCHAR
+STARTCHAR underscore
+ENCODING 95
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 1 0 -1
+BITMAP
+f0
+ENDCHAR
+STARTCHAR grave
+ENCODING 96
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 2 1 4
+BITMAP
+80
+80
+ENDCHAR
+STARTCHAR a
+ENCODING 97
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 4 0 0
+BITMAP
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR b
+ENCODING 98
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+80
+c0
+a0
+a0
+c0
+ENDCHAR
+STARTCHAR c
+ENCODING 99
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 4 0 0
+BITMAP
+40
+80
+80
+40
+ENDCHAR
+STARTCHAR d
+ENCODING 100
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+20
+60
+a0
+a0
+60
+ENDCHAR
+STARTCHAR e
+ENCODING 101
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR f
+ENCODING 102
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 0
+BITMAP
+20
+40
+e0
+40
+40
+ENDCHAR
+STARTCHAR g
+ENCODING 103
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 -1
+BITMAP
+70
+a0
+40
+a0
+40
+ENDCHAR
+STARTCHAR h
+ENCODING 104
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+80
+c0
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR i
+ENCODING 105
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 6 0 0
+BITMAP
+80
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR j
+ENCODING 106
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 8 -1 -2
+BITMAP
+40
+00
+40
+40
+40
+40
+40
+80
+ENDCHAR
+STARTCHAR k
+ENCODING 107
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+80
+a0
+c0
+c0
+a0
+ENDCHAR
+STARTCHAR l
+ENCODING 108
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 1 5 0 0
+BITMAP
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR m
+ENCODING 109
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+d0
+a8
+a8
+a8
+ENDCHAR
+STARTCHAR n
+ENCODING 110
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+c0
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR o
+ENCODING 111
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR p
+ENCODING 112
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+c0
+a0
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR q
+ENCODING 113
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+60
+a0
+a0
+60
+20
+20
+ENDCHAR
+STARTCHAR r
+ENCODING 114
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 4 0 0
+BITMAP
+a0
+c0
+80
+80
+ENDCHAR
+STARTCHAR s
+ENCODING 115
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 4 0 0
+BITMAP
+c0
+80
+40
+c0
+ENDCHAR
+STARTCHAR t
+ENCODING 116
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 5 0 0
+BITMAP
+80
+c0
+80
+80
+40
+ENDCHAR
+STARTCHAR u
+ENCODING 117
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR v
+ENCODING 118
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+a0
+a0
+a0
+40
+ENDCHAR
+STARTCHAR w
+ENCODING 119
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+a8
+a8
+a8
+50
+ENDCHAR
+STARTCHAR x
+ENCODING 120
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR y
+ENCODING 121
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -2
+BITMAP
+a0
+a0
+a0
+40
+40
+80
+ENDCHAR
+STARTCHAR z
+ENCODING 122
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 4 0 0
+BITMAP
+e0
+40
+80
+e0
+ENDCHAR
+STARTCHAR braceleft
+ENCODING 123
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 -1
+BITMAP
+20
+40
+40
+c0
+40
+40
+20
+ENDCHAR
+STARTCHAR bar
+ENCODING 124
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 0 -1
+BITMAP
+80
+80
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR braceright
+ENCODING 125
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 -1
+BITMAP
+80
+40
+40
+60
+40
+40
+80
+ENDCHAR
+STARTCHAR asciitilde
+ENCODING 126
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 2 0 2
+BITMAP
+68
+b0
+ENDCHAR
+STARTCHAR nobreakspace
+ENCODING 160
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 0
+BITMAP
+00
+ENDCHAR
+STARTCHAR exclamdown
+ENCODING 161
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 0 -2
+BITMAP
+80
+00
+80
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR cent
+ENCODING 162
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -1
+BITMAP
+40
+60
+80
+80
+60
+40
+ENDCHAR
+STARTCHAR sterling
+ENCODING 163
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 0
+BITMAP
+20
+40
+e0
+40
+f0
+ENDCHAR
+STARTCHAR currency
+ENCODING 164
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR yen
+ENCODING 165
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+88
+50
+f8
+20
+20
+ENDCHAR
+STARTCHAR brokenbar
+ENCODING 166
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 7 0 -1
+BITMAP
+80
+80
+80
+00
+80
+80
+80
+ENDCHAR
+STARTCHAR section
+ENCODING 167
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 -1
+BITMAP
+60
+80
+c0
+a0
+60
+20
+c0
+ENDCHAR
+STARTCHAR diaeresis
+ENCODING 168
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 1 1 6
+BITMAP
+90
+ENDCHAR
+STARTCHAR copyright
+ENCODING 169
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+84
+94
+a4
+94
+84
+78
+ENDCHAR
+STARTCHAR ordfeminine
+ENCODING 170
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 5 0 1
+BITMAP
+80
+40
+c0
+00
+c0
+ENDCHAR
+STARTCHAR guillemotleft
+ENCODING 171
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 4 0 0
+BITMAP
+50
+a0
+a0
+50
+ENDCHAR
+STARTCHAR notsign
+ENCODING 172
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 4 3 1 1
+BITMAP
+f0
+10
+10
+ENDCHAR
+STARTCHAR hyphen
+ENCODING 173
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 1 0 2
+BITMAP
+c0
+ENDCHAR
+STARTCHAR registered
+ENCODING 174
+SWIDTH 840 0
+DWIDTH 7 0
+BBX 6 7 1 -1
+BITMAP
+78
+b4
+ac
+b4
+ac
+84
+78
+ENDCHAR
+STARTCHAR macron
+ENCODING 175
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 1 0 6
+BITMAP
+e0
+ENDCHAR
+STARTCHAR degree
+ENCODING 176
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 3 0 2
+BITMAP
+40
+a0
+40
+ENDCHAR
+STARTCHAR plusminus
+ENCODING 177
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 3 5 1 0
+BITMAP
+40
+e0
+40
+00
+e0
+ENDCHAR
+STARTCHAR twosuperior
+ENCODING 178
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 4 0 2
+BITMAP
+80
+40
+80
+c0
+ENDCHAR
+STARTCHAR threesuperior
+ENCODING 179
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 5 0 1
+BITMAP
+80
+40
+80
+40
+80
+ENDCHAR
+STARTCHAR acute
+ENCODING 180
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 2 0 5
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR mu
+ENCODING 181
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 5 0 -1
+BITMAP
+a0
+a0
+a0
+d0
+80
+ENDCHAR
+STARTCHAR paragraph
+ENCODING 182
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 5 7 0 -1
+BITMAP
+f8
+d0
+d0
+50
+50
+50
+50
+ENDCHAR
+STARTCHAR periodcentered
+ENCODING 183
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 1 1 0 2
+BITMAP
+80
+ENDCHAR
+STARTCHAR cedilla
+ENCODING 184
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 2 0 -2
+BITMAP
+40
+80
+ENDCHAR
+STARTCHAR onesuperior
+ENCODING 185
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 4 0 2
+BITMAP
+c0
+40
+40
+e0
+ENDCHAR
+STARTCHAR masculine
+ENCODING 186
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 5 0 1
+BITMAP
+40
+a0
+40
+00
+e0
+ENDCHAR
+STARTCHAR guillemotright
+ENCODING 187
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 4 0 0
+BITMAP
+a0
+50
+50
+a0
+ENDCHAR
+STARTCHAR onequarter
+ENCODING 188
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+44
+48
+50
+24
+4c
+9c
+04
+ENDCHAR
+STARTCHAR onehalf
+ENCODING 189
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+44
+48
+50
+28
+44
+88
+0c
+ENDCHAR
+STARTCHAR threequarters
+ENCODING 190
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 -1
+BITMAP
+80
+44
+88
+54
+ac
+5c
+04
+ENDCHAR
+STARTCHAR questiondown
+ENCODING 191
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 6 0 -1
+BITMAP
+40
+00
+40
+80
+80
+40
+ENDCHAR
+STARTCHAR Agrave
+ENCODING 192
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+40
+20
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aacute
+ENCODING 193
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+10
+20
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Acircumflex
+ENCODING 194
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Atilde
+ENCODING 195
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+28
+50
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Adiaeresis
+ENCODING 196
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+50
+00
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR Aring
+ENCODING 197
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+20
+20
+20
+50
+70
+d8
+ENDCHAR
+STARTCHAR AE
+ENCODING 198
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 5 0 0
+BITMAP
+3c
+50
+7c
+50
+dc
+ENDCHAR
+STARTCHAR Ccedilla
+ENCODING 199
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -2
+BITMAP
+70
+88
+80
+88
+70
+20
+40
+ENDCHAR
+STARTCHAR Egrave
+ENCODING 200
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+40
+20
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Eacute
+ENCODING 201
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+10
+20
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Ecircumflex
+ENCODING 202
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 8 0 0
+BITMAP
+20
+50
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Ediaeresis
+ENCODING 203
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 7 0 0
+BITMAP
+50
+00
+f0
+40
+60
+40
+f0
+ENDCHAR
+STARTCHAR Igrave
+ENCODING 204
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+80
+40
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Iacute
+ENCODING 205
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+20
+40
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Icircumflex
+ENCODING 206
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 8 0 0
+BITMAP
+40
+a0
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR Idiaeresis
+ENCODING 207
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+e0
+40
+40
+40
+e0
+ENDCHAR
+STARTCHAR ETH
+ENCODING 208
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 5 0 0
+BITMAP
+f0
+48
+e8
+48
+f0
+ENDCHAR
+STARTCHAR Ntilde
+ENCODING 209
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+28
+50
+00
+cc
+68
+58
+48
+c8
+ENDCHAR
+STARTCHAR Ograve
+ENCODING 210
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+40
+20
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Oacute
+ENCODING 211
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+10
+20
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Ocircumflex
+ENCODING 212
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+20
+50
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Otilde
+ENCODING 213
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+28
+50
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR Odiaeresis
+ENCODING 214
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 0
+BITMAP
+50
+00
+70
+88
+88
+88
+70
+ENDCHAR
+STARTCHAR multiply
+ENCODING 215
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 4 0 0
+BITMAP
+90
+60
+60
+90
+ENDCHAR
+STARTCHAR Ooblique
+ENCODING 216
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 7 0 -1
+BITMAP
+08
+70
+98
+a8
+c8
+70
+80
+ENDCHAR
+STARTCHAR Ugrave
+ENCODING 217
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+20
+10
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Uacute
+ENCODING 218
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+08
+10
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Ucircumflex
+ENCODING 219
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 8 0 0
+BITMAP
+10
+28
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Udiaeresis
+ENCODING 220
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 6 7 0 0
+BITMAP
+28
+00
+cc
+48
+48
+48
+30
+ENDCHAR
+STARTCHAR Yacute
+ENCODING 221
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 8 0 0
+BITMAP
+10
+20
+00
+d8
+50
+50
+20
+20
+ENDCHAR
+STARTCHAR THORN
+ENCODING 222
+SWIDTH 600 0
+DWIDTH 5 0
+BBX 4 5 0 0
+BITMAP
+c0
+60
+50
+60
+c0
+ENDCHAR
+STARTCHAR ssharp
+ENCODING 223
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 0 -1
+BITMAP
+60
+90
+a0
+90
+a0
+80
+ENDCHAR
+STARTCHAR agrave
+ENCODING 224
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 0 0
+BITMAP
+80
+40
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR aacute
+ENCODING 225
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 2 7 0 0
+BITMAP
+40
+80
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR acircumflex
+ENCODING 226
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR atilde
+ENCODING 227
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 4 7 0 0
+BITMAP
+50
+a0
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR adiaeresis
+ENCODING 228
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+00
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR aring
+ENCODING 229
+SWIDTH 360 0
+DWIDTH 3 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+40
+80
+40
+c0
+c0
+ENDCHAR
+STARTCHAR ae
+ENCODING 230
+SWIDTH 720 0
+DWIDTH 6 0
+BBX 5 4 0 0
+BITMAP
+90
+78
+e0
+d0
+ENDCHAR
+STARTCHAR ccedilla
+ENCODING 231
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 2 5 1 -1
+BITMAP
+40
+80
+80
+40
+80
+ENDCHAR
+STARTCHAR egrave
+ENCODING 232
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+80
+40
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR eacute
+ENCODING 233
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+40
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR ecircumflex
+ENCODING 234
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR ediaeresis
+ENCODING 235
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+00
+40
+e0
+80
+40
+ENDCHAR
+STARTCHAR igrave
+ENCODING 236
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 0
+BITMAP
+80
+40
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR iacute
+ENCODING 237
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 2 7 0 0
+BITMAP
+40
+80
+00
+80
+80
+80
+80
+ENDCHAR
+STARTCHAR icircumflex
+ENCODING 238
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 7 -1 0
+BITMAP
+40
+a0
+00
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR idiaeresis
+ENCODING 239
+SWIDTH 240 0
+DWIDTH 2 0
+BBX 3 6 -1 0
+BITMAP
+a0
+00
+40
+40
+40
+40
+ENDCHAR
+STARTCHAR eth
+ENCODING 240
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 6 0 0
+BITMAP
+a0
+40
+a0
+50
+50
+20
+ENDCHAR
+STARTCHAR ntilde
+ENCODING 241
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 0 0
+BITMAP
+50
+a0
+00
+c0
+a0
+a0
+a0
+ENDCHAR
+STARTCHAR ograve
+ENCODING 242
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+80
+40
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR oacute
+ENCODING 243
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+40
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR ocircumflex
+ENCODING 244
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR otilde
+ENCODING 245
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 0 0
+BITMAP
+50
+a0
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR odiaeresis
+ENCODING 246
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+a0
+00
+00
+40
+a0
+a0
+40
+ENDCHAR
+STARTCHAR division
+ENCODING 247
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 5 0 0
+BITMAP
+40
+00
+e0
+00
+40
+ENDCHAR
+STARTCHAR oslash
+ENCODING 248
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 -1
+BITMAP
+20
+60
+a0
+a0
+c0
+80
+ENDCHAR
+STARTCHAR ugrave
+ENCODING 249
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+80
+40
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR uacute
+ENCODING 250
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+20
+40
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR ucircumflex
+ENCODING 251
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 7 0 0
+BITMAP
+40
+a0
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR udiaeresis
+ENCODING 252
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 6 0 0
+BITMAP
+a0
+00
+a0
+a0
+a0
+60
+ENDCHAR
+STARTCHAR yacute
+ENCODING 253
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 9 0 -2
+BITMAP
+20
+40
+00
+a0
+a0
+a0
+40
+40
+80
+ENDCHAR
+STARTCHAR thorn
+ENCODING 254
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 4 7 -1 -2
+BITMAP
+c0
+60
+50
+50
+60
+40
+c0
+ENDCHAR
+STARTCHAR ydiaeresis
+ENCODING 255
+SWIDTH 480 0
+DWIDTH 4 0
+BBX 3 8 0 -2
+BITMAP
+a0
+00
+a0
+a0
+a0
+40
+40
+80
+ENDCHAR
+ENDFONT
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times8.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times8.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/rotfont/times8.h	(revision 16632)
@@ -0,0 +1,769 @@
+static unsigned char times8_0_bits[] = {
+0x00};
+static unsigned char times8_1_bits[] = {
+0x00};
+static unsigned char times8_2_bits[] = {
+0x00};
+static unsigned char times8_3_bits[] = {
+0x00};
+static unsigned char times8_4_bits[] = {
+0x00};
+static unsigned char times8_5_bits[] = {
+0x00};
+static unsigned char times8_6_bits[] = {
+0x00};
+static unsigned char times8_7_bits[] = {
+0x00};
+static unsigned char times8_8_bits[] = {
+0x00};
+static unsigned char times8_9_bits[] = {
+0x00};
+static unsigned char times8_10_bits[] = {
+0x00};
+static unsigned char times8_11_bits[] = {
+0x00};
+static unsigned char times8_12_bits[] = {
+0x00};
+static unsigned char times8_13_bits[] = {
+0x00};
+static unsigned char times8_14_bits[] = {
+0x00};
+static unsigned char times8_15_bits[] = {
+0x00};
+static unsigned char times8_16_bits[] = {
+0x00};
+static unsigned char times8_17_bits[] = {
+0x00};
+static unsigned char times8_18_bits[] = {
+0x00};
+static unsigned char times8_19_bits[] = {
+0x00};
+static unsigned char times8_20_bits[] = {
+0x00};
+static unsigned char times8_21_bits[] = {
+0x00};
+static unsigned char times8_22_bits[] = {
+0x00};
+static unsigned char times8_23_bits[] = {
+0x00};
+static unsigned char times8_24_bits[] = {
+0x00};
+static unsigned char times8_25_bits[] = {
+0x00};
+static unsigned char times8_26_bits[] = {
+0x00};
+static unsigned char times8_27_bits[] = {
+0x00};
+static unsigned char times8_28_bits[] = {
+0x00};
+static unsigned char times8_29_bits[] = {
+0x00};
+static unsigned char times8_30_bits[] = {
+0x00};
+static unsigned char times8_31_bits[] = {
+0x00};
+static unsigned char times8_32_bits[] = {
+0x00};
+static unsigned char times8_33_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x00, 0x01};
+static unsigned char times8_34_bits[] = {
+0x05, 0x05};
+static unsigned char times8_35_bits[] = {
+0x0a, 0x0f, 0x0a, 0x0f, 0x0a};
+static unsigned char times8_36_bits[] = {
+0x02, 0x06, 0x01, 0x06, 0x05, 0x03, 0x02};
+static unsigned char times8_37_bits[] = {
+0x13, 0x0b, 0x04, 0x1a, 0x19};
+static unsigned char times8_38_bits[] = {
+0x04, 0x0a, 0x06, 0x15, 0x09, 0x1e};
+static unsigned char times8_39_bits[] = {
+0x01, 0x01};
+static unsigned char times8_40_bits[] = {
+0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02};
+static unsigned char times8_41_bits[] = {
+0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times8_42_bits[] = {
+0x05, 0x02, 0x05};
+static unsigned char times8_43_bits[] = {
+0x04, 0x04, 0x0f, 0x04, 0x04};
+static unsigned char times8_44_bits[] = {
+0x02, 0x01};
+static unsigned char times8_45_bits[] = {
+0x0f};
+static unsigned char times8_46_bits[] = {
+0x01};
+static unsigned char times8_47_bits[] = {
+0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01};
+static unsigned char times8_48_bits[] = {
+0x02, 0x05, 0x05, 0x05, 0x02};
+static unsigned char times8_49_bits[] = {
+0x02, 0x03, 0x02, 0x02, 0x07};
+static unsigned char times8_50_bits[] = {
+0x03, 0x04, 0x02, 0x01, 0x07};
+static unsigned char times8_51_bits[] = {
+0x03, 0x04, 0x02, 0x04, 0x03};
+static unsigned char times8_52_bits[] = {
+0x04, 0x06, 0x05, 0x0f, 0x04};
+static unsigned char times8_53_bits[] = {
+0x07, 0x01, 0x06, 0x04, 0x03};
+static unsigned char times8_54_bits[] = {
+0x06, 0x01, 0x03, 0x05, 0x02};
+static unsigned char times8_55_bits[] = {
+0x07, 0x04, 0x02, 0x01, 0x01};
+static unsigned char times8_56_bits[] = {
+0x02, 0x05, 0x02, 0x05, 0x02};
+static unsigned char times8_57_bits[] = {
+0x02, 0x05, 0x06, 0x04, 0x03};
+static unsigned char times8_58_bits[] = {
+0x01, 0x00, 0x01};
+static unsigned char times8_59_bits[] = {
+0x02, 0x00, 0x02, 0x01};
+static unsigned char times8_60_bits[] = {
+0x04, 0x02, 0x01, 0x02, 0x04};
+static unsigned char times8_61_bits[] = {
+0x0f, 0x00, 0x0f};
+static unsigned char times8_62_bits[] = {
+0x01, 0x02, 0x04, 0x02, 0x01};
+static unsigned char times8_63_bits[] = {
+0x03, 0x04, 0x02, 0x00, 0x02};
+static unsigned char times8_64_bits[] = {
+0x1e, 0x21, 0x39, 0x25, 0x3d, 0x01, 0x1e};
+static unsigned char times8_65_bits[] = {
+0x04, 0x0a, 0x0e, 0x0a, 0x1b};
+static unsigned char times8_66_bits[] = {
+0x07, 0x0a, 0x06, 0x0a, 0x07};
+static unsigned char times8_67_bits[] = {
+0x0e, 0x11, 0x01, 0x11, 0x0e};
+static unsigned char times8_68_bits[] = {
+0x0f, 0x12, 0x12, 0x12, 0x0f};
+static unsigned char times8_69_bits[] = {
+0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_70_bits[] = {
+0x0f, 0x02, 0x0e, 0x02, 0x03};
+static unsigned char times8_71_bits[] = {
+0x0e, 0x01, 0x1d, 0x11, 0x0e};
+static unsigned char times8_72_bits[] = {
+0x33, 0x12, 0x1e, 0x12, 0x33};
+static unsigned char times8_73_bits[] = {
+0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_74_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times8_75_bits[] = {
+0x13, 0x0a, 0x06, 0x0a, 0x1b};
+static unsigned char times8_76_bits[] = {
+0x07, 0x02, 0x02, 0x0a, 0x0f};
+static unsigned char times8_77_bits[] = {
+0x77, 0x36, 0x2a, 0x2a, 0x63};
+static unsigned char times8_78_bits[] = {
+0x33, 0x16, 0x16, 0x1a, 0x13};
+static unsigned char times8_79_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_80_bits[] = {
+0x0f, 0x12, 0x0e, 0x02, 0x03};
+static unsigned char times8_81_bits[] = {
+0x0e, 0x11, 0x11, 0x11, 0x0e, 0x04, 0x08};
+static unsigned char times8_82_bits[] = {
+0x07, 0x0a, 0x06, 0x0a, 0x1b};
+static unsigned char times8_83_bits[] = {
+0x0e, 0x01, 0x06, 0x08, 0x07};
+static unsigned char times8_84_bits[] = {
+0x1f, 0x15, 0x04, 0x04, 0x0e};
+static unsigned char times8_85_bits[] = {
+0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_86_bits[] = {
+0x1b, 0x0a, 0x0a, 0x04, 0x04};
+static unsigned char times8_87_bits[] = {
+0xcb, 0x4a, 0x52, 0x5a, 0x34};
+static unsigned char times8_88_bits[] = {
+0x33, 0x0c, 0x0c, 0x12, 0x33};
+static unsigned char times8_89_bits[] = {
+0x1b, 0x0a, 0x04, 0x04, 0x0e};
+static unsigned char times8_90_bits[] = {
+0x0f, 0x05, 0x02, 0x09, 0x0f};
+static unsigned char times8_91_bits[] = {
+0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03};
+static unsigned char times8_92_bits[] = {
+0x01, 0x01, 0x02, 0x02, 0x02, 0x04, 0x04};
+static unsigned char times8_93_bits[] = {
+0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03};
+static unsigned char times8_94_bits[] = {
+0x02, 0x05};
+static unsigned char times8_95_bits[] = {
+0x0f};
+static unsigned char times8_96_bits[] = {
+0x01, 0x01};
+static unsigned char times8_97_bits[] = {
+0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_98_bits[] = {
+0x01, 0x03, 0x05, 0x05, 0x03};
+static unsigned char times8_99_bits[] = {
+0x02, 0x01, 0x01, 0x02};
+static unsigned char times8_100_bits[] = {
+0x04, 0x06, 0x05, 0x05, 0x06};
+static unsigned char times8_101_bits[] = {
+0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_102_bits[] = {
+0x04, 0x02, 0x07, 0x02, 0x02};
+static unsigned char times8_103_bits[] = {
+0x0e, 0x05, 0x02, 0x05, 0x02};
+static unsigned char times8_104_bits[] = {
+0x01, 0x03, 0x05, 0x05, 0x05};
+static unsigned char times8_105_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_106_bits[] = {
+0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01};
+static unsigned char times8_107_bits[] = {
+0x01, 0x05, 0x03, 0x03, 0x05};
+static unsigned char times8_108_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_109_bits[] = {
+0x0b, 0x15, 0x15, 0x15};
+static unsigned char times8_110_bits[] = {
+0x03, 0x05, 0x05, 0x05};
+static unsigned char times8_111_bits[] = {
+0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_112_bits[] = {
+0x03, 0x05, 0x05, 0x03, 0x01, 0x01};
+static unsigned char times8_113_bits[] = {
+0x06, 0x05, 0x05, 0x06, 0x04, 0x04};
+static unsigned char times8_114_bits[] = {
+0x05, 0x03, 0x01, 0x01};
+static unsigned char times8_115_bits[] = {
+0x03, 0x01, 0x02, 0x03};
+static unsigned char times8_116_bits[] = {
+0x01, 0x03, 0x01, 0x01, 0x02};
+static unsigned char times8_117_bits[] = {
+0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_118_bits[] = {
+0x05, 0x05, 0x05, 0x02};
+static unsigned char times8_119_bits[] = {
+0x15, 0x15, 0x15, 0x0a};
+static unsigned char times8_120_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char times8_121_bits[] = {
+0x05, 0x05, 0x05, 0x02, 0x02, 0x01};
+static unsigned char times8_122_bits[] = {
+0x07, 0x02, 0x01, 0x07};
+static unsigned char times8_123_bits[] = {
+0x04, 0x02, 0x02, 0x03, 0x02, 0x02, 0x04};
+static unsigned char times8_124_bits[] = {
+0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_125_bits[] = {
+0x01, 0x02, 0x02, 0x06, 0x02, 0x02, 0x01};
+static unsigned char times8_126_bits[] = {
+0x16, 0x0d};
+static unsigned char times8_127_bits[] = {
+0x00};
+static unsigned char times8_128_bits[] = {
+0x00};
+static unsigned char times8_129_bits[] = {
+0x00};
+static unsigned char times8_130_bits[] = {
+0x00};
+static unsigned char times8_131_bits[] = {
+0x00};
+static unsigned char times8_132_bits[] = {
+0x00};
+static unsigned char times8_133_bits[] = {
+0x00};
+static unsigned char times8_134_bits[] = {
+0x00};
+static unsigned char times8_135_bits[] = {
+0x00};
+static unsigned char times8_136_bits[] = {
+0x00};
+static unsigned char times8_137_bits[] = {
+0x00};
+static unsigned char times8_138_bits[] = {
+0x00};
+static unsigned char times8_139_bits[] = {
+0x00};
+static unsigned char times8_140_bits[] = {
+0x00};
+static unsigned char times8_141_bits[] = {
+0x00};
+static unsigned char times8_142_bits[] = {
+0x00};
+static unsigned char times8_143_bits[] = {
+0x00};
+static unsigned char times8_144_bits[] = {
+0x00};
+static unsigned char times8_145_bits[] = {
+0x00};
+static unsigned char times8_146_bits[] = {
+0x00};
+static unsigned char times8_147_bits[] = {
+0x00};
+static unsigned char times8_148_bits[] = {
+0x00};
+static unsigned char times8_149_bits[] = {
+0x00};
+static unsigned char times8_150_bits[] = {
+0x00};
+static unsigned char times8_151_bits[] = {
+0x00};
+static unsigned char times8_152_bits[] = {
+0x00};
+static unsigned char times8_153_bits[] = {
+0x00};
+static unsigned char times8_154_bits[] = {
+0x00};
+static unsigned char times8_155_bits[] = {
+0x00};
+static unsigned char times8_156_bits[] = {
+0x00};
+static unsigned char times8_157_bits[] = {
+0x00};
+static unsigned char times8_158_bits[] = {
+0x00};
+static unsigned char times8_159_bits[] = {
+0x00};
+static unsigned char times8_160_bits[] = {
+0x00};
+static unsigned char times8_161_bits[] = {
+0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_162_bits[] = {
+0x02, 0x06, 0x01, 0x01, 0x06, 0x02};
+static unsigned char times8_163_bits[] = {
+0x04, 0x02, 0x07, 0x02, 0x0f};
+static unsigned char times8_164_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char times8_165_bits[] = {
+0x11, 0x0a, 0x1f, 0x04, 0x04};
+static unsigned char times8_166_bits[] = {
+0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01};
+static unsigned char times8_167_bits[] = {
+0x06, 0x01, 0x03, 0x05, 0x06, 0x04, 0x03};
+static unsigned char times8_168_bits[] = {
+0x09};
+static unsigned char times8_169_bits[] = {
+0x1e, 0x21, 0x29, 0x25, 0x29, 0x21, 0x1e};
+static unsigned char times8_170_bits[] = {
+0x01, 0x02, 0x03, 0x00, 0x03};
+static unsigned char times8_171_bits[] = {
+0x0a, 0x05, 0x05, 0x0a};
+static unsigned char times8_172_bits[] = {
+0x0f, 0x08, 0x08};
+static unsigned char times8_173_bits[] = {
+0x03};
+static unsigned char times8_174_bits[] = {
+0x1e, 0x2d, 0x35, 0x2d, 0x35, 0x21, 0x1e};
+static unsigned char times8_175_bits[] = {
+0x07};
+static unsigned char times8_176_bits[] = {
+0x02, 0x05, 0x02};
+static unsigned char times8_177_bits[] = {
+0x02, 0x07, 0x02, 0x00, 0x07};
+static unsigned char times8_178_bits[] = {
+0x01, 0x02, 0x01, 0x03};
+static unsigned char times8_179_bits[] = {
+0x01, 0x02, 0x01, 0x02, 0x01};
+static unsigned char times8_180_bits[] = {
+0x02, 0x01};
+static unsigned char times8_181_bits[] = {
+0x05, 0x05, 0x05, 0x0b, 0x01};
+static unsigned char times8_182_bits[] = {
+0x1f, 0x0b, 0x0b, 0x0a, 0x0a, 0x0a, 0x0a};
+static unsigned char times8_183_bits[] = {
+0x01};
+static unsigned char times8_184_bits[] = {
+0x02, 0x01};
+static unsigned char times8_185_bits[] = {
+0x03, 0x02, 0x02, 0x07};
+static unsigned char times8_186_bits[] = {
+0x02, 0x05, 0x02, 0x00, 0x07};
+static unsigned char times8_187_bits[] = {
+0x05, 0x0a, 0x0a, 0x05};
+static unsigned char times8_188_bits[] = {
+0x22, 0x12, 0x0a, 0x24, 0x32, 0x39, 0x20};
+static unsigned char times8_189_bits[] = {
+0x22, 0x12, 0x0a, 0x14, 0x22, 0x11, 0x30};
+static unsigned char times8_190_bits[] = {
+0x01, 0x22, 0x11, 0x2a, 0x35, 0x3a, 0x20};
+static unsigned char times8_191_bits[] = {
+0x02, 0x00, 0x02, 0x01, 0x01, 0x02};
+static unsigned char times8_192_bits[] = {
+0x02, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_193_bits[] = {
+0x08, 0x04, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_194_bits[] = {
+0x04, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_195_bits[] = {
+0x14, 0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_196_bits[] = {
+0x0a, 0x00, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_197_bits[] = {
+0x04, 0x0a, 0x04, 0x04, 0x04, 0x0a, 0x0e, 0x1b};
+static unsigned char times8_198_bits[] = {
+0x3c, 0x0a, 0x3e, 0x0a, 0x3b};
+static unsigned char times8_199_bits[] = {
+0x0e, 0x11, 0x01, 0x11, 0x0e, 0x04, 0x02};
+static unsigned char times8_200_bits[] = {
+0x02, 0x04, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_201_bits[] = {
+0x08, 0x04, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_202_bits[] = {
+0x04, 0x0a, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_203_bits[] = {
+0x0a, 0x00, 0x0f, 0x02, 0x06, 0x02, 0x0f};
+static unsigned char times8_204_bits[] = {
+0x01, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_205_bits[] = {
+0x04, 0x02, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_206_bits[] = {
+0x02, 0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_207_bits[] = {
+0x05, 0x00, 0x07, 0x02, 0x02, 0x02, 0x07};
+static unsigned char times8_208_bits[] = {
+0x0f, 0x12, 0x17, 0x12, 0x0f};
+static unsigned char times8_209_bits[] = {
+0x14, 0x0a, 0x00, 0x33, 0x16, 0x1a, 0x12, 0x13};
+static unsigned char times8_210_bits[] = {
+0x02, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_211_bits[] = {
+0x08, 0x04, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_212_bits[] = {
+0x04, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_213_bits[] = {
+0x14, 0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_214_bits[] = {
+0x0a, 0x00, 0x0e, 0x11, 0x11, 0x11, 0x0e};
+static unsigned char times8_215_bits[] = {
+0x09, 0x06, 0x06, 0x09};
+static unsigned char times8_216_bits[] = {
+0x10, 0x0e, 0x19, 0x15, 0x13, 0x0e, 0x01};
+static unsigned char times8_217_bits[] = {
+0x04, 0x08, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_218_bits[] = {
+0x10, 0x08, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_219_bits[] = {
+0x08, 0x14, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_220_bits[] = {
+0x14, 0x00, 0x33, 0x12, 0x12, 0x12, 0x0c};
+static unsigned char times8_221_bits[] = {
+0x08, 0x04, 0x00, 0x1b, 0x0a, 0x0a, 0x04, 0x04};
+static unsigned char times8_222_bits[] = {
+0x03, 0x06, 0x0a, 0x06, 0x03};
+static unsigned char times8_223_bits[] = {
+0x06, 0x09, 0x05, 0x09, 0x05, 0x01};
+static unsigned char times8_224_bits[] = {
+0x01, 0x02, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_225_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_226_bits[] = {
+0x02, 0x05, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_227_bits[] = {
+0x0a, 0x05, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_228_bits[] = {
+0x05, 0x00, 0x00, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_229_bits[] = {
+0x02, 0x05, 0x02, 0x01, 0x02, 0x03, 0x03};
+static unsigned char times8_230_bits[] = {
+0x09, 0x1e, 0x07, 0x0b};
+static unsigned char times8_231_bits[] = {
+0x02, 0x01, 0x01, 0x02, 0x01};
+static unsigned char times8_232_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_233_bits[] = {
+0x04, 0x02, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_234_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_235_bits[] = {
+0x05, 0x00, 0x00, 0x02, 0x07, 0x01, 0x02};
+static unsigned char times8_236_bits[] = {
+0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_237_bits[] = {
+0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01};
+static unsigned char times8_238_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x02, 0x02, 0x02};
+static unsigned char times8_239_bits[] = {
+0x05, 0x00, 0x02, 0x02, 0x02, 0x02};
+static unsigned char times8_240_bits[] = {
+0x05, 0x02, 0x05, 0x0a, 0x0a, 0x04};
+static unsigned char times8_241_bits[] = {
+0x0a, 0x05, 0x00, 0x03, 0x05, 0x05, 0x05};
+static unsigned char times8_242_bits[] = {
+0x01, 0x02, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_243_bits[] = {
+0x04, 0x02, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_244_bits[] = {
+0x02, 0x05, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_245_bits[] = {
+0x0a, 0x05, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_246_bits[] = {
+0x05, 0x00, 0x00, 0x02, 0x05, 0x05, 0x02};
+static unsigned char times8_247_bits[] = {
+0x02, 0x00, 0x07, 0x00, 0x02};
+static unsigned char times8_248_bits[] = {
+0x04, 0x06, 0x05, 0x05, 0x03, 0x01};
+static unsigned char times8_249_bits[] = {
+0x01, 0x02, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_250_bits[] = {
+0x04, 0x02, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_251_bits[] = {
+0x02, 0x05, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_252_bits[] = {
+0x05, 0x00, 0x05, 0x05, 0x05, 0x06};
+static unsigned char times8_253_bits[] = {
+0x04, 0x02, 0x00, 0x05, 0x05, 0x05, 0x02, 0x02, 0x01};
+static unsigned char times8_254_bits[] = {
+0x03, 0x06, 0x0a, 0x0a, 0x06, 0x02, 0x03};
+static unsigned char times8_255_bits[] = {
+0x05, 0x00, 0x05, 0x05, 0x05, 0x02, 0x02, 0x01};
+static RotFont times8font[] = {
+{5, 1, 1, times8_0_bits},
+{5, 1, 1, times8_1_bits},
+{5, 1, 1, times8_2_bits},
+{5, 1, 1, times8_3_bits},
+{5, 1, 1, times8_4_bits},
+{5, 1, 1, times8_5_bits},
+{5, 1, 1, times8_6_bits},
+{5, 1, 1, times8_7_bits},
+{5, 1, 1, times8_8_bits},
+{5, 1, 1, times8_9_bits},
+{5, 1, 1, times8_10_bits},
+{5, 1, 1, times8_11_bits},
+{5, 1, 1, times8_12_bits},
+{5, 1, 1, times8_13_bits},
+{5, 1, 1, times8_14_bits},
+{5, 1, 1, times8_15_bits},
+{5, 1, 1, times8_16_bits},
+{5, 1, 1, times8_17_bits},
+{5, 1, 1, times8_18_bits},
+{5, 1, 1, times8_19_bits},
+{5, 1, 1, times8_20_bits},
+{5, 1, 1, times8_21_bits},
+{5, 1, 1, times8_22_bits},
+{5, 1, 1, times8_23_bits},
+{5, 1, 1, times8_24_bits},
+{5, 1, 1, times8_25_bits},
+{5, 1, 1, times8_26_bits},
+{5, 1, 1, times8_27_bits},
+{5, 1, 1, times8_28_bits},
+{5, 1, 1, times8_29_bits},
+{5, 1, 1, times8_30_bits},
+{5, 1, 1, times8_31_bits},
+{4, 1, 1, times8_32_bits},
+{1, 6, 6, times8_33_bits},
+{3, 2, 5, times8_34_bits},
+{4, 5, 5, times8_35_bits},
+{3, 7, 6, times8_36_bits},
+{5, 5, 5, times8_37_bits},
+{5, 6, 6, times8_38_bits},
+{1, 2, 6, times8_39_bits},
+{2, 7, 6, times8_40_bits},
+{2, 7, 6, times8_41_bits},
+{3, 3, 5, times8_42_bits},
+{4, 5, 5, times8_43_bits},
+{2, 2, 1, times8_44_bits},
+{4, 1, 3, times8_45_bits},
+{1, 1, 1, times8_46_bits},
+{3, 7, 6, times8_47_bits},
+{3, 5, 5, times8_48_bits},
+{3, 5, 5, times8_49_bits},
+{3, 5, 5, times8_50_bits},
+{3, 5, 5, times8_51_bits},
+{4, 5, 5, times8_52_bits},
+{3, 5, 5, times8_53_bits},
+{3, 5, 5, times8_54_bits},
+{3, 5, 5, times8_55_bits},
+{3, 5, 5, times8_56_bits},
+{3, 5, 5, times8_57_bits},
+{1, 3, 3, times8_58_bits},
+{2, 4, 3, times8_59_bits},
+{3, 5, 5, times8_60_bits},
+{4, 3, 4, times8_61_bits},
+{3, 5, 5, times8_62_bits},
+{3, 5, 5, times8_63_bits},
+{6, 7, 6, times8_64_bits},
+{5, 5, 5, times8_65_bits},
+{4, 5, 5, times8_66_bits},
+{5, 5, 5, times8_67_bits},
+{5, 5, 5, times8_68_bits},
+{4, 5, 5, times8_69_bits},
+{4, 5, 5, times8_70_bits},
+{5, 5, 5, times8_71_bits},
+{6, 5, 5, times8_72_bits},
+{3, 5, 5, times8_73_bits},
+{2, 5, 5, times8_74_bits},
+{5, 5, 5, times8_75_bits},
+{4, 5, 5, times8_76_bits},
+{7, 5, 5, times8_77_bits},
+{6, 5, 5, times8_78_bits},
+{5, 5, 5, times8_79_bits},
+{5, 5, 5, times8_80_bits},
+{5, 7, 5, times8_81_bits},
+{5, 5, 5, times8_82_bits},
+{4, 5, 5, times8_83_bits},
+{5, 5, 5, times8_84_bits},
+{6, 5, 5, times8_85_bits},
+{5, 5, 5, times8_86_bits},
+{8, 5, 5, times8_87_bits},
+{6, 5, 5, times8_88_bits},
+{5, 5, 5, times8_89_bits},
+{4, 5, 5, times8_90_bits},
+{2, 7, 6, times8_91_bits},
+{3, 7, 6, times8_92_bits},
+{2, 7, 6, times8_93_bits},
+{3, 2, 6, times8_94_bits},
+{4, 1, 0, times8_95_bits},
+{1, 2, 6, times8_96_bits},
+{2, 4, 4, times8_97_bits},
+{3, 5, 5, times8_98_bits},
+{2, 4, 4, times8_99_bits},
+{3, 5, 5, times8_100_bits},
+{3, 4, 4, times8_101_bits},
+{3, 5, 5, times8_102_bits},
+{4, 5, 4, times8_103_bits},
+{3, 5, 5, times8_104_bits},
+{1, 6, 6, times8_105_bits},
+{2, 8, 6, times8_106_bits},
+{3, 5, 5, times8_107_bits},
+{1, 5, 5, times8_108_bits},
+{5, 4, 4, times8_109_bits},
+{3, 4, 4, times8_110_bits},
+{3, 4, 4, times8_111_bits},
+{3, 6, 4, times8_112_bits},
+{3, 6, 4, times8_113_bits},
+{3, 4, 4, times8_114_bits},
+{2, 4, 4, times8_115_bits},
+{2, 5, 5, times8_116_bits},
+{3, 4, 4, times8_117_bits},
+{3, 4, 4, times8_118_bits},
+{5, 4, 4, times8_119_bits},
+{4, 4, 4, times8_120_bits},
+{3, 6, 4, times8_121_bits},
+{3, 4, 4, times8_122_bits},
+{3, 7, 6, times8_123_bits},
+{1, 7, 6, times8_124_bits},
+{3, 7, 6, times8_125_bits},
+{5, 2, 4, times8_126_bits},
+{5, 1, 1, times8_127_bits},
+{5, 1, 1, times8_128_bits},
+{5, 1, 1, times8_129_bits},
+{5, 1, 1, times8_130_bits},
+{5, 1, 1, times8_131_bits},
+{5, 1, 1, times8_132_bits},
+{5, 1, 1, times8_133_bits},
+{5, 1, 1, times8_134_bits},
+{5, 1, 1, times8_135_bits},
+{5, 1, 1, times8_136_bits},
+{5, 1, 1, times8_137_bits},
+{5, 1, 1, times8_138_bits},
+{5, 1, 1, times8_139_bits},
+{5, 1, 1, times8_140_bits},
+{5, 1, 1, times8_141_bits},
+{5, 1, 1, times8_142_bits},
+{5, 1, 1, times8_143_bits},
+{5, 1, 1, times8_144_bits},
+{5, 1, 1, times8_145_bits},
+{5, 1, 1, times8_146_bits},
+{5, 1, 1, times8_147_bits},
+{5, 1, 1, times8_148_bits},
+{5, 1, 1, times8_149_bits},
+{5, 1, 1, times8_150_bits},
+{5, 1, 1, times8_151_bits},
+{5, 1, 1, times8_152_bits},
+{5, 1, 1, times8_153_bits},
+{5, 1, 1, times8_154_bits},
+{5, 1, 1, times8_155_bits},
+{5, 1, 1, times8_156_bits},
+{5, 1, 1, times8_157_bits},
+{5, 1, 1, times8_158_bits},
+{5, 1, 1, times8_159_bits},
+{1, 1, 1, times8_160_bits},
+{1, 7, 5, times8_161_bits},
+{3, 6, 5, times8_162_bits},
+{4, 5, 5, times8_163_bits},
+{4, 4, 4, times8_164_bits},
+{5, 5, 5, times8_165_bits},
+{1, 7, 6, times8_166_bits},
+{3, 7, 6, times8_167_bits},
+{4, 1, 7, times8_168_bits},
+{6, 7, 6, times8_169_bits},
+{2, 5, 6, times8_170_bits},
+{4, 4, 4, times8_171_bits},
+{4, 3, 4, times8_172_bits},
+{2, 1, 3, times8_173_bits},
+{6, 7, 6, times8_174_bits},
+{3, 1, 7, times8_175_bits},
+{3, 3, 5, times8_176_bits},
+{3, 5, 5, times8_177_bits},
+{2, 4, 6, times8_178_bits},
+{2, 5, 6, times8_179_bits},
+{2, 2, 7, times8_180_bits},
+{4, 5, 4, times8_181_bits},
+{5, 7, 6, times8_182_bits},
+{1, 1, 3, times8_183_bits},
+{2, 2, 0, times8_184_bits},
+{3, 4, 6, times8_185_bits},
+{3, 5, 6, times8_186_bits},
+{4, 4, 4, times8_187_bits},
+{6, 7, 6, times8_188_bits},
+{6, 7, 6, times8_189_bits},
+{6, 7, 6, times8_190_bits},
+{2, 6, 5, times8_191_bits},
+{5, 8, 8, times8_192_bits},
+{5, 8, 8, times8_193_bits},
+{5, 8, 8, times8_194_bits},
+{5, 8, 8, times8_195_bits},
+{5, 7, 7, times8_196_bits},
+{5, 8, 8, times8_197_bits},
+{6, 5, 5, times8_198_bits},
+{5, 7, 5, times8_199_bits},
+{4, 8, 8, times8_200_bits},
+{4, 8, 8, times8_201_bits},
+{4, 8, 8, times8_202_bits},
+{4, 7, 7, times8_203_bits},
+{3, 8, 8, times8_204_bits},
+{3, 8, 8, times8_205_bits},
+{3, 8, 8, times8_206_bits},
+{3, 7, 7, times8_207_bits},
+{5, 5, 5, times8_208_bits},
+{6, 8, 8, times8_209_bits},
+{5, 8, 8, times8_210_bits},
+{5, 8, 8, times8_211_bits},
+{5, 8, 8, times8_212_bits},
+{5, 8, 8, times8_213_bits},
+{5, 7, 7, times8_214_bits},
+{4, 4, 4, times8_215_bits},
+{5, 7, 6, times8_216_bits},
+{6, 8, 8, times8_217_bits},
+{6, 8, 8, times8_218_bits},
+{6, 8, 8, times8_219_bits},
+{6, 7, 7, times8_220_bits},
+{5, 8, 8, times8_221_bits},
+{4, 5, 5, times8_222_bits},
+{4, 6, 5, times8_223_bits},
+{2, 7, 7, times8_224_bits},
+{2, 7, 7, times8_225_bits},
+{3, 7, 7, times8_226_bits},
+{4, 7, 7, times8_227_bits},
+{3, 7, 7, times8_228_bits},
+{3, 7, 7, times8_229_bits},
+{5, 4, 4, times8_230_bits},
+{2, 5, 4, times8_231_bits},
+{3, 7, 7, times8_232_bits},
+{3, 7, 7, times8_233_bits},
+{3, 7, 7, times8_234_bits},
+{3, 7, 7, times8_235_bits},
+{2, 7, 7, times8_236_bits},
+{2, 7, 7, times8_237_bits},
+{3, 7, 7, times8_238_bits},
+{3, 6, 6, times8_239_bits},
+{4, 6, 6, times8_240_bits},
+{4, 7, 7, times8_241_bits},
+{3, 7, 7, times8_242_bits},
+{3, 7, 7, times8_243_bits},
+{3, 7, 7, times8_244_bits},
+{4, 7, 7, times8_245_bits},
+{3, 7, 7, times8_246_bits},
+{3, 5, 5, times8_247_bits},
+{3, 6, 5, times8_248_bits},
+{3, 7, 7, times8_249_bits},
+{3, 7, 7, times8_250_bits},
+{3, 7, 7, times8_251_bits},
+{3, 6, 6, times8_252_bits},
+{3, 9, 7, times8_253_bits},
+{4, 7, 5, times8_254_bits},
+{3, 8, 6, times8_255_bits}};
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/DrawRotString.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/DrawRotString.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/DrawRotString.c	(revision 16632)
@@ -0,0 +1,242 @@
+# include <kapa_internal.h>
+
+# define NROTCHARS 256
+# define XPROC(x,y) (scale*(cs*((x) - x0) - sn*((y) - y0)) + X0)
+# define YPROC(x,y) (scale*(cs*((y) - y0) + sn*((x) - x0)) + Y0)
+# define NEARINT(x) ((x < 0) ? ((int)(x - 0.5)) : ((int)(x + 0.5)))
+  
+static Display *RotDisplay;
+static Window   RotWindow;
+static GC       RotGC;
+static unsigned long RotForeground;
+static unsigned long RotBackground;
+
+int DrawRotTextInit (Display *display, Window window, GC gc, unsigned long fore, unsigned long back) {
+
+    RotDisplay = display;
+    RotWindow  = window;
+    RotGC      = gc;
+    RotForeground = fore;
+    RotBackground = back;
+
+    return (TRUE);
+}
+
+int DrawRotText (int x, int y, char *string, int pos, double angle) {
+
+  unsigned char *bitmap;
+  char *currentname, basename[64]; 
+  int i, dy, dx, N, X, Y, code;
+  int dX, Xoff, dY, Yoff, YoffBase;
+  int currentsize, basesize;
+  double cs, sn, currentscale;
+  RotFont *currentfont;
+
+  currentname = GetRotFont (&currentsize);
+  currentfont = GetRotFontData (&currentscale);
+  strcpy (basename, currentname);
+  basesize = currentsize;
+
+  /* strip leading WHITESPACE */
+  stripwhite (string);
+  if (*string == 0) return (FALSE);
+  
+  /* compute string length */
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  dX = RotStrlen (string);
+  dY = currentfont[65].ascent;
+
+  /* apply appropriate offset */
+  Xoff = Yoff = 0;
+  switch (pos) {
+  case 0: Xoff =     -dX; Yoff = dY; break;
+  case 1: Xoff = -0.5*dX; Yoff = dY; break;
+  case 2: Xoff =       0; Yoff = dY; break;
+  case 3: Xoff =     -dX; Yoff = 0.5*dY; break;
+  case 4: Xoff = -0.5*dX; Yoff = 0.5*dY; break;
+  case 5: Xoff =       0; Yoff = 0.5*dY; break;
+  case 6: Xoff =     -dX; Yoff = 0; break;
+  case 7: Xoff = -0.5*dX; Yoff = 0; break;
+  case 8: Xoff =       0; Yoff = 0; break;
+  }
+
+  code = FALSE;
+
+  YoffBase = Yoff;
+  /* draw characters one-by-one */
+  for (i = 0; i < strlen(string); i++) {
+    N = (int)(string[i]);
+    if ((N < 0) || (N >= NROTCHARS)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) {
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	Yoff -= 0.5*currentscale*dY;
+	continue;
+      }
+      if (N == 95) { 
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	Yoff += 0.5*currentscale*dY;
+	continue;
+      }
+      if (N == 124) {
+	SetRotFont (currentname, basesize);
+	currentfont = GetRotFontData (&currentscale);
+	Yoff = YoffBase;
+	continue;
+      }
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) {
+	if (string[i+1] == 'h') {
+	  SetRotFont ("helvetica", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 't') {
+	  SetRotFont ("times", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 'c') {
+	  SetRotFont ("courier", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 's') {
+	  SetRotFont ("symbol", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+
+    bitmap = currentfont[N].bits;
+    dx = currentfont[N].dx;
+    dy = currentfont[N].dy;
+    X = x + (int)(Xoff*cs - Yoff*sn) + (int)(currentscale*currentfont[N].ascent*sn);
+    Y = y + (int)(Xoff*sn + Yoff*cs) - (int)(currentscale*currentfont[N].ascent*cs);
+    DrawRotBitmap (X, Y, dx, dy, bitmap, TRUE, angle, currentscale);
+    Xoff += 1 + (int)(currentscale*dx + 0.5);
+  }
+  SetRotFont (basename, basesize);
+  return (TRUE);
+}
+
+int DrawRotBitmap (int x, int y, int dx, int dy, unsigned char *bitmap, int mode, double angle, double scale) {
+
+  int ii, jj, byte_line, byte, bit, flag;
+  unsigned long int fore, back;
+  double i, j, cs, sn, rscale, tmp;
+  int X, Y, X0, X1, X2, Y0, Y1, Y2, x0, y0;
+
+  if (mode) {
+    fore = RotForeground;
+    back = RotBackground;
+  } else {
+    fore = RotBackground;
+    back = RotForeground;
+  } 
+    
+  byte_line = (int) ((dx + 7) / 8);
+
+  cs = cos(angle*RAD_DEG);  sn = sin(angle*RAD_DEG);
+  rscale = 1.0 / scale;
+
+  X0 = 0;
+  Y0 = 0;
+  x0 = 0;
+  y0 = 0;
+
+  X2 = X1 = XPROC (0,0);
+  Y2 = Y1 = YPROC (0,0);
+
+  X = XPROC (dx,0);
+  Y = YPROC (dx,0);
+# ifdef DRAWBOXES
+  XDrawLine (RotDisplay, RotWindow, RotGC, x+X, y+Y, x+X1, y+Y1);
+  Xt = X;
+  Yt = Y;
+# endif
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+
+  X = XPROC (dx,dy);
+  Y = YPROC (dx,dy);
+# ifdef DRAWBOXES
+  XDrawLine (RotDisplay, RotWindow, RotGC, x+X, y+Y, x+Xt, y+Yt);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  X = XPROC (0,dy);
+  Y = YPROC (0,dy);
+# ifdef DRAWBOXES
+  XDrawLine (RotDisplay, RotWindow, RotGC, x+X, y+Y, x+Xt, y+Yt);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  XSetForeground (RotDisplay, RotGC, fore);
+  if (scale > 1) {
+    for (i = X1; i <= X2; i+=1) {
+      for (j = Y1; j <= Y2; j+=1) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	/* fprintf (stderr, "%d %d  %d %d\n", i, j, ii, jj);  */
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	if (flag) XDrawPoint (RotDisplay, RotWindow, RotGC, x + i, y + j);
+      }
+    }
+  } else {
+    for (i = X1; i <= X2; i+=scale) {
+      for (j = Y1; j <= Y2; j+=scale) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	/* fprintf (stderr, "%d %d  %d %d\n", i, j, ii, jj);  */
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	/* fprintf (stderr, "%2d %2d  %3d %3d  %1d  %f  %f\n", i, j, ii, jj, flag,
+	   rscale*(cs*(i - X0) + sn*(j - Y0)) + x0, rscale*(cs*(j - Y0) - sn*(i - X0)) + y0);  */
+	if (flag) XDrawPoint (RotDisplay, RotWindow, RotGC, x + i, y + j);
+      }
+    }
+# if (0)
+    for (i = 0; i < dx; i++) {
+      for (j = 0; j < dy; j++) {
+	tmp = scale*(cs*(i - x0) - sn*(j - y0)) + X0; ii = NEARINT (tmp);
+	tmp = scale*(cs*(j - y0) + sn*(i - x0)) + Y0; jj = NEARINT (tmp);
+	/* if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue; */
+	byte = byte_line * j + (i / 8);
+	bit = i % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	fprintf (stderr, "%2d %2d  %3d %3d  %1d  %f  %f\n", i, j, ii, jj, flag, 
+		 scale*(cs*(i - x0) - sn*(j - y0)) + X0, scale*(cs*(j - y0) + sn*(i - x0)) + Y0); 
+	if (flag) XDrawPoint (RotDisplay, RotWindow, RotGC, x + ii, y + jj);
+      }
+    }
+# endif
+  }
+  XSetForeground (RotDisplay, RotGC, RotForeground);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/IOfuncs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/IOfuncs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/IOfuncs.c	(revision 16632)
@@ -0,0 +1,169 @@
+# include <kapa_internal.h>
+
+/** these function expect to operate with a BLOCKing socket **/
+
+/* why is this not defined in stdarg.h for linux/x64? */
+int vsscanf(const char *str, const char *format, va_list ap);
+
+int KiiSendData (int device, char *data, int Nbytes) {
+
+  KiiSendCommand (device, 16, "LEN: %11d", Nbytes);
+  write (device, data, Nbytes);
+  return (TRUE);
+} 
+
+char *KiiRecvData (int device) {
+
+  int status, Nbytes;
+  char *data, buffer[20];
+
+  /* read 16 bytes: LEN (length) */
+  status = read (device, buffer, 16);
+  buffer[16] = 0;
+
+  /* find the message length, allocate space */
+  sscanf (buffer, "%*s %d", &Nbytes);
+  ALLOCATE (data, char, Nbytes + 1);
+  read (device, data, Nbytes);
+  data[Nbytes] = 0;
+
+  return (data);
+} 
+
+/* send a message of arbitrary size, sending the size first */
+int KiiSendMessage (int device, char *format, ...) {
+
+  int Nbyte, status;
+  char tmp;
+  va_list argp;  
+
+  va_start (argp, format);
+  Nbyte = vsnprintf (&tmp, 0, format, argp);
+  va_end (argp);
+
+  if (!Nbyte) return (FALSE);
+
+  /* the message may contain up to 99,999,999,999 bytes (100MB) */
+  va_start (argp, format);
+  KiiSendCommand (device, 16, "LEN: %11d", Nbyte);
+  status = KiiSendCommandV (device, Nbyte, format, argp);
+  va_end (argp);
+
+  return (status);
+}
+
+/* scan a message of arbitrary size, accepting the size first */
+int KiiScanMessage (int device, char *format, ...) {
+
+  int Nbytes, status;
+  char buffer[20], *message;
+  va_list argp;  
+
+  /* read 16 bytes: LEN (length) */
+  status = read (device, buffer, 16);
+  buffer[16] = 0;
+  if (status != 16) fprintf (stderr, "dropped message length\n");
+
+  /* find the message length, allocate space */
+  sscanf (buffer, "%*s %d", &Nbytes);
+  ALLOCATE (message, char, Nbytes + 1);
+
+  /* read Nbytes from the device */
+  status = read (device, message, Nbytes);
+  if (status != Nbytes) fprintf (stderr, "Kii/Kapa comm error\n");
+  message[status] = 0;
+  /* make the string easy to parse */
+
+  // fprintf (stderr, "recv: %s\n", message);
+
+  /* scan the incoming message */
+  va_start (argp, format);
+  Nbytes = vsscanf (message, format, argp);
+  va_end (argp);
+
+  free (message);
+
+  return (status);
+}
+
+/* send a command of fixed size */
+int KiiSendCommand (int device, int length, char *format, ...) {
+
+  int status;
+  va_list argp;  
+
+  va_start (argp, format);
+  status = KiiSendCommandV (device, length, format, argp);
+  va_end (argp);
+
+  return (status);
+}
+  
+int KiiSendCommandV (int device, int length, char *format, va_list argp) {
+
+  char *string;
+
+  /* string is sent WITHOUT ending NULL char */
+  /* allocate and zero length + 1 extra byte */
+  ALLOCATE (string, char, length + 1);
+  memset (string, 0, length + 1);
+  vsnprintf (string, length + 1, format, argp);
+
+  write (device, string, length);
+
+  // fprintf (stderr, "send: %s\n", string);
+
+  free (string);
+  return (TRUE);
+}
+
+/* scan a command of fixed size */
+int KiiScanCommand (int device, int length, char *format, ...) {
+
+  int status;
+  char *message;
+  va_list argp;  
+
+  ALLOCATE (message, char, length + 1);
+
+  /* read Nbytes from the device */
+  status = read (device, message, length);
+
+  if (status != length) {
+      fprintf (stderr, "Kii/Kapa comm error\n");
+      return (0);
+  }
+  message[status] = 0; // make the string easy to parse
+
+  /* scan the incoming message */
+  va_start (argp, format);
+  vsscanf (message, format, argp);
+  va_end (argp);
+
+  free (message);
+
+  return (1);
+}
+
+int KiiWaitAnswer (int device, char *expect) {
+
+  int Nbytes;
+  char *answer;
+
+  Nbytes = strlen (expect);
+  ALLOCATE (answer, char, Nbytes + 1);
+
+  KiiScanCommand (device, Nbytes, "%s", answer);
+  if (strcmp (answer, expect)) {
+      fprintf (stderr, "unexpected response %s, expected %s\n", answer, expect); 
+      REALLOCATE (answer, char, 128);
+      Nbytes = read (device, answer, 127);
+      answer[Nbytes] = 0;
+      fprintf (stderr, "extra data in buffer: %d bytes\n", Nbytes);
+      fprintf (stderr, "garbage: %s\n", answer);
+      free (answer);
+      return (FALSE);
+  }
+  free (answer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaColors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaColors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaColors.c	(revision 16632)
@@ -0,0 +1,103 @@
+# include <kapa_internal.h>
+
+# define N_KAPA_COLORS 23
+
+static char KAPA_COLORS[N_KAPA_COLORS][3][16] = {
+{"black",    	 "black",    	 "0.00 0.00 0.00"}, 
+{"white",    	 "white",    	 "1.00 1.00 1.00"}, 
+{"red",      	 "red",      	 "1.00 0.00 0.00"}, 
+{"pink",     	 "pink",     	 "1.00 0.75 0.80"}, 
+{"orange",   	 "orange",   	 "1.00 0.65 0.00"}, 
+{"yellow",   	 "yellow",   	 "1.00 1.00 0.00"}, 
+{"wheat",    	 "wheat",    	 "0.96 0.87 0.70"}, 
+{"gold",     	 "gold",     	 "1.00 0.84 0.00"}, 
+{"green",    	 "green",    	 "0.00 1.00 0.00"}, 
+{"darkgreen",	 "darkgreen",	 "0.00 0.40 0.00"}, 
+{"blue",     	 "blue",     	 "0.00 0.00 1.00"}, 
+{"skyblue",  	 "skyblue",  	 "0.53 0.81 0.92"}, 
+{"indigo",   	 "mediumpurple", "0.57 0.44 0.86"}, 
+{"violet",   	 "darkviolet", 	 "0.58 0.00 0.88"},
+{"grey10",   	 "grey10",   	 "0.10 0.10 0.10"},
+{"grey20",   	 "grey20",   	 "0.20 0.20 0.20"},
+{"grey30",   	 "grey30",   	 "0.30 0.30 0.30"},
+{"grey40",   	 "grey40",   	 "0.40 0.40 0.40"},
+{"grey50",   	 "grey50",   	 "0.50 0.50 0.50"},
+{"grey60",   	 "grey60",   	 "0.60 0.60 0.60"},
+{"grey70",   	 "grey70",   	 "0.70 0.70 0.70"},
+{"grey80",   	 "grey80",   	 "0.80 0.80 0.80"},
+{"grey90",   	 "grey90",   	 "0.90 0.90 0.90"}};
+
+int KapaColorByName (char *name) {
+
+  int i;
+  
+  for (i = 0; i < N_KAPA_COLORS; i++) {
+    if (!strcmp (name, KAPA_COLORS[i][0])) {
+      return (i);
+    }	
+  }
+  fprintf (stderr, "color may be one of:\n");
+  for (i = 0; i < N_KAPA_COLORS; i++) {
+    fprintf (stderr, "  %s\n", KAPA_COLORS[i][0]);
+  }
+  return (-1);
+}	
+
+int KapaColormapSize () {
+  return (N_KAPA_COLORS);
+}
+
+char *KapaColorRGBString (int N) {
+  return (KAPA_COLORS[N][2]);
+}
+
+char *KapaColorName (int N) {
+  return (KAPA_COLORS[N][0]);
+}
+
+png_color *KapaPNGPalette (int *Npalette) {
+
+  int i;
+  float red, green, blue;
+  png_color *palette;
+
+  ALLOCATE (palette, png_color, N_KAPA_COLORS);
+
+  /* define the palette */
+  for (i = 0; i < N_KAPA_COLORS; i++) {
+    sscanf (KAPA_COLORS[i][2], "%f %f %f", &red, &green, &blue);
+    palette[i].red = (0xff * red);
+    palette[i].green = (0xff * green);
+    palette[i].blue = (0xff * blue);
+  }
+  *Npalette = N_KAPA_COLORS;
+  return (palette);
+}
+
+unsigned long *KapaX11colors (Display *display, Colormap colormap, unsigned long default_color, int *Ncolors) {
+
+  int i;
+  int status;
+  unsigned long *colors;
+  XColor rgbcolor, hardwarecolor;
+
+  *Ncolors = N_KAPA_COLORS;
+  ALLOCATE (colors, unsigned long, N_KAPA_COLORS);
+
+  for (i = 0; i < N_KAPA_COLORS; i++) {
+    colors[i] = default_color;
+    status = XLookupColor (display, colormap, KAPA_COLORS[i][1], &rgbcolor, &hardwarecolor);
+    if (!status) continue;
+    status = XAllocColor (display, colormap, &hardwarecolor);
+    if (!status) continue;
+    colors[i] = hardwarecolor.pixel;
+  }
+  return (colors);
+}
+
+/*
+
+kapa objects, bDraw, and png all use the same pallete sequence, defined by
+KAPA_COLORS above.  the color correspond to a color sequence.  
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaOpen.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaOpen.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaOpen.c	(revision 16632)
@@ -0,0 +1,315 @@
+# include "kapa_internal.h"
+
+# define MY_PORT 2500
+# define MY_WAIT 100000
+# define DEBUG 0
+
+static int Nvalid = 0;
+static int *VALID = NULL;
+
+int KapaServerInit (KapaSockAddress *Address) {
+
+  int status, InitSocket, length;
+
+  Address[0].sin_family = AF_INET;
+  Address[0].sin_port   = MY_PORT;
+  Address[0].sin_addr.s_addr = INADDR_ANY; // use this line to bind any address / port?
+
+retry_server:
+
+  length = sizeof(Address[0]);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (2);
+  }
+
+  if (DEBUG) fprintf (stderr, "init sock: %d, len: %d\n", InitSocket, length);
+  status = bind (InitSocket, (struct sockaddr *) Address, length);
+  if (status == -1) {
+    if (errno == EADDRINUSE) {
+	close (InitSocket);
+	Address[0].sin_port ++;
+	if (Address[0].sin_port > MY_PORT + 10) exit (2);
+	goto retry_server;
+    }
+    perror ("bind: ");
+    exit (2);
+  }
+
+  /* repeated starts of the server are limited by xinetd or something:
+     requires 60sec timeout of the selected socket */
+
+  if (DEBUG) fprintf (stderr, "bound to port: %d\n", Address[0].sin_port);
+  status = listen (InitSocket, 10);
+  if (status == -1) {
+    perror ("listen: ");
+    exit (2);
+  }
+  return (InitSocket);
+}
+
+int KapaServerWait (int InitSocket, KapaSockAddress *Address) {
+
+  int i, status, BindSocket;
+  KapaSockAddress Address_in;
+  socklen_t length;
+  u_int32_t addr;
+  fd_set rfds;
+  struct timeval wait;
+
+  Address_in = Address[0];
+
+  length = sizeof(Address_in);
+
+  wait.tv_sec = 0;
+  wait.tv_usec = MY_WAIT;
+
+  /* do I need to clear rfds on each pass? */
+  FD_SET (InitSocket, &rfds);
+  status = select (InitSocket + 1, &rfds, NULL, NULL, &wait);
+  if (status == -1) {
+    perror ("select");
+    abort ();
+  }
+  if (!status) return (-1);
+
+  if (DEBUG) fprintf (stderr, "init sock: %d, len: %d\n", InitSocket, length);
+  BindSocket = accept (InitSocket, (struct sockaddr *) &Address_in, &length);
+  if (DEBUG) fprintf (stderr, "bind sock: %d\n", BindSocket);
+  if (BindSocket == -1) {
+    perror ("accept: ");
+    exit (2);
+  }
+
+  addr = Address_in.sin_addr.s_addr;
+  if (DEBUG) {
+    fprintf (stderr, "incoming connection from: ");
+    fprintf (stderr, " %u", (0xff & (addr >>  0)));
+    fprintf (stderr, ".%u", (0xff & (addr >>  8)));
+    fprintf (stderr, ".%u", (0xff & (addr >> 16)));
+    fprintf (stderr, ".%u", (0xff & (addr >> 24)));
+    fprintf (stderr, "\n");
+  }
+
+  if (Nvalid == 0) goto accepted;
+
+  for (i = 0; i < Nvalid; i++) {
+    /* valid IP addresses may be machines (120.90.121.142) or 
+       class C networks (120.90.121.0) */
+       
+    /* for machine, address must match */
+    if ((0xff & (VALID[i] >> 24)) != 0) {
+      if (addr == VALID[i]) goto accepted;
+    }
+
+    /* for network, lower three bytes of address must match */
+    if ((0xff & (VALID[i] >> 24)) == 0) {
+      if ((0x00ffffff & addr) == VALID[i]) goto accepted;
+    }
+  }
+
+  if (DEBUG) fprintf (stderr, "connection rejected\n");
+  close (BindSocket);
+  return (-1);
+
+accepted:
+  if (DEBUG) fprintf (stderr, "connection accepted\n");
+  return (BindSocket);
+}
+
+/* load valid ip list */
+int KapaDefineValidIP (char *ipstring) {
+
+  int ip1, ip2, ip3, ip4, test, status;
+  char string[80];
+
+  if (Nvalid == 0) {
+    Nvalid = 1;
+    ALLOCATE (VALID, int, Nvalid);
+  } else {
+    Nvalid ++;
+    REALLOCATE (VALID, int, Nvalid);
+  }
+
+  status = sscanf (ipstring, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+  test = TRUE;
+  test &= (status == 4);
+  test &= ((ip1 > 0) && (ip1 < 256)); 
+  test &= ((ip2 > 0) && (ip2 < 256)); 
+  test &= ((ip3 > 0) && (ip3 < 256)); 
+  test &= ((ip4 >=0) && (ip4 < 256)); 
+  if (!test) {
+    fprintf (stderr, "invalid IP address %s\n", string);
+    exit (2);
+  }
+  VALID[Nvalid-1] = ip1 | (ip2 << 8) | (ip3 << 16) | (ip4 << 24);
+  return (TRUE);
+}
+
+/* connect to a running server on the specified host */
+int KapaClientSocket (char *hostname) {
+
+  int i, status, InitSocket, length;
+  KapaSockAddress Address;
+  struct hostent  *host;
+  char tmpline[80], hostip[80];
+
+  host = gethostbyname (hostname);
+  bzero (hostip, 80);
+  for (i = 0; i < host[0].h_length; i++) {
+    sprintf (tmpline, "%u", (0xff & host[0].h_addr[i]));
+    strcat (hostip, tmpline);
+    if (i < host[0].h_length - 1) strcat (hostip, ".");
+  }
+
+  if (DEBUG) {
+    fprintf (stderr, "trying %s (%s:%d)...", host[0].h_name, hostip, MY_PORT);
+  }
+
+  Address.sin_family = AF_INET;
+  Address.sin_port   = MY_PORT;
+
+retry_client:
+  status = inet_aton (hostip, &Address.sin_addr);
+  if (!status) {
+    fprintf (stderr, "invalid address\n");
+    exit (2);
+  }
+
+  length = sizeof(Address);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (2);
+  }
+
+  status = connect (InitSocket, (struct sockaddr *) &Address, length);
+  if (status == -1) {
+    if (DEBUG) fprintf (stderr, "error connecting: %d\n", errno);
+    if (errno == ECONNREFUSED) {
+      close (InitSocket);
+      Address.sin_port ++;
+      if (Address.sin_port > MY_PORT + 10) return (-1);
+      goto retry_client;
+    }
+    perror ("connect: ");
+    exit (2);
+  }
+
+  if (DEBUG) fprintf (stderr, "connected on port: %d\n", Address.sin_port);
+  if (DEBUG) fprintf (stderr, "connected\n");
+
+  // the client uses a BLOCKing socket by default
+  fcntl (InitSocket, F_SETFL, !O_NONBLOCK); 
+  return (InitSocket);
+}
+
+int KapaOpen (char *kapa_exec, char *kapa_name) {
+
+  // kapa_exec may be kapa://host, in which case we attempt to connect to an 
+  // already running kapa, or the program path, in which case we are supposed
+  // to launch it locally, then connect to it.
+
+  int sock, Ntry;
+  char line[128];
+
+  if (!strncmp (kapa_exec, "kapa://", 7)) {
+    sock = KapaClientSocket (&kapa_exec[7]);
+    return (sock);
+  }
+
+  if (kapa_name == NULL) {
+    sprintf (line, "%s &", kapa_exec);
+  } else {
+    sprintf (line, "%s -name '%s' &", kapa_exec, kapa_name);
+  }
+  system (line);
+
+# define NTRY 500
+  Ntry = 0;
+  while (Ntry < NTRY) {
+    sock = KapaClientSocket ("localhost");
+    if (sock != -1) break;
+    // if (errno != EAGAIN) break;
+    if (errno != ECONNREFUSED) break;
+    usleep (10000);
+    Ntry ++;
+  }
+
+  if (sock < 0) return (-1);
+  return (sock);
+}
+
+/* start socketed connection (UNIX Socket) */
+int KapaOpenNamedSocket (char *kapa_exec, char *name) {
+
+  int InitSocket, status;
+  struct sockaddr_un Address;
+  socklen_t AddressLength;
+  char temp[128], socket_name[64];
+  int Ntry, fd;
+
+  sprintf (socket_name, "/tmp/Kapa.XXXXXX");
+  if ((fd = mkstemp (socket_name)) == -1) {
+    fprintf (stderr, "error starting kapa\n");
+    return (-1);
+  }
+  close (fd);
+  unlink (socket_name);
+
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, (struct sockaddr *) &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  if (name == NULL) {
+    sprintf (temp, "%s -socket %s &", kapa_exec, socket_name);
+  } else {
+    sprintf (temp, "%s -socket %s -name %s &", kapa_exec, socket_name, name);
+  }
+  system (temp);
+
+  AddressLength =  sizeof (Address);
+  fcntl (InitSocket, F_SETFL, O_NONBLOCK); 
+
+# define NTRY 500
+  Ntry = 0;
+  while (Ntry < NTRY) {
+    fd = accept (InitSocket, (struct sockaddr *)&Address, &AddressLength);
+    if (fd != -1) break;
+    if (errno != EAGAIN) break;
+    usleep (10000);
+    Ntry ++;
+  }
+
+  if (fd < 0) return (-1);
+
+  // the client uses a BLOCKing socket by default
+  fcntl (fd, F_SETFL, !O_NONBLOCK); 
+  return (fd);
+}
+
+// wait for the initiating process to connect to the socket
+int KapaWaitNamedSocket (char *sockpath) {
+
+  int sock, status;
+  struct sockaddr_un Address;
+
+  strcpy (Address.sun_path, sockpath);
+  Address.sun_family = AF_UNIX;
+  sock = socket (AF_UNIX, SOCK_STREAM, 0);
+  status = connect (sock, (struct sockaddr *) &Address, sizeof (Address));
+  if (status < 0) {
+    fprintf (stderr, "unsuccessful connection: %d\n", status);
+    exit (0);
+  }
+
+  // the server uses an unblocked socket
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  unlink (sockpath);
+  return (sock);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaWindow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaWindow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KapaWindow.c	(revision 16632)
@@ -0,0 +1,332 @@
+# include <kapa_internal.h>
+
+int KiiCenter (int fd, double x, double y, int zoom) {
+
+  KiiSendCommand (fd, 4, "CENT");
+  KiiSendMessage (fd, "%8.3f %8.3f %8d ", x, y, zoom);
+  KiiWaitAnswer (fd, "DONE");
+  
+  return (TRUE);
+}
+
+int KiiResize (int fd, int Nx, int Ny) {
+
+  KiiSendCommand (fd, 4, "RSIZ");
+  KiiSendMessage (fd, "%d %d", Nx, Ny); 
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaBox (int fd, Graphdata *graphdata) {
+
+  KiiSendCommand (fd, 4, "DBOX");
+  KiiSendMessage (fd, "%12.6g %12.6g %12.6g %12.6g", 
+		    graphdata[0].xmin, graphdata[0].xmax, graphdata[0].ymin, graphdata[0].ymax);
+
+  KiiSendMessage (fd, "%s %s %s", graphdata[0].axis, graphdata[0].labels, graphdata[0].ticks);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaClearCurrentPlot (int fd) {
+  
+  KiiSendCommand (fd, 4, "ERSC");
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaClearPlots (int fd) {
+  
+  KiiSendCommand (fd, 4, "ERSP");
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaClearSections (int fd) {
+  
+  KiiSendCommand (fd, 4, "ERSS");
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaClearImage (int fd) {
+  
+  KiiSendCommand (fd, 4, "ERSI");
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSetToolbox (int fd, int location) {
+  
+  KiiSendCommand (fd, 4, "TOOL");
+  KiiSendMessage (fd, "%d", location); 
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaInitGraph (Graphdata *graphdata) {
+
+  graphdata[0].xmin = graphdata[0].ymin = 0.0;
+  graphdata[0].xmax = graphdata[0].ymax = 1.0;
+  graphdata[0].style = graphdata[0].ptype = 0;
+  graphdata[0].ltype = graphdata[0].color = 0;
+  graphdata[0].etype = graphdata[0].ebar = 0;
+  graphdata[0].lweight = graphdata[0].size = 1.0;
+    
+  graphdata[0].coords.pc1_1 = graphdata[0].coords.pc2_2 = 1.0;
+  graphdata[0].coords.pc1_2 = graphdata[0].coords.pc2_1 = 0.0;
+  strcpy (graphdata[0].coords.ctype, "RA---LIN");
+  graphdata[0].coords.crval1 = 0.0;
+  graphdata[0].coords.crval2 = 0.0;
+  graphdata[0].coords.crpix1 = 0.0;
+  graphdata[0].coords.crpix2 = 0.0;
+  graphdata[0].coords.cdelt1 = graphdata[0].coords.cdelt2 = 1.0;
+  graphdata[0].flipeast = TRUE;
+  graphdata[0].flipnorth = FALSE;
+  strcpy (graphdata[0].axis, "2222");
+  strcpy (graphdata[0].ticks, "2222");
+  strcpy (graphdata[0].labels, "2222");
+
+  return (TRUE);
+}
+
+int KapaPrepPlot (int fd, int Npts, Graphdata *data) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "PLOT"); 
+  
+  /* send kapa the plot details */
+  KiiSendMessage (fd, "%8d %8d %d %d %d %d %d %f %f", 
+		  Npts, data[0].style, 
+		  data[0].ptype, data[0].ltype, 
+		  data[0].etype, data[0].ebar, data[0].color, 
+		  data[0].lweight, data[0].size);
+  KiiSendMessage (fd, "%g %g %g %g", 
+		  data[0].xmin, data[0].xmax, 
+		  data[0].ymin, data[0].ymax);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSetGraphData (int fd, Graphdata *data) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "SSTY"); 
+  
+  /* send kapa the plot details */
+  KiiSendMessage (fd, "%8d %d %d %d %d %d %f %f", 
+		  data[0].style, 
+		  data[0].ptype, data[0].ltype, 
+		  data[0].etype, data[0].ebar, data[0].color, 
+		  data[0].lweight, data[0].size);
+
+  KiiSendMessage (fd, "%g %g %g %g", 
+		  data[0].xmin, data[0].xmax, 
+		  data[0].ymin, data[0].ymax);
+
+  KiiSendMessage (fd, "%g %g %g %g", 
+		  data[0].coords.pc1_1, data[0].coords.pc2_2,
+		  data[0].coords.pc1_2, data[0].coords.pc2_1);
+
+  KiiSendMessage (fd, "%d %d %s", 
+		  data[0].flipeast, data[0].flipnorth,
+		  data[0].coords.ctype);
+
+  KiiSendMessage (fd, "%g %g %g %g %g %g", 
+		  data[0].coords.crval1,
+		  data[0].coords.crval2,
+		  data[0].coords.crpix1,
+		  data[0].coords.crpix2,
+		  data[0].coords.cdelt1,
+		  data[0].coords.cdelt2);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaGetGraphData (int fd, Graphdata *data) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "GSTY"); 
+  
+  /* send kapa the plot details */
+  KiiScanMessage (fd, "%d %d %d %d %d %d %lf %lf", 
+		  &data[0].style, 
+		  &data[0].ptype, &data[0].ltype, 
+		  &data[0].etype, &data[0].ebar, &data[0].color, 
+		  &data[0].lweight, &data[0].size);
+
+  KiiScanMessage (fd, "%lf %lf %lf %lf", 
+		  &data[0].xmin, &data[0].xmax, 
+		  &data[0].ymin, &data[0].ymax);
+
+  KiiScanMessage (fd, "%f %f %f %f", 
+		  &data[0].coords.pc1_1, &data[0].coords.pc2_2,
+		  &data[0].coords.pc1_2, &data[0].coords.pc2_1);
+
+  KiiScanMessage (fd, "%d %d %s", 
+		  &data[0].flipeast, &data[0].flipnorth,
+		  data[0].coords.ctype);
+
+  KiiScanMessage (fd, "%lf %lf %f %f %f %f", 
+		  &data[0].coords.crval1,
+		  &data[0].coords.crval2,
+		  &data[0].coords.crpix1,
+		  &data[0].coords.crpix2,
+		  &data[0].coords.cdelt1,
+		  &data[0].coords.cdelt2);
+
+  // XXX at some point, we need to add polynomials and 2-level mosaic
+  // astrometry here.
+
+  data[0].coords.Npolyterms = 0;
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSetImageData (int fd, KapaImageData *data) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "SIMD"); 
+  
+  /* send kapa the plot details */
+  KiiSendMessage (fd, "%g %g %s %s", 
+		  data[0].zero, data[0].range, data[0].name, data[0].file);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaGetImageData (int fd, KapaImageData *data) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "GIMD"); 
+  
+  KiiScanMessage (fd, "%lf %lf %s %s", 
+		  &data[0].zero, &data[0].range, data[0].name, data[0].file);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaPlotVector (int fd, int Npts, float *values, char *type) {
+
+  int Nbytes;
+  int swap;
+
+# ifdef BYTE_SWAP
+  swap = 1;
+# else
+  swap = 0;
+# endif
+
+  Nbytes = Npts * sizeof (float);
+
+  if (!strcmp(type, "x")) goto valid;
+  if (!strcmp(type, "y")) goto valid;
+  if (!strcmp(type, "z")) goto valid;
+  if (!strcmp(type, "dym")) goto valid;
+  if (!strcmp(type, "dyp")) goto valid;
+  if (!strcmp(type, "dxm")) goto valid;
+  if (!strcmp(type, "dxp")) goto valid;
+  return (FALSE);
+
+valid:
+  KiiSendCommand (fd, 4, "PLOB"); 
+  KiiSendMessage (fd, "%s %d %d %d", type, Npts, Nbytes, swap); 
+
+  write (fd, values, Nbytes);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSetFont (int fd, char *name, int size) {
+
+  KiiSendCommand (fd, 4, "FONT");
+  KiiSendCommand (fd, 16, "%s", name);
+  KiiSendCommand (fd, 16, "%d", size);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSendLabel (int fd, char *string, int mode) {
+
+  KiiSendCommand (fd, 4, "LABL");
+  KiiSendMessage (fd, "%6d", mode);
+  KiiSendData (fd, string, strlen(string));
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSendTextline (int fd, char *string, float x, float y, float angle) {
+  
+  KiiSendCommand (fd, 4, "PTXT");
+  KiiSendMessage (fd, "%f %f %f", x, y, angle);
+  KiiSendData (fd, string, strlen(string));
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSetLimits (int fd, Graphdata *data) {
+
+  KiiSendCommand (fd, 4, "SLIM");
+  KiiSendMessage (fd, "%g %g %g %g ", data[0].xmin, data[0].xmax, data[0].ymin, data[0].ymax);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+// for now, this just gets the dimensions
+int KapaGetLimits (int fd, float *dx, float *dy) {
+
+  KiiSendCommand (fd, 4, "GLIM"); 
+  KiiScanMessage (fd, "%f %f", dx, dy); 
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSetSection (int fd, KapaSection *section) {
+
+  KiiSendCommand (fd, 4, "DSEC");
+  KiiSendMessage (fd, "%s %6.3f %6.3f %6.3f %6.3f", 
+		  section[0].name, 
+		  section[0].x,
+		  section[0].y,
+		  section[0].dx,
+		  section[0].dy);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaMoveSection (int fd, char *name, char *direction) {
+
+  if (!strcasecmp(direction, "up")) goto valid;
+  if (!strcasecmp(direction, "down")) goto valid;
+  if (!strcasecmp(direction, "top")) goto valid;
+  if (!strcasecmp(direction, "bottom")) goto valid;
+  
+  fprintf (stderr, "unexpected direction %s\n", direction); 
+  return (FALSE);
+
+valid:
+  KiiSendCommand (fd, 4, "MSEC");
+  KiiSendMessage (fd, "%s %s", name, direction);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSelectSection (int fd, char *name) {
+
+  KiiSendCommand (fd, 4, "SSEC");
+  KiiSendMessage (fd, "%s", name);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaGetSection (int fd, char *name) {
+
+  KiiSendCommand (fd, 4, "LSEC");
+  KiiSendMessage (fd, "%s", name);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiConvert.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiConvert.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiConvert.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include <kapa_internal.h>
+
+int KiiJPEG (int fd, const char *filename) {
+
+  KiiSendCommand (fd, 4, "JPEG");
+  KiiSendMessage (fd, "%s", filename);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaPNG (int fd, const char *filename) {
+
+  KiiSendCommand (fd, 4, "PNGF");
+  KiiSendMessage (fd, "%s", filename);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaPPM (int fd, const char *filename) {
+
+  KiiSendCommand (fd, 4, "PPMF");
+  KiiSendMessage (fd, "%s", filename);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiPS (int fd, const char *filename, int scaleMode, int pageMode, char *pagename) {
+
+  KiiSendCommand (fd, 4, "PSIT");
+  KiiSendMessage (fd, "%s %s %d %d", filename, pagename, scaleMode, pageMode);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiCursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiCursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiCursor.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include <kapa_internal.h>
+
+int KiiCursorOn (int fd) {
+
+  KiiSendCommand (fd, 4, "CURS");
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiCursorOff (int fd) {
+
+  KiiSendCommand (fd, 4, "NCUR");
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiCursorRead (int fd, double *x, double *y, double *z, double *r, double *d, char *key) {
+
+  KiiScanMessage (fd, "%s %lf %lf %lf %lf %lf", key, x, y, z, r, d);
+  if (ispunct(key[0])) strcpy (key, "_");
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiOpen.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiOpen.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiOpen.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include <kapa_internal.h>
+
+/** start socketed connection */
+int KiiOpen (char *kii_exec, char *name) {
+
+  int InitSocket, status;
+  struct sockaddr_un Address;
+  socklen_t AddressLength;
+  char temp[128], socket_name[64];
+  int Ntry, fd;
+
+  sprintf (socket_name, "/tmp/Kii.XXXXXX");
+  if ((fd = mkstemp (socket_name)) == -1) {
+    fprintf (stderr, "error starting kii\n");
+    return (-1);
+  }
+  close (fd);
+  unlink (socket_name);
+
+  strcpy (Address.sun_path, socket_name); 
+  Address.sun_family = AF_UNIX; 
+  InitSocket = socket (AF_UNIX, SOCK_STREAM, 0); 
+  status = bind (InitSocket, (struct sockaddr *) &Address, sizeof (Address));
+  status = listen (InitSocket, 1);
+  
+  if (name == NULL) {
+    sprintf (temp, "%s %s &", kii_exec, socket_name);
+  } else {
+    sprintf (temp, "%s %s -name %s &", kii_exec, socket_name, name);
+  }
+  system (temp);
+
+  AddressLength =  sizeof (Address);
+  fcntl (InitSocket, F_SETFL, O_NONBLOCK); 
+
+# define NTRY 500
+  Ntry = 0;
+  while (Ntry < NTRY) {
+    fd = accept (InitSocket, (struct sockaddr *)&Address, &AddressLength);
+    if (fd != -1) break;
+    if (errno != EAGAIN) break;
+    usleep (10000);
+    Ntry ++;
+  }
+
+  if (fd < 0) return (-1);
+
+  fcntl (fd, F_SETFL, !O_NONBLOCK); 
+  return (fd);
+}
+
+int KiiWait (char *sockpath) {
+
+  int sock, status;
+  struct sockaddr_un Address;
+
+  strcpy (Address.sun_path, sockpath);
+  Address.sun_family = AF_UNIX;
+  sock = socket (AF_UNIX, SOCK_STREAM, 0);
+  status = connect (sock, (struct sockaddr *) &Address, sizeof (Address));
+  if (status < 0) {
+    fprintf (stderr, "unsuccessful connection: %d\n", status);
+    exit (0);
+  }
+  fcntl (sock, F_SETFL, O_NONBLOCK);  
+  unlink (sockpath);
+  return (sock);
+}
+
+int KiiClose (int fd) {
+
+  if (fd < 1) return (FALSE);
+  KiiSendCommand (fd, 4, "QUIT");
+  close (fd);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiOverlay.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiOverlay.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiOverlay.c	(revision 16632)
@@ -0,0 +1,130 @@
+# include <kapa_internal.h>
+
+# define NOVERLAY_TYPE 5
+static char KiiOverlayTypeName[NOVERLAY_TYPE][16] = {
+  "NONE",
+  "TEXT", 
+  "BOX", 
+  "LINE",
+  "CIRCLE", 
+};
+
+int KiiOverlayTypeByName (char *overname) {
+
+  int i;
+
+  for (i = 1; i < NOVERLAY_TYPE; i++) {
+    if (!strcasecmp (overname, KiiOverlayTypeName[i])) return (i);
+  }
+  return (0);
+}
+
+char *KiiOverlayTypeByNumber (int n) {
+
+  if ((n < 0) || (n >= NOVERLAY_TYPE)) return NULL;
+  return (KiiOverlayTypeName[n]);
+}
+
+int KiiSelectOverlay (char *overname, int *number) {
+
+  *number = -1;
+  if (!strcmp (overname, "red") || !strcmp (overname, "0")) {
+    *number = 0;
+    return (TRUE);
+  }
+  if (!strcmp (overname, "green") || !strcmp (overname, "1")) {
+    *number = 1;
+    return (TRUE);
+  }
+  if (!strcmp (overname, "blue") || !strcmp (overname, "2")) {
+    *number = 2;
+    return (TRUE);
+  }
+  if (!strcmp (overname, "yellow") || !strcmp (overname, "3")) {
+    *number = 3;
+    return (TRUE);
+  }
+
+  fprintf (stderr, "valid overlays may be: red (0), green (1), blue (2), yellow (3)\n");
+  return (FALSE);
+}
+
+int KiiLoadOverlay (int fd, KiiOverlay *overlay, int Noverlay, char *overname) {
+
+  int i, overnum, Ntextdata, NTEXTDATA, Ntext, Nchar;
+  char *textdata;
+  KiiOverlayBase *buffer;
+
+  Ntext = 0;
+  KiiSelectOverlay (overname, &overnum);
+
+  Ntextdata = 0;
+  NTEXTDATA = 1024;
+  ALLOCATE (textdata, char, 1024);
+
+  // we send the position information as a binary block
+  ALLOCATE (buffer, KiiOverlayBase, Noverlay);
+  for (i = 0; i < Noverlay; i++) {
+    buffer[i].x     = overlay[i].x;
+    buffer[i].y     = overlay[i].y;
+    buffer[i].dx    = overlay[i].dx;
+    buffer[i].dy    = overlay[i].dy;
+    buffer[i].angle = overlay[i].angle;
+    buffer[i].type  = overlay[i].type;
+    if (buffer[i].type == KII_OVERLAY_TEXT) {
+      Ntext ++;
+      Nchar = strlen(overlay[i].text) + 1;
+      if (Ntextdata + Nchar >= NTEXTDATA) {
+	NTEXTDATA += 1024;
+	REALLOCATE (textdata, char, NTEXTDATA);
+      }
+      sprintf (&textdata[Ntextdata], "%s\n", overlay[i].text);
+      Ntextdata += Nchar;
+    }
+  }
+
+  KiiSendCommand (fd,  4, "LOAD");
+  KiiSendMessage (fd, "%d %d %d %d", overnum, Noverlay, Ntext, Ntextdata);
+
+  // we could break this into segments if we want to trap an interrupt, but why bother?
+  Nchar = write (fd, buffer, Noverlay*sizeof(KiiOverlayBase));
+  KiiWaitAnswer (fd, "DONE");
+
+  write (fd, textdata, Ntextdata);
+  KiiWaitAnswer (fd, "DONE");
+
+  free (buffer);
+  free (textdata);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiEraseOverlay (int fd, char *overname) {
+
+  int n;
+
+  KiiSelectOverlay (overname, &n);
+    
+  KiiSendCommand (fd, 4, "ERSO");
+  KiiSendCommand (fd, 16, "OVERLAY %7d ", n);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiSaveOverlay (int fd, int celestial, char *overname, char *file) {
+
+  int n;
+
+  KiiSelectOverlay (overname, &n);
+    
+  if (celestial) {
+    KiiSendCommand (fd, 4, "CSVE");
+  } else {
+    KiiSendCommand (fd, 4, "SAVE");
+  }
+
+  KiiSendMessage (fd, "FILE: %d %s", n, file);
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiPicture.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiPicture.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/KiiPicture.c	(revision 16632)
@@ -0,0 +1,239 @@
+# include <kapa_internal.h>
+
+int KiiSetChannel (int fd, int channel) {
+
+  KiiSendCommand (fd, 4, "CHAN"); /* tell kapa to look for the incoming image */
+  KiiSendMessage (fd, "%1d", channel);
+  
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiSetColormap (int fd, char *colormap) {
+
+  KiiSendCommand (fd, 4, "CMAP"); /* tell kapa to look for the incoming image */
+  KiiSendMessage (fd, "%s", colormap);
+  
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiNewPicture1D (int fd, KiiImage *image, KapaImageData *data, Coords *coords) {
+
+  int Npix, Ncolors, size;
+  float *in, min, max;
+
+  Npix = image[0].Nx*image[0].Ny;
+
+  KiiSendCommand (fd, 4, "READ"); /* tell kapa to look for the incoming image */
+  KiiScanMessage (fd, "%d", &Ncolors);
+
+  in = image[0].data1d;
+
+  /* these are for a future upgrade */
+  min = max = 0.0;
+  size = Npix*sizeof(float);
+
+  /* done with the conversion, now send kapa the converted picture */
+  KiiSendMessage (fd, "%8d %8d", image[0].Nx, image[0].Ny);
+  KiiSendMessage (fd, "-32 1 0.0 1.0");
+  KiiSendMessage (fd, "%f %f %s %s", data[0].zero, data[0].range, data[0].name, data[0].file);
+  KiiSendMessage (fd, "%f %f %d ", min, max, size);
+  KiiSendMessage (fd, "%f %f %g %g %g ", coords[0].crval1, coords[0].crpix1, coords[0].cdelt1, coords[0].pc1_1, coords[0].pc1_2);
+  KiiSendMessage (fd, "%f %f %g %g %g ", coords[0].crval2, coords[0].crpix2, coords[0].cdelt2, coords[0].pc2_1, coords[0].pc2_2);
+  KiiSendMessage (fd, "%s", coords[0].ctype);
+
+  /* send the image data */
+  write (fd, image[0].data1d, size);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiNewPicture1D_8bit (int fd, KiiImage *image, KapaImageData *data, Coords *coords) {
+
+  int i;
+  int Npix, Ncolors, NNcolors, size;
+  float *in, min, max;
+  char *out, *outbuffer;
+  double a1, a2;
+
+  Npix = image[0].Nx*image[0].Ny;
+
+  KiiSendCommand (fd, 4, "READ"); /* tell kapa to look for the incoming image */
+  KiiScanMessage (fd, "%d", &Ncolors);
+
+  ALLOCATE (outbuffer, char, Npix);
+  out = outbuffer;
+  in = image[0].data1d;
+
+  /* need to invert the logic if range < 0 */
+
+  /* define color table, */
+  NNcolors = Ncolors - 1;
+  if (data[0].logflux) {
+    data[0].range = MAX (2, data[0].range);
+    a1 = Ncolors / log10 (data[0].range);
+    a2 = data[0].zero;
+    for (i = 0; i < Npix; i++, in++, out++) {
+      *out = (char) MIN (a1 * log10 (MAX (*in - a2, 1.0)), NNcolors);
+    }
+  } else {
+    a1 = Ncolors / data[0].range;
+    a2 = Ncolors * data[0].zero / data[0].range;
+    for (i = 0; i < Npix; i++, in++, out++) {
+      *out = (char) MIN (MAX (a1 * *in - a2, 0), NNcolors);
+    }
+  }
+  
+  /* these are for a future upgrade */
+  min = max = 0.0;
+  size = Npix*sizeof(char);
+
+  /* done with the conversion, now send kapa the converted picture */
+  KiiSendMessage (fd, "%8d %8d", image[0].Nx, image[0].Ny);
+  KiiSendMessage (fd, "8 1 0.0 1.0");
+  KiiSendMessage (fd, "%f %f %s %s", data[0].zero, data[0].range, data[0].name, data[0].file);
+  KiiSendMessage (fd, "%f %f %d ", min, max, size);
+  KiiSendMessage (fd, "%f %f %g %g %g ", coords[0].crval1, coords[0].crpix1, coords[0].cdelt1, coords[0].pc1_1, coords[0].pc1_2);
+  KiiSendMessage (fd, "%f %f %g %g %g ", coords[0].crval2, coords[0].crpix2, coords[0].cdelt2, coords[0].pc2_1, coords[0].pc2_2);
+  KiiSendMessage (fd, "%s", coords[0].ctype);
+
+  /* send the image data */
+  write (fd, outbuffer, size);
+  free (outbuffer);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KiiNewPicture2D (int fd, KiiImage *image, KapaImageData *data, Coords *coords) {
+
+  int i, j;
+  int Npix, Ncolors, NNcolors, size;
+  float *in, min, max;
+  char *out, *outbuffer;
+  double a1, a2;
+
+  Npix = image[0].Nx*image[0].Ny;
+
+  KiiSendCommand (fd, 4, "READ"); /* tell kapa to look for the incoming image */
+  KiiScanMessage (fd, "%d", &Ncolors);
+
+  ALLOCATE (outbuffer, char, Npix);
+  out = outbuffer;
+
+  /* need to invert the logic if range < 0 */
+
+  /* define color table, */
+  NNcolors = Ncolors - 1;
+  if (data[0].logflux) {
+    data[0].range = MAX (2, data[0].range);
+    a1 = Ncolors / log10 (data[0].range);
+    a2 = data[0].zero;
+    for (j = 0; j < image[0].Ny; j++) {
+      in = image[0].data2d[j];
+      for (i = 0; i < image[0].Nx; i++, in++, out++) {
+	*out = (char) MIN (a1 * log10 (MAX (*in - a2, 1.0)), NNcolors);
+      }
+    }
+  } else {
+    a1 = Ncolors / data[0].range;
+    a2 = Ncolors * data[0].zero / data[0].range;
+    for (j = 0; j < image[0].Ny; j++) {
+      in = image[0].data2d[j];
+      for (i = 0; i < image[0].Nx; i++, in++, out++) {
+	*out = (char) MIN (MAX (a1 * *in - a2, 0), NNcolors);
+      }
+    }
+  }
+  
+  /* these are for a future upgrade */
+  min = max = 0.0;
+  size = Npix*sizeof(char);
+
+  /* done with the conversion, now send kapa the converted picture */
+  KiiSendMessage (fd, "%8d %8d", image[0].Nx, image[0].Ny);
+  KiiSendMessage (fd, "8 1 0.0 1.0");
+  KiiSendMessage (fd, "%f %f %s %s", data[0].zero, data[0].range, data[0].name, data[0].file);
+  KiiSendMessage (fd, "%f %f %d ", min, max, size);
+  KiiSendMessage (fd, "%f %f %g %g %g ", coords[0].crval1, coords[0].crpix1, coords[0].cdelt1, coords[0].pc1_1, coords[0].pc1_2);
+  KiiSendMessage (fd, "%f %f %g %g %g ", coords[0].crval2, coords[0].crpix2, coords[0].cdelt2, coords[0].pc2_1, coords[0].pc2_2);
+  KiiSendMessage (fd, "%s", coords[0].ctype);
+
+  /* send the image data */
+  write (fd, outbuffer, size);
+  free (outbuffer);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaSetImageCoords (int fd, Coords *coords) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "SIMC"); 
+  
+  KiiSendMessage (fd, "%g %g %g %g", 
+		  coords[0].pc1_1, coords[0].pc2_2,
+		  coords[0].pc1_2, coords[0].pc2_1);
+
+  KiiSendMessage (fd, "%s", coords[0].ctype);
+
+  KiiSendMessage (fd, "%g %g %g %g %g %g", 
+		  coords[0].crval1,
+		  coords[0].crval2,
+		  coords[0].crpix1,
+		  coords[0].crpix2,
+		  coords[0].cdelt1,
+		  coords[0].cdelt2);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaGetImageCoords (int fd, Coords *coords) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "GIMC"); 
+  
+  KiiScanMessage (fd, "%f %f %f %f", 
+		  &coords[0].pc1_1, &coords[0].pc2_2,
+		  &coords[0].pc1_2, &coords[0].pc2_1);
+
+  KiiScanMessage (fd, "%s", coords[0].ctype);
+
+  KiiScanMessage (fd, "%lf %lf %f %f %f %f", 
+		  &coords[0].crval1,
+		  &coords[0].crval2,
+		  &coords[0].crpix1,
+		  &coords[0].crpix2,
+		  &coords[0].cdelt1,
+		  &coords[0].cdelt2);
+
+  // XXX at some point, we need to add polynomials and 2-level mosaic
+  // astrometry here.
+
+  coords[0].Npolyterms = 0;
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+int KapaGetImageRange (int fd, double *Xmin, double *Xmax, double *Ymin, double *Ymax) {
+
+  /* tell kapa to look for the incoming image */
+  KiiSendCommand (fd, 4, "GIMR"); 
+  
+  KiiScanMessage (fd, "%lf %lf %lf %lf", Xmin, Xmax, Ymin, Ymax);
+
+  KiiWaitAnswer (fd, "DONE");
+  return (TRUE);
+}
+
+
+/* this function should be broken into pieces: 
+   KiiSendImage
+   KiiSendCoords (default to 0 otherwise)
+   KiiSendFilename
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/PSRotFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/PSRotFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/PSRotFont.c	(revision 16632)
@@ -0,0 +1,182 @@
+# include <kapa_internal.h>
+# define NROTCHARS 256
+
+/* writes commands to print string at location and angle using
+   currently set font and size */
+void PSRotText (FILE *f, int x, int y, char *string, int pos, double angle) {
+
+  char *segment, basename[64], *currentname;
+  int i, N, code;
+  int dX, dY, Xoff, Yoff, X, Y, Nseg, NSEG, YoffBase;
+  double cs, sn, fscale, currentscale;
+  int basesize, currentsize;
+  RotFont *currentfont;
+  
+  currentname = GetRotFont (&currentsize);
+  currentfont = GetRotFontData (&currentscale);
+  strcpy (basename, currentname);
+  basesize = currentsize;
+
+  /* strip off leading WHITESPACE */
+  stripwhite (string);
+  if (*string == 0) return;
+  
+  /* compute string length */
+  /* PS fonts are somewhat different scales from bitmap font equivalents */
+  fscale = 1.0;
+  if (!strcmp (currentname, "times")) fscale = 1.07;
+  if (!strcmp (currentname, "courier")) fscale = 1.5;
+  if (!strcmp (currentname, "helvetica")) fscale = 0.9;
+  if (!strcmp (currentname, "symbol")) fscale = 1.2;
+  dX = fscale*RotStrlen (string);
+  dY = currentfont[65].ascent;
+  
+  /* apply appropriate offset */
+  Xoff = Yoff = 0;
+  switch (pos) {
+  case 0: Xoff =     -dX; Yoff = -dY; break;
+  case 1: Xoff = -0.5*dX; Yoff = -dY; break;
+  case 2: Xoff =       0; Yoff = -dY; break;
+  case 3: Xoff =     -dX; Yoff = -0.5*dY; break;
+  case 4: Xoff = -0.5*dX; Yoff = -0.5*dY; break;
+  case 5: Xoff =       0; Yoff = -0.5*dY; break;
+  case 6: Xoff =     -dX; Yoff = 0; break;
+  case 7: Xoff = -0.5*dX; Yoff = 0; break;
+  case 8: Xoff =       0; Yoff = 0; break;
+  }
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  X = x + Xoff*cs + Yoff*sn;
+  Y = y - Xoff*sn + Yoff*cs;
+
+  PSSetFont (f, currentname, currentsize);
+  fprintf (f, "gsave\n");
+  fprintf (f, " %d %d moveto %f rotate\n", X, Y, -angle);
+
+  Nseg = 0;
+  NSEG = strlen(string) + 2;
+  ALLOCATE (segment, char, NSEG);
+  bzero (segment, NSEG);
+
+  code = FALSE;
+  YoffBase = 0;
+  /* accumulate string segments with common state */
+  for (i = 0; i < strlen (string); i++) {
+    N = (int)(string[i]);
+    if ((N < 0) || (N >= NROTCHARS)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      /* superscript character (^) */
+      if (N == 94) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	Yoff = 0.75*currentscale*dY;
+	fprintf (f, "0 %d rmoveto\n", Yoff);
+	YoffBase += Yoff;
+	PSSetFont (f, currentname, currentsize);
+	continue;
+      }
+      /* subscript character (_) */
+      if (N == 95) { 
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	Yoff = -0.5*currentscale*dY;
+	fprintf (f, "0 %d rmoveto\n", Yoff);
+	YoffBase += Yoff;
+	PSSetFont (f, currentname, currentsize);
+	continue;
+      }
+      /* end super/sub script (|) */
+      if (N == 124) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	SetRotFont (currentname, basesize);
+	currentfont = GetRotFontData (&currentscale);
+	fprintf (f, "0 %d rmoveto\n", -YoffBase);
+	YoffBase = 0;
+	PSSetFont (f, currentname, currentsize);
+	continue;
+      }
+      /* escape char (\) */
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      /* begin paren (insert \) */
+      if (N == 40) {
+	code = FALSE;
+	segment[Nseg] = 92;
+	Nseg ++;
+	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+      }
+      /* end paren (insert \) */
+      if (N == 41) {
+	code = FALSE;
+	segment[Nseg] = 92;
+	Nseg ++;
+	CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+      }
+      /* font change character (&) */
+      if (N == 38) {
+	PSDumpRotSegment (f, segment, &Nseg);
+	if (string[i+1] == 'h') {
+	  SetRotFont ("helvetica", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  PSSetFont (f, currentname, currentsize);
+	}
+	if (string[i+1] == 't') {
+	  SetRotFont ("times", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  PSSetFont (f, currentname, currentsize);
+	}
+	if (string[i+1] == 'c') {
+	  SetRotFont ("courier", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  PSSetFont (f, currentname, currentsize);
+	}
+	if (string[i+1] == 's') {
+	  SetRotFont ("symbol", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	  PSSetFont (f, currentname, currentsize);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    segment[Nseg] = N;
+    Nseg ++;
+    CHECK_REALLOCATE (segment, char, NSEG, Nseg, 64);
+  }
+  PSDumpRotSegment (f, segment, &Nseg);
+  fprintf (f, "stroke grestore\n");
+  free (segment);
+  SetRotFont (basename, basesize);
+}
+
+void PSDumpRotSegment (FILE *f, char *segment, int *Nseg) {
+  segment[*Nseg] = 0;
+  fprintf (f, "(%s) show\n", segment);
+  bzero (segment, *Nseg);
+  *Nseg = 0;
+}
+
+void PSSetFont (FILE *f, char *name, int size) {
+  if (!strcmp (name, "times")) 
+    fprintf (f, "/Times-Roman findfont %d scalefont setfont\n", size);
+  if (!strcmp (name, "helvetica")) 
+    fprintf (f, "/Helvetica findfont %d scalefont setfont\n", size);
+  if (!strcmp (name, "courier")) 
+    fprintf (f, "/Courier findfont %d scalefont setfont\n", size);
+  if (!strcmp (name, "symbol")) 
+    fprintf (f, "/Symbol findfont %d scalefont setfont\n", size);
+}
+
+
+
+  /* test cross hair
+  fprintf (f, "%d %d %d %d L\n", x-10, y, x+10, y);
+  fprintf (f, "%d %d %d %d L\n", x, y-10, x, y+10);
+  */
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/RotFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/RotFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/RotFont.c	(revision 16632)
@@ -0,0 +1,124 @@
+# include <kapa_internal.h>
+# include "alphabet.h"
+  
+static int Nrotfonts;
+static FontSet *RotFonts;
+
+static char currentname[64];
+static int  currentsize;
+static double currentscale;
+static RotFont *currentfont;
+
+void InitRotFonts () {
+
+  int i, Nhardwired;
+
+  Nhardwired = sizeof (HardwiredFonts) / sizeof (FontSet);
+  
+  Nrotfonts = Nhardwired;
+  ALLOCATE (RotFonts, FontSet, Nrotfonts);
+  
+  for (i = 0; i < Nhardwired; i++) {
+    RotFonts[i] = HardwiredFonts[i];
+  }
+
+  currentfont = RotFonts[DEFFONT].font;
+  currentscale = 1.0;
+  strcpy (currentname, RotFonts[DEFFONT].name);
+  currentsize = RotFonts[DEFFONT].size;
+}
+
+int SetRotFont (char *name, int size) {
+  
+  int i, nsize, msize, bsize, bigger, dsize, match, good;
+
+  bigger = good = match = -1;
+  dsize = 10000;
+  bsize = 10000;
+  for (i = 0; i < Nrotfonts; i++) {
+    if (!strcasecmp (RotFonts[i].name, name)) {
+      good = i;
+      nsize = abs (RotFonts[i].size - size);
+      if (nsize < dsize) {
+	match = i;
+	dsize = nsize;
+      }
+      msize = RotFonts[i].size - size;
+      if ((msize < bsize) && (msize >= 0)) {
+	bigger = i;
+	bsize = msize;
+      }
+    }
+  }
+  
+  if ((match == -1) && (good != -1)) match = good;
+  if (bigger != -1) match = bigger;
+  if (match != -1) {
+    currentfont = RotFonts[match].font;
+    currentscale = (double) size / RotFonts[match].size;
+    currentsize = size;
+    strcpy (currentname, name);
+    return (TRUE);
+  } else {
+    fprintf (stderr, "no matching font\n");
+    return (FALSE);
+  }
+
+}
+  
+char *GetRotFont (int *size) {
+
+  *size = currentsize;
+  return (currentname);
+
+}
+
+RotFont *GetRotFontData (double *scale) {
+  *scale = currentscale;
+  return (currentfont);
+}
+
+int RotStrlen (char *c) {
+
+  int i, N, dX, code;
+  double scale; 
+  
+  scale = currentscale;
+
+  /* find string length */
+  dX = 0;
+
+  code = FALSE;
+  for (i = 0; i < strlen (c); i++) {
+    N = (int)(c[i]);
+    /* skip non-printing characters */
+    if ((N < 0) || (N >= NROT)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) { /* super-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 95) { /* sub-script */
+	scale *= 0.8;
+	continue;
+      }
+      if (N == 124) { /* normal-script */
+	scale = currentscale;
+	continue;
+      }
+      if (N == 92) { /* backslash */
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) { /* font-code */
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+    dX += scale*currentfont[N].dx + 1;
+  }
+  return (dX);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/bDrawFuncs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/bDrawFuncs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/bDrawFuncs.c	(revision 16632)
@@ -0,0 +1,418 @@
+# include <kapa_internal.h>
+
+static int bWeight;
+static int bType;
+static bDrawColor bColor;
+static bDrawBuffer *bBuffer;
+void bDrawCircleSingle (double xc, double yc, double radius);
+
+bDrawBuffer *bDrawBufferCreate (int Nx, int Ny) {
+
+  int i, j;
+  bDrawColor white;
+  bDrawBuffer *buffer;
+
+  white = KapaColorByName ("white");
+
+  ALLOCATE (buffer, bDrawBuffer, 1);
+  buffer[0].Nx = Nx;
+  buffer[0].Ny = Ny;
+
+  ALLOCATE (buffer[0].pixels, bDrawColor *, Ny);
+  for (i = 0; i < Ny; i++) {
+    ALLOCATE (buffer[0].pixels[i], bDrawColor, Nx);
+    for (j = 0; j < Nx; j++) {
+      buffer[0].pixels[i][j] = white;
+    }
+  }
+  return (buffer);
+}
+
+void bDrawBufferFree (bDrawBuffer *buffer) {
+
+  int i;
+
+  for (i = 0; i < buffer[0].Ny; i++) {
+    free (buffer[0].pixels[i]);
+  }
+  free (buffer[0].pixels);
+  free (buffer);
+  return;
+}
+
+void bDrawSetBuffer (bDrawBuffer *buffer) {
+  bBuffer = buffer;
+  return;
+}
+
+void bDrawSetStyle (bDrawColor color, int lw, int lt) {
+  bColor = color;
+  bWeight = lw;
+  bType = lt;
+  return;
+}
+
+// draw a point in the current color 
+void bDrawPoint (int x, int y) {
+
+  if (x < 0) return;
+  if (y < 0) return;
+  if (x >= bBuffer[0].Nx) return;
+  if (y >= bBuffer[0].Ny) return;
+  bBuffer[0].pixels[y][x] = bColor;
+  return;
+}
+
+// draw a point in the current color 
+void bDrawPointf (float x, float y) {
+
+  bDrawPoint (ROUND(x), ROUND(y));
+  return;
+}
+
+void bDrawTriOpen (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  bDrawLine (x1, y1, x2, y2);
+  bDrawLine (x2, y2, x3, y3);
+  bDrawLine (x3, y3, x1, y1);
+
+  return;
+}
+
+void bDrawRectOpen (double x1, double y1, double x2, double y2) {
+
+  int X1, Y1, X2, Y2;
+
+  if (x1 > x2) SWAP (x1, x2);
+  if (y1 > y2) SWAP (y1, y2);
+
+  X1 = MIN (MAX (ROUND (x1), 0), bBuffer[0].Nx - 1);
+  X2 = MIN (MAX (ROUND (x2), 1), bBuffer[0].Nx);
+
+  Y1 = MIN (MAX (ROUND (y1), 0), bBuffer[0].Ny - 1);
+  Y2 = MIN (MAX (ROUND (y2), 1), bBuffer[0].Ny);
+
+  bDrawLineHorizontal (X1, X2, Y1);
+  bDrawLineHorizontal (X1, X2, Y2);
+  bDrawLineVertical (X1, Y1, Y2);
+  bDrawLineVertical (X2, Y1, Y2);
+  return;
+}
+
+void bDrawRectFill (double x1, double y1, double x2, double y2) {
+
+  int i;
+  int X1, Y1, X2, Y2;
+
+  if (x1 > x2) SWAP (x1, x2);
+  if (y1 > y2) SWAP (y1, y2);
+
+  X1 = MIN (MAX (ROUND (x1), 0), bBuffer[0].Nx - 1);
+  X2 = MIN (MAX (ROUND (x2), 1), bBuffer[0].Nx);
+
+  Y1 = MIN (MAX (ROUND (y1), 0), bBuffer[0].Ny - 1);
+  Y2 = MIN (MAX (ROUND (y2), 0), bBuffer[0].Ny);
+
+  for (i = Y1; i < Y2; i++) {
+    bDrawLineHorizontal (X1, X2, i);
+  } 
+  return;
+}
+
+// identify the quadrant and draw the correct line
+void bDrawLine (double x1, double y1, double x2, double y2) {
+
+  int FlipDirect, FlipCoords;
+  int X1, Y1, X2, Y2, dX, dY;
+
+  /* rather than draw the line from float positions, we find the closest
+     integer end-points and draw the line between those pixels */ 
+
+  X1 = ROUND(x1);
+  Y1 = ROUND(y1);
+  X2 = ROUND(x2);
+  Y2 = ROUND(y2);
+
+  dX = X2 - X1;
+  dY = Y2 - Y1;
+
+  FlipCoords = (abs(dX) < abs(dY));
+  FlipDirect = FlipCoords ? (y1 > y2) : (x1 > x2);
+
+  if (!FlipDirect && !FlipCoords) bDrawLineWeight (X1, Y1, X2, Y2, FALSE);
+  if ( FlipDirect && !FlipCoords) bDrawLineWeight (X2, Y2, X1, Y1, FALSE);
+  if (!FlipDirect &&  FlipCoords) bDrawLineWeight (Y1, X1, Y2, X2, TRUE);
+  if ( FlipDirect &&  FlipCoords) bDrawLineWeight (Y2, X2, Y1, X1, TRUE);
+
+  return;
+}
+
+// draw a series of lines to give the line weight
+void bDrawLineWeight (int X1, int Y1, int X2, int Y2, int swapcoords) {
+
+  int dN, dNs, dNe;
+
+  dNs = -0.5*(bWeight - 1); 
+  /* 0, 0, 0, -1, -1, -2, -2 */
+
+  dNe = +0.5*bWeight + 1; 
+  /* 1, 1, 2, 2, 2, 3, 3 */
+
+  for (dN = dNs; dN < dNe; dN++) {
+    bDrawLineBresen (X1, Y1 + dN, X2, Y2 + dN, swapcoords);
+  }
+  return;
+}
+
+// use the Bresenham line drawing technique
+// integer-only Bresenham line-draw version which is fast
+void bDrawLineBresen (int X1, int Y1, int X2, int Y2, int swapcoords) {
+
+  int X, Y, dX, dY;
+  int e, e2;
+  int N, DashOn;
+
+  dX = X2 - X1;
+  dY = Y2 - Y1;
+
+  DashOn = TRUE;
+
+  Y = Y1;
+  e = 0;
+  for (X = X1, N = 0; X <= X2; X++, N++) {
+    if (bType == 1) { DashOn = (N % 10) < 5; }
+    if (bType == 2) { DashOn = (N % 6) < 3; }
+    if (swapcoords) {
+      if (DashOn) bDrawPoint (Y,X);
+    } else {
+      if (DashOn) bDrawPoint (X,Y);
+    }
+    e += dY;
+    e2 = 2 * e;
+    if (e2 > dX) {
+      Y++;
+      e -= dX;
+    } 
+    if (e2 < -dX) {
+      Y--;
+      e += dX;
+    }
+  }
+  return;
+}
+
+void bDrawLineHorizontal (int X1, int X2, int Y) {
+  
+  int i;
+
+  for (i = X1; i < X2; i++) {
+    bBuffer[0].pixels[Y][i] = bColor;
+  }
+  return;
+}
+
+void bDrawLineVertical (int X, int Y1, int Y2) {
+  
+  int i;
+
+  for (i = Y1; i < Y2; i++) {
+    bBuffer[0].pixels[i][X] = bColor;
+  }
+  return;
+}
+
+void bDrawTriFill (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  bDrawTriOpen (x1, y1, x2, y2, x3, y3);
+  return;
+}
+
+void bDrawArc (double Xc, double Yc, double Xr, double Yr, double Ts, double Te) {
+
+  float t, dt;
+  int x, y;
+
+  /* drawing a complete circle */
+//  if ((fabs(Te - Ts) > 360.0) && (Xr == Yr)) {
+//    bDrawCircle (Xc, Yc, Xr);
+//    return;
+//  }
+
+  /* only draw a single loop */
+  if (fabs(Te - Ts) > 360.0) {
+    Te = 360.0;
+    Ts = 0.0;
+  }
+
+  /* smallest angle is 1/Rmax */
+  dt = MAX (fabs(Xr * sin(Ts*RAD_DEG)), fabs(Yr * cos(Ts*RAD_DEG)));
+  dt = 1.0 / dt;
+
+  for (t = Ts*RAD_DEG; t <= Te*RAD_DEG; t += dt) {
+    x = Xr*cos(t) + Xc;
+    y = Yr*sin(t) + Yc;
+
+    /* we could use the value of MAX(dy/dt,dx/dt) to set dt */
+    bDrawPoint (x,y);
+
+    dt = MAX (fabs(Xr * sin(t)), fabs(Yr * cos(t)));
+    dt = 1.0 / dt;
+  }
+  return;
+}
+
+// draw a series of circles to give line weight
+void bDrawCircle (double xc, double yc, double radius) {
+
+  int dN, dNs, dNe;
+
+  dNs = -0.5*(bWeight - 1); 
+  /* 0, 0, 0, -1, -1, -2, -2 */
+
+  dNe = +0.5*bWeight + 1; 
+  /* 1, 1, 2, 2, 2, 3, 3 */
+
+  for (dN = dNs; dN < dNe; dN++) {
+    bDrawCircleSingle (xc, yc, radius + dN);
+  }
+  return;
+}
+
+// draw a pure circle  
+void bDrawCircleSingle (double xc, double yc, double radius) {
+
+  int Xc, Yc, Radius;
+  int x, y, d;
+
+  Xc = ROUND(xc);
+  Yc = ROUND(yc);
+  Radius = ROUND(radius);
+
+  x = 0;
+  y = Radius;
+
+  // d = 3 - 2*Radius;
+  d = 5 - 4*radius;
+
+  while (x <= y) {
+    bDrawPoint (Xc+x, Yc+y);
+    bDrawPoint (Xc+x, Yc-y);
+    bDrawPoint (Xc-x, Yc+y);
+    bDrawPoint (Xc-x, Yc-y);
+    bDrawPoint (Xc+y, Yc+x);
+    bDrawPoint (Xc+y, Yc-x);
+    bDrawPoint (Xc-y, Yc+x);
+    bDrawPoint (Xc-y, Yc-x);
+
+    if (d < 0) {
+      // d = d + 4*x + 6;
+      d = d + 8*x + 4;
+    } else {
+      // d = d + 4*(x-y) + 10;
+      d = d + 8*(x-y) + 8;
+      y--;
+    }
+    x++;
+  }
+}
+
+// draw a pure circle  
+void bDrawCircleFill (double xc, double yc, double radius) {
+
+  int Xc, Yc, Radius;
+  int x, y, d;
+
+  Xc = ROUND(xc);
+  Yc = ROUND(yc);
+  Radius = ROUND(radius);
+
+  x = 0;
+  y = Radius;
+
+  // d = 3 - 2*Radius;
+  d = 5 - 4*radius;
+
+  while (x <= y) {
+    bDrawLineHorizontal (Xc-x, Xc+x, Yc+y);
+    bDrawLineHorizontal (Xc-x, Xc+x, Yc-y);
+    bDrawLineHorizontal (Xc-y, Xc+y, Yc+x);
+    bDrawLineHorizontal (Xc-y, Xc+y, Yc-x);
+
+    if (d < 0) {
+      // d = d + 4*x + 6;
+      d = d + 8*x + 4;
+    } else {
+      // d = d + 4*(x-y) + 10;
+      d = d + 8*(x-y) + 8;
+      y--;
+    }
+    x++;
+  }
+}
+
+/* 
+the discriminant of inside or outside the circle is:
+
+f(x,y) = x^2 + y^2 - r^2
+
+- negative: (x,y) inside circle
+- positive: (x,y) outside circle
+
+given d(0) = f(x,y); find d(1) = f(x+1,y):
+d(1) = (x+1)^2 + y^2 - r^2
+d(1) = d(0) + 2x + 1
+(use d(1) if d(0) < 0, ie inside circle)
+
+given d(0) = f(x,y); find d(1) = f(x+1,y-1):
+d(1) = (x+1)^2 + (y-1)^2 - r^2
+d(1) = d(0) + 2x + 1 - 2y + 1
+d(1) = d(0) + 2(x-y) + 2
+
+* init d to f(1,r-1/2) instead of r, keeping the effective boundary 
+  between two pixels (also, an inside point)
+
+f(1,r-1/2) = 1 + (r-1/2)^2 - r^2 = 5/4 - r
+f(1,r-1/4) = 1 + (r-1/4)^2 - r^2 = 1 + r/2 + 1/16 = 17/16 + r/2
+
+f(1,r-x)   = 1 + (r-x)^2 - r^2 = 1 - 2xr + x^2 = A (3 - 2r)
+
+1+x^2 = 3A
+-2x = -2A
+
+A = x
+
+1 - 3x + x^2 = 0
+
+(3 +/- sqrt(9 - 4))/2 = (3 - sqrt(5))/2
+
+multiply all d values by 4 to get integer tests:
+
+d'(0) = 5 - 4r
+d'(in) = d' + 8x + 4
+d'(out) = d' + 8(x-y) + 8
+
+*/
+
+/* This is the Bresenham line-drawing algorithm for 1st and 4th quandrant
+   vectors with positive and negative slopes < 1. this is the sequence if we use
+   float errors and tests it is easy to understand, but slower than it could be
+
+  { 
+    float e, m;
+    m = dY / dX;
+    Y = Y1;
+    e = 0;
+    for (X = X1; X <= X2; X++) {
+      plot (X,Y);
+      e += m;
+      if (e > 0.5) {
+	Y++;
+	e -= 1.0;
+      }
+      if (e < -0.5) {
+	Y--;
+	e += 1.0;
+      }
+    }
+  }
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libkapa/src/bDrawRotFont.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libkapa/src/bDrawRotFont.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libkapa/src/bDrawRotFont.c	(revision 16632)
@@ -0,0 +1,211 @@
+# include <kapa_internal.h>
+
+# define NROTCHARS 256
+# define XPROC(x,y) (scale*(cs*((x) - x0) - sn*((y) - y0)) + X0)
+# define YPROC(x,y) (scale*(cs*((y) - y0) + sn*((x) - x0)) + Y0)
+# define NEARINT(x) ((x < 0) ? ((int)(x - 0.5)) : ((int)(x + 0.5)))
+  
+static bDrawColor black;
+static bDrawColor white;
+
+int bDrawRotText (int x, int y, char *string, int pos, double angle) {
+
+  unsigned char *bitmap;
+  char *currentname, basename[64]; 
+  int i, dy, dx, N, X, Y, code;
+  int dX, Xoff, dY, Yoff, YoffBase;
+  int currentsize, basesize;
+  double cs, sn, currentscale;
+  RotFont *currentfont;
+
+  white = KapaColorByName ("white");
+  black = KapaColorByName ("black");
+
+  currentname = GetRotFont (&currentsize);
+  currentfont = GetRotFontData (&currentscale);
+  strcpy (basename, currentname);
+  basesize = currentsize;
+
+  /* strip leading WHITESPACE */
+  stripwhite (string);
+  if (*string == 0) return (FALSE);
+  
+  /* compute string length */
+  cs = cos(angle*RAD_DEG);
+  sn = sin(angle*RAD_DEG);
+  dX = RotStrlen (string);
+  dY = currentfont[65].ascent;
+
+  /* apply appropriate offset */
+  Xoff = Yoff = 0;
+  switch (pos) {
+  case 0: Xoff =     -dX; Yoff = dY; break;
+  case 1: Xoff = -0.5*dX; Yoff = dY; break;
+  case 2: Xoff =       0; Yoff = dY; break;
+  case 3: Xoff =     -dX; Yoff = 0.5*dY; break;
+  case 4: Xoff = -0.5*dX; Yoff = 0.5*dY; break;
+  case 5: Xoff =       0; Yoff = 0.5*dY; break;
+  case 6: Xoff =     -dX; Yoff = 0; break;
+  case 7: Xoff = -0.5*dX; Yoff = 0; break;
+  case 8: Xoff =       0; Yoff = 0; break;
+  }
+
+  code = FALSE;
+
+  YoffBase = Yoff;
+  /* draw characters one-by-one */
+  for (i = 0; i < strlen(string); i++) {
+    N = (int)(string[i]);
+    if ((N < 0) || (N >= NROTCHARS)) continue;
+
+    /* check for special characters */
+    if (!code) {
+      if (N == 94) {
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	Yoff -= 0.5*currentscale*dY;
+	continue;
+      }
+      if (N == 95) { 
+	SetRotFont (currentname, (int)(0.8*currentsize));
+	currentfont = GetRotFontData (&currentscale);
+	Yoff += 0.5*currentscale*dY;
+	continue;
+      }
+      if (N == 124) {
+	SetRotFont (currentname, basesize);
+	currentfont = GetRotFontData (&currentscale);
+	Yoff = YoffBase;
+	continue;
+      }
+      if (N == 92) {
+	code = TRUE;
+	continue;
+      } 
+      if (N == 38) {
+	if (string[i+1] == 'h') {
+	  SetRotFont ("helvetica", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 't') {
+	  SetRotFont ("times", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 'c') {
+	  SetRotFont ("courier", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	if (string[i+1] == 's') {
+	  SetRotFont ("symbol", currentsize);
+	  currentfont = GetRotFontData (&currentscale);
+	}
+	i++;
+	continue;
+      }
+    }
+    code = FALSE;
+
+    bitmap = currentfont[N].bits;
+    dx = currentfont[N].dx;
+    dy = currentfont[N].dy;
+    X = x + (int)(Xoff*cs - Yoff*sn) + (int)(currentscale*currentfont[N].ascent*sn);
+    Y = y + (int)(Xoff*sn + Yoff*cs) - (int)(currentscale*currentfont[N].ascent*cs);
+    bDrawRotBitmap (X, Y, dx, dy, bitmap, TRUE, angle, currentscale);
+    Xoff += 1 + (int)(currentscale*dx + 0.5);
+  }
+  SetRotFont (basename, basesize);
+  return (TRUE);
+}
+
+int bDrawRotBitmap (int x, int y, int dx, int dy, unsigned char *bitmap, int mode, double angle, double scale) {
+
+  int ii, jj, byte_line, byte, bit, flag;
+  bDrawColor color;
+  double i, j, cs, sn, rscale, tmp;
+  int X, Y, X0, X1, X2, Y0, Y1, Y2, x0, y0;
+
+  /* this mode option is nort actually used... */
+  if (mode) {
+    color = black;
+  } else {
+    color = white;
+  } 
+    
+  byte_line = (int) ((dx + 7) / 8);
+
+  cs = cos(angle*RAD_DEG);  sn = sin(angle*RAD_DEG);
+  rscale = 1.0 / scale;
+
+  X0 = 0;
+  Y0 = 0;
+  x0 = 0;
+  y0 = 0;
+
+  X2 = X1 = XPROC (0,0);
+  Y2 = Y1 = YPROC (0,0);
+
+  X = XPROC (dx,0);
+  Y = YPROC (dx,0);
+# ifdef DRAWBOXES
+  bDrawLine (x+X, y+Y, x+X1, y+Y1);
+  Xt = X;
+  Yt = Y;
+# endif
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+
+  X = XPROC (dx,dy);
+  Y = YPROC (dx,dy);
+# ifdef DRAWBOXES
+  bDrawLine (x+X, y+Y, x+Xt, y+Yt);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  X = XPROC (0,dy);
+  Y = YPROC (0,dy);
+# ifdef DRAWBOXES
+  bDrawLine (x+X, y+Y, x+Xt, y+Yt);
+  Xt = X;
+  Yt = Y;
+# endif
+  Y1 = MIN (Y, Y1);
+  Y2 = MAX (Y, Y2);
+  X1 = MIN (X, X1);
+  X2 = MAX (X, X2);
+
+  bDrawSetStyle (color, 0, 0);
+  if (scale > 1) {
+    for (i = X1; i <= X2; i+=1) {
+      for (j = Y1; j <= Y2; j+=1) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	if (flag) bDrawPointf (x + i, y + j);
+      }
+    }
+  } else {
+    for (i = X1; i <= X2; i+=scale) {
+      for (j = Y1; j <= Y2; j+=scale) {
+	tmp = rscale*(cs*(i - X0) + sn*(j - Y0)) + x0;  ii = NEARINT (tmp);
+	tmp = rscale*(cs*(j - Y0) - sn*(i - X0)) + y0;  jj = NEARINT (tmp);
+	if ((ii < 0) || (ii >= dx) || (jj < 0) || (jj >= dy)) continue;
+	byte = byte_line * jj + (ii / 8);
+	bit = ii % 8;
+	flag = 0x01 & (bitmap[byte] >> bit);
+	if (flag) bDrawPointf (x + i, y + j);
+      }
+    }
+  }
+  bDrawSetStyle (black, 0, 0);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+lib
Index: /branches/eam_branch_20080223/Ohana/src/libohana/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/Makefile	(revision 16632)
@@ -0,0 +1,62 @@
+default: install
+help:
+	@echo "make options: install libohana clean dist"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/libohana
+BIN	= 	$(HOME)/bin
+LIB	= 	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	=	$(HOME)/include
+TESTDIR =       $(HOME)/test
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+TFLAGS        = $(FULL_CFLAGS) $(FULL_LDFLAGS) -ltap_ohana
+
+install: $(DESTLIB)/libohana.a $(DESTLIB)/libohana.$(DLLTYPE)
+libohana: $(LIB)/libohana.$(ARCH).a $(LIB)/libohana.$(ARCH).$(DLLTYPE)
+testcode: install $(TEST)
+test:
+	make testcode
+	for i in $(TEST); do $$i; done
+
+INCS = \
+$(DESTINC)/ohana_allocate.h \
+$(DESTINC)/ohana_sort.h \
+$(DESTINC)/ohana.h
+
+OBJS = \
+$(SRC)/ohana_allocate.$(ARCH).o  \
+$(SRC)/sorts.$(ARCH).o		 \
+$(SRC)/string.$(ARCH).o		 \
+$(SRC)/findexec.$(ARCH).o	 \
+$(SRC)/glockfile.$(ARCH).o	 \
+$(SRC)/time.$(ARCH).o		 \
+$(SRC)/gaussj.$(ARCH).o		 \
+$(SRC)/config.$(ARCH).o		 \
+$(SRC)/Fread.$(ARCH).o		 \
+$(SRC)/IOBufferOps.$(ARCH).o	 \
+$(SRC)/CommOps.$(ARCH).o	 \
+$(SRC)/version.$(ARCH).o
+
+TEST = \
+$(TESTDIR)/string.$(ARCH)
+
+$(OBJS): $(INCS)
+
+$(LIB)/libohana.$(ARCH).a: $(OBJS)
+$(LIB)/libohana.$(ARCH).$(DLLTYPE): $(OBJS)
+
+$(DESTLIB)/libohana.a:  $(LIB)/libohana.$(ARCH).a
+$(DESTLIB)/libohana.$(DLLTYPE): $(LIB)/libohana.$(ARCH).$(DLLTYPE)
+
+$(TESTDIR)/%.$(ARCH) : $(TESTDIR)/%.c
+	$(CC) $^ -o $@ $(TFLAGS)
+
+.PHONY: test
+
Index: /branches/eam_branch_20080223/Ohana/src/libohana/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,66 @@
+
+- libohana 1.8.1 : 2006.10.04
+  * added tap-based tests
+  * added strsubs functions
+
+- libohana 1.8 : 2006.08.23
+  * cleanups in ohana.h
+  * moved gaussj to libohana
+  * added PrintIOBuffer functions
+  * added check_dir_access 
+  * added ohana_lst to time.c
+
+- libohana 1.7
+  * added 'mode' to mkdirhier
+  * moved _check_permissions to check_file_exec
+
+- libohana 1.6
+  * added check_file_access (check parent dirs and permissions)
+  * cleaned up signed/unsigned inconsistencies
+  * allow date_to_set to handle enclosing quotes
+
+libohana-1-5
+  moved dvo functions to libdvo
+  made libfits depend on libohana
+  added IOBuffer and Comm functions to libohana
+  added time functions from opihi and others
+  moved Fseek into findexec.c
+
+2005.10.07
+
+	I was having some memory collision problems, and attempting to
+	use the ohana_allocate functions reminded me that the libFITS
+	functions were not supported under ohana_allocate.  This was
+	unhelpful.  I bit the bullet and split libohana into libohana
+	(base functions only, including ohana_allocate) and libdvo
+	(functions based on the libautocode structures).  Doing this
+	allowed me to make libFITS depend on libohana (including
+	ohana_allocate).  BUT, this forced me to change all LDFLAGS
+	entries in ohana to swap -lohana -lFITS for -lFITS -lohana,
+	and to add include <fitsio.h> in some cases.
+
+libohana-1-4
+  further cleanup of the autocode system
+  eliminated the elixir.h, panstarrs.h, loneos.h files:
+   these are now completely absorbed into libautocode
+  minor improvements to ohana_allocate
+
+libohana-1-3
+  changed meaning of PLY / WRP / DIS (see coordtrans.txt)
+  added check on ALLOCATE/REALLOCATE to avoid failures on Nvalues < 1
+  added ohana_allocate system (memory tracking)
+  added autocode elements (refers to libautocode)
+  cleanup glockfile APIs
+
+libohana-1-2
+  added 'STG' to allowed coordinate transforms (inaccurate & stop-gap)
+  set default Npolyterms to 1
+  initialized filemode in glockfile.c
+
+libohana-1-1
+  dropped the configuration source ./.(name)rc : was just confusing
+  in glockfile : made closing a NULL file OK
+  added imreg_datatypes (part of imregister-1-1 datatype reorganization)
+
+libohana-1-0
+  import to CVS
Index: /branches/eam_branch_20080223/Ohana/src/libohana/doc/VERSIONS
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/doc/VERSIONS	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/doc/VERSIONS	(revision 16632)
@@ -0,0 +1,5 @@
+
+tag names used by libohana:
+
+TAG         : Comment
+libohana-1-0 : first version under CVS
Index: /branches/eam_branch_20080223/Ohana/src/libohana/doc/autocode.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/doc/autocode.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/doc/autocode.txt	(revision 16632)
@@ -0,0 +1,71 @@
+
+This directory contains a collection of autocoded FITS I/O routines
+used to define FITS Table DB functions.  
+
+The autocoder program is a perl script 'generate'.  This scripts takes
+as input a schema file and a template source code file, and produces
+an output file from these two inputs.  A single schema file is meant
+to be associated with a single data concept which is being coded.  For
+example, in the case of the FITS DB tables, a single schema file
+defines a single FITS table, or equivalently, a single C structure
+representing a row in that FITS table.
+
+Schema File
+
+The schema file currently consists of two types of information.
+
+First, there are simple keyword / name pairs which the autocoder
+simply applies as a direct replacement anywhere in the template.  For
+example, the keyword NAME replaces any instance of "$NAME" in the
+template with the corresponding value.  
+
+Second, there is a special type of keyword: FIELD.  The FIELD entry
+defines an entry in the data structure.  The FIELD entry is followed
+by the following comma-separated pieces of information:
+
+- the element name
+- the element data type
+- the element description
+- the element physical unit
+
+Template File
+
+The template file is a source code in whatever language is desired.
+Within the template, the defined keywords may be used as desired,
+wherever needed.  In addition, there are special directives which
+invoke additional special behavior.  All special directives have the
+form of comments within their target language.  They are replaced with
+a block of code in that target language, normally one which iterates
+over the FIELD elements of the schema file.  As such, the directive
+appropriate for one language should not be used within code for a
+different language.  Here is a list of existing special directives:
+
+/** STRUCT DEFINITION **/
+
+This tells the autocoder to create a structure definition for the
+schema.  The structure definition creates a structure with elements
+based on the FIELD entries, with the name $NAME (NOTE: this is perhaps
+making too much of an assumption.  we could require the template to
+provide the wrapper: "typedef struct { } $NAME;" and have the
+autocoder only insert the field lines).  
+
+/** TABLE DEFINITION **/
+
+This tells the autocoder to output the lines which add a column to an
+exiting empty table.  The assumption is that the template contains
+code to initialize a table.  It then invokes the table definition
+code, which defines each of the appropriate columns.  This is perhaps
+followed by some code which finalizes the table definition.  (Note:
+the code output by the autocoder in this block is not very flexible:
+it the current example, it explicitly uses the Elixir FITS Table
+functions, and refers to some data elements in the template code.  The
+latter could possibly be more abstracted with the keyword / value
+pairs, but in any case, the autocoded lines will have to be
+constructed somewhat by hand for a specific API set.
+
+/** BYTE SWAP **/
+
+This tells the autocoder to output code defining the byte swaps
+appropriat to the data structure.  Again, the resulting code depends a
+bit on the intended use and API set.
+
Index: /branches/eam_branch_20080223/Ohana/src/libohana/doc/coords_minimal.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/doc/coords_minimal.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/doc/coords_minimal.c	(revision 16632)
@@ -0,0 +1,115 @@
+/* 
+here is some C code to project from R,D to x,y (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+# define FULLPROJECTION 0
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+RD_to_XY (double *x, double *y, double R, double D, double Ro, double Do) {
+
+  double sdp, cdp, salp, calp, sdel, cdel, stht, sphi, cphi;
+                 
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  salp = sin(RAD_DEG*(ra - Ro));
+  calp = cos(RAD_DEG*(ra - Ro));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+  
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) { return 0; /* projection from the wrong side of the sphere */ }
+  
+  X =  DEG_RAD * sphi;
+  Y = -DEG_RAD * cphi;
+  
+# if (FULLPROJECTION) 
+  
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+
+  tmp_d = 1.0 / (pc_1_1*pc_2_2 - pc_1_2*pc_2_1); 
+  *x = tmp_d * (pc_2_2*X - pc_1_2*Y) / cdelt1 + Xo;
+  *y = tmp_d * (pc_1_1*Y - pc_2_1*X) / cdelt2 + Yo;
+
+# else
+
+  *x = X;
+  *y = Y;
+  
+# endif
+
+
+  return (1);
+
+}
+
+
+/* 
+here is some C code to project from x,y to R,D (all in decimal
+degrees) in a SIN projection, with Ro, Do as projection center:
+*/
+
+XY_to_RD (double *ra, double *dec, double x, double y, double Ro, double Do) {
+
+
+  double L, M, X, Y, T, Z;
+  double R, sphi, cphi, stht, ctht;
+  double alpha, delta, salp, calp, sdel, sdp, cdp;
+  
+  *ra  = 0;
+  *dec = 0;
+  stht = ctht = 1;
+
+  
+# if (FULLPROJECTION) 
+  /* 
+     these lines allow for a rotation / distortion 2x2 matrix (pci_j),
+     a (two direction) plate-scale shift (cdelt1, cdelt2), 
+     and a reference center offset of Xo, Yo, if desired. 
+  */
+  X = cdelt1 * (x - Xo);
+  Y = cdelt2 * (y - Yo);
+
+  L = (X*pc1_1 + Y*pc1_2);
+  M = (X*pc2_1 + Y*pc2_2);
+# else 
+  L = x;
+  M = y;
+# endif
+
+  R = hypot (L,M);
+  if ((L == 0) && (M == 0)) {
+    sphi = 0;
+    cphi = 1;
+  }
+  else {
+    sphi =  L / R;
+    cphi = -M / R;
+  }
+
+  ctht = RAD_DEG * R;
+  stht = sqrt (1 - ctht*ctht);
+
+  sdp  = sin(RAD_DEG*Do);
+  cdp  = cos(RAD_DEG*Do);
+  
+  sdel = stht*sdp - ctht*cphi*cdp;
+  salp = ctht*sphi;
+  calp = stht*cdp + ctht*cphi*sdp;
+  alpha = atan2 (salp, calp);
+  delta = asin (sdel);
+  
+  *ra  = DEG_RAD*alpha + Ro;
+  *dec = DEG_RAD*delta;
+  
+  return (1);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libohana/doc/coordtrans.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/doc/coordtrans.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/doc/coordtrans.txt	(revision 16632)
@@ -0,0 +1,70 @@
+
+I have changed the meaning of coord type PLY from the historical
+meaning.  The only previous use that is in a DVO-style database is in
+the loneos data (all cfht data needed to go to linear terms).  these
+can be easily converted by changing from PLY to DIS.
+
+There are now three types of higher-order transformation which may be
+used depending on the circumstance.  The new naming scheme is:
+
+PLY : a cartesian transformation (ie, no projection implied)
+DIS : equivalent to TAN projection with up-to-3rd order polynomial
+WRP : a second-level cartesian transformation, implying the presence
+      of a DIS coord frame (must be registered with libohana function)
+
+{ 
+
+  X = coords[0].cdelt1*(x - coords[0].crpix1);
+  Y = coords[0].cdelt2*(y - coords[0].crpix2);
+  L = (X*coords[0].pc1_1 + Y*coords[0].pc1_2);
+  M = (X*coords[0].pc2_1 + Y*coords[0].pc2_2);
+  R = hypot (L,M);
+  if ((L == 0) && (M == 0)) {
+    sphi = 0;
+    cphi = 1;
+  } else {
+    sphi =  L / R;
+    cphi = -M / R;
+  }
+  if (R == 0) {
+    stht = 1.0;
+    ctht = 0.0;
+  } else {
+    T = DEG_RAD / R;
+    stht =   T / sqrt ( 1.0 + T*T);
+    ctht = 1.0 / sqrt ( 1.0 + T*T);
+  }
+  sdp  = sin(RAD_DEG*coords[0].crval2);
+  cdp  = cos(RAD_DEG*coords[0].crval2);
+    
+  sdel = stht*sdp - ctht*cphi*cdp;
+  salp = ctht*sphi;
+  calp = stht*cdp + ctht*cphi*sdp;
+  alpha = atan2 (salp, calp);
+  delta = asin (sdel);
+    
+  *ra  = DEG_RAD*alpha + coords[0].crval1;
+  *dec = DEG_RAD*delta;
+}
+
+RD_to_XY () {
+
+  sdp  = sin(RAD_DEG*coords[0].crval2);
+  cdp  = cos(RAD_DEG*coords[0].crval2);
+  salp = sin(RAD_DEG*(ra - coords[0].crval1));
+  calp = cos(RAD_DEG*(ra - coords[0].crval1));
+  sdel = sin(RAD_DEG*dec);
+  cdel = cos(RAD_DEG*dec);
+
+  stht = sdel*sdp + cdel*cdp*calp;    /* sin(theta) */
+  sphi = cdel*salp;                   /* = cos(theta)*sin(phi) */
+  cphi = cdel*sdp*calp - sdel*cdp;    /* = cos(theta)*cos(phi) */
+  if (stht < 0) status = FALSE;
+
+  X =  DEG_RAD * sphi / stht;
+  Y = -DEG_RAD * cphi / stht;
+  tmp_d = 1.0 / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  *x = tmp_d * (coords[0].pc2_2*X - coords[0].pc1_2*Y) / coords[0].cdelt1 + coords[0].crpix1;
+  *y = tmp_d * (coords[0].pc1_1*Y - coords[0].pc2_1*X) / coords[0].cdelt2 + coords[0].crpix2;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/doc/gaussj_bevington.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/doc/gaussj_bevington.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/doc/gaussj_bevington.c	(revision 16632)
@@ -0,0 +1,466 @@
+// ----------------------- invert a matrix
+double MatInv()	
+{
+	int i, j, k, L, ik[10], jk[10];
+	double aMax, save, det;
+	
+	det = 0;
+//------------------------------------  find largest element 
+	for (k = 1; k <= g_m; k++)
+	{
+		aMax = 0;
+FIND_AMAX:	
+		for (i = k; i <= g_m; i++)
+		{
+			for (j = k; j <= g_m;j++)
+			{
+				if  (fabs(alpha[i][j]) > fabs(aMax)) 
+				{
+					aMax = alpha[i][j];
+					ik[k] = i;
+					jk[k] = j;
+				}   //if
+			}  //for j
+		}  //for i
+		if (aMax == 0)  return(det);  //with 0 determinant as signal
+		det = 1;
+// -------------------------------------- interchange rows and columns to put aMax in alpha[k,k]---
+		i = ik[k];
+		if (i < k) goto FIND_AMAX;
+		else if (i > k) 
+		{
+			for (j = 1;j <= g_m;j++)
+			{
+				save = alpha[k][j];
+				alpha[k][j] = alpha[i][j];
+				alpha[i][j] = -save;
+			}	  //for j
+		}  //else if 
+		j = jk[k];
+		if	(j < k) goto FIND_AMAX;
+		else if (j > k)
+		{
+			for (i = 1; i <= g_m; i++)
+			{
+				save = alpha[i][k];
+				alpha[i][k] = alpha[i][j];
+				alpha[i][j] = -save;
+			}	 //for i
+		}//else if j
+// ---------------------------------------- accumulate elements of inverse matrix 
+		for (i = 1; i <= g_m; i++)
+		{
+			if (i != k) alpha[i][k] = -alpha[i][k]/aMax;
+		}	//for i
+		for (i = 1; i <= g_m; i++)
+		{
+			for (j = 1; j <= g_m;j++) 
+			{
+				if ((i != k) && (j != k)) alpha[i][j] = alpha[i][j] + alpha[i][k]*alpha[k][j];
+			}	//for j
+		}   //for i
+		for (j = 1; j <= g_m;j++)
+		{
+			if (j != k)  alpha[k][j] = alpha[k][j]/aMax;
+		}           //for j
+		alpha[k][k] = 1/aMax;
+		det = det * aMax;
+	} //for k
+// ------------------------------------------ restore ordering of matrix 
+	for (L = 1; L <= g_m; L++)  
+	{
+		k = g_m + 1 - L;
+		j = ik[k];
+		if (j > k) 
+		{
+			for (i = 1; i <= g_m; i++) 
+			{
+				save        = alpha[i][k];
+				alpha[i][k] = -alpha[i][j];
+				alpha[i][j] = save;
+			}  //for i
+		}  //if j
+		i = jk[k];
+		if (i > k)
+		{
+			for (j = 1; j <= g_m;j++)
+			{
+				save        =  alpha[k][j];
+				alpha[k][j] = -alpha[i][j];
+				alpha[i][j] =  save;
+			} //for j
+		} //if i
+	}  //for L
+	return(det);
+}
+
+void SquareByRow()  // multiply square matrix by row matrix
+{
+	int		i,j;
+								
+	for (i = 1; i <= g_m; i++) 
+	{
+		if(g_linearFn)
+		{
+			a[i]  = 0.0;
+			for (j= 1; j<= g_m;j++)
+				a[i] = a[i] + beta[j]*alpha[i][j];
+		}
+		else
+		{
+			da[i] = 0.0;
+			for (j= 1; j<= g_m;j++)
+				da[i] = da[i] + beta[j]*alpha[i][j];
+		}
+	}
+		
+}
+
+// ----Standard deviations calc'd from chiSq change of 1 (parabola fit at Xi2 minimum)
+void  SigParab()
+{
+	int j;
+
+	for(j = 1; j<= g_m; j++)
+	{
+		chiSq2 = CalcChiSq();
+		a[j]   = a[j] + deltaa[j];
+		chiSq3 = CalcChiSq();
+		a[j]   = a[j] - 2*deltaa[j];
+		chiSq1 = CalcChiSq();
+		a[j]   = a[j] + deltaa[j];
+		siga[j] = deltaa[j]*sqrt(2/(chiSq1-2*chiSq2+chiSq3));
+	}
+}
+// ---standard deviations as sqrt of diagonal elements of eror matrix.
+void SigMatrix()
+{
+	int j;
+	for (j = 1; j <= g_m;j++)		
+
+		siga[j] = sqrt(alpha[j][j]);
+}
+
+//-------------------------  Non-linear Fits ------------------------------------
+
+//Numerical Derivatives------------------------------
+// Can be replaced by analytic derivatives, if they can be calculated. 
+// However, numerical calculation is general, and convenient.
+double dXiSq_da(int j)		//See Eq. 8.26 - this sums over nPts
+{
+	double  static XiSq0;
+	double   XiSqPlus, dXiSqDa;
+
+	if (j == 1)   
+		XiSq0 = CalcChiSq();				//starting point-calculate it once
+	a[j] = a[j] + deltaa[j];
+	XiSqPlus  = CalcChiSq();
+	a[j] = a[j] - deltaa[j];		//restore
+	dXiSqDa   =  (XiSqPlus - XiSq0)/(deltaa[j]);
+	return (dXiSqDa);
+}
+
+double d2XiSq_da2(int j) // See Eq. 8.35  - this sums over nPts
+{
+	double tem; 
+	int i;
+
+	if (j == 1) 
+		for (i = 1; i<= g_nPts; i++) 
+			y_0[i] = yFunction(x[i]);		//Starting point-calculate it once
+	a[j] = a[j] + deltaa[j];
+	tem = 0.0;
+	for (i = 1; i <= g_nPts; i++)
+		{
+			dYda[i][j] = (yFunction(x[i]) - y_0[i])/deltaa[j]/sigY[i];
+			tem  = tem + sqr(dYda[i][j]);
+		}
+		a[j] = a[j] - deltaa[j];
+		return(2*tem);
+}
+
+double d2XiSq_dajk(int j, int k)	//See Eq. 8.35
+{
+	double tem = 0.0;
+	int i;
+	for (i = 1; i <= g_nPts; i++)
+	{
+ 		tem = tem + dYda[i][j]*dYda[i][k];
+	}
+	return(2*tem);
+}
+
+// ====================  Non-linear Fitting Routines ==================================
+//---------------------------- GridSearch ---------------------------------------------
+
+// Program 8.1:Non-linear least-squares fit by the grid-search method
+
+void Gridls(double &chiSqr)
+{
+//
+	double delta;
+	double save, delta1, del1, del2, aa, bb, cc, disc, alpha, x1, x2;
+	int j;
+
+	//cout << "enter Grids, x[1], y[1] " <<x[1] <<"  "<<y[1]<<"  ";  cin >> j;
+
+	chiSq2 = CalcChiSq();
+// -find local minimum for each parameter- 
+	for (j = 1; j <= g_m;j++)
+    {
+		delta    = deltaa[j];
+		a[j]     = a[j] + delta;
+		chiSq3   = CalcChiSq();
+		if (chiSq3 > chiSq2) 
+		{                  //started in wrong direction
+			delta  = -delta;
+			a[j]   =  a[j] + delta;
+			save   =  chiSq2;    //interchange 2 and 3 so 3 is lower
+			chiSq2 =  chiSq3;
+			chiSq3 =  save;
+		}
+// -Increment or decrement a[j] until chi squared increases- 
+		do
+		{
+			chiSq1 = chiSq2; //move back to prepare for quad fit
+			chiSq2 = chiSq3;
+			a[j]   = a[j] + delta;
+			chiSq3 = CalcChiSq();
+		}  while (chiSq3 < chiSq2);
+   
+// -Find minimum of parabola defined by last three points  -
+		del1 = chiSq2 - chiSq1;
+		del2 = chiSq3 - 2*chiSq2 + chiSq1;
+		delta1 = delta * (del1/del2 + 1.5);
+		a[j] = a[j]  - delta1;
+		chiSq2 = CalcChiSq();    //	at new local minimum
+// -Adjust delta for change of 2 from chiSq at minimum  -
+		aa = del2/2;								//chiSq = aa*sqr(a[j] + bb*a[j] + cc
+		bb = del1 - del2/2;
+		cc = chiSq1-chiSq2;
+		disc = sqr(bb) -4*aa*(cc-2);				//chiSqr difference=2
+		if (disc > 0) 								//if not true, then probably not parabolic yet
+		{
+			disc = sqrt(disc) ;
+			alpha = (-bb - disc)/(2*aa);
+			x1 = alpha*delta +  a[1] - 2*delta;		//	a[j] at chiSq minimum+2
+			disc = sqr(bb) - 4*aa*cc;
+			if (disc > 0) 
+				disc=sqrt(disc); 
+			else 
+				disc=0;		// elim round err
+			alpha = (-bb - disc)/(2*aa);
+			x2 = alpha*delta + a[1] - 2*delta;		// at chiSq minimum
+			delta = x1 - x2;
+			deltaa[j] = delta;
+		}
+	}    // for j = 1 to m}
+  chiSqr = chiSq2;
+}
+
+//---------------------------- GradSearch ---------------------------------------------
+//Program 8.2 Non-linear least-squares fit by gradient-search method}
+
+	double	grad[10];
+void Gradls(double &chiSqr, double stepDown)
+// label  5;
+{
+	double stepSum,step1;
+	double fract = 0.001;
+	int   j;
+
+	CalcGrad();   //calculate the gradient
+//-Evaluate chiSqr at new point and make sure chiSqr decreases-
+	do
+	{
+		for (j = 1; j <= g_m;j++)
+			a[j] = a[j] + stepDown * grad[j]; //slide down
+		chiSq3 = CalcChiSq();
+		if (chiSq3 >= chiSq2)
+		{                         //must have overshot minimum
+			for (j = 1; j <= g_m;j++)
+				a[j] = a[j] - stepDown * grad[j]; //restore
+			stepDown = stepDown/2;              //decrease stepSize
+		}
+	} while (chiSq3 > chiSq2);
+	stepSum = 0;
+// -- Increment parameters until chiSqr starts to increase -- 
+	do
+	{
+		stepSum = stepSum + stepDown;   //counts total increment
+		chiSq1 = chiSq2;
+		chiSq2 = chiSq3;
+		for (j = 1; j <= g_m;j++) 
+			a[j] = a[j] + stepDown * grad[j];
+		chiSq3 = CalcChiSq();
+	} while (chiSq3 <= chiSq2);
+// -- Find minimum of parabola defined by last three points -- 
+	step1=stepDown*((chiSq3-chiSq2)/(chiSq1-2*chiSq2+chiSq3)+0.5);
+	for (j = 1; j <= g_m;j++)
+		a[j] = a[j] - step1 * grad[j];    //move to minimum
+	chiSqr = CalcChiSq();
+	stepDown = stepSum;                 //start with this next time
+}
+
+void CalcGrad()
+{
+	double fract = 0.001;
+	int   j;
+	double  dA, sum;
+
+	sum = 0.0;
+	chiSq2 = CalcChiSq();
+
+	for (j = 1; j <=  g_m;j++)
+  {
+		dA  = fract * deltaa[j];     //differential element for gradent
+		a[j]    = a[j] + dA;
+		chiSq1  = CalcChiSq();
+		a[j]    = a[j] - dA;
+		grad[j] = chiSq2 - chiSq1;   //2*da*grad
+		sum     = sum + sqr(grad[j]);
+  }
+	for (j = 1; j <= g_m;j++)
+		grad[j] =  deltaa[j]*grad[j]/sqrt(sum); //step * grad
+}
+
+//----------------------------------- Expand Function -------------------------------------
+//Program  8.3: Non-linear least-squares fit by expansion of the fitting function
+ 
+void ChiFit(double &chiSqr)			// double  det, chiSq1;
+{
+	int  j;
+	double det;
+
+	MakeBeta();
+	MakeAlpha();
+	det = MatInv();					// Invert matrix
+	SquareByRow();				// Evalulate parameter increments
+	for (j = 1; j <= g_m;j++)
+		a[j] = a[j] + da[j];	// Increment to next solution. 
+	chiSqr= CalcChiSq();
+	return;
+}
+
+// ------------------------------------- Marquard ---------------------------------------------
+//Program 8.4: Non-linear least-squares fit by the gradient-expansion (Marquardt) method
+
+void Marquardt(double &chiSqr, double chiCut, double lambda)
+{
+	int  j;
+	double  det, chiSq1;
+
+TOP:
+	MakeBeta();
+	MakeAlpha();
+	for (j = 1; j <= g_m;j++) 
+		alpha[j][j] = (1 + lambda) * alpha[j][j];
+	det = MatInv();					// Invert matrix 
+	if (lambda > 0)					//On final call, enter with lambda = 0 to get the error matrix
+	{
+		SquareByRow();//Evaluate parameter increments 
+		chiSq1 = chiSqr;
+		for (j = 1; j <= g_m; j++)
+			a[j] = a[j] + da[j];	//Incr to next solution
+		chiSqr = CalcChiSq();
+		if (chiSqr > (chiSq1 + chiCut) )
+		{
+			for (j = 1; j <= g_m; j++)
+				a[j]=a[j]-da[j];	//Return to prev solution
+			chiSqr = CalcChiSq();
+			lambda = 10*lambda;		//and repeat the calc, with larger lambda
+			goto TOP;
+		}
+		lambda = 0.1 * lambda;
+	}
+}
+
+// --------------------------------  Output to Disk File -------------------------------------------
+
+void FitOut(char outFile[], double chi2, char aErrorsFrom)
+{
+	int i, k, j ,nFree;
+	double X2Prob, chi2PerDof;
+
+	ofstream fOut(outFile);			// open file for output 
+	fOut << setiosflags(ios::fixed |ios::showpoint);
+	
+	nFree = g_nPts-g_m;
+	chi2PerDof = chi2/nFree;
+	X2Prob = 100*ChiProb(nFree, chi2);
+	switch(aErrorsFrom)
+	{
+		case 'D':			// already calculated in LineFit
+			;			
+		break;
+		case 'C':			// vary chi^2 by 1
+			SigParab();		
+		break;
+		case 'M':			// error Matrix
+			SigMatrix();
+		break;
+	}
+
+	fOut << title <<endl; 
+	fOut ;
+	fOut 
+		<< " ChiSqr =" 
+		<< setprecision(1)<<chi2 
+		<< " for " 
+		<< nFree 
+		<<" deg of freedom," 
+		<<" chiSqr/dof =" 
+		<< setprecision(1)<<chi2PerDof 
+		<< " Prob =" 
+		<< setprecision(1)<< X2Prob
+		<<"%"
+		<< endl;
+	fOut 
+		<< " Fitted Parameters:  a[i] +- sig-a[i]"
+		<< endl;
+	for (i = 1; i <= g_m; i++)  	
+		fOut 
+			<<setprecision(4)<<setw(10) << a[i]
+			<<"  +-  "
+			<<setw(10)<< siga[i]
+			<< "  " 
+			<< endl;
+	fOut << endl; 	
+
+	if (!(aErrorsFrom == 'M'))
+		cout <<  endl <<" Output written to disk file " << outFile << endl;
+	else
+	{
+		fOut << " Error Matrix" << endl;
+		for (k = 1; k <= g_m; k++)
+		{
+			for (j = 1; j <= g_m;j++)
+			{ 
+				fOut 
+					<<"    "
+					<< setprecision(8) <<setw(12) 
+					<< alpha[k][j];
+			}
+			fOut << endl;
+		}
+		fOut << endl;
+		cout << endl <<" Output written to disk file " << outFile << endl;
+	}
+
+// Tabulate data with fitted Y
+	fOut << "      pt #             X(cm)      Y            dY         yCalc " << endl;
+	for (i = 1; i <= g_nPts; i++)  
+	{
+			fOut 
+			<< setiosflags( ios::right )
+			<< setprecision(1)<<setw(10)<< i 
+			<< setprecision(4)
+			<< setw(16)<< x[i] 
+			<< setw(12)<< y[i]
+		    << setw(12)<< sigY[i]
+			<< setw(12)<< yCalc[i] 
+			<< endl;
+	}
+	fOut.close();
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/libohana/doc/glockfile.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/doc/glockfile.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/doc/glockfile.txt	(revision 16632)
@@ -0,0 +1,55 @@
+
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state);
+   
+ set a lockfile on [path]/filename.  
+
+ we allow three types of locks: 
+ LCK_HARD - exclusive lock with persistent lock file
+ LCK_XCLD - exclusive lock, no persistent lock file
+ LCK_SOFT - shared lock
+
+ all three types of locks set a filesystem lock (using NFS lockd) on
+ the given file, using an exclusive lock for HARD and XCLD and a
+ shared lock for SOFT locks.  
+
+ a HARD lock also uses a lockfile to make the lock persistent in the
+ event the calling program crashes: the lockfile must be actively
+ removed and will not vanish even if the locking program dies
+
+ SOFT and XCLD locks will vanish if the locking program dies.
+
+ if a HARD or XCLD lock is set, HARD, XCLD & SOFT locks will block
+
+ if a SOFT lock is set, HARD and XCLD locks will block, but not a SOFT
+ lock
+
+ the hard lockfile uses the file [path]/.filename.lck
+
+ this function locks and opens the file, returning the file pointer to
+ the now opened file.  the file is either opened for reading and
+ writing (HARD, XCLD == r+) or just reading (SOFT).
+
+ Error Conditions:
+
+ on error, fsetlockfile closes the file, closes the lockfile, and
+ returns NULL.  In come cases, an empty file may be left behind
+ (LCK_TIMEOUT, LCK_HARDOPEN, LCK_HARDLOCK, LCK_HARDLOCKHARD,
+ LCK_HARDLOCKCLOSE)
+
+ - invalid type (LCK_INVALID)
+   * no file created, no lock file created : OK
+ - SOFT and file does not exist (LCK_EMPTY)
+   * no file created, no lock file created : OK 
+ - file not accessible, cannot be opened (LCK_ACCESS)
+   * no file created, no lock file created : OK
+ - FS lock timed out (LCK_TIMEOUT)
+   * new file is created, file is open, file is unlocked, lock file is not created : OK
+ - lockfile not accessible (LCK_HARDOPEN)
+   * new file is created, file is open, file is locked, lock file is not created : OK
+ - cannot lock lockfile, held by another user (LCK_HARDLOCK)
+   * new file is created, file is open, file is locked, lock file is created : OK
+ - lockfile says 'BUSY', previous holder crashed (LCK_HARDLOCKHARD)
+   * new file is created, file is open, file is locked, lock file exists, lock file locked : OK
+ - error writing 'BUSY' to lockfile (LCK_HARDCLOSE)
+   * new file is created, file is open, file is locked, lock file exists, lock file locked
+
Index: /branches/eam_branch_20080223/Ohana/src/libohana/include/Xohana.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/include/Xohana.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/include/Xohana.h	(revision 16632)
@@ -0,0 +1,8 @@
+# include <ohana.h>
+# include <X11/Xatom.h>
+# include <X11/Xlib.h>
+# include <X11/Xresource.h>
+# include <X11/Xutil.h>
+# include <X11/cursorfont.h>
+# include <X11/keysym.h>
+# include <X11/keysymdef.h>
Index: /branches/eam_branch_20080223/Ohana/src/libohana/include/convert.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/include/convert.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/include/convert.h	(revision 16632)
@@ -0,0 +1,3 @@
+Measure *FixOldMeasure (OldMeasure *in, int Nvalues);
+Average *FixOldAverage (OldAverage *in, int Nvalues);
+SecFilt *FixOldSecFilt (OldSecFilt *in, int Nvalues);
Index: /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana.h	(revision 16632)
@@ -0,0 +1,243 @@
+# include <stdio.h>
+# include <fcntl.h>
+# include <math.h>
+# include <float.h>
+# include <errno.h>
+# include <time.h>
+# include <stdlib.h>
+# include <string.h>
+# include <sys/socket.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/uio.h>
+# include <sys/un.h>
+# include <unistd.h>
+# include <stdarg.h> 
+# include <readline/history.h>
+# include <readline/readline.h>
+
+// XXX I was including these before, but RHL claims they are not needed
+// # include <malloc.h>
+// # include <memory.h>
+
+/* OHANA included stuff */
+# ifndef OHANA_H
+# define OHANA_H
+
+# ifndef TRUE
+# define TRUE (1)
+# endif
+
+# ifndef FALSE
+# define FALSE (0)
+# endif 
+
+// XXX these should probably use safe name-spaces (eg, OHANA_MIN)
+# ifndef SIGN
+# define SIGN(X) (((X) == 0) ? 0 : ((fabs((double)(X))) / (X)))
+# endif
+
+# ifndef ROUND
+# define ROUND(X) ((int) ((X) + 0.5*SIGN(X)))
+# endif
+
+# ifndef SQR
+# define SQR(X)   (double) (((double)(X))*((double)(X)))
+# endif
+
+# ifndef SQ
+# define SQ(X)    (double) (((double)(X))*((double)(X)))
+# endif
+
+# ifndef MIN
+# define MIN(X,Y) ((X) < (Y) ? (X) : (Y))
+# endif
+
+# ifndef MAX
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# endif
+
+# ifndef SWAP
+# define SWAP(X,Y) {double tmp=(X); (X) = (Y); (Y) = tmp;}
+# endif
+
+# ifndef DTIME
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+# endif
+
+enum {
+ LCK_UNLOCK,        /* file is unlocked */
+ LCK_INVALID,       /* invalid locktype requested */
+ LCK_MISSING,       /* soft requested and file missing (error) */
+ LCK_ACCESS,        /* can't get access to file */
+ LCK_TIMEOUT,       /* timeout setting lock */
+ LCK_HARDOPEN,      /* cannot open hard lockfile */
+ LCK_HARDLOCK,      /* cannot lock hard lockfile */
+ LCK_HARDLOCKHARD,  /* hard lockfile is locked */
+ LCK_HARDCLOSE,     /* cannot write to hardlock */
+
+ LCK_EMPTY,         /* file is locked and empty */
+ LCK_FULL,          /* file is locked and not empty */
+ LCK_UNKNOWN,       /* file is locked, but can't get size */
+
+ LCK_SOFT,          /* soft lock */
+ LCK_HARD,          /* hard lock */
+ LCK_XCLD,          /* exclusive soft lock */
+};
+
+# ifndef M_PI
+# define M_PI 3.14159265358979323846264
+# endif
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+# ifndef PROTO
+#   define PROTO(A) A
+# endif
+
+/* 
+# else
+#   ifndef PROTO
+#   define PROTO(A) ()
+#   endif
+# include <varargs.h>
+# endif
+*/
+
+/* ohana_allocate.h provides ohana memory tools.  to use them
+   you must # define OHANA_MEMORY before including ohana.h */
+# include <ohana_allocate.h>
+
+# ifndef FOPEN 
+# define FOPEN(F,NAME) \
+  F = fopen (NAME, "r"); \
+  if (F == NULL) { \
+    fprintf (stderr, "failed to open %s\n", NAME); \
+    exit (0); \
+  }
+# endif /* FOPEN */
+
+/*
+  isspace is c99 : do we require c99 now? 
+  isspace()
+   checks  for white-space characters.  In the "C" and "POSIX" locales, these are: space, form-feed ('\f'), newline ('\n'),
+   carriage return ('\r'), horizontal tab ('\t'), and vertical tab ('\v').
+   horiz. tab: 0x09, vert. tab: 0x0b, newline: 0x0a, form-feed: 0x0c, return: 0x0d, space: 0x20, 
+*/
+# define OHANA_WHITESPACE(c)(((c) == 0x09) || ((c) == 0x0a) || ((c) == 0x0b) || ((c) == 0x0b) || ((c) == 0x0c) || ((c) == 0x0d) || ((c) == 0x20))
+
+// sorting is now defined as a macro call
+# include <ohana_sort.h>
+
+/* socket / pipe communication buffer */
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nreset;
+  int   Nblock;
+  int   Nbuffer;
+} IOBuffer;
+
+extern double hypot();
+
+/* in string.c */
+int     stripwhite             PROTO((char *string));
+int     strnumcmp              PROTO((char *str1, char *str2));
+char   *strcreate              PROTO((char *string));
+char   *strncreate             PROTO((char *string, int n));
+int     scan_line              PROTO((FILE *f, char *line)); 
+int     dparse                 PROTO((double *X, int NX, char *line));
+int     fparse                 PROTO((float *X, int NX, char *line));
+int     get_argument           PROTO((int argc, char **argv, char *arg));
+int     remove_argument        PROTO((int N, int *argc, char **argv));
+void    uppercase              PROTO((char *string));
+char   *strip_version          PROTO((char *input));
+char   *strsubs                PROTO((char *string, char *match, char *with));
+
+/* in findexec.c */
+char   *pathname               PROTO((char *name));
+char   *filebasename           PROTO((char *name));
+char   *filerootname           PROTO((char *name));
+char   *fileextname            PROTO((char *file));
+char   *findexec               PROTO((int argc, char **argv));
+int     mkdirhier              PROTO((char *path, int mode));
+void    make_backup            PROTO((char *filename));
+int     check_file_access      PROTO((char *basefile, int backup, int verbose));
+int     check_dir_access       PROTO((char *path, int verbose));
+int     check_file_exec        PROTO((char *filename));
+
+/* in glockfile.c */
+FILE   *fsetlockfile           PROTO((char *filename, double timeout, int type, int *state));
+int     fclearlockfile         PROTO((char *filename, FILE *f, int type, int *state));
+
+/* in config.c */
+char   *SelectConfigFile       PROTO((int *argc, char **argv, char *progname));
+char   *LoadConfigFile         PROTO((char *filename));
+char   *ScanConfig             PROTO((char *config, char *field, char *mode, int N,...));
+char   *expandline             PROTO((char *line, char *config));
+char   *fileextname            PROTO((char *file));
+char   *LoadRawConfigFile      PROTO((char *, int));
+
+/* others */
+int     Fseek                  PROTO((FILE *f, long offset, int whence));
+char   *ohana_version          PROTO(());
+
+int     dgaussjordan           PROTO((double **A, double **B, int N, int M));
+int     fgaussjordan           PROTO((float **A, float **B, int n, int m));
+
+/* in time.c */
+enum {TIME_NONE, TIME_DATE, TIME_DAYS, TIME_HOURS, TIME_MINUTES, TIME_SECONDS, TIME_JD, TIME_MJD};
+
+int     ohana_chk_time         PROTO((char *line));
+time_t  ohana_date_to_sec      PROTO((char *date));
+int     ohana_dms_to_ddd       PROTO((double *Value, char *string));
+time_t  ohana_jd_to_sec        PROTO((double jd));
+time_t  ohana_mjd_to_sec       PROTO((double mjd));
+char   *ohana_sec_to_date      PROTO((time_t second));
+double  ohana_sec_to_jd        PROTO((time_t second));
+int     ohana_str_to_dtime     PROTO((char *line, double *second));
+int     ohana_str_to_time      PROTO((char *line, time_t *second));
+double  ohana_sec_to_mjd       PROTO((time_t second));
+double  ohana_lst              PROTO((double jd, double longitude));
+int     ohana_str_to_radec     PROTO((double *ra, double *dec, char *str1, char *str2));
+
+int     hstgsc_hms_to_deg      PROTO((double *h0, double *h1, double *d0, double *d1, char *string));
+
+/* IO Buffer functions */
+int     InitIOBuffer   	       PROTO((IOBuffer *buffer, int Nalloc));
+int 	FlushIOBuffer  	       PROTO((IOBuffer *buffer));
+int 	ReadtoIOBuffer 	       PROTO((IOBuffer *buffer, int fd));
+int 	EmptyIOBuffer  	       PROTO((IOBuffer *buffer, int Nmax, int fd));
+void    FreeIOBuffer   	       PROTO((IOBuffer *buffer));
+int 	PrintIOBuffer  	       PROTO((IOBuffer *buffer, char *format, ...));
+int 	vPrintIOBuffer 	       PROTO((IOBuffer *buffer, char *format, va_list argp));
+
+/* communication functions */
+int 	ExpectMessage 	       PROTO((int device, double timeout, IOBuffer *message));
+int 	ExpectCommand 	       PROTO((int device, int length, double timeout, IOBuffer *buffer));
+int 	SendMessage   	       PROTO((int device, char *format, ...));
+int 	SendMessageFixed       PROTO((int device, int length, char *messge));
+int 	SendCommand   	       PROTO((int device, int length, char *format, ...));
+int 	SendCommandV  	       PROTO((int device, int length, char *format, va_list argp));
+
+char   *CheckForMessage        PROTO((IOBuffer *buffer));
+
+/*
+#   define F_SETFL         4   
+#   define O_NONBLOCK      0200000  
+#   define AF_UNIX         1          
+#   define SOCK_STREAM     1
+*/
+
+/*
+# ifndef ANSI
+# include <varargs.h>
+# else
+# include <stdarg.h> 
+# include <cfuncs.h> 
+# endif
+*/
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana_allocate.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana_allocate.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana_allocate.h	(revision 16632)
@@ -0,0 +1,55 @@
+# ifndef OHANA_ALLOCATE
+# define OHANA_ALLOCATE
+
+/* default is to use basic system memory functions */
+# ifdef OHANA_MEMORY
+
+void *ohana_malloc (char *file, int line, int Nelem, size_t esize);
+void *ohana_realloc (char *file, int line, void *in, int Nelem, size_t esize);
+void  ohana_free (char *file, int line, void *in);
+void  ohana_memregister_func (char *file, int line, void *ptr);
+void  ohana_memdump_func (int mode);
+void  ohana_memcheck_func (int mode);
+
+# define ohana_memregister(X) ohana_memregister_func (__FILE__, __LINE__, (X));
+# define ohana_memcheck(X) ohana_memcheck_func (X);
+# define ohana_memdump(X) ohana_memdump_func (X);
+
+# define ALLOCATE(PTR,TYPE,SIZE) \
+  PTR = (TYPE *) ohana_malloc (__FILE__, __LINE__, (SIZE), sizeof(TYPE))
+# define REALLOCATE(PTR,TYPE,SIZE) \
+  PTR = (TYPE *) ohana_realloc(__FILE__, __LINE__, PTR, (SIZE), sizeof(TYPE));
+# define CHECK_REALLOCATE(PTR,TYPE,SIZE,NCURR,DELTA) \
+  if ((NCURR) >= (SIZE)) { SIZE += DELTA; \
+  PTR = (TYPE *) ohana_realloc(__FILE__, __LINE__, PTR, (SIZE), sizeof(TYPE)); }
+# define FREE(PTR) if (PTR != NULL) { ohana_free (__FILE__, __LINE__, PTR); }
+# define free(PTR) ohana_free(__FILE__, __LINE__, PTR)
+
+# else 
+# define ohana_memregister(X) /* NOP */
+# define ohana_memcheck(X) /* NOP */
+# define ohana_memdump(X) /* NOP */
+# endif /* OHANA_MEMORY */
+
+# ifndef ALLOCATE
+# define ALLOCATE(PTR,TYPE,SIZE)  \
+  PTR = (TYPE *) malloc ((unsigned)(MAX(((SIZE)*((int)sizeof(TYPE))),1))); \
+  if (PTR == NULL) { \
+    fprintf(stderr,"failed malloc at %d in %s\n", __LINE__, __FILE__);\
+    exit (10); } 
+# define REALLOCATE(PTR,TYPE,SIZE) \
+  PTR = (TYPE *) realloc(PTR,(unsigned)(MAX(((SIZE)*((int)sizeof(TYPE))),1))); \
+  if (PTR == NULL) { \
+    fprintf(stderr,"failed realloc at %d in %s\n", __LINE__, __FILE__);\
+    exit (10); }
+# define CHECK_REALLOCATE(PTR,TYPE,SIZE,NCURR,DELTA) \
+  if ((NCURR) >= (SIZE)) { \
+    SIZE += DELTA; \
+    PTR = (TYPE *) realloc(PTR,(unsigned)(MAX(((SIZE)*((int)sizeof(TYPE))),1))); \
+    if (PTR == NULL) { \
+      fprintf(stderr,"failed realloc increment at %d in %s\n", __LINE__, __FILE__);\
+      exit (10); } }
+# define FREE(PTR) if (PTR != NULL) { free (PTR); }
+# endif /* ALLOCATE */
+
+# endif /* OHANA_ALLOCATE */
Index: /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana_sort.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana_sort.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/include/ohana_sort.h	(revision 16632)
@@ -0,0 +1,75 @@
+// Heap sort based on descriptions in Sedgewick "Algorithms in C"
+//
+// Copyright (C) 1999  Thomas Walter
+// Copyright (C) 2007  Paul Price, Institute for Astronomy, University of Hawaii
+// Copyright (C) 2008  Eugene Magnier, Institute for Astronomy, University of Hawaii
+//
+// 18 February 2000: Modified for GSL by Brian Gough
+// 29 November 2007: Modified for psLib by Paul Price
+// 07 January 2008: Modified for ohana by Eugene Magnier
+//
+//
+// This is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option) any
+// later version.
+//
+// This source is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+//
+
+#ifndef OHANA_SORT_H
+#define OHANA_SORT_H
+
+// The following sort code is based on gsl_heapsort from GSL-1.8 (www.gnu.org/software/gsl), file
+// gsl-1.8/sort/sort.c, which is distributed under the GNU General Public License, version 2.
+
+// Use of the PSSORT() macro requires additional macros defined:
+// COMPAREEXPR(A,B): expression to compare element A with element B; true if element A is smaller than B.
+// SWAPFUNC(A,B): swap element A with element B
+
+# define OHANA_DOWNHEAP(COMPARE, SWAPFUNC, K) { \
+  unsigned long k = K; /* Local version of i in main loop */ \
+  while (k <= last / 2) {  \
+    unsigned long j = 2 * k;  \
+    if ((j < last) && COMPARE(j, j + 1)) {  \
+      j++;  \
+    }  \
+    if (COMPARE(k, j)) {  \
+      SWAPFUNC(j, k);  \
+    } else {  \
+      break;  \
+    }  \
+    k = j;  \
+  } \
+}
+
+# define OHANA_SORT(NVALUE, COMPARE, SWAPFUNC) { \
+  unsigned long last = NVALUE - 1; \
+  unsigned long i = last / 2 + 1; \
+  if (NVALUE > 1) { \
+    do { \
+      i--;  \
+      OHANA_DOWNHEAP (COMPARE, SWAPFUNC, i); \
+    } while (i > 0); \
+    while (last > 0) { \
+      SWAPFUNC(0, last); /* Swap elements */ \
+      /* Process the heap */ \
+      last--; \
+      OHANA_DOWNHEAP (COMPARE, SWAPFUNC, 0); \
+    } \
+  } \
+}
+
+// pre-defined function versions
+void dsort (double *value, int N);
+void fsort (float *value, int N);
+void fsortpair (float *X, float *Y, int N);
+void dsortpair (double *X, double *Y, int N);
+void isortpair (int *X, int *Y, int N);
+void fsortthree (float *X, float *Y, float *Z, int N);
+void dsortthree (double *X, double *Y, double *Z, int N);
+
+#endif
Index: /branches/eam_branch_20080223/Ohana/src/libohana/lib/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/lib/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/lib/.cvsignore	(revision 16632)
@@ -0,0 +1,3 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.darwin.dylib
+*.darwin_x86.dylib
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/CommOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/CommOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/CommOps.c	(revision 16632)
@@ -0,0 +1,179 @@
+# include <ohana.h>
+
+// XXX this is somewhat poor: the Send commands return TRUE / FALSE for success/failure
+// the Expect commands return 0 for success, -N for different errors
+
+int ExpectMessage (int device, double timeout, IOBuffer *message) {
+
+  int status, length;
+  IOBuffer command;
+
+  status = ExpectCommand (device, 16, timeout, &command);
+  if (status) {
+    FreeIOBuffer (&command);
+    return (status);
+  }
+
+  /* buffer contains an EOL NULL, we can just sscan it */
+  sscanf (command.buffer, "%*s %d", &length);
+  FreeIOBuffer (&command);
+  
+  status = ExpectCommand (device, length, timeout, message);
+  return (status);
+}
+
+int ExpectCommand (int device, int length, double timeout, IOBuffer *buffer) {
+
+  /* read from device until we have length bytes, or timeout */
+
+  int Nread;
+  double dtime;
+  struct timespec request, remain;
+  struct timeval start, stop;
+
+  gettimeofday (&start, NULL);
+
+  /* avoid blocking on waitpid, test every 1000 usec, up to timeout msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 1000000;
+
+  InitIOBuffer (buffer, length + 1);
+
+  while (buffer[0].Nbuffer < length) {
+    Nread = read (device, &buffer[0].buffer[buffer[0].Nbuffer], length - buffer[0].Nbuffer);
+    
+    if (Nread > 0) {
+      buffer[0].Nbuffer += Nread;
+      continue;
+    }
+
+    if (Nread == -1) {
+      switch (errno) {
+	case EAGAIN:
+	case EIO:
+	  /** no data available in pipe, wait a bit, check for timeout **/
+	  nanosleep (&request, &remain);
+	  break;
+	default:
+	  /** error reading from pipe **/
+	  perror ("ReadtoIOBuffer read error");
+	  return (-2);
+      }
+    }
+
+    if (Nread == 0) return (-3);
+
+    gettimeofday (&stop, NULL);
+    dtime = DTIME (stop, start);
+    if (dtime > timeout) return (-1);
+  }
+  return (0);
+}
+
+/* send a message of arbitrary size, sending the size first */
+int SendMessage (int device, char *format, ...) {
+
+  int Nbyte;
+  char tmp;
+  va_list argp;  
+
+  va_start (argp, format);
+  Nbyte = vsnprintf (&tmp, 0, format, argp);
+  va_end (argp);
+
+  if (!Nbyte) return (FALSE);
+
+  va_start (argp, format);
+  if (!SendCommand (device, 16, "NBYTES: %6d", Nbyte)) goto escape;
+  if (!SendCommandV (device, Nbyte, format, argp)) goto escape;
+  va_end (argp);
+  return TRUE;
+
+escape:
+  va_end (argp);
+  return FALSE;
+}
+
+/* send a message of known size, sending the size first */
+int SendMessageFixed (int device, int length, char *message) {
+
+  if (!SendCommand (device, 16, "NBYTES: %6d", length)) return FALSE;
+  if (!SendCommand (device, length, message)) return FALSE;
+  return TRUE;
+}
+
+int SendCommand (int device, int length, char *format, ...) {
+
+  int status;
+  va_list argp;  
+
+  va_start (argp, format);
+  status = SendCommandV (device, length, format, argp);
+  va_end (argp);
+  return (status);
+}
+  
+int SendCommandV (int device, int length, char *format, va_list argp) {
+
+  int status;
+  char *string;
+
+  /* I allocated and zero 1 extra byte */
+  ALLOCATE (string, char, length + 1);
+  memset (string, 0, length + 1);
+  vsnprintf (string, length + 1, format, argp);
+
+  status = write (device, string, length);
+  free (string);
+
+  if (status == -1) return FALSE;
+  return (TRUE);
+}
+
+/* 
+
+ I need an alternative ExpectCommand function which appends to an existing buffer
+ until the complete message is ready.  
+
+ A command looks like this (pre-determined length):
+ NN bytes: XXXXX\0 
+
+ A message looks like this (preceded by NBYTES command) :
+ 16 bytes: WORD NNN\0
+ NNN bytes: message.... \0
+
+ the expect function needs to monitor the number of bytes already received
+ we need to be able to call it repeatedly until the buffer is full.
+
+*/
+
+/* check if the first entry in the buffer corresponds to a message:
+   A message looks like this (preceded by NBYTES command) :
+    16 bytes: WORD NNN
+    NNN bytes: message....
+    note that the NULL bytes are not sent
+  If a message is found, it is popped off the buffer and sent back as a
+  complete line (the length portion is dropped) 
+*/
+
+char *CheckForMessage (IOBuffer *buffer) {
+
+  int Nbytes;
+  char command[20], *line;
+
+  if (buffer[0].Nbuffer < 16) return NULL;
+  memcpy (command, buffer[0].buffer, 16);
+  command[16] = 0;
+
+  sscanf (command, "NBYTES: %d", &Nbytes);
+
+  if (buffer[0].Nbuffer < Nbytes + 16) return NULL;
+
+  ALLOCATE (line, char, Nbytes + 1);
+  memcpy (line, &buffer[0].buffer[16], Nbytes);
+  line[Nbytes] = 0;
+
+  buffer[0].Nbuffer -= Nbytes + 16;
+  memmove (buffer[0].buffer, &buffer[0].buffer[Nbytes+16], buffer[0].Nbuffer);
+  return (line);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/Fread.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/Fread.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/Fread.c	(revision 16632)
@@ -0,0 +1,474 @@
+# include <ohana.h>
+
+int   ByteSwap (char *ptr, int size, int nitems, char *type);
+
+# define BYTE_EXCHANGE(X,Y) tmp = byte[X]; byte[X] = byte[Y]; byte[Y] = tmp;
+# define SWAP_BYTE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+1]; byte[X+1] = tmp;
+# define SWAP_WORD(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+3]; byte[X+3] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+2]; byte[X+2] = tmp;
+# define SWAP_DBLE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+7]; byte[X+7] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+6]; byte[X+6] = tmp; \
+  tmp = byte[X+2]; byte[X+2] = byte[X+5]; byte[X+5] = tmp; \
+  tmp = byte[X+3]; byte[X+3] = byte[X+4]; byte[X+4] = tmp;
+
+/** this is also used in libautocode/def/common.h -- consolidate **/
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+# ifdef dec
+# define BYTE_SWAP
+# endif
+
+/* add other architectures here, ie dec, alpha, etc */ 
+
+int Fread (void *ptr, int size, int nitems, FILE *f, char *type) {
+
+  int valid, status;
+
+  status = fread (ptr, size, nitems, f);
+
+  valid = ByteSwap (ptr, size, nitems, type);
+
+  if (!valid) return (FALSE);
+  return (status);
+}
+
+int Fwrite (void *ptr, int size, int nitems, FILE *f, char *type) {
+
+  int valid, status;
+
+  valid = ByteSwap (ptr, size, nitems, type);
+
+  if (!valid) return (FALSE);
+
+  status = fwrite (ptr, size, nitems, f);
+  return (status);
+}
+
+int ByteSwap (char *ptr, int size, int nitems, char *type) {
+
+# ifdef BYTE_SWAP
+
+  int i;
+  unsigned char *byte0, *byte1, *byte2, *byte3, *byte4, *byte5, *byte6, *byte7, tmp;
+
+  if (!strcmp (type, "char")) return (TRUE);
+
+  if (!strcmp (type, "short")) {
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    for (i = 0; i < nitems; i++, byte0 += 2, byte1 += 2) {
+      tmp = *byte0;
+      *byte0 = *byte1;
+      *byte1 = tmp;
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "int") || !strcmp (type, "float")) {
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    byte2 = (unsigned char *)ptr + 2;
+    byte3 = (unsigned char *)ptr + 3;
+    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+      tmp = *byte0;
+      *byte0 = *byte3;
+      *byte3 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte2;
+      *byte2 = tmp;
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "double")) {
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    byte2 = (unsigned char *)ptr + 2;
+    byte3 = (unsigned char *)ptr + 3;
+    byte4 = (unsigned char *)ptr + 4;
+    byte5 = (unsigned char *)ptr + 5;
+    byte6 = (unsigned char *)ptr + 6;
+    byte7 = (unsigned char *)ptr + 7;
+    for (i = 0; i < nitems; i++, byte0 += 8, byte1 += 8, byte2 += 8, byte3 += 8, byte4 += 8, byte5 += 8, byte6 += 8, byte7 += 8) {
+      tmp = *byte0;
+      *byte0 = *byte7;
+      *byte7 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte6;
+      *byte6 = tmp;
+      tmp = *byte1;
+      *byte2 = *byte5;
+      *byte5 = tmp;
+      tmp = *byte1;
+      *byte3 = *byte4;
+      *byte4 = tmp;
+    }
+    return (TRUE);
+  }
+
+# if (0) /** now in autocode **/
+  if (!strcmp (type, "regimage")) {
+    if (size != REGIMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (RegImage) %d vs %d\n", size, REGIMAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += REGIMAGE_SIZE) {
+      SWAP_WORD (284); /* exptime */ 
+      SWAP_WORD (288); /* airmass */ 
+      SWAP_WORD (292); /* sky */     
+      SWAP_WORD (296); /* bias */    
+      SWAP_WORD (300); /* fwhm */    
+      SWAP_WORD (304); /* telfocus */ 
+      SWAP_WORD (308); /* xprobe */ 
+      SWAP_WORD (312); /* yprobe */ 
+      SWAP_WORD (316); /* zprobe */ 
+      SWAP_WORD (320); /* dettemp */ 
+      SWAP_WORD (324); /* teltemp[0] */ 
+      SWAP_WORD (328); /* teltemp[1] */  
+      SWAP_WORD (332); /* teltemp[2] */ 
+      SWAP_WORD (336); /* teltemp[3] */ 
+      SWAP_WORD (340); /* rotangle */
+      SWAP_WORD (344); /* ra */      
+      SWAP_WORD (348); /* dec */     
+      SWAP_WORD (352); /* obstime */ 
+      SWAP_WORD (356); /* regtime */  
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "detreg")) {
+    if (size != DETREG_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, DETREG_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += DETREG_SIZE) {
+      SWAP_WORD (0);   /* tstart */
+      SWAP_WORD (4);   /* tstop */
+      SWAP_WORD (8);   /* treg */
+      SWAP_WORD (12);  /* exptime */
+      SWAP_WORD (16);  /* type */
+      SWAP_WORD (20);  /* filter */
+      SWAP_WORD (24);  /* ccd */
+      SWAP_WORD (28);  /* Nentry */
+      SWAP_WORD (32);  /* Norder */
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "photpars")) {
+    if (size != PHOTPARS_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (PhotPars) %d vs %d\n", size, PHOTPARS_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += PHOTPARS_SIZE) {
+      SWAP_WORD (0);    /* ZP */
+      SWAP_WORD (4);    /* ZPo */
+      SWAP_WORD (8);    /* dZP */
+      SWAP_WORD (12);   /* K */
+      SWAP_WORD (16);   /* A */
+      SWAP_WORD (20);   /* tstart */
+      SWAP_WORD (24);   /* tstop */
+      SWAP_BYTE (28);   /* c1 */
+      SWAP_BYTE (30);   /* c2 */
+      SWAP_BYTE (32);   /* photcode */
+      SWAP_WORD (100);   /* Ntime */
+      SWAP_WORD (104);   /* Nmeas */
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "missing")) {
+    if (size != MISSING_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Missing) %d vs %d\n", size, MISSING_SIZE);
+      return (FALSE);
+    }
+    byte0 = (unsigned char *)ptr;
+    byte1 = (unsigned char *)ptr + 1;
+    byte2 = (unsigned char *)ptr + 2;
+    byte3 = (unsigned char *)ptr + 3;
+    for (i = 0; i < nitems; i++, byte0 += 4, byte1 += 4, byte2 += 4, byte3 += 4) {
+      tmp = *byte0;
+      *byte0 = *byte3;
+      *byte3 = tmp;
+      tmp = *byte1;
+      *byte1 = *byte2;
+      *byte2 = tmp;
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "secfilt")) {
+    if (size != SECFILT_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (SecFilt) %d vs %d\n", size, SECFILT_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *) ptr;
+    for (i = 0; i < nitems; i++, byte += SECFILT_SIZE) {
+      SWAP_BYTE (0);   /* M */
+      SWAP_BYTE (2);   /* Xm */
+      SWAP_BYTE (4);   /* dM */
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "spectrum")) {
+    if (size != SPECTRUM_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Spectrum) %d vs %d\n", size, SPECTRUM_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += SPECTRUM_SIZE) {
+      SWAP_WORD (0);  /* ra */ 
+      SWAP_WORD (4);  /* dec */ 
+      SWAP_WORD (8);  /* exptime */ 
+      SWAP_WORD (12); /* airmass */ 
+      SWAP_WORD (16); /* Ws */ 
+      SWAP_WORD (20); /* We */ 
+      SWAP_WORD (24); /* dW */ 
+      SWAP_WORD (28); /* Nspec */ 
+      SWAP_WORD (32); /* obstime */ 
+      SWAP_WORD (36); /* regtime */ 
+    }
+    return (TRUE);
+  }
+
+  if (!strcmp (type, "image")) {
+    if (size != IMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Image) %d vs %d\n", size, IMAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += IMAGE_SIZE) {
+      SWAP_DBLE (0); /* coords.crval1 */
+      SWAP_DBLE (8); /* coords.crval2 */
+      for (j = 16; j < 104; j+=4) { /* coords.crpix, delt, pc_ij, polyterms[7][2] */
+	SWAP_WORD (j);
+      }
+      SWAP_WORD (120); /* tzero */
+      SWAP_WORD (124); /* nstar */
+      for (j = 128; j < 146; j+=2) { /* sec z, NX, NY, apmifit, dapmifit, source, Mcal, dMcal, Xm */
+	SWAP_BYTE (j);
+      }
+      SWAP_WORD (184); /* exptime */
+      SWAP_WORD (210); /* order */
+      /**** this (210) is an error! (don't fix, replaced with autocode) ****/
+      for (j = 212; j < 240; j+=2) {
+	SWAP_BYTE (j); /* Mx - Myyy */
+      }
+    }
+    return (TRUE);
+  }
+
+# if (PANSTARRS)
+  if (!strcmp (type, "average")) {
+    if (size != AVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Average) %d vs %d\n", size, AVERAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += AVERAGE_SIZE) {
+      SWAP_DBLE (0);   /* R */
+      SWAP_DBLE (8);   /* D */
+      SWAP_BYTE (16);  /* M */
+      SWAP_BYTE (18);  /* Nm */
+      SWAP_BYTE (20);  /* Nn */
+      SWAP_BYTE (22);  /* Xp */
+      SWAP_BYTE (24);  /* Xm */
+      SWAP_BYTE (26);  /* code */
+      SWAP_WORD (28);  /* offset */
+      SWAP_WORD (32);  /* missing */
+      SWAP_BYTE (36);  /* dM */
+      SWAP_BYTE (38);  /* Xg */
+    }
+    return (TRUE);
+  } 
+  if (!strcmp (type, "measure")) {
+    if (size != MEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Measure) %d vs %d\n", size, MEASURE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += MEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (8);   /* Mgal */
+      SWAP_BYTE (10);  /* Map  */
+      SWAP_BYTE (12);  /* FWx */
+      /* 14, 15, 16, 17 - char */
+      SWAP_BYTE (18);  /* source */
+      SWAP_WORD (20);  /* t */
+      SWAP_WORD (24);  /* averef */
+      SWAP_BYTE (28);  /* dt */
+      SWAP_BYTE (30);  /* flags */
+    }
+    return (TRUE);
+  }
+
+# endif /** PANSTARRS **/
+
+
+# if (ELIXIR)
+  if (!strcmp (type, "average")) {
+    if (size != AVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Average) %d vs %d\n", size, AVERAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += AVERAGE_SIZE) {
+      SWAP_WORD (0);   /* R */
+      SWAP_WORD (4);   /* D */
+      SWAP_BYTE (8);   /* M */
+      SWAP_BYTE (10);  /* Nm */
+      SWAP_BYTE (12);  /* Nn */
+      SWAP_BYTE (14);  /* Xp */
+      SWAP_BYTE (16);  /* Xm */
+      SWAP_BYTE (18);  /* code */
+      SWAP_WORD (20);  /* offset */
+      SWAP_WORD (24);  /* missing */
+      SWAP_BYTE (28);  /* dM */
+      SWAP_BYTE (30);  /* Xg */
+    }
+    return (TRUE);
+  } 
+  if (!strcmp (type, "measure")) {
+    if (size != MEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (Measure) %d vs %d\n", size, MEASURE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += MEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (8);   /* Mgal */
+      SWAP_BYTE (10);  /* Map  */
+      SWAP_BYTE (12);  /* FWx */
+      /* 14, 15, 16, 17 - char */
+      SWAP_BYTE (18);  /* source */
+      SWAP_WORD (20);  /* t */
+      SWAP_WORD (24);  /* averef */
+      SWAP_BYTE (28);  /* dt */
+      SWAP_BYTE (30);  /* flags */
+    }
+    return (TRUE);
+  }
+
+# endif /** ELIXIR **/
+
+
+# if (LONEOS)
+  if (!strcmp (type, "average")) {
+    if (size != OLDAVERAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldAverage) %d vs %d\n", size, OLDAVERAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDAVERAGE_SIZE) {
+      SWAP_WORD (0);   /* R */
+      SWAP_WORD (4);   /* D */
+      SWAP_BYTE (8);   /* M */
+      SWAP_BYTE (10); /* Nm */
+      SWAP_BYTE (12); /* Nn */
+      SWAP_BYTE (14); /* Xp */
+      SWAP_BYTE (16); /* Xm */
+      SWAP_BYTE (18); /* code */
+      SWAP_WORD (20); /* offset */
+      SWAP_WORD (24); /* missing */
+    }
+    return (TRUE);
+  } 
+  if (!strcmp (type, "measure")) {
+    if (size != OLDMEASURE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldMeasure) %d vs %d\n", size, OLDMEASURE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDMEASURE_SIZE) {
+      SWAP_BYTE (0);   /* dR */
+      SWAP_BYTE (2);   /* dD */
+      SWAP_BYTE (4);   /* M  */
+      SWAP_BYTE (6);   /* Mcal */
+      SWAP_BYTE (10);  /* source */
+      SWAP_WORD (12);  /* t */
+      SWAP_WORD (16);  /* average */
+    }
+    return (TRUE);
+  }
+# endif /** LONEOS **/
+
+# if (0) /*** others ***/
+  if (!strcmp (type, "oldsecfilt")) {
+    if (size != OLDSECFILT_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (OldSecFilt) %d vs %d\n", size, OLDSECFILT_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *) ptr;
+    for (i = 0; i < nitems; i++, byte += OLDSECFILT_SIZE) {
+      SWAP_BYTE (0);   /* M */
+      SWAP_BYTE (2);   /* Xm */
+    }
+    return (TRUE);
+  }
+  if (!strcmp (type, "rufimage")) {
+    if (size != RUFIMAGE_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (RufImage) %d vs %d\n", size, RUFIMAGE_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += RUFIMAGE_SIZE) {
+      SWAP_WORD (0);   /* sky */
+      SWAP_WORD (4);   /* bias */
+      SWAP_WORD (8);  /* fwhm */
+      SWAP_WORD (12); /* exptime */
+      SWAP_WORD (16); /* airmass */
+      SWAP_WORD (20); /* obstime */
+      SWAP_BYTE (24); /* ccdnum */
+    }
+    return (TRUE);
+  }
+  if (!strcmp (type, "olddetreg")) {
+    if (size != OLDDETREG_SIZE) {
+      fprintf (stderr, "mismatch in type sizes (DetReg) %d vs %d\n", size, OLDDETREG_SIZE);
+      return (FALSE);
+    }
+    byte = (unsigned char *)ptr;
+    for (i = 0; i < nitems; i++, byte += OLDDETREG_SIZE) {
+      SWAP_WORD (0);   /* tstart */
+      SWAP_WORD (4);   /* tstop */
+      SWAP_WORD (8);   /* treg */
+      SWAP_WORD (12);  /* sigma */
+      SWAP_WORD (16);  /* clipsigma */
+      SWAP_WORD (20);  /* type */
+      SWAP_WORD (24);  /* filter */
+      SWAP_WORD (28);  /* ccd */
+    }
+    return (TRUE);
+  }
+# endif /** others **/
+# endif /** now in autocode **/
+
+  fprintf (stderr, "unknown type %s\n", type);
+  return (FALSE);
+
+# else
+
+  return (TRUE);
+
+# endif 
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/IOBufferOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/IOBufferOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/IOBufferOps.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include <ohana.h>
+# define DEBUG 0
+
+int InitIOBuffer (IOBuffer *buffer, int Nalloc) {
+
+  buffer[0].Nalloc = Nalloc;
+  buffer[0].Nreset = Nalloc;
+  buffer[0].Nblock = Nalloc / 2;
+  buffer[0].Nbuffer = 0;
+
+  ALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+  bzero (buffer[0].buffer, buffer[0].Nalloc);
+
+  return (TRUE);
+}
+
+int FlushIOBuffer (IOBuffer *buffer) {
+
+  buffer[0].Nbuffer = 0;
+  buffer[0].Nalloc = buffer[0].Nreset;
+  REALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+  bzero (buffer[0].buffer, buffer[0].Nalloc);
+
+  return (TRUE);
+}
+
+int ReadtoIOBuffer (IOBuffer *buffer, int fd) {
+
+  int Nread, Nfree;
+
+  if (fd == 0) {
+    /* pipe is closed */
+    return (0);
+  }
+
+  Nfree = buffer[0].Nalloc - buffer[0].Nbuffer;
+  if (Nfree < buffer[0].Nblock) {
+    buffer[0].Nblock *= 2;
+    buffer[0].Nblock = MIN (buffer[0].Nblock, 0x10000);
+    buffer[0].Nalloc += 2*buffer[0].Nblock;
+    REALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+    Nfree = buffer[0].Nalloc - buffer[0].Nbuffer;
+    bzero (buffer[0].buffer + buffer[0].Nbuffer, Nfree);
+  }
+
+  Nread = read (fd, &buffer[0].buffer[buffer[0].Nbuffer], buffer[0].Nblock);
+  if (DEBUG) fprintf (stderr, "read IO buffer: (%lx) %d from %d\n", (unsigned long) buffer, Nread, buffer[0].Nblock); 
+
+  /* on success, increase the block size for the next read */
+  
+  if (Nread >= 0) {
+    buffer[0].Nbuffer += Nread;
+    return (Nread);
+  }
+
+  if (Nread == -1) {
+    switch (errno) {
+    case EAGAIN:
+    case EIO:
+      /** no data available in pipe **/
+      return (-1);
+    default:
+      /** error reading from pipe **/
+      perror ("ReadtoIOBuffer read error");
+      return (-2);
+    }
+  }
+  return (Nread);
+}
+
+/* read until buffer is empty (Nmax retries) */
+int EmptyIOBuffer (IOBuffer *buffer, int Nmax, int fd) {
+
+  int i, status;
+
+  status = -1;
+  for (i = 0; (status != 0) && (i < Nmax); i++) {
+    status = ReadtoIOBuffer (buffer, fd);
+    if (status == -1) usleep (10000);
+    if (status > 0) i = 0;
+  }
+  if (status == -1) return (FALSE);
+  return (TRUE);
+}
+
+void FreeIOBuffer (IOBuffer *buffer) {
+
+  if (buffer[0].buffer != (char *) NULL) {
+    free (buffer[0].buffer);
+  }
+}
+
+/* print to an IOBuffer (varargs form) */
+int PrintIOBuffer (IOBuffer *buffer, char *format, ...) {
+
+  int status;
+  va_list argp;  
+
+  va_start (argp, format);
+  status = vPrintIOBuffer (buffer, format, argp);
+  va_end (argp);
+  return (status);
+}
+
+/* print to an IOBuffer (va_list form) */
+int vPrintIOBuffer (IOBuffer *buffer, char *format, va_list argp) {
+
+  /* add the output line to the given IOBuffer */
+  
+  int Nbyte;
+  char tmp;
+  va_list argp2;
+
+  va_copy (argp2, argp);
+
+  Nbyte = vsnprintf (&tmp, 0, format, argp2);
+
+  if (buffer[0].Nbuffer + Nbyte + 1>= buffer[0].Nalloc) {
+    buffer[0].Nalloc = buffer[0].Nbuffer + Nbyte + 64;
+    REALLOCATE (buffer[0].buffer, char, buffer[0].Nalloc);
+  }
+
+  vsnprintf (&buffer[0].buffer[buffer[0].Nbuffer], Nbyte + 1, format, argp);
+  buffer[0].Nbuffer += Nbyte;
+  return (TRUE);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/config.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/config.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/config.c	(revision 16632)
@@ -0,0 +1,454 @@
+# include <ohana.h>
+
+# define D_NBYTES 4096
+
+static char *ConfigVariable = (char *) NULL;
+static int NDefineVariable;
+static char **DefineVariable;
+static char **DefineValue;
+
+char *SelectConfigFile (int *argc, char **argv, char *progname) {
+  
+  /* 
+     config file selection rules (first ones override later ones):
+
+     1) -c Filename   : use Filename
+     2) PROGNAME      : use environment variable as config file
+     3) progname.rc   : use alternate name in local dir as config file
+     4) .prognamerc   : use rc file in local dir as config file
+     5) ~/.prognamerc : use rc file in homedir as config file
+
+     special variable definitions:
+     1) -C WORD       : set CONFIG variable to WORD
+     2) -D NAME WORD  : set NAME variable to WORD
+        -D overrides variables in param file
+
+     these command-line options are removed and a complete arg list left behind
+  */
+
+  char *filename, *find, *home;
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int i, N, NDEF, status;
+  
+  /* first look for -C CONFIG variable */
+  if ((N = get_argument (*argc, argv, "-C"))) {
+    remove_argument (N, argc, argv);
+    if (ConfigVariable != (char *) NULL) free (ConfigVariable);
+    ConfigVariable = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+    
+  /* next look for -D NAME WORD variables */
+  NDEF = 10;
+  ALLOCATE (DefineVariable, char *, NDEF);
+  ALLOCATE (DefineValue, char *, NDEF);
+  for (i = 0; (N = get_argument (*argc, argv, "-D")); i++) {
+    remove_argument (N, argc, argv);
+    DefineVariable[i] = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    DefineValue[i] = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    if (i == NDEF - 1) {
+      NDEF += 10;
+      REALLOCATE (DefineVariable, char *, NDEF);
+      REALLOCATE (DefineValue, char *, NDEF);
+    }      
+  }    
+  NDefineVariable = i;
+  REALLOCATE (DefineVariable, char *, MAX (1, i));
+    
+  /* look for -c FILENAME for config file */
+  if ((N = get_argument (*argc, argv, "-c"))) {
+    remove_argument (N, argc, argv);
+    filename = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    return (filename);
+  }
+  
+  /* look for PROGNAME env var */
+  find = strcreate (progname);
+  for (i = 0; i < strlen(find); i++) find[i] = toupper (find[i]);
+  filename = getenv (find);
+  free (find);
+  if (filename != (char *) NULL) {
+    find = strcreate (filename);
+    return (find);
+  }
+
+  uid = getuid();
+  gid = getgid();
+  ALLOCATE (find, char, strlen(progname) + 32);
+
+  /* look for progname.rc */
+  sprintf (find, "%s.rc", progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+  free (find);
+
+  /* we eliminate this option: this is just confusing */
+# if (0)  
+  /* look for ./.prognamerc */
+  sprintf (find, ".%src", progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+# endif
+
+  /* look for ~/.prognamerc */
+  home = getenv ("HOME");
+  if (home == (char *) NULL) { return ((char *) NULL); }
+  ALLOCATE (find, char, 1024);
+  sprintf (find, "%s/.%src", home, progname);
+  status = stat (find, &filestat);
+  if (status == 0) { 
+    /* file exists, can we read it? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP)) || 
+	(                            (filestat.st_mode & S_IROTH))) {
+      return (find);
+    }
+  }
+  free (find);
+  return ((char *) NULL);
+}
+
+char *LoadConfigFile (char *filename) {
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, nbytes, Nout, Ncpy, INPUT, Nlevel;
+  char *ibuffer, *obuffer, *tbuffer;
+  char *last, *next;
+  char infile[256], line[256];
+  
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return ((char *) NULL);
+  }
+ 
+  /* allocate tmp space, 2 extra bytes for a final return and EOL */
+  Nbytes = 0;
+  NBYTES = D_NBYTES;
+  ALLOCATE (ibuffer, char, NBYTES + 2);
+    
+  /* load data from file */
+  done = FALSE;
+  while ((nbytes = fread (&ibuffer[Nbytes], sizeof(char), D_NBYTES, f)) == D_NBYTES) {
+    Nbytes += nbytes;
+    NBYTES += D_NBYTES;
+    REALLOCATE (ibuffer, char, NBYTES + 2);
+  }
+  Nbytes += nbytes;
+  fclose (f);
+
+  /* add final return & EOL if non-existent */
+  if (ibuffer[Nbytes-1] != '\n') {
+    ibuffer[Nbytes] = '\n';
+    Nbytes ++;
+  }
+  if (ibuffer[Nbytes]) ibuffer[Nbytes] = 0;
+
+  /* add the optional variables to the end of the input buffer */
+  if (ConfigVariable != (char *) NULL) {
+    snprintf (line, 256, "%s %s\n", "CONFIG", ConfigVariable);
+    Ncpy = strlen (line);
+    if (Nbytes + Ncpy >= NBYTES - 1) {
+      NBYTES = Nbytes + Ncpy + D_NBYTES;
+      REALLOCATE (ibuffer, char, NBYTES);
+    }    
+    memcpy (&ibuffer[Nbytes], line, Ncpy);
+    Nbytes += Ncpy;
+    ibuffer[Nbytes] = 0;
+  }
+  for (i = 0; i < NDefineVariable; i++) {
+    snprintf (line, 256, "%s %s\n", DefineVariable[i], DefineValue[i]);
+    Ncpy = strlen (line);
+    if (Nbytes + Ncpy >= NBYTES - 1) {
+      NBYTES = Nbytes + Ncpy + D_NBYTES;
+      REALLOCATE (ibuffer, char, NBYTES);
+    }    
+    memcpy (&ibuffer[Nbytes], line, Ncpy);
+    Nbytes += Ncpy;
+    ibuffer[Nbytes] = 0;
+  }
+  
+  /* loop over input buffer, interpolating 'input' lines until none are added */
+  Nlevel = 0;
+  do {
+    INPUT = FALSE;
+
+    /* allocate output buffer & set counter */
+    NBYTES = Nbytes + D_NBYTES;
+    ALLOCATE (obuffer, char, NBYTES);
+    Nout = 0;
+    
+    /* copy from ibuffer to obuffer, interpolating 'input' lines */
+    last = next = ibuffer;
+    for (i = 1; (next = ScanConfig (ibuffer, "input", "%s", i, infile)) != (char *) NULL; i++) {
+      /* copy data from last point to before 'input' */ 
+      Ncpy = next - last - 5;
+      if (Nout + Ncpy >= NBYTES - 1) {
+	NBYTES = Nout + Ncpy + D_NBYTES;
+	REALLOCATE (obuffer, char, NBYTES);
+      }      
+      memcpy (&obuffer[Nout], last, Ncpy);
+      Nout += Ncpy;
+      obuffer[Nout] = 0;
+      
+      /* insert data from 'input' file */
+      tbuffer = LoadRawConfigFile (infile, FALSE);
+      if (tbuffer != (char *) NULL) {
+	Ncpy = strlen (tbuffer);
+	if (Nout + Ncpy >= NBYTES - 1) {
+	  NBYTES = Nout + Ncpy + D_NBYTES;
+	  REALLOCATE (obuffer, char, NBYTES);
+	}      
+	memcpy (&obuffer[Nout], tbuffer, Ncpy);
+	free (tbuffer);
+	Nout += Ncpy;
+	obuffer[Nout] = 0;
+      }
+      
+      /* pointer goes to end of input line */
+      last = strchr (next, '\n');
+      if (last == (char *) NULL) break;
+      last ++;
+      INPUT = TRUE;
+    }
+    /* last set of bytes after last input */
+    Ncpy = strlen (last);
+    if (Nout + Ncpy >= NBYTES - 1) {
+      NBYTES = Nout + Ncpy + D_NBYTES;
+      REALLOCATE (obuffer, char, NBYTES);
+    }      
+    memcpy (&obuffer[Nout], last, Ncpy);
+    Nout += Ncpy;
+    obuffer[Nout] = 0;
+    free (ibuffer);
+    ibuffer = obuffer;
+    Nlevel ++;
+  } while (INPUT && (Nlevel < 20));
+  if (Nlevel == 20) {
+    fprintf (stderr, "warning: config reached max depth of 20\n");
+  }
+
+  /* 'obuffer' now has complete set of interpolated lines from 'filename' */
+  return (obuffer);
+}
+
+char *ScanConfig (char *config, char *field, char *mode, int Nentry, ...) {
+  
+  int i;
+  char *p, *p2, *tmp, *tfield, *start, *expandline();
+  va_list argp;
+  double value;
+  
+  if (config == (char *) NULL) return ((char *) NULL);
+  va_start (argp, Nentry);
+
+  ALLOCATE (tfield, char, strlen (field) + 3);
+  sprintf (tfield, "\n%s", field);
+
+  /* we search for Nentry matching fields,
+     or until the end if Nentry == 0 */
+  p = (char *) NULL;
+  p2 = config;
+  for (i = 0; (i < Nentry) || !Nentry;) {
+    tmp = strstr (p2, tfield);
+    if (tmp == (char *) NULL) {
+      break;
+    }
+    p2 = tmp + strlen (tfield);
+    if (OHANA_WHITESPACE (*p2)) {
+      p = p2;
+      i++;
+    }
+  }
+  free (tfield);
+  if (Nentry && (i != Nentry)) {
+    p = va_arg (argp, char *);
+    p[0] = 0;
+    return ((char *) NULL);
+  }
+  if (p == (char *) NULL) {
+    p = va_arg (argp, char *);
+    p[0] = 0;
+    return ((char *) NULL);
+  }
+
+  start = p;
+  if (!strcmp (mode, "%s")) {
+    p2 = strchr (p, '\n');
+    if (p2 == (char *) NULL) p2 = config + strlen(config);
+    ALLOCATE (tmp, char, p2-p + 2);
+    memcpy (tmp, p, (p2-p));
+    tmp[(p2-p)] = 0;
+    stripwhite (tmp);
+    tmp = expandline (tmp, config);
+    p2 = va_arg (argp, char *);
+    strcpy (p2, tmp);
+    free (tmp);
+  } else {
+ 
+    /* try to get a numerical value from the field */
+    value = strtod (p, &p2);
+    if ((*p2 == 'd') || (*p2 == 'D')) 
+      value *= pow (10.0, atof (p2 + 1));
+    
+    if (!strcmp (mode, "%d"))  *va_arg (argp, int *)       = value;
+    if (!strcmp (mode, "%u"))  *va_arg (argp, unsigned *)  = value;
+    if (!strcmp (mode, "%ld")) *va_arg (argp, long *)      = value;
+    if (!strcmp (mode, "%hd")) *va_arg (argp, short *)     = value;
+    if (!strcmp (mode, "%f"))  *va_arg (argp, float *)     = value;
+    if (!strcmp (mode, "%lf")) *va_arg (argp, double *)    = value;
+    
+  }
+ 
+  va_end (argp);
+  return (start);
+  
+}
+
+
+char *expandline (char *line, char *config) {
+
+  int Nin, Nout, Ncpy, NBYTES;
+  char *p1, *p2, word[256], value[256];
+  char *outline;
+  
+  NBYTES = 256;
+  ALLOCATE (outline, char, NBYTES);
+  Nout = 0;
+  Nin  = 0;
+  while ((p1 = strchr (&line[Nin], '$')) != (char *) NULL) {
+    Ncpy = p1 - line - Nin;
+    if (Nout + Ncpy >= NBYTES) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES - 2);
+    }
+    memcpy (&outline[Nout], &line[Nin], Ncpy);
+    Nout += Ncpy;
+    
+    p1 ++;
+    for (p2 = p1; isalnum (*p2) || (*p2 == '_') || (*p2 == '-'); p2++);
+    memcpy (word, p1, p2 - p1);
+    word[p2-p1] = 0;
+    Nin += Ncpy + 1 + p2 - p1;
+    
+    /* search for last entry of word */
+    if (!ScanConfig (config, word, "%s", 0, value)) {
+      fprintf (stderr, "variable %s not found in config file\n", word);
+      return (line);
+    }
+    Ncpy = strlen(value);
+    if (Nout + Ncpy >= NBYTES - 2) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES);
+    }    
+    memcpy (&outline[Nout], value, Ncpy);
+    Nout += Ncpy;
+  }
+  Ncpy = strlen(&line[Nin]);
+  if (Nout + Ncpy >= NBYTES - 2) {
+    NBYTES = Nout + Ncpy + 256;
+    REALLOCATE (outline, char, NBYTES);
+  }  
+  memcpy (&outline[Nout], &line[Nin], Ncpy);
+  Nout += Ncpy;
+  outline[Nout] = 0;
+  free (line);
+  return (outline);
+
+}
+
+char *LoadRawConfigFile (char *filename, int options) {
+  
+  FILE *f;
+  int i, done, Nbytes, NBYTES, nbytes, Ncpy;
+  char *ibuffer;
+  char line[256];
+  
+  /* open file */
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    return ((char *) NULL);
+  }
+ 
+  /* allocate tmp space, 2 extra bytes for a final return and EOL */
+  Nbytes = 0;
+  NBYTES = D_NBYTES;
+  ALLOCATE (ibuffer, char, NBYTES + 2);
+    
+  /* load data from file */
+  done = FALSE;
+  while ((nbytes = fread (&ibuffer[Nbytes], sizeof(char), D_NBYTES, f)) == D_NBYTES) {
+    Nbytes += nbytes;
+    NBYTES += D_NBYTES;
+    REALLOCATE (ibuffer, char, NBYTES + 2);
+  }
+  Nbytes += nbytes;
+  fclose (f);
+
+  /* add final return & EOL, if non-existent */
+  if (ibuffer[Nbytes-1] != '\n') {
+    ibuffer[Nbytes] = '\n';
+    Nbytes ++;
+  }
+  if (ibuffer[Nbytes]) ibuffer[Nbytes] = 0;
+
+  if (options) {
+    /* write optional variables to bottom of buffer, overriding entries in the file */
+    if (ConfigVariable != (char *) NULL) {
+      snprintf (line, 256, "%s %s\n", "CONFIG", ConfigVariable);
+      Ncpy = strlen (line);
+      if (Nbytes + Ncpy >= NBYTES) {
+	NBYTES = Nbytes + Ncpy + D_NBYTES;
+	REALLOCATE (ibuffer, char, NBYTES + 2);
+      }    
+      memcpy (&ibuffer[Nbytes], line, Ncpy);
+      Nbytes += Ncpy;
+      ibuffer[Nbytes] = 0;
+    }
+    for (i = 0; i < NDefineVariable; i++) {
+      snprintf (line, 256, "%s %s\n", DefineVariable[i], DefineValue[i]);
+      Ncpy = strlen (line);
+      if (Nbytes + Ncpy >= NBYTES) {
+	NBYTES = Nbytes + Ncpy + D_NBYTES;
+	REALLOCATE (ibuffer, char, NBYTES + 2);
+      }    
+      memcpy (&ibuffer[Nbytes], line, Ncpy);
+      Nbytes += Ncpy;
+      ibuffer[Nbytes] = 0;
+    }
+  }
+
+  return (ibuffer);
+}
+
+/* 
+char *LoadConfigFile (char *filename) {
+  
+  char *config;
+
+  config = LoadSubConfigFile (filename, TRUE);
+
+  return (config);
+
+}
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/findexec.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/findexec.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/findexec.c	(revision 16632)
@@ -0,0 +1,380 @@
+# include <ohana.h>
+
+int check_file_exec (char *filename) {
+  
+  struct stat filestat;
+  uid_t uid;
+  gid_t 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 {
+      return (FALSE);
+    }
+  }
+  return (FALSE);
+}
+
+/* check that:
+   - dir exists
+   - dir permissions OK
+*/
+int check_dir_access (char *path, int VERBOSE) {
+  
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status, cmode;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  status = stat (path, &filestat);
+  if (status == -1) {
+    if (VERBOSE) fprintf (stderr, "directory %s does not exist, creating...\n", path);
+    cmode = S_IRWXU | S_IRWXG | S_IRWXO;
+    status = mkdirhier (path, cmode);
+    if (status == -1) {
+      if (VERBOSE) fprintf (stderr, "can't create %s\n", path);
+      return (FALSE);
+    }
+  } 
+  status = stat (path, &filestat);
+  if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRWXU)) ||
+      ((gid == filestat.st_gid) && (filestat.st_mode & S_IRWXG)) || 
+      (filestat.st_mode & S_IRWXO)) {
+  } else {
+    if (VERBOSE) fprintf (stderr, "can't write to %s\n", path);
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* check that file can be written to:
+   - dir exists
+   - dir permissions OK
+   - file permissions OK, 
+   - file backup permission OK (optional)
+*/
+int check_file_access (char *basefile, int BACKUP, int VERBOSE) {
+  
+  char *path, *filename;
+  struct stat filestat;
+  uid_t uid;
+  gid_t gid;
+  int status;
+
+  uid = getuid();
+  gid = getgid();
+
+  /* check permission to write to directory */
+  path = pathname (basefile);
+  status = check_dir_access (path, VERBOSE);
+  free (path);
+  if (!status) return (FALSE);
+  
+  /* check permission to write to file */
+  status = stat (basefile, &filestat);
+  if (status == 0) { /* file exists, are permissions OK? */
+    if (((uid == filestat.st_uid) && (filestat.st_mode & S_IRUSR) && (filestat.st_mode & S_IWUSR)) ||
+	((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+    } else {
+      if (VERBOSE) fprintf (stderr, "can't write to %s\n", basefile);
+      return (FALSE);
+    }
+  }
+  
+  /* check permission to write to backup file */
+  if (BACKUP) {
+    ALLOCATE (filename, char, strlen(basefile) + 2);
+    sprintf (filename, "%s~", basefile);
+    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_IWUSR)) ||
+	  ((gid == filestat.st_gid) && (filestat.st_mode & S_IRGRP) && (filestat.st_mode & S_IWGRP)) || 
+	  ((filestat.st_mode & S_IROTH) && (filestat.st_mode & S_IWOTH))) {
+      } else {
+	if (VERBOSE) fprintf (stderr, "can't write to %s\n", filename);
+	return (FALSE);
+      }
+    }
+    free (filename);
+  }
+  return (TRUE);
+}
+
+/* pathname:
+   given path/filename, returns path
+   given just filename, returns . 
+   given path1/path2/,  returns path1
+*/
+
+char *pathname (char *infile) {
+ 
+  int i;
+  char *c, *file;
+
+  /* make working version */
+  file = strcreate (infile);
+
+  /* strip off trailing / */
+  for (i = strlen (file); (i > 0) && (file[i] == '/'); i--) file[i] = 0;
+
+  c = strrchr (file, '/');
+  if (c == (char *) NULL) {
+    strcpy (file, ".");
+  } else {
+    *c = 0;
+  }
+  
+  return (file);
+  
+}
+
+/* filerootname
+
+   given /path/file.ext return file 
+   given /path/file return file 
+   given /path/file/ return file 
+*/
+
+char *filerootname (char *infile) {
+
+  int i;
+  char *file, *root, *p1, *p2;
+
+  /* make working version */
+  file = strcreate (infile);
+
+  /* strip off trailing / */
+  for (i = strlen (file); (i > 0) && (file[i] == '/'); i--) file[i] = 0;
+
+  /* find last / */
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) 
+    p1 = file;
+  else
+  p1 ++;
+
+  /* find last . */
+  p2 = strrchr (file, '.');
+  if (p2 == (char *) NULL) p2 = p1 + strlen(p1);
+
+  /* create new string, free working space */
+  root = strncreate (p1, p2-p1);
+  free (file);
+
+  return (root);
+
+}  
+
+/* fileextname
+
+   given /path/file.ext return ext 
+   given /path/file return NULL 
+   given /path/file/ return NULL 
+   given file.ext return ext
+*/
+
+char *fileextname (char *file) {
+
+  char *root, *p1, *p2;
+
+  /* find last / */
+  p1 = strrchr (file, '/');
+  if (p1 == (char *) NULL) p1 = file;
+
+  /* find last . after p1 */
+  p2 = strrchr (p1, '.');
+  if (p2 == (char *) NULL) return ((char *) NULL);
+  p2 ++;
+
+  /* create new string, free working space */
+  root = strncreate (p2, strlen(p2));
+  return (root);
+
+}  
+
+/* given /path/file.ext return file.ext */
+char *filebasename (char *name) {
+ 
+  char *c, *file;
+
+  ALLOCATE (file, char, strlen(name) + 1);
+  strcpy (file, name);
+  c = strrchr (file, '/');
+  if (c == (char *) NULL) {
+    strcpy (file, name);
+  } else {
+    strcpy (file, c+1);
+  }
+  
+  return (file);
+  
+}
+
+char *findexec (int argc, char **argv) {
+
+  int i, N, done, status;
+  char *c, *e, *dir, path[1024], name[1024];
+
+  /* if given an absolute or relative path, use it */
+  if (strchr (argv[0], '/') != (char *) NULL) {
+    status = check_file_exec (argv[0]);
+    if (status) {
+      if (realpath (argv[0], path) == (char *) NULL) return ((char *) NULL);
+      dir = pathname (path);
+      return (dir);
+    } else {
+      return ((char *) NULL);
+    }
+  }
+  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) {
+      bzero (path, 1024);
+      if (e == (char *) NULL) {
+	done = TRUE;
+	strncpy (path, c, strlen(c));
+      } else {
+	strncpy (path, c, e-c);
+	c = e+1;
+	e = strchr (c, ':');
+      }
+      sprintf (name, "%s/%s", path, argv[0]);
+      status = check_file_exec (name);
+
+      if (status) {
+	if (realpath (name, path) == (char *) NULL) continue;
+	dir = pathname (path);
+	return (dir);
+      }
+    }
+  }
+  return ((char *) NULL);
+}
+
+/* make directory hierarchy, 0: success, -1: failure (just like mkdir) */
+int mkdirhier (char *path, int mode) {
+
+  char *tpath;
+
+  /* force addition of user exec/read/write */
+  mode |= S_IRWXU;
+  if (mkdir (path, mode)) {
+    if (errno == ENOENT) { 
+      tpath = pathname (path);
+      if (!mkdirhier (tpath, mode)) {
+	free (tpath);
+	if (mkdir (path, mode)) {
+	  return (-1);
+	} else {
+	  errno = 0;
+	  return (0);
+	}
+      } else {
+	free (tpath);
+	return (-1);
+      }
+    } else {
+      return (-1);
+    }
+  } else {
+    return (0);
+  }
+}
+
+char *getcwd_cfht (char *path, int size) {
+  
+  char *hostname, *newpath, *p;
+
+  path = getcwd (path, size);
+  
+  if (!strncmp (path, "/local/data", strlen ("/local/data"))) {
+    
+    ALLOCATE (hostname, char, size);
+
+    if (gethostname (hostname, size-1)) {
+      fprintf (stderr, "ERROR: can't get hostname\n");
+      free (hostname);
+      return ((char *) NULL);
+    }
+    if ((p = strchr (hostname, '.')) != (char *) NULL) *p = 0;
+    
+    ALLOCATE (newpath, char, size);
+    /* path might be just /local/data or /local/data/ */
+       
+    p = path + strlen ("/local/data/");
+    if (strlen (path) <= strlen ("/local/data/")) {
+      snprintf (newpath, size, "/data/%s", hostname);
+    } else {
+      snprintf (newpath, size, "/data/%s/%s", hostname, p);
+    }      
+
+    free (hostname);
+    strcpy (path, newpath);
+
+    free (newpath);
+
+  }
+
+  return (path);
+
+}
+
+void make_backup (char *filename) {
+
+  int status, cmode;
+  struct stat filestat;
+  char line[256];
+
+  status = stat (filename, &filestat);
+  if (status == 0) { /* file exists, make backup copy */
+    sprintf (line, "cp %s %s~", filename, filename);
+    status = system (line);
+    if (status) {
+      fprintf (stderr, "ERROR: unable to create %s~, exiting\n", filename);
+      exit (1);
+    }
+    cmode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    sprintf (line, "%s~", filename);
+    chmod (line, cmode);
+  }
+}
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status, k;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      return (0);
+    }
+  }
+  return (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/gaussj.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/gaussj.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/gaussj.c	(revision 16632)
@@ -0,0 +1,262 @@
+# include <ohana.h>
+
+// Gauss-Jordan elimination using full pivots based on Press et al's description.  Substantially
+// reworked for Ohana: major modifications to conform to C indexing, use a boolean to track the
+// completed pivot rows and catch the singular matrix early on.  Also, much cleaner control loops
+// than their implementation.  XXX this really needs to check on round-off errors (see version by
+// William Kahan
+int dgaussjordan (double **A, double **B, int N, int M) {
+
+  int *colIndex;
+  int *rowIndex;
+  int *pivot;
+  
+  int diag, col, row;
+
+  ALLOCATE (colIndex, int, N);
+  ALLOCATE (rowIndex, int, N);
+  ALLOCATE (pivot, int, N);
+  memset (pivot, 0, N*sizeof(int));
+
+  // determine underflow conditions
+  // double underFlow = DBL_MIN;
+# if (0)
+  double roundTest = 4.0;
+  roundTest /= 3.0;
+  roundTest -= 1.0;
+  double epsilon = fabs(((roundTest+roundTest) - 1.0) + roundTest);
+  double growth = 1.0;
+# endif
+
+  // Following the algorithm laid out by Press et al., we loop along the matrix diagonal,
+  // but we do not operate on the diagonal elements in order instead, we are looking for
+  // the current max element and operating on that diagonal element.  this is effectively
+  // column pivoting.  row pivoting is perfomed explicitly.  
+
+  for (diag = 0; diag < N; diag++) {
+
+    double maxval = 0.0;
+    int maxrow = 0;
+    int maxcol = 0;
+
+    // search for the next pivot
+    for (row = 0; row < N; row++) {
+      if (!finite(A[row][diag])) goto escape;
+
+      // if we have already operated on this row (pivot[row] is true), skip it
+      if (pivot[row]) continue;
+
+      // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row
+      for (col = 0; col < N; col++) {
+	if (pivot[col]) continue;
+	if (fabs (A[row][col]) < maxval) continue;
+	maxval = fabs (A[row][col]);
+	maxrow = row;
+	maxcol = col;
+      }
+    }
+
+    // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix
+    if (pivot[maxcol]) goto escape;
+    pivot[maxcol] = TRUE;
+
+    // if the selected pivot is off the diagonal, do a row swap
+    if (maxrow != maxcol) {
+      for (col = 0; col < N; col++) SWAP (A[maxrow][col], A[maxcol][col]);
+      for (col = 0; col < M; col++) SWAP (B[maxrow][col], B[maxcol][col]);
+    }
+    rowIndex[diag] = maxrow;
+    colIndex[diag] = maxcol;
+    if (A[maxcol][maxcol] == 0.0) goto escape;
+    // XXX Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow
+
+    /* rescale by pivot reciprocal */
+    double tmpval = 1.0 / A[maxcol][maxcol];
+    A[maxcol][maxcol] = 1.0;
+    for (col = 0; col < N; col++) A[maxcol][col] *= tmpval;
+    for (col = 0; col < M; col++) B[maxcol][col] *= tmpval;
+    // XXX measure the pivot growth and trigger on over/under flow
+    // growth *= tmpval;
+    // fprintf (stderr, "column: %d, growth: %e, epsilon: %e\n", maxcol, growth, epsilon);
+
+    /* adjust the elements above the pivot */
+    for (row = 0; row < N; row++) {
+      if (row == maxcol) continue;
+      tmpval = A[row][maxcol];
+      A[row][maxcol] = 0.0;
+      for (col = 0; col < N; col++) A[row][col] -= A[maxcol][col]*tmpval;
+      for (col = 0; col < M; col++) B[row][col] -= B[maxcol][col]*tmpval;
+    }
+  }
+
+  // swap back the inverse matrix based on the row swaps above
+  for (col = N - 1; col >= 0; col--) {
+    if (rowIndex[col] != colIndex[col]) {
+      for (row = 0; row < N; row++) SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]);
+    }
+  }
+
+  free (pivot);
+  free (rowIndex);
+  free (colIndex);
+  return (TRUE);
+
+escape:
+  free (pivot);
+  free (rowIndex);
+  free (colIndex);
+  return (FALSE);
+}
+
+int fgaussjordan (float **A, float **B, int N, int M) {
+
+  int *colIndex;
+  int *rowIndex;
+  int *pivot;
+  
+  int diag, col, row;
+
+  ALLOCATE (colIndex, int, N);
+  ALLOCATE (rowIndex, int, N);
+  ALLOCATE (pivot, int, N);
+  memset (pivot, 0, N*sizeof(int));
+
+  // determine underflow conditions
+  // float underFlow = FLT_MIN;
+# if (0)
+  float roundTest = 4.0;
+  roundTest /= 3.0;
+  roundTest -= 1.0;
+  float epsilon = fabs(((roundTest+roundTest) - 1.0) + roundTest);
+  float growth = 1.0;
+# endif
+
+  // we loop along the matrix diagonal, but we do not operate on the diagonal elements in
+  // order instead, we are looking for the current max element and operating on that
+  // diagonal element.  this is effectively column pivoting.  row pivoting is perfomed
+  // explicitly 
+
+  for (diag = 0; diag < N; diag++) {
+
+    float maxval = 0.0;
+    int maxrow = 0;
+    int maxcol = 0;
+
+    // search for the next pivot
+    for (row = 0; row < N; row++) {
+      if (!finite(A[row][diag])) goto escape;
+
+      // if we have already operated on this row (pivot[row] is true), skip it
+      if (pivot[row]) continue;
+
+      // if we have not yet operated on this row (pivot[row] is false), look for pivot for this row
+      for (col = 0; col < N; col++) {
+	if (pivot[col]) continue;
+	if (fabs (A[row][col]) < maxval) continue;
+	maxval = fabs (A[row][col]);
+	maxrow = row;
+	maxcol = col;
+      }
+    }
+
+    // if pivot[maxcol] is set, we have already done this row: this implies a singular matrix
+    if (pivot[maxcol]) goto escape;
+    pivot[maxcol] = TRUE;
+
+    // if the selected pivot is off the diagonal, do a row swap
+    if (maxrow != maxcol) {
+      for (col = 0; col < N; col++) SWAP (A[maxrow][col], A[maxcol][col]);
+      for (col = 0; col < M; col++) SWAP (B[maxrow][col], B[maxcol][col]);
+    }
+    rowIndex[diag] = maxrow;
+    colIndex[diag] = maxcol;
+    if (A[maxcol][maxcol] == 0.0) goto escape;
+    // XXX Kahan replaces the 0.0 pivot with epsilon*(largest element in column) + underFlow
+
+    /* rescale by pivot reciprocal */
+    float tmpval = 1.0 / A[maxcol][maxcol];
+    A[maxcol][maxcol] = 1.0;
+    for (col = 0; col < N; col++) A[maxcol][col] *= tmpval;
+    for (col = 0; col < M; col++) B[maxcol][col] *= tmpval;
+    // growth *= tmpval;
+    // fprintf (stderr, "column: %d, growth: %e, epsilon: %e\n", maxcol, growth, epsilon);
+
+    /* adjust the elements above the pivot */
+    for (row = 0; row < N; row++) {
+      if (row == maxcol) continue;
+      tmpval = A[row][maxcol];
+      A[row][maxcol] = 0.0;
+      for (col = 0; col < N; col++) A[row][col] -= A[maxcol][col]*tmpval;
+      for (col = 0; col < M; col++) B[row][col] -= B[maxcol][col]*tmpval;
+    }
+  }
+
+  // swap back the inverse matrix based on the row swaps above
+  for (col = N - 1; col >= 0; col--) {
+    if (rowIndex[col] != colIndex[col]) {
+      for (row = 0; row < N; row++) SWAP (A[row][rowIndex[col]], A[row][colIndex[col]]);
+    }
+  }
+
+  free (pivot);
+  free (rowIndex);
+  free (colIndex);
+  return (TRUE);
+
+escape:
+  free (pivot);
+  free (rowIndex);
+  free (colIndex);
+  return (FALSE);
+}
+
+
+/* Gauss-Jordan Inversion from William Kahan in Basic
+500 ' Gauss-Jordan Matrix Inversion     X = A^(-1) in IBM PC BASIC
+510 ' including checks for excessive    growth despite row-pivoting,
+520 '          and adjustments for zero pivots to avoid .../0 .
+530 ' DIM A(N,N), X(N,N), P(N) ...      are assumed.
+540     DEFINT I-N ' ... integer variables; the rest are REAL.
+550   '
+560   ' First determine levels of roundoff and over/underflow.
+570     UFL = 5.9E-39 ' ... = max{ under, 1/over}flow thresholds.
+580        G=4 : G=G/3 : G=G-1      ' ... = 1/3 + roundoff in 4/3
+590     EPS = ABS( ((G+G) - 1) + G ) ' ... = roundoff level.
+600     G = 1 ' ... will record pivot-growth factor
+610   '
+620   ' Copy A to X and record each column's biggest element.
+630     FOR J=1 TO N : P(J)=0
+640          FOR I=1 TO N : T = A(I,J) : X(I,J) = T : T = ABS(T)
+650                IF T > P(J) THEN P(J) = T
+660                NEXT I : NEXT J
+670   '
+680     FOR K=1 TO N :' ... perform elimination upon column K .
+690          Q=0 : J=K : ' ... search for Kth pivot ...
+700          FOR I=K TO N
+710                T=ABS(X(I,K)) : IF T>Q THEN Q=T : J=I
+720                NEXT I
+730          IF Q=0 THEN Q = EPS*P(K) + UFL : X(K,K)=Q
+740          IF P(K)>0 THEN Q=Q/P(K) : IF Q>G THEN G=Q
+750          IF G<=8*K THEN GOTO 790
+760      PRINT "Growth factor g = ";G;" exceeds ";8*K;" ; try"
+770      PRINT "moving A's column ";K;" to col. 1 to reduce g ."
+780            STOP ' ... or go back to re-order A's columns.
+790         P(K)=J ' ... record pivotal row exchange, if any.
+800         IF J=K THEN GOTO 830 ' ... Don't bother to swap.
+810             FOR L=1 TO N : Q=X(J,L) : X(J,L)=X(K,L)
+820                              X(K,L)=Q : NEXT L
+830         Q = X(K,K) : X(K,K) = 1
+840         FOR J=1 TO N : X(K,J) = X(K,J)/Q : NEXT J
+850         FOR I=1 TO N : IF I=K THEN GOTO 890
+860              Q = X(I,K) : X(I,K) = 0
+870              FOR J=1 TO N
+880                   X(I,J) = X(I,J) - X(K,J)*Q : NEXT J
+890              NEXT I : NEXT K
+900 '
+910 FOR K=N-1 TO 1 STEP -1 ' ... unswap columns of X
+920         J=P(K) : IF J=K THEN GOTO 950
+930         FOR I=1 TO N : Q=X(I,K) : X(I,K)=X(I,J)
+940                          X(I,J)=Q : NEXT I
+950         NEXT K
+960 RETURN
+*/
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/glockfile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/glockfile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/glockfile.c	(revision 16632)
@@ -0,0 +1,242 @@
+# include <ohana.h>
+
+FILE *fsetlockfile (char *filename, double timeout, int type, int *state) {
+  
+  int i, nbytes, status;
+  char *lockname, buffer[64];
+  char *file, *path, mode[3];
+  int fd;
+  FILE *f, *flock;
+  struct stat filestat;
+  struct flock filelock;
+  struct timeval now, then;
+
+  f = flock = NULL;
+  file = path = lockname = NULL;
+
+  /* define lock type */
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+  switch (type) {
+  case LCK_HARD:
+  case LCK_XCLD:
+    filelock.l_type   = F_WRLCK;  /* set an exclusive lock */
+    strcpy (mode, "r+");
+    break;
+  case LCK_SOFT:
+    filelock.l_type   = F_RDLCK;  /* set a shared lock */
+    strcpy (mode, "r");
+    break;
+  default:
+    *state = LCK_INVALID;
+    goto failure;
+  }
+
+  /* check if file exists */
+  status = stat (filename, &filestat);
+  if ((status == -1) && (errno == ENOENT)) {
+    /* if soft, return LCK_ACCESS */
+    if (type == LCK_SOFT) {
+      *state = LCK_MISSING;
+      goto failure;
+    } 
+    /* otherwise, we need to be able to create file */ 
+    strcpy (mode, "w+");
+  }
+  
+  /* try to open file (create if it does not exist) */
+  f = fopen (filename, mode);
+  if (f == NULL) {
+    *state = LCK_ACCESS;
+    goto failure;
+  }
+  fd = fileno (f);
+
+  /* we first try to set a FS level lock on the file */
+  gettimeofday (&then, (void *) NULL);
+  while (1) {
+    /* try to lock file */
+    if (fcntl (fd, F_SETLK, &filelock) != -1) goto got_lock;
+
+    /* check for timeout */
+    gettimeofday (&now, (void *) NULL);
+    if (DTIME (now, then) > timeout) {
+      *state = LCK_TIMEOUT;
+      goto failure;
+    }
+    usleep (10000); /* 10 ms is min utime */
+  }
+got_lock:
+
+  /* check if blocking hardlock exists */
+  if (type == LCK_HARD) {
+    /* set up name to lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+
+    status = stat (lockname, &filestat);
+    if ((status == -1) && (errno == ENOENT)) {
+      strcpy (mode, "w+");
+    } else {
+      strcpy (mode, "r+");
+    }
+
+    /* try to open lockfile */
+    flock = fopen (lockname, mode);
+    if (flock == NULL) {
+      *state = LCK_HARDOPEN;
+      goto failure;
+    }
+    fd = fileno (flock);
+    
+    /* try a few times to lock lockfile (locking the lockfile before checking
+       the contents will ensure the data is synced across NFS) */
+    for (i = 0; (i < 20) && (fcntl (fd, F_SETLK, &filelock) == -1); i++) usleep (10000);
+    if (i == 20) {
+      *state = LCK_HARDLOCK;
+      goto failure;
+    }
+    
+    /* we've locked the lockfile, now read the contents */
+    nbytes = fread (buffer, 1, 4, flock);
+    if (nbytes == 4) { /* lock file has a word in it */
+      buffer[4] = 0;
+      if (!strcmp (buffer, "BUSY")) { 
+	*state = LCK_HARDLOCKHARD;
+	goto failure;
+      }
+      /* note that we don't care if the lockfile has random garbage */
+    }
+  }
+    
+  /* set blocking hardlock */
+  if (type == LCK_HARD) {
+    /* we've really got the lock, write BUSY to protect it */
+    fseek (flock, 0, SEEK_SET);
+    nbytes = fprintf (flock, "BUSY\n");
+
+    /* 
+    if (nbytes != 5) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+      } */
+    
+    /* now fclose lockfile (also unlocks file) */
+    if (fclose (flock)) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+    }
+    flock = NULL;
+  }
+
+  /* check if file is empty or not */
+  fd = fileno (f);
+  if (fstat (fd, &filestat)) {
+    *state = LCK_UNKNOWN;
+  } else {
+    if (filestat.st_size == 0) {
+      *state = LCK_EMPTY;
+    } else {
+      *state = LCK_FULL;
+    }
+  }
+
+  if (path     != NULL) free (path);
+  if (file     != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  if (flock    != NULL) fclose (flock);
+  return (f);
+
+failure:
+  if (f        != NULL) fclose (f);
+  if (flock    != NULL) fclose (flock);
+  if (path     != NULL) free (path);
+  if (file     != NULL) free (file);
+  if (lockname != NULL) free (lockname);
+  return (NULL);
+}
+  
+/* clears lock. removes hardlock even if file pointer is not supplied */
+int fclearlockfile (char *filename, FILE *f, int type, int *state) {
+
+  int i, fd, status, nbytes;
+  char *lockname, *path, *file;
+  FILE *flock;
+  struct stat filestat;
+  struct flock filelock;
+
+  file = path = lockname = (char *) NULL;
+
+  /* define lock */
+  filelock.l_type   = F_UNLCK;
+  filelock.l_start  = 0;
+  filelock.l_whence = SEEK_SET;
+  filelock.l_len    = 0;
+  filelock.l_pid    = getpid ();
+
+  /* first clear hard lockfile */
+  if (type == LCK_HARD) {
+
+    /* define lockfile */
+    path = pathname (filename);
+    file = filebasename (filename);
+    ALLOCATE (lockname, char, strlen (path) + strlen (file) + 10);
+    sprintf (lockname, "%s/.%s.lck", path, file);
+    
+    /* check for lockfile existance */
+    status = stat (lockname, &filestat);
+    if (status == -1) {
+      *state = LCK_HARDLOCK;
+      goto failure;
+    } 
+  
+    /* try to open lockfile */
+    flock = fopen (lockname, "w+");
+    if (flock == NULL) {
+      *state = LCK_HARDOPEN;
+      goto failure;
+    }
+    fd = fileno (flock);
+
+    /* try a few times to lock lockfile */
+    filelock.l_type = F_WRLCK;
+    for (i = 0; (i < 20) && (fcntl (fd, F_SETLK, &filelock) == -1); i++) usleep (10000);
+    if (i == 20) {
+      *state = LCK_HARDLOCKHARD;
+      goto failure;
+    }
+
+    /* set value to IDLE */
+    fseek (flock, 0, SEEK_SET);
+    nbytes = fprintf (flock, "IDLE\n");
+    if (nbytes != 5) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+    }
+
+    if (fclose (flock)) {
+      *state = LCK_HARDCLOSE;
+      goto failure;
+    }
+    flock = NULL;
+  }
+  
+  /* now unlock the file */
+  fclose (f);
+
+  *state = LCK_UNLOCK;
+  if (path != NULL)     free (path);
+  if (file != NULL)     free (file);
+  if (lockname != NULL) free (lockname);
+  return (1);
+
+failure:
+  if (path != NULL)     free (path);
+  if (file != NULL)     free (file);
+  if (lockname != NULL) free (lockname);
+  return (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/ohana_allocate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/ohana_allocate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/ohana_allocate.c	(revision 16632)
@@ -0,0 +1,293 @@
+# include <stdio.h>
+# include <stdlib.h>
+# include <stdarg.h>
+
+/* need an internal version that does not use ohana_memory functions */
+# define FALSE 0 
+# define TRUE 1
+# define MAX(X,Y) ((X) > (Y) ? (X) : (Y))
+# define OHANA_ALLOCATE(X,T,S)  \
+  X = (T *) malloc ((unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+  if (X == NULL) { \
+    fprintf(stderr,"failed malloc at %d in %s\n", __LINE__, __FILE__);\
+    abort(); } 
+# define OHANA_REALLOCATE(X,T,S) \
+  X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+  if (X == NULL) { \
+    fprintf(stderr,"failed realloc at %d in %s\n", __LINE__, __FILE__);\
+    abort(); }
+# define OHANA_CHECK_REALLOCATE(X,T,S,N,D) \
+  if ((N) >= (S)) { \
+    S += D; \
+    X = (T *) realloc(X,(unsigned)(MAX(((S)*((int)sizeof(T))),1))); \
+    if (X == NULL) { \
+      fprintf(stderr,"failed realloc increment at %d in %s\n", __LINE__, __FILE__);\
+      abort(); } }
+# define OHANA_FREE(X) free(X)
+
+# define STATE_ALLOC    0
+# define STATE_REALLOC  1
+# define STATE_FREE     2
+# define STATE_EXTERNAL 3
+
+typedef struct {
+  char *file;
+  int   line;
+  void *ptr;   // location of externally visible entry
+  int   size;
+  int   state;
+} Memlist;
+
+// XXX consider fixing the memory tracking model (list?)
+// static long *memsort;
+// static long *memhash;
+static Memlist *memlist = NULL;
+int Nmemlist = 0;
+int NMEMLIST = 0;
+int NMEMBYTE = 0;
+
+void ohana_meminit () {
+  Nmemlist = 0;
+  NMEMLIST = 1000;
+  OHANA_ALLOCATE (memlist, Memlist, NMEMLIST);
+  // OHANA_ALLOCATE (memsort, long, NMEMLIST);
+  // OHANA_ALLOCATE (memhash, long, NMEMLIST);
+  NMEMBYTE = sizeof(size_t);
+}
+
+void ohana_memabort (char *format, ...) {
+  va_list argp;  
+
+  va_start (argp, format);
+  vfprintf (stderr, format, argp);
+  va_end (argp);
+  abort();
+}
+
+void *ohana_malloc (char *file, int line, int Nelem, size_t esize) {
+
+  void *ptr, *new;
+  int size;
+  size_t *marker;
+
+  if (memlist == NULL) ohana_meminit ();
+
+  Nelem = MAX (1, Nelem);
+  size = Nelem * esize;
+
+  new = malloc (size + 2*NMEMBYTE); /* 2 extra locations to save endposts */
+  if (new == NULL) ohana_memabort ("failed to allocate memory (%s, %d)\n", file, line);
+  ptr = new + NMEMBYTE;
+
+  marker = (size_t *) new;
+  *marker = 0xdeadbeef;
+  marker = (size_t *)(new + size + NMEMBYTE);
+  *marker = 0xdeadbeef;
+
+  /* new memory, add to stack */
+  memlist[Nmemlist].ptr  = ptr;
+  memlist[Nmemlist].file = file;
+  memlist[Nmemlist].line = line;
+  memlist[Nmemlist].size = size;
+  memlist[Nmemlist].state = STATE_ALLOC;
+
+  // before each free, we sort this pair to speed up searching
+  // memsort[Nmemlist] = ptr;
+  // memhash[Nmemlist] = Nmemlist;
+
+  Nmemlist ++;
+  if (Nmemlist == NMEMLIST) {
+    NMEMLIST += 1000;
+    OHANA_REALLOCATE (memlist, Memlist, NMEMLIST);
+  }
+  return (ptr);
+}
+
+void *ohana_realloc (char *file, int line, void *in, int Nelem, size_t esize) {
+
+  int i, size;
+  void *ptr, *ref, *new;
+  size_t *marker;
+
+  if (memlist == NULL) ohana_memabort ("REALLOCATE before ALLOCATE");
+
+  Nelem = MAX (1, Nelem);
+  size = Nelem * esize;
+
+  ref = in - NMEMBYTE;
+
+  /* find old entry, update ptr, file, line */
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_FREE) continue;
+    if (memlist[i].ptr == in) {
+
+      if (memlist[i].state == STATE_EXTERNAL) ohana_memabort ("ERROR: realloc of external memory");
+
+      /* ask for new memory */
+      new = realloc (ref, size + 2*NMEMBYTE); /* 2 extra slots to save endposts */
+      if (new == NULL) ohana_memabort ("failed to reallocate memory (%s, %d)\n", file, line);
+      ptr = new + NMEMBYTE;
+      
+      /* set the marker */
+      marker = (size_t *) new;
+      *marker = 0xdeadbeef;
+      marker = (size_t *)(ptr + size);
+      *marker = 0xdeadbeef;
+
+      /* otherwise, update memory new location */
+      memlist[i].ptr = ptr;
+      memlist[i].size = size;
+      memlist[i].state = STATE_REALLOC;
+
+      /* if new memory in new location, update references */
+      if (ptr != in) {
+	memlist[i].file = file;
+	memlist[i].line = line;
+      }
+
+      return (ptr);
+    }
+  }
+  ohana_memabort ("allocated memory not found for realloc (%s, %d)\n", file, line);
+  return (NULL);
+}
+
+// this is very slow.  should we speed this up by indexing on the ptr?
+void ohana_free (char *file, int line, void *in) {
+
+  int i;
+
+  if (memlist == NULL) ohana_memabort ("FREE before ALLOCATE");
+
+  /* find old entry, set state */
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_FREE) continue;
+    if (memlist[i].ptr == in) {
+      memlist[i].state = STATE_FREE;
+      return;
+    }
+  }
+
+  /* find already freed examples */
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].ptr == in) {
+      fprintf (stderr, "used here: %4d %s %d\n", i, memlist[i].file, memlist[i].line);
+    }
+  }
+
+  ohana_memabort ("allocated memory not found for free (%s, %d : %x)\n", file, line, in);
+  return;
+}
+
+/* register externally allocated memory with ohana memory manager */
+void ohana_memregister_func (char *file, int line, void *ptr) {
+
+  if (memlist == NULL) ohana_meminit ();
+
+  /* add to stack */
+  memlist[Nmemlist].ptr  = ptr;
+  memlist[Nmemlist].file = file;
+  memlist[Nmemlist].line = line;
+  memlist[Nmemlist].state = STATE_EXTERNAL;
+  Nmemlist ++;
+  if (Nmemlist == NMEMLIST) {
+    NMEMLIST += 1000;
+    OHANA_REALLOCATE (memlist, Memlist, NMEMLIST);
+  }
+  return;
+}
+
+void ohana_memcheck_func (int allmemory) {
+
+  int i, j, next, prev, header;
+  size_t *marker;
+  char top, bottom;
+
+  if (Nmemlist == 0) {
+    fprintf (stderr, "no memory allocated\n");
+    return;
+  }
+
+  header = FALSE;
+  fprintf (stderr, "checking %d memory blocks\n", Nmemlist);
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_EXTERNAL) continue;
+    if ((allmemory == 0) && (memlist[i].state == STATE_FREE)) continue;
+
+    top = bottom = 'Y';
+    marker = (size_t *)(memlist[i].ptr - NMEMBYTE);
+    if (*marker == 0xdeadbeef) bottom = 'N';
+    marker = (size_t *)(memlist[i].ptr + memlist[i].size);
+    if (*marker == 0xdeadbeef) top = 'N';
+    
+    if ((top == 'N') && (bottom == 'N')) continue;
+    if (!header) {
+      fprintf (stderr, "         Nmem start end file            line\n");
+      header = TRUE;
+    }
+      fprintf (stderr, "corrupt:  %3d   %c    %c  %-15s %3d\n", i, bottom, top, memlist[i].file, memlist[i].line);
+    prev = next = -1;
+    for (j = 0; j < Nmemlist; j++) {
+      if (memlist[j].ptr < memlist[i].ptr) {
+	if (prev == -1) prev = j;
+	if (memlist[j].ptr > memlist[prev].ptr) prev = j;
+      }
+      if (memlist[j].ptr > memlist[i].ptr) {
+	if (next == -1) next = j;
+	if (memlist[j].ptr < memlist[next].ptr) next = j;
+      }
+    }	  
+    if (prev == -1) {
+      fprintf (stderr, "no previous memory block\n");
+    } else {
+      fprintf (stderr, "prev:     %3d           %-15s %3d\n", prev, memlist[prev].file, memlist[prev].line);
+    }
+    if (next == -1) {
+      fprintf (stderr, "no next memory block\n");
+    } else {
+      fprintf (stderr, "next:     %3d           %-15s %3d\n", next, memlist[next].file, memlist[next].line);
+    }
+    abort ();
+  }
+  return;
+}
+
+void ohana_memdump_func (int allmemory) {
+
+  int i, Ns[3], N;
+  char S[3];
+
+  if (Nmemlist == 0) {
+    fprintf (stderr, "no memory allocated\n");
+    return;
+  }
+
+  S[0] = 'A';
+  S[1] = 'R';
+  S[2] = 'F';
+  S[3] = 'X';
+  Ns[0] = Ns[1] = Ns[2] = Ns[3] = 0;
+  N = 0;
+
+  for (i = 0; i < Nmemlist; i++) {
+    if (memlist[i].state == STATE_ALLOC)    N = 0;
+    if (memlist[i].state == STATE_REALLOC)  N = 1;
+    if (memlist[i].state == STATE_FREE)     N = 2;
+    if (memlist[i].state == STATE_EXTERNAL) N = 2;
+    Ns[N] ++;
+    if ((allmemory == 0) && (memlist[i].state == STATE_FREE)) continue;
+    if (memlist[i].state == STATE_EXTERNAL) {
+      fprintf (stderr, "%3d %4d %lx : %lx - extern (extern     extern) %c %s %d\n", 
+	       Ns[N], i, (long)memlist[i].ptr, (long)memlist[i].ptr, 
+	       S[N], memlist[i].file, memlist[i].line);
+    } else {
+      fprintf (stderr, "%3d %4d %lx : %lx - %lx (%lx %lx) %c %s %d\n", 
+	       Ns[N], i, (long)memlist[i].ptr, (long)(memlist[i].ptr - NMEMBYTE), (long)(memlist[i].ptr + memlist[i].size + NMEMBYTE), 
+	       *(long *)(memlist[i].ptr - NMEMBYTE), *(long *)(memlist[i].ptr + memlist[i].size), 
+	       S[N], memlist[i].file, memlist[i].line);
+    }
+  }
+  fprintf (stderr, "Nused: %d (Nalloc: %d, Nrealloc: %d), Nfree: %d\n", 
+	   Ns[0]+Ns[1], Ns[0], Ns[1], Ns[2]);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/sorts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/sorts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/sorts.c	(revision 16632)
@@ -0,0 +1,105 @@
+# include <ohana.h>
+
+/* various widely-used sort functions for specific sets of types */
+
+void dsort (double *value, int N) {
+
+# define SWAPFUNC(A,B){ double tmp = value[A]; value[A] = value[B]; value[B] = tmp; }
+# define COMPARE(A,B)(value[A] < value[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void fsort (float *value, int N) {
+
+# define SWAPFUNC(A,B){ float tmp = value[A]; value[A] = value[B]; value[B] = tmp; }
+# define COMPARE(A,B)(value[A] < value[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void fsortpair (float *X, float *Y, int N) {
+
+# define SWAPFUNC(A,B){ float tmp; \
+  tmp = X[A]; X[A] = X[B]; X[B] = tmp; \
+  tmp = Y[A]; Y[A] = Y[B]; Y[B] = tmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void dsortpair (double *X, double *Y, int N) {
+
+# define SWAPFUNC(A,B){ double tmp; \
+  tmp = X[A]; X[A] = X[B]; X[B] = tmp; \
+  tmp = Y[A]; Y[A] = Y[B]; Y[B] = tmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+// sort two int vectors by first vector
+void isortpair (int *X, int *Y, int N) {
+
+# define SWAPFUNC(A,B){ int tmp; \
+  tmp = X[A]; X[A] = X[B]; X[B] = tmp; \
+  tmp = Y[A]; Y[A] = Y[B]; Y[B] = tmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void fsortthree (float *X, float *Y, float *Z, int N) {
+
+# define SWAPFUNC(A,B){ float tmp; \
+  tmp = X[A]; X[A] = X[B]; X[B] = tmp; \
+  tmp = Y[A]; Y[A] = Y[B]; Y[B] = tmp; \
+  tmp = Z[A]; Z[A] = Z[B]; Z[B] = tmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
+
+void dsortthree (double *X, double *Y, double *Z, int N) {
+
+# define SWAPFUNC(A,B){ double tmp; \
+  tmp = X[A]; X[A] = X[B]; X[B] = tmp; \
+  tmp = Y[A]; Y[A] = Y[B]; Y[B] = tmp; \
+  tmp = Z[A]; Z[A] = Z[B]; Z[B] = tmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/string.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/string.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/string.c	(revision 16632)
@@ -0,0 +1,239 @@
+# include <ohana.h>
+
+/* Strip WHITESPACE from the start and end of STRING. */
+int stripwhite (char *string) {
+
+  int i;
+
+  if (string == (char *) NULL) return (FALSE);
+
+  for (i = 0; OHANA_WHITESPACE (string[i]); i++);
+  if (i) memmove (string, string + i, strlen(string+i)+1);
+  for (i = strlen (string) - 1; (i > 0) && OHANA_WHITESPACE (string[i]); i--);
+  string[++i] = 0;
+  return (i);
+
+}
+
+/* compare two strings either as strings, or as numbers if both are
+   pure numeric strings (base 10) */
+int strnumcmp (char *str1, char *str2) {
+
+  char *end1;
+  char *end2;
+  int num1, num2;
+  int value;
+ 
+  value = FALSE;
+  num1 = strtol (str1, &end1, 10);
+  num2 = strtol (str2, &end2, 10);
+
+  if (!end1[0] && !end2[0] && (num1 == num2)) {
+    value = TRUE;
+  }
+  if (!strcmp (str1, str2)) {
+    value = TRUE;
+  }
+  
+  return (value);
+}
+
+/* create a new string from this string */
+char *strcreate (char *string) {
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, MAX (1, strlen(string)) + 1);
+  line = strcpy (line, string);
+
+  return (line);
+}
+
+/* create a new string of length n from this string */
+char *strncreate (char *string, int n) {
+
+  char *line;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  ALLOCATE (line, char, n + 1);
+  memcpy (line, string, n);
+  line[n] = 0;
+  return (line);
+}
+
+// replace a single entry of 'match' in the string with 'with'
+// (quick-and-dirty regex for a common case...)
+char *strsubs (char *string, char *match, char *with) {
+
+  int N1, N2, N3;
+  char *root;
+  char *out;
+  char *ext;
+
+  if (string == NULL) return NULL;
+  if (match == NULL) return NULL;
+  if (with == NULL) return NULL;
+
+  root = strstr (string, match);
+  if (root == NULL) {
+    return (strcreate (string));
+  }
+  N1 = root - string;
+
+  N2 = strlen (with);
+
+  ext = root + strlen(match);
+  N3 = strlen (ext);
+
+  ALLOCATE (out, char, N1 + N2 + N3 + 1);
+
+  strncpy (out, string, N1);
+  strncpy (&out[N1], with, N2);
+  strncpy (&out[N1+N2], ext, N3);
+  out[N1+N2+N3] = 0;
+
+  return out;
+}
+
+# if 0
+// replace a single entry of 'match' in the string with 'with'
+// (quick-and-dirty regex for a common case...)
+char *strrsubs (char *string, char *match, char *with) {
+
+  char *root;
+  char *out;
+
+  if (string == NULL) return NULL;
+  if (match == NULL) return NULL;
+  if (with == NULL) return NULL;
+
+  root = strstr (string, match);
+  if (root == NULL) return NULL;
+
+  ext = string + strlen (match);
+  ALLOCATE (out, char *, strlen(with) + strlen(ext) + 1);
+  strcpy (out, with);
+  strcat (out, ext);
+
+  return out;
+}
+# endif
+
+int scan_line (FILE *f, char *line) {
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+}
+
+char *_parse_nextword (char *string) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
+int dparse (double *X, int NX, char *line) {
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word) return (FALSE);
+  if (word[0] == '-') return (-1);
+  return (1);
+}
+
+int fparse (float *X, int NX, char *line) {
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = _parse_nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word) return (FALSE);
+  if (word[0] == '-') return (-1);
+  return (1);
+}
+
+int get_argument (int argc, char **argv, char *arg) {
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int)NULL);
+}
+
+int remove_argument (int N, int *argc, char **argv) {
+
+  int i;
+
+  if ((N != (int)NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+}
+
+void uppercase (char *string) {
+
+  int i;
+    
+  for (i = 0; i < strlen (string); i++) string[i] = toupper (string[i]);
+
+}
+
+/* expect a line of the form "$Name: not supported by cvs2svn $", strip out contents */
+char *strip_version (char *input) {
+
+  char *p, *q;
+
+  p = strstr (input, "$Name:");
+  if (p == NULL) return (strcreate ("NONE"));
+
+  q = strcreate (input + 6);
+  p = strrchr (q, '$');
+  if (p != NULL) *p = 0;
+  stripwhite (q);
+  if (*q == 0) {
+    free (q);
+    q = strcreate ("NONE");
+  }
+
+  return (q);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/time.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/time.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/time.c	(revision 16632)
@@ -0,0 +1,435 @@
+# include "ohana.h"
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int ohana_dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int ohana_str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (ohana_dms_to_ddd (&Ra, str1)) {
+    case 0:
+      fprintf (stderr, "syntax error in RA\n");
+      return (FALSE);
+    case 1:
+      break;
+    case 2:
+      Ra = Ra * 15;
+      break;
+  }
+  switch (ohana_dms_to_ddd (&Dec, str2)) {
+    case 0:
+      fprintf (stderr, "syntax error in DEC\n");
+      return (FALSE);
+    case 1:
+    case 2:
+      break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+/**********/
+int ohana_chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  mode = TIME_DATE;
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = TIME_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = TIME_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = TIME_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = TIME_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = TIME_JD;
+    }
+    if (*p2 == 'J') {
+      mode = TIME_MJD;
+    }
+  }
+  return (mode);
+}
+
+/**********/
+int ohana_str_to_time (char *line, time_t *second) {
+  
+  char *tmpline;
+  struct tm *gmt;
+  struct timeval now;
+  double jd;
+  time_t tsec;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strncasecmp (line, "TODAY", 5)) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    if (line[5]) { /* line has extra data (ie, hh:mm:ss) */
+      tsec = now.tv_sec;
+      ALLOCATE (tmpline, char, 64);
+      gmt   = gmtime (&tsec);
+      sprintf (tmpline, "%04d/%02d/%02d,%s", 1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, &line[6]);
+      *second = ohana_date_to_sec (tmpline);
+      free (tmpline);
+      return (TRUE);
+    } else {
+      *second = 86400 * ((int)(now.tv_sec / 86400));
+      return (TRUE); 
+    }
+  }
+    
+  switch (ohana_chk_time (line)) {
+    case 0:
+      return (FALSE);
+    case TIME_DATE:
+      *second = ohana_date_to_sec (line);
+      return (TRUE);
+    case TIME_DAYS:
+      *second = strtod (line, 0) * 86400.0;
+      return (TRUE);
+    case TIME_HOURS:
+      *second = strtod (line, 0) * 3600.0;
+      return (TRUE);
+    case TIME_MINUTES:
+      *second = strtod (line, 0) * 60.0;
+      return (TRUE);
+    case TIME_SECONDS:
+      *second = strtod (line, 0);
+      return (TRUE);
+    case TIME_JD:
+      jd = strtod (line, 0);
+      *second = ohana_jd_to_sec (jd);
+      return (TRUE);
+    case TIME_MJD:
+      jd = strtod (line, 0);
+      *second = ohana_mjd_to_sec (jd);
+      return (TRUE);
+  }
+  return (FALSE);
+}
+
+
+/**********/
+int ohana_str_to_dtime (char *line, double *second) {
+  
+  switch (ohana_chk_time (line)) {
+    case 0:
+    case TIME_JD:
+    case TIME_MJD:
+    case TIME_DATE:
+      return (FALSE);
+    case TIME_DAYS:
+      *second = strtod (line, 0) * 86400.0;
+      return (TRUE);
+    case TIME_HOURS:
+      *second = strtod (line, 0) * 3600.0;
+      return (TRUE);
+    case TIME_MINUTES:
+      *second = strtod (line, 0) * 60.0;
+      return (TRUE);
+    case TIME_SECONDS:
+      *second = strtod (line, 0);
+      return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double ohana_sec_to_jd (time_t second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+time_t ohana_jd_to_sec (double jd) {
+
+  time_t second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+double ohana_sec_to_mjd (time_t second) {
+
+  double mjd;
+  
+  mjd = second/86400.0 + 40587.0;
+  return (mjd);
+}
+
+/**********/
+time_t ohana_mjd_to_sec (double mjd) {
+
+  time_t second;
+
+  second = (mjd - 40587.0)*86400;
+  return (second);
+}
+
+/**********/
+char *ohana_sec_to_date (time_t second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%04d/%02d/%02d,%02d:%02d:%02d", 1900 + gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+time_t ohana_date_to_sec (char *date) {
+  
+  time_t second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  if (p1 == NULL) return 0;
+
+  /* ignore standard leading quoting options: " ' ( */
+  if (*p1 == 0x22) p1++; /* " */
+  if (*p1 == 0x27) p1++; /* ' */
+  if (*p1 == 0x28) p1++; /* ( */
+
+  px = p1 + strlen(p1);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+/***** short date in format yymmdd *****/
+time_t short_date_to_sec (char *date) {
+  
+  time_t second;
+  double jd;
+  struct tm now;
+  
+  bzero (&now, sizeof(now));
+
+  sscanf (date, "%2d%2d%2d", &now.tm_year, &now.tm_mon, &now.tm_mday);
+
+  if (now.tm_year >   51) now.tm_year +=   0;
+  if (now.tm_year <   50) now.tm_year += 100;
+  now.tm_mon --; /* tm_mon runs from 0 - 11 */
+
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+/**********/
+int hstgsc_hms_to_deg (double *h0, double *h1, double *d0, double *d1, char *string) {
+  
+  int flag_d0, flag_d1, flag_h0, flag_h1;
+  double tmp;
+  
+  *d0 = *h0 = *d1 = *h1 = 0;
+
+  flag_h0 = dparse (h0, 1, string);
+  flag_h1 = dparse (h1, 4, string);
+  flag_d0 = dparse (d0, 7, string);
+  flag_d1 = dparse (d1, 9, string);
+  *h0 *= flag_h0;
+  *h1 *= flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  dparse (&tmp, 2, string);
+  *h0 += tmp/60.0;
+  dparse (&tmp, 3, string);
+  *h0 += tmp/3600.0;
+  
+  dparse (&tmp, 5, string);
+  *h1 += tmp/60.0;
+  dparse (&tmp, 6, string);
+  *h1 += tmp/3600.0;
+  
+  dparse (&tmp, 8, string);
+  *d0 += tmp/60.0;
+
+  dparse (&tmp, 10, string);
+  *d1 += tmp/60.0;
+
+  *h0 *= 15*flag_h0;
+  *h1 *= 15*flag_h1;
+  *d0 *= flag_d0;
+  *d1 *= flag_d1;
+
+  return (TRUE);
+}
+
+/* times may be in forms as:
+ * 20040200450s (N seconds since 1970.0)
+ * 2440900.232j (julian date)
+ * 99/02/23,03:22:18 (date string)
+ * (separators may be anything except space, +, -)
+ * 99:02:15:12:23:30
+ * 99:02:15:12h23m30s
+ */
+
+
+/* returns the local MEAN sidereal time (dec hrs) at julian date jd
+   at west longitude long (decimal hours).  Follows
+   definitions in 1992 Astronomical Almanac, pp. B7 and L2.
+   Expression for GMST at 0h ut referenced to Aoki et al, A&A 105,
+   p.359, 1982.  On workstations, accuracy (numerical only!)
+   is about a millisecond in the 1990s.
+   EAM: function from skycalc (thorstensen) 
+*/
+#define  J2000             2451545.        /* Julian date at standard epoch */
+#define  SEC_IN_DAY        86400.
+
+double ohana_lst (double jd, double longitude) {
+
+  double t, ut, jdmid, jdint, jdfrac, sid_g;
+  long sid_int;
+
+  jdint = (int) jd;
+  jdfrac = jd - jdint;
+
+  if (jdfrac < 0.5) {
+    jdmid = jdint - 0.5;
+    ut = jdfrac + 0.5;
+  } else {
+    jdmid = jdint + 0.5;
+    ut = jdfrac - 0.5;
+  }
+
+  t = (jdmid - J2000)/36525;
+  sid_g = (24110.54841+8640184.812866*t+0.093104*t*t-6.2e-6*t*t*t)/SEC_IN_DAY;
+  sid_int = sid_g;
+  sid_g = sid_g - (double) sid_int;
+  sid_g = sid_g + 1.0027379093 * ut - longitude/24.;
+  sid_int = sid_g;
+  sid_g = (sid_g - (double) sid_int) * 24.;
+  if (sid_g < 0.) sid_g = sid_g + 24.;
+  return (sid_g);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/src/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/src/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/src/version.c	(revision 16632)
@@ -0,0 +1,6 @@
+# include <ohana.h>
+static char *name = "$Name: not supported by cvs2svn $";
+
+char *ohana_version () {
+  return (name);
+}
Index: /branches/eam_branch_20080223/Ohana/src/libohana/test/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/test/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/test/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+*.linux *.lin64 *.sol
Index: /branches/eam_branch_20080223/Ohana/src/libohana/test/string.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libohana/test/string.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libohana/test/string.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "ohana.h"
+# include "tap_ohana.h"
+
+int main (void) {
+
+  plan_tests (16);
+
+  diag ("libohana string.c tests");
+
+  /*** stripwhite ***/
+  {
+    int status;
+    char string[128];
+
+    status = stripwhite (NULL);
+    
+    ok (!status, "stripwhite status for NULL is FALSE");
+
+    sprintf (string, "  a test line  ");
+    status = stripwhite (string);
+    
+    ok (status, "stripwhite returns %d", status);
+    ok (!strcmp (string, "a test line"), "string is stripped");
+
+    sprintf (string, "a test line");
+    status = stripwhite (string);
+    
+    ok (status, "stripwhite returns %d", status);
+    ok (!strcmp (string, "a test line"), "string is stripped");
+  }
+    
+  /*** strsubs ***/
+  {
+    char *output;
+
+    output = strsubs (NULL, "needle", "noodle");
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", NULL, "noodle");
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", "needle", NULL);
+    ok (output == NULL, "strsubs for NULL is NULL");
+
+    output = strsubs ("needle in haystack", "needle", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "noodle in haystack"), "successful sustitution at beginning: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "in", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle noodle haystack"), "successful sustitution in middle: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "stack", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle in haynoodle"), "successful sustitution at end: %s", output);
+    skip_end();
+
+    output = strsubs ("needle in haystack", "junk", "noodle");
+    ok (output != NULL, "stripwhite status is TRUE");
+    skip_start (output == NULL, 1, "Skipping 1 test because strsubs returned NULL");
+    ok (!strcmp (output, "needle in haystack"), "successful sustitution without match: %s", output);
+    skip_end();
+  }
+  return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+lib
Index: /branches/eam_branch_20080223/Ohana/src/libtap/INSTALL
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/INSTALL	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/INSTALL	(revision 16632)
@@ -0,0 +1,8 @@
+Quick Installation
+
+    ./configure
+    make
+    make check
+    make install
+
+Run "configure --help" for additional options.
Index: /branches/eam_branch_20080223/Ohana/src/libtap/LICENSE
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/LICENSE	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/LICENSE	(revision 16632)
@@ -0,0 +1,23 @@
+Copyright (c) 2004 Nik Clayton
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
Index: /branches/eam_branch_20080223/Ohana/src/libtap/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/Makefile	(revision 16632)
@@ -0,0 +1,33 @@
+default: install
+help:
+	@echo "make options: install libtap clean dist"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/libtap
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+install: $(DESTLIB)/libtap_ohana.a $(DESTLIB)/libtap_ohana.$(DLLTYPE)
+libtap: $(LIB)/libtap_ohana.$(ARCH).a $(LIB)/libtap_ohana.$(ARCH).$(DLLTYPE)
+
+INCS = $(DESTINC)/tap_ohana.h
+TAP = $(SRC)/tap_ohana.$(ARCH).o
+
+$(TAP): $(INCS)
+
+$(LIB)/libtap_ohana.$(ARCH).a: $(TAP)
+$(LIB)/libtap_ohana.$(ARCH).$(DLLTYPE): $(TAP)
+
+$(DESTLIB)/libtap_ohana.a:  $(LIB)/libtap_ohana.$(ARCH).a
+$(DESTLIB)/libtap_ohana.$(DLLTYPE): $(LIB)/libtap_ohana.$(ARCH).$(DLLTYPE)
+
+# libtap tests are currently not compiled or run
Index: /branches/eam_branch_20080223/Ohana/src/libtap/README
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/README	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/README	(revision 16632)
@@ -0,0 +1,22 @@
+NAME
+     tap -- write tests that implement the Test Anything Protocol
+
+SYNOPSIS
+     #include <tap.h>
+
+DESCRIPTION
+     The tap library provides functions for writing test scripts that produce
+     output consistent with the Test Anything Protocol.  A test harness that
+     parses this protocol can run these tests and produce useful reports indi-
+     cating their success or failure.
+
+
+---
+
+*** Note for Ohana ***
+
+This is a locally modified version of tap to work within the Ohana
+framework.  I have stripped the library down to the source code and
+tests, removed the autogen and libtool stuff, and made a Makefile
+which uses the Ohana $(ARCH) system.  The tap library is installed
+with the name tap_ohana (-ltap_ohana, tap_ohana.h).
Index: /branches/eam_branch_20080223/Ohana/src/libtap/include/tap_ohana.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/include/tap_ohana.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/include/tap_ohana.h	(revision 16632)
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting
+   and requires the caller to add the final comma if they've ommitted
+   the optional arguments */
+#ifdef __GNUC__
+# define ok(e, test, ...) ((e) ?					\
+			   _gen_result(1, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__) :		\
+			   _gen_result(0, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(test, ...) ok(1, test, ## __VA_ARGS__);
+# define fail(test, ...) ok(0, test, ## __VA_ARGS__);
+
+# define skip_start(test, n, fmt, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n, fmt, ## __VA_ARGS__);	\
+			continue;			\
+		}
+#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
+# define ok(e, ...) ((e) ?						\
+		     _gen_result(1, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__) :				\
+		     _gen_result(0, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(...) ok(1, __VA_ARGS__);
+# define fail(...) ok(0, __VA_ARGS__);
+
+# define skip_start(test, n, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n,  __VA_ARGS__);		\
+			continue;			\
+		}
+#else /* __STDC_VERSION__ */
+# error "Needs gcc or C99 compiler for variadic macros."
+#endif /* __STDC_VERSION__ */
+
+#define skip_end() } while(0);
+
+unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...);
+
+int plan_no_plan(void);
+int plan_skip_all(char *);
+int plan_tests(unsigned int);
+
+unsigned int diag(char *, ...);
+
+int skip(unsigned int, char *, ...);
+
+void todo_start(char *, ...);
+void todo_end(void);
+
+int exit_status(void);
+
+# ifndef _GNU_SOURCE
+/* if these are not in your headers, are they in your libc? */
+int asprintf(char **strp, const char *fmt, ...);
+int vasprintf(char **strp, const char *fmt, va_list ap);
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/libtap/lib/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/lib/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/lib/.cvsignore	(revision 16632)
@@ -0,0 +1,3 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.darwin.dylib
+*.darwin_x86.dylib
Index: /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.3
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.3	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.3	(revision 16632)
@@ -0,0 +1,380 @@
+.Dd December 20, 2004
+.Os
+.Dt TAP 3
+.Sh NAME
+.Nm tap
+.Nd write tests that implement the Test Anything Protocol
+.Sh SYNOPSIS
+.In tap.h
+.Sh DESCRIPTION
+The
+.Nm
+library provides functions for writing test scripts that produce output
+consistent with the Test Anything Protocol.  A test harness that parses
+this protocol can run these tests and produce useful reports indicating
+their success or failure.
+.Ss PRINTF STRINGS
+In the descriptions that follow, for any function that takes as the
+last two parameters
+.Dq Fa char * , Fa ...
+it can be assumed that the
+.Fa char *
+is a
+.Fn printf
+-like format string, and the optional arguments are values to be placed
+in that string.
+.Ss TEST PLANS
+.Bl -tag -width indent
+.It Xo
+.Ft int
+.Fn plan_tests "unsigned int"
+.Xc
+.It Xo
+.Ft int
+.Fn plan_no_plan "void"
+.Xc
+.It Xo
+.Ft int
+.Fn plan_skip_all "char *" "..."
+.Xc
+.El
+.Pp
+You must first specify a test plan.  This indicates how many tests you
+intend to run, and allows the test harness to notice if any tests were
+missed, or if the test program exited prematurely.
+.Pp
+To do this, use
+.Fn plan_tests ,
+which returns the number of planned tests.  The function will cause
+your program to exit prematurely if you specify 0 tests.
+.Pp
+In some situations you may not know how many tests you will be running, or
+you are developing your test program, and do not want to update the
+.Fn plan_tests
+parameter every time you make a change.  For those situations use
+.Fn plan_no_plan .
+It returns 1, and indicates to the test harness that an indeterminate number
+of tests will be run.
+.Pp
+Both
+.Fn plan_tests
+and
+.Fn plan_no_plan
+will cause your test program to exit prematurely with a diagnostic
+message if they are called more than once.
+.Pp
+If your test program detects at run time that some required functionality
+is missing (for example, it relies on a database connection which is not
+present, or a particular configuration option that has not been included
+in the running kernel) use
+.Fn plan_skip_all ,
+passing as parameters a string to display indicating the reason for skipping
+the tests.
+.Ss SIMPLE TESTS
+.Bl -tag -width indent
+.It Xo
+.Ft unsigned int
+.Fn ok "expression" "char *" "..."
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn ok1 "expression"
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn pass "char *" "..."
+.Xc
+.It Xo
+.Ft unsigned int
+.Fn fail "char *" "..."
+.Xc
+.El
+.Pp
+Tests are implemented as expressions checked by calls to the
+.Fn ok
+and
+.Fn ok1
+macros.  In both cases
+.Fa expression
+should evaluate to true if the test succeeded.
+.Pp
+.Fn ok
+allows you to specify a name, or comment, describing the test which will
+be included in the output.
+.Fn ok1
+is for those times when the expression to be tested is self
+explanatory and does not need an associated comment.  In those cases
+the test expression becomes the comment.
+.Pp
+These four calls are equivalent:
+.Bd -literal -offset indent
+int i = 5;
+
+ok(i == 5, "i equals 5");      /* Overly verbose */
+ok(i == 5, "i equals %d", i);  /* Just to demonstrate printf-like
+                                  behaviour of the test name */
+ok(i == 5, "i == 5");          /* Needless repetition */
+ok1(i == 5);                   /* Just right */
+.Ed
+.Pp
+It is good practice to ensure that the test name describes the meaning
+behind the test rather than what you are testing.  Viz
+.Bd -literal -offset indent
+ok(db != NULL, "db is not NULL");            /* Not bad, but */
+ok(db != NULL, "Database conn. succeeded");  /* this is better */
+.Ed
+.Pp
+.Fn ok
+and
+.Fn ok1
+return 1 if the expression evaluated to true, and 0 if it evaluated to
+false.  This lets you chain calls from
+.Fn ok
+to
+.Fn diag
+to only produce diagnostic output if the test failed.  For example, this
+code will include diagnostic information about why the database connection
+failed, but only if the test failed.
+.Bd -literal -offset indent
+ok(db != NULL, "Database conn. succeeded") ||
+    diag("Database error code: %d", dberrno);
+.Ed
+.Pp
+You also have
+.Fn pass
+and
+.Fn fail .
+From the Test::More documentation:
+.Bd -literal -offset indent
+Sometimes you just want to say that the tests have passed.
+Usually the case is you've got some complicated condition
+that is difficult to wedge into an ok().  In this case,
+you can simply use pass() (to declare the test ok) or fail
+(for not ok).
+
+Use these very, very, very sparingly.
+.Ed
+.Pp
+These are synonyms for ok(1, ...) and ok(0, ...).
+.Ss SKIPPING TESTS
+.Bl -tag -width indent
+.It Xo
+.Ft int
+.Fn skip "unsigned int" "char *" "..."
+.Xc
+.It Xo
+.Fn skip_start "expression" "unsigned int" "char *" "..."
+.Xc
+.It Xo
+.Fn skip_end
+.Xc
+.El
+.Pp
+Sets of tests can be skipped.  Ordinarily you would do this because
+the test can't be run in this particular testing environment.
+.Pp
+For example, suppose some tests should be run as root.  If the test is
+not being run as root then the tests should be skipped.  In this 
+implementation, skipped tests are flagged as being ok, with a special
+message indicating that they were skipped.  It is your responsibility
+to ensure that the number of tests skipped (the first parameter to
+.Fn skip )
+is correct for the number of tests to skip.
+.Pp
+One way of implementing this is with a
+.Dq do { } while(0);
+loop, or an
+.Dq if( ) { } else { }
+construct, to ensure that there are no additional side effects from the
+skipped tests.
+.Bd -literal -offset indent
+if(getuid() != 0) {
+        skip(1, "because test only works as root");
+} else {
+        ok(do_something_as_root() == 0, "Did something as root");
+}
+.Ed
+.Pp
+Two macros are provided to assist with this.  The previous example could
+be re-written as follows.
+.Bd -literal -offset indent
+skip_start(getuid() != 0, 1, "because test only works as root");
+
+ok(do_something_as_root() == 0, "Did something as root");
+
+skip_end();
+.Ed
+.Ss MARKING TESTS AS Dq TODO
+.Bl -tag -width indent
+.It Xo
+.Ft void
+.Fn todo_start "char *" "..."
+.Xc
+.It Xo
+.Ft void
+.Fn todo_end "void"
+.Xc
+.El
+.Pp
+Sets of tests can be flagged as being
+.Dq TODO .
+These are tests that you expect to fail, probably because you haven't
+fixed a bug, or finished a new feature yet.  These tests will still be
+run, but with additional output that indicates that they are expected
+to fail.  Should a test start to succeed unexpectedly, tools like
+.Xr prove 1
+will indicate this, and you can move the test out of the todo
+block.  This is much more useful than simply commenting out (or
+.Dq #ifdef 0 ... #endif )
+the tests.
+.Bd -literal -offset indent
+todo_start("dwim() not returning true yet");
+
+ok(dwim(), "Did what the user wanted");
+
+todo_end();
+.Ed
+.Pp
+Should
+.Fn dwim
+ever start succeeding you will know about it as soon as you run the
+tests.  Note that
+.Em unlike
+the
+.Fn skip_*
+family, additional code between
+.Fn todo_start
+and
+.Fn todo_end
+.Em is
+executed.
+.Ss SKIP vs. TODO
+From the Test::More documentation;
+.Bd -literal -offset indent
+If it's something the user might not be able to do, use SKIP.
+This includes optional modules that aren't installed, running
+under an OS that doesn't have some feature (like fork() or
+symlinks), or maybe you need an Internet connection and one
+isn't available.
+
+If it's something the programmer hasn't done yet, use TODO.
+This is for any code you haven't written yet, or bugs you have
+yet to fix, but want to put tests in your testing script 
+(always a good idea).
+.Ed
+.Ss DIAGNOSTIC OUTPUT
+.Bl -tag -width indent
+.It Xo
+.Fr unsigned int
+.Fn diag "char *" "..."
+.Xc
+.El
+.Pp
+If your tests need to produce diagnostic output, use
+.Fn diag .
+It ensures that the output will not be considered by the TAP test harness.
+.Fn diag
+adds the necessary trailing
+.Dq \en
+for you.
+.Bd -literal -offset indent
+diag("Expected return code 0, got return code %d", rcode);
+.Ed
+.Pp
+.Fn diag
+always returns 0.
+.Ss EXIT STATUS
+.Bl -tag -width indent
+.It Xo
+.Fr int
+.Fn exit_status void
+.Xc
+.El
+.Pp
+For maximum compatability your test program should return a particular
+exit code.  This is calculated by
+.Fn exit_status
+so it is sufficient to always return from
+.Fn main
+with either
+.Dq return exit_status();
+or
+.Dq exit(exit_status());
+as appropriate.
+.Sh ENVIRONMENT
+The following environment variables affect
+.Nm .
+.Bl -tag -width indent
+.It Ev HARNESS_ACTIVE
+Causes an extra
+.Dq \en
+to be printed before any diagnostic failure output generated by
+.Nm .
+This variable is normally set if tests are being run under Perl's
+Test::Harness.
+.El
+.Sh EXAMPLES
+The
+.Pa tests
+directory in the source distribution contains numerous tests of
+.Nm
+functionality, written using
+.Nm .
+Examine them for examples of how to construct test suites.
+.Sh COMPATABILITY
+.Nm
+strives to be compatible with the Perl Test::More and Test::Harness 
+modules.  The test suite verifies that
+.Nm
+is bug-for-bug compatible with their behaviour.  This is why some
+functions which would more naturally return nothing return constant
+values.
+.Pp
+If the
+.Lb libpthread
+is found at compile time,
+.Nm
+.Em should
+be thread safe.  Indications to the contrary (and test cases that expose
+incorrect behaviour) are very welcome.
+.Sh SEE ALSO
+.Xr Test::More 1 ,
+.Xr Test::Harness 1 ,
+.Xr prove 1
+.Sh STANDARDS
+.Nm
+requires a
+.St -isoC-99
+compiler.  Some of the
+.Nm
+functionality is implemented as variadic macros, and that functionality
+was not formally codified until C99.  Patches to use
+.Nm
+with earlier compilers that have their own implementation of variadic
+macros will be gratefully received.
+.Sh HISTORY
+.Nm
+was written to help improve the quality and coverage of the FreeBSD
+regression test suite, and released in the hope that others find it
+a useful tool to help improve the quality of their code.
+.Sh AUTHORS
+.An "Nik Clayton" Aq nik@ngo.org.uk ,
+.Aq nik@FreeBSD.org
+.Pp
+.Nm
+would not exist without the efforts of
+.An "Michael G Schwern" Aq schqern@pobox.com ,
+.An "Andy Lester" Aq andy@petdance.com ,
+and the countless others who have worked on the Perl QA programme.
+.Sh BUGS
+Ideally, running the tests would have no side effects on the behaviour
+of the application you are testing.  However, it is not always possible
+to avoid them.  The following side effects of using
+.Nm
+are known.
+.Bl -bullet -offset indent
+.It
+stdout is set to unbuffered mode after calling any of the
+.Fn plan_*
+functions.
+.El
Index: /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.c	(revision 16632)
@@ -0,0 +1,426 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap.h"
+
+static int no_plan = 0;
+static int skip_all = 0;
+static int have_plan = 0;
+static unsigned int test_count = 0; /* Number of tests that have been run */
+static unsigned int e_tests = 0; /* Expected number of tests to run */
+static unsigned int failures = 0; /* Number of tests that failed */
+static char *todo_msg = NULL;
+static char *todo_msg_fixed = "libtap malloc issue";
+static int todo = 0;
+static int test_died = 0;
+
+/* Encapsulate the pthread code in a conditional.  In the absence of
+   libpthread the code does nothing */
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
+# define LOCK pthread_mutex_lock(&M);
+# define UNLOCK pthread_mutex_unlock(&M);
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+static void _expected_tests(unsigned int);
+static void _tap_init(void);
+static void _cleanup(void);
+
+/*
+ * Generate a test result.
+ *
+ * ok -- boolean, indicates whether or not the test passed.
+ * test_name -- the name of the test, may be NULL
+ * test_comment -- a comment to print afterwards, may be NULL
+ */
+unsigned int
+_gen_result(int ok, const char *func, char *file, unsigned int line, 
+	    char *test_name, ...)
+{
+	va_list ap;
+	char *local_test_name = NULL;
+	char *c;
+	int name_is_digits;
+
+	LOCK;
+
+	test_count++;
+
+	/* Start by taking the test name and performing any printf()
+	   expansions on it */
+	if(test_name != NULL) {
+		va_start(ap, test_name);
+		vasprintf(&local_test_name, test_name, ap);
+		va_end(ap);
+
+		/* Make sure the test name contains more than digits
+		   and spaces.  Emit an error message and exit if it
+		   does */
+		if(local_test_name) {
+			name_is_digits = 1;
+			for(c = local_test_name; *c != '\0'; c++) {
+				if(!isdigit(*c) && !isspace(*c)) {
+					name_is_digits = 0;
+					break;
+				}
+			}
+
+			if(name_is_digits) {
+				diag("    You named your test '%s'.  You shouldn't use numbers for your test names.", local_test_name);
+				diag("    Very confusing.");
+			}
+		}
+	}
+
+	if(!ok) {
+		printf("not ");
+		failures++;
+	}
+
+	printf("ok %d", test_count);
+
+	if(test_name != NULL) {
+		printf(" - ");
+
+		/* Print the test name, escaping any '#' characters it
+		   might contain */
+		if(local_test_name != NULL) {
+			flockfile(stdout);
+			for(c = local_test_name; *c != '\0'; c++) {
+				if(*c == '#')
+					fputc('\\', stdout);
+				fputc((int)*c, stdout);
+			}
+			funlockfile(stdout);
+		} else {	/* vasprintf() failed, use a fixed message */
+			printf("%s", todo_msg_fixed);
+		}
+	}
+
+	/* If we're in a todo_start() block then flag the test as being
+	   TODO.  todo_msg should contain the message to print at this
+	   point.  If it's NULL then asprintf() failed, and we should
+	   use the fixed message.
+
+	   This is not counted as a failure, so decrement the counter if
+	   the test failed. */
+	if(todo) {
+		printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
+		if(!ok)
+			failures--;
+	}
+
+	printf("\n");
+
+	if(!ok) {
+		if(getenv("HARNESS_ACTIVE") != NULL)
+			fputs("\n", stderr);
+
+		diag("    Failed %stest (%s:%s() at line %d)", 
+		     todo ? "(TODO) " : "", file, func, line);
+	}
+	free(local_test_name);
+
+	UNLOCK;
+
+	/* We only care (when testing) that ok is positive, but here we
+	   specifically only want to return 1 or 0 */
+	return ok ? 1 : 0;
+}
+
+/*
+ * Initialise the TAP library.  Will only do so once, however many times it's
+ * called.
+ */
+void
+_tap_init(void)
+{
+	static int run_once = 0;
+
+	if(!run_once) {
+		atexit(_cleanup);
+
+		/* stdout needs to be unbuffered so that the output appears
+		   in the same place relative to stderr output as it does 
+		   with Test::Harness */
+		setbuf(stdout, 0);
+		run_once = 1;
+	}
+}
+
+/*
+ * Note that there's no plan.
+ */
+int
+plan_no_plan(void)
+{
+
+	LOCK;
+
+	_tap_init();
+
+	if(have_plan != 0) {
+		fprintf(stderr, "You tried to plan twice!\n");
+		test_died = 1;
+		UNLOCK;
+		exit(255);
+	}
+
+	have_plan = 1;
+	no_plan = 1;
+
+	UNLOCK;
+
+	return 1;
+}
+
+/*
+ * Note that the plan is to skip all tests
+ */
+int
+plan_skip_all(char *reason)
+{
+
+	LOCK;
+
+	_tap_init();
+
+	skip_all = 1;
+
+	printf("1..0");
+
+	if(reason != NULL)
+		printf(" # Skip %s", reason);
+
+	printf("\n");
+
+	UNLOCK;
+
+	exit(0);
+}
+
+/*
+ * Note the number of tests that will be run.
+ */
+int
+plan_tests(unsigned int tests)
+{
+
+	LOCK;
+
+	_tap_init();
+
+	if(have_plan != 0) {
+		fprintf(stderr, "You tried to plan twice!\n");
+		test_died = 1;
+		UNLOCK;
+		exit(255);
+	}
+
+	if(tests == 0) {
+		fprintf(stderr, "You said to run 0 tests!  You've got to run something.\n");
+		test_died = 1;
+		UNLOCK;
+		exit(255);
+	}
+
+	have_plan = 1;
+
+	_expected_tests(tests);
+
+	UNLOCK;
+
+	return e_tests;
+}
+
+unsigned int
+diag(char *fmt, ...)
+{
+	va_list ap;
+
+	fputs("# ", stderr);
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+
+	fputs("\n", stderr);
+
+	return 0;
+}
+
+void
+_expected_tests(unsigned int tests)
+{
+
+	printf("1..%d\n", tests);
+	e_tests = tests;
+}
+
+int
+skip(unsigned int n, char *fmt, ...)
+{
+	va_list ap;
+	char *skip_msg;
+
+	LOCK;
+
+	va_start(ap, fmt);
+	asprintf(&skip_msg, fmt, ap);
+	va_end(ap);
+
+	while(n-- > 0) {
+		test_count++;
+		printf("ok %d # skip %s\n", test_count, 
+		       skip_msg != NULL ? 
+		       skip_msg : "libtap():malloc() failed");
+	}
+
+	free(skip_msg);
+
+	UNLOCK;
+
+	return 1;
+}
+
+void
+todo_start(char *fmt, ...)
+{
+	va_list ap;
+
+	LOCK;
+
+	va_start(ap, fmt);
+	vasprintf(&todo_msg, fmt, ap);
+	va_end(ap);
+
+	todo = 1;
+
+	UNLOCK;
+}
+
+void
+todo_end(void)
+{
+
+	LOCK;
+
+	todo = 0;
+	free(todo_msg);
+
+	UNLOCK;
+}
+
+int
+exit_status(void)
+{
+	int r;
+
+	LOCK;
+
+	/* If there's no plan, just return the number of failures */
+	if(no_plan || !have_plan) {
+		UNLOCK;
+		return failures;
+	}
+
+	/* Ran too many tests?  Return the number of tests that were run
+	   that shouldn't have been */
+	if(e_tests < test_count) {
+		r = test_count - e_tests;
+		UNLOCK;
+		return r;
+	}
+
+	/* Return the number of tests that failed + the number of tests 
+	   that weren't run */
+	r = failures + e_tests - test_count;
+	UNLOCK;
+
+	return r;
+}
+
+/*
+ * Cleanup at the end of the run, produce any final output that might be
+ * required.
+ */
+void
+_cleanup(void)
+{
+
+	LOCK;
+
+	/* If plan_no_plan() wasn't called, and we don't have a plan,
+	   and we're not skipping everything, then something happened
+	   before we could produce any output */
+	if(!no_plan && !have_plan && !skip_all) {
+		diag("Looks like your test died before it could output anything.");
+		UNLOCK;
+		return;
+	}
+
+	if(test_died) {
+		diag("Looks like your test died just after %d.", test_count);
+		UNLOCK;
+		return;
+	}
+
+
+	/* No plan provided, but now we know how many tests were run, and can
+	   print the header at the end */
+	if(!skip_all && (no_plan || !have_plan)) {
+		printf("1..%d\n", test_count);
+	}
+
+	if((have_plan && !no_plan) && e_tests < test_count) {
+		diag("Looks like you planned %d %s but ran %d extra.",
+		     e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
+		UNLOCK;
+		return;
+	}
+
+	if((have_plan || !no_plan) && e_tests > test_count) {
+		diag("Looks like you planned %d %s but only ran %d.",
+		     e_tests, e_tests == 1 ? "test" : "tests", test_count);
+		UNLOCK;
+		return;
+	}
+
+	if(failures)
+		diag("Looks like you failed %d %s of %d.", 
+		     failures, failures == 1 ? "test" : "tests", test_count);
+
+	UNLOCK;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/src/tap.h	(revision 16632)
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* '## __VA_ARGS__' is a gcc'ism. C99 doesn't allow the token pasting
+   and requires the caller to add the final comma if they've ommitted
+   the optional arguments */
+#ifdef __GNUC__
+# define ok(e, test, ...) ((e) ?					\
+			   _gen_result(1, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__) :		\
+			   _gen_result(0, __func__, __FILE__, __LINE__,	\
+				       test, ## __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(test, ...) ok(1, test, ## __VA_ARGS__);
+# define fail(test, ...) ok(0, test, ## __VA_ARGS__);
+
+# define skip_start(test, n, fmt, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n, fmt, ## __VA_ARGS__);	\
+			continue;			\
+		}
+#elif __STDC_VERSION__ >= 199901L /* __GNUC__ */
+# define ok(e, ...) ((e) ?						\
+		     _gen_result(1, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__) :				\
+		     _gen_result(0, __func__, __FILE__, __LINE__,	\
+				 __VA_ARGS__))
+
+# define ok1(e) ((e) ?							\
+		 _gen_result(1, __func__, __FILE__, __LINE__, "%s", #e) : \
+		 _gen_result(0, __func__, __FILE__, __LINE__, "%s", #e))
+
+# define pass(...) ok(1, __VA_ARGS__);
+# define fail(...) ok(0, __VA_ARGS__);
+
+# define skip_start(test, n, ...)			\
+	do {						\
+		if((test)) {				\
+			skip(n,  __VA_ARGS__);		\
+			continue;			\
+		}
+#else /* __STDC_VERSION__ */
+# error "Needs gcc or C99 compiler for variadic macros."
+#endif /* __STDC_VERSION__ */
+
+#define skip_end() } while(0);
+
+unsigned int _gen_result(int, const char *, char *, unsigned int, char *, ...);
+
+int plan_no_plan(void);
+int plan_skip_all(char *);
+int plan_tests(unsigned int);
+
+unsigned int diag(char *, ...);
+
+int skip(unsigned int, char *, ...);
+
+void todo_start(char *, ...);
+void todo_end(void);
+
+int exit_status(void);
+
+# ifndef _GNU_SOURCE
+/* if these are not in your headers, are they in your libc? */
+int asprintf(char **strp, const char *fmt, ...);
+int vasprintf(char **strp, const char *fmt, va_list ap);
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/libtap/src/tap_ohana.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/src/tap_ohana.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/src/tap_ohana.c	(revision 16632)
@@ -0,0 +1,426 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap_ohana.h"
+
+static int no_plan = 0;
+static int skip_all = 0;
+static int have_plan = 0;
+static unsigned int test_count = 0; /* Number of tests that have been run */
+static unsigned int e_tests = 0; /* Expected number of tests to run */
+static unsigned int failures = 0; /* Number of tests that failed */
+static char *todo_msg = NULL;
+static char *todo_msg_fixed = "libtap malloc issue";
+static int todo = 0;
+static int test_died = 0;
+
+/* Encapsulate the pthread code in a conditional.  In the absence of
+   libpthread the code does nothing */
+#ifdef HAVE_LIBPTHREAD
+#include <pthread.h>
+static pthread_mutex_t M = PTHREAD_MUTEX_INITIALIZER;
+# define LOCK pthread_mutex_lock(&M);
+# define UNLOCK pthread_mutex_unlock(&M);
+#else
+# define LOCK
+# define UNLOCK
+#endif
+
+static void _expected_tests(unsigned int);
+static void _tap_init(void);
+static void _cleanup(void);
+
+/*
+ * Generate a test result.
+ *
+ * ok -- boolean, indicates whether or not the test passed.
+ * test_name -- the name of the test, may be NULL
+ * test_comment -- a comment to print afterwards, may be NULL
+ */
+unsigned int
+_gen_result(int ok, const char *func, char *file, unsigned int line, 
+	    char *test_name, ...)
+{
+	va_list ap;
+	char *local_test_name = NULL;
+	char *c;
+	int name_is_digits;
+
+	LOCK;
+
+	test_count++;
+
+	/* Start by taking the test name and performing any printf()
+	   expansions on it */
+	if(test_name != NULL) {
+		va_start(ap, test_name);
+		vasprintf(&local_test_name, test_name, ap);
+		va_end(ap);
+
+		/* Make sure the test name contains more than digits
+		   and spaces.  Emit an error message and exit if it
+		   does */
+		if(local_test_name) {
+			name_is_digits = 1;
+			for(c = local_test_name; *c != '\0'; c++) {
+				if(!isdigit(*c) && !isspace(*c)) {
+					name_is_digits = 0;
+					break;
+				}
+			}
+
+			if(name_is_digits) {
+				diag("    You named your test '%s'.  You shouldn't use numbers for your test names.", local_test_name);
+				diag("    Very confusing.");
+			}
+		}
+	}
+
+	if(!ok) {
+		printf("not ");
+		failures++;
+	}
+
+	printf("ok %d", test_count);
+
+	if(test_name != NULL) {
+		printf(" - ");
+
+		/* Print the test name, escaping any '#' characters it
+		   might contain */
+		if(local_test_name != NULL) {
+			flockfile(stdout);
+			for(c = local_test_name; *c != '\0'; c++) {
+				if(*c == '#')
+					fputc('\\', stdout);
+				fputc((int)*c, stdout);
+			}
+			funlockfile(stdout);
+		} else {	/* vasprintf() failed, use a fixed message */
+			printf("%s", todo_msg_fixed);
+		}
+	}
+
+	/* If we're in a todo_start() block then flag the test as being
+	   TODO.  todo_msg should contain the message to print at this
+	   point.  If it's NULL then asprintf() failed, and we should
+	   use the fixed message.
+
+	   This is not counted as a failure, so decrement the counter if
+	   the test failed. */
+	if(todo) {
+		printf(" # TODO %s", todo_msg ? todo_msg : todo_msg_fixed);
+		if(!ok)
+			failures--;
+	}
+
+	printf("\n");
+
+	if(!ok) {
+		if(getenv("HARNESS_ACTIVE") != NULL)
+			fputs("\n", stderr);
+
+		diag("    Failed %stest (%s:%s() at line %d)", 
+		     todo ? "(TODO) " : "", file, func, line);
+	}
+	free(local_test_name);
+
+	UNLOCK;
+
+	/* We only care (when testing) that ok is positive, but here we
+	   specifically only want to return 1 or 0 */
+	return ok ? 1 : 0;
+}
+
+/*
+ * Initialise the TAP library.  Will only do so once, however many times it's
+ * called.
+ */
+void
+_tap_init(void)
+{
+	static int run_once = 0;
+
+	if(!run_once) {
+		atexit(_cleanup);
+
+		/* stdout needs to be unbuffered so that the output appears
+		   in the same place relative to stderr output as it does 
+		   with Test::Harness */
+		setbuf(stdout, 0);
+		run_once = 1;
+	}
+}
+
+/*
+ * Note that there's no plan.
+ */
+int
+plan_no_plan(void)
+{
+
+	LOCK;
+
+	_tap_init();
+
+	if(have_plan != 0) {
+		fprintf(stderr, "You tried to plan twice!\n");
+		test_died = 1;
+		UNLOCK;
+		exit(255);
+	}
+
+	have_plan = 1;
+	no_plan = 1;
+
+	UNLOCK;
+
+	return 1;
+}
+
+/*
+ * Note that the plan is to skip all tests
+ */
+int
+plan_skip_all(char *reason)
+{
+
+	LOCK;
+
+	_tap_init();
+
+	skip_all = 1;
+
+	printf("1..0");
+
+	if(reason != NULL)
+		printf(" # Skip %s", reason);
+
+	printf("\n");
+
+	UNLOCK;
+
+	exit(0);
+}
+
+/*
+ * Note the number of tests that will be run.
+ */
+int
+plan_tests(unsigned int tests)
+{
+
+	LOCK;
+
+	_tap_init();
+
+	if(have_plan != 0) {
+		fprintf(stderr, "You tried to plan twice!\n");
+		test_died = 1;
+		UNLOCK;
+		exit(255);
+	}
+
+	if(tests == 0) {
+		fprintf(stderr, "You said to run 0 tests!  You've got to run something.\n");
+		test_died = 1;
+		UNLOCK;
+		exit(255);
+	}
+
+	have_plan = 1;
+
+	_expected_tests(tests);
+
+	UNLOCK;
+
+	return e_tests;
+}
+
+unsigned int
+diag(char *fmt, ...)
+{
+	va_list ap;
+
+	fputs("# ", stderr);
+
+	va_start(ap, fmt);
+	vfprintf(stderr, fmt, ap);
+	va_end(ap);
+
+	fputs("\n", stderr);
+
+	return 0;
+}
+
+void
+_expected_tests(unsigned int tests)
+{
+
+	printf("1..%d\n", tests);
+	e_tests = tests;
+}
+
+int
+skip(unsigned int n, char *fmt, ...)
+{
+	va_list ap;
+	char *skip_msg;
+
+	LOCK;
+
+	va_start(ap, fmt);
+	asprintf(&skip_msg, fmt, ap);
+	va_end(ap);
+
+	while(n-- > 0) {
+		test_count++;
+		printf("ok %d # skip %s\n", test_count, 
+		       skip_msg != NULL ? 
+		       skip_msg : "libtap():malloc() failed");
+	}
+
+	free(skip_msg);
+
+	UNLOCK;
+
+	return 1;
+}
+
+void
+todo_start(char *fmt, ...)
+{
+	va_list ap;
+
+	LOCK;
+
+	va_start(ap, fmt);
+	vasprintf(&todo_msg, fmt, ap);
+	va_end(ap);
+
+	todo = 1;
+
+	UNLOCK;
+}
+
+void
+todo_end(void)
+{
+
+	LOCK;
+
+	todo = 0;
+	free(todo_msg);
+
+	UNLOCK;
+}
+
+int
+exit_status(void)
+{
+	int r;
+
+	LOCK;
+
+	/* If there's no plan, just return the number of failures */
+	if(no_plan || !have_plan) {
+		UNLOCK;
+		return failures;
+	}
+
+	/* Ran too many tests?  Return the number of tests that were run
+	   that shouldn't have been */
+	if(e_tests < test_count) {
+		r = test_count - e_tests;
+		UNLOCK;
+		return r;
+	}
+
+	/* Return the number of tests that failed + the number of tests 
+	   that weren't run */
+	r = failures + e_tests - test_count;
+	UNLOCK;
+
+	return r;
+}
+
+/*
+ * Cleanup at the end of the run, produce any final output that might be
+ * required.
+ */
+void
+_cleanup(void)
+{
+
+	LOCK;
+
+	/* If plan_no_plan() wasn't called, and we don't have a plan,
+	   and we're not skipping everything, then something happened
+	   before we could produce any output */
+	if(!no_plan && !have_plan && !skip_all) {
+		diag("Looks like your test died before it could output anything.");
+		UNLOCK;
+		return;
+	}
+
+	if(test_died) {
+		diag("Looks like your test died just after %d.", test_count);
+		UNLOCK;
+		return;
+	}
+
+
+	/* No plan provided, but now we know how many tests were run, and can
+	   print the header at the end */
+	if(!skip_all && (no_plan || !have_plan)) {
+		printf("1..%d\n", test_count);
+	}
+
+	if((have_plan && !no_plan) && e_tests < test_count) {
+		diag("Looks like you planned %d %s but ran %d extra.",
+		     e_tests, e_tests == 1 ? "test" : "tests", test_count - e_tests);
+		UNLOCK;
+		return;
+	}
+
+	if((have_plan || !no_plan) && e_tests > test_count) {
+		diag("Looks like you planned %d %s but only ran %d.",
+		     e_tests, e_tests == 1 ? "test" : "tests", test_count);
+		UNLOCK;
+		return;
+	}
+
+	if(failures)
+		diag("Looks like you failed %d %s of %d.", 
+		     failures, failures == 1 ? "test" : "tests", test_count);
+
+	UNLOCK;
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/README
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/README	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/README	(revision 16632)
@@ -0,0 +1,12 @@
+Most of the tests follow the same pattern.
+
+ * test.pl that uses Test::More, and demonstrates whatever functionality 
+   that we're trying to test.  This is the reference code.
+
+ * test.c, which tests the libtap reimplementation of the same functionality.
+
+ * test.t, which compiles the .c program, runs both test scripts, and then 
+   diffs their output to make sure it's identical.
+
+   Right now, test.t is identical in every directory.  This sucks somewhat.
+   It should either be a symlink to a common script
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.c	(revision 16632)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	plan_tests(2);
+
+	rc = diag("A diagnostic message");
+	diag("Returned: %d", rc);
+
+	/* Make sure the failure is passed through */
+	ok(1, "test 1") || diag("ok() failed, and shouldn't");
+	ok(0, "test 2") || diag("ok() passed, and shouldn't");
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.pl	(revision 16632)
@@ -0,0 +1,16 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+plan tests => 2;
+
+$rc = diag("A diagnostic message");
+diag("Returned: $rc");
+
+ok(1, 'test 1') or diag "ok() failed, and shouldn't";
+ok(0, 'test 2') or diag "ok() passed, and shouldn't";
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/diag/test.t	(revision 16632)
@@ -0,0 +1,67 @@
+#!/bin/sh
+
+echo '1..7'
+
+perl $srcdir/test.pl 2>/dev/null >test.pl.out
+perlstatus=$?
+
+./test > test.c.out 2>&1
+cstatus=$?
+
+if grep "^# A diagnostic message$" test.c.out > /dev/null ; then
+    echo "ok 1 - found a diagnostic message"
+else
+    echo "not ok 1 - found a diagnostic message"
+    retval=1
+fi
+
+if grep "^# Returned: 0$" test.c.out > /dev/null ; then
+    echo "ok 2 - diag() expected return value" 
+else
+    echo "not ok 2 - diag() expected return value" 
+    retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 43)$" test.c.out > /dev/null ; then
+    echo "ok 3 - 'failed test at line' diag" 
+else
+    echo "not ok 3 - 'failed test at line' diag" 
+    retval=1
+fi
+
+if grep "^# ok() passed, and shouldn't$" test.c.out > /dev/null ; then
+    echo "ok 4 - expected diag"
+else
+    echo "ok 4 - expected diag"
+    retval=1
+fi
+
+if grep "^# Looks like you failed 1 test of 2.$" test.c.out > /dev/null ; then
+    echo "ok 5 - failed 1 test"
+ else
+    echo "ok 5 - failed 1 test"
+    retval=1
+fi
+
+sed -e '/^#/D' test.c.out > tmp
+mv tmp test.c.out
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 6 - TAP output is identical'
+else
+	retval=1
+	echo 'not ok 6 - TAP output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 7 - status code'
+else
+	retval=1
+	echo 'not ok 7 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.c	(revision 16632)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(2);
+	diag("Returned: %d", rc);
+
+	rc = fail("test to fail");
+	diag("Returned: %d", rc);
+
+	rc = fail("test to fail %s", "with extra string");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.pl	(revision 16632)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 2;
+diag("Returned: " . sprintf('%d', $rc));
+
+$rc = fail('test to fail');
+diag("Returned: $rc");
+
+$rc = fail('test to fail with extra string');
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/fail/test.t	(revision 16632)
@@ -0,0 +1,74 @@
+#!/bin/sh
+
+echo '1..8'
+
+perl $srcdir/test.pl 2>/dev/null > test.pl.out
+perlstatus=$?
+
+./test > test.c.out 2>&1 
+cstatus=$?
+
+if grep "^# Returned: 2$" test.c.out >/dev/null ; then
+  echo "ok 1 - expected return value";
+else
+  echo "not ok 1 - expected return value";
+  retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 39)$" test.c.out >/dev/null ; then
+  echo "ok 2 - failed expected test";
+else
+  echo "not ok 2 - failed expected test";
+  retval=1
+fi
+
+if grep "^# Returned: 0$" test.c.out >/dev/null ; then
+  echo "ok 3 - expected return value";
+else
+  echo "not ok 3 - expected return value";
+  retval=1
+fi
+
+if grep "^#     Failed test (.*test.c:main() at line 42)$" test.c.out >/dev/null ; then
+  echo "ok 4 - failed expected test";
+else
+  echo "not ok 4 - failed expected test";
+  retval=1
+fi
+  
+if grep "^# Returned: 0$" test.c.out >/dev/null ; then
+  echo "ok 5 - expected return value";
+else
+  echo "not ok 5 - expected return value";
+  retval=1
+fi
+
+if grep "^# Looks like you failed 2 tests of 2.$" test.c.out >/dev/null ; then
+  echo "ok 6 - expected return value";
+else
+  echo "not ok 6 - expected return value";
+  retval=1
+fi
+
+sed -e '/^#/D' test.c.out > tmp
+mv tmp test.c.out
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 7 - output is identical'
+else
+	retval=1
+	echo 'not ok 7 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 8 - status code'
+else
+	retval=1
+	echo 'not ok 8 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.c	(revision 16632)
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(4);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with no hash");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with one # hash");
+	diag("Returned: %d", rc);
+
+        rc = ok(1, "Test with # two # hashes");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Test with ## back to back hashes");
+	diag("Returned: %d", rc);
+	
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.pl	(revision 16632)
@@ -0,0 +1,24 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 4;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1, 'Test with no hash');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with one # hash');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with # two # hashes');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Test with ## back to back hashes');
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-hash/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.c	(revision 16632)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(3);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "First test");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "1");
+	diag("Returned: %d", rc);
+
+	rc = ok(1, "Third test");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.pl	(revision 16632)
@@ -0,0 +1,21 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 3;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1, 'First test');
+diag("Returned: $rc");
+
+$rc = ok(1, '1');
+diag("Returned: $rc");
+
+$rc = ok(1, 'Third test');
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok-numeric/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.c	(revision 16632)
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals %d", 1);
+	diag("Returned: %d", rc);
+
+	rc = ok1(1 == 1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 2, "1 equals 2");
+	diag("Returned: %d", rc);
+
+	rc = ok1(1 == 2);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.pl	(revision 16632)
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 1, '1 equals 1'); # Used for %d testing in test.c
+diag("Returned: $rc");
+
+$rc = ok(1 == 1, '1 == 1');	# Test ok1() passes when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 2, '1 equals 2');	# Test ok() fails when it should
+diag("Returned: $rc");
+
+$rc = ok(1 == 2, '1 == 2');	# Test ok1() fails when it should
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/ok/ok/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.c	(revision 16632)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(2);
+	diag("Returned: %d", rc);
+
+	rc = pass("test to pass");
+	diag("Returned: %d", rc);
+
+	rc = pass("test to pass %s", "with extra string");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.pl	(revision 16632)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 2;
+diag("Returned: " . sprintf('%d', $rc));
+
+$rc = pass('test to pass');
+diag("Returned: $rc");
+
+$rc = pass('test to pass with extra string');
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/pass/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.c	(revision 16632)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(0);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.pl	(revision 16632)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 0;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no-tests/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.c	(revision 16632)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_no_plan();
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.pl	(revision 16632)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+my $rc = 0;
+
+use Test::More;
+
+$rc = plan qw(no_plan);
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/no_plan/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.c	(revision 16632)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.pl	(revision 16632)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/not-enough-tests/test.t	(revision 16632)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	# comment this out until we're exit-code compatible with Test::More
+	#retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.c	(revision 16632)
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.pl	(revision 16632)
@@ -0,0 +1,14 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/sane/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/plan.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/plan.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/plan.c	(revision 16632)
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "tap.h"
+
+/* Run pre-defined tests on the test library to make sure that the basic
+   functionality works, and it can be used to test itself afterwards */
+
+int
+main(int argc, char *argv[])
+{
+	plan_skip_all("No good reason");
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.c	(revision 16632)
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_skip_all("No good reason");
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.pl	(revision 16632)
@@ -0,0 +1,11 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan skip_all => "No good reason";
+diag("Returned: " . sprintf("%d", $rc));
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/skip_all/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.c	(revision 16632)
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = plan_tests(1);
+	diag("Returned: %d", rc);
+
+	rc = ok(0, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.pl	(revision 16632)
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 1;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = plan tests => 1;
+diag("Returned: $rc");
+
+$rc = ok(0);
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-plans/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.c	(revision 16632)
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1, NULL);
+	diag("Returned: %d", rc);
+
+	rc = ok(0, NULL);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.pl	(revision 16632)
@@ -0,0 +1,17 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+$rc = ok(1);
+diag("Returned: $rc");
+
+$rc = ok(0);
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/plan/too-many-tests/test.t	(revision 16632)
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+    # we're not exit-status compatible with Test::More yet
+	#retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.c	(revision 16632)
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+	unsigned int side_effect = 0;
+
+	rc = plan_tests(4);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");	/* Should always work */
+	diag("Returned: %d", rc);
+
+	do {
+		if(1) {
+			rc = skip(1, "Testing skipping");
+			continue;
+		}
+		
+		side_effect++;
+
+		ok(side_effect == 1, "side_effect checked out");
+
+	} while(0);
+
+	diag("Returned: %d", rc);
+
+	skip_start(1 == 1, 1, "Testing skipping #2");
+
+	side_effect++;
+	rc = ok(side_effect == 1, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	skip_end();
+
+	rc = ok(side_effect == 0, "side_effect is %d", side_effect);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.pl	(revision 16632)
@@ -0,0 +1,40 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 4;
+diag("Returned: " . sprintf("%d", $rc));
+
+my $side_effect = 0;		# Check whether skipping has side effects
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+# Start skipping
+SKIP: {
+	$rc = skip "Testing skipping", 1;
+
+	$side_effect++;
+
+	$rc = ok($side_effect == 1, '$side_effect checked out');
+}
+
+diag("Returned: $rc");
+
+SKIP: {
+	$rc = skip "Testing skipping #2", 1;
+	diag("Returned: $rc");
+
+	$side_effect++;
+
+	$rc = ok($side_effect == 1, '$side_effect checked out');
+	diag("Returned: $rc");
+}
+
+$rc = ok($side_effect == 0, "side_effect is $side_effect");
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/skip/test.t	(revision 16632)
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.c	(revision 16632)
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2004 Nik Clayton
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+
+#include "tap.h"
+
+int
+main(int argc, char *argv[])
+{
+	unsigned int rc = 0;
+	unsigned int side_effect = 0;
+
+	rc = plan_tests(5);
+	diag("Returned: %d", rc);
+
+	rc = ok(1 == 1, "1 equals 1");	/* Should always work */
+	diag("Returned: %d", rc);
+
+	todo_start("For testing purposes");
+
+	side_effect++;
+
+	/* This test should fail */
+	rc = ok(side_effect == 0, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	/* This test should unexpectedly succeed */
+	rc = ok(side_effect == 1, "side_effect checked out");
+	diag("Returned: %d", rc);
+
+	todo_end();
+
+	todo_start("Testing printf() %s in todo_start()", "expansion");
+
+	rc = ok(0, "dummy test");
+	diag("Returned: %d", rc);
+
+	todo_end();
+
+	rc = ok(side_effect == 1, "side_effect is %d", side_effect);
+	diag("Returned: %d", rc);
+
+	return exit_status();
+}
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.pl	(revision 16632)
@@ -0,0 +1,41 @@
+#!/usr/bin/perl
+
+use warnings;
+use strict;
+
+use Test::More;
+
+my $rc = 0;
+
+$rc = plan tests => 5;
+diag("Returned: " . sprintf("%d", $rc));
+
+my $side_effect = 0;		# Check whether TODO has side effects
+
+$rc = ok(1 == 1, '1 equals 1');	# Test ok() passes when it should
+diag("Returned: $rc");
+
+# Start TODO tests
+TODO: {
+	local $TODO = 'For testing purposes';
+
+	$side_effect++;
+
+	# This test should fail
+	$rc = ok($side_effect == 0, 'side_effect checked out');
+	diag("Returned: $rc");
+
+	# This test should unexpectedly succeed
+	$rc = ok($side_effect == 1, 'side_effect checked out');
+	diag("Returned: $rc");
+}
+
+TODO: {
+	local $TODO = 'Testing printf() expansion in todo_start()';
+
+	$rc = ok(0, 'dummy test');
+	diag("Returned: $rc");
+}
+
+$rc = ok($side_effect == 1, "side_effect is $side_effect");
+diag("Returned: $rc");
Index: /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.t
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.t	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/libtap/tests/todo/test.t	(revision 16632)
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+echo '1..2'
+
+perl $srcdir/test.pl 2> /dev/null > test.pl.out
+perlstatus=$?
+
+# Test:;More prints diagnostic from TODO tests on stdout
+# http://rt.cpan.org/Ticket/Display.html?id=14982
+sed '/^#/D' test.pl.out > tmp
+mv tmp test.pl.out
+
+./test 2> /dev/null > test.c.out
+cstatus=$?
+
+diff -u test.pl.out test.c.out
+
+if [ $? -eq 0 ]; then
+	echo 'ok 1 - output is identical'
+else
+	retval=1
+	echo 'not ok 1 - output is identical'
+fi
+
+if [ $perlstatus -eq $cstatus ]; then
+	echo 'ok 2 - status code'
+else
+	retval=1
+	echo 'not ok 2 - status code'
+	echo "# perlstatus = $perlstatus"
+	echo "#    cstatus = $cstatus"
+fi
+
+exit $retval
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/Makefile	(revision 16632)
@@ -0,0 +1,31 @@
+default: lightcurve
+help:
+	@echo "make options: lightcurve (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/lightcurve
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+lightcurve: $(BIN)/lightcurve.$(ARCH)
+install: $(DESTBIN)/lightcurve
+
+LIGHTCURVE = \
+$(SRC)/args.$(ARCH).o 		$(SRC)/get_names.$(ARCH).o \
+$(SRC)/get_stars.$(ARCH).o 	$(SRC)/sort_stars.$(ARCH).o \
+$(SRC)/get_unique.$(ARCH).o 	$(SRC)/get_sources.$(ARCH).o \
+$(SRC)/get_info.$(ARCH).o 	$(SRC)/make_table.$(ARCH).o \
+$(SRC)/lightcurve.$(ARCH).o	\
+$(SRC)/help.$(ARCH).o 
+
+$(LIGHTCURVE): $(INC)/lightcurve.h
+$(BIN)/lightcurve.$(ARCH): $(LIGHTCURVE)
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/include/lightcurve.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/include/lightcurve.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/include/lightcurve.h	(revision 16632)
@@ -0,0 +1,67 @@
+# include <ohana.h>
+
+# define EMPTY          -1   
+# define END            (star_data_type *) -1
+
+# define C_LAMBDA       23.0
+# define MCAL(I,dR,dD) (((I.Mcal) + (dR)*(I.McalR) + (dD)*(I.McalD) + (dR)*(dR)*(I.McalR2) + (dD)*(dD)*(I.McalD2) + (dD)*(dR)*(I.McalRD)))
+
+int PRINT;
+int MIDAS;
+int EXTRASTARS;
+int PIXELS;
+int NLOOP;
+double RADIUS;
+double A_LAMBDA;
+double SIG;
+double COS;
+double MCUTOFF;
+char OUTFILE[100];
+char IMAGES[100];
+
+typedef struct Star {
+  double RA, Dec;
+  double ap, m, dm;
+  struct Star *next_this_unique;
+  struct Star *next_this_image;
+  int    image_number, star_number, unique_number;
+} Star;
+
+typedef struct {
+  char    name[50];
+  int     Nunique, Nstars;
+  int     fixed, empty;
+  Star   *first_this_image;
+  double  Mcal, dMcal;
+  double  exptime, airmass, clouds, Mtime, AmF, dAmF, JD;
+  double  RA_O, RA_X, RA_Y, DEC_O, DEC_X, DEC_Y;
+  double  McalR, McalD, McalR2, McalD2, McalRD;
+} Image;
+
+typedef struct {
+  double  Mrel, dMrel;
+  int     Nmeasurements;
+  Star   *first_this_unique;
+} Unique;
+
+
+/******************** PROTOTYPES ********************/
+void args             PROTO((int, char **));
+void get_names        PROTO((Image **, int  *));
+void get_sources      PROTO((Star **, int *));
+void get_stars        PROTO((Star  **, int  *, Image  *, int));
+void sort_stars       PROTO((int  **, Star *, int));
+void get_unique       PROTO((Unique **, int    *, Star *, int *, int, Star *, int));
+void count_unique     PROTO((Image *, int, int));
+void set_Mcal         PROTO((Image *, int));
+void get_Mrel         PROTO((Unique *, Image *, int)); 
+void get_Mcal         PROTO((Image *, Unique *, int));
+void ChiSquare        PROTO((Unique *, Image *, int, int));
+void get_Alam         PROTO((Unique *, Image *, int, int));
+void alter_headers    PROTO((Image *, int));
+void make_table       PROTO((Star *, int, Unique *, Image *, int));
+void get_info         PROTO((Image *));
+char *nextword        PROTO((char *));
+
+extern double hypot PROTO((double, double));
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/ChiSquare.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/ChiSquare.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/ChiSquare.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "lightcurve.h"
+
+void ChiSquare (unique, images, Nunique, Nimages)
+Unique    *unique;
+Image     *images;
+int        Nunique;
+int        Nimages;
+{
+
+  int    i, j;
+  Star   *this_star;
+  double m, dm, Mcal, Mrel, ChiSquare, Ndof;
+
+  Ndof = ChiSquare = 0.0;
+  for (i = 0; i < Nunique; i ++) {
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mcal = images[this_star[0].image_number].Mcal;
+      Mrel = unique[i].Mrel;
+      Ndof += 1.0;
+      ChiSquare += SQ (m - Mcal - Mrel) / SQ (dm);
+      this_star = this_star[0].next_this_unique;
+    }
+  }
+  Ndof = Ndof - Nunique - Nimages;
+  fprintf (stderr, "Chi Square %9.2f  Ndof %6.0f  Reduced %6.3f  A_LAMBDA  %6.4f\n", 
+	   ChiSquare, Ndof, ChiSquare/Ndof, A_LAMBDA);
+}
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/alter_headers.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/alter_headers.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/alter_headers.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "relphot.h"
+
+void alter_headers  (images, Nimages)
+Image  *images;
+int     Nimages;
+{
+
+  int i;
+  Header header;
+  char line[1000], head[1000];
+  double clouds;
+  FILE *f;
+
+  if (!strcmp(IMFILE, "-")) {
+    fprintf (stderr, "using stderr\n");
+    f = stderr;
+  }
+  else {
+    fprintf (stderr, "using %s for image stats\n", IMFILE);
+    f = fopen (IMFILE, "w");
+    if (f == NULL) {
+      fprintf (stderr, "could not open output file, using stderr\n");
+      f = stderr;
+    }
+  }
+  
+  fprintf (f, "# name                Mcal    dMcal   [time]  airmass   clouds <ap-fit> Nstars  Nunique  fixed  empty\n");
+  for (i = 0; i < Nimages; i++) {
+    strcpy (head, images[i].name);
+    strcpy (strchr(head, '.'), ".head");
+    gfits_read_header (head, &header);
+
+    sprintf (line, "mv %s %s~\0", head, head);
+    system (line);
+
+    images[i].clouds = images[i].Mcal + C_LAMBDA - A_LAMBDA*images[i].airmass + images[i].AmF;
+
+    fprintf (f, "%s  %8.3f %8.3f %8.3f %8.3f %8.3f %8.3f  %6d   %6d      %1d      %1d\n",  
+	     images[i].name, images[i].Mcal, images[i].dMcal, images[i].Mtime, 
+	     images[i].airmass, images[i].clouds, images[i].AmF, images[i].Nstars, 
+	     images[i].Nunique, images[i].fixed, images[i].empty);
+
+    gfits_modify (&header, "Mcal",   "%lf", 1, images[i].Mcal);
+    gfits_modify (&header, "dMcal",  "%lf", 1, images[i].dMcal);
+    gfits_modify (&header, "clouds", "%lf", 1, images[i].clouds);
+    gfits_modify (&header, "NMcal",  "%d", 1,  images[i].Nstars);
+
+    gfits_modify (&header, "Mcal",   "%C", 1, "relphot: calibration magnitude");
+    gfits_modify (&header, "dMcal",  "%C", 1, "relphot: calibration error");
+    gfits_modify (&header, "clouds", "%C", 1, "relphot: cloud level");
+    gfits_modify (&header, "NMcal",  "%C", 1, "relphot: number of stars");
+
+    gfits_write_header (head, &header);
+    gfits_free_header (&header);
+  }
+  fclose (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/args.c	(revision 16632)
@@ -0,0 +1,78 @@
+# include "lightcurve.h"
+# define NARGS 1
+
+void args (argc, argv)
+int      argc;
+char   **argv;
+{
+  
+  int N;
+
+  /** mandatory arguments (see help.c) **/
+  if (N = get_argument (argc, argv, "-P")) {
+    remove_argument (N, &argc, argv);
+    RADIUS = atof (argv[N]);
+    PIXELS = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  else {
+    if (N = get_argument (argc, argv, "-A")) {
+      remove_argument (N, &argc, argv);
+      RADIUS = atof (argv[N]) / 3600.0;
+      PIXELS = FALSE;
+      remove_argument (N, &argc, argv);
+    }
+    else 
+      help (argv[0]);
+  }
+  
+  if (N = get_argument (argc, argv, "-im")) {
+    remove_argument(N, &argc, argv);
+    strcpy (IMAGES, argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+  else
+    help (argv[0]);
+
+  /**** optional arguments (see help.c) ****/
+  if (N = get_argument (argc, argv, "-o")) {
+    remove_argument(N, &argc, argv);
+    strcpy (OUTFILE, argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+  else
+    strcpy (OUTFILE, "-");
+
+  if (N = get_argument (argc, argv, "-midas")) {
+    remove_argument(N, &argc, argv);
+    MIDAS = TRUE;
+  }
+  else
+    MIDAS = FALSE;
+
+  if (N = get_argument (argc, argv, "-m")) {
+    remove_argument(N, &argc, argv);
+    MCUTOFF = atof(argv[N]);
+    remove_argument(N, &argc, argv);
+  }
+  else 
+    MCUTOFF = 0.05;
+
+  if (N = get_argument (argc, argv, "-X")) {
+    remove_argument(N, &argc, argv);
+    EXTRASTARS = TRUE;
+  }
+  else 
+    EXTRASTARS = FALSE;
+
+  if (remove_argument(get_argument (argc, argv, "-h"), &argc, argv) ||
+      remove_argument(get_argument (argc, argv, "-help"), &argc, argv))
+    help(argv[0]);
+
+  if (argc != NARGS) {
+    fprintf (stderr,  "%s%s%s", "USAGE: ", 
+	     argv[0], " (-P / -A) radius  (-im images) [-o file] [-midas]\n");
+    exit (0);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/count_unique.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/count_unique.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/count_unique.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "lightcurve.h"
+
+void count_unique (images, Nimages, Nstars)
+Image *images;
+int    Nimages; 
+int    Nstars;
+{
+
+  int i, j;
+  Star *this_star;
+
+  for (i = 0; i < Nimages; i++) {
+    images[i].Nunique = 0;
+    this_star = images[i].first_this_image;
+    for (j = 0; j < images[i].Nstars; j++) {
+      if (this_star[0].unique_number != EMPTY)
+	images[i].Nunique ++;
+      this_star = this_star[0].next_this_image;
+    }
+  }
+}
+
+    
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/fix_header.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/fix_header.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/fix_header.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "lightcurve.h"
+
+/* this repairs headers screwed up in the very specific way of 
+   astro_again: not 80 chars per line on new lines, and no padding
+   of the buffer.
+
+*/
+
+void
+  fix_header 
+  (Header     *header)
+{
+
+  int i, j, Nbytes, N;
+  char *p1, *p2;
+
+  Nbytes = 2880 * (int) (header[0].size / 2880 + 1);
+  reallocate (header[0].buffer, char, Nbytes);
+  bzero (&header[0].buffer[header[0].size], Nbytes - header[0].size - 1);
+
+  p1 = header[0].buffer - 1;
+  p2 = strchr (p1 + 1, RETURN);
+
+  while (p2 != NULL) {
+    if ((N = p2 - p1) != 80) {
+      bcopy (p2, p1 + 80, header[0].size - (p2 - header[0].buffer));
+      for (i = 0; i < 80 - N; i++) {
+	*(p2 + i) = ' ';
+      }
+      header[0].size += 80 - N;
+    }
+    p1 = strchr (p1 + 1, RETURN);
+    p2 = strchr (p1 + 1, RETURN);
+  }
+
+  header[0].size = Nbytes;
+  p1 = gfits_header_field (header, "END", 1);
+  for (i = 3; i < 79; i++) 
+    *(p1 + i) = ' ';
+  *(p1 + 79) = RETURN;
+  
+  Nbytes = header[0].size - (p1 - header[0].buffer) - 80;
+  
+  for (i = 0; i < Nbytes; i++) {
+    for (j = 0; j < 79; j++, i++) 
+      *(p1 + i + 80) = '.';
+    *(p1 + i + 80) = RETURN;
+  }
+
+  Nbytes = header[0].size - (p1 - header[0].buffer) - 80;
+  while (Nbytes >= 2880) {
+    header[0].size -= 2880;
+    Nbytes = header[0].size - (p1 - header[0].buffer) - 80;
+  }
+
+  reallocate (header[0].buffer, char, header[0].size);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Alam.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Alam.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Alam.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "lightcurve.h"
+
+void get_Alam (unique, images, Nunique, Nimages)
+Unique    *unique;
+Image     *images;
+int        Nunique;
+int        Nimages;
+{
+
+  int    i, j;
+  Star   *this_star;
+  double m, dm, Mcal, Mrel, Alm, R, zeta, clouds;
+  double Clouds, dClouds, R2, N;
+
+  R = R2 = N = 0.0;
+  for (i = 0; i < Nimages; i++) {
+    images[i].clouds = images[i].Mcal + C_LAMBDA - A_LAMBDA * images[i].airmass + images[i].AmF;
+    if (!images[i].empty && images[i].fixed) {
+      R  +=     images[i].clouds;
+      R2 += SQ (images[i].clouds);
+      N  += 1.0;
+    }
+  }
+
+  Clouds  = R / N;
+  dClouds = sqrt (R2 / N - Clouds*Clouds);
+  dClouds = MAX (0.0001, dClouds);
+
+  R = Alm = 0.0;
+  for (i = 0; i < Nunique; i ++) {
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mrel = unique[i].Mrel;
+      zeta = images[this_star[0].image_number].airmass;
+      clouds = images[this_star[0].image_number].clouds;
+      if (fabs(clouds - Clouds) > SIG*dClouds) {
+	R   +=   zeta / SQ(dm);
+	Alm += zeta * (m + C_LAMBDA - clouds - Mrel) / SQ (dm);
+      }
+      this_star = this_star[0].next_this_unique;
+    }
+  }
+  if (R > 0) 
+    A_LAMBDA = (9.0*A_LAMBDA + Alm / R) / 10.0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Mcal.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Mcal.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Mcal.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "lightcurve.h"
+
+void get_Mcal (images, unique, Nimages)
+Image  *images;
+Unique *unique;
+int     Nimages;
+{
+  
+  int    i, j;
+  Star  *this_star;
+  double m, dm, Mrel, r, R, M, M2, N;
+  
+  for (i = 0; i < Nimages; i++) {
+    N = M = M2 = R = 0;
+    this_star = images[i].first_this_image;
+    for (j = 0; j < images[i].Nstars; j++) {
+      if (this_star[0].unique_number != EMPTY) {
+	dm   = this_star[0].dm;
+	m    = this_star[0].m;
+	Mrel = unique[this_star[0].unique_number].Mrel;
+	r    = 1.0 / (dm*dm);
+	R   += r;
+	M   +=    (m - Mrel) * r;
+	M2  +=  SQ(m - Mrel) * r;
+	N   += 1.0;
+      }
+      this_star = this_star[0].next_this_image;
+    }
+    if (R != 0) {
+      images[i].Mcal  = M / R;
+      images[i].dMcal = sqrt(fabs(M2 / R - SQ(M/R))) / sqrt (N);
+    }
+    else {
+      /* no multiple detections on this image! */
+      images[i].empty = TRUE;
+      images[i].Mcal  = 9.999;
+      images[i].dMcal = 9.999;
+    }
+  }
+}
+
+/* m (instrumental) = Mrel (star) + Mcal (image) */
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Mrel.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Mrel.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_Mrel.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "relphot.h"
+
+void get_Mrel (unique, images, Nunique)
+Unique   *unique;
+Image    *images;
+int       Nunique;
+{
+  
+  int    i, j;
+  Star  *this_star;
+  double dm, m, r, R, M, M2, Mcal, N;
+
+  for (i = 0; i < Nunique; i++) {
+    N = M = M2 = R = 0;
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mcal = images[this_star[0].image_number].Mcal;
+      r    = 1.0 / (dm*dm);
+      R   += r;
+      M   +=    (m - Mcal) * r;
+      M2  +=  SQ(m - Mcal) * r;
+      N   += 1.0;
+      this_star = this_star[0].next_this_unique;
+    }
+    unique[i].Mrel  = M / R;
+    unique[i].dMrel = sqrt(fabs(M2 / R - SQ(M/R))) / sqrt (N);
+  }
+
+  for (i = 0; i < Nunique; i++) {
+    N = X2 = 0;
+    Mrel = unique[i].Mrel;
+    this_star = unique[i].first_this_unique;
+    for (j = 0; j < unique[i].Nmeasurements; j ++) {
+      dm   = this_star[0].dm;
+      m    = this_star[0].m;
+      Mcal = images[this_star[0].image_number].Mcal;
+      X2  += SQ((m - Mcal - Mrel) / dm);
+      this_star = this_star[0].next_this_unique;
+    }
+    unique[i].ChiSq = X2 / (N - 1);
+  }
+}
+
+/* m (instrumental) = Mrel (star) + Mcal (image) */
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_argument.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_argument.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_argument.c	(revision 16632)
@@ -0,0 +1,19 @@
+# include "lightcurve.h"
+
+int get_argument (argc, argv, arg)
+int    argc;
+char **argv;
+char  *arg;
+{
+
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    if (!strcmp(argv[i], arg))
+      return (i);
+  }
+  
+  return ((int)NULL);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_info.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_info.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_info.c	(revision 16632)
@@ -0,0 +1,128 @@
+# include "lightcurve.h"
+
+void  get_info (images)
+Image *images;
+{
+
+  char head[500], line[500];
+  Header header;
+  int i, status;
+  double jd, days, hrs, min, sec, atof();
+
+  status = TRUE;
+
+  strcpy (head, images[0].name);
+  strcpy (strchr(head, '.'), ".head");
+
+  status = gfits_read_header (head, &header);
+  if (!status) {
+    fprintf (stderr, "could not open header file %s\n", head);
+    exit (0);
+  }
+  status = TRUE;
+
+  switch (PIXELS) {
+  case 0:
+    status &= gfits_scan (&header, "RA_O",    "%lf", 1, &images[0].RA_O);
+    status &= gfits_scan (&header, "RA_X",    "%lf", 1, &images[0].RA_X);
+    status &= gfits_scan (&header, "RA_Y",    "%lf", 1, &images[0].RA_Y);
+    status &= gfits_scan (&header, "DEC_O",   "%lf", 1, &images[0].DEC_O);
+    status &= gfits_scan (&header, "DEC_X",   "%lf", 1, &images[0].DEC_X);
+    status &= gfits_scan (&header, "DEC_Y",   "%lf", 1, &images[0].DEC_Y);
+    COS = cos (RAD_DEG * images[0].DEC_O);
+    break;
+
+  case 1:
+    status &= gfits_scan (&header, "X_O",    "%lf", 1, &images[0].RA_O);
+    status &= gfits_scan (&header, "X_X",    "%lf", 1, &images[0].RA_X);
+    status &= gfits_scan (&header, "X_Y",    "%lf", 1, &images[0].RA_Y);
+    status &= gfits_scan (&header, "Y_O",    "%lf", 1, &images[0].DEC_O);
+    status &= gfits_scan (&header, "Y_X",    "%lf", 1, &images[0].DEC_X);
+    status &= gfits_scan (&header, "Y_Y",    "%lf", 1, &images[0].DEC_Y);
+    COS = 1;
+    break;
+  }
+  
+  gfits_scan (&header, "ORIGIN", "%s", 1, line);
+  /* interpret the silly way ESO / La Palma stores exposure time and duration   */
+  if (!strcmp (line, "ESO-MIDAS")) { 
+    status &= gfits_scan (&header, "DATE-OBS", "%s", 1, line);
+    stripwhite (line);
+    fprintf (stderr, "date line: %s\n", line);
+    line[2] = 0;
+    jd = atof(line);
+    line[0] = 0;
+    status = gfits_scan (&header, "TM-START", "%lf", 1, &sec);
+    fprintf (stderr, "date: %f, sec: %f\n", jd, sec);
+    jd += (sec/86400.0) + 0.5;
+    images[0].JD =  jd;
+    gfits_scan (&header, "EXPTIME", "%lf", 1, &images[0].exptime);
+  }
+  else {
+    status &= gfits_scan (&header, "JD", "%lf", 1, &images[0].JD);
+    images[0].JD -= 2400000.5;   /* convert to MJD */
+    gfits_scan (&header, "EXPTIME", "%lf", 1, &images[0].exptime);
+  }
+
+  status &= gfits_scan (&header, "Mcal", "%lf", 1, &images[0].Mcal);
+  status &= gfits_scan (&header, "McalR", "%lf", 1, &images[0].McalR);
+  status &= gfits_scan (&header, "McalD", "%lf", 1, &images[0].McalD);
+  status &= gfits_scan (&header, "McalR2", "%lf", 1, &images[0].McalR2);
+  status &= gfits_scan (&header, "McalD2", "%lf", 1, &images[0].McalD2);
+  status &= gfits_scan (&header, "McalRD", "%lf", 1, &images[0].McalRD);
+  status &= gfits_scan (&header, "dMcal", "%lf", 1, &images[0].dMcal);
+
+  images[0].airmass = 1000;  
+  gfits_scan (&header, "SECZ", "%lf", 1, &images[0].airmass);
+  gfits_scan (&header, "AIRMASS", "%lf", 1, &images[0].airmass);
+  /* a stupid value as a flag (i hate flags!) but gfits_scan will not alter the
+     value if it fails to find the entry.  try a couple possibilities */
+ 
+  fprintf (stderr, "%s: %10.6f %10.6f  %lf  %6.3f %8.2f %5.2f\n", 
+	   head, images[0].RA_O, images[0].DEC_O, images[0].JD, 
+	   images[0].Mcal, images[0].exptime, images[0].airmass);
+   
+  if (!status) {
+    fprintf (stderr, "error getting header info from %s\n", head);
+    exit(0);
+  }
+
+  if (images[0].airmass > 10) {
+    images[0].airmass = 1.1;
+    fprintf (stderr, "warning: no airmass info\n");
+  }
+  
+  images[0].Nstars  = 0;
+  images[0].fixed   = TRUE;
+  images[0].empty   = FALSE;
+  images[0].Mtime   = 2.5*log10(images[0].exptime);
+  images[0].clouds  = 0.0;
+
+  gfits_free_header (&header);
+  
+}
+
+
+
+/* airmass formula (only used if needed) */
+/* page 264 of Kitchin */
+
+/*    z = 1 / ( .5294258 * sin(pi * d / 180.0) + .84835625 * cos(pi * d / 180.0) *
+ cos(pi * h / 12.0));
+
+n
+p status
+
+*/
+
+
+/*
+   code for using RA, DEC, ST info, if needed. 
+    status &= gfits_scan (&header, "ST", "%lf", 1, &LST);
+    ra  =  info[0].RA_O  + info[0].RA_X *CCD_X/2.0 + info[0].RA_Y *CCD_Y/2.0;
+    dec =  info[0].DEC_O + info[0].DEC_X*CCD_X/2.0 + info[0].DEC_Y*CCD_Y/2.0;
+    temp1 = sin(OBS_LAT*DEG_RAD)*sin(dec*DEG_RAD);
+    temp2 = cos(OBS_LAT*DEG_RAD)*cos(dec*DEG_RAD);
+    temp3 = cos(((360./24.)*LST - ra)*DEG_RAD);
+    (info[0].airmass) = 1.0 / (temp1 + temp2*temp3);
+*/
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_names.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_names.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_names.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "lightcurve.h"
+# define D_NIMAGE 200
+  
+void get_names (images, Nimages)
+Image **images;
+int   *Nimages;
+{
+  
+  int N, i;
+  char line[500];
+  FILE *f;
+
+  f = fopen (IMAGES, "r"); 
+  if (f == NULL) { 
+    fprintf (stderr, "failed to open %s\n", IMAGES); 
+    exit (0); 
+  }
+  N = D_NIMAGE;
+  ALLOCATE (images[0], Image, N);
+
+  for (i = 0; (fscanf (f, "%s", line) != EOF); i++) { 
+    strcpy (images[0][i].name, line);
+    strcpy (strchr(images[0][i].name, '.'), ".obj_out");
+    if (i == N - 1) {
+      N += D_NIMAGE;
+      REALLOCATE (images[0], Image, N);
+    }
+  }
+  *Nimages = i;
+  fprintf (stderr, "Nimages: %d\n", *Nimages);
+  fclose (f);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_sources.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_sources.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_sources.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "lightcurve.h"
+# define D_NSOURCES 200
+
+void get_sources (sources, Nsources)
+Star  **sources;
+int    *Nsources;
+{
+  
+  int N, i;
+
+  ALLOCATE (sources[0], Star, D_NSOURCES);
+
+  for (i = 0; (fscanf (stdin, "%lf %lf", &sources[0][i].RA, &sources[0][i].Dec) != EOF); i++) { 
+    sources[0][i].unique_number = EMPTY;
+    if (i == D_NSOURCES - 1) {
+      fprintf (stderr, "No More Sources: %d\n", i);
+      break;
+    }
+  }
+  *Nsources = i;
+  fprintf (stderr, "Nsources: %d\n", *Nsources);
+}
+
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_stars.c	(revision 16632)
@@ -0,0 +1,99 @@
+# include "lightcurve.h"
+# define D_NSTARS 1000
+
+void get_stars (stars, Nstars, images, Nimages)
+Star  **stars;
+int    *Nstars;
+Image   images[];
+int     Nimages;
+{
+
+  double type, mag, dmag, X, Y, ap, dap, AmF, A, A2, S;
+  int i, j, image_number;
+  int NSTARS, status, n, nperf;
+  FILE *f;
+  char line[200];
+
+  j = 0;
+  NSTARS = D_NSTARS;
+  ALLOCATE (stars[0], Star, NSTARS);
+
+  for (i = 0; i < Nimages; i++) { 
+    
+    get_info (&images[i]);
+    f = fopen (images[i].name, "r"); 
+    if (f == NULL) { 
+      fprintf (stderr, "failed to open %s\n", images[i].name); 
+      exit (0); 
+    }
+    nperf = A = A2 = S = 0;
+    for (n = 0; scan_line (f, line) != EOF; n++) {
+      status = TRUE;
+      status &= dparse (&type, 2, line);
+      status &= dparse (&X,    3, line);
+      status &= dparse (&Y,    4, line);
+      status &= dparse (&mag,  5, line);
+      status &= dparse (&dmag, 6, line);
+      status &= dparse (&ap,  12, line);
+      status &= dparse (&dap, 13, line);
+      status &= dparse (&AmF, 15, line);
+      if (!status) {
+	fprintf (stderr, "error on line %d in file %s\n", n, images[i].name);
+	continue;  /* go on to the next line */
+      }
+      stars[0][j].ap = 0;
+      if (ap < 99) {
+	nperf ++;
+	A  += AmF/SQ(dap);
+	A2 += SQ(AmF)/SQ(dap);
+	S  += 1.0/SQ(dap);
+	stars[0][j].ap = ap;    /* if the ap mag is good, use it, not the <ap-fit> adjusted value */
+      }
+      if ((dmag < MCUTOFF) && ((type == 1) || (EXTRASTARS && ((type == 2) || (type == 3) || (type == 4) || (type == 5) || (type == 7))))) {  /* for now, this uses only type 1s */
+	stars[0][j].RA  = images[i].RA_O  + X*images[i].RA_X  + Y*images[i].RA_Y;
+	stars[0][j].Dec = images[i].DEC_O + X*images[i].DEC_X + Y*images[i].DEC_Y;
+	stars[0][j].m   = mag + images[i].Mtime;
+	stars[0][j].dm  = sqrt (SQ(dmag) + SQ(images[i].dMcal));
+	
+	stars[0][j].next_this_unique = NULL;
+	stars[0][j].image_number     = i;
+	stars[0][j].star_number      = n;
+	stars[0][j].unique_number    = EMPTY;
+	
+	if (j == NSTARS - 1) {
+	  NSTARS += D_NSTARS;
+	  fprintf (stderr, "!");
+	  REALLOCATE (stars[0], Star, NSTARS);
+	}
+	j ++;
+	images[i].Nstars ++;   /* this is set to 0 in "get_info" */
+      }
+    }
+    if (nperf > 2) {
+      images[i].AmF = A / S;
+      images[i].dAmF = sqrt(A2/S - A*A/SQ(S));
+    }
+    else {
+      images[i].AmF = 0.0;
+      images[i].dAmF = 0.0;
+    }     
+    fclose (f);
+/*    images[i].Mcal    = - C_LAMBDA + A_LAMBDA*images[i].airmass - images[i].AmF; */
+    stars[0][j - 1].next_this_image = NULL;
+  }
+  
+  image_number = 0;
+  for (i = 0; i < j; ) {
+    images[image_number].first_this_image = &stars[0][i];
+    for (i++; ((stars[0][i].image_number == image_number) && (i < j)); i++)  {
+      stars[0][i - 1].next_this_image = &stars[0][i];
+    }
+    stars[0][i - 1].next_this_image = NULL;
+    image_number = stars[0][i].image_number;
+  }
+
+  *Nstars = j;
+  fprintf (stderr, "Nstars: %d\n", *Nstars);
+}
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_unique.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_unique.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/get_unique.c	(revision 16632)
@@ -0,0 +1,186 @@
+# include "lightcurve.h"
+# define D_NUNIQUE 1000;
+
+void get_unique (unique, N, stars, radec, Nstars, sources, Nsources)
+Unique **unique;
+int    *N;
+Star   *stars;
+int    *radec;
+int     Nstars;
+Star   *sources;
+int     Nsources;
+{
+
+  int i, j, link, k, n, confused, Nchain, NUNIQUE, Nunique, first, NTEMP;
+  int Ntemp, Nclump, Nblobs;
+  Unique  temp_unique;
+  int    *templist;
+  Star   *next_unique, *this_unique;
+  double radius, dRA, dDec, RAo, DECo, dRA2, dDec2;
+  double dRo, dDo, dRo2, dDo2;
+
+  NUNIQUE = D_NUNIQUE;
+  ALLOCATE (unique[0], Unique, NUNIQUE);
+  NTEMP = 100;
+  ALLOCATE (templist, int, NTEMP);  
+  Nblobs = dRo = dDo = dRo2 = dDo2 = 0;
+
+  for (i = Nunique = 0; (i < Nstars - 1); i++) {
+    
+    /* check if this star is not already assigned to a clump */
+    if (stars[radec[i]].next_this_unique == NULL) {
+      
+      /* first, find all stars within 2*RADIUS of this star */
+      first = i;
+      Ntemp = 1;
+      dRA = 0;
+      templist[0] = radec[first];  
+      for (j = first + 1; (dRA <= 2.0*RADIUS) && (j < Nstars); j++) {
+	if (stars[radec[j]].next_this_unique != NULL)
+	  continue;
+	dRA  = COS * (stars[radec[j]].RA - stars[radec[first]].RA);  
+	dDec = stars[radec[j]].Dec - stars[radec[first]].Dec;
+	radius = hypot(dRA, dDec);
+	if (radius < 2.0*RADIUS) {
+	  /* add to templist: */
+	  templist[Ntemp] = radec[j];
+	  Ntemp ++;
+	  if (Ntemp == NTEMP - 1) {
+	    NTEMP += 100;
+	    REALLOCATE (templist, int, NTEMP); 
+	  }
+	}
+      }
+	     
+      if (Ntemp < 3) {
+	continue; /* check this pops out of the right level... */
+      }
+
+      /* next, find the centroid of this subset of stars */
+      dRA = dDec = dRA2 = dDec2 = 0;
+      for (j = 0; j < Ntemp; j++) {
+	dRA   += stars[templist[j]].RA;
+	dDec  += stars[templist[j]].Dec;
+	dRA2  += SQ(stars[templist[j]].RA);
+	dDec2 += SQ(stars[templist[j]].Dec);
+      }
+      RAo   = dRA / (double)Ntemp;
+      DECo  = dDec / (double)Ntemp;
+      dRA2  = sqrt(dRA2 / (double)Ntemp - SQ(RAo));
+      dDec2 = sqrt(dDec2 / (double)Ntemp - SQ(DECo));
+
+      /* then, find all stars within 1 RADIUS of this centroid */
+      Nclump = 0;
+      unique[0][Nunique].first_this_unique = (Star *) NULL;
+      for (j = 0; j < Ntemp; j++) {
+	dRA  = COS * (stars[templist[j]].RA - RAo);
+	dDec = stars[templist[j]].Dec - DECo;
+	radius = hypot(dRA, dDec);
+	if (radius < RADIUS) {
+	  if (Nclump != 0) {
+	    this_unique[0].next_this_unique = &stars[templist[j]];
+	    this_unique = &stars[templist[j]];
+	    this_unique[0].unique_number = Nunique;
+	  }
+	  else {
+	    unique[0][Nunique].first_this_unique = &stars[templist[j]];
+	    this_unique = &stars[templist[j]];
+	    this_unique[0].unique_number = Nunique;
+	  }
+	  Nclump ++;
+	}
+      }
+      
+      /* if too few in clump, eliminate, move on */
+      if (Nclump < 5) {
+	this_unique = unique[0][Nunique].first_this_unique;
+	unique[0][Nunique].first_this_unique = NULL;
+	while (this_unique != NULL) {
+	  next_unique = this_unique[0].next_this_unique;
+	  this_unique[0].unique_number = EMPTY;
+	  this_unique[0].next_this_unique = NULL;
+	  this_unique = next_unique;
+	}
+	continue;
+      }
+
+      /* count number of confused stars...
+      this_unique = unique[0][Nunique].first_this_unique;
+      for (j = 0, confused = FALSE; j < Nclump - 1; j++) {
+	next_unique = this_unique[0].next_this_unique;
+	for (k = j + 1; k < Nclump; k++) {
+	  if (this_unique[0].image_number == next_unique[0].image_number) {
+	    confused = TRUE;
+	  }
+	  next_unique = next_unique[0].next_this_unique;
+	}
+	this_unique = this_unique[0].next_this_unique;
+      } 
+       */
+
+      /* if this object is confused, ignore it and move on.  
+	 keep the "next_this_unique" values on, but remove
+	 the "unique_number" */
+
+      /*
+      
+      if (confused) {
+	this_unique = unique[0][Nunique].first_this_unique;
+	unique[0][Nunique].first_this_unique = NULL;
+	while (this_unique != NULL) {
+	  this_unique[0].unique_number = EMPTY;
+	  this_unique = this_unique[0].next_this_unique;
+	}
+	Nblobs ++;
+	continue;
+      }
+      */
+      
+      this_unique = unique[0][Nunique].first_this_unique;
+      for (j = 0; j < Nclump; j++) {
+	dRA   += this_unique[0].RA;
+	dDec  += this_unique[0].Dec;
+	dRA2  += SQ(this_unique[0].RA);
+	dDec2 += SQ(this_unique[0].Dec);
+	next_unique = this_unique[0].next_this_unique;
+      }
+      RAo   = dRA / (double)Nclump;
+      DECo  = dDec / (double)Nclump;
+      for (n = 0; n < Nsources; n++) {
+	dRA = COS * (RAo - sources[n].RA);
+	dDec = (DECo - sources[n].Dec);
+	radius = hypot(dRA, dDec);
+	if (radius < RADIUS) {
+	  sources[n].unique_number = Nunique;
+	  fprintf (stderr, "%d %d  %f %f  %f %f\n", 
+		   n, Nunique, RAo, DECo, sources[n].RA, sources[n].Dec);
+	  break;
+	}
+      } 
+      
+      unique[0][Nunique].Nmeasurements = Nclump;
+      unique[0][Nunique].Mrel = 0.0;
+      /* use only stars which show up on all images */
+      
+      dRo += dRA2;
+      dDo += dDec2;
+      dRo2 += dRA2*dRA2;
+      dDo2 += dDec2*dDec2;
+      Nunique ++;
+      if (Nunique == NUNIQUE - 1) { 
+	NUNIQUE += D_NUNIQUE;
+	REALLOCATE(unique[0], Unique, NUNIQUE);
+      }
+    }
+  } 
+
+  *N = Nunique;
+  dRo = dRo / (double)Nunique;
+  dDo = dDo / (double)Nunique;
+  dRo2 = sqrt(dRo2 / (double)Nunique - SQ(dRo));
+  dDo2 = sqrt(dDo2 / (double)Nunique - SQ(dDo));
+
+  fprintf (stderr, "%f   %f %f %f %f   %4d %3d\n", 3600*RADIUS, dRo, dDo, dRo2, dDo2, Nunique, Nblobs);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/help.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/help.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/help.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "lightcurve.h"
+
+void
+help (name)
+char name[];
+{
+  
+  fprintf (stderr, "%s%s%s%s%s%s%s%s%s%s%s%s%s",
+	   "USAGE: ", name, " (-P / -A) radius  \n",
+	   "\n",
+           "  Mandatory Flags:\n",
+           "  -P / -A      one of these must be used: \n",
+           "    -P  pixs     radius of search in pixels -- uses relative astrometry (rastro)\n",
+           "    -A  asec     radius of search in arcsec -- uses absolute astrometry  (astro)\n",
+           "  -im images   file with the list of images to use\n",
+           "\n",
+           "  Optional Flags:\n",
+           "  -o  file  output file for star data\n",
+           "  -midas    use MIDAS format time info from headers\n"
+           "  -h        print this list\n\n",
+	   "  ", name, " expects a series of (Ra,Dec) or (X,Y) pairs\n\n");
+  
+  exit (0);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/imstats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/imstats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/imstats.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "lightcurve.h"
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Image   *images;
+  Star    *stars, *sources;
+  Unique  *unique;
+  int     *radec;
+  int      Nimages, Nstars, Nunique, Nsources;
+  int      i, j;
+
+  /*** this still needs to be fixed / updated */
+  args (argc, argv);
+
+  get_names (&images, &Nimages);
+  get_sources (&sources, &Nsources);
+  get_stars  (&stars, &Nstars, images, Nimages);
+  sort_stars (&radec, stars, Nstars);
+
+  get_unique (&unique, &Nunique, stars, radec, Nstars, sources, Nsources);
+
+  make_table (sources, Nsources, unique, images, Nimages);
+  
+}
+
+
+/* 
+   list of system wide variables that are (should be) defined in relphot.h:
+
+   RADIUS  (radius of search in pixels or arcsec)
+   A_LAMBDA (airmass extinction coefficient)
+   C_LAMBDA (zero point C_\lambda)
+   NLOOP   (desired number of interations)
+   SIG     (number of sigma for cloudiness criterion)
+   OUTFILE (output file)
+   PRINT   (print processing info?)
+   PIXELS  (RADIUS in pixels (rastro) or degrees (astro))
+   COS     (RA scaling factor = cos(DEC(center of field)) if astro, 
+                              = 1 if rastro )
+
+*/
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/jd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/jd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/jd.c	(revision 16632)
@@ -0,0 +1,72 @@
+      SUBROUTINE locate(xx,n,x,j)
+      INTEGER j,n
+      REAL x,xx(n)
+      INTEGER jl,jm,ju
+      jl=0
+      ju=n+1
+10    if(ju-jl.gt.1)then
+        jm=(ju+jl)/2
+        if((xx(n).gt.xx(1)).eqv.(x.gt.xx(jm)))then
+          jl=jm
+        else
+          ju=jm
+        endif
+      goto 10
+      endif
+      j=jl
+      return
+      END
+
+      FUNCTION julday(mm,id,iyyy)
+      INTEGER julday,id,iyyy,mm,IGREG
+      PARAMETER (IGREG=15+31*(10+12*1582))
+      INTEGER ja,jm,jy
+      jy=iyyy
+      if (jy.eq.0) pause 'julday: there is no year zero'
+      if (jy.lt.0) jy=jy+1
+      if (mm.gt.2) then
+        jm=mm+1
+      else
+        jy=jy-1
+        jm=mm+13
+      endif
+      julday=int(365.25*jy)+int(30.6001*jm)+id+1720995
+      if (id+31*(mm+12*iyyy).ge.IGREG) then
+        ja=int(0.01*jy)
+        julday=julday+2-ja+int(0.25*ja)
+      endif
+      return
+      END
+
+function mjd(yr,hr,sc)
+	implicit none
+	integer iyr, mn, n, jd, j, julday, idy
+	real*8 yr,hr,sc,mjd
+	real*4 month(12), dy
+	n = 12
+	data month/0,31,59,90,120,151,181,212,243,273,304,334/
+	iyr = yr
+	if((mod(iyr,4).eq.0.and.mod(iyr,100).ne.0).or.(mod(iyr,400).eq.0)) then
+	  dy = int(366.*(yr-iyr)+.0001) + 1
+	  do j = 3, 12
+	    month(j) = month(j) + 1.
+	  end do
+	else
+	  dy = int(365.*(yr-iyr)+.0001) + 1
+	end if
+c 
+c locate, from Numrec library
+c
+	call locate(month,n,dy,mn)
+	dy = dy - month(mn)
+	idy = dy
+c
+c julday, from Numrec library
+c
+	jd = julday(mn,idy,iyr)
+	mjd = jd - 2440000.5
+	mjd = mjd + hr / 24. + sc / 86400. / 2.
+	end
+
+
+z
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/lightcurve.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/lightcurve.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/lightcurve.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "lightcurve.h"
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Image   *images;
+  Star    *stars, *sources;
+  Unique  *unique;
+  int     *radec;
+  int      Nimages, Nstars, Nunique, Nsources;
+  int      i, j;
+
+  /*** this still needs to be fixed / updated */
+  args (argc, argv);
+
+  get_names (&images, &Nimages);
+  get_sources (&sources, &Nsources);
+  get_stars  (&stars, &Nstars, images, Nimages);
+  sort_stars (&radec, stars, Nstars);
+
+  get_unique (&unique, &Nunique, stars, radec, Nstars, sources, Nsources);
+
+  make_table (sources, Nsources, unique, images, Nimages);
+  
+}
+
+
+/* 
+   list of system wide variables that are (should be) defined in relphot.h:
+
+   RADIUS  (radius of search in pixels or arcsec)
+   A_LAMBDA (airmass extinction coefficient)
+   C_LAMBDA (zero point C_\lambda)
+   NLOOP   (desired number of interations)
+   SIG     (number of sigma for cloudiness criterion)
+   OUTFILE (output file)
+   PRINT   (print processing info?)
+   PIXELS  (RADIUS in pixels (rastro) or degrees (astro))
+   COS     (RA scaling factor = cos(DEC(center of field)) if astro, 
+                              = 1 if rastro )
+
+*/
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/make_table.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/make_table.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/make_table.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "lightcurve.h"
+
+void make_table (sources, Nsources, unique, images, Nimages)
+Star   *sources;
+int     Nsources;
+Unique *unique;
+Image  *images;
+int     Nimages;
+{
+
+  double  N, M, dM;
+  int     i, j, n, im;
+  Star   *next_measurement;
+  FILE   *f;
+  double  dR, dD;
+
+  if (!strcmp(OUTFILE, "-")) {
+    fprintf (stderr, "using stdout\n");
+    f = stdout;
+  }
+  else {
+    fprintf (stderr, "using %s for output\n", OUTFILE);
+    f = fopen (OUTFILE, "w");
+    if (f == NULL) {
+      fprintf (stderr, "could not open output file, using stdout\n");
+      f = stdout;
+    }
+  }
+  
+  fprintf (f, "# This is a table of data from relphot.\n");
+  fprintf (f, "# This table contains the following data:\n");
+  if (PIXELS) 
+    fprintf (f, "# star number, <X> dX  <Y> dY  <Mrel> dMrel  Nstars\n");
+  else
+    fprintf (f, "# star number, <RA> dRA  <Dec> dDec  <Mrel> dMrel  Nstars\n");
+
+  for (j = 0; j < Nsources; j++) {
+    fprintf (f, "%5d %10.6f %10.6f ", j, sources[j].RA, sources[j].Dec);
+    if (sources[j].unique_number == EMPTY) {
+      fprintf (f, "%5d\n", 0.0);
+      continue;
+    }
+    N = unique[sources[j].unique_number].Nmeasurements;
+    fprintf (f, "%5.0f\n", N);
+    next_measurement = unique[sources[j].unique_number].first_this_unique;
+    M = 100.0; dM = 0.0;
+    for (n = 0; n < N; n++) {
+      im = next_measurement[0].image_number;
+      dR = (next_measurement[0].RA - images[im].RA_O);
+      dD = (next_measurement[0].Dec - images[im].DEC_O);
+      M = next_measurement[0].m - MCAL(images[im], dR, dD);
+      dM = next_measurement[0].dm;
+      dR = (next_measurement[0].RA - sources[j].RA);
+      dD = (next_measurement[0].Dec - sources[j].Dec);
+      fprintf (f, "%-40s  %15.6f  %7.3f %7.3f  %7.3f %7.3f\n", images[im].name, images[im].JD, dR, dD, M, dM);
+      next_measurement = next_measurement[0].next_this_unique;
+    }
+  }
+  fclose (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/match_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/match_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/match_stars.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "relphot.h"
+# define D_NUNIQUE 1000;
+
+void match_stars (unique, N, stars, radec, Nstars, sources, Nsources)
+Unique **unique;
+int    *N;
+Star   *stars;
+int    *radec;
+int     Nstars;
+Source *sources;
+int     Nsources;
+{
+
+  int i, j, link, k, good, Nchain, NUNIQUE, Nunique;
+  Unique  temp_unique;
+  Star   *next_unique, *this_unique;
+  double radius, dRA, dDec;
+
+  NUNIQUE = D_NUNIQUE;
+  ALLOCATE (unique[0], Unique, NUNIQUE);
+
+  for (i = Nunique = 0; (i < Nstars - 1); i++) {
+    
+    dRA = COS * (stars[radec[i+1]].RA - stars[radec[i]].RA);
+
+    if (dRA < 0.0) {
+      fprintf (stderr, "stars out of order!!!  %d  %d  %f  %f\n", 
+	       radec[i+1], radec[i], stars[radec[i+1]].RA, stars[radec[i]].RA);
+    }
+
+    if ((fabs(dRA) < RADIUS) && (stars[radec[i]].next_this_unique == NULL)) {
+
+      /* set up the chain */
+      for (link = i, j = link + 1, Nchain = 1; (fabs(dRA) < RADIUS) && (j < Nstars); j++) {
+	dDec   = stars[radec[j]].Dec - stars[radec[link]].Dec;
+	radius = hypot(dRA, dDec);
+	if (radius < RADIUS) {
+	  stars[radec[link]].next_this_unique = &stars[radec[j]];
+	  link = j;
+	  Nchain ++;
+	}
+	if (j < Nstars - 1)
+	  dRA  = COS * (stars[radec[j + 1]].RA - stars[radec[link]].RA);
+      }
+
+      /* are any 2 links on the same image? */
+      this_unique = &stars[radec[i]];
+      for (j = 0, good = TRUE; j < Nchain - 1; j++) {
+	next_unique = this_unique[0].next_this_unique;
+	for (k = j + 1; k < Nchain; k++) {
+	  if (this_unique[0].image_number == next_unique[0].image_number) {
+	    good = FALSE;
+	    fprintf (stderr, "clump on image %d, stars %d and %d\n", 
+		     this_unique[0].image_number, 
+		     this_unique[0].star_number, 
+		     next_unique[0].star_number);
+	  }
+	  next_unique = next_unique[0].next_this_unique;
+	}
+	this_unique = this_unique[0].next_this_unique;
+      }
+
+      /* if not, add chain to unique[] */
+      if ((good) && (Nchain > 1)) {
+	this_unique = unique[0][Nunique].first_this_unique = &stars[radec[i]];
+	while (this_unique != NULL) {
+	  this_unique[0].unique_number = Nunique;
+	  this_unique = this_unique[0].next_this_unique;
+	}
+	unique[0][Nunique].Nmeasurements = Nchain;
+	Nunique ++;
+	if (Nunique == NUNIQUE - 1) { 
+	  NUNIQUE += D_NUNIQUE;
+	  REALLOCATE(unique[0], Unique, NUNIQUE);
+	}
+      }
+    }
+  } 
+
+  *N = Nunique;
+  fprintf (stderr, "Nunique: %d\n", Nunique);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/mjd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/mjd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/mjd.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include "lightcurve.h"
+# define GREG (15+31*(10+12*1582))
+
+double mjd (year, hour, second)
+double year, hour, second;
+{
+
+  int iyear;
+  int Months[] = {0,31,59,90,120,151,181,212,243,273,304,334};
+
+  /* convert year, which contains year + day, into year, month, day */
+  iyear = year;
+  if ((!(iyear % 4) && (iyear % 100)) || !(iyear % 400)) { /* leap year */
+    day = 366*(year - iyear) + 1;
+    for (i = 2; i < 12; i++) 
+      Months[i]++;
+  }
+  else {
+    day = 365*(year - iyear) + 1;
+  }
+  for (i = 0; month[i] < day; i++);
+  month = Months[i-1];
+  
+  if (day + 31*(month + 12*iyear) >= GREG) 
+    extra = 2 - (int)(0.01*jy) + (int)(0.25*((int)(0.01*jy)));
+  else 
+    extra = 0;
+
+  if (year == 0) {
+    fprintf (stderr, "error: there is no year zero\n");
+    exit (0);
+  }
+  if (year < 0) 
+    year += 1.0;
+  if (month > 2) 
+    jmonth = month + 1;
+  else {
+    year -= 1;
+    month += 13;
+  }
+
+  julday = (int)(365.25*year)+int(30.6001*jm)+id+1720995
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/parse.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/parse.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/parse.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "lightcurve.h"
+
+int parse (X, NX, line)
+double *X;
+int NX;
+char *line;
+{
+
+  int i;
+  char *word;
+  char *ptr;
+
+  word = line;
+  for (i = 0; i < NX - 1; i++)
+    word = nextword (word);
+
+  *X = strtod (word, &ptr);
+  if (ptr == word)
+    return (FALSE);
+  else
+    return (TRUE);
+}
+
+
+char *nextword(string)
+char *string;
+{
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (; isspace (*string); string++);
+  for (; (*string != 0) && !isspace (*string); string++);
+  for (; isspace (*string); string++);
+  return (string);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/relphot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/relphot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/relphot.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "lightcurve.h"
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Image   *images;
+  Star    *stars;
+  Unique  *unique;
+  int     *radec;
+  int      Nimages, Nstars, Nunique;
+  int      i, j;
+
+  /*** this still needs to be fixed / updated */
+  args (argc, argv);
+
+  get_names  (&images, &Nimages);
+  get_stars  (&stars, &Nstars, images, Nimages);
+  sort_stars (&radec, stars, Nstars);
+
+  get_unique (&unique, &Nunique, stars, radec, Nstars);
+  count_unique (images, Nimages, Nstars);
+
+  for (i = 0; i < NLOOP; i++) {
+    set_Mcal (images, Nimages);
+    get_Mrel (unique, images, Nunique);
+    get_Mcal (images, unique, Nimages);
+    ChiSquare (unique, images, Nunique, Nimages);
+  }  
+ 
+
+  if (PRINT) {
+    alter_headers (images, Nimages);
+    make_table (unique, images, Nunique);
+  }
+  
+}
+
+
+/* 
+   list of system wide variables that are (should be) defined in relphot.h:
+
+   RADIUS  (radius of search in pixels or arcsec)
+   A_LAMBDA (airmass extinction coefficient)
+   C_LAMBDA (zero point C_\lambda)
+   NLOOP   (desired number of interations)
+   SIG     (number of sigma for cloudiness criterion)
+   OUTFILE (output file)
+   PRINT   (print processing info?)
+   PIXELS  (RADIUS in pixels (rastro) or degrees (astro))
+   COS     (RA scaling factor = cos(DEC(center of field)) if astro, 
+                              = 1 if rastro )
+
+*/
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/remove_argument.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/remove_argument.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/remove_argument.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "lightcurve.h"
+
+int remove_argument (N, argc, argv)
+int    N;
+int   *argc;
+char **argv;
+{
+
+  int i;
+
+  if ((N != (int)NULL) && (N != 0)) {
+    (*argc)--;
+    for (i = N; i < *argc; i++) {
+      argv[i] = argv[i+1];
+    }
+  }
+
+  return (N);
+    
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/scan_line.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/scan_line.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/scan_line.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "lightcurve.h"
+
+/*************/
+int
+scan_line (f, line) 
+FILE *f;
+char line[];
+{
+
+  int i, status;
+  char c;
+  
+  status = EOF + 1;
+  
+  for (i = 0, c = 0; (c != '\n') && (status != EOF); i++) {
+    status = fscanf (f, "%c", &c);
+    line[i] = c;
+  }
+  line[i - 1] = 0;  /* this could make things crash! */
+
+  if (i > 1) {
+    status = EOF + 1;
+  }
+
+  return (status);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/set_Mcal.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/set_Mcal.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/set_Mcal.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "lightcurve.h"
+
+void set_Mcal (images, Nimages)
+Image    *images;
+int       Nimages;
+{
+
+  int i;
+  double clouds, Clouds, dClouds, R, R2, N;
+  
+  R = R2 = N = 0.0;
+  for (i = 0; i < Nimages; i++) {
+    images[i].clouds = images[i].Mcal + C_LAMBDA - A_LAMBDA * images[i].airmass + images[i].AmF;
+    if (!images[i].empty && images[i].fixed) {
+      R  +=     images[i].clouds;
+      R2 += SQ (images[i].clouds);
+      N  += 1.0;
+    }
+  }
+
+  Clouds  = R / N;
+  dClouds = sqrt (R2 / N - Clouds*Clouds);
+
+  fprintf (stderr, "Clouds = %f, dClouds = %f, N / Nimages: %f / %d\n", Clouds, dClouds, N, Nimages);
+
+  dClouds = MAX (0.0001, dClouds);
+
+  for (i = 0; i < Nimages; i++) {
+    if (fabs(images[i].clouds - Clouds) > SIG*dClouds) 
+      images[i].fixed = FALSE;
+    else {
+      images[i].fixed  = TRUE;
+      images[i].Mcal   = - C_LAMBDA + A_LAMBDA * images[i].airmass - images[i].AmF;
+      images[i].clouds = 0.0;
+    }
+  }
+}
+
+/*  BIG IMPORTANT NOTE:  equations (3) and (7) in Magnier et al 1992, A&A 96, 379
+    are not consistent with positive defined A_LAMBDA.  
+
+    the equations should read:
+
+    (3)  M_app = c_lambda + m - a_lambda*\zeta ... + clouds    (... is color term)
+    (7)  M_cal = -c_lambda + a_lambda*\zeta
+
+    The point is that a_lambda is a positive coeff, so as \zeta increases, the
+    image is *less* sensitive, so M_cal goes up.  conversely, c_lambda is also
+    a positive defined number, so as c_lambda increases, the image is *more* 
+    sensitive.  Since the a_lambda and c_lambda have opposite senses, they 
+    must have opposite signs.  
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/lightcurve/src/sort_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/lightcurve/src/sort_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/lightcurve/src/sort_stars.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "lightcurve.h"
+
+// construct an index for the stars sorted by RA
+void sort_stars (int **index, Star *stars, int Nstars) {
+  
+  int i;
+  double *RAs;
+
+  ALLOCATE (myIndex, int, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    myIndex[i] = i;
+  }
+
+# define SWAPFUNC(A,B){ int tmp = myIndex[A]; myIndex[A] = myIndex[B]; myIndex[B] = tmp; }
+# define COMPARE(A,B)(stars[myIndex[A]].RA < stars[myIndex[B]].RA)
+
+  OHANA_SORT (Nstars, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+  *index = myIndex;
+}
Index: /branches/eam_branch_20080223/Ohana/src/markrock/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/Makefile	(revision 16632)
@@ -0,0 +1,37 @@
+default: markrock
+help:
+	@echo "make options: markrock (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/markrock
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+markrock: $(BIN)/markrock.$(ARCH)
+install: $(DESTBIN)/markrock
+
+MARKROCK = \
+$(SRC)/markrock.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   	\
+$(SRC)/coordops.$(ARCH).o	$(SRC)/sorts.$(ARCH).o 		\
+$(SRC)/ConfigInit.$(ARCH).o 	$(SRC)/photometry.$(ARCH).o \
+$(SRC)/check_lockfile.$(ARCH).o \
+$(SRC)/find_rocks.$(ARCH).o 	$(SRC)/wcatalog.$(ARCH).o	\
+$(SRC)/gcatstats.$(ARCH).o	$(SRC)/wrocks.$(ARCH).o 	\
+$(SRC)/check_permissions.$(ARCH).o \
+$(SRC)/gregions.$(ARCH).o \
+$(SRC)/aregion.$(ARCH).o \
+$(SRC)/find_bright_stars.$(ARCH).o \
+$(SRC)/load_gsc_data.$(ARCH).o \
+$(SRC)/count_neighbors.$(ARCH).o
+
+$(MARKROCK): $(INC)/markrock.h
+$(BIN)/markrock.$(ARCH): $(MARKROCK)
Index: /branches/eam_branch_20080223/Ohana/src/markrock/doc/example.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/doc/example.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/doc/example.txt	(revision 16632)
@@ -0,0 +1,13 @@
+
+rats: foreach f ( */*.cpt )
+foreach? echo $f
+foreach? echo $f >> bright.log
+foreach? (markstar -v $f >> bright.dat) >>& bright.log
+foreach? end
+
+
+
+ echo $f
+ echo $f >> bright.log
+ (markstar -v $f >> bright.dat) >>& bright.log
+ end
Index: /branches/eam_branch_20080223/Ohana/src/markrock/include/markrock.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/include/markrock.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/include/markrock.h	(revision 16632)
@@ -0,0 +1,46 @@
+# include <ohana.h>
+# include <dvo.h>
+
+typedef struct {
+  Coords coords;
+  double *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+typedef struct {
+  double ra[3];
+  double dec[3];
+  double X[3];
+  double Y[3];
+  unsigned int t[3];
+  double mag[3];
+  int N[3];
+} Rocks;
+
+/* global variables set in parameter file */
+
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+
+char   GSCFILE[256];
+char   GSCDIR[256];
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char   RockCat[256];
+
+double RADIUS;
+double MAX_RADIUS;
+double MAX_SPEED;
+double MAX_DELAY;
+double ZERO_POINT;
+
+double BRIGHT_HALO_MAG;
+double BRIGHT_HALO_SLOPE;
+double ROCK_NEIGHBOR_RADIUS;
+int    ROCK_NEIGHBOR_NMAX;
+
+PhotCodeData photcodes;
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "markrock.h"
+
+ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* used in other pipeline functions */
+  ScanConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
+  /* unique to markrock */
+  ScanConfig (config, "ROCK_NEIGHBOR_RADIUS",   "%lf", 0, &ROCK_NEIGHBOR_RADIUS);
+  ScanConfig (config, "ROCK_NEIGHBOR_NMAX",     "%d",  0, &ROCK_NEIGHBOR_NMAX);
+
+  ScanConfig (config, "ROCK_RADIUS",            "%lf", 0, &RADIUS);
+  ScanConfig (config, "ROCK_MAX_RADIUS",        "%lf", 0, &MAX_RADIUS);
+  ScanConfig (config, "ROCK_MAX_SPEED",         "%lf", 0, &MAX_SPEED);
+  ScanConfig (config, "ROCK_MAX_DELAY",         "%lf", 0, &MAX_DELAY);
+  ScanConfig (config, "ROCK_CATALOG",           "%s",  0, RockCat);
+
+  ScanConfig (config, "BRIGHT_HALO_MAG",        "%lf", 0, &BRIGHT_HALO_MAG);
+  ScanConfig (config, "BRIGHT_HALO_SLOPE",      "%lf", 0, &BRIGHT_HALO_SLOPE);
+  ScanConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  ScanConfig (config, "GSCDIR",                 "%s",  0, GSCDIR);
+  ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/count_neighbors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/count_neighbors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/count_neighbors.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "markrock.h"
+
+count_neighbors (rocks, Nrocks, catalog, catstats)
+Rocks *rocks;
+int Nrocks;
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  float *x, *y;
+  double X, Y, dx, dy, dr;
+  int i, j, k;
+
+  x = catstats[0].X;
+  y = catstats[0].Y;
+
+  for (i = 0; i < Nrocks; i++) {
+    for (k = 0; k < 3; k++) {
+      X = rocks[i].X[k];
+      Y = rocks[i].Y[k];
+      rocks[i].N[k] = 0;
+      for (j = 0; j < catalog[0].Naverage; j++) {
+	if ((dx = X - x[j]) > ROCK_NEIGHBOR_RADIUS) continue;
+	if (dx < -ROCK_NEIGHBOR_RADIUS) break;
+	dy = Y - y[j];
+	dr = hypot (dx, dy);
+	if (dr > ROCK_NEIGHBOR_RADIUS) continue;
+	rocks[i].N[k] ++;
+      }
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/find_bright_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/find_bright_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/find_bright_stars.c	(revision 16632)
@@ -0,0 +1,144 @@
+# include "markrock.h"
+
+void find_bright_stars (Catalog *catalog, CatStats *catstats) {
+
+  int i, j, n, m, first_j, Nave, Ngsc, Nmark;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  double *X1, *Y1, *X2, *Y2;
+  int *N1, *N2;
+  char *mark;
+  double dX, dY, dR, MaxDist, MaxDist1, MaxRadius, radius, radius2;
+
+  load_gsc_data (&GSCdata, catstats);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  /* in the function below, it is better to have the catalog with
+     more stars associated with index 2 (j) */ 
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+  ALLOCATE (X1, double, Ngsc);
+  ALLOCATE (Y1, double, Ngsc);
+  ALLOCATE (N1, int, Ngsc);
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    RD_to_XY (&X1[i], &Y1[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Ngsc > 1) sort_coords_index (X1, Y1, N1, Ngsc);
+  
+  /* first find stellar halos */
+  /* max radius (mag = -1) */
+  /** the j index moves quickly and is better associated with the catalog with more stars */
+  MaxRadius = BRIGHT_HALO_SLOPE * (-1.0 - BRIGHT_HALO_MAG); 
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*MaxRadius) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*MaxRadius) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    radius = MAX (BRIGHT_HALO_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_HALO_MAG), 0.0);
+    if (radius == 0) {
+      i++; 
+      continue;
+    }
+    radius2 = radius*radius;
+    for (; (dX > -2*radius) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < radius2) {  /* new measurement of this star */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+# if (0)
+  /* next find y spikes */
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -BRIGHT_YTRAIL_WIDTH) {
+      i++;
+      continue;
+    }
+    if (dX >= BRIGHT_YTRAIL_WIDTH) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist = MAX (BRIGHT_YTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_YTRAIL_MAG), 0.0);
+    for (; (dX > -BRIGHT_YTRAIL_WIDTH) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dX) < BRIGHT_YTRAIL_WIDTH) && (fabs(dY) < MaxDist)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find x spikes */
+  /** find catalog stars near GSC stars **/
+  MaxDist = MAX (BRIGHT_XTRAIL_SLOPE * (-1.0 - BRIGHT_XTRAIL_MAG), 0.0);
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -MaxDist) {
+      i++;
+      continue;
+    }
+    if (dX >= MaxDist) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist1 = MAX (BRIGHT_XTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_XTRAIL_MAG), 0.0);
+    for (; (dX > -MaxDist1) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dY) < BRIGHT_XTRAIL_WIDTH) && (fabs(dX) < MaxDist1)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+# endif
+
+  /* done with search, mark selected stars */
+  Nmark = 0;
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      Nmark ++;
+      catalog[0].average[N2[i]].code = ID_BLEED;
+    }
+  } 
+  fprintf (stderr, "marked %d stars for bright star\n", Nmark);
+  
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (mark);
+  free (GSCdata.average);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/find_ghosts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/find_ghosts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/find_ghosts.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "markrock.h"
+
+find_ghosts (catalog, catstats, filename, image, Nimage)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+Image image[];
+int Nimage;
+{
+
+  int i, j, first_j, Nave, Ngsc, Nregions;
+  Catalog GSCdata, Ghostdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius, X, Y, R, D;
+  Image timage;
+  GSCRegion *region, *gregions();
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* coords structure for ghost image */
+    timage = image[i];
+    timage.coords.cdelt1 = -1*image[i].coords.cdelt1;
+    timage.coords.cdelt2 = -1*image[i].coords.cdelt2;
+    timage.coords.crpix1 = 2*OPTICAL_AXIS1 - image[i].coords.crpix1;
+    timage.coords.crpix2 = 2*OPTICAL_AXIS2 - image[i].coords.crpix2;
+
+    region = gregions2 (&timage, &Nregions);
+    
+    /* find ghost stars */
+    load_gsc_data_ghost (&GSCdata, region, Nregions, &timage);
+
+    /* refect ghost stars to find locations of ghosts */
+    ALLOCATE (Ghostdata.average, Average, MAX (GSCdata.Naverage, 1));
+    for (j = 0; j < GSCdata.Naverage; j++) {
+      RD_to_XY (&X, &Y, GSCdata.average[j].R, GSCdata.average[j].D, &timage);
+      fXY_to_RD (&Ghostdata.average[j].R, &Ghostdata.average[j].D, X, Y, &image[i]);
+      Ghostdata.average[j].M = GSCdata.average[j].M;
+    }    
+    Ghostdata.Naverage = GSCdata.Naverage;
+
+    /* match ghosts and image stars, mark ghosts */
+    find_matches (catalog, catstats, &Ghostdata, i);
+
+    free (Ghostdata.average);
+    free (GSCdata.average);
+  }
+
+}
+
+/* 
+
+   just to be clear on some of the terms:
+
+   the "ghost" is the fuzzy patch of light on an image caused by
+     a reflected star
+
+   the "ghost star" is the star in the sky which causes a ghost
+
+   the "ghost image" is the image location on the sky 
+     where ghost stars may come from.
+
+   the "image stars" are observed stars at the location of the
+     ghost - these are detections of the ghost
+
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/find_group.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/find_group.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/find_group.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "markrock.h"
+
+find_group (catstats, mark, Npts, i, ANGLE)
+     CatStats catstats[];
+     double *ANGLE;
+     int i, Npts;
+     char *mark;
+{
+ 
+  float *R, *D;
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Ra, De, dR, dD, angle, limit;
+
+   /* assign some parameter values */
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  limit = 10.0*sqrt((double)(M_PI*RADIUS*RADIUS*catstats[0].density)/(double)(NBINS));
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS)
+  bzero (A, NBINS*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  if (mark[i]) return (FALSE);
+  Ra = R[i];
+  De = D[i];
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) 
+	continue;
+      if (angle < 0) angle += M_PI;
+      bin = 1 + angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      if (A[bin] > limit) {
+	*ANGLE = (bin - 1.0) / (DEG_RAD*Ndegbin);
+	return (TRUE);
+      }
+      N ++;
+    }
+  }
+  return (FALSE);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/find_rocks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/find_rocks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/find_rocks.c	(revision 16632)
@@ -0,0 +1,189 @@
+# include "markrock.h"
+
+Rocks *find_rocks (Catalog *catalog, CatStats *catstats, int *nrocks) {
+
+  int i, j, k, n, m, N, M, first_j, NOBJECT, Nobject, Nrocks, NROCKS;
+  double X, Y, RADIUS2;
+  double *X1, *Y1;
+  double dX, dY, dR;
+  float dtime;
+  int *N1, *N0;
+  unsigned int Tref;
+  int *T1, Ttmp;
+  int Nstar, Nghost, Ng;
+  unsigned int flags;
+  unsigned short NotRock, IsProper;
+  Coords *tcoords;
+  double ax, ay, cx, cy, dt, dt1, dt2, dt3, dX1, dX2, speed, distance;
+  Rocks *rocks;
+  struct timeval now, then;  
+  double MaxSeparation;
+
+  gettimeofday (&then, (void *) NULL);
+
+  Nstar = catalog[0].Naverage;
+
+  NOBJECT = 1000;
+  ALLOCATE (X1, double, NOBJECT);
+  ALLOCATE (Y1, double, NOBJECT);
+  ALLOCATE (T1, int,   NOBJECT);
+  ALLOCATE (N1, int,   NOBJECT);
+  Nobject = 0;
+  N0 = catstats[0].N;
+
+  NROCKS = 3000;
+  ALLOCATE (rocks, Rocks, NROCKS);
+  Nrocks = 0;
+
+  Tref = 0;
+  NotRock = (ID_ROCK ^ 0xffff);
+  IsProper = ID_USNO | ID_PROPER;
+  for (i = 0; i < Nstar; i++) {
+    N = N0[i];
+    if (RESET && ((catalog[0].average[N].code & ID_ROCK) == ID_ROCK)) {
+      /* resets both relevant bits */
+      catalog[0].average[N].code &= NotRock;
+    }
+    if (RESET && (catalog[0].average[N].code == ID_COSMIC)) {
+      /* resets both relevant bits */
+      catalog[0].average[N].code = 0;
+    }
+    /* accept a measurement if it is either unmarked or marked as a proper motion star */
+    if ((catalog[0].average[N].Nm == 1) && (catalog[0].average[N].Nn > 0) && ((catalog[0].average[N].code == 0) || ((catalog[0].average[N].code & IsProper) == IsProper))) {
+      if (Tref == 0) Tref = catalog[0].measure[catalog[0].average[N].offset].t;
+      X1[Nobject] = catstats[0].X[i];
+      Y1[Nobject] = catstats[0].Y[i];
+      if (catalog[0].measure[catalog[0].average[N].offset].t > Tref) 
+	T1[Nobject] = catalog[0].measure[catalog[0].average[N].offset].t - Tref;
+      else {
+	Ttmp = Tref - catalog[0].measure[catalog[0].average[N].offset].t;
+	T1[Nobject] = -Ttmp;
+      }      
+      N1[Nobject] = N;
+      Nobject ++;
+      if (Nobject == NOBJECT - 1) {
+	NOBJECT += 1000;
+	REALLOCATE (X1, double, NOBJECT);
+	REALLOCATE (Y1, double, NOBJECT);
+	REALLOCATE (T1, int, NOBJECT);
+	REALLOCATE (N1, int,   NOBJECT);
+      }
+    }
+  }
+  REALLOCATE (X1, double, Nobject);
+  REALLOCATE (Y1, double, Nobject);
+  REALLOCATE (T1, int, Nobject);
+  REALLOCATE (N1, int,   Nobject);
+  if (Nobject > 1) sort_set (X1, Y1, T1, N1, Nobject);
+
+  fprintf (stderr, "Nobj: %d\n", Nobject);
+
+  MaxSeparation = MAX_SPEED * MAX_DELAY;
+  fprintf (stderr, "%f %f %f %f %f\n", MaxSeparation, MAX_RADIUS, RADIUS, MAX_SPEED, MAX_DELAY);
+
+  /** find 3 rocks in a line **/
+  for (i = 0; i < Nobject - 2; i++) {
+    fprintf (stderr, ".");
+    for (j = i + 1; j < Nobject - 1; j++) {
+      if (X1[j] - X1[i] > MaxSeparation) goto NEXTi;
+      if (X1[i] - X1[j] > MaxSeparation) goto NEXTj;
+      if (T1[i] == T1[j]) continue;
+      dt = (int)(T1[j] - T1[i]);
+      if (fabs(dt) > MAX_DELAY) continue;
+      ax = (X1[j] - X1[i])/dt;
+      cx = (X1[i]*T1[j] - X1[j]*T1[i])/dt;
+      ay = (Y1[j] - Y1[i])/dt;
+      cy = (Y1[i]*T1[j] - Y1[j]*T1[i])/dt;
+      speed = hypot (ax, ay);
+      if (speed > MAX_SPEED) continue;
+      for (k = j + 1; k < Nobject; k++) {
+	if (X1[k] - X1[j] > MaxSeparation) goto NEXTj;
+	if (X1[j] - X1[k] > MaxSeparation) goto NEXTk;
+	if (T1[i] == T1[k]) continue;
+	if (T1[j] == T1[k]) continue;
+	dt1 = fabs(dt);
+	dt2 = fabs ((int)(T1[i] - T1[k]));
+	dt3 = fabs ((int)(T1[j] - T1[k]));
+	dt1 = MIN(MIN(dt1,dt2),dt3);
+	dt3 = MAX(MAX(dt1,dt2),dt3);
+	if (fabs(dt3) > MAX_DELAY) continue;
+	/* errors are too large by this point */
+	if (RADIUS * dt3 / dt1 > MAX_RADIUS) continue; 
+	dX1 = T1[k]*ax - X1[k] + cx;
+	dX2 = T1[k]*ay - Y1[k] + cy;
+	distance = hypot (dX1, dX2);
+	/*
+        fprintf (stderr, "%d %d %d %f %f %d %f %f\n", i, j, k, ax, cx, T1[k], X1[k], dX1);
+	if (k > 100) exit (0);
+	*/
+	if (distance < RADIUS){
+	  catalog[0].average[N1[i]].code |= ID_ROCK;
+	  catalog[0].average[N1[j]].code |= ID_ROCK;
+	  catalog[0].average[N1[k]].code |= ID_ROCK;
+
+	  rocks[Nrocks].X[0]     = X1[i];
+	  rocks[Nrocks].Y[0]     = Y1[i];
+	  rocks[Nrocks].ra[0]    = catalog[0].average[N1[i]].R;
+	  rocks[Nrocks].dec[0]   = catalog[0].average[N1[i]].D;
+
+	  m = catalog[0].average[N1[i]].offset;
+	  rocks[Nrocks].mag[0]   = PhotRel (&catalog[0].measure[m], &photcodes, ZERO_POINT);
+	  rocks[Nrocks].t[0]     = catalog[0].measure[m].t;
+
+	  rocks[Nrocks].X[1]     = X1[j];
+	  rocks[Nrocks].Y[1]     = Y1[j];
+	  rocks[Nrocks].ra[1]    = catalog[0].average[N1[j]].R;
+	  rocks[Nrocks].dec[1]   = catalog[0].average[N1[j]].D;
+
+	  m = catalog[0].average[N1[j]].offset;
+	  rocks[Nrocks].mag[1]   = PhotRel (&catalog[0].measure[m], &photcodes, ZERO_POINT);
+	  rocks[Nrocks].t[1]     = catalog[0].measure[m].t;
+
+	  rocks[Nrocks].X[2]     = X1[k];
+	  rocks[Nrocks].Y[2]     = Y1[k];
+	  rocks[Nrocks].ra[2]    = catalog[0].average[N1[k]].R;
+	  rocks[Nrocks].dec[2]   = catalog[0].average[N1[k]].D;
+
+	  m = catalog[0].average[N1[k]].offset;
+	  rocks[Nrocks].mag[2]   = PhotRel (&catalog[0].measure[m], &photcodes, ZERO_POINT);
+	  rocks[Nrocks].t[2]     = catalog[0].measure[m].t;
+
+	  fprintf (stderr, "*");
+	  Nrocks ++;
+	  if (Nrocks >= NROCKS) {
+	    NROCKS += 3000;
+	    REALLOCATE (rocks, Rocks, NROCKS);
+	  }
+	}
+      NEXTk:
+      }
+    NEXTj:
+    }
+    gettimeofday (&now, (void *) NULL);
+    dtime = (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec);
+    if (dtime > 200) {
+      fprintf (stderr, "taking too long to find all rocks, giving up...\n");
+      goto escape_loop;
+    }
+  NEXTi:
+  }
+
+escape_loop:
+  for (i = 0; i < Nobject; i++) {
+    if ((catalog[0].average[N1[i]].code == 0) && (catalog[0].average[N1[i]].Nn >= 2)) {
+      catalog[0].average[N1[i]].code = ID_COSMIC;
+    }
+  }
+
+  fprintf (stderr, "found %d rocks\n", Nrocks);
+
+  free (T1);
+  free (X1);
+  free (Y1);
+  free (N1);
+
+  REALLOCATE (rocks, Rocks, MAX (1, Nrocks));
+  *nrocks = Nrocks;
+  return (rocks);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/find_slow_rocks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/find_slow_rocks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/find_slow_rocks.c	(revision 16632)
@@ -0,0 +1,135 @@
+# include "markrock.h"
+
+Rocks *find_slow_rocks (catalog, catstats, nrocks)
+Catalog catalog[];
+CatStats catstats[];
+int *nrocks;
+{
+
+  int i, j, k, m, N, Nm, NOBJECT, Nobject, Nrocks, NROCKS;
+  double RADIUS2;
+  double *R1, *D1, *X1, *Y1, *M1;
+  double R, D, X, Y, M;
+  double dX, dY, dR;
+  int *N1, *N0;
+  unsigned int *T1, T;
+  int Nstar, Nghost, Ng, Nmax;
+  unsigned int flags;
+  Coords *tcoords;
+  double ax, ay, cx, cy, dt, dX1, dX2, speed, distance;
+  Rocks *rocks;
+  unsigned short IsProper;
+
+  Nstar = catalog[0].Naverage;
+
+  NOBJECT = 1000;
+  ALLOCATE (N1, int,   NOBJECT);
+  Nobject = 0;
+  N0 = catstats[0].N;
+
+  NROCKS = 3000;
+  ALLOCATE (rocks, Rocks, NROCKS);
+  Nrocks = 0;
+
+  Nmax = 0;
+  IsProper = ID_USNO | ID_PROPER;
+  for (i = 0; i < Nstar; i++) {
+    N = N0[i];
+    /* accept a measurement if it is either unmarked or marked as a proper motion star and may have multiple measurements */
+    if ((catalog[0].average[N].code == 0) || (catalog[0].average[N].code & IsProper == IsProper)) {
+      Nmax = MAX (catalog[0].average[N].Nm, Nmax);
+      N1[Nobject] = N;
+      Nobject ++;
+      if (Nobject == NOBJECT - 1) {
+	NOBJECT += 1000;
+	REALLOCATE (N1, int,   NOBJECT);
+      }
+    }
+  }
+  REALLOCATE (N1, int,   Nobject);
+  fprintf (stderr, "Nobj: %d\n", Nobject);
+
+  ALLOCATE (R1, double, Nmax);
+  ALLOCATE (D1, double, Nmax);
+  ALLOCATE (X1, double, Nmax);
+  ALLOCATE (Y1, double, Nmax);
+  ALLOCATE (T1, unsigned int, Nmax);
+  ALLOCATE (M1, double, Nmax);
+  /** find multiple measured objects, find additional measurements along that line */
+
+  for (i = 0; i < Nobject; i++) {
+    fprintf (stderr, ",");
+    if (catalog[0].average[N1[i]].Nm > 1) {
+      N = N1[i];
+      Nm = catalog[0].average[N].Nm;
+      m = catalog[0].average[N].offset;
+      for (j = 0; j < 2; j++) {
+	R1[j] = catalog[0].average[N].R - catalog[0].measure[m+j].dR/360000.0;
+	D1[j] = catalog[0].average[N].D - catalog[0].measure[m+j].dD/360000.0;
+	RD_to_XY (&X1[j], &Y1[j], R1[j], D1[j], &catstats[0].coords);
+	T1[j] = catalog[0].measure[m+j].t;
+	M1[j] = catalog[0].measure[m+j].M - catalog[0].measure[m+j].Mcal;
+      }
+      dt = T1[1] - T1[0];
+      ax = (X1[1] - X1[0])/dt;
+      cx = (X1[0]*T1[1] - X1[1]*T1[0])/dt;
+      ay = (Y1[1] - Y1[0])/dt;
+      cy = (Y1[0]*T1[1] - Y1[1]*T1[0])/dt;
+      speed = hypot (ax, ay);
+      for (k = 0; k < Nobject; k++) {
+	N = N1[k];
+	Nm = catalog[0].average[N].Nm;
+	m = catalog[0].average[N].offset;
+	for (j = 0; j < Nm; j++) {
+	  R = catalog[0].average[N].R - catalog[0].measure[m+j].dR/360000.0;
+	  D = catalog[0].average[N].D - catalog[0].measure[m+j].dD/360000.0;
+	  RD_to_XY (&X, &Y, R, D, &catstats[0].coords);
+	  T = catalog[0].measure[m+j].t;
+	  M = catalog[0].measure[m+j].M - catalog[0].measure[m+j].Mcal;
+	  if (T1[0] == T) continue;
+	  if (T1[1] == T) continue;
+	  dX1 = T*ax - X + cx;
+	  dX2 = T*ay - Y + cy;
+	  distance = hypot (dX1, dX2);
+	  if (distance < RADIUS){
+	    catalog[0].average[N1[i]].code |= ID_ROCK;
+	    catalog[0].average[N1[k]].code |= ID_ROCK;
+	    rocks[Nrocks].ra    = R1[0];
+	    rocks[Nrocks].dec   = D1[0];
+	    rocks[Nrocks].mag   = M1[0];
+	    rocks[Nrocks].t     = T1[0];
+	    rocks[Nrocks+1].ra  = R1[1];
+	    rocks[Nrocks+1].dec = D1[1];
+	    rocks[Nrocks+1].mag = T1[1];
+	    rocks[Nrocks+1].t   = M1[1];
+	    rocks[Nrocks+2].ra  = R;
+	    rocks[Nrocks+2].dec = D;
+	    rocks[Nrocks+2].mag = M;
+	    rocks[Nrocks+2].t   = T;
+	    fprintf (stderr, "%f %f %f %d   %f\n", rocks[Nrocks].ra, rocks[Nrocks].dec, rocks[Nrocks].mag, rocks[Nrocks].t, speed);
+	    Nrocks += 3;
+	    if (Nrocks > NROCKS - 3) {
+	      NROCKS += 3000;
+	      REALLOCATE (rocks, Rocks, NROCKS);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "found %d rocks\n", Nrocks);
+
+  free (R1);
+  free (D1);
+  free (M1);
+  free (T1);
+  free (X1);
+  free (Y1);
+  free (N1);
+
+  REALLOCATE (rocks, Rocks, Nrocks);
+  *nrocks = Nrocks;
+  return (rocks);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/gcatstats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/gcatstats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/gcatstats.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "markrock.h"
+
+gcatstats (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  double *X1, *Y1;
+  int *N1;
+  Coords tcoords;
+  
+  gfits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  gfits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  gfits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  gfits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+ /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+  /* number of stars per square arcsec */
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, double, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, double, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    fRD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, &catstats[0].coords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_coords_index (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/markrock.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/markrock.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/markrock.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "markrock.h"
+
+main (int argc, char **argv) {
+  
+  int i, Nrocks1, Nrocks2;
+  Catalog catalog;
+  CatStats catstats;
+  Rocks *rocks1, *rocks2, *find_rocks(), *find_slow_rocks();
+  struct timeval now, then;  
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (&argc, argv);
+  
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  FORCE_RUN = FALSE;
+  if ((i = get_argument (argc, argv, "-f"))) {
+    FORCE_RUN = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: markstar (catalog)\n");
+    exit (0);
+  }
+
+  /* if lockfile exists, program will complain and quit */
+  if (!check_file_access (argv[1], TRUE, TRUE)) exit (1);
+  if (!check_file_access (RockCat, TRUE, TRUE)) exit (1);
+
+  catalog.filename = argv[1];
+  catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+  catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "a")) {
+    fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+    exit (2);
+  }
+  if (catalog.Naves_disk) {
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+    continue;
+  }
+
+  gcatstats (&catalog, &catstats);
+
+  find_bright_stars (&catalog, &catstats); 
+
+  rocks1 = find_rocks (&catalog, &catstats, &Nrocks1); 
+  count_neighbors (rocks1, Nrocks1, &catalog, &catstats);
+
+  /* rocks2 = find_slow_rocks (&catalog, &catstats, &Nrocks2);  */
+  dvo_catalog_save (&catalog, VERBOSE);
+  dvo_catalog_unlock (&catalog);
+  dvo_catalog_free (&catalog);
+
+  wrocks (rocks1, Nrocks1);
+  /* wrocks (rocks2, Nrocks2); */
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/sorts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/sorts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/sorts.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "markrock.h"
+
+void sort_set (double *X, double *Y, int *T, int *S, int N) {
+
+# define SWAPFUNC(A,B){ double dtmp; int itmp; \
+  dtmp = X[A]; X[A] = X[B]; X[B] = dtmp; \
+  dtmp = Y[A]; Y[A] = Y[B]; Y[B] = dtmp; \
+  itmp = T[A]; T[A] = T[B]; T[B] = itmp; \
+  itmp = S[A]; S[A] = S[B]; S[B] = itmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
Index: /branches/eam_branch_20080223/Ohana/src/markrock/src/wrocks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markrock/src/wrocks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markrock/src/wrocks.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "markrock.h"
+
+wrocks (Rocks *rocks, int Nrocks) {
+  
+  int i, j;
+  FILE *f;
+  double X, Y, t, dSx, dSy, dS, speed;
+  double Sx, Sy, Sxt, Syt, St, St2, Sn;
+  double Mx, Bx, My, By, D;
+  unsigned int Tref;
+
+  f = fopen (RockCat, "a+");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't create/open rock catalog file: %s\n", RockCat);
+    exit (0);
+  }
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_END);
+
+  /* get statistics on rocks */
+
+  for (i = 0; i< Nrocks; i++) {
+    /* fit a line to the three points, the ask for the scatter about the solution */
+    Tref = rocks[i].t[0];
+    Sx = Sy = Sxt = Syt = St = St2 = Sn = 0;
+    for (j = 0; j < 3; j++) {
+      X = rocks[i].X[j];
+      Y = rocks[i].Y[j];
+      if (rocks[i].t[j] > Tref) 
+	t = rocks[i].t[j] - Tref;
+      else
+	t = -1*((double)(Tref - rocks[i].t[j]));
+      Sx  += X;
+      Sy  += Y;
+      Sxt += X*t;
+      Syt += Y*t;
+      St  += t;
+      St2 += t*t;
+      Sn  += 1;
+    }
+    D = St2*Sn - St*St;
+    My = (Syt*Sn - Sy*St) / D;
+    By = (Sy*St2 - Syt*St) / D;
+    Mx = (Sxt*Sn - Sx*St) / D;
+    Bx = (Sx*St2 - Sxt*St) / D;
+    
+    dS = 0;
+    for (j = 0; j < 3; j++) {
+      X = rocks[i].X[j];
+      Y = rocks[i].Y[j];
+      if (rocks[i].t[j] > Tref) 
+	t = rocks[i].t[j] - Tref;
+      else 
+	t = -1*((double)(Tref - rocks[i].t[j]));
+      dSx = (Mx*t + Bx - X);
+      dSy = (My*t + By - Y);
+      dS += dSx*dSx + dSy*dSy;
+    }
+    dS = sqrt (dS/3);
+    speed = hypot (Mx, My);
+    fprintf (f, "%5.2f %9.4e ", dS, speed);
+    for (j = 0; j < 3; j++) {
+      fprintf (f, "%10d %10.6f %10.6f %6.3f ", rocks[i].t[j], rocks[i].ra[j], rocks[i].dec[j], rocks[i].mag[j]);
+    }
+    /* fprintf (f, "%3d %3d %3d\n", rocks[i].N[0], rocks[i].N[1], rocks[i].N[2]); */
+    fprintf (f, "\n");
+  }
+  fclose (f);
+  
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/markstar/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/Makefile	(revision 16632)
@@ -0,0 +1,37 @@
+default: markstar
+help:
+	@echo "make options: markstar (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/markstar
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+markstar: $(BIN)/markstar.$(ARCH)
+install: $(DESTBIN)/markstar
+
+MARKSTAR = \
+$(SRC)/markstar.$(ARCH).o 	$(SRC)/gcatalog.$(ARCH).o   \
+$(SRC)/coordops.$(ARCH).o	$(SRC)/sorts.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/check_lockfile.$(ARCH).o \
+$(SRC)/find_trails.$(ARCH).o	$(SRC)/find_group.$(ARCH).o \
+$(SRC)/find_line.$(ARCH).o	$(SRC)/mark_trail.$(ARCH).o \
+$(SRC)/load_gsc_data.$(ARCH).o	$(SRC)/find_bright_stars.$(ARCH).o \
+$(SRC)/wcatalog.$(ARCH).o	$(SRC)/find_images.$(ARCH).o	\
+$(SRC)/load_gsc_data_ghost.$(ARCH).o	$(SRC)/find_ghosts.$(ARCH).o \
+$(SRC)/gcatstats.$(ARCH).o	$(SRC)/match_images.$(ARCH).o	\
+$(SRC)/gregions.$(ARCH).o	$(SRC)/aregion.$(ARCH).o	\
+$(SRC)/find_matches.$(ARCH).o	$(SRC)/check_permissions.$(ARCH).o
+
+$(MARKSTAR): $(INC)/markstar.h
+$(BIN)/markstar.$(ARCH): $(MARKSTAR)
Index: /branches/eam_branch_20080223/Ohana/src/markstar/doc/example.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/doc/example.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/doc/example.txt	(revision 16632)
@@ -0,0 +1,13 @@
+
+rats: foreach f ( */*.cpt )
+foreach? echo $f
+foreach? echo $f >> bright.log
+foreach? (markstar -v $f >> bright.dat) >>& bright.log
+foreach? end
+
+
+
+ echo $f
+ echo $f >> bright.log
+ (markstar -v $f >> bright.dat) >>& bright.log
+ end
Index: /branches/eam_branch_20080223/Ohana/src/markstar/doc/process.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/doc/process.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/doc/process.txt	(revision 16632)
@@ -0,0 +1,69 @@
+
+hi chad,
+
+the process i use is a bit complex, but makes some reasonable
+comprimises about distance between points in a line and processing
+time.  
+
+First, the process I am about to describe is run on every "star" in
+the image.  However, the whole process gets speeded up in part because
+entries which are known stars can be ignored and entries which are
+already identified as part of a line associated with an earlier entry
+get ignored as well.  In fact, this step is done for a new part of the
+sky before the USNO stars are identified without much reduction in the
+processing speed, so the fact that you don't identify fixed stars in
+your data should not really be an issue.
+
+In the following, I use the term "star" to mean any detected object
+in the image frame.
+
+So, let me now discuss the process for a given test star, call it
+S(0).  
+
+The first step is to find likely directions with trails.  I first look
+at all other stars within a specific radius (say 100") around that
+star, call them S(i).  For each star S(i), I find the angle between
+S(i) and S(0).  I accumulate a histogram of these angles, a bin size
+of say a degree. (Note, both the Radius and the BinSize should be
+parameters that might change depending on the density of stars).  If
+any of the angle bins have a significant number of entries, then this
+is the likely direction of a trail.  There are three things to note
+about this process.  First, it makes processing the lists much quicker
+if you have the stars sorted by X or Y (or RA or DEC) and use that
+information in your search for the stars within 100".  Second, I
+define a significance cutoff for an angle bin based on the density of
+stars in the field (this is a useful parameter for all of the
+comparisons I discuss).  Once any of the angle bins surpasses the
+significance criterion, I stop searching around this test star and
+just work on the identified angle.  I assume that if the test star
+just happens to lie at the intersection of two lines, the other line
+will be identified by another test star.  Finally, the angle histogram
+only needs to run from 0 to 180, and angles in the range 180 to 360
+should be reflected back into the first half to increase the number
+statistics.  In general, your test star will be somewhere in the
+middle of a line.
+
+Once an angle of interest is found, I fit a line to all of the points
+in that angle bin, then narrow down improve the fit by refitting to
+all points within a fixed distance of the line.  You can itereate on
+the second step if the line is not well determined the first time
+around.  One point of interest:  for the line fits, if the angle of
+the line is 0 - 45 deg, I fit the line Y = mX + b, but if the angle is
+45 - 90 deg, I fit the line X = mY + b, to keep the slope near 1.  
+
+Once I have a good fit to a line, I try to decide if the line is
+really a trail or if it is just a coincidence of points.  I demand 
+both a minimum linear density of points in the line (related to the
+density of stars in the frame) and a minimum number of points in the
+line.  Another thing to watch out for is including points well beyond
+the end of the line which just happen to lie along the line.  I demand
+that the distance between points be less than some distance related to
+the linear density.  
+
+I hope this is a helpful description.  The routine I run is quite
+quick.  It takes about 10 seconds for a 1 degree region (about 10,000
+real stars) to do the line search, the bright star wings, and the
+search for ghosts on a 300 MHz Pentium II.  
+
+good luck
+gene
Index: /branches/eam_branch_20080223/Ohana/src/markstar/include/markstar.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/include/markstar.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/include/markstar.h	(revision 16632)
@@ -0,0 +1,46 @@
+# include <ohana.h>
+# include <dvo.h>
+
+int    VERBOSE;
+int    RESET;
+int    FORCE_RUN;
+
+/* global variables set in parameter file */
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+
+char   GSCDIR[256];
+char   ImageCat[256];
+char   GSCFILE[256];
+
+double RADIUS;
+double TRAIL_WIDTH;
+int    NBINS;
+int    NPTSINLINE;
+double MIN_DENSITY;
+double NSIGMA;
+
+double BRIGHT_HALO_MAG;
+double BRIGHT_HALO_SLOPE;
+double BRIGHT_XTRAIL_WIDTH;
+double BRIGHT_XTRAIL_MAG;
+double BRIGHT_XTRAIL_SLOPE;
+double BRIGHT_YTRAIL_WIDTH;
+double BRIGHT_YTRAIL_MAG;
+double BRIGHT_YTRAIL_SLOPE;
+
+double GHOST_MAG;
+double GHOST_RADIUS;
+double OPTICAL_AXIS1;
+double OPTICAL_AXIS2;
+
+typedef struct {
+  Coords coords;
+  double *X, *Y;
+  int *N;
+  double RA[2], DEC[2];
+  double Area, density, spacing;
+} CatStats;
+
+PhotCodeData photcodes;
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "markstar.h"
+
+ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  /* used in other pipeline functions */
+  ScanConfig (config, "CATDIR",          "%s",  0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  ScanConfig (config, "GSCDIR",          "%s",  0, GSCDIR);
+  ScanConfig (config, "GSCFILE",         "%s",  0, GSCFILE);
+  /* unique to markstar */
+  ScanConfig (config, "SEARCH_RADIUS",   "%lf", 0, &RADIUS);
+  ScanConfig (config, "TRAIL_WIDTH",     "%lf", 0, &TRAIL_WIDTH);
+  ScanConfig (config, "NANGLE_BINS",     "%d",  0, &NBINS);
+  ScanConfig (config, "NPTSINLINE",      "%d",  0, &NPTSINLINE);
+  ScanConfig (config, "MIN_DENSITY",     "%lf", 0, &MIN_DENSITY);
+  ScanConfig (config, "SPACE_SIGMA",     "%lf", 0, &NSIGMA); 
+
+  ScanConfig (config, "BRIGHT_HALO_MAG",     "%lf", 0, &BRIGHT_HALO_MAG);
+  ScanConfig (config, "BRIGHT_HALO_SLOPE",   "%lf", 0, &BRIGHT_HALO_SLOPE);
+  ScanConfig (config, "BRIGHT_XTRAIL_WIDTH", "%lf", 0, &BRIGHT_XTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_XTRAIL_MAG",   "%lf", 0, &BRIGHT_XTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_XTRAIL_SLOPE", "%lf", 0, &BRIGHT_XTRAIL_SLOPE);
+  ScanConfig (config, "BRIGHT_YTRAIL_WIDTH", "%lf", 0, &BRIGHT_YTRAIL_WIDTH);
+  ScanConfig (config, "BRIGHT_YTRAIL_MAG",   "%lf", 0, &BRIGHT_YTRAIL_MAG);
+  ScanConfig (config, "BRIGHT_YTRAIL_SLOPE", "%lf", 0, &BRIGHT_YTRAIL_SLOPE);
+
+  ScanConfig (config, "GHOST_MAG",       "%lf", 0, &GHOST_MAG);
+  ScanConfig (config, "GHOST_RADIUS",    "%lf", 0, &GHOST_RADIUS);
+  ScanConfig (config, "OPTICAL_AXIS1",   "%lf", 0, &OPTICAL_AXIS1);
+  ScanConfig (config, "OPTICAL_AXIS2",   "%lf", 0, &OPTICAL_AXIS2);
+ 
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+}
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/find_bright_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/find_bright_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/find_bright_stars.c	(revision 16632)
@@ -0,0 +1,140 @@
+# include "markstar.h"
+
+void find_bright_stars (Catalog *catalog, CatStats *catstats) {
+
+  int i, j, n, m, first_j, Nave, Ngsc;
+  Catalog GSCdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  double *X1, *Y1, *X2, *Y2;
+  int *N1, *N2;
+  char *mark;
+  double dX, dY, dR, MaxDist, MaxDist1, MaxRadius, radius, radius2;
+
+  // put limits on the ref catalog mags
+  load_gsc_data (&GSCdata, catstats);
+
+  Nave = catalog[0].Naverage;
+  Ngsc = GSCdata.Naverage;
+    
+  /* in the function below, it is better to have the catalog with
+     more stars associated with index 2 (j) */ 
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+  ALLOCATE (X1, double, Ngsc);
+  ALLOCATE (Y1, double, Ngsc);
+  ALLOCATE (N1, int, Ngsc);
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Ngsc; i++) {
+    RD_to_XY (&X1[i], &Y1[i], GSCdata.average[i].R, GSCdata.average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Ngsc > 1) sort_coords_index (X1, Y1, N1, Ngsc);
+  
+  /* first find stellar halos */
+  /* max radius (mag = -1) */
+  /** the j index moves quickly and is better associated with the catalog with more stars */
+  MaxRadius = BRIGHT_HALO_SLOPE * (-1.0 - BRIGHT_HALO_MAG); 
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*MaxRadius) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*MaxRadius) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    radius = MAX (BRIGHT_HALO_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_HALO_MAG), 0.0);
+    if (radius == 0) {
+      i++; 
+      continue;
+    }
+    radius2 = radius*radius;
+    for (; (dX > -2*radius) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < radius2) {  /* new measurement of this star */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find y spikes */
+  /** find catalog stars near GSC stars **/
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -BRIGHT_YTRAIL_WIDTH) {
+      i++;
+      continue;
+    }
+    if (dX >= BRIGHT_YTRAIL_WIDTH) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist = MAX (BRIGHT_YTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_YTRAIL_MAG), 0.0);
+    for (; (dX > -BRIGHT_YTRAIL_WIDTH) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dX) < BRIGHT_YTRAIL_WIDTH) && (fabs(dY) < MaxDist)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+  
+  /* next find x spikes */
+  /** find catalog stars near GSC stars **/
+  MaxDist = MAX (BRIGHT_XTRAIL_SLOPE * (-1.0 - BRIGHT_XTRAIL_MAG), 0.0);
+  for (i = j = 0; (i < Ngsc) && (j < Nave); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -MaxDist) {
+      i++;
+      continue;
+    }
+    if (dX >= MaxDist) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    MaxDist1 = MAX (BRIGHT_XTRAIL_SLOPE * (0.001*GSCdata.average[N1[i]].M - BRIGHT_XTRAIL_MAG), 0.0);
+    for (; (dX > -MaxDist1) && (j < Nave); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      if ((fabs(dY) < BRIGHT_XTRAIL_WIDTH) && (fabs(dX) < MaxDist1)) {  /* star on spike */
+	mark[j] = TRUE;
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  /* done with search, mark selected stars */
+  for (i = 0; i < Nave; i++) {
+    if (mark[i]) {
+      catalog[0].average[N2[i]].code = ID_BLEED;
+    }
+  } 
+  
+  free (X1);
+  free (Y1);
+  free (N1);
+  free (mark);
+  free (GSCdata.average);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/find_ghosts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/find_ghosts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/find_ghosts.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "markstar.h"
+
+find_ghosts (catalog, catstats, filename, image, Nimage)
+Catalog catalog[];
+CatStats catstats[];
+char *filename;
+Image image[];
+int Nimage;
+{
+
+  int i, j, first_j, Nave, Ngsc, Nregions;
+  Catalog GSCdata, Ghostdata;
+  double MinRA, MinDEC, MaxRA, MaxDEC, RaCenter, DecCenter;
+  Coords *tcoords;
+  float *X1, *Y1, *X2, *Y2;
+  int *N1, *N2, *match;
+  char *mark;
+  double dX, dY, dR, RADIUS2, BRIGHT_RADIUS, radius, X, Y, R, D;
+  Image timage;
+  GSCRegion *region, *gregions2();
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* coords structure for ghost image */
+    timage = image[i];
+    timage.coords.cdelt1 = -1*image[i].coords.cdelt1;
+    timage.coords.cdelt2 = -1*image[i].coords.cdelt2;
+    timage.coords.crpix1 = 2*OPTICAL_AXIS1 - image[i].coords.crpix1;
+    timage.coords.crpix2 = 2*OPTICAL_AXIS2 - image[i].coords.crpix2;
+
+    region = gregions2 (&timage, &Nregions);
+    
+    /* find ghost stars */
+    // put limits on the ref catalog mags
+    load_gsc_data_ghost (&GSCdata, region, Nregions, &timage);
+
+    /* refect ghost stars to find locations of ghosts */
+    ALLOCATE (Ghostdata.average, Average, MAX (GSCdata.Naverage, 1));
+    for (j = 0; j < GSCdata.Naverage; j++) {
+      RD_to_XY (&X, &Y, GSCdata.average[j].R, GSCdata.average[j].D, &timage);
+      fXY_to_RD (&Ghostdata.average[j].R, &Ghostdata.average[j].D, X, Y, &image[i]);
+      Ghostdata.average[j].M = GSCdata.average[j].M;
+    }    
+    Ghostdata.Naverage = GSCdata.Naverage;
+
+    /* match ghosts and image stars, mark ghosts */
+    find_matches (catalog, catstats, &Ghostdata, i);
+
+    free (Ghostdata.average);
+    free (GSCdata.average);
+  }
+
+}
+
+/* 
+
+   just to be clear on some of the terms:
+
+   the "ghost" is the fuzzy patch of light on an image caused by
+     a reflected star
+
+   the "ghost star" is the star in the sky which causes a ghost
+
+   the "ghost image" is the image location on the sky 
+     where ghost stars may come from.
+
+   the "image stars" are observed stars at the location of the
+     ghost - these are detections of the ghost
+
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/find_group.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/find_group.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/find_group.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "markstar.h"
+
+find_group (catstats, mark, Npts, i, ANGLE)
+     CatStats catstats[];
+     double *ANGLE;
+     int i, Npts;
+     char *mark;
+{
+ 
+  float *R, *D;
+  int j, N, bin, Ndegbin;
+  unsigned short int *A;
+  double Ra, De, dR, dD, angle, limit;
+
+   /* assign some parameter values */
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  Ndegbin = NBINS / 180.0;
+  ALLOCATE (A, unsigned short int, NBINS + 1)
+  bzero (A, (NBINS+1)*sizeof(short));
+
+  /* look for points concentrated in an angle bin */
+  if (mark[i]) return (FALSE);
+  Ra = R[i];
+  De = D[i];
+  N = 0;
+  /* points east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;  /* only NaN if dD = dR = 0 */
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;
+      N ++;
+    }
+  }
+  /* points west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      bin = angle*DEG_RAD*Ndegbin;
+      A[bin] ++;	
+      N ++;
+    }
+  }
+  limit = NSIGMA*sqrt((double)(N)/(double)(NBINS));
+  for (j = 0; j < NBINS; j++) {
+    if (A[j] > limit) {
+      *ANGLE = j / (DEG_RAD*Ndegbin);
+      return (TRUE);
+    }
+  }
+  return (FALSE);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/find_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/find_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/find_images.c	(revision 16632)
@@ -0,0 +1,177 @@
+# include "markstar.h"
+double opening_angle ();
+
+Image *find_images (FITS_DB *db, CatStats *catstats, int *Nimages) {
+  
+  Header header;
+  Image *timage, *image;
+  int i, j, k, found, nimage, Nimage, NIMAGE, NTIMAGE, Nloop, Nlast;
+  int n, Nim, status, InRange;
+  FILE *f;
+  double Xc[6], Yc[6], Xi[6], Yi[6], r, d, x, y, dx, dy;
+  Coords *tcoords;
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords = &catstats[0].coords;
+  /* define catalog corners */
+  Xc[0] = catstats[0].RA[0]; Yc[0] = catstats[0].DEC[0];
+  Xc[1] = catstats[0].RA[1]; Yc[1] = catstats[0].DEC[0];
+  Xc[2] = catstats[0].RA[1]; Yc[2] = catstats[0].DEC[1];
+  Xc[3] = catstats[0].RA[0]; Yc[3] = catstats[0].DEC[1];
+  Xc[4] = catstats[0].RA[0]; Yc[4] = catstats[0].DEC[0];
+  for (j = 0; j < 5; j++) {
+    r = Xc[j]; d = Yc[j];
+    RD_to_XY (&Xc[j], &Yc[j], r, d, tcoords);
+  }
+
+  timage = gfits_table_get_Image (&db[0].ftable, &Ntimage, &db[0].swapped);
+
+  /* set up buffers for images, temporary storage */
+  nimage = 0;
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+
+  /* test each image in block */
+  for (i = 0; i < Ntimage; i++) {
+    /* define image corners */
+    Xi[0] = 0;            Yi[0] = 0;
+    Xi[1] = timage[i].NX; Yi[1] = 0;
+    Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+    Xi[3] = 0;            Yi[3] = timage[i].NY;
+    Xi[4] = 0;            Yi[4] = 0;
+    found = FALSE;
+    /* transform to tcoords */
+    if (catstats[0].DEC[1] > 86.25) { /* pole */
+      for (j = 0; j < 5; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	if (d > catstats[0].DEC[0] - 0.5) found = TRUE;
+      }
+    } else {
+      for (j = 0; j < 6; j++) {
+	XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+	InRange = RD_to_XY (&Xi[j], &Yi[j], r, d, tcoords);
+	if (!InRange) {
+	  /* if RD_to_XY returns false, the coords are ~180 away from
+	     the projection center */ 
+	  goto imskip;
+	}
+      }
+      /* check if image corner inside catalog */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xi[j], &Yi[j], &Xc[0], &Yc[0]);
+      }
+      /* check if catalog corner inside image */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xc[j], &Yc[j], &Xi[0], &Yi[0]);
+      }
+      /* check if edges cross */
+      for (j = 0; (j < 4) && !found; j++) {
+	for (k = 0; (k < 4) && !found; k++) {
+	  found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	}
+      }
+    }
+    if (found) {
+      image[nimage] = timage[i]; 
+      image[nimage].code = 0;
+      nimage ++;
+      if (nimage == NIMAGE) {
+	NIMAGE += 100;
+	REALLOCATE (image, Image, NIMAGE);
+      }
+    }
+  imskip:
+  }
+      
+  if (VERBOSE) { 
+    for (i = 0; i < nimage; i++) {
+      XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+      fprintf (stderr, "associated images: %d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	       i, r, d, image[i].tzero, image[i].nstar, 0.001*image[i].secz, 
+	       0.001*image[i].Mcal, 0.001*image[i].dMcal);
+    }
+  }
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  *Nimages = nimage;
+  return (image);
+}
+
+int edge_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/* returns the opening angle between the three points (2 is in middle) 
+   in range -pi to pi */
+double opening_angle (x1, y1, x2, y2, x3, y3)
+double x1, y1, x2, y2, x3, y3;
+{
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
+/* check if point x1,y1 is in box formed by x2[0-4] */
+int corner_check (x1, y1, x2, y2)
+double *x1, *y1, *x2, *y2;
+{
+
+  int i;
+  double theta;
+
+  theta = 0;
+
+  for (i = 0; i < 4; i++) {
+    theta += opening_angle (x2[i], y2[i], x1[0], y1[0], x2[i+1], y2[i+1]); 
+  }
+  if (fabs(theta) > 6) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/find_line.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/find_line.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/find_line.c	(revision 16632)
@@ -0,0 +1,161 @@
+# include "markstar.h"
+
+find_line (catstats, mark, Npts, i, M, B, Angle)
+     CatStats catstats[];
+     double *M, *B, Angle;
+     int i, Npts;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, angle;
+  char Flipped;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Ra;
+  Y = De;
+  X2 = Ra*Ra;
+  Y2 = De*De;
+  XY = Ra*De;
+  N = 1;
+  /* points to the east */
+  for (j = i + 1; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; !mark[i] && (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    if (mark[j]) continue;
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      angle = atan2 (dD,dR);
+      if (!finite(angle)) continue;
+      if (angle < 0) angle += M_PI;
+      if (fabs(angle - Angle) < RAD_DEG) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  Flipped = 0;
+  det = 1.0 / (X2*N - X*X);
+  m = det * (XY*N - X*Y);
+  b = det * (X2*Y - XY*X);
+  if (fabs(m) > 1.1) { /* use a line of R = m*D + b instead */
+    /* fprintf (stderr, "high slope object: %f %f  -> ", m, b); */
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+    Flipped = 1;
+    /* fprintf (stderr, "%f %f\n", m, b); */
+  }
+
+  *M = m;
+  *B = b;
+  return (Flipped);
+
+}
+
+
+find_better_line (catstats, mark, Npts, i, M, B, axis)
+     CatStats catstats[];
+     double *M, *B;
+     int i, Npts, axis;
+     char *mark;
+{
+  
+  float *R, *D;
+  int j, N;
+  double X, Y, X2, Y2, XY, m, b, det;
+  double dR, dD, Ra, De, delta;
+  
+  R = catstats[0].X;
+  D = catstats[0].Y;
+
+  /* fit a line to points near line */
+  Ra = R[i];
+  De = D[i];
+  X = Y = X2 = Y2 = XY = N = 0;
+  m = *M;  b = *B;
+
+  /* points to the east */
+  for (j = i; (j < Npts) && (R[j] - Ra < RADIUS); j++) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* points to the west */
+  for (j = i - 1; (j >= 0) && (Ra - R[j] < RADIUS); j--) {
+    dD = D[j] - De;
+    if (fabs(dD) < RADIUS) {
+      dR = R[j] - Ra;
+      if (axis == 1) 
+	delta = R[j] - m*D[j] - b;
+      else
+	delta = D[j] - m*R[j] - b;
+      if (fabs(delta) < 2*TRAIL_WIDTH) {
+	X += R[j];
+	Y += D[j];
+	X2 += R[j]*R[j];
+	Y2 += D[j]*D[j];
+	N ++;
+	XY += R[j]*D[j];
+      }
+    }
+  }
+  /* determine coeffs */
+  if (axis == 0) {
+    det = 1.0 / (X2*N - X*X);
+    m = det * (XY*N - X*Y);
+    b = det * (X2*Y - XY*X);
+  } else {
+    det = 1.0 / (Y2*N - Y*Y);
+    m = det * (XY*N - X*Y);
+    b = det * (Y2*X - XY*Y);
+  }
+
+  /* fprintf (stderr, "%f %f %d\n", m, b, N); */
+
+  *M = m;
+  *B = b;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/find_matches.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/find_matches.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/find_matches.c	(revision 16632)
@@ -0,0 +1,83 @@
+# include "markstar.h"
+
+int find_matches (Catalog *catalog, CatStats *catstats, Catalog *Ghostdata, int Nimage) {
+
+  int i, j, k, n, m, N, M, first_j;
+  double X, Y, RADIUS, RADIUS2;
+  double *X1, *Y1, *X2, *Y2;
+  double dX, dY, dR;
+  int *N1, *N2;
+  int Nstar, Nghost, Ng;
+  unsigned int flags;
+  Coords *tcoords;
+
+  Nstar = catalog[0].Naverage;
+  Nghost = Ghostdata[0].Naverage;
+
+  if (Nghost < 1) return (0);
+
+  /* it is better to have the catalog with fewer stars
+     assigned to the X1 set */
+  X2 = catstats[0].X;
+  Y2 = catstats[0].Y;
+  N2 = catstats[0].N;
+
+  ALLOCATE (X1, double, Nghost);
+  ALLOCATE (Y1, double, Nghost);
+  ALLOCATE (N1, int, Nghost);
+
+  /* project ghosts to the frame of the catalog */
+  tcoords = &catstats[0].coords;
+  for (i = 0; i < Nghost; i++) {
+    RD_to_XY (&X1[i], &Y1[i], Ghostdata[0].average[i].R, Ghostdata[0].average[i].D, tcoords);
+    N1[i] = i;
+  }
+  if (Nghost > 1) sort_coords_index (X1, Y1, N1, Nghost);
+
+  /* choose a radius for matches */
+  RADIUS2 = GHOST_RADIUS*GHOST_RADIUS;
+
+  /** find matched stars **/
+  for (i = j = 0; (i < Nghost) && (j < Nstar); ) {
+    dX = X1[i] - X2[j];
+    if (dX <= -2*GHOST_RADIUS) {
+      i++;
+      continue;
+    }
+    if (dX >= 2*GHOST_RADIUS) {
+      j++;
+      continue;
+    }
+    /* negative dX: j is too large, positive dX, i is too large */
+    first_j = j;
+    for (; (dX > -2*GHOST_RADIUS) && (j < Nstar); j++) {
+      dX = X1[i] - X2[j];
+      dY = Y1[i] - Y2[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  
+	/* this object may be a ghost star, 
+	   but only mark those measurements on the correct image */
+	M = N2[j];
+	m = catalog[0].average[M].offset;
+	Ng = 0;
+	for (k = 0; k < catalog[0].average[M].Nm; k++) {
+	  if (catalog[0].image[m+k] == Nimage) {
+	    catalog[0].measure[m+k].average |= GHOST_DATA;
+	    Ng ++;
+	  }
+	}
+	/* all measurements are ghosts */
+	if (catalog[0].average[M].Nm == Ng) {
+	  catalog[0].average[M].code = ID_GHOST;
+	}
+      }
+    }
+    j = first_j;
+    i++;
+  }
+
+  free (X1);
+  free (Y1);
+  free (N1);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/find_trails.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/find_trails.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/find_trails.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "markstar.h"
+
+find_trails (catalog, catstats)
+Catalog catalog[];
+CatStats catstats[];
+{
+
+  int i, j, N, Nave, axis, marked;
+  double density, spacing, Area, Angle, m, b, RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  float *X1, *Y1;
+  char *mark;
+  int *N1;
+  Coords tcoords;
+  
+  Nave = catalog[0].Naverage;
+  N1 = catstats[0].N;
+
+  ALLOCATE (mark, char, Nave);
+  bzero (mark, Nave);
+
+  for (i = 0; i < Nave; i++) {
+    /* already marked, ignore */
+    if ((mark[i]) || 
+	(catalog[0].average[N1[i]].code == ID_BLEED) || 
+	(catalog[0].average[N1[i]].code == ID_GHOST))
+      continue;
+    /* a good star, ignore */
+    if ((catalog[0].average[N1[i]].Nm > 3) && 
+	(catalog[0].average[N1[i]].Nm > 4*catalog[0].average[N1[i]].Nn)) {
+      continue;
+    }
+    if (find_group (catstats, mark, Nave, i, &Angle)) {
+      /* this point has an excess nearby concentration, find the line */
+      axis = find_line (catstats, mark, Nave, i, &m, &b, Angle);
+      find_better_line (catstats, mark, Nave, i, &m, &b, axis);
+      mark_trail (catstats, mark, Nave, i, m, b, axis, catalog);
+    }
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/gcatstats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/gcatstats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/gcatstats.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "markstar.h"
+
+void gcatstats (Catalog *catalog, CatStats *catstats) {
+
+  int i;
+  double RaCenter, DecCenter;
+  double MinRA, MaxRA, MinDEC, MaxDEC;
+  double *X1, *Y1;
+  int *N1;
+  Coords tcoords;
+  
+  gfits_scan (&catalog[0].header, "RA0", "%lf", 1, &MinRA);
+  gfits_scan (&catalog[0].header, "RA1", "%lf", 1, &MaxRA);
+  gfits_scan (&catalog[0].header, "DEC0", "%lf", 1, &MinDEC);
+  gfits_scan (&catalog[0].header, "DEC1", "%lf", 1, &MaxDEC);
+
+  /* double check on region RA and DEC ranges */
+  DecCenter = 0.5*(MinDEC + MaxDEC);
+  RaCenter = 0.5*(MinRA + MaxRA);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    DecCenter = 90.0;
+    RaCenter = 0.0;
+  }
+
+  catstats[0].RA[0] = MinRA;
+  catstats[0].RA[1] = MaxRA;
+  catstats[0].DEC[0] = MinDEC;
+  catstats[0].DEC[1] = MaxDEC;
+  catstats[0].Area = (MaxDEC - MinDEC)*(MaxRA - MinRA) / cos (RAD_DEG*DecCenter);
+  if (MaxDEC > 86.25) {  /* we are on the pole */
+    catstats[0].Area = 44.2;
+  }
+  catstats[0].density = catalog[0].Naverage / (3600*3600*catstats[0].Area);
+  /* catstats[0].density = MIN_DENSITY; */
+  catstats[0].spacing = 1.0 / (NSIGMA * catstats[0].density * 2*TRAIL_WIDTH);
+  fprintf (stderr, "Area, density, spacing: %f %f %f\n", catstats[0].Area, 
+	   catstats[0].density, catstats[0].spacing);
+  /* number of stars per square arcsec */
+
+  /** allocate local arrays **/
+  ALLOCATE (catstats[0].X, double, catalog[0].Naverage);
+  ALLOCATE (catstats[0].Y, double, catalog[0].Naverage);
+  ALLOCATE (catstats[0].N, int,   catalog[0].Naverage);
+
+  /* project onto rectilinear grid with 1 arcsec pixels, sort by X */
+  /* reference for coords is center of field  */
+  catstats[0].coords.crval1 = RaCenter;
+  catstats[0].coords.crval2 = DecCenter;
+  catstats[0].coords.crpix1 = catstats[0].coords.crpix2 = 0.0;
+  catstats[0].coords.cdelt1 = catstats[0].coords.cdelt2 = 1.0 / 3600.0;
+  catstats[0].coords.pc1_1 = catstats[0].coords.pc2_2 = 1.0;
+  catstats[0].coords.pc1_2 = catstats[0].coords.pc2_1 = 0.0;
+  strcpy (catstats[0].coords.ctype, "RA---TAN");
+
+  X1 = catstats[0].X;
+  Y1 = catstats[0].Y;
+  for (i = 0; i < catalog[0].Naverage; i++, X1++, Y1++) {
+    RD_to_XY (X1, Y1, catalog[0].average[i].R, catalog[0].average[i].D, &catstats[0].coords);
+    catstats[0].N[i] = i;
+  }
+  if (catalog[0].Naverage > 1) sort_coords_index (catstats[0].X, catstats[0].Y, catstats[0].N, catalog[0].Naverage);
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/mark_trail.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/mark_trail.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/mark_trail.c	(revision 16632)
@@ -0,0 +1,272 @@
+# include "markstar.h"
+int *make_common_list ();
+int *check_common_list ();
+
+mark_trail (catstats, mark, Nave, i, m, b, axis, catalog)
+     CatStats catstats[];
+     char *mark;
+     int i, Nave, axis;
+     double m, b;
+     Catalog catalog[];
+{
+
+  float *R, *D;
+  int j, k, jj, kk, N, NPTS, marked, start, end, Nm;
+  int *good, *seq, *N1;
+  double *dist, *dist2;
+  double d2, di, Di, dD, n, Dist, scale, norm;
+  double spacing;
+  int *list, Nlist;
+  int M, Nmeas, thisimage;
+
+  R = catstats[0].X;
+  D = catstats[0].Y;
+  N1 = catstats[0].N;
+  spacing = catstats[0].spacing;
+
+  NPTS = 200;
+  ALLOCATE (good, int, NPTS);
+  ALLOCATE (dist, double, NPTS);
+  ALLOCATE (dist2, double, NPTS);
+  ALLOCATE (seq, int, NPTS);
+
+  /* Find all points which lie near line */
+  /* save the entry number and distance along line */
+  N = 0;
+  scale = sqrt (1.0 + m*m);
+
+  if (axis == 1) {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(R[j] - m*D[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (D[j] - D[i] + m*(R[j] - R[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  } else {
+    for (j = 0; j < Nave; j++) {
+      norm = scale * fabs(D[j] - m*R[j] - b);
+      if (!mark[j] && (norm < TRAIL_WIDTH)) {
+	good[N] = j;
+	dist[N] = scale * (R[j] - R[i] + m*(D[j] - D[i]));
+	seq[N] = N;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 200;
+	  REALLOCATE (good, int, NPTS);
+	  REALLOCATE (dist, double, NPTS);
+	  REALLOCATE (dist2, double, NPTS);
+	  REALLOCATE (seq, int, NPTS);
+	}
+      }
+    }
+  }
+  
+  if (N < NPTSINLINE) 
+    return (0);
+
+  sort_seq (dist, seq, N);
+  
+  start = -1; end = -1;
+  for (j = 0; j < N-1; j++) {
+    /* if we have part of a line, and next point is in the line, check for common images */
+    if ((start != -1) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      list = check_common_list (list, N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, dump list and continue */
+	end = j + 1;
+	if (end - start > NPTSINLINE) {
+	  if (axis == 0)
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	  else
+	    fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	  for (k = start; k < end; k++) {
+	    M = N1[good[seq[k]]];
+	    mark[good[seq[k]]] = TRUE;
+	    /* we need to mark measurements from all images in common on the line */
+	    Nm = 0;
+	    for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	      Nmeas = catalog[0].average[M].offset + jj;
+	      thisimage = catalog[0].image[Nmeas];
+	      for (kk = 0; kk < Nlist; kk++) {
+		if (thisimage == list[kk]) {
+		  catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		  Nm ++;
+		}
+	      }
+	    }
+	    /* if there is only 1 measurement, mark object as bad */
+	    if (catalog[0].average[M].Nm == Nm) {
+	      catalog[0].average[M].code = ID_TRAIL;
+	    }
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	}
+	start = -1;
+	end = -1;
+      }
+    }
+    /* if we haven't yet found a line segment, check for the beginning */
+    if ((start < 0) && (fabs(dist[j] - dist[j+1]) < spacing)) {
+      start = j;
+      list = make_common_list (N1[good[seq[j]]], N1[good[seq[j+1]]], &Nlist, catalog);
+      if (Nlist == 0) { /* if no common images, move on */
+	start = -1;
+	free (list);
+      }
+    }
+    /* if we have a complete line, check for validity.  if it has enough members,
+	 mark them and continue searching for lines */
+    if ((start != -1) && ((fabs(dist[j] - dist[j+1]) >= spacing) || (j == N-2))) {
+      end = j + 1;
+      if (end - start > NPTSINLINE) {
+	if (axis == 0)
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", m, b, N, end-start, start, end, dist[start], dist[end-1]);
+	else
+	  fprintf (stderr, "marking line %f %f  %d pts  %d  %d %d, %f %f\n", 1.0/m, -1.0*b/m, N, end-start, start, end, dist[start], dist[end-1]);
+	for (k = start; k < end; k++) {
+	  M = N1[good[seq[k]]];
+	  mark[good[seq[k]]] = TRUE;
+	  if (catalog[0].average[M].code == ID_BLEED) continue;
+	  /* we need to mark measurements from all images in common on the line */
+	  Nm = 0;
+	  for (jj = 0; jj < catalog[0].average[M].Nm; jj++) {
+	    Nmeas = catalog[0].average[M].offset + jj;
+	    thisimage = catalog[0].image[Nmeas];
+	    for (kk = 0; kk < Nlist; kk++) {
+	      if (thisimage == list[kk]) {
+		catalog[0].measure[Nmeas].average |= PART_OF_TRAIL;
+		Nm ++;
+	      }
+	    }
+	  }
+	  /* if there is only 1 measurement, mark object as bad */
+	  if (catalog[0].average[M].Nm == Nm) {
+	    catalog[0].average[M].code = ID_TRAIL;
+	  }
+	  catalog[0].average[M].code = ID_TRAIL;
+	}
+      }
+      free (list);
+      start = -1;
+      end = -1;
+    }
+  }
+}
+
+
+/* I is Average seq number for star 1, J for star 2 */
+/* make a list of images in common between two measurements */
+int *make_common_list (I, J, Nlist, catalog)
+int I, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N1, N2, nlist, NLIST;
+  int *list;
+  int k, already;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+
+  for (i = 0; i < catalog[0].average[I].Nm; i++) {
+    N1 = catalog[0].average[I].offset + i;
+    if (catalog[0].image[N1] == -1)
+      continue; /* not a real measurement */
+    for (j = 0; j < catalog[0].average[J].Nm; j++) {
+      N2 = catalog[0].average[J].offset + j;
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (catalog[0].image[N1] == catalog[0].image[N2]) {
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (catalog[0].image[N1] == list[k]) { 
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = catalog[0].image[N1];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  REALLOCATE (list, int, MAX(nlist, 1));
+  *Nlist = nlist;
+  return (list);
+
+}
+
+
+
+/* J is Average seq number for star */
+
+int *check_common_list (inlist, J, Nlist, catalog)
+int *inlist, J, *Nlist;
+Catalog catalog[];
+{
+
+  int i, j, N2, Ninlist;
+  int *list, NLIST, nlist;
+  int already, found, k;
+
+  NLIST = 50;
+  ALLOCATE (list, int, NLIST);
+  nlist = 0;
+  Ninlist = *Nlist;
+
+  for (j = 0; j < catalog[0].average[J].Nm; j++) {
+    N2 = catalog[0].average[J].offset + j;
+    found = FALSE;
+    for (i = 0; !found && (i < Ninlist); i++) {
+      if (catalog[0].image[N2] == -1)
+	continue; /* not a real measurement */
+      if (inlist[i] == catalog[0].image[N2]) {
+	found = TRUE;
+	already = FALSE; 
+	for (k = 0; !already && (k < nlist); k++) {
+	  if (inlist[i] == list[k]) {
+	    already = TRUE;
+	  }
+	}
+	if (!already) {
+	  list[nlist] = inlist[i];
+	  nlist ++;
+	  if (nlist == NLIST - 1) {
+	    NLIST += 50;
+	    REALLOCATE (list, int, NLIST);
+	  }
+	}
+      }
+    }
+  }
+  
+  /* if there are no common images, return the input list */
+  if (nlist != 0) {
+    free (inlist);
+    REALLOCATE (list, int, MAX(nlist, 1));
+    *Nlist = nlist;
+    return (list);
+  } else {
+    return (inlist);
+  }
+
+}
+
+
+/* measurements associated with image number -1 are not 
+   measurements we made, but are added, like USNO */
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/markstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/markstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/markstar.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "markstar.h"
+
+/*** this needs to be cleaned to match current db I/O model ***/
+
+int main (int argc, char **argv) {
+
+  FILE *f;
+  int i, Nstars, Nimage, Nregions, Nmissed;
+  Image *image, *find_images();
+  Catalog catalog;
+  CatStats catstats;
+  struct timeval now, then;  
+  FITS_DB db;
+  
+  gettimeofday (&then, (void *) NULL);
+  ConfigInit (&argc, argv);
+
+  VERBOSE = FALSE;
+  if ((i = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  FORCE_RUN = FALSE;
+  if ((i = get_argument (argc, argv, "-f"))) {
+    FORCE_RUN = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  RESET = FALSE;
+  if ((i = get_argument (argc, argv, "-reset"))) {
+    RESET = TRUE;
+    remove_argument (i, &argc, argv);
+  }
+  if (argc < 2) {
+    fprintf (stderr, "ERROR: Usage: markstar (catalog)\n");
+    exit (0);
+  }
+
+  set_db (&db);
+  dvo_image_lock (&db, ImageCat, 3600.0, LCK_XCLD);
+
+  catalog.filename = argv[1];
+  catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+  catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog, NULL, VERBOSE, "a")) {
+    fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+    exit (2);
+  }
+  if (!catalog.Naves_disk) {
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+    exit (0);
+  }
+
+  gcatstats (&catalog, &catstats);
+
+  image = find_images (&catstats, &Nimage);
+
+  match_images (&catalog, image, Nimage);
+    
+  find_trails (&catalog, &catstats, i);  
+
+  /* find_bright_stars (&catalog, &catstats);  */
+
+  /* find_ghosts (&catalog, &catstats, argv[1], image, Nimage); */
+
+  dvo_catalog_save (&catalog, VERBOSE);
+  dvo_catalog_unlock (&catalog);
+  dvo_catalog_free (&catalog);
+
+  if (VERBOSE) {
+    gettimeofday (&now, (void *) NULL);
+    fprintf (stderr, "%s: elapsed time = %.2f sec\n", argv[1], 
+	     (now.tv_sec - then.tv_sec) + 1e-6*(now.tv_usec - then.tv_usec));
+  }
+  fprintf (stderr, "SUCCESS\n");
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/match_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/match_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/match_images.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "markstar.h"
+
+match_images (catalog, image, Nimage)
+Catalog catalog[];
+Image   image[];
+int Nimage;
+{
+  
+  int j, k, found;
+  unsigned int *start, *stop;
+  short int *source;
+
+  /* this must be allocated so future free will not fail */
+  ALLOCATE (catalog[0].image, int, MAX (catalog[0].Nmeasure, 1));
+  if (catalog[0].Naverage == 0) {
+    if (VERBOSE) fprintf (stderr, "no stars in catalog, skipping\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (start, unsigned int, Nimage);
+  ALLOCATE (stop,  unsigned int, Nimage);
+  ALLOCATE (source, short int, Nimage);
+  for (j = 0; j < Nimage; j++) {
+    start[j] = image[j].tzero - MAX(0.05*image[j].trate*image[j].NY, 1);
+    stop[j]  = image[j].tzero + MAX(1.05*image[j].trate*image[j].NY, 1);
+    source[j] = image[j].photcode;
+  }
+
+  for (j = 0; j < catalog[0].Nmeasure; j++) {
+    found = FALSE;
+    if (catalog[0].measure[j].t == 0) {
+      catalog[0].image[j] = -1;
+      found = TRUE;
+    }
+    for (k = 0; (k < Nimage) && !found; k++) {
+      if ((catalog[0].measure[j].t >= start[k]) && 
+	  (catalog[0].measure[j].t <= stop[k])  &&
+	  (catalog[0].measure[j].photcode == source[k])) {
+	catalog[0].image[j] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      fprintf (stderr, "ERROR: can't find source image for this measurement: %d %d)\n",
+	       catalog[0].measure[j].t, catalog[0].measure[j].photcode);
+      exit (0);
+    }
+  }
+  free (start);
+  free (stop);
+  free (source);
+}
+
+  /* this routine uses the time of each measurement to match the
+measurement with an image.  Since the measurement is only store to 1
+sec accuracy, which corresponds to roughly 30 rows at nominal speed,
+we can't tell exactly which image the star come from.  However, this
+doesn't matter, and in fact this helps a bit: a measurement from the
+top of one image is the same as from the bottom of the next.
+Therefore, we intentionally blur the edges of the images by 5%, which
+will help to tie together neighboring images... */
+
Index: /branches/eam_branch_20080223/Ohana/src/markstar/src/sorts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/markstar/src/sorts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/markstar/src/sorts.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "markstar.h"
+
+void sort_seq (double *X, int *S, int N) {
+
+# define SWAPFUNC(A,B){ \
+  double dtmp; dtmp = X[A]; X[A] = X[B]; X[B] = dtmp; }
+  int    itmp; itmp = S[A]; S[A] = S[B]; S[B] = itmp; }
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/Makefile	(revision 16632)
@@ -0,0 +1,75 @@
+default: misc
+help:
+	@echo "make options: misc (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/misc
+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 = mknames mkgauss mkfringetable gtfringetable applyscat fiximg
+
+misc: $(PROGRAMS)
+
+$(PROGRAMS): % : $(BIN)/%.$(ARCH)
+
+fakestars: $(BIN)/fakestars.$(ARCH)
+$(BIN)/fakestars.$(ARCH): $(SRC)/fakestars.$(ARCH).o $(SRC)/random.$(ARCH).o
+
+#### cfhtlog is special (requires additional libs and includes)
+
+$(BIN)/cfhtlog.$(ARCH): $(SRC)/cfhtlog.c
+	$(CC) -I/cfht/include -L/cfht/lib -o $(BIN)/cfhtlog.$(ARCH) $(SRC)/cfhtlog.c -lcfht 
+
+$(DESTBIN)/cfhtlog: $(BIN)/cfhtlog.$(ARCH)
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	cp $(SRC)/cfhtlog.$(ARCH) $(DESTBIN)/
+
+cfhtlog:
+	make $(DESTBIN)/cfhtlog
+
+# 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/eam_branch_20080223/Ohana/src/misc/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/misc/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,26 @@
+
+- misc-1-3 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+
+misc-1-2:
+
+  - minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+2005.10.07
+
+	I was having some memory collision problems, and attempting to
+	use the ohana_allocate functions reminded me that the libFITS
+	functions were not supported under ohana_allocate.  This was
+	unhelpful.  I bit the bullet and split libohana into libohana
+	(base functions only, including ohana_allocate) and libdvo
+	(functions based on the libautocode structures).  Doing this
+	allowed me to make libFITS depend on libohana (including
+	ohana_allocate).  BUT, this forced me to change all LDFLAGS
+	entries in ohana to swap -lohana -lFITS for -lFITS -lohana,
+	and to add include <fitsio.h> in some cases.
+
+misc-1-1:
+  - dropped old, out-of-date programs
+  - minor changes for loneos.h -> dvo.h
+  - cleanup of glockfile things
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/include/cfht/cfht.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/include/cfht/cfht.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/include/cfht/cfht.h	(revision 16632)
@@ -0,0 +1,793 @@
+/* Copyright (C) 1991-1999  Canada-France-Hawaii Telescope Corp.         */
+/* This program is distributed WITHOUT any warranty, and is under the    */
+/* terms of the GNU General Public License, see the file COPYING         */
+/*****************************************************************************
+ *
+ * file: cfht.h
+ * $Id: cfht.h,v 1.1.1.1 2004-11-24 04:39:33 eugene Exp $
+ * $Locker:  $
+ *
+ * This file is the main include file for the generic library.
+ *
+ *
+ * HISTORY
+ *
+ * who       when          what
+ * -------   -----------   ----------------------------------------------
+ * jab       27 Jan 1988   Original coding
+ * jab        1 Mar 1988   Added config file stuff
+ * jab       12 Mar 1988   Added logging stuff
+ * jk        22 Mar 1988   Added cfht_od()
+ * jk/jab    24 Mar 1988   Added CFHT_TAPE and CFHT_DISPLAY
+ * jab        6 Apr 1988   Added puma link device
+ * jab       29 Apr 1988   Added already included check
+ * sss       08 May 1988   Added CFHT_NPIPE
+ * jk        17 May 1988   Modified tape and display because of collision
+ * jk        06 Oct 1988   added cfht_resetetimer as a define
+ * sss       17 Mar 1989   added cfht_log() support stuffs
+ * sss       11 Apr 1989   added real time defines for detectors,etc.
+ * sss       24 Oct 1989   added CFHT_RELEASE define for .,config access
+ * sss        3 Jan 1990   added CFHT_*SESSIONHOST defines for env. vars
+ * jrw       01 Oct 1990   added stuff for cfht_number
+ * jrw       02 Nov 1990   added CFHT_STR_* defines
+ * jk        27 Feb 1991   cfht_exec unions not used anymore
+ * sss       27 Mar 1991   added cfht_basename()
+ * jrw       09 May 1991   added function definitions (ANSI and crufty flavors)
+ * jk        29 Aug 1991   changed cfht_errno from BOOLEAN to int
+ *
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1  2001/07/25 02:59:23  eugene
+ * import Ohana
+ *
+ * Revision 1.44  2000/04/10  11:28:40  isani
+ * Added prototype for cfht_log_proxy.
+ * 
+ * Revision 1.43  2000/02/10 13:19:08  isani
+ * Added include of sys/types.h whenever pid_t is needed.
+ *
+ * Revision 1.42  1999/12/02 21:40:30  thomas
+ * Added PFVint
+ *
+ * Revision 1.41  1999/07/25 06:29:57  thomas
+ * Added UTDATE/TIME and PFDATE defs
+ *
+ * Revision 1.40  1999/04/29 17:18:00  thomas
+ * Added @ ( # ) to RCSID string for what(1) to find
+ * Added non-gcc but STDC version of above
+ * Added changes for switch to /cfht
+ *
+ * Revision 1.39  99/02/17  13:55:15  13:55:15  thomas (Jim Thomas)
+ * Added cfht_cfhthome
+ * 
+ * Revision 1.38  98/12/11  18:23:20  18:23:20  thomas (Jim Thomas)
+ * Added CFHT_*OBSERVERPATH
+ * 
+ * Revision 1.37  98/10/22  17:52:44  17:52:44  thomas (Jim Thomas)
+ * Added CFHT_ESESSION
+ * 
+ * Revision 1.36  98/07/16  15:53:32  15:53:32  thomas (Jim Thomas)
+ * Added cfht_system
+ * 
+ * Revision 1.35  98/07/07  12:52:47  12:52:47  thomas (Jim Thomas)
+ * Added CFHTPATH , IOCONFDIR , and CONFDIR definitions
+ * 
+ * Revision 1.34  98/04/09  17:52:20  17:52:20  thomas (Jim Thomas)
+ * Added cfht_argsToString
+ * 
+ * Revision 1.33  98/02/25  16:35:00  16:35:00  thomas (Jim Thomas)
+ * Added prototype for cfht_logpv
+ * 
+ * Revision 1.32  97/12/09  00:11:48  00:11:48  healey (SueAnn Healey)
+ * added CFHT_LIBSSX
+ * 
+ * Revision 1.31  1997/12/01 16:03:29  isani
+ * Moved missing protos to separate file.
+ * Added extern "C" declarations for C++ projects.
+ *
+ * Revision 1.30  1997/09/17 13:48:31  thomas
+ * Added CFHT_EXEC_NOT_EXITED and CFHT_EXEC_FAILED
+ * Documented bogus use of FAIL in exp_controller_t
+ *
+ * Revision 1.29  97/06/29  15:41:07  15:41:07  isani (Sidik Isani)
+ * Had to fiddle with some of the includes to get to compile with GCC
+ *   on the sparc engines.
+ * 
+ * Revision 1.28  97/05/28  02:51:35  isani
+ * added CFHT_SIG_ defines for handler argument of cfht_signal()
+ * 
+ * Revision 1.27  97/04/07  20:10:26  thomas
+ * Added LIBOMS, changed cfht_signal event prototypes
+ * 
+ * Revision 1.26  96/11/22  02:36:44  02:36:44  isani (Sidik Isani)
+ * added macro for TEMP_FAILURE_RETRY, in case anyone wants to use it
+ * changed cfht_delay(n) into a macro that calls cfht_sleep(n,1)
+ * 
+ * Revision 1.25  96/11/19  22:24:19  isani
+ * moved P() and Q() macros closer to top of file
+ * added RCSID() macro
+ * define volatile to nothing on compilers where everything is volatile
+ * define UNUSED for use with gcc, or nothing on compilers that don't care
+ * added a few more missing libcfht prototypes
+ * concentrated most of the old-sun hacks here rather than in each file
+ *   (protos for getenv, putenv, different name for mktime, etc.)
+ * fixed order of arguments in cfht_fromjulian prototype
+ * 
+ * Revision 1.24  96/08/14  13:01:17  13:01:17  thomas (Jim Thomas)
+ * Added TCS_ConsolePrompt error return code
+ * 
+ * Revision 1.23  96/05/20  16:01:16  16:01:16  thomas (Jim Thomas)
+ * Added LIBCX, TCS_CommandFailed,
+ * Fixed F4 cfht_errno definitions
+ * 
+ * Revision 1.22  96/02/21  11:16:07  11:16:07  isani (Sidik Isani)
+ * cfht_errno codes for gecko and f4 server
+ * 
+ * Revision 1.21  1995/07/19 12:48:00  thomas
+ * Added AOB cfht_errno codes
+ *
+ * Revision 1.20  95/06/29  11:38:38  11:38:38  thomas (Jim Thomas)
+ * Added cfht_errno codes for IDS
+ * 
+ * Revision 1.19  95/06/13  12:03:06  12:03:06  thomas (Jim Thomas)
+ * Added environment variables and cfht_log_who entries for CS, DUCK, HELP,
+ * IDS, PIXD, TCS, and UI libraries
+ * 
+ * Revision 1.18  95/06/07  17:22:30  17:22:30  thomas (Jim Thomas)
+ * Added typedef for cfht_errno codes
+ * 
+ * Revision 1.17  94/12/28  17:06:51  17:06:51  thomas (Jim Thomas)
+ * Moved strerror definition for suns here from cfp.h (for cfht_logv)
+ * 
+ * Revision 1.16  94/12/21  10:35:46  10:35:46  john (John Kerr)
+ * add pid_t.
+ * 
+ * Revision 1.15  94/12/15  10:46:42  10:46:42  john (John Kerr)
+ * modified pid in cfht_exec_data to be a pid_t type.
+ * 
+ * Revision 1.14  94/12/14  10:50:01  10:50:01  thomas (Jim Thomas)
+ * Added CFHT_LIBMUSIC, CFHT_VALUE_SIZE, Q macro
+ * Deleted BYTE
+ * 
+ * Revision 1.13  94/09/20  18:40:45  18:40:45  thomas (Jim Thomas)
+ * added CFHT_LOGONLY, CFHT_LIBOCS
+ * reworked symbols related to cfht_log
+ * 
+ * Revision 1.12  94/08/14  10:27:17  10:27:17  jwright (Jim Wright)
+ * add warning log messages and color messages
+ * 
+ * Revision 1.11  94/07/11  15:48:53  15:48:53  veran (Jean-Pierre Veran)
+ * AAdded net logging capabilities
+ * 
+ * Revision 1.10  94/02/02  14:08:00  14:08:00  jwright (Jim Wright)
+ * remove typedef of FILE_ID form cfp.h and put it in cfht.h.  reason is
+ * that cfht_exec() has an argument of type FILE_ID and thus needs to have
+ * this type visible so that it can correctly declare an ANSI prototype.
+ * it is presumed that any file including cfp.h will first have included
+ * cfht.h.
+ * 
+ * Revision 1.9  94/01/20  20:35:13  20:35:13  jwright (Jim Wright)
+ * fix enum
+ * 
+ * Revision 1.8  94/01/20  04:51:31  04:51:31  jwright (Jim Wright)
+ * add enumeration for controller types
+ * 
+ * Revision 1.7  93/11/26  10:14:09  10:14:09  jwright (Jim Wright)
+ * added definitions to retrieve info from net.par
+ * 
+ * Revision 1.6  93/05/19  08:45:49  08:45:49  steve (Steven Smith)
+ * added cfht_logv TIMING define
+ * 
+ * Revision 1.5  93/02/16  16:21:15  16:21:15  john (John Kerr)
+ * added a CFHT_INSTRUMENT_TYPE
+ * 
+ * Revision 1.4  92/12/01  19:21:47  19:21:47  steve (Steven Smith)
+ * added CFHT_ELOGHOST for cfht_log() net based
+ * 
+ * Revision 1.3  92/11/09  13:11:03  13:11:03  john (John Kerr)
+ * added void cfht_goDaemon()
+ * 
+ * Revision 1.2  91/11/15  10:07:52  10:07:52  jwright (Jim Wright)
+ * add macro to handle both ansi and k&r style parameters
+ * in function declarations; convert declarations to use macro
+ * 
+ * Revision 1.1  91/09/24  15:59:31  15:59:31  steve (Steven S Smith)
+ * Initial revision
+ * 
+ ****************************************************************************/
+
+#ifndef CFHTDOTH
+#define CFHTDOTH
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef pid_t
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#endif /* pid_t */
+
+/******************************************************************
+ * macro to declare prototypes for ansi, but still works with k&r *
+ *                                                                *
+ * define prototype like                                          *
+ *        int foo P((int a, char c))                              *
+ *                                                                *
+ * note that the space before the P and the doubled parentheses   *
+ *      are needed                                                *
+ ******************************************************************/
+
+#ifndef P
+#ifdef __STDC__
+#define P(args) args
+#else
+#define P(args) ()
+#endif
+#endif
+
+/********************************************************************
+ * macro to declare routine parameters for ansi that works with k&r *
+ *                                                                  *
+ * define actual routine like                                       *
+ *        int foo Q((int a, char c), (a, c), int a; char c;) {      *
+ *                                                                  *
+ * note that inner parentheses are needed on the ansi parameters    *
+ *                                 needed on the K&R parameters     *
+ *                             and must not be there on the K&R     *
+ *                                          type definition         *
+ *           there must be a space before the Q                     *
+ *           the arguments to Q can be on separate lines like       *
+ *                         int foo Q((int a, char c),               *
+ *                                   (a, c),                        *
+ *                                   int a; char c;)                *
+ *                         {                                        *
+ ********************************************************************/
+
+#ifndef Q
+#ifdef __STDC__
+#define Q(ansi, karparm, kartype) ansi
+#else
+#define Q(ansi, karparm, kartype) karparm kartype
+#endif
+#endif
+
+/*
+ * UNUSED attribute to tell Gnu compiler not to warn
+ * and define volatile to nothing for compilers where everything
+ * is volatile (We hope!)
+ */
+#ifdef __STDC__
+#ifdef __GNUC__
+#define UNUSED __attribute__ ((__unused__))
+#else
+#define UNUSED
+#endif
+#else
+#define UNUSED
+#define volatile
+#endif
+
+/*
+ * Macro to use for inserting rcs id's 
+ */
+
+#ifdef __LINT__
+#define RCSID(string) extern int lint_rcs_id_dummy
+#else
+#if defined(__GNUC__) && defined(__STDC__)
+#define RCSID(string) \
+  static const char rcs_id[] __attribute__ ((__unused__)) = "@(#) " string
+#else
+#if defined(__STDC__)
+#define RCSID(string) static char rcs_id[] = "@(#) " string
+#else
+#define RCSID(string) static char rcs_id[] = string
+#endif
+#endif
+#endif
+
+/*********************
+ * type definitions *
+ ********************/
+
+typedef int BOOLEAN;           /* should only contain TRUE, or FALSE */
+typedef double ANGLE;          /* floating pt. arc seconds */
+typedef double TIME;           /* floating pt. seconds */
+typedef double JDATE;          /* julian day number */
+typedef char *DATE;            /* ascii string date */
+typedef int PASSFAIL;          /* for functions that return PASS, or FAIL */
+typedef void (*PFV) P((void));   /* pointer to function that returns void */
+typedef void (*PFVint) P((int));   /*  ditto, with int parameter */
+typedef void (*PFVui) P((int,int,void*));  /* used for ui callbacks */
+typedef void (*PFVexec) P((pid_t,int));    /* used by cfht_exec() */
+
+enum exp_controller_t {       /* valid detector controller types */
+    FAIL = -1,			  /* NOTE - depends on define below :-( */
+    CONTROLLER_GENIII,
+    CONTROLLER_CC200,
+    CONTROLLER_FTS,
+    CONTROLLER_RETICON
+};
+
+typedef int FILE_ID;              /* used for parse file instance handles */
+
+/*************
+ * constants *
+ *************/
+
+#define PASS  0           /* function returning with no error */
+#define FAIL  -1          /* function returning an error in errno */
+			  /* lots of things depend on FAIL being negative!! */
+
+#define TRUE  1           /* 'C' boolean */
+#define FALSE 0           /* 'C' boolean */
+
+#ifndef NULL              /* make sure it's not already defined */
+#define NULL  0           /* used mostly for null string pointers */
+#endif  /* NULL */
+
+#define CFHTLOCKS  "/tmp/cfhtlocks"
+
+/********************
+ * real time defs   *
+ ********************/
+
+#define CFHT_RT_DETECTOR 65    /* about 1/2 */
+#define CFHT_RT_MOMMA    75    /* not as fast */
+#define CFHT_RT_HANDLER  85    /* slower yet */
+
+/********************
+ * exec definitions *
+ ********************/
+
+#define CFHT_EXEC_NUM    10    /* number of pending deaths allowed */
+#define CFHT_EXEC         1    /* straight exec */
+#define CFHT_EXECFG       2    /* wait and return exit code */
+#define CFHT_EXECBG       3    /* dont wait and dont ever bother me */
+#define CFHT_EXECBGC      4    /* dont wait but deposit exit code when ... */
+#define CFHT_EXECBGH      5    /* dont wait but call handler when ... */
+                               /* (handler is called with pid and exit code */
+#define CFHT_EXEC_NOT_EXITED -1 /* initial value of exit code */
+#define CFHT_EXEC_FAILED -2    /*  exit code if ran but failed to exit */
+/* #define CFHT_EXEC_EXITED (8 bits of system exit code) */ /* normal exit */
+
+#define CFHT_ARGV_NUM   100    /* size of cfht_argv() arg list */
+#define CFHT_ARGS_SIZE 1024    /* size of string to make args out of */
+#define CFHT_VALUE_SIZE 256    /* max length of a value (as in name=value) */
+
+union cfht_exec_addr {
+    volatile int *code;        /* exit code (-1 -> not yet exited) */
+    PFV func;                  /* handler to call */
+};
+
+struct cfht_exec_data {
+    volatile pid_t pid;        /* process id (0 -> unused) */
+    volatile int type;         /* CFHT_EXECBGC, or CFHT_EXECBGH (0 -> ignore) */
+    volatile void *addr;       /* union not used anymore */
+};
+
+extern int cfht_exec_rtprio;
+
+/*
+ * paths and file names
+ * CFHT_E* is the name in the environment, without the E is the actual value
+ * at the moment - so try not to use these (unfortunately that means programs
+ * don't work outside the session, sigh, so they appear in cfp_file.c and
+ * roll.c at least :-(
+ */
+/*
+ * The original path to everything started at /usr/local/cfht .  To get things
+ * out from under /usr/local , we created an automount collection for /cfht .
+ * To make things more consistent with other packages, we changed from
+ * /usr/local/cfht/dev to /cfht/src for the top of the source tree.  While
+ * both paths still exist, handle both possibilities here (and nowhere else in
+ * any c code please :-)
+ */
+#if defined(HPUX10) || defined(Solaris)
+#define CFHT_ECFHTPATH   "cfhtdir"			/* top of our tree */
+#define CFHT_CFHTPATH    "/cfht"			/*   which is */
+#define CFHT_CONFDIR     "src/conf"			/* dir for par files */
+#define CFHT_IOCONFDIR   "conf"				/*   except ioconfig */
+#define CFHT_ECONFPATH   "CFHTCONFPATH"			/* path to par files */
+#define CFHT_CONFPATH    "/cfht/src/conf"		/*   which is */
+#else
+#define CFHT_ECFHTPATH   "cfhtdir"			/* top of our tree */
+#define CFHT_CFHTPATH    "/usr/local/cfht"		/*   which is */
+#define CFHT_CONFDIR     "dev/conf"			/* dir for par files */
+#define CFHT_IOCONFDIR   "conf"				/*   except ioconfig */
+#define CFHT_ECONFPATH   "CFHTCONFPATH"                 /* path to par files */
+#define CFHT_CONFPATH    "/usr/local/cfht/dev/conf"     /*   which is */
+#endif /* HPUX10 or Solaris */
+#define CFHT_ECONFNAME   "CFHTCONFNAME"                 /* name for .,config */
+#define CFHT_CONFNAME    "config"                       /*   which is */
+#define CFHT_ESESSION    "Session"			/* master session name */
+#define CFHT_EOBSERVERPATH "observer"                   /* path to top of homes */
+#define CFHT_OBSERVERPATH "/users/observer"             /*   which is */
+
+/* identifiers within config file */
+#define CFHT_DETECTOR    "detector"                     /* e.g. th1 */
+#define CFHT_RELEASE     "release"                      /* e.g. 901231 */
+#define CFHT_INSTRUMENT  "instrument"                   /* 'who am i' */
+#define CFHT_INSTRUMENT_TYPE  "instrument_type"         /* e.g. FTS */
+#define CFHT_HANDLERS    "handlers"                     /* e.g. tcsh, ccdh */
+#define CFHT_FOCUS       "focus"                        /* e.g. prime */
+#define CFHT_DISPLAY     "display_guy"                  /* display handler */
+#define CFHT_TAPE        "tape_guy"                     /* tape handler */
+#define CFHT_SESSION     "session"                      /* e.g. ccd, focam */
+
+/*****************
+ * net.par stuff *
+ *****************/
+
+#define CFHT_CCDSERVER	"ccdserver"
+#define CFHT_F4SERVER	"f4server"
+#define CFHT_FOCAMSERVER "focamserver"
+#define CFHT_GENSERVER	"genserver"
+#define CFHT_LOGSERVER	"logserver"
+#define CFHT_RFSERVER	"rfserver"
+#define CFHT_TCSSERVER	"tcsserver"
+#define CFHT_TRAFFIC	"traffic"
+
+/**********************
+ * session host stuff *
+ **********************/
+
+#define CFHT_ESESSIONHOST    "SESSIONHOST"    /* used in xstart files */
+#define CFHT_SESSIONHOST     "moe"            /* perhaps hostname()? */
+
+/*****************
+ * logging stuff *
+ *****************/
+
+/* environment variables */
+
+/*
+ * The following are viewed as boolean flags.  For each, the indicated setting
+ * has the described effect (e.g., "setenv CFHTERROR off" will cause error
+ * messages not to appear in the feedback window), and the inverse setting or
+ * no setting has the opposite effect (e.g., otherwise error messages appear
+ * in the feedback window).
+ */
+#define CFHT_EERROR     "CFHTERROR"     /* Off -> no error messages to
+					 * feedback window */
+#define CFHT_EWARN      "CFHTWARN"      /* Off -> no warning messages to
+					 * feedback window */
+#define CFHT_ENODISP    "CFHTNODISP"    /* On -> no START/STATUS/DONE messages
+					 * to feedback window */
+#define CFHT_EDEBUG     "CFHTDEBUG"     /* On -> CFHT_MAIN debug messages to
+					 * log file */
+#define CFHT_ELIB       "CFHTLIB"       /* On -> unknown lib debug messages to
+					 * log file */
+#define CFHT_ELIBCAMAC  "CFHTLIBCAMAC"  /* On -> libcamac debug to log file */
+#define CFHT_ELIBCCD    "CFHTLIBCCD"    /* On -> libccd debug to log file */
+#define CFHT_ELIBCFHT   "CFHTLIBCFHT"   /* On -> libcfht debug to log file */
+#define CFHT_ELIBCFP    "CFHTLIBCFP"    /* On -> libcfp debug to log file */
+#define CFHT_ELIBCS     "CFHTLIBCS"     /* On -> libcs debug to log file */
+#define CFHT_ELIBCX     "CFHTLIBCX"     /* On -> libcx debug to log file */
+#define CFHT_ELIBDUCK   "CFHTLIBDUCK"   /* On -> libduck debug to log file */
+#define CFHT_ELIBFF     "CFHTLIBFF"     /* On -> libff debug to log file */
+#define CFHT_ELIBHELP   "CFHTLIBHELP"   /* On -> libhelp debug to log file */
+#define CFHT_ELIBHH     "CFHTLIBHH"     /* On -> libhh debug to log file */
+#define CFHT_ELIBIDS    "CFHTLIBIDS"    /* On -> libids debug to log file */
+#define CFHT_ELIBMUSIC  "CFHTLIBMUSIC"  /* On -> libmusic debug to log file */
+#define CFHT_ELIBOCS    "CFHTLIBOCS"    /* On -> libocs debug to log file */
+#define CFHT_ELIBOMS    "CFHTLIBOMS"    /* On -> liboms debug to log file */
+#define CFHT_ELIBPIXD   "CFHTLIBPIXD"   /* On -> libpixd debug to log file */
+#define CFHT_ELIBRET    "CFHTLIBRET"    /* On -> libret debug to log file */
+#define CFHT_ELIBRET    "CFHTLIBRET"    /* On -> libret debug to log file */
+#define CFHT_ELIBSSX    "CFHTLIBSSX"    /* On -> libssx debug to log file */
+#define CFHT_ELIBTCS    "CFHTLIBTCS"    /* On -> libtcs debug to log file */
+#define CFHT_ELIBUI     "CFHTLIBUI"     /* On -> libui debug to log file */
+
+#define CFHT_ECOLORLOG	"CFHTCOLORLOG" 	/* Off -> no color on user log */
+
+#define CFHT_LOGU       "CFHTLOGU"      /* user log messages file name */
+#define CFHT_LOGS       "CFHTLOGS"      /* system log messages file name */
+#define CFHT_ELOGHOST	"CFHTLOGHOST" 	/* host for netbased logging */
+
+/* who  (NOTE, should be alphabetized only at release time) */
+typedef enum {
+    CFHT_MAIN = 0,		  /* caller is end user */
+    CFHT_LIB,			  /* caller is undefined library */
+    CFHT_LIBCAMAC,		  /* caller is CAMAC library */
+    CFHT_LIBCCD,		  /* caller is ccd library */
+    CFHT_LIBCFHT,		  /* caller is CFHT library */
+    CFHT_LIBCFP,		  /* caller is CFP library */
+    CFHT_LIBFF,			  /* caller is FITS library */
+    CFHT_LIBHH,			  /* caller is high level HPIB library */
+    CFHT_LIBMUSIC,		  /* caller is music library */
+    CFHT_LIBOCS,		  /* caller is OCS library */
+    CFHT_LIBRET,		  /* caller is reticon library */
+    CFHT_LIBCS,			  /* caller is client/server library */
+    CFHT_LIBDUCK,		  /* caller is DUCK library */
+    CFHT_LIBHELP,		  /* caller is Pegasus help library */
+    CFHT_LIBIDS,		  /* caller is IDS communication library */
+    CFHT_LIBPIXD,		  /* caller is pixel library */
+    CFHT_LIBTCS,		  /* caller is Telescope Control System */
+    CFHT_LIBUI,			  /* caller is user interface library */
+    CFHT_LIBCX,			  /* caller is coordinate transform library */
+    CFHT_LIBOMS,		  /* caller is OMS library */
+    CFHT_LIBSSX			  /* caller is ssx controller library */
+} cfht_log_who;
+
+/* type */
+typedef enum {
+    CFHT_LOG_ID = 0,		  /* client side initialization msg type */
+    CFHT_START,			  /* program is starting */
+    CFHT_STATUS,		  /* something interesting to the user */
+    CFHT_ERROR,			  /* error */
+    CFHT_FATAL = CFHT_ERROR,	  /* obsolete - about to exit due to error */
+    CFHT_ERRNO,			  /* do not use - error with errno message */
+    CFHT_WARN,			  /* warning - something's wrong */
+    CFHT_DONE,			  /* about to exit normally */
+    CFHT_LOGONLY,		  /* operational diagnositc info */
+    CFHT_DEBUG,			  /* program trace info */
+    CFHT_TIMING,		  /* print elapsed + delta times */
+    CFHT_FEEDINIT,		  /* init a feedback type output sink */
+    CFHT_FEEDQUIT,		  /* free up fd's, etc for feedback sinks */
+    CFHT_ROLLINIT,		  /* start up another roll type output sink */
+    CFHT_ROLLQUIT,		  /* shut down roll type output sinks */
+    CFHT_SHOWSINKS,		  /* used by developer to debug...  */
+    CFHT_SERVINIT		  /* re-init da logserver without killing it */
+} cfht_log_type;
+
+#define CFHT_DATE_SIZE 29	  /* size needed for cfht_date result */
+#define CFHT_UTDATE_SIZE 11	  /* size needed for cfht_UTdate result */
+#define CFHT_PFDATE_SIZE 11	  /* size needed for cfht_PFdate result */
+#define CFHT_TIME_SIZE 12	  /* size needed for cfht_time result */
+#define CFHT_UTTIME_SIZE 12	  /* size needed for cfhtUTtime result */
+
+/***********************
+ * parsing definitions *
+ ***********************/
+
+#define CFHT_STR_MATCH     1  /* check if input matches one of set of strings */
+#define CFHT_STR_INCLUDE   2  /* only pass through characters mentioned */
+#define CFHT_STR_EXCLUDE   3  /* only pass through characters not mentioned */
+#define CFHT_STR_NOWHITE   4  /* remove all white space from string */
+#define CFHT_STR_NOTRAIL   5  /* remove all trailing white space */
+#define CFHT_STR_ESCAPE    6  /* convert non-printing chars to escape codes */
+#define CFHT_STR_UNESCAPE  7  /* convert escape codes to chars */
+
+/**************************
+ * cfht_errno definitions *
+ **************************/
+
+typedef enum {
+    /* general error numbers */
+    CHECK_ERRNO = -1,		  /* check unix(tm) errno variable for reason */
+
+    /* unfortunately, some code stuffs errno into cfht_errno (e.g., old libids) */
+    /* so we need to use 0 but skip all low positive values */
+
+    NO_ERROR = 0,		  /* success */
+    NOT_A_TTY = 1000,		  /* historical uses, and general laziness */
+    PARSE_FAILED,		  /* unable to cope with input */
+    TOO_BIG,			  /* input exceeds hardware limit */
+    OUT_OF_RANGE,		  /* input exceeds software restriction */
+    TYPE_ERROR,			  /* incompatible or unexpected type */
+    UNIMPLEMENTED,		  /* feature not yet implemented */
+    BAD_OPTION,			  /* option passed in to routine was invalid */
+    INVALID_RANGE,		  /* range structure malformed or illegal */
+
+    /* OCS error codes */
+
+    OCS_FAILURE = 1100,		  /* internal OCS problem, e.g., buffers*/
+    OCS_NoSuchServer,		  /* requested non-existent server name */
+    OCS_SERVER_BUSY,		  /* couldn't get server's attention */
+    OCS_SERVER_T_REJECTED,	  /* task rejected by the server */
+    OCS_SERVER_T_FAILED,	  /* task didn't complete successfully */
+    OCS_NOTIFYCLOSED,		  /* server quit during transactions */
+    OCS_SERVER_TIMEOUT,		  /* server time-out on request */
+    OCS_ERROR,			  /* catchall */
+
+    /* OCS stuffs music's merrno in, so those should be here too */
+
+    M_NOSTART = 1200,		  /* did not call mstart() */
+    M_BODYTOOBIG,		  /* body overflow */
+    M_WRITERR,			  /* system error during write */
+    M_PARTWRITE,		  /* wrote partial message */
+    M_READERR,			  /* system error during read */
+    M_READCLOSED,		  /* read a closed fd */
+    M_BODYTOOSHORT,		  /* not enough in body for mget() */
+    M_BADMAGIC,			  /* bad magic numbers in header */
+    M_TIMEOUT,			  /* mread_until() timed-out */
+    M_NOQMSG,			  /* nothing to read on msg queue */
+
+    /* ids error codes */
+    IDS_openError = 1300,	  /* problem opening terminal */
+    IDS_termioError,		  /* problem doing termio ioctl */
+    IDS_FlushError,		  /* problem flushing buffer */
+    IDS_writeError,		  /* problem on write */
+    IDS_TimeOut,		  /* no response */
+    IDS_read0Bytes,		  /* read got nothing */
+    IDS_readError,		  /* read failed - not time out */
+
+    /* Client/Server codes */
+    CS_FakeMode = 1400,		  /* server is in fake mode */
+    CS_Disabled,		  /* server is disabled */
+
+    /* TCS error return codes */
+    TCS_InvalidCommand = 1500,	  /* invalid command sent to TCS */
+    TCS_InvalidArgument,	  /* invalid command argument sent to TCS */
+    TCS_NotTracking,		  /* TCS ignored command 'cause it's not on */
+    TCS_CommandFailed,		  /* TCS did command, but it did not work */
+    TCS_ConsolePrompt,		  /* TCS command prompt is probably up */
+    TCS_UnknownStatus,		  /* we don't understand returned code */
+
+    /* AOB error return codes */
+    AOB_UnknownCommand = 1600,	  /* we do not understand the command */
+    AOB_UnlockNotLocked,	  /* unlock when not locked */
+    AOB_NotLockOwner,		  /* unlock attempt by someone else? */
+    AOB_CurrentlyLocked,	  /* OMBA locked by another process */
+    AOB_BadArgValue,		  /* some argument was bad */
+
+    /* Coude f/4 and Gecko server conditions */
+    F4_UnknownCommand = 1700,	  /* empty / badly formed command */
+    F4_UnlockNotLocked,		  /* (NYI) already unlocked */
+    F4_NotLockOwner,		  /* (NYI) not server lock owner */
+    F4_CurrentlyLocked,		  /* (NYI) server locked by another process */
+    F4_BadArgValue,		  /* (NYI) server got bad argument */
+    F4_NotInitialized,		  /* no answer from the instrument hardware */
+    F4_TrafficError,		  /* server had trouble with ocs */
+    F4_DuckCommandError,	  /* problem sending to duck */
+    F4_DuckResponseError,	  /* problem with duck response */
+
+    cfht_errno_codes_filler	  /* ending dummy entry with no comma */
+} cfht_errno_CodesType;
+
+/*************************
+ * structure definitions *
+ *************************/
+
+struct cfht_rng_double {
+    double min;
+    double max;
+    BOOLEAN min_inclusive;
+    BOOLEAN max_inclusive;
+};
+struct cfht_rng_int {
+    int min;
+    int max;
+    BOOLEAN min_inclusive;
+    BOOLEAN max_inclusive;
+};
+struct cfht_rng_string {
+    char **string_array;
+};
+struct cfht_rng_char {
+    char *list_of_chars;
+};
+union cfht_ranges {
+    struct cfht_rng_double cfht_double_range;
+    struct cfht_rng_int cfht_int_range;
+    struct cfht_rng_string cfht_string_range;
+    struct cfht_rng_char cfht_char_range;
+};
+
+typedef union cfht_ranges *cfht_range_t;
+
+/*********************
+ * global references *
+ *********************/
+
+extern BOOLEAN cfht_debug;
+extern BOOLEAN cfht_error;
+extern BOOLEAN cfht_lib;
+extern BOOLEAN cfht_nodisp;
+extern int cfht_errno;
+
+extern union cfht_ranges *CFHT_RNG_RA;
+extern union cfht_ranges *CFHT_RNG_DEC;
+
+#define cfht_resetetimer() cfht_etimer(TRUE)
+#define cfht_delay(millisec) (void)cfht_sleep((millisec),1)
+
+/*
+ * Macro to put around system calls that might be interrupted by a signal.
+ * This is ripped from glibc.  It will keep re-trying systems calls until
+ * at least a partial success, or fatal error is encountered.  Note that
+ * read might still return FEWER BYTES than you told it to read if it is
+ * interrupted!
+ */
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(expression)               \
+({ long int __result;                                \
+     do __result = (long int) (expression);          \
+     while (__result == -1L && errno == EINTR);      \
+     __result; })
+#endif
+
+/*
+ * Special values that can be passed to cfht_signal()'s arg2
+ */
+
+#include <signal.h> /* for SIG_DFL and SIG_IGN */
+
+#define CFHT_SIG_TRAP ((PFV)cfht_signal_handler)
+  /* %%% The protos for CFHT_SIG_DFL et al are defined in terms of
+   *     SIG_DFL et al defined in signal.h, but unfortunately these
+   *     are not properly prototyped either :-(  Overriding them here
+   *     is kind of dangerous, and should be checked carefully.
+   */
+#undef  CFHT_SIG_DFL
+#undef  CFHT_SIG_IGN
+#define CFHT_SIG_DFL ((PFV)(0))
+#define CFHT_SIG_IGN ((PFV)(1))
+/*
+#define CFHT_SIG_DFL  ((PFV)SIG_DFL)
+#define CFHT_SIG_IGN  ((PFV)SIG_IGN)
+*/
+
+/*********************************************
+ * complete (?) list of all cfht_* functions *
+ *********************************************/
+
+char    *cfht_argsToString P((int argc, char *argv[]));
+void	cfht_awake P((double when_from_now, double how_often));
+char	*cfht_basename P((char *dest, char *filename, char *suffix));
+char	*cfht_cfhthome P((void));
+char	*cfht_date P((long *clockp));
+char	*cfht_PFdate P((int  days));
+char	*cfht_UTdate P((long *clockp));
+char	*cfht_UTtime P((long *clockp));
+char	*cfht_doupper P((char *str));
+double	cfht_dtime P((void));
+char	*cfht_fre P((unsigned char *src, unsigned char *dest, int *dsize));
+char	*cfht_toe P((unsigned char *src, unsigned char *dest, int ssize));
+double	cfht_etimer P((BOOLEAN reset));
+void	cfht_signal P((int signo, PFV handler));
+void	cfht_signal_block P((int signo));
+void	cfht_signal_unblock P((int signo));
+void    cfht_signal_handler P((int));
+BOOLEAN	cfht_signal_event P((int signo));
+BOOLEAN	cfht_signal_peek P((int signo));
+int	cfht_exec P((FILE_ID id, char *string, int type, volatile void *addr));
+int	cfht_system P((char *string));
+char	*cfht_frs P((char *dest, double val, int scale, int prec));
+void	cfht_genh P((int argc, char **argv, char **envp));
+void	usage P((char **msg));
+void	getcurdeath P((char *what));
+double	cfht_julian P((int year, int month, int day, int hour, int minute, double sec));
+void    cfht_fromjulian P((double jd, int *year, int *month, int *day, int *hour, int *minute, double *sec));
+char	*cfht_Mjulian P((long *clockp));
+char	*cfht_LocalSidTime P((long *clockp));
+BOOLEAN	cfht_checksem P((int semid));
+int	cfht_initsem P((char *path, char id));
+PASSFAIL cfht_setsem P((int semid));
+PASSFAIL cfht_setsemwait P((int semid, BOOLEAN sigign));
+PASSFAIL cfht_relsem P((int semid));
+PASSFAIL cfht_waitsemrel P((int semid, BOOLEAN sigign));
+PASSFAIL cfht_waitsemset P((int semid, BOOLEAN sigign));
+BOOLEAN cfht_checklock P((int fd));
+int	cfht_initlock P((char *path, char id));
+PASSFAIL cfht_setlock P((int fd));
+PASSFAIL cfht_setlockwait P((int fd, BOOLEAN sigign));
+PASSFAIL cfht_rellock P((int fd));
+PASSFAIL cfht_waitlockrel P((int fd, BOOLEAN sigign));
+PASSFAIL cfht_waitlockset P((int fd, BOOLEAN sigign));
+void	cfht_logv P((int who, int type, char *fmt, ...));
+void	cfht_logpv P((int who, int type, char *fmt, ...));
+void	cfht_log P((int who, int type, char *mess));
+void	cfht_log_proxy P((int who, int type, char *mess, char* id, int pid));
+PASSFAIL cfht_int P((char *in_str, int *out_addr, cfht_range_t rangeinfo));
+PASSFAIL cfht_double P((char *in_str, double *out_addr, cfht_range_t rangeinfo));
+long	cfht_od P((void));
+int	cfht_sleep P((int msec, int igsig));
+char	*cfht_string P((char *in_str, int operation, cfht_range_t rangeinfo));
+char	*cfht_time P((long *clockp));
+BOOLEAN	cfht_tob P((char *string));
+char	*cfht_tok P((char *string, char *sep, char **tail));
+void	cfht_goDaemon P((void));
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * See comments in missing_protos.h
+ */
+#include <missing_protos.h>
+
+#endif /* CFHTDOTH */
Index: /branches/eam_branch_20080223/Ohana/src/misc/include/cfht/exits.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/include/cfht/exits.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/include/cfht/exits.h	(revision 16632)
@@ -0,0 +1,61 @@
+/* Copyright (C) 1991, 94, 96    Canada-France-Hawaii Telescope Corp.    */
+/* This program is distributed WITHOUT any warranty, and is under the    */
+/* terms of the GNU General Public License, see the file COPYING    */
+/*****************************************************************************
+ *
+ * file: exits.h
+ * $Header: /cvsroot/pan-starrs/datasys/IPP/Ohana/src/misc/include/cfht/exits.h,v 1.1.1.1 2004-11-24 04:39:33 eugene Exp $
+ * $Locker:  $
+ *
+ * This file defines the various exit codes for controllers and handlers.
+ *
+ * NOTE: please see ui/listexits.c also when you change this !!!!!!!!!
+ *       The values of these exit codes are available symbolically in
+ *       shell scripts by using ". setexits".
+ *
+ * HISTORY
+ *
+ * who       when           what
+ * ------    -----------    ----------------------------------------------
+ * jk        24 Mar 1988    Original
+ *
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1  2001/07/25 02:59:24  eugene
+ * import Ohana
+ *
+ * Revision 1.4  96/08/12  15:30:00  15:30:00  thomas (Jim Thomas)
+ * Added AOB exit codes and some comments
+ * 
+ * Revision 1.3  94/12/14  17:27:07  17:27:07  thomas (Jim Thomas)
+ * Added pinger exit codes
+ * 
+ * Revision 1.2  93/06/26  17:59:06  17:59:06  steve (Steven Smith)
+ * added define for environment var to pass exit code of data taking handlers
+ * (ccdh, etc) for passing to all interested -E handlers.
+ * 
+ * Revision 1.1  91/09/24  17:38:54  17:38:54  steve (Steven Smith)
+ * Original checkin
+ * 
+ *****************************************************************************/
+
+#define EXIT_ENV_NAME	"CFHT_EXPOSURE_EXIT"
+#define EXIT_PASS 0		  /* everything is OK */
+#define EXIT_FAIL 1		  /* there was a real problem */
+#define EXIT_EXP_IN_PROGRESS 2	  /* can't do request - exposure already on */
+#define EXIT_EXP_ABORTED 3	  /* exposure trashed by user */
+#define EXIT_EXP_STOPPED 4	  /* exposure stopped by user */
+#define EXIT_CANCEL 5		  /* they hit the cancel button */
+
+/* pinger exit codes */
+#define PNG_EXIT_PASS EXIT_PASS	  /* service is healthy */
+#define PNG_EXIT_BUSY 1		  /* service is busy */
+#define PNG_EXIT_FAKE 2		  /* service is there but in FAKE mode */
+#define PNG_EXIT_NOTTHERE 3	  /* service isn't there at all */
+#define PNG_EXIT_NOTRAFFIC 4	  /* traffic isn't there */
+#define PNG_EXIT_ERROR 5	  /* some program or argument error happened */
+#define PNG_EXIT_HELP 6		  /* typed out the help message */
+
+/* AOB exit codes */
+#define AOB_EXIT_PASS EXIT_PASS	  /* things OK */
+#define AOB_EXIT_FAIL EXIT_FAIL	  /* real problem */
+#define AOB_EXIT_SEPARATION 2	  /* guide and object too far apart */
Index: /branches/eam_branch_20080223/Ohana/src/misc/include/missing_protos.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/include/missing_protos.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/include/missing_protos.h	(revision 16632)
@@ -0,0 +1,307 @@
+/* Copyright (C) 1997-1999  Canada-France-Hawaii Telescope Corp.         */
+/* This program is distributed WITHOUT any warranty, and is under the    */
+/* terms of the GNU General Public License, see the file COPYING         */
+/*****************************************************************************
+ *
+ * missing_protos.h - ANSI prototypes for systems that lack complete ANSI
+ *                    system header files (especially SunOS 4.x).  This file
+ *                    should be included with `#include <missing_protos.h>'
+ *                    from "cfht/cfht.h" so that it does not show up in
+ *                    the dependencies generated by "gcc -MM".  Proper ANSI
+ *                    systems should not need anything from this file anyway,
+ *                    and thus will not be tempted to re-compile everything
+ *                    which depends on this file every time we need to add
+ *                    a new prototype for the SunOS machines.
+ * $Id: missing_protos.h,v 1.2 2007-04-18 19:21:46 eugene Exp $
+ * $Locker:  $
+ *
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1  2004/11/24 04:39:33  eugene
+ * importing elixir components
+ *
+ * Revision 1.1.1.1  2001/07/25 02:59:23  eugene
+ * import Ohana
+ *
+ * Revision 1.11  2000/02/10 13:52:23  isani
+ * Added a few more prototypes.
+ * Changed to new way of doing SELECT() call.
+ *
+ * Revision 1.10  1999/07/30 22:14:51  thomas
+ * HP added openlog/syslog in 10.X, if it out there
+ *
+ * Revision 1.9  1999/07/13 21:27:28  thomas
+ * Added WCOREDUMP for SunOS
+ *
+ * Revision 1.8  1999/07/13 00:17:24  thomas
+ * Fix 1.7, Sidik's model was not sufficient, plus GNU rcs would not let me
+ * cancel it ???
+ *
+ * Revision 1.7  1999/07/03 04:10:58  thomas
+ * Changed select for 10.20
+ *
+ * Revision 1.6  98/07/10  10:38:35  10:38:35  thomas (Jim Thomas)
+ * Added perror, strerror, memset, drand48 to SunOS prototypes
+ * 
+ * Revision 1.5  97/12/18  21:28:43  21:28:43  thomas (Jim Thomas)
+ * Put floatingpoint.h back in, added strtol, changed __STDC__ to __GNUC__
+ * 
+ * Revision 1.4  97/12/18  02:38:20  02:38:20  isani (Sidik Isani)
+ * Added redefinition of CFHT_SIG_{DFL,IGN} for SunOS
+ * 
+ * Revision 1.3  1997/12/05 20:49:44  thomas
+ * Added definition of const if not ANSI C
+ *
+ * Revision 1.2  97/12/05  20:20:44  20:20:44  jcc (Jean-Charles Cuillandre)
+ * Added include of resource.h
+ * 
+ * Revision 1.1  1997/11/23 11:29:04  isani
+ * Initial revision
+ *
+ ****************************************************************************/
+
+#ifndef _INCLUDED_missing_protos
+#define _INCLUDED_missing_protos 1
+
+/*
+ * Make.Common defines *one* of the following:
+ *             SUNOS, SOLARIS, HPUX, LINUX, VXWORKS, or CYGWIN32
+ * We will use these here, but for projects where Make.Include is used
+ * instead of Make.Common, check for some other predefined symbols like
+ * __sun__ to try to figure out the system type.
+ */
+
+#if defined(SunOS) && !defined(SUNOS)
+#define SUNOS
+#endif
+
+#if (defined(Linux) || defined(linux)) && !defined(LINUX)
+#define LINUX
+#endif
+
+/*
+ * First, make sure SUNOS didn't get defined by accident for a Solaris box.
+ * We use SOLARIS instead, because they are really different OS's.
+ */
+
+#if defined(SUNOS) && defined(__svr4__)
+#undef SUNOS
+#ifndef SOLARIS
+#define SOLARIS
+#endif
+#endif
+
+#if !defined(SUNOS) && !defined(SOLARIS) && !defined(HPUX) && !defined(LINUX) && !defined(CYGWIN32) && !defined(VXWORKS)
+/*
+ * If Make.Common isn't being used ...
+ */
+#if defined(__sun__) || defined(sun)
+#ifndef sun
+#define sun
+#endif
+#ifdef __svr4__
+#define SOLARIS
+#else
+#define SUNOS
+#endif
+#else
+#if defined(__hpux__) || defined(hpux)
+#ifndef hpux
+#define hpux
+#endif
+#define HPUX
+#else
+error: Unknown system type!
+error: This software has not been tested on this platform.
+error: (comment out this block to compile anyway).
+#endif /* __hpux__ */
+#endif /* __sun__ */
+#endif /* !SUNOS && !SOLARIS && !HPUX ... */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* "const" has been added to a bunch of definitions, but that is ANSI :-( */
+#ifndef __STDC__
+#define const
+#endif
+
+/*
+ * Here are the hacks for the old suns, so we don't have to include them
+ * in each source file.  Solaris 2.x does not need any of this stuff...
+ */
+
+#ifdef SUNOS
+#define mktime timelocal
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#ifndef WCOREDUMP
+#define WCOREDUMP(n) 0
+#endif
+#include <malloc.h>
+#include <unistd.h>
+#ifdef __GNUC__
+#include <float.h>             /* for DBL_MIN and DBL_MAX */
+#else
+/* XXX RHL claims values.h is not needed
+ * #include <values.h> */
+#ifndef DBL_MIN
+#define DBL_MIN MINDOUBLE
+#define DBL_MAX MAXDOUBLE
+#endif
+#endif /* !__GNUC__ */
+#ifdef __GNUC__
+void    perror(const char *s);
+char	*strerror(int);
+int     ioctl(int, int, ...);
+int     select(int, fd_set*, fd_set*, fd_set*, struct timeval*);
+/* bzero is not ANSI, but the FD_ macros for select need it, so we need a
+ * proto here to prevent warnings.  Use memset() in your own code instead!
+ */
+void    bzero(char*, int);
+void*   memset(void*, int, size_t);
+int     socket(int, int, int);
+int     bind(int,  struct sockaddr*, int);
+int     listen(int, int);
+int     connect(int, struct sockaddr*, int);
+int     accept(int, struct sockaddr*, int*);
+int     shutdown(int, int);
+int     getsockname(int,struct sockaddr*,int*);
+int     getpeername(int,struct sockaddr*,int*);
+int     setsockopt(int,int,int,const void*,int);
+int     socketpair(int,int,int,int [2]);
+int     getrlimit(int,struct rlimit*);
+int     setrlimit(int,const struct rlimit*);
+int     gettimeofday(struct timeval *tp, struct timezone *tzp);
+int     rename(const char*, const char*);
+int     symlink(const char*, const char*);
+int     readlink(const char*, char*, int);
+int     lstat(const char*, struct stat*);
+int     openlog(const char*, int, int);
+int     syslog(int, const char*, ...);
+int     getitimer(int, struct itimerval*);
+int     setitimer(int, const struct itimerval*, struct itimerval*);
+int	fchmod(int, int);
+int	getdtablesize(void);
+int	semop(int, struct sembuf*, unsigned int);
+key_t	ftok(const char *, int);
+int	semget(key_t, int, int);
+int	lockf(int, int, off_t);
+int	ftruncate(int, off_t);
+/* %%% The protos for CFHT_SIG_DFL et al are defined in terms of
+ *     SIG_DFL et al defined in signal.h, but unfortunately these
+ *     are not properly prototyped either :-(  Overriding them here
+ *     is kind of dangerous, and should be checked carefully.
+ */
+#undef  CFHT_SIG_DFL
+#undef  CFHT_SIG_IGN
+#define CFHT_SIG_DFL ((PFV)(0))
+#define CFHT_SIG_IGN ((PFV)(1))
+#else  /* not __GNUC__ */
+#include <floatingpoint.h>
+void perror();
+char *strerror();
+void *memset();
+double drand48();
+long strtol();
+#endif /* __GNUC__ */
+#endif /* SUNOS */
+
+/*
+ * Here are the hacks that are also needed on the newer Solaris 2.x machines.
+ */
+#if defined(SUNOS) || defined(SOLARIS)
+#include <unistd.h>
+#ifdef __STDC__
+int	gethostname(char*, int);
+int     seteuid(uid_t euid);
+int     setegid(gid_t egid);
+int	setreuid(uid_t, uid_t);
+int	setregid(gid_t, gid_t);
+char*   crypt(const char*, const char*);
+#endif
+extern char** environ;
+#endif
+
+/*
+ * HPUX has some quirks too.
+ */
+#ifdef HPUX
+#if defined(OSVersion) && (OSVersion < 10)
+/*
+ * Make.Common defines HACK_SELECT directly and doesn't use this.
+ * See #if/not HACK_SELECT below also.
+ */
+#define HACK_SELECT
+#endif
+
+/* HP 10.20 seems not to define socklen_t */
+
+#define socklen_t int
+
+/* See comments above under SUNOS */
+#undef  CFHT_SIG_DFL
+#undef  CFHT_SIG_IGN
+#define CFHT_SIG_DFL ((PFV)(0))
+#define CFHT_SIG_IGN ((PFV)(1))
+
+#define seteuid(euid) setresuid(-1,(euid),-1)
+#define setegid(egid) setresgid(-1,(egid),-1)
+#ifdef __STDC__
+/* HP-UX 9 needed these.  Shouldn't hurt under 10.20 as long as they match. */
+void openlog(const char *, int, int);
+void syslog(int, const char *, ...);
+#endif
+#else /* not HP */
+#ifdef __STDC__
+/* only HP provides a prealloc function */
+int	prealloc(int fildes, unsigned size);
+#endif
+#endif
+
+/*
+ * CYGWIN32 is still in beta, so probably much of this stuff
+ * will need to be removed once this compiler stabilizes.
+ */
+#ifdef CYGWIN32
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#define seteuid(x) (0)
+#define setegid(x) (0)
+#define setuid(x)  (0)
+#define setgid(x)  (0)
+int readlink(const char*, char*, int);
+int select(int,fd_set*,fd_set*,fd_set*,struct timeval*);
+int lstat(const char*, struct stat*);
+int gettimeofday(struct timeval*, struct timezone*);
+const char* crypt(const char*, const char*);
+#endif
+
+/*
+ * Before version 10, HP defines fd_set, but doesn't use it in the prototype
+ * for select().  Also the count is size_t (which is right, why did ANSI
+ * lose that one?  I guess because C does not really support types :-( ).
+ * So do select() like this to avoid warnings on HP
+ *
+ *   Status = SELECT(n, read, write, error, &timestruct);
+ */
+#ifdef HACK_SELECT
+#define SELECT(n, read, write, error, tp)        \
+        select((size_t) (n), (int *) (read),     \
+               (int *) (write), (int *) (error), \
+	       (tp))
+#else
+/* Let the compiler check against a real prototype. */
+#define SELECT select
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !_INCLUDED_missing_protos */
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/SAOobjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/SAOobjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/SAOobjects.c	(revision 16632)
@@ -0,0 +1,87 @@
+# include "ohana.h"
+# include "dvo.h"
+
+main (int argc, char **argv) {
+
+  FILE *f;
+  char line[256], name[256];
+  Header header;
+  Coords coords;
+  double R, D, dR, dD;
+  double X, Y, dX, dY;
+  double angle;
+  int Nfield;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: %s (image.fits) (input)\n", argv[0]);
+    exit (1);
+  }
+
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "can't read header from file %s\n", argv[1]);
+    exit (1);
+  }
+
+  if (!GetCoords (&coords, &header)) {
+    fprintf (stderr, "can't find appropriate astrometry in image header\n");
+    exit (1);
+  }
+
+  /* load in the object description list */
+
+  /* fields for each line should be:
+     name (string)
+     Ra (dec. degrees)
+     Dec (dec. degrees)
+     dRa (arcsec)
+     dDec (arcsec)
+     angle (degrees)
+  */
+
+  if (argv[2][0] == '-') {
+    f = stdin;
+  } else {
+    f = fopen (argv[2], "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "can't open input data file\n");
+      exit (1);
+    }
+  }
+
+  while (scan_line (f, line) != EOF) {
+    Nfield = sscanf (line, "%s %lf %lf %lf %lf %lf", name, &R, &D, &dR, &dD, &angle);
+    
+    if (Nfield < 4) {
+      fprintf (stderr, "*");
+      continue;
+    }
+    
+    RD_to_XY (&X, &Y, R, D, &coords);
+
+    /* we won't worry about the case of cdelt1 != cdelt2,
+       in which case we don't have to worry about rotation 
+       between RA,DEC and X,Y for the calculation of the
+       slit lenghts.  Note that this assumption does not 
+       cause errors with the varying projected slitlength in
+       RA units, that is taken care of by the projection.
+       But, we are not taking into account a rotated slit */
+
+    dX = dR / 3600.0 / coords.cdelt1;
+    dY = dD / 3600.0 / coords.cdelt2;
+
+    switch (Nfield) {
+    case 4:
+      fprintf (stdout, "%s(%f,%f,%f)\n", name, X, Y, dX);
+      break;
+    case 5:
+      fprintf (stdout, "%s(%f,%f,%f,%f)\n", name, X, Y, dX, dY);
+      break;
+    case 6:
+      fprintf (stdout, "%s(%f,%f,%f,%f,%f)\n", name, X, Y, dX, dY, angle);
+      break;
+    }
+  }
+
+  if (f != stdin) fclose (f);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/addastro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/addastro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/addastro.c	(revision 16632)
@@ -0,0 +1,105 @@
+# include <ohana.h>
+# define BLOCK 0x1000
+
+main (int argc, char **argv) {
+
+  /* USAGE: addastro (cmp) (ref) */
+
+  int i, j, nbytes, itmp, oldsize;
+  double tmp;
+  Header header, refhead;
+  FILE *f, *g;
+  char filename[1024];
+  char buffer[0x1000];
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: addastro (cmp) (ref)\n");
+    exit (1);
+  }
+
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", argv[1]);
+    exit (1);
+  }
+  oldsize = header.size;
+
+  if (!gfits_read_header (argv[2], &refhead)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", argv[2]);
+    exit (1);
+  }
+
+  gfits_scan   (&refhead, "CDELT1",   "%lf", 1, &tmp);
+  gfits_modify (&header,  "CDELT1",   "%le", 1, tmp);
+  gfits_scan   (&refhead, "CDELT2",   "%lf", 1, &tmp);
+  gfits_modify (&header,  "CDELT2",   "%le", 1, tmp);
+  gfits_scan   (&refhead, "CRVAL1",   "%lf", 1, &tmp);
+  gfits_modify (&header,  "CRVAL1",   "%lf", 1, tmp);
+  gfits_scan   (&refhead, "CRVAL2",   "%lf", 1, &tmp);
+  gfits_modify (&header,  "CRVAL2",   "%lf", 1, tmp);
+  gfits_scan   (&refhead, "CRPIX1",   "%lf", 1, &tmp);
+  gfits_modify (&header,  "CRPIX1",   "%lf", 1, tmp);
+  gfits_scan   (&refhead, "CRPIX2",   "%lf", 1, &tmp);
+  gfits_modify (&header,  "CRPIX2",   "%lf", 1, tmp);
+  gfits_scan   (&refhead, "PC001001", "%lf", 1, &tmp);
+  gfits_modify (&header,  "PC001001", "%le", 1, tmp);
+  gfits_scan   (&refhead, "PC001002", "%lf", 1, &tmp);
+  gfits_modify (&header,  "PC001002", "%le", 1, tmp);
+  gfits_scan   (&refhead, "PC002001", "%lf", 1, &tmp);
+  gfits_modify (&header,  "PC002001", "%le", 1, tmp);
+  gfits_scan   (&refhead, "PC002002", "%lf", 1, &tmp);
+  gfits_modify (&header,  "PC002002", "%le", 1, tmp);
+  gfits_scan   (&refhead, "NPLYTERM", "%d",  1, &itmp);
+  gfits_modify (&header,  "NPLYTERM", "%d",  1, itmp);
+  gfits_scan   (&refhead, "NASTRO",   "%d",  1, &itmp);
+  gfits_modify (&header,  "NASTRO",   "%d",  1, itmp);
+  gfits_scan   (&refhead, "CERROR",   "%lf", 1, &tmp);
+  gfits_modify (&header,  "CERROR",   "%lf", 1, tmp);
+  gfits_scan   (&refhead, "CPRECISE", "%lf", 1, &tmp);
+  gfits_modify (&header,  "CPRECISE", "%lf", 1, tmp);
+
+  gfits_modify (&header, "CERROR", "%C", 1, "scatter in astrometry soln (arcsec)");
+  gfits_modify (&header, "CPRECISE", "%C", 1, "precision of astrometry soln (arcsec)");
+
+  /* write to file */
+  sprintf (filename, "%s.tmp", argv[1]);
+  if (!gfits_write_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't write header for %s\n", filename);
+    exit (1);
+  }
+  g = fopen (filename, "w");
+  if (g == NULL) {
+    fprintf (stderr, "ERROR: can't read write to %s\n", filename);
+    exit (1);
+  }
+  nbytes = fwrite (header.buffer, 1, header.size, g);
+  fseek (g, header.size, SEEK_SET); 
+
+  /* read date from file */
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", argv[1]);
+    exit (1);
+  }
+  fseek (f, oldsize, SEEK_SET); 
+
+  while ((nbytes = fread (buffer, 1, BLOCK, f)) > 0) {
+    if (nbytes != fwrite (buffer, 1, nbytes, g)) {
+      fprintf (stderr, "ERROR: failure writing output data file\n");
+      exit (0);
+    }
+  }
+  
+  fclose (f);
+  fclose (g);
+
+  sprintf (buffer, "mv %s %s~\n", argv[1], argv[1]);
+  system (buffer);
+
+  sprintf (buffer, "mv %s %s\n", filename, argv[1]);
+  system (buffer);
+
+  fprintf (stdout, "SUCCESS\n");
+
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/applyscat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/applyscat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/applyscat.c	(revision 16632)
@@ -0,0 +1,128 @@
+# include <ohana.h>
+# include <dvo.h>
+# define BYTES_STAR 66
+
+int main (int argc, char **argv) {
+
+  Header header;
+  Matrix matrix;
+  Stars *stars;
+  int Nstar, Nbytes, nbytes;
+  FILE *f;
+  char *buffer, line[10];
+  double dmag, ratio;
+  int i, x, y;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: applyscat (input) (scatter) (output)\n");
+    exit (1);
+  }
+
+  /* read smp header */
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "ERROR: can't find image file %s\n", argv[1]);
+    exit (1);
+  }
+
+  /* open file for star data */
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", argv[1]);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find expected number of stars */
+  gfits_scan (&header, "NSTARS", "%d", 1, &Nstar);
+  if (Nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+
+  /* allocate work space */
+  Nbytes = Nstar*BYTES_STAR;
+  ALLOCATE (stars, Stars, Nstar);
+  ALLOCATE (buffer, char, Nbytes + 1);
+
+  /* load in data */
+  nbytes = fread (buffer, 1, Nbytes, f);
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "ERROR: can't load in all stars\n");
+    exit (1);
+  }
+  buffer[Nbytes] = 0;
+  fclose (f);
+  
+  for (i = 0; i < Nstar; i++) {
+    dparse (&stars[i].X,  1, &buffer[i*BYTES_STAR]);
+    dparse (&stars[i].Y,  2, &buffer[i*BYTES_STAR]);
+    dparse (&stars[i].M,  3, &buffer[i*BYTES_STAR]);
+  }
+
+  if (!gfits_read_matrix (argv[2], &matrix)) {
+    fprintf (stderr, "ERROR: can't open scatter image file %s\n", argv[2]);
+    exit (1);
+  }
+  
+  /* flat' = flat*ratio
+     flux' = flux / ratio
+     mag'  = mag - dmag
+     dmag = -2.5*log10(ratio) 
+
+     ie, ratio = 1.1
+     flux' = 0.9*flux (flux' < flux)
+     dmag = -0.103
+     mag' = mag + 0.103 (mag' > mag)
+  */
+
+  for (i = 0; i < Nstar; i++) {
+    x = stars[i].X;
+    y = stars[i].Y;
+    ratio = gfits_get_matrix_value (&matrix, x, y);
+    dmag = -2.5*log10(ratio);
+    dmag = (dmag > +1.0) ? 0.0 : dmag;
+    dmag = (dmag < -1.0) ? 0.0 : dmag;
+    stars[i].M -= dmag;
+  }
+
+  /* full format line: "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", X, Y, M, dM, dophot, sky, Mgal, Map, fx, fy, df */
+  for (i = 0; i < Nstar; i++) {
+    sprintf (line, "%6.3f", stars[i].M);
+    memcpy (&buffer[i*BYTES_STAR+14], line, 6);
+  }
+
+  /* write smp header */
+  if (!gfits_write_header (argv[3], &header)) {
+    fprintf (stderr, "ERROR: can't write output file header %s\n", argv[3]);
+    exit (1);
+  }
+
+  /* open file for star data */
+  f = fopen (argv[3], "a");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open output file %s\n", argv[3]);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* load in data */
+  nbytes = Fwrite (buffer, 1, Nbytes, f, "char");
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "ERROR: problem writing stars\n");
+    exit (1);
+  }
+  fclose (f);
+
+  exit (0);
+}
+
+
+
+
+/* load in smp header
+   load in smp stars
+   load in scatter frame
+   apply corrections
+   write smp header
+   write smp stars
+*/
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/cfhtlog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/cfhtlog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/cfhtlog.c	(revision 16632)
@@ -0,0 +1,405 @@
+/****************************************************************************
+    Copyright (C) 1991, 1995    Canada-France-Hawaii Telescope Corp.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 1, or (at your option)
+    any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    Contact information:
+    CFHT, PO Box 1597, Kamuela, HI 96743, USA
+    daprog@cfht.hawaii.edu
+
+****************************************************************************/
+/*!****************************************************************************
+ * FILE
+ *
+ * $Header: /cvsroot/pan-starrs/datasys/IPP/Ohana/src/misc/src/cfhtlog.c,v 1.1 2003-01-17 18:42:35 eugene Exp $
+ * $Locker:  $
+ *
+ * ROUTINES
+ *
+ *
+ * HISTORY
+ * who          when            what
+ * ---------    ------------    ----------------------------------------------
+ *
+ * $Log: not supported by cvs2svn $
+ * Revision 1.1.1.1  2001/07/25 02:59:22  eugene
+ * import Ohana
+ *
+ * Revision 1.4  2001/01/25 21:21:06  bernt
+ * nothing changed
+ *
+ * Revision 1.3  1999/07/06 14:14:07  bernt
+ * *** empty log message ***
+ *
+ * Revision 1.2  98/06/09  22:50:01  22:50:01  bernt (Bernt Grundseth)
+ * clean some unused vars
+ * 
+ * Revision 1.1  97/11/21  11:28:53  11:28:53  bernt (Bernt Grundseth)
+ * Initial revision
+ * 
+ * Revision 1.5  96/11/17  22:59:00  22:59:00  bernt (Bernt Grundseth)
+ * *** empty log message ***
+ * 
+ * Revision 1.4  96/05/29  15:27:03  15:27:03  bernt (Bernt Grundseth)
+ * removed reading from current.dat file, because the last data file is 
+ * copied to uwila_data every ten minutes instead of the temporary kludge
+ * with the current.dat file.
+ * 
+ * Revision 1.3  96/05/29  07:23:29  07:23:29  bernt (Bernt Grundseth)
+ * *** empty log message ***
+ * 
+ * Revision 1.2  96/02/20  21:58:38  21:58:38  bernt (Bernt Grundseth)
+ * basic operations working still need improvements, range checking
+ * 
+ * Revision 1.1  96/02/19  22:31:43  22:31:43  bernt (Bernt Grundseth)
+ * Initial revision
+ * 
+ * 
+ ***************************************************************************!*/
+
+#include <stdio.h>
+#include <string.h>		  /* for string functions */
+#include <stdlib.h>		  /* for strtoul */
+#ifdef sun
+#define strtoul strtol		  /*   but sun doesn't have one */
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <time.h>		  /* for time functions */
+#ifdef sun
+#define mktime timelocal	  /*   but sun has a different name */
+#endif
+#include <errno.h>		  /* for ERANGE */
+
+#include <cfht/cfht.h>		  /* for P macro */
+#include <cfht/exits.h>           /* for standard exit codes */
+
+
+void dp_usage P((char *s));       	  /* usage exit */
+PASSFAIL TimeStringToTime P((char *String, time_t *Time));
+double cfht_julian();
+void cfht_fromjulian();
+double atof();
+
+time_t TimeNow;			  /* current time */
+static char path[] = "/data/logger/";
+#define NUMITEMS 915
+
+int main(argc, argv)
+    int argc;
+    char *argv[];
+{
+#ifndef __LINT__
+    static char rcs_id[] =
+      "$Header: /cvsroot/pan-starrs/datasys/IPP/Ohana/src/misc/src/cfhtlog.c,v 1.1 2003-01-17 18:42:35 eugene Exp $";
+#endif
+    /* command line argument values */
+    char *OurName;		  /* name of executing program */
+    char *Input = (char *) NULL;  /* name of [pipe] to read */
+    char *SessionName = (char *) NULL; /* name of session to match */
+    char *FromString = (char *) NULL; /* time to start outputting */
+    char *ToString = (char *) NULL; /* time to stop outputting */
+    char *ProbeString = (char *) NULL; /* probes  */
+    BOOLEAN Verbose = FALSE;	  /* want lots of debug output? */
+    BOOLEAN GoBackwards = TRUE;	  /* want LIFO or FIFO?  TRUE = LIFO */
+    BOOLEAN Dosuid = FALSE;	  /* do suid?  TRUE = yes */
+    unsigned int HoursBack = 0;	  /* start output this far back */
+    time_t FromTime;		  /* from time in internal form */
+    time_t ToTime;		  /* to time in internal form */
+
+    int Probes[100], nprobes;
+    double JDFrom, JDTo;
+    struct tm *tmd;
+
+
+
+    int i;			  /* index into argv */
+    int nlen;			  /* temporary  */
+
+    
+    OurName = cfht_basename((char *) NULL, argv[0], (char *) NULL);
+    if (argc < 2) {
+        dp_usage(argv[0]); /* else error */
+        exit(EXIT_FAIL);
+    }
+
+
+    time(&TimeNow);		  /* get current time */
+    tmd = localtime(&TimeNow);
+    printf("# DATE/TIME now %d %d %d %d %d %d\n",
+		   tmd->tm_year+1900, tmd->tm_mon+1, tmd->tm_mday,
+		   tmd->tm_hour, tmd->tm_min, tmd->tm_sec);
+    
+    for (i = 1 ; i < argc ; i++) {
+	if (argv[i][0] == '-') {
+	    switch (argv[i][1]) {
+
+	      case 'f':
+		FromString = argv[++i]; /* get from time from command line */
+		printf("# from date %s \n",FromString);
+                if (get_JDdate(FromString, &JDFrom)) {
+		    printf("# malformed date: %s \n",FromString);
+                    exit(EXIT_FAIL);
+                }
+		printf("#  julian day = %lf\n", JDFrom);
+		break;
+
+	      case 't':
+		ToString = argv[++i]; /* get to time from command line */
+		printf("# to date %s \n",ToString);
+                if (get_JDdate(ToString, &JDTo)) {
+		    printf("# malformed date: %s \n",ToString);
+                    exit(EXIT_FAIL);
+                }
+		printf("#  julian day = %lf\n", JDTo);
+		break;
+
+	      case 'p':
+		ProbeString = argv[++i]; /* get probes from command line */
+		break;
+
+	      case 'h':
+		/* one hour */
+
+                JDTo = cfht_julian(tmd->tm_year + 1900, tmd->tm_mon + 1,
+		  		  tmd->tm_mday, tmd->tm_hour,
+				  tmd->tm_min, (double)tmd->tm_sec);
+                JDTo = JDTo + 10./24.;
+                JDFrom = JDTo - 1.0/24.0;
+		printf("# INTERVAL: hour\n");
+		break;
+
+	      case 'd':
+		/* one day */
+
+                JDTo = cfht_julian(tmd->tm_year + 1900, tmd->tm_mon + 1,
+		  		  tmd->tm_mday, tmd->tm_hour,
+				  tmd->tm_min, (double)tmd->tm_sec);
+                JDTo = JDTo + 10./24.;
+                JDFrom = JDTo - 1.0;
+		printf("# INTERVAL: day\n");
+		break;
+
+	      case 'w':
+		/* one week */
+
+                JDTo = cfht_julian(tmd->tm_year + 1900, tmd->tm_mon + 1,
+		  		  tmd->tm_mday, tmd->tm_hour,
+				  tmd->tm_min, (double)tmd->tm_sec);
+                JDTo = JDTo + 10./24.;
+                JDFrom = JDTo - 7.0;
+		printf("# INTERVAL: week\n");
+		break;
+
+	      case 'm':
+		/* one month */
+
+                JDTo = cfht_julian(tmd->tm_year + 1900, tmd->tm_mon + 1,
+		  		  tmd->tm_mday, tmd->tm_hour,
+				  tmd->tm_min, (double)tmd->tm_sec);
+                JDTo = JDTo + 10./24.;
+                JDFrom = JDTo - 30.0;
+		printf("# INTERVAL: month\n");
+		break;
+
+	      default:
+		dp_usage(argv[0]); /* else error */
+	    }
+	} 
+
+    }
+
+    /* parse the probes numbers requested, and total # of probes */
+    if (ProbeString == NULL) { printf("# no probes selected\n");
+        exit(EXIT_FAIL);
+	}
+
+    get_tokens(ProbeString, " ,",Probes, &nprobes);
+    printf("# PROBES: %d ", nprobes); 
+    for (i = 0; i < nprobes; i++) {
+	if (Probes[i] < 0 || Probes[i] > 99 ) {
+	    printf("# error probe # out of range\n");
+            exit(EXIT_FAIL);
+        }
+    printf(" %d ", Probes[i]); 
+    }
+    printf("\n"); 
+    get_data(JDFrom, JDTo, Probes, nprobes); 
+
+
+    exit(EXIT_PASS);
+    return(0);			  /* dummy */
+}
+
+PASSFAIL
+get_data(JDstart, JDend, probes, nprobes)
+double JDstart, JDend;
+int probes[], nprobes;
+{
+    FILE *infile;
+    double julind, jd, jd0;
+    int year, month, day, hour, min, dayno;
+    double sec;
+    char fullname[64];
+    char filename[32];
+
+    char string[512];
+    double timestamp;
+    char data[915];
+    char bufstr[12];
+    long line = 0;
+    int nchar,j;
+
+    /* make JDstart to be in the 10 minutes boundary */
+    cfht_fromjulian(JDstart, &year, &month, &day, &hour, &min, &sec);
+    min = min/10*10;
+    sec = 0.;
+    JDstart = cfht_julian(year, month , day, hour, min, sec);
+
+
+    /* At this point it is assumed that the dates are OK.  */
+    /* get get year and day number at start  */
+    for (julind = JDstart -1; julind <= JDend; julind=julind+1.) {
+	jd = julind -10./24.;
+        cfht_fromjulian(jd, &year, &month, &day, &hour, &min, &sec);
+        jd0 = cfht_julian(year, 1 , 1, 0, 0, 0.);
+	dayno = jd -jd0 + 1;
+	strcpy (fullname, path);
+	sprintf(filename, "%d/%d%.3d.dat",year,(year-1900),dayno);
+	strcat (fullname, filename);
+
+	infile = fopen(fullname, "r");
+	if (infile == NULL) {
+	    if ( (int)julind < (int)JDend ) { /* last one ??? */
+	        sprintf (string, "# unable to open input file '%s'", fullname);
+	        perror (string);
+	    }
+
+	} else {
+        /*********************
+         * process each line *
+         *********************/
+            while ((nchar = fread(data, sizeof(char), NUMITEMS, infile)) > 0 ) {
+	        timestamp = atof(data) + 0.00001;
+
+	        if ((timestamp >= JDstart) && (timestamp <= JDend)) {
+                    cfht_fromjulian((timestamp-10./24.), &year, &month, &day,
+				    &hour, &min, &sec);
+		    printf("%lf ", timestamp - JDstart);
+		    printf("%lf ", (timestamp - JDstart)*24.0);
+		    printf("%.2d/%.2d/%.2d %.2d:%.2d ",
+		           year, month,day,hour,min);
+		    for (j = 0; j < nprobes; j++) {
+		        strncpy(bufstr, data + (14 + probes[j]*9), 9);
+		        bufstr[9] =0;
+		        printf("%s ", bufstr);
+		    }
+		    printf("\n");
+                }
+            }
+	    fclose(infile);
+        }
+
+    }
+    return(PASS);
+}
+
+
+PASSFAIL
+get_JDdate(datestring, JD)
+char *datestring;
+double *JD;
+{
+    int vect[10];
+    int n;
+    int year, month, day, hour, min, sec;
+    get_tokens(datestring, " /:", vect, &n);
+    if (n < 3 ) {
+	return(FAIL);
+    }
+/*    year = vect[0] + 1900; */
+    year = vect[0];
+    if (year < 1993 || year > 2010 )
+	return(FAIL);
+    month = vect[1];
+    if (month < 1 || month > 12 )
+	return(FAIL);
+    day = vect[2];
+    if (day < 1 || day > 31 )
+	return(FAIL);
+    hour = 0;
+    min  = 0;
+    sec  = 0;
+    if ( n > 3 ) {
+       hour = vect[3];
+       if (hour < 0 || hour > 23 )
+           return(FAIL);
+    }
+    if ( n > 4 ) {
+       min = vect[4];
+       if (min < 0 || min > 59 )
+           return(FAIL);
+    }
+    if ( n > 5 ) {
+       sec = vect[5];
+       if (sec < 0 || sec > 59 )
+           return(FAIL);
+    }
+    *JD = cfht_julian(year, month, day, hour, min, (double)sec);
+    *JD = *JD + 10.0 / 24.0;
+    return(PASS);
+}
+
+PASSFAIL
+get_tokens(buf, sep, vect, nitems)
+char buf[];
+char *sep;
+int vect[];
+int *nitems;
+{
+    char *cp;
+    int i;
+
+    cp = strtok(buf, sep);
+    vect[0] = atoi(cp);
+
+
+    i = 1;
+    while( 1 ) {
+
+        if( (cp = strtok(0, sep) ) == 0 ) {
+        break;
+        }
+        vect[i] = atoi(cp);
+        i++;
+    }
+    *nitems = i;
+
+    return(PASS);
+}
+
+/* usage: prints default error message and then exits */
+/* s is program name */
+void dp_usage(s)
+    char *s;
+{
+    fprintf(stderr, "Usage: %s\n", s);
+    fprintf(stderr, " [-h ] [-d] [-w] [-m]\n");
+    fprintf(stderr, " 1 hour, 1 day, 1 week, 1 month  \n");
+    fprintf(stderr, " [-f timefrom] [-t timeto] -p probeNumber\n");
+    fprintf(stderr, " Ex. -f \"2000/02/23 10:00:00\" -t \"2000/02/24\" -p 1,2,13,45\n");
+    exit(EXIT_FAIL);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/cubefilter.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/cubefilter.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/cubefilter.c	(revision 16632)
@@ -0,0 +1,110 @@
+# include <ohana.h>
+# define D_NFILES 100
+
+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 != 5) {
+    fprintf (stderr, "USAGE: minmaxfilter infile 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);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/dastro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/dastro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/dastro.c	(revision 16632)
@@ -0,0 +1,112 @@
+# include <ohana.h>
+
+main (argc, argv)
+     int argc;
+     char **argv;
+{
+  
+  int status, REL, N;
+  Header header, refhead;
+  char  filename[1024], reffile[1024], *p;
+  double X_O, X_X, X_Y, Y_O, Y_X, Y_Y;
+  double RA_O, RA_X, RA_Y, DEC_O, DEC_X, DEC_Y;
+  double ra_o, ra_x, ra_y, dec_o, dec_x, dec_y;
+  double dRA, dDEC, dX, dY, dra, ddec;
+  
+  if (N = get_argument (argc, argv, "-rel")) {
+    remove_argument (N, &argc, argv);
+    REL = TRUE;
+  }
+  else {
+    REL = FALSE;
+  }
+  
+  while (fscanf (stdin, "%s", filename) != EOF) {
+    
+    status = gfits_read_header (filename, &header);
+    if (!status) {
+      fprintf (stderr, "error opening file %s\n", filename);
+      continue;
+    }
+    status = gfits_scan (&header, "rREF", "%s", 1, reffile);
+    status &= gfits_scan (&header, "X_O", "%lf", 1, &X_O);
+    status &= gfits_scan (&header, "X_X", "%lf", 1, &X_X);
+    status &= gfits_scan (&header, "X_Y", "%lf", 1, &X_Y);
+    status &= gfits_scan (&header, "Y_O", "%lf", 1, &Y_O);
+    status &= gfits_scan (&header, "Y_X", "%lf", 1, &Y_X);
+    status &= gfits_scan (&header, "Y_Y", "%lf", 1, &Y_Y);
+    status &= gfits_scan (&header, "dX", "%lf", 1, &dX);
+    status &= gfits_scan (&header, "dY", "%lf", 1, &dY);
+    if (!status) {
+      fprintf (stderr, "file missing rastro info: %s\n", filename);
+      gfits_free_header (&header);
+      continue;
+    }
+
+    while ((p = strstr (reffile, "'")) != NULL) {
+      *p = ' ';
+    }
+    stripwhite (reffile);
+    if ((p = strrchr(reffile, '.')) != NULL)
+      strcpy(p, ".head");
+    else 
+      strcat(reffile, ".head");
+
+    if (!strcmp (reffile, filename)) {
+      fprintf (stderr, "%s is %s, not altering\n", reffile, filename);
+      continue;
+    }
+
+    status  = gfits_read_header (reffile, &refhead);
+    if (!status) {
+      fprintf (stderr, "error opening file %s\n", reffile);
+      continue;
+    }
+    status &= gfits_scan (&refhead, "RA_O", "%lf", 1, &RA_O);
+    status &= gfits_scan (&refhead, "RA_X", "%lf", 1, &RA_X);
+    status &= gfits_scan (&refhead, "RA_Y", "%lf", 1, &RA_Y);
+    status &= gfits_scan (&refhead, "DEC_O", "%lf", 1, &DEC_O);
+    status &= gfits_scan (&refhead, "DEC_X", "%lf", 1, &DEC_X);
+    status &= gfits_scan (&refhead, "DEC_Y", "%lf", 1, &DEC_Y);
+    status &= gfits_scan (&refhead, "dRA",   "%lf", 1, &dRA);
+    status &= gfits_scan (&refhead, "dDEC",  "%lf", 1, &dDEC);
+    if (!status) {
+      fprintf (stderr, "file missing rastro info: %s\n", reffile);
+      gfits_free_header (&header);
+      gfits_free_header (&refhead);
+      continue;
+    }
+
+    fprintf (stderr, "%f %f %f\n%f %f %f\n", RA_O, RA_X, RA_Y, DEC_O, DEC_X, DEC_Y);
+    fprintf (stderr, "\n%f %f %f\n%f %f %f\n", X_O, X_X, X_Y, Y_O, Y_X, Y_Y);
+    
+    ra_o = RA_X*X_O + RA_Y*Y_O + RA_O;
+    dec_o = DEC_X*X_O + DEC_Y*Y_O + DEC_O;
+    
+    ra_x = RA_X*X_X + RA_Y*Y_X;
+    ra_y = RA_X*X_Y + RA_Y*Y_Y;
+    dec_x = DEC_X*X_X + DEC_Y*Y_X;
+    dec_y = DEC_X*X_Y + DEC_Y*Y_Y;
+    
+    fprintf (stderr, "%f %f %f\n%f %f %f\n", ra_o, ra_x, ra_y, dec_o, dec_x, dec_y);
+
+    dra = sqrt(dRA*dRA + SQ(3600*dX*RA_X) + SQ(3600*dY*RA_Y));
+    ddec = sqrt(dDEC*dDEC + SQ(3600*dX*DEC_X) + SQ(3600*dY*DEC_Y));
+			   
+    status &= gfits_modify (&header, "RA_O", "%lf", 1, ra_o);
+    status &= gfits_modify (&header, "RA_X", "%le", 1, ra_x);
+    status &= gfits_modify (&header, "RA_Y", "%le", 1, ra_y);
+    status &= gfits_modify (&header, "DEC_O", "%lf", 1, dec_o);
+    status &= gfits_modify (&header, "DEC_X", "%le", 1, dec_x);
+    status &= gfits_modify (&header, "DEC_Y", "%le", 1, dec_y);
+    status &= gfits_modify (&header, "dRA",   "%lf", 1, dra);
+    status &= gfits_modify (&header, "dDEC",  "%lf", 1, ddec);
+    
+    gfits_write_header (filename, &header);
+    gfits_free_header (&header);
+    gfits_free_header (&refhead);
+    
+  }
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/dbtest.c.failed
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/dbtest.c.failed	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/dbtest.c.failed	(revision 16632)
@@ -0,0 +1,106 @@
+# include <ohana.h>
+
+static char dbfile[] = "/h/eugene/d4/flattest/test.db";
+
+void main (int argc, char **argv) {
+
+  char buffer[10000];
+  int vbuffer[10000];
+  FILE *f;
+  int i, j, Nrun, status, fd;
+
+  if (argc > 1) {
+    if (!strcmp (argv[1], "-check")) {
+      f = fopen (dbfile, "r");
+      if (f == (FILE *) NULL) {
+	fprintf (stderr, "ERROR: can't open file\n");
+	exit (0);
+      }
+      status = fread (buffer, 1, 5000, f);
+      if (status != 5000) {
+	fprintf (stderr, "ERROR: can't read header\n");
+	exit (0);
+      }
+      sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+      for (j = 0 ; j < Nrun; j++) {
+	status = fread (vbuffer, 4, 1000, f);
+	if (status != 1000) {
+	  fprintf (stderr, "ERROR: can't read data\n");
+	  exit (0);
+	}
+	for (i = 0; i < 1000; i++) {
+	  if (vbuffer[i] != j) {
+	    fprintf (stderr, "ERROR: invalid data %d/%d,  %d - %d\n", j, Nrun, i, vbuffer[i]);
+	    exit (0);
+	  }
+	}
+      }
+      fprintf (stderr, "Data is good\n");
+      exit (0);
+    }
+  }	  
+
+  /* read the header block, change one line, write the header block */
+  /* write a block to EOF */
+
+  /* if lockfile exists, program will complain and quit */
+  if ((fd = setlockfile (dbfile, 60.0)) == -1) {
+    fprintf (stderr, "ERROR: can't set lock on %s\n", dbfile);
+    exit (1);
+  }
+
+  f = fopen (dbfile, "r");
+  if (f == (FILE *) NULL) {
+    /* make a header block */
+    for (i = 0; i < 50; i++) {
+      memset (&buffer[100*i], 65+i, 99);
+      buffer[100*i + 99] = '\n';
+    }
+    sprintf (&buffer[500], "THIS IS TEST    0   \n");
+    Nrun = 0;
+  } else {
+    status = fread (buffer, 1, 5000, f);
+    if (status != 5000) {
+      fprintf (stderr, "ERROR: can't read data\n");
+      exit (0);
+    }
+    
+    sscanf (&buffer[500], "%*s %*s %*s %d", &Nrun);
+    Nrun ++;
+    sprintf (&buffer[500], "THIS IS TEST    %d   \n", Nrun);
+  }
+
+  f = fopen (dbfile, "r+");
+  if (f == NULL) {
+    f = fopen (dbfile, "w");
+    if (f == NULL) {
+      fprintf (stderr, "ERROR: can't create/open file %s\n", dbfile);
+      exit (0);
+    }
+  }
+
+  /* position to begining of file to write header */
+  fseek (f, 0, SEEK_SET);
+  status = fwrite (buffer, 1, 5000, f);
+  if (status != 5000) {
+    fprintf (stderr, "ERROR: failed writing data to header\n");
+    exit (0);
+  }
+
+  for (i = 0; i < 1000; i++) vbuffer[i] = Nrun;
+
+  fseek (f, 0, SEEK_END);
+  status = fwrite (vbuffer, 4, 1000, f);
+  if (status != 1000) {
+    fprintf (stderr, "ERROR: failed writing data to file\n");
+    exit (0);
+  }
+
+  if (!gnfsflush (dbfile)) {
+    fprintf (stderr, "ERROR: failed to flush image catalog\n");
+    exit (0);
+  }
+
+  clearlockfile (dbfile, fd);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/doscript.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/doscript.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/doscript.c	(revision 16632)
@@ -0,0 +1,179 @@
+# include <ohana.h>
+
+void args(), error();
+int COLDSTART, OUTIMAGE;
+double THRESHOLD;
+
+main (argc, argv) 
+     int argc;
+     char **argv;
+{
+  
+  FILE *f, *ft;
+  char name[128], root[128], line[256];
+  double psfx, psfy, sky, tilt;
+
+  args (argc, argv);
+
+  while (fscanf (stdin, "%s", root) != EOF) {
+    if (COLDSTART) {
+      fscanf (stdin, "%lf %lf", &psfx, &sky);
+    }
+    else {
+      fscanf (stdin, "%lf %lf %lf %lf", &psfx, &psfy, &tilt, &sky);
+    }
+
+    /* we demand that the image names have the *.f extension */
+    if (strncmp (&root[strlen(root) - 2], ".f", 2)) {
+      fprintf (stderr, "valid image names are *.f\n");
+      exit (0);
+    }
+
+    ft = fopen (root, "r");
+    if (ft == NULL) {
+      fprintf (stderr, "image %s does not exist\n", root);
+      continue;
+    }
+    fclose(ft);
+
+    /* root contains *.f, remove the .f portion: */
+    root[strlen(root) - 2] = 0;
+
+    strcpy (name, root);
+    strcat (name, ".par_in");
+    f = fopen (name, "w");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "couldn't write to parameter file %s\n", name);
+      continue;
+    }
+    fprintf (f, "FWHM = %f\n", psfx);
+    fprintf (f, "SKY = %f\n", sky);
+    if (!COLDSTART) {
+      fprintf (f, "AXIS_RATIO = %f\n", psfy/psfx);
+      fprintf (f, "TILT = %f\n", tilt);
+    }
+    fprintf (f, "=\n");
+    fprintf (f, "PARAMS_DEFAULT = 'dophot.params'\n");
+    fprintf (f, "PARAMS_OUT = '%s.par_out'\n", root);
+    if (THRESHOLD) {
+      fprintf (f, "AUTOTHRESH = 'NO'\n");     
+      fprintf (f, "THRESHMIN = %f\n", THRESHOLD);
+    }
+    else {
+      fprintf (f, "AUTOTHRESH = 'YES'\n");     
+    }
+    fprintf (f, "=\n");
+    fprintf (f, "IMAGE_IN = '%s.f'\n", root);
+    if (OUTIMAGE) 
+      fprintf (f, "IMAGE_OUT = '%s.s'\n", root);
+    else
+      fprintf (f, "IMAGE_OUT = ' '\n");
+    if (!COLDSTART) {
+      strcpy (name, root);
+      strcat (name, ".obj_out");
+      ft = fopen (name, "r");
+      if (ft != (FILE *) NULL) {
+	fclose (ft);
+	sprintf (line, "mv %s.obj_out %s.obj_in\0", root, root);
+	system (line);
+	fprintf (f, "OBJECTS_IN = '%s.obj_in'\n", root);
+      }
+      else {
+	fprintf (f, "OBJECTS_IN = ' '\n");
+      }
+    }
+    else {
+      fprintf (f, "OBJECTS_IN = ' '\n");
+    }
+    fprintf (f, "OBJECTS_OUT = '%s.obj_out'\n", root);
+    fprintf (f, "=\n");
+
+    if (!COLDSTART) {
+      strcpy (name, root);
+      strcat (name, ".shd_out");
+      ft = fopen (name, "r");
+      if (ft != (FILE *) NULL) {
+	fclose (ft);
+	sprintf (line, "mv %s.shd_out %s.shd_in\0", root, root);
+	system (line);
+	fprintf (f, "SHADOWFILE_IN = '%s.shd_in'\n", root);
+      }
+      else {
+	fprintf (f, "SHADOWFILE_IN = ' '\n");
+      }
+    }
+    else {
+      fprintf (f, "SHADOWFILE_IN = ' '\n");
+    }
+    fprintf (f, "SHADOWFILE_OUT = '%s.shd_out'\n", root);
+    
+    fprintf (f, "END\n");
+    fclose (f);
+
+    fprintf (stdout, "dophot << END > %s.dout\n", root);
+    fprintf (stdout, "%s.par_in\n", root);
+    fprintf (stdout, "END\n");
+  }
+}
+
+/* 
+  original image: image
+  flattened im:   image.f
+  star sub image: image.s
+  dp params in:   image.par_in
+  dp params out:  image.par_out
+  dp objects in:  image.obj_in
+  dp objects out: image.obj_out
+  dp shadow in:   image.shd_in
+  dp shadow out:  image.shd_out
+*/
+
+void args (argc, argv)
+     int      argc;
+     char   **argv;
+{
+  
+  int N;
+  
+  if (get_argument (argc, argv, "-h") || get_argument (argc, argv, "-help")) {
+    error ();
+  }
+
+  COLDSTART = TRUE;
+  if (N = get_argument (argc, argv, "-w")) {
+    remove_argument (N, &argc, argv);
+    COLDSTART = FALSE;
+  }
+  if (N = get_argument (argc, argv, "-warm")) {
+    remove_argument (N, &argc, argv);
+    COLDSTART = FALSE;
+  }
+  
+  OUTIMAGE = FALSE;
+  if (N = get_argument (argc, argv, "-sub")) {
+    remove_argument (N, &argc, argv);
+    OUTIMAGE = TRUE;
+  }
+
+  THRESHOLD = 0;
+  if (N = get_argument (argc, argv, "-t")) {
+    remove_argument (N, &argc, argv);
+    if (N < argc) {
+      THRESHOLD = atof (argv[N]);
+    } 
+    else {
+      error ();
+    }   
+  }
+}
+
+void error ()
+{
+  fprintf (stderr, "USAGE:\n");
+  fprintf (stderr, "  doscript [-w/-warm] [-sub] [-t threshold]\n");
+  fprintf (stderr, "    default is coldstart -- takes from stdin: filename FWHM sky\n");
+  fprintf (stderr, "    -w, -warm: warmstart -- takes from stdin: filename FWHMx FWHMy angle sky'\n");
+  fprintf (stderr, "    -t: set minimum threshold, also sets AUTOTHRESH = 'NO'\n");
+  fprintf (stderr, "    -sub: generate star-substracted images\n");
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/dostat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/dostat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/dostat.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include <ohana.h>
+
+main() {
+
+  FILE *f, *fopen();
+  char file[50];
+  int N,n1,n2,n3,n4,n5,n6,n7,n8,nperf,type,status;
+  double Fx,Fy,alpha, FWHMx,FWHMy,angle, ap, F, S, sky;
+  double dtype, A, A2, Ap, Ap2, apmifit, df, S2;
+  char line[512];
+
+  while (fscanf (stdin, "%s", file) != EOF) {
+    f = fopen (file, "r");
+    if (f == NULL) {
+      fprintf (stderr, "file %s not found\n", file);
+      continue;
+    }
+    n1 = n2 = n3 = n4 = n5 = n6 = n7 = n8 = nperf = 0;
+    S2 = S = Fx = Fy = alpha = A = A2 = 0;
+    while (scan_line (f, line) != EOF) {
+      status = TRUE;
+      status &= dparse (&dtype, 2, line);
+      status &= dparse (&df,   6, line);
+      status &= dparse (&sky,   7, line);
+      status &= dparse (&FWHMx, 8, line);
+      status &= dparse (&FWHMy, 9, line);
+      status &= dparse (&angle, 10, line);
+      status &= dparse (&ap,      12, line);
+      status &= dparse (&apmifit, 15, line);
+      if (!status) {
+	fprintf (stderr, "error in file %s, line %d\n", file, n1+n2+n3+n4+n5+n6+n7+n8);
+	continue;
+      }
+      type = dtype;
+      switch (type) {
+      case 1:
+	n1 ++;
+	S += sky;
+	if (ap < 99) {
+	  nperf ++;
+	  A += apmifit/(df*df);
+	  A2 += apmifit*apmifit/(df*df);
+	  S2 += 1.0/(df*df);
+	}
+	Fx = FWHMx;
+	Fy = FWHMy;
+	alpha = angle;
+	break;
+      case 2:
+	n2 ++;
+	break;
+      case 3:
+	n3 ++;
+	break;
+      case 4:
+	n4 ++;
+	break;
+      case 5:
+	n5 ++;
+	break;
+      case 6:
+	n6 ++;
+	break;
+      case 7:
+	n7 ++;
+	break;
+      case 8:
+	n8 ++;
+	break;
+      }
+    }
+    S= S / (1.0*n1);
+    F = nperf / (1.0 * n1);
+    N = n1+n2+n3+n4+n5+n6+n7+n8;
+    Ap = A / S2;
+    Ap2 = sqrt(A2 / (S2) - Ap*Ap);
+    fprintf (stdout, "%s: %5d %5d %5d %5d %5d %5d %5d %5d",
+	     file,n1,n2,n3,n4,n5,n6,n7,n8);
+    fprintf (stdout, "  %5d %5d  %5.3f %7.2f %7.2f %7.1f %7.1f %7.3f %7.3f\n",
+	     N, nperf, F, Fx, Fy, alpha, S, Ap, Ap2);
+    fclose(f);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fakecmp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fakecmp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fakecmp.c	(revision 16632)
@@ -0,0 +1,137 @@
+# include <ohana.h>
+static char reserved[] = "COMMENT  Reserved space.  This line can be used to add a new FITS card.";
+
+void main (int argc, char **argv) {
+
+  int i, j, N, status;
+  int Nreserved, start_size;
+  char *p, keyword[16], line[256];
+  FILE *f;
+  Header header;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: gfits_insert (input) (template) (output)\n");
+    exit (2);
+  }
+  
+  /*
+    input file consists of: RA DEC MAG dMAG
+    we generate an artificial image with 1 arcsec/pix
+    and the pixel (0,0) at (<RA>,<DEC>)
+    
+    1) find <RA>, <DEC>
+    2) convert X,Y to R,D using <RA>,<DEC> (ra---sin)
+    3) fix template entries: CRVAL1, CRVAL2, NSTARS, (JD)
+    4) write out template
+    5) write out infile in correct format:
+    X     Y      M      dM   T S   Ma     Mb        Fx     Fy  Th
+    237.2 2646.1 16.748 085  1 2.0 17.930 17.768    nan    nan -48.0
+  */
+
+  /* allocate data space */
+  NSTARS = 1000;
+  ALLOCATE (ra, double, NSTARS);
+  ALLOCATE (dec, double, NSTARS);
+  ALLOCATE (mag, double, NSTARS);
+  ALLOCATE (dmag, double, NSTARS);
+
+  /* open data file */
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open data file %s\n", argv[1]);
+    exit (1);
+  }
+
+  /* load data file into array */
+  for (i = 0;
+       fscanf (f, "%lf %lf %lf %lf", &ra[i], &dec[i], &mag[i], &dmag[i]) != EOF;
+       i++) {
+    
+    if (i == NSTARS - 1) {
+      NSTARS += 1000;
+      REALLOCATE (ra, double, NSTARS);
+      REALLOCATE (dec, double, NSTARS);
+      REALLOCATE (mag, double, NSTARS);
+      REALLOCATE (dmag, double, NSTARS);
+    }
+  }
+  NSTARS = i;
+
+  /* calculate <ra>, <dec> */
+  RA = DEC = 0;
+  for (i = 0; i < NSTARS; i++) {
+    RA += ra[i];
+    
+
+  /* load header from image file */
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "can't open fits file %s\n", argv[1]);
+    exit (1);
+  }
+  start_size = header.size;
+
+  /* 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;
+      }
+    }
+
+    /* 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], reserved, Nreserved)) {
+	p = &header.buffer[i];
+      }
+    }
+    if (p == (char *) NULL) {
+      fprintf (stderr, "no more reserved spaces!\n");
+      exit (1);
+    }
+
+    /* insert the new line here */
+    strncpy (p, line, 80);
+  }
+
+  fclose (f);
+
+  /* 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, 0, 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);
+  }
+  fclose (f);
+
+  exit (0);
+}
+    
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fakedist.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fakedist.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fakedist.c	(revision 16632)
@@ -0,0 +1,548 @@
+# include <ohana.h>
+
+# define NGAUSS 2048
+double drand48();
+double gaussint[NGAUSS];
+double gaussian();
+double rnd_gauss();
+
+# define MMIN 1.0
+# define MMAX 120.0
+double rnd_mass();
+double MassTerm;
+
+# define NMASS 87
+# define DMASS 0.05
+# define NPARMAX 30
+int N_Av, N_dist, N_alpha, N_age, NSTARS, NTRY;
+double Av[NPARMAX], dist[NPARMAX], alpha[NPARMAX], age[NPARMAX];
+
+double dVo, dVref, dMo;   /* determine the noise distribution */
+
+double ldA, lAo, ldM, lMo;
+double UV0, V0, DV, DUV;
+Header header, UV_h, V_h, mass_h, age_h;
+Matrix matrix, UV_i, V_i, mass_i, age_i;
+int UV_NX, UV_NY;
+float *UVbuffer, *Vbuffer;
+int MS_NX, MS_NY;
+float *Mbuffer, *Abuffer;
+
+char fakefile[256], magfile[256], colorfile[256], massfile[256], agefile[256];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, j, m, n, M, A, Nstars;
+  double mag, color, mass, noise, inflation;
+  float *in;
+  char line[1024];
+
+  load_parameters (argc, argv);
+
+  init_outmatrix (); 
+ 
+  gauss_init ();
+
+  read_datafiles ();
+
+  gfits_modify (&header, "SFR", "%s", 1, "Star Formation Rate (Mo / Myr)");
+  for (i = 0; i < N_Av; i++) {
+    for (j = 0; j < N_dist; j++) {
+      for (m = 0; m < N_alpha; m++) {
+	
+	MassTerm = (pow((MMAX/MMIN), -alpha[m]) - 1.0);
+	for (n = 0; n < N_age; n++) {
+	  fprintf (stderr, "age: %d %f -- %f\n", n, age[n], age[n+1]);
+	  
+	  mass = 0;
+	  for (Nstars = 0; Nstars < NSTARS; Nstars++) {
+	    fakestar (Av[i], dist[j], alpha[m], age[n], age[n+1], 
+		      &mag, &color, &mass, &noise);
+	    
+	    magtomass (Av[i], dist[j], mag, color, noise, &M, &A, &inflation);
+
+	    if (inflation > 0.0) add_to_outmatrix (i, j, m, n, A, M, inflation);
+	    
+	  }
+	  /* store the parameters and total mass for this Mass*Age matrix in the (N_age) column */
+	  /* mass is the total mass generated between 1 and 120 Mo for the NSTARS points in this matrix */
+	  sprintf (line, "SFR_%0d\0", n);
+	  gfits_modify (&header, line, "%lf", 1, mass / (age[n+1] - age[n]));
+	  add_to_outmatrix (i, j, m, n, N_age, 0, mass);
+	  add_to_outmatrix (i, j, m, n, N_age, 1, Av[i]);
+	  add_to_outmatrix (i, j, m, n, N_age, 2, dist[j]);
+	  add_to_outmatrix (i, j, m, n, N_age, 3, alpha[m]);
+	  add_to_outmatrix (i, j, m, n, N_age, 4, age[n]);
+	  add_to_outmatrix (i, j, m, n, N_age, 5, age[n+1]);
+	  
+	}
+      }
+    }
+  }
+
+  /* 
+  in = (float *)matrix.buffer;
+  for (i = 0; i < matrix.Naxis[0]; i++) {
+    for (j = 0; j < matrix.Naxis[1]; j++) {
+      mass = in[i + matrix.Naxis[0]*(j + matrix.Naxis[1]*2)];
+      fprintf (stderr, "%f ", mass);
+    }
+    fprintf (stderr, "\n");
+  }
+  */
+
+  gfits_write_header (fakefile, &header);
+  gfits_write_matrix (fakefile, &matrix);
+}
+
+/*****************************************************************************/
+
+load_parameters (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i, stat, test_dVo, test_dVref, test_dMo;
+  int Ffile, Mfile, Cfile, Afile, MSfile;
+  FILE *f;
+  char line[1024];
+  double N_stars, N_try, Ntotal, time;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: %s pfile\n", argv[0]);
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "parameter file %s not found\n", argv[1]);
+    exit (0);
+  }
+
+  N_Av = N_dist = N_alpha = N_age = N_stars = N_try = 0.0;
+  test_dVo = test_dVref = test_dMo = FALSE;
+  Ffile = Mfile = Cfile = Afile = MSfile = FALSE;
+  while (scan_line (f, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    
+    if (!strncmp (line, "Av ", strlen ("Av "))) {
+      for (i = 0; (i < NPARMAX) && (stat = dparse (&Av[i], i+2, line)); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_Av = i;
+    }
+
+    if (!strncmp (line, "dist ", strlen ("dist "))) {
+      for (i = 0; (i < NPARMAX) && dparse (&dist[i], i+2, line); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_dist = i;
+    }
+
+    if (!strncmp (line, "alpha ", strlen ("alpha "))) {
+      for (i = 0; (i < NPARMAX) && dparse (&alpha[i], i+2, line); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_alpha = i;
+    }
+
+    if (!strncmp (line, "age ", strlen ("age "))) {
+      for (i = 0; (i < NPARMAX) && dparse (&age[i], i+2, line); i++);
+      if (i == NPARMAX) {
+	fprintf (stderr, "maximum of %d parameter values per parameter\n", NPARMAX);
+	exit (0);
+      }
+      N_age = MAX (0, i - 1);
+    }
+
+    if (!strncmp (line, "dVo ", strlen ("dVo "))) {
+      dparse (&dVo, 2, line);
+      test_dVo = TRUE;
+    }
+    
+    if (!strncmp (line, "dVref ", strlen ("dVref "))) {
+      dparse (&dVref, 2, line);
+      test_dVref = TRUE;
+    }
+    
+    if (!strncmp (line, "dMo ", strlen ("dMo "))) {
+      dparse (&dMo, 2, line);
+      test_dMo = TRUE;
+    }
+    
+    if (!strncmp (line, "nstars ", strlen ("nstars "))) {
+      dparse (&N_stars, 2, line);
+      NSTARS = N_stars;
+    }
+    
+    if (!strncmp (line, "ntry ", strlen ("ntry "))) {
+      dparse (&N_try, 2, line);
+      NTRY = N_try;
+    }
+    
+    if (!strncmp (line, "magfile ", strlen ("magfile "))) {
+      sscanf (line, "%*s %s", magfile);
+      fprintf (stderr, "magfile: %s\n", magfile);
+      Mfile = TRUE;
+    }
+    
+    if (!strncmp (line, "colorfile ", strlen ("colorfile "))) {
+      sscanf (line, "%*s %s", colorfile);
+      fprintf (stderr, "colorfile: %s\n", colorfile);
+      Cfile = TRUE;
+    }
+    
+    if (!strncmp (line, "agefile ", strlen ("agefile "))) {
+      sscanf (line, "%*s %s", agefile);
+      fprintf (stderr, "agefile: %s\n", agefile);
+      Afile = TRUE;
+    }
+    
+    if (!strncmp (line, "massfile ", strlen ("massfile "))) {
+      sscanf (line, "%*s %s", massfile);
+      fprintf (stderr, "massfile: %s\n", massfile);
+      MSfile = TRUE;
+    }
+    
+    if (!strncmp (line, "fakefile ", strlen ("fakefile "))) {
+      sscanf (line, "%*s %s", fakefile);
+      fprintf (stderr, "fakefile: %s\n", fakefile);
+      Ffile = TRUE;
+    }
+    
+    if (N_Av && N_dist && N_alpha && N_age && N_stars && N_try && 
+	test_dVo && test_dVref && test_dMo &&
+	Ffile && Mfile && Cfile && Afile && MSfile) {
+      Ntotal = N_Av * N_dist * N_alpha * N_age * N_stars * N_try;
+      time = (Ntotal / 1250000.0);
+      fprintf (stderr, "%.0f iterations\n", Ntotal);
+      fprintf (stderr, "process should take about %.1f minutes\n", time);
+      return;
+    }
+  }
+  
+  if (!(N_Av && N_dist && N_alpha && N_age && NSTARS && NTRY && 
+	test_dVo && test_dVref && test_dMo && 
+	Ffile && Mfile && Cfile && Afile && MSfile)) {
+    fprintf (stderr, "failed to get all parameter lines\n");
+    fprintf (stderr, "N_Av: %d\n", N_Av);
+    fprintf (stderr, "N_dist: %d\n", N_dist);
+    fprintf (stderr, "N_alpha: %d\n", N_alpha);
+    fprintf (stderr, "N_age: %d\n", N_age);
+    fprintf (stderr, "N_stars: %d\n", NSTARS);
+    fprintf (stderr, "N_try: %d\n", NTRY);
+    fprintf (stderr, "dVo: %f (%d)\n", dVo, test_dVo);
+    fprintf (stderr, "dVref: %f (%d)\n", dVref, test_dVref);
+    fprintf (stderr, "dMo: %f (%d)\n", dMo, test_dMo);
+    fprintf (stderr, "Ffile: %d\n", Ffile);
+    fprintf (stderr, "Mfile: %d\n", Mfile);
+    fprintf (stderr, "Cfile: %d\n", Cfile);
+    fprintf (stderr, "Afile: %d\n", Afile);
+    fprintf (stderr, "MSfile: %d\n", MSfile);
+    exit (0);
+  }
+  
+}
+
+/*****************************************************************************/
+
+
+init_outmatrix () 
+{
+
+  int i;
+  char line[32];
+  double value;
+
+  gfits_init_header (&header);
+  header.bitpix = -32;
+  header.Naxes = 7;
+  header.Naxis[0] = NMASS;
+  header.Naxis[1] = N_age + 1;
+  header.Naxis[2] = N_age;
+  header.Naxis[3] = N_alpha;
+  header.Naxis[4] = N_dist;
+  header.Naxis[5] = N_Av;
+  header.Naxis[6] = 2;
+  header.bzero = 0.0;
+  header.bscale = 1.0;
+  header.unsign = FALSE;
+  header.extend = FALSE;
+
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+
+  gfits_modify (&header, "PAR_1", "%s", 1, "mass (Mo)");
+  for (i = 0; i < NMASS + 1; i++) {
+    sprintf (line, "PAR_1_%0d\0", i);
+    value = 10.0 / SQ(4.5 - DMASS*i);
+    gfits_modify (&header, line, "%lf", 1, value);
+  }
+  
+  gfits_modify (&header, "PAR_2", "%s", 1, "age out (Myr)");
+  for (i = 0; i < N_age + 1; i++) {
+    sprintf (line, "PAR_2_%0d\0", i);
+    gfits_modify (&header, line, "%lf", 1, age[i]);
+  }
+
+  gfits_modify (&header, "PAR_3", "%s", 1, "age in (Myr)");
+  for (i = 0; i < N_age + 1; i++) {
+    sprintf (line, "PAR_3_%0d\0", i);
+    gfits_modify (&header, line, "%lf", 1, age[i]);
+  }
+  
+  gfits_modify (&header, "PAR_4", "%s", 1, "alpha");
+  for (i = 0; i < N_alpha; i++) {
+    sprintf (line, "PAR_4_%0d\0", i);
+    gfits_modify (&header, line, "%lf", 1, alpha[i]);
+  }
+
+  gfits_modify (&header, "PAR_5", "%s", 1, "dist (mag)");
+  for (i = 0; i < N_dist; i++) {
+    sprintf (line, "PAR_5_%0d\0", i);
+    gfits_modify (&header, line, "%lf", 1, dist[i]);
+  }
+
+  gfits_modify (&header, "PAR_6", "%s", 1, "A_V (mag)");
+  for (i = 0; i < N_Av; i++) {
+    sprintf (line, "PAR_6_%0d\0", i);
+    gfits_modify (&header, line, "%lf", 1, Av[i]);
+  }
+
+}
+
+
+/*****************************************************************************/
+
+fakestar (A_V, Dist, Alpha, AgeS, AgeE, mag, color, Mass, Noise)
+double A_V, Dist, Alpha, AgeS, AgeE;
+double *Mass, *mag, *color, *Noise;
+{
+
+  int X, Y, i;
+  double mass, Age, v, uv, noise;
+
+  for (i = 0; i < 500; i++) {
+    mass = rnd_mass (Alpha);
+    Age = (AgeE - AgeS)*drand48() + AgeS;
+    *Mass += mass;
+    
+    /* find star in color, mag images */
+    X = (log10(Age) - lAo) / ldA;
+    Y = (log10(mass) - lMo) / ldM;
+    if ((X >= 0) && (X < UV_NX) && (Y >= 0) && (Y < UV_NY)) {
+      uv = UVbuffer[X + UV_NX*Y];
+      if (uv != 100.0) {
+	uv += 0.7*A_V;   /***** this depends on the extinction law and colors U-V ***/
+	v = Vbuffer[X + UV_NX*Y] + Dist + A_V; 
+	noise = dVo*sqrt(1.0 + pow (10.0, (0.4*(v - dVref)))); 
+	if (noise < dMo) {
+	  *Noise = noise;
+	  *mag = rnd_gauss (v, noise);
+	  *color = rnd_gauss (uv, 1.4*noise);
+	  return;
+	}
+      }
+    }
+  }
+  fprintf (stderr, "problem with generating stars:  none land in safe zone\n");
+  exit (0);
+}
+
+
+
+/* rnd_mass only returns stars with masses in the range MMIN to MMAX */
+double
+rnd_mass (Alpha)
+double Alpha;
+{
+  
+  double dP, x;
+  
+  x = (MMAX + 1);
+  while (x > MMAX) {
+    dP = drand48();
+    x = MMIN * pow ((dP*MassTerm + 1.0), 1.0 / (-Alpha));
+  }
+  return (x);
+
+}
+
+/*****************************************************************************/
+
+read_datafiles ()
+{
+
+  gfits_read_header (colorfile, &UV_h);
+  gfits_read_matrix (colorfile, &UV_i);
+  gfits_read_header (magfile, &V_h);
+  gfits_read_matrix (magfile, &V_i); 
+  UV_NX = UV_h.Naxis[0];
+  UV_NY = UV_h.Naxis[1];
+  UVbuffer = (float *)UV_i.buffer;
+  Vbuffer = (float *)V_i.buffer;
+
+  gfits_scan (&UV_h, "RA_O",  "%lf", 1, &lAo);
+  gfits_scan (&UV_h, "RA_X",  "%lf", 1, &ldA);
+  gfits_scan (&UV_h, "DEC_O", "%lf", 1, &lMo);
+  gfits_scan (&UV_h, "DEC_Y", "%lf", 1, &ldM);
+
+  gfits_read_header (massfile, &mass_h);
+  gfits_read_matrix (massfile, &mass_i);
+  gfits_read_header (agefile, &age_h);
+  gfits_read_matrix (agefile, &age_i); 
+  MS_NX = mass_h.Naxis[0];
+  MS_NY = mass_h.Naxis[1];
+  Mbuffer = (float *)mass_i.buffer;
+  Abuffer = (float *)age_i.buffer;
+
+  gfits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  gfits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  gfits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  gfits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+} 
+
+/*****************************************************************************/
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+/*****************************************************************************/
+
+magtomass (A_V, Dist, mag, color, noise, M, A, inflation)
+double A_V, Dist, mag, color, noise;
+int *M, *A;
+double *inflation;
+{
+
+  int x, y, I, J, i, j, k;
+  double mass, Age, v, uv, Ngood;
+
+  *inflation = 0.0;
+  x = (color - UV0 - 0.7*A_V) / DUV;   /* again, depends on U-V and extinction */
+  y = (mag - Dist - V0 - A_V) / DV;
+  if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+    mass = Mbuffer[x + MS_NX*y];
+    if (mass > 0.0) {
+      Age = Abuffer[x + MS_NX*y];
+      /* age[i]: i = 0,N_age */
+      if ((Age < age[0]) || (Age > age[N_age])) {
+	*inflation = 0.0;
+	return;
+      }
+      for (I = 0; (I < N_age) && (Age > age[I+1]); I++);
+      J = MAX (MIN ((4.5 - sqrt(10.0/mass)) / DMASS, NMASS - 1), 0);
+      Ngood = 1.0;
+      for (k = 0; k < NTRY; k++) {
+	v = rnd_gauss (mag, noise);
+	uv = rnd_gauss (color, 1.4*noise);
+	x = (uv - UV0 - 0.7*A_V) / DUV;
+	y = (v - V0 - Dist - A_V) / DV;
+	if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+	  mass = Mbuffer[x + MS_NX*y];
+	  if (mass > 0.0) {
+	    Age = Abuffer[x + MS_NX*y];
+	    for (i = -1; (i < N_age) && (Age > age[i+1]); i++);
+	    j = MAX (MIN ((4.5 - sqrt(10.0/mass)) / DMASS, NMASS - 1), 0);
+	    if ((i == I) && (j == J)) {
+	      Ngood += 1.0;
+	    }
+	  }
+	}
+      }
+      *inflation = (NTRY / Ngood);
+      *M = J;
+      *A = I;
+    }
+  }
+  if (mass == 0.0) *inflation = 0.0;
+}
+ 
+
+/*****************************************************************************/
+
+add_to_outmatrix (AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS, value)
+int AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS;
+double value;
+{
+
+  float *buffer;
+
+  buffer = (float *)matrix.buffer;
+  
+  /* elements in the (N_age) row of each Mass*Age matrix contain special numbers for the matrix */
+  buffer[MASS + NMASS*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(0))))))] += value;
+  buffer[MASS + NMASS*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(1))))))] += 1.0;
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fakedump.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fakedump.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fakedump.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include <ohana.h>
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header in_h, out_h;
+  Matrix in_m, out_m;
+  int i, j;
+  int Nage, Nalpha, Ndist, NAv;
+  float *in, *out;
+
+  if (argc < 7) {
+    fprintf (stderr, "USAGE fakedump infile outfile Nage Nalpha Ndist NAv\n");
+    exit (0);
+  }
+  Nage = atof(argv[3]);
+  Nalpha = atof(argv[4]);
+  Ndist = atof(argv[5]);
+  NAv = atof(argv[6]);
+
+  gfits_read_header (argv[1], &in_h);
+  gfits_read_matrix (argv[1], &in_m);
+
+  if (Nage > in_h.Naxis[2] - 1) {
+    fprintf (stderr, "Nage too big (%d, %d)\n", Nage, in_h.Naxis[2] - 1);
+    exit (0);
+  }
+
+  if (Nalpha > in_h.Naxis[3] - 1) {
+    fprintf (stderr, "Nalpha too big (%d, %d)\n", Nalpha, in_h.Naxis[3] - 1);
+    exit (0);
+  }
+
+  if (Ndist > in_h.Naxis[4] - 1) {
+    fprintf (stderr, "Ndist too big (%d, %d)\n", Ndist, in_h.Naxis[4] - 1);
+    exit (0);
+  }
+
+  if (NAv > in_h.Naxis[5] - 1) {
+    fprintf (stderr, "NAv too big (%d, %d)\n", NAv, in_h.Naxis[5] - 1);
+    exit (0);
+  }
+
+  gfits_init_header (&out_h);
+  out_h.bitpix = -32;
+  out_h.Naxes = 2;
+  out_h.Naxis[0] = in_h.Naxis[0];
+  out_h.Naxis[1] = in_h.Naxis[1] - 1;
+  out_h.bzero = 0.0;
+  out_h.bscale = 1.0;
+  out_h.unsign = FALSE;
+  out_h.extend = FALSE;
+  gfits_create_header (&out_h);
+  gfits_create_matrix (&out_h, &out_m);
+  
+  in = (float *)in_m.buffer;
+  out = (float *)out_m.buffer;
+  for (i = 0; i < out_h.Naxis[0]; i++) {
+    for (j = 0; j < out_h.Naxis[1]; j++) {
+      out[i + out_h.Naxis[0]*j] = in[i + in_h.Naxis[0]*(j + in_h.Naxis[1]*(Nage + in_h.Naxis[2]*(Nalpha + in_h.Naxis[3]*(Ndist + in_h.Naxis[4]*(NAv + in_h.Naxis[5] * 0)))))];
+      fprintf (stderr, "%f ", out[i + out_h.Naxis[0]*j]);
+    }
+    fprintf (stderr, "\n");
+  }
+  
+  gfits_write_header (argv[2], &out_h);
+  gfits_write_matrix (argv[2], &out_m);
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fakepop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fakepop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fakepop.c	(revision 16632)
@@ -0,0 +1,293 @@
+# include <ohana.h>
+# define MMIN 1.0
+# define MMAX 120.0
+extern double drand48();
+extern double rnd_mass();
+double rnd_mass();
+double term;
+extern double rnd_gauss();
+extern double rnd_integrate ();
+extern double gaussian ();
+
+double gaussian();
+double rnd_gauss();
+double rnd_integrate();
+
+# define NGAUSS 2048
+double gaussint[NGAUSS];
+
+double AgeS, AgeE, alpha, d, Av, dMo, dVo, dVref;
+char colorfile[256], magfile[256];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header UV_h, V_h;
+  Matrix UV_i, V_i;
+  double Mtot, M, mass;
+  double age, noise, v, uv, V, UV;
+  double lAo, ldA, lMo, ldM, stage;
+  int X, Y;
+  long A, B;
+  
+  load_parameters (argc, argv);
+  Mtot = atof (argv[2]);
+  term = (pow((MMAX/MMIN), -alpha) - 1.0);
+  
+  gfits_read_header (colorfile, &UV_h);
+  gfits_read_matrix (colorfile, &UV_i);
+  gfits_read_header (magfile, &V_h);
+  gfits_read_matrix (magfile, &V_i); 
+
+  gfits_scan (&UV_h, "RA_O",  "%lf", 1, &lAo);
+  gfits_scan (&UV_h, "RA_X",  "%lf", 1, &ldA);
+  gfits_scan (&UV_h, "DEC_O", "%lf", 1, &lMo);
+  gfits_scan (&UV_h, "DEC_Y", "%lf", 1, &ldM);
+  
+  gauss_init ();
+
+  fprintf (stderr, "beginning main loop\n");
+  
+  stage = 1;
+  for (M = 0; M < Mtot; ) {
+    age = (AgeE - AgeS)*drand48() + AgeS;
+    X = (log10(age) - lAo) / ldA;
+    if (M > stage * Mtot / 10.0) {
+      fprintf (stderr, "M: %f\n", M);
+      stage += 1.0;
+    }
+    mass = rnd_mass (alpha);
+    Y = (log10(mass) - lMo) / ldM;
+    if ((X >= 0) && (X < UV_h.Naxis[0]) &&
+	(Y >= 0) && (Y < UV_h.Naxis[1])) {
+      uv = gfits_get_matrix_value (&UV_i, X, Y); 
+      if (uv != 100.0) {
+	uv += 0.7*Av;
+	v = gfits_get_matrix_value (&V_i, X, Y) + d + Av; 
+	noise = dVo*sqrt(1.0 + pow (10.0, (0.4*(v - dVref)))); 
+	V = rnd_gauss (v, noise);
+	UV = rnd_gauss (uv, 1.4*noise);
+	if (noise < dMo) {
+	  fprintf (stdout, "%f %f   %f %f   %f  %f\n", V, noise, V+UV, noise, mass, age);
+	}
+      }
+    }
+    M += mass;
+  }
+}
+
+/* rnd_mass only returns stars with masses in the range MMIN to MMAX */
+double
+rnd_mass (alpha)
+double alpha;
+{
+  
+  double dP, x;
+  
+  x = (MMAX + 1);
+  while (x > MMAX) {
+    dP = drand48();
+    x = MMIN * pow ((dP*term + 1.0), 1.0 / (-alpha));
+  }
+  return (x);
+
+}
+
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+rnd_integrate (function, range, mean, sigma) 
+double (*function) ();
+double range, mean, sigma;
+{
+
+  double val, x, dx, dx1, dx2, dx3, df;
+
+  range += 0.0001;
+  val = 0;
+  dx = sigma / 10.0;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+
+  for (x = mean - 7*sigma; (val < range) && (x < mean + 7*sigma); x += dx)  {
+    df = (3.0*function(x    , mean, sigma) + 
+	  9.0*function(x+dx1, mean, sigma) +
+	  9.0*function(x+dx2, mean, sigma) + 
+	  3.0*function(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+
+/*****************************************************************************/
+
+load_parameters (argc, argv)
+int argc;
+char **argv;
+{
+
+  int test_dVo, test_dVref, test_dMo;
+  int test_Age, test_Av, test_alpha, test_d;
+  int Mfile, Cfile;
+  FILE *f;
+  char line[1024];
+
+  if (argc < 3) {
+    fprintf (stderr, "USAGE: %s pfile Mtot\n", argv[0]);
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "parameter file %s not found\n", argv[1]);
+    exit (0);
+  }
+
+  test_Age = test_Av = test_alpha = test_d = FALSE;
+  test_dVo = test_dVref = test_dMo = FALSE;
+  Mfile = Cfile = FALSE;
+  while (scan_line (f, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    
+    fprintf (stderr, "%s\n", line);
+    if (!strncmp (line, "Av ", strlen ("Av "))) {
+      dparse (&Av, 2, line);
+      test_Av = TRUE;
+    }
+
+    if (!strncmp (line, "dist ", strlen ("dist "))) {
+      dparse (&d, 2, line);
+      test_d = TRUE;
+    }
+
+    if (!strncmp (line, "alpha ", strlen ("alpha "))) {
+      dparse (&alpha, 2, line);
+      test_alpha = TRUE;
+    }
+
+    if (!strncmp (line, "age ", strlen ("age "))) {
+      test_Age  = dparse (&AgeS, 2, line);
+      test_Age &= dparse (&AgeE, 3, line);
+    }
+
+    if (!strncmp (line, "dVo ", strlen ("dVo "))) {
+      dparse (&dVo, 2, line);
+      test_dVo = TRUE;
+    }
+    
+    if (!strncmp (line, "dVref ", strlen ("dVref "))) {
+      dparse (&dVref, 2, line);
+      test_dVref = TRUE;
+    }
+    
+    if (!strncmp (line, "dMo ", strlen ("dMo "))) {
+      dparse (&dMo, 2, line);
+      test_dMo = TRUE;
+    }
+    
+    if (!strncmp (line, "magfile ", strlen ("magfile "))) {
+      sscanf (line, "%*s %s", magfile);
+      fprintf (stderr, "magfile: %s\n", magfile);
+      Mfile = TRUE;
+    }
+    
+    if (!strncmp (line, "colorfile ", strlen ("colorfile "))) {
+      sscanf (line, "%*s %s", colorfile);
+      fprintf (stderr, "colorfile: %s\n", colorfile);
+      Cfile = TRUE;
+    }
+    
+    if (test_Age && test_Av && test_d && test_alpha && 
+	test_dVo && test_dVref && test_dMo &&
+	Mfile && Cfile) {
+      return;
+    }
+  }
+  
+  if (!(test_Age && test_Av && test_d && test_alpha && 
+	test_dVo && test_dVref && test_dMo && 
+	Mfile && Cfile)) {
+    fprintf (stderr, "failed to get all parameter lines\n");
+    fprintf (stderr, "test_Av: %d\n", test_Av);
+    fprintf (stderr, "test_d: %d\n", test_d);
+    fprintf (stderr, "test_alpha: %d\n", test_alpha);
+    fprintf (stderr, "test_age: %d\n", test_Age);
+    fprintf (stderr, "dVo: %f (%d)\n", dVo, test_dVo);
+    fprintf (stderr, "dVref: %f (%d)\n", dVref, test_dVref);
+    fprintf (stderr, "dMo: %f (%d)\n", dMo, test_dMo);
+    fprintf (stderr, "Mfile: %d\n", Mfile);
+    fprintf (stderr, "Cfile: %d\n", Cfile);
+    exit (0);
+  }
+  
+}
+
+/*****************************************************************************/
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fakestars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fakestars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fakestars.c	(revision 16632)
@@ -0,0 +1,121 @@
+# include <ohana.h>
+# define NCHAR 66 /* 65 char EXCLUDING return */
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+} Stars;
+
+void   gauss_init ();
+double gaussian (double x, double mean, double sigma);
+double rnd_gauss (double mean, double sigma);
+
+  /* 
+     load in a list of stars in cmp format
+     generate a new list of stars in cmp format
+     new measurements should have the requested noise characteristics */
+
+int main (int argc, char **argv) {
+
+  int Nstar, N, Nbytes, nbytes, i;
+  FILE *f;
+  char *input, *output, *buffer, line[NCHAR];
+  Header header;
+  Stars *stars;
+  double tmp, dMs, dMr, dMo, dM, offset;
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: fakestars (input) (output) (syserr) (offset)\n");
+    exit (2);
+  }
+  input  = argv[1];
+  output = argv[2];
+  dMs    = atof (argv[3]);
+  offset = atof (argv[4]);
+
+  gauss_init ();
+
+  /* load header, open file */
+  if (!gfits_read_header (input, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", input);
+    exit (1);
+  }
+  f = fopen (input, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", input);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find expected number of stars */
+  gfits_scan (&header, "NSTARS", "%d", 1, &Nstar);
+  if (Nstar == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header\n");
+    exit (1);
+  }
+  ALLOCATE (stars, Stars, Nstar);
+
+  /* load in stars */
+  Nbytes = Nstar*BYTES_STAR;
+  ALLOCATE (buffer, char, Nbytes + 1);
+  nbytes = fread (buffer, 1, Nbytes, f);
+  if (nbytes != Nbytes) {
+    fprintf (stderr, "ERROR: failed to read in %d stars\n", Nstar);
+    exit (1);
+  }
+  buffer[Nbytes] = 0;
+
+  for (i = 0; i < Nstar; i++) {
+    Nbytes = i*BYTES_STAR;
+    dparse (&stars[i].X,    1, &buffer[Nbytes]);
+    dparse (&stars[i].Y,    2, &buffer[Nbytes]);
+    dparse (&stars[i].M,    3, &buffer[Nbytes]);
+    dparse (&stars[i].dM,   4, &buffer[Nbytes]);
+    dparse (&stars[i].Mgal, 7, &buffer[Nbytes]);
+    dparse (&stars[i].Map,  8, &buffer[Nbytes]);
+    dparse (&stars[i].fx,   9, &buffer[Nbytes]);
+    dparse (&stars[i].fy,  10, &buffer[Nbytes]);
+    dparse (&stars[i].df,  11, &buffer[Nbytes]);
+    
+    dparse (&tmp,           5, &buffer[Nbytes]);
+    stars[i].dophot = tmp;
+  }
+  fclose (f);
+
+  /* error per star is hypot of systematic & poisson */
+  for (i = 0; i < Nstar; i++) {
+    dMr = 0.001 * stars[i].dM;
+    dMo = hypot (dMs, dMr);
+    dM  = rnd_gauss (0.0, dMo);
+    stars[i].M += dM + offset;
+  }
+
+  gfits_write_header (output, &header);
+  f = fopen (output, "a");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open file for output: %s\n", output);
+    exit (1);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  for (i = 0; i < Nstar; i++) {
+    snprintf (line, NCHAR, "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", 
+	      stars[i].X, stars[i].Y, stars[i].M, 
+	      (int)stars[i].dM, stars[i].dophot, stars[i].sky, 
+	      stars[i].Mgal, stars[i].Map, stars[i].fx, stars[i].fy, stars[i].df);
+    fprintf (f, "%s\n", line);
+  }
+  fclose (f);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fitdist.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fitdist.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fitdist.c	(revision 16632)
@@ -0,0 +1,627 @@
+# include <ohana.h>
+
+# define NGAUSS 2048
+double drand48();
+double gaussint[NGAUSS];
+double gaussian();
+double rnd_gauss();
+
+# define MMIN 1.0
+# define MMAX 120.0
+double rnd_mass();
+double MassTerm;
+
+# define NPARMAX 30
+int Nmass, N_Av, N_dist, N_alpha, N_age, NTRY;
+double *Mass, Av[NPARMAX], dist[NPARMAX], alpha[NPARMAX], age[NPARMAX];
+
+int COL1, COL2;
+double *mag, *color, *noise;
+double *obsdata;
+
+double UV0, V0, DV, DUV;
+Header fake_h, mass_h, age_h;
+Matrix fake_m, mass_i, age_i;
+int MS_NX, MS_NY;
+float *Mbuffer, *Abuffer;
+
+char datafile[256], fakefile[256], massfile[256], agefile[256];
+
+double get_obs(), get_fake(), get_error(), get_fake_err(), get_chisq();
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+  
+  Header header;
+  Matrix matrix;
+  int i, j, m, n, M, A, Nstars, I, J, k, done, grid, tries;
+  double mass, inflation, sumterm, errterm;
+  double dm, a1, a2, chisq_0, chisq_1, chisq_min, Ndof, *delta;
+  double temp_Factor, *Factor, *dFactor, *SFR, dFactor1, dFactor2;
+
+  load_parameters (argc, argv);
+  fprintf (stderr, "read in parameters\n");
+
+  gauss_init ();
+
+  read_datafiles ();
+  fprintf (stderr, "read in data files (%d x %d)\n", Nmass, N_age);
+
+  Nstars = load_realstars ();
+  fprintf (stderr, "read in %d real stars\n", Nstars);
+
+  ALLOCATE (SFR, double, N_age);
+  ALLOCATE (Factor, double, N_age);
+  ALLOCATE (dFactor, double, N_age);
+  ALLOCATE (delta, double, N_age);
+
+  fprintf (stdout, "# Av   dist   alpha  chisq Ndof");
+  for (n = 0; n < N_age; n++) {
+    fprintf (stdout, " %3.0f My ", age[n]);
+  }
+  fprintf (stdout, "\n");
+
+  for (i = 0; i < N_Av; i++) {
+    for (j = 0; j < N_dist; j++) {
+      
+      /* unique obs. matrix for each Av, dist value only */
+      bzero (obsdata, sizeof(double) * N_age*Nmass*2);
+      for (k = 0; k < Nstars; k++) {
+	magtomass (Av[i], dist[j], mag[k], color[k], noise[k], &M, &A, &inflation);
+	if (inflation > 0.0) add_obs (A, M, inflation);
+      }
+      
+      /* now fit to fake matrices */
+      for (m = 0; m < N_alpha; m++) {
+
+	for (n = 0; n < N_age; n++) {
+	  dm = get_fake (i, j, m, n, N_age, 0);
+	  a1 = get_fake (i, j, m, n, N_age, 4);
+	  a2 = get_fake (i, j, m, n, N_age, 5);
+	  SFR[n] = dm / (a2 - a1);
+	  delta[n] = 0.1;
+	  Factor[n] = 0.0;
+	}	
+	
+	chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	chisq_0 = 2*chisq_1;
+	done = FALSE;
+	/* 	while (!done) { */
+	for (tries = 0; ((fabs (chisq_1 - chisq_0) / Ndof > 0.001) && (tries < 100)); tries++) {
+	  chisq_0 = chisq_1;
+	  for (n = 0; n < N_age; n++) {
+	    Factor[n] += delta[n];
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	    dFactor1 = MAX (0.0, MIN (0.5*delta[n], 5.0 * delta[n] * (1.0 - chisq_1/chisq_0)));
+	    Factor[n] -= 2*delta[n];
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	    dFactor2 = MIN (0.0, MAX (-0.5*delta[n], -5.0 * delta[n] * (1.0 - chisq_1/chisq_0)));
+	    if (dFactor1 > fabs(dFactor2)) {
+	      dFactor[n] = dFactor1;
+	    }
+	    else {
+	      dFactor[n] = dFactor2;
+	    }
+	    Factor[n] += delta[n];
+	    if ((delta[n] > 0.001) && (!(tries % 5) || (fabs(dFactor[n]) < 0.01 * delta[n]))) {
+	      /* small grid search */
+	      dFactor1 = temp_Factor = Factor[n];
+	      chisq_min = chisq_0;
+	      for (grid = 0, Factor[n] = MAX (0.0, Factor[n] - 2*delta[n]); grid < 5; grid ++, Factor[n] += delta[n]) {
+		chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+		if (chisq_1 < chisq_min) {
+		  dFactor1 = Factor[n];
+		  chisq_min = chisq_1;
+		}
+	      }
+	      if (dFactor1 == temp_Factor) {
+		delta[n] = delta[n] / 2.0;
+	      }
+	      Factor[n] = dFactor1;
+	    }
+	  }
+	  done = TRUE; 
+	  for (n = 0; n < N_age; n++) {
+	    Factor[n] += dFactor[n];
+	    Factor[n] = MAX (0.0, Factor[n]);  /* negative star formation is unphysical */
+	    if ((Factor[n] > 0.0) && (fabs(dFactor[n]) == delta[n])) {
+	      delta[n] = MIN (0.1, delta[n] * 1.5);
+	    }
+	  }
+	  chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	  /*
+	  fprintf (stderr, "%f %f ", chisq_0, chisq_1);
+	  for (n = 0; n < N_age; n++) {
+	    fprintf (stderr, "%f ", Factor[n]);
+	  }
+	  fprintf (stderr, "\n");
+	  fprintf (stderr, "                       ");
+	  for (n = 0; n < N_age; n++) {
+	    fprintf (stderr, "%f ", delta[n]);
+	  }
+	  fprintf (stderr, "\n");
+	  */
+	}
+
+	chisq_0 = chisq_1;
+	for (n = 0; n < N_age; n++) {
+	  temp_Factor = Factor[n];
+	  for (; chisq_1 < chisq_0 + 1; Factor[n] += 0.1*delta[n])
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	  dFactor[n] = Factor[n] - temp_Factor;
+	  /* fprintf (stderr, "%d %f %f\n", n, Factor[n], dFactor[n]); */
+	  Factor[n] = temp_Factor;
+	  chisq_1 = chisq_0;
+	  for (; chisq_1 < chisq_0 + 1; Factor[n] -= 0.1*delta[n])
+	    chisq_1 = get_chisq (Factor, i, j, m, &Ndof);
+	  dFactor[n] =  0.5 * (dFactor[n] + temp_Factor  - Factor[n]);
+	  Factor[n] = temp_Factor;
+	}
+	if (tries == 100) {
+	  fprintf (stdout, "*** failed to converge *** \n");
+	}
+	fprintf (stdout, "%5.2f %6.2f %4.1f   %6.2f  %.0f ", Av[i], dist[j], alpha[m], chisq_1/Ndof, Ndof);
+	for (n = 0; n < N_age; n++) {
+	  fprintf (stdout, "%7.0f ", SFR[n]*Factor[n]);
+	}
+	fprintf (stdout, "\n");
+	fprintf (stdout, "                               ");
+	for (n = 0; n < N_age; n++) {
+	  fprintf (stdout, "%7.0f ", SFR[n]*dFactor[n]);
+	}
+	fprintf (stdout, "\n");
+      }
+    }
+  }
+}
+
+
+/*****************************************************************************/
+
+double get_chisq (Factor, AV, DIST, ALPHA, Ndof)
+double *Factor;
+int AV, DIST, ALPHA;
+double *Ndof;
+{
+
+  double chisq, sumterm, errterm;
+  int I, J, n;
+
+  *Ndof = chisq = 0.0;
+  for (I = 0; I < Nmass; I++) {
+    for (J = 0; J < N_age; J++) {
+      errterm = get_error (J, I);
+      sumterm = get_obs (J, I);
+      for (n = 0; n < N_age; n++) {
+	sumterm -= Factor[n]*get_fake (AV, DIST, ALPHA, n, J, I);
+	errterm += Factor[n]*get_fake_err (AV, DIST, ALPHA, n, J, I);
+      }
+      if (errterm > 0.0) {
+	chisq += SQ (sumterm) / errterm;
+	*Ndof += 1.0;
+      }
+    }
+  }
+  *Ndof -= N_age + N_Av + N_dist + N_alpha;
+
+  return (chisq);
+}
+
+/*****************************************************************************/
+
+load_parameters (argc, argv)
+int argc;
+char **argv;
+{
+
+  int i;
+  int Dfile, Ffile, Afile, MSfile;
+  FILE *f;
+  char line[1024];
+  double tmp;
+
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: %s pfile\n", argv[0]);
+    exit (0);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    fprintf (stderr, "parameter file %s not found\n", argv[1]);
+    exit (0);
+  }
+
+  COL1 = COL1 = NTRY = 0.0;
+  Dfile = Ffile = Afile = MSfile = FALSE;
+  while (scan_line (f, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+        
+    if (!strncmp (line, "ntry ", strlen ("ntry "))) {
+      dparse (&tmp, 2, line);
+      NTRY = tmp;
+    }
+  
+    if (!strncmp (line, "col1 ", strlen ("col1 "))) {
+      dparse (&tmp, 2, line);
+      COL1 = tmp;
+    }
+  
+    if (!strncmp (line, "col2 ", strlen ("col2 "))) {
+      dparse (&tmp, 2, line);
+      COL2 = tmp;
+    }
+  
+    if (!strncmp (line, "agefile ", strlen ("agefile "))) {
+      sscanf (line, "%*s %s", agefile);
+      fprintf (stderr, "agefile: %s\n", agefile);
+      Afile = TRUE;
+    }
+    
+    if (!strncmp (line, "massfile ", strlen ("massfile "))) {
+      sscanf (line, "%*s %s", massfile);
+      fprintf (stderr, "massfile: %s\n", massfile);
+      MSfile = TRUE;
+    }
+    
+    if (!strncmp (line, "datafile ", strlen ("datafile "))) {
+      sscanf (line, "%*s %s", datafile);
+      fprintf (stderr, "datafile: %s\n", datafile);
+      Dfile = TRUE;
+    }
+    
+    if (!strncmp (line, "fakefile ", strlen ("fakefile "))) {
+      sscanf (line, "%*s %s", fakefile);
+      fprintf (stderr, "fakefile: %s\n", fakefile);
+      Ffile = TRUE;
+    }
+    
+    if (COL1 && COL2 && NTRY && Dfile && Ffile && Afile && MSfile) {
+      return;
+    }
+  }
+  
+  if (!(COL1 && COL2 && NTRY && Dfile && Ffile && Afile && MSfile)) {
+    fprintf (stderr, "failed to get all parameter lines\n");
+    fprintf (stderr, "NTRY: %d\n", NTRY);
+    fprintf (stderr, "COL1: %d\n", COL1);
+    fprintf (stderr, "COL2: %d\n", COL2);
+    fprintf (stderr, "Dfile: %d\n", Dfile);
+    fprintf (stderr, "Ffile: %d\n", Ffile);
+    fprintf (stderr, "Afile: %d\n", Afile);
+    fprintf (stderr, "MSfile: %d\n", MSfile);
+    exit (0);
+  }
+  
+}
+
+/*****************************************************************************/
+
+read_datafiles ()
+{
+
+  int i;
+  char line[1024];
+
+  gfits_read_header (massfile, &mass_h);
+  gfits_read_matrix (massfile, &mass_i);
+  gfits_read_header (agefile, &age_h);
+  gfits_read_matrix (agefile, &age_i); 
+  MS_NX = mass_h.Naxis[0];
+  MS_NY = mass_h.Naxis[1];
+  Mbuffer = (float *)mass_i.buffer;
+  Abuffer = (float *)age_i.buffer;
+
+  gfits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  gfits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  gfits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  gfits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+
+  gfits_read_header (fakefile, &fake_h);
+  gfits_read_matrix (fakefile, &fake_m);
+  Nmass = fake_h.Naxis[0];
+  ALLOCATE (Mass, double, Nmass + 1);
+  for (i = 0; i < Nmass + 1; i++) {
+    sprintf (line, "PAR_1_%0d\0", i);
+    gfits_scan (&fake_h, line, "%lf", 1, &Mass[i]);
+  }
+  
+  N_age = fake_h.Naxis[1] - 1;
+  for (i = 0; i < N_age + 1; i++) {
+    sprintf (line, "PAR_2_%0d\0", i);
+    gfits_scan (&fake_h, line, "%lf", 1, &age[i]);
+  }
+
+  N_alpha = fake_h.Naxis[3];
+  for (i = 0; i < N_alpha; i++) {
+    sprintf (line, "PAR_4_%0d\0", i);
+    gfits_scan (&fake_h, line, "%lf", 1, &alpha[i]);
+  }
+
+  N_dist = fake_h.Naxis[4];
+  for (i = 0; i < N_dist; i++) {
+    sprintf (line, "PAR_5_%0d\0", i);
+    gfits_scan (&fake_h, line, "%lf", 1, &dist[i]);
+  }
+
+  N_Av = fake_h.Naxis[5];
+  for (i = 0; i < N_Av; i++) {
+    sprintf (line, "PAR_6_%0d\0", i);
+    gfits_scan (&fake_h, line, "%lf", 1, &Av[i]);
+  }
+
+  ALLOCATE (obsdata, double, Nmass*N_age*2);
+
+}
+ 
+
+/*****************************************************************************/
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+/*****************************************************************************/
+
+magtomass (A_V, Dist, Mag, Color, Noise, M, A, inflation)
+double A_V, Dist, Mag, Color, Noise;
+int *M, *A;
+double *inflation;
+{
+
+  int x, y, I, J, i, j, k;
+  double mass, Age, v, uv, Ngood;
+
+  *inflation = 0.0;
+  x = (Color - UV0 - 0.7*A_V) / DUV;   /* again, depends on U-V and extinction */
+  y = (Mag - Dist - V0 - A_V) / DV;
+  if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+    mass = Mbuffer[x + MS_NX*y];
+    if (mass > 0.0) {
+      Age = Abuffer[x + MS_NX*y];
+      if ((Age < age[0]) || (Age > age[N_age])) {
+	*inflation = 0.0;
+	return;
+      }
+      for (I = 0; (I < N_age) && (Age > age[I+1]); I++);
+      if ((mass < Mass[0]) || (mass > Mass[Nmass])) {
+	*inflation = 0.0;
+	return;
+      }
+      for (J = 0; (J < Nmass) && (mass > Mass[J+1]); J++);
+      Ngood = 1.0;
+      for (k = 0; k < NTRY; k++) {
+	v = rnd_gauss (Mag, Noise);
+	uv = rnd_gauss (Color, 1.4*Noise);
+	x = (uv - UV0 - 0.7*A_V) / DUV;
+	y = (v - V0 - Dist - A_V) / DV;
+	if ((x > 0) && (x < MS_NX) && (y > 0) && (y < MS_NY)) {
+	  mass = Mbuffer[x + MS_NX*y];
+	  if (mass > 0.0) {
+	    Age = Abuffer[x + MS_NX*y];
+	    for (i = -1; (i < N_age) && (Age > age[i+1]); i++);
+	    for (j = -1; (j < Nmass) && (mass > Mass[j+1]); j++);
+	    if ((i == I) && (j == J)) {
+	      Ngood += 1.0;
+	    }
+	  }
+	}
+      }
+      *inflation = (NTRY / Ngood);
+      *M = J;
+      *A = I;
+    }
+  }
+  if (mass == 0.0) *inflation = 0.0;
+}
+ 
+
+/*****************************************************************************/
+
+add_obs (AGE, MASS, value)
+int AGE, MASS;
+double value;
+{
+
+  if (value == 0.0) {
+    fprintf (stderr, "error: %d %d %f\n", AGE, MASS, value);
+  }
+  else {
+    obsdata[MASS + Nmass*(AGE        )] += value;
+    obsdata[MASS + Nmass*(AGE + N_age)] += 1.0;
+  }
+}
+
+
+/*****************************************************************************/
+
+double get_obs (AGE, MASS)
+int AGE, MASS;
+{
+
+  double value;
+
+  value = obsdata[MASS + Nmass*(AGE)];
+
+  return (value);
+
+}
+
+/*****************************************************************************/
+
+double get_error (AGE, MASS)
+int AGE, MASS;
+{
+
+  double value;
+
+  if (obsdata[MASS + Nmass*(AGE + N_age)] > 5) {
+    value = SQ (obsdata[MASS + Nmass*(AGE)]) / obsdata[MASS + Nmass*(AGE + N_age)];
+    return (value);
+  }
+  if ((obsdata[MASS + Nmass*(AGE + N_age)] < 1) && (obsdata[MASS + Nmass*(AGE)] > 0)) {
+    fprintf (stderr, "error: %d %d %e %e\n", AGE, MASS, 
+	     obsdata[MASS + Nmass*(AGE + 0)], obsdata[MASS + Nmass*(AGE + 1)]);
+  }
+  if (obsdata[MASS + Nmass*(AGE + N_age)] > 0) {
+    value = SQ (3.0 * obsdata[MASS + Nmass*(AGE)] / obsdata[MASS + Nmass*(AGE + N_age)]);
+    return (value);
+  }
+  value = 0.0;
+  return (value);
+
+}
+
+
+/*****************************************************************************/
+
+double get_fake (AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS)
+int AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS;
+{
+
+  double value;
+  float *buffer;
+
+  buffer = (float *)fake_m.buffer;
+  
+  /* elements in the (N_age) row of each Mass*Age matrix contain special numbers for the matrix */
+  value = buffer[MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(0))))))];
+  /* buffer[MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(1))))))] += 1.0; */
+
+  return (value);
+
+}
+
+/*****************************************************************************/
+
+double get_fake_err (AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS)
+int AV, DIST, ALPHA, AGE_IN, AGE_OUT, MASS;
+{
+
+  double value;
+  float *buffer;
+  int pix1, pix2;
+
+  buffer = (float *)fake_m.buffer;
+  
+  /* elements in the (N_age) row of each Mass*Age matrix contain special numbers for the matrix */
+  pix1 = MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(0))))));
+  pix2 = MASS + Nmass*(AGE_OUT + (N_age + 1)*(AGE_IN + N_age*(ALPHA + N_alpha*(DIST + N_dist*(AV + N_Av*(1))))));
+
+  if (buffer[pix2] > 5) {
+    value = SQ (buffer[pix1]) / buffer[pix2];
+    return (value);
+  }
+
+  if (buffer[pix2] > 0) {
+    value = SQ (3.0 * buffer[pix1] / buffer[pix2]);
+    return (value);
+  }
+
+  value = 0.0;
+  return (value);
+
+}
+
+/***************************************************************************/
+
+int load_realstars () 
+
+{
+
+  char line[1024];
+  FILE *f;
+  double U;
+  int i, Nstars;
+
+  f = fopen (datafile, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "couldn't find data file %s\n", datafile);
+    exit (0);
+  }
+  
+  Nstars = 1000;
+  ALLOCATE (mag, double, Nstars);
+  ALLOCATE (color, double, Nstars);
+  ALLOCATE (noise, double, Nstars);
+  
+  /* need to fix allocations */
+  for (i = 0; scan_line (f, line) != EOF; i++) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    dparse (&mag[i], COL1, line);
+    dparse (&noise[i], (COL1+1), line);
+    dparse (&U, COL2, line);
+    color[i] = U - mag[i];
+    if (i == Nstars - 1) {
+      Nstars += 1000;
+      REALLOCATE (mag, double, Nstars);
+      REALLOCATE (color, double, Nstars);
+      REALLOCATE (noise, double, Nstars);
+    }
+  }
+
+  return (i);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fiximg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fiximg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fiximg.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+int main (int argc, char **argv) {
+
+  char *p;
+  int i, N;
+  Matrix matrix;
+  Header header;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: fiximg (input) (output)\n");
+    exit (1);
+  }
+
+  /* read catalog header */
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "error loading file %s\n", argv[1]);
+    exit (1);
+  }
+  if (!gfits_read_matrix (argv[1], &matrix)) {
+    fprintf (stderr, "error loading file %s\n", argv[1]);
+    exit (1);
+  }
+
+  N = 0;
+  while (gfits_header_field (&header, "COMMENT", 1) != (char *) NULL) {
+    N++;
+    gfits_delete (&header, "COMMENT", 1);
+  }
+  fprintf (stderr, "deleted %d comments\n", N);
+  p = gfits_header_field (&header, "END", 1);
+  for (i = 3; i < header.size - (int) (p - header.buffer); i++) { 
+    p[i] = ' '; 
+  }
+
+  /* read catalog header */
+  if (!gfits_write_header (argv[2], &header)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  if (!gfits_write_matrix (argv[2], &matrix)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  exit (0);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/fixsimple.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/fixsimple.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/fixsimple.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include <ohana.h>
+
+main (int argc, char **argv) {
+
+  char *p;
+  int i, N;
+  Matrix matrix;
+  Header header;
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: fixsimple (input) (output)\n");
+    exit (1);
+  }
+
+  /* read header */
+  if (!gfits_read_header (argv[1], &header)) {
+    fprintf (stderr, "error loading file %s\n", argv[1]);
+    exit (1);
+  }
+
+  N = 0;
+  while (gfits_header_field (&header, "COMMENT", 1) != (char *) NULL) {
+    N++;
+    gfits_delete (&header, "COMMENT", 1);
+  }
+  fprintf (stderr, "deleted %d comments\n", N);
+  p = gfits_header_field (&header, "END", 1);
+  for (i = 3; i < header.size - (int) (p - header.buffer); i++) { 
+    p[i] = ' '; 
+  }
+
+  /* read catalog header */
+  if (!gfits_write_header (argv[2], &header)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  if (!gfits_write_matrix (argv[2], &matrix)) {
+    fprintf (stderr, "error writing file %s\n", argv[2]);
+    exit (1);
+  }
+  exit (0);
+
+  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);
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/gtfringetable.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/gtfringetable.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/gtfringetable.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+static char *version = "gtfringetable $Revision: 1.5 $";
+
+void get_version (int argc, char **argv, char *version);
+
+int main (int argc, char **argv) {
+
+  int i;
+  double binning;
+  float *xmin, *xmax, *ymin, *ymax;
+  FILE *f;
+  FTable table;
+  Header header;
+
+  get_version (argc, argv, version);
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: (table) (ccd) (binning)\n");
+    exit (2);
+  }
+
+  binning = atof (argv[3]);
+
+  /* load data from fringe points file */
+  f = fopen (argv[1], "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "error opening fringe file %s\n", argv[1]);
+    exit (1);
+  }
+  table.header = &header;
+  if (!gfits_fread_ftable (f, &table, argv[2])) {
+    fprintf (stderr, "error reading table %s\n", argv[2]);
+    exit (1);
+  }
+  fclose (f);
+
+  gfits_get_table_column (&header, &table, "X_MIN", (void **) &xmin);
+  gfits_get_table_column (&header, &table, "X_MAX", (void **) &xmax);
+  gfits_get_table_column (&header, &table, "Y_MIN", (void **) &ymin);
+  gfits_get_table_column (&header, &table, "Y_MAX", (void **) &ymax);
+
+  for (i = 0; i < header.Naxis[1]; i++) {
+    fprintf (stdout, "%f %f\n", xmin[i] / binning, ymin[i] / binning);
+    fprintf (stdout, "%f %f\n", xmax[i] / binning, ymax[i] / binning);
+  }
+  exit (0);
+}
+
+/**** support functions ******/
+void get_version (int argc, char **argv, char *version) {
+
+  int N;
+  char *p, *q, *line;
+
+  if (get_argument (argc, argv, "-version")) {
+
+    N = strlen (version) + 2;
+    line = (char *) malloc (N);
+    bzero (line, N);
+
+    p = strstr (version, "$Revision: ");
+    if (p != (char *) NULL) 
+      p += strlen ("$Revision: ");
+    else
+      p = version;
+
+    q = strstr (p, "$");
+    if (q != (char *) NULL) 
+      N = q - p; 
+    else
+      N = strlen (p);
+
+    strncpy (line, p, N);
+
+    fprintf (stderr, "%s\n", line);
+    exit (2);
+  }
+}  
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/gunlock.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/gunlock.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/gunlock.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include <stdio.h>
+
+main (int argc, char **argv) {
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: gunlock (filename)\n");
+    exit (1);
+  }
+
+  if (!clearlockfile (argv[1], -1, 1)) {
+    fprintf (stdout, "LOCK NOT REMOVED\n");
+    exit (1);
+  }
+  
+  fprintf (stdout, "LOCK REMOVED\n");
+  exit (0);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/magtoage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/magtoage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/magtoage.c	(revision 16632)
@@ -0,0 +1,221 @@
+# include <ohana.h>
+# define MMIN 1.0
+# define MMAX 120.0
+extern double drand48();
+extern double rnd_gauss();
+extern double rnd_integrate ();
+extern double gaussian ();
+
+double gaussian();
+double rnd_gauss();
+double rnd_integrate();
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header mass_h, age_h;
+  Matrix mass_i, age_i;
+  double UV0, V0, DV, DUV;
+  double Uo, Vo;
+  double U, V, dUV, dU, dV, mass, age, d, a, da;
+  double M, dM, Ms, M2, m, dm, ldM, lMo, ldA, lAo;
+  double u, v, uv, Av, f, top, bot, alpha;
+  double **Masses, *maxmass, *minmass;
+  double **Ages;
+  int x, y, i, j, Ntry, NAGE, N;
+  char line[1024];
+  long A, B;
+  
+  lAo =   0.0;
+  ldA =   1.0;
+  NAGE =  320;
+  if (N = get_argument (argc, argv, "-age")) {
+    remove_argument (N, &argc, argv);
+    lAo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldA = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NAGE = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 9) {
+    fprintf (stderr, "USAGE: magtoage massfile agefile d Av Ntry Uo Vo alpha ldM\n");
+    exit (0);
+  }
+  d = atof (argv[3]);
+  Av = atof (argv[4]);
+  Ntry = atof (argv[5]);
+  Uo = atof (argv[6]);
+  Vo = atof (argv[7]);
+  alpha = atof (argv[8]);
+  /*
+  ldM   = atof (argv[9]);
+  lMo = 0.0;
+  */
+  
+  gfits_read_header (argv[1], &mass_h);
+  gfits_read_matrix (argv[1], &mass_i);
+  gfits_read_header (argv[2], &age_h);
+  gfits_read_matrix (argv[2], &age_i); 
+
+  gfits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  gfits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  gfits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  gfits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+
+  ALLOCATE (Ages, double *, (Ntry+2));
+  ALLOCATE (maxmass, double, NAGE);
+  ALLOCATE (minmass, double, NAGE);
+  for (i = 0; i < Ntry + 2; i++) {
+    ALLOCATE (Ages[i], double, NAGE);
+    bzero (Ages[i], sizeof(double) * NAGE);
+  }
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  /* find max and min masses for each age bin */
+  for (i = 0; i < NAGE; i++) {
+    maxmass[i] = 0.0;
+    minmass[i] = 1000.0;
+  }
+  for (x = 0; x < age_h.Naxis[0]; x++) {
+    for (y = 0; y < age_h.Naxis[1]; y++) {
+      mass = gfits_get_matrix_value (&mass_i, x, y);
+      if (mass == 0.0) continue;
+      age  = gfits_get_matrix_value (&age_i, x, y);
+      uv = x*DUV + UV0 + 0.7*Av;
+      v  = y*DV + V0 + Av + d;
+      u  = v + uv;
+      if ((u <= Uo) && (v <= Vo)) {
+	i = (age - lAo) / ldA;
+	if ((i > 0) && (i < NAGE)) {
+	  maxmass[i] = MAX(mass, maxmass[i]);
+	  minmass[i] = MIN(mass, minmass[i]);
+	}
+      }
+    }
+  }
+
+  fprintf (stderr, "beginning main loop\n");
+  while (scan_line (stdin, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    dparse (&V, 8, line);
+    dparse (&dV, 9, line);
+    dparse (&U, 12, line);
+    dparse (&dU, 13, line);
+    dUV = sqrt (dU*dU + dV*dV);
+    for (i = 0; i < Ntry + 1; i++) {
+      if (i == 0) {
+	fprintf (stderr, ".");
+	v = V;
+	uv = U - V;
+      }
+      else {
+	v = rnd_gauss (V, dV);
+	uv = rnd_gauss ((U-V), dUV);
+      }
+      x = (uv - UV0 - 0.7*Av) / DUV;
+      y = (v - d - V0 - Av) / DV;
+      if ((x > 0) && (x < mass_h.Naxis[0]) &&
+	  (y > 0) && (y < mass_h.Naxis[1])) {
+	mass = gfits_get_matrix_value (&mass_i, x, y);
+	if (mass > 0.0) {
+	  age = gfits_get_matrix_value (&age_i, x, y); 
+	  j = (age - lAo) / ldA;
+	  if ((j >= 0) && (j < NAGE))
+	    Ages[i][j] += pow(mass, alpha);
+	}
+      }
+    }
+  }
+
+  top = pow (MMAX, 1.0 - alpha) - pow (MMIN, 1.0 - alpha);
+  fprintf (stderr, "finding scatter per bin\n");
+  for (j = 0; j < NAGE; j++) {
+    Ms = M2 = 0.0;
+    for (i = 1; i < Ntry + 1; i++) {
+      Ms += Ages[i][j];
+      M2 += (Ages[i][j]*Ages[i][j]);
+    }
+    M = dM = 0.0;
+    if (Ms > 0) {
+      M  = Ms / (1.0*Ntry);
+      dM = sqrt (M2 / (1.0*Ntry) - M*M);
+    }
+    Ages[1][j] = M;
+    Ages[2][j] = dM;
+    /*
+    a = pow (10.0, j*ldA + lAo);
+    da = pow (10.0, (j+1)*ldA + lAo) - a;
+    */
+    a = j*ldA + lAo;
+    da = ldA;
+    f = 0.0;
+    if (maxmass[j] > minmass[j]) {
+      bot = pow (maxmass[j], 1.0 - alpha) - pow (minmass[j], 1.0 - alpha);
+      if (bot != 0.0) 
+	f = top * top / ((1.0 - alpha) * bot * 2.30158509);
+    }
+    fprintf (stdout, "%d %f %f %f %f %f %f %f\n", j, a, da, Ages[0][j], Ages[1][j], Ages[2][j], f, Ages[1][j]*f/da);
+  }
+}
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  double range, x;
+
+  range = drand48();
+  x = rnd_integrate (*gaussian, range, mean, sigma);
+
+  return (x);
+
+}
+
+
+double 
+rnd_integrate (function, range, mean, sigma) 
+double (*function) ();
+double range, mean, sigma;
+{
+
+  double val, x, dx, dx1, dx2, dx3, df;
+
+  range += 0.0001;
+  val = 0;
+  dx = sigma / 10.0;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+
+  for (x = mean - 7*sigma; (val < range) && (x < mean + 7*sigma); x += dx)  {
+    df = (3.0*function(x    , mean, sigma) + 
+	  9.0*function(x+dx1, mean, sigma) +
+	  9.0*function(x+dx2, mean, sigma) + 
+	  3.0*function(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/magtomass.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/magtomass.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/magtomass.c	(revision 16632)
@@ -0,0 +1,292 @@
+# include <ohana.h>
+extern double drand48();
+extern double rnd_gauss();
+extern double rnd_integrate ();
+extern double gaussian ();
+# define NEWWAY 1
+
+double gaussian();
+double rnd_gauss();
+double rnd_integrate();
+
+# define NGAUSS 2048
+double gaussint[NGAUSS];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header mass_h, age_h;
+  Matrix mass_i, age_i;
+  double UV0, V0, DV, DUV, ra, dec;
+  double U, V, dUV, dU, dV, mass, age, d;
+  double M, dM, Ms, M2, m, ldM, lMo, lAo, ldA, dlogM;
+  double v, uv, Av, eta, deta, Ngood;
+  double ***Masses, *maxmass, *minmass;
+  float *Mbuffer, *Abuffer;
+  int x, y, i, j, I, J, Ntry, dump, NMASS, N, NAGE, k, try;
+  int NX, NY;
+  char line[1024];
+  int col1, col2;
+  
+  dump = FALSE;
+  if (N = get_argument (argc, argv, "-dump")) {
+    remove_argument (N, &argc, argv);
+    dump = TRUE;
+  }
+
+  col1 = 8;
+  if (N = get_argument (argc, argv, "-col1")) {
+    remove_argument (N, &argc, argv);
+    col1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  col2 = 12;
+  if (N = get_argument (argc, argv, "-col2")) {
+    remove_argument (N, &argc, argv);
+    col2 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  fprintf (stderr, "using mags in columns %d & %d\n", col1, col2);
+
+  gauss_init ();
+
+  lAo = 0.1;
+  ldA =  0.3;
+  NAGE = 10;
+  lMo = 0.0;
+  ldM =  0.05;
+  if (NEWWAY)
+    NMASS = 87;
+  else 
+    NMASS = 50;
+  if (N = get_argument (argc, argv, "-mass")) {
+    if (dump) {
+      fprintf (stderr, "-mass and -dump incompatible\n");
+      exit (0);
+    }
+    remove_argument (N, &argc, argv);
+    lMo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldM = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NMASS = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    fprintf (stderr, "USAGE: magtomass massfile agefile d Av Ntry\n");
+    exit (0);
+  }
+  d = atof (argv[3]);
+  Av = atof (argv[4]);
+  Ntry = atof (argv[5]);
+
+  gfits_read_header (argv[1], &mass_h);
+  gfits_read_matrix (argv[1], &mass_i);
+  gfits_read_header (argv[2], &age_h);
+  gfits_read_matrix (argv[2], &age_i); 
+
+  gfits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  gfits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  gfits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  gfits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+  Mbuffer = (float *)mass_i.buffer;
+  Abuffer = (float *)age_i.buffer;
+  NX = mass_h.Naxis[0];
+  NY = mass_h.Naxis[1];
+  
+  ALLOCATE (Masses, double **, NAGE);
+  for (i = 0; i < NAGE; i++) {
+    ALLOCATE (Masses[i], double *, NMASS);
+    for (j = 0; j < NMASS; j++) {
+      ALLOCATE (Masses[i][j], double, 3);
+      Masses[i][j][0] = 0.0;
+	Masses[i][j][1] = 0.0;
+    }
+  }
+
+  fprintf (stderr, "beginning main loop\n");
+  while (scan_line (stdin, line) != EOF) {
+    if (!stripwhite (line)) continue;
+    if (line[0] == '#') continue;
+    /* appropriate columns hardwired */
+    dparse (&ra, 1, line);
+    dparse (&dec, 2, line);
+    dparse (&V, col1, line);
+    dparse (&dV, (col1+1), line);
+    dparse (&U, col2, line);
+    dparse (&dU, (col2+1), line);
+    dUV = sqrt (dU*dU + dV*dV);
+    x = (U-V - UV0 - 0.7*Av) / DUV;
+    y = (V - d - V0 - Av) / DV;
+    if ((x > 0) && (x < mass_h.Naxis[0]) && (y > 0) && (y < mass_h.Naxis[1])) {
+      mass = Mbuffer[x + NX*y];
+      /*      mass = gfits_get_matrix_value (&mass_i, x, y); */
+      if (mass > 0.0) {
+	age = Abuffer[x + NX*y];
+	fprintf (stdout, "%f %f %f %f %f %f\n", ra, dec, V, U-V, mass, age);
+      }
+    }
+  }
+}
+
+
+
+/*
+
+	**	age = gfits_get_matrix_value (&age_i, x, y);  **
+	I = MAX (MIN ((log10(age) - lAo) / ldA, NAGE - 1), 0); 
+	if (NEWWAY) {
+	  J = MAX (MIN ((4.5 - sqrt(10.0/mass)) / ldM, NMASS - 1), 0);
+	} else {
+	  J = MAX (MIN ((log10(mass) - lMo) / ldM, NMASS - 1), 0); 
+	}
+	Ngood = 1.0;
+	for (k = 0; k < Ntry; k++) {
+	  v = rnd_gauss (V, dV);
+	  uv = rnd_gauss ((U-V), dUV);
+	  x = (uv - UV0 - 0.7*Av) / DUV;
+	  y = (v - d - V0 - Av) / DV;
+	  if ((x > 0) && (x < mass_h.Naxis[0]) && (y > 0) && (y < mass_h.Naxis[1])) {
+	    mass = Mbuffer[x + NX*y];
+	    **	    mass = gfits_get_matrix_value (&mass_i, x, y); **
+	    if (mass > 0.0) {
+	      age = Abuffer[x + NX*y];
+	      ** age = gfits_get_matrix_value (&age_i, x, y);  **
+	      i = MAX (MIN ((log10(age) - lAo) / ldA, NAGE - 1), 0);
+	      if (NEWWAY) {
+		j = MAX (MIN ((4.5 - sqrt(10.0/mass)) / ldM, NMASS - 1), 0);
+	      } else {
+		j = MAX (MIN ((log10(mass) - lMo) / ldM, NMASS - 1), 0); 
+	      }
+	      if ((i == I) && (j == J)) {
+		Ngood += 1.0;
+	      }
+	    }
+	  }
+	}
+	Masses[I][J][0] += (Ntry / Ngood);
+	Masses[I][J][1] += 1.0;
+      }
+    }
+  }
+
+  fprintf (stderr, "finding scatter per bin\n");
+  fprintf (stdout, "# measured IMF \n");
+  fprintf (stdout, "# distance modulus = %5.2, extinction (A_V) = %5.2f\n", d, Av);
+  fprintf (stdout, "# reference mass and age filess: %s, %s\n", argv[1], argv[2]);
+  fprintf (stdout, "# eta = N(logM, logM+dlogM) / dlogM \\sim ln(10.0) * M dN/dM)\n");
+  fprintf (stdout, "# i  Mass   N(mass)  eta   d_eta\n");
+  for (i = 0; i < NAGE; i++) {
+    for (j = 0; j < NMASS; j++) {
+      if (NEWWAY) {
+	mass = 10.0 / SQ(4.5 - ldM*(j+0.5));
+	dlogM = 2.0 * (log10(4.5 - ldM*j) - log10(4.5 - ldM*(j+1)));
+      } else {
+	mass = pow (10.0, (lMo + ldM*(j+0.5)));
+	dlogM = ldM;
+      }
+      eta  = Masses[i][j][0] / dlogM;
+      deta = (Masses[i][j][1] > 0) ? eta / sqrt(Masses[i][j][1]) : 0.0;
+      age  = pow (10.0, (ldA*i + lAo));
+      M = (Masses[i][j][1] > 0) ? Masses[i][j][0]/Masses[i][j][1] : 0;  ** average correction factor **
+      dM = (Masses[i][j][1] > 0) ? Masses[i][j][0]/sqrt(Masses[i][j][1]) : 0;  ** average correction factor **
+      fprintf (stdout, "%4d %4d %5.1f %5.1f %7.1f %7.1f %6.2f %4.0f\n", i, j, mass, age, eta, deta, M, Masses[i][j][1]);
+    }
+  }
+}
+
+*/
+
+double
+rnd_gauss (mean, sigma)
+double mean, sigma; 
+{
+
+  int i;
+  double y;
+
+  y = drand48();
+  i = NGAUSS*y;
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+
+}
+
+
+gauss_init ()
+{
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+	  9.0*gaussian(x+dx1, mean, sigma) +
+	  9.0*gaussian(x+dx2, mean, sigma) + 
+	  3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+rnd_integrate (function, range, mean, sigma) 
+double (*function) ();
+double range, mean, sigma;
+{
+
+  double val, x, dx, dx1, dx2, dx3, df;
+
+  range += 0.0001;
+  val = 0;
+  dx = sigma / 100.0;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+
+  for (x = mean - 7*sigma; (val < range) && (x < mean + 7*sigma); x += dx)  {
+    df = (3.0*function(x    , mean, sigma) + 
+	  9.0*function(x+dx1, mean, sigma) +
+	  9.0*function(x+dx2, mean, sigma) + 
+	  3.0*function(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+  }
+  return (x + dx / 2.0);
+}
+
+double 
+gaussian (x, mean, sigma) 
+double x, mean, sigma; 
+{
+
+  double f, X;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/mkfringetable.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/mkfringetable.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/mkfringetable.c	(revision 16632)
@@ -0,0 +1,207 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+static char *version = "mkfringetable $Revision: 1.9 $";
+
+void get_version (int argc, char **argv, char *version);
+
+int main (int argc, char **argv) {
+
+  int i, j, Npts, NPTS, Nccd, status;
+  char *layout, *config, *file;
+  char filter[64], start[64], stop[64], camera[64], *datestr;
+  char ImagetypeKeyword[64], CCDnumKeyword[64], FilterKeyword[64], CameraKeyword[64];
+  char *row, line[512], field[64], extname[64], filename[512];
+  double x, y, *xmin, *xmax, *ymin, *ymax;
+  FILE *f, *g;
+
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+
+  get_version (argc, argv, version);
+
+  /*** load ptolemy/elixir configuration info ***/
+  file = SelectConfigFile (&argc, argv, "ptolemy");
+  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 (0);
+  }
+  ScanConfig (config, "IMAGETYPE-KEYWORD",           "%s", 0, ImagetypeKeyword);
+  ScanConfig (config, "CCDNUM-KEYWORD",              "%s", 0, CCDnumKeyword);
+  ScanConfig (config, "FILTER-KEYWORD",              "%s", 0, FilterKeyword);
+  ScanConfig (config, "CAMERA-KEYWORD",              "%s", 0, CameraKeyword);
+  free (config);
+  free (file);
+
+  if (argc != 3) {
+    fprintf (stderr, "USAGE: (layout) (output)\n");
+    exit (2);
+  }
+
+  g = fopen (argv[2], "w");
+  if (g == (FILE *) NULL) { 
+    fprintf (stderr, "cannot open %s for output\n", argv[2]);
+    exit (1);
+  }
+
+  /* load info from layout file */
+  layout = LoadConfigFile (argv[1]);
+  if (layout == (char *) NULL) {
+    fprintf (stderr, "cannot open layout file %s\n", argv[1]);
+    exit (1);
+  }
+  status = TRUE;
+  status = status && (NULL == ScanConfig (layout, "NCCD",    "%d", 1, &Nccd));
+  status = status && (NULL == ScanConfig (layout, "FILTER",  "%s", 1, filter));
+  status = status && (NULL == ScanConfig (layout, "CAMERA",  "%s", 1, camera));
+  status = status && (NULL == ScanConfig (layout, "TVSTOP",  "%s", 1, stop));
+  status = status && (NULL == ScanConfig (layout, "TVSTART", "%s", 1, start));
+  if (!status) {
+    fprintf (stderr, "error in layout file\n");
+    fprintf (stderr, "Nccd: %d\n", Nccd);
+    fprintf (stderr, "filter: %s\n", filter);
+    fprintf (stderr, "camera: %s\n", camera);
+    fprintf (stderr, "tvstart: %s\n", start);
+    fprintf (stderr, "tvstop: %s\n", stop);
+    exit (1);
+  }
+
+  { /* save file creation date */ 
+    struct timeval now;
+    gettimeofday (&now, (struct timezone *) NULL);
+    datestr = ohana_sec_to_date (now.tv_sec);
+  }
+
+  /* make phu header (no matrix needed) */
+  gfits_init_header (&header);    
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  
+  gfits_modify (&header, "NEXTEND",        "%d", 1, Nccd);
+  gfits_modify (&header, "DATE",           "%s", 1, datestr);
+  gfits_modify (&header, "TVSTART",        "%s", 1, start);
+  gfits_modify (&header, "TVSTOP",         "%s", 1, stop);
+  gfits_modify (&header, "VERSION",        "%s", 1, version);
+  gfits_modify (&header, CameraKeyword,    "%s", 1, camera);
+  gfits_modify (&header, ImagetypeKeyword, "%s", 1, "FRPTS");
+  gfits_modify (&header, FilterKeyword,    "%s", 1, filter);
+    
+  gfits_fwrite_header  (g, &header);
+  gfits_fwrite_matrix  (g, &matrix);
+
+  ALLOCATE (xmin, double, 1);
+  ALLOCATE (xmax, double, 1);
+  ALLOCATE (ymin, double, 1);
+  ALLOCATE (ymax, double, 1);
+
+  for (i = 0; i < Nccd; i++) {
+
+    /* load entry from layout file */
+    sprintf (field, "CCD%02d", i);
+    if (!ScanConfig (layout, field, "%s", 1, line)) {
+      fprintf (stderr, "missing entry for %s\n", field);
+      exit (1);
+    }
+    sscanf (line, "%s %s", extname, filename);
+
+    /* load data from fringe points file */
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "error opening data file %s\n", filename);
+      exit (1);
+    }
+
+    NPTS = 100;
+    Npts = 0;
+    REALLOCATE (xmin, double, NPTS);
+    REALLOCATE (xmax, double, NPTS);
+    REALLOCATE (ymin, double, NPTS);
+    REALLOCATE (ymax, double, NPTS);
+
+    while (fscanf (f, "%lf %lf", &x, &y) == 2) {
+      xmin[Npts] = x;
+      ymin[Npts] = y;
+      if (fscanf (f, "%lf %lf", &x, &y) != 2) {
+	fprintf (stderr, "Funny line at %d?", Npts);
+	goto done;
+      }
+      xmax[Npts] = x;
+      ymax[Npts] = y;
+      Npts ++;
+      if (Npts == NPTS) {
+	NPTS += 100;
+	REALLOCATE (xmin, double, NPTS);
+	REALLOCATE (xmax, double, NPTS);
+	REALLOCATE (ymin, double, NPTS);
+	REALLOCATE (ymax, double, NPTS);
+      }
+    }
+  done:
+
+    /* create table header */
+    gfits_create_table_header (&theader, "TABLE", extname);
+      
+    /* add current date/time to header */
+    gfits_modify (&theader, "DATE",          "%s", 1, datestr);
+    gfits_modify (&theader, "TVSTART",       "%s", 1, start);
+    gfits_modify (&theader, "TVSTOP",        "%s", 1, stop);
+    gfits_modify (&header, CameraKeyword,    "%s", 1, camera);
+    gfits_modify (&header, ImagetypeKeyword, "%s", 1, "FRPTS");
+    gfits_modify (&header, FilterKeyword,    "%s", 1, filter);
+    gfits_modify (&header, CCDnumKeyword,    "%s", 1, extname);
+    
+    
+    /* define table layout */
+    gfits_define_table_column (&theader, "F6.1", "X_MIN", "min couple x", "pixels"); 
+    gfits_define_table_column (&theader, "F6.1", "Y_MIN", "min couple y", "pixels"); 
+    gfits_define_table_column (&theader, "F6.1", "X_MAX", "max couple x", "pixels"); 
+    gfits_define_table_column (&theader, "F6.1", "Y_MAX", "max couple y", "pixels"); 
+    
+    /* create table, add data values */
+    gfits_create_table (&theader, &table);
+  
+    for (j = 0; j < Npts; j++) {
+      row = gfits_table_print (&table, xmin[j], ymin[j], xmax[j], ymax[j]);
+      gfits_add_rows (&table, row, 1, strlen (row));
+    }
+
+    gfits_fwrite_Theader (g, &theader);
+    gfits_fwrite_table   (g, &table);
+  }
+  exit (0);
+}
+
+/**** support functions ******/
+void get_version (int argc, char **argv, char *version) {
+
+  int N;
+  char *p, *q, *line;
+
+  if (get_argument (argc, argv, "-version")) {
+
+    N = strlen (version) + 2;
+    line = (char *) malloc (N);
+    bzero (line, N);
+
+    p = strstr (version, "$Revision: ");
+    if (p != (char *) NULL) 
+      p += strlen ("$Revision: ");
+    else
+      p = version;
+
+    q = strstr (p, "$");
+    if (q != (char *) NULL) 
+      N = q - p; 
+    else
+      N = strlen (p);
+
+    strncpy (line, p, N);
+
+    fprintf (stderr, "%s\n", line);
+    exit (2);
+  }
+}  
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/mkgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/mkgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/mkgauss.c	(revision 16632)
@@ -0,0 +1,88 @@
+# include <ohana.h>
+
+void   gauss_init ();
+double gaussian (double x, double mean, double sigma);
+double rnd_gauss (double mean, double sigma);
+
+/* NGAUSS defines the resolution of the distribution */
+# define NGAUSS 2048
+static double gaussint[NGAUSS];
+
+int main (int argc, char **argv) {
+
+  int i, Npts;
+  double mean, sigma, f;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: mkgauss (mean) (sigma) (npts)\n");
+    exit (2);
+  }
+
+  mean = atof (argv[1]);
+  sigma = atof (argv[2]);
+  Npts = atoi (argv[3]);
+
+  gauss_init ();
+
+  for (i = 0; i < Npts; i++) {
+    f = rnd_gauss (mean, sigma);
+    fprintf (stdout, "%f\n", f);
+  }
+
+  exit (0);
+}
+
+void gauss_init () {
+
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  val = 0;
+  dx = 0.001;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+
+  for (i = 0, x = -7.0; (i < NGAUSS) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , 0.0, 1.0) + 
+	  9.0*gaussian(x+dx1, 0.0, 1.0) +
+	  9.0*gaussian(x+dx2, 0.0, 1.0) + 
+	  3.0*gaussian(x+dx3, 0.0, 1.0)) * (dx1/8.0);
+    val += df;
+    if (val > (i / (double) NGAUSS)) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+  return;
+}
+
+double gaussian (double x, double mean, double sigma) {
+  double f;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+  return (f);
+}
+
+double rnd_gauss (double mean, double sigma) {
+
+  int i;
+  double y;
+
+  i = 0;
+  while ((i == 0) || (i == NGAUSS - 1)) {
+    y = drand48();
+    i = MIN (NGAUSS - 1, MAX (0, NGAUSS*y));
+  }
+  y = gaussint[i]*sigma + mean;
+
+  return (y);
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/mknames.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/mknames.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/mknames.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "ohana.h"
+extern double drand48();
+
+# define NFILTER 5
+static char filtlist[NFILTER][2] = {"B", "V", "R", "I", "Z"};
+
+int main (int argc, char **argv) {
+ 
+  FILE *f;
+  int j, rnd;
+  int ccd, state;
+  char type[64], filter[64], name[64];
+  struct timeval now;
+  struct tm *gmt;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: mknames (fifo)\n");
+    exit (1);
+  }
+
+  /* lock fifo */
+  f = fsetlockfile (argv[1], 60.0, LCK_XCLD, &state);
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "can't open fifo file\n");
+    fclearlockfile (argv[1], f, LCK_XCLD, &state);
+    exit (1);
+  }
+
+  gettimeofday (&now, (void *) NULL);
+  gmt = gmtime (&now.tv_sec);
+  srand48(now.tv_usec);
+  rnd = 1000*drand48();
+  sprintf (name, "%04d.%02d.%02d.%03d", gmt[0].tm_year + 1900, gmt[0].tm_mon + 1, gmt[0].tm_mday, rnd);
+
+  for (ccd = 0; ccd < 12; ccd++) {
+    strcpy (filter, "X");
+    strcpy (type, "bias");
+    fprintf (f, "%02d %s %s %s\n", ccd, type, filter, name);
+    strcpy (type, "dark");
+    fprintf (f, "%02d %s %s %s\n", ccd, type, filter, name);
+    strcpy (type, "flat");
+    for (j = 0; j < NFILTER; j++) {
+      strcpy (filter, filtlist[j]);
+      fprintf (f, "%02d %s %s %s\n", ccd, type, filter, name);
+    }
+  }
+  fclearlockfile (argv[1], f, LCK_XCLD, &state);
+  exit (0);
+}
+
+  /* 
+     
+     we need to generate a list of entries for 'elixir flips'
+     the entries look like:
+
+     (ccd) (type) (filter) (tend) (nameref)
+
+     (ccd)  - ranges from 00 to 11 
+     (type) - values are bias, dark, flat, ?
+     (filter) - for bias & dark = X
+                for flat = B,V,R,I,Z (Hon?, Hoff?)
+     (tend) = 'NOW' (probably don't need to generate this!)
+     (nameref) = SSSSSS (some string, needs to be unique... based on date?)
+
+  */
+		
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/posscontour.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/posscontour.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/posscontour.c	(revision 16632)
@@ -0,0 +1,126 @@
+# include <stdio.h>
+# include <gfitsio.h>
+# include <math.h>
+# include <malloc.h>
+# include <string.h>
+# include <sys/time.h>
+# include <stdarg.h>
+# include <stdlib.h>
+
+# define TRUE (1)
+# define FALSE (0)
+# define DEG_RAD (57.29578)
+# define RAD_DEG (0.017453293)
+
+char PLTDECSN[5];
+
+double NX, NY, PLTRAH, PLTRAM, PLTRAS, PLTDECD, PLTDECM, PLTDECS, Do, Ro;
+double CNPIX1, CNPIX2, XPIXELSZ, YPIXELSZ, PPO1, PPO2, PPO3, PPO4, PPO5, PPO6;
+double AMDX1, AMDX2, AMDX3, AMDX4, AMDX5, AMDX6, AMDX7, AMDX8, AMDX9, AMDX10, AMDX11, AMDX12, AMDX13;
+double AMDY1, AMDY2, AMDY3, AMDY4, AMDY5, AMDY6, AMDY7, AMDY8, AMDY9, AMDY10, AMDY11, AMDY12, AMDY13;
+
+convert (ra, dec, X, Y) 
+     double *ra, *dec;
+     double X, Y;
+{
+
+  double x, y, Azeta, Aeta, eta, zeta;
+
+  x = (PPO3 - XPIXELSZ*(X+CNPIX1)) / 1000.0;
+  y = (YPIXELSZ*(Y+CNPIX2) - PPO6) / 1000.0;
+  Azeta = AMDX3 + x*(AMDX1 + x*(AMDX4 + AMDX7 + x*AMDX8)) + y*(AMDX2 + y*(AMDX6 + AMDX7 + y*AMDX11)) + x*y*(AMDX9*x + AMDX10*y + AMDX5) + x*(x*x+y*y)*(AMDX12 + AMDX13*(x*x+y*y));
+  Aeta  = AMDY3 + y*(AMDY1 + y*(AMDY4 + AMDY7 + y*AMDY8)) + x*(AMDY2 + x*(AMDY6 + AMDY7 + x*AMDY11)) + x*y*(AMDY9*y + AMDY10*x + AMDY5) + y*(x*x+y*y)*(AMDY12 + AMDY13*(x*x+y*y));
+  
+  eta = Aeta*RAD_DEG/3600.0;
+  zeta = Azeta*RAD_DEG/3600.0;
+  
+  *ra  = DEG_RAD*atan((zeta/cos(RAD_DEG*Do)) / (1.0 - eta*tan(RAD_DEG*Do))) + Ro;
+  *dec = DEG_RAD*atan(((eta + tan(RAD_DEG*Do)) * (cos (RAD_DEG*(*ra - Ro)))) / (1 - eta * tan(RAD_DEG*Do)));
+  
+}
+
+
+main (int argc, char **argv) 
+{
+
+  int i, status;
+  Header header;
+  double RA, DEC, ra, dec, dRA, dDEC;
+  double X, Y, dX, dY;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: posscontour filename < contour.reg\n");
+    exit (0);
+  }
+
+  status = gfits_read_header (argv[1], &header);
+  if (!status) {
+    fprintf (stderr, "error opening file %s\n", argv[1]);
+    exit (0);
+  }
+
+  gfits_scan (&header, "NAXIS1", "%lf", 1, &NX);
+  gfits_scan (&header, "NAXIS2", "%lf", 1, &NY);
+  gfits_scan (&header, "PLTRAH", "%lf", 1, &PLTRAH);
+  gfits_scan (&header, "PLTRAM", "%lf", 1, &PLTRAM);
+  gfits_scan (&header, "PLTRAS", "%lf", 1, &PLTRAS);
+  gfits_scan (&header, "PLTDECD", "%lf", 1, &PLTDECD);
+  gfits_scan (&header, "PLTDECM", "%lf", 1, &PLTDECM);
+  gfits_scan (&header, "PLTDECS", "%lf", 1, &PLTDECS);
+  gfits_scan (&header, "PLTDECSN", "%s", 1, &PLTDECSN);
+  gfits_scan (&header, "CNPIX1", "%lf", 1, &CNPIX1);
+  gfits_scan (&header, "CNPIX2", "%lf", 1, &CNPIX2);
+  gfits_scan (&header, "XPIXELSZ", "%lf", 1, &XPIXELSZ);
+  gfits_scan (&header, "YPIXELSZ", "%lf", 1, &YPIXELSZ);
+  gfits_scan (&header, "PPO1", "%lf", 1, &PPO1);
+  gfits_scan (&header, "PPO2", "%lf", 1, &PPO2);
+  gfits_scan (&header, "PPO3", "%lf", 1, &PPO3);
+  gfits_scan (&header, "PPO4", "%lf", 1, &PPO4);
+  gfits_scan (&header, "PPO5", "%lf", 1, &PPO5);
+  gfits_scan (&header, "PPO6", "%lf", 1, &PPO6);
+  gfits_scan (&header, "AMDX1", "%lf", 1, &AMDX1);
+  gfits_scan (&header, "AMDX2", "%lf", 1, &AMDX2);
+  gfits_scan (&header, "AMDX3", "%lf", 1, &AMDX3);
+  gfits_scan (&header, "AMDX4", "%lf", 1, &AMDX4);
+  gfits_scan (&header, "AMDX5", "%lf", 1, &AMDX5);
+  gfits_scan (&header, "AMDX6", "%lf", 1, &AMDX6);
+  gfits_scan (&header, "AMDX7", "%lf", 1, &AMDX7);
+  gfits_scan (&header, "AMDX8", "%lf", 1, &AMDX8);
+  gfits_scan (&header, "AMDX9", "%lf", 1, &AMDX9);
+  gfits_scan (&header, "AMDX10", "%lf", 1, &AMDX10);
+  gfits_scan (&header, "AMDX11", "%lf", 1, &AMDX11);
+  gfits_scan (&header, "AMDX12", "%lf", 1, &AMDX12);
+  gfits_scan (&header, "AMDX13", "%lf", 1, &AMDX13);
+  gfits_scan (&header, "AMDY1", "%lf", 1, &AMDY1);
+  gfits_scan (&header, "AMDY2", "%lf", 1, &AMDY2);
+  gfits_scan (&header, "AMDY3", "%lf", 1, &AMDY3);
+  gfits_scan (&header, "AMDY4", "%lf", 1, &AMDY4);
+  gfits_scan (&header, "AMDY5", "%lf", 1, &AMDY5);
+  gfits_scan (&header, "AMDY6", "%lf", 1, &AMDY6);
+  gfits_scan (&header, "AMDY7", "%lf", 1, &AMDY7);
+  gfits_scan (&header, "AMDY8", "%lf", 1, &AMDY8);
+  gfits_scan (&header, "AMDY9", "%lf", 1, &AMDY9);
+  gfits_scan (&header, "AMDY10", "%lf", 1, &AMDY10);
+  gfits_scan (&header, "AMDY11", "%lf", 1, &AMDY11);
+  gfits_scan (&header, "AMDY12", "%lf", 1, &AMDY12);
+  gfits_scan (&header, "AMDY13", "%lf", 1, &AMDY13);
+  Ro = 15.0*(PLTRAH + PLTRAM/60.0 + PLTRAS/3600.0);
+  Do = (PLTDECD + PLTDECM/60.0 + PLTDECS/3600.0);
+  if (PLTDECSN[0] == '-') {
+    Do *= -1;
+  }
+
+  while (fscanf (stdin, "%*s %lf %lf %lf %lf", &X, &Y, &dX, &dY) != EOF) {
+    convert (&RA, &DEC, X, Y);
+    convert (&ra, &dec, (X+dX), (Y+dY));
+    dRA = ra - RA;
+    dDEC = dec - DEC;
+    fprintf (stdout, "LINE %f %f %f %f\n", RA, DEC, dRA, dDEC);
+  }
+  
+  gfits_free_header (&header);
+  
+}
+
+
+/* USAGE: posscontour filename < contour.reg > contour2.reg */
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/smaeder.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/smaeder.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/smaeder.c	(revision 16632)
@@ -0,0 +1,516 @@
+# include <ohana.h>
+
+typedef struct {
+  double age;
+  double UV;
+  double V;
+} Model;
+
+typedef struct {
+  double mass;
+  int   Nmodel;
+  Model *model;
+} Track;
+
+int metal;
+double UV0, UV1, dUV;
+double V0, V1, dV;
+int dump, sdump;
+int col1, col2;
+char massfile[1024], agefile[1024];
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  int Ntrack;
+  Track *track, *newtrack;
+
+  args (argc, argv);
+
+  fprintf (stderr, "reading in tracks...\n");
+  readmaeder (argv[1], &track, &Ntrack);
+
+  fprintf (stderr, "smoothing tracks...\n");
+  smoothtracks (&newtrack, track, Ntrack); 
+
+  fprintf (stderr, "interpolating tracks...\n");
+  interpolate_tracks (newtrack, Ntrack);
+
+}
+
+args (argc, argv) 
+int argc;
+char **argv;
+{
+
+  int N;
+
+  metal = 4; /* solar metal */
+  if (N = get_argument (argc, argv, "-metal")) {
+    remove_argument (N, &argc, argv);
+    metal = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  else {
+    fprintf (stderr, "using solar metallicity\n");
+  }
+  
+  dump = -1;
+  if (N = get_argument (argc, argv, "-dump")) {
+    remove_argument (N, &argc, argv);
+    dump = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  sdump = -1;
+  if (N = get_argument (argc, argv, "-sdump")) {
+    remove_argument (N, &argc, argv);
+    sdump = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  col1 = 3;
+  if (N = get_argument (argc, argv, "-col1")) {
+    remove_argument (N, &argc, argv);
+    col1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  col2 = 5;
+  if (N = get_argument (argc, argv, "-col2")) {
+    remove_argument (N, &argc, argv);
+    col2 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  fprintf (stderr, "using mags in columns %d & %d\n", col1, col2);
+  
+  UV0 = -2.0;
+  UV1 =  2.0;
+  dUV =  0.01; 
+  if (N = get_argument (argc, argv, "-color")) {
+    remove_argument (N, &argc, argv);
+    UV0 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    UV1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    dUV = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  V0 =   5.0;
+  V1 = -15.0;
+  dV =  -0.02; 
+  if (N = get_argument (argc, argv, "-mag")) {
+    remove_argument (N, &argc, argv);
+    V0 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    V1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    dV = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (massfile, "mass.fits");
+  if (N = get_argument (argc, argv, "-mass")) {
+    remove_argument (N, &argc, argv);
+    strcpy (massfile, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (agefile, "age.fits");
+  if (N = get_argument (argc, argv, "-age")) {
+    remove_argument (N, &argc, argv);
+    strcpy (agefile, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  
+  if (argc < 2) {
+    fprintf (stderr, "USAGE: smaeder (filename) [options]\n");
+    fprintf (stderr, "  options:\n");
+    fprintf (stderr, "  [-metal N] (N = 0,1,2,3,4)\n");
+    fprintf (stderr, "  [-color min max delta] \n");
+    fprintf (stderr, "  [-mag min max delta] \n");
+    fprintf (stderr, "  [-mass file] \n");
+    fprintf (stderr, "  [-age file]\n");
+    exit (0);
+  }
+}
+
+/* read in the tracks for the requested metalicity */
+/* fairly dependent on the format of the files that Andy produces */
+readmaeder (maederfile, track, Ntrack)
+char  *maederfile;
+Track **track;
+int   *Ntrack;
+{
+
+  int i, j, m;
+  FILE *f;
+  char line[1024];
+  double U, V, ntrack, nmodel;
+
+  f = fopen (maederfile, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "couldn't find maeder tracks (%s)\n", maederfile);
+    exit (0);
+  }
+
+  for (m = 0; m < 5; m ++) {
+    scan_line (f, line);
+    dparse (&ntrack, 1, line);
+    *Ntrack = ntrack;
+    if (m == metal) {
+      ALLOCATE (track[0], Track, *Ntrack);
+    }
+    for (i = 0; i < ntrack; i++) {
+      scan_line (f, line);
+      dparse (&nmodel, 2, line);
+      if (m == metal) {
+	track[0][i].Nmodel = nmodel;
+	dparse (&track[0][i].mass, 1, line);
+	ALLOCATE (track[0][i].model, Model, track[0][i].Nmodel);
+      }
+      for (j = 0; j < nmodel; j++) {
+	scan_line (f, line);
+	if (m == metal) {
+	  dparse (&track[0][i].model[j].age, 1, line);
+	  track[0][i].model[j].age /= 1000000.0;   /* convert to Myrs */
+	  dparse (&U, col1, line);
+	  dparse (&V, col2, line);
+	  track[0][i].model[j].V = V;
+	  track[0][i].model[j].UV = U-V;
+	}
+      }
+    }
+  }
+  fclose (f);
+
+  if (dump > -1) {
+    if (dump >= *Ntrack) {
+      fprintf (stderr, "track %d not found\n", dump);
+      exit (0);
+    } 
+    for (i = 0; i < track[0][dump].Nmodel; i++) {
+      fprintf (stderr, "%d %d %f %e %f %f\n", 
+	       i, track[0][dump].Nmodel, track[0][dump].mass, track[0][dump].model[i].age,
+	       track[0][dump].model[i].V, track[0][dump].model[i].UV);
+    }
+    exit (0);
+  }
+
+}
+
+
+/* convert the tracks to smooth, monotonically increasing color tracks */
+smoothtracks (newtrack, track, Ntrack)
+Track **newtrack, *track;
+int Ntrack;
+{
+
+  int i, j, J1, J2, npts, done;
+  double minC, maxC, dadc, dmdc, age1, mag1, dcolor;
+  double resolution, c1, c2;
+  
+  fprintf (stderr, "smoothing..\n");
+  resolution = dUV;
+  ALLOCATE (newtrack[0], Track, Ntrack);
+  for (i = 0; i < Ntrack ; i++) {
+    /* find min & max colors */
+    minC = track[i].model[0].UV;
+    maxC = -1000;
+    for (j = 0; j < track[i].Nmodel; j++) {
+      maxC = MAX (track[i].model[j].UV, maxC);
+    }
+    npts = (int) ((maxC - minC) / resolution) + 1;
+    ALLOCATE (newtrack[0][i].model, Model, npts);
+    newtrack[0][i].mass = track[i].mass;
+    newtrack[0][i].Nmodel = npts;
+    for (j = 0; j < npts; j++) {
+      newtrack[0][i].model[j].UV = minC + resolution*j;
+    }
+    if (npts == 1) {
+      newtrack[0][i].model[0].age = track[i].model[0].age;
+      newtrack[0][i].model[0].V = track[i].model[0].V;
+      continue;
+    }
+    J1 = 0;
+    for (J2 = J1+1; (J2 < track[i].Nmodel) 
+	   && (track[i].model[J2].UV < track[i].model[J1].UV); J2++);
+    if (J2 == track[i].Nmodel) {
+      fprintf (stderr, "logical error 1\n");
+      exit (0);
+    }
+    dadc = (track[i].model[J2].age   - track[i].model[J1].age) /
+      (track[i].model[J2].UV - track[i].model[J1].UV);
+    dmdc = (track[i].model[J2].V   - track[i].model[J1].V) /
+      (track[i].model[J2].UV - track[i].model[J1].UV);
+    age1 = track[i].model[J1].age;
+    mag1 = track[i].model[J1].V;
+    for (j = 0; j < npts; j++) {
+      if (track[i].model[J2].UV < newtrack[0][i].model[j].UV) {
+	J1 = J2;
+	for (J2 = J1+1; (J2 < track[i].Nmodel) && ((track[i].model[J2].UV < track[i].model[J1].UV) || (track[i].model[J2].UV < newtrack[0][i].model[j].UV)); J2++) {
+	}
+	if (J2 == track[i].Nmodel) {
+	  fprintf (stderr, "logical error 2\n");
+	  exit (0);
+	}
+	dadc = (track[i].model[J2].age   - track[i].model[J1].age) /
+	       (track[i].model[J2].UV - track[i].model[J1].UV);
+	dmdc = (track[i].model[J2].V   - track[i].model[J1].V) /
+	       (track[i].model[J2].UV - track[i].model[J1].UV);
+	age1 = track[i].model[J1].age;
+	mag1 = track[i].model[J1].V;
+      }	
+      dcolor = newtrack[0][i].model[j].UV - track[i].model[J1].UV;
+      newtrack[0][i].model[j].age = dadc * dcolor + age1; 
+      newtrack[0][i].model[j].V = dmdc * dcolor + mag1; 
+    }
+  }
+  fprintf (stderr, "\n");
+
+  if (sdump > -1) {
+    if (sdump >= Ntrack) {
+      fprintf (stderr, "track %d not found\n", sdump);
+      exit (0);
+    }
+    for (i = 0; i < newtrack[0][sdump].Nmodel; i++) {
+      fprintf (stderr, "%d %f %e %f %f\n", 
+	       i, newtrack[0][sdump].mass, newtrack[0][sdump].model[i].age,
+	       newtrack[0][sdump].model[i].V, newtrack[0][sdump].model[i].UV);
+    }
+    exit (0);
+  }
+  
+}
+
+interpolate_tracks (newtrack, Ntrack)
+Track *newtrack;
+int Ntrack;
+{
+ 
+  Header mass_h, age_h;
+  Matrix mass_i, age_i;
+  double Ms, As, Vs, dM, dA, DV, m, a, a1, a2, m1, m2, v, dummy, tmp;
+  double d, minD, uv;
+  int i, j, k, J1, Sx, Sy, Ey;
+  int ii, I0, I1;
+
+  mass_h.bitpix = -32;
+  mass_h.Naxes = 2;
+  mass_h.Naxis[0] = (UV1 - UV0) / dUV;
+  mass_h.Naxis[1] = fabs((V1 - V0) / dV);
+  mass_h.bzero = 0.0;
+  mass_h.bscale = 1.0;
+  mass_h.unsign = FALSE;
+  mass_h.extend = FALSE;
+
+  age_h.bitpix = -32;
+  age_h.Naxes = 2;
+  age_h.Naxis[0] = (UV1 - UV0) / dUV;
+  age_h.Naxis[1] = fabs((V1 - V0) / dV);
+  age_h.bzero = 0.0;
+  age_h.bscale = 1.0;
+  age_h.unsign = FALSE;
+  age_h.extend = FALSE;
+
+  gfits_init_header (&mass_h);
+  gfits_create_header (&mass_h);
+  gfits_create_matrix (&mass_h, &mass_i);
+
+  gfits_init_header (&age_h);
+  gfits_create_header (&age_h);
+  gfits_create_matrix (&age_h, &age_i);
+
+  fprintf (stderr, "created FITS buffers\n");
+
+  for (i = 1; i < Ntrack; i++) {
+    fprintf (stderr, "%d  %d\n", i, newtrack[i].Nmodel);
+    J1 = 0;
+    for (j = 0; j < newtrack[i].Nmodel; j++) {
+      if ((newtrack[i].model[j].V < V0) &&
+	  (newtrack[i].model[j].V > V1) &&
+	  (newtrack[i].model[j].UV > UV0) &&
+	  (newtrack[i].model[j].UV < UV1)) {
+	while ((J1 < newtrack[i-1].Nmodel - 1) && ((int)((newtrack[i].model[j].UV  - UV0) / dUV) > (int)((newtrack[i-1].model[J1].UV  - UV0) / dUV))) {
+	  J1++;
+	}
+	uv = newtrack[i].model[j].UV;
+	Sx = (newtrack[i].model[j].UV  - UV0) / dUV;
+	Sy = (newtrack[i].model[j].V   -  V0) / dV;
+	if (newtrack[i].model[j].UV < newtrack[i-1].model[0].UV) {
+	  tmp = (uv - newtrack[i-1].model[0].UV) / (newtrack[i].model[0].UV -  newtrack[i-1].model[0].UV);
+	  Vs = newtrack[i-1].model[0].V +  tmp * (newtrack[i].model[0].V -  newtrack[i-1].model[0].V);
+	}
+	else {
+	  Vs = newtrack[i-1].model[J1].V;
+	}
+	Ey = (Vs - V0) / dV;
+	if ((j > 20) && (J1 > 20)) {
+	  Vs = newtrack[i-1].model[J1].V;
+	  Ms = newtrack[i-1].mass;
+	  As = newtrack[i-1].model[J1].age;
+	  Ey = (newtrack[i-1].model[J1].V - V0) / dV;
+	  DV = newtrack[i].model[j].V - Vs;
+	  dM = newtrack[i].mass - Ms;
+	  dA = newtrack[i].model[j].age - As;
+	  for (k = Sy; (k >= Ey) && (k >= 0); k--) {
+	    v = k*dV + V0;
+	    m = (v - Vs) * dM / DV + Ms;
+	    a = (v - Vs) * dA / DV + As;
+	    gfits_set_matrix_value (&mass_i, Sx, k, m);
+	    gfits_set_matrix_value (&age_i, Sx, k, a);
+	  }
+	}
+	else {
+	  for (k = Sy; (k >= Ey) && (k >= 0); k--) {
+	    v = k*dV + V0;
+	    minD = 1000;
+	    for (ii = 0; (ii < newtrack[i].Nmodel); ii++) {
+	      I0 = MIN (ii, 20);
+	      tmp = 1.0 / hypot(newtrack[i].model[ii].V - newtrack[i-1].model[I0].V, newtrack[i].model[ii].UV - newtrack[i-1].model[I0].UV);
+	      d = -tmp * ((newtrack[i].model[ii].UV - newtrack[i-1].model[I0].UV)*(v - newtrack[i-1].model[I0].V) - 
+			  (newtrack[i].model[ii].V - newtrack[i-1].model[I0].V)*(uv - newtrack[i-1].model[I0].UV));
+	      if ((d > 0) && (d < minD)) {
+		I1 = ii;
+		minD = d;
+	      }
+	      if (d > minD) {
+		break;
+	      }
+	    }
+	    I0 = MIN (I1, 20);
+	    tmp = ((newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV)*(uv - newtrack[i-1].model[I0].UV) + 
+		   (newtrack[i].model[I1].V - newtrack[i-1].model[I0].V)*(v - newtrack[i-1].model[I0].V)) / 
+	      hypot(newtrack[i].model[I1].V - newtrack[i-1].model[I0].V, newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV);
+	    d = tmp / hypot (newtrack[i].model[I1].V - newtrack[i-1].model[I0].V, newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV);
+	    dM = newtrack[i].mass - newtrack[i-1].mass;
+	    dA = newtrack[i].model[I1].age - newtrack[i-1].model[I0].age;
+	    m1 = d * dM + newtrack[i-1].mass;
+	    a1 = d * dA + newtrack[i-1].model[I0].age;
+	    /*	    fprintf (stderr, "%d  %f  %f  %f  %f  %f\n", I1, minD, d, tmp, dM, m1); */
+	    
+	    tmp = ((newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV)*(uv - newtrack[i-1].model[I0+1].UV) + 
+		   (newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V)*(v - newtrack[i-1].model[I0+1].V)) / 
+	      hypot(newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V, newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV);
+	    d = tmp / hypot (newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V, newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV);
+	    dM = newtrack[i].mass - newtrack[i-1].mass;
+	    dA = newtrack[i].model[I1+1].age - newtrack[i-1].model[I0+1].age;
+	    m2 = d * dM + newtrack[i-1].mass;
+	    a2 = d * dA + newtrack[i-1].model[I0+1].age;
+
+	    d = -((newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV)*(v - newtrack[i-1].model[I0].V) - 
+		 (newtrack[i].model[I1].V - newtrack[i-1].model[I0].V)*(uv - newtrack[i-1].model[I0].UV))
+	      / hypot(newtrack[i].model[I1].V - newtrack[i-1].model[I0].V, newtrack[i].model[I1].UV - newtrack[i-1].model[I0].UV);
+	    tmp = ((newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV)*(v - newtrack[i-1].model[I0+1].V) - 
+		 (newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V)*(uv - newtrack[i-1].model[I0+1].UV))
+	      / hypot(newtrack[i].model[I1+1].V - newtrack[i-1].model[I0+1].V, newtrack[i].model[I1+1].UV - newtrack[i-1].model[I0+1].UV);
+
+	    a = d * (a2 - a1) / (d + tmp) + a1;
+	    m = d * (m2 - m1) / (d + tmp) + m1;
+	    gfits_set_matrix_value (&mass_i, Sx, k, m);
+	    gfits_set_matrix_value (&age_i, Sx, k, a);
+	  }
+	}
+      }
+    }
+  }
+  /*   
+  for (i = 1; i < Ntrack; i++) {
+    fprintf (stderr, "%d  %d\n", i, newtrack[i].Nmodel);
+    for (j = 0; j < newtrack[i].Nmodel; j++) {
+      if ((newtrack[i].model[j].V < V0) &&
+	  (newtrack[i].model[j].V > V1) &&
+	  (newtrack[i].model[j].UV > UV0) &&
+	  (newtrack[i].model[j].UV < UV1)) {
+	Sx = (newtrack[i].model[j].UV  - UV0) / dUV;
+	Sy = (newtrack[i].model[j].V   -  V0) / dV;
+	gfits_set_matrix_value (&age_i, Sx, Sy, 1000.0);
+	gfits_set_matrix_value (&mass_i, Sx, Sy, 1000.0);
+      }
+    }
+  }
+  */
+
+  gfits_modify (&mass_h, "RA_O", "%lf", 1, UV0);
+  gfits_modify (&mass_h, "RA_X", "%lf", 1, dUV);
+  gfits_modify (&mass_h, "RA_Y", "%lf", 1, 0.0);
+  gfits_modify (&mass_h, "DEC_O", "%lf", 1, V0);
+  gfits_modify (&mass_h, "DEC_Y", "%lf", 1, dV);
+  gfits_modify (&mass_h, "DEC_X", "%lf", 1, 0.0);
+
+  gfits_write_header (massfile, &mass_h);
+  gfits_write_matrix (massfile, &mass_i);
+
+  gfits_modify (&age_h, "RA_O",  "%lf", 1, UV0);
+  gfits_modify (&age_h, "RA_X",  "%lf", 1, dUV);
+  gfits_modify (&age_h, "RA_Y",  "%lf", 1, 0.0);
+  gfits_modify (&age_h, "DEC_O", "%lf", 1, V0);
+  gfits_modify (&age_h, "DEC_Y", "%lf", 1, dV);
+  gfits_modify (&age_h, "DEC_X", "%lf", 1, 0.0);
+
+  gfits_write_header (agefile, &age_h);
+  gfits_write_matrix (agefile, &age_i);
+
+}
+
+/*
+ 	  minD = 1000;
+	  for (ii = 0; ii < newtrack[i-1].Nmodel; ii++) {
+	    d = hypot(newtrack[i-1].model[ii].V - v, newtrack[i-1].model[ii].UV - uv);
+	    if (d < minD) {
+	      I0 = ii;
+	      minD = d;
+	    }
+	  }
+	  minD = 1000;
+	  for (ii = 0; ii < newtrack[i].Nmodel; ii++) {
+	    d = hypot(newtrack[i].model[ii].V - v, newtrack[i].model[ii].UV - uv);
+	    if (d < minD) {
+	      I1 = ii;
+	      minD = d;
+	    }
+	  }
+ for (i = 1; i < Ntrack; i++) {
+    fprintf (stderr, "%d  %d\n", i, newtrack[i].Nmodel);
+    J1 = 0;
+    for (j = 0; j < newtrack[i].Nmodel; j++) {
+      if ((newtrack[i].model[j].V < V0) &&
+	  (newtrack[i].model[j].V > V1) &&
+	  (newtrack[i].model[j].UV > UV0) &&
+	  (newtrack[i].model[j].UV < UV1)) {
+	while ((J1 < newtrack[i-1].Nmodel - 1) && ((int)((newtrack[i].model[j].UV  - UV0) / dUV) > (int)((newtrack[i-1].model[J1].UV  - UV0) / dUV))) {
+	  J1++;
+	}
+	Sx = (newtrack[i].model[j].UV  - UV0) / dUV;
+	Sy = (newtrack[i].model[j].V   -  V0) / dV;
+	if (newtrack[i].model[j].UV < newtrack[i-1].model[0].UV) {
+	  tmp = (newtrack[i].model[j].UV - newtrack[i-1].model[0].UV) / (newtrack[i].model[0].UV -  newtrack[i-1].model[0].UV);
+	  Vs = newtrack[i-1].model[0].V +  tmp * (newtrack[i].model[0].V -  newtrack[i-1].model[0].V);
+	  As = newtrack[i-1].model[0].age + tmp * (newtrack[i].model[0].age -  newtrack[i-1].model[0].age);
+	  Ms = newtrack[i-1].mass + tmp * (newtrack[i].mass - newtrack[i-1].mass);
+	  Ey = (Vs  - V0) / dV;
+	}
+	else {
+	  Vs = newtrack[i-1].model[J1].V;
+	  Ms = newtrack[i-1].mass;
+	  As = newtrack[i-1].model[J1].age;
+	  Ey = (newtrack[i-1].model[J1].V - V0) / dV;
+	}
+	DV = newtrack[i].model[j].V - Vs;
+	dM = newtrack[i].mass - Ms;
+	dA = newtrack[i].model[j].age - As;
+	for (k = Sy; (k >= Ey) && (k >= 0); k--) {
+	  v = k*dV + V0;
+	  m = (v - Vs) * dM / DV + Ms;
+	  gfits_set_matrix_value (&mass_i, Sx, k, m);
+	  a = (v - Vs) * dA / DV + As;
+	  gfits_set_matrix_value (&age_i, Sx, k, a);
+	}
+      }
+    }
+  }
+*/
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/striphead.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/striphead.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/striphead.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include <ohana.h>
+
+main (argc, argv) 
+int argc;
+char *argv[];
+{
+
+  int i, j, status, N, FORCE;
+  char head[1000];
+  Header header;
+  char *p;
+  FILE *f;
+
+  if (get_argument (argc, argv, "-help") || get_argument (argc, argv, "-h")) {
+    fprintf (stderr, "USAGE: %s [-f] (filenames)\n", argv[0]);
+    exit (0);
+  }
+
+  if (N = get_argument (argc, argv, "-f")) {
+    remove_argument (N, &argc, argv);
+    FORCE = TRUE;
+  }
+  else 
+    FORCE = FALSE;
+  
+  if (argc == 1) {
+    fprintf (stderr, "USAGE: %s [-f] (filenames)\n", argv[0]);
+    exit (0);
+  }
+
+  for (i = 1; i < argc; i++) {
+    
+    strcpy (head, argv[i]);
+    if (strrchr(head, '.') !=NULL)
+      strcpy(strrchr(head, '.'), ".head");
+    else 
+      strcat(head, ".head");
+    
+    if (!FORCE) {
+      f = fopen (head, "r");
+      if (f != NULL) {
+	fprintf (stderr, "header file exists for %s, skipping\n", argv[i]);
+	fclose (f);
+	continue;
+      }
+    }
+    
+    if (!gfits_read_header (argv[i], &header)) {
+      fprintf (stderr, "failed to open file %s\n", argv[i]);
+      continue;
+    }
+    
+    for (j = 79; j < header.size; j+= 80) {
+      header.buffer[j] = 10;
+    }
+
+    if (!gfits_write_header (head, &header)) {
+      fprintf (stderr, "failed to write file %s\n", head);
+      continue;
+    }
+    
+    gfits_free_header (&header);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/misc/src/usmaeder.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/misc/src/usmaeder.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/misc/src/usmaeder.c	(revision 16632)
@@ -0,0 +1,194 @@
+# include <ohana.h>
+
+
+void main (argc, argv)
+int argc;
+char **argv;
+{
+
+  Header mass_h, age_h, UV_h, V_h;
+  Matrix mass_i, age_i, UV_i, V_i;
+  int x, y, X, Y, X0, X1, Y0, Y1, NAGE, NMASS, N;
+  double ldA, lAo, ldM, lMo, age, mass;
+  double v, uv, UV0, DUV, V0, DV, slope_x, slope_y, tmp;
+  
+  lAo =   0.0;
+  ldA =   0.01;
+  NAGE =  320;
+  if (N = get_argument (argc, argv, "-age")) {
+    remove_argument (N, &argc, argv);
+    lAo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldA = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NAGE = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  lMo = -0.1;
+  ldM =  0.05;
+  NMASS = 50;
+  if (N = get_argument (argc, argv, "-mass")) {
+    remove_argument (N, &argc, argv);
+    lMo = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ldM = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NMASS = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE %s massfile agefile colorfile magfile\n", argv[0]);
+    fprintf (stderr, "  options:\n");
+    fprintf (stderr, "  [-mass lMo ldM NMASS]\n");
+    fprintf (stderr, "  [-age  lAo ldA NAGE]\n");
+    exit (0);
+  }
+
+  gfits_read_header (argv[1], &mass_h);
+  gfits_read_matrix (argv[1], &mass_i);
+  gfits_read_header (argv[2], &age_h);
+  gfits_read_matrix (argv[2], &age_i); 
+
+  gfits_scan (&mass_h, "RA_O",  "%lf", 1, &UV0);
+  gfits_scan (&mass_h, "RA_X",  "%lf", 1, &DUV);
+  gfits_scan (&mass_h, "DEC_O", "%lf", 1, &V0);
+  gfits_scan (&mass_h, "DEC_Y", "%lf", 1, &DV);
+
+  V_h.bitpix = -32;
+  V_h.Naxes = 2;
+  V_h.Naxis[0] = NAGE;
+  V_h.Naxis[1] = NMASS;
+  V_h.bzero = 0.0;
+  V_h.bscale = 1.0;
+  V_h.unsign = FALSE;
+  V_h.extend = FALSE;
+
+  UV_h.bitpix = -32;
+  UV_h.Naxes = 2;
+  UV_h.Naxis[0] = NAGE;
+  UV_h.Naxis[1] = NMASS;
+  UV_h.bzero = 0.0;
+  UV_h.bscale = 1.0;
+  UV_h.unsign = FALSE;
+  UV_h.extend = FALSE;
+
+  gfits_init_header (&V_h);
+  gfits_create_header (&V_h);
+  gfits_create_matrix (&V_h, &V_i);
+
+  gfits_init_header (&UV_h);
+  gfits_create_header (&UV_h);
+  gfits_create_matrix (&UV_h, &UV_i);
+  fprintf (stderr, "created FITS buffers\n");
+
+  gfits_modify (&V_h, "RA_O", "%lf", 1, lAo);
+  gfits_modify (&V_h, "RA_X", "%lf", 1, ldA);
+  gfits_modify (&V_h, "RA_Y", "%lf", 1, 0.0);
+  gfits_modify (&V_h, "DEC_O", "%lf", 1, lMo);
+  gfits_modify (&V_h, "DEC_Y", "%lf", 1, ldM);
+  gfits_modify (&V_h, "DEC_X", "%lf", 1, 0.0);
+
+  gfits_modify (&UV_h, "RA_O",  "%lf", 1, lAo);
+  gfits_modify (&UV_h, "RA_X",  "%lf", 1, ldA);
+  gfits_modify (&UV_h, "RA_Y",  "%lf", 1, 0.0);
+  gfits_modify (&UV_h, "DEC_O", "%lf", 1, lMo);
+  gfits_modify (&UV_h, "DEC_Y", "%lf", 1, ldM);
+  gfits_modify (&UV_h, "DEC_X", "%lf", 1, 0.0);
+
+  /* the value of 100 is hard wired in this and the others as a bad color */
+
+  for (x = 0; x < NAGE; x++) {
+    for (y = 0; y < NMASS; y++) {
+      gfits_set_matrix_value (&UV_i, x, y, 100.0); 
+      gfits_set_matrix_value (&V_i, x, y, 100.0); 
+    }
+  }
+
+  for (x = 0; x < mass_h.Naxis[0]; x++) {
+    fprintf (stderr, ".");
+    for (y = 0; y < mass_h.Naxis[1]; y++) {
+      mass = gfits_get_matrix_value (&mass_i, x, y);
+      age = gfits_get_matrix_value (&age_i, x, y); 
+      if (mass > 0) {
+	X = (log10(age) - lAo) / ldA;
+	Y = (log10(mass) - lMo) / ldM;
+	if ((X >= 0) && (X < NAGE) &&
+	    (Y >= 0) && (Y < NMASS)) {
+	  uv = x*DUV + UV0;
+	  v  = y*DV + V0;
+	  gfits_set_matrix_value (&UV_i, X, Y, uv); 
+	  gfits_set_matrix_value (&V_i, X, Y, v); 
+	}
+      }
+    }
+  }
+  fprintf (stderr, "\n");
+
+  /* fix the holes */
+  for (x = 0; x < NAGE; x++) {
+    for (y = 0; y < NMASS; y++) {
+      uv = gfits_get_matrix_value (&UV_i, x, y);
+      if (uv == 100.0) {
+	/* find neighbors up and down */
+	X1 = NAGE; Y1 = NMASS;
+	X0 = Y0 = -1;
+	for (X = x + 1; X < NAGE; X++) {
+	  if ((gfits_get_matrix_value (&UV_i, X, y)) != 100.0) {
+	    X1 = X;
+	    break;
+	  }
+	}
+	for (X = x - 1; X >= 0; X--) {
+	  if ((gfits_get_matrix_value (&UV_i, X, y)) != 100.0) {
+	    X0 = X;
+	    break;
+	  }
+	}
+	for (Y = y + 1; Y < NMASS; Y++) {
+	  if ((gfits_get_matrix_value (&UV_i, x, Y)) != 100.0) {
+	    Y1 = Y;
+	    break;
+	  }
+	}
+	for (Y = y - 1; Y >= 0; Y--) {
+	  if ((gfits_get_matrix_value (&UV_i, x, Y)) != 100.0) {
+	    Y0 = Y;
+	    break;
+	  }
+	}
+	slope_x = slope_y = 100000.0;
+	if ((X1 < NAGE) && (X0 > -1)) {
+	  slope_x = (gfits_get_matrix_value (&UV_i, X1, y) - gfits_get_matrix_value (&UV_i, X0, y)) / (X1 - X0);
+	}
+	if ((Y1 < NMASS) && (Y0 > -1)) {
+	  slope_y = (gfits_get_matrix_value (&UV_i, x, Y1) - gfits_get_matrix_value (&UV_i, x, Y0)) / (Y1 - Y0);
+	}
+	if ((fabs(slope_x) < fabs(slope_y)) && (slope_x != 100000.0)) {
+	  uv = (x - X0) * slope_x + gfits_get_matrix_value (&UV_i, X0, y);
+	  tmp = (gfits_get_matrix_value (&V_i, X1, y) - gfits_get_matrix_value (&V_i, X0, y)) / (X1 - X0);
+	  v  = (x - X0) * tmp + gfits_get_matrix_value (&V_i, X0, y);
+	  gfits_set_matrix_value (&UV_i, x, y, uv); 
+	  gfits_set_matrix_value (&V_i, x, y, v); 
+	}	  
+	if ((fabs(slope_x) >= fabs(slope_y)) && (slope_y != 100000.0)) {
+	  uv = (y - Y0) * slope_y + gfits_get_matrix_value (&UV_i, x, Y0);
+	  tmp = (gfits_get_matrix_value (&V_i, x, Y1) - gfits_get_matrix_value (&V_i, x, Y0)) / (Y1 - Y0);
+	  v  = (y - Y0) * tmp + gfits_get_matrix_value (&V_i, x, Y0);
+	  gfits_set_matrix_value (&UV_i, x, y, uv); 
+	  gfits_set_matrix_value (&V_i, x, y, v); 
+	}	  
+      }
+    }
+  }
+	
+
+
+  gfits_write_header (argv[3], &V_h);
+  gfits_write_matrix (argv[3], &V_i);
+  gfits_write_header (argv[4], &UV_h);
+  gfits_write_matrix (argv[4], &UV_i);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/Makefile	(revision 16632)
@@ -0,0 +1,97 @@
+default: mosastro
+help:
+	@echo "make options: mosastro (default) mkstandards mkobs warptest"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/mosastro
+LIB	=	$(HOME)/lib
+BIN	=	$(HOME)/bin
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+mosastro: $(BIN)/mosastro.$(ARCH)
+mkstandards: $(BIN)/mkstandards.$(ARCH)
+mkobs: $(BIN)/mkobs.$(ARCH)
+warptest: $(BIN)/warptest.(ARCH)
+install: $(DESTBIN)/mosastro $(DESTBIN)/mosastro $(DESTBIN)/mosastro
+
+MOS = \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/ConvertMatch.$(ARCH).o \
+$(SRC)/FitChips.$(ARCH).o \
+$(SRC)/FitGradients.$(ARCH).o \
+$(SRC)/GetGradients.$(ARCH).o \
+$(SRC)/GetScatter.$(ARCH).o \
+$(SRC)/LoadStars.$(ARCH).o \
+$(SRC)/SaveResiduals.$(ARCH).o \
+$(SRC)/args.$(ARCH).o \
+$(SRC)/chips.$(ARCH).o \
+$(SRC)/clip.$(ARCH).o \
+$(SRC)/dump.$(ARCH).o \
+$(SRC)/field.$(ARCH).o \
+$(SRC)/fitpoly.$(ARCH).o \
+$(SRC)/getgsc.$(ARCH).o \
+$(SRC)/getptolemy.$(ARCH).o \
+$(SRC)/getstone.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/getusnob.$(ARCH).o \
+$(SRC)/greference.$(ARCH).o \
+$(SRC)/match.$(ARCH).o \
+$(SRC)/mkheader.$(ARCH).o \
+$(SRC)/mkmosaic.$(ARCH).o \
+$(SRC)/mkpolyterm.$(ARCH).o \
+$(SRC)/mosastro.$(ARCH).o \
+$(SRC)/output.$(ARCH).o \
+$(SRC)/parse_time.$(ARCH).o \
+$(SRC)/project.$(ARCH).o \
+$(SRC)/rfits.$(ARCH).o \
+$(SRC)/rtext.$(ARCH).o \
+$(SRC)/testcoords.$(ARCH).o \
+$(SRC)/transforms.$(ARCH).o \
+$(SRC)/wfits.$(ARCH).o \
+$(SRC)/wstars.$(ARCH).o
+
+STD = \
+$(SRC)/mkstandards.$(ARCH).o \
+$(SRC)/mkheader.$(ARCH).o \
+$(SRC)/random.$(ARCH).o \
+$(SRC)/wstars.$(ARCH).o \
+$(SRC)/wfits.$(ARCH).o
+
+OBS = \
+$(SRC)/args_obs.$(ARCH).o \
+$(SRC)/mkobs.$(ARCH).o \
+$(SRC)/mkheader.$(ARCH).o \
+$(SRC)/fakefield.$(ARCH).o \
+$(SRC)/greference.$(ARCH).o \
+$(SRC)/project.$(ARCH).o \
+$(SRC)/transforms.$(ARCH).o \
+$(SRC)/dump.$(ARCH).o \
+$(SRC)/ConfigInit.$(ARCH).o \
+$(SRC)/get2mass.$(ARCH).o \
+$(SRC)/getgsc.$(ARCH).o \
+$(SRC)/getptolemy.$(ARCH).o \
+$(SRC)/getstone.$(ARCH).o \
+$(SRC)/gptolemy.$(ARCH).o \
+$(SRC)/gregions.$(ARCH).o \
+$(SRC)/gcatalog.$(ARCH).o \
+$(SRC)/getusno.$(ARCH).o \
+$(SRC)/mkpolyterm.$(ARCH).o \
+$(SRC)/random.$(ARCH).o \
+$(SRC)/wstars.$(ARCH).o
+
+$(MOS) : $(INC)/mosastro.h
+$(OBS) : $(INC)/mosastro.h
+$(STD) : $(INC)/mosastro.h
+
+$(BIN)/mosastro.$(ARCH) : $(MOS)
+$(BIN)/mkstandards.$(ARCH) : $(STD)
+$(BIN)/mkobs.$(ARCH) : $(OBS)
+$(BIN)/warptest.(ARCH) : $(SRC)/warptest.$(ARCH).o
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,17 @@
+
+- mosastro 1.3 : 2006.08.23
+  * converted to gfits APIs (forces libfits 1.6)
+  * converted to new DVO APIs (forces libdvo 1.3)
+  * removed old unused code
+
+- mosastro 1.2
+  * added USNO-B
+  * require min number on chip
+
+- mosastro 1.1
+  * minor cleanups
+
+2005.10.20 : mosastro-1-0
+
+  added support for new dvo load methods
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/doc/astrom.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/doc/astrom.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/doc/astrom.txt	(revision 16632)
@@ -0,0 +1,99 @@
+mosaic astrometry keywords
+
+terms to model:
+
+boresite + projection
+Ro, Do, Theta, PS
+CTYPE, CRVAL, CRPIX, CD1_1
+
+distortion 
+A(i,j), D(i,j)
+WLi_j
+WMi_j
+
+chips
+WXi_j
+WYi_j
+
+-- these are not general since they don't allow for more than 2 dimensions
+-- these have the advantage of specifying which terms are available (WX0_2 is unambiguously X term for L^0M^2)
+
+- load the astrometry from a table (not very efficient unless all chip
+  terms are in the same table, which is an option)
+
+X = \Sum (WX_i_j) L^i M^j
+Y = \Sum (WY_i_j) L^i M^j
+
+L = \Sum (WL_i_j) P^i Q^j
+M = \Sum (WM_i_j) P^i Q^j
+
+P,Q = proj (R,D)[CTYPE, CRVAL, CRPIX, CDi_j]
+
+      
+Implementing the mosaic astrometry information in Elixir systems vs IPP.
+
+Elixir uses libohana/coordops to handle all coordinate
+transformations.  The coordinate structure (Coords) is part of the
+DVO/Images.h structure.  I cannot add an additional set of entries to
+that structure without breaking old DVO or other elixir code.  It is
+also not strictly relevant since the Coords structure is used to
+define the transformation of a single chip (and is sufficient to carry
+those terms up to 3rd order).  
+
+For elixir, we will need a two stage process, with one stage
+transforming the celestial coords to the focal plane, with PLY terms
+and a second to represent the chip to FP transform, with a varient on
+PLY terms.  (we can't use PLY since those use a projection, while we
+want a transform that only corrsponds to an Nth order polynomial onto
+a plane.  We should call this transform WRP, with ctype PLN-WRP and
+terms:
+
+crval1,2 = L,M coordinates for reference pixel
+crpix1,2 = X,Y coordinates for reference pixel
+cdelt1,2 = plate scale (should be  1,1 by default)
+etc.
+
+A third order warp couple to a third order distortion leads to 6th
+order terms in general.  
+
+--
+
+My plan is now to allow the dvo image table to represent chips in a mosaic
+with either the current (per-chip) entry or an entry per chip coupled
+to an entry per mosaic.  The chip image entries would have astrometric
+terms of up-to third order which transform from chip to focal plane,
+coupled in turn to a mosaic entry in the table giving astrometry from
+focal plane to the sky.  The chip-to-fp entries would be identified
+with astrometry CTYPE value of "-WRP" and the fp-to-sky would have
+entries with CTYPE value of "-MOS". 
+
+- does this information go in the header of each *.smp file?  
+- does this require us to package all chips in a single MEF smp
+- package?
+- mosastro would create the astrometry terms (per-chip and
+- per-mosaic), where does it store them?
+- minimal impact on addstar?
+
+- what are the implications for dvo?
+  - image I/O functions need to know about the mosaic
+
+- how do we match a chip to a mosaic?
+  chip is unique based on time and photcode.
+  - we could require the mosaic photcode entries to have values of
+  PRI/SEC
+
+: mosastro should construct a PHU element 654321oXX.smp which contains
+  the mosaic astrometry terms
+
+: alternatively: each .smp file could have a collection of header
+  keywords which specify the mosaic astrometry terms.
+
+: alternatively again, the 
+
+: photcode for the mosaic entry is CAMERA.FILTER.XX
+: addstar would have to have access to this file for each chip
+: addstar should not create a new mosaic entry
+
+: how do we handle GetCoords (which needs to construct TWO coords
+  structures for output in the case of a mosaic?)
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/doc/notes.txt	(revision 16632)
@@ -0,0 +1,59 @@
+
+- need to update header astrometry 
+  - determine higher-order polynomial terms from fit?
+  - insert all distortion & warping terms into header?
+
+- better input parameters:
+  - use camera to define chips we expect to find
+  - camera -> default warp
+  - add dispersion stats to header in output (CERROR, CPRECISE)
+
+- allow chips to have full linear terms (after warp)
+
+- load 2mass, USNO SA data
+
+-----------------------------------------
+- load *.smp / *.cmp : 
+  chip[i].pt[j].x
+  chip[i].pt[j].y
+  chip[i].coords
+  (global Ro, Do = RA_DEG, DEC_DEG)
+
+- load usno in region
+  stars[i].r, stars[i].d
+
+- match usno:smp:
+  chip[i].pt[j].r, chip[i].pt[j].d
+
+- project ra,dec to p,q (arcsec on sky relative to Ro, Do)
+  chip[i].pt[j].p, chip[i].pt[j].q
+
+- init chip paramters:
+  chip[i].Px, chip[i].Py - parities
+  chip[i].Po, chip[i].Qo, chip[i].To
+
+  * p' = Px*(p - Po), q' = Py*(q - Qo)
+  * x = cos(To) p' + sin(To) q'
+  * y = cos(To) p' + sin(To) q'
+
+- other parameter:
+  * field.Ro, field.Do - not fitted
+  field.A[0] - field.A[5]
+  field.D[0] - field.D[5]
+
+
+  (r,d) -> field.coords -> (p,q) [arcsec from field center]
+  (p,q) -> field.A,D    -> (L,M) [pixels from field center]
+  (L,M) -> Px,Py,Po,Qo  -> (P,Q) [pixels from chip corner]
+  (P,Q) -> To		-> (x,y) [pixels on chip]
+
+  L = A[0] + A[1]*p + A[2]*q + A[3]*p^2 + A[4]*q^2 + A[5]*p*q
+  M = D[0] + D[1]*p + D[2]*q + D[3]*p^2 + D[4]*q^2 + D[5]*p*q
+
+  p' = Px*(L - Po)
+  q' = Py*(M - Qo)
+
+  x = cos(To) p' + sin(To) q'
+  y = cos(To) p' + sin(To) q'
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/doc/update.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/doc/update.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/doc/update.txt	(revision 16632)
@@ -0,0 +1,8 @@
+
+mosastro USAGE:
+
+  - mosastro (inglob) (outext) [-dist (distort)] [-chips (chipset)]
+
+  * given a collection of chip data, measure the complete model
+    parameters relative to reference.  output is individual chip files
+    with a new extension (and updated header contents)
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/include/mosastro.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/include/mosastro.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/include/mosastro.h	(revision 16632)
@@ -0,0 +1,197 @@
+# include <ohana.h>
+# include <dvo.h>
+
+# define PSASTRO_MODE 0
+
+typedef struct {
+  double R, D;  /* Sky Coords    - degrees */
+  double P, Q;  /* Tangent Plane - pixels  */
+  double L, M;  /* Focal Plane   - pixels  */
+  double X, Y;  /* Chip Coords   - pixels  */
+  double Mag, dMag;
+  int mask;
+} StarData;
+
+typedef struct {
+  double RA[2], DEC[2];
+  double Area;
+  char *name;
+} CatStats;
+
+typedef struct {
+  char *file;
+  int Nstars;
+  int NX, NY;
+  StarData *stars;
+  Header header;
+  Header theader;
+  Matrix matrix;
+
+  char *buffer;
+  int Nbuffer;
+  int FITS;
+
+  int Nmatch;
+  StarData *raw, *ref;
+
+  Coords coords;
+  Coords map;
+} Chip;
+
+typedef struct {
+  double Ro, Do, PSx, PSy, To;
+  double Rmin, Rmax, Dmin, Dmax;
+  int    Norder;
+  double **A;
+  double **D;
+  Coords project;
+  Coords distort;
+  int    fit;
+} Field;
+
+typedef struct {
+  double *dPdL;
+  double *dPdM;
+  double *dQdL;
+  double *dQdM;
+  double *Lo;
+  double *Mo;
+  int Npts;
+} Gradients;
+
+typedef struct {
+  double Rraw, Draw; /* Sky Coords    - degrees */
+  float Praw, Qraw;  /* Tangent Plane - pixels  */
+  float Lraw, Mraw;  /* Focal Plane   - pixels  */
+  float Xraw, Yraw;  /* Chip Coords   - pixels  */
+
+  double Rref, Dref; /* Sky Coords    - degrees */
+  float Pref, Qref;  /* Tangent Plane - pixels  */
+  float Lref, Mref;  /* Focal Plane   - pixels  */
+  float Xref, Yref;  /* Chip Coords   - pixels  */
+
+  float Mcat, dMcat;
+  float Minst, dMinst;
+  char mask;
+} MatchData;
+
+int  ChipOrder;
+int  Nchip;
+Chip *chip;
+Field field;
+double Year;  /** carried for precession - probably put this in chip data **/
+double RADIUS; /** raw / ref matching radius (pixels on Focal Plane) **/
+double SIGMA;
+double SIGMA_LIM;
+double IMAG_MIN;
+double IMAG_MAX;
+double INST_BRIGHT;
+double ZERO_POINT;
+
+char REFCAT[256];
+char CATMODE[16];    /* raw, mef, split, mysql */
+char CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char ExptimeKeyword[256];
+char DateKeyword[256];
+char DateMode[256];
+char UTKeyword[256];
+char MJDKeyword[256];
+char JDKeyword[256];
+int VERBOSE;
+int NO_CHIPS;
+int SAVE_RESID;
+
+char CATDIR[256];
+char GSCFILE[256];
+char GSCDIR[256];
+char USNO_A_DIR[256];
+char USNO_B_DIR[256];
+char TWO_MASS_DIR[256];
+char ASTROM_CATDIR[256];
+char StoneRegions[256];
+
+char *FIELD;
+char *CHIPS;
+char *OUTPUT;
+char *DUMP;
+char *FOCAL_PLANE;
+
+/*** mosastro prototypes ***/
+void       ChipToFP           PROTO((StarData *stars, int Nstars, Coords *coords));
+void       ChipToSky          PROTO((StarData *stars, int Nstars, Coords *coords));
+int        ClipOnFP           PROTO((double Nsigma));
+void       ConfigInit         PROTO((int *argc, char **argv));
+int        ConvertMatch       PROTO((MatchData *data, int size, int nitems));
+void       FPtoChip           PROTO((StarData *stars, int Nstars, Coords *coords));
+void       FPtoTP             PROTO((StarData *stars, int Nstars, Coords *coords));
+void       FitChip            PROTO((StarData *raw, StarData *ref, int Nmatch, Coords *coords));
+void       FitChipLinear      PROTO((StarData *raw, StarData *ref, int Nmatch, Coords *coords));
+void       FitChipResid       PROTO((StarData *raw, StarData *ref, int Nmatch, Coords *coords));
+void       FitChips           PROTO((int Norder));
+void       FitGradients       PROTO((Gradients *grad));
+void       GetConfig          PROTO((char *config, char *field, char *format, int N, void *ptr));
+Gradients *GetGradients       PROTO(());
+double     GetScatter         PROTO((int *Nscatter, double *DL, double *DM, int bright));
+int        LoadStars          PROTO((int Nfile, char **file));
+void       SaveResiduals      PROTO((FILE *f, Header *header));
+void       SkyToTP            PROTO((StarData *stars, int Nstars, Coords *coords));
+void       TPtoFP             PROTO((StarData *stars, int Nstars, Coords *coords));
+void       TPtoSky            PROTO((StarData *stars, int Nstars, Coords *coords));
+void       add_to_regions     PROTO((CatStats *area));
+void       area_of_region     PROTO((CatStats *region));
+void       args               PROTO((int *argc, char **argv));
+int        deproject_raw      PROTO(());
+int        deproject_stars    PROTO(());
+int        dump_grads         PROTO((Gradients *grad, char *filename));
+int        dump_match         PROTO(());
+int        dump_rawstars      PROTO(());
+int        dump_refcat        PROTO((StarData *refcat, int Nrefcat));
+int        dump_stars         PROTO((FILE *f, StarData *stars, int Nstars));
+int        fake_field         PROTO((double RA, double DEC));
+void       field_combine      PROTO(());
+void       field_stats        PROTO(());
+int        find_dec_bands     PROTO((CatStats *area));
+void       fit_add            PROTO((double x1, double y1, double x2, double y2));
+void       fit_apply_coords   PROTO((Coords *coords));
+void       fit_apply_grads    PROTO((Coords *distort, Coords *project, int term));
+void       fit_correct_grads  PROTO((Gradients *in, Gradients *out, int term));
+void       fit_eval           PROTO(());
+void       fit_free           PROTO(());
+void       fit_init           PROTO((int order));
+int        gaussj             PROTO((double **a, int n, double **b, int m));
+StarData  *gcatalog           PROTO((char *filename, int *Nstars));
+StarData  *get2mass           PROTO((CatStats *catstats, int *NSTARS));
+StarData  *getgsc             PROTO((CatStats *catstats, int *NSTARS));
+StarData  *getptolemy         PROTO((CatStats *catstats, int *NSTARS));
+StarData  *getstone           PROTO((CatStats *input, int *nstars));
+StarData  *getusno            PROTO((CatStats *catstats, int *Nstars));
+StarData  *getusnob           PROTO((CatStats *catstats, int *Nstars));
+StarData  *gptolemy           PROTO((char *filename, int *NSTARS));
+StarData  *greference         PROTO((int *Nrefcat));
+CatStats  *gregions           PROTO((CatStats *patch, int *nregion));
+int        init_chips         PROTO(());
+int        init_field         PROTO(());
+void       init_regions       PROTO(());
+int        load_chips         PROTO((char *filename));
+int        load_field         PROTO((char *filename));
+int        load_ra_blocks     PROTO((int Ndec, CatStats *area));
+int        match              PROTO((StarData *refcat, int Nrefcat));
+Header    *mkheader           PROTO((int Nx, int Ny, int Nstars, Coords *coords));
+Header    *mkmosaic           PROTO((int Nx, int Ny, int Nstars, Coords *coords));
+int        mkpolyterm         PROTO((int n, int m));
+int        mkvector           PROTO((int n, int m, int norder));
+void       output             PROTO((char *ext, char *phu));
+int        parse_GSC_line     PROTO((CatStats *tregion, char *line));
+e_time     parse_time         PROTO((Header *header));
+void       print_help         PROTO(());
+int        project_ref        PROTO(());
+int        project_refcat     PROTO((StarData *refcat, int Nrefcat));
+int        project_stars      PROTO(());
+int        rfits              PROTO((Chip *mychip));
+int        rtext              PROTO((Chip *mychip));
+void       set_catalog        PROTO((char *catdir));
+int        sortthree          PROTO((double *X, double *Y, int *Z, int N));
+void       uppercase          PROTO((char *string));
+void       wchip              PROTO((char *filename, Chip *data));
+void       wfits              PROTO((char *filename, SMPData *stars, int Nstars, Header *header));
+void       wstars             PROTO((char *filename, SMPData *stars, int Nstars, Header *header));
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "mosastro.h"
+
+void ConfigInit (int *argc, char **argv) {
+  
+  char *config, *file;
+
+  VERBOSE = TRUE;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "GSCFILE",          "%s",  0, GSCFILE);
+
+  GetConfig (config, "ASTRO_REFCAT",      "%s",  0, REFCAT);
+
+  /* possible sources of astrometric reference data */
+  if (!ScanConfig (config, "USNO_A_DIR",             "%s",  0, USNO_A_DIR)) {
+    ScanConfig (config, "USNO_CDROM",             "%s",  0, USNO_A_DIR);
+  }
+  ScanConfig (config, "USNO_B_DIR",       "%s",  0, USNO_B_DIR);
+  ScanConfig (config, "GSCDIR",           "%s",  0, GSCDIR);
+  ScanConfig (config, "STONE_DIR",        "%s",  0, StoneRegions);
+  ScanConfig (config, "2MASS_DIR",        "%s",  0, TWO_MASS_DIR);
+  ScanConfig (config, "ASTROM_CATDIR",    "%s",  0, ASTROM_CATDIR);
+
+  /* abstracted header keywords - used by parse_time */
+  ScanConfig (config, "DATE-KEYWORD",     "%s",  0, DateKeyword);
+  ScanConfig (config, "DATE-MODE",        "%s",  0, DateMode);
+  ScanConfig (config, "UT-KEYWORD",       "%s",  0, UTKeyword);
+  ScanConfig (config, "MJD-KEYWORD",      "%s",  0, MJDKeyword);
+  ScanConfig (config, "JD-KEYWORD",       "%s",  0, JDKeyword);
+  ScanConfig (config, "EXPTIME-KEYWORD",  "%s",  0, ExptimeKeyword);
+
+  GetConfig  (config, "RADIUS",           "%lf", 0, &RADIUS);
+  GetConfig  (config, "SIGMA_LIM",        "%lf", 0, &SIGMA_LIM);
+  ScanConfig (config, "ZERO_PT",          "%lf", 0, &ZERO_POINT);
+
+  ScanConfig (config, "INST_MAG_MIN",     "%lf", 0, &IMAG_MIN);
+  ScanConfig (config, "INST_MAG_MAX",     "%lf", 0, &IMAG_MAX);
+  ScanConfig (config, "INST_BRIGHT",      "%lf", 0, &INST_BRIGHT);
+  
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  free (config);
+  free (file);
+
+  return;
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/ConvertMatch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/ConvertMatch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/ConvertMatch.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "mosastro.h"
+
+# define SWAP_BYTE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+1]; byte[X+1] = tmp;
+# define SWAP_WORD(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+3]; byte[X+3] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+2]; byte[X+2] = tmp;
+# define SWAP_DBLE(X) \
+  tmp = byte[X+0]; byte[X+0] = byte[X+7]; byte[X+7] = tmp; \
+  tmp = byte[X+1]; byte[X+1] = byte[X+6]; byte[X+6] = tmp; \
+  tmp = byte[X+2]; byte[X+2] = byte[X+5]; byte[X+5] = tmp; \
+  tmp = byte[X+3]; byte[X+3] = byte[X+4]; byte[X+4] = tmp;
+
+# ifdef linux
+# define BYTE_SWAP
+# endif
+
+# ifdef sid
+# define BYTE_SWAP
+# endif
+
+# ifdef dec
+# define BYTE_SWAP
+# endif
+
+# define MATCH_SIZE 104
+
+int ConvertMatch (MatchData *data, int size, int nitems) {
+
+  int i;
+  unsigned char *byte, tmp;
+
+# ifdef BYTE_SWAP
+
+  if (size != MATCH_SIZE) {
+    fprintf (stderr, "mismatch in type sizes (MatchData) %d vs %d\n", size, MATCH_SIZE);
+    return (FALSE);
+  }
+
+  byte = (unsigned char *) data;
+  for (i = 0; i < nitems; i++, byte += size) {
+    SWAP_DBLE (0);   /* R */
+    SWAP_DBLE (8);   /* D */
+    SWAP_WORD (16);  /* P */
+    SWAP_WORD (20);  /* Q */
+    SWAP_WORD (24);  /* L */
+    SWAP_WORD (28);  /* M */
+    SWAP_WORD (32);  /* X */
+    SWAP_WORD (36);  /* Y */
+
+    SWAP_DBLE (40);  /* R */
+    SWAP_DBLE (40);  /* D */
+    SWAP_WORD (56);  /* P */
+    SWAP_WORD (60);  /* Q */
+    SWAP_WORD (64);  /* L */
+    SWAP_WORD (68);  /* M */
+    SWAP_WORD (72);  /* X */
+    SWAP_WORD (76);  /* Y */
+
+    SWAP_WORD (80);  /* Mcat */
+    SWAP_WORD (84);  /* dMcat */
+    SWAP_WORD (88);  /* Minst */
+    SWAP_WORD (92);  /* dMinst */
+  }
+  return (TRUE);
+
+# else
+  return (TRUE);
+# endif  
+} 
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/FitChips.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/FitChips.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/FitChips.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "mosastro.h"
+
+void FitChips (int Norder) {
+
+  int i;
+
+  for (i = 0; i < Nchip; i++) {
+    chip[i].map.Npolyterms = Norder;
+    FitChip (chip[i].raw, chip[i].ref, chip[i].Nmatch, &chip[i].map);
+  }
+  deproject_raw ();
+  project_ref ();
+}
+
+void FitChip (StarData *raw, StarData *ref, int Nmatch, Coords *coords) {
+
+  int i;
+
+  fit_init (coords[0].Npolyterms);
+  for (i = 0; i < Nmatch; i++) {
+    if (raw[i].mask) continue;
+    fit_add (raw[i].X, raw[i].Y, ref[i].L, ref[i].M);
+  }
+  fit_eval ();
+  fit_apply_coords (coords);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/FitGradients.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/FitGradients.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/FitGradients.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "mosastro.h"
+
+/* fit dPdL, etc vs L,M */
+void FitGradients (Gradients *grad) {
+
+  int i, Norder;
+  Gradients grfix;
+
+  ALLOCATE (grfix.dPdL, double, grad[0].Npts);
+  ALLOCATE (grfix.dPdM, double, grad[0].Npts);
+  ALLOCATE (grfix.dQdL, double, grad[0].Npts);
+  ALLOCATE (grfix.dQdM, double, grad[0].Npts);
+
+  ALLOCATE (grfix.Lo,   double, grad[0].Npts);
+  ALLOCATE (grfix.Mo,   double, grad[0].Npts);
+  grfix.Npts = grad[0].Npts;
+
+  /* where do we set field.distort.Npolyterms? */
+  Norder = 3;
+
+  fit_init (Norder - 1);
+  for (i = 0; i < grad[0].Npts; i++) {
+    fit_add (grad[0].Lo[i], grad[0].Mo[i], grad[0].dPdL[i], grad[0].dPdM[i]);
+  }
+  fit_eval ();
+  fit_apply_grads (&field.distort, &field.project, 0);
+  fit_correct_grads (grad, &grfix, 0);
+  fit_free ();
+
+  fit_init (Norder - 1);
+  for (i = 0; i < grad[0].Npts; i++) {
+    fit_add (grad[0].Lo[i], grad[0].Mo[i], grad[0].dQdL[i], grad[0].dQdM[i]);
+  }
+  fit_eval ();
+  fit_apply_grads (&field.distort, &field.project, 1);
+  fit_correct_grads (grad, &grfix, 1);
+  fit_free ();
+
+  /* use new model of field to get TP & FP coords */
+  deproject_raw ();
+  project_ref ();
+
+  if ((DUMP != NULL) && !strcmp (DUMP, "grads")) {
+    dump_grads (&grfix, "gradfix.dat");
+    exit (0);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/GetGradients.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/GetGradients.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/GetGradients.c	(revision 16632)
@@ -0,0 +1,108 @@
+# include "mosastro.h"
+
+/* measure local gradient vs field position : dP, dQ = f(L,M) 
+   gradient is measured in small boxes across the field */
+Gradients *GetGradients () {
+
+  int i, j, nx, ny, Nval, Nx, Ny, Npts, DX, DY;
+  double **a, **b;
+  double L, M, dP, dQ;
+  double Xmin, Xmax, Ymin, Ymax;
+
+  Gradients *grad;
+
+  ALLOCATE (grad, Gradients, 1);
+
+  /** this should not be hard-wired **/
+  Nx = 2;
+  Ny = 2;
+
+  ALLOCATE (grad[0].dPdL, double, Nchip*Nx*Ny);
+  ALLOCATE (grad[0].dPdM, double, Nchip*Nx*Ny);
+  ALLOCATE (grad[0].dQdL, double, Nchip*Nx*Ny);
+  ALLOCATE (grad[0].dQdM, double, Nchip*Nx*Ny);
+
+  ALLOCATE (grad[0].Lo, double, Nchip*Nx*Ny);
+  ALLOCATE (grad[0].Mo, double, Nchip*Nx*Ny);
+  
+  ALLOCATE (a, double *, 3);
+  ALLOCATE (b, double *, 3);
+  for (i = 0; i < 3; i++) {
+    ALLOCATE (a[i], double, 3);
+    ALLOCATE (b[i], double, 2);
+  }
+
+  Nval = 0;
+  for (i = 0; i < Nchip; i++) {
+    DX = chip[i].NX / Nx;
+    DY = chip[i].NY / Ny;
+    for (nx = 0; nx < Nx; nx++) {
+      for (ny = 0; ny < Ny; ny++) {
+	Xmin = nx*DX;
+	Xmax = Xmin + DX;
+	Ymin = ny*DY;
+	Ymax = Ymin + DY;
+
+	for (j = 0; j < 3; j++) {
+	  bzero (a[j], 3*sizeof(double));
+	  bzero (b[j], 2*sizeof(double));
+	}
+  
+	/* find local gradient in limited box */
+	for (j = 0; j < chip[i].Nmatch; j++) {
+	  if (chip[i].raw[j].X < Xmin) continue;
+	  if (chip[i].raw[j].X > Xmax) continue;
+	  if (chip[i].raw[j].Y < Ymin) continue;
+	  if (chip[i].raw[j].Y > Ymax) continue;
+	  
+	  L   = chip[i].ref[j].L;
+	  M   = chip[i].ref[j].M;
+	  dP  = chip[i].ref[j].P - chip[i].raw[j].P;
+	  dQ  = chip[i].ref[j].Q - chip[i].raw[j].Q;
+	  
+	  a[0][0] += 1;
+	  a[1][0] += L;
+	  a[2][0] += M;
+	  a[1][1] += L*L;
+	  a[2][1] += L*M;
+	  a[2][2] += M*M;
+
+	  b[0][0] += dP;
+	  b[1][0] += dP*L;
+	  b[2][0] += dP*M;
+
+	  b[0][1] += dQ;
+	  b[1][1] += dQ*L;
+	  b[2][1] += dQ*M;
+
+	}
+	/* fitting dP = a[0][0] + a[1][0]*L + a[2][0]*M
+	           dQ = a[0][1] + a[1][1]*L + a[2][1]*M 
+	*/
+	a[0][1] = a[1][0];
+	a[0][2] = a[2][0];
+	a[1][2] = a[2][1];
+
+	Npts = a[0][0];
+	grad[0].Lo[Nval] = a[1][0] / a[0][0];
+	grad[0].Mo[Nval] = a[2][0] / a[0][0];
+	/* point-weighted average coordinate */
+
+	if (Npts < 5) continue;
+	if (!dgaussjordan (a, b, 3, 2)) continue;
+
+	/* we only care about the slopes, not the offsets */
+	grad[0].dPdL[Nval] = b[1][0];
+	grad[0].dPdM[Nval] = b[2][0];
+	grad[0].dQdL[Nval] = b[1][1];
+	grad[0].dQdM[Nval] = b[2][1];
+
+	Nval ++;
+
+      }
+    }
+  }
+  grad[0].Npts = Nval;
+  if ((DUMP != NULL) && !strcmp (DUMP, "grads")) dump_grads (grad, "grads.dat");
+  return (grad);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/GetScatter.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/GetScatter.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/GetScatter.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "mosastro.h"
+
+/* measure scatter on the focal plane */
+double GetScatter (int *Nscatter, double *DL, double *DM, int bright) {
+
+  int i, j, Ntotal;
+  double dL, dM, dL2, dM2, dl, dm, dR;
+  StarData *raw, *ref;
+
+  Ntotal = 0.0;
+  dL = dL2 = dM = dM2 = 0;
+  for (i = 0; i < Nchip; i++) {
+    raw = chip[i].raw;
+    ref = chip[i].ref;
+    for (j = 0; j < chip[i].Nmatch; j++) {
+      if (raw[j].mask) continue;
+      if (bright && (raw[j].Mag > INST_BRIGHT)) continue;
+      dl = raw[j].L - ref[j].L;
+      dm = raw[j].M - ref[j].M;
+      dL  += dl;
+      dL2 += SQ(dl);
+      dM  += dm;
+      dM2 += SQ(dm);
+      Ntotal ++;
+    }
+  }
+  dL = sqrt (fabs(dL2 / Ntotal - (dL*dL) / (Ntotal*Ntotal)));
+  dM = sqrt (fabs(dM2 / Ntotal - (dM*dM) / (Ntotal*Ntotal)));
+  dR = hypot(dL, dM) * 3600.0 * field.project.cdelt1;
+  *Nscatter = Ntotal;
+  *DL = dL;
+  *DM = dM;
+  return (dR);
+}
+
+/* sigma is returned in arcsec, dL, dM are in pixels */
+/* return dL and dM independently as well */
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/LoadStars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/LoadStars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/LoadStars.c	(revision 16632)
@@ -0,0 +1,77 @@
+# include "mosastro.h"
+
+int LoadStars (int Nfile, char **file) {
+
+  int i, itmp, status, extend;
+  time_t tsval;
+  struct tm *tmval;
+
+  ALLOCATE (chip, Chip, Nfile);
+
+  /* Nchip is number of valid chips */
+
+  Nchip = 0;
+  for (i = 0; i < Nfile; i++) {
+    chip[Nchip].file = strcreate (file[i]);
+
+    /* load header */
+    if (!gfits_read_header (chip[Nchip].file, &chip[Nchip].header)) {
+      fprintf (stderr, "ERROR: can't read header for %s\n", file[i]);
+      free (chip[Nchip].file);
+      continue;
+    }
+
+    /* get image dimensions */
+    gfits_scan (&chip[Nchip].header, "NAXIS1",   "%d", 1, &chip[Nchip].NX);
+    gfits_scan (&chip[Nchip].header, "NAXIS2",   "%d", 1, &chip[Nchip].NY);
+
+    /* get astrometry information */
+    if (!GetCoords (&chip[Nchip].coords, &chip[Nchip].header)) {
+      fprintf (stderr, "ERROR: no astrometric solution in header\n");
+      free (chip[Nchip].file);
+      gfits_free_header (&chip[Nchip].header);
+      continue;
+    }
+    while (chip[Nchip].coords.crval1 < 0) chip[Nchip].coords.crval1 += 360.0;
+    while (chip[Nchip].coords.crval1 > 360.0) chip[Nchip].coords.crval1 -= 360.0;
+
+    itmp = 0;
+    gfits_scan (&chip[Nchip].header, "NASTRO",   "%d", 1, &itmp);
+    if (itmp == 0) {
+      fprintf (stderr, "ERROR: bad astrometric solution in header %s\n", file[i]);
+      free (chip[Nchip].file);
+      gfits_free_header (&chip[Nchip].header);
+      continue;
+    }
+
+    /* get time info */
+    tsval = parse_time (&chip[Nchip].header);
+    tmval = gmtime (&tsval);
+    Year = tmval[0].tm_year;
+
+    extend = FALSE;
+    gfits_scan (&chip[Nchip].header, "EXTEND",  "%t", 1, &extend);
+    if (extend) {
+      status = rfits (&chip[Nchip]);
+    } else {
+      status = rtext (&chip[Nchip]);
+    }
+    if (!status) {
+      /* skip on failure */
+      free (chip[Nchip].file);
+      gfits_free_header (&chip[Nchip].header);
+      continue;
+    }
+
+    if (VERBOSE) fprintf (stderr, "loaded %d stars from %s\n", chip[Nchip].Nstars, chip[Nchip].file);
+
+    Nchip ++;
+  }
+ 
+  if (Nchip == 0) {
+    fprintf (stderr, "no valid data in chip files, exiting\n");
+    exit (1);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/SaveResiduals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/SaveResiduals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/SaveResiduals.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "mosastro.h"
+
+void SaveResiduals (FILE *f, Header *header) {
+
+  int i, j, N, Nmatch;
+  MatchData *match;
+  Matrix matrix;
+  Header theader;
+  FTable table;
+
+  header[0].extend = TRUE;
+  header[0].Naxes = 0;
+  gfits_modify (header, "NAXIS",   "%d", 1, 0);
+  gfits_modify (header, "EXTEND",  "%t", 1, TRUE);
+  gfits_modify (header, "NEXTEND", "%d", 1, 1);
+
+  /* add in some keywords to specify the datatype & software version? */
+
+  /* create (empty) data matrix */
+  gfits_create_matrix (header, &matrix);
+    
+  /* create bintable header */
+  gfits_create_table_header (&theader, "BINTABLE", "MOSASTRO_RESIDUALS");
+
+  /* define bintable layout */
+  gfits_define_bintable_column (&theader, "D",    "R_RAW",      "ra (raw)",             "degrees",                        1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "D",    "D_RAW",      "dec (raw)",            "degrees",                        1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "P_RAW",      "P coord (raw)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "Q_RAW",      "Q coord (raw)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "L_RAW",      "L coord (raw)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "M_RAW",      "M coord (raw)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "X_RAW",      "X coord (raw)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "Y_RAW",      "Y coord (raw)",        "pixels",                         1.0, 0.0); 
+
+  gfits_define_bintable_column (&theader, "D",    "R_REF",      "ra (ref)",             "degrees",                        1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "D",    "D_REF",      "dec (ref)",            "degrees",                        1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "P_REF",      "P coord (ref)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "Q_REF",      "Q coord (ref)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "L_REF",      "L coord (ref)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "M_REF",      "M coord (ref)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "X_REF",      "X coord (ref)",        "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "Y_REF",      "Y coord (ref)",        "pixels",                         1.0, 0.0); 
+
+  gfits_define_bintable_column (&theader, "E",    "MAG_REF",    "catalog mag",          "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "DMAG_REF",   "catalog mag err",      "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "MAG_RAW",    "instrum mag",          "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "E",    "DMAG_RAW",   "instrum mag err",      "pixels",                         1.0, 0.0); 
+  gfits_define_bintable_column (&theader, "B",    "MASK",       "excluded from fit?",   "",                               1.0, 0.0);
+  gfits_define_bintable_column (&theader, "7A",   "DUMMY",      "padding",              "",                               1.0, 0.0);
+
+  /* create table, add data values */
+  gfits_create_table (&theader, &table);
+
+  /* create output data block and assign */
+  Nmatch = 0;
+  for (i = 0; i < Nchip; i++) Nmatch += chip[i].Nmatch; 
+  ALLOCATE (match, MatchData, Nmatch);
+
+  for (i = N = 0; i < Nchip; i++) {
+    for (j = 0; j < chip[i].Nmatch; j++, N++) {
+      match[N].Rraw = chip[i].raw[j].R;
+      match[N].Draw = chip[i].raw[j].D;
+      match[N].Praw = chip[i].raw[j].P;
+      match[N].Qraw = chip[i].raw[j].Q;
+      match[N].Lraw = chip[i].raw[j].L;
+      match[N].Mraw = chip[i].raw[j].M;
+      match[N].Xraw = chip[i].raw[j].X;
+      match[N].Yraw = chip[i].raw[j].Y;
+
+      match[N].Rref = chip[i].ref[j].R;
+      match[N].Dref = chip[i].ref[j].D;
+      match[N].Pref = chip[i].ref[j].P;
+      match[N].Qref = chip[i].ref[j].Q;
+      match[N].Lref = chip[i].ref[j].L;
+      match[N].Mref = chip[i].ref[j].M;
+      match[N].Xref = chip[i].ref[j].X;
+      match[N].Yref = chip[i].ref[j].Y;
+
+      match[N].Mcat   = chip[i].ref[j].Mag;
+      match[N].dMcat  = chip[i].ref[j].dMag;
+      match[N].Minst  = chip[i].raw[j].Mag;
+      match[N].dMinst = chip[i].raw[j].dMag;
+      match[N].mask   = chip[i].raw[j].mask;
+    }
+  }
+
+  /* fix byte order issues */
+  ConvertMatch (match, sizeof (MatchData), Nmatch);
+  gfits_add_rows (&table, (char *) match, Nmatch, sizeof (MatchData));
+
+  gfits_fwrite_header  (f, header);
+  gfits_fwrite_matrix  (f, &matrix);
+  gfits_fwrite_Theader (f, &theader);
+  gfits_fwrite_table   (f, &table);
+  fclose (f);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/args.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "mosastro.h"
+
+void print_help () {
+
+  fprintf (stderr, "mosastro -- mosaic astrometry\n");
+  fprintf (stderr, "\n"); 
+  exit (0);
+
+}
+
+void args (int *argc, char **argv) {
+  
+  int N;
+
+  if (get_argument (*argc, argv, "-help") ||
+      get_argument (*argc, argv, "-h")) {
+    print_help ();
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (*argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, argc, argv);
+  }
+
+  DUMP = NULL;
+  if ((N = get_argument (*argc, argv, "-dump"))) {
+    remove_argument (N, argc, argv);
+    DUMP = strcreate(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  SAVE_RESID = FALSE;
+  if ((N = get_argument (*argc, argv, "-save-residuals"))) {
+    remove_argument (N, argc, argv);
+    SAVE_RESID = TRUE;
+  }
+
+  CHIPS = (char *) NULL;
+  if ((N = get_argument (*argc, argv, "-chips"))) {
+    remove_argument (N, argc, argv);
+    CHIPS = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  FIELD = (char *) NULL;
+  if ((N = get_argument (*argc, argv, "-field"))) {
+    remove_argument (N, argc, argv);
+    FIELD = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /** currently unused **/
+  field.Norder = 0;
+  if ((N = get_argument (*argc, argv, "-order"))) {
+    remove_argument (N, argc, argv);
+    field.Norder = atoi (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /** currently unused **/
+  ChipOrder = 1;
+  if ((N = get_argument (*argc, argv, "-chiporder"))) {
+    remove_argument (N, argc, argv);
+    ChipOrder = atoi (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/args_obs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/args_obs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/args_obs.c	(revision 16632)
@@ -0,0 +1,91 @@
+# include "mosastro.h"
+
+void print_help () {
+  fprintf (stderr, "USAGE: mkobs (RA) (DEC) (output) [-p param value]\n");
+  exit (1);
+}
+
+void args (int *argc, char **argv) {
+  
+  int N, No, Np, Nx, Ny;
+  double theta;
+  char line[500];
+
+  if (get_argument (*argc, argv, "--help")) print_help ();
+  if (get_argument (*argc, argv, "-h")) print_help ();
+
+  FOCAL_PLANE = NULL;
+  if ((N = get_argument (*argc, argv, "-fp"))) {
+    remove_argument (N, argc, argv);
+    FOCAL_PLANE = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  NO_CHIPS = FALSE;
+  if ((N = get_argument (*argc, argv, "-nochips"))) {
+    remove_argument (N, argc, argv);
+    NO_CHIPS = TRUE;
+  }
+
+  SIGMA = 0;
+  if ((N = get_argument (*argc, argv, "-sigma"))) {
+    remove_argument (N, argc, argv);
+    SIGMA = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  fake_field_defaults ();
+
+  while ((N = get_argument (*argc, argv, "-p"))) {
+    remove_argument (N, argc, argv);
+    
+    if (!strcmp (argv[N], "help")) {
+      fprintf (stderr, "valid parameters:\n");
+      fprintf (stderr, "cdelt (arcsec/pix)\n");
+      fprintf (stderr, "crpix (Xo) (Yo)\n");
+      fprintf (stderr, "theta (angle)\n");
+      exit (2);
+    }
+
+    if (!strcmp (argv[N], "cdelt")) {
+      remove_argument (N, argc, argv);
+      field.project.cdelt2 = field.project.cdelt1 = atof(argv[N])/3600.0;
+      remove_argument (N, argc, argv);
+      continue;
+    }
+    if (!strcmp (argv[N], "crpix")) {
+      remove_argument (N, argc, argv);
+      field.project.crpix1 = atof(argv[N]);
+      remove_argument (N, argc, argv);
+      field.project.crpix2 = atof(argv[N]);
+      remove_argument (N, argc, argv);
+      continue;
+    }
+    if (!strcmp (argv[N], "theta")) {
+      remove_argument (N, argc, argv);
+      theta = atof(argv[N]);
+      remove_argument (N, argc, argv);
+      field.project.pc1_1 = +cos (RAD_DEG*theta);
+      field.project.pc1_2 = -sin (RAD_DEG*theta);
+      field.project.pc2_1 = +sin (RAD_DEG*theta);
+      field.project.pc2_2 = +cos (RAD_DEG*theta);
+      continue;
+    }
+    if (!strncmp (argv[N], "pca", 3)) {
+      No = argv[N][3] - '0';
+      Nx = argv[N][5] - '0';
+      Ny = argv[N][7] - '0';
+      if ((Nx + Ny > 3) || (No > 1)) {
+	fprintf (stderr, "PCA out of range\n");
+	exit (1);
+      }
+      Np = mkpolyterm (Nx, Ny);
+      remove_argument (N, argc, argv);
+      field.distort.polyterms[Np][No] = atof(argv[N]);
+      remove_argument (N, argc, argv);
+      continue;
+    }
+  }
+
+  if (*argc != 4) print_help ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/chips.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/chips.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/chips.c	(revision 16632)
@@ -0,0 +1,82 @@
+# include "mosastro.h"
+
+/* set chip model based on initial header info */
+
+/** when the chips and field terms are treated independently, they must be of 
+    ctype PLY.  When we reach a solution, and write out a coupled set of chip 
+    and field terms, then we need to transition to WRP (chip) & DIS (field
+**/
+
+int init_chips () {
+
+  int i, j;
+  double R, D, P, Q, L, M, Scale, Det;
+
+  if (CHIPS != (char *) NULL) {
+    load_chips (CHIPS);
+    return (1);
+  }
+
+  for (i = 0; i < Nchip; i++) {
+
+    /* bore site center guess */
+    strcpy (chip[i].map.ctype, "DEC--PLY");
+    chip[i].map.crpix1 = 0.0;
+    chip[i].map.crpix2 = 0.0;
+    chip[i].map.cdelt1 = 1.0;
+    chip[i].map.cdelt2 = 1.0;
+
+    /* find (L,M) coords of reference pixel (0,0) */
+    XY_to_RD (&R, &D, 0.0, 0.0, &chip[i].coords);
+    RD_to_XY (&P, &Q, R, D, &field.project);
+    RD_to_XY (&L, &M, P, Q, &field.distort);
+    chip[i].map.crval1 = L;
+    chip[i].map.crval2 = M;
+
+    /** we preserve the rotation and parity of coords.pc_ij, but renormalize to unity scale **/
+    Det = chip[i].coords.pc1_1*chip[i].coords.pc2_2 - chip[i].coords.pc1_2*chip[i].coords.pc2_1;
+    Scale = 1.0 / sqrt(fabs(chip[i].coords.cdelt1*chip[i].coords.cdelt2*Det));
+
+    /** test for NaN Scale **/
+
+    // XXX : temporarily drop the re-scaling to compare with psastro
+    # if (PSASTRO_MODE)
+    chip[i].map.pc1_1  = chip[i].coords.pc1_1;
+    chip[i].map.pc2_2  = chip[i].coords.pc2_2;
+    chip[i].map.pc1_2  = chip[i].coords.pc1_2;
+    chip[i].map.pc2_1  = chip[i].coords.pc2_1;
+    # else
+    chip[i].map.pc1_1  = Scale * chip[i].coords.pc1_1 * chip[i].coords.cdelt1;
+    chip[i].map.pc2_2  = Scale * chip[i].coords.pc2_2 * chip[i].coords.cdelt2;
+    chip[i].map.pc1_2  = Scale * chip[i].coords.pc1_2 * chip[i].coords.cdelt2;
+    chip[i].map.pc2_1  = Scale * chip[i].coords.pc2_1 * chip[i].coords.cdelt1;
+    # endif
+
+    # if 0
+    // XXX this is the wrong choice: re-scaling each chip ruins distortion measurement
+    chip[i].map.pc1_1  = chip[i].coords.pc1_1 * chip[i].coords.cdelt1 / chip[0].coords.cdelt1;
+    chip[i].map.pc2_2  = chip[i].coords.pc2_2 * chip[i].coords.cdelt2 / chip[0].coords.cdelt2;
+    chip[i].map.pc1_2  = chip[i].coords.pc1_2 * chip[i].coords.cdelt1 / chip[0].coords.cdelt1;
+    chip[i].map.pc2_1  = chip[i].coords.pc2_1 * chip[i].coords.cdelt2 / chip[0].coords.cdelt2;
+    # endif
+
+    fprintf (stderr, "chip: %f %f (%f,%f),(%f,%f)\n", 
+	     chip[i].map.crval1, chip[i].map.crval2, 
+	     chip[i].map.pc1_1, chip[i].map.pc1_2, 
+	     chip[i].map.pc2_1, chip[i].map.pc2_2);
+
+    chip[i].map.Npolyterms = 1;
+    for (j = 0; j < 7; j++) {
+      chip[i].map.polyterms[j][0] = 0;
+      chip[i].map.polyterms[j][1] = 0;
+    }
+  }
+  return (1);
+}
+
+int load_chips (char *filename) {
+
+  fprintf (stderr, "not ready yet\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/clip.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/clip.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/clip.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "mosastro.h"
+
+int ClipOnFP (double Nsigma) {
+
+  int i, j, Nscatter, Nmask, Nkeep, Nkpcp;
+  double DL, DM, dL, dM;
+  double sigma;
+  StarData *raw, *ref;
+
+  Nmask = Nkeep = 0;
+  sigma = GetScatter (&Nscatter, &DL, &DM, FALSE);
+
+  for (i = 0; i < Nchip; i++) {
+    raw = chip[i].raw;
+    ref = chip[i].ref;
+    Nkpcp = 0;
+    for (j = 0; j < chip[i].Nmatch; j++) {
+      dL = raw[j].L - ref[j].L;
+      dM = raw[j].M - ref[j].M;
+      if ((fabs(dL) > Nsigma*DL) || (fabs(dM) > Nsigma*DM)) {
+	raw[j].mask = TRUE;
+	Nmask ++;
+      } else {
+	raw[j].mask = FALSE;	
+	Nkeep ++;
+	Nkpcp ++;
+      }
+    }
+    fprintf (stderr, "Nchip: %d\n", Nkpcp);
+  }
+
+  fprintf (stderr, "Nmask: %d, Nkeep: %d\n", Nmask, Nkeep);
+  return (TRUE);
+}
+
+/*
+  sigma = sigma / (3600.0 * field.project.cdelt1);
+*/
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/dump.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/dump.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/dump.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "mosastro.h"
+
+int dump_stars (FILE *f, StarData *stars, int Nstars) {
+
+  int i;
+
+  for (i = 0; i < Nstars; i++) {
+    fprintf (f, "%4d  %12.8f %12.8f  %8.2f %8.2f  %8.2f %8.2f  %7.2f %7.2f  %7.2f %7.2f  %d\n", 
+	     i, 
+	     stars[i].R, stars[i].D,
+	     stars[i].P, stars[i].Q,
+	     stars[i].L, stars[i].M,
+	     stars[i].X, stars[i].Y,
+	     stars[i].Mag, stars[i].dMag, stars[i].mask);
+  }
+  return (1);
+}
+
+int dump_grads (Gradients *grad, char *filename) {
+
+  int i;
+  FILE *f;
+
+  fprintf (stderr, "printing to file %s\n", filename);
+
+  f = fopen (filename, "w");
+
+  for (i = 0; i < grad[0].Npts; i++) {
+    fprintf (f, "%4d  %10.6f %10.6f  %10.6f %10.6f   %10.6f %10.6f\n", 
+	     i, 
+	     grad[0].dPdL[i], grad[0].dPdM[i], 
+	     grad[0].dQdL[i], grad[0].dQdM[i], 
+	     grad[0].Lo[i], grad[0].Mo[i]);
+  }
+  fclose (f);
+  return (1);
+}
+
+int dump_match () {
+
+  int i;
+  FILE *f, *g;
+  f = fopen ("raw.dat", "w");
+  g = fopen ("ref.dat", "w");
+  for (i = 0; i < Nchip; i++) {
+    dump_stars (f, chip[i].raw, chip[i].Nmatch);
+    dump_stars (g, chip[i].ref, chip[i].Nmatch);
+  }
+  fclose (f);
+  fclose (g);
+  exit (1);
+}
+
+int dump_rawstars () {
+
+  int i;
+  FILE *f;
+  f = fopen ("stars.dat", "w");
+  for (i = 0; i < Nchip; i++) {
+    dump_stars (f, chip[i].stars, chip[i].Nstars);
+  }
+  fclose (f);
+  exit (1);
+}
+
+int dump_refcat (StarData *refcat, int Nrefcat) {
+
+  FILE *f;
+  f = fopen ("refcat.dat", "w");
+  dump_stars (f, refcat, Nrefcat);
+  fclose (f);
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/fakefield.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/fakefield.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/fakefield.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "mosastro.h"
+
+/* determine an initial guess to field parameters from data */ 
+int fake_field_center (double RA, double DEC) {
+
+  field.Rmin = RA  - 0.5;
+  field.Rmax = RA  + 0.5;
+  field.Dmin = DEC - 0.5;
+  field.Dmax = DEC + 0.5;
+
+  /* bore site center guess */
+  field.project.crval1 = 0.5*(field.Rmin + field.Rmax);
+  field.project.crval2 = 0.5*(field.Dmin + field.Dmax);
+  
+  return (1);
+}
+
+/* set default field parameters (overridden in args_obs) */ 
+int fake_field_defaults () {
+
+  int i;
+
+  /* bore site center guess */
+  strcpy (field.project.ctype, "DEC--TAN");
+  field.project.crpix1 = 0;
+  field.project.crpix2 = 0;
+  
+  /* set TP plate scale */
+  field.project.cdelt1 = 1.0/3600.0;
+  field.project.cdelt2 = 1.0/3600.0;
+
+  /** allow guess at field rotation?? **/
+  field.project.pc1_1  = 1;
+  field.project.pc2_2  = 1;
+  field.project.pc1_2  = 0;
+  field.project.pc2_1  = 0;
+  field.project.Npolyterms = 1;
+
+  /** distort only has power in polyterms **/
+  strcpy (field.distort.ctype, "DEC--PLY");
+  field.distort.crval1 = 0.0;
+  field.distort.crval2 = 0.0;
+  field.distort.crpix1 = 0.0;
+  field.distort.crpix2 = 0.0;
+  field.distort.cdelt1 = 1.0;
+  field.distort.cdelt2 = 1.0;
+  
+  field.distort.pc1_1  = 1;
+  field.distort.pc2_2  = 1;
+  field.distort.pc1_2  = 0;
+  field.distort.pc2_1  = 0;
+
+  /* how do we handle renormalization? (fixed at 1000 pixels??) */
+  field.distort.Npolyterms = 3;
+  for (i = 0; i < 7; i++) {
+    field.distort.polyterms[i][0] = 0;
+    field.distort.polyterms[i][1] = 0;
+  }
+
+  return (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/field.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/field.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/field.c	(revision 16632)
@@ -0,0 +1,199 @@
+# include "mosastro.h"
+
+/* determine an initial guess to field parameters from data */ 
+int init_field () {
+
+  int i;
+
+  if (FIELD != (char *) NULL) {
+    load_field (FIELD);
+    return (TRUE);
+  }
+
+  /* bore site center guess */
+  strcpy (field.project.ctype, "DEC--TAN");
+
+  # if (PSASTRO_MODE)
+  // XXX : temporarily use a fixed ref point to compare with psastro
+  field.project.crval1 = chip[0].coords.crval1;
+  field.project.crval2 = chip[0].coords.crval2;
+  # else
+  field.project.crval1 = 0.5*(field.Rmin + field.Rmax);
+  field.project.crval2 = 0.5*(field.Dmin + field.Dmax);
+  # endif
+
+  field.project.crpix1 = 0;
+  field.project.crpix2 = 0;
+  
+  /* measure average plate scale - would be better using parabolic min... */
+  field.project.cdelt1 = 0;
+  field.project.cdelt2 = 0;
+  for (i = 0; i < Nchip; i++) {
+    field.project.cdelt1 += chip[i].coords.cdelt1;
+    field.project.cdelt2 += chip[i].coords.cdelt2;
+  }
+  field.project.cdelt1 /= Nchip;
+  field.project.cdelt2 /= Nchip;
+
+  # if (PSASTRO_MODE)
+  // XXX : temporarily use first chip as ref scale to compare with psastro
+  field.project.cdelt1 = chip[0].coords.cdelt1;
+  field.project.cdelt2 = chip[0].coords.cdelt2;
+  # endif
+  /* force starting guess to have equal x & y plate scales? */
+
+  fprintf (stderr, "field: %f,%f  %f,%f\n", 
+	   field.project.crval1, field.project.crval2, 
+	   3600*field.project.cdelt1, 3600*field.project.cdelt2);
+
+  /** allow guess at field rotation?? **/
+  field.project.pc1_1  = 1;
+  field.project.pc2_2  = 1;
+  field.project.pc1_2  = 0;
+  field.project.pc2_1  = 0;
+  field.project.Npolyterms = 1;
+
+  /* bore site center guess */
+  strcpy (field.distort.ctype, "DEC--PLY");
+  field.distort.crval1 = 0.0;
+  field.distort.crval2 = 0.0;
+  field.distort.crpix1 = 0.0;
+  field.distort.crpix2 = 0.0;
+  field.distort.cdelt1 = 1.0;
+  field.distort.cdelt2 = 1.0;
+  
+  /** allow guess at field rotation?? **/
+  field.distort.pc1_1  = 1;
+  field.distort.pc2_2  = 1;
+  field.distort.pc1_2  = 0;
+  field.distort.pc2_1  = 0;
+
+  /* allow 2nd and 3rd order? */
+  /* how do we handle renormalization? (fixed at 1000 pixels??) */
+  field.distort.Npolyterms = 1;
+  for (i = 0; i < 7; i++) {
+    field.distort.polyterms[i][0] = 0;
+    field.distort.polyterms[i][1] = 0;
+  }
+  return (TRUE);
+}
+
+void field_stats () {
+  
+  int i, j;
+  double Rmin, Rmax, Dmin, Dmax;
+
+  /* find range for single image */
+  Rmin = Dmin = 360.0;
+  Rmax = Dmax = -90.0;
+
+  for (i = 0; i < Nchip; i++) {
+    for (j = 0; j < chip[i].Nstars; j++) {
+      Rmin = MIN (Rmin, chip[i].stars[j].R);
+      Dmin = MIN (Dmin, chip[i].stars[j].D);
+      Rmax = MAX (Rmax, chip[i].stars[j].R);
+      Dmax = MAX (Dmax, chip[i].stars[j].D);
+    }
+  }
+  field.Rmin = Rmin;
+  field.Rmax = Rmax;
+  field.Dmin = Dmin;
+  field.Dmax = Dmax;
+
+}
+
+void field_combine () {
+
+  int i;
+  double cd1, cd2, pc11, pc12, pc21, pc22;
+
+  /* combine boresite & distortion parameters: ctype DIS */
+  strcpy (field.project.ctype, "DEC--DIS");
+
+  cd1  = field.project.cdelt1;
+  cd2  = field.project.cdelt2;
+  pc11 = field.project.pc1_1;
+  pc12 = field.project.pc1_2;
+  pc21 = field.project.pc2_1;
+  pc22 = field.project.pc2_2;
+
+  field.project.Npolyterms = field.distort.Npolyterms;
+
+  for (i = 0; i < 7; i++) {
+    field.project.polyterms[i][0] = (pc11*cd1*field.distort.polyterms[i][0] + pc12*cd2*field.distort.polyterms[i][1]);
+    field.project.polyterms[i][1] = (pc21*cd1*field.distort.polyterms[i][0] + pc22*cd2*field.distort.polyterms[i][1]);
+  }
+  for (i = 0; i < 2; i++) {
+    field.project.polyterms[0][i] =  field.project.polyterms[0][i] / (cd1*cd1);
+    field.project.polyterms[1][i] =  field.project.polyterms[1][i] / (cd1*cd2);
+    field.project.polyterms[2][i] =  field.project.polyterms[2][i] / (cd2*cd2);
+
+    field.project.polyterms[3][i] =  field.project.polyterms[3][i] / (cd1*cd1*cd1);
+    field.project.polyterms[4][i] =  field.project.polyterms[4][i] / (cd1*cd1*cd2);
+    field.project.polyterms[5][i] =  field.project.polyterms[5][i] / (cd1*cd2*cd2);
+    field.project.polyterms[6][i] =  field.project.polyterms[6][i] / (cd2*cd2*cd2);
+  }
+}
+
+int load_field (char *filename) {
+
+  int i;
+  Coords coords;
+  Header header;
+
+  /* load header */
+  if (!gfits_read_header (filename, &header)) {
+    fprintf (stderr, "ERROR: can't read header for %s\n", filename);
+    exit (1);
+  }
+  /* get astrometry information */
+  if (!GetCoords (&coords, &header)) {
+    fprintf (stderr, "ERROR: no astrometric solution in field %s\n", filename);
+    exit (1);
+  }
+ 
+  /* separate field into boresite + distortion terms */
+
+  /* bore site center guess */
+  strcpy (field.project.ctype, "DEC--TAN");
+  field.project.crval1 = 0.5*(field.Rmin + field.Rmax);
+  field.project.crval2 = 0.5*(field.Dmin + field.Dmax);
+  field.project.crpix1 = 0;
+  field.project.crpix2 = 0;
+  
+  /* measure average plate scale - would be better using parabolic min... */
+  field.project.cdelt1 = coords.cdelt1;
+  field.project.cdelt2 = coords.cdelt2;
+
+  /** allow guess at field rotation?? **/
+  field.project.pc1_1  = coords.pc1_1;
+  field.project.pc2_2  = coords.pc2_2;
+  field.project.pc1_2  = coords.pc1_2;
+  field.project.pc2_1  = coords.pc2_1;
+  field.project.Npolyterms = 1;
+
+  /* bore site center guess */
+  strcpy (field.distort.ctype, "DEC--PLY");
+  field.distort.crval1 = 0.0;
+  field.distort.crval2 = 0.0;
+  field.distort.crpix1 = 0.0;
+  field.distort.crpix2 = 0.0;
+  field.distort.cdelt1 = 1.0;
+  field.distort.cdelt2 = 1.0;
+  
+  /** allow guess at field rotation?? **/
+  field.distort.pc1_1  = 1;
+  field.distort.pc2_2  = 1;
+  field.distort.pc1_2  = 0;
+  field.distort.pc2_1  = 0;
+
+  /* allow 2nd and 3rd order? */
+  /* how do we handle renormalization? (fixed at 1000 pixels??) */
+  field.distort.Npolyterms = coords.Npolyterms;
+  for (i = 0; i < 7; i++) {
+    field.distort.polyterms[i][0] = coords.polyterms[i][0];
+    field.distort.polyterms[i][1] = coords.polyterms[i][1];
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/fitpoly.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/fitpoly.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/fitpoly.c	(revision 16632)
@@ -0,0 +1,284 @@
+# include "mosastro.h"
+
+static int NTERM, NPOWER, NPARS, NORDER, Npts;
+static double **sum, **xsum, **ysum;
+static double **matrix, **vector;
+
+void fit_init (int order) {
+
+  int i;
+
+  Npts  = 0;
+  NORDER = order;
+  NPOWER = NORDER + 1;
+  NTERM = 2*NORDER + 1;
+  NPARS = (NORDER + 1)*(NORDER + 2) / 2;
+
+  /* allocate arrays for fit solution */
+  ALLOCATE (sum, double *, NTERM);
+  ALLOCATE (xsum, double *, NTERM);
+  ALLOCATE (ysum, double *, NTERM);
+  for (i = 0; i < NTERM; i++) {
+    ALLOCATE (sum[i], double, NTERM);
+    bzero (sum[i], NTERM*sizeof(double));
+    ALLOCATE (xsum[i], double, NTERM);
+    bzero (xsum[i], NTERM*sizeof(double));
+    ALLOCATE (ysum[i], double, NTERM);
+    bzero (ysum[i], NTERM*sizeof(double));
+  }
+  ALLOCATE (matrix, double *, NPARS);
+  ALLOCATE (vector, double *, NPARS);
+  for (i = 0; i < NPARS; i++) {
+    ALLOCATE (matrix[i], double, NPARS);
+    ALLOCATE (vector[i], double, 2);
+    bzero (vector[i], 2*sizeof(double));
+    bzero (matrix[i], NPARS*sizeof(double));
+  }
+
+}
+
+# define SCALE 1.0
+void fit_add (double x1, double y1, double x2, double y2) {
+
+  int n, m;
+  double xterm, yterm, term;
+
+  xterm = 1;
+  for (n = 0; n < NTERM; n++) {
+    yterm = 1;
+    for (m = 0; m < NTERM; m++) {
+      term = xterm*yterm;
+      if (n+m < NTERM) {
+	sum[n][m] += term;
+      }
+      if (n+m < NPOWER) {
+	xsum[n][m] += x2*term;
+	ysum[n][m] += y2*term;
+      }
+      yterm *= y1/SCALE;
+    }
+    xterm *= x1/SCALE;
+  }
+  Npts ++;
+}
+
+/** I am renormalizing here by the max pivots to keep gaussj sane **
+ ** would not be needed if the fit used scaled ind. variables **/
+void fit_eval () {
+
+  int i, j, n, m, M, N;
+
+  if (Npts == 0) {
+    fprintf (stderr, "warning: no valid pts\n");
+  }
+
+  i = 0;
+  for (m = 0; m < NPOWER; m++) {
+    for (n = 0; n < NPOWER - m; n++, i++) {
+      vector[i][0] = xsum[n][m];
+      vector[i][1] = ysum[n][m];
+    }	
+  }
+  j = 0;
+  for (M = 0; M < NPOWER; M++) {
+    for (N = 0; N < NPOWER - M; N++, j++) {
+      i = 0;
+      for (m = 0; m < NPOWER; m++) {
+	for (n = 0; n < NPOWER - m; n++, i++) {
+	  matrix[i][j] = sum[n+N][m+M];
+	}	
+      }
+    }
+  }       
+# if (0)
+  max = 0.0;
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      max = MAX (max, fabs(matrix[i][j]));
+    }
+    max = MAX (max, fabs(vector[i][0]));
+    max = MAX (max, fabs(vector[i][1]));
+  }
+  for (i = 0; i < NPARS; i++) {
+    for (j = 0; j < NPARS; j++) {
+      matrix[i][j] /= max;
+    }
+    vector[i][0] /= max;
+    vector[i][1] /= max;
+  }
+# endif
+
+  dgaussjordan (matrix, vector, NPARS, 2); 
+
+# if (0)
+  i = 0;
+  for (m = 0; m < NPOWER; m++) {
+    for (n = 0; n < NPOWER - m; n++, i++) {
+      fprintf (stderr, "RA x^%dy^%d: %10.4g    DEC x^%dy^%d: %10.4g \n", 
+	       n, m, vector[i][0], n, m, vector[i][1]);
+    }	
+  }
+# endif
+}
+
+/* linear portion of fit : NORDER is 1 */
+void fit_apply_coords (Coords *coords) {
+
+  int i, j, Np, Nv, N;
+  double c11, c12;
+  double c21, c22;
+  double R;
+
+  /* update the higher order terms */
+  if (NORDER > 1) {
+    for (i = 0; i < NPOWER; i++) {
+      for (j = 0; j < (NPOWER - i); j++) {
+	if (i + j < 2) continue;
+	Np = mkpolyterm (i, j);
+	Nv = mkvector (i, j, NORDER);
+	coords[0].polyterms[Np][0] = vector[Nv][0];
+	coords[0].polyterms[Np][1] = vector[Nv][1];
+      }
+    }
+  }
+
+  /* get the correct vector entries for the linear terms */
+  N = mkvector (0, 0, NORDER);
+  coords[0].crval1 = vector[N][0];  
+  coords[0].crval2 = vector[N][1];
+
+  N = mkvector (1, 0, NORDER);
+  c11 = vector[N][0];  
+  c21 = vector[N][1];
+  N = mkvector (0, 1, NORDER);
+  c12 = vector[N][0];  
+  c22 = vector[N][1];
+  coords[0].cdelt1 = coords[0].cdelt2 = sqrt(fabs(c11*c22 - c12*c21));
+  R = 1 / coords[0].cdelt1;
+
+  coords[0].pc1_1  = c11*R;
+  coords[0].pc2_1  = c21*R;
+  coords[0].pc1_2  = c12*R;
+  coords[0].pc2_2  = c22*R;
+
+  coords[0].crpix1 = 0;
+  coords[0].crpix2 = 0;
+
+  coords[0].Npolyterms = NORDER;
+  strcpy (coords[0].ctype, "DEC--PLY");
+}
+
+/*
+  if we have just linear terms, the following holds for crpix1,2:
+  D = R / (coords[0].pc1_1*coords[0].pc2_2 - coords[0].pc1_2*coords[0].pc2_1);
+  coords[0].crpix1 = D * (coords[0].pc1_2*c20 - coords[0].pc2_2*c10);
+  coords[0].crpix2 = D * (coords[0].pc2_1*c10 - coords[0].pc1_1*c20);
+*/
+
+/* NORDER is order of gradient fit : Npolyterms is Norder + 1 */
+void fit_apply_grads (Coords *distort, Coords *project, int term) {
+
+  int i, j, Np, Nv1, Nv2;
+
+  distort[0].Npolyterms = NORDER + 1;
+  if (distort[0].Npolyterms > 1) strcpy (distort[0].ctype, "DEC--PLY");
+
+  for (i = 0; i < NPOWER + 1; i++) {
+    for (j = 0; j < (NPOWER + 1 - i); j++) {
+      
+      if (i + j < 2) continue;
+      Np  = mkpolyterm (i, j);
+      Nv1 = mkvector (i-1, j, NORDER);
+      Nv2 = mkvector (i, j-1, NORDER);
+
+      /** why do we have the negative sign? **/
+      if (j == 0) {
+	distort[0].polyterms[Np][term] = vector[Nv1][0] / i;
+      }
+      if (i == 0) {
+	distort[0].polyterms[Np][term] = vector[Nv2][1] / j;
+      }
+      if ((i > 0) && (j > 0)) {
+	distort[0].polyterms[Np][term] = 0.5*(vector[Nv1][0] / i + vector[Nv2][1] / j);
+      }
+    }
+  }
+
+  Nv1 = mkvector (0, 0, NORDER);
+  if (term == 0) {
+    project[0].pc1_1 = project[0].pc1_1 * (1 + vector[Nv1][0]);
+    project[0].pc1_2 = project[0].pc1_2 * (1 + vector[Nv1][1]);
+  } else {
+    project[0].pc2_1 = project[0].pc2_1 * (1 + vector[Nv1][0]);
+    project[0].pc2_2 = project[0].pc2_2 * (1 + vector[Nv1][1]);
+  }
+}
+
+void fit_correct_grads (Gradients *in, Gradients *out, int term) {
+
+  int i, k, m, n;
+  double x, y, dx, dy, dz1, dz2;
+
+  for (i = 0; i < in[0].Npts; i++) {
+    
+    dx = in[0].Lo[i];
+    dy = in[0].Mo[i];
+    dz1 = dz2 = 0.0;
+
+    k = 0;
+    x = y = 1;
+    for (m = 0; m < NPOWER; m++) {
+      x = y;
+      for (n = 0; n < NPOWER - m; n++, k++) {
+	dz1 += vector[k][0]*x;
+	dz2 += vector[k][1]*x;
+	x = x * dx / SCALE;
+      }
+      y = y * dy / SCALE;
+    }
+
+    out[0].Lo[i] = dx;
+    out[0].Mo[i] = dy;
+    if (term == 0) {
+      out[0].dPdL[i] = in[0].dPdL[i] - dz1;
+      out[0].dPdM[i] = in[0].dPdM[i] - dz2;
+    } else {
+      out[0].dQdL[i] = in[0].dQdL[i] - dz1;
+      out[0].dQdM[i] = in[0].dQdM[i] - dz2;
+    }
+  }
+}
+
+int mkvector (int n, int m, int norder) {
+  
+  int i, N;
+  
+  N = 0;
+  for (i = 0; i < m; i++) {
+    N += (norder - i + 1);
+  }
+  N += n;
+  return (N);
+}
+
+void fit_free () {
+
+  int i;
+
+  for (i = 0; i < NTERM; i++) {
+    free (sum[i]);
+    free (xsum[i]);
+    free (ysum[i]);
+  }
+  free (sum);
+  free (xsum);
+  free (ysum);
+
+  for (i = 0; i < NPARS; i++) {
+    free (matrix[i]);
+    free (vector[i]);
+  }
+  free (matrix);
+  free (vector);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/getgsc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/getgsc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/getgsc.c	(revision 16632)
@@ -0,0 +1,87 @@
+# include "mosastro.h"
+# define BYTES_STAR 23
+# define BLOCK 1000
+
+StarData *rd_gsc (char *filename, int *Nstars);
+
+StarData *getgsc (CatStats *catstats, int *NSTARS) {
+  
+  int i, j, k, Ns, Ngsc, Nstars; 
+  StarData *gsc;
+  StarData *stars;
+  SkyList *skylist;
+  SkyTable *sky;
+  SkyRegion patch;
+
+  patch.Rmin = catstats[0].RA[0];
+  patch.Rmax = catstats[0].RA[1];
+  patch.Dmin = catstats[0].DEC[0];
+  patch.Dmax = catstats[0].DEC[1];
+
+  /* load regions from GSC table, restrict to patch */
+  sky = SkyTableFromGSC (GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, GSCDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, &patch);
+  
+  Nstars = 0;
+  ALLOCATE (stars, StarData, 1);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    gsc = rd_gsc (skylist[0].filename[i], &Ngsc);
+
+    Ns = Nstars;
+    Nstars += Ngsc;
+
+    REALLOCATE (stars, StarData, MAX (1, Nstars));
+    for (k = Ns, j = 0; j < Ngsc; k++, j++) {
+      stars[k].R = gsc[j].R;
+      stars[k].D = gsc[j].D;
+      stars[k].M = gsc[j].M;
+    }      
+    free (gsc);
+  }
+  SkyTableFree (sky);
+
+  if (VERBOSE) fprintf (stderr, "%d stars from HST GSC\n", Nstars);
+  *NSTARS = Nstars;
+  return (stars);
+}  
+
+StarData *rd_gsc (char *filename, int *Nstars) {
+  
+  StarData *stars;
+  int i, NSTAR, nstar, Nbytes, nbytes;
+  char *buffer;
+  FILE *f;
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't find catalog file %s\n", filename);
+    exit (1);
+  }
+  
+  nstar = 0;
+  NSTAR = 1000;
+  ALLOCATE (stars, StarData, NSTAR);
+
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+  Nbytes = BLOCK*BYTES_STAR;
+
+  while ((nbytes = fread (buffer, 1, Nbytes, f)) > 0) {
+    for (i = 0; i < nbytes / BYTES_STAR; i++) {
+      dparse (&stars[nstar].R, 1, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].D, 2, &buffer[i*BYTES_STAR]);
+      dparse (&stars[nstar].M, 3, &buffer[i*BYTES_STAR]);
+      nstar++;
+      if (nstar == NSTAR) {
+	NSTAR += 1000;
+	REALLOCATE (stars, StarData, NSTAR);
+      }
+    }
+  }
+
+  free (buffer);
+
+  *Nstars = nstar;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/getptolemy.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/getptolemy.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/getptolemy.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "mosastro.h"
+
+StarData *getptolemy (CatStats *catstats, int *NSTARS) {
+  
+  int i, j, k, Ns, Nstars; 
+  Catalog catalog;
+  StarData *stars;
+  SkyList *skylist;
+  SkyTable *sky;
+  SkyRegion patch;
+
+  patch.Rmin = catstats[0].RA[0];
+  patch.Rmax = catstats[0].RA[1];
+  patch.Dmin = catstats[0].DEC[0];
+  patch.Dmax = catstats[0].DEC[1];
+
+  Nstars = 0;
+  ALLOCATE (stars, StarData, 1);
+
+  /* load regions from GSC table, restrict to patch */
+  sky = SkyTableLoadOptimal (CATDIR, NULL, GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, &patch);
+  
+  for (i = 0; i <skylist[0].Nregions; i++) {
+    // set the parameters which guide catalog open/load/create
+    catalog.filename  = skylist[0].filename[i];
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS;
+    catalog.Nsecfilt  = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    // Naves_disk == 0 implies an empty catalog file
+    // for only_match, skip empty catalogs
+    if (!catalog.Naves_disk) {
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    Ns = Nstars;
+    Nstars += catalog.Naverage;
+
+    REALLOCATE (stars, StarData, MAX (1, Nstars));
+    for (k = Ns, j = 0; j < catalog.Naverage; k++, j++) {
+      stars[k].R = catalog.average[j].R;
+      stars[k].D = catalog.average[j].D;
+      stars[k].M = catalog.measure[catalog.average[j].offset].M;
+    }      
+    dvo_catalog_free (&catalog);
+  }
+
+  if (VERBOSE) fprintf (stderr, "%d stars from PTOLEMY\n", Nstars);
+  *NSTARS = Nstars;
+  return (stars);
+}  
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/getstone.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/getstone.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/getstone.c	(revision 16632)
@@ -0,0 +1,89 @@
+# include "mosastro.h"
+
+StarData *getstone (CatStats *input, int *nstars) {
+
+  FILE *f;
+  int i, Nregion, NREGION, Nstars, NSTARS;
+  double r, d, R, D, M, Tr, Td, dRdT, dDdT;
+  char **regname, filename[1024], line[1024];
+  StarData *stars;
+  CatStats *regions;
+
+  sprintf (filename, "%s/Regions.dat", StoneRegions);
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't open stone %s\n", filename);
+    exit (1);
+  }
+
+  Nregion = 0;
+  NREGION = 20;
+  ALLOCATE (regions, CatStats, NREGION);
+  ALLOCATE (regname, char *, NREGION);
+
+  /* strip off first commented line */
+  scan_line (f, line);
+  while (scan_line (f, line) != EOF) {
+    sscanf (line, "%s %lf %lf %lf %lf", filename, 
+	    &regions[Nregion].RA[0], &regions[Nregion].RA[1], 
+	    &regions[Nregion].DEC[0], &regions[Nregion].DEC[1]);
+    sprintf (line, "%s/%s", StoneRegions, filename);
+    regname[Nregion] = strcreate (line);
+    Nregion ++;
+    if (Nregion == NREGION) {
+      NREGION += 50;
+      REALLOCATE (regions, CatStats, NREGION);
+      REALLOCATE (regname, char *, NREGION);
+    }	  
+  }
+  fclose (f);
+
+  Nstars = 0;
+  NSTARS = 1000;
+  ALLOCATE (stars, StarData, NSTARS);
+
+  /* find the region(s) that overlap the input region */
+  for (i = 0; i < Nregion; i++) {
+    if (input[0].RA[0] > regions[i].RA[1]) continue;
+    if (input[0].RA[1] < regions[i].RA[0]) continue;
+    if (input[0].DEC[0] > regions[i].DEC[1]) continue;
+    if (input[0].DEC[1] < regions[i].DEC[0]) continue;
+    /* this will fail on 0,360 boundary */
+    fprintf (stderr, "loading data from %s\n", regname[i]);
+
+    f = fopen (regname[i], "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open stone %s\n", regname[i]);
+      exit (1);
+    }
+
+    while (scan_line (f, line) != EOF) {
+    
+      dparse (&R, 3, line);
+      dparse (&D, 4, line);
+      dparse (&M, 5, line);
+      
+      dparse (&Tr, 12, line);
+      dparse (&Td, 13, line);
+      dparse (&dRdT, 14, line);
+      dparse (&dDdT, 15, line);
+      
+      r = R + dRdT*(Year - Tr)/(100.0*3600.0);
+      d = D + dDdT*(Year - Td)/(100.0*3600.0);
+      
+      stars[Nstars].M = M;
+      stars[Nstars].R = r*15.0;
+      stars[Nstars].D = d;
+      Nstars ++;
+      if (Nstars == NSTARS) {
+	NSTARS += 5000;
+	REALLOCATE (stars, StarData, NSTARS);
+      }	  
+    }
+    fclose (f);
+  }
+
+  *nstars = Nstars;
+  return (stars);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/getusno.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/getusno.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/getusno.c	(revision 16632)
@@ -0,0 +1,130 @@
+# include "mosastro.h"
+# define NZONE 24
+
+int SPDzone[] = {
+  0, 75, 450, 375, 1500, 1650, 300, 1425, 1725, 525, 1275, 225, 
+  675, 150, 600, 1575, 750, 975, 900, 1050, 1125, 1200, 825, 1350};
+
+int USNOdisk[] = {
+  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10};
+
+StarData *getusno (CatStats *catstats, int *Nstars) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128];
+  FILE *f;
+  int iRA0, iRA1, iDEC0, iDEC1;
+  double RA0, RA1, DEC0, DEC1, dec;
+  int spd, spd_start, spd_end, disk;
+  int NUSNO, Nusno;
+  StarData *stars;
+
+  RA0  = catstats[0].RA[0]; 
+  RA1  = catstats[0].RA[1]; 
+  DEC0 = catstats[0].DEC[0];
+  DEC1 = catstats[0].DEC[1];
+
+  /* identify ra & dec range of interest */
+  iRA0 = RA0 * 360000.0;
+  iRA1 = RA1 * 360000.0;
+  iDEC0 = (DEC0 + 90.0) * 360000.0;
+  iDEC1 = (DEC1 + 90.0) * 360000.0;
+  
+  /* data is organized in south-pole distance zones */
+  spd_start = (int)((DEC0 + 90) / 7.5) * 75.0;
+  dec = (DEC1 + 90) / 7.5;
+  if (dec > (int)(dec)) {
+    spd_end =   (int)(1 + (DEC1 + 90) / 7.5) * 75.0;
+  } else {
+    spd_end =   (int)(0 + (DEC1 + 90) / 7.5) * 75.0;
+  }
+
+  Nusno = 0;
+  NUSNO = 5000;
+  ALLOCATE (stars, StarData, NUSNO);
+
+  for (spd = spd_start; spd < spd_end; spd += 75) {
+    disk = -1;
+    for (i = 0; i < NZONE; i++) {
+      if (spd == SPDzone[i]) 
+	disk = USNOdisk[i];
+    }
+    if (disk < 0) {
+      fprintf (stderr, "ERROR: can't find cdrom for spd %d\n",  spd);
+      exit (0);
+    }
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/zone%04d.acc", USNO_A_DIR, spd); 
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s, is cdrom %d in drive?\n", filename, disk);
+      exit (1);  
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = RA0 / 3.75;
+    if ((RA1 / 3.75) == (int) (RA1 / 3.75)) 
+      last  = RA1 / 3.75;
+    else 
+      last  = 1 + RA1 / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "ERROR: RA out of range\n");
+      exit (1);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/zone%04d.cat", USNO_A_DIR, spd);
+    if (VERBOSE) fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s\n", filename);
+      exit (1);
+    }
+    /* advance file pointer to first slice */
+    offset = 3*sizeof(int)*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+    /* on each loop, load data from an RA slice of the catalog */
+    for (bin = first; bin < last; bin++) {
+      Nitems = 3*number[bin];
+      ALLOCATE (buffer, int, Nitems);
+      nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+      if (nitems != Nitems) {
+	fprintf (stderr, "ERROR: failure reading data from file %s\n", filename);
+	exit (1);
+      }
+      buf = buffer;
+      /* print out data from slice within RA and DEC range */
+      for (i = 0; i < number[bin]; i++, buf+=3) {
+	if ((buf[0] > iRA0) && (buf[0] < iRA1) &&
+	    (buf[1] > iDEC0) && (buf[1] < iDEC1)) {
+	  bzero (&stars[Nusno], sizeof(StarData));
+	  stars[Nusno].R = buf[0]/360000.0;
+	  stars[Nusno].D = buf[1]/360000.0 - 90.0;
+	  stars[Nusno].Mag = fabs (0.1*(buf[2] - 1000*((int)(buf[2]/1000))));
+	  /* b = 0.1*((int)(buf[2] - 1000000*((int)(buf[2]/1000000))) / 1000); */
+	  Nusno ++;
+	  if (Nusno == NUSNO) {
+	    NUSNO += 5000;
+	    REALLOCATE (stars, StarData, NUSNO);
+	  }	  
+	}
+      }
+      free (buffer);
+    }
+    fclose (f);
+  }
+
+  *Nstars = Nusno;
+  if (VERBOSE) fprintf (stderr, "%d stars from USNO 1.0\n", Nusno);
+  return (stars);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/getusnob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/getusnob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/getusnob.c	(revision 16632)
@@ -0,0 +1,148 @@
+# include "mosastro.h"
+# define NBYTE   4
+# define NELEM  20
+
+StarData *getusnob (CatStats *catstats, int *Nstars) {
+
+  long int offset;
+  int i, bin, first, last, nitems, Nitems, Nbins;
+  float hours[100];
+  int start[100], number[100], *buffer, *buf;
+  char filename[128];
+  FILE *f;
+  double DEC1;
+  double uR, uD;
+  float mB1, mB2, mR1, mR2, mB, mR;
+  int iDEC0, iDEC1, iRA0, iRA1;
+  int spd, spd_start, spd_end;
+  int NUSNO, Nusno, nstars;
+  StarData *stars;
+
+  /* identify ra & dec range of interest */
+  iRA0 = catstats[0].RA[0] * 360000.0;
+  iRA1 = catstats[0].RA[1] * 360000.0;
+  iDEC0 = (catstats[0].DEC[0] + 90.0) * 360000.0;
+  iDEC1 = (catstats[0].DEC[1] + 90.0) * 360000.0;
+  /* note that DEC is in SPD, while both have units to 0.01 degrees */
+  
+  /* data is organized in south-pole distance zones, 1 deg per direction, 0.1 deg per file */
+  spd_start = (int)(10*(catstats[0].DEC[0] + 90));
+  DEC1 = 10*(catstats[0].DEC[1] + 90);
+  if (DEC1 > (int)(DEC1)) {
+    spd_end =   (int)(1 + 10*(catstats[0].DEC[1] + 90));
+  } else {
+    spd_end =   (int)(0 + 10*(catstats[0].DEC[1] + 90));
+  }
+
+  Nusno = 0;
+  NUSNO = 5000;
+  ALLOCATE (stars, StarData, NUSNO);
+
+  for (spd = spd_start; spd < spd_end; spd ++) {
+    
+    /* load accelerator file */
+    sprintf (filename, "%s/%03d/b%04d.acc", USNO_B_DIR, (int)(spd/10), spd); 
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open accelerator file %s\n", filename);
+      exit (1);  
+    }
+    for (i = 0; fscanf (f, "%f %d %d", &hours[i], &start[i], &number[i]) != EOF; i++);
+    Nbins = i;
+    fclose (f);
+    
+    first = catstats[0].RA[0] / 3.75;
+    if ((catstats[0].RA[1] / 3.75) == (int) (catstats[0].RA[1] / 3.75)) 
+      last  = catstats[0].RA[1] / 3.75;
+    else 
+      last  = 1 + catstats[0].RA[1] / 3.75;
+
+    if ((first > Nbins) || (last > Nbins)) {
+      fprintf (stderr, "ERROR: RA out of range\n");
+      exit (1);
+    }
+    
+    /* open data file */
+    sprintf (filename, "%s/%03d/b%04d.cat", USNO_B_DIR, (int)(spd/10), spd); 
+    fprintf (stderr, "reading from %s\n", filename);
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't open file %s\n", filename);
+      exit (1);
+    }
+
+    /** USNO-B consists of 20 x 4byte (int) records **/
+    /* advance file pointer to first slice */
+    offset = NELEM*NBYTE*(start[first] - 1);
+    fseek (f, offset, SEEK_SET);
+
+    /* sum the number of stars in data segment of interest */
+    nstars = 0;
+    for (bin = first; bin < last; bin++) {
+      nstars += number[bin];
+    }
+    Nitems = NELEM*nstars;  /* number of integer blocks; need to use Fread for byte-swapping read */
+
+    /* allocate space for stars in segment */
+    ALLOCATE (buffer, int, Nitems);
+    // data has the WRONG byte order?
+    // nitems = Fread (buffer, sizeof(int), Nitems, f, "int");
+    nitems = fread (buffer, sizeof(int), Nitems, f);
+    if (nitems != Nitems) {
+      fprintf (stderr, "ERROR: failure reading data from file %s\n", filename);
+      exit (1);
+    }
+
+    buf = buffer;
+    /* print out data from slice within RA and DEC range */
+    for (i = 0; i < nstars; i++, buf+=NELEM) {
+      if (buf[0] < iRA0) continue;
+      if (buf[0] > iRA1) continue;
+      if (buf[1] < iDEC0) continue;
+      if (buf[1] > iDEC1) continue;
+      
+      bzero (&stars[Nusno], sizeof(StarData));
+      stars[Nusno].R = buf[0]/360000.0;
+      stars[Nusno].D = buf[1]/360000.0 - 90.0;
+      
+      uR = (buf[2] % 10000);
+      uR = (uR - 5000.0) * 0.002 / 3600.0;
+      uD = ((buf[2] / 10000) % 10000);
+      uD = (uD - 5000.0) * 0.002 / 3600.0;
+
+      /* 1st blue mag */
+      mB1 = 0.01 * (buf[5] % 10000);
+      /* 1st blue mag */
+      mB2 = 0.01 * (buf[6] % 10000);
+      /* 1st blue mag */
+      mR1 = 0.01 * (buf[7] % 10000);
+      /* 1st blue mag */
+      mR2 = 0.01 * (buf[8] % 10000);
+
+      if (mB1 && mB2) {
+	mB = 0.5*(mB1 + mB2);
+      } else {
+	mB = (mB1) ? mB1 : mB2;
+      }
+
+      if (mR1 && mR2) {
+	mR = 0.5*(mR1 + mR2);
+      } else {
+	mR = (mR1) ? mR1 : mR2;
+      }
+      
+      stars[Nusno].M = mB;
+      stars[Nusno].R += uR*(Year - 2000.0);
+      stars[Nusno].D += uD*(Year - 2000.0);
+      Nusno ++;
+      CHECK_REALLOCATE (stars, StarData, NUSNO, Nusno, 5000);
+    }
+    free (buffer);
+    fclose (f);
+  }
+  
+  *Nstars = Nusno;
+  if (VERBOSE) fprintf (stderr, "%d stars from USNO B1.0\n", Nusno);
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/greference.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/greference.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/greference.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "mosastro.h"
+
+StarData *greference (int *Nrefcat) {
+
+  int Nstars;
+  StarData *stars;
+  CatStats catstats;
+
+  if (VERBOSE) fprintf (stderr, "loading astrometric reference data from %s\n", REFCAT); 
+
+  stars = NULL;
+  Nstars = 0;
+  catstats.RA[0]  = field.Rmin;
+  catstats.RA[1]  = field.Rmax;
+  catstats.DEC[0] = field.Dmin;
+  catstats.DEC[1] = field.Dmax;
+
+  if (VERBOSE) fprintf (stderr, "full region: %f - %f, %f - %f\n", catstats.RA[0], catstats.RA[1], catstats.DEC[0], catstats.DEC[1]);
+
+  /* get stars from the Stone et al catalog for the given region */
+  if (!strcmp (REFCAT, "STONE")) {
+    stars = getstone (&catstats, &Nstars);
+  }
+
+  /* get stars from the USNO A catalog for the given region */
+  if (!strcmp (REFCAT, "USNO")) {
+    stars = getusno (&catstats, &Nstars);
+  }
+
+  /* get stars from the USNO A catalog for the given region */
+  if (!strcmp (REFCAT, "USNOB")) {
+    stars = getusnob (&catstats, &Nstars);
+  }
+
+  /* get stars from the HST GSC catalog for the given region */
+  if (!strcmp (REFCAT, "GSC")) {
+    stars = getgsc (&catstats, &Nstars);
+  }
+  
+  /* get stars from 2MASS for the given region -- add PHOTCODE check? */
+  if (!strcmp (REFCAT, "2MASS")) {
+    strcpy (CATDIR, TWO_MASS_DIR);
+    stars = getptolemy (&catstats, &Nstars);
+  }
+  
+  /* get stars from the DVO CATDIR for the given region */
+  if (!strcmp (REFCAT, "PTOLEMY")) {
+    strcpy (CATDIR, ASTROM_CATDIR);
+    stars = getptolemy (&catstats, &Nstars);
+  }
+  
+  if (Nstars == 0) {
+    fprintf (stderr, "no ref objs: %s\n", REFCAT);
+    exit (1);
+  }
+  *Nrefcat = Nstars;
+  return (stars);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/match.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/match.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/match.c	(revision 16632)
@@ -0,0 +1,117 @@
+# include "mosastro.h"
+/* match is done on tangent plane : should be focal plane in some cases? */
+
+int match (StarData *refcat, int Nrefcat) {
+
+  int i, j, k, K, Ntotal;
+  int Nmatch, NMATCH;
+  double dp, dq, radius, Radius;
+  double *p, *q, *P, *Q;
+  int *U, *u;
+
+  /* requested radius is in arcsec ; internally radius is in pixels */
+  Radius = RADIUS / (3600.0 * field.project.cdelt2);
+  fprintf (stderr, "mosastro match radius: %f\n", Radius);
+
+  /* sort the REFCAT data by P in tangent plane */ 
+  ALLOCATE (P, double, Nrefcat);
+  ALLOCATE (Q, double, Nrefcat);
+  ALLOCATE (U, int, Nrefcat);
+  for (i = 0; i < Nrefcat; i++) {
+    U[i] = i;
+    P[i] = refcat[i].P;
+    Q[i] = refcat[i].Q;
+  }
+  sort_coords_index (P, Q, U, Nrefcat);
+
+  for (i = 0; i < Nchip; i++) {
+
+    Nmatch = 0;
+    NMATCH = 1000;
+    ALLOCATE (chip[i].raw, StarData, NMATCH);
+    ALLOCATE (chip[i].ref, StarData, NMATCH);
+
+    /* sort the star data by P in tangent plane */ 
+    ALLOCATE (p, double, chip[i].Nstars);
+    ALLOCATE (q, double, chip[i].Nstars);
+    ALLOCATE (u, int, chip[i].Nstars);
+    for (j = 0; j < chip[i].Nstars; j++) {
+      u[j] = j;
+      p[j] = chip[i].stars[j].P;
+      q[j] = chip[i].stars[j].Q;
+    }
+    sort_coords_index (p, q, u, chip[i].Nstars);
+
+    /* find star matches in the tangent plane coord system */
+    for (j = k = 0; (j < chip[i].Nstars) && (k < Nrefcat); ) {
+
+      /** instrumental magnitude limits for raw data **/
+      if (IMAG_MIN && (chip[i].stars[u[j]].Mag - ZERO_POINT < IMAG_MIN)) {
+	j++;
+	continue;
+      }
+      if (IMAG_MAX && (chip[i].stars[u[j]].Mag - ZERO_POINT > IMAG_MAX)) {
+	j++;
+	continue;
+      }
+      /* skip anything with dMag too large */
+      if (SIGMA_LIM > 0.0) {
+	if (chip[i].stars[u[j]].dMag > SIGMA_LIM) {
+	  j++;
+	  continue;
+	}
+      }
+	
+      dp = p[j] - P[k];
+	
+      if (dp <= -2*Radius) {
+	j++;
+	continue;
+      }
+      if (dp >= 2*Radius) {
+	k++;
+	continue;
+      }
+
+      K = k;
+      for (; (dp > -2*Radius) && (k < Nrefcat); k++) {
+	dp = p[j] - P[k];
+	dq = q[j] - Q[k];
+	radius = hypot (dp, dq);
+	if (radius < Radius) {
+	  chip[i].ref[Nmatch] = refcat[U[k]];
+	  chip[i].raw[Nmatch] = chip[i].stars[u[j]];
+	  chip[i].raw[Nmatch].Mag -= ZERO_POINT;  /* raw in instrumental mags */
+	  Nmatch ++;
+	  if (Nmatch == NMATCH) {
+	    NMATCH += 1000;
+	    REALLOCATE (chip[i].raw, StarData, NMATCH);
+	    REALLOCATE (chip[i].ref, StarData, NMATCH);
+	  }
+	  goto done;
+	}
+      }
+    done:
+      k = K;
+      j++;
+    }
+    REALLOCATE (chip[i].raw, StarData, MAX (1, Nmatch));
+    REALLOCATE (chip[i].ref, StarData, MAX (1, Nmatch));
+    chip[i].Nmatch = Nmatch;
+    free (p);
+    free (q);
+    free (u);
+  }
+  free (P);
+  free (Q);
+  free (U);
+  
+  Ntotal = 0;
+  for (i = 0; i < Nchip; i++) {
+    Ntotal += chip[i].Nmatch;
+    if (VERBOSE) fprintf (stderr, "chip %d: %d of %d stars\n", 
+			  i, chip[i].Nmatch, chip[i].Nstars);
+  }
+  fprintf (stderr, "Nchips: %d  Nmatch:  %d\n", Nchip, Ntotal);
+  return (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkheader.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkheader.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkheader.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "mosastro.h"
+
+Header *mkheader (int Nx, int Ny, int Nstars, Coords *coords) {
+
+  Header *header;
+
+  ALLOCATE (header, Header, 1);
+
+  gfits_init_header (header);
+  header[0].bitpix = -32;
+  header[0].Naxes = 2;
+  header[0].Naxis[0] = Nx;
+  header[0].Naxis[1] = Ny;
+
+  gfits_create_header (header);
+
+  gfits_modify (header, "NSTARS",   "%d", 1, Nstars);
+  gfits_modify (header, "PHOTCODE", "%s", 1, "STD.R");
+  gfits_modify (header, "DATE-OBS", "%s", 1, "2004-04-22");
+  gfits_modify (header, "UTC-OBS",  "%s", 1, "14:27:45.30");
+  gfits_modify (header, "ZERO_PT", "%lf", 1, 25.0);
+  gfits_modify (header, "EXPTIME", "%lf", 1, 2.0);
+
+  PutCoords (coords, header);
+
+  gfits_modify (header, "NASTRO",   "%d", 1, 1); 
+
+  return (header);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkmosaic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkmosaic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkmosaic.c	(revision 16632)
@@ -0,0 +1,88 @@
+# include "mosastro.h"
+
+Header *mkmosaic (int Nx, int Ny, int Nstars, Coords *coords) {
+
+  int Nastro;
+  double Xmin, Xmax, Ymin, Ymax, tmp;
+  double DL, DM, Cerror, Cprecise;
+  Header *header;
+  char line[80];
+
+  /* mosaic header has info to define the outline of the mosaic */
+  RD_to_XY (&Xmin, &Ymin, field.Rmin, field.Dmin, coords);
+  RD_to_XY (&Xmax, &Ymax, field.Rmax, field.Dmax, coords);
+
+  ALLOCATE (header, Header, 1);
+
+  gfits_init_header (header);
+
+  header[0].bitpix = -32;
+  header[0].Naxes = 2;
+  header[0].Naxis[0] = Xmax - Xmin;
+  header[0].Naxis[1] = Ymax - Ymin;
+
+  gfits_create_header (header);
+
+  /* calculate image-wide astrometry scatter */
+  Cerror   = GetScatter (&Nastro, &DL, &DM, FALSE);
+  Cprecise = Cerror / sqrt (Nastro);
+  gfits_modify (header, "CERROR",   "%lf", 1, Cerror);
+  gfits_modify (header, "CERR_L",   "%lf", 1, DL*3600.0 * field.project.cdelt1);
+  gfits_modify (header, "CERR_M",   "%lf", 1, DM*3600.0 * field.project.cdelt1);
+
+  gfits_modify (header, "CPRECISE", "%lf", 1, Cprecise);
+  gfits_modify (header, "NSTARS",   "%d",  1, 0);  /*** modify addstar to allow NSTARS = 0 ***/
+  gfits_modify (header, "NASTRO",   "%d",  1, Nastro);
+
+  GetScatter (&Nastro, &DL, &DM, TRUE);
+  gfits_modify (header, "CERR_LB",  "%lf", 1, DL*3600.0 * field.project.cdelt1);
+  gfits_modify (header, "CERR_MB",  "%lf", 1, DM*3600.0 * field.project.cdelt1);
+  gfits_modify (header, "NBRIGHT",  "%d",  1, Nastro);
+
+  fprintf (stderr, "bright: %f %f %d\n", DL*3600.0 * field.project.cdelt1, DM*3600.0 * field.project.cdelt1, Nastro);
+
+  /* make a better selection for the mosaic photcode? */
+  gfits_scan (&chip[0].header, "PHOTCODE", "%s", 1, line);
+  gfits_modify (header, "PHOTCODE", "%s", 1, line);
+
+  gfits_scan (&chip[0].header, "ZERO_PT", "%lf", 1, &tmp);
+  gfits_modify (header, "ZERO_PT", "%lf", 1, tmp);
+
+  gfits_scan (&chip[0].header, ExptimeKeyword,  "%lf", 1, &tmp);
+  gfits_modify (header, ExptimeKeyword,  "%lf", 1, tmp);
+
+  /* insert time data from chip[0] */
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    gfits_scan (&chip[0].header, JDKeyword, "%lf", 1, &tmp);
+    gfits_modify (header, JDKeyword, "%lf", 1, tmp);
+    goto got_time;
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    gfits_scan (&chip[0].header, MJDKeyword, "%lf", 1, &tmp);
+    gfits_modify (header, MJDKeyword, "%lf", 1, tmp);
+    goto got_time;
+  }
+    
+  /* get UT and DATE */
+  if (strcasecmp (UTKeyword, "NONE") && strcasecmp (DateKeyword, "NONE")) {
+    uppercase (UTKeyword);
+    gfits_scan (&chip[0].header, UTKeyword, "%s", 1, line);
+    gfits_modify (header, UTKeyword, "%s", 1, line);
+    uppercase (DateKeyword);
+    gfits_scan (&chip[0].header, DateKeyword, "%s",  1, line);
+    gfits_modify (header, DateKeyword, "%s", 1, line);
+    goto got_time;
+  }
+  fprintf (stderr, "ERROR: missing time abstraction in config\n");
+  exit (1);
+
+got_time:
+
+  PutCoords (coords, header);
+  return (header);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkobs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkobs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkobs.c	(revision 16632)
@@ -0,0 +1,142 @@
+# include "mosastro.h"
+
+int main (int argc, char **argv) {
+
+  int i, j, N, Nrefcat, Nchip, Nstars, NSTARS;
+  double Ro, Do, Po, Qo, Lo, Mo;
+  double dX, dY, Dist;
+  double RA, DEC;
+  char filename[64];
+  Coords map, coords;
+  StarData *refcat;
+  SMPData *stars;
+  Header *header;
+
+  ConfigInit (&argc, argv);
+  args (&argc, argv);
+  init_random ();
+
+  RA  = atof(argv[1]);
+  DEC = atof(argv[2]);
+  OUTPUT = argv[3];
+  fake_field_center (RA, DEC);
+
+  /* chip size in pixels (output is 5x5 grid of chips */
+  dX = 0.1 / field.project.cdelt1;
+  dY = 0.1 / field.project.cdelt2;
+
+  refcat = greference (&Nrefcat);
+  project_refcat (refcat, Nrefcat);
+  if (FOCAL_PLANE != NULL) {
+    FILE *f;
+    f = fopen (FOCAL_PLANE, "w");
+    dump_stars (f, refcat, Nrefcat);
+    fclose (f);
+  }
+  if (NO_CHIPS) exit (0);
+
+  Nchip = 0;
+  for (i = -2; i < 3; i++) {
+    for (j = -2; j < 3; j++) {
+
+      /* find chip center in TP, FP and Sky */
+      Po = 2*dX*i;
+      Qo = 2*dY*j;
+      RD_to_XY (&Lo, &Mo, Po, Qo, &field.distort);
+      XY_to_RD (&Ro, &Do, Po, Qo, &field.project);
+
+      /* FP-Chip terms */
+      strcpy (map.ctype, "DEC--WRP");
+      map.crval1 = Lo;
+      map.crval2 = Mo;
+      map.crpix1 = dX;
+      map.crpix2 = dX;
+  
+      map.cdelt1 = 1.0;
+      map.cdelt2 = 1.0;
+
+      map.pc1_1  = 1;
+      map.pc2_2  = 1;
+      map.pc1_2  = 0;
+      map.pc2_1  = 0;
+
+      map.Npolyterms = 2;
+      for (N = 0; N < 7; N++) {
+	map.polyterms[N][0] = 0;
+	map.polyterms[N][1] = 0;
+      }
+      map.polyterms[2][1] = 1e-5;
+
+      /* project catalog stars to chip */
+      FPtoChip (refcat, Nrefcat, &map);
+
+      Nstars = 0;
+      NSTARS = 1000;
+      ALLOCATE (stars, SMPData, NSTARS);
+
+      /* find catalog stars on chip */
+      for (N = 0; N < Nrefcat; N++) {
+	if (refcat[N].X < 0) continue;
+	if (refcat[N].Y < 0) continue;
+	if (refcat[N].X >= 2*dX) continue;
+	if (refcat[N].Y >= 2*dY) continue;
+
+	/* add random noise - not gaussian noise */
+	stars[Nstars].X = refcat[N].X + SIGMA*(drand48() - 0.5);
+	stars[Nstars].Y = refcat[N].Y + SIGMA*(drand48() - 0.5);
+	stars[Nstars].M = 16.0;
+	stars[Nstars].dM = 0.02;
+	stars[Nstars].dophot = 1;
+	stars[Nstars].sky = 1.0;
+	stars[Nstars].Mgal = 16.0;
+	stars[Nstars].Map = 16.0;
+	stars[Nstars].fx = 1.0;
+	stars[Nstars].fy = 1.0;
+	stars[Nstars].df = 0.0;
+
+	Nstars ++;
+	if (Nstars >= NSTARS) {
+	  NSTARS += 1000;
+	  REALLOCATE (stars, SMPData, NSTARS);
+	}
+      }
+
+
+      /* Chip-Sky terms */
+      strcpy (coords.ctype, "DEC--WRP");
+      coords.crval1 = Ro;
+      coords.crval2 = Do;
+      coords.crpix1 = dX;
+      coords.crpix2 = dY;
+  
+      { 
+	double dP, dQ, dL, dM;
+	double Mx, Lx, scale;
+
+	dP = 10;
+	dQ = 10;
+	RD_to_XY (&Lx, &Mx, Po+dP, Qo+dQ, &field.distort);
+	dL = Lx - Lo;
+	dM = Mx - Mo;
+	scale = hypot (10.0, 10.0) / hypot (dL, dM);
+	coords.cdelt1 = scale/3600.0;
+	coords.cdelt2 = scale/3600.0;
+      }
+
+      coords.pc1_1  = 1;
+      coords.pc2_2  = 1;
+      coords.pc1_2  = 0;
+      coords.pc2_1  = 0;
+      coords.Npolyterms = 1;
+
+      header = mkheader (2*dX, 2*dY, Nstars, &coords);
+
+      sprintf (filename, "%s.%02d.fits", OUTPUT, Nchip);
+      wstars (filename, stars, Nstars, header);
+      gfits_free_header (header);
+      free (stars);
+      Nchip ++;
+    }
+  }
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkpolyterm.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkpolyterm.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkpolyterm.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "mosastro.h"
+
+int mkpolyterm (int n, int m) {
+  
+  int i, nt, N;
+  
+  N = 0;
+  nt = n + m;
+  for (i = 2; i < nt; i++) {
+    N += i + 1;
+  }
+  N += m;
+  return (N);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkstandards.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkstandards.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/mkstandards.c	(revision 16632)
@@ -0,0 +1,99 @@
+# include "mosastro.h"
+# define DX 30.0
+# define DY 30.0
+
+extern double drand48();
+void init_random ();
+
+/* build a grid of reference stars */
+int main (int argc, char **argv) {
+
+  int i, N, Nstars, NSTARS, Random;
+  double x, y, m, dX, dY;
+  Header *header;
+  Coords coords;
+  SMPData *stars;
+
+  Random = FALSE;
+  if ((N = get_argument (argc, argv, "-random"))) {
+    Random = TRUE;
+    remove_argument (N, &argc, argv);
+    Nstars = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    fprintf (stderr, "USAGE: mkstandards (RA) (DEC) (half-width) (output) [-random Nstars]\n");
+    exit (2);
+  }
+
+  /* generate grid of stars */
+  dX = dY = 3600*atof (argv[3]);
+
+  /* bore site center guess */
+  strcpy (coords.ctype, "DEC--TAN");
+  coords.crval1 = atof(argv[1]);
+  coords.crval2 = atof(argv[2]);
+  coords.crpix1 = dX;
+  coords.crpix2 = dX;
+  
+  coords.cdelt1 = 1/3600.0;
+  coords.cdelt2 = 1/3600.0;
+
+  coords.pc1_1  = 1;
+  coords.pc2_2  = 1;
+  coords.pc1_2  = 0;
+  coords.pc2_1  = 0;
+  coords.Npolyterms = 1;
+
+  if (Random) {
+    
+    init_random ();
+
+    ALLOCATE (stars, SMPData, Nstars);
+    for (i = 0; i < Nstars; i++) {
+      x = 2*dX*drand48();
+      y = 2*dY*drand48();
+      m = 14.0 + 4.0*drand48();
+      stars[i].X = x;
+      stars[i].Y = y;
+      stars[i].M = m;
+      stars[i].dM = 0.02;
+    }
+  } else {
+
+    Nstars = 0;
+    NSTARS = 1000;
+    ALLOCATE (stars, SMPData, NSTARS);
+
+    for (x = 0; x < 2*dX; x += DX) {
+      for (y = 0; y < 2*dY; y += DY) {
+	stars[Nstars].X = x;
+	stars[Nstars].Y = y;
+	stars[Nstars].M = 16.0;
+
+	Nstars ++;
+	if (Nstars >= NSTARS) {
+	  NSTARS += 1000;
+	  REALLOCATE (stars, SMPData, NSTARS);
+	}
+      }
+    }
+  }
+
+  for (i = 0; i < Nstars; i++) {
+    stars[i].dophot = 1;
+    stars[i].sky = 1.0;
+    stars[i].Mgal = 16.0;
+    stars[i].Map = 16.0;
+    stars[i].fx = 1.0;
+    stars[i].fy = 1.0;
+    stars[i].df = 0.0;
+  }
+
+  header = mkheader (2*dX, 2*dY, Nstars, &coords);
+  wstars (argv[4], stars, Nstars, header);
+  gfits_free_header (header);
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/mosastro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/mosastro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/mosastro.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "mosastro.h"
+# include <glob.h>
+
+int main (int argc, char **argv) {
+
+  int Nrefcat, Nastro;
+  double Cerror, DL, DM;
+  double Scale;
+  glob_t pglob;
+  StarData *refcat;
+  Gradients *grad;
+
+
+  ConfigInit (&argc, argv);
+  args (&argc, argv); 
+
+  if (argc != 4) { 
+    fprintf (stderr, "USAGE: mosastro (inglob) (ext) (mosaic.phu)\n");
+    exit (2);
+  }
+
+  pglob.gl_offs = 0;
+  glob (argv[1], 0, NULL, &pglob);
+
+  LoadStars (pglob.gl_pathc, pglob.gl_pathv);
+
+  /* use per-chip astrometry to find ra,dec range */ 
+  deproject_stars ();
+  field_stats (); /** needs coords from deproject_stars **/
+  init_field ();  /** needs results from field stats **/
+  init_chips ();  /** needs results from init_field **/
+  Scale = 3600.0 * field.project.cdelt1;
+
+  /* use field model to get TP & FP coords */
+  project_stars ();
+  if ((DUMP != NULL) && !strcmp (DUMP, "rawstars")) dump_rawstars();
+
+  refcat = greference (&Nrefcat);
+  project_refcat (refcat, Nrefcat);
+  if ((DUMP != NULL) && !strcmp (DUMP, "refcat")) dump_refcat(refcat, Nrefcat);
+
+  match (refcat, Nrefcat);
+  deproject_raw ();
+  project_ref ();
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (raw) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+  if ((DUMP != NULL) && !strcmp (DUMP, "rawmatch")) dump_match();
+
+  grad = GetGradients ();
+  FitGradients (grad);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (grad) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+  if ((DUMP != NULL) && !strcmp (DUMP, "fitgrads")) dump_match();
+  Scale = 3600.0 * field.project.cdelt1;
+
+  FitChips (ChipOrder);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (chip) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+  if ((DUMP != NULL) && !strcmp (DUMP, "fitchips_unclip")) dump_match();
+
+  ClipOnFP (2.5);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (clip) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+
+  FitChips (ChipOrder);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (chip) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+
+  ClipOnFP (2.5);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (clip) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+
+  FitChips (ChipOrder);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (chip) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+
+  ClipOnFP (2.5);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (clip) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+
+  FitChips (ChipOrder);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, FALSE);
+  fprintf (stderr, "scatter (brit) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+  Cerror   = GetScatter (&Nastro, &DL, &DM, TRUE);
+  fprintf (stderr, "scatter (chip) : %6.4f for %d stars (%6.4f, %6.4f)\n", Cerror, Nastro, DL*Scale, DM*Scale);
+  if ((DUMP != NULL) && !strcmp (DUMP, "fitchips")) dump_match();
+
+  /* testcoords (); */
+  output (argv[2], argv[3]);
+  exit (0);
+
+/*
+  FitField (3);
+  FitChips (3);
+*/
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/output.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "mosastro.h"
+
+void output (char *ext, char *phu) {
+
+  int i, N;
+  char *p, outname[256];
+  FILE *f;
+  Header *header;
+  
+  for (i = 0; i < Nchip; i++) {
+    
+    /* convert chip[i].file to output name */
+    
+    p = strrchr (chip[i].file, '.');
+    N = p - chip[i].file + 1;
+    if (p == NULL) N = strlen (chip[i].file);
+
+    bzero (outname, 256);
+    strncpy (outname, chip[i].file, N);
+
+    strcat (outname, ext);
+
+    /* convert chip from PLY to WRP (linked to field model) */
+    strcpy (chip[i].map.ctype, "DEC--WRP");
+    PutCoords (&chip[i].map, &chip[i].header);
+    wchip (outname, &chip[i]);
+  }
+
+  field_combine ();
+
+  f = fopen (phu, "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file %s\n", phu);
+    exit (1);
+  }
+
+  header = mkmosaic (1, 1, 0, &field.project);
+  if (SAVE_RESID) {
+    SaveResiduals (f, header);
+    return;
+  }
+
+  fwrite (header[0].buffer, 1, header[0].size, f);
+  fclose (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/parse_time.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/parse_time.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/parse_time.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "mosastro.h"
+
+e_time parse_time (Header *header) {
+
+  double jd;
+  int Ny, Nf, mode;
+  int hour, min, sec, year, month, day;
+  char *py, *pm, *pd, *c;
+  char line[256];
+  e_time Nsec;
+
+  /* we want to find JD or MJD to get Nsec (seconds since 01/01/1970) */
+
+  /* try JD first */
+  if (strcasecmp (JDKeyword, "NONE")) {
+    uppercase (JDKeyword);
+    gfits_scan (header, JDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 2440587.5)*86400;
+    return (Nsec);
+  }
+
+  /* try MJD next */
+  if (strcasecmp (MJDKeyword, "NONE")) {
+    uppercase (MJDKeyword);
+    gfits_scan (header, MJDKeyword, "%lf", 1, &jd);
+    Nsec = (jd - 40587.0)*86400;
+    return (Nsec);
+  }
+    
+  /* get UT and DATE */
+  uppercase (UTKeyword);
+  gfits_scan (header, UTKeyword, "%s", 1, line);
+  /* remove ':' characters */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  sscanf (line, "%d %d %d", &hour, &min, &sec);
+
+  /* parse mode line */
+  uppercase (DateMode);
+  for (Ny = 0, c = strchr (DateMode, 'Y'); c != (char ) NULL; c = strchr (c + 1, 'Y'), Ny++);
+  if ((Ny != 2) && (Ny != 4)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  py = strchr (DateMode, 'Y');
+  pm = strchr (DateMode, 'M');
+  pd = strchr (DateMode, 'D');
+  if ((py == (char *) NULL) || (pm == (char *) NULL) || (pd == (char *) NULL)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pm) && (py < pd)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  if ((py > pd) && (py < pm)) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+  mode = 0;
+  if ((py < pm) && (pm < pd)) { mode = 1; }  /* yyyy-mm-dd */
+  if ((py < pm) && (pm > pd)) { mode = 2; }  /* yyyy-dd-mm */
+  if ((py > pm) && (pm < pd)) { mode = 3; }  /* mm-dd-yyyy */
+  if ((py > pm) && (pm > pd)) { mode = 4; }  /* dd-mm-yyyy */
+  if (!mode) {
+    fprintf (stderr, "error in DATE-MODE format: %s\n", DateMode);
+    exit (1);
+  }
+
+  /* parse date entry */
+  uppercase (DateKeyword);
+  gfits_scan (header, DateKeyword, "%s",  1, line);
+  /* remove possible separators: ':', '/' '.', '-' */
+  for (c = strchr (line, 0x3a); c != (char *) NULL; c = strchr (line, 0x3a)) { *c = ' '; }
+  for (c = strchr (line, 0x2f); c != (char *) NULL; c = strchr (line, 0x2f)) { *c = ' '; }
+  for (c = strchr (line, 0x2e); c != (char *) NULL; c = strchr (line, 0x2e)) { *c = ' '; }
+  for (c = strchr (line, 0x2d); c != (char *) NULL; c = strchr (line, 0x2d)) { *c = ' '; }
+
+  Nf = 0;
+  switch (mode) {
+  case 1:
+    Nf = sscanf (line, "%d %d %d", &year, &month, &day);
+    break;
+  case 2:
+    Nf = sscanf (line, "%d %d %d", &year, &day, &month);
+    break;
+  case 3:
+    Nf = sscanf (line, "%d %d %d", &month, &day, &year);
+    break;
+  case 4:
+    Nf = sscanf (line, "%d %d %d", &day, &month, &year);
+    break;
+  }
+  if (Nf != 3) {
+    fprintf (stderr, "error in date entry (%s) or DATE-MODE format (%s)\n", line, DateMode);
+    exit (1);
+  }
+
+  if (year > 1000) {
+    if (Ny == 2) {
+      fprintf (stderr, "warning: mode line claims 2 digit year, but 4 digit year found\n");
+    }
+  } else {
+    if (Ny == 4) {
+      fprintf (stderr, "warning: mode line claims 4 digit year, but 2 digit year found\n");
+    }
+    if (year < 50) year += 100;
+    year += 1900;
+  }    
+
+  /* convert yy.mm.dd hh.mm.ss to Nsec since 1970 (jd = 2440587.5) */
+  /* note that in this section, tm_mon has range 1-12, unlike for gmtime () */
+  jd = day - 32075 + (int)(1461*(year + 4800 + (int)(((month)-14)/12))/4)
+    + (int)(367*((month) - 2 - (int)(((month) - 14)/12)*12)/12)
+    - (int)(3*(int)((year + 4900 + (int)(((month) - 14)/12))/100)/4) - 0.5;
+  /* jd is the julian day of the whole day only not the time */
+  Nsec = (jd - 2440587.5)*86400 + 3600.0*hour + min*60.0 + sec;
+  
+  return (Nsec);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/project.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/project.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/project.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "mosastro.h"
+
+int project_refcat (StarData *refcat, int Nrefcat) {
+
+  SkyToTP (refcat, Nrefcat, &field.project);
+  TPtoFP  (refcat, Nrefcat, &field.distort);
+
+  return (1);
+}
+
+int deproject_stars () {
+
+  int i;
+
+  for (i = 0; i < Nchip; i++) {
+    ChipToSky (chip[i].stars, chip[i].Nstars, &chip[i].coords);
+  }
+  return (1);
+}
+
+int project_stars () {
+
+  int i;
+
+  for (i = 0; i < Nchip; i++) {
+    SkyToTP (chip[i].stars, chip[i].Nstars, &field.project);
+    TPtoFP  (chip[i].stars, chip[i].Nstars, &field.distort);
+  }
+  return (1);
+}
+
+int deproject_raw () {
+
+  int i;
+
+  for (i = 0; i < Nchip; i++) {
+    ChipToFP (chip[i].raw, chip[i].Nmatch, &chip[i].map);
+    FPtoTP   (chip[i].raw, chip[i].Nmatch, &field.distort);
+    TPtoSky  (chip[i].raw, chip[i].Nmatch, &field.project);
+  }
+  return (1);
+}
+
+int project_ref () {
+
+  int i;
+
+  for (i = 0; i < Nchip; i++) {
+    SkyToTP  (chip[i].ref, chip[i].Nmatch, &field.project);
+    TPtoFP   (chip[i].ref, chip[i].Nmatch, &field.distort);
+    FPtoChip (chip[i].ref, chip[i].Nmatch, &chip[i].map);
+  }
+  return (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/random.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/random.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/random.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include <stdio.h>
+# include <time.h>
+# include <stdlib.h>
+
+void init_random () {
+
+  long A, B;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/rfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/rfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/rfits.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "mosastro.h"
+
+int rfits (Chip *mychip) {
+
+  int i, Nx;
+  FILE *f;
+  FTable table;
+  SMPData *stars;
+
+  /* open file for stars */
+  f = fopen (mychip[0].file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't open file to load stars\n");
+    exit (1);
+  }
+  fseek (f, mychip[0].header.size, SEEK_SET); 
+
+  /* init & load in table data */
+  table.header   = &mychip[0].theader;
+  if (!gfits_fread_matrix (f, &mychip[0].matrix, &mychip[0].header)) {
+    fprintf (stderr, "error reading file\n");
+    fclose (f);
+    return (FALSE);
+  }
+  if (!gfits_fread_ftable (f, &table, "SMPFILE")) {
+    fprintf (stderr, "error reading file\n");
+    gfits_free_matrix (&mychip[0].matrix);
+    fclose (f);
+    return (FALSE);
+  }
+
+  stars = gfits_table_get_SMPData (&table, &mychip[0].Nstars, NULL);
+  gfits_scan (table.header, "NAXIS1", "%d", 1, &Nx);
+
+  /* save raw data for output */
+  mychip[0].FITS = TRUE;
+  mychip[0].buffer = (char *) stars;
+  mychip[0].Nbuffer = Nx*mychip[0].Nstars;
+
+  if (mychip[0].Nstars < 5) { 
+    fprintf (stderr, "Too few stars for reliable solution, only %d\n", mychip[0].Nstars);
+    gfits_free_matrix (&mychip[0].matrix);
+    gfits_free_table (&table);
+    fclose (f);
+    return (FALSE);
+  }
+
+  /* note the different structures for mychip[0].stars and stars */
+  ALLOCATE (mychip[0].stars, StarData, mychip[0].Nstars);
+  for (i = 0; i < mychip[0].Nstars; i++) {
+    mychip[0].stars[i].X    = stars[i].X;
+    mychip[0].stars[i].Y    = stars[i].Y;
+    mychip[0].stars[i].Mag  = stars[i].M;
+    mychip[0].stars[i].dMag = stars[i].dM;
+  }    
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/rtext.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/rtext.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/rtext.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "mosastro.h"
+# define BYTES_STAR 66
+
+int rtext (Chip *mychip) {
+
+  int i, Nbytes, nbytes;
+  FILE *f;
+
+  f = fopen (mychip[0].file, "r");
+  if (f == NULL) {
+    fprintf (stderr, "ERROR: can't read data from %s\n", mychip[0].file);
+    return (FALSE);
+  }
+  fseek (f, mychip[0].header.size, SEEK_SET); 
+
+  /* find expected number of stars */
+  gfits_scan (&mychip[0].header, "NSTARS", "%d", 1, &mychip[0].Nstars);
+  if (mychip[0].Nstars == 0) {
+    fprintf (stderr, "ERROR: can't get NSTARS from header for %s\n", mychip[0].file);
+    return (FALSE);
+  }
+  ALLOCATE (mychip[0].stars, StarData, mychip[0].Nstars);
+    
+  Nbytes = BYTES_STAR * mychip[0].Nstars;
+  ALLOCATE (mychip[0].buffer, char, Nbytes + 1);
+  nbytes = fread (mychip[0].buffer, 1, Nbytes, f);
+  if (nbytes != Nbytes) { exit (1); }
+  mychip[0].Nbuffer = Nbytes;
+  mychip[0].FITS = FALSE;
+
+  for (i = 0; i < mychip[0].Nstars; i++) {
+    bzero (&mychip[0].stars[i], sizeof(StarData));
+    dparse (&mychip[0].stars[i].X,    1, &mychip[0].buffer[i*BYTES_STAR]);
+    dparse (&mychip[0].stars[i].Y,    2, &mychip[0].buffer[i*BYTES_STAR]);
+    dparse (&mychip[0].stars[i].Mag,  3, &mychip[0].buffer[i*BYTES_STAR]);
+    dparse (&mychip[0].stars[i].dMag, 4, &mychip[0].buffer[i*BYTES_STAR]);
+    mychip[0].stars[i].dMag *= 0.001;  /* millimag errors stored in file */
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/testcoords.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/testcoords.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/testcoords.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "mosastro.h"
+
+void testcoords () {
+
+  int i;
+  FILE *f;
+  double R, D, P, Q, L, M, X, Y;
+  
+  fprintf (stderr, "starting test.dat\n");
+
+  /* version 1: transform with three separate stages */
+  /* X,Y -> L,M -> P,Q -> R,D */
+  f = fopen ("test.1.dat", "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file \n");
+    exit (1);
+  }
+  for (i = 0; i < chip[0].Nmatch; i++) {
+    X = chip[0].raw[i].X;
+    Y = chip[0].raw[i].Y;
+    XY_to_RD (&L, &M, X, Y, &chip[0].map);
+    XY_to_RD (&P, &Q, L, M, &field.distort);
+    XY_to_RD (&R, &D, P, Q, &field.project);
+    fprintf (f, "%4d  %10.6f %10.6f  %8.2f %8.2f %8.2f %8.2f  %8.2f %8.2f\n", 
+	     i, R, D, P, Q, L, M, X, Y);
+  }
+  fclose (f);
+
+  /* version 2: transform with two separate stages */
+  /* X,Y -> L,M -> R,D */
+  f = fopen ("test.2.dat", "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file \n");
+    exit (1);
+  }
+  field_combine ();
+  for (i = 0; i < chip[0].Nmatch; i++) {
+    X = chip[0].raw[i].X;
+    Y = chip[0].raw[i].Y;
+    XY_to_RD (&L, &M, X, Y, &chip[0].map);
+    XY_to_RD (&R, &D, L, M, &field.project);
+    fprintf (f, "%4d  %10.6f %10.6f   %8.2f %8.2f  %8.2f %8.2f\n", 
+	     i, R, D, L, M, X, Y);
+  }
+  fclose (f);
+
+
+  /* version 3: transform with automatic two stages in coordops */
+  /* X,Y -> R,D */
+  f = fopen ("test.3.dat", "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file \n");
+    exit (1);
+  }
+  RegisterMosaic (&field.project);
+  strcpy (chip[0].map.ctype, "DEC--WRP");
+  for (i = 0; i < chip[0].Nmatch; i++) {
+    X = chip[0].raw[i].X;
+    Y = chip[0].raw[i].Y;
+    XY_to_RD (&R, &D, X, Y, &chip[0].map);
+    fprintf (f, "%4d  %10.6f %10.6f   %8.2f %8.2f\n", 
+	     i, R, D, X, Y);
+  }
+  fclose (f);
+  exit (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/transforms.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/transforms.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/transforms.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "mosastro.h"
+
+void ChipToSky (StarData *stars, int Nstars, Coords *coords) {
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    XY_to_RD (&stars[i].R, &stars[i].D, stars[i].X, stars[i].Y, coords);
+    while (stars[i].R < 0.0)    stars[i].R += 360.0;
+    while (stars[i].R >= 360.0) stars[i].R -= 360.0;
+  }
+}
+
+void ChipToFP (StarData *stars, int Nstars, Coords *coords) {
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    XY_to_RD (&stars[i].L, &stars[i].M, stars[i].X, stars[i].Y, coords);
+  }
+}
+
+void FPtoTP (StarData *stars, int Nstars, Coords *coords) {
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    XY_to_RD (&stars[i].P, &stars[i].Q, stars[i].L, stars[i].M, coords);
+  }
+}
+
+void TPtoSky (StarData *stars, int Nstars, Coords *coords) {
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    XY_to_RD (&stars[i].R, &stars[i].D, stars[i].P, stars[i].Q, coords);
+    while (stars[i].R < 0.0)    stars[i].R += 360.0;
+    while (stars[i].R >= 360.0) stars[i].R -= 360.0;
+  }
+}
+
+void SkyToTP (StarData *stars, int Nstars, Coords *coords) {
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    RD_to_XY (&stars[i].P, &stars[i].Q, stars[i].R, stars[i].D, coords);
+  }
+}
+
+void TPtoFP (StarData *stars, int Nstars, Coords *coords) {
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    RD_to_XY (&stars[i].L, &stars[i].M, stars[i].P, stars[i].Q, coords);
+  }
+}
+
+void FPtoChip (StarData *stars, int Nstars, Coords *coords) {
+  int i;
+  for (i = 0; i < Nstars; i++) {
+    RD_to_XY (&stars[i].X, &stars[i].Y, stars[i].L, stars[i].M, coords);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/warptest.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/warptest.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/warptest.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "mosastro.h"
+int XY_to_RD (double *ra, double *dec, double x, double y, Coords *coords);
+int RD_to_XY (double *x, double *y, double ra, double dec, Coords *coords);
+
+main (int argc, char **argv) {
+
+  int i, status;
+  double X, Y, x, y, p, q;
+  Coords coords;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: warptest (system)\n");
+    exit (2);
+  }
+
+  /* bore site center guess */
+  sprintf (coords.ctype, "RA---%s", argv[1]);
+  coords.crval1 = 0.0;
+  coords.crval2 = 0.0;
+  coords.crpix1 = 0.0;
+  coords.crpix2 = 0.0;
+  coords.cdelt1 = 1.0;
+  coords.cdelt2 = 1.0;
+
+  /* 
+  coords.cdelt1 = 1.0/3600.0;
+  coords.cdelt2 = 1.0/3600.0;
+  */
+  
+  /** allow guess at field rotation?? **/
+  coords.pc1_1  = 1;
+  coords.pc2_2  = 1;
+  coords.pc1_2  = 0;
+  coords.pc2_1  = 0;
+
+  /* allow 2nd and 3rd order? */
+  /* how do we handle renormalization? (fixed at 1000 pixels??) */
+  coords.Npolyterms = 3;
+  for (i = 0; i < 7; i++) {
+    coords.polyterms[i][0] = 0;
+    coords.polyterms[i][1] = 0;
+  }
+  coords.polyterms[3][0] = 1e-10;
+  coords.polyterms[6][1] = 1e-10;
+
+  for (x = -10000; x <= 10000; x+= 500) {
+    for (y = -10000; y <= 10000; y+= 500) {
+      status = XY_to_RD (&p, &q, x, y, &coords);
+      status = RD_to_XY (&X, &Y, p, q, &coords);
+      fprintf (stdout, "%f %f   %f %f   %f %f\n", x, y, p, q, X, Y);
+      if (!status) exit (1);
+    }
+  }
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/wfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/wfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/wfits.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "mosastro.h"
+
+void wfits (char *filename, SMPData *stars, int Nstars, Header *header) {
+
+  Matrix matrix;
+  Header theader;
+  FTable table;
+
+  header[0].extend = TRUE;
+  header[0].Naxes = 0;
+  gfits_modify (header, "NAXIS",   "%d", 1, 0);
+  gfits_modify (header, "EXTEND",  "%t", 1, TRUE);
+  gfits_modify (header, "NEXTEND", "%d", 1, 1);
+
+  /* add in some keywords to specify the datatype & software version? */
+
+  /* create (empty) data matrix */
+  gfits_create_matrix (header, &matrix);
+    
+  table.header = &theader;
+  gfits_table_set_SMPData (&table, stars, Nstars);
+
+  gfits_write_header  (filename, header);
+  gfits_write_matrix  (filename, &matrix);
+  gfits_write_Theader (filename, &theader);
+  gfits_write_table   (filename, &table);
+  return;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/mosastro/src/wstars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/mosastro/src/wstars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/mosastro/src/wstars.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "mosastro.h"
+# define NCHAR 66 /* 65 char EXCLUDING return */
+
+void wchip (char *filename, Chip *data) {
+  
+  FILE *g;
+
+  if (data[0].FITS) {
+    wfits (filename, (SMPData *) data[0].buffer, data[0].Nstars, &data[0].header);
+  } else {
+
+    g = fopen (filename, "w");
+    if (g == (FILE *) NULL) {
+      fprintf (stderr, "ERROR: can't create output file %s\n", filename);
+      exit (1);
+    }
+
+    fwrite (data[0].header.buffer, 1, data[0].header.size, g);
+    fwrite (data[0].buffer, 1, data[0].Nbuffer, g);
+    fclose (g);
+  }  
+}
+
+void wstars (char *filename, SMPData *stars, int Nstars, Header *header) {
+  
+  int i, Nchar;
+  FILE *g;
+  char line[NCHAR + 3];
+
+  g = fopen (filename, "w");
+  if (g == (FILE *) NULL) {
+    fprintf (stderr, "ERROR: can't create output file %s\n", filename);
+    exit (1);
+  }
+
+  fwrite (header[0].buffer, 1, header[0].size, g);
+
+  for (i = 0; i < Nstars; i++) {
+    if (stars[i].dophot == 0) continue;
+    Nchar = snprintf (line, NCHAR, "%6.1f %6.1f %6.3f %03d %2d %3.1f %6.3f %6.3f %6.2f %6.2f %5.1f", 
+		      stars[i].X, stars[i].Y, stars[i].M, 
+		      (int)(1000*stars[i].dM), stars[i].dophot, stars[i].sky, 
+		      stars[i].Mgal, stars[i].Map, stars[i].fx, stars[i].fy, stars[i].df);
+    
+    /* this is just a little funny.  NCHAR (in) includes the trailing NULL, Nchar (out) excludes it */
+    if (Nchar != NCHAR - 1) {
+      fprintf (stderr, "funny line %d (%d)\n%s\n", i, Nchar, line);
+    } else {
+      fprintf (g, "%s\n", line);
+    }
+  }
+
+  fclose (g);
+
+}
+
+/*
+
+  63.6 2869.5 17.568 157 17.568 17.568 25.01 25.00 360.0 7 2.9
+
+  63.6 2869.5 17.568 157 7 2.9
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/nightd/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/Makefile	(revision 16632)
@@ -0,0 +1,29 @@
+default: nightd
+help:
+	@echo "make options: nightd (default)"
+
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/nightd
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+nightd: $(BIN)/nightd.$(ARCH)
+install: $(DESTBIN)/nightd
+
+NIGHTD = \
+$(SRC)/nightd.$(ARCH).o 	$(SRC)/ConfigInit.$(ARCH).o 	\
+$(SRC)/DoCommand.$(ARCH).o 	$(SRC)/GetStatus.$(ARCH).o 	\
+$(SRC)/SetSignals.$(ARCH).o 	$(SRC)/StartUp.$(ARCH).o 	\
+$(SRC)/misc.$(ARCH).o
+
+$(NIGHTD): $(INC)/nightd.h
+$(BIN)/nightd.$(ARCH): $(NIGHTD)
Index: /branches/eam_branch_20080223/Ohana/src/nightd/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/nightd/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,10 @@
+
+- nightd 1.3 : 2006.08.23
+  - moved to ChangeLog.txt
+
+nightd-1-2:
+  - fixed minor compile warning
+
+nightd-1-1:
+  - minor cleanups for gcc -Wall
+  - nightd will be superceded eventually by sched/pcontrol?
Index: /branches/eam_branch_20080223/Ohana/src/nightd/include/nightd.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/include/nightd.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/include/nightd.h	(revision 16632)
@@ -0,0 +1,47 @@
+# include <ohana.h>
+# include <signal.h>
+# include <errno.h>
+
+FILE *LogFile;
+char *Program;
+
+char logfile[256];
+char **MainCommand;
+char **InitCommand;
+char **DoneCommand;
+
+char TestCommand[256];
+
+char DateStr[256];
+char TimeStr[256];
+
+char PIDFile[256];
+
+float NightStart;
+float NightStop;
+
+int SuspendAction;
+
+int ConfigInit (int *argc, char **argv);
+void LoadConfig (int sig);
+int dms_to_ddd (double *Value, char *string);
+int SetPID (pid_t *Xpid, char *Xuser, char *Xmachine);
+int GetDateTime (char *datestr, char *timestr, float *time);
+int WaitForMinute ();
+int GetStatus ();
+int ResetConfig ();
+int SendShutdown ();
+int StartUp ();
+int SetSignals ();
+void ToggleSuspend (int sig);
+void Shutdown (int sig);
+int Expose (char *filename);
+int vsystem (char *line);
+char *ExpandWords (char *line);
+int pcommand (char *line, int timeout);
+int WaitForPeriod ();
+int DoCommand (char *command, char *name);
+int freeargs (char **arglist);
+
+int PERIOD;
+int TIMEOUT;
Index: /branches/eam_branch_20080223/Ohana/src/nightd/scripts/ertrc
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/scripts/ertrc	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/scripts/ertrc	(revision 16632)
@@ -0,0 +1,29 @@
+
+# multiple entries are allowed for each 
+# command line, MAIN, INIT, DONE. they 
+# are performed in sequence
+
+# there are run at the start of the night
+INIT_COMMAND el_plots init
+INIT_COMMAND elixir.reload sextract
+INIT_COMMAND elixir.reload imstats
+
+MAIN_COMMAND gettemps
+MAIN_COMMAND el_plots plot
+MAIN_COMMAND elixir.link
+
+# these are run at the end of the night
+DONE_COMMAND el_plots done
+DONE_COMMAND elixir.launch mkdetrend 
+
+# PID_FILE /h/eugene/skyprobe/ert.pid
+# LOG_FILE /h/eugene/skyprobe/ert.log
+
+PID_FILE /data/milo/elixir/log/ert.pid
+LOG_FILE /data/milo/elixir/log/ert.log
+
+NIGHT_START 18:00
+NIGHT_STOP  06:00
+
+PERIOD 180
+TIMEOUT 360
Index: /branches/eam_branch_20080223/Ohana/src/nightd/scripts/skyproberc
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/scripts/skyproberc	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/scripts/skyproberc	(revision 16632)
@@ -0,0 +1,20 @@
+
+HOME      /h/skyprobe
+
+DATA_PATH $HOME/data
+PID_FILE  $HOME/.skyprobe.pid
+LOG_FILE  $HOME/sp_daemon.log
+
+CCD_TEMP -20
+EXPTIME   30
+
+INIT_COMMAND sp_command cool $CCD_TEMP
+INIT_COMMAND sp_command init $DATA_PATH/&DATE
+MAIN_COMMAND sp_command expose $EXPTIME $DATA_PATH/&DATE/sp_&DATE_&TIME.fits
+DONE_COMMAND sp_command warm
+
+NIGHT_START 18:00
+NIGHT_STOP  06:00
+
+PERIOD 60
+TIMEOUT 300
Index: /branches/eam_branch_20080223/Ohana/src/nightd/scripts/srtrc
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/scripts/srtrc	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/scripts/srtrc	(revision 16632)
@@ -0,0 +1,21 @@
+
+# wrap the commands (init, main, done) in a single script
+# this will let the config info come from the config system
+
+INIT_COMMAND sp_plots init
+
+MAIN_COMMAND sp_plots plot 
+
+DONE_COMMAND sp_plots done &DATE
+
+PID_FILE /data/milo/elixir/log/srt.pid
+LOG_FILE /data/milo/elixir/log/srt.log
+
+# PID_FILE /h/eugene/skyprobe/skyprobe.pid
+# LOG_FILE /h/eugene/skyprobe/skyprobe.log
+
+NIGHT_START 18:00
+NIGHT_STOP  06:00
+
+PERIOD 60
+TIMEOUT 300
Index: /branches/eam_branch_20080223/Ohana/src/nightd/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,115 @@
+# include "nightd.h"
+
+static char *file;
+
+int ConfigInit (int *argc, char **argv) {
+
+  char *home;
+
+  /*** load configuration info ***/
+  home = getenv ("HOME");
+  if (home == (char *) NULL) {
+    fprintf (stderr, "can't determine HOME, please set\n");
+    exit (2);
+  }
+  ALLOCATE (file, char, strlen (home) + strlen (Program) + 10);
+
+  sprintf (file, "%s/.%src", home, Program);
+  LoadConfig (SIGKILL);
+  return (TRUE);
+}
+
+void LoadConfig (int sig) {
+
+  int i, Ncmd;
+  char *config, *found;
+  char line[256];
+  double tmp;
+
+  if (sig == SIGUSR1) {
+    fprintf (LogFile, "re-loading config file %s\n", file);
+    fflush (LogFile);
+  }
+
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    fprintf (LogFile, "can't find configuration file %s\n", file);
+    exit (2);
+  }
+
+  /* need to check for error status */
+  ScanConfig (config, "PERIOD",                 "%d", 0, &PERIOD);
+  ScanConfig (config, "TIMEOUT",                "%d", 0, &TIMEOUT);
+
+  /* load list of InitCommands */
+  found = config;
+  Ncmd = 10;
+  ALLOCATE (InitCommand, char *, Ncmd);
+  for (i = 0; found != NULL; i++) {
+    ALLOCATE (InitCommand[i], char, 256);
+    bzero (InitCommand[i], 256);
+    found = ScanConfig (config, "INIT_COMMAND", "%s", i + 1, InitCommand[i]);
+    if (i == Ncmd - 1) {
+      Ncmd += 10;
+      REALLOCATE (InitCommand, char *, Ncmd);
+    }      
+  }
+  
+  /* load list of MainCommands */
+  found = config;
+  Ncmd = 10;
+  ALLOCATE (MainCommand, char *, Ncmd);
+  for (i = 0; found != NULL; i++) {
+    ALLOCATE (MainCommand[i], char, 256);
+    bzero (MainCommand[i], 256);
+    found = ScanConfig (config, "MAIN_COMMAND", "%s", i + 1, MainCommand[i]);
+    if (i == Ncmd - 1) {
+      Ncmd += 10;
+      REALLOCATE (MainCommand, char *, Ncmd);
+    }      
+  }
+
+  /* load list of DoneCommands */
+  found = config;
+  Ncmd = 10;
+  ALLOCATE (DoneCommand, char *, Ncmd);
+  for (i = 0; found != NULL; i++) {
+    ALLOCATE (DoneCommand[i], char, 256);
+    bzero (DoneCommand[i], 256);
+    found = ScanConfig (config, "DONE_COMMAND", "%s", i + 1, DoneCommand[i]);
+    if (i == Ncmd - 1) {
+      Ncmd += 10;
+      REALLOCATE (DoneCommand, char *, Ncmd);
+    }      
+  }
+
+  ScanConfig (config, "PID_FILE",               "%s", 0, PIDFile);
+  ScanConfig (config, "LOG_FILE",               "%s", 0, logfile);
+    
+  ScanConfig (config, "NIGHT_START",            "%s", 0, line);
+  if (!ohana_dms_to_ddd (&tmp, line)) { 
+    fprintf (LogFile, "format error in NIGHT_START\n");
+    exit (2);
+  } 
+  NightStart = tmp;
+  if (NightStart < 12.0) {
+    fprintf (LogFile, "warning: night starts before noon!\n");
+    fprintf (LogFile, "if you live in the Arctic Circle (or Antarctic), you might need to adjust the program\n");
+    exit (2);
+  }
+  ScanConfig (config, "NIGHT_STOP",             "%s", 0, line);
+  if (!ohana_dms_to_ddd (&tmp, line)) { 
+    fprintf (LogFile, "format error in NIGHT_STOP\n");
+    exit (2);
+  } 
+  NightStop = tmp;
+  if (NightStop > 12.0) {
+    fprintf (LogFile, "warning: night ends after noon!\n");
+    fflush (LogFile);
+  }
+  if (NightStop < 12.0) NightStop += 24.0;
+
+  /* check format of command calls: must have a certain set of %d, %s, etc */
+  free (config);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/nightd/src/DoCommand.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/src/DoCommand.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/src/DoCommand.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "nightd.h"
+
+/* special words:
+   word    variable
+   DATE    DateStr
+   TIME    TimeStr
+*/
+
+int DoCommand (char *command, char *name) {
+  
+  char *line;
+
+  line = strcreate (command);
+  line = ExpandWords (line);
+  if (pcommand (line, TIMEOUT)) {
+    fprintf (LogFile, "error running %s command\n", name);
+    fflush (LogFile);
+  }
+  free (line);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/nightd/src/GetStatus.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/src/GetStatus.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/src/GetStatus.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "nightd.h"
+
+int GetStatus () {
+
+  char user[256], machine[256];
+  pid_t pid;
+
+  if (SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s is not running\n", Program);
+    unlink (PIDFile);
+    exit (1);
+  }
+
+  fprintf (stderr, "%s apparently running:\n\n", Program);
+  fprintf (stderr, "  machine: %s\n", machine);
+  fprintf (stderr, "  user: %s\n", user);
+  fprintf (stderr, "  PID: %d\n", pid);
+  fprintf (stderr, "  remove %s if %s has died unexpectedly\n", PIDFile, Program);
+  exit (0);
+
+}
+  
+int ResetConfig () {
+
+  char user[256], machine[256], line[256];
+  pid_t pid;
+
+  if (SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s is not running\n", Program);
+    unlink (PIDFile);
+    exit (1);
+  }
+
+  sprintf (line, "rsh %s kill -USR1 %d", machine, pid);
+  system (line);
+  exit (0);
+
+}
+  
+int SendShutdown () {
+
+  char user[256], machine[256], line[256];
+  pid_t pid;
+
+  if (SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s is not running\n", Program);
+    unlink (PIDFile);
+    exit (1);
+  }
+
+  sprintf (line, "rsh %s kill -TERM %d", machine, pid);
+  system (line);
+  exit (0);
+
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/nightd/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "nightd.h"
+
+int SetSignals () {
+
+  signal (SIGTERM, Shutdown);
+  signal (SIGUSR1, LoadConfig);
+  signal (SIGUSR2, ToggleSuspend);
+  return (TRUE);
+}
+
+void ToggleSuspend (int sig) {
+
+  SuspendAction = SuspendAction ^ TRUE;
+
+}
+
+void Shutdown (int sig) {
+
+  fprintf (LogFile, "shutting down skyprobed\n");
+  fflush (LogFile);
+
+  if (unlink (PIDFile)) {
+    fprintf (LogFile, "error deleting PID File %s\n", PIDFile);
+    exit (1);
+  }   
+
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/nightd/src/StartUp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/src/StartUp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/src/StartUp.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "nightd.h"
+
+int StartUp () {
+
+  int i;
+  int night, NightTime;
+  char user[256], machine[256];
+  float time;
+  pid_t pid;
+
+  if (!SetPID (&pid, user, machine)) {
+    fprintf (stderr, "%s apparently running:\n\n", Program);
+    fprintf (stderr, "  machine: %s\n", machine);
+    fprintf (stderr, "  user: %s\n", user);
+    fprintf (stderr, "  PID: %d\n", pid);
+    fprintf (stderr, "  remove %s if %s has died unexpectedly\n", PIDFile, Program);
+    exit (1);
+  }
+
+  SetSignals ();
+
+  SuspendAction = FALSE;
+  NightTime = FALSE;
+
+  /* Event Loop */
+  while (1) {
+
+    if (SuspendAction) {
+      usleep (100000);
+      continue;
+    }
+
+    /* events happen at time % PERIOD */
+    WaitForPeriod ();
+
+    /* time should be UTCmidnight - UTCmidnight + 24 */
+    GetDateTime (DateStr, TimeStr, &time);
+    night = (time > NightStart) && (time < NightStop);
+
+    /* start of night */
+    if (night && !NightTime) {
+      NightTime = TRUE;
+      fprintf (LogFile, "beginning of night %s, running INIT commands\n", DateStr);
+      fflush (LogFile);
+      for (i = 0; InitCommand[i][0]; i++) {
+	DoCommand (InitCommand[i], "INIT");
+      }
+    }
+
+    /* end of night */
+    if (!night && NightTime) {
+      NightTime = FALSE;
+      fprintf (LogFile, "end of night %s, running DONE commands\n", DateStr);
+      fflush (LogFile);
+      for (i = 0; DoneCommand[i][0]; i++) {
+	DoCommand (DoneCommand[i], "DONE");
+      }
+    }
+
+    /* main event */
+    if (NightTime) {
+      for (i = 0; MainCommand[i][0]; i++) {
+	DoCommand (MainCommand[i], "MAIN");
+      }
+    }
+
+  }
+}
+
+/* 
+   SuspendAction - loop without operations, used for testing
+   NightStart    - time in hours of beginning of night
+   NightStop     - time in hours of end of night
+   NightTime     - current night / day state
+*/
Index: /branches/eam_branch_20080223/Ohana/src/nightd/src/misc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/src/misc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/src/misc.c	(revision 16632)
@@ -0,0 +1,278 @@
+# include "nightd.h"
+# include <time.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <unistd.h>
+# include <fcntl.h>
+
+char **getargs (char *);
+
+/* SetPID is always called outside of daemon loop, send errors to stderr */
+int SetPID (pid_t *Xpid, char *Xuser, char *Xmachine) {
+  
+  pid_t pid;
+  char *username, machine[256];
+  FILE *f;
+
+  f = fopen (PIDFile, "r");
+  if (f == (FILE *) NULL) { 
+
+    pid = getpid ();
+    username = getenv ("USER");
+    if (username == (char *) NULL) {
+      fprintf (stderr, "error getting username\n");
+      exit (2);
+    }
+    bzero (machine, 256);
+    if (gethostname (machine, 256)) {
+      fprintf (stderr, "error getting hostname\n");
+      exit (2);
+    }
+
+    f = fopen (PIDFile, "w");
+    if (f == (FILE *) NULL) { 
+      fprintf (stderr, "can't write to PID file %s\n", PIDFile);
+      exit (2);
+    }
+
+    fprintf (f, "PID:     %d\n", pid);
+    fprintf (f, "USER:    %-s\n", username);
+    fprintf (f, "MACHINE: %-s\n", machine);
+    fclose (f);
+    return (TRUE); 
+  }
+
+  fscanf (f, "%*s %d", Xpid);
+  fscanf (f, "%*s %s", Xuser);
+  fscanf (f, "%*s %s", Xmachine);
+  fclose (f);
+  return (FALSE);
+}
+
+/* date is the UT date at 09:00 local time for day starting at 12:00 */
+int GetDateTime (char *datestr, char *timestr, float *time) {
+
+  struct tm *local, *gmt;
+  struct timeval now;
+  time_t tsec, tref;
+  int dsec;
+  float hour;
+
+  gettimeofday (&now, (struct timezone *) NULL);
+  tsec = now.tv_sec;
+  local = localtime (&tsec);
+
+  sprintf (timestr, "%02dh%02dm", local[0].tm_hour, local[0].tm_min);
+  hour = local[0].tm_hour + local[0].tm_min / 60.0 + local[0].tm_sec / 3600.0;
+  if (hour < 12) hour += 24.0;
+
+  dsec = 3600.0*(33.0 - hour);
+  tref = tsec + dsec;
+
+  gmt = gmtime (&tref);
+
+  sprintf (datestr, "%04d%02d%02d", 1900 + gmt[0].tm_year, gmt[0].tm_mon + 1, gmt[0].tm_mday);
+  *time = hour;
+  
+  return (TRUE);
+}
+
+int WaitForPeriod () {
+
+  int Nsec;
+  struct timeval now;
+  
+  gettimeofday (&now, (struct timezone *) NULL);
+  Nsec = PERIOD - (now.tv_sec % PERIOD);
+  sleep (Nsec);
+  return (TRUE);
+}
+
+int pcommand (char *line, int timeout) {
+
+  int i, status, eof, done, pidstat, Nread, exit_good, exit_stat;
+  int rfd[2], wfd[2];
+  pid_t pid;
+  char buffer[0x4000];
+  char **arglist;
+
+  /* create pipes for communications */
+  status = pipe (rfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (1);
+  }
+  status = pipe (wfd);
+  if (status < 0) {
+    perror ("pipe");
+    return (1);
+  }
+
+  arglist = getargs (line);
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    dup2 (wfd[0], STDIN_FILENO);
+    dup2 (rfd[1], STDOUT_FILENO);
+    dup2 (rfd[1], STDERR_FILENO);
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ); 
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    status = execvp (arglist[0], arglist);
+    fprintf (stderr, "error starting command %s\n", arglist[0]);
+    exit (1);
+  }
+
+  eof = 0x04;
+  write (wfd[1], &eof, 1);
+  close (wfd[1]);
+ 
+  /* ok to close these here? */
+  close (rfd[1]);
+  close (wfd[0]);
+
+  fcntl (rfd[0], F_SETFL, O_NONBLOCK);
+
+  done = FALSE;
+  exit_good = exit_stat = FALSE;
+  for (i = 0; !done && (i < 10*timeout); i++) {
+    Nread = read (rfd[0], buffer, 0x4000);
+    if (Nread > 0) {
+      fwrite (buffer, 1, Nread, LogFile);
+    }
+    fflush (LogFile);
+    pidstat = waitpid (pid, &status, WNOHANG);
+    if (pidstat == pid) { 
+      done = TRUE;
+      exit_good = WIFEXITED (status);
+      exit_stat = WEXITSTATUS (status);
+    } else {
+      usleep (100000);
+    }
+  }
+  
+  if (i == 10*timeout) {
+    exit_good = FALSE;
+    fprintf (LogFile, "timeout on %s\n", arglist[0]);
+    fflush (LogFile);
+    fprintf (stderr, "timeout on %s\n", arglist[0]);
+    kill (pid, SIGKILL);
+
+    done = FALSE;
+    for (i = 0; !done && (i < 2*timeout); i++) {
+      pidstat = waitpid (pid, &status, WNOHANG);
+      if (pidstat == pid) { 
+	done = TRUE;
+      } else {
+	usleep (100000);
+      }
+    }
+  }
+  
+  close (rfd[0]);
+  freeargs (arglist);
+  if (exit_good) return (exit_stat);
+  return (1);
+}
+    
+/* split line into words by spaces, end with NULL */
+char **getargs (char *input) {
+
+  char **args, *line, *p, *e;
+  int Nargs, N, Nchar;
+
+  line = strcreate (input);
+  stripwhite (line);
+  p = line;
+
+  /* count words in line */
+  Nargs = 0;
+  while (*p != 0) {
+    for (; (*p != 0) && !isspace (*p); p++);
+    for (; isspace (*p); p++);
+    Nargs ++;
+  }
+  Nargs ++;
+  ALLOCATE (args, char *, Nargs);
+
+  /* extract words from line */
+  N = 0;
+  e = line;
+  p = line;
+  while (*p != 0) {
+    for (; (*e != 0) && !isspace (*e); e++);
+    Nchar = e - p;
+    ALLOCATE (args[N], char, Nchar + 1);
+    strncpy (args[N], p, Nchar);
+    args[N][Nchar] = 0;
+    p = e;
+    for (; isspace (*p); p++);
+    e = p;
+    N ++;
+  }
+  args[N] = (char *) NULL;
+  free (line);
+  return (args);
+}
+
+int freeargs (char **arglist) {
+
+  int i;
+
+  for (i = 0; arglist[i] != (char *) NULL; i++) {
+    free (arglist[i]);
+  }
+  free (arglist);
+  return (TRUE);
+}
+
+char *ExpandWords (char *line) {
+
+  int Nin, Nout, Ncpy, NBYTES;
+  char *p1, *p2, word[256], value[256];
+  char *outline;
+  
+  NBYTES = 256;
+  ALLOCATE (outline, char, NBYTES);
+  Nout = 0;
+  Nin  = 0;
+  while ((p1 = strchr (&line[Nin], '&')) != (char *) NULL) {
+    Ncpy = p1 - line - Nin;
+    if (Nout + Ncpy >= NBYTES) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES - 2);
+    }
+    memcpy (&outline[Nout], &line[Nin], Ncpy);
+    Nout += Ncpy;
+    
+    p1 ++;
+    for (p2 = p1; isalnum (*p2); p2++);
+    memcpy (word, p1, p2 - p1);
+    word[p2-p1] = 0;
+    Nin += Ncpy + 1 + p2 - p1;
+    
+    /* substitute value for word */
+    bzero (value, 256);
+    if (!strcasecmp (word, "DATE")) strcpy (value, DateStr);
+    if (!strcasecmp (word, "TIME")) strcpy (value, TimeStr);
+
+    Ncpy = strlen(value);
+    if (Nout + Ncpy >= NBYTES - 2) {
+      NBYTES = Nout + Ncpy + 256;
+      REALLOCATE (outline, char, NBYTES);
+    }    
+    memcpy (&outline[Nout], value, Ncpy);
+    Nout += Ncpy;
+  }
+  Ncpy = strlen(&line[Nin]);
+  if (Nout + Ncpy >= NBYTES - 2) {
+    NBYTES = Nout + Ncpy + 256;
+    REALLOCATE (outline, char, NBYTES);
+  }  
+  memcpy (&outline[Nout], &line[Nin], Ncpy);
+  Nout += Ncpy;
+  outline[Nout] = 0;
+  free (line);
+  return (outline);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/nightd/src/nightd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/nightd/src/nightd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/nightd/src/nightd.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "nightd.h"
+
+int main (int argc, char **argv) {
+
+  Program = filebasename (argv[0]);
+
+  LogFile = stderr;
+  ConfigInit (&argc, argv);  
+  
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: %s [mode]\n", Program);
+    fprintf (stderr, " mode = start, stop, status, config\n");
+    exit (2);
+  }
+
+  if (!strcasecmp(argv[1], "status")) GetStatus ();
+  if (!strcasecmp(argv[1], "config")) ResetConfig ();
+  if (!strcasecmp(argv[1], "stop"))   SendShutdown ();
+
+  /* execute in background, send output to logfile */
+  LogFile = fopen (logfile, "w");
+  if (LogFile == (FILE *) NULL) {
+    LogFile = stderr;
+    fprintf (LogFile, "can't open Log File %s, writing to stderr\n", logfile);
+  }
+  if (!strcasecmp(argv[1], "start"))  StartUp ();
+  /* if (!strcasecmp(argv[1], "test"))   TestMode (); */
+
+  fprintf (stderr, "invalid %s command %s\n", Program, argv[1]);
+  exit (2);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/.cvsignore	(revision 16632)
@@ -0,0 +1,2 @@
+lib
+bin
Index: /branches/eam_branch_20080223/Ohana/src/opihi/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/Makefile	(revision 16632)
@@ -0,0 +1,81 @@
+
+### this is the top-level makefile for the opihi collection of programs
+
+default: all
+
+### the include file dependencies need to be cleaned up still
+
+mana:     	 lib.data lib.shell cmd.basic cmd.data cmd.astro
+dimm:     	 lib.data lib.shell cmd.basic cmd.data cmd.astro
+dvo:      	 lib.data lib.shell cmd.basic cmd.data cmd.astro
+pantasks: 	 lib.data lib.shell cmd.basic cmd.data cmd.astro
+pantasks_server: lib.data lib.shell cmd.basic cmd.data cmd.astro
+pantasks_client: lib.data lib.shell cmd.basic cmd.data cmd.astro
+pclient:  	 lib.data lib.shell cmd.basic
+pcontrol: 	 lib.data lib.shell cmd.basic
+
+LIBS = lib.data lib.shell cmd.basic cmd.data cmd.astro
+
+PROGRAM = mana dvo pantasks pclient pcontrol
+SPECIAL = pantasks_client pantasks_server
+
+EXTRAS = dimm
+
+all:
+	for i in $(PROGRAM) $(SPECIAL); do make $$i || exit; done
+	make pantasks_client
+	make pantasks_server
+
+libs:
+	for i in $(LIBS); do make $$i || exit; done
+
+extras:
+	for i in $(EXTRAS); do make $$i || exit; done
+
+install:
+	for i in $(PROGRAM) $(SPECIAL); do make $$i.install || exit; done
+	make pantasks_client.install
+	make pantasks_server.install
+
+extras-install:
+	for i in $(EXTRAS); do make $$i.install || exit; done
+
+clean:
+	for i in $(PROGRAM) $(SPECIAL) $(EXTRAS) $(LIBS); do make $$i.clean || exit; done
+
+libs-uninstall:
+	for i in $(LIBS); do make $$i.uninstall || exit; done
+
+dist: clean
+	for i in $(PROGRAM) $(SPECIAL) $(EXTRAS) $(LIBS); do make $$i.dist || exit; done
+	rm -rf bin
+	rm -rf lib
+
+#############################################################
+
+pantasks_client pantasks_server:
+	if [ -d pantasks ]; then (cd pantasks && make $@); fi
+
+pantasks_client.install: pantasks_client
+	if [ -d pantasks ]; then (cd pantasks && make $@); fi
+
+pantasks_server.install: pantasks_server
+	if [ -d pantasks ]; then (cd pantasks && make $@); fi
+
+$(PROGRAM) $(LIBS) $(EXTRAS):
+	if [ -d "$@" ]; then (cd $@ && make); fi
+
+%.install:
+	if [ -d "$*" ]; then make $*; fi
+	if [ -d "$*" ]; then (cd $* && make install); fi
+
+%.clean:
+	if [ -d "$*" ]; then (cd $* && make clean); fi
+
+%.dist:
+	if [ -d "$*" ]; then (cd $* && make dist); fi
+
+%.uninstall:
+	if [ -d "$*" ]; then (cd $* && make uninstall); fi
+
+.PHONY: $(PROGRAM) $(LIBS) pantasks_server pantasks_client
Index: /branches/eam_branch_20080223/Ohana/src/opihi/Makefile.Common
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/Makefile.Common	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/Makefile.Common	(revision 16632)
@@ -0,0 +1,88 @@
+
+# utilities #################################################
+# .SUFFIXES: .$(ARCH).o
+
+BASE_CFLAGS   =	$(CFLAGS)
+BASE_CPPFLAGS =	$(CPPFLAGS) -I$(INC) -I$(DESTINC) $(INCDIRS) -D$(ARCH)
+BASE_LDFLAGS  = $(LDFLAGS) -L$(LIB) -L$(DESTLIB) $(LIBDIRS) $(LIBFLAGS)
+
+%.c : %.c.in
+	sed "s|@DATADIR@|$(DATA)|" $< > $@
+
+%.$(ARCH).o : %.c
+	$(CC) $(FULL_CFLAGS) $(FULL_CPPFLAGS) -c $< -o $@
+
+$(BIN)/%.$(ARCH):
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $(FULL_CFLAGS) -o $@ $^ $(FULL_LDFLAGS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH) 
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(LIB)/%.$(ARCH).a:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	ar rcv $@ $^ 
+	$(RANLIB) $@
+	@echo "compiled library $*"
+	@echo ""
+
+$(DESTLIB)/%.a: $(LIB)/%.$(ARCH).a
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f $@
+	cp $< $@
+
+$(LIB)/%.$(ARCH).so:
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $@
+	gcc -shared -Wl,-soname,$*.so -o $@ $^ -lc
+
+$(DESTLIB)/%.so: $(LIB)/%.$(ARCH).so
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f $@
+	cp $< $@
+
+lib%.clean:
+	rm -f $(LIB)/lib$*.$(ARCH).a
+	rm -f $($*)
+	@echo ""
+
+%.help:
+	@echo "installing help files for $*"
+	@if [ ! -d $(DATA)/help ]; then mkdir -p $(DATA)/help; fi
+	@rm -f $(HOME)/$*/help/*~
+	@rm -f $(HOME)/$*/help/#*
+	@for i in `find $(HOME)/$*/help -maxdepth 1 -type f`; do cp -f $$i $(DATA)/help; done
+
+%.modules:
+	@echo "installing modules for $*"
+	@if [ ! -d $(DATA)/modules ]; then mkdir -p $(DATA)/modules; fi
+	@if [ ! -d $(HOME)/modules/$* ]; then echo "no modules for $*"; fi
+	@if [   -d $(HOME)/modules/$* ]; then rm -f $(HOME)/modules/$*/*~; fi
+	@if [   -d $(HOME)/modules/$* ]; then rm -f $(HOME)/modules/$*/#*; fi
+	@if [   -d $(HOME)/modules/$* ]; then for i in `find $(HOME)/modules/$* -name CVS -prune -o -type f -print`; do cp -f $$i $(DATA)/modules; done; fi
+
+%.clean:
+	rm -f $(BIN)/$*.$(ARCH)
+	@echo ""
+
+clean:
+	rm -f $(BIN)/*.$(ARCH)
+	rm -f $(LIB)/*.$(ARCH).a
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+dist: clean
+	rm -rf $(BIN)/*
+	rm -rf $(LIB)/*
+
+clean-help:
+	@if [ ! -d $(DATA)/help ]; then mkdir -p $(DATA)/help; fi
+	rm -f $(DATA)/help/*
Index: /branches/eam_branch_20080223/Ohana/src/opihi/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/Makefile	(revision 16632)
@@ -0,0 +1,82 @@
+default: libastrocmd
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SRC     =       $(HOME)/cmd.astro
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+# astro user commands ########################
+srcs = \
+$(SRC)/init.$(ARCH).o             \
+$(SRC)/biassub.$(ARCH).o	   \
+$(SRC)/cgrid.$(ARCH).o		   \
+$(SRC)/coords.$(ARCH).o	   \
+$(SRC)/cplot.$(ARCH).o		   \
+$(SRC)/csystem.$(ARCH).o	   \
+$(SRC)/ctimes.$(ARCH).o	   \
+$(SRC)/cval.$(ARCH).o		   \
+$(SRC)/czplot.$(ARCH).o	   \
+$(SRC)/drizzle.$(ARCH).o	   \
+$(SRC)/flux.$(ARCH).o		   \
+$(SRC)/fixwrap.$(ARCH).o	   \
+$(SRC)/gauss.$(ARCH).o		   \
+$(SRC)/getvel.$(ARCH).o	   \
+$(SRC)/getlst.$(ARCH).o	   \
+$(SRC)/medianmap.$(ARCH).o	   \
+$(SRC)/mkgauss.$(ARCH).o	   \
+$(SRC)/multifit.$(ARCH).o	   \
+$(SRC)/objload.$(ARCH).o	   \
+$(SRC)/outline.$(ARCH).o	   \
+$(SRC)/polar.$(ARCH).o		   \
+$(SRC)/precess.$(ARCH).o	   \
+$(SRC)/profile.$(ARCH).o	   \
+$(SRC)/region.$(ARCH).o	   \
+$(SRC)/rotcurve.$(ARCH).o	   \
+$(SRC)/scale.$(ARCH).o		   \
+$(SRC)/sexigesimal.$(ARCH).o	   \
+$(SRC)/spec.$(ARCH).o		   \
+$(SRC)/star.$(ARCH).o		   \
+$(SRC)/transform.$(ARCH).o        \
+$(SRC)/imsub.$(ARCH).o		   \
+$(SRC)/imfit.$(ARCH).o		   \
+$(SRC)/imfit-fgauss.$(ARCH).o	   \
+$(SRC)/imfit-pgauss.$(ARCH).o	   \
+$(SRC)/imfit-pgauss-psf.$(ARCH).o	   \
+$(SRC)/imfit-qgauss.$(ARCH).o	   \
+$(SRC)/imfit-qgauss-psf.$(ARCH).o	   \
+$(SRC)/imfit-sgauss.$(ARCH).o	   \
+$(SRC)/imfit-sgauss-psf.$(ARCH).o	   \
+$(SRC)/imfit-qfgauss.$(ARCH).o	   \
+$(SRC)/imfit-qrgauss.$(ARCH).o	   
+
+# dependancy rules for include files ########################
+incs = \
+$(INC)/opihi.h \
+$(INC)/external.h \
+$(INC)/shell.h \
+$(INC)/dvomath.h \
+$(INC)/convert.h \
+$(INC)/display.h 
+
+$(srcs): $(incs)
+
+$(LIB)/libastrocmd.$(ARCH).a: $(srcs)
+$(LIB)/libastrocmd.$(ARCH).$(DLLTYPE): $(srcs)
+
+$(DESTLIB)/libastrocmd.a: $(LIB)/libastrocmd.$(ARCH).a
+$(DESTLIB)/libastrocmd.$(DLLTYPE): $(LIB)/libastrocmd.$(ARCH).$(DLLTYPE)
+
+libastrocmd: $(DESTLIB)/libastrocmd.a $(DESTLIB)/libastrocmd.$(DLLTYPE)
+
+uninstall:
+	rm -f $(DESTLIB)/libastrocmd.a
+	rm -f $(DESTLIB)/libastrocmd.$(DLLTYPE)
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/biassub.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/biassub.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/biassub.c	(revision 16632)
@@ -0,0 +1,126 @@
+# include "astro.h"
+
+int biassub (int argc, char **argv) {
+  
+  int i, j, k, N, dir, nlong, nwide, start;
+  int sx, sy, nx, ny, NX, NY, NoVector, Nval;
+  float *V, *DV, dV, *vect, *segment, val;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  xvec = yvec = NULL;
+  NoVector = TRUE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    NoVector = FALSE;
+    remove_argument (N, &argc, argv);
+    if ((xvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+    if ((yvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: biassub <buffer> sx sy nx ny dir [-v N V]\n");
+    gprint (GP_ERR, "  optional storage of vector and sequence in N and V\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+  dir = atof (argv[6]);
+  if ((dir != 0) && (dir != 1)) {
+    gprint (GP_ERR, " dir must be either 0 (x) or 1 (y)\n");
+    return (FALSE);
+  }
+  if (dir) {
+    start = sy;
+    nwide = nx;
+    nlong = ny;
+  } else {
+    start = sx;
+    nwide = ny;
+    nlong = nx;
+  }    
+  gprint (GP_LOG, "start: %d %d  size: %d %d\n", sx, sy, nx, ny);
+
+    if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (vect, float, nlong);
+  ALLOCATE (segment, float, nwide);
+
+  NX = buf[0].matrix.Naxis[0];
+  NY = buf[0].matrix.Naxis[1];
+  if (dir) {
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*NX + sx; 
+      for (i = 0; i < nx; i++, V++) {
+	segment[i] = *V;
+      }
+      fsort (segment, nwide);
+      val = Nval = 0;
+      for (k = 0.25*nwide; k <=0.75*nwide; k++) {
+	val += segment[k];
+	Nval ++;
+      }
+      vect[j-sy] = val / Nval;
+    }
+  } else {
+    for (i = 0; i < nx; i++) {
+      V = (float *)(buf[0].matrix.buffer) + sy*NX + sx + i; 
+      for (j = 0; j < ny; j++, V+=NX) {
+	segment[j] = *V;
+      }
+      fsort (segment, nwide);
+      val = Nval = 0;
+      for (k = 0.25*nwide; k <=0.75*nwide; k++) {
+	val += segment[k];
+	Nval ++;
+      }
+      vect[i] = val / Nval;
+    }
+  }
+
+  if (!NoVector) {
+    xvec[0].Nelements = yvec[0].Nelements = nlong;
+    REALLOCATE (xvec[0].elements, float, nlong);
+    REALLOCATE (yvec[0].elements, float, nlong);
+    for (i = 0; i < nlong; i++) {
+      xvec[0].elements[i] = i + start;
+      yvec[0].elements[i] = vect[i];
+    }
+  }
+
+  if (dir) {
+    /* here we run all the way across in X for the defined Y range */
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*NX; 
+      dV = vect[j];
+      for (i = 0; i < NX; i++, V++) {
+	*V -= dV;
+      }
+    }
+  } else {
+    /* here we run all the way across in Y for the defined X range */
+    for (j = 0; j < NY; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*NX + sx; 
+      DV = vect;
+      for (i = 0; i < nx; i++, V++, DV++) {
+	*V -= *DV;
+      }
+    }
+  }
+
+  free (segment);
+  free (vect);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cgrid.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cgrid.c	(revision 16632)
@@ -0,0 +1,399 @@
+# include "astro.h"
+# define CHECKELEMENTS \
+  if (N == NELEMENTS) { \
+    NELEMENTS +=200; \
+    REALLOCATE (Xvec.elements, float, NELEMENTS); \
+    REALLOCATE (Yvec.elements, float, NELEMENTS); \
+  }
+
+int cgrid (int argc, char **argv) {
+  
+  double range, lrange, factor, mantis, power, fmantis;
+  double firstRA, firstDEC, minorRA, minorDEC;
+  double r, d, dR, dD, D;
+  double x, y;
+  Vector Xvec, Yvec;
+  int kapa, NorthPole, SouthPole, N, OnPic, LOnPic, status, NELEMENTS, First;
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: cgrid [style]\n");
+    return (FALSE);
+  }
+
+  /* are we plotting one of the poles? */
+  NorthPole = SouthPole = FALSE;
+  status = RD_to_XY (&x, &y, 0.0, 90.0, &graphmode.coords);
+  if ((x >= graphmode.xmin) && (x <= graphmode.xmax) && 
+      (y >= graphmode.ymin) && (y <= graphmode.ymax) && status)
+    NorthPole = TRUE;
+  status = RD_to_XY (&x, &y, 0.0, -90.0, &graphmode.coords);
+  if ((x >= graphmode.xmin) && (x <= graphmode.xmax) && 
+      (y >= graphmode.ymin) && (y <= graphmode.ymax) && status)
+    SouthPole = TRUE;
+
+  /* set spacings for RA */
+  minorRA = minorDEC = 0.1;
+  range = MIN (fabs(graphmode.xmax-graphmode.xmin), fabs(graphmode.ymax-graphmode.ymin));
+  if (NorthPole || SouthPole) range = 360;
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    minorRA = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    minorRA = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    minorRA = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    minorRA = 0.5 * power;
+  }
+  dR = range / 100.0;
+  /* set spacings for DEC */
+  range = MIN (fabs(graphmode.xmax-graphmode.xmin), fabs(graphmode.ymax-graphmode.ymin));
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    minorDEC = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    minorDEC = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    minorDEC = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    minorDEC = 0.5 * power;
+  }
+  dD = range / 100.0;
+
+  /* choose a starting point */
+  if ((int)(graphmode.coords.crval1/minorRA) == (graphmode.coords.crval1/minorRA)) {
+    firstRA = graphmode.coords.crval1;
+  } else {
+    firstRA = minorRA + minorRA*((int)(graphmode.coords.crval1/minorRA));
+  }
+  if ((int)(graphmode.coords.crval2/minorDEC) == (graphmode.coords.crval2/minorDEC)) {
+    firstDEC = graphmode.coords.crval2;
+  } else {
+    firstDEC = minorDEC + minorDEC*((int)(graphmode.coords.crval2/minorDEC));
+  }
+  if (SouthPole) firstDEC = -90;
+  if (NorthPole) firstDEC = 90;
+  
+  /* prepare vectors to hold data */
+  NELEMENTS = 200;
+  ALLOCATE (Xvec.elements, float, NELEMENTS);
+  ALLOCATE (Yvec.elements, float, NELEMENTS);
+  N = 0;
+  
+  /***  do consecutive RA lines, first increasing **/
+  OnPic = TRUE;
+  for (r = firstRA; (r <= firstRA + 180) && (OnPic); r += minorRA) {
+    /* first, DEC increasing */
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    First = TRUE;
+    for (d = firstDEC; (d < 90 + dD) && (LOnPic || NorthPole || SouthPole); d += dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, DEC decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (d = firstDEC; (d > -90 - dD) && (LOnPic || NorthPole || SouthPole); d -= dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      } 
+    }
+  }
+
+  /***  do consecutive RA lines, decreasing **/
+  OnPic = TRUE;
+  for (r = firstRA; (r >=  firstRA - 180) && (OnPic); r -= minorRA) {
+    /* first, DEC increasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    for (d = firstDEC; (d < 90 + dD) && (LOnPic || NorthPole || SouthPole); d += dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, DEC decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (d = firstDEC; (d > -90 - dD) && (LOnPic || NorthPole || SouthPole); d -= dD) {
+      D = MAX (-90, MIN(90, d));
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+  }
+
+  /***  do consecutive DEC lines, first increasing **/
+  OnPic = TRUE;
+  for (d = firstDEC; (d < 90 + dD) && (OnPic); d += minorDEC) {
+    D = MAX (-90, MIN(90, d));
+    /* first, RA increasing */
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    First = TRUE;
+    for (r = firstRA; (r < firstRA + 180) && (LOnPic || NorthPole || SouthPole); r += dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, RA decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (r = firstRA; (r > firstRA - 180) && (LOnPic || NorthPole || SouthPole); r -= dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+  }
+
+  /***  do consecutive DEC lines, decreasing **/
+  OnPic = TRUE;
+  for (d = firstDEC; (d > -90 - dD) && (OnPic); d -= minorDEC) {
+    D = MAX (-90, MIN(90, d));
+    /* first, RA increasing */
+    LOnPic = TRUE;
+    OnPic = FALSE;
+    First = TRUE;
+    for (r = firstRA; (r < firstRA + 180) && (LOnPic || NorthPole || SouthPole); r += dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+    /* next, RA decreasing */
+    First = TRUE;
+    LOnPic = TRUE;
+    for (r = firstRA; (r > firstRA - 180) && (LOnPic || NorthPole || SouthPole); r -= dR) {
+      status = fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, D, &graphmode.coords);
+      /*
+      if ((fabs(Xvec.elements[N] - Xvec.elements[N-1]) > 10) && (fabs(Yvec.elements[N] - Yvec.elements[N-1]) > 10))
+	First = TRUE;
+	*/
+      if ((Xvec.elements[N] >= graphmode.xmin) && (Xvec.elements[N] <= graphmode.xmax) && 
+	  (Yvec.elements[N] >= graphmode.ymin) && (Yvec.elements[N] <= graphmode.ymax) && status) {
+	N++;
+	CHECKELEMENTS;
+	OnPic = TRUE;
+	if (!First) {
+	  Xvec.elements[N] = Xvec.elements[N-1];
+	  Yvec.elements[N] = Yvec.elements[N-1];
+	  N++;
+	  CHECKELEMENTS;
+	} else {
+	  if (N > 1) {
+	    Xvec.elements[N-2] = Xvec.elements[N-1];
+	    Yvec.elements[N-2] = Yvec.elements[N-1];
+	    N--;
+	  }
+	  First = FALSE;
+	}
+      } else {
+	LOnPic = FALSE;
+	First = TRUE;
+      }
+    }
+  }
+  
+  /* send the line segments as connect-points */
+  Xvec.Nelements = Yvec.Nelements = N;
+  graphmode.style = 2; /* points */
+  graphmode.ptype = 100; /* connect a pair */
+  graphmode.etype = 0;
+  PlotVectorPair (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/coords.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/coords.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/coords.c	(revision 16632)
@@ -0,0 +1,109 @@
+# include "astro.h"
+
+enum {NONE, SKY, PIXEL, VECTOR, SCALAR};
+
+int coords (int argc, char **argv) {
+
+  int i, mode, form, N, Quiet;
+  double Xin, Yin, Xout, Yout;
+  char *MOSAIC;
+  Coords coords, moscoords;
+  Buffer *buf, *mosbuffer;
+  Vector *xvec, *yvec;
+
+  MOSAIC = NULL;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    remove_argument (N, &argc, argv);
+    MOSAIC = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  form = NONE;
+  mode = NONE;
+  if ((N = get_argument (argc, argv, "-p"))) {
+    remove_argument (N, &argc, argv);
+    mode = SKY;
+  }
+  if ((N = get_argument (argc, argv, "-c"))) {
+    if (mode == SKY) goto syntax;
+    remove_argument (N, &argc, argv);
+    mode = PIXEL;
+  }
+  if (mode == NONE) goto syntax;
+  if (argc != 4) goto syntax;
+
+  if (SelectScalar (argv[2], &Xin)) {
+    if (!SelectScalar (argv[3], &Yin)) {
+      gprint (GP_ERR, "syntax error: mixed vector and scalar?\n");
+      return (FALSE);
+    }
+    form = SCALAR;
+  } else {
+    if ((xvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((yvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    if (xvec[0].Nelements != yvec[0].Nelements) {
+      fprintf (stderr, "mis-matched vector lengths\n");
+      return (FALSE);
+    }
+    form = VECTOR;
+  }      
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) goto escape;
+  GetCoords (&coords, &buf[0].header);
+  if (!strcmp(&coords.ctype[4], "-WRP")) {
+    if (MOSAIC == NULL) {
+      gprint (GP_ERR, "must supply mosaic for WRP coords\n");
+      return (FALSE);
+    }
+    if ((mosbuffer = SelectBuffer (MOSAIC, OLDBUFFER, TRUE)) == NULL) goto escape;
+    GetCoords (&moscoords, &mosbuffer[0].header);
+    RegisterMosaic (&moscoords);
+  }
+  
+  if (form == SCALAR) {
+    if (mode == SKY) {
+      XY_to_RD (&Xout, &Yout, Xin, Yin, &coords);
+      if (!Quiet) gprint (GP_LOG, "%10.6f %10.6f\n", Xout, Yout);
+      set_variable ("RA", Xout);
+      set_variable ("DEC", Yout);
+      return (TRUE);
+    }
+    if (mode == PIXEL) {
+      RD_to_XY (&Xout, &Yout, Xin, Yin, &coords);
+      if (!Quiet) gprint (GP_LOG, "%7.2f %7.2f\n", Xout, Yout);
+      set_variable ("Xc", Xout);
+      set_variable ("Yc", Yout);
+      return (TRUE);
+    }
+  }
+  if (mode == SKY) {
+    for (i = 0; i < xvec[0].Nelements; i++) {
+      fXY_to_RD (&xvec[0].elements[i], &yvec[0].elements[i], xvec[0].elements[i], yvec[0].elements[i], &coords);
+    }
+    return (TRUE);
+  }
+  if (mode == PIXEL) {
+    for (i = 0; i < xvec[0].Nelements; i++) {
+      fRD_to_XY (&xvec[0].elements[i], &yvec[0].elements[i], xvec[0].elements[i], yvec[0].elements[i], &coords);
+    }
+    return (TRUE);
+  }
+  return (FALSE);
+
+ syntax:
+  gprint (GP_ERR, "USAGE: coords [buffer] (-c R D) | (-p X Y)\n");
+  gprint (GP_ERR, "only one of -p or -c can be used\n");
+ escape:
+  if (MOSAIC != NULL) free (MOSAIC);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cplot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cplot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cplot.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "astro.h"
+
+int cplot (int argc, char **argv) {
+  
+  int i, kapa, Npts, status, leftside;
+  float *x, *y, *r, *d, Rmin, Rmax, Rmid;
+  Vector Xvec, Yvec, *xvec, *yvec;
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: cplot <ra> <dec> [style]\n");
+    return (FALSE);
+  }
+
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+  Rmid = 0.5*(Rmin + Rmax);
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors are not the same length\n");
+    return (FALSE);
+  }
+
+  ALLOCATE (Xvec.elements, float, xvec[0].Nelements);
+  ALLOCATE (Yvec.elements, float, xvec[0].Nelements);
+    
+  Xvec.Nelements = xvec[0].Nelements;
+  Yvec.Nelements = xvec[0].Nelements;
+  
+  r = xvec[0].elements;
+  d = yvec[0].elements;
+  x = Xvec.elements;
+  y = Yvec.elements;
+  
+  Npts = 0;
+  for (i = 0; i < Xvec.Nelements; i++, r++, d++) {
+    while (*r < Rmin) *r += 360.0;
+    while (*r > Rmax) *r -= 360.0;
+
+    // for pair-by-pair connections, check on second point if we straddle the back midline
+    if ((graphmode.ptype == 100) && (i % 2)) {
+      leftside = (r[-1] < Rmid); // if first of the pair is left, second must be as well
+      if ( leftside && (r[0] > Rmid + 90)) { r[0] -= 360.0; }
+      if (!leftside && (r[0] < Rmid - 90)) { r[0] += 360.0; }
+    }
+    status = fRD_to_XY (x, y, *r, *d, &graphmode.coords);
+
+    // if we fail on one of the points, drop the corresponding pair
+    if (!status) {
+      if (graphmode.ptype == 100) {
+	if (i % 2) {
+	  // for odd points, skip previous also
+	  x--;
+	  y--;
+	  Npts--;
+	} else {
+	  // for even points, skip previous also
+	  i++;
+	  r++;
+	  d++;
+	}
+      }
+      continue;
+    }
+    x++;
+    y++;
+    Npts++;
+  }
+  Xvec.Nelements = Npts;
+
+  graphmode.etype = 0;
+  PlotVectorPair (kapa, Npts, Xvec.elements, Yvec.elements, &graphmode);
+  
+  free (Xvec.elements);
+  free (Yvec.elements);
+    
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/csystem.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/csystem.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/csystem.c	(revision 16632)
@@ -0,0 +1,141 @@
+# include "astro.h"
+
+int csystem (int argc, char **argv) {
+
+  /* USAGE: csystem [C/G/E/H] [C/G/E/H] [epoch] */
+  int i;
+  double X, Y, Xo, xo, phi, T;
+  double sin_x, sin_y, cos_x, cos_y;
+  float *x, *y;
+  struct timeval now;
+  struct tm *local;
+  Vector *xvec, *yvec;
+   
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: csystems [C/G/E/H] [C/G/E/H] X Y\n");
+    return (FALSE);
+  }
+
+  Xo = xo = phi = 0;
+  switch (argv[1][0]) {
+  case 'C':
+    switch (argv[2][0]) {
+    case 'C': 
+      gprint (GP_ERR, "same coordinate system\n");
+      return (TRUE);
+      break;
+    case 'G':
+      phi = -62.6*RAD_DEG;
+      Xo = 282.25;
+      xo = 33;
+      break;
+    case 'E':
+      gettimeofday (&now, (struct timezone *) NULL);
+      local = localtime (&now.tv_sec);
+      T = local[0].tm_year / 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': 
+      gettimeofday (&now, (struct timezone *) NULL);
+      local = localtime (&now.tv_sec);
+      T = local[0].tm_year / 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':
+      gprint (GP_ERR, "error: conversions between galactic and ecliptic not implemented\n");
+      return (FALSE);
+      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':
+      gprint (GP_ERR, "error: conversions between galactic and ecliptic not implemented\n");
+      return (FALSE);
+      gettimeofday (&now, (struct timezone *) NULL);
+      local = localtime (&now.tv_sec);
+      T = local[0].tm_year / 100.0;
+      phi = -1*(23.452294 - 0.013013*T - 0.000001639*T*T + 0.000000503*T*T*T);
+      Xo = xo = 0.0;
+      break;
+    }
+  }
+ 
+  Xo *= RAD_DEG;
+
+  if (SelectScalar (argv[3], &X)) {
+      if (!SelectScalar (argv[4], &Y)) return (FALSE);
+      
+      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;
+      
+      X = (DEG_RAD * atan2 (sin_x, cos_x) + xo + 360);
+      
+      while (X >= 360.0)
+	  X -= 360;
+      Y = DEG_RAD * atan2 (sin_y, cos_y);
+
+      gprint (GP_LOG, "%10.6f %10.6f\n", X, Y);
+      return (TRUE);
+  }
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[3], argv[4]);
+    return (FALSE);
+  }
+  
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+
+  for (i = 0; i < xvec[0].Nelements; i++, x++, y++) {
+    X = *x*RAD_DEG;
+    Y = *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;
+    
+    X = (DEG_RAD * atan2 (sin_x, cos_x) + xo + 360);
+    
+    while (X >= 360.0)
+      X -= 360;
+    Y = DEG_RAD * atan2 (sin_y, cos_y);
+    *x = X;
+    *y = Y;
+  }
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/ctimes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/ctimes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/ctimes.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "astro.h"
+
+int ctimes (int argc, char **argv) {
+
+  int Reference, TimeFormat, N;
+  double value;
+  time_t time, TimeReference;
+  char *date, *Variable;
+
+  Variable = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    Variable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: ctimes [-ref (value) / -abs (date)] [-var name]\n");
+    return (FALSE);
+  }
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  Reference = FALSE;
+  if (!strcmp (argv[1], "-ref")) Reference = TRUE;
+
+  if (Reference) {
+
+    value = atof (argv[2]);
+    time = TimeRef (value, TimeReference, TimeFormat);
+    date = ohana_sec_to_date (time);
+    
+    if (Variable != (char *) NULL) {
+      set_str_variable (Variable, date);
+      free (Variable);
+    } else {
+      gprint (GP_ERR, "time: %s\n", date);
+    }
+
+    free (date);
+    return (TRUE);
+
+  } else {
+
+    if (strcmp (argv[1], "-abs")) {
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+
+    if (!ohana_str_to_time (argv[2], &time)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    
+    value = TimeValue (time, TimeReference, TimeFormat);
+    
+    if (Variable != (char *) NULL) {
+      set_variable (Variable, value);
+      free (Variable);
+      return (TRUE);
+    }
+    gprint (GP_ERR, "time: %f\n", value);
+    return (TRUE);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cval.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cval.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/cval.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "astro.h"
+
+int cval (int argc, char **argv) {
+  
+  int i, j, Nx;
+  int sx, sy, nx, ny, xo, yo, dx, dy;
+  float *V, cval, val, sn, sky;
+  Buffer *buf;
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: cval <buffer> x y dx dy sky\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  xo = atof (argv[2]);
+  yo = atof (argv[3]);
+  dx = atof (argv[4]);
+  dy = atof (argv[5]);
+  sky = atof (argv[6]);
+
+  sx = xo - dx;
+  sy = yo - dy;
+  nx = 2*dx + 1;
+  ny = 2*dy + 1;
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+
+  V = (float *)buf[0].matrix.buffer;
+  Nx = buf[0].matrix.Naxis[0];
+  val = V[xo + yo*Nx];
+
+  sn = 0;
+  cval = 0;
+  for (j = sy; j < sy + ny; j++) {
+    for (i = sx; i < sx + nx; i++) {
+      cval += (val - V[i + j*Nx]) / sqrt(V[i + j*Nx]);
+      sn += SQ (V[i + j*Nx] - sky) / V[i + j*Nx];
+    }
+  }
+
+  gprint (GP_ERR, "cval: %f  sn: %f\n", cval, sqrt(sn));
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/czplot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/czplot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/czplot.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "astro.h"
+
+int czplot (int argc, char **argv) {
+  
+  int i, kapa, Npts;
+  double min, range, Rmin, Rmax;
+  float *in, *out, *r, *d, *x, *y;
+  Vector Xvec, Yvec, Zvec, *xvec, *yvec, *zvec;
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: czplot <x> <y> <z> min max\n");
+    return (FALSE);
+  }
+
+  min = atof(argv[4]);
+  range = atof(argv[5]) - min;
+  Rmin = graphmode.coords.crval1 - 180.0;
+  Rmax = graphmode.coords.crval1 + 180.0;
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  if (xvec[0].Nelements != zvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[1], argv[3]);
+    return (FALSE);
+  }
+  Xvec.Nelements = xvec[0].Nelements;
+  Yvec.Nelements = xvec[0].Nelements;
+  Zvec.Nelements = zvec[0].Nelements;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+  
+  r   = xvec[0].elements;
+  d   = yvec[0].elements;
+  in  = zvec[0].elements;
+  x   = Xvec.elements;
+  y   = Yvec.elements;
+  out = Zvec.elements;
+  for (i = 0; i < Zvec.Nelements; i++, in++, out++, r++, d++, x++, y++) {
+    *out = MIN (1.0, MAX (0.01, (*in - min) / range));
+    while (*r < Rmin) *r += 360.0;
+    while (*r > Rmax) *r -= 360.0;
+    fRD_to_XY (x, y, *r, *d, &graphmode.coords);
+  }
+
+  graphmode.style = 2;
+  graphmode.size = -1; /* point size determined by Zvec */
+  graphmode.etype = 0;
+  Npts = Xvec.Nelements;
+  PlotVectorTriplet (kapa, Npts, Xvec.elements, Yvec.elements, Zvec.elements, &graphmode);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (Zvec.elements);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/drizzle.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/drizzle.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/drizzle.c	(revision 16632)
@@ -0,0 +1,302 @@
+# include "astro.h"
+
+/*** needs mosaic astrometry ***/
+
+static double XO, XX, XY;
+static double YO, YX, YY;
+static int ZERO;
+
+static int ROTATE;
+static double rot_phi, rot_alpha, rot_delta;
+static double rot_cdp, rot_sdp;
+
+int map_output_to_input (int Npix, double df);
+int map_input_to_output (int Npix, double df);
+int set_linear_terms (Coords *in, Coords *out, int i, int j, int Npix);
+void apply_terms (double *Xout, double *Yout, double Xin, double Yin);
+
+Coords coords_in, coords_out;
+Buffer *in, *out, *wt, *mask;
+
+int drizzle (int argc, char **argv) {
+
+  int Nlinear, Np, N;
+  double scale_in, scale_out, df;
+
+  ZERO = FALSE;
+  if ((N = get_argument (argc, argv, "-zero"))) {
+    ZERO = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  ROTATE = FALSE;
+  if ((N = get_argument (argc, argv, "-roll"))) {
+    /* -roll phi alpha_pole delta_pole */
+    /* XXX need to clarify the meaning of phi, alpha, delta */
+    ROTATE = TRUE;
+    remove_argument (N, &argc, argv);
+    rot_phi   = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    rot_alpha = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    rot_delta = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+
+    rot_cdp = cos(RAD_DEG*rot_delta);
+    rot_sdp = sin(RAD_DEG*rot_delta);
+  }
+
+  mask = NULL;
+  if ((N = get_argument (argc, argv, "-mask"))) {
+    remove_argument (N, &argc, argv);
+    if ((mask = SelectBuffer (argv[N], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: transform <from> <to> <weight> (Nlinear)\n");
+    gprint (GP_ERR, "  output buffer must exist with target astrometry header\n");
+    gprint (GP_ERR, "  Nlinear is the pixel scale for linear astrometric transformation\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((wt  = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Nlinear = atoi (argv[4]);
+
+  GetCoords (&coords_in, &in[0].header);
+  GetCoords (&coords_out, &out[0].header);
+
+  /* for the moment, disable WRP / DIS */
+  if (!strcmp(&coords_in.ctype[4], "-WRP") || !strcmp(&coords_out.ctype[4], "-WRP")) {
+    gprint (GP_ERR, "WRP mode not implemented for astrom\n");
+    return (FALSE);
+  }
+  
+  scale_in = sqrt(fabs(coords_in.cdelt1*coords_in.cdelt2*(coords_in.pc1_1*coords_in.pc2_2 - coords_in.pc1_2*coords_in.pc2_1)));
+  scale_out = sqrt(fabs(coords_out.cdelt1*coords_out.cdelt2*(coords_out.pc1_1*coords_out.pc2_2 - coords_out.pc1_2*coords_out.pc2_1)));
+  
+  gprint (GP_ERR, "%f - %f\n", scale_in, scale_out);
+
+  if (scale_in > scale_out) {
+    Np = MAX (1, 3*scale_out / scale_in);
+    df = 1.0 / Np;
+    map_output_to_input (Nlinear, df);
+  } else {
+    Np = MAX (1, 3*scale_in / scale_out);
+    df = 1.0 / Np;
+    map_input_to_output (Nlinear, df);
+  }
+  return (TRUE);
+}
+
+/* mode 1: input pixels >> output pixels: loop over output pixels */
+/* mode 2: input pixels << output pixels: loop over input pixels */
+/* mode 3: input pixels ~= output pixels: drizzle input to output */
+
+/* loop over the input pixels, map input output image */
+int map_output_to_input (int Npix, double df) {
+
+  int i, j, Ni, No, Nx, Ny, nx, ny;
+  float *Vin, *Vout, *Vwt, *Vmk;
+  double x, y, X, Y;
+
+  /* loop over output pixels */
+  /* set up pointers for buffers */
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Vwt  = (float *) wt[0].matrix.buffer;
+  Vmk  = NULL;
+  Vmk = (mask == NULL) ? NULL : (float *) mask[0].matrix.buffer;
+
+  nx = in[0].header.Naxis[0];
+  ny = in[0].header.Naxis[1];
+  Nx = out[0].header.Naxis[0];
+  Ny = out[0].header.Naxis[1];
+
+  if (ZERO) {
+    bzero (Vout, Nx*Ny*sizeof(float));
+    bzero (Vwt,  Nx*Ny*sizeof(float));
+  }
+
+  gprint (GP_ERR, "mapping output to input\n");
+
+  for (j = 0; j < Ny; j+=Npix) {
+    for (i = 0; i < Nx; i+=Npix) {
+      
+      /* define linear transformation in region */
+      if (!set_linear_terms (&coords_out, &coords_in, i, j, Npix)) continue;
+
+      for (X = i; (X < i + Npix) && (X < Nx); X += df) {
+	for (Y = j; (Y < j + Npix) && (Y < Ny); Y += df) {
+	  
+	  No = (int)X + ((int)Y)*Nx;
+	  apply_terms (&x, &y, X, Y);
+	  if (x < 0) continue;
+	  if (x >= nx) continue;
+	  if (y < 0) continue;
+	  if (y >= ny) continue;
+	  Ni = (int)x + ((int)y)*nx;
+
+	  if (Vmk && Vmk[Ni]) continue;
+	  Vout[No] += Vin[Ni];
+	  Vwt[No] ++;
+	}
+      }
+    }
+  }
+  return (TRUE);
+}
+
+/* loop over the input pixels, map input output image */
+int map_input_to_output (int Npix, double df) {
+
+  int i, j, Ni, No, Nx, Ny, nx, ny;
+  float *Vin, *Vout, *Vwt, *Vmk;
+  double x, y, X, Y;
+
+  /* loop over output pixels */
+  /* set up pointers for buffers */
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Vwt  = (float *) wt[0].matrix.buffer;
+  Vmk  = NULL;
+  Vmk = (mask == NULL) ? NULL : (float *) mask[0].matrix.buffer;
+
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  nx = out[0].header.Naxis[0];
+  ny = out[0].header.Naxis[1];
+
+  if (ZERO) {
+    bzero (Vout, nx*ny*sizeof(float));
+    bzero (Vwt,  nx*ny*sizeof(float));
+  }
+
+  gprint (GP_ERR, "mapping input to output\n");
+
+  for (j = 0; j < Ny; j+=Npix) {
+    for (i = 0; i < Nx; i+=Npix) {
+      
+      /* define linear transformation in region */
+      if (!set_linear_terms (&coords_in, &coords_out, i, j, Npix)) continue;
+
+      for (X = i; (X < i + Npix) && (X < Nx); X += df) {
+	for (Y = j; (Y < j + Npix) && (Y < Ny); Y += df) {
+	  
+	  Ni = (int)X + ((int)Y)*Nx;
+	  apply_terms (&x, &y, X, Y);
+	  if (x < 0) continue;
+	  if (x >= nx) continue;
+	  if (y < 0) continue;
+	  if (y >= ny) continue;
+	  No = (int)x + ((int)y)*nx;
+
+	  if (Vmk && Vmk[Ni]) continue;
+	  Vout[No] += Vin[Ni];
+	  Vwt[No] ++;
+	}
+      }
+    }
+  }
+  return (TRUE);
+}
+
+int rotate_coords (double *phi, double *theta, double alpha, double delta) {
+
+  double sda, cda, cd, sd, sth;
+  double x, y;
+  
+  sda = sin(RAD_DEG*(alpha - rot_alpha));
+  cda = cos(RAD_DEG*(alpha - rot_alpha));
+  sd = sin(RAD_DEG*delta);
+  cd = cos(RAD_DEG*delta);
+  
+  sth = -cd*sda*rot_cdp + sd*rot_sdp;
+  y   = +cd*sda*rot_sdp + sd*rot_cdp;
+  x   = +cd*cda;
+
+  *theta = DEG_RAD*asin(sth);
+  *phi   = DEG_RAD*atan2(y,x) + rot_phi;
+  
+  while (*phi <   0.0) *phi += 360.0;
+  while (*phi > 360.0) *phi -= 360.0;
+  return (TRUE);
+}
+
+/* find the linear astrometric fix between images at this location */
+int set_linear_terms (Coords *in, Coords *out, int i, int j, int Npix) {
+
+  int n;
+  double x, y, x2, y2, xy, X, Y, Xx, Xy, Yx, Yy;
+  double Xin, Yin, Xout, Yout;
+  double Sx2, Sy2, Sxy, SXx, SXy, SYx, SYy;
+  double N, r, d, phi, theta;
+
+  Xin = Yin = 0;
+  N = x = y = x2 = y2 = xy = X = Y = Xx = Xy = Yx = Yy = 0;
+
+  /* define several test points, fit a line to the input,output pairs */
+  for (n = 0; n < 3; n++) {
+
+    switch (n) {
+    case 0:
+      Xin = i;
+      Yin = j;
+      break;
+    case 1:
+      Xin = i + Npix;
+      Yin = j;
+      break;
+    case 2:
+      Xin = i;
+      Yin = j + Npix;
+      break;
+    }
+
+    if (!XY_to_RD (&r, &d, Xin, Yin, in)) return (FALSE);
+    if (ROTATE) { 
+      rotate_coords (&phi, &theta, r, d);
+      r = phi;
+      d = theta;
+    }
+    if (!RD_to_XY (&Xout, &Yout, r, d, out)) return (FALSE);
+
+    x  += Xin;
+    y  += Yin;
+    x2 += Xin*Xin;
+    y2 += Yin*Yin;
+    xy += Xin*Yin;
+    X  += Xout;
+    Y  += Yout;
+    Xx += Xout*Xin;
+    Xy += Xout*Yin;
+    Yx += Yout*Xin;
+    Yy += Yout*Yin;
+    N  += 1.0;
+  }
+
+  Sx2 = x2 - x*x/N;
+  Sy2 = y2 - y*y/N;
+  Sxy = xy - x*y/N;
+  SXx = Xx - X*x/N;
+  SXy = Xy - X*y/N;
+  SYx = Yx - Y*x/N;
+  SYy = Yy - Y*y/N;
+  
+  XX = (SXx*Sy2 - SXy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  XY = (SXy*Sx2 - SXx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  XO = X/N - XX*x/N - XY*y/N;
+
+  YX = (SYx*Sy2 - SYy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  YY = (SYy*Sx2 - SYx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  YO = Y/N - YX*x/N - YY*y/N;
+  return (TRUE);
+}
+
+
+void apply_terms (double *Xout, double *Yout, double Xin, double Yin) {
+  *Xout = XO + XX*Xin + XY*Yin;
+  *Yout = YO + YX*Xin + YY*Yin;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/fixwrap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/fixwrap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/fixwrap.c	(revision 16632)
@@ -0,0 +1,110 @@
+# include "astro.h"
+
+int fixwrap (int argc, char **argv) {
+  
+  int i, j, Nflip, n, Ny, Nx, flip, sat, rowfix;
+  float *Vin, *outf, *outb, dO;
+  Buffer *in;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: fixwrap <in> (rowfix)\n");
+    return (FALSE);
+  }
+
+  if ((in = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  rowfix = atoi (argv[2]);
+
+  Nx = in[0].matrix.Naxis[0];
+  Ny = in[0].matrix.Naxis[1];
+
+  ALLOCATE (outf, float, MAX(Nx, Ny));
+  ALLOCATE (outb, float, MAX(Nx, Ny));
+
+  for (j = 0; j < Ny; j++) {
+    Vin  = (float *)(in[0].matrix.buffer)  + j*Nx;
+
+    /* measure forward flips */ 
+    sat = FALSE;
+    for (i = 0; i < Nx; i++) {
+      if ((i < 1056) || (i > 2079)) {
+	outf[i] = Vin[i];
+	continue;
+      }
+
+      dO = 2*outf[i-1] - outf[i-2] - Vin[i];
+      flip = (fabs(dO - 0x8000) < fabs(dO));
+
+      /* going onto saturation */
+      if (!sat && (Vin[i] > 32766.5) && (Vin[i+1]  > 32766.5)) sat  = TRUE;
+      if (!sat && (Vin[i] > 32766.5) && (Vin[i-Nx] > 65534.5)) sat  = TRUE;
+
+      /* exiting saturation region */
+      if ( sat && (Vin[i] < 32766.5) && (Vin[i-1] < 32766.5)) sat = FALSE;
+
+      if (sat) flip = TRUE;
+
+      outf[i] = flip ? (Vin[i] + 0x8000) : Vin[i];
+    }
+
+    /* measure backward flips */ 
+    sat = FALSE;
+    for (i = Nx - 1; i >= 0; i--) {
+      if ((i < 1056) || (i > 2077)) {
+	outb[i] = Vin[i];
+	continue;
+      }
+
+      dO = 2*outb[i+1] - outb[i+2] - Vin[i];
+      flip = (fabs(dO - 0x8000) < fabs(dO));
+
+      /* going onto saturation */
+      if (!sat && (Vin[i] > 32766.5) && (Vin[i-1] > 32766.5)) sat  = TRUE;
+
+      /* exiting saturation region */
+      if ( sat && (Vin[i] < 32766.5) && (Vin[i+1] < 32766.5)) sat = FALSE;
+
+      if (sat) flip = TRUE;
+
+      outb[i] = flip ? (Vin[i] + 0x8000) : Vin[i];
+    }
+
+    /* compare forward and backward flips: where they disagree, use column to predict */
+    for (i = 0; (j > 1) && (i < Nx); i++) {
+      if ((i < 1056) || (i > 2077)) continue;
+      if (outf[i] != outb[i]) {
+	/* use this column to predict, not the row */
+	dO = 2*Vin[i - Nx] - Vin[i-2*Nx] - Vin[i];
+	flip = (fabs(dO - 0x8000) < fabs(dO));
+	outf[i] = flip ? Vin[i] + 0x8000 : Vin[i];
+	outb[i] = outf[i];  /* save this for the row segments below */
+      }
+    }
+
+    /* compare this row and previous (now fixed) row. if large segments are flipped, fix them */
+    for (i = 0; rowfix && (j > 1) && (i < Nx); i++) {
+      if ((i < 1056) || (i > 2077)) continue;
+
+      if (fabs(outf[i] - Vin[i-Nx]) > 15000) {
+	Nflip = 0;
+	for (n = i - 8; n < i + 9; n++) {
+	  if (fabs(outb[n] - Vin[n-Nx]) > 15000) {
+	    Nflip ++;
+	  }
+	}
+	if (Nflip > 5) {
+	  if (outf[i] - Vin[i-Nx] > 15000) {
+	    outf[i] -= 0x8000;
+	  } else {
+	    outf[i] += 0x8000;
+	  }	    
+	}
+      }
+    }
+    for (i = 0; i < Nx; i++) {
+      Vin[i] = outf[i];
+    }
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/flux.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/flux.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/flux.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "astro.h"
+
+int flux (int argc, char **argv) {
+  
+  int i, j, k, xmin, ymin, xmax, ymax;
+  void *oldsignal;
+  double ax, ay, s, S, flux;
+  double bx[5], by[5], x[5], y[5], bb[5];
+  float *V;
+  FILE *f;
+  Buffer *buf;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: flux <buffer> (region)\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "file %s not found\n", argv[2]);
+    return (FALSE);
+  }
+
+  xmin = buf[0].matrix.Naxis[0];
+  xmax = 0;
+  ymin = buf[0].matrix.Naxis[1];
+  ymax = 0;
+  for (i = 0; i < 4; i++) {
+    fscanf (f, "%lf %lf", &x[i], &y[i]);
+    xmin = MAX (0, MIN (xmin, x[i] - 1));
+    ymin = MAX (0, MIN (ymin, y[i] - 1));
+    xmax = MIN (MAX (xmax, x[i] + 1), buf[0].matrix.Naxis[0]);
+    ymax = MIN (MAX (ymax, y[i] + 1), buf[0].matrix.Naxis[1]);
+  }
+  fclose (f);
+
+  x[4] = x[0]; y[4] = y[0];
+  for (i = 0; i < 4; i++) {
+    bx[i] = x[i+1] - x[i];
+    by[i] = y[i+1] - y[i];
+  }
+  bx[4] = bx[0]; by[4] = by[0];
+  for (i = 0; i < 4; i++) {
+    bb[i] = hypot (bx[i], by[i]) * SIGN (bx[i]*by[i+1] - bx[i+1]*by[i]);
+  }
+  gprint (GP_ERR, "%f %f %f %f\n", bb[0], bb[1], bb[2], bb[3]);
+
+  /* this only works for convex contours --
+   we have to add up the angles for concave contours */
+  flux = 0;
+  oldsignal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+  for (j = ymin; (j < ymax) && !interrupt; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + xmin; 
+    for (i = xmin; (i < xmax) && !interrupt; i++, V++) {
+      S = 1.0;
+      for (k = 0; k < 4; k++) {
+	ax = i - x[k];
+	ay = j - y[k];
+	s = (ay*bx[k] - ax*by[k]) / bb[k] + 0.5;
+	/* s = b x a / |b|, with the correct sign (above) so inside is positive */
+	s = MAX (0.0, MIN (1.0, s));  /* s is between 0.0 and 1.0 */
+	S *= s;
+      }
+      flux += S * (*V);
+    }
+  }
+  signal (SIGINT, oldsignal);
+
+  gprint (GP_LOG, "flux: %f\n", flux);
+  set_variable ("FLUX", flux);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/gauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/gauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/gauss.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "astro.h"
+
+int gauss (int argc, char **argv) {
+
+  char key[20];
+  int i, N, Npix, Nborder, Nspot;
+  double X, Y, Z, ZP, RA, DEC, max;
+  int kapa;
+  char *name;
+  Buffer *buf;
+  KapaImageData data;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImageData (&data, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  Nborder = 3;
+  if ((N = get_argument (argc, argv, "-border"))) {
+    remove_argument (N, &argc, argv);
+    Nborder  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Nborder = MAX (Nborder, 1);
+  
+  max = 60000;
+  if ((N = get_argument (argc, argv, "-sat"))) {
+    remove_argument (N, &argc, argv);
+    max  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  if ((argc != 2) && (argc != 3)) {
+    gprint (GP_ERR, "USAGE: gauss Npix [Nspots] [-border N] [-sat cnts]\n");
+    return (FALSE);
+  }
+  
+  if (kapa < 1) {
+    gprint (GP_ERR, "no active TV\n");
+    return (FALSE);
+  }
+
+  Nspot = 0;
+  Npix = atof (argv[1]);
+  if (argc == 3) {
+    Nspot = atof (argv[2]);
+  }
+
+  if ((buf = SelectBuffer (data.name, OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  KiiCursorOn (kapa);
+
+  for (i = 0; (i < Nspot) || (Nspot == 0); i++) {
+    KiiCursorRead (kapa, &X, &Y, &ZP, &RA, &DEC, key);
+    if (!strcasecmp (key, "Q")) break;
+    Z = get_aperture_stats (&buf[0].matrix, (int)(X+0.5), (int)(Y+0.5), Npix, Nborder, max);
+  }
+  KiiCursorOff (kapa);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/getlst.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/getlst.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/getlst.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "astro.h"
+
+int getlst (int argc, char **argv) {
+
+  int N;
+  time_t time;
+  double jd, lst, longitude;
+  char *Variable;
+
+  Variable = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    Variable = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (argc != 3) goto syntax;
+
+  if (!ohana_str_to_time (argv[1], &time)) {
+      if (Variable != NULL) free (Variable);
+      return (FALSE);
+  }
+
+  longitude = atof (argv[2]);
+
+  jd = ohana_sec_to_jd (time);
+  fprintf (stderr, "jd: %f\n", jd);
+
+  lst = ohana_lst (jd, longitude);
+
+  if (Variable != NULL) {
+      set_variable (Variable, lst);
+      free (Variable);
+      return (TRUE);
+  }
+  gprint (GP_ERR, "lst: %f\n", lst);
+  return (TRUE);
+
+ syntax:
+  gprint (GP_ERR, "USAGE: getlst (time) (longitude) [-var name]\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/getvel.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/getvel.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/getvel.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "astro.h"
+
+int getvel (int argc, char **argv) {
+  
+  int i, n, Ncurve;
+  int nx, ny;
+  double L, V, Vo, dV, Bo, dB;
+  double xo, yo;
+  double sl, cl, wo, Ro, Rs, wr, r, fr, d, x;
+  double R[100], T[100], W[100];
+  FILE *f;
+  Buffer *buf;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: rotcurve buf X Y curve.txt\n");
+    return (FALSE);
+  }
+
+  f = fopen (argv[4], "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't find rotation curve data file %s\n", argv[4]);
+    return (FALSE);
+  }
+  for (i = 0; fscanf (f, "%lf %lf", &R[i], &T[i]) != EOF; i++) {
+    W[i] = T[i] / R[i];
+  }  
+  fclose (f);
+  Ncurve = i;
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  nx = buf[0].matrix.Naxis[0];
+  ny = buf[0].matrix.Naxis[1];
+
+  /* we expect the input image to have units of velocity, lattitude, and longitude */
+  gfits_scan (&buf[0].header, "CRVAL1", "%lf", 1, &Vo);
+  gfits_scan (&buf[0].header, "CDELT1", "%lf", 1, &dV);
+  gfits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &xo);
+  gfits_scan (&buf[0].header, "CRVAL2", "%lf", 1, &Bo);
+  gfits_scan (&buf[0].header, "CDELT2", "%lf", 1, &dB);
+  gfits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &yo);
+  gfits_scan (&buf[0].header, "CRVAL3", "%lf", 1, &L);
+  Vo *= 0.001;
+  dV *= 0.001;
+
+  while (L >= 360) {L -= 360.0;}
+  while (L < 0.0)  {L += 360.0;}
+  gprint (GP_ERR, "L: %f\n", L);
+
+  cl = cos (L*RAD_DEG);
+  sl = sin (L*RAD_DEG);
+  wo = 25.0;
+  Ro = 10.0;
+  Rs = Ro*sl;
+  x = atof (argv[2]);
+  /* this method depends on wr monotonically decreasing */
+
+  V = (x - xo) * dV + Vo;
+  wr = V/Rs + wo;
+  for (n = 0; (n < Ncurve) && (wr < W[n]); n++);
+  if ((n == 0) || (n == Ncurve)) {
+    gprint (GP_ERR, "velocity out of reasonable range\n");
+    gprint (GP_ERR, "%f %f %f %f\n", V, wr, W[0], W[Ncurve-1]);
+    return (TRUE);
+  }
+  r = (wr - W[n]) *  (R[n-1] - R[n]) / (W[n-1] - W[n]) + R[n];
+  fr = (Ro/r);
+  if (r < fabs(Rs)) { /* can't be on rotation curve */
+    gprint (GP_ERR, "velocity out of reasonable range\n");
+    gprint (GP_ERR, "%f %f %f %f %f %f %f\n", V, wr, W[0], W[Ncurve-1], r, fr, Rs);
+    return (TRUE);
+  }
+  if (r < Ro)
+    d = Ro*cl - sqrt(r*r - Rs*Rs);
+  else 
+    d = Ro*cl + sqrt(r*r - Rs*Rs);
+  
+  gprint (GP_ERR, "dist: %f, vel: %f\n", d, V);
+
+  return (TRUE);
+
+} 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/biassub
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/biassub	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/biassub	(revision 16632)
@@ -0,0 +1,9 @@
+
+  biassub buffer sx sy nx ny dir [-v N V]
+
+  Apply a bias correction.  The region defines a vector 
+  (median is taken perpendicular to the dir direction) which 
+  is subtracted from the image.
+
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/cgrid
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/cgrid	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/cgrid	(revision 16632)
@@ -0,0 +1,6 @@
+
+  cgrid
+
+  draws a grid in RA and DEC on window 0 approriate for the current
+  region.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/coords
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/coords	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/coords	(revision 16632)
@@ -0,0 +1,19 @@
+
+  coords <buffer> (filename)
+
+  "coords" loads astrometric parameters for the given buffer from the
+header of the named file.  The parameters are applied to the buffer,
+and will register in the Ki'i window if the buffer it tv'ed again.
+This is particularly convenient for intercomparing coordinate system
+or in the event the astrometry is stored in a different file (eg, a
+stripped off header).  Currently, the only format of coordinate
+information that is looked for are gene's linear transformation: RA_O,
+RA_X, RA_Y, DEC_O, DEC_X, DEC_Y such that the RA,DEC of an object is
+given by:
+
+RA  = RA_O  + x*RA_X  + y*RA_Y
+DEC = DEC_O + x*DEC_X + y*DEC_Y.
+
+
+  See also: rd, tv
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/flux
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/flux	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/flux	(revision 16632)
@@ -0,0 +1,7 @@
+
+   flux buffer (file)
+
+   calculate the flux enclosed by the contour given in the file.  The
+   file contains the coordinates of the polygon corners.
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/gauss
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/gauss	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/gauss	(revision 16632)
@@ -0,0 +1,15 @@
+
+   gauss Npix [Nspots] [-border N] [-sat cnts]
+
+   calculate statistics on stars, assuming a Gaussian profile.  The
+   user types a key on a star in the Kii window, and the resulting
+   information is printed on the screen.  This is really aperture
+   photometry.  Npix defines the aperture width (square aperture), the
+   optional -border defines the number of pixels in an annulus used to
+   find the background, -sat defines the value of a saturated pixel.
+   If the Nspots option is given, exactly Nspots stars are chosen.
+   Otherwise, the user may type on stars until the 'q' is typed.  The
+   results of the last star are stored the a set of Mana variables.
+
+   See also: star, cursor
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/profile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/profile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/profile	(revision 16632)
@@ -0,0 +1,6 @@
+
+   profile <buffer> <X vector> <Y vector> x y N
+
+   Find the radial profile of an image at the location x, y.  the
+   radius is placed in the X vector and the pixel value is placed in
+   the Y vector.   
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/region
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/region	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/help/region	(revision 16632)
@@ -0,0 +1,18 @@
+
+  region RA DEC Radius [projection]
+
+  define the current sky region and optionally the projection.  
+  RA, DEC and Radius are all values in decimal degrees.  The possible 
+  values for "projection" are:
+
+  TAN - a tangent plane projection (default, and typical for optical images)
+  SIN - a sine plane projection (more appropriate for polar regions)
+  AIT - aitoff projection (good for the full sky)
+  GLS - ?? (also good for the full sky)
+
+  optional orientation flags:
+
+  -ew : display with East Left (default)
+  +ew : display with East Right 
+  -ns : display with North Down
+  +ns : display with North Up (default)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-fgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-fgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-fgauss.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "imfit.h"
+
+float fgaussTD (float, float, float *, int, float *);
+void  fgaussCL ();
+
+void fgauss_setup (char *name) {
+
+  if (strcmp(name, "fgauss")) return;
+
+  fitfunc = fgaussTD;
+  imfit_cleanup = fgaussCL;
+  Npar = 7;
+  Nfpar = 0;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = 2.35 / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 / get_variable_default ("SYg", 2.0);
+  par[4] = get_variable_default ("SXYg", 0);
+  par[5] = get_variable_default ("Zpk", 10000);
+  par[6] = get_variable_default ("Sg", 0.0);
+  sky = &par[6];
+}
+
+void fgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 / par[2]);
+  set_variable ("SYg",  2.35 / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+}
+
+/* real 2D gaussian -- x, y, sx, sy, sxy, I, sky */
+float fgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+  r = exp (-z);
+  q = par[5]*r;
+  f = q + par[6];
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X;
+    dpar[3] = -2*q*py*Y;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+  }
+  return (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-pgauss-psf.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-pgauss-psf.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-pgauss-psf.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "imfit.h"
+
+float pgauss_psfTD (float, float, float *, int, float *);
+void  pgauss_psfCL ();
+
+void  pgauss_psf_setup (char *name) {
+
+  if (strcmp(name, "pgauss_psf")) return;
+
+  fitfunc = pgauss_psfTD;
+  imfit_cleanup = pgauss_psfCL;
+  Npar = 4;
+  Nfpar = 3;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = get_variable_default ("Zpk", 10000);
+  par[3] = get_variable_default ("Sg", 0.0);
+  sky = &par[3];
+
+  fpar[0] = 2.35 / get_variable_default ("SXg", 2.0);
+  fpar[1] = 2.35 / get_variable_default ("SYg", 2.0);
+  fpar[2] = get_variable_default ("SXYg", 0);
+}
+
+void pgauss_psfCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("Zpk",  par[2]);
+  set_variable ("Sg",   par[3]);
+}
+
+/* pseudo 2D gaussian -- x, y, (sx), (sy), (sxy), I, sky */
+float pgauss_psfTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  /* par -> fpar: (2,0), (3,1), (4,2) */
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = fpar[0]*X;
+  py = fpar[1]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + fpar[2]*X*Y;
+  r = 1.0 / (1 + z + 0.5*z*z*(1 + z/3)); /* ~ exp (-Z) */
+  f = par[2]*r + par[3];
+  q = par[2]*r*r*(1 + z + 0.5*z*z);
+  /* note difference from gaussian: q = par[5]*r */
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*fpar[0] + fpar[2]*Y);
+    dpar[1] = q*(2*py*fpar[1] + fpar[2]*X);
+    dpar[2] = +r;
+    dpar[3] = +1;
+  }
+  return (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-pgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-pgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-pgauss.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "imfit.h"
+
+float pgaussTD (float, float, float *, int, float *);
+void  pgaussCL ();
+
+void  pgauss_setup (char *name) {
+
+  if (strcmp(name, "pgauss")) return;
+
+  fitfunc = pgaussTD;
+  imfit_cleanup = pgaussCL;
+  Npar = 7;
+  Nfpar = 0;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0.0);
+  par[1] = get_variable_default ("Yg", 0.0);
+  par[2] = 2.35 / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 / get_variable_default ("SYg", 2.0);
+  par[4] = get_variable_default ("SXYg", 0.0);
+  par[5] = get_variable_default ("Zpk", 10000);
+  par[6] = get_variable_default ("Sg", 0.0);
+  sky = &par[6];
+}
+
+void pgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 / par[2]);
+  set_variable ("SYg",  2.35 / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+}
+
+/* pseudo 2D gaussian -- x, y, sx, sy, sxy, I, sky */
+float pgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+  r = 1.0 / (1 + z + 0.5*z*z*(1 + z/3)); /* ~ exp (-Z) */
+  f = par[5]*r + par[6];
+  q = par[5]*r*r*(1 + z + 0.5*z*z);
+  /* note difference from gaussian: q = par[5]*r */
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X;
+    dpar[3] = -2*q*py*Y;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+  }
+  return (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qfgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qfgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qfgauss.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "imfit.h"
+
+float qfgaussTD (float, float, float *, int, float *);
+void  qfgaussCL ();
+
+void qfgauss_setup (char *name) {
+
+  if (strcmp(name, "qfgauss")) return;
+
+  fitfunc = qfgaussTD;
+  imfit_cleanup = qfgaussCL;
+  Npar = 7;
+  Nfpar = 2;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0]  = get_variable_default ("Xg", 0);
+  par[1]  = get_variable_default ("Yg", 0);
+  par[2]  = 2.35 / get_variable_default ("SXg", 2.0);
+  par[3]  = 2.35 / get_variable_default ("SYg", 2.0);
+  par[4]  = get_variable_default ("SXYg", 0);
+  par[5]  = get_variable_default ("Zpk", 10000);
+  par[6]  = get_variable_default ("Sg", 0.0);
+
+  fpar[0] = get_variable_default ("Npow", 2.25);
+  fpar[1]  = get_variable_default ("Sr", 1.0);
+
+  sky = &par[6];
+}
+
+void qfgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 / par[2]);
+  set_variable ("SYg",  2.35 / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+}
+
+/* one component, two slopes: (1 + z^M + z^N)^(-1) -- x, y, sx, sy, sxy, I, sky */
+float qfgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+
+  r = 1.0 / (1 + fpar[1]*z + pow(z,fpar[0]));
+  f = par[5]*r + par[6];
+  q = par[5]*SQ(r)*(fpar[1] + fpar[0]*pow(z,(fpar[0]-1)));
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X*2;
+    dpar[3] = -2*q*py*Y*2;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+  }
+  return (f);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qgauss-psf.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qgauss-psf.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qgauss-psf.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "imfit.h"
+
+float qgauss_psfTD (float, float, float *, int, float *);
+void  qgauss_psfCL ();
+
+void qgauss_psf_setup (char *name) {
+
+  if (strcmp(name, "qgauss_psf")) return;
+
+  fitfunc = qgauss_psfTD;
+  imfit_cleanup = qgauss_psfCL;
+  Npar = 4;
+  Nfpar = 5;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0]  = get_variable_default ("Xg", 0);
+  par[1]  = get_variable_default ("Yg", 0);
+  par[2]  = get_variable_default ("Zpk", 10000);
+  par[3]  = get_variable_default ("Sg", 0.0);
+
+  fpar[0] = 2.35 / get_variable_default ("SXg", 15.0);
+  fpar[1] = 2.35 / get_variable_default ("SYg", 15.0);
+  fpar[2] = get_variable_default ("SXYg", 0.0);
+  fpar[3] = get_variable_default ("Sr", 1.0);
+  fpar[4] = get_variable_default ("Npow", 2.25);
+
+  sky = &par[3];
+}
+
+void qgauss_psfCL () {
+  set_variable ("Xg",  par[0]);
+  set_variable ("Yg",  par[1]);
+  set_variable ("Zpk", par[2]);
+  set_variable ("Sg",  par[3]);
+}
+
+/* one component, two slopes: (1 + z^M + z^N)^(-1) -- x, y, sx, sy, sxy, I, sky, sr */
+float qgauss_psfTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = fpar[0]*X;
+  py = fpar[1]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + fpar[2]*X*Y;
+
+  r = 1.0 / (1 + fpar[3]*z + pow(z,fpar[4]));
+  f = par[2]*r + par[3];
+  q = par[2]*SQ(r)*(fpar[3] + fpar[4]*pow(z,(fpar[4]-1)));
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*fpar[0] + fpar[2]*Y);
+    dpar[1] = q*(2*py*fpar[1] + fpar[2]*X);
+    dpar[2] = +r;
+    dpar[3] = +1;
+  }
+  return (f);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qgauss.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "imfit.h"
+
+float qgaussTD (float, float, float *, int, float *);
+void  qgaussCL ();
+
+void qgauss_setup (char *name) {
+
+  if (strcmp(name, "qgauss")) return;
+
+  fitfunc = qgaussTD;
+  imfit_cleanup = qgaussCL;
+  Npar = 8;
+  Nfpar = 1;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0]  = get_variable_default ("Xg", 0);
+  par[1]  = get_variable_default ("Yg", 0);
+  par[2]  = 2.35 / get_variable_default ("SXg", 2.0);
+  par[3]  = 2.35 / get_variable_default ("SYg", 2.0);
+  par[4]  = get_variable_default ("SXYg", 0);
+  par[5]  = get_variable_default ("Zpk", 10000);
+  par[6]  = get_variable_default ("Sg", 0.0);
+  par[7]  = get_variable_default ("Sr", 1.0);
+  fpar[0] = get_variable_default ("Npow", 2.25);
+
+  sky = &par[6];
+}
+
+void qgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 / par[2]);
+  set_variable ("SYg",  2.35 / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+  set_variable ("Sr", par[7]);
+}
+
+/* one component, two slopes: (1 + z^M + z^N)^(-1) -- x, y, sx, sy, sxy, I, sky, sr */
+float qgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+
+  r = 1.0 / (1 + par[7]*z + pow(z,fpar[0]));
+  f = par[5]*r + par[6];
+  q = par[5]*SQ(r)*(par[7] + fpar[0]*pow(z,(fpar[0]-1)));
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X*2;
+    dpar[3] = -2*q*py*Y*2;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -par[5]*SQ(r)*z;
+  }
+  return (f);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qrgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qrgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-qrgauss.c	(revision 16632)
@@ -0,0 +1,110 @@
+# include "imfit.h"
+
+float qrgaussTD (float, float, float *, int, float *);
+void  qrgaussCL ();
+
+void qrgauss_setup (char *name) {
+
+  if (strcmp(name, "qrgauss")) return;
+
+  fitfunc = qrgaussTD;
+  imfit_cleanup = qrgaussCL;
+  Npar = 8;
+  Nfpar = 1;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0]  = get_variable_default ("Xg", 0);
+  par[1]  = get_variable_default ("Yg", 0);
+  par[2]  = 2.35 / get_variable_default ("SXg", 2.0);
+  par[3]  = 2.35 / get_variable_default ("SYg", 2.0);
+  par[4]  = get_variable_default ("SXYg", 0);
+  par[5]  = get_variable_default ("Zpk", 10000);
+  par[6]  = get_variable_default ("Sg", 0.0);
+  par[7]  = get_variable_default ("Npow", 2.25);
+
+  fpar[0] = get_variable_default ("Sr", 1.0);
+
+  sky = &par[6];
+}
+
+void qrgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 / par[2]);
+  set_variable ("SYg",  2.35 / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+  set_variable ("Npow", par[7]);
+}
+
+float qrgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+
+  r = 1.0 / (1 + fpar[0]*z + pow(z,par[7]));
+  f = par[5]*r + par[6];
+  q = par[5]*SQ(r)*(fpar[0] + par[7]*pow(z,(par[7]-1)));
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X*2;
+    dpar[3] = -2*q*py*Y*2;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -5*par[5]*SQ(r)*log(z)*pow(z,par[7]);
+  }
+  return (f);
+}
+
+
+# if (0)
+/* one component, two slopes: (1 + z^M + z^N)^(-1) -- x, y, sx, sy, sxy, I, sky, sr */
+float qrgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f;
+
+  /* if (par[7] < 1.0) par[7] = 1.0; */
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+
+  r = 1.0 / (1 + fpar[0]*z + pow(z,par[7]) + 0.05*z*z*z);
+  f = par[5]*r + par[6];
+  q = par[5]*SQ(r)*(fpar[0] + par[7]*pow(z,(par[7]-1)) + 0.15*z*z);
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X*2;
+    dpar[3] = -2*q*py*Y*2;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -5*par[5]*SQ(r)*log(z)*pow(z,par[7]);
+  }
+  return (f);
+}
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-rgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-rgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-rgauss.c	(revision 16632)
@@ -0,0 +1,86 @@
+# include "imfit.h"
+
+float rgaussTD (float, float, float *, int, float *);
+void  rgaussCL ();
+
+void rgauss_setup (char *name) {
+
+  if (strcmp(name, "rgauss")) return;
+
+  fitfunc = rgaussTD;
+  cleanup = rgaussCL;
+  Npar = 10;
+  Nfpar = 1;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = 2.35 * sqrt(2.0) / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 * sqrt(2.0) / get_variable_default ("SYg", 2.0);
+  par[4] = 0.0;
+  par[5] = get_variable_default ("Zpk", 10000);
+  par[6] = get_variable_default ("Sg", 0.0);
+  par[7] = 2.35 * sqrt(2.0) / get_variable_default ("SXf", 15.0);
+  par[8] = 2.35 * sqrt(2.0) / get_variable_default ("SYf", 15.0);
+  par[9] = get_variable_default ("SXYf", 0.0);
+
+  fpar[0] = get_variable_default ("Npow", 2.25);
+
+  sky = &par[6];
+}
+
+/* two components: (1 + z_1 + 0.5*z_1^2 + z_2^N)^(-1) -- x, y, sx1, sy1, sxy1, I, sky, sx2, sy2, sxy2 */
+float rgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px1, py1, px2, py2;
+  float z1, z2, r, q1, q2, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px1 = par[2]*X;
+  py1 = par[3]*Y;
+  px2 = par[7]*X;
+  py2 = par[8]*Y;
+
+  z1 = 0.5*SQ(px1) + 0.5*SQ(py1) + par[4]*X*Y;
+  z2 = 0.5*SQ(px2) + 0.5*SQ(py2) + par[9]*X*Y;
+
+  r = 1.0 / (1 + z1 + 0.5*SQ(z1)+ pow(z2,fpar[0]));
+  f = par[5]*r + par[6];
+
+  q1 = par[5]*SQ(r)*(1 + z1);
+  q2 = par[5]*SQ(r)*fpar[0]*pow(z2,(fpar[0]-1));
+
+  if (dpar != NULL) {
+    dpar[0] = q1*(2*px1*par[2] + par[4]*Y) + q2*(2*px2*par[7] + par[9]*Y);
+    dpar[1] = q1*(2*py1*par[3] + par[4]*X) + q2*(2*py2*par[8] + par[9]*X);
+    dpar[2] = -2*q1*px1*X;
+    dpar[3] = -2*q1*py1*Y;
+    dpar[4] = -q1*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -2*q2*px2*X;
+    dpar[8] = -2*q2*py2*Y;
+    dpar[9] = -q2*X*Y;
+  }
+  return (f);
+}
+
+int rgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 * sqrt(2.0) / par[2]);
+  set_variable ("SYg",  2.35 * sqrt(2.0) / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+  set_variable ("SXf", 2.35 * sqrt(2.0) / par[7]);
+  set_variable ("SYf", 2.35 * sqrt(2.0) / par[8]);
+  set_variable ("SXYf", par[9]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-serbulge.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-serbulge.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-serbulge.c	(revision 16632)
@@ -0,0 +1,102 @@
+# include "imfit.h"
+
+float serbulgeTD (float, float, float *, int, float *);
+void  serbulgeCL ();
+
+void serbulge_setup (char *name) {
+
+  if (strcmp(name, "serbulge")) return;
+
+  fitfunc = serbulgeTD;
+  cleanup = serbulgeCL;
+  Npar = 12;
+  Nfpar = 0;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = 2.35 * sqrt(2.0) / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 * sqrt(2.0) / get_variable_default ("SYg", 2.0);
+  par[4] = 0.0;
+  par[5] = get_variable_default ("Zpk", 10000) / 2.0;
+
+  par[6] = get_variable_default ("Sg", 0.0);
+
+  par[7] = 2.35 * sqrt(2.0) / get_variable_default ("SXf", 15.0);
+  par[8] = 2.35 * sqrt(2.0) / get_variable_default ("SYf", 15.0);
+  par[9] = get_variable_default ("SXYf", 0.0);
+  par[10] = get_variable_default ("Zpk", 10000) / 2.0;
+
+  par[11] = get_variable_default ("Sr", 1.0);
+
+  sky = &par[6];
+}
+
+/*                                  0  1    2   3   4      5    6     7   8   9       10  11 */
+/* sersic galaxy model w/ bulge: -- x, y, (sx, sy, sxy)_1, I_1, sky, (sx, sy, sxy)_2, I_2, n */
+/* exp (-b (r/r_e)^(1/n)) + pgauss (r) */
+float serbulgeTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px1, px2, py1, py2;
+  float z1, z2, r1, r2, t, q1, q2, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px1 = par[2]*X;
+  py1 = par[3]*Y;
+  px2 = par[7]*X;
+  py2 = par[8]*Y;
+
+  z1 = 0.5*SQ(px1) + 0.5*SQ(py1) + par[4]*X*Y;
+  z2 = 0.5*SQ(px2) + 0.5*SQ(py2) + par[9]*X*Y;
+
+  /* bulge component */
+  r1 = 1.0 / (1 + z1 + 0.5*z1*z1*(1 + z1/3)); /* ~ exp (-Z) */
+
+  /* disk component */
+  t = pow (z2, par[11]);
+  r2 = exp (-t);
+
+  f = par[5]*r1 + par[10]*r2 + par[6];
+
+  q1 = par[5]*r1*r1*(1 + z1 + 0.5*z1*z1);
+  q2 = par[10]*r2*par[11]*pow(z2, par[11]-1);
+
+  if (dpar != NULL) {
+    dpar[0] = q1*(2*px1*par[2] + par[4]*Y) + q2*(2*px2*par[7] + par[9]*Y);
+    dpar[1] = q1*(2*py1*par[3] + par[4]*X) + q2*(2*py2*par[8] + par[9]*X);
+    dpar[2] = -2*q1*px1*X;
+    dpar[3] = -2*q1*py1*Y;
+    dpar[4] = -q1*X*Y;
+    dpar[5] = +r1;
+    dpar[6] = +1;
+    dpar[7] = -2*q2*px2*X*50;
+    dpar[8] = -2*q2*py2*Y*50;
+    dpar[9] = -q2*X*Y*50;
+    dpar[10] = +r2*50;
+    dpar[11] = -q2*log(z2)*t*50;
+  }
+  return (f);
+}
+
+int serbulgeCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 * sqrt(2.0) / par[2]);
+  set_variable ("SYg",  2.35 * sqrt(2.0) / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zb",   par[5]);
+  set_variable ("Sg",   par[6]);
+
+  set_variable ("SXf",  2.35 * sqrt(2.0) / par[7]);
+  set_variable ("SYf",  2.35 * sqrt(2.0) / par[8]);
+  set_variable ("SXYf", par[9]);
+  set_variable ("Zd",   par[10]);
+  set_variable ("Sr",   par[11]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sersic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sersic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sersic.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "imfit.h"
+
+float sersicTD (float, float, float *, int, float *);
+void  sersicCL ();
+
+void sersic_setup (char *name) {
+
+  if (strcmp(name, "sersic")) return;
+
+  fitfunc = sersicTD;
+  cleanup = sersicCL;
+  Npar = 8;
+  Nfpar = 0;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = 2.35 * sqrt(2.0) / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 * sqrt(2.0) / get_variable_default ("SYg", 2.0);
+  par[4] = 0.0;
+  par[5] = get_variable_default ("Zpk", 10000);
+  par[6] = get_variable_default ("Sg", 0.0);
+  par[7] = get_variable_default ("Sr", 1.0);
+
+  sky = &par[6];
+}
+
+/* sersic galaxy model -- x, y, sx, sy, sxy, I, sky, n */
+/* exp (-b (r/r_e)^(1/n)) */
+float sersicTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, t, q, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+  t = pow (z, par[7]);
+  r = exp (-t);
+  f = par[5]*r + par[6];
+  q = par[5]*r*par[7]*pow(z, par[7]-1);
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X;
+    dpar[3] = -2*q*py*Y;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -q*log(z)*t;
+  }
+  return (f);
+}
+
+int sersicCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 * sqrt(2.0) / par[2]);
+  set_variable ("SYg",  2.35 * sqrt(2.0) / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+  set_variable ("Sr", par[7]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sgauss-psf.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sgauss-psf.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sgauss-psf.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "imfit.h"
+
+float sgauss_psfTD (float, float, float *, int, float *);
+void  sgauss_psfCL ();
+
+void sgauss_psf_setup (char *name) {
+
+  if (strcmp(name, "sgauss_psf")) return;
+
+  fitfunc = sgauss_psfTD;
+  imfit_cleanup = sgauss_psfCL;
+  Npar = 4;
+  Nfpar = 7;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = get_variable_default ("Zpk", 10000);
+  par[3] = get_variable_default ("Sg", 0.0);
+
+  fpar[0] = 2.35 / get_variable_default ("SXg", 15.0);
+  fpar[1] = 2.35 / get_variable_default ("SYg", 15.0);
+  fpar[2] = get_variable_default ("SXYg", 0.0);
+  fpar[3] = 2.35 / get_variable_default ("SXf", 15.0);
+  fpar[4] = 2.35 / get_variable_default ("SYf", 15.0);
+  fpar[5] = get_variable_default ("SXYf", 0.0);
+  fpar[6] = get_variable_default ("Npow", 2.25);
+
+  sky = &par[3];
+}
+
+void sgauss_psfCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("Zpk",  par[2]);
+  set_variable ("Sg",   par[3]);
+}
+
+/* two components: (1 + z_1 + z_2^N)^(-1) -- x, y, sx1, sy1, sxy1, I, sky, sx2, sy2, sxy2 */
+float sgauss_psfTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px1, py1, px2, py2;
+  float z1, z2, r, q1, q2, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px1 = fpar[0]*X;
+  py1 = fpar[1]*Y;
+  px2 = fpar[3]*X;
+  py2 = fpar[4]*Y;
+
+  z1 = 0.5*SQ(px1) + 0.5*SQ(py1) + fpar[2]*X*Y;
+  z2 = 0.5*SQ(px2) + 0.5*SQ(py2) + fpar[5]*X*Y;
+
+  r = 1.0 / (1 + z1 + pow(z2,fpar[6]));
+  f = par[2]*r + par[3];
+
+  q1 = par[2]*SQ(r);
+  q2 = par[2]*SQ(r)*fpar[6]*pow(z2,(fpar[6]-1));
+
+  if (dpar != NULL) {
+    dpar[0] = q1*(2*px1*fpar[0] + fpar[2]*Y) + q2*(2*px2*fpar[3] + fpar[5]*Y);
+    dpar[1] = q1*(2*py1*fpar[1] + fpar[2]*X) + q2*(2*py2*fpar[4] + fpar[5]*X);
+    dpar[2] = +r;
+    dpar[3] = +1;
+  }
+  return (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-sgauss.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "imfit.h"
+# define FFACTOR 200
+# define FSCALE 1.2
+
+float sgaussTD (float, float, float *, int, float *);
+void  sgaussCL ();
+
+void sgauss_setup (char *name) {
+
+  if (strcmp(name, "sgauss")) return;
+
+  fitfunc = sgaussTD;
+  imfit_cleanup = sgaussCL;
+  Npar = 10;
+  Nfpar = 2;
+
+  /* allocate free and fixed parameters */
+  ALLOCATE (par, float, MAX (Npar, 1));
+  bzero (par, Npar*sizeof(float));
+  ALLOCATE (fpar, float, MAX (Nfpar, 1));
+  bzero (fpar, Nfpar*sizeof(float));
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = 2.35 / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 / get_variable_default ("SYg", 2.0);
+  par[4] = get_variable_default ("SXYg", 0);
+  par[5] = get_variable_default ("Zpk", 10000);
+  par[6] = get_variable_default ("Sg", 0.0);
+  par[7] = 2.35 / get_variable_default ("SXf", 15.0);
+  par[8] = 2.35 / get_variable_default ("SYf", 15.0);
+  par[9] = get_variable_default ("SXYf", 0.0);
+
+  fpar[0] = get_variable_default ("Npow", 2.25);
+  fpar[1] = get_variable_default ("Npin", 1.00); // drop this?
+
+  sky = &par[6];
+}
+
+void sgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 / par[2]);
+  set_variable ("SYg",  2.35 / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+  set_variable ("SXf", 2.35 / par[7]);
+  set_variable ("SYf", 2.35 / par[8]);
+  set_variable ("SXYf", par[9]);
+}
+
+/* two components: (1 + z_1 + z_2^N)^(-1) -- x, y, sx1, sy1, sxy1, I, sky, sx2, sy2, sxy2 */
+float sgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px1, py1, px2, py2;
+  float z1, z2, r, q1, q2, f, f1, f2;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px1 = par[2]*X;
+  py1 = par[3]*Y;
+  px2 = par[7]*X;
+  py2 = par[8]*Y;
+
+  z1 = 0.5*SQ(px1) + 0.5*SQ(py1) + par[4]*X*Y;
+  z2 = 0.5*SQ(px2) + 0.5*SQ(py2) + par[9]*X*Y;
+
+  r = 1.0 / (1 + z1 + pow(z2,fpar[0]));
+  f = par[5]*r + par[6];
+
+  q1 = par[5]*SQ(r);
+  q2 = par[5]*SQ(r)*fpar[0]*pow(z2,(fpar[0]-1));
+
+  if (dpar != NULL) {
+    dpar[0] = q1*(2*px1*par[2] + par[4]*Y) + q2*(2*px2*par[7] + par[9]*Y);
+    dpar[1] = q1*(2*py1*par[3] + par[4]*X) + q2*(2*py2*par[8] + par[9]*X);
+
+    /* these fudge factors impede the growth of par[2] beyond par[7] */
+    f1 = fabs(par[7]) / fabs(par[2]);
+    f2 = (f1 < FSCALE) ? 1 : FFACTOR*(f1 - FSCALE) + 1;
+    dpar[2] = -2*q1*px1*X*f2;
+
+    f1 = fabs(par[8]) / fabs(par[3]);
+    f2 = (f1 < FSCALE) ? 1 : FFACTOR*(f1 - FSCALE) + 1;
+    dpar[3] = -2*q1*py1*Y*f2;
+
+    dpar[4] = -q1*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -2*q2*px2*X;
+    dpar[8] = -2*q2*py2*Y;
+    dpar[9] = -q2*X*Y;
+  }
+  return (f);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-test.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-test.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-test.c	(revision 16632)
@@ -0,0 +1,314 @@
+  if (ShapeVariation) {
+    /* find dChi/dSx and dChi/dSy given by increasing shape terms by 5% */
+    float tp1, tp2, chix, chiy;
+    chix = chiy = 0;
+    if (fitfunc == sgaussTD) {
+      tp1 = par[2];
+      tp2 = par[7];
+      par[2] = par[2]*1.05;
+      par[7] = par[7]*1.05;
+      chix = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[2] = tp1;
+      par[7] = tp2;
+
+      tp1 = par[3];
+      tp2 = par[8];
+      par[3] = par[3]*1.05;
+      par[8] = par[8]*1.05;
+      chiy = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[3] = tp1;
+      par[8] = tp2;
+    }
+    if (fitfunc == pgaussTD) {
+      tp1 = par[2];
+      par[2] = par[2]*1.05;
+      chix = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[2] = tp1;
+
+      tp1 = par[3];
+      par[3] = par[3]*1.05;
+      chiy = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[3] = tp1;
+    }
+    if (fitfunc == sgauss_psfTD) {
+      tp1 = par[0];
+      tp2 = par[3];
+      par[0] = par[0]*1.05;
+      par[3] = par[3]*1.05;
+      chix = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[0] = tp1;
+      par[3] = tp2;
+
+      tp1 = par[1];
+      tp2 = par[4];
+      par[1] = par[1]*1.05;
+      par[4] = par[4]*1.05;
+      chiy = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[1] = tp1;
+      par[4] = tp2;
+    }
+    if (fitfunc == pgauss_psfTD) {
+      tp1 = par[0];
+      par[0] = par[0]*1.05;
+      chix = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[0] = tp1;
+
+      tp1 = par[1];
+      par[1] = par[1]*1.05;
+      chiy = mrq2dchi (x, y, z, dz, Npts, par, Npar, fitfunc) - chisq;
+      par[1] = tp1;
+    }
+    set_variable ("dChiX", chix/chisq);
+    set_variable ("dChiY", chiy/chisq);
+  }
+
+# if (0)
+/* pars: x, y, sx, sy, sxy, I, sky */
+float fgalaxyTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, Z, E, F, q, R, f, p2, p3;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  p2 = X / par[2];
+  p3 = Y / par[3];
+
+  Z = sqrt (0.5*p2*X + X*Y*par[4] + 0.5*p3*Y);                 /* R */
+  E = 1.0 / (1 + Z);   
+
+  q = par[5] * E;
+  R = q*E;
+  F = 0.5 / Z;
+  
+  f = q + par[6];
+
+  dpar[0] = F*R*(p2 + par[4]*Y);
+  dpar[1] = F*R*(p3 + par[4]*X);
+  dpar[2] = F*0.5*R*p2*p2;
+  dpar[3] = F*0.5*R*p3*p3;
+  dpar[4] = -R*X*Y*F;
+    
+  dpar[5] = E;
+  dpar[6] = 1;
+  return (f);
+}
+
+/* pars: x, y, sx, sy, sxy, I, sky */
+float fbarTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, Z, E, F, q, R, f, p2, p3;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  p2 = X / par[2];
+  p3 = Y / par[3];
+
+  Z = 0.5*p2*X + X*Y*par[4] + 0.5*p3*Y;                 /* R */
+  E = 1.0 / (1 + Z*Z*Z);   
+
+  q = par[5] * E;
+  F = 3*Z*Z;
+  R = q*E*F;
+  
+  f = q + par[6];
+
+  dpar[0] = R*(p2 + par[4]*Y);
+  dpar[1] = R*(p3 + par[4]*X);
+  dpar[2] = 0.5*R*p2*p2;
+  dpar[3] = 0.5*R*p3*p3;
+  dpar[4] = -R*X*Y;
+    
+  dpar[5] = E;
+  dpar[6] = 1;
+  return (f);
+}
+
+/* convert from x,y to major,minor */
+void fix_ellipsegauss_pars (float *par, int Npar) {
+
+  float p2, p4, angle, t1, t2, tmp, area;
+
+  /* par[0], par[1] = Xo, Yo - stay the same */
+
+  p2 = 1/par[2];
+  p4 = 1/par[3];
+
+  angle = 0.5 * atan2 (-2*par[4], p4 - p2); 
+
+  tmp = sqrt (SQ(p2 - p4) + 4*SQ(par[4]));
+  t1 = (p2 + p4 + tmp) / 2;
+  t2 = t1 - tmp;
+
+  par[2] = 2.35482*sqrt(1/t2);
+  par[3] = 2.35482*sqrt(1/t1);
+  par[4] = DEG_RAD * angle;
+
+  area = 2*M_PI/sqrt(t1*t2);
+
+  par[5] *= area;
+
+}
+# endif
+
+/***  options for later
+
+  Subtract = FALSE;
+  if ((N = get_argument (argc, argv, "-sub"))) {
+    remove_argument (N, &argc, argv);
+    Subtract  = TRUE;
+  }
+
+  DFact = 1;
+  if ((N = get_argument (argc, argv, "-D"))) {
+    remove_argument (N, &argc, argv);
+    DFact  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  fitfunc = fgaussTD;
+  if ((N = get_argument (argc, argv, "-gal"))) {
+    remove_argument (N, &argc, argv);
+    fitfunc = fgalaxyTD; 
+  }
+  if ((N = get_argument (argc, argv, "-bar"))) {
+    remove_argument (N, &argc, argv);
+    fitfunc = fbarTD; 
+  }
+
+
+  f1 = 1;
+  if ((c = get_variable ("BETA1")) != (char *) NULL) f1 = atof (c);
+
+  f2 = 1;
+  if ((c = get_variable ("BETA2")) != (char *) NULL) f2 = atof (c);
+
+  if (Subtract) {
+    tmpsky = par[6];
+    par[6] = 0;
+    for (N = j = 0; j < ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + (j+sy)*buf[0].matrix.Naxis[0] + sx; 
+      for (i = 0; i < nx; i++, V++, N++) {
+	dx = i + sx;
+	dy = j + sy;
+	*V -= fitfunc (dx, dy, par, Npar, (float *) NULL);
+      }
+    }
+    par[6] = tmpsky;
+  }
+
+***/
+
+# if (0)
+
+/* these two tests were not very succcessful.  the first did not model the shape well because 
+   it could not match the change in roundness with radius.  the second did not work because the 
+   parameters were degenerate (amplitude and slope of second component) */
+
+/* test: fixed, non-integer higher-order term -- x, y, sx, sy, sxy, I, sky, f1, f2 */
+float qgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f, k;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+  k = pow(z,1.75*par[8]);
+  r = 1.0 / (1 + z + par[7]*k); /* ~ exp (-Z) */
+  q = par[5]*r*r*(1 + 1.75*par[7]*par[8]*pow(z,1.75*par[8]-1));
+  /* note difference from gaussian: q = par[5]*r */
+  f = par[5]*r + par[6];
+
+  dpar[0] = q*(2*px*par[2] + par[4]*Y);
+  dpar[1] = q*(2*py*par[3] + par[4]*X);
+  dpar[2] = -2*q*px*X;
+  dpar[3] = -2*q*py*Y;
+  dpar[4] = -q*X*Y;
+  dpar[5] = +r;
+  dpar[6] = +1;
+  dpar[7] = -10*par[5]*r*r*k;
+  dpar[8] = -10*par[5]*r*r*par[7]*k*1.75*log(z);
+
+  return (f);
+}
+
+/* test: two component model: inner pseudo gaussian with outer z^1.75 x, y, sx, sy, sxy, I, sky */
+float rgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px1, py1, px2, py2;
+  float z1, z2, r1, r2, q1, q2, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px1 = par[2]*X;
+  py1 = par[3]*Y;
+  px2 = par[8]*X;
+  py2 = par[9]*Y;
+
+  z1 = 0.5*SQ(px1) + 0.5*SQ(py1) + par[4]*X*Y;
+  z2 = 0.5*SQ(px2) + 0.5*SQ(py2) + par[10]*X*Y;
+
+  r1 = 1.0 / (1 + z1 + 0.5*SQ(z1)*(1 + z1/3)); /* ~ exp (-Z) */
+  r2 = 1.0 / (1 + pow(z2,1.75));
+
+  f = par[5]*r1 + par[6] + par[7]*r2;
+
+  q1 = par[5]*SQ(r1)*(1 + z1 + 0.5*SQ(z1));
+  q2 = par[7]*SQ(r2)*(1.75*pow(z2,0.75));
+
+  dpar[	0] = q1*(2*px1*par[2] + par[4]*Y) + q2*(2*px2*par[8] + par[10]*Y);
+  dpar[	1] = q1*(2*py1*par[3] + par[4]*X) + q2*(2*py2*par[9] + par[10]*X);
+  dpar[	2] = -2*q1*px1*X;
+  dpar[	3] = -2*q1*py1*Y;
+  dpar[	4] = -q1*X*Y;
+  dpar[	5] = +r1;
+  dpar[	6] = +1;
+  dpar[	7] = +r2*2;
+  dpar[	8] = -2*q2*px2*X*2;
+  dpar[	9] = -2*q2*py2*Y*2;
+  dpar[10] = -q2*X*Y;
+
+  return (f);
+}
+
+# endif
+
+  /* forcing values to have a rational range
+  ALLOCATE (parmin, float, Npar);
+  ALLOCATE (parmax, float, Npar);
+  bzero (parmin, Npar*sizeof(float));
+  bzero (parmax, Npar*sizeof(float));
+  parmin[0] = parmin[1] = 0;
+  parmax[0] = buf[0].matrix.Naxis[0];
+  parmax[1] = buf[0].matrix.Naxis[1];
+
+  parmin[2] = parmin[3] = 0.01;
+  parmax[2] = parmax[3] = 100.0;
+  parmin[4] = -1000;
+  parmax[4] = -1000;
+  
+  parmin[5] = 1;
+  parmax[5] = 1e5;
+
+  parmin[6] = 0.0;
+  parmax[6] = 1e5;
+
+  if (Npar == 9) {
+    parmin[7] = parmin[8] = 0.01;
+    parmax[7] = parmax[8] = 10.0;
+  }
+  if (Npar == 10) {
+    parmin[7] = parmin[8] = 0.01;
+    parmax[7] = parmax[8] = 10.0;
+    parmin[9] = -1000;
+    parmax[9] = -1000;
+  }
+  */
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-tgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-tgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-tgauss.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "imfit.h"
+
+float tgaussTD (float, float, float *, int, float *);
+void  tgaussCL ();
+
+void tgauss_setup (char *name) {
+
+  if (strcmp(name, "tgauss")) return;
+
+  fitfunc = tgaussTD;
+  cleanup = tgaussCL;
+  Npar = 10;
+  Nfpar = 2;
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = 2.35 * sqrt(2.0) / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 * sqrt(2.0) / get_variable_default ("SYg", 2.0);
+  par[4] = 0.0;
+  par[5] = get_variable_default ("Zpk", 10000);
+  par[6] = get_variable_default ("Sg", 0.0);
+  par[7] = 2.35 * sqrt(2.0) / get_variable_default ("SXf", 15.0);
+  par[8] = 2.35 * sqrt(2.0) / get_variable_default ("SYf", 15.0);
+  par[9] = get_variable_default ("SXYf", 0.0);
+
+  fpar[0] = get_variable_default ("Npow", 2.25);
+  fpar[1] = get_variable_default ("Npin", 1.00); // drop this?
+
+  sky = &par[6];
+}
+
+/* two components: (1 + z_1^M + z_2^N)^(-1) -- x, y, sx1, sy1, sxy1, I, sky, sx2, sy2, sxy2 */
+float tgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px1, py1, px2, py2;
+  float z1, z2, r, q1, q2, f;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px1 = par[2]*X;
+  py1 = par[3]*Y;
+  px2 = par[7]*X;
+  py2 = par[8]*Y;
+
+  z1 = 0.5*SQ(px1) + 0.5*SQ(py1) + par[4]*X*Y;
+  z2 = 0.5*SQ(px2) + 0.5*SQ(py2) + par[9]*X*Y;
+
+  r = 1.0 / (1 + pow(z1,fpar[1]) + pow(z2,fpar[0]));
+  f = par[5]*r + par[6];
+
+  q1 = par[5]*SQ(r)*fpar[1]*pow(z1,(fpar[1]-1));
+  q2 = par[5]*SQ(r)*fpar[0]*pow(z2,(fpar[0]-1));
+
+  if (dpar != NULL) {
+    dpar[0] = q1*(2*px1*par[2] + par[4]*Y) + q2*(2*px2*par[7] + par[9]*Y);
+    dpar[1] = q1*(2*py1*par[3] + par[4]*X) + q2*(2*py2*par[8] + par[9]*X);
+    dpar[2] = -2*q1*px1*X*2;
+    dpar[3] = -2*q1*py1*Y*2;
+    dpar[4] = -q1*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -2*q2*px2*X;
+    dpar[8] = -2*q2*py2*Y;
+    dpar[9] = -q2*X*Y;
+  }
+  return (f);
+}
+
+int tgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 * sqrt(2.0) / par[2]);
+  set_variable ("SYg",  2.35 * sqrt(2.0) / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+  set_variable ("SXf",  2.35 * sqrt(2.0) / par[7]);
+  set_variable ("SYf",  2.35 * sqrt(2.0) / par[8]);
+  set_variable ("SXYf", par[9]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-vgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-vgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit-vgauss.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "imfit.h"
+
+float vgaussTD (float, float, float *, int, float *);
+void  vgaussCL ();
+
+void  vgauss_setup (char *name) {
+
+  if (strcmp(name, "vgauss")) return;
+
+  fitfunc = vgaussTD;
+  cleanup = vgaussCL;
+  Npar = 9;
+  Nfpar = 0;
+
+  par[0] = get_variable_default ("Xg", 0);
+  par[1] = get_variable_default ("Yg", 0);
+  par[2] = 2.35 * sqrt(2.0) / get_variable_default ("SXg", 2.0);
+  par[3] = 2.35 * sqrt(2.0) / get_variable_default ("SYg", 2.0);
+  par[4] = 0.0;
+  par[5] = get_variable_default ("Zpk", 10000);
+  par[6] = get_variable_default ("Sg", 0.0);
+  par[7] = 1;
+  par[8] = 1;
+  sky = &par[6];
+}
+
+/* pseudo 2D gaussian with floating 2nd and 3rd order terms -- x, y, sx, sy, sxy, I, sky, f1, f2 */
+float vgaussTD (float x, float y, float *par, int Npar, float *dpar) {
+
+  float X, Y, px, py;
+  float z, r, q, f, k;
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  px = par[2]*X;
+  py = par[3]*Y;
+
+  z = 0.5*SQ(px) + 0.5*SQ(py) + par[4]*X*Y;
+  k = 0.5*z*z*(1 + par[8]*z/3);
+  r = 1.0 / (1 + z + par[7]*k); /* ~ exp (-Z) */
+  f = par[5]*r + par[6];
+  q = par[5]*r*r*(1 + par[7]*z*(1 + par[8]*z/2));
+  /* note difference from gaussian: q = par[5]*r */
+
+  if (dpar != NULL) {
+    dpar[0] = q*(2*px*par[2] + par[4]*Y);
+    dpar[1] = q*(2*py*par[3] + par[4]*X);
+    dpar[2] = -2*q*px*X;
+    dpar[3] = -2*q*py*Y;
+    dpar[4] = -q*X*Y;
+    dpar[5] = +r;
+    dpar[6] = +1;
+    dpar[7] = -100*par[5]*r*r*k;
+    dpar[8] = -100*par[5]*r*r*par[7]*(z*z*z)/6;
+  }
+  return (f);
+}
+
+int vgaussCL () {
+  set_variable ("Xg",   par[0]);
+  set_variable ("Yg",   par[1]);
+  set_variable ("SXg",  2.35 * sqrt(2.0) / par[2]);
+  set_variable ("SYg",  2.35 * sqrt(2.0) / par[3]);
+  set_variable ("SXYg", par[4]);
+  set_variable ("Zpk",  par[5]);
+  set_variable ("Sg",   par[6]);
+  set_variable ("SXf", par[7]);
+  set_variable ("SYf", par[8]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imfit.c	(revision 16632)
@@ -0,0 +1,185 @@
+# include "imfit.h"
+
+int imfit (int argc, char **argv) {
+
+  int i, j, N, Npts, Save, VERBOSE, ShapeVariation;
+  int sx, sy, nx, ny, Nx, Ny;
+  float chisq, ochisq, dchisq, Gain, RDnoise, SatThreshold;
+  float *x, *y, *z, *dz, *V;
+  Buffer *buf;
+
+  Save = FALSE;
+  if ((N = get_argument (argc, argv, "-save"))) {
+    remove_argument (N, &argc, argv);
+    Save = TRUE;
+  }
+
+  ShapeVariation = FALSE;
+  if ((N = get_argument (argc, argv, "-shapes"))) {
+    remove_argument (N, &argc, argv);
+    ShapeVariation = TRUE;
+  }
+
+  SatThreshold = 0xffff;
+  if ((N = get_argument (argc, argv, "-sat"))) {
+    remove_argument (N, &argc, argv);
+    SatThreshold = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* Gain in e/DN */
+  Gain = 1.0;
+  if ((N = get_argument (argc, argv, "-gain"))) {
+    remove_argument (N, &argc, argv);
+    Gain = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* RD noise in DN */
+  RDnoise = 0.0;
+  if ((N = get_argument (argc, argv, "-rdnoise"))) {
+    remove_argument (N, &argc, argv);
+    RDnoise = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  /* set fitting function */
+  fgauss_setup ("fgauss");
+  if ((N = get_argument (argc, argv, "-func"))) {
+    fitfunc = NULL;
+    remove_argument (N, &argc, argv);
+    fgauss_setup (argv[N]);
+    pgauss_setup (argv[N]);
+    pgauss_psf_setup (argv[N]);
+    sgauss_setup (argv[N]);
+    sgauss_psf_setup (argv[N]);
+    qgauss_setup (argv[N]);
+    qgauss_psf_setup (argv[N]);
+    qfgauss_setup (argv[N]);
+    qrgauss_setup (argv[N]);
+    if (fitfunc == NULL) {
+      gprint (GP_ERR, "unknown function %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: imfit <buffer> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  /* non-optional arguments */
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  /* check if region is valid */
+  if (sx + 0.5*nx < 0) goto range;
+  if (sy + 0.5*ny < 0) goto range;
+  if (sx + 0.5*nx >= Nx) goto range;
+  if (sy + 0.5*ny >= Ny) goto range;
+
+  /* convert array z[x,y] to x[i], y[i], z[i] */
+  N = 0;
+  Npts = nx*ny;
+  ALLOCATE (x,  float, 2*Npts);
+  ALLOCATE (y,  float, 2*Npts);
+  ALLOCATE (z,  float, 2*Npts);
+  ALLOCATE (dz, float, 2*Npts);
+  for (j = 0; j < ny; j++) {
+    if (j + sy < 0) continue;
+    if (j + sy >= Ny) continue;
+    V = (float *)(buf[0].matrix.buffer) + (j+sy)*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++) {
+      if (i + sx < 0) continue;
+      if (i + sx >= Nx) continue;
+      if (*V > SatThreshold) goto next;
+      dz[N] = (SQ(RDnoise) + *V/Gain);
+      if (dz[N] <= 0) goto next;
+      dz[N] = 1.0 / dz[N];
+      x[N] = i + sx;
+      y[N] = j + sy;
+      z[N] = *V;
+      N++;
+    next:
+      V++;
+    }
+  }
+  Npts = N;
+
+  /* run fit routine */
+  ochisq = mrq2dinit (x, y, z, dz, Npts, par, Npar, fitfunc, VERBOSE);
+  dchisq = ochisq;
+  chisq  = ochisq;
+  for (i = 0; (i < 25) && ((dchisq <= 0.0) || (dchisq > 0.01*(Npts - Npar))); i++) {
+    chisq = mrq2dmin (x, y, z, dz, Npts, par, Npar, fitfunc, VERBOSE);
+    dchisq = ochisq - chisq;
+    ochisq = chisq;
+  }  
+  set_int_variable ("Niter",  i);
+
+  /** create output image (keep in sky) **/
+  if (Save) {
+    Buffer *out;
+    float *Vi, *Vo, vr, vf;
+
+    if ((out = SelectBuffer ("out",   ANYBUFFER, TRUE)) == NULL) return (FALSE);
+    free (out[0].header.buffer);
+    free (out[0].matrix.buffer);
+
+    strcpy (out[0].file, "(empty)");
+    CreateBuffer (out, 2*nx, 2*ny, -32, 0.0, 1.0);
+
+    /* four panels: 1) raw image. 2) fit  3) raw - fit   4) ?? */
+    Vi = (float *)buf[0].matrix.buffer;
+    Vo = (float *)out[0].matrix.buffer;
+    for (j = 0; j < ny; j++) {
+      for (i = 0; i < nx; i++) {
+	vf = fitfunc ((float)(i+sx), (float)(j+sy), par, Npar, NULL);
+	vr = Vi[(i+sx)+(j+sy)*Nx];
+	Vo[(i   )+(j   )*2*nx] = vr;
+	Vo[(i+nx)+(j   )*2*nx] = vf;
+	Vo[(i   )+(j+ny)*2*nx] = vr - vf + *sky;
+	Vo[(i+nx)+(j+ny)*2*nx] = fabs(vr-vf) + *sky;
+      }
+    }
+  }
+
+  /* save parameters to opihi variables */
+  imfit_cleanup ();
+
+  set_variable ("ChiSq", chisq/(Npts - Npar));
+
+  if (VERBOSE) {
+    for (i = 0; i < Npar; i++) {
+      gprint (GP_ERR, "%g ", par[i]);
+    }
+    gprint (GP_ERR, "\n");
+  }
+
+  free (x);
+  free (y);
+  free (z);
+  free (dz);
+  free (par);
+  free (fpar);
+
+  mrq2dfree (Npar);
+  return (TRUE);
+
+range:
+  gprint (GP_ERR, "region out of range\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imsub.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imsub.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/imsub.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "imfit.h"
+
+int imsub (int argc, char **argv) {
+
+  int i, j, N, VERBOSE;
+  int sx, sy, nx, ny, Nx, Ny;
+  float value;
+  float *V;
+  Buffer *buf;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  /* set fitting function */
+  fgauss_setup ("fgauss");
+  if ((N = get_argument (argc, argv, "-func"))) {
+    fitfunc = NULL;
+    remove_argument (N, &argc, argv);
+    fgauss_setup (argv[N]);
+    pgauss_setup (argv[N]);
+    pgauss_psf_setup (argv[N]);
+    sgauss_setup (argv[N]);
+    sgauss_psf_setup (argv[N]);
+    qgauss_setup (argv[N]);
+    qgauss_psf_setup (argv[N]);
+    qfgauss_setup (argv[N]);
+    qrgauss_setup (argv[N]);
+    if (fitfunc == NULL) {
+      gprint (GP_ERR, "unknown function %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: imfit <buffer> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  /* non-optional arguments */
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  /* check if region is valid */
+  if (sx >= Nx) goto range;
+  if (sy >= Ny) goto range;
+  if (sx + nx < 0) goto range;
+  if (sy + ny < 0) goto range;
+
+  /* subtract model fit, but not local sky */
+  for (j = 0; j < ny; j++) {
+    if (j + sy < 0) continue;
+    if (j + sy >= Ny) continue;
+    V = (float *)(buf[0].matrix.buffer) + (j+sy)*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      if (i + sx < 0) continue;
+      if (i + sx >= Nx) continue;
+      value = fitfunc ((float)(i+sx), (float)(j+sy), par, Npar, NULL);
+      *V -= value;
+    }
+  }
+
+  free (par);
+  free (fpar);
+  return (TRUE);
+
+range:
+  gprint (GP_ERR, "region out of range\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/init.c	(revision 16632)
@@ -0,0 +1,88 @@
+# include "astro.h"
+
+int biassub                 PROTO((int, char **));
+int cgrid                   PROTO((int, char **));
+int coords                  PROTO((int, char **));
+int cplot                   PROTO((int, char **));
+int csystem                 PROTO((int, char **));
+int ctimes                  PROTO((int, char **));
+int cval                    PROTO((int, char **));
+int czplot                  PROTO((int, char **));
+int drizzle                 PROTO((int, char **));
+int flux                    PROTO((int, char **));
+int fixwrap                 PROTO((int, char **));
+int gauss                   PROTO((int, char **));
+int gaussfit                PROTO((int, char **));
+int getvel                  PROTO((int, char **));
+int getlst                  PROTO((int, char **));
+int imfit                   PROTO((int, char **));
+int imsub                   PROTO((int, char **));
+int medianmap               PROTO((int, char **));
+int mkgauss                 PROTO((int, char **));
+int multifit                PROTO((int, char **));
+int objload                 PROTO((int, char **));
+int outline                 PROTO((int, char **));
+int polar                   PROTO((int, char **));
+int precess                 PROTO((int, char **));
+int profile                 PROTO((int, char **));
+int region                  PROTO((int, char **));
+int rotcurve                PROTO((int, char **));
+int scale                   PROTO((int, char **));
+int sexigesimal             PROTO((int, char **));
+int spec                    PROTO((int, char **));
+int star                    PROTO((int, char **));
+int times                   PROTO((int, char **));
+int transform               PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "biassub",     biassub,      "subtract medianed overscan row or column"},
+  {1, "cgrid",       cgrid,        "plot sky coordinate grid"},
+  {1, "coords",      coords,       "load coordinates for buffer from file"},
+  {1, "cplot",       cplot,        "plot vectors in sky coordinates"},
+  {1, "csystem",     csystem,      "convert between coordinate systems"},
+  {1, "ctimes",      ctimes,       "convert between time formats"},
+  {1, "cval",        cval,         "cosmic ray flux?"},
+  {1, "czplot",      czplot,       "plot scaled vectors in sky coordinates"},
+  {1, "drizzle",     drizzle,      "transform image to image"},
+  {1, "flux",        flux,         "flux in a convex contour"},
+  {1, "fixwrap",     fixwrap,      "fix megacam over-wrapped pixels"},
+  {1, "gauss",       gauss,        "get statistics on a star, assuming gaussian profile"},
+  {1, "getvel",      getvel,       "rotcurve to velocities"},
+  {1, "getlst",      getlst,       "return LST given time and longitude"},
+  {1, "imfit",       imfit,        "fit function"},
+  {1, "imsub",       imsub,        "subtract function"},
+  {1, "medianmap",   medianmap,    "small median image"},
+  {1, "mkgauss",     mkgauss,      "generate a 2-D gaussian centered in image"},
+  {1, "multifit",    multifit,     "fit multi-order spectrum"},
+  {1, "objload",     objload,      "plot obj data on Ximage "},
+  {1, "outline",     outline,      "fit outline region"},
+  {1, "polar",       polar,        "convert polar image to cartesian"},
+  {1, "precess",     precess,      "precess coordinates"},
+  {1, "profile",     profile,      "radial profile at X, Y"},
+  {1, "region",      region,       "define sky region for plot"},
+  {1, "rotcurve",    rotcurve,     "convert CO images to polar coords"},
+  {1, "scale",       scale,        "get / set real bzero / bscale values"},
+  {1, "sexigesimal", sexigesimal,  "convert to/from sexigesimal/decimal"},
+  {1, "spec",        spec,         "extract a spectrum"},
+  {1, "star",        star,         "star stats at rough coords"},
+  {1, "transform",   transform,    "geometric transformation of image"},
+}; 
+
+/* not currently implemented 
+  {"gaussfit",    gaussfit,     "fit a gaussian to pixels in a region"},
+  {"testfit",     testfit, ""},
+  {"times", , ""},
+*/
+
+void InitAstro () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
+
+void FreeAstro () {
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/medianmap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/medianmap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/medianmap.c	(revision 16632)
@@ -0,0 +1,114 @@
+# include "astro.h"
+
+int medianmap (int argc, char **argv) {
+  
+  float *temp, *tp;
+  int i, j, k, I0, I1, J0, J1, I, J, n, N;
+  int nx, ny, Nx, Ny, NX, NY, Ignore;
+  float Mv, Nv, Mv2, value, min, max, IgnoreValue;
+  float *In, *Out, *ip;
+  float fx, fy;
+  Buffer *in, *out;
+
+  IgnoreValue = 0;
+  Ignore = FALSE;
+  if ((N = get_argument (argc, argv, "-ignore"))) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  min = 0.45;
+  max = 0.55;
+  if ((N = get_argument (argc, argv, "-range"))) {
+    remove_argument (N, &argc, argv);
+    min  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    max  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: medianmap (in) (out) Nx Ny [-range min max]\n");
+    gprint (GP_ERR, "       Nx, Ny specify dimensions of output image\n");
+    gprint (GP_ERR, "       min, max specify fractional range for sorted average\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = atof (argv[3]);
+  Ny = atof (argv[4]);
+  NX = in[0].header.Naxis[0];
+  NY = in[0].header.Naxis[1];
+
+  /* duplicate the (in) buffer to the (out), with different size */
+  /* this should probably be a function in misc */
+  gfits_free_matrix (&out[0].matrix);
+  gfits_free_header (&out[0].header);
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  gfits_copy_header (&in[0].header, &out[0].header);
+  gfits_modify (&out[0].header, "NAXIS1", "%d", 1, Nx);
+  gfits_modify (&out[0].header, "NAXIS2", "%d", 1, Ny);
+  out[0].header.Naxis[0] = Nx;
+  out[0].header.Naxis[1] = Ny;
+  gfits_create_matrix (&out[0].header, &out[0].matrix);
+
+  In = (float *) in[0].matrix.buffer;
+  Out = (float *) out[0].matrix.buffer;
+
+  fx = (float) Nx / NX;
+  fy = (float) Ny / NY;
+
+  nx = 1 + 1/fx;
+  ny = 1 + 1/fy;
+
+  ALLOCATE (temp, float, 2*nx*ny);
+
+  Nv = Mv = Mv2 = 0.0;
+
+  for (j = 0; j < Ny; j++) {
+    J0 = j / fy;
+    J1 = (j + 1) / fy;
+    for (i = 0; i < Nx; i++) {
+      
+      I0 = i / fx;
+      I1 = (i + 1) / fx;
+
+      n = 0;
+      tp = temp;
+      for (J = J0; J < J1; J++) {
+	ip = &In[J*NX + I0];
+	for (I = I0; I < I1; I++, tp++, ip++) {
+	  if (Ignore && (fabs (*ip - IgnoreValue) < 0.01)) continue;
+	  if (isnan (*ip)) continue;
+	  if (isinf (*ip)) continue;
+	  *tp = *ip;
+	  n++;
+	}
+      }
+
+      fsort (temp, n);
+
+      value = 0;
+      N = 0;
+      for (k = min*n; k < max*n; k++) {
+	value += temp[k];
+	N ++;
+      }
+      if (N == 0)
+	Out[j*Nx + i] = 0;
+      else 
+	Out[j*Nx + i] = value / N;
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/mkgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/mkgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/mkgauss.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "astro.h"
+
+int mkgauss (int argc, char **argv) {
+  
+  int i, j, Nx, Ny, N;
+  float *in;
+  double Sig_x, Sig_y, Theta;
+  double root1, root2, R, A1, A2, A3;
+  double Sx, Sy, Sxy;
+  double x, y, r, f, Xo, Yo;
+  Buffer *buf;
+
+  Xo = Yo = 0;
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    Xo = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    Yo = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc < 3) || (argc > 5)) {
+    gprint (GP_ERR, "USAGE: mkgauss (buffer) (sigma) [[sy/sx] angle]\n");
+    return (FALSE);
+  }
+
+  /* select input / output buffers */
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Nx = buf[0].header.Naxis[0];
+  Ny = buf[0].header.Naxis[1];
+  
+  /* gaussian parameters */
+  Sig_x = atof (argv[2]);
+  Sig_y = Sig_x;
+  Theta = 0.0;
+  if (argc > 3) {
+    Sig_y = Sig_x*atof (argv[3]);
+    if (argc == 5) {
+      Theta = atof (argv[4]);
+    }
+  }
+
+  /* given Sig_x, Sig_y, Theta, find Sx, Sy, Sxy */
+  root1 = SQ(1.0 / Sig_y);
+  root2 = SQ(1.0 / Sig_x);
+
+  R = 0.5 * (root1 - root2);
+  A1 = 0.25*(root1 + root2) - 0.5*R*cos(2*RAD_DEG*Theta);
+  A2 = 0.25*(root1 + root2) + 0.5*R*cos(2*RAD_DEG*Theta);
+  A3 = -R*sin(2*RAD_DEG*Theta);
+
+  Sx = 0.5/A1;
+  Sy = 0.5/A2;
+  Sxy = A3;
+
+  /* f = exp (-r), r = (x^2 / 2Sx) + (y^2 / 2Sy) + Sxy*x*y */
+
+  in = (float *) buf[0].matrix.buffer;
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++, in++) {
+
+      x = i - Xo;
+      y = j - Yo;
+      r = 0.5*x*x/Sx + 0.5*y*y/Sy + x*y*Sxy;
+      f = exp (-r);
+      *in += f;
+    }
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/multifit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/multifit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/multifit.c	(revision 16632)
@@ -0,0 +1,179 @@
+# include "astro.h"
+
+int multifit (int argc, char **argv) {
+  
+  char *p, name[64];
+  double **a, **b, v;
+  int i, j, I, J, n, valid;
+  Vector **Nc, **Nmb, **NMb, **Nwb, **Nmh, **Nml, **Nwo;
+  int *nterm;
+  int Ndim, Norder, Nx, Ny;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: multifit (Norder)\n");
+    return (FALSE);
+  }
+
+  Ndim = 0;
+  Norder = atoi (argv[1]);
+  ALLOCATE (nterm, int, Norder);
+  for (i = 0; i < Norder; i++) {
+    sprintf (name, "nterm:%d", i);
+    p = get_variable (name);
+    nterm[i] = atoi (p); 
+    Ndim += nterm[i];
+    free (p);
+  }
+
+  ALLOCATE (a, double *, Ndim);
+  ALLOCATE (b, double *, Ndim);
+  for (i = 0; i < Ndim; i++) {
+    ALLOCATE (a[i], double, Ndim);
+    ALLOCATE (b[i], double, 1);
+    bzero (a[i], Ndim*sizeof(double));
+    bzero (b[i], sizeof(double));
+  }
+ 
+  ALLOCATE (Nc,  Vector *, Norder);
+  ALLOCATE (NMb, Vector *, Norder);
+  ALLOCATE (Nmb, Vector *, Norder);
+  ALLOCATE (Nwb, Vector *, Norder);
+  ALLOCATE (Nmh, Vector *, Norder - 1);
+  ALLOCATE (Nml, Vector *, Norder - 1);
+  ALLOCATE (Nwo, Vector *, Norder - 1);
+  
+  for (i = 0; i < Norder; i++) {
+    sprintf (name, "c%d", i);
+    if ((Nc[i]  = SelectVector (name, ANYVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "Mb%d", i);
+    if ((NMb[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "mb%d", i);
+    if ((Nmb[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "wb%d", i);
+    if ((Nwb[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+  }
+  for (i = 0; i < Norder - 1; i++) {
+    sprintf (name, "ml%d", i);
+    if ((Nml[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "mh%d", i);
+    if ((Nmh[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+    sprintf (name, "wo%d", i);
+    if ((Nwo[i] = SelectVector (name, OLDVECTOR, TRUE)) == NULL) goto escape;
+  }
+
+  Ny = 0;
+  for (i = 0; i < Norder; i++) {
+    for (j = 0; j < nterm[i]; j++, Ny++) {
+      Nx = 0;
+      valid = FALSE;
+      for (I = 0; I < Norder; I++) {
+	if (I == i - 1) { 
+	  for (J = 0; J < nterm[I]; J++) {
+	    v = 0;
+	    for (n = 0; n < Nwo[i-1][0].Nelements; n++) {
+	      v += -pow (Nwo[i-1][0].elements[n], (double)(j+J));
+	    }
+	    a[Ny][Nx] = v;
+	    Nx ++;
+	  }
+	  valid = TRUE;
+	}
+	if (I == i + 1) { 
+	  for (J = 0; J < nterm[I]; J++) {
+	    v = 0;
+	    for (n = 0; n < Nwo[i][0].Nelements; n++) {
+	      v += -pow (Nwo[i][0].elements[n], (double)(j+J));
+	    }
+	    a[Ny][Nx] = v;
+	    Nx ++;
+	  }
+	  valid = TRUE;
+	}
+	if (I == i) { 
+	  for (J = 0; J < nterm[I]; J++) {
+	    v = 0;
+	    for (n = 0; n < Nwb[i][0].Nelements; n++) {
+	      v += pow (Nwb[i][0].elements[n], (double)(j+J));
+	    }
+	    if (i > 0) {
+	      for (n = 0; n < Nwo[i-1][0].Nelements; n++) {
+		v += pow (Nwo[i-1][0].elements[n], (double)(j+J));
+	      }
+	    }
+	    if (i < Norder - 1) {
+	      for (n = 0; n < Nwo[i][0].Nelements; n++) {
+		v += pow (Nwo[i][0].elements[n], (double)(j+J));
+	      }
+	    }
+	    a[Ny][Nx] = v;
+	    Nx ++;
+	  }
+	  valid = TRUE;
+	}
+	if (!valid) {
+	  Nx += nterm[I];
+	}
+      }
+    }
+  }
+
+  Ny = 0;
+  for (i = 0; i < Norder; i++) {
+    for (j = 0; j < nterm[i]; j++, Ny++) {
+      v = 0;
+      for (n = 0; n < Nwb[i][0].Nelements; n++) {
+	v += NMb[i][0].elements[n]*pow (Nwb[i][0].elements[n], (double)j);
+	v -= Nmb[i][0].elements[n]*pow (Nwb[i][0].elements[n], (double)j);
+      }
+      if (i > 0) {
+	for (n = 0; n < Nwo[i-1][0].Nelements; n++) {
+	  v += Nmh[i-1][0].elements[n] * pow (Nwo[i-1][0].elements[n], (double)j);
+	  v -= Nml[i-1][0].elements[n] * pow (Nwo[i-1][0].elements[n], (double)j);
+	}
+      }
+      if (i < Norder - 1) {
+	for (n = 0; n < Nwo[i][0].Nelements; n++) {
+	  v += Nml[i][0].elements[n] * pow (Nwo[i][0].elements[n], (double)j);
+	  v -= Nmh[i][0].elements[n] * pow (Nwo[i][0].elements[n], (double)j);
+	}
+      }
+      b[Ny][0] = v;
+    }
+  }
+  dgaussjordan (a, b, Ndim, 1);
+
+  Ny = 0;
+  for (i = 0; i < Norder; i++) {
+    Nc[i][0].Nelements = nterm[i];
+    REALLOCATE (Nc[i][0].elements, float, nterm[i]);
+    for (j = 0; j < nterm[i]; j++, Ny++) {
+      Nc[i][0].elements[j] = b[Ny][0];
+    }
+  }
+
+  for (i = 0; i < Ndim; i++) {
+    free (a[i]);
+    free (b[i]);
+  }
+  free (a);
+  free (b);
+  free (nterm);
+  free (Nc);
+  free (NMb);
+  free (Nmb);
+  free (Nwb);
+  free (Nmh);
+  free (Nml);
+  free (Nwo);
+  
+  return (TRUE);
+  
+ escape: 
+  gprint (GP_ERR, "syntax error\n");
+  return (FALSE);
+  
+}
+
+
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/objload.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/objload.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/objload.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "dvoshell.h"
+# define CHAR_LINE 104
+# define NBLOCK 100
+
+int objload (int argc, char **argv) {
+  
+  int i, N, Objtype, type, Nline, status;
+  FILE *f;
+  char *buffer, *line, *name;
+  int kapa, Noverlay, NOVERLAY;
+  KiiOverlay *overlay;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  Objtype = 0;
+  if ((N = get_argument (argc, argv, "-t"))) {
+    remove_argument (N, &argc, argv);
+    Objtype = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: objload (overlay) <filename>\n");
+    return (FALSE);
+  }
+
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "ERROR: can't find object file %s\n", argv[2]);
+    return (FALSE);
+  }
+
+  /* read average values from first line */
+  ALLOCATE (line, char, 129);
+  scan_line (f, line);
+
+  ALLOCATE (buffer, char, CHAR_LINE*NBLOCK);
+
+  Noverlay = 0;
+  NOVERLAY = 1000;
+  ALLOCATE (overlay, KiiOverlay, Noverlay);
+  
+  /* read in data from obj file */
+  while ((Nline = fread (buffer, CHAR_LINE, NBLOCK, f)) > 0) {
+    for (i = 0; i < Nline; i++) {
+      /* we are now using all entries on the *.obj line */
+      status = sscanf (&buffer[i*CHAR_LINE], "%d %f %f",  &type, &overlay[Noverlay].x, &overlay[Noverlay].y);
+      if (Objtype && (Objtype != type)) continue;
+      overlay[Noverlay].type = KII_OVERLAY_BOX;
+      overlay[Noverlay].dx = 5.0;
+      overlay[Noverlay].dy = 5.0;
+      Noverlay ++;
+      CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000);
+    }
+  }
+  fclose (f);
+  free (buffer);
+
+  KiiLoadOverlay (kapa, overlay, Noverlay, argv[1]);
+
+  free (overlay);
+  free (buffer);
+  free (line);
+
+  gprint (GP_ERR, "loaded %d objects\n", Noverlay);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/outline.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/outline.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/outline.c	(revision 16632)
@@ -0,0 +1,289 @@
+# include "astro.h"
+
+float par[5];
+float dpar[5];
+float Dpar[5];
+float outline_chi (float, float *, int, int, float *);
+
+int outline (int argc, char **argv) {
+  
+  int i, j, k, Npar, BigChange, ABigChange;
+  float Io, *in, ochisq, dchi, chisq, chisq_p, chisq_m, dp, tmp_par;
+  float curve, frac;
+  Buffer *buf;
+
+  if (argc != 9) {
+    gprint (GP_ERR, "USAGE: outline x y dx dy dxy Io (buffer) Npar\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[7], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  par[0] = atof(argv[1]);
+  par[1] = atof(argv[2]);
+  par[2] = atof(argv[3]);
+  par[3] = atof(argv[4]);
+  par[4] = atof(argv[5]);
+  Io = atof(argv[6]);
+  Npar = atof (argv[8]);
+
+  dpar[0] = 10;
+  dpar[1] = 10;
+  dpar[2] = 10;
+  dpar[3] = 10;
+  dpar[4] = 10;
+
+  Dpar[0] = 10;
+  Dpar[1] = 10;
+  Dpar[2] = 10;
+  Dpar[3] = 10;
+  Dpar[4] = 10;
+
+  in = (float *) buf[0].matrix.buffer;
+
+  chisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+  gprint (GP_ERR, "chisq (1): %f\n", chisq);
+  
+  for (j = 0; j < 15; j++) {
+
+    /*
+    if (!(j % 3)) {
+      chisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+      for (k = 0; (k < 3) && (fabs (frac) > 0.3); k++) {
+	tmp1 = par[2];
+	tmp2 = par[3];
+	par[2] *= 1 + 0.1*frac;
+	par[3] *= 1 + 0.1*frac;
+	nchisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	if (nchisq > chisq) {
+	  par[2] = tmp1;
+	  par[3] = tmp2;
+	  k = 3;
+	} else {
+	  chisq = nchisq;
+	}
+	gprint (GP_ERR, "frac: %f  %f %f   %f\n", frac, par[2], par[3], chisq);
+      }
+    }
+    */
+    
+    ABigChange = FALSE;
+    ochisq = chisq;
+    for (i = 4; i >= 0; i--) {
+      /* find +chisq, -chisq for this par & adjust par as needed */
+
+      for (k = 0, BigChange = TRUE; (k < 3) && BigChange; k++) {
+	tmp_par = par[i];
+	par[i] = tmp_par + dpar[i];
+	chisq_p = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	par[i] = tmp_par - dpar[i];
+	chisq_m = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	
+	/* have we braketted a minimum? (curve < 0) */
+	curve = (chisq_p - chisq) * (chisq - chisq_m);
+	if (curve > 0) {
+	  dp = 2*dpar[i];
+	} else {
+	  dp = 0.5 * dpar[i] * (chisq_m - chisq_p) / (chisq_m + chisq_p - 2*chisq);
+	}      
+	if (chisq_m + chisq_p - 2*chisq == 0) dp = 0;
+	/* don't let extrapolation go too far */
+	if (fabs (dp) > 2*fabs(dpar[i])) { dp = SIGN(dp) * fabs (2*dpar[i]); }
+	
+	par[i] = tmp_par + dp;
+	chisq = outline_chi (Io, in, buf[0].matrix.Naxis[0], buf[0].matrix.Naxis[1], &frac);
+	
+	BigChange = FALSE;
+	if (chisq <= 1.001*ochisq) {
+	  /* got better */
+	  dchi = (ochisq - chisq) / ochisq; 
+	  if ((dchi > 0.03) || (curve > 0)) BigChange = TRUE;
+	} else {
+	  par[i] = tmp_par;
+	  chisq = ochisq;
+	  if (chisq_m < chisq) {
+	    chisq = chisq_m;
+	    par[i] = tmp_par - dpar[i];
+	  }	
+	  if (chisq_p < chisq) {
+	    chisq = chisq_p;
+	    par[i] = tmp_par + dpar[i];
+	  }	
+	}	
+	/*
+	gprint (GP_ERR, "try: %d  %f   ", i, chisq);
+	for (k = 0; k < 5; k++) {
+	  gprint (GP_ERR, "%f ", par[k]);
+	}
+	gprint (GP_ERR, "\n");
+	*/
+	ochisq = chisq;
+	ABigChange |= BigChange;
+      }
+      if (!BigChange) dpar[i] *= 0.8;
+    }
+
+    if (ABigChange) {
+      for (i = 0; i < 5; i++) {
+	dpar[i] = Dpar[i];
+      }
+    }
+
+    gprint (GP_ERR, "try: %d  %f   ", j, chisq);
+    for (i = 0; i < 5; i++) {
+      gprint (GP_ERR, "%f ", par[i]);
+    }
+    gprint (GP_ERR, "\n          ");
+    for (i = 0; i < 5; i++) {
+      gprint (GP_ERR, "%f ", dpar[i]);
+    }
+    gprint (GP_ERR, "\n");
+    dchi -= chisq;
+
+  }
+
+    /* code to draw dots on Ximage */
+    {
+      int kapa;
+      float xp, yp, x, y;
+      float dx, dy, theta, t, dt;
+      int Noverlay, NOVERLAY;
+      KiiOverlay *overlay;
+      
+      if (!GetImage (NULL, &kapa, NULL)) return (FALSE);
+      
+      Noverlay = 0;
+      NOVERLAY = 1000;
+      ALLOCATE (overlay, KiiOverlay, Noverlay);
+  
+      dx = par[2];
+      dy = par[3];
+      dt = 1 / MAX (dx, dy);
+      theta = par[4];
+      
+      for (t = 0; t < 6.3; t += dt) {
+	xp = dx * cos (t);
+	yp = dy * sin (t);
+	
+	x = xp * cos (theta * RAD_DEG) - yp * sin (theta * RAD_DEG) + par[0];
+	y = xp * sin (theta * RAD_DEG) + yp * cos (theta * RAD_DEG) + par[1];
+	
+	overlay[Noverlay].type = KII_OVERLAY_BOX;
+	overlay[Noverlay].x = x;
+	overlay[Noverlay].y = y;
+	overlay[Noverlay].dx = 1.0;
+	overlay[Noverlay].dy = 1.0;
+
+	Noverlay ++;
+	CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000);
+      }
+      KiiLoadOverlay (kapa, overlay, Noverlay, "red");
+      free (overlay);
+    }
+
+  return (TRUE);
+
+}
+
+/* par[0] = x
+   par[1] = y
+   par[2] = dx
+   par[3] = dy
+   par[4] = dxy
+   
+   ellipse is:  
+
+   ((X-x)/dx)^2 + ((Y-y)/dy)^2 + (X-x)(Y-y)dxy = 1
+  
+   (yp/dy)^2 + xp yp dxy + (xp/dx)^2 - 1 = 0
+
+   yp^2 + yp xp dxy dy^2 + xp^2 (dy/dx)^2 - dy^2 = 0
+
+*/
+
+float outline_chi (float Io, float *in, int Nx, int Ny, float *frac) {
+
+  int npts, xo, yo, x, y;
+  float xp, yp, dx, dy, theta;
+  float t, dt, dv, Dv;
+  float chisq, v, Frac;
+
+  /* 
+  if (!SelectVector (&Nvec, "diffs", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvec2, "angle", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecx, "xdif", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecy, "ydif", ANYVECTOR)) return (FALSE);
+  */
+
+  dx = par[2];
+  dy = par[3];
+  theta = par[4];
+  dt = 1 / MAX (dx, dy);
+
+  Frac = 0;
+  chisq = 0;
+  npts = 0;
+  xo = -1; yo = -1;  /* an impossible coordinate */
+
+  /*
+  Npts = 1000;
+  REALLOCATE (vectors[Nvec].elements, float, Npts);
+  REALLOCATE (vectors[Nvec2].elements, float, Npts);
+  REALLOCATE (vectors[Nvecx].elements, float, Npts);
+  REALLOCATE (vectors[Nvecy].elements, float, Npts);
+  */
+
+  for (t = 0; t < 6.3; t += dt) {
+    xp = dx * cos (t);
+    yp = dy * sin (t);
+    
+    x = xp * cos (theta * RAD_DEG) - yp * sin (theta * RAD_DEG) + par[0];
+    y = xp * sin (theta * RAD_DEG) + yp * cos (theta * RAD_DEG) + par[1];
+    
+    if ((x == xo) && (y == yo)) continue;
+    xo = x; yo = y;
+
+    if ((x >= 0) && (x < Nx) && (y >= 0) && (y < Ny)) {
+      v = in[y*Nx + x];
+      if (v > 0) {
+	Dv = v - Io;
+	dv = v + 0.2 * fabs (Dv);
+	chisq += Dv * Dv / dv;
+	if (Dv > sqrt(dv)) Frac += 1.0;
+	if (Dv < sqrt(dv)) Frac -= 1.0;
+	/*
+	vectors[Nvec].elements[npts] = Dv;
+	vectors[Nvec2].elements[npts] = t*DEG_RAD;
+	vectors[Nvecx].elements[npts] = x;
+	vectors[Nvecy].elements[npts] = y;
+	*/
+	npts ++;
+	/* 
+	if (npts == Npts - 1) {
+	  Npts += 1000;
+	  REALLOCATE (vectors[Nvec].elements, float, Npts);
+	  REALLOCATE (vectors[Nvec2].elements, float, Npts);
+	  REALLOCATE (vectors[Nvecx].elements, float, Npts);
+	  REALLOCATE (vectors[Nvecy].elements, float, Npts);
+	}
+	*/
+      }
+    }
+  }
+  /* 
+  vectors[Nvec].Nelements = npts;
+  vectors[Nvec2].Nelements = npts;
+  vectors[Nvecx].Nelements = npts;
+  vectors[Nvecy].Nelements = npts;
+  */
+
+  chisq = chisq / npts;
+  *frac = Frac / npts;
+  if (npts == 0) {
+    chisq = 1e8;
+    *frac = -1.0;
+  }
+
+  return (chisq);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/outline2.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/outline2.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/outline2.c	(revision 16632)
@@ -0,0 +1,341 @@
+# include "astro.h"
+
+int Npts;
+float *xs, *ys, *zs;
+float par[5];
+float dpar[5];
+float Dpar[5];
+float outline_chi (float, float *);
+int plot_outline ();
+
+int outline (int argc, char **argv) {
+  
+  int i, j, k, Nx, Ny, NPTS, BigChange;
+  float dIo, Io, ochisq, dchi, chisq, chisq_p, chisq_m, dp;
+  float tmp_par, curve, value;
+  float *in;
+  Buffer *buf;
+
+  if (argc != 9) {
+    gprint (GP_ERR, "USAGE: outline x y dx dy dxy Io dIo (buffer)\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[8], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  par[0] = atof(argv[1]);
+  par[1] = atof(argv[2]);
+  par[2] = atof(argv[3]);
+  par[3] = atof(argv[4]);
+  par[4] = atof(argv[5]);
+  Io = atof(argv[6]);
+  dIo = atof(argv[7]);
+
+  dpar[0] = 10;
+  dpar[1] = 10;
+  dpar[2] = 10;
+  dpar[3] = 10;
+  dpar[4] = 10;
+
+  Dpar[0] = 10;
+  Dpar[1] = 10;
+  Dpar[2] = 10;
+  Dpar[3] = 10;
+  Dpar[4] = 10;
+
+  in = (float *) buf[0].matrix.buffer;
+
+  /* find all pixels within range Io-dIo : Io+dIo, in region about center guess */
+
+  Nx = buf[0].matrix.Naxis[0];  
+  Ny = buf[0].matrix.Naxis[1];
+  Npts = 0;
+  NPTS = 1000;
+  ALLOCATE (xs, float, NPTS);
+  ALLOCATE (ys, float, NPTS);
+  ALLOCATE (zs, float, NPTS);
+  for (j = par[1]-2*par[3]; j < par[1]+2*par[3]; j++) {
+    if (j < 0) continue;
+    if (j >= buf[0].matrix.Naxis[1]) continue;
+    for (i = par[0]-2*par[2]; i < par[0]+2*par[2]; i++) {
+      if (i < 0) continue;
+      if (i >= buf[0].matrix.Naxis[0]) continue;
+      value = in[i + Nx*j];
+      if (fabs (value - Io) < dIo) {
+	xs[Npts] = i;
+	ys[Npts] = j;
+	zs[Npts] = value;
+	Npts ++;
+	if (Npts == NPTS) {
+	  NPTS += 1000;
+	  REALLOCATE (xs, float, NPTS);
+	  REALLOCATE (ys, float, NPTS);
+	  REALLOCATE (zs, float, NPTS);
+	}
+      }
+    }
+  }
+
+  if (Npts == 0) {
+    gprint (GP_ERR, "no valid points in box, try again\n");
+    free (xs);
+    free (ys);
+    free (zs);
+    return (FALSE);
+  }
+
+  plot_outline ();
+  chisq = outline_chi (Io, in);
+  gprint (GP_ERR, "starting chisq: %f for %d pts\n", chisq, Npts);
+
+# if (1)
+  for (j = 0; j < 15; j++) {
+    
+    ochisq = chisq;
+    for (i = 0; i < 5; i++) {
+      /* find +chisq, -chisq for this par & adjust par as needed */
+
+      for (k = 0, BigChange = TRUE; (k < 3) && BigChange; k++) {
+	tmp_par = par[i];
+	par[i] = tmp_par + dpar[i];
+	chisq_p = outline_chi (Io, in);
+	par[i] = tmp_par - dpar[i];
+	chisq_m = outline_chi (Io, in);
+	
+	/* have we braketted a minimum? (curve < 0) */
+	curve = (chisq_p - chisq) * (chisq - chisq_m);
+	if (curve > 0) {
+	  dp = 2*dpar[i];
+	} else {
+	  dp = 0.5 * dpar[i] * (chisq_m - chisq_p) / (chisq_m + chisq_p - 2*chisq);
+	}      
+	if (chisq_m + chisq_p - 2*chisq == 0) dp = 0;
+	/* don't let extrapolation go too far */
+	if (fabs (dp) > 2*fabs(dpar[i])) { dp = SIGN(dp) * fabs (2*dpar[i]); }
+	
+	par[i] = tmp_par + dp;
+	chisq = outline_chi (Io, in);
+	
+	BigChange = FALSE;
+	if (chisq <= 1.001*ochisq) {
+	  /* got better */
+	  dchi = (ochisq - chisq) / ochisq; 
+	  if ((dchi > 0.03) || (curve > 0)) BigChange = TRUE;
+	} else {
+	  par[i] = tmp_par;
+	  chisq = ochisq;
+	  if (chisq_m < chisq) {
+	    chisq = chisq_m;
+	    par[i] = tmp_par - dpar[i];
+	  }	
+	  if (chisq_p < chisq) {
+	    chisq = chisq_p;
+	    par[i] = tmp_par + dpar[i];
+	  }	
+	}	
+	ochisq = chisq;
+      }
+      if (!BigChange) dpar[i] *= 0.8;
+    }
+
+    gprint (GP_ERR, "try: %d  %f   ", j, chisq);
+    for (i = 0; i < 5; i++) {
+      gprint (GP_ERR, "%f ", par[i]);
+    }
+    gprint (GP_ERR, "\n          ");
+    for (i = 0; i < 5; i++) {
+      gprint (GP_ERR, "%f ", dpar[i]);
+    }
+    gprint (GP_ERR, "\n");
+    dchi -= chisq;
+
+  }
+# endif
+
+  free (xs);
+  free (ys);
+  free (zs);
+  
+  plot_outline ();
+  return (TRUE);
+
+}
+
+/* par[0] = x
+   par[1] = y
+   par[2] = dx
+   par[3] = dy
+   par[4] = dxy
+   
+    xp = par[2] * cos (t);
+    yp = par[3] * sin (t);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+*/
+
+# if (1)
+
+float outline_chi (float Io, float *in) {
+
+  int i;
+  float theta, phi;
+  float xp, yp, x, y;
+  float chisq, R2;
+
+  chisq = 0;
+
+  for (i = 0; i < Npts; i++) {
+    
+    phi = atan2 (ys[i] - par[1], xs[i] - par[0]) - RAD_DEG * par[4];
+    /* find a point:
+
+       xp, yp such that atan (r2 sin(phi), r1 cos(phi)) == theta 
+
+       tan (theta) = r2 sin(phi) / r1 cos (phi)
+
+       (r1/r2) tan(theta) = sin(phi) / cos (phi);
+       (r1/r2) tan(theta) = tan (phi)
+
+       phi = atan2 (r1 sin(theta), r2 cos(theta))
+    */
+
+    theta = atan2 (par[2]*sin(phi), par[3]*cos(phi));
+
+    /* this is the point on the ellipse at the same angle as ref point */
+    /* this is wrong, but close -- tends to make ellipses too fat */
+    xp = par[2] * cos (theta);
+    yp = par[3] * sin (theta);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+    R2 = sqrt (SQ (x - xs[i]) + SQ (y - ys[i]));
+
+    /*
+    Dv = zs[i] - Io;
+    dv = fabs(zs[i]);
+    F2 = Dv * Dv / dv;
+    */
+
+    chisq += R2;
+
+  }
+
+  chisq = chisq / Npts;
+  return (chisq);
+
+}
+
+# else 
+
+float outline_chi (float Io, float *in) {
+
+  int i;
+  float theta, theta1, theta2;
+  float xp, yp, x, y;
+  float chisq, dv, Dv, R2, F2, R, dR;
+
+  int Nvec, Nvec2, Nvecx, Nvecy, Nv, nv;
+
+  chisq = 0;
+
+  nv = 0;
+  Nv = 1000;
+  if (!SelectVector (&Nvec, "dR", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvec2, "dF", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecx, "x", ANYVECTOR)) return (FALSE);
+  if (!SelectVector (&Nvecy, "y", ANYVECTOR)) return (FALSE);
+  REALLOCATE (vectors[Nvec].elements, float, Nv);
+  REALLOCATE (vectors[Nvec2].elements, float, Nv);
+  REALLOCATE (vectors[Nvecx].elements, float, Nv);
+  REALLOCATE (vectors[Nvecy].elements, float, Nv);
+
+  for (i = 0; i < Npts; i++) {
+    
+    theta1 = atan2 (ys[i] - par[1], xs[i] - par[0]) - RAD_DEG * par[4];
+    theta = atan2 (par[2]*sin(theta1), par[3]*cos(theta1));
+
+    xp = par[2] * cos (theta);
+    yp = par[3] * sin (theta);
+    
+    x = xp * cos (par[4] * RAD_DEG) - yp * sin (par[4] * RAD_DEG) + par[0];
+    y = xp * sin (par[4] * RAD_DEG) + yp * cos (par[4] * RAD_DEG) + par[1];
+
+    R2 = SQ (x - xs[i]) + SQ (y - ys[i]);
+
+    /* 
+    Dv = fabs (zs[i] - Io) + 1;
+    dv = zs[i] + 0.2 * fabs (Dv);
+    F2 = Dv * Dv / dv;
+    */
+
+    vectors[Nvec].elements[nv] = x;
+    vectors[Nvec2].elements[nv] = y;
+    vectors[Nvecx].elements[nv] = xs[i];
+    vectors[Nvecy].elements[nv] = ys[i];
+    nv ++;
+    if (nv == Nv - 1) {
+      Nv += 1000;
+      REALLOCATE (vectors[Nvec].elements, float, Nv);
+      REALLOCATE (vectors[Nvec2].elements, float, Nv);
+      REALLOCATE (vectors[Nvecx].elements, float, Nv);
+      REALLOCATE (vectors[Nvecy].elements, float, Nv);
+    }
+
+    /* typical distance might be 1 - 10 pix,
+       typical z error might be 100 cts */
+    chisq += R2; 
+
+  }
+  vectors[Nvec].Nelements = nv;
+  vectors[Nvec2].Nelements = nv;
+  vectors[Nvecx].Nelements = nv;
+  vectors[Nvecy].Nelements = nv;
+
+  chisq = chisq / Npts;
+  return (chisq);
+
+}
+# endif
+
+int plot_outline () {
+  
+  int kapa;
+  float xp, yp, x, y;
+  float dx, dy, theta, t, dt;
+  int Noverlay, NOVERLAY;
+  KiiOverlay *overlay;
+  
+  if (!GetImage (NULL, &kapa, NULL)) return (FALSE);
+  
+  Noverlay = 0;
+  NOVERLAY = 1000;
+  ALLOCATE (overlay, KiiOverlay, Noverlay);
+  
+  dx = par[2];
+  dy = par[3];
+  dt = 1 / MAX (dx, dy);
+  theta = par[4];
+  
+  for (t = 0; t < 6.3; t += dt) {
+    xp = dx * cos (t);
+    yp = dy * sin (t);
+    
+    x = xp * cos (theta * RAD_DEG) - yp * sin (theta * RAD_DEG) + par[0];
+    y = xp * sin (theta * RAD_DEG) + yp * cos (theta * RAD_DEG) + par[1];
+    
+    overlay[Noverlay].type = KII_OVERLAY_BOX;
+    overlay[Noverlay].x = x;
+    overlay[Noverlay].y = y;
+    overlay[Noverlay].dx = 1.0;
+    overlay[Noverlay].dy = 1.0;
+
+    Noverlay ++;
+    CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000);
+  }
+  KiiLoadOverlay (kapa, overlay, Noverlay, "red");
+  free (overlay);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/polar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/polar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/polar.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "astro.h"
+
+int polar (int argc, char **argv) {
+  
+  double Lo, dL, Do, dD, Mo, dM, No, dN;
+  double xo, yo, Xo, Yo;
+  double x, y, r, t;
+  float *Vin, *Vout, *Vmask;
+  int i, j, nx, ny, Nx, Ny;
+  int X, Y;
+  Buffer *in, *out, *mask;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: polar in out\n");
+    return (FALSE);
+  }
+
+  if ((in   = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out  = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((mask = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = out[0].matrix.Naxis[0];
+  Ny = out[0].matrix.Naxis[1];
+  nx = mask[0].matrix.Naxis[0];
+  ny = mask[0].matrix.Naxis[1];
+  if ((Nx != nx) && (Ny != ny)) {
+    gprint (GP_ERR, "output and mask must have same dimensions\n");
+    return (FALSE);
+  }
+  nx = in[0].matrix.Naxis[0];
+  ny = in[0].matrix.Naxis[1];
+
+  /* we expect the output image to have units of longitude and distance */
+  gfits_scan (&in[0].header, "CRVAL1", "%lf", 1, &Lo);
+  gfits_scan (&in[0].header, "CDELT1", "%lf", 1, &dL);
+  gfits_scan (&in[0].header, "CRPIX1", "%lf", 1, &xo);
+  gfits_scan (&in[0].header, "CRVAL2", "%lf", 1, &Do);
+  gfits_scan (&in[0].header, "CDELT2", "%lf", 1, &dD);
+  gfits_scan (&in[0].header, "CRPIX2", "%lf", 1, &yo);
+
+  /* we expect the input image to have units of distance X and Y */
+  gfits_scan (&out[0].header, "CRVAL1", "%lf", 1, &Mo);
+  gfits_scan (&out[0].header, "CDELT1", "%lf", 1, &dM);
+  gfits_scan (&out[0].header, "CRPIX1", "%lf", 1, &Xo);
+  gfits_scan (&out[0].header, "CRVAL2", "%lf", 1, &No);
+  gfits_scan (&out[0].header, "CDELT2", "%lf", 1, &dN);
+  gfits_scan (&out[0].header, "CRPIX2", "%lf", 1, &Yo);
+
+  Vin  = (float *)in[0].matrix.buffer;
+  Vout = (float *)out[0].matrix.buffer;
+  Vmask = (float *)mask[0].matrix.buffer;
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++, Vout++, Vmask++) {
+      x = (i - Xo) * dM + Mo;
+      y = (j - Yo) * dN + No;
+      r = hypot(x, y);
+      t = DEG_RAD*atan2 (y, x);
+      while (t < 360.0) {t += 360.0;}
+      while (t > 360.0) {t -= 360.0;}
+      X = (t - Lo) / dL + xo;
+      Y = (r - Do) / dD + yo;
+      if ((X >= 0) && (X < nx) && (Y >= 0) && (Y < ny)) {
+	*Vout += Vin[Y*nx + X];
+	*Vmask += 1;
+      }
+    }
+  }
+
+ return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/precess.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/precess.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/precess.c	(revision 16632)
@@ -0,0 +1,112 @@
+# include "astro.h"
+
+int precess (int argc, char **argv) {
+
+  int i, Julian, Besselian;
+  double T, in_epoch, out_epoch;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  Vector *xvec, *yvec;
+
+  Besselian = Julian = 0;
+  Besselian = get_argument (argc, argv, "B");
+  Julian    = get_argument (argc, argv, "J");
+
+  in_epoch = out_epoch = 2000.0;
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE:  precess (from) (to) RA DEC \n");
+    gprint (GP_ERR, "   you may use B for B1950.0 or J for J2000.0\n");
+    return (FALSE);
+  }
+
+  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); 
+    }
+  }
+
+  gprint (GP_ERR, "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;
+
+  if (ISNUM(argv[3][0]) && ISNUM(argv[4][0])) {
+    A = atof (argv[3]);
+    D = atof (argv[4]);
+    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;
+    gprint (GP_LOG, "%f %f -> %f %f\n", A, D, RA, DEC);
+    return (TRUE);
+  }    
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[3], argv[4]);
+    return (FALSE);
+  }
+  
+  for (i = 0; i < xvec[0].Nelements; i++) {
+    A = xvec[0].elements[i];
+    D = yvec[0].elements[i];
+    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;
+    
+    xvec[0].elements[i] = RA;
+    yvec[0].elements[i] = DEC; 
+  }
+
+  return (TRUE);
+
+}  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/profile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/profile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/profile.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "astro.h"
+
+int profile (int argc, char **argv) {
+  
+  int i, j, N, Nx, Npt;
+  float *V;
+  double sx, sy;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: profile <buffer> <X vector> <Y vector> x y N\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  
+  sx = atof (argv[4]);
+  sy = atof (argv[5]);
+  N  = atof (argv[6]);
+
+  if (sx - N < 0) goto range_error;
+  if (sy - N < 0) goto range_error;
+  if (sx + N > buf[0].matrix.Naxis[0]) goto range_error;
+  if (sy + N > buf[0].matrix.Naxis[1]) goto range_error;
+
+  if ((xvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  xvec[0].Nelements = yvec[0].Nelements = (int)SQ(2*N+1);
+  REALLOCATE (xvec[0].elements, float, 5*(int)SQ(2*N+1));
+  REALLOCATE (yvec[0].elements, float, 5*(int)SQ(2*N+1));
+  bzero (yvec[0].elements, (int)SQ(2*N+1)*sizeof(float)+1);
+  V = (float *)(buf[0].matrix.buffer); 
+  Npt = 0;
+  Nx = buf[0].matrix.Naxis[0];
+  for (i = sx - N; i < sx + N; i++) {
+    for (j = sy - N; j < sy + N; j++, Npt++) {
+      yvec[0].elements[Npt] = V[i + j*Nx];
+      xvec[0].elements[Npt] = hypot (i - sx, j - sy);
+    }
+  }
+
+  fsortpair (xvec[0].elements, yvec[0].elements, xvec[0].Nelements);
+
+  return (TRUE);
+
+range_error:
+  gprint (GP_ERR, "region out of range\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/region.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/region.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/region.c	(revision 16632)
@@ -0,0 +1,136 @@
+# include "astro.h"
+
+int region (int argc, char **argv) {
+  
+  char string[256];
+  double Ra, Dec, Radius;
+  float dx, dy;
+  int N, kapa;
+  char *name;
+  Graphdata graphmode;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if ((N = get_argument (argc, argv, "-image"))) {
+    remove_argument (N, &argc, argv);
+    KapaGetImageCoords (kapa, &graphmode.coords);
+    KapaGetImageRange (kapa, &graphmode.xmin, &graphmode.xmax, &graphmode.ymax, &graphmode.ymin);
+    SetGraph (&graphmode);
+    return (TRUE);
+    // Set Region based on image
+  }
+
+  if ((N = get_argument (argc, argv, "-ew"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipeast = TRUE;
+  }
+
+  if ((N = get_argument (argc, argv, "+ew"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipeast = FALSE;
+  }
+
+  if ((N = get_argument (argc, argv, "-ns"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipnorth = TRUE;
+  }
+
+  if ((N = get_argument (argc, argv, "+ns"))) {
+    remove_argument (N, &argc, argv);
+    graphmode.flipnorth = FALSE;
+  }
+
+  if ((argc != 4) && (argc != 5)) {
+    gprint (GP_ERR, "USAGE: region Ra Dec Radius [projection] [orientation]\n");
+    gprint (GP_ERR, " current: %f %f (%f x %f) (%s)\n", 
+	     graphmode.coords.crval1, graphmode.coords.crval2, 
+	     fabs(graphmode.xmax - graphmode.xmin), 
+	     fabs(graphmode.ymax - graphmode.ymin), 
+	     &graphmode.coords.ctype[5]);
+    return (FALSE);
+  }
+  
+  if (!ohana_str_to_radec (&Ra, &Dec, argv[1], argv[2])) return (FALSE);
+  Radius = atof (argv[3]);
+  strcpy (graphmode.coords.ctype, "RA---TAN");
+  if (argc == 5) {
+    if (!strcasecmp (argv[4], "TAN")) 
+      strcpy (graphmode.coords.ctype, "RA---TAN");
+    if (!strcasecmp (argv[4], "SIN")) 
+      strcpy (graphmode.coords.ctype, "RA---SIN");
+    if (!strcasecmp (argv[4], "ARC")) 
+      strcpy (graphmode.coords.ctype, "RA---ARC");
+    if (!strcasecmp (argv[4], "STG")) 
+      strcpy (graphmode.coords.ctype, "RA---STG");
+    if (!strcasecmp (argv[4], "ZEA"))
+      strcpy (graphmode.coords.ctype, "RA---ZEA");
+    if (!strcasecmp (argv[4], "AIT")) 
+      strcpy (graphmode.coords.ctype, "RA---AIT");
+    if (!strcasecmp (argv[4], "GLS")) 
+      strcpy (graphmode.coords.ctype, "RA---GLS");
+    if (!strcasecmp (argv[4], "PAR")) 
+      strcpy (graphmode.coords.ctype, "RA---PAR");
+  }
+
+  
+  /* ask kapa for coordinate limits, to get the right aspect ratio */
+  KapaGetLimits (kapa, &dx, &dy);
+  dx = fabs (dx);
+  dy = fabs (dy); 
+
+  /* define limits for Ra, Dec at center, grid in degrees */
+  if (dy < dx) {
+    graphmode.xmin = -(dx/dy)*Radius;
+    graphmode.ymin = -Radius;
+    graphmode.xmax = (dx/dy)*Radius;
+    graphmode.ymax = Radius;
+  } else {
+    graphmode.xmin = -Radius;
+    graphmode.ymin = -(dy/dx)*Radius;
+    graphmode.xmax = Radius;
+    graphmode.ymax = (dy/dx)*Radius;
+  } 
+
+  set_variable ("XMIN", graphmode.xmin);
+  set_variable ("XMAX", graphmode.xmax);
+  set_variable ("YMIN", graphmode.ymin);
+  set_variable ("YMAX", graphmode.ymax);
+
+  set_variable ("RMIN", Ra  + graphmode.xmin);
+  set_variable ("RMAX", Ra  + graphmode.xmax);
+  set_variable ("DMIN", Dec + graphmode.ymin);
+  set_variable ("DMAX", Dec + graphmode.ymax);
+
+  set_int_variable ("EAST_RIGHT", !graphmode.flipeast);
+  set_int_variable ("NORTH_UP", !graphmode.flipnorth);
+
+  graphmode.coords.pc1_1 = (graphmode.flipeast) ? -1 : 1;
+  graphmode.coords.pc2_2 = (graphmode.flipnorth) ? -1 : 1;
+
+  graphmode.coords.pc1_2 = graphmode.coords.pc2_1 = 0.0;
+  graphmode.coords.crval1 = Ra;
+  graphmode.coords.crval2 = Dec;
+  graphmode.coords.crpix1 = 0.0;
+  graphmode.coords.crpix2 = 0.0;
+  graphmode.coords.cdelt1 = graphmode.coords.cdelt2 = 1.0;
+
+  KapaClearSections (kapa);
+  KapaSetLimits (kapa, &graphmode);
+
+  /* drop this? */
+  sprintf (string, "%8.4f %8.4f (%f)", Ra, Dec, Radius);
+  KapaSendLabel (kapa, string, 2);
+
+  // XXX is this the right thing to be doing?
+  SetGraph (&graphmode);
+  return (TRUE);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/rotcurve.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/rotcurve.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/rotcurve.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "astro.h"
+
+int rotcurve (int argc, char **argv) {
+  
+  int i, j, X, Y, n, Ncurve;
+  float *Vin, *Vout, *Vmask;
+  int nx, ny, Nx, Ny, N;
+  double L, dL, Lo, V, Vo, dV, Bo, dB, Do, dD;
+  double xo, yo, Xo, Yo;
+  double sl, cl, wo, Ro, Rs, wr, r, fr, d, min;
+  double R[100], T[100], W[100];
+  FILE *f;
+  Buffer *in, *out, *mask;
+
+  min = -1000;
+  if ((N = get_argument (argc, argv, "-min"))) {
+    remove_argument (N, &argc, argv);
+    min = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: rotcurve in out mask curve.txt\n");
+    return (FALSE);
+  }
+
+  f = fopen (argv[4], "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't find rotation curve data file %s\n", argv[4]);
+    return (FALSE);
+  }
+  for (i = 0; fscanf (f, "%lf %lf", &R[i], &T[i]) != EOF; i++) {
+    W[i] = T[i] / R[i];
+  }  
+  fclose (f);
+  Ncurve = i;
+
+  if ((in   = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out  = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((mask = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = out[0].matrix.Naxis[0];
+  Ny = out[0].matrix.Naxis[1];
+  nx = mask[0].matrix.Naxis[0];
+  ny = mask[0].matrix.Naxis[1];
+  if ((Nx != nx) && (Ny != ny)) {
+    gprint (GP_ERR, "output and mask must have same dimensions\n");
+    return (FALSE);
+  }
+  nx = in[0].matrix.Naxis[0];
+  ny = in[0].matrix.Naxis[1];
+
+  /* we expect the input image to have units of velocity, lattitude, and longitude */
+  gfits_scan (&in[0].header, "CRVAL1", "%lf", 1, &Vo);
+  gfits_scan (&in[0].header, "CDELT1", "%lf", 1, &dV);
+  gfits_scan (&in[0].header, "CRPIX1", "%lf", 1, &xo);
+  gfits_scan (&in[0].header, "CRVAL2", "%lf", 1, &Bo);
+  gfits_scan (&in[0].header, "CDELT2", "%lf", 1, &dB);
+  gfits_scan (&in[0].header, "CRPIX2", "%lf", 1, &yo);
+  gfits_scan (&in[0].header, "CRVAL3", "%lf", 1, &L);
+  Vo *= 0.001;
+  dV *= 0.001;
+
+  /* we expect the output image to have units of longitude and distance */
+  gfits_scan (&out[0].header, "CRVAL1", "%lf", 1, &Lo);
+  gfits_scan (&out[0].header, "CDELT1", "%lf", 1, &dL);
+  gfits_scan (&out[0].header, "CRPIX1", "%lf", 1, &Xo);
+  gfits_scan (&out[0].header, "CRVAL2", "%lf", 1, &Do);
+  gfits_scan (&out[0].header, "CDELT2", "%lf", 1, &dD);
+  gfits_scan (&out[0].header, "CRPIX2", "%lf", 1, &Yo);
+
+  while (L >= 360) {L -= 360.0;}
+  while (L < 0.0)  {L += 360.0;}
+  X = (L - Lo) / dL + Xo;
+  if ((X >= Nx) || (X < 0)) {
+    gprint (GP_ERR, "X out of range\n");
+    return (FALSE);
+  }
+  gprint (GP_ERR, "L: %f (%d)\n", L, X);
+
+  cl = cos (L*RAD_DEG);
+  sl = sin (L*RAD_DEG);
+  wo = 25.0;
+  Ro = 10.0;
+  Rs = Ro*sl;
+  /* this method depends on wr monotonically decreasing */
+
+  Vin  = (float *)in[0].matrix.buffer;
+  Vout = (float *)out[0].matrix.buffer;
+  Vmask = (float *)mask[0].matrix.buffer;
+  for (j = 0; j < ny; j++) {
+    for (i = 0; i < nx; i++, Vin++) {
+      if (*Vin <= min) continue;
+      V = (i - xo) * dV + Vo;
+      wr = V/Rs + wo;
+      for (n = 0; (n < Ncurve) && (wr < W[n]); n++);
+      if ((n == 0) || (n == Ncurve)) {
+	continue;
+      }
+      r = (wr - W[n]) *  (R[n-1] - R[n]) / (W[n-1] - W[n]) + R[n];
+      fr = (Ro/r);
+      if (r < fabs(Rs)) { /* can't be on rotation curve */
+	continue;
+      }
+      if (r < Ro)
+	d = Ro*cl - sqrt(r*r - Rs*Rs);
+      else 
+	d = Ro*cl + sqrt(r*r - Rs*Rs);
+      Y = (d - Do) / dD + Yo;
+      if ((Y < Ny) && (Y >= 0)) {
+	Vout[Y*Nx + X] += *Vin;
+	Vmask[Y*Nx + X] += 1.0;
+      }
+    }
+  }
+
+
+  return (TRUE);
+
+} 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/scale.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/scale.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/scale.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "astro.h"
+
+int scale (int argc, char **argv) {
+
+  Buffer *buf;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: scale (buffer) (key) [-r/-w] (value)\n");
+    return (FALSE);
+  }  
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (strcasecmp (argv[2], "bzero") && strcasecmp (argv[2], "bscale")) {
+    gprint (GP_ERR, "use bzero or bscale only\n");
+    return (FALSE);
+  }
+    
+  if (strcmp (argv[3], "-r") && strcmp (argv[3], "-w")) {
+    gprint (GP_ERR, "use -r or -w only\n");
+    return (FALSE);
+  }
+    
+  if (!strcmp (argv[3], "-r")) {
+    if (!strcasecmp (argv[2], "bzero")) {
+      set_variable (argv[4], (double) buf[0].bzero);
+    } else {
+      set_variable (argv[4], (double) buf[0].bscale);
+    }      
+  } else {
+    if (!strcasecmp (argv[2], "bzero")) {
+      buf[0].bzero = atof (argv[4]);
+    } else {
+      buf[0].bscale = atof (argv[4]);
+    }      
+  }
+
+  return (TRUE);
+}
+
+/* get or set external bzero / bscale values 
+   (these keywords are set to 0,1 internally, 
+   so we can't just manipulate them like other keywords */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/sexigesimal.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/sexigesimal.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/sexigesimal.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "astro.h"
+
+int sexigesimal (int argc, char **argv) {
+  
+  int HMS, N;
+  double value;
+  char string[80];
+
+  HMS = TRUE;
+  if ((N = get_argument (argc, argv, "-hms"))) {
+    HMS = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-hh"))) {
+    HMS = FALSE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 3) && (argc != 2)) {
+    gprint (GP_ERR, "USAGE: sexigesimal (from) [to]\n");
+    return (FALSE);
+  }
+
+  if (HMS) {
+    if (!ohana_dms_to_ddd (&value, argv[1])) {
+      gprint (GP_ERR, "syntax error in input\n");
+      return (FALSE);
+    }
+    if (argc == 3) {
+      set_variable (argv[2], value);
+    } else {
+      gprint (GP_LOG, "%10.6f\n", value);
+    }
+    return (TRUE);
+  } else {
+    value = atof (argv[1]);
+    hms_format (string, value);
+    if (argc == 3) {
+      set_str_variable (argv[2], string);
+    } else {
+      gprint (GP_LOG, "%s\n", string);
+    }
+    return (TRUE);
+  }      
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/spec.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/spec.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/spec.c	(revision 16632)
@@ -0,0 +1,112 @@
+# include "astro.h"
+
+int spec (int argc, char **argv) {
+
+  int i, j, Xo, X1, y1, y2, Nx, Ny;
+  int Nlong, Ngap, Nrow, N, Nring;
+  float *buffer, *V;
+  double sky, sky2, S, SX, F, R, Npts;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  Nlong = 31;
+  if ((N = get_argument (argc, argv, "-Nlong"))) {
+    remove_argument (N, &argc, argv);
+    Nlong  = 0.5*atof(argv[N]);
+    Nlong = 2*Nlong + 1;  /* force an odd number */
+    remove_argument (N, &argc, argv);
+  }
+  
+  Ngap = 15;
+  if ((N = get_argument (argc, argv, "-Ngap"))) {
+    remove_argument (N, &argc, argv);
+    Ngap  = 0.5*atof(argv[N]);
+    Ngap = 2*Ngap + 1;  /* force an odd number */
+    remove_argument (N, &argc, argv);
+  }
+  
+  Nrow = 1;
+  if ((N = get_argument (argc, argv, "-Nrow"))) {
+    remove_argument (N, &argc, argv);
+    Nrow  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: spec buffer x y1 y2 X Y [-Nlong N] [-Ngap N] [-Nrow N]\n");
+    return (FALSE);
+  }
+  
+  if ((Nrow < 1) || (Nlong < 2) || (Ngap < 1) || (Nlong - Ngap < 2)) {
+    gprint (GP_ERR, "bad values for options\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  Xo = atof (argv[2]);
+  y1 = atof (argv[3]);
+  y2 = atof (argv[4]);
+
+  if ((xvec = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[6], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  N = y2 - y1;
+  REALLOCATE (xvec[0].elements, float, N);
+  REALLOCATE (yvec[0].elements, float, N);
+  xvec[0].Nelements = N;
+  yvec[0].Nelements = N;
+  
+  ALLOCATE (buffer, float, Nlong);
+
+  for (j = 0; j < y2 - y1; j++) {
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + Xo - (int)(0.5*Nlong);
+    /* find sky on edge */
+    for (i = 0, Nring = 0; i < 0.5*(Nlong - Ngap); i++, V++, Nring++) {
+      buffer[i] = *V;
+    }
+    fsort (buffer, Nring);
+    for (Npts = sky = 0, i = 0.25*Nring; i < 0.75*Nring; i++, Npts += 1.0) {
+      sky += buffer[i];
+    }
+    sky = sky / Npts;
+    /* find center column for this row */
+    for (S = SX = i = 0, Nring = 0; i < Ngap; i++, V++, Nring++) {
+      S += (*V - sky);
+      SX += (*V - sky)*(i + Xo - 0.5*Ngap);
+    }
+    X1 = SX / S;
+    gprint (GP_ERR, "%4d %4d %5.1f ", j+y1, X1, sky);
+    /*    X1 = MAX (MIN (X1, Xo + 0.5+Ngap), Xo - 0.5+Ngap); */
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + X1 - (int)(0.5*Nlong);
+    /* find sky on edges */
+    for (i = 0, Nring = 0; i < 0.5*(Nlong - Ngap); i++, V++, Nring++) {
+      buffer[Nring] = *V;
+    }
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + X1 + (int)(0.5*Ngap);
+    for (i = 0; i < 0.5*(Nlong - Ngap); i++, V++, Nring++) {
+      buffer[Nring] = *V;
+    }
+    fsort (buffer, Nring);
+    for (Npts = sky = sky2 = 0, i = 0.25*Nring; i < 0.75*Nring; i++, Npts += 1.0) {
+      sky += buffer[i];
+      sky2 += buffer[i]*buffer[i];
+    }
+    sky = sky / Npts;
+    sky2 = (sky2 / Npts - sky*sky);
+    /* find weighted flux */
+    V = (float *) (buf[0].matrix.buffer) + Nx*(y1 + j) + X1 - (int)(0.5*Ngap);
+    for (F = R = i = 0; i < Ngap; i++, V++) {
+      F += (*V - sky) / sky2;
+      R += 1.0 / sky2;
+    }
+    xvec[0].elements[j] = j + y1; 
+    yvec[0].elements[j] = F / R; 
+    gprint (GP_ERR, " %5.1f %7.1f  %6.2f\n", sky, sky2, (F/R));
+  }    
+
+  free (buffer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/star.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/star.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/star.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "astro.h"
+
+int star (int argc, char **argv) {
+
+  int x, y, N, dx, Nborder;
+  double Z, max;
+  Buffer *buf;
+
+  Nborder = 3;
+  if ((N = get_argument (argc, argv, "-border"))) {
+    remove_argument (N, &argc, argv);
+    Nborder  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Nborder = MAX (Nborder, 1);
+  
+  max = 60000;
+  if ((N = get_argument (argc, argv, "-sat"))) {
+    remove_argument (N, &argc, argv);
+    max  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  
+  if ((argc != 4) && (argc != 5)) {
+    gprint (GP_ERR, "USAGE: star (buffer) x y [dx] [-border N] [-sat cnts]\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  dx = 11;
+  x = atof (argv[2]);
+  y = atof (argv[3]);
+  if (argc == 5) {
+    dx = atof (argv[4]);
+  }
+
+  Z = get_aperture_stats (&buf[0].matrix, x, y, dx, Nborder, max);
+  
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/testfit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/testfit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/testfit.c	(revision 16632)
@@ -0,0 +1,161 @@
+# include "astro.h"
+
+/* local private functions */
+float fgaussOD (float, float *, int, float *);
+
+int imfit (int argc, char **argv) {
+
+  float par[4], *v1, *v2, *dy, chisq, **covar;
+  int i, Npts, Npar;
+  Vector *xvec, *yvec, *svec;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: imfit <x> <y> <dy>\n");
+    return (FALSE);
+  }
+  
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((svec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Npts = xvec[0].Nelements;
+  ALLOCATE (dy, float, Npts);
+  v1 = svec[0].elements;
+  v2 = dy;
+  
+  for (i = 0; i < Npts; i++, v1++, v2++) *v2 = 1.0 / (*v1 * *v1);
+  
+  par[0] = 7;
+  par[1] = 2;
+  par[2] = 6;
+  par[3] = 1;
+  Npar = 4;
+
+  mrqinit (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fgaussOD);
+
+  for (i = 0; i < 10; i++) {
+
+    chisq = mrqmin (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fgaussOD);
+    gprint (GP_ERR, "chisq: %f, %f %f %f %f\n", chisq, par[0], par[1], par[2], par[3]);
+
+  }  
+
+  covar = mrqcovar (Npar);
+
+  for (i = 0; i < Npar; i++) {
+    gprint (GP_ERR, "%d  %f  %f\n", i, par[i], covar[i][i]);
+  }
+
+  mrqfree (Npar);
+  return (TRUE);
+}
+
+
+/* pars: x, y, sx, sy, sxy, sky I, */
+float fgaussOD (float x, float *par, int Npar, float *dpar) {
+
+  float X, S, Z, R, f;
+
+  X = x - par[0];
+  S = 1.0 / (par[1]*par[1]);
+  Z = -0.5*X*X*S;
+  R = exp (Z);
+  f = par[2]*R + par[3];
+
+  dpar[0] = par[2]*R*X*S;
+  dpar[1] = dpar[0]*X/par[1];
+  dpar[2] = R;
+  dpar[3] = 1;
+  
+  return (f);
+
+}
+
+# if (0)
+
+/* pars: x, y, sx, sy, sxy, sky I, */
+float testF (float x, float *par, int Npar, float *dpar) {
+
+  float f;
+
+  f = par[0]*x + par[1];
+
+  dpar[0] = x;
+  dpar[1] = 1;
+  
+  return (f);
+
+}
+
+
+/* pars: x, y, sx, sy, sxy, sky I, */
+float fgaussTD (float x, float y, float *par, int Npar) {
+
+  X = x - par[0];
+  Y = y - par[1];
+  
+  t1 = X / par[2];
+  t2 = Y * Y / par[3];
+  t3 = Y * par[4] * 2.0;
+
+  r = 0.5 * ((t1 + t3)*X + t2);
+  f = par[5] + par[6] / (1.0 + r*(1.0 + 0.5*r*(1.0 + 0.33333333*r)));
+  
+  return (f);
+
+}
+
+float chisq (float *buf, float *sig, int Nx, int Ny, float (func)(), float *par, int Npar) {
+
+  float *ptr;
+
+  X = 0;
+  ptr = buf;
+  for (i = 0; i < Nx; i++) {
+    for (j = 0; j < Ny; j++, ptr++, sig++) {
+      f = *ptr - func ((float) i, (float) j, par, Npar);
+      X += (f * f) / *sig;
+    }
+  }    
+  return (X);
+}
+
+  int i, j, Nbuf, status;
+  char *string;
+  double Npix, N1, N2, max, min, range, median;
+  float *V;
+  int sx, sy, nx, ny, *hist, Nhist, bin;
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: imfit <buffer> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  if (!SelectBuffer (&Nbuf, argv[1], OLDBUFFER)) return (FALSE);
+
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+
+  Npix = N1 = N2 = 0;
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buffers[Nbuf].matrix.Naxis[0]) || 
+      (sy+ny > buffers[Nbuf].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+
+  Npix = nx*ny;
+
+  ALLOCATE (tempbuf, float, Npix);
+
+  buf = tempbuf;
+  for (j = 0; j < ny; j++) {
+    V = (float *)(buffers[Nbuf].matrix.buffer) + (j+sy)*buffers[Nbuf].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      *buf = *V;
+    }
+  }
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/transform.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/transform.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/transform.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "astro.h"
+
+int transform (int argc, char **argv) {
+
+  int i, j, Nx, Ny;
+  Coords coords_in, coords_out;
+  double scale_in, scale_out;
+  int X, Y;
+  double x, y, r, d, dx, dy;
+  double frac;
+  char *Sout, *S;
+  float *Vin, *Vout;
+  Buffer *in, *out;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: transform <from> <to>\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  GetCoords (&coords_in, &in[0].header);
+  GetCoords (&coords_out, &out[0].header);
+
+  /* for the moment, disable WRP / DIS */
+  if (!strcmp(&coords_in.ctype[4], "-WRP") || !strcmp(&coords_out.ctype[4], "-WRP")) {
+    gprint (GP_ERR, "WRP mode not implemented for astrom\n");
+    return (FALSE);
+  }
+  
+  scale_in = sqrt(fabs(coords_in.cdelt1*coords_in.cdelt2*(coords_in.pc1_1*coords_in.pc2_2 - coords_in.pc1_2*coords_in.pc2_1)));
+  scale_out = sqrt(fabs(coords_out.cdelt1*coords_out.cdelt2*(coords_out.pc1_1*coords_out.pc2_2 - coords_out.pc1_2*coords_out.pc2_1)));
+
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Nx = out[0].header.Naxis[0];
+  Ny = out[0].header.Naxis[1];
+  bzero (Vout, Nx*Ny*sizeof(float));
+  ALLOCATE (S, char, Nx*Ny);
+  Sout = S;
+  bzero (Sout, Nx*Ny*sizeof(char));
+  frac = 0.333;
+
+  /* if (scale_in < scale_out) { */
+
+  for (j = 0; j < in[0].header.Naxis[1]; j++) {
+    gprint (GP_ERR, ".");
+    for (i = 0; i < in[0].header.Naxis[0]; i++, Vin++) {
+      for (dx = 0.0 + 0.5*frac; dx < 1.0 - 0.5*frac; dx += frac) {
+	for (dy = 0.0 + 0.5*frac; dy < 1.0 - 0.5*frac; dy += frac) {
+	  XY_to_RD (&r, &d, i + dx, j + dy, &coords_in);
+	  RD_to_XY (&x, &y, r, d, &coords_out);
+	  X = x; Y = y;
+	  if ((X > -1) && (X < Nx) && (Y > -1) && (Y < Ny)) {
+	    Vout[X + Y*Nx] += *Vin;
+	    Sout[X + Y*Nx] ++;
+	  }
+	}
+      }
+    }
+  }
+
+  Sout = S;
+  Vout = (float *) out[0].matrix.buffer;
+  for (i = 0; i < Nx*Ny; i++, Vout++, Sout++) {
+    *Vout = *Vout / *Sout;
+  }
+
+  free (S);
+    
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/warp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/warp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.astro/warp.c	(revision 16632)
@@ -0,0 +1,237 @@
+# include "astro.h"
+
+/*** needs mosaic astrometry ***/
+
+static double XO, XX, XY;
+static double YO, YX, YY;
+int ZERO;
+
+int map_output_to_input (int Npix, double df);
+int map_input_to_output (int Npix, double df);
+void set_linear_terms (Coords *in, Coords *out, int i, int j, int Npix);
+void apply_terms (double *Xout, double *Yout, double Xin, double Yin);
+
+Coords coords_in, coords_out;
+Buffer *in, *out, *wt;
+
+int warp (int argc, char **argv) {
+
+  int Nlinear, Np, N;
+  double scale_in, scale_out, df;
+
+  ZERO = FALSE;
+  if ((N = get_argument (argc, argv, "-zero"))) {
+    ZERO = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: transform <from> <to> <weight> (Nlinear)\n");
+    gprint (GP_ERR, "  output buffer must exist with target astrometry header\n");
+    gprint (GP_ERR, "  Nlinear is the pixel scale for linear astrometric transformation\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((wt  = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Nlinear = atoi (argv[4]);
+
+  GetCoords (&coords_in, &in[0].header);
+  GetCoords (&coords_out, &out[0].header);
+
+  /* for the moment, disable WRP / DIS */
+  if (!strcmp(&coords_in.ctype[4], "-WRP") || !strcmp(&coords_out.ctype[4], "-WRP")) {
+    gprint (GP_ERR, "WRP mode not implemented for astrom\n");
+    return (FALSE);
+  }
+  
+  scale_in = sqrt(fabs(coords_in.cdelt1*coords_in.cdelt2*(coords_in.pc1_1*coords_in.pc2_2 - coords_in.pc1_2*coords_in.pc2_1)));
+  scale_out = sqrt(fabs(coords_out.cdelt1*coords_out.cdelt2*(coords_out.pc1_1*coords_out.pc2_2 - coords_out.pc1_2*coords_out.pc2_1)));
+  
+  gprint (GP_ERR, "%f - %f\n", scale_in, scale_out);
+
+  if (scale_in > scale_out) {
+    Np = MAX (1, 3*scale_out / scale_in);
+    df = 1.0 / Np;
+    map_output_to_input (Nlinear, df);
+  } else {
+    Np = MAX (1, 3*scale_in / scale_out);
+    df = 1.0 / Np;
+    map_input_to_output (Nlinear, df);
+  }
+  return (TRUE);
+}
+
+/* mode 1: input pixels >> output pixels: loop over output pixels */
+/* mode 2: input pixels << output pixels: loop over input pixels */
+/* mode 3: input pixels ~= output pixels: drizzle input to output */
+
+/* loop over the input pixels, map input output image */
+int map_output_to_input (int Npix, double df) {
+
+  int i, j, Ni, No, Nx, Ny, nx, ny;
+  float *Vin, *Vout, *Vwt;
+  double x, y, X, Y;
+
+  /* loop over output pixels */
+  /* set up pointers for buffers */
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Vwt  = (float *) wt[0].matrix.buffer;
+
+  nx = in[0].header.Naxis[0];
+  ny = in[0].header.Naxis[1];
+  Nx = out[0].header.Naxis[0];
+  Ny = out[0].header.Naxis[1];
+
+  if (ZERO) {
+    bzero (Vout, Nx*Ny*sizeof(float));
+    bzero (Vwt,  Nx*Ny*sizeof(float));
+  }
+
+  for (j = 0; j < Ny; j+=Npix) {
+    for (i = 0; i < Nx; i+=Npix) {
+      
+      /* define linear transformation in region */
+      set_linear_terms (&coords_out, &coords_in, i, j, Npix);
+
+      for (X = i; (X < i + Npix) && (X < Nx); X += df) {
+	for (Y = j; (Y < j + Npix) && (Y < Ny); Y += df) {
+	  
+	  No = (int)X + ((int)Y)*Nx;
+	  apply_terms (&x, &y, X, Y);
+	  if (x < 0) continue;
+	  if (x >= nx) continue;
+	  if (y < 0) continue;
+	  if (y >= ny) continue;
+	  Ni = (int)x + ((int)y)*nx;
+
+	  Vout[No] += Vin[Ni];
+	  Vwt[No] ++;
+	}
+      }
+    }
+  }
+  return (TRUE);
+}
+
+/* loop over the input pixels, map input output image */
+int map_input_to_output (int Npix, double df) {
+
+  int i, j, Ni, No, Nx, Ny, nx, ny;
+  float *Vin, *Vout, *Vwt;
+  double x, y, X, Y;
+
+  /* loop over output pixels */
+  /* set up pointers for buffers */
+  Vin  = (float *) in[0].matrix.buffer;
+  Vout = (float *) out[0].matrix.buffer;
+  Vwt  = (float *) wt[0].matrix.buffer;
+
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  nx = out[0].header.Naxis[0];
+  ny = out[0].header.Naxis[1];
+
+  if (ZERO) {
+    bzero (Vout, nx*ny*sizeof(float));
+    bzero (Vwt,  nx*ny*sizeof(float));
+  }
+
+  for (j = 0; j < Ny; j+=Npix) {
+    for (i = 0; i < Nx; i+=Npix) {
+      
+      /* define linear transformation in region */
+      set_linear_terms (&coords_in, &coords_out, i, j, Npix);
+
+      for (X = i; (X < i + Npix) && (X < Nx); X += df) {
+	for (Y = j; (Y < j + Npix) && (Y < Ny); Y += df) {
+	  
+	  Ni = (int)X + ((int)Y)*Nx;
+	  apply_terms (&x, &y, X, Y);
+	  if (x < 0) continue;
+	  if (x >= nx) continue;
+	  if (y < 0) continue;
+	  if (y >= ny) continue;
+	  No = (int)x + ((int)y)*nx;
+
+	  Vout[No] += Vin[Ni];
+	  Vwt[No] ++;
+	}
+      }
+    }
+  }
+  return (TRUE);
+}
+
+/* find the linear astrometric fix between images at this location */
+void set_linear_terms (Coords *in, Coords *out, int i, int j, int Npix) {
+
+  int n;
+  double x, y, x2, y2, xy, X, Y, Xx, Xy, Yx, Yy;
+  double Xin, Yin, Xout, Yout;
+  double Sx2, Sy2, Sxy, SXx, SXy, SYx, SYy;
+  double N, r, d;
+
+  Xin = Yin = 0;
+  N = x = y = x2 = y2 = xy = X = Y = Xx = Xy = Yx = Yy = 0;
+
+  /* define several test points, fit a line to the input,output pairs */
+  for (n = 0; n < 3; n++) {
+
+    switch (n) {
+    case 0:
+      Xin = i;
+      Yin = j;
+      break;
+    case 1:
+      Xin = i + Npix;
+      Yin = j;
+      break;
+    case 2:
+      Xin = i;
+      Yin = j + Npix;
+      break;
+    }
+
+    XY_to_RD (&r, &d, Xin, Yin, in);
+    RD_to_XY (&Xout, &Yout, r, d, out);
+
+    x  += Xin;
+    y  += Yin;
+    x2 += Xin*Xin;
+    y2 += Yin*Yin;
+    xy += Xin*Yin;
+    X  += Xout;
+    Y  += Yout;
+    Xx += Xout*Xin;
+    Xy += Xout*Yin;
+    Yx += Yout*Xin;
+    Yy += Yout*Yin;
+    N  += 1.0;
+  }
+
+  Sx2 = x2 - x*x/N;
+  Sy2 = y2 - y*y/N;
+  Sxy = xy - x*y/N;
+  SXx = Xx - X*x/N;
+  SXy = Xy - X*y/N;
+  SYx = Yx - Y*x/N;
+  SYy = Yy - Y*y/N;
+  
+  XX = (SXx*Sy2 - SXy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  XY = (SXy*Sx2 - SXx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  XO = X/N - XX*x/N - XY*y/N;
+
+  YX = (SYx*Sy2 - SYy*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  YY = (SYy*Sx2 - SYx*Sxy) / (Sx2*Sy2 - Sxy*Sxy);
+  YO = Y/N - YX*x/N - YY*y/N;
+
+}
+
+
+void apply_terms (double *Xout, double *Yout, double Xin, double Yin) {
+  *Xout = XO + XX*Xin + XY*Yin;
+  *Yout = YO + YX*Xin + YY*Yin;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/Makefile	(revision 16632)
@@ -0,0 +1,78 @@
+default: libbasiccmd
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+SRC     =       $(HOME)/cmd.basic
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+# basic user commands ########################
+
+srcs = \
+$(SRC)/init.$(ARCH).o       \
+$(SRC)/break.$(ARCH).o	     \
+$(SRC)/cd.$(ARCH).o	     \
+$(SRC)/config.$(ARCH).o     \
+$(SRC)/continue.$(ARCH).o   \
+$(SRC)/dirname.$(ARCH).o     \
+$(SRC)/date.$(ARCH).o	     \
+$(SRC)/echo.$(ARCH).o	     \
+$(SRC)/file.$(ARCH).o	     \
+$(SRC)/getchr.$(ARCH).o     \
+$(SRC)/help.$(ARCH).o	     \
+$(SRC)/input.$(ARCH).o	     \
+$(SRC)/list.$(ARCH).o	     \
+$(SRC)/list_help.$(ARCH).o  \
+$(SRC)/list_vars.$(ARCH).o  \
+$(SRC)/local.$(ARCH).o	     \
+$(SRC)/macro.$(ARCH).o	     \
+$(SRC)/memory.$(ARCH).o     \
+$(SRC)/mkdir.$(ARCH).o     \
+$(SRC)/module.$(ARCH).o     \
+$(SRC)/output.$(ARCH).o     \
+$(SRC)/quit.$(ARCH).o	     \
+$(SRC)/run_for.$(ARCH).o    \
+$(SRC)/run_if.$(ARCH).o     \
+$(SRC)/run_while.$(ARCH).o  \
+$(SRC)/scan.$(ARCH).o	     \
+$(SRC)/shell.$(ARCH).o	     \
+$(SRC)/sprintf.$(ARCH).o    \
+$(SRC)/fprintf.$(ARCH).o    \
+$(SRC)/strlen.$(ARCH).o     \
+$(SRC)/substr.$(ARCH).o     \
+$(SRC)/strpop.$(ARCH).o     \
+$(SRC)/strsub.$(ARCH).o     \
+$(SRC)/usleep.$(ARCH).o     \
+$(SRC)/sleep.$(ARCH).o	     \
+$(SRC)/wait.$(ARCH).o	     \
+$(SRC)/which.$(ARCH).o
+
+# dependancy rules for include files ########################
+incs = \
+$(INC)/opihi.h \
+$(INC)/external.h \
+$(INC)/shell.h \
+$(INC)/dvomath.h \
+$(INC)/convert.h \
+$(INC)/display.h 
+
+$(srcs): $(incs)
+
+$(LIB)/libbasiccmd.$(ARCH).a: $(srcs)
+$(LIB)/libbasiccmd.$(ARCH).$(DLLTYPE): $(srcs)
+
+$(DESTLIB)/libbasiccmd.a: $(LIB)/libbasiccmd.$(ARCH).a
+$(DESTLIB)/libbasiccmd.$(DLLTYPE): $(LIB)/libbasiccmd.$(ARCH).$(DLLTYPE)
+
+libbasiccmd: $(DESTLIB)/libbasiccmd.a $(DESTLIB)/libbasiccmd.$(DLLTYPE)
+
+uninstall:
+	rm -f $(DESTLIB)/libbasiccmd.a
+	rm -f $(DESTLIB)/libbasiccmd.$(DLLTYPE)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/break.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/break.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/break.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "basic.h"
+
+int exec_break (int argc, char **argv) {
+
+  int N, value;
+
+  if ((N = get_argument (argc, argv, "-auto"))) {
+    remove_argument (N, &argc, argv);
+    value = -1;
+    if (!strcasecmp (argv[N], "on")) value = TRUE;
+    if (!strcasecmp (argv[N], "off")) value = FALSE;
+    if (value == -1) {
+      gprint (GP_ERR, "USAGE: break -auto [on / off]\n");
+      if (auto_break) 
+	gprint (GP_ERR, "auto break on\n");
+      else 
+	gprint (GP_ERR, "auto break off\n");
+      return (FALSE);
+    }
+    auto_break = value;
+    return (TRUE);
+  }
+
+  loop_break = TRUE;
+  return (FALSE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/cd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/cd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/cd.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "basic.h"
+
+int cd (int argc, char **argv) {
+
+  int N, VERBOSE, status;
+  char *cwd;
+
+  VERBOSE = TRUE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = FALSE;
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: cd <path>\n");
+    return (FALSE);
+  }
+
+  status = chdir (argv[1]);
+  if (!status) {
+    if ((cwd = getcwd (NULL, 64)) == NULL) {
+      gprint (GP_ERR, "error getting cwd\n");
+      return (FALSE);
+    }
+    if (VERBOSE) gprint (GP_LOG, "cwd: %s\n", cwd);
+    ohana_memregister (cwd);
+    free (cwd);
+    return (TRUE);
+  }
+
+  gprint (GP_ERR, "error changing to %s\n", argv[1]);
+  return (FALSE);
+
+}
+
+int pwd (int argc, char **argv) {
+
+  int N;
+  char *cwd, *var;
+
+  var = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    var = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: pwd [-var variable]\n");
+    return (FALSE);
+  }
+  
+  if ((cwd = getcwd(NULL, 64)) == NULL) {
+    gprint (GP_ERR, "error getting cwd\n");
+    if (var != NULL) free (var);
+    return (FALSE);
+  }
+  if (var == NULL) {
+      gprint (GP_LOG, "cwd: %s\n", cwd);
+  } else {
+      set_str_variable (var, cwd);
+      free (var);
+  }
+  ohana_memregister (cwd);
+  free (cwd);
+  return (TRUE);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/config.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/config.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/config.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "basic.h"
+
+int config (int argc, char **argv) {
+
+  if (!ConfigInit (&argc, argv)) return (FALSE);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/continue.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/continue.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/continue.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "basic.h"
+
+int exec_next (int argc, char **argv) {
+  loop_next = TRUE;
+  return (TRUE);
+}
+
+int exec_last (int argc, char **argv) {
+  loop_last = TRUE;
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/date.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/date.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/date.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "basic.h"
+
+int date (int argc, char **argv) {
+  
+  int N, SECONDS, REFTIME;
+  struct timeval now;
+  char *tstring = NULL;
+  char *varName = NULL;
+
+  SECONDS = FALSE;
+  if ((N = get_argument (argc, argv, "-seconds"))) {
+    remove_argument (N, &argc, argv);
+    SECONDS = TRUE;
+  } else {
+    ALLOCATE (tstring, char, 32);
+  }
+
+  REFTIME = 0;
+  if ((N = get_argument (argc, argv, "-reftime"))) {
+    remove_argument (N, &argc, argv);
+    REFTIME = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  } 
+
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: date [-var variable] [-seconds] [-reftime seconds]\n");
+    return (FALSE);
+  }
+
+  gettimeofday (&now, NULL);
+  if (SECONDS) {
+    if (varName) {
+      set_int_variable (varName, now.tv_sec - REFTIME);
+    } else {
+      gprint (GP_ERR, "%d\n", now.tv_sec - REFTIME);
+    }
+  } else {
+    ctime_r (&now.tv_sec, tstring);
+    N = strlen (tstring) - 1;
+    tstring[N] = 0;
+
+    if (varName) {
+      set_str_variable (varName, tstring);
+    } else {
+      gprint (GP_ERR, "%s\n", tstring);
+    }
+    free (tstring);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/dirname.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/dirname.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/dirname.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "basic.h"
+
+int dirname_opihi (int argc, char **argv) {
+
+  int N;
+  char *dirName, *varName;
+
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: dirname (path) [-var name]\n");
+    return (FALSE);
+  }
+
+  dirName = pathname (argv[1]);
+
+  if (varName == NULL) {
+    gprint (GP_LOG, "%s\n", dirName);
+  } else {
+    set_str_variable (varName, dirName);
+    free (varName);
+  }    
+
+  free (dirName);
+  return (TRUE);
+}
+
+// XXX need to add mode option
+// XXX need to respect umask (need umask command?)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/echo.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/echo.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/echo.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "basic.h"
+
+int echo (int argc, char **argv) {
+  
+  int i;
+
+  for (i = 1; i < argc - 1; i++) {
+    gprint (GP_LOG, "%s ", argv[i]);
+  }
+  if (argc >= 2) {
+      gprint (GP_LOG, "%s\n", argv[argc - 1]);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/file.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/file.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/file.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "basic.h"
+
+int file (int argc, char **argv) {
+  
+  /* usage: file (filename) [var] */
+
+  int status, vstat;
+  struct stat fstats;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: file (filename) [var]\n");
+    return (FALSE);
+  }
+
+  status = stat (argv[1], &fstats);
+
+  vstat = !status;
+
+  if (argc == 3) {
+      
+    set_int_variable (argv[2], vstat);
+
+  } else {
+
+    gprint (GP_ERR, "file %s is ", argv[1]);
+    if (!vstat) gprint (GP_ERR, "not ");
+    gprint (GP_ERR, "found\n");
+    
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/fprintf.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/fprintf.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/fprintf.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "basic.h"
+# define NCHAR 1024
+
+// XXX this function should ALLOCATE the output buffers
+int fprintf_opihi (int argc, char **argv) {
+
+  int i;
+  char line[NCHAR], tmp[NCHAR], fmt[NCHAR];
+  char *p1, *p2, *q;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: fprintf format value value ...\n");
+    return (FALSE);
+  }
+
+  q  = line;
+  bzero (line, NCHAR);
+
+  p1 = argv[1];
+  for (i = 2; i < argc; i++) {
+    bzero (tmp, NCHAR);
+    bzero (fmt, NCHAR);
+
+    /* find next format character */
+    p2 = strchr (p1, '%');
+    if (p2 == (char *) NULL) {
+      gprint (GP_ERR, "mismatch between format and values\n");
+      return (FALSE);
+    }
+    if (strlen(q) + p2 - p1 > NCHAR) {
+      gprint (GP_ERR, "line too long");
+      return (FALSE);
+    }
+    memcpy (q, p1, p2-p1);
+    q = line + strlen(line);
+    
+    /* identify type (%NNNs %NNNNd %NNNNf) */
+    for (p1 = p2 + 1; (*p1 == '.') || (*p1 == '-') || (*p1 == '+') || (*p1 == ' ') || isdigit(*p1); p1++);
+    memcpy (fmt, p2, p1 - p2 + 1);
+    switch (*p1) {
+      case 'e':
+      case 'f':
+	sprintf (tmp, fmt, atof(argv[i]));
+	break;
+      case 's':
+	sprintf (tmp, fmt, argv[i]);
+	break;
+      case 'd':
+      case 'c':
+      case 'x':
+	sprintf (tmp, fmt, atoi(argv[i]));
+	break;
+      default:
+	gprint (GP_ERR, "syntax error in format (only e,f,s,d,c,x allowed)\n");
+	return (FALSE);
+    }
+    if (strlen(q) + strlen(tmp) > NCHAR) {
+      gprint (GP_ERR, "line too long");
+      return (FALSE);
+    }
+    memcpy (q, tmp, strlen(tmp));
+    q = line + strlen(line);
+    p1++;
+  }
+  p2 = strchr (p1, '%');
+  if (p2 != (char *) NULL) {
+    gprint (GP_ERR, "mismatch between format and values\n");
+    return (FALSE);
+  }
+  
+  p2 = p1 + strlen (p1);
+  if (strlen(q) + p2 - p1 > NCHAR) {
+    gprint (GP_ERR, "line too long");
+    return (FALSE);
+  }
+  memcpy (q, p1, p2-p1);
+  gprint (GP_LOG, "%s\n", line);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/getchr.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/getchr.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/getchr.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "basic.h"
+
+int getchr_func (int argc, char **argv) {
+
+  /* returns position of the first given character */ 
+  char *c;
+  int pos;
+
+  if ((argc != 3) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: getchr (string) (char) [var]\n");
+    return (FALSE);
+  }
+
+  c = strchr (argv[1], argv[2][0]);
+
+  if (c == (char *) NULL) {
+    pos = -1;
+  } else {
+    pos = c - argv[1];
+  }
+
+  if (argc == 4) {
+    set_int_variable (argv[3], pos);
+  } else {
+    gprint (GP_ERR, "%d\n", pos);
+  }
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "basic.h"
+
+int help (int argc, char **argv) {
+
+  int Nbytes;
+  FILE *f;
+  char *helpdir, *file, buff[512];
+
+  helpdir = get_variable ("HELPDIR");
+  if (helpdir == (char *) NULL) {
+    gprint (GP_ERR, "variable HELPDIR not found\n");
+    return (FALSE);
+  }
+
+  if (argc == 1) {
+    sprintf (buff, "ls %s", helpdir);
+    system (buff);
+    return (TRUE);
+  }
+
+  Nbytes = strlen(helpdir) + strlen(argv[1]) + 2;
+  ALLOCATE (file, char, Nbytes);
+  snprintf (file, Nbytes, "%s/%s", helpdir, argv[1]);
+
+  f = fopen (file, "r");
+  free (file);
+
+  if (f == NULL) {
+    gprint (GP_ERR, "No help for: %s\n", argv[1]);
+    return (FALSE);
+  }
+
+  while (scan_line (f, buff) != EOF)
+    gprint (GP_LOG, "%s\n", buff);
+
+  fclose (f);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/!
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/!	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/!	(revision 16632)
@@ -0,0 +1,6 @@
+
+  exec (line)
+
+  perform a system call.  this can also be invoked with "!".  
+  don't use ! in a macro or input script as it is interpreted as a
+  comment character. 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/?
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/?	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/?	(revision 16632)
@@ -0,0 +1,6 @@
+
+  exec (line)
+
+  perform a system call.  this can also be invoked with "!".  
+  don't use ! in a macro or input script as it is interpreted as a
+  comment character. 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Opihi
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Opihi	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Opihi	(revision 16632)
@@ -0,0 +1,5 @@
+
+
+    Opihi
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Shell
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Shell	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Shell	(revision 16632)
@@ -0,0 +1,5 @@
+
+
+    Opihi
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Variables
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Variables	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/Variables	(revision 16632)
@@ -0,0 +1,17 @@
+
+  Opihi shell variables (scalars):
+
+  The Opihi shell can have variables which are designated by a word
+following a dollar sign: $foo.  Certain Mana function create and set
+variables (ie, stats, cursor).  You can also set a variable to the
+result of an arithmetic expression or just a number like this:
+
+  $foo = 10.0
+  $bar = 5*$foo + 0.6
+
+Mana will replace the variables on a line before executing a command.
+See also "Math" for more description of arithmetic operations.
+
+  See Also:  Math
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/break
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/break	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/break	(revision 16632)
@@ -0,0 +1,10 @@
+
+  break [-auto on/off]
+
+  halts macro, if, or for processes and returns to the basic prompt.
+
+  -auto: enables or disables DVO from automatically breaking
+   when it encounters an error
+
+  See also: macro, if, for
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/cd
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/cd	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/cd	(revision 16632)
@@ -0,0 +1,9 @@
+
+   cd (path)
+
+   change current working directory. 
+
+   Note that Kii or Kapa will be launched in the original 
+   directory, which means PS files created by Kii or Kapa 
+   will land in that directory (perhaps an unexpected result).
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/continue
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/continue	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/continue	(revision 16632)
@@ -0,0 +1,4 @@
+
+   continue
+
+   Return to the start of a for-loop.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/date
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/date	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/date	(revision 16632)
@@ -0,0 +1,6 @@
+
+   date (variable)
+
+   Return the date and place it into (variable).
+
+   Default: print to window
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/echo
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/echo	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/echo	(revision 16632)
@@ -0,0 +1,10 @@
+
+  echo [anything]
+
+  prints the rest of the line, after variables and math expressions
+are parsed.  
+
+
+  See Also:  Opihi, math
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/exec
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/exec	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/exec	(revision 16632)
@@ -0,0 +1,6 @@
+
+   exec (shell command)
+
+   Allows a shell command to be run while running DVO
+   On the command line, this can also be done by placing a "!" before the shell
+    command
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/file
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/file	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/file	(revision 16632)
@@ -0,0 +1,9 @@
+
+   file (filename) (variable)
+
+   Checks to see if a file exists
+
+   If a variable is specified, then it is set to 1 if the file is present
+    and set to 0 if it is not.
+
+   Default: output printed to the window
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/for
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/for	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/for	(revision 16632)
@@ -0,0 +1,19 @@
+
+   for var (start) (stop) [delta]
+
+    perform a loop, with $var as the loop variable. 
+    the value of $var runs from (start) to (stop) inclusive, 
+    and is incremented by [delta] (1 by default).
+
+    The loop commands are entered until the appropriate "end" is typed;
+    if there are nested loops, macro definitions, or logical blocks,
+    the correct "end" is used!
+
+    for may be used at the command line, in a macro, or in an input
+    file with no ill effects.
+
+    the variable $var may be accessed during the loop execution.  if
+    the variable $var is assigned a value beyond (stop) during the
+    loop, the loop execution will end.
+
+    See also: macro, if
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/fprintf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/fprintf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/fprintf	(revision 16632)
@@ -0,0 +1,15 @@
+
+   fprintf ("format codes") (value1 value2 ...)
+
+   Prints output according to a specified format
+
+   Fomat codes must match the order and number of values.
+
+   FORMAT CODES:
+    %x.yf : floating point number with x total places and y places after
+             the decimal point; further decimal places are rounded
+    %x.ye : number in scientific notation with x places and y places after
+             the decimal point; further decimal places are rounded
+    %xs : ASCII output with x places
+    %xd : Integers with x places
+    %x : Express number in hexidesimal
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/getchr
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/getchr	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/getchr	(revision 16632)
@@ -0,0 +1,8 @@
+
+   getchr (string) (char) [variable]
+
+   Return the index of the string in the position of the specified character
+
+   Only the first instance of a character is returned.
+
+   If not found, the variable is set to -1.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/help
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/help	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/help	(revision 16632)
@@ -0,0 +1,7 @@
+
+   help (function)
+
+   print the contents of the help file.  
+   typing "help" without an argument will list the available help
+   files.  
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/if
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/if	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/if	(revision 16632)
@@ -0,0 +1,22 @@
+
+   if (logic)
+     (commands)
+   end
+
+   or:
+
+   if (logic)
+     (commands)
+   else 
+     (commnds)
+   end
+
+   logical block.  The commands are performed subject to the logical
+   condition.  The syntax is simplified C:  
+   examples: (x = 6), (x < 6) , (x ! 6), ((x = 6) | (x > 10))
+
+   there are no delimiter characters.
+
+   See also: for, macro
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/input
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/input	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/input	(revision 16632)
@@ -0,0 +1,15 @@
+
+   input (filename)
+
+   execute a series of commands given in the file.
+
+   Two special examples:  
+   ~/.manarc is loaded on startup, which give the user a place to
+   define personal macros, or interesting variables, etc.
+
+   If mana is called in the form "mana file", the file is loaded
+   (after .manarc) before the user is given the command-line prompt.
+   This can be used to invoke mana in a shell script, but care should
+   be taken in a shell-script that the file ends with the word "exit"
+   or "quit", or strange things may happen...
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/list
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/list	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/list	(revision 16632)
@@ -0,0 +1,23 @@
+
+   list (name) (string1) (string2) ... end
+   OR
+   list (name) -split (string1) (string2) ...
+   OR
+   list (name) -x "(ls command)"
+   OR
+   list (name) -x "cat (file)" 
+
+   Create a list of strings that are zero indexed.
+
+   $(name):n = the number of elements in the list (name)
+
+   $(name):5 = the 6th element of the list (name)
+
+   -split option: Turn a list of strings (separated by white spaces)
+     into a list
+
+   -x option: turn an ls command or file into a list (one list element per
+     line in the file + 1 white space)
+
+   ***Note: the list ... end version of the command does not currently work
+             within macros
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/local
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/local	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/local	(revision 16632)
@@ -0,0 +1,7 @@
+
+   local (var)
+
+   Creates a variable that is accessible only within the macro
+    in which it is created.
+
+   Variable value is listed as (macro).(var) using the "??" command
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/macro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/macro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/macro	(revision 16632)
@@ -0,0 +1,11 @@
+
+   macro (name)
+
+   create a macro.  the commands are entered until the word 'end' is
+   reached.  nested if, for, and macro definitions use the
+   appropriately matched occurances of the 'end'.
+
+   Within a macro, the command-line arguments are refered to as $1,
+   $2, etc.  The number of command-line arguments is given by $0.
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/memory
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/memory	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/memory	(revision 16632)
@@ -0,0 +1,12 @@
+
+  memory [x]
+
+  list the currently used memory.  This gives a (possibly very) long
+  listing of the size of every allocated piece of memory.  Placing
+  anything after the word "memory" gives a summary also.  This is
+  useful to see just how close you are to filling your computer's
+  entire memory (Does not include memory allocated to Kii!)
+
+  See Also: buffers
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/output
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/output	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/output	(revision 16632)
@@ -0,0 +1,10 @@
+
+  output (filename or "stdout")
+
+  redirect the output to a file (concat to the end of the file).  This
+  can also be done with the UNIX ">".  However, this command is useful
+  to send information to a file for a part of a Mana session.  For
+  example, you can save results of a "stats" command.
+
+  See Also: input, stats
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/pwd
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/pwd	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/pwd	(revision 16632)
@@ -0,0 +1,7 @@
+
+   pwd -var (variable)
+
+   print current working directory
+
+   Using -var will place the output into the specified variable.
+   Default: print to window
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/quit
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/quit	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/quit	(revision 16632)
@@ -0,0 +1,4 @@
+
+   quit
+
+   Exit from DVO
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/scan
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/scan	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/scan	(revision 16632)
@@ -0,0 +1,8 @@
+
+   scan (filename) (variable) [Nline]
+
+   Place the Nth line of the file into the named variable
+
+   Default N value: 1 (the 1st line)
+
+   The variable recieves the line + 1 white space
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/sleep
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/sleep	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/sleep	(revision 16632)
@@ -0,0 +1,4 @@
+
+   sleep (N)
+
+   Wait for (N) seconds before continuing
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/sprintf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/sprintf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/sprintf	(revision 16632)
@@ -0,0 +1,17 @@
+
+   sprintf (var) ("format codes") (value1 value2 ...)
+
+   Prints output according to a specified format
+
+   Works same as fprintf, except it places the output as a string into (var)
+
+   Fomat codes must match the order and number of values.
+
+   FORMAT CODES:
+    %x.yf : floating point number with x total places and y places after
+             the decimal point; further decimal places are rounded
+    %x.ye : number in scientific notation with x places and y places after
+             the decimal point; further decimal places are rounded
+    %xs : ASCII output with x places
+    %xd : Integers with x places
+    %x : Express number in hexidesimal
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/strlen
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/strlen	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/strlen	(revision 16632)
@@ -0,0 +1,10 @@
+
+   strlen (string) [var]
+
+   Determines the number of characters (plus white spaces) in a string
+    and places it into var
+
+   Default: print to window
+
+   Note: If the string has white spaces, you need to place it within
+    double-quotes.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/strpop
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/strpop	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/strpop	(revision 16632)
@@ -0,0 +1,12 @@
+
+   strpop (string) [var]
+
+   Pops part of a string or a list element that can be placed
+    into [var]
+
+   Default: print to window
+
+   The output is the first set of characters bordered by white space
+
+   ***Note: Both (string) and [var] must be entered without the "$"
+    variable identifier for the program to work properly.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/substr
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/substr	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/substr	(revision 16632)
@@ -0,0 +1,11 @@
+
+   substr (string) (index) (length) [var]
+
+   Returns part of a string starting at the position (index)
+    and of size (length), which can then be placed into [var]
+
+   Default: print to window
+
+   The sub-string is not removed from the original string
+
+   ***Note: Character positions in strings are zero-indexed
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/usleep
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/usleep	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/usleep	(revision 16632)
@@ -0,0 +1,4 @@
+
+   usleep (N)
+
+   Wait for (N) microseconds before continuing
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/wait
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/wait	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/wait	(revision 16632)
@@ -0,0 +1,5 @@
+
+  wait [anything]
+
+  wait echos the rest of the line and waits for <return> to be typed.
+Very useful for pausing the processing of an input file or a macro.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/which
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/which	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/which	(revision 16632)
@@ -0,0 +1,5 @@
+
+   which (command)
+
+   give a short summary info line on a command
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/while
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/while	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/help/while	(revision 16632)
@@ -0,0 +1,5 @@
+
+   while (condition) ... end
+
+   Perform a set of actions until the condition is true
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/init.c	(revision 16632)
@@ -0,0 +1,136 @@
+# include "basic.h"
+
+int config          PROTO((int, char **));
+int exec_sleep      PROTO((int, char **));
+int exec_usleep     PROTO((int, char **));
+int cd              PROTO((int, char **));
+int date            PROTO((int, char **));
+int dirname_opihi   PROTO((int, char **));
+int echo            PROTO((int, char **));
+int exec_last       PROTO((int, char **));
+int exec_next       PROTO((int, char **));
+int exec_break      PROTO((int, char **));
+int file            PROTO((int, char **));
+int getchr_func     PROTO((int, char **));
+int help            PROTO((int, char **));
+int input           PROTO((int, char **));
+int list            PROTO((int, char **));
+int list_help       PROTO((int, char **));
+int list_vars       PROTO((int, char **));
+int local           PROTO((int, char **)); /* data? */
+int macro           PROTO((int, char **));
+int memory          PROTO((int, char **));
+int mkdir_opihi     PROTO((int, char **));
+int module          PROTO((int, char **));
+int output          PROTO((int, char **));
+int pwd             PROTO((int, char **));
+int quit            PROTO((int, char **));
+int run_for         PROTO((int, char **));
+int run_if          PROTO((int, char **));
+int run_while       PROTO((int, char **));
+int scan            PROTO((int, char **));
+int shell           PROTO((int, char **));
+int sprintf_opihi   PROTO((int, char **));
+int fprintf_opihi   PROTO((int, char **));
+int strlen_func     PROTO((int, char **));
+int substr_func     PROTO((int, char **));
+int strpop          PROTO((int, char **));
+int strsub          PROTO((int, char **));
+int wait_func       PROTO((int, char **));
+int which           PROTO((int, char **));
+
+/** mapping of the command names to command functions **/
+static Command cmds[] = {  
+  {1, "config",        config,             "(re)load config file?"},
+  {1, "sleep",         exec_sleep,         "sleep for N seconds"},
+  {1, "usleep",        exec_usleep,        "sleep for N microseconds"},
+  {1, "cd",            cd,                 "change directory"},
+  {1, "date",          date,               "get current date"},
+  {1, "dirname",       dirname_opihi,      "built-in dirname function"},
+  {1, "echo",          echo,               "type this line *"},
+  {1, "break",         exec_break,         "escape from function *"},
+  {1, "continue",      exec_next,          "next loop iteration"},
+  {1, "next",          exec_next,          "next loop iteration"},
+  {1, "last",          exec_last,          "last loop iteration"},
+  {1, "return",        exec_last,          "exit from macro"},
+  {1, "file",          file,               "test file existence"},
+  {1, "getchr",        getchr_func,        "find character in string"},
+  {1, "help",          help,               "get help on a function *"},
+  {1, "input",         input,              "read command lines from a file *"},
+  {1, "list",          list,               "get variable list"},
+  {1, "?",             list_help,          "list commands *"},
+  {1, "??",            list_vars,          "list variables *"},
+  {1, "local",         local,              "define local variables"},
+  {1, "macro",         macro,              "deal with the macros *"}, 
+  {1, "memory",        memory,             "long listing of the allocated memory"},
+  {1, "mkdir",         mkdir_opihi,        "built-in mkdir command"},
+  {1, "module",        module,             "load script file from the modules directories"},
+  {1, "output",        output,             "redirect output to file"},
+  {1, "pwd",           pwd,                "print current working directory"},
+  {1, "exit",          quit,               "exit program *"}, 
+  {1, "quit",          quit,               "exit program *"},
+  {1, "for",           run_for,            "for loop"}, 
+  {1, "if",            run_if,             "logical cases *"}, 
+  {1, "while",         run_while,          "while loop"}, 
+  {1, "scan",          scan,               "scan line from keyboard or file to variable *"},
+  {1, "!",             shell,              "system call"},
+  {1, "exec",          shell,              "system call"},
+  {1, "sprintf",       sprintf_opihi,      "formatted print to a variable"},
+  {1, "fprintf",       fprintf_opihi,      "formatted print to standard output"},
+  {1, "strlen",        strlen_func,        "string length"},
+  {1, "substr",        substr_func,        "substring"},
+  {1, "strpop",        strpop,             "pop a string"},
+  {1, "strsub",        strsub,             "replace instances of a key in a string"},
+  {1, "wait",          wait_func,          "wait until return is typed"},
+  {1, "which",         which,              "show command *"}
+};
+
+void InitBasic () {
+  
+  int i;
+
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+  InitLists ();
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+  
+}
+
+void InitBasic_PantasksClient () {
+  
+  int i;
+
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+  InitLists ();
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    if (!strcmp (cmds[i].name, "quit")) goto valid;
+    if (!strcmp (cmds[i].name, "exit")) goto valid;
+    if (!strcmp (cmds[i].name, "exec")) goto valid;
+    if (!strcmp (cmds[i].name, "!")) goto valid;
+    continue;
+
+  valid:
+    AddCommand (&cmds[i]);
+  }
+}
+
+void FreeBasic () {
+
+  FreeCommands ();
+  FreeMacros ();
+  FreeBuffers ();
+  FreeVectors ();
+  FreeVariables ();
+  FreeLists ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/input.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/input.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/input.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "basic.h"
+# define D_NLINES 100
+
+int input (int argc, char **argv) {
+  
+  int i, NLINES, status;
+  FILE *infile;
+  Macro inlist;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: input <filename>\n");
+    return (FALSE);
+  }
+
+  infile = fopen (argv[1], "r");
+  if (infile == NULL) {
+    gprint (GP_ERR, "no file %s\n", argv[1]); 
+    return (FALSE);
+  }
+
+  /* read file into the current list */
+  NLINES = D_NLINES;
+  ALLOCATE (inlist.line, char *, NLINES);
+  ALLOCATE (inlist.line[0], char, 1024);
+  for (i = 0; (scan_line (infile, inlist.line[i]) != EOF);) {
+    stripwhite (inlist.line[i]);
+    if (inlist.line[i][0] == 0) continue;
+    if (inlist.line[i][0] == '#') continue;
+    if (inlist.line[i][0] == '!') continue;
+
+    REALLOCATE (inlist.line[i], char, strlen(inlist.line[i]) + 1);
+    if (i == NLINES - 1) {
+      NLINES += D_NLINES;
+      REALLOCATE (inlist.line, char *, NLINES)
+    }
+    i++;
+    ALLOCATE (inlist.line[i], char, 1024);
+  }
+  inlist.Nlines = i;
+  fclose (infile);
+
+  /* process this list */
+  status = exec_loop (&inlist);
+
+  /* cleanup list */
+  for (i = 0; i < inlist.Nlines; i++) {
+    free (inlist.line[i]);
+  }
+  free (inlist.line[i]); /* note that we always alloc one extra line */
+  free (inlist.line);
+  return (status);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list.c	(revision 16632)
@@ -0,0 +1,201 @@
+# include "basic.h"
+# define D_NLINES 100
+static char prompt[] = ">> ";
+
+int list (int argc, char **argv) {
+
+  int ThisList, depth, i, done, found;
+  char *input, line[1024];
+  int N, Nbytes, NBYTES, Nread, status;
+  int RunCommand;
+  char *A, *B, *val, *Cmd;
+  FILE *f;
+
+  Cmd = NULL;
+  RunCommand = FALSE;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    Cmd = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    RunCommand = TRUE;
+  }
+
+  // return an error if -add is given with no other args
+  if ((argc > 2) && (!strcmp (argv[2], "-split"))) {
+    if (argc == 3) {
+      gprint (GP_ERR, "USAGE: list (root) -split (word) (word) ...\n");
+      return (FALSE);
+    }
+    
+    for (i = 0; i < argc - 3; i++) {
+      sprintf (line, "%s:%d", argv[1], i);
+      set_str_variable (line, argv[i+3]);
+    }
+    sprintf (line, "%s:n", argv[1]);
+    set_int_variable (line, i);
+
+    return (TRUE);
+  }
+
+  // return an error if -add is given with no other args
+  if ((argc > 2) && (!strcmp (argv[2], "-add"))) {
+    if (argc == 3) {
+      gprint (GP_ERR, "USAGE: list (root) -add (word) (word) ...\n");
+      return (FALSE);
+    }
+    
+    sprintf (line, "%s:n", argv[1]);
+    N = get_int_variable (line, &found);
+    for (i = 0; i < argc - 3; i++) {
+      sprintf (line, "%s:%d", argv[1], N + i);
+      set_str_variable (line, argv[i+3]);
+    }
+    sprintf (line, "%s:n", argv[1]);
+    set_int_variable (line, N + i);
+
+    return (TRUE);
+  }
+
+  // remove the single named entry from the list (finds entry with given name, reduces list length by one)
+  // return an error if -add is given with no other args
+  if ((argc > 2) && (!strcmp (argv[2], "-del"))) {
+    if (argc != 4) {
+      gprint (GP_ERR, "USAGE: list (root) -del (word)\n");
+      return (FALSE);
+    }
+    
+    int j;
+    char *value, *next_value;
+    char line2[1024];
+
+    sprintf (line, "%s:n", argv[1]);
+    N = get_int_variable (line, &found);
+    for (i = 0; i < N; i++) {
+      sprintf (line, "%s:%d", argv[1], i);
+      value = get_variable (line);
+      if (value == NULL) continue;
+      if (!strcmp (value, argv[3])) {
+	free (value);
+	for (j = i + 1; j < N; j++) {
+	  sprintf (line2, "%s:%d", argv[1], j);
+	  next_value = get_variable (line2);
+	  set_str_variable (line, next_value);
+	  strcpy (line, line2);
+	}
+	DeleteNamedScalar (line);
+	sprintf (line2, "%s:n", argv[1]);
+	set_int_variable (line2, N - 1);
+	return (TRUE);
+      }
+      free (value);
+    }      
+    gprint (GP_ERR, "value %s not found in list\n", argv[3]);
+    return (FALSE);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: list (root)                : supply list data, terminate with 'END'\n");
+    gprint (GP_ERR, "USAGE: list (root) -x (command)   : create list from shell output\n");
+    gprint (GP_ERR, "USAGE: list (root) -split (words) : create list from words\n");
+    gprint (GP_ERR, "USAGE: list (root) -add (words)   : extend a list\n");
+    return (FALSE);
+  }
+
+  if (RunCommand) {
+    
+    /* val will hold the result */
+    NBYTES = 1024;
+    ALLOCATE (val, char, NBYTES);
+    
+    /* need to loop until command produces no more output, 
+       REALLOCATING as needed. */
+    f = popen (Cmd, "r");
+    done = FALSE;
+    Nbytes = 0;
+    while (!done) {
+      Nread = fread (&val[Nbytes], 1, 1023, f);
+      if (Nread < 0) { 
+	gprint (GP_ERR, "error reading from command\n");
+	done = TRUE;
+      }
+      if (Nread > 0) {
+	Nbytes += Nread;
+	NBYTES = 1024 + Nbytes;
+	REALLOCATE (val, char, NBYTES);
+      }
+      if (Nread == 0) {
+	done = TRUE;
+      }
+      
+    }
+    val[Nbytes] = 0;
+    status = pclose (f);
+    free (Cmd);
+    
+    if (status) {
+      gprint (GP_ERR, "warning: exit status of command %d\n", status);
+    }
+      
+    A = B = val;
+    for (i = 0; B != (char *) NULL;) {
+      while (isspace (*A) && (*A != 0)) A++;
+      B = strchr (A, '\n');
+      if (B != (char *) NULL) { *B = 0; }
+      if (*A != 0) {
+	sprintf (line, "%s:%d", argv[1], i);
+	set_str_variable (line, A);
+	A = B + 1;
+	i++;
+      }
+    }      
+    free (val);
+    
+    sprintf (line, "%s:n", argv[1]);
+    set_int_variable (line, i);
+    return (TRUE);
+  }
+
+  /* read in loop */
+  depth = 0;
+  ThisList = current_list_depth();
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) {
+      input = readline (prompt);
+    } else {
+      input = get_next_listentry (ThisList);
+    }
+
+    if ((ThisList == 0) && (input == NULL)) {
+      gprint (GP_ERR, "end list with 'END'\n");
+      continue;
+    }
+    if ((ThisList >  0) && (input == NULL)) {
+      gprint (GP_ERR, "missing 'END' in list\n");
+      input = strcreate ("end");
+    }
+    if (ThisList == 0) ohana_memregister (input);
+
+    stripwhite (input);
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { /* we hit the last "END", loop is done */
+	sprintf (line, "%s:n", argv[1]);
+	set_int_variable (line, i);
+	free (input);
+	return (TRUE);
+      }
+    }
+
+    if (*input) { 
+      sprintf (line, "%s:%d", argv[1], i);
+      set_str_variable (line, input);
+      free (input);
+      i++;
+   }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list_help.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list_help.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list_help.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "basic.h"
+
+int list_help (int argc, char **argv) {
+
+  FILE *f;
+  int fd;
+  char filename[128], line[256];
+
+  sprintf (filename, "/tmp/status.XXXXXX");
+  if ((fd = mkstemp (filename)) == -1) {
+    gprint (GP_ERR, "error opening output\n");
+    return (FALSE);
+  }
+  f = fdopen (fd, "w");
+  if (f == (FILE *) NULL) f = stdout;
+  print_commands (f);
+  if (f != stdout) {
+    fclose (f);
+    sprintf (line, "more %s", filename);
+    system (line);
+  }
+  unlink (filename);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list_vars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list_vars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/list_vars.c	(revision 16632)
@@ -0,0 +1,8 @@
+# include "basic.h"
+
+int list_vars (int argc, char **argv) {
+
+  ListVariables ();
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/local.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/local.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/local.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "basic.h"
+
+int local (int argc, char **argv) {
+
+  int i, N, STATIC;
+  char *p;
+
+  /* create a variable named MacroDepth.argv[1] */
+
+  STATIC = FALSE;
+  if ((N = get_argument (argc, argv, "-static"))) {
+    remove_argument (N, &argc, argv);
+    STATIC = TRUE;
+  }
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: local (variable)\n");
+    return (FALSE);
+  }
+  
+  for (i = 1; i < argc; i++) {
+    if (STATIC) {
+      p = get_local_variable_ptr (argv[i]);
+      if (p == NULL) {
+	set_local_variable (argv[i], "NULL");
+      }
+    } else {
+      set_local_variable (argv[i], "NULL");
+    }      
+  }
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/macro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/macro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/macro.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "basic.h"
+
+int macro (int argc, char **argv) {
+
+  int status;
+  CommandF *cmd;
+
+  if ((argc != 2) && (argc != 3) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: macro (cmd)\n");
+    gprint (GP_ERR, "  (cmd) can be one of:\n");
+    gprint (GP_ERR, "    (name)         -- create macro (name)\n");
+    gprint (GP_ERR, "    create (name)  -- create macro (name)\n");
+    gprint (GP_ERR, "    delete (name)  -- delete macro (name)\n");
+    gprint (GP_ERR, "    list   (name)  -- list macro (name)\n");
+    gprint (GP_ERR, "    edit   (name)  -- edit macro (name) <not working yet!> *\n");
+    gprint (GP_ERR, "    read   (name)  -- read macro(s) from file (name) <not working yet!> *\n");
+    gprint (GP_ERR, "    write  (name)  -- write macro (name) to a file <not working yet!> *\n");
+    return (FALSE);
+  }
+
+  cmd = find_macro_command (argv[1]);
+  if (cmd != NULL) {
+    status = (*cmd) (argc - 1, argv + 1);
+  } else {
+    /* sub-command was not found, pass argv[1..N] to macro_create */
+    status = macro_create (argc, argv);
+  }
+
+  return (status);
+}
+
+/* macro is called with the command "macro".  
+   the command line word "macro" is meant to be followed the one of several 
+   possible options:
+   
+   macro create
+   macro delete
+   macro list
+   macro edit
+   macro read
+   macro write
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/memory.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/memory.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/memory.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include "basic.h"
+
+// XXX add a warning if ohana_memory is not compiled in 
+int memory (int argc, char **argv) {
+  
+  if (argc < 2) goto usage;
+
+  if (!strcasecmp (argv[1], "all")) {
+    ohana_memdump (1);
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "leaks")) {
+    ohana_memdump (0);
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "check")) {
+    ohana_memcheck (0);
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "checkfree")) {
+    ohana_memcheck (1);
+    return (TRUE);
+  }
+  if (!strncasecmp ("variables", argv[1], strlen(argv[1]))) {
+    ListVariables ();
+    return (TRUE);
+  }
+  if (!strncasecmp ("vectors", argv[1], strlen(argv[1]))) {
+    ListVectors ();
+    return (TRUE);
+  }
+  if (!strncasecmp ("buffers", argv[1], strlen(argv[1]))) {
+    PrintBuffers (0);
+    return (TRUE);
+  }
+  if (!strncasecmp ("macros", argv[1], strlen(argv[1]))) {
+    ListMacros();
+    return (TRUE);
+  }
+  if (!strncasecmp ("commands", argv[1], strlen(argv[1]))) {
+    print_commands (stderr);
+    return (TRUE);
+  }
+
+usage:
+  gprint (GP_ERR, "USAGE: memory (all/leaks)\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/mkdir.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/mkdir.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/mkdir.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "basic.h"
+
+int mkdir_opihi (int argc, char **argv) {
+
+  int mode, status;
+  struct stat fstats;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: mkdir (path)\n");
+    return (FALSE);
+  }
+
+  mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
+
+  status = stat (argv[1], &fstats);
+  if (!status) {
+    // argv[1] exists, is it a directory?
+    if (!S_ISDIR(fstats.st_mode)) {
+      gprint (GP_ERR, "cannot create directory %s: is an existing file\n", argv[1]);
+      return (FALSE);
+    }
+    return (TRUE);
+  }
+
+  status = mkdirhier (argv[1], mode);
+  if (status == -1) {
+    gprint (GP_ERR, "cannot create directory %s\n", argv[1]);
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+// XXX need to add mode option
+// XXX need to respect umask (need umask command?)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/module.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/module.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/module.c	(revision 16632)
@@ -0,0 +1,77 @@
+# include "basic.h"
+# define D_NLINES 100
+
+/* module loads an opihi script files from the installed module tree */
+int module (int argc, char **argv) {
+  
+  int i, NLINES, Nmodules, Nbytes, status;
+  Macro inlist;
+  char modname[16], *modpath, *filename;
+  FILE *infile = NULL;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: module <filename>\n");
+    return (FALSE);
+  }
+
+  Nmodules = get_int_variable ("MODULES:n", &status);
+  if (!status) {
+    gprint (GP_ERR, "MODULES list not found\n");
+    return (FALSE);
+  }
+
+  /* search for requested file in MODULES:0 - MODULES:n */
+  for (i = 0; i < Nmodules; i++) {
+    snprintf (modname, 16, "MODULES:%d", i);
+    modpath = get_variable (modname);
+    if (modpath == NULL) {
+      gprint (GP_ERR, "MODULES list element %d not found\n", i);
+      return (FALSE);
+    }
+
+    Nbytes = strlen(modpath) + strlen(argv[1]) + 2;
+    ALLOCATE (filename, char, Nbytes);
+    snprintf (filename, Nbytes, "%s/%s", modpath, argv[1]);
+    
+    infile = fopen (filename, "r");
+    free (filename);
+
+    if (infile != NULL) break;
+  }
+  if (infile == NULL) {
+    gprint (GP_ERR, "module %s not found\n", argv[1]); 
+    return (FALSE);
+  }
+    
+  /* read file into the current list */
+  NLINES = D_NLINES;
+  ALLOCATE (inlist.line, char *, NLINES);
+  ALLOCATE (inlist.line[0], char, 1024);
+  for (i = 0; (scan_line (infile, inlist.line[i]) != EOF);) {
+    stripwhite (inlist.line[i]);
+    if (inlist.line[i][0] == 0) continue;
+    if (inlist.line[i][0] == '#') continue;
+    if (inlist.line[i][0] == '!') continue;
+
+    REALLOCATE (inlist.line[i], char, strlen(inlist.line[i]) + 1);
+    if (i == NLINES - 1) {
+      NLINES += D_NLINES;
+      REALLOCATE (inlist.line, char *, NLINES)
+    }
+    i++;
+    ALLOCATE (inlist.line[i], char, 1024);
+  }
+  inlist.Nlines = i;
+  fclose (infile);
+
+  /* process this list */
+  status = exec_loop (&inlist);
+
+  /* cleanup list */
+  for (i = 0; i < inlist.Nlines; i++) {
+    free (inlist.line[i]);
+  }
+  free (inlist.line[i]); /* note that we always alloc one extra line */
+  free (inlist.line);
+  return (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/output.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "basic.h"
+
+int output (int argc, char **argv) {
+  
+  int N, Noutput;
+  gpDest dest;
+  IOBuffer *buffer;
+  char *output, *current;
+
+  dest = GP_LOG;
+  if ((N = get_argument (argc, argv, "-err"))) {
+    dest = GP_ERR;
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-current"))) {
+    current = gprintGetName (dest);
+    remove_argument (N, &argc, argv);
+    set_str_variable (argv[N], current);
+    remove_argument (N, &argc, argv);
+    return (TRUE);
+  }
+
+  if ((N = get_argument (argc, argv, "-buffer"))) {
+    remove_argument (N, &argc, argv);
+    gprintSetBuffer (dest);
+    return (TRUE);
+  }
+    
+  /* set the output target and dump the current buffer there */
+  if ((N = get_argument (argc, argv, "-dump"))) {
+    buffer = gprintGetBuffer (dest);
+    if (buffer == NULL) return (FALSE);
+
+    /* save the current buffer contents */
+    Noutput = buffer[0].Nbuffer;
+    ALLOCATE (output, char, Noutput);
+    memcpy (output, buffer[0].buffer, Noutput);
+    
+    /* set the output target to the specified name */
+    remove_argument (N, &argc, argv);
+    gprintSetFileAllThreads (dest, argv[N]);
+    remove_argument (N, &argc, argv);
+
+    /* send the output to the appropriate destination */
+    gwrite (output, 1, Noutput, dest);
+    free (output);
+    return (TRUE);
+  }
+    
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: output <filename> [-err] [-buffer] [-current var] [-dump filename]\n");
+    return (FALSE);
+  }
+
+  gprintSetFileAllThreads (dest, argv[1]);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/quit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/quit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/quit.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "basic.h"
+
+int quit (int argc, char **argv) {
+
+  int state;
+
+  cleanup ();
+
+  state = 0;
+  if (argc > 1) {
+    state = atof (argv[1]);
+  } 
+
+// the libedit version of readline does not support an incremental write to history file
+# ifndef RL_READLINE_VERSION
+  history = get_variable("HISTORY");
+  if (history != NULL) write_history (history);
+# endif
+
+  exit (state);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_for.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_for.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_for.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include "basic.h"
+# define D_NLINES 100
+static char prompt[] = ">> ";
+
+int run_for (int argc, char **argv) {
+
+  int ThisList, depth, i, done, status, found, NLINES, j;
+  double start, end, delta;
+  char *input;
+  double value, sign;
+  Macro loop;
+
+  if ((argc != 4) && (argc != 5)) {
+    gprint (GP_ERR, "USAGE: for (var) (start) (stop) [delta] -- terminate with 'END'\n");
+    return (FALSE);
+  }
+
+  start = atof (argv[2]);
+  end   = atof (argv[3]);
+  delta = 1.0;
+  if (argc == 5) delta = atof (argv[4]);
+  sign = SIGN(delta);
+
+  NLINES = D_NLINES;
+  ALLOCATE (loop.line, char *, NLINES);
+
+  /* read in loop */
+  depth = 0;
+  ThisList = current_list_depth();
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+    stripwhite (input);
+
+    /* check for end-of-data syntax error */
+    if (input == NULL) {
+      if (ThisList == 0)  {
+	gprint (GP_ERR, "end loop with 'END'\n");
+	continue;
+      } else {
+	gprint (GP_ERR, "misbalanced loop\n");
+	for (j = 0; j < loop.Nlines; j++) {
+	  free (loop.line[j]);
+	}
+	free (loop.line);
+	return (FALSE);
+      }	
+    }
+    if (ThisList == 0) ohana_memregister (input);
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { 
+	free (input);
+	break;
+      }
+    }
+
+    /* if line has data, add to loop list */
+    if (*input) { 
+      loop.line[i] = input;
+      i++;
+      if (i == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (loop.line, char *, NLINES);
+      }
+    }
+  }
+
+  /* cleanup loop data */
+  loop.Nlines = i;
+  REALLOCATE (loop.line, char *, MAX (loop.Nlines, 1));
+
+  status = TRUE;
+  interrupt = FALSE;
+  for (value = start; (sign*value < sign*end) && !interrupt; value += delta) {
+    if ((int)value == value) 
+      set_int_variable (argv[1], (int) value);
+    else 
+      set_variable (argv[1], value);
+    status = exec_loop (&loop);
+    value = get_double_variable (argv[1], &found);
+    if (loop_next) continue;
+    if (loop_last) break;
+    if (loop_break) break;
+  }
+  /* 'last' and 'next' should only affect one loop */
+  loop_last = loop_next = FALSE; 
+
+  /* break should propagate up if auto_break is set */
+  loop_break = FALSE;
+  if (auto_break && !status) loop_break = TRUE;
+
+  /* cleanup list */
+  for (j = 0; j < loop.Nlines; j++) {
+    free (loop.line[j]);
+  }
+  free (loop.line);
+
+  if (loop_break) return (FALSE);
+  return (TRUE);
+}
+
+/*
+  If we are entering at the keyboard (ThisList == 0), use readline.
+  Otherwise, read from the current list, remove list lines.
+  execute when we hit the final "END" (the true END -- we count macro defines!!) 
+*/
+     
+/* while processing the loop, the loop status variables may be set
+   by the loop commands, or the loop may quite on a failed command,
+   setting the exec_loop return status to false. the loop status variables
+   are:
+   loop_next : stop this loop, but try another loop
+   loop_last : stop loop processing, but return true so external loop may continue
+   loop_break : stop loop processing, and return false so external loop will break
+   interrupt : external interrupt signal
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_if.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_if.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_if.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include "basic.h"
+# define prompt    "if: "
+
+int run_if (int argc, char **argv) {
+
+  int ThisList, depth, done, status, InlineCommand;
+  int i, length, logic;
+  char *input, *val, *line;
+  int nloop, size;
+
+  InlineCommand = FALSE;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: if (conditional) : follow with commands, end with the word 'END'\n");
+    gprint (GP_ERR, "   OR: if (conditional) command\n");
+    return (FALSE);
+  }
+  if (argc > 2) {
+    InlineCommand = TRUE;
+  }
+
+  /* determine value of conditional expression */
+  val = dvomath (1, &argv[1], &size, 0);
+  if (val == NULL) {
+    gprint (GP_ERR, "syntax error in logic: %s\n", argv[1]);
+    return (FALSE);
+  }
+  logic = atof (val); /* is round-off error a danger? */ 
+  free (val);
+
+  if (InlineCommand) {
+    if (logic) {
+      /* re-build a command line from the remaining strings */
+      length = 0;
+      for (i = 2; i < argc; i++) {
+	length += strlen(argv[i]) + 1;
+      }
+      length++;
+      ALLOCATE (line, char, length);
+      memset (line, 0, length);
+      for (i = 2; i < argc; i++) {
+	if (i == 2) {
+	  strcpy (line, argv[i]);
+	} else {
+	  strcat (line, " ");
+	  strcat (line, argv[i]);
+	}
+      }
+      status = multicommand (line);
+      free (line);
+      return (status);
+    } else {
+      return (TRUE);
+    }
+  }    
+
+  /* read in if-list */
+  nloop = 0;
+  depth = 0;
+  ThisList = current_list_depth();
+
+  done = FALSE;
+  while (!done) {
+
+    nloop ++;
+    /* get the next line (from correct place) */
+    if (ThisList == 0) {
+      input = readline (prompt);
+    } else {
+      input = get_next_listentry (ThisList);
+    }
+
+    if ((ThisList == 0) && (input == NULL)) {
+      gprint (GP_ERR, "end if-block with 'END'\n");
+      continue;
+    }
+    if ((ThisList >  0) && (input == NULL)) {
+      gprint (GP_ERR, "missing 'END' in if-block\n");
+      input = strcreate ("end");
+    }
+    if (ThisList == 0) ohana_memregister (input);
+
+    stripwhite (input);
+
+    /* test for new macro, search for "end" statement */
+    if (!logic && is_list (input)) {
+      depth ++;
+      free (input);
+      continue;
+    }
+    
+    /* check for an "else", invert logic */
+    if ((depth == 0) && !strncasecmp (input, "ELSE", 4)) {
+      logic ^= TRUE;
+      free (input);
+      continue;
+    }
+
+    /* test for end of nested block -- if not nested, END refers to this if */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { 
+	/* we hit the last "END", if-block is done */
+	free (input);
+	return (TRUE);	
+      }
+      free (input);  /* a do-nothing line */
+      continue;
+    }
+
+    if (logic) {
+      if (*input) { 
+	status = multicommand (input);
+	if (ThisList == 0) add_history (input);
+	if (auto_break && !status) return (FALSE);
+      }
+    } 
+    free (input);
+  }
+  return (TRUE);
+}
+
+/*
+     If we are entering at the keyboard (ThisList == 0), use readline.
+     Otherwise, read from the current list, remove list lines.
+     End when we hit the final "END" (the true END -- we count macro defines!!) 
+     */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_while.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_while.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/run_while.c	(revision 16632)
@@ -0,0 +1,109 @@
+# include "basic.h"
+# define D_NLINES 100
+static char prompt[] = ">> ";
+
+int run_while (int argc, char **argv) {
+
+  int ThisList, depth, i, done, status, NLINES, j;
+  char *input, *val, *logic_line;
+  int logic, size;
+  Macro loop;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: while (condition)\n");
+    return (FALSE);
+  }
+
+  val = dvomath (1, &argv[1], &size, 0);
+  if (val == NULL) return (FALSE);
+  logic = atof (val); /* warning: round-off error is a danger */
+  free (val);
+  
+  NLINES = D_NLINES;
+  ALLOCATE (loop.line, char *, NLINES);
+
+  /* read in loop */
+  depth = 0;
+  ThisList = current_list_depth();
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+    stripwhite (input);
+
+    /* check for end-of-data syntax error */
+    if (input == (char *) NULL) {
+      if (ThisList == 0)  {
+	gprint (GP_ERR, "end 'while' loop with 'END'\n");
+	continue;
+      } else {
+	gprint (GP_ERR, "misbalanced 'while' loop\n");
+	for (j = 0; j < loop.Nlines; j++) {
+	  free (loop.line[j]);
+	}
+	free (loop.line);
+	return (FALSE);
+      }	
+    }
+    if (ThisList == 0) ohana_memregister (input);
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) break;
+    }
+
+    /* if line has data, add to loop list */
+    if (*input) { 
+      loop.line[i] = input;
+      i++;
+      if (i == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (loop.line, char *, NLINES);
+      }
+    }
+  }
+
+  /* cleanup loop data */
+  free (input);
+  loop.Nlines = i;
+  REALLOCATE (loop.line, char *, MAX (loop.Nlines, 1));
+
+  /* execute for loop */
+  do { 
+    status = exec_loop (&loop);
+    if (loop_next) continue;
+    if (loop_last) break;
+    if (loop_break) break;
+
+    logic_line = strcreate (argv[1]);
+    logic_line = expand_vars (logic_line);
+    val = dvomath (1, &logic_line, &size, 0);
+    free (logic_line);
+
+    if (val == NULL) return (FALSE);
+    logic = atof (val); /* warning: round-off error is a danger */
+    free (val);
+  } while (logic && !interrupt);
+  /* 'last' and 'next' should only affect one loop */
+  loop_last = loop_next = FALSE; 
+
+  /* break should propagate up if auto_break is set */
+  loop_break = FALSE;
+  if (auto_break && !status) loop_break = TRUE;
+
+  /* cleanup list */
+  for (j = 0; j < loop.Nlines; j++) {
+    free (loop.line[j]);
+  }
+  free (loop.line);
+
+  if (loop_break) return (FALSE);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/scan.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/scan.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/scan.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "basic.h"
+
+int scan (int argc, char **argv) {
+
+  int i, N, status;
+  char *line;
+  FILE *f;
+
+  if ((argc != 3) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: scan <filename> <var> [N]\n");
+    return (FALSE);
+  }
+
+  f = stdin;
+  if (strcmp (argv[1], "stdin")) {
+    f = fopen (argv[1], "r");
+    if (f == (FILE *) NULL) {
+      gprint (GP_ERR, "file %s not found\n", argv[1]);
+      return (FALSE);
+    }
+  }
+  
+  ALLOCATE (line, char, 1024);
+  N = 1;
+  if (argc == 4) {
+    N = atof(argv[3]);
+    if (N < 1) {
+      gprint (GP_ERR, "scan: line numbers must start at 1\n");
+      return (FALSE);
+    }
+  }
+
+  for (i = 0; (i < N) && ((status = scan_line (f, line)) != EOF); i++);
+  if (i < N) {
+    set_str_variable (argv[2], "EOF");
+  } else {
+    set_str_variable (argv[2], line);
+  }
+  free (line);
+
+  if (f != stdin) {
+    fclose (f);
+  }
+  return (TRUE);
+ 
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/shell.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/shell.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/shell.c	(revision 16632)
@@ -0,0 +1,96 @@
+# include "basic.h"
+
+static char *defshell = "/bin/sh";
+static char *cmdflag = "-c";
+
+// XXX add the ability to exec without a separate shell
+// XXX add an option to modify the timeout
+
+int shell (int argc, char **argv) {
+  
+  int i, pid;
+  int exit_status;
+  int wait_status;
+  int result, length;
+  char **args, *shell;
+
+  shell = getenv ("SHELL");
+  if (shell == NULL) shell = defshell;
+
+  // we are creating a command of the form /bin/sh -c argv[1] argv[2] etc, where
+  // the argv[1], etc elements are concatenated into a single string
+  ALLOCATE (args, char *, 4);
+  args[0] = shell;
+  args[1] = cmdflag;
+
+  length = 0;
+  for (i = 1; i < argc; i++) {
+    length += strlen(argv[i]) + 1;
+  }
+  
+  ALLOCATE (args[2], char, length);
+  args[2][0] = 0;
+  for (i = 1; i < argc; i++) {
+    strcat (args[2], argv[i]);
+    if (i < argc - 1) strcat (args[2], " ");
+  }
+  args[3] = NULL;
+
+  // send the commands to the shell specified in the env variable SHELL, or else /bin/sh
+
+  // use execvp to enable a timeout on the system call 
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    execvp (shell, args);
+    exit (1);
+  }
+  free (args[2]);
+  free (args);
+  
+  // wait for process to finish or timeout
+  for (i = 0; i < 200; i++) {
+    result = waitpid (pid, &wait_status, WNOHANG);
+    switch (result) {
+      case -1:   // error on waitpid
+	switch (errno) {
+	  case ECHILD:
+	    gprint (GP_ERR, "unknown PID, not a child process: %d\n", pid);
+	    return (FALSE);
+	  default:
+	    gprint (GP_ERR, "unexpected response to waitpid: %d\n", result);
+	    abort();
+	}
+	break;
+
+      case 0:   // child not yet exited
+	usleep (10000);
+	continue;
+
+      default:
+	if (result != pid) {
+	  gprint (GP_ERR, "waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, pid);
+	  abort();
+	}
+	if (WIFEXITED(wait_status)) {
+	  exit_status = WEXITSTATUS(wait_status);
+	  if (exit_status) {
+	    return FALSE;
+	  } else {
+	    return TRUE;
+	  }
+	}
+	if (WIFSIGNALED(wait_status)) {
+	  gprint (GP_ERR, "job %d exited on signal %d\n", pid, WTERMSIG(wait_status));
+	  return (FALSE);
+	}
+	if (WIFSTOPPED(wait_status)) {
+	  gprint (GP_ERR, "waitpid returns 'stopped' programming error\n");
+	  abort();
+	}
+    }
+  }
+
+  gprint (GP_ERR, "timeout on %d\n", pid);
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/sleep.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/sleep.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/sleep.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "basic.h"
+
+int exec_sleep (int argc, char **argv) {
+
+  int i;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "usage: sleep N\n");
+    return (FALSE);
+  }
+
+  i = atof (argv[1]);
+  sleep (i);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/sprintf.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/sprintf.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/sprintf.c	(revision 16632)
@@ -0,0 +1,83 @@
+# include "basic.h"
+# define NCHAR 1024
+
+// XXX this function uses fixed string lengths....
+/* convert line, tmp, fmt to dynamic strings? */
+
+int sprintf_opihi (int argc, char **argv) {
+
+  int i;
+  char line[NCHAR], tmp[NCHAR], fmt[NCHAR];
+  char *p1, *p2, *q;
+
+  if (argc < 3) {
+    gprint (GP_ERR, "USAGE: sprintf var format value value ...\n");
+    return (FALSE);
+  }
+
+  q  = line;
+  bzero (line, NCHAR);
+
+  p1 = argv[2];
+  for (i = 3; i < argc; i++) {
+    bzero (tmp, NCHAR);
+    bzero (fmt, NCHAR);
+
+    /* find next format character */
+    p2 = strchr (p1, '%');
+    if (p2 == (char *) NULL) {
+      gprint (GP_ERR, "mismatch between format and values\n");
+      return (FALSE);
+    }
+    if (strlen(q) + p2 - p1 > NCHAR) {
+      gprint (GP_ERR, "line too long");
+      return (FALSE);
+    }
+    memcpy (q, p1, p2-p1);
+    q = line + strlen(line);
+    
+    /* identify type (%NNNs %NNNNd %NNNNf) */
+    for (p1 = p2 + 1; (*p1 == '.') || (*p1 == '-') || (*p1 == '+') || (*p1 == ' ') || isdigit(*p1); p1++);
+    memcpy (fmt, p2, p1 - p2 + 1);
+    switch (*p1) {
+      case 'e':
+      case 'f':
+	sprintf (tmp, fmt, atof(argv[i]));
+	break;
+      case 's':
+	sprintf (tmp, fmt, argv[i]);
+	break;
+      case 'd':
+      case 'c':
+      case 'x':
+	sprintf (tmp, fmt, atoi(argv[i]));
+	break;
+      default:
+	gprint (GP_ERR, "syntax error in format (only e,f,s,d,c,x allowed)\n");
+	return (FALSE);
+    }
+    if (strlen(q) + strlen(tmp) > NCHAR) {
+      gprint (GP_ERR, "line too long");
+      return (FALSE);
+    }
+    memcpy (q, tmp, strlen(tmp));
+    q = line + strlen(line);
+    p1++;
+  }
+  p2 = strchr (p1, '%');
+  if (p2 != (char *) NULL) {
+    gprint (GP_ERR, "mismatch between format and values\n");
+    return (FALSE);
+  }
+  
+  p2 = p1 + strlen (p1);
+  if (strlen(q) + p2 - p1 > NCHAR) {
+    gprint (GP_ERR, "line too long");
+    return (FALSE);
+  }
+  memcpy (q, p1, p2-p1);
+  set_str_variable (argv[1], line);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strchr.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strchr.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strchr.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "basic.h"
+
+int getchr_func (int argc, char **argv) {
+
+  /* returns position of the first given character */ 
+  char *c;
+  int pos;
+
+  if ((argc != 3) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: strchr (string) (char) [var]\n");
+    return (FALSE);
+  }
+
+  c = strchr (argv[1], argv[2][0]);
+
+  if (c == (char *) NULL) {
+    pos = -1;
+  } else {
+    pos = c - argv[1];
+  }
+
+  if (argc == 5) {
+    set_variable (argv[3], pos);
+  } else {
+    gprint (GP_ERR, "%d\n", pos);
+  }
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strlen.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strlen.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strlen.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "basic.h"
+
+int strlen_func (int argc, char **argv) {
+
+  /* returns length of the given string */ 
+  int len;
+
+  if ((argc != 2) && (argc != 3)) {
+    gprint (GP_ERR, "USAGE: strlen (string) [var]\n");
+    return (FALSE);
+  }
+
+  len = strlen (argv[1]);
+
+  if (argc == 3) {
+    set_int_variable (argv[2], len);
+  } else {
+    gprint (GP_ERR, "%d\n", len);
+  }
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strpop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strpop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strpop.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "basic.h"
+
+int strpop (int argc, char **argv) {
+
+  char *p, *q, *string;
+
+  if ((argc != 2) && (argc != 3)) {
+    gprint (GP_ERR, "USAGE: strpop (var) [out]\n");
+    return (FALSE);
+  }
+
+  /* string is a copy of the value on the variable stack */
+  string = get_variable (argv[1]);
+  if (string == NULL) return (FALSE);
+  
+  /* thisword is an allocated string */
+  p = thisword (string);
+
+  q = nextword (string);
+  if (q == NULL) {
+    set_str_variable (argv[1], "NULL");
+  } else {
+    set_str_variable (argv[1], q);
+  }
+  
+  if (argc == 3) {
+    set_str_variable (argv[2], p);
+  } else {
+    gprint (GP_LOG, "%s\n", p);
+  }
+
+  free (p);
+  free (string);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strsub.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strsub.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/strsub.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "basic.h"
+
+int strsub (int argc, char **argv) {
+
+  int N, Nkey, Noutput;
+  char *varName;
+  char *p, *q, *input, *output, *key, *value;
+
+  // clear all sections
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: strsub (string) (key) (value) [-var out]\n");
+    gprint (GP_ERR, "  replace instances of 'key' with the 'value'\n");
+    return (FALSE);
+  }
+
+  // input string 
+  input = argv[1];
+  
+  // find this in the string
+  key = argv[2];
+  Nkey = strlen(key);
+
+  // replace with this
+  value = argv[3];
+
+  Noutput = MAX (16, strlen(input));
+  ALLOCATE (output, char, Noutput);
+  memset (output, 0, Noutput);
+
+  // 0123456789
+  // wordKEYnew
+  // p = 0, q = 4, q-p = 4 -> p = 7
+
+  p = input;
+  while (*p && ((q = strstr (p, key)) != NULL)) {
+    output = opihi_append (output, &Noutput, p, q);
+    output = opihi_append (output, &Noutput, value, value + strlen(value));
+    p = q + Nkey;
+  }
+  if (*p) {
+    output = opihi_append (output, &Noutput, p, p + strlen(p));
+  }
+  
+  if (varName) {
+    set_str_variable (varName, output);
+  } else {
+    gprint (GP_LOG, "%s\n", output);
+  }
+
+  free (output);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/substr.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/substr.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/substr.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "basic.h"
+
+int substr_func (int argc, char **argv) {
+
+  int N1, N2, len;
+  char *c, *string;
+
+  if ((argc != 4) && (argc != 5)) {
+    gprint (GP_ERR, "USAGE: substr (string) N1 N2 [var]\n");
+    return (FALSE);
+  }
+
+  N1 = atof (argv[2]);
+  N2 = atof (argv[3]);
+
+  len = strlen (argv[1]);
+  if ((N1 >= len) || (N1 + N2 > len)) {
+    c = (char *) NULL;
+  } else {
+    c = strncreate (&argv[1][N1], N2);
+  }
+
+  if (c == (char *) NULL) {
+    string = strcreate ("");
+  } else {
+    string = strcreate (c);
+  }
+
+  if (argc == 5) {
+    set_str_variable (argv[4], string);
+  } else {
+    gprint (GP_ERR, "%s\n", string);
+  }
+  free (c);
+  free (string);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/break.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/break.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/break.sh	(revision 16632)
@@ -0,0 +1,19 @@
+
+list tests
+ test1
+end
+
+# test that break will halt operation
+macro test1
+ $PASS = 1
+ break -auto off
+ for i 0 10
+   if ($i == 5)
+     break
+   end
+ end
+ if ($i != 5)
+   $PASS = 0
+ end
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/cd.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/cd.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/cd.sh	(revision 16632)
@@ -0,0 +1,34 @@
+
+list tests
+ test1
+ test2
+end
+
+# test that cd will go into a new directory
+macro test1
+ $PASS = 1
+ exec mkdir test.dir
+ output /dev/null
+ cd test.dir
+ exec touch foo.test
+ cd ..
+ output stdout
+ file test.dir/foo.test exists
+ if ($exists != 1)
+   $PASS = 0
+ end
+ exec rm -f test.dir/foo.test
+ exec rmdir test.dir
+end
+
+# test that pwd output is correct
+macro test2
+ $PASS = 1
+ exec touch foo.test
+ pwd -var testdir
+ file $testdir\/foo.test exists
+ if ($exists != 1)
+  $PASS = 0
+ end
+ exec rm foo.test
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/config.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/config.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/config.sh	(revision 16632)
@@ -0,0 +1,14 @@
+
+list tests
+ test1
+end
+
+# test that config does not return an error
+macro test1
+ $PASS = 1
+ config
+ if ($STATUS == 0)
+   $PASS = 0
+ end
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/continue.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/continue.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/continue.sh	(revision 16632)
@@ -0,0 +1,18 @@
+
+list tests
+ test1
+end
+
+# test that continue skips within a loop
+macro test1
+ $PASS = 1
+ for i 0 10
+   if ($i > 5)
+      continue
+   end
+   $j = $i
+ end
+ if ($j != 5)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/date.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/date.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/date.sh	(revision 16632)
@@ -0,0 +1,33 @@
+
+list tests
+ test1
+ test2
+end
+
+# test that date does not return an error
+macro test1
+ $PASS = 1
+ date -var var
+ if ($STATUS == 0)
+   $PASS = 0
+ end
+end
+
+# test that date constructs a reasonable sample date
+macro test2
+ $PASS = 1
+ date -var date1
+ $date2 = `date`
+ list w1 -split $date1
+ list w2 -split $date2
+ # check the first 3 entries (day, month, date)
+ if ($w1:0 != $w2:0)
+   $PASS = 0
+ end
+ if ($w1:1 != $w2:1)
+   $PASS = 0
+ end
+ if ($w1:2 != $w2:2)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/echo.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/echo.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/echo.sh	(revision 16632)
@@ -0,0 +1,19 @@
+
+list tests
+ test1
+end
+
+# test that echo actually echoes
+macro test1
+ $PASS = 1
+ exec rm -f test.dat
+ output test.dat
+ echo foobar
+ output stdout
+ $line = `cat test.dat`
+ # exec rm -f test.dat
+ if ($line != foobar)
+   $PASS = 0
+ end
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/file.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/file.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/file.sh	(revision 16632)
@@ -0,0 +1,19 @@
+
+list tests
+ test1
+end
+
+# test that the file test function works at all
+macro test1
+ $PASS = 1
+ exec touch foo.test
+ file foo.test exists
+ if ($exists != 1)
+   $PASS = 0
+ end
+ exec rm -f foo.test
+ file foo.test exists
+ if ($exists != 0)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/for.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/for.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/for.sh	(revision 16632)
@@ -0,0 +1,216 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test5
+ memtest1
+ memtest2
+ memtest3
+end
+
+# do we loop up correctly?
+macro test1
+
+  $PASS = 0
+
+  local i
+
+  for i 0 100
+  end    
+  
+ if ($i == 99)
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+
+end
+
+# do we loop down correctly?
+macro test2
+
+  $PASS = 0
+
+  local i
+
+  for i 100 0 -1
+  end    
+  
+ if ($i == 1)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i : $i"
+ end
+
+end
+
+# do we loop up in small steps correctly?
+macro test3
+
+  $PASS = 0
+
+  local i N
+
+  $N = 0
+  for i 0 100 0.1
+   $N = $N + 1
+  end    
+  
+ if (($i == 99.9) && ($N == 1000))
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+   echo "N: $N"
+ end
+
+end
+
+# do we loop down in small steps correctly?
+macro test4
+
+  $PASS = 0
+
+  local i N
+
+  $N = 0
+  for i 100 0 -0.1
+   $N = $N + 1
+  end    
+  
+ if (($i == 0.1) && ($N == 1000))
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+   echo "N: $N"
+ end
+
+end
+
+# do we break from a loop correctly
+macro test5
+
+  $PASS = 0
+
+  break -auto off
+
+  local i N
+
+  $N = 0
+  for i 0 100
+   $N = $N + 1
+   if ($i == 30)
+     break
+   end
+  end    
+
+  $PASS = 1
+  
+  if (($i != 30) || ($N != 31))
+    $PASS = 0
+    echo "i: $i"
+    echo "N: $N"
+  end
+end
+
+# check memleaks
+macro memtest1
+
+ $PASS = 0
+
+ local i N
+
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks with many loop lines
+macro memtest2
+
+ $PASS = 0
+
+ local i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+  echo "test line in loop"
+  echo "test line in loop"
+  echo "test line in loop"
+  echo "test line in loop"
+  echo "test line in loop"
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks on break
+macro memtest3
+
+ $PASS = 0
+
+ local i N
+
+ break -auto off
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+  for j 0 5
+    break
+    echo "test line in loop"
+    echo "test line in loop"
+    echo "test line in loop"
+    echo "test line in loop"
+    echo "test line in loop"
+  end
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($i != 9999)
+   $PASS = 0
+   echo "break jumped outer loop: i = $i" 
+ end
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/fprintf.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/fprintf.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/fprintf.sh	(revision 16632)
@@ -0,0 +1,84 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test5
+end
+
+macro test1
+ exec rm -f test.dat
+ output test.dat
+ fprintf "test %03d" 50
+ output stdout
+ $line = `cat test.dat`
+ if ("$line" == "test 050")
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+macro test2
+ exec rm -f test.dat
+ output test.dat
+ fprintf "test %6.3f" 123.45678
+ output stdout
+ $line = `cat test.dat`
+ if ("$line" == "test 123.457")
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+macro test3
+ exec rm -f test.dat
+ output test.dat
+ fprintf "test %x" 32
+ output stdout
+ $line = `cat test.dat`
+ if ("$line" == "test 20")
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+macro test4
+ exec rm -f test.dat
+ output test.dat
+ fprintf "test %10s" foobar
+ output stdout
+ $line = `cat test.dat`
+ if ("$line" == "test     foobar")
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+# check for memory leaks
+macro test5
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 1000
+   fprintf "test %10s" foobar
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ($endmem - $startmem < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo growth: {$endmem - $startmem}
+   echo kB/loop: {($endmem - $startmem)/1000}
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/getchr.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/getchr.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/getchr.sh	(revision 16632)
@@ -0,0 +1,23 @@
+
+list tests
+ test1
+ test2
+end
+
+# index test
+macro test1
+ $PASS = 1
+ getchr "a long string.string" . var
+ if ($var != 13)
+   $PASS = 0
+ end
+end
+
+# null test
+macro test2
+ $PASS = 1
+ getchr "a long string.string" x var
+ if ($var != -1)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/if.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/if.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/if.sh	(revision 16632)
@@ -0,0 +1,263 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test5
+ test6
+ test7
+ test8
+ test9
+ test10
+ test11
+ test12
+ test13
+# test14
+end
+
+# basic logical test
+macro test1
+
+ local a
+
+ $a = 1
+
+ if ($a == 1)
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+
+# basic logical test
+macro test2
+
+ local a b
+
+ $a = 1
+ $b = 2
+
+ if (($a == 1) && ($b == 2))
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+
+# basic logical test
+macro test3
+
+ local a b
+
+ $a = 1
+ $b = 5
+
+ if (($a == 1) && ($b < 10))
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+
+# basic logical test
+macro test4
+
+ local a
+
+ $a = 0
+
+ if ($a == 1)
+   $PASS = 0
+ else
+   $PASS = 1
+ end
+end
+
+
+# basic logical test
+macro test5
+
+ local a
+
+ $a = 1
+
+ if ($a > 0)
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+
+# basic logical test
+macro test6
+
+ local a
+
+ $a = 1
+
+ if ($a < 2)
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+
+# basic logical test
+macro test7
+
+ local a
+
+ $a = test
+
+ if ("$a" == "test")
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+
+# basic logical test
+macro test8
+
+ local a
+
+ $a = foobar
+
+ if ("$a" == "test")
+   $PASS = 0
+ else
+   $PASS = 1
+ end
+end
+
+
+# basic logical test
+macro test9
+
+ local a b
+
+ $a = 1
+ $b = 2
+
+ if (($a == 0) || ($b == 2))
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+end
+
+
+# basic logical test
+macro test10
+
+ local a b
+
+ $a = 1
+ $b = 2
+
+ if (($a == 0) || ($b == 1))
+   $PASS = 0
+ else
+   $PASS = 1
+ end
+end
+
+
+# basic logical test
+macro test11
+
+ local a b
+
+ $a = 1
+ $b = 2
+
+ if (($a <= 0) || ($b >= 3))
+   $PASS = 0
+ else
+   $PASS = 1
+ end
+end
+
+
+# basic logical test
+macro test12
+
+ local a
+
+ $a = 1
+
+ if ($a != 1)
+   $PASS = 0
+ else
+   $PASS = 1
+ end
+end
+
+
+# check memleaks
+macro test13
+
+ local a b i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ $a = 1
+ $b = 2
+ for i 0 10000
+   if (($a == 1) && ($b == 2))
+    echo "run"    
+   end
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# memory test using break
+macro test14
+
+ local a b i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ $a = 1
+ $b = 2
+ for i 0 10000
+   if (($a == 1) && ($b == 2))
+    break
+    echo "run"    
+   end
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/list.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/list.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/list.sh	(revision 16632)
@@ -0,0 +1,174 @@
+list tests
+ test1
+ test2
+ test3
+ test4
+ memtest2
+ memtest3
+ memtest4
+end
+
+list check
+  this
+  is
+  a
+  list
+end
+
+# Does list work?
+macro test1
+ $PASS = 1
+ if ($check:n != 4)
+  $PASS = 0
+  echo "Number of list elements: $check:n"
+ end
+ if (("$check:0" != "this") || ("$check:1" != "is") || ("$check:2" != "a") || ("$check:3" != "list"))
+  $PASS = 0
+  echo "List element does not return correctly!"
+ end
+end
+
+# Test split option
+macro test2
+ $PASS = 1
+ list check2 -split This is a list
+ if ($check2:n != 4)
+  $PASS = 0
+  echo "Number of list elements: $check2:n"
+ end
+ if (("$check2:0" != "This") || ("$check2:1" != "is") || ("$check2:2" != "a") || ("$check2:3" != "list"))
+  $PASS = 0
+  echo "List element does not return correctly!"
+ end
+end
+
+# Test -x option for the ls command
+macro test3
+ $PASS = 1
+ list check3 -x "ls /dev/null"
+ if ($check3:n != 1)
+  $PASS = 0
+  echo "Number of list elements: $check3:n"
+ end
+ if ("$check3:0" != "/dev/null")
+  $PASS = 0
+  echo "List element does not return correctly!"
+ end
+end
+
+# Test -x for files
+macro test4
+ $PASS = 1
+ file list_test.txt fchk
+ if ($fchk)
+  exec rm list_test.txt
+ end
+ output list_test.txt
+ echo This
+ echo is
+ echo a
+ echo list
+ output stdout
+ list check4 -x "cat list_test.txt"
+ if ($check4:n != 4)
+  $PASS = 0
+  echo "Number of list elements: $check4:n"
+ end
+ if (("$check4:0" != "This") || ("$check4:1" != "is") || ("$check4:2" != "a") || ("$check4:3" != "list"))
+  $PASS = 0
+  echo "List element does not return correctly!"
+ end
+ if ($PASS)
+  exec rm list_test.txt
+ end
+end
+
+# Memory test for list -split
+macro memtest2
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  list check2 -split This is a list
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+end
+
+# Memory test for list -x
+macro memtest3
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  list check3 -x "ls /dev/null"
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+end
+
+# Memory test for list -x
+macro memtest4
+
+ file list_test.txt fchk
+ if ($fchk)
+  exec rm list_test.txt
+ end
+ output list_test.txt
+ echo This
+ echo is
+ echo a
+ echo list
+ output stdout
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  list check4 -x "cat list_test.txt"
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+ if ($PASS)
+  exec rm list_test.txt
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/local.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/local.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/local.sh	(revision 16632)
@@ -0,0 +1,51 @@
+list tests
+ test1
+ memtest1
+end
+
+# Does local work?
+macro test1
+
+ $PASS = 1
+
+ local lvar
+
+ $lvar = 5
+
+ if ($?lvar != 1)
+  $PASS = 0
+  echo "Local variable failed to be created!"
+ end
+
+ if ($lvar != 5)
+  $PASS = 0
+  echo "Local variable value not assigned!"
+ end
+
+end
+
+
+# Memory test for local
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  local lvar2
+  $lvar2 = 9
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/macro.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/macro.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/macro.sh	(revision 16632)
@@ -0,0 +1,48 @@
+list tests
+ test_prep
+ test1
+ memtest1
+end
+
+# Is the macro working?
+macro test_prep
+ $test_var1 = check1
+ $test_var2 = check2
+ $var_count = $0
+end
+
+macro test1
+ $PASS = 1
+ $var_count = 0
+ $test_var1 = blank
+ $test_var2 = blank
+ test_prep var1 var2 var3
+ if ($var_count != 4)
+  $PASS = 0
+  echo "Number of parameters (should be 4): $var_count"
+ end
+ if (("$test_var1" != "check1") || ("$test_var2" != "check2"))
+  $PASS = 0
+  echo "Paramaters not assigned correctly!: $test_var1 $test_var2"
+ end
+end
+
+# Memory Test for macro
+macro memtest1
+ $PASS = 1
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+  test_prep
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/math.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/math.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/math.sh	(revision 16632)
@@ -0,0 +1,149 @@
+
+list tests
+ test1
+ test2
+ testmem1
+ testmem2
+ testmem3
+ testmem4
+end
+
+# test subtraction
+macro test1
+
+  $PASS = 1
+  local i
+
+  exec rm -f tmp.txt
+  output tmp.txt
+  echo {99 - 98}
+  output stdout
+
+  $i = `cat tmp.txt` 
+ 
+ if ($i != 1)
+   $PASS = 0
+   echo "i : $i"
+ end
+
+end
+
+# test addition, division, and multiplication
+macro test2
+
+ $PASS = 1
+ local a b c
+
+ $a = {2 + 4}
+ $b = {12 / 2}
+ $c = {2 * 3}
+
+ if (($a != 6) || ($b != 6) || ($c != 6))
+   $PASS = 0
+   echo "ALL VALUES NOT 6: a=$a\ b=$b\ c=$c\"
+ end
+
+end
+
+# check memleaks (set global)
+macro testmem1
+
+ $PASS = 1
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   echo {99 - 98}
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (set global)
+macro testmem2
+
+ $PASS = 1
+ local i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   $N = 99 - 98
+   $N = 1 + 1
+   $N = 2 * 2
+   $N = 22/7
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (set global)
+macro testmem3
+
+ $PASS = 1
+ local i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   $N = 99
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (set global)
+macro testmem4
+
+ $PASS = 1
+ local i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   $N = word
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/module.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/module.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/module.sh	(revision 16632)
@@ -0,0 +1,16 @@
+
+list tests
+ test1
+end
+
+# Test if the $MODULES list is available
+macro test1
+
+ $PASS = 1
+
+ if ($?MODULES:0 != 1)
+  $PASS = 0
+  echo "Modules list not loaded!"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/output.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/output.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/output.sh	(revision 16632)
@@ -0,0 +1,63 @@
+
+list tests
+ test1
+ testmem1
+end
+
+# test subtraction
+macro test1
+
+ $PASS = 1
+
+ output testout.txt
+
+ file testout.txt fchk
+ output stdout
+ if ($fchk != 1)
+  $PASS = 0
+  echo "Output did not create test file!"
+ end
+
+ output testout.txt
+ echo "This is a test."
+ output stdout
+ $line = `cat testout.txt`
+ if ("$line" == "This is a test.")
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "Output: $line"
+ end
+
+ exec rm testout.txt
+
+end
+
+
+# check memleaks
+macro testmem1
+
+ $PASS = 1
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 1000
+  output testout.txt
+  echo "This is a test."
+  output stdout
+  exec rm testout.txt
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/scan.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/scan.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/scan.sh	(revision 16632)
@@ -0,0 +1,117 @@
+list tests
+ test1
+ memtest1
+ memtest2
+end
+
+# Does scan work?
+macro test1
+ $PASS = 1
+ file test_file.txt fchk
+ if ($fchk)
+  exec rm test_file.txt
+ end
+ output test_file.txt
+ echo This
+ echo is
+ echo a
+ echo test
+ echo file
+ output stdout
+ scan test_file.txt fscan
+ if ("$fscan" != "This")
+  $PASS = 0
+  echo "Default not working!"
+ end
+ scan test_file.txt fscan 4
+ if ("$fscan" != "test")
+  $PASS = 0
+  echo "Scan failure!"
+ end
+ if ($PASS)
+  exec rm test_file.txt
+ end
+end
+
+# Memory test for scan (default)
+macro memtest1
+
+ file test_file.txt fchk
+ if ($fchk)
+  exec rm test_file.txt
+ end
+ output test_file.txt
+ echo This
+ echo is
+ echo a
+ echo test
+ echo file
+ output stdout
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  scan test_file.txt fscan
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+ if ($PASS)
+  exec rm test_file.txt
+ end
+
+end
+
+
+# Memory test for scan (specified)
+macro memtest2
+
+ file test_file.txt fchk
+ if ($fchk)
+  exec rm test_file.txt
+ end
+ output test_file.txt
+ echo This
+ echo is
+ echo a
+ echo test
+ echo file
+ output stdout
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  scan test_file.txt fscan 5
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+ if ($PASS)
+  exec rm test_file.txt
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/shell.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/shell.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/shell.sh	(revision 16632)
@@ -0,0 +1,35 @@
+
+list tests
+ test1
+ test2
+end
+
+# test that a shell function works at all
+macro test1
+ $PASS = 1
+ exec touch foo.test
+ file foo.test exists
+ if ($exists != 1)
+   $PASS = 0
+ end
+ exec rm -f foo.test
+ file foo.test exists
+ if ($exists != 0)
+   $PASS = 0
+ end
+end
+
+# test that the shell status is returned
+macro test2
+ $PASS = 1
+ exec touch foo.test
+ exec ls foo.test >& /dev/null
+ if ($STATUS != 1)
+   $PASS = 0
+ end
+ exec rm -f foo.test
+ exec ls foo.test >& /dev/null
+ if ($STATUS != 0)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/sleep.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/sleep.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/sleep.sh	(revision 16632)
@@ -0,0 +1,25 @@
+list tests
+ test1
+end
+
+# Does sleep work?
+macro test1
+ $PASS = 1
+
+ list tstart -x "date +%S"
+
+ sleep 3
+
+ list tend -x "date +%S"
+
+ if ($tstart:0 >= 57)
+  $tend:0 = $tend:0 + 60
+ end
+
+ $diff = abs (3 - abs($tstart:0 - $tend:0))
+
+ if ($diff > 1.1)
+  $PASS = 0
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/sprintf.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/sprintf.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/sprintf.sh	(revision 16632)
@@ -0,0 +1,43 @@
+list tests
+ test1
+ memtest1
+end
+
+# Does sprintf work?
+macro test1
+ $PASS = 1
+
+ local test_var
+
+ sprint test_var "%7s %5.2f %9.3e" float 34.5 12630000
+
+ if ("$test_var" != "  float 34.50 1.263e+07")
+  $PASS = 0
+ end
+
+end
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+  sprint test_var "%7s %5.2f %9.3e" float 34.5 12630000
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/strlen.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/strlen.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/strlen.sh	(revision 16632)
@@ -0,0 +1,47 @@
+list tests
+ test1
+ memtest1
+end
+
+# Does strlen work?
+macro test1
+ 
+ $PASS = 1
+
+ $tstr = "Test string"
+
+ strlen $tstr len
+
+ if ($len != 11)
+  $PASS = 0
+  echo "Incorrect length: $len"
+ end
+
+end
+
+# Memory Test
+macro memtest1
+
+ local i
+
+ $tstr = "Test string"
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  strlen $tstr len
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/strpop.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/strpop.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/strpop.sh	(revision 16632)
@@ -0,0 +1,105 @@
+list tests
+ test1
+ test2
+ memtest1
+ memtest2
+end
+
+# Does strpop work with variables?
+macro test1
+
+ $PASS = 1
+
+ $tstr = a test string
+
+ local a b c
+
+ strpop tstr a
+ strpop tstr b
+ strpop tstr c
+
+ if (("$a" != "a") || ("$b" != "test") || ("$c" != "string"))
+  $PASS = 0
+  echo "Incorrect value returned!"
+ end
+end
+
+
+# Does strpop work with lists?
+macro test2
+
+ $PASS = 1
+
+ list tlis -split list of strings
+
+ local a b c
+
+ strpop tlis:0 a
+ strpop tlis:1 b
+ strpop tlis:2 c
+
+ if (("$a" != "list") || ("$b" != "of") || ("$c" != "strings"))
+  $PASS = 0
+  echo "Incorrect value returned!"
+ end
+end
+
+
+# Memory test for variables
+macro memtest1
+
+ local i tstr a b c d
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  $tstr = one two three
+  strlen tstr a
+  strlen tstr b
+  strlen tstr c
+  strlen tstr d
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+end
+
+
+# Memory test for lists
+macro memtest2
+
+ local i tstr a b c d
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  list tstr -split one two three
+  strlen tstr:0 a
+  strlen tstr:1 b
+  strlen tstr:2 c
+  strlen tstr:0 d
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/substr.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/substr.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/substr.sh	(revision 16632)
@@ -0,0 +1,49 @@
+list tests
+ test1
+ memtest1
+end
+
+# Does substr work?
+macro test1
+
+ $PASS = 1
+
+ local tstr ss
+
+ $tstr = "riddle me this"
+
+ substr $tstr 4 8 ss
+
+ if ("$ss" != "le me th")
+  $PASS = 0
+  echo "Incorrect substring returned!"
+ end
+end
+
+
+# Memory test
+macro memtest1
+
+ local i tstr ss
+
+ $tstr = "riddle me this"
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+  substr $tstr 4 8 ss
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/test.dat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/test.dat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/test.dat	(revision 16632)
@@ -0,0 +1,1 @@
+test     foobar
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/usleep.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/usleep.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/usleep.sh	(revision 16632)
@@ -0,0 +1,25 @@
+list tests
+ test1
+end
+
+# Does usleep work?
+macro test1
+ $PASS = 1
+
+ list tstart -x "date +%S"
+
+ usleep 3000000
+
+ list tend -x "date +%S"
+
+ if ($tstart:0 >= 57)
+  $tend:0 = $tend:0 + 60
+ end
+
+ $diff = abs (3 - abs($tstart:0 - $tend:0))
+
+ if ($diff > 1.1)
+  $PASS = 0
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/variable.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/variable.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/variable.sh	(revision 16632)
@@ -0,0 +1,504 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test5
+ test6
+ test7
+ test8
+ test9
+ test10
+ test11
+ test12
+ test13
+ test14
+ testmem1
+ testmem2
+ testmem3
+ testmem4
+ testmem5
+ testmem6
+ testmem7
+ testmem8
+ testmem9
+ testmem10
+end
+
+# do we set variables correctly?
+macro test1
+
+ local i
+
+ $i = 99
+  
+ if ($i == 99)
+   $PASS = 1
+ else
+   $PASS = 0
+ end
+
+end
+
+# do math expressions assign the correct value (test2 -> test8)
+macro test2
+
+  local i
+
+  $i = 99 - 98
+  
+ if ($i == 1)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i : $i"
+ end
+
+end
+
+macro test3
+
+  local i
+
+  $i = 2*3
+  
+ if ($i == 6)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+ end
+
+end
+
+macro test4
+
+  local i
+
+  $i = 2^3
+
+ if ($i == 8)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+ end
+
+end
+
+macro test5
+
+  local i
+
+  $i = 2+3
+
+ if ($i == 5)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+ end
+
+end
+
+macro test6
+
+  local i
+
+  $i = 6/3
+
+ if ($i == 2)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+ end
+
+end
+
+# testing operation priority
+macro test7
+
+  local i j
+
+  $i = 2 - 3*2
+  $j = 10/2*5+5
+
+ if (($i == -4) && ($j == 30))
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i\ j: $j"
+ end
+
+end
+
+# testing math on negative numbers
+macro test8
+
+  local i
+
+  $i = -2 - -3
+
+ if ($i == 1)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+ end
+
+end
+
+# testing the existance of variables
+macro test9
+
+  local i
+
+  $i = 0
+
+ if ($?i == 1)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "i: $i"
+ end
+end
+
+# test increment
+macro test10
+
+  local i N
+
+  $N = 0
+  for i 0 100
+    $N ++
+  end
+
+  if ($N == 100)
+   $PASS = 1
+  else
+   $PASS = 0
+   echo "N: $N"
+ end
+end
+
+# test decrement
+macro test11
+
+  local i N
+
+  $N = 100
+  for i 0 100
+    $N --
+  end
+
+  if ($N == 0)
+   $PASS = 1
+  else
+   $PASS = 0
+   echo "N: $N"
+ end
+end
+
+# test command assign
+macro test12
+
+  local i N
+
+  $N = `ls -dF /etc`
+
+  if ("$N" == "/etc/")
+   $PASS = 1
+  else
+   $PASS = 0
+   echo "N: $N"
+ end
+end
+
+# test vector assign
+macro test13
+
+  local i N
+
+  create v1 0 100
+  v1[5] = 10
+  set v2 = v1 + 20
+
+  if (v2[5] == 30)
+   $PASS = 1
+  else
+   $PASS = 0
+   echo "v1\[5\]: v1[5]"
+   echo "v2\[5\]: v2[5]"
+ end
+end
+
+# test local variables
+macro test14
+
+ $PASS = 1
+
+ if (($?i == 1) || ($?N == 1))
+  $PASS = 0
+ end
+end
+
+# check memleaks (set global)
+macro testmem1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+   $Nvar = 10
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (set string)
+macro testmem2
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   $Nvar = test line
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (set double)
+macro testmem3
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+   $Nvar = 5.212
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (set local)
+macro testmem4
+
+ local i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+   $N = 10
+ end    
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (existence)
+macro testmem5
+
+ local i N
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   echo $?N
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (get variable)
+macro testmem6
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ $Nvar = 5
+ output /dev/null
+ for i 0 10000
+   echo $Nvar
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (increment)
+macro testmem7
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ $Nvar = 0
+ output /dev/null
+ for i 0 10000
+   $Nvar ++
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (decrement)
+macro testmem8
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ $Nvar = 10000
+ output /dev/null
+ for i 0 10000
+   $Nvar --
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# check memleaks (command)
+macro testmem9
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 100
+   $Nvar = `ls -d /etc`
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/100}"
+ end
+end
+
+# check memleaks (vector assign)
+macro testmem10
+
+ local i
+
+ create v1 0 100
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   v1[5] = $i
+ end    
+ output stdout
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/while.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/while.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/test/while.sh	(revision 16632)
@@ -0,0 +1,19 @@
+list tests
+ test1
+end
+
+# Does while work?
+macro test1
+ $PASS = 1
+ local i
+ $i = 0
+ while ($i <= 10)
+  if ($i == 11)
+   $PASS = 0
+   echo "While loop failure!"
+   echo "i: $i"
+   break
+  end
+  $i++
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/usleep.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/usleep.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/usleep.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "basic.h"
+
+int exec_usleep (int argc, char **argv) {
+
+  int i;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "usage: usleep N\n");
+    return (FALSE);
+  }
+
+  i = atof (argv[1]);
+  usleep (i);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/wait.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/wait.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/wait.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "basic.h"
+
+int wait_func (int argc, char **argv) {
+
+  char buff[1024];
+  int i;
+
+  for (i = 1; i < argc; i++) {
+    gprint (GP_ERR, "%s ", argv[i]);
+  }
+  gprint (GP_ERR, "\n");
+  scan_line (stdin, buff);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/which.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/which.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.basic/which.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "basic.h"
+
+int which (int argc, char **argv) {
+
+  Command *cmd;
+ 
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: which <filename>\n");
+    return (FALSE);
+  }
+
+  cmd = MatchCommand (argv[1], TRUE, TRUE);
+  if (cmd == NULL) return (FALSE);
+
+  gprint (GP_ERR, "%-25s -- %s\n", cmd[0].name, cmd[0].help);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/Makefile	(revision 16632)
@@ -0,0 +1,158 @@
+default: libdatacmd
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+SRC     =       $(HOME)/cmd.data
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+DATA    =       $(DESTDATA)/mana
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+# data user commands ########################
+srcs = \
+$(SRC)/init.$(ARCH).o          \
+$(SRC)/accum.$(ARCH).o		\
+$(SRC)/applyfit2d.$(ARCH).o	\
+$(SRC)/applyfit.$(ARCH).o	\
+$(SRC)/box.$(ARCH).o		\
+$(SRC)/book.$(ARCH).o		\
+$(SRC)/book_commands.$(ARCH).o	\
+$(SRC)/center.$(ARCH).o	\
+$(SRC)/clear.$(ARCH).o		\
+$(SRC)/clip.$(ARCH).o		\
+$(SRC)/close.$(ARCH).o		\
+$(SRC)/concat.$(ARCH).o	\
+$(SRC)/contour.$(ARCH).o	\
+$(SRC)/create.$(ARCH).o	\
+$(SRC)/cumulative.$(ARCH).o	\
+$(SRC)/cursor.$(ARCH).o	\
+$(SRC)/cut.$(ARCH).o		\
+$(SRC)/delete.$(ARCH).o	\
+$(SRC)/device.$(ARCH).o	\
+$(SRC)/dimendown.$(ARCH).o	\
+$(SRC)/dimenup.$(ARCH).o	\
+$(SRC)/dbconnect.$(ARCH).o	\
+$(SRC)/dbselect.$(ARCH).o	\
+$(SRC)/erase.$(ARCH).o		\
+$(SRC)/extract.$(ARCH).o	\
+$(SRC)/fft1d.$(ARCH).o		\
+$(SRC)/fft2d.$(ARCH).o		\
+$(SRC)/fit2d.$(ARCH).o		\
+$(SRC)/fit.$(ARCH).o		\
+$(SRC)/gaussj.$(ARCH).o	\
+$(SRC)/gaussdeviate.$(ARCH).o	\
+$(SRC)/grid.$(ARCH).o		\
+$(SRC)/gridify.$(ARCH).o       \
+$(SRC)/grow.$(ARCH).o		\
+$(SRC)/ungridify.$(ARCH).o     \
+$(SRC)/histogram.$(ARCH).o	\
+$(SRC)/imcut.$(ARCH).o	 	\
+$(SRC)/imhist.$(ARCH).o	\
+$(SRC)/imsmooth.$(ARCH).o	\
+$(SRC)/integrate.$(ARCH).o	\
+$(SRC)/interpolate.$(ARCH).o	\
+$(SRC)/jpeg.$(ARCH).o		\
+$(SRC)/kern.$(ARCH).o		\
+$(SRC)/keyword.$(ARCH).o	\
+$(SRC)/labels.$(ARCH).o	\
+$(SRC)/limits.$(ARCH).o	\
+$(SRC)/line.$(ARCH).o		\
+$(SRC)/list_buffers.$(ARCH).o	\
+$(SRC)/list_header.$(ARCH).o	\
+$(SRC)/list_vectors.$(ARCH).o	\
+$(SRC)/load.$(ARCH).o		\
+$(SRC)/lookup.$(ARCH).o	\
+$(SRC)/mkrgb.$(ARCH).o	\
+$(SRC)/mcreate.$(ARCH).o	\
+$(SRC)/medacc.$(ARCH).o	\
+$(SRC)/mget.$(ARCH).o		\
+$(SRC)/minterpolate.$(ARCH).o	\
+$(SRC)/mset.$(ARCH).o		\
+$(SRC)/peak.$(ARCH).o		\
+$(SRC)/periodogram.$(ARCH).o	\
+$(SRC)/plot.$(ARCH).o		\
+$(SRC)/dot.$(ARCH).o		\
+$(SRC)/point.$(ARCH).o		\
+$(SRC)/ps.$(ARCH).o		\
+$(SRC)/queuedelete.$(ARCH).o	\
+$(SRC)/queuedrop.$(ARCH).o	\
+$(SRC)/queuelist.$(ARCH).o	\
+$(SRC)/queueload.$(ARCH).o	\
+$(SRC)/queuesize.$(ARCH).o	\
+$(SRC)/queuepush.$(ARCH).o	\
+$(SRC)/queuepop.$(ARCH).o	\
+$(SRC)/queueprint.$(ARCH).o	\
+$(SRC)/queueinit.$(ARCH).o	\
+$(SRC)/radial.$(ARCH).o	\
+$(SRC)/rd.$(ARCH).o		\
+$(SRC)/rdseg.$(ARCH).o		\
+$(SRC)/read_vectors.$(ARCH).o	\
+$(SRC)/rebin.$(ARCH).o		\
+$(SRC)/resize.$(ARCH).o	\
+$(SRC)/roll.$(ARCH).o		\
+$(SRC)/rotate.$(ARCH).o	\
+$(SRC)/save.$(ARCH).o		\
+$(SRC)/section.$(ARCH).o	\
+$(SRC)/select.$(ARCH).o	\
+$(SRC)/set.$(ARCH).o		\
+$(SRC)/shift.$(ARCH).o		\
+$(SRC)/sort.$(ARCH).o		\
+$(SRC)/spline_apply.$(ARCH).o	\
+$(SRC)/spline_construct.$(ARCH).o \
+$(SRC)/stats.$(ARCH).o		   \
+$(SRC)/style.$(ARCH).o		   \
+$(SRC)/subraster.$(ARCH).o	   \
+$(SRC)/subset.$(ARCH).o	   \
+$(SRC)/svd.$(ARCH).o		   \
+$(SRC)/swapbytes.$(ARCH).o	   \
+$(SRC)/textline.$(ARCH).o	   \
+$(SRC)/tv.$(ARCH).o		   \
+$(SRC)/tvchannel.$(ARCH).o	   \
+$(SRC)/tvcolors.$(ARCH).o	   \
+$(SRC)/tvcontour.$(ARCH).o	   \
+$(SRC)/tvgrid.$(ARCH).o	   \
+$(SRC)/uniq.$(ARCH).o		   \
+$(SRC)/unsign.$(ARCH).o	   \
+$(SRC)/vbin.$(ARCH).o		   \
+$(SRC)/vclip.$(ARCH).o		   \
+$(SRC)/vgauss.$(ARCH).o           \
+$(SRC)/vmaxwell.$(ARCH).o           \
+$(SRC)/vgrid.$(ARCH).o		   \
+$(SRC)/vload.$(ARCH).o		   \
+$(SRC)/vpop.$(ARCH).o		   \
+$(SRC)/vroll.$(ARCH).o		   \
+$(SRC)/vsmooth.$(ARCH).o	\
+$(SRC)/vstat.$(ARCH).o		   \
+$(SRC)/wd.$(ARCH).o		   \
+$(SRC)/write_vectors.$(ARCH).o	   \
+$(SRC)/zap.$(ARCH).o		   \
+$(SRC)/zplot.$(ARCH).o
+
+# dependancy rules for include files ########################
+incs = \
+$(INC)/opihi.h \
+$(INC)/external.h \
+$(INC)/shell.h \
+$(INC)/dvomath.h \
+$(INC)/convert.h \
+$(INC)/display.h 
+
+$(srcs): $(incs)
+
+$(LIB)/libdatacmd.$(ARCH).a: $(srcs)
+$(LIB)/libdatacmd.$(ARCH).$(DLLTYPE): $(srcs)
+
+$(DESTLIB)/libdatacmd.a: $(LIB)/libdatacmd.$(ARCH).a
+$(DESTLIB)/libdatacmd.$(DLLTYPE): $(LIB)/libdatacmd.$(ARCH).$(DLLTYPE)
+
+libdatacmd: $(DESTLIB)/libdatacmd.a  $(DESTLIB)/libdatacmd.$(DLLTYPE)
+
+uninstall:
+	rm -f $(DESTLIB)/libdatacmd.a
+	rm -f $(DESTLIB)/libdatacmd.$(DLLTYPE)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/accum.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/accum.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/accum.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "data.h"
+
+int accum (int argc, char **argv) {
+  
+  int i, Nbins, bin, N, Normalize;
+  float start, end, delta;
+  float *V, *K, *O, *NV;
+  Vector *val, *key, *out;
+
+  NV = NULL;
+  Normalize = FALSE;
+  if ((N = get_argument (argc, argv, "-norm"))) {
+    remove_argument (N, &argc, argv);
+    Normalize = TRUE;
+  }
+
+  if ((argc != 6) && (argc != 7)) {
+    gprint (GP_ERR, "USAGE: accum <value> <vector> <key> start end [delta]\n");
+    gprint (GP_ERR, "  sum <value> in bins corresponding to the value of <key>\n");
+    return (FALSE);
+  }
+
+  if ((val = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((key = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (val[0].Nelements != key[0].Nelements) {
+    gprint (GP_ERR, "key and value don't match\n");
+    return (FALSE);
+  }
+  if ((out = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[4]);
+  end   = atof (argv[5]);
+  if (argc == 7) 
+    delta = atof (argv[6]);
+  else 
+    delta = 1;
+  if ((start == end) || (delta == 0)) {
+    gprint (GP_ERR, "error in value: %f to %f, %f\n", start, end, delta);
+    return (FALSE);
+  }
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+  Nbins = (end - start) / delta;
+
+  out[0].Nelements = Nbins;
+  REALLOCATE (out[0].elements, float, out[0].Nelements);
+  bzero (out[0].elements, sizeof(float)*out[0].Nelements);
+  if (Normalize) {
+    ALLOCATE (NV, float, Nbins);
+    bzero (NV, sizeof(float)*Nbins);
+  }
+
+  V = val[0].elements;
+  K = key[0].elements;
+  O = out[0].elements;
+
+  for (i = 0; i < val[0].Nelements; i++, V++, K++) {
+    bin = MIN (MAX (0, (*K - start) / delta), Nbins - 1);
+    O[bin] += *V;
+    if (Normalize) NV[bin] ++;
+  }      
+
+  if (Normalize) {
+    for (i = 0; i < Nbins; i++) {
+      O[i] /= (float) NV[i];
+    }
+    free (NV);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/applyfit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/applyfit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/applyfit.c	(revision 16632)
@@ -0,0 +1,57 @@
+# include "data.h"
+
+char *get_variable (char *);
+
+int applyfit (int argc, char **argv) {
+  
+  int i, j, order;
+  char *c, name[64];
+  double *C, X;
+  float *x, *y;
+  Vector *xvec, *yvec;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: applyfit x y\n");
+    return (FALSE);
+  }
+
+  c = get_variable ("Cn");
+  if (c == NULL) {
+    gprint (GP_ERR, "no fit available\n");
+    return (FALSE);
+  }
+  order = atof (c);
+  free (c);
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  ALLOCATE (C, double, order+1);
+  for (i = 0; i < order + 1; i++) {
+    sprintf (name, "C%d", i);
+    c = get_variable (name);
+    if (c == NULL) {
+      gprint (GP_ERR, "missing fit term %d\n", i);
+      return (FALSE);
+    }
+    C[i] = atof (c);
+    free (c);
+  }
+  yvec[0].Nelements = xvec[0].Nelements;
+  REALLOCATE (yvec[0].elements, float, yvec[0].Nelements);
+  bzero (yvec[0].elements, sizeof(float)*yvec[0].Nelements);
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+
+  for (j = 0; j < xvec[0].Nelements; j++, x++, y++) {
+    X = 1;
+    for (i = 0; i < order + 1; i++) {
+      *y += C[i]*X;
+      X = X * (*x);
+    }
+  }
+
+  free (C);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/applyfit2d.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/applyfit2d.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/applyfit2d.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+char *get_variable (char *);
+
+int applyfit2d (int argc, char **argv) {
+  
+  int i, j, n, order;
+  char *c, name[64];
+  double **C, X, Y;
+  float *x, *y, *z;
+  Vector *xvec, *yvec, *zvec;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: applyfit x y z\n");
+    return (FALSE);
+  }
+
+  c = get_variable ("Cnn");
+  if (c == NULL) {
+    gprint (GP_ERR, "no fit available\n");
+    return (FALSE);
+  }
+  order = atof (c);
+  free (c);
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((zvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  ALLOCATE (C, double *, order+1);
+  for (i = 0; i < order + 1; i++) {
+    ALLOCATE (C[i], double, order+1);
+    for (j = 0; j < order + 1 - i; j++) {
+      sprintf (name, "CX%dY%d", i, j);
+      c = get_variable (name);
+      if (c == NULL) {
+	gprint (GP_ERR, "missing fit term %d,%d\n", i, j);
+	for (j = 0; j < i; j++) free (C[j]);
+	free (C);
+	return (FALSE);
+      }
+      C[i][j] = atof (c);
+      free (c);
+    }
+  }
+
+  zvec[0].Nelements = xvec[0].Nelements;
+  REALLOCATE (zvec[0].elements, float, zvec[0].Nelements);
+  bzero (zvec[0].elements, sizeof(float)*zvec[0].Nelements);
+  x = xvec[0].elements;
+  y = yvec[0].elements;
+  z = zvec[0].elements;
+
+  for (n = 0; n < xvec[0].Nelements; n++, x++, y++, z++) {
+    Y = X = 1;
+    for (j = 0; j < order + 1; j++) {
+      X = Y;
+      for (i = 0; i < order + 1 - j; i++) {
+	*z += C[i][j]*X;
+	X = X * (*x);
+      }
+      Y = Y * (*y);
+    }
+  }
+  for (i = 0; i < order + 1; i++) free (C[i]);
+  free (C);
+
+  return (TRUE);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/book.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/book.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/book.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "data.h"
+
+int book_list (int argc, char **argv);
+int book_init (int argc, char **argv);
+int book_create (int argc, char **argv);
+int book_delete (int argc, char **argv);
+int book_getbook (int argc, char **argv);
+int book_listbook (int argc, char **argv);
+int book_shuffle (int argc, char **argv);
+int book_npages (int argc, char **argv);
+int book_newpage (int argc, char **argv);
+int book_getpage (int argc, char **argv);
+int book_delpage (int argc, char **argv);
+int book_listpage (int argc, char **argv);
+int book_setword (int argc, char **argv);
+int book_getword (int argc, char **argv);
+
+static Command book_commands[] = {
+  {1, "list",     book_list,     "list books"},
+  {1, "init",     book_init,     "initialize a book"},
+  {1, "create",   book_create,   "create a book"},
+  {1, "delete",   book_delete,   "delete a book"},
+  {1, "getbook",  book_getbook,  "get book name by location"},
+  {1, "listbook", book_listbook, "list pages in a book"},
+  {1, "shuffle",  book_shuffle,  "shuffle pages in a book"},
+  {1, "npages",   book_npages,   "return number of pages in a book"},
+  {1, "newpage",  book_newpage,  "create a new page in a book"},
+  {1, "getpage",  book_getpage,  "get page name by location"},
+  {1, "delpage",  book_delpage,  "delete a page in a book"},
+  {1, "listpage", book_listpage, "list a page in a book"},
+  {1, "setword",  book_setword,  "set the value of a word in a page"},
+  {1, "getword",  book_getword,  "set the value of a word from a page"},
+};
+
+int book_command (int argc, char **argv) {
+
+  int i, N, status;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: book (command)\n");
+    gprint (GP_ERR, "    book list                                  : list books\n");
+    gprint (GP_ERR, "    book init     (book)                       : removes all pages from book\n");
+    gprint (GP_ERR, "    book create   (book)                       : create a book\n");
+    gprint (GP_ERR, "    book delete   (book)                       : delete a book\n");
+    gprint (GP_ERR, "    book getbook  (where) [-var var]           : get book name\n");
+    gprint (GP_ERR, "    book listbook (book)                       : list a book\n");
+    gprint (GP_ERR, "    book shuffle  (book)                       : randomize pages in a book\n");
+    gprint (GP_ERR, "    book npages   (book) [-var var] [-key key] : return number of pages in a book\n");
+    gprint (GP_ERR, "    book newpage  (book) (page)                : create a new page in a book\n");
+    gprint (GP_ERR, "    book getpage  (book) (where) [-var var] [-key key value] : get page name in a book\n");
+    gprint (GP_ERR, "    book delpage  (book) (page) [-key key]     : delete a page in a book\n");
+    gprint (GP_ERR, "    book delpage  (book) -key name value       : delete a page in a book\n");
+    gprint (GP_ERR, "    book listpage (book) (page)                : list a page in a book\n");
+    gprint (GP_ERR, "    book setword  (book) (page) (word) (value) : set the value of a word in a page\n");
+    gprint (GP_ERR, "    book getword  (book) (page) (word) [-var var] : set the value of a word from a page\n");
+    return (FALSE);
+  }
+
+  N = sizeof (book_commands) / sizeof (Command);
+
+  /* find the book sub-command which matches */
+  for (i = 0; i < N; i++) {
+    if (!strcmp (book_commands[i].name, argv[1])) {
+      status = (*book_commands[i].func) (argc - 1, argv + 1);
+      return (status);
+    }
+  }
+
+  gprint (GP_ERR, "unknown book command %s\n", argv[1]);
+  return (FALSE);
+}
+
+/* book is called with the command "book".  
+   the command line word "book" is meant to be followed the one of several 
+   possible options:
+   
+   book create
+   book delete
+   book list
+   book edit
+   book read
+   book write
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/book_commands.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/book_commands.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/book_commands.c	(revision 16632)
@@ -0,0 +1,492 @@
+# include "data.h"
+
+int book_list (int argc, char **argv) {
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: book list\n");
+    return FALSE;
+  }
+
+  ListBooks();
+  return TRUE;
+}
+
+int book_create (int argc, char **argv) {
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book create (book)\n");
+    return FALSE;
+  }
+
+  CreateBook (argv[1]);
+  return TRUE;
+}
+
+int book_delete (int argc, char **argv) {
+
+  int status;
+  Book *book;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book delete (book)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    return FALSE;
+  }
+
+  status = DeleteBook (book);
+  if (!status) abort ();
+  return TRUE;
+}
+
+int book_init (int argc, char **argv) {
+
+  int status;
+  Book *book;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book init (book)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book != NULL) {
+      status = DeleteBook (book);
+      if (!status) abort ();
+  }
+
+  CreateBook (argv[1]);
+  return TRUE;
+}
+
+int book_listbook (int argc, char **argv) {
+
+  Book *book;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book listbook (book)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    return FALSE;
+  }
+
+  ListPages (book);
+  return TRUE;
+}
+
+int book_npages (int argc, char **argv) {
+
+  int i, N, Npages;
+  Book *book;
+  char *varName;
+  char *Key, *Value, *value;
+
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Key = NULL;
+  Value = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    Key = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Value = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book npages (book) [-var result] [-key name value]\n");
+    gprint (GP_ERR, "  reports the number of pages (optionally limited to those matching the key)\n");
+    FREE (varName);
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    FREE (varName);
+    return FALSE;
+  }
+
+  Npages = book[0].Npages;
+  if (Key) {
+    /* count only matching key */
+    Npages = 0;
+    for (i = 0; i < book[0].Npages; i++) {
+      value = BookGetWord (book[0].pages[i], Key);
+      if (value == NULL) {
+	if (!strcmp(Value, "NULL")) { 
+	  Npages ++;
+	} else {
+	  continue;
+	}
+      } else {
+	if (!strcmp(value, Value)) Npages ++;
+      }
+    }
+  }
+
+  if (varName) {
+    set_int_variable (varName, Npages);
+  } else {
+    gprint (GP_ERR, "%d pages\n", Npages);
+  }
+  FREE (Key);
+  FREE (Value);
+  FREE (varName);
+  return TRUE;
+}
+
+int book_getbook (int argc, char **argv) {
+
+  int where, N;
+  char *varName;
+  Book *book;
+
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book getbook (where) [-var var]\n");
+    FREE (varName);
+    return FALSE;
+  }
+
+  where = atoi (argv[1]);
+  book = GetBook (where);
+  if (book == NULL) {
+    if (varName) {
+      set_str_variable (varName, "NULL");
+      FREE (varName);
+      return TRUE;
+    } 
+
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    FREE (varName);
+    return FALSE;
+  }
+
+  if (varName) {
+    set_str_variable (varName, book[0].name);
+  } else {
+    gprint (GP_LOG, "%s\n", book[0].name);
+  }
+  FREE (varName);
+  return TRUE;
+}
+
+int book_newpage (int argc, char **argv) {
+
+  Book *book;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: book newpage (book) (page)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    return FALSE;
+  }
+  
+  CreatePage (book, argv[2]);
+  return TRUE;
+}
+
+int book_delpage (int argc, char **argv) {
+
+  int i, N;
+  Page *page;
+  Book *book;
+  char *Key, *Value, *value;
+
+  Key = NULL;
+  Value = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    Key = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Value = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 3) && (argc != 2)) {
+    gprint (GP_ERR, "USAGE: book delpage (book) (page)\n");
+    gprint (GP_ERR, "USAGE: book delpage (book) -key name value\n");
+    FREE (Key);
+    FREE (Value);
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    FREE (Key);
+    FREE (Value);
+    return FALSE;
+  }
+  
+  if (Key) {
+    /* delete by matching key */
+    for (i = 0; i < book[0].Npages; i++) {
+      value = BookGetWord (book[0].pages[i], Key);
+      if (value == NULL) continue;
+      if (!strcmp(value, Value)) {
+	DeletePage (book, book[0].pages[i]);
+	i--; /* if we delete this page, don't advance the counter */
+      }
+    }
+    FREE (Key);
+    FREE (Value);
+    return TRUE;
+  }
+
+  page = FindPage (book, argv[2]);
+  if (page == NULL) {
+    gprint (GP_ERR, "page %s in book %s not found\n", argv[2], argv[1]);
+    FREE (Key);
+    FREE (Value);
+    return FALSE;
+  }
+
+  DeletePage (book, page);
+  FREE (Key);
+  FREE (Value);
+  return TRUE;
+}
+
+int book_listpage (int argc, char **argv) {
+
+  Page *page;
+  Book *book;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: book listpage (book) (page)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    return FALSE;
+  }
+  
+  page = FindPage (book, argv[2]);
+  if (page == NULL) {
+    gprint (GP_ERR, "page %s in book %s not found\n", argv[2], argv[1]);
+    return FALSE;
+  }
+
+  ListWords (page);
+  return TRUE;
+}
+
+int book_getpage (int argc, char **argv) {
+
+  int where, N;
+  char *varName, *keyName, *keyValue;
+  Book *book;
+  Page *page;
+
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  keyValue = keyName = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    keyName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    keyValue = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: book getpage (book) (where) [-var var] [-key key value]\n");
+    FREE (varName);
+    FREE (keyName);
+    FREE (keyValue);
+    return FALSE;
+  }
+
+  where = atoi (argv[2]);
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    if (varName) {
+      set_str_variable (varName, "NULL");
+      FREE (varName);
+      FREE (keyName);
+      FREE (keyValue);
+      return TRUE;
+    } 
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    FREE (varName);
+    FREE (keyName);
+    FREE (keyValue);
+    return FALSE;
+  }
+
+  if (keyName == NULL) {
+    page = GetPage (book, where);
+  } else {
+    page = GetPageRestricted (book, where, keyName, keyValue);
+  }
+
+  if (page == NULL) {
+    if (varName) {
+      set_str_variable (varName, "NULL");
+      FREE (varName);
+      FREE (keyName);
+      FREE (keyValue);
+      return TRUE;
+    } 
+    gprint (GP_ERR, "page %d not found in %s\n", where, argv[1]);
+    FREE (varName);
+    FREE (keyName);
+    FREE (keyValue);
+    return FALSE;
+  }
+
+  if (varName) {
+    set_str_variable (varName, page[0].name);
+  } else {
+    gprint (GP_LOG, "%s\n", page[0].name);
+  }
+  FREE (varName);
+  FREE (keyName);
+  FREE (keyValue);
+  return TRUE;
+}
+
+int book_shuffle (int argc, char **argv) {
+
+  int where, N;
+  char *varName, *keyName, *keyValue;
+  Book *book;
+  Page *page;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: book shuffle (book)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    return FALSE;
+  }
+
+  ShufflePages (book);
+  return TRUE;
+}
+
+int book_setword (int argc, char **argv) {
+
+  Page *page;
+  Book *book;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: book setword (book) (page) (word) (value)\n");
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    return FALSE;
+  }
+  
+  page = FindPage (book, argv[2]);
+  if (page == NULL) {
+    gprint (GP_ERR, "page %s in book %s not found\n", argv[2], argv[1]);
+    return FALSE;
+  }
+
+  BookSetWord (page, argv[3], argv[4]);
+  return TRUE;
+}
+
+int book_getword (int argc, char **argv) {
+
+  int N;
+  Page *page;
+  Book *book;
+  char *value, *varName;
+
+  varName = NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    varName = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: book getword (book) (page) (word)\n");
+    FREE (varName);
+    return FALSE;
+  }
+
+  book = FindBook (argv[1]);
+  if (book == NULL) {
+    if (varName) {
+      set_str_variable (varName, "NULL");
+      FREE (varName);
+      return TRUE;
+    } 
+    gprint (GP_ERR, "book %s not found\n", argv[1]);
+    FREE (varName);
+    return FALSE;
+  }
+  
+  page = FindPage (book, argv[2]);
+  if (page == NULL) {
+    if (varName) {
+      set_str_variable (varName, "NULL");
+      FREE (varName);
+      return TRUE;
+    } 
+    gprint (GP_ERR, "page %s in book %s not found\n", argv[2], argv[1]);
+    FREE (varName);
+    return FALSE;
+  }
+
+  value = BookGetWord (page, argv[3]);
+  if (value == NULL) {
+    if (varName) {
+      set_str_variable (varName, "NULL");
+      FREE (varName);
+      return TRUE;
+    }
+    gprint (GP_ERR, "value %s on page %s in book %s not found\n", argv[3], argv[2], argv[1]);
+    FREE (varName);
+    return FALSE;
+  }
+
+  if (varName) {
+    set_str_variable (varName, value);
+  } else {
+    gprint (GP_LOG, "%s\n", value);
+  }
+    
+  FREE (varName);
+  return TRUE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/box.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/box.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/box.c	(revision 16632)
@@ -0,0 +1,91 @@
+# include "data.h"
+
+int box (int argc, char **argv) {
+  
+  int i, N, kapa;
+  char *name;
+  Graphdata graphmode;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  strcpy (graphmode.ticks, "2222");
+  if ((N = get_argument (argc, argv, "-ticks"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (graphmode.ticks, argv[N]);
+    remove_argument (N, &argc, argv);
+    if (strlen (graphmode.ticks) != 4) { goto usage; }
+    for (i = 0; i < strlen (graphmode.ticks); i++) {
+      if ((graphmode.ticks[i] != '0') && (graphmode.ticks[i] != '1') && (graphmode.ticks[i] != '2')) { goto usage; }
+    }
+  }
+  
+  strcpy (graphmode.labels, "2222");
+  if ((N = get_argument (argc, argv, "-labels"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (graphmode.labels, argv[N]);
+    remove_argument (N, &argc, argv);
+    if (strlen (graphmode.labels) != 4) { goto usage; }
+    for (i = 0; i < strlen (graphmode.labels); i++) {
+      if ((graphmode.labels[i] != '0') && (graphmode.labels[i] != '1') && (graphmode.labels[i] != '2')) { goto usage; }
+    }
+  }
+
+  strcpy (graphmode.axis, "2222");
+  if ((N = get_argument (argc, argv, "-axis"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (graphmode.axis, argv[N]);
+    remove_argument (N, &argc, argv);
+    if (strlen (graphmode.axis) != 4) { goto usage; }
+    for (i = 0; i < strlen (graphmode.axis); i++) {
+      if ((graphmode.axis[i] != '0') && (graphmode.axis[i] != '1') && (graphmode.axis[i] != '2')) { goto usage; }
+    }
+  }
+
+  if (argc != 1) goto usage;
+
+  KapaBox (kapa, &graphmode);
+  return (TRUE);
+      
+ usage:
+  gprint (GP_ERR, "USAGE: box [-ticks NNNN] [-axis NNNN] [-labels NNNN]\n");
+  return (FALSE);
+}
+
+
+/* box has:
+   axis
+   labels
+   ticks
+
+   assign like this:   
+   -axis 0000
+   -labels 0000
+   -ticks 0000
+
+   default:
+   -axis 1111
+   -labels 1100
+   -ticks 1111
+
+   messages to kapa:
+
+   DBOX
+   (xmin) (xmax) (ymin) (ymax)
+   AAAA LLLL TTTT
+
+   A = axis
+   L = label
+   T = ticks
+   
+   0 = off
+   1 = on
+   2 = default / maintain
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/center.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/center.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/center.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "data.h"
+
+int center (int argc, char **argv) {
+  
+  double x, y;
+  int zoom;
+  int kapa, N;
+  char *name;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if ((argc != 3) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: center x y [zoom]\n");
+    return (FALSE);
+  }
+
+  x = atof (argv[1]);
+  y = atof (argv[2]);
+  zoom = 0;
+  if (argc == 4) zoom = atof (argv[3]);
+
+  KiiCenter (kapa, x, y, zoom);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/clear.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/clear.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/clear.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include "data.h"
+
+// default is to clear all plots, but not the sections or the images
+int clear (int argc, char **argv) {
+  
+  int N;
+  int kapa;
+  char *name;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  // clear all sections
+  if ((N = get_argument (argc, argv, "-s")) || 
+      (N = get_argument (argc, argv, "-section"))) {
+      KapaClearSections (kapa);
+      return (TRUE);
+  }
+
+  // clear all sections
+  if ((N = get_argument (argc, argv, "-graph"))) {
+      KapaClearCurrentPlot (kapa);
+      return (TRUE);
+  }
+
+  // clear image
+  if ((N = get_argument (argc, argv, "-image"))) {
+      KapaClearImage (kapa);
+      return (TRUE);
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: clear [-n Xgraph] [-s|-section] [-image] [-graph]\n");
+    gprint (GP_ERR, "       [-s|-section] : clear all sections\n");
+    gprint (GP_ERR, "       [-graph]      : clear current graph\n");
+    gprint (GP_ERR, "       [-image]      : clear current image\n");
+    return (FALSE);
+  }
+
+  KapaClearPlots (kapa);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/clip.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/clip.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/clip.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "data.h"
+
+int clip (int argc, char **argv) {
+
+  int i, Npix, DO_NAN, DO_INF, N;
+  double min, Vmin, max, Vmax, nan_val, inf_val;
+  float *in;
+  Buffer *buf;
+
+  inf_val = nan_val = min = Vmin = max = Vmax = 0;
+
+  DO_NAN = FALSE;
+  if ((N = get_argument (argc, argv, "-nan"))) {
+    remove_argument (N, &argc, argv);
+    nan_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_NAN = TRUE;
+  }
+
+  DO_INF = FALSE;
+  if ((N = get_argument (argc, argv, "-inf"))) {
+    remove_argument (N, &argc, argv);
+    inf_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_INF = TRUE;
+  }
+
+  if ((argc != 6) && (!(DO_INF || DO_NAN))) {
+    gprint (GP_ERR, "USAGE: clip (buffer) [min Vmin max Vmax] [-inf val] [-nan val]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (argc == 6) {
+    min = atof (argv[2]);
+    Vmin = atof (argv[3]);
+    max = atof (argv[4]);
+    Vmax = atof (argv[5]);
+  }
+
+  Npix = buf[0].matrix.Naxis[0]*buf[0].matrix.Naxis[1];
+  in = (float *) buf[0].matrix.buffer;
+
+  if (argc == 6) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (*in < min) 
+	*in = Vmin;
+      if (*in > max)
+	*in = Vmax;
+    }
+  }
+  in = (float *) buf[0].matrix.buffer;
+  if (DO_NAN) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (isnan (*in)) {
+	*in = nan_val;
+      }
+    }
+  }
+  in = (float *) buf[0].matrix.buffer;
+  if (DO_INF) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (!finite (*in)) {
+	*in = inf_val;
+      }
+    }
+  }
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/close.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/close.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/close.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "data.h"
+
+int close_device (int argc, char **argv) {
+
+  int N, kapa;
+  char *name;
+  /* close current graphics device */
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (!GetGraph (NULL, &kapa, name)) return (FALSE);
+
+  close_kapa (name); 
+  FREE (name);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/concat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/concat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/concat.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "data.h"
+
+int concat (int argc, char **argv) {
+
+  int  i, j, Nin;
+  double value;
+  Vector *ivec, *ovec;
+
+  /** check basic syntax **/
+  if (argc != 3) {
+    gprint (GP_ERR, "SYNTAX: concat (vector/value) vector\n");
+    gprint (GP_ERR, "  concatanate (vector/value) to vector\n");
+    return (FALSE);
+  }
+
+  if ((ovec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (SelectScalar (argv[1], &value)) {
+    Nin = ovec[0].Nelements;
+    ovec[0].Nelements++;
+    REALLOCATE (ovec[0].elements, float, ovec[0].Nelements);
+    ovec[0].elements[Nin] = value;
+    return (TRUE);
+  } 
+  
+  if ((ivec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  
+  REALLOCATE (ovec[0].elements, float, ovec[0].Nelements + ivec[0].Nelements);
+  for (j = ovec[0].Nelements, i = 0; i < ivec[0].Nelements; i++, j++) {
+    ovec[0].elements[j] = ivec[0].elements[i];
+  }
+  ovec[0].Nelements += ivec[0].Nelements;
+  
+  return (TRUE);
+    
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/contour.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/contour.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/contour.c	(revision 16632)
@@ -0,0 +1,262 @@
+# include "data.h"
+# define LL { \
+ dx =  d00 / (*v01 - *v00); \
+ dy = -d00 / (*v10 - *v00); \
+ x = i - 0.5; \
+ y = j - dy - 0.5; }
+
+# define UL { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = 1 - tmp; \
+ dx =  d10 / (*v11 - *v10); \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+      
+# define LR { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = 1 - tmp; \
+ dy = d01 / (*v11 - *v01); \
+ x = i + tmp - 0.5; \
+ y = j - 0.5; }
+
+# define UR { \
+ tmp = d10 / (*v11 - *v10); \
+ dx = 1 - tmp; \
+ dy = -d11 / (*v01 - *v11); \
+ x = i + tmp - 0.5; \
+ y = j + 1 - 0.5; }
+      
+# define HZ { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = d01 / (*v11 - *v01) - tmp; \
+ dx = 1; \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+
+# define VT { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = d10 / (*v11 - *v10) - tmp; \
+ x = i + tmp - 0.5; \
+ dy = 1; \
+ y = j - 0.5; }
+
+Vector *xv, *yv;
+int N, NVEC;
+
+void DUMP (float x, float y, float dx, float dy) {
+  
+  xv[0].elements[N]   = x;
+  xv[0].elements[N+1] = x+dx;
+  
+  yv[0].elements[N]   = y;
+  yv[0].elements[N+1] = y+dy;
+  
+  N+=2;
+
+  if (N >= NVEC - 2) {
+    NVEC += 100;
+    REALLOCATE (xv[0].elements, float, NVEC);
+    REALLOCATE (yv[0].elements, float, NVEC);
+  }
+}
+
+int contour (int argc, char **argv) {
+
+  int i, j, Nx, Ny;
+  float level, d00, d01, d10, d11, tmp;
+  float x, y, dx, dy;
+  float *v00, *v01, *v10, *v11;
+  float *matrix;
+  Buffer *buf;
+  
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: contour <buffer> X Y level\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((xv = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yv = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  level = atof (argv[4]);
+  matrix = (float *)(buf[0].matrix.buffer);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  v00 = matrix;
+  v01 = matrix + 1;
+  v10 = matrix + Nx;
+  v11 = matrix + Nx + 1;
+  d01 = (level - *v00);
+  d11 = (level - *v10);
+
+  N = 0;
+  NVEC = 100;
+  REALLOCATE (xv[0].elements, float, NVEC);
+  REALLOCATE (yv[0].elements, float, NVEC);
+
+  for (j = 1; j < Ny; j++) {
+    if (!(j%10)) gprint (GP_ERR, ".");
+    for (i = 1; i < Nx; i++, v00++, v01++, v10++, v11++) {
+
+      d00 = d01;
+      d10 = d11;
+      d01 = (level - *v01);
+      d11 = (level - *v11);
+
+      if (((d00 > 0) && (d01 > 0) && (d10 > 0) && (d11 > 0)) ||
+	  ((d00 < 0) && (d01 < 0) && (d10 < 0) && (d11 < 0)))
+	continue;
+
+      if ((d00 > 0) && (d10 <= 0)) { 
+	if ((d01 <= 0) && (d11 <= 0)) { /* \  */
+	  LL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* -  */
+	  HZ;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) { /* /  */
+	  UL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* \\  */
+	  LL;
+	  DUMP (x,y,dx,dy);
+	  UR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+
+      if ((d00 <= 0) && (d10 > 0)) {
+	if ((d01 > 0) && (d11 > 0)) { /* \  */
+	  LL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* -  */
+	  HZ;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) { /* /  */
+	  UL;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* //  */
+	  UL;
+	  DUMP (x,y,dx,dy);
+	  LR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+      
+
+      if ((d00 <= 0) && (d10 <= 0)) { 
+	if ((d01 > 0) && (d11 <= 0)) {
+	  LR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) {
+	  UR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) {
+	  VT;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+
+      if ((d00 > 0) && (d10 > 0)) { 
+	if ((d01 <= 0) && (d11 > 0)) {
+	  LR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) {
+	  UR;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) {
+	  VT;
+	  DUMP (x,y,dx,dy);
+	  continue;
+	}
+      }
+
+    }
+    /* skip left-hand edge */
+    v00++; v01++; v10++; v11++;
+    d01 = (level - *v00);
+    d11 = (level - *v10);
+  }
+
+  /****** bottom line *******/
+  v00 = matrix;  
+  v01 = matrix + 1;  
+  y = 0;
+  dx = 0;
+  dy = -0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+
+  /********** top line *******/
+  v00 = matrix + Nx*(Ny - 1);  
+  v01 = v00 + 1;
+  y = Ny - 1;
+  dx = 0;
+  dy = 0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+
+  /******** left line *********/
+  v00 = matrix; 
+  v01 = matrix + Nx;
+  x = 0;
+  dx = -0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+
+  /******** right line *********/
+  v00 = matrix + Nx - 1; 
+  v01 = v00 + Nx;
+  x = Nx - 1;
+  dx = 0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP (x,y,dx,dy);
+    }
+  }
+  
+/* free anything? */
+
+  xv[0].Nelements = N;
+  yv[0].Nelements = N;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/create.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/create.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/create.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "data.h"
+
+int create (int argc, char **argv) {
+  
+  int i;
+  float start, end, delta;
+  Vector *vec;
+  
+  if ((argc != 5) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: create vector start end [delta]\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[2]);
+  end   = atof (argv[3]);
+  delta = 1;
+  if (argc == 5) delta = atof (argv[4]);
+  if ((start == end) || (delta == 0)) {
+    gprint (GP_ERR, "error in value: %f to %f, %f\n", start, end, delta);
+    return (FALSE);
+  }
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+
+  vec[0].Nelements = (end - start) / delta;
+  REALLOCATE (vec[0].elements, float, vec[0].Nelements);
+
+  for (i = 0; i < vec[0].Nelements; i++) {
+    vec[0].elements[i] = start + i*delta;
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cumulative.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cumulative.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cumulative.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "data.h"
+
+int cumulative (int argc, char **argv) {
+  
+  int i;
+  float *Vi, *Vo;
+  Vector *ivec, *ovec;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: cumulative invec outvec\n");
+    return (FALSE);
+  }
+
+  if ((ivec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  ovec[0].Nelements = ivec[0].Nelements;
+    
+  REALLOCATE (ovec[0].elements, float, ovec[0].Nelements);
+  bzero (ovec[0].elements, sizeof(float)*ovec[0].Nelements);
+
+  Vi = ivec[0].elements;
+  Vo = ovec[0].elements;
+  *Vo = *Vi;
+  for (i = 1; i < ivec[0].Nelements; i++, Vi++, Vo++) {
+    *Vo = Vo[-1] + *Vi;
+  }      
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cursor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cursor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cursor.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "data.h"
+
+int cursor (int argc, char **argv) {
+
+  char string[20], key[20], *name;
+  int i, N, kapa;
+  double X, Y, R, D, Z;
+  void *oldsignal;
+
+  // XXX need to be able to specify graph vs image coords
+  // currently, if only one exists, that frame will be used
+  // if both exist, defaults to ??
+  // if ((N = get_argument (argc, argv, "-g"))) {
+  // if ((N = get_argument (argc, argv, "-i"))) {
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraphData (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  N = 0;
+  if (argc == 2) N = atof (argv[1]);
+
+  if ((argc != 1) && (argc != 2)) {
+    gprint (GP_ERR, "USAGE: cursor [Npts] [-n window] [-g | -i]\n");
+    return (FALSE);
+  }
+  
+  KiiCursorOn (kapa);
+  
+  oldsignal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+
+  for (i = 0; ((i < N) || (N == 0)) && !interrupt; i++) {
+
+    KiiCursorRead (kapa, &X, &Y, &Z, &R, &D, key);
+
+    sprintf (string, "X%s", key);
+    set_variable (string, X);
+    sprintf (string, "Y%s", key);
+    set_variable (string, Y);
+    sprintf (string, "Z%s", key);
+    set_variable (string, Z);
+    sprintf (string, "R%s", key);
+    set_variable (string, R);
+    sprintf (string, "D%s", key);
+    set_variable (string, D);
+
+    set_str_variable ("KEY", key);
+    
+    gprint (GP_LOG, "%s %f %f %f %f %f\n", key, X, Y, Z, R, D);
+
+    if (!strcasecmp (key, "Q")) break;
+  }
+
+  signal (SIGINT, oldsignal);
+  KiiCursorOff (kapa);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cut.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cut.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/cut.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "data.h"
+
+enum {SUM, MEAN, MEDIAN};
+
+int cut (int argc, char **argv) {
+  
+  int i, j, N, Nx, Ny, Mode;
+  float *Vin, *Vbuf, value;
+  int sx, sy, nx, ny;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  Mode = SUM;
+  if ((N = get_argument (argc, argv, "-median"))) {
+    remove_argument (N, &argc, argv);
+    Mode = MEDIAN;
+  }
+  if ((N = get_argument (argc, argv, "-mean"))) {
+    remove_argument (N, &argc, argv);
+    Mode = MEAN;
+  }
+
+  if (argc != 9) {
+    gprint (GP_ERR, "USAGE: cut <buffer> <X vector> <Y vector> <X|Y> sx sy nx ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+ 
+  sx = atof (argv[5]);
+  sy = atof (argv[6]);
+  nx = atof (argv[7]);
+  ny = atof (argv[8]);
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  if ((sx < 0) || (sy < 0) || (sx+nx > Nx) || (sy+ny > Ny)) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+
+  if ((xvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  switch (argv[4][0]) {
+  case 'x':
+  case 'X':
+    /* create output vectors */
+    xvec[0].Nelements = yvec[0].Nelements = nx;
+    REALLOCATE (xvec[0].elements, float, MAX (nx, 1));
+    REALLOCATE (yvec[0].elements, float, MAX (nx, 1));
+    bzero (yvec[0].elements, nx*sizeof(float));
+    for (i = 0; i < nx; i++) {
+      xvec[0].elements[i] = i + sx; 
+    }
+    ALLOCATE (Vbuf, float, MAX (ny, 1));
+
+    for (i = 0; i < nx; i++) {
+      /* accumulate values */
+      Vin = (float *)(buf[0].matrix.buffer) + sy*Nx + sx + i; 
+      for (j = 0; j < ny; j++, Vin += Nx) {
+	Vbuf[j] = *Vin;
+      }
+      /* apply stat of choice */
+      if (Mode == MEDIAN) {
+	fsort (Vbuf, ny);
+	value = Vbuf[(int)(0.5*ny)];
+      } else {
+	value = 0;
+	for (j = 0; j < ny; j++) {
+	  value += Vbuf[j];
+	}
+	if (Mode == MEAN) { value /= ny; }
+      }
+      yvec[0].elements[i] = value;
+    }
+    free (Vbuf);
+    break;
+    
+  case 'y':
+  case 'Y':
+    xvec[0].Nelements = yvec[0].Nelements = ny;
+    REALLOCATE (xvec[0].elements, float, ny);
+    REALLOCATE (yvec[0].elements, float, ny);
+    bzero (yvec[0].elements, ny*sizeof(float));
+    for (i = 0; i < ny; i++) {
+      xvec[0].elements[i] = i + sy; 
+    }
+    ALLOCATE (Vbuf, float, MAX (nx, 1));
+
+    for (i = 0; i < ny; i++) {
+      /* accumulate values */
+      Vin = (float *)(buf[0].matrix.buffer) + (sy + i)*Nx + sx; 
+      for (j = 0; j < nx; j++, Vin ++) {
+	Vbuf[j] = *Vin;
+      }
+      /* apply stat of choice */
+      if (Mode == MEDIAN) {
+	fsort (Vbuf, nx);
+	value = Vbuf[(int)(0.5*nx)];
+      } else {
+	value = 0;
+	for (j = 0; j < nx; j++) {
+	  value += Vbuf[j];
+	}
+	if (Mode == MEAN) { value /= nx; }
+      }
+      yvec[0].elements[i] = value;
+    }
+    free (Vbuf);
+    break;
+
+  default:
+    gprint (GP_ERR, "<dir> can be X or Y\n");
+    return (FALSE);
+    break;
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dbconnect.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dbconnect.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dbconnect.c	(revision 16632)
@@ -0,0 +1,117 @@
+# include "data.h"
+# if (HAVE_MYSQL_H)
+# include "mysql.h"
+
+MYSQL mysql;
+MYSQL *connection = NULL;
+
+int dbconnect (int argc, char **argv) {
+  
+  char query[256];
+  char password[1024];
+  MYSQL_RES *result;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: dbconnect (hostname) (username) (database)\n");
+    return FALSE;
+  }
+
+  fprintf (stdout, "Enter password: ");
+  scan_line (stdin, password);
+
+# if (0)
+  int i;
+  char c;
+
+  initscr();
+  noecho();
+  i = 0;
+  while (((c = getch()) != EOF) && (c != '\n')) {
+    password[i] = c;
+    i++;
+  }
+  password[i] = 0;
+# endif
+
+  mysql_init (&mysql);
+  connection = mysql_real_connect (&mysql, argv[1], argv[2], password, argv[3], 0, 0, 0);
+
+  if (connection == NULL) {
+    gprint (GP_ERR, "failed to connect to database\n");
+    gprint (GP_ERR, "%s\n", mysql_error (&mysql));
+    return (FALSE);
+  }
+    
+  sprintf (query, "set @@interactive_timeout = 30000");
+  if (mysql_query (connection, query)) {
+    gprint (GP_ERR, "failed to set interactive timout\n");
+    gprint (GP_ERR, "%s\n", mysql_error (connection));
+    free (query);
+    return (FALSE);
+  }
+  result = mysql_store_result (connection);
+  mysql_free_result (result);
+    
+  sprintf (query, "set @@wait_timeout = 30000");
+  if (mysql_query (connection, query)) {
+    gprint (GP_ERR, "failed to set wait timout\n");
+    gprint (GP_ERR, "%s\n", mysql_error (connection));
+    free (query);
+    return (FALSE);
+  }
+  result = mysql_store_result (connection);
+  mysql_free_result (result);
+    
+# if (0)
+  int Nrows;
+  MYSQL_ROW row;
+
+  sprintf (query, "select @@interactive_timeout");
+  if (mysql_query (connection, query)) {
+    gprint (GP_ERR, "failed to get timout\n");
+    gprint (GP_ERR, "%s\n", mysql_error (connection));
+    free (query);
+    return (FALSE);
+  }
+  result = mysql_store_result (connection);
+  Nrows = mysql_num_rows(result);
+  row = mysql_fetch_row(result);
+  fprintf (stderr, "interactive timeout: %s\n", row[0]);
+  mysql_free_result (result);
+
+  sprintf (query, "select @@wait_timeout");
+  if (mysql_query (connection, query)) {
+    gprint (GP_ERR, "failed to get timout\n");
+    gprint (GP_ERR, "%s\n", mysql_error (connection));
+    free (query);
+    return (FALSE);
+  }
+  result = mysql_store_result (connection);
+  Nrows = mysql_num_rows(result);
+  row = mysql_fetch_row(result);
+  fprintf (stderr, "wait timeout: %s\n", row[0]);
+  mysql_free_result (result);
+# endif
+    
+  return (TRUE);
+}
+
+// XXX do I need to close the connection before opening a new one? 
+
+void *db_getConnection () {
+  return connection;
+}
+
+# else 
+
+int dbconnect (int argc, char **argv) {
+
+  gprint (GP_ERR, "mysql library is not available\n");
+  return FALSE;
+}
+
+void *db_getConnection () {
+  return NULL;
+}
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dbselect.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dbselect.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dbselect.c	(revision 16632)
@@ -0,0 +1,100 @@
+# include "data.h"
+# if (HAVE_MYSQL_H) 
+# include "mysql.h"
+
+int dbselect (int argc, char **argv) {
+  
+  int i, j, Nbytes, Ncols, Nrows;
+  char *query;
+  Vector **vec;
+
+  MYSQL_RES *result;
+  MYSQL_ROW row;
+  MYSQL_FIELD *fields;
+  MYSQL *connection = NULL;
+
+  if (argc < 4) {
+    gprint (GP_ERR, "USAGE: dbselect (fields) from (table) [where]\n");
+    return FALSE;
+  }
+
+  connection = db_getConnection ();
+  if (connection == NULL) {
+    gprint (GP_ERR, "database not defined; use dbconnect\n");
+    return (FALSE);
+  }
+
+  // generate the query line (concat the argv[i] entries)
+  Nbytes = 0;
+  for (i = 1; i < argc; i++) {
+    Nbytes += strlen(argv[i]) + 1;
+  }
+  Nbytes += 10;
+
+  ALLOCATE (query, char, Nbytes);
+  bzero (query, Nbytes);
+  strcat (query, "select ");
+  for (i = 1; i < argc; i++) {
+    strcat (query, argv[i]);
+    strcat (query, " ");
+  }
+  // strcat (query, ";");
+  // fprintf (stderr, "query: %s\n", query);
+
+  if (mysql_query (connection, query)) {
+    gprint (GP_ERR, "problem with query\n");
+    gprint (GP_ERR, "%s\n", mysql_error (connection));
+    free (query);
+    return (FALSE);
+  }
+    
+  result = mysql_store_result (connection);
+
+  Nrows = mysql_num_rows(result);
+  Ncols = mysql_num_fields(result);
+  fields = mysql_fetch_fields (result);
+
+  // fprintf (stderr, "Nrows: %d\n", Nrows);
+  // fprintf (stderr, "Ncols: %d\n", Ncols);
+
+  ALLOCATE (vec, Vector *, Ncols);
+  for (i = 0; i < Ncols; i++) {
+    if ((vec[i] = SelectVector (fields[i].name, ANYVECTOR, TRUE)) == NULL) {
+      gprint (GP_ERR, "trouble creating vector named %s\n", fields[i].name);
+      free (query);
+      free (vec);
+      return (FALSE);
+    }
+    REALLOCATE (vec[i][0].elements, float, Nrows);
+    vec[i][0].Nelements = Nrows;
+  }
+
+  for (j = 0; j < Nrows; j++) {
+    row = mysql_fetch_row(result);
+    if (row == NULL) {
+      gprint (GP_ERR, "inconsistent row count: expected %d, got %d\n", Nrows, j);
+      free (query);
+      free (vec);
+      mysql_free_result (result);
+      return (FALSE);
+    }
+    for (i = 0; i < Ncols; i++) {
+      vec[i][0].elements[j] = atof (row[i]);
+    }
+  }
+
+  free (query);
+  free (vec);
+  mysql_free_result (result);
+  return (TRUE);
+}
+
+# else 
+
+int dbselect (int argc, char **argv) {
+
+  gprint (GP_ERR, "mysql library is not available\n");
+  return FALSE;
+}
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/delete.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "data.h"
+
+int delete (int argc, char **argv) {
+  
+  int i, N, Quiet;
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: delete <obiect> [<object> ..]\n");
+    return (FALSE);
+  }
+
+  for (i = 1; i < argc; i++) {
+    if (DeleteNamedBuffer (argv[i])) continue; 
+    if (DeleteNamedVector (argv[i])) continue;
+    if (DeleteNamedScalar (argv[i])) continue; 
+    if (!Quiet) gprint (GP_ERR, "can't find object %s\n", argv[i]);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/device.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/device.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/device.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "data.h"
+
+int device (int argc, char **argv) {
+
+  int N, kapa;
+  char *name;;
+  /* set / get current graphics device */
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (name == NULL) {
+    name = GetKapaName ();
+    if (name == NULL) {
+      gprint (GP_ERR, "no device defined\n");
+      return (FALSE);
+    }
+  } else {
+    if (!GetGraph (NULL, &kapa, name)) return (FALSE);
+  }
+  gprint (GP_ERR, "kapa %s\n", name); 
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dimendown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dimendown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dimendown.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "data.h"
+
+enum {VALUE, XCOORD, YCOORD};
+
+int dimendown (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix, N, mode;
+  float *in, *out;
+  Vector *vec;
+  Buffer *buf;
+
+  mode = VALUE;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    mode = XCOORD;
+  }
+  if ((N = get_argument (argc, argv, "-y"))) {
+    remove_argument (N, &argc, argv);
+    mode = YCOORD;
+  }
+
+  if (argc != 3) goto usage;
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+  Npix = Nx * Ny;
+
+  vec[0].Nelements = Npix;
+  REALLOCATE (vec[0].elements, float, Npix);
+
+  in = (float *) buf[0].matrix.buffer;
+  out = vec[0].elements;
+
+  switch (mode) {
+    case VALUE:
+      for (i = 0; i < Npix; i++, in++, out++) {
+	*out = *in;
+      }
+      break;
+
+    case XCOORD:
+      for (i = 0; i < Npix; i++, out++) {
+	*out = i % Nx;
+      }
+      break;
+
+    case YCOORD:
+      for (i = 0; i < Npix; i++, out++) {
+	*out = i / Nx;
+      }
+      break;
+  }
+      
+  return (TRUE);
+
+ usage:
+    gprint (GP_ERR, "USAGE: dimendown <buffer> <vector>\n");
+    gprint (GP_ERR, "  -x : fill vector with buffer x-coords\n");
+    gprint (GP_ERR, "  -y : fill vector with buffer y-coords\n");
+    return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dimenup.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dimenup.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dimenup.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "data.h"
+
+int dimenup (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix;
+  float *in, *out;
+  Vector *vec;
+  Buffer *buf;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: dimenup <vector> <buffer> Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((buf = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Npix = vec[0].Nelements;
+  Nx = atof (argv[3]);
+  Ny = atof (argv[4]);
+  if (Npix != Nx * Ny) {
+    gprint (GP_ERR, "dimensions don't match\n");
+    return (FALSE);
+  }
+
+  gfits_free_matrix (&buf[0].matrix);
+  gfits_free_header (&buf[0].header);
+  CreateBuffer (buf, Nx, Ny, -32, 0.0, 1.0);
+
+  out = (float *) buf[0].matrix.buffer;
+  in = vec[0].elements;
+
+  for (i = 0; i < Npix; i++, in++, out++) {
+    *out = *in;
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/dot.c	(revision 16632)
@@ -0,0 +1,27 @@
+# include "data.h"
+
+int dot (int argc, char **argv) {
+  
+  int kapa;
+  Graphdata graphmode;
+  float x, y;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: dot <x> <y>\n");
+    return (FALSE);
+  }
+  x = atof(argv[1]);
+  y = atof(argv[2]);
+
+  /* set point style and errorbar mode (these are NOT sticky) */
+  graphmode.style = 2;
+  graphmode.etype = 0;
+
+  if (!KapaPrepPlot (kapa, 1, &graphmode)) return (FALSE);
+  KapaPlotVector (kapa, 1, &x, "x");
+  KapaPlotVector (kapa, 1, &y, "y");
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/erase.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/erase.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/erase.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "data.h"
+
+int erase (int argc, char **argv) {
+  
+  int i, N;
+  int kapa;
+  char *name;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: erase (overlay) [overlay, overlay, ..] \n");
+    gprint (GP_ERR, " (overlay) may be: red (0), green (1), blue (2), yellow (3) or all\n");
+    return (FALSE);
+  }
+
+  for (i = 1; i < argc; i++) {
+    if (!(strcasecmp (argv[i], "all"))) {
+      KiiEraseOverlay (kapa, "red");
+      KiiEraseOverlay (kapa, "green");
+      KiiEraseOverlay (kapa, "blue");
+      KiiEraseOverlay (kapa, "yellow");
+      continue;
+    }
+    if (!KiiSelectOverlay (argv[i], &N)) {
+      gprint (GP_ERR, "%s is not a valid overlay\n", argv[i]);
+      return (FALSE);
+    }
+    KiiEraseOverlay (kapa, argv[i]);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/extract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/extract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/extract.c	(revision 16632)
@@ -0,0 +1,92 @@
+# include "data.h"
+
+int extract (int argc, char **argv) {
+  
+  int i, j;
+  float *Vin, *Vout;
+  int sx, sy, nx, ny, NX, NY;
+  int Sx, Sy, Nx, Ny;
+  Buffer *in, *out;
+
+  if (argc != 11) {
+    gprint (GP_ERR, "USAGE: extract <from> <to> sx sy nx ny Sx Sy Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((in = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  NX = in[0].matrix.Naxis[0];
+  NY = in[0].matrix.Naxis[1];
+
+  sx = atof (argv[3]);
+  sy = atof (argv[4]);
+  nx = atof (argv[5]);
+  ny = atof (argv[6]);
+
+  Sx = atof (argv[7]);
+  Sy = atof (argv[8]);
+  Nx = atof (argv[9]);
+  Ny = atof (argv[10]);
+
+  if ((Sy + ny > Ny) || (Sx + nx > Nx)) {
+    gprint (GP_ERR, "mismatch between source and dest regions\n");
+    gprint (GP_ERR, "%d + %d > %d or %d + %d > %d\n", Sy, ny, Ny, Sx, nx, Nx);
+    return (FALSE);
+  }
+
+  /* region is not on first image */
+  if ((sx + nx < 0) || (sy + ny < 0) || 
+      (sx > in[0].matrix.Naxis[0]) || 
+      (sy > in[0].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region outside of source image\n");
+    return (FALSE);
+  }
+
+  if ((Sx + nx > Nx) || (Sy + ny > Ny)) {
+    gprint (GP_ERR, "source region larger than dest region\n");
+    return (FALSE);
+  }
+  if ((Sx < 0) || (Sy < 0)) {
+    gprint (GP_ERR, "dest region out of range\n");
+    return (FALSE);
+  }
+
+  if ((out = SelectBuffer (argv[2], OLDBUFFER, FALSE)) == NULL) {
+    if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+    gfits_free_matrix (&out[0].matrix);
+    gfits_free_header (&out[0].header);
+
+    out[0].bitpix = in[0].bitpix;
+    out[0].unsign = in[0].unsign;
+    out[0].bscale = in[0].bscale;
+    out[0].bzero  = in[0].bzero;
+    gfits_copy_header (&in[0].header, &out[0].header);
+    gfits_modify (&out[0].header, "NAXIS1", "%d", 1, Nx);
+    gfits_modify (&out[0].header, "NAXIS2", "%d", 1, Ny);
+    out[0].header.Naxis[0] = Nx;
+    out[0].header.Naxis[1] = Ny;
+    gfits_create_matrix (&out[0].header, &out[0].matrix);
+  } else {
+    if ((out[0].header.Naxis[1] != Ny) || (out[0].header.Naxis[0] != Nx)) {
+      gprint (GP_ERR, "matrix sizes mis-matched\n");
+      gprint (GP_ERR, "%d x %d  vs  %d x %d\n", Nx, Ny, 
+	       out[0].header.Naxis[0], out[0].header.Naxis[1]);
+      return (FALSE);
+    }
+  }
+
+  for (j = 0; j < ny; j++) {
+    if (j + sy < 0) continue;
+    if (j + sy >= NY) continue;
+    Vin = (float *)(in[0].matrix.buffer) + (j + sy)*in[0].matrix.Naxis[0] + sx;  
+    Vout = (float *)(out[0].matrix.buffer) + (j + Sy)*out[0].matrix.Naxis[0] + Sx;   
+    for (i = 0; i < nx; i++, Vin++, Vout++) {
+      if (i + sx < 0) continue;
+      if (i + sx >= NX) continue;
+      *Vout = *Vin;
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft1d.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft1d.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft1d.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "data.h"
+
+int fft1d (int argc, char **argv) {
+  
+  int N, Npix, Nbit, ZeroImaginary, forward;
+  Vector *Ire, *Iim, *Ore, *Oim;
+
+  forward = TRUE;
+  if ((N = get_argument (argc, argv, "-inverse"))) {
+    remove_argument (N, &argc, argv);
+    forward = FALSE;
+  }
+
+  if ((argc != 6) || (strcmp (argv[3], "to"))) {
+    gprint (GP_ERR, "USAGE: fft1d (real) (imag) to (real) (imag)\n");
+    return (FALSE);
+  }
+
+  Iim = NULL;
+  ZeroImaginary = TRUE;
+  if (strcmp (argv[2], "0")) {
+    ZeroImaginary = FALSE;
+    if ((Iim = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  }    
+  if ((Ire = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  
+  // check the input data (match lengths? binary length?)
+  Npix = Ire[0].Nelements;
+  if (!ZeroImaginary && (Npix != Iim[0].Nelements)) {
+    gprint (GP_ERR, "vector size mismatch\n");
+    return (FALSE);
+  }
+  if (!IsBinary (Npix, &Nbit)) {
+    gprint (GP_ERR, "Npix is not a binary number!\n");
+    return (FALSE);
+  }
+
+  // select or create the output vectors
+  if ((Ore = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((Oim = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  // allocate sufficient output space
+  Ore[0].Nelements = Npix;
+  Oim[0].Nelements = Npix;
+  REALLOCATE (Ore[0].elements, float, Npix);
+  REALLOCATE (Oim[0].elements, float, Npix);
+ 
+  // copy data to output vectors (fft is done in place)
+  memcpy (Ore[0].elements, Ire[0].elements, Npix*sizeof(float));
+
+  // copy imaginary vector or create a zero vector
+  if (ZeroImaginary) {
+    memset (Oim[0].elements, 0, Npix*sizeof(float));
+  } else {
+    memcpy (Oim[0].elements, Iim[0].elements, Npix*sizeof(float));
+  }    
+
+  fft1D (Ore[0].elements, Oim[0].elements, Npix, Nbit, forward); 
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft1d.old.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft1d.old.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft1d.old.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "data.h"
+
+int fft1dold (int argc, char **argv) {
+  
+  int i, Npix, ZeroImaginary;
+  float *t1, *t2, *temp;
+  Vector *Ire, *Iim, *Ore, *Oim;
+
+  if ((argc != 6) || (strcmp (argv[3], "to"))) {
+    gprint (GP_ERR, "USAGE: fft1d (real) (imag) to (real) (imag)\n");
+    return (FALSE);
+  }
+
+  Iim = NULL;
+  ZeroImaginary = TRUE;
+  if (strcmp (argv[2], "0")) {
+    ZeroImaginary = FALSE;
+    if ((Iim = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  }    
+  if ((Ire = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((Ore = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((Oim = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Npix = Ire[0].Nelements;
+  if (!ZeroImaginary && (Npix != Iim[0].Nelements)) {
+    gprint (GP_ERR, "vector mismatch in size\n");
+    return (FALSE);
+  }
+
+  if (!IsBinaryOld (Npix)) {
+    gprint (GP_ERR, "Npix is not a binary number!\n");
+    return (FALSE);
+  }
+  
+  ALLOCATE (temp, float, 2*Npix);
+  if (ZeroImaginary) {
+    t1 = Ire[0].elements;
+    for (i = 0; i < Npix; i++, t1++) {
+      temp[2*i  ] = *t1;
+      temp[2*i+1] = 0;
+    }
+  } else {
+    t1 = Ire[0].elements;
+    t2 = Iim[0].elements;
+    for (i = 0; i < Npix; i++, t1++, t2++) {
+      temp[2*i  ] = *t1;
+      temp[2*i+1] = *t2;
+    }
+  }    
+    
+  fftold (temp, Npix, 1); 
+
+  Ore[0].Nelements = Npix;
+  Oim[0].Nelements = Npix;
+  REALLOCATE (Ore[0].elements, float, Npix);
+  REALLOCATE (Oim[0].elements, float, Npix);
+ 
+  t1 = Ore[0].elements;
+  t2 = Oim[0].elements;
+  for (i = 0; i < Npix; i++, t1++, t2++) {
+    *t1 = temp[2*i  ] / Npix;
+    *t2 = temp[2*i+1] / Npix;
+  }    
+  
+  free (temp);
+  
+  return (TRUE);
+}
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft2d.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft2d.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft2d.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "data.h"
+
+int fft2d (int argc, char **argv) {
+  
+  int ZeroImaginary, forward;
+  int N, Nx, Ny;
+  Buffer *Ire, *Iim, *Ore, *Oim;;
+
+  forward = TRUE;
+  if ((N = get_argument (argc, argv, "-inverse"))) {
+    remove_argument (N, &argc, argv);
+    forward = FALSE;
+  }
+
+  if ((argc != 6) || (strcmp (argv[3], "to"))) {
+    gprint (GP_ERR, "USAGE: fft2d (real) (imag) to (real) (imag)\n");
+    return (FALSE);
+  }
+
+  /* select input / output buffers */
+  Iim = NULL;
+  ZeroImaginary = TRUE; /* Input(imaginary) may be 0, in which case we create a 0 filled image */
+  if (!strcmp (argv[2], "0")) { 
+  } else {
+    ZeroImaginary = FALSE;
+    if ((Iim = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  }    
+  if ((Ire = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = Ire[0].header.Naxis[0];
+  Ny = Ire[0].header.Naxis[1];
+
+  // check input image dimensions (match lengths? binary lengths?)
+  if (!ZeroImaginary) {
+    if ((Nx != Iim[0].header.Naxis[0]) || 
+	(Ny != Iim[0].header.Naxis[1])) {
+      gprint (GP_ERR, "image size mismatch\n");
+      return (FALSE);
+    }
+  }
+  if (!IsBinary (Nx, NULL)) {
+    gprint (GP_ERR, "Nx is not a binary number!\n");
+    return (FALSE);
+  }
+  if (!IsBinary (Ny, NULL)) {
+    gprint (GP_ERR, "Ny is not a binary number!\n");
+    return (FALSE);
+  }
+
+  if ((Ore = SelectBuffer (argv[4], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Oim = SelectBuffer (argv[5], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  /* free up output space */
+  gfits_free_matrix (&Ore[0].matrix);
+  gfits_free_header (&Ore[0].header);
+  gfits_free_matrix (&Oim[0].matrix);
+  gfits_free_header (&Oim[0].header);
+  
+  /* fix up output headers (real) & allocate data buffer */
+  CreateBuffer (Ore, Nx, Ny, -32, 0.0, 1.0);
+  CreateBuffer (Oim, Nx, Ny, -32, 0.0, 1.0);
+
+  gfits_copy_header (&Ire[0].header, &Ore[0].header);
+  gfits_copy_header (&Ire[0].header, &Oim[0].header);
+
+  // copy data to output buffers (fft is done in place)
+  memcpy (Ore[0].matrix.buffer, Ire[0].matrix.buffer, Nx*Ny*sizeof(float));
+
+  if (ZeroImaginary) {
+    memset (Oim[0].matrix.buffer, 0, Nx*Ny*sizeof(float));
+  } else {
+    memcpy (Oim[0].matrix.buffer, Iim[0].matrix.buffer, Nx*Ny*sizeof(float));
+  }
+
+  /* run the fft */
+  fftND ((float *)Ore[0].matrix.buffer, (float *)Oim[0].matrix.buffer, 2, Ire[0].header.Naxis, forward);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft2d.old.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft2d.old.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fft2d.old.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "data.h"
+
+int fft2dold (int argc, char **argv) {
+  
+  int i, N, Nx, Ny, Naxis[2];
+  int Npix, ZeroImaginary, isign;
+  float *t1, *t2, *out, *temp;
+  Buffer *Ire, *Iim, *Ore, *Oim;;
+
+  isign = 1;
+  if ((N = get_argument (argc, argv, "-inverse"))) {
+    remove_argument (N, &argc, argv);
+    isign = -1;
+  }
+
+  if ((argc != 6) || (strcmp (argv[3], "to"))) {
+    gprint (GP_ERR, "USAGE: fft2d (real) (imag) to (real) (imag)\n");
+    return (FALSE);
+  }
+
+  /* select input / output buffers */
+  Iim = NULL;
+  ZeroImaginary = TRUE; /* Input(imaginary) may be 0, in which case we create a 0 filled image */
+  if (!strcmp (argv[2], "0")) { 
+  } else {
+    ZeroImaginary = FALSE;
+    if ((Iim = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  }    
+  if ((Ire = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Ore = SelectBuffer (argv[4], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Oim = SelectBuffer (argv[5], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  /* free up output space */
+  gfits_free_matrix (&Ore[0].matrix);
+  gfits_free_header (&Ore[0].header);
+  gfits_free_matrix (&Oim[0].matrix);
+  gfits_free_header (&Oim[0].header);
+
+  /* get image dimensions, check value */
+  Npix = Ire[0].header.Naxis[0]*Ire[0].header.Naxis[1];
+  Nx = Ire[0].header.Naxis[0];
+  Ny = Ire[0].header.Naxis[1];
+  Naxis[0] = Ny; Naxis[1] = Nx;
+  if (!IsBinaryOld (Npix)) {
+    gprint (GP_ERR, "dimensions are not binary!\n");
+    return (FALSE);
+  }
+  
+  /* create working space */
+  t1 = (float *) Ire[0].matrix.buffer;
+  ALLOCATE (temp, float, 2*Npix);
+  out = temp;
+
+  /* copy input to working space */
+  if (ZeroImaginary) {
+    for (i = 0; i < Npix; i++, t1++) {
+      *out = *t1;
+      out++;
+      *out = 0;
+      out++;
+    }
+  } else {
+    t2 = (float *) Iim[0].matrix.buffer;
+    for (i = 0; i < Npix; i++, t1++, t2++) {
+      *out = *t1;
+      out++;
+      *out = *t2;
+      out++;
+    }
+  } 
+    
+  /* run the fft */
+  fftNold (temp, Naxis, 2, isign);
+
+  /* fix up output headers (real) */
+  gfits_copy_header (&Ire[0].header, &Ore[0].header);
+  gfits_modify (&Ore[0].header, "NAXIS1", "%d", 1, Nx);
+  gfits_modify (&Ore[0].header, "NAXIS2", "%d", 1, Ny);
+  Ore[0].header.Naxis[0] = Nx;
+  Ore[0].header.Naxis[1] = Ny;
+  Ore[0].bitpix = Ire[0].bitpix;
+  Ore[0].unsign = Ire[0].unsign;
+  Ore[0].bscale = Ire[0].bscale;
+  Ore[0].bzero  = Ire[0].bzero;
+  gfits_create_matrix (&Ore[0].header, &Ore[0].matrix);
+
+  /* fix up output headers (imaginary) */
+  gfits_copy_header (&Ire[0].header, &Oim[0].header);
+  gfits_modify (&Oim[0].header, "NAXIS1", "%d", 1, Nx);
+  gfits_modify (&Oim[0].header, "NAXIS2", "%d", 1, Ny);
+  Oim[0].header.Naxis[0] = Nx;
+  Oim[0].header.Naxis[1] = Ny;
+  Oim[0].bitpix = Ire[0].bitpix;
+  Oim[0].unsign = Ire[0].unsign;
+  Oim[0].bscale = Ire[0].bscale;
+  Oim[0].bzero  = Ire[0].bzero;
+  gfits_create_matrix (&Oim[0].header, &Oim[0].matrix);
+
+  /* move data from working space to output buffers */
+  out = temp;
+  t1 = (float *) Ore[0].matrix.buffer;
+  t2 = (float *) Oim[0].matrix.buffer;
+  for (i = 0; i < Npix; i++, t1++, t2++) {
+    *t1 = *out / Npix;
+    out ++;
+    *t2 = *out / Npix;
+    out ++;
+  }    
+
+  free (temp);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fit.c	(revision 16632)
@@ -0,0 +1,227 @@
+# include "data.h"
+
+int fit (int argc, char **argv) {
+  
+  double **c, **b, *s, X, Y, dY, dY2;
+  double ClipNSigma, mean, sigma, maxsigma;
+  int i, j, nterm, mterm, order, Npt, Nmask;
+  int N, Weight, Quiet, ClipNiter;
+  Vector *xvec, *yvec, *dyvec;
+  float *x, *y, *dy, *yf, *yfit;
+  char name[64], *mask;
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  ClipNSigma = 0;
+  ClipNiter  = 1;
+  if ((N = get_argument (argc, argv, "-clip"))) {
+    remove_argument (N, &argc, argv);
+    ClipNSigma = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ClipNiter  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  dy = NULL;
+  dyvec = NULL;
+  Weight = FALSE;
+  if ((N = get_argument (argc, argv, "-dy"))) {
+    remove_argument (N, &argc, argv);
+    if ((dyvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+    Weight = TRUE;
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: fit x y order [-dy wt] [-quiet/-q] [-clip Nsigma Niter]\n");
+    return (FALSE);
+  }
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors must have same length\n");
+    return (FALSE);
+  }
+  if (Weight && xvec[0].Nelements != dyvec[0].Nelements) {
+    gprint (GP_ERR, "vectors must have same length\n");
+    return (FALSE);
+  }
+  
+  /* nterm is number of polynomial terms, starting at x^0 */
+  order = atof (argv[3]);
+  nterm = order + 1;
+  mterm = 2*nterm;
+
+  ALLOCATE (yfit, float, xvec[0].Nelements);
+  ALLOCATE (mask, char, xvec[0].Nelements);
+  memset (mask, 0, xvec[0].Nelements);
+
+  ALLOCATE (s, double, mterm);
+  ALLOCATE (b, double *, nterm);
+  ALLOCATE (c, double *, nterm);
+  for (i = 0; i < nterm; i++) {
+    ALLOCATE (c[i], double, nterm);
+    ALLOCATE (b[i], double, 1);
+  }
+
+  Nmask = 0;
+  sigma = 0.0;
+
+  for (N = 0; N < ClipNiter; N++) {
+
+    /* init registers for current pass */
+    memset (s, 0, mterm*sizeof(double));
+    for (i = 0; i < nterm; i++) {
+      memset (c[i], 0, nterm*sizeof(double));
+      memset (b[i], 0, sizeof(double));
+    }
+
+    /* perform linear fit */
+    x = xvec[0].elements;
+    y = yvec[0].elements;
+    if (Weight) dy = dyvec[0].elements;
+
+    for (i = 0; i < xvec[0].Nelements; i++, x++, y++) {
+      if (mask[i]) continue;
+      if (!(finite(*x) && finite(*y))) continue;
+      dY = 1.0;
+      if (Weight) { 
+	dY = 1.0 / SQ(*dy);
+	dy ++;
+      }
+      X = 1*dY;
+      Y = *y*dY;
+      for (j = 0; j < nterm; j++) {
+	s[j] += X;
+	b[j][0] += Y;
+	X = X * (*x);
+	Y = Y * (*x);
+      }
+      for (j = nterm; j < mterm; j++) {
+	s[j] += X;
+	X = X * (*x);
+      }
+    }
+    for (i = 0; i < nterm; i++) {
+      for (j = 0; j < nterm; j++) {
+	c[i][j] = s[i + j];
+      }
+    }
+    if (!dgaussjordan (c, b, nterm, 1)) goto escape;
+
+    /* generate fitted values */
+    x = xvec[0].elements;
+    yf = yfit;
+    for (i = 0; i < xvec[0].Nelements; i++, x++, yf++) {
+      if (!finite(*x)) continue;
+      *yf = 0;
+      X = 1;
+      for (j = 0; j < order + 1; j++) {
+	*yf += b[j][0]*X;
+	X = X * (*x);
+      }
+    }
+
+    /* measure fit residual scatter */
+    x  = xvec[0].elements;
+    y  = yvec[0].elements;
+    yf = yfit;
+    dY = dY2 = 0;
+    for (i = Npt = 0; i < xvec[0].Nelements; i++, x++, y++, yf++) {
+      if (mask[i]) continue;
+      if (!finite(*x)) continue;
+      dY  += (*y - *yf);
+      dY2 += SQ(*y - *yf);
+      Npt ++;
+    }
+    mean  = dY / Npt;
+    sigma = sqrt (fabs(dY2/Npt - SQ(mean)));
+    maxsigma = ClipNSigma * sigma;
+
+    /* mask outlier points */
+    x  = xvec[0].elements;
+    y  = yvec[0].elements;
+    yf = yfit;
+    Nmask = 0;
+    for (i = 0; ClipNSigma && (i < xvec[0].Nelements); i++, x++, y++, yf++) {
+      dY = (*y - *yf);
+      if (fabs(dY) > maxsigma) {
+	mask[i] = TRUE;
+	Nmask ++;
+      } else {
+	mask[i] = FALSE;
+      }	
+    }
+  }
+      
+  /* print & save basic fit parameters */
+  if (!Quiet) gprint (GP_ERR, "y = ");
+  for (i = 0; i < nterm; i++) {
+    sprintf (name, "C%d", i);
+    set_variable (name, b[i][0]);
+    if (!Quiet) gprint (GP_ERR, "%f x^%d ", b[i][0], i);
+  }
+  sprintf (name, "Cn");
+  set_variable (name, (double) order);
+  
+  /* print & save basic fit parameters */
+  if (!Quiet) gprint (GP_ERR, "\n");
+  if (!Quiet) gprint (GP_ERR, "    ");
+  for (i = 0; i < nterm; i++) {
+    sprintf (name, "dC%d", i);
+    set_variable (name, sqrt(c[i][i]));
+    if (!Quiet) gprint (GP_ERR, "%f     ", sqrt(c[i][i]));
+  }
+  if (!Quiet) gprint (GP_ERR, "\n");
+
+  set_variable ("dC", sigma);
+  set_variable ("Cnv", (xvec[0].Nelements - Nmask));
+
+  /* save mask and yfit for testing? */
+  if (1) { 
+    Vector *fvec, *mvec;
+    if ((fvec = SelectVector ("yfit", ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+    if ((mvec = SelectVector ("mask", ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+    free (fvec[0].elements);
+    fvec[0].elements = yfit;
+    fvec[0].Nelements = xvec[0].Nelements;
+    mvec[0].Nelements = xvec[0].Nelements;
+
+    REALLOCATE (mvec[0].elements, float, xvec[0].Nelements);
+    for (i = 0; i < xvec[0].Nelements; i++) {
+      mvec[0].elements[i] = mask[i];
+    }
+  } else {
+    free (yfit);
+  }
+  free (mask);
+
+  for (i = 0; i < nterm; i++) {
+    free (b[i]);
+    free (c[i]);
+  }
+  free (b);
+  free (c);
+  free (s);
+  return (TRUE);
+
+escape:
+  for (i = 0; i < nterm; i++) {
+    free (b[i]);
+    free (c[i]);
+  }
+  free (b);
+  free (c);
+  free (s);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fit2d.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fit2d.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/fit2d.c	(revision 16632)
@@ -0,0 +1,265 @@
+# include "data.h"
+
+int fit2d (int argc, char **argv) {
+  
+  double **c, **b, **s, X, Y, dZ, dZ2;
+  double ClipNSigma, mean, sigma, maxsigma;
+  int k, K, i, j, n, Npt, Nmask, nx, ny, nterm, mterm, wterm, order;
+  int N, Weight, Quiet, ClipNiter, VERBOSE;
+  float *x, *y, *z, *dz, *zfit, *zf; 
+  char name[64], *mask;
+  Vector *xvec, *yvec, *zvec, *dzvec;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  ClipNSigma = 0;
+  ClipNiter  = 1;
+  if ((N = get_argument (argc, argv, "-clip"))) {
+    remove_argument (N, &argc, argv);
+    ClipNSigma = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    ClipNiter  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  dz = NULL;
+  dzvec = NULL;
+  Weight = FALSE;
+  if ((N = get_argument (argc, argv, "-dz"))) {
+    remove_argument (N, &argc, argv);
+    if ((dzvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+    Weight = TRUE;
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: fit x y z order [-dz wt]\n");
+    return (FALSE);
+  }
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors must have same length\n");
+    return (FALSE);
+  }
+  if (xvec[0].Nelements != zvec[0].Nelements) {
+    gprint (GP_ERR, "vectors must have same length\n");
+    return (FALSE);
+  }
+  if (Weight && xvec[0].Nelements != dzvec[0].Nelements) {
+    gprint (GP_ERR, "vectors must have same length\n");
+    return (FALSE);
+  }
+  
+  order = atof (argv[4]);
+  nterm = order + 1;
+  wterm = nterm*(nterm + 1)/2;
+  mterm = 2*order + 1;
+
+  ALLOCATE (zfit, float, xvec[0].Nelements);
+  ALLOCATE (mask, char, xvec[0].Nelements);
+  memset (mask, 0, xvec[0].Nelements);
+
+  /* allocate the summation matrices */
+  ALLOCATE (s, double *, mterm);
+  ALLOCATE (b, double *, wterm);
+  ALLOCATE (c, double *, wterm);
+  for (i = 0; i < wterm; i++) {
+    ALLOCATE (c[i], double, wterm);
+    ALLOCATE (b[i], double, 1);
+  }
+  for (i = 0; i < mterm; i++) {
+    ALLOCATE (s[i], double, mterm);
+  }
+
+  for (N = 0; N < ClipNiter; N++) {
+
+    /* init registers for current pass */
+    // XXX this was incorrectly using nterm (missing 1 row)
+    for (i = 0; i < wterm; i++) {
+      memset (c[i], 0, wterm*sizeof(double));
+      memset (b[i], 0, sizeof(double));
+    }
+    for (i = 0; i < mterm; i++) {
+      memset (s[i], 0, mterm*sizeof(double));
+    }
+
+    x = xvec[0].elements;
+    y = yvec[0].elements;
+    z = zvec[0].elements;
+    if (Weight) dz = dzvec[0].elements;
+
+    /* add up the x,y values */
+    for (i = 0; i < xvec[0].Nelements; i++, x++, y++) {
+      if (mask[i]) continue;
+      if (!finite(*x) || !finite(*y)) continue;
+      dZ = 1.0;
+      if (Weight) { 
+	dZ = 1.0 / SQ(*dz);
+	dz ++;
+      }
+      Y = X = 1*dZ;
+      for (ny = 0; ny < mterm; ny++) {
+	X = Y;
+	for (nx = 0; nx < mterm - ny; nx++) {
+	  s[nx][ny] += X;
+	  X = X * (*x);
+	}
+	Y = Y * (*y);
+      }
+    }
+
+    /* add up the z values */
+    x = xvec[0].elements;
+    y = yvec[0].elements;
+    z = zvec[0].elements;
+    for (i = 0; i < xvec[0].Nelements; i++, x++, y++, z++) {
+      if (mask[i]) continue;
+      if (!finite(*x) || !finite(*y)) continue;
+      dZ = 1.0;
+      if (Weight) { 
+	dZ = 1.0 / SQ(*dz);
+	dz ++;
+      }
+      Y = X = *z*dZ;
+      for (j = 0, ny = 0; ny < nterm; ny++) {
+	X = Y;
+	for (nx = 0; nx < nterm - ny; nx++, j++) {
+	  b[j][0] += X;
+	  X = X * (*x);
+	}
+	Y = Y * (*y);
+      }
+    }
+
+    /* re-sort mterm x mterm matrix to wterm matrix */
+    for (k = j = 0; j < nterm; j++) {
+      for (i = 0; i < nterm - j; i++, k++) {
+	for (K = ny = 0; ny < nterm; ny++) {
+	  for (nx = 0; nx < nterm - ny; nx++, K++) {
+	    c[K][k] = s[nx+i][ny+j];
+	  }
+	}
+      }
+    }
+
+    dgaussjordan (c, b, wterm, 1);
+
+    /** test print **/
+    if (VERBOSE) {
+      for (i = ny = 0; ny < nterm; ny++) {
+	for (nx = 0; nx < nterm - ny; nx++, i++) {
+	  gprint (GP_ERR, "x^%d y^%d: %g\n", nx, ny, b[i][0]);
+	}
+      }
+    }
+
+    /* the b[][0] terms are in the following order:
+       y^0 x^0, y^0 x^1, ... y^0 x^N
+       y^1 x^0, y^1 x^1, ... y^1 x^N
+       ...
+       y^N x^0, y^N x^1, ... y^N x^N
+    */
+    /* generate fitted values */
+    x = xvec[0].elements;
+    y = yvec[0].elements;
+    zf = zfit;
+    for (n = 0; n < xvec[0].Nelements; n++, x++, y++, zf++) {
+      if (!finite(*x) || !finite(*y)) continue;
+      *zf = 0;
+      Y = X = 1;
+      for (i = ny = 0; ny < nterm; ny++) {
+	Y = X;
+	for (nx = 0; nx < nterm - ny; nx++, i++) {
+	  *zf += b[i][0]*Y;
+	  Y = Y * (*y);
+	}
+	X = X * (*x);
+      }
+    }
+
+    /* measure fit residual scatter */
+    x  = xvec[0].elements;
+    y  = yvec[0].elements;
+    z  = zvec[0].elements;
+    zf = zfit;
+    dZ = dZ2 = 0;
+    for (i = Npt = 0; i < xvec[0].Nelements; i++, x++, y++, z++, zf++) {
+      if (mask[i]) continue;
+      if (!finite(*x) || !finite(*y)) continue;
+      dZ  += (*z - *zf);
+      dZ2 += SQ(*z - *zf);
+      Npt ++;
+    }
+    mean  = dZ / Npt;
+    sigma = sqrt (fabs(dZ2/Npt - SQ(mean)));
+    maxsigma = ClipNSigma * sigma;
+
+    if (VERBOSE) gprint (GP_ERR, "mean: %g, sigma: %g, maxsigma: %g\n", mean, sigma, maxsigma);
+
+    /* mask outlier points */
+    x  = xvec[0].elements;
+    y  = yvec[0].elements;
+    z  = zvec[0].elements;
+    zf = zfit;
+    Nmask = 0;
+    for (i = 0; ClipNSigma && (i < xvec[0].Nelements); i++, x++, y++, z++, zf++) {
+      dZ = (*z - *zf);
+      if (fabs(dZ) > maxsigma) {
+	mask[i] = TRUE;
+	Nmask ++;
+      } else {
+	mask[i] = FALSE;
+      }	
+    }
+    if (VERBOSE) gprint (GP_ERR, "pass: %d, Nmask: %d\n", N, Nmask);
+  }
+
+  if (!Quiet) gprint (GP_ERR, "z = ");
+  for (N = ny = 0; ny < nterm; ny++) {
+    for (nx = 0; nx < nterm - ny; nx++, N++) {
+      sprintf (name, "CX%dY%d", nx, ny);
+      set_variable (name, b[N][0]);
+      if (!Quiet) gprint (GP_ERR, "%f x^%d y^%d  ", b[N][0], nx, ny);
+    }
+  }
+  sprintf (name, "Cnn");
+  set_variable (name, (double) order);
+  
+  if (!Quiet) gprint (GP_ERR, "\n");
+
+  /* free internal data */
+  free (zfit);
+  free (mask);
+
+  for (i = 0; i < wterm; i++) {
+    free (c[i]);
+    free (b[i]);
+  }
+  free (b);
+  free (c);
+
+  for (i = 0; i < mterm; i++) {
+    free (s[i]);
+  }
+  free (s);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gaussdeviate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gaussdeviate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gaussdeviate.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "data.h"
+
+int gaussdeviate (int argc, char **argv) {
+  
+  int i, Npts;
+  double mean, sigma;
+  Vector *vec;
+
+  if (argc != 5) goto usage;
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  Npts = atoi (argv[2]);
+  mean = atof (argv[3]);
+  sigma = atof (argv[4]);
+
+  vec[0].Nelements = Npts;
+  REALLOCATE (vec[0].elements, float, Npts);
+
+  gauss_init (2048);
+  for (i = 0; i < Npts; i++) {
+    vec[0].elements[i] = rnd_gauss (mean, sigma);
+  }
+  return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "USAGE: gaussdeviate (vector) Npts mean sigma\n");
+  return (FALSE);
+    
+}
+
+double int_gauss (int i);
+
+int gaussintegral (int argc, char **argv) {
+  
+  int i, Npts;
+  double mean, sigma;
+  Vector *vec;
+
+  if (argc != 5) goto usage;
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  Npts = atoi (argv[2]);
+  mean = atof (argv[3]);
+  sigma = atof (argv[4]);
+
+  vec[0].Nelements = Npts;
+  REALLOCATE (vec[0].elements, float, Npts);
+
+  gauss_init (Npts);
+  for (i = 0; i < Npts; i++) {
+    vec[0].elements[i] = int_gauss (i);
+  }
+  return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "USAGE: gaussintegral Npts mean sigma\n");
+  return (FALSE);
+    
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gaussj.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gaussj.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gaussj.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "data.h"
+
+int gaussjordan (int argc, char **argv) {
+  
+  float *m, *v;
+  double **a, **b;
+  int i, j, N, status, QUIET;
+  Vector *B;
+  Buffer *A;
+
+  QUIET = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    QUIET = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) goto usage;
+
+  if ((A = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);    
+  if ((B = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+
+  N = B[0].Nelements;
+  if (A[0].matrix.Naxis[0] != N) goto usage;
+  if (A[0].matrix.Naxis[1] != N) goto usage;
+  
+  ALLOCATE (a, double *, N);
+  ALLOCATE (b, double *, N);
+  for (i = 0; i < N; i++) {
+    ALLOCATE (a[i], double, N);
+    ALLOCATE (b[i], double, 1);
+  }
+
+  m = (float *) A[0].matrix.buffer;
+  v = B[0].elements;
+  for (i = 0; i < N; i++) {
+    for (j = 0; j < N; j++) {
+      a[i][j] = m[i+j*N];
+    }
+    b[i][0] = v[i]; 
+  }
+
+  status = dgaussjordan (a, b, N, 1);
+
+  for (i = 0; i < N; i++) {
+    for (j = 0; j < N; j++) {
+       m[i+j*N] = a[i][j];
+    }
+    v[i] = b[i][0]; 
+  }
+
+  for (i = 0; i < N; i++) {
+    free (a[i]);
+    free (b[i]);
+  }
+  free (a);
+  free (b);
+
+  if (!status && !QUIET) {
+      gprint (GP_ERR, "failure in matrix solution\n");
+  }
+  return (status);
+
+ usage:
+  gprint (GP_ERR, "USAGE: gaussj A B\n");
+  gprint (GP_ERR, "  solves Ax = B, returns 1/A in A and x in B\n");
+  gprint (GP_ERR, "  A must be square, B same dimensions\n");
+  return (FALSE);
+    
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/grid.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/grid.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/grid.c	(revision 16632)
@@ -0,0 +1,203 @@
+# include "data.h"
+
+int grid (int argc, char **argv) {
+  
+  int j, kapa, N, MinorTick, MajorTick;
+  Vector Xvec, Yvec;
+  double range, lrange, factor, mantis, fmantis, power, major, minor, first, next;
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return (FALSE);
+
+  MajorTick = TRUE;
+  MinorTick = FALSE;
+  if ((N = get_argument (argc, argv, "-all"))) {
+    remove_argument (N, &argc, argv);
+    MinorTick = TRUE;
+  }
+
+  if (argc > 1) {
+    gprint (GP_ERR, "USAGE: grid [-n graph]\n");
+    return (FALSE);
+  }
+
+  N = 0;
+  Xvec.Nelements = 200;
+  Yvec.Nelements = 200;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+
+  major = minor = 1;
+  range = graphmode.xmax - graphmode.xmin;
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    major = 0.5 * power;
+    minor = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    major = 1.0 * power;
+    minor = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    major = 1.0 * power;
+    minor = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    major = 2.0 * power;
+    minor = 0.5 * power;
+  }
+  if (graphmode.xmin > 0)
+    first = minor + minor*((int)(graphmode.xmin/minor));
+  else 
+    first = -minor + minor*((int)(graphmode.xmin/minor));
+  if (minor*((int)(graphmode.xmin/minor)) == graphmode.xmin) {
+    first = graphmode.xmin;
+  }
+  
+  for (j = 0, next = first; next <= graphmode.xmax; j++) {
+    if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major))) {
+      if (MajorTick) {
+	/* major tick */
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymin;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymax;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    } else {
+      if (MinorTick) {
+	/* minor tick */
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymin;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = next;
+	Yvec.elements[N] = graphmode.ymax;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    }
+    next += minor;
+  }
+
+  range = graphmode.ymax - graphmode.ymin;
+  lrange = log10(MAX(fabs(range), 1e-30));
+  factor = (int) (lrange);
+  if (lrange < 0) { factor -= 1; }
+  mantis = lrange - factor;
+  power = pow(10.0, factor);
+  fmantis = pow(10.0, mantis);
+  if ((fmantis >= 1.0) && (fmantis <=  2.0)) {
+    major = 0.5 * power;
+    minor = 0.1 * power;
+  }
+  if ((fmantis > 2.0) && (fmantis <=  4.0)) {
+    major = 1.0 * power;
+    minor = 0.2 * power;
+  }
+  if ((fmantis > 4.0) && (fmantis <=  6.0)) {
+    major = 1.0 * power;
+    minor = 0.5 * power;
+  }
+  if ((fmantis > 6.0) && (fmantis <=  10.0)) {
+    major = 2.0 * power;
+    minor = 0.5 * power;
+  }
+  if (graphmode.ymin > 0)
+    first = minor + minor*((int)(graphmode.ymin/minor));
+  else 
+    first = -minor + minor*((int)(graphmode.ymin/minor));
+  if (minor*((int)(graphmode.ymin/minor)) == graphmode.ymin) {
+    first = graphmode.ymin;
+  }
+  
+  for (j = 0, next = first; next <= graphmode.ymax; j++) {
+    if ((fabs((int)(next/major) - (next/major)) < 0.5*(minor/major)) || (fabs ((int)((next + 0.5*minor)/major) - (next/major)) < 0.5*(minor/major))) {
+      if (MajorTick) {
+	/* major tick */
+	Xvec.elements[N] = graphmode.xmin;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = graphmode.xmax;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    } else {
+      if (MinorTick) {
+	/* minor tick */
+	Xvec.elements[N] = graphmode.xmin;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+	Xvec.elements[N] = graphmode.xmax;
+	Yvec.elements[N] = next;
+	N++;
+	if (N == Xvec.Nelements) {
+	  Xvec.Nelements += 200;
+	  Yvec.Nelements += 200;
+	  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+	  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+	}
+      }
+    }
+    next += minor;
+  }
+
+  Xvec.Nelements = Yvec.Nelements = N;
+  graphmode.style = 2; /* points */
+  graphmode.ptype = 100; /* connect a pair */
+  graphmode.etype = 0;
+  PlotVectorPair (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gridify.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gridify.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/gridify.c	(revision 16632)
@@ -0,0 +1,82 @@
+# include "data.h"
+
+int gridify (int argc, char **argv) {
+
+  int i, Nx, Ny, Xb, Yb, Normalize, N;
+  float Xmin, Xmax, dX, Ymin, Ymax, dY;
+  float *buf, *val, *x, *y, *z;
+  int *Nval;
+  Buffer *bf;
+  Vector *vx, *vy, *vz;
+
+  Normalize = TRUE;
+  if ((N = get_argument (argc, argv, "-raw"))) {
+    remove_argument (N, &argc, argv);
+    Normalize = FALSE;
+  }
+
+  if (argc != 11) {
+    gprint (GP_ERR, "USAGE: gridify x y z buffer Xmin Xmax dX Ymin Ymax dY\n");
+    return (FALSE);
+  }
+  
+  if ((vx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vz = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((bf = SelectBuffer (argv[4], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (vx[0].Nelements != vy[0].Nelements) return (FALSE);
+  if (vx[0].Nelements != vz[0].Nelements) return (FALSE);
+
+  Xmin = atof (argv[5]);
+  Xmax = atof (argv[6]);
+  dX   = atof (argv[7]);
+
+  Ymin = atof (argv[8]);
+  Ymax = atof (argv[9]);
+  dY   = atof (argv[10]);
+
+  Nx = (Xmax - Xmin) / dX + 1;
+  Ny = (Ymax - Ymin) / dY + 1;
+  
+  gfits_free_matrix (&bf[0].matrix);
+  gfits_free_header (&bf[0].header);
+  CreateBuffer (bf, Nx, Ny, -32, 0.0, 1.0);
+  strcpy (bf[0].file, "(empty)");
+
+  ALLOCATE (val, float, Nx*Ny);
+  bzero (val, Nx*Ny*sizeof(float));
+  ALLOCATE (Nval, int, Nx*Ny);
+  bzero (Nval, Nx*Ny*sizeof(int));
+
+  x = vx[0].elements;
+  y = vy[0].elements;
+  z = vz[0].elements;
+  for (i = 0; i < vx[0].Nelements; i++, x++, y++, z++) {
+    Xb = (*x - Xmin) / dX;
+    Yb = (*y - Ymin) / dY;
+    if (Xb >= Nx) continue;
+    if (Yb >= Ny) continue;
+    val[Xb + Yb*Nx] += *z;
+    Nval[Xb + Yb*Nx]++;
+  }
+
+  buf = (float *) bf[0].matrix.buffer;
+  for (i = 0; i < Nx*Ny; i++) {
+    if (Normalize) {
+      if (Nval[i] == 0) {
+	buf[i] = 0;
+	continue;
+      }
+      buf[i] = val[i] / Nval[i];
+    } else {
+      buf[i] = val[i];
+    }
+  }
+
+  free (val);
+  free (Nval);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/grow.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/grow.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/grow.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "data.h"
+
+int grow (int argc, char **argv) {
+  
+  int i, j, nx, ny, npix, nsum, Nx, Ny;
+  float *input, *output;
+  Buffer *in;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: grow (input) (npix)\n");
+    return (FALSE);
+  }
+  
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  npix = atoi (argv[2]);
+
+  Nx = in[0].matrix.Naxis[0];
+  Ny = in[0].matrix.Naxis[1];
+  ALLOCATE (output, float, Nx*Ny);
+  memset (output, 0, Nx*Ny*sizeof(float));
+
+  input = (float *) in[0].matrix.buffer;
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      nsum = 0;
+      for (ny = -1; ny <= +1; ny++) {
+	if (j + ny < 0) continue;
+	if (j + ny >= Ny) continue;
+	for (nx = -1; nx <= +1; nx++) {
+	  if (i + nx < 0) continue;
+	  if (i + nx >= Nx) continue;
+	  if (!nx && !ny) continue;
+	  if (input[i + nx + Nx*(j + ny)] == 0) continue;
+	  nsum ++;
+	}
+      }
+      if (nsum >= npix) {
+	output[i + j*Nx] = 1;
+      } else {
+	output[i + j*Nx] = input[i + j*Nx];
+      }
+    }
+  }
+  
+  free (in[0].matrix.buffer);
+  in[0].matrix.buffer = (char *) output;
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Graphics
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Graphics	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Graphics	(revision 16632)
@@ -0,0 +1,20 @@
+
+  Kapa, the graphics window.
+
+  Kapa is the program which Status uses to display plots on an X
+terminal.  There are actually 5 graphics windows available to Status,
+though several functions write to specific windows by default.  All
+plots of sky coordinates are displayed on window 0, while 
+functions which plot other types of data use window 1.  Most functions
+have an option -n which allows the user to specify which Kapa window.
+If it is not specified, the last window used will receive the action.
+
+  Below are the available Resources.  
+
+  kii*Foreground:			white
+  kii*Background:			maroon
+  kii*geometry:				540x540+10+10
+
+  See Also: box, clear, limits, plot
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Kii
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Kii	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Kii	(revision 16632)
@@ -0,0 +1,57 @@
+
+
+  Kii (= "picture" in Hawaiian) is the program which Mana uses to
+display images on an X terminal.  The window consists of a main region
+where the image is displayed, a small "zoom box" where a magnified
+view of the region around the cursor is shown, a colorbar showing the
+current color map across the top of the window, a status box where the
+coordinates and pixel values are displayed, and several buttons.
+Clicking with the mounse in the different regions produces different
+effects.
+
+  Image Window:  Clicking with the left mouse button (mouse-1)
+recenters the image at the specified location.  Clicking with the
+right button (mouse-3) also recenters, but increases the zoom factor
+by one.  Clicking with the middle button centers and decreases the
+zoom factor.  
+
+  Colorbar: Clicking and draging with the left button (mouse-1) alters
+the color mapping.  Moving left-to-right slides the center of the
+color scale with the mouse.  Moving up-and-down squeezes or expands
+the color scale.  The middle button resets the color mapping.
+Clicking and dragging side-to-side with the right button expands or
+squeezes the color mapping.  **Note: the dynamic colormap cannot be
+used with a 24 or 32 bit visual.  The standard Linux XFree86 server
+does not support 8 bit visuals in 24 or 32 bit/pixel mode.  In this
+case, the Kii window must resort to a static colormap with the
+colorbar disabled.  In Linux, it is possible to run startx with the
+following command-line options to force the 8 bit/pixel mode:
+# startx -- -bpp 8 
+This assumes that you have an 8bpp Display mode set in the XF86Config
+file.  If not, you can just duplicate the 24 or 32 bpp Display modes
+which will enable this option.
+
+  Buttons:
+    PS: this button creates a PostScript version of the image.
+    Grey: this button makes the colormap a greyscale.
+    Rainbow: this button makes the colormap a rainbow.
+    Puns: this button make the colormap a blue and yellow mapping.
+    Recenter: this button recenters the image and resets the zoom.
+
+  Kii also recognizes several X Resource values:
+
+  Below are the available Resources (with Gene's default values).  Unlike
+most standard X programs, the geometry resource specifies the size of
+the Image Window, not the borders of the entire window.  Valid values
+for the colormap are: greyscale, grayscale (photonegative), -greyscale,
+-grayscale (photopositive), Puns, GoBears (buff 'n blue colormap),
+Rainbow (a rainbow map).  
+
+  kii*Foreground:			white
+  kii*Background:			maroon
+  kii*Colormap:				greyscale
+  kii*geometry:				540x540+10+10
+  
+
+  See Also: tv, cursor
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Math
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Math	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/Math	(revision 16632)
@@ -0,0 +1,58 @@
+
+  Opihi shell math operations:
+
+  Mana will evaluate scalar (1D) arithmetic expresions in two
+situations.  To set a variable equal to a math operation, use the
+syntax is:
+
+  $foo = expression
+
+where "expression" is an arithmetic expression on numbers and
+variables, including a variety of functions (see below).  After
+performing the arithmetic and setting the variable to the resulting
+value, mana returns the prompts without performing any further
+command.  Mana will also evaluate any arithmetic expression enclosed
+in curly brackets before attempting to perform the given command.  For
+example, if the variables $MEAN and $SIGMA contain the mean and
+standard deviation of an image, it would be possible to display the
+image with a zero and range based on $MEAN and $SIGMA like this:
+
+  tv image {$MEAN - 1.5*$SIGMA} {5*$SIGMA}
+
+
+The two expressions in curly brackets are evaluated and the resulting
+numbers passed as arguments to the "tv" command.
+
+  See Also:  Variables, tv
+
+
+list of valid math operations:
+
+  binary operators:
+  * (times)
+  / (divided by)
+  + (plus)
+  - (minus)
+  ^ (to the power of: 2^3 = 8)
+
+  unary operators:
+  exp (e to the power of)
+  ten (10 to the power of)
+  ln  (natural logarithm)
+  log (log base 10)
+
+  angles in radians:
+  sin (sine)
+  cos (cosine)
+  tan (tangent)
+  asin (arcsin)
+  acos (arccos)
+  atan (arctan)
+
+  angles in degrees:
+  dsin (sine)
+  dcos (cosine)
+  dtan (tangent)
+  dasin (arcsin)
+  dacos (arccos)
+  datan (arctan)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/applyfit
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/applyfit	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/applyfit	(revision 16632)
@@ -0,0 +1,10 @@
+
+  applyfit x y
+
+  apply the results of a polynomial fit (stored in variables 
+  $C0, $C1, etc, with $Cn representing the order of the fit).
+  The second vector will contain the function value at the 
+  corresponding x coordinates of the first vector.
+
+  See also: fit
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/box
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/box	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/box	(revision 16632)
@@ -0,0 +1,11 @@
+
+  box [-n Nwindow]
+
+  draw a coordinate box on the current kapa window, or on the window
+specified by -n (0 - 4).
+
+  See also: Kapa
+
+
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/buffers
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/buffers	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/buffers	(revision 16632)
@@ -0,0 +1,9 @@
+
+  buffers
+
+  buffers gives information about the currently allocated buffers.  
+A * next to the filename means the data has been altered from the
+originally read in image.
+
+  See also: memory
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/center
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/center	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/center	(revision 16632)
@@ -0,0 +1,10 @@
+
+  center (xpix) (ypix) [magnification]
+
+  "center" centers the Kii window at the specified pixel coordinates.
+Specifying a magnification will change the image scale to the
+specified magnification.  If you do not specify a magnification
+(default), the image scale will remain the same.
+
+  See also: Kii, tv
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/clear
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/clear	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/clear	(revision 16632)
@@ -0,0 +1,5 @@
+
+   clear
+
+   clear the Kapa window
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/clip
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/clip	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/clip	(revision 16632)
@@ -0,0 +1,8 @@
+
+  clip (buffer) [min Vmin max Vmax] [-inf val] [-nan val]
+
+  clip values in an image.  A min/max clip can be applied, 
+  in which case all values above max are set to Vmax and all
+  below min are set to Vmin.  -nan and -inf flags will set all 
+  instances of NaN or any non-finite values to the given value.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/close
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/close	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/close	(revision 16632)
@@ -0,0 +1,14 @@
+
+
+   close [-n win] [-g Kapa win] [-i Kii win]
+
+   Closes the specified graphics window
+
+   Default: the most recently activated window (only works
+    for the first call)
+
+   [win]: the index of the window to close
+
+   -n: any graphics or plotting window
+   -g: the Kapa plotting window
+   -i: the Kii image window
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/concat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/concat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/concat	(revision 16632)
@@ -0,0 +1,7 @@
+
+   concat v1 v2
+
+   Concatenates the values of vector v1 to the end of vector
+    v2, increasing the length of v2.
+
+   See also: subset, set
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/contour
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/contour	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/contour	(revision 16632)
@@ -0,0 +1,13 @@
+
+  contour <buffer> (overlay) level [Npix]
+
+  "contour" makes a contour plot from the given <buffer> at the
+specified level.  If Npix is specified, the image is rebinned by a
+factor of Npix in each direction.  The contour is drawn as a series of
+lines on the specified overlay.  The new lines are added to any
+existing shapes.  (Use "erase" first to erase all objects if desired).
+
+Valid overlays may be: 0, red, 1, green, 2, blue, 3, yellow.
+
+  See also: load, save, erase
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/create
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/create	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/create	(revision 16632)
@@ -0,0 +1,9 @@
+
+   create (vector) (start) (end) [delta]
+
+   Create a vector of uniformly spaced values, starting at
+   (start) and going to (end).  By default the spacing is 1, but
+   may be chosen with the [delta] option.
+
+   Note: A vector cannot be created if an image buffer already
+    exists with the same name
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cumulative
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cumulative	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cumulative	(revision 16632)
@@ -0,0 +1,8 @@
+
+
+   cumulative (invec) (outvec)
+
+   Creates a vector (outvec) where the element N is the sum of the elements
+    0-N of (invec)
+
+   Note: The final element of (outvec) is always 0
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cursor
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cursor	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cursor	(revision 16632)
@@ -0,0 +1,13 @@
+
+  cursor
+
+  place cursor coordinates (and values ??) into Mana variables.  to do
+this, type cursor, then place the cursor on the desired spot in the
+Ki'i window and type a digit (0 - 9).  The coordinates of the cursor
+are then placed in the variables $Xn and $Yn (where n is the digit you
+typed).  To exit the cursor mode, type "q" (or "Q") in the Ki'i
+window.  
+
+  See Also: Kii, tv, center
+
+ 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cut
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cut	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/cut	(revision 16632)
@@ -0,0 +1,9 @@
+
+   cut buffer <X vector> <Y vector> <X|Y> sx sy nx ny
+
+   take a cut from an image and place it in a pair of vectors.
+   the <X vector> gets the pixel coordinate in the given direction,
+   the <Y vector> gets the pixel values.  <X|Y> specifies the 
+   direction of the cut.  the region sx, sy, nx, ny specifies the
+   region for the cut, with summation in the cross-direction.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/datafile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/datafile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/datafile	(revision 16632)
@@ -0,0 +1,6 @@
+
+   datafile (filename)
+
+   define a data file for subsequent vector reads.
+
+   See also: read
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/delete
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/delete	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/delete	(revision 16632)
@@ -0,0 +1,10 @@
+
+  delete (buffer/vector/variable)
+
+  Delete the named buffer/vector/variable.
+
+  Warning: no second chances are given!
+
+  Note: Delete will remove the buffer/vector of a
+   given name first, then delete the variable of
+   the same name upon the second call.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dimendown
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dimendown	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dimendown	(revision 16632)
@@ -0,0 +1,7 @@
+
+
+   dimendown (buffer) (vector) [-x/-y]
+
+   Compresses an image into a vector
+
+   The vector can be given either the x or y coordinates of the image
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dimenup
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dimenup	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dimenup	(revision 16632)
@@ -0,0 +1,5 @@
+
+
+   dimenup (vector) (buffer) (Nx) (Ny)
+
+   Expands a vector into an image with dimensions Nx,Ny
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/dot	(revision 16632)
@@ -0,0 +1,7 @@
+
+
+   dot (x) (y)
+
+   Plots a single point
+
+   Uses the same style options as plot
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/erase
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/erase	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/erase	(revision 16632)
@@ -0,0 +1,8 @@
+
+  erase (overlay)
+
+  "erase" erases all objects on the specified overlay.  
+  Valid overlays may be: all, red, green, blue, yellow.
+
+  See also: load, save, contour
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/extract
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/extract	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/extract	(revision 16632)
@@ -0,0 +1,12 @@
+
+  extract <from> <to> sx sy nx ny sx sy nx ny
+
+  extract takes a portion of an image (buffer <from>) and creates a
+new image (buffer <to>).  The source region is defined by the first
+set of (sx sy nx ny), the resulting image and the location of the
+extracted image are defined by the second (sx sy nx ny).  This allows
+a portion of an image to be overlayed at a particular location in a
+larger image.
+
+  See also: Kii, tv
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/fit
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/fit	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/fit	(revision 16632)
@@ -0,0 +1,15 @@
+
+   fit (-q) x y (order) (-dy wt) (-clip sig N)
+
+   perform a lease-square polynomial fit to the data defined 
+   by vectors x and y.  the coefficients are placed in the variables
+   $C0, $C1, ..., and the order is placed in $Cn.
+
+   order: order of fit
+   -q: quiets the fit (no output to window)
+   -dy: take into account the error vector wt
+   -clip: remove outliers beyond sig*sigma from the fit;
+           perform N iterations of this
+
+   See also: applyfit
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/grid
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/grid	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/grid	(revision 16632)
@@ -0,0 +1,6 @@
+
+   grid (overlay) (buffer)
+
+   draw a coordinate grid for the given buffer in the 
+   given overlay in Kii.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/header
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/header	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/header	(revision 16632)
@@ -0,0 +1,8 @@
+
+   header (buffer)
+
+   print the header information for the given buffer.  The header
+   information is Meta-information associated with an image.  It is
+   well-defined for the FITS images, but may not exist for some of the
+   other possible data types.  
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/histogram
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/histogram	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/histogram	(revision 16632)
@@ -0,0 +1,8 @@
+
+   histogram <buffer> <x> <y> [-region sx sy nx ny] [-range min max]
+
+   calculate a histogram of the image pixel values in the given
+   buffer, optionally constrained to the given region, with optional
+   max and min values.  the results are placed in the vectors x and y,
+   which contain the pixel values and the number of occurences.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/integrate
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/integrate	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/integrate	(revision 16632)
@@ -0,0 +1,10 @@
+
+   integrate (x) (y) (start) (end)
+
+   Perform an integration of (y) as a function of (x) from (start) to (end)
+
+   The result is placed into the variable: $sum
+
+   Caution!: Program uses the front end of each x bin to approximate the integral.
+    Very coarse bins (delta x = 1) over small regions (x=1->5) can introduce
+    errors as large as 20%. Fine bins are reccommended.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/interpolate
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/interpolate	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/interpolate	(revision 16632)
@@ -0,0 +1,5 @@
+
+   interpolate (xin) (yin) (xout) (yout)
+
+   Performs an interpolation of (xin) and (yin) onto the new grid (xout),
+    producing the corresponding y values in (yout)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/kern
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/kern	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/kern	(revision 16632)
@@ -0,0 +1,4 @@
+
+   kern buffer (kernel file or -)
+
+   apply a 3x3 kernel to the image.  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/keyword
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/keyword	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/keyword	(revision 16632)
@@ -0,0 +1,11 @@
+
+  keyword <buffer> (KEYWORD) [variable] [-w value]
+
+  "keyword" extracts the specified keyword from the header of the
+   specified buffer.  If a third word is listed, the value of the
+   keyword is stored in a variable with the given name.  If the -w
+   option is given, the value is written to the header keyword.
+
+   The header Meta-data is well-defined for FITS, but not necessarily
+   for other data types.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/labels
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/labels	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/labels	(revision 16632)
@@ -0,0 +1,23 @@
+
+   labels 
+
+   write a label on the Kapa window.  there are many options:
+
+   -fn font size -- define the font (may be times, helvetica, courier)
+
+   -x "a long line" -- label on the bottom x-axis
+
+   +x "a long line" -- label on the top x-axis
+
+   -y "a long line" -- label on the left y-axis
+
+   +y "a long line" -- label on the right y-axis
+
+   -ul "a long line" -- label on the upper left of plot
+
+   -ll "a long line" -- label on the lower left of plot
+
+   -ur "a long line" -- label on the upper right of plot
+
+   -lr "a long line" -- label on the lower right of plot
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/limits
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/limits	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/limits	(revision 16632)
@@ -0,0 +1,12 @@
+
+   limits min max min max
+   limits x y
+   limits x min max
+   limits min max y
+   
+   set Kapa plot limits.  The x and y axis limits may be explicitly
+   set (first example), or they may be assigned based on the range of
+   values in a pair of vectors (second examples), or one range may be
+   explicit and the other range assigned from a vector.
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/load
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/load	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/load	(revision 16632)
@@ -0,0 +1,20 @@
+
+   load (overlay) (filename)
+
+  "load" reads a file with objects in SAOimage style into the
+  specified overlay.  If the specified overlay is already used, the
+  new objects are added to the old.  If you do not want this, use
+  "erase" to erase all objects in the overlay first.  Valid overlays
+  may be: 0, red, 1, green, 2, blue, 3, yellow.
+
+Examples of SAOimage style objects:
+BOX   300  200  100 50  : draws a box centered at pixel 300,200 that
+			  is 100 pixels wide, and 50 pixels high
+
+CIRCLE 500 400 200 : draws a circle centered at pixel 500,400 with a
+                     radius of 200 pixels
+
+LINE 100 100 200 200 : draws a line from (100,100) with length (200,200)
+
+  See also: save, erase, contour
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/peak
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/peak	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/peak	(revision 16632)
@@ -0,0 +1,12 @@
+
+   peak [-q] (x) (y) [startx endx]
+
+   Determines the peak of the y vector between starx and endx
+    or between the extrema of the x vector (default)
+
+   -q: quiets the script (no output to the window)
+
+   Outputs:
+    $peakval: Value of the peak
+    $peakpos: X value corresponding to the peak value
+    $peaknum: Index of the peak value
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/periodogram
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/periodogram	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/periodogram	(revision 16632)
@@ -0,0 +1,6 @@
+
+   periodogram (time) (flux) (minP) (maxP) (period) (power)
+
+   creates a periodogram from the vectors (time) and (flux)
+    between (minP) and (maxP) and outputs the results to
+    (period) and (power)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/plot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/plot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/plot	(revision 16632)
@@ -0,0 +1,13 @@
+
+   plot <x> <y> [-dx dx] [-dy dy] [+dx dx] [+dy dy]
+
+   plot a pair of vectors.  the options allow for errorbars.  If only
+   one of -dy or +dy is given, the given vector is used for the
+   errorbar.  If both are given, -dy defines the lower errorbar, while
+   +dy defines the upper errorbar.  This allows for assymetric errors
+   in a trivial fashion.  The same applies to the -dx, +dx values.  
+
+   The vectors are plotted with the current plot style.  See style for
+   all of the options.
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/ps
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/ps	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/ps	(revision 16632)
@@ -0,0 +1,16 @@
+
+   ps [-name file.ps] [-g | -i] [-n device] [-raw] [-noscale] [-newpage]
+
+   create a PostScript file from the current graphics window (Kii or
+   Kapa).  The target graphics window may be selected with the -g or
+   -i options (to choose between Kii or Kapa) in combination the -n
+   option (to specify which instance).
+
+   With no additional arguments, Kii produces an encapsulated
+   postscript file called Ximage.ps, while Kapa produces a file called
+   Xgraph.ps.  The output name may be set with the -name (file.ps)
+   option. 
+
+   By default, the output is scaled to fit on a letter page 
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuedelete
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuedelete	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuedelete	(revision 16632)
@@ -0,0 +1,4 @@
+
+   queuedelete (name)
+
+   Deletes the entire queue (name)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queueinit
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queueinit	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queueinit	(revision 16632)
@@ -0,0 +1,4 @@
+
+   queueinit (name)
+
+   Creates a queue (name) with an initial size of 0
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuepush
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuepush	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuepush	(revision 16632)
@@ -0,0 +1,8 @@
+
+   queuepush (queue) (value) [-key N] [-uniq] [-replace]
+
+   Pushes (value) onto the back of (queue)
+
+   -key N:
+   -uniq:
+   -replace:
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuesize
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuesize	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/queuesize	(revision 16632)
@@ -0,0 +1,5 @@
+
+   queuesize (name) [-var variable]
+
+   Returns the size of the queue (name), either to variable
+    or to the window (default)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rd
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rd	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rd	(revision 16632)
@@ -0,0 +1,10 @@
+
+  rd (buffer) (filename)
+
+  "rd" reads a file into the specified buffer, creating the buffer if
+  none exists.  A buffer name may consist of any letters, numbers, and
+  some limited other characters.  However, the name may not start with
+  a digit.
+
+  See also: wd, tv
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/read
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/read	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/read	(revision 16632)
@@ -0,0 +1,10 @@
+
+   read vect col [vect col, ...]
+
+   read vector values from a file.  An arbitrary number of vectors can
+   be specified, and the (whitespace-separated) field number given for
+   each vector.  Data is read from the file defined by "datafile".
+
+   See also: datafile
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rebin
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rebin	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rebin	(revision 16632)
@@ -0,0 +1,9 @@
+
+  rebin <from> <to> scale
+
+  "rebin" rebins the specified buffer by the given scale factor and
+  places the result in the <to> buffer.  Negative integer values imply
+  expansion, positive numbers imply compression.
+
+  See also: extract
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/resize
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/resize	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/resize	(revision 16632)
@@ -0,0 +1,6 @@
+
+   resize Nx Ny
+
+   change the size of the Kii window to have image dimensions Nx x
+   Ny.  
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rotate
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rotate	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/rotate	(revision 16632)
@@ -0,0 +1,10 @@
+
+   rotate (buffer) (angle) [-center x y]
+
+   rotate the buffer by the given angle.  The angle may also be one of
+   the following special words:
+
+   -flipx - flip in the x direction
+   -flipy - flip in the y direction
+
+   if the optional center is given the rotation is about this position.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/save
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/save	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/save	(revision 16632)
@@ -0,0 +1,16 @@
+  save (overlay) (filename)
+
+  "save" stores the objects from the specified overlay into the named
+file.  Valid overlays may be: 0, red, 1, green, 2, blue, 3, yellow.
+
+Examples of SAOimage style objects:
+BOX   300  200  100 50  : draws a box centered at pixel 300,200 that
+			  is 100 pixels wide, and 50 pixels high
+
+CIRCLE 500 400 200 : draws a circle centered at pixel 500,400 with a
+                     radius of 200 pixels
+
+LINE 100 100 200 200 : draws a line from (100,100) with length (200,200)
+
+  See also: load, erase, contour
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/set
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/set	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/set	(revision 16632)
@@ -0,0 +1,41 @@
+
+  set (buffer) = expression..
+
+  perform math operations on images.  there are several allowed
+  operators.  the standard math functions are + - * /.  Exponentiation
+  is performed with ^ (set c = a ^ b).  There are several "logic"
+  operators which need some explanation.
+
+  set c = a < b  -- c is 1 if a < b, 0 otherwise
+  set c = a > b  -- c is 1 if a > b, 0 otherwise
+  set c = m1 & m1 - c is 1 if m1 AND m2 true (non-zero is true)
+  set c = m1 | m1 - c is 1 if m1 OR m2 true (non-zero is true)
+  set c = a << b -- c is the minimum of a and b
+  set c = a >> b -- c is maximum of a and b
+
+  complex operations may be performed:
+
+  set c = a*(a < b) + c*((a < c) | (c < d))
+
+  unary operators also exist:
+
+  exp(a) - e to the power of a
+  ten(a) - 10 to the power of a
+  ln(a) - log base e of a
+  log(a) - log base 10 of a
+  sqrt(a) - square root of a
+  sin(a) - sin of a
+  cos(a) - sin of a
+  tan(a) - sin of a
+  not(a) - logical inverse of a
+  abs(a) - absolute value of a
+  int(a) - integer value of a
+
+  Examples:
+  
+  set a = b + 10  (add 10 to every pixel in b and put the answer in a)
+  set a = a / b   (divide every pixel in a by the corresponding pixel
+                     b and put the answer in a)
+  set b = 10 / a  (divide 10 by every pixel in a and put the answer
+                     in b)
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/shift
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/shift	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/shift	(revision 16632)
@@ -0,0 +1,6 @@
+
+   shift buffer dx dy
+
+   shift image by dx,dy pixels (may be fractional values).
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/stats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/stats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/stats	(revision 16632)
@@ -0,0 +1,10 @@
+
+  stats (buffer) (x) (y) (nx) (ny)
+
+  report the statistics on a portion of an image.  (x) and (y) specify
+the starting corner of the region, (nx) and (ny) specify the width and
+height of the region.  stats reports the mean, sigma, and number of
+pixels in the region.
+
+  See Also: ??
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/style
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/style	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/style	(revision 16632)
@@ -0,0 +1,36 @@
+
+   style -- many options
+
+   define or check the Kapa plotting style.  without any command-line arguments,
+   style prints the current style.  
+
+   option definitions:
+
+   -n	window number (0-4), can also be used to change active window.
+   -pt	point style: 
+		0 = filled box
+		1 = open box
+		2 = +
+		3 = X
+		4 = filled triangle
+		5 = blank
+		6 = open triangle 
+		7 = open circle
+		100 = connect pair of points
+   -x	plotting method:
+		0 = connect
+		1 = histogram
+		2 = points
+   -lt	line type:
+		0 = solid
+		1 = dashed
+		2 = dotted??
+   -lw	line weight (0-10)
+   -sz	point size
+   -c   color:
+	black, white, red, orange, 
+	yellow, green, blue, indigo, violet
+   -eb  errorbar with no top
+   +eb  errorbar with top
+
+   See also: plot, box
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/subset
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/subset	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/subset	(revision 16632)
@@ -0,0 +1,12 @@
+
+   subset vec = vec if (logic expression)
+
+   reduce the length of a vector based on logical expression.  The
+   logic expression is some function of vectors of equal length to the
+   main vector.
+
+   for example, we have vectors x and y of the same length:
+   
+   subset X = x if ((y > 100) | (x < 10))
+
+    
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/textline
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/textline	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/textline	(revision 16632)
@@ -0,0 +1,7 @@
+
+   textline x y (line) [-fn (font) size] [-rot angle]
+
+   write the string at the given coordinates and rotation,
+   in the given font.
+
+   (enclose long strings with spaces in quotes)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/tv
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/tv	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/tv	(revision 16632)
@@ -0,0 +1,13 @@
+
+  tv [-log] (buffer) [zero range]
+
+  display an image in the Ki'i window (X display program).  zero and
+  range specify the data values corresponding to the color mapping.
+  If they are not specified, the old values are used (default is 0,
+  1024).
+
+  If -log is specified the color mapping scale will be logarithmic.  
+
+
+  See Also: Kii, rd, cursor
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/unsign
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/unsign	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/unsign	(revision 16632)
@@ -0,0 +1,20 @@
+  unsign
+
+  "unsign" toggles the status of the UNSIGN mode.  Warning: This is a
+non-FITS standard implementation.  The FITS standard does not allow
+for unsigned integer data values, but many sites write CCD images with
+16 bit UNSIGNED data.  Mana looks for a FITS keyword "UNSIGN" to
+determine if an image which is read in has signed or unsigned
+integers.  However, since this is a non-standard concept, many sites
+do not use the UNSIGN flag, yet still write unsigned data.  If the
+user knows the data in the file is unsigned (ie, the user must have
+apriori knowledge -- a FITS no-no!), then the user should set the
+UNSIGN mode to true.  In the event that the UNSIGN mode is set, if a
+FITS file is encountered which contains integers, but which does not
+contain the UNSIGN keyword, Mana will make the default assumption that
+the data is unsigned.  If the SIGNED mode is set, Mana will assume all
+integer FITS files contain signed integers.  
+
+((( should be able to say "unsign <buffer>" to convert the status of a
+buffer to UNSIGN or to toggle the buffer's status, but not yet
+implemented)))
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/vectors
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/vectors	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/vectors	(revision 16632)
@@ -0,0 +1,5 @@
+
+   vectors
+
+   list the currently defined vectors and lengths
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/wd
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/wd	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/wd	(revision 16632)
@@ -0,0 +1,29 @@
+
+  wd (buffer) (filename) [BITPIX]
+
+  wd writes a buffer to the specified file in FITS format.  (You may
+need quotes around the filename if there are any /'s in the path).
+The FITS keyword BITPIX may be specified.  Valid values are 8, 16, 32
+(integer formats) and -32, -64 (floating point formats).  If BITPIX is
+unspecified, the original value of the image is used.  The image is
+converted blindly to the format and written out.  This may mean that
+values are rounded (integers), or wrapped by the range of the number
+of bits.  Also beware of the issue of signed vs unsigned images.
+
+  See Also: rd
+
+bitpix  bzero  bscale  file range     data range
+16      0      1       -32k : 32k     -32k : 32k
+16	32k    1       -32k : 32k        0 : 64k
+16	0      2       -32k : 32k     -64k : 64k
+16	0      0.001   -32k : 32k     -32. : 32.
+32	0      1       -2e9 : 2e9     -2e9 : 2e9
+8	0      1       -128 : 128     -128 : 128
+
+so for example, a file with a data range of -128k to +128k written
+with bitpix 16, bzero 0, bscale 1 will have all data outside -32k :
++32k wrapped back in that range.
+
+note: on write, bzero is subtracted from the data before the data is
+      divided by bscale.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/zplot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/zplot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/help/zplot	(revision 16632)
@@ -0,0 +1,7 @@
+
+   zplot x y z min max
+
+   plot the vector pair x and y as a series of points with size scaled
+   by the values in the vector z, with the smallest point having
+   values <= min and the largest having values >= max.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/histogram.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/histogram.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/histogram.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "data.h"
+
+int histogram (int argc, char **argv) {
+  
+  int i, bin, Nbins;
+  float *V, start, end, delta;
+  Vector *xvec, *yvec;
+
+  if ((argc != 6) && (argc != 5)) {
+    gprint (GP_ERR, "USAGE: hist invec outvec start end [delta]\n");
+    return (FALSE);
+  }
+
+  delta = 1;
+  start = atof (argv[3]);
+  end   = atof (argv[4]);
+  if (argc == 6) delta = atof (argv[5]);
+ 
+  if ((start == end) || (delta == 0)) {
+    gprint (GP_ERR, "error in value: %f to %f, %f\n", start, end, delta);
+    return (FALSE);
+  }
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+  Nbins = (end - start) / delta;
+  /* number here should match number in create.c */
+
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  yvec[0].Nelements = Nbins;
+    
+  REALLOCATE (yvec[0].elements, float, yvec[0].Nelements);
+  bzero (yvec[0].elements, sizeof(float)*yvec[0].Nelements);
+
+  V = xvec[0].elements;
+  for (i = 0; i < xvec[0].Nelements; i++, V++) {
+    if (isnan(*V)) continue;
+    bin = MIN (MAX (0, (*V - start) / delta), Nbins - 1);
+    yvec[0].elements[bin] += 1.0;
+  }      
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imcut.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imcut.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imcut.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "data.h"
+
+int imcut (int argc, char **argv) {
+  
+  int i, Nx, Ny, xi, yi, L;
+  double xs, ys, xe, ye, dX, dY;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+  float *V;
+
+  if (argc != 8) {
+    gprint (GP_ERR, "USAGE: cut <buffer> <X vector> <Y vector> xs ys xe ye\n");
+    return (FALSE);
+  }
+
+  if ((buf  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) goto missed;
+  if ((xvec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) goto usage;
+  if ((yvec = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) goto usage;
+ 
+  xs = atof (argv[4]);
+  ys = atof (argv[5]);
+  xe = atof (argv[6]);
+  ye = atof (argv[7]);
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  if ((xs < 0) || (xs > Nx)) goto range;
+  if ((ys < 0) || (ys > Ny)) goto range;
+  if ((xe < 0) || (xe > Nx)) goto range;
+  if ((ye < 0) || (ye > Ny)) goto range;
+
+  dX = xe - xs;
+  dY = ye - ys;
+  L = hypot (dX, dY);
+  dX = dX / L;
+  dY = dY / L;
+
+  REALLOCATE (xvec[0].elements, float, MAX (L, 1));
+  REALLOCATE (yvec[0].elements, float, MAX (L, 1));
+  xvec[0].Nelements = L;
+  yvec[0].Nelements = L;
+
+  V = (float *)buf[0].matrix.buffer;
+  for (i = 0; i < L; i++) {
+    xi = xs + i*dX - 0.5;
+    yi = ys + i*dY - 0.5;
+    xvec[0].elements[i] = i;
+    yvec[0].elements[i] = V[xi + Nx*yi];
+  }
+
+  return (TRUE);
+
+ usage: 
+  gprint (GP_ERR, "USAGE: circstats <buffer> x y radius\n");
+  return (FALSE);
+
+ range:
+  gprint (GP_ERR, "ERROR: coordinates out of range\n");
+  return (FALSE);
+
+ missed:
+  gprint (GP_ERR, "ERROR: buffer not found\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imhist.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imhist.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imhist.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include "data.h"
+
+int imhist (int argc, char **argv) {
+  
+  int i, j, N, Nbins, Quiet;
+  int sx, sy, nx, ny, bin;
+  float *V, delta;
+  double max, min, dx;
+  Vector *vec1, *vec2;
+  Buffer *buf;
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  delta = 0;
+  if ((N = get_argument (argc, argv, "-delta"))) {
+    remove_argument (N, &argc, argv);
+    delta = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  min = max = 0.0;
+  if ((N = get_argument (argc, argv, "-range"))) {
+    remove_argument (N, &argc, argv);
+    min = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    max = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  sx = sy = 0.0;
+  nx = ny = 0.0;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    sx = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    sy = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    nx = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ny = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: histogram <buffer> <x> <y> [-region sx sy nx ny] [-range min max] [-delta binsize]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  
+  /* if either range is set to zero, use the rest of the chip */
+  if (nx == 0)
+    nx = buf[0].matrix.Naxis[0] - sx;
+  if (ny == 0)
+    ny = buf[0].matrix.Naxis[1] - sy;
+
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+
+  if ((vec1 = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vec2 = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* unfortunately, we must do this in two passes:
+     first pass finds the max and min and defines the bin size
+     second pass counts the pixes in each bin 
+     */
+
+  if ((max == 0) && (min == 0)) {
+    max = min = *((float *)(buf[0].matrix.buffer) + sy*buf[0].matrix.Naxis[0] + sx);
+    gprint (GP_ERR, "sx: %d, sy: %d, first: %f\n", sx, sy, max);
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+      for (i = 0; i < nx; i++, V++) {
+	max = MAX (max, *V);
+	min = MIN (min, *V);
+      }
+    }
+  }
+
+  if (delta == 0) {
+    Nbins = 1024;
+    dx = (max - min) / Nbins;
+  } else {
+    dx = delta;
+    Nbins = (max - min) / dx;
+  }
+  if (Quiet) {
+    set_variable ("MIN", min);
+    set_variable ("MAX", max);
+    set_variable ("DX",  dx);
+  } else {
+    gprint (GP_LOG, "max %f, min %f, dx %f\n", max, min, dx);
+  }  
+
+  vec1[0].Nelements = Nbins + 1;
+  vec2[0].Nelements = Nbins + 1;
+  REALLOCATE (vec1[0].elements, float, vec1[0].Nelements);
+  bzero (vec1[0].elements, vec1[0].Nelements*sizeof(float));
+  REALLOCATE (vec2[0].elements, float, vec2[0].Nelements);
+  bzero (vec2[0].elements, vec2[0].Nelements*sizeof(float));
+  
+  for (j = sy; j < sy + ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      bin = MAX (MIN (Nbins, (*V - min) / dx), 0);
+      vec2[0].elements[bin] += 1.0;
+    }
+  }
+  for (i = 0; i < Nbins + 1; i++, V++) {
+    vec1[0].elements[i] = i*dx + min;
+  }
+  
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imsmooth.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imsmooth.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/imsmooth.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "data.h"
+
+int imsmooth (int argc, char **argv) {
+  
+  int i, j, n, N, Nx, Ny, Ns, Ngauss;
+  float *vi, *vo, *gauss, *gaussnorm;
+  float g, s, sigma, Nsigma;
+  Buffer *in;
+  float *temp;
+
+  Nsigma = 3;
+  if ((N = get_argument (argc, argv, "-Nsigma"))) {
+    remove_argument (N, &argc, argv);
+    Nsigma = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: imsmooth (input) sigma\n");
+    return (FALSE);
+  }
+  
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  sigma = atof (argv[2]);
+
+  Nx = in[0].matrix.Naxis[0];
+  Ny = in[0].matrix.Naxis[1];
+  ALLOCATE (temp, float, Nx*Ny);
+
+  /* build a 1D gaussian */
+  Ns = (int) (Nsigma*sigma + 0.5);
+  Ngauss = 2*Ns + 1;
+  ALLOCATE (gaussnorm, float, Ngauss);
+  gauss = &gaussnorm[Ns];
+  for (i = -Ns; i < Ns + 1; i++) {
+    gauss[i] = exp ((i*i)/(-2*sigma*sigma));
+  }
+
+  /* smooth in X direction */
+  for (j = 0; j < Ny; j++) {
+    vi = (float *) in[0].matrix.buffer + j*Nx;
+    vo = &temp[j*Nx];
+    for (i = 0; i < Nx; i++) {
+      g = s = 0;
+      for (n = -Ns; n < Ns + 1; n++) {
+	if (i+n < 0) continue;
+	if (i+n >= Nx) continue;
+	s += gauss[n]*vi[i+n];
+	g += gauss[n];
+      }
+      vo[i] = s / g;
+    }
+  }
+
+  /* smooth in Y direction */
+  for (i = 0; i < Nx; i++) {
+    vi = &temp[i];
+    vo = (float *)in[0].matrix.buffer + i;
+    for (j = 0; j < Ny; j++) {
+      g = s = 0;
+      for (n = -Ns; n < Ns + 1; n++) {
+	if (j+n < 0) continue;
+	if (j+n >= Ny) continue;
+	s += gauss[n]*vi[(n+j)*Nx];
+	g += gauss[n];
+      }
+      vo[j*Nx] = s / g;
+    }
+  }
+
+  free (temp);
+  free (gaussnorm);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/init.c	(revision 16632)
@@ -0,0 +1,261 @@
+# include "data.h"
+
+int accum            PROTO((int, char **));
+int applyfit         PROTO((int, char **));
+int applyfit2d       PROTO((int, char **));
+int box              PROTO((int, char **));
+int book_command     PROTO((int, char **));
+int center           PROTO((int, char **));
+int circstats        PROTO((int, char **));
+int clear            PROTO((int, char **));
+int clip             PROTO((int, char **));
+int close_device     PROTO((int, char **));
+int concat           PROTO((int, char **));
+int contour          PROTO((int, char **));
+int create           PROTO((int, char **));
+int cumulative       PROTO((int, char **));
+int cursor           PROTO((int, char **));
+int cut              PROTO((int, char **));
+int datafile         PROTO((int, char **));
+int dbconnect        PROTO((int, char **));
+int dbselect         PROTO((int, char **));
+int delete           PROTO((int, char **));
+int device           PROTO((int, char **));
+int dimendown        PROTO((int, char **));
+int dimenup          PROTO((int, char **));
+int erase            PROTO((int, char **));
+int extract          PROTO((int, char **));
+int fft1d            PROTO((int, char **));
+int fft2d            PROTO((int, char **));
+int fit2d            PROTO((int, char **));
+int fit              PROTO((int, char **));
+int gaussjordan      PROTO((int, char **));
+int gaussdeviate     PROTO((int, char **));
+int gaussintegral    PROTO((int, char **));
+int grid             PROTO((int, char **));
+int gridify          PROTO((int, char **));
+int grow             PROTO((int, char **));
+int ungridify        PROTO((int, char **));
+int histogram        PROTO((int, char **));
+int imcut            PROTO((int, char **));
+int imhist           PROTO((int, char **));
+int imsmooth         PROTO((int, char **));
+int integrate        PROTO((int, char **));
+int interpolate      PROTO((int, char **));
+int jpeg             PROTO((int, char **));
+int kern             PROTO((int, char **));
+int keyword          PROTO((int, char **));
+int labels           PROTO((int, char **));
+int limits           PROTO((int, char **));
+int line             PROTO((int, char **));
+int list_buffers     PROTO((int, char **));
+int header           PROTO((int, char **));
+int list_vectors     PROTO((int, char **));
+int load             PROTO((int, char **));
+int lookup           PROTO((int, char **));
+int mkrgb            PROTO((int, char **));
+int mcreate          PROTO((int, char **));
+int medacc           PROTO((int, char **));
+int mget             PROTO((int, char **));
+int minterp          PROTO((int, char **));
+int mset             PROTO((int, char **));
+int peak             PROTO((int, char **));
+int periodogram      PROTO((int, char **));
+int plot             PROTO((int, char **));
+int dot              PROTO((int, char **));
+int point            PROTO((int, char **));
+int ps               PROTO((int, char **));
+int queuelist        PROTO((int, char **));
+int queueload        PROTO((int, char **));
+int queueinit        PROTO((int, char **));
+int queuedelete      PROTO((int, char **));
+int queuedrop        PROTO((int, char **));
+int queuepop         PROTO((int, char **));
+int queueprint       PROTO((int, char **));
+int queuepush        PROTO((int, char **));
+int queuesize        PROTO((int, char **));
+int rd               PROTO((int, char **));
+int rdseg            PROTO((int, char **));
+int read_vectors     PROTO((int, char **));
+int rebin            PROTO((int, char **));
+int resize           PROTO((int, char **));
+int roll             PROTO((int, char **));
+int rotate           PROTO((int, char **));
+int save             PROTO((int, char **));
+int section          PROTO((int, char **));
+int set              PROTO((int, char **));
+int shift            PROTO((int, char **));
+int sort_vectors     PROTO((int, char **));
+int spline_apply_cmd PROTO((int, char **));
+int spline_construct_cmd PROTO((int, char **));
+int stats            PROTO((int, char **));
+int style            PROTO((int, char **));
+int subraster        PROTO((int, char **));
+int subset           PROTO((int, char **));
+int svd              PROTO((int, char **));
+int swapbytes        PROTO((int, char **));
+int textline         PROTO((int, char **));
+int tv               PROTO((int, char **));
+int tvchannel        PROTO((int, char **));
+int tvcolors         PROTO((int, char **));
+int tvcontour        PROTO((int, char **));
+int tvgrid           PROTO((int, char **));
+int uniq             PROTO((int, char **));
+int unsign           PROTO((int, char **));
+int vbin             PROTO((int, char **));
+int vclip            PROTO((int, char **));
+int vect_select      PROTO((int, char **));
+int vgrid            PROTO((int, char **));
+int vgauss           PROTO((int, char **));
+int vmaxwell         PROTO((int, char **));
+int vload            PROTO((int, char **));
+int vstat            PROTO((int, char **));
+int vroll            PROTO((int, char **));
+int vpop             PROTO((int, char **));
+int vsmooth          PROTO((int, char **));
+int wd               PROTO((int, char **));
+int write_vectors    PROTO((int, char **));
+int zap              PROTO((int, char **));
+int zplot            PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "accum",        accum,            "accumulate vector values in another vector"},
+  {1, "applyfit",     applyfit,         "apply fit to new vector"},
+  {1, "applyfit2d",   applyfit2d,       "apply 2-d fit to new vector"},
+  {1, "box",          box,              "draw a box on the plot"},
+  {1, "book",         book_command,     "commands to manipulate book/page/word data"},
+  {1, "center",       center,           "center image on coords"},
+  {1, "circstats",    circstats,        "circular statistics"},
+  {1, "clear",        clear,            "erase plot"},
+  {1, "clip",         clip,             "clip values in a buffer to be within a range"},
+  {1, "close",        close_device,     "close the current display device"},
+  {1, "concat",       concat,           "reduce vector dimension"},
+  {1, "contour",      contour,          "create contour from image"},
+  {1, "create",       create,           "create a new vector"},
+  {1, "cumulative",   cumulative,       "build a cumulative histogram from a specific histogram"},
+  {1, "cursor",       cursor,           "get coords from cursor"},
+  {1, "cut",          cut,              "extract a cut across an image"},
+  {1, "datafile",     datafile,         "define file to read vectors"},
+  {1, "dbconnect",    dbconnect,        "setup mysql db connection"},
+  {1, "dbselect",     dbselect,         "extract vectors from mysql database table"},
+  {1, "delete",       delete,           "delete vectors or matrices"},
+  {1, "device",       device,           "set / get current graphics device"},
+  {1, "dimendown",    dimendown,        "convert matrix to vector"},
+  {1, "dimenup",      dimenup,          "convert vector to matrix"},
+  {1, "erase",        erase,            "erase objects on an overlay"},
+  {1, "extract",      extract,          "extract a portion of a buffer into another buffer"},
+  {1, "fft1d",        fft1d,            "fft on the pixel-stream in an image"},
+  {1, "fft2d",        fft2d,            "fft on an image"},
+  {1, "fit",          fit,              "fit polynomial to vector pair"},
+  {1, "fit2d",        fit2d,            "fit 2-d polynomial to vector triplet"},
+  {1, "gaussj",       gaussjordan,      "solve Ax = B (N-D)"},
+  {1, "gaussdev",     gaussdeviate,     "generate a gaussian deviate vector"},
+  {1, "gaussint",     gaussintegral,    "return the integrated gaussian vector"},
+  {1, "grid",         grid,             "plot cartesian grid"},
+  {1, "gridify",      gridify,          "convert vector triplet to buffer"},
+  {1, "grow",         grow,             "grow a mask"},
+  {1, "ungridify",    ungridify,        "convert buffer region to vector triplet"},
+  {1, "header",       header,           "print buffer header"},
+  {1, "histogram",    histogram,        "generate histogram from vector"},
+  {1, "imcut",        imcut,            "linear image cut between arbitrary coords"},
+  {1, "imhist",       imhist,           "histogram of an image region"},
+  {1, "imsmooth",     imsmooth,         "circular gaussian smoothing"},
+  {1, "integrate",    integrate,        "integrate a vector"},
+  {1, "interpolate",  interpolate,      "interpolate between vector pairs"},
+  {1, "jpeg",         jpeg,             "write text line on graph"},
+  {1, "png",          jpeg,             "write text line on graph"},
+  {1, "ppm",          jpeg,             "write text line on graph"},
+  {1, "kern",         kern,             "convolve with 3x3 kernel"},
+  {1, "keyword",      keyword,          "extract a FITS keyword from buffer header"},
+  {1, "labels",       labels,           "define labels for plot"},
+  {1, "limits",       limits,           "define plot limits"},
+  {1, "line",         line,             "plot line"},
+  {1, "buffers",      list_buffers,     "list the currently allocated buffers"},
+  {1, "vectors",      list_vectors,     "list vectors"},
+  {1, "load",         load,             "load an SAOimage style overlay"},
+  {1, "lookup",       lookup,           "convert vector via lookup table (vector pair)"},
+  {1, "mkrgb",        mkrgb,            "convert 3 images to rgb jpeg"},
+  {1, "mcreate",      mcreate,          "create a matrix"},
+  {1, "medacc",       medacc,           "accumulate vector values in another vector"},
+  {1, "mget",         mget,             "extract a vector from a matrix"},
+  {1, "minterp",      minterp,          "interpolate image pixels"},
+  {1, "mset",         mset,             "insert a vector in a matrix"},
+  {1, "peak",         peak,             "find vector peak in range"},
+  {1, "periodogram",  periodogram,      "measure periods in unevenly sampled data"},
+  {1, "plot",         plot,             "plot a pair of vectors"},
+  {1, "dot",          dot,              "plot a single point"},
+  {1, "point",        point,            "load overlay with single point"},
+  {1, "ps",           ps,               "define labels for plot"},
+  {1, "queuepop",     queuepop,         "pop value from queue to variable"},
+  {1, "queuedrop",    queuedrop,        "drop values from queue matching a key"},
+  {1, "queueprint",   queueprint,       "print the contents of a queue"},
+  {1, "queuepush",    queuepush,        "push value onto queue"},
+  {1, "queueinit",    queueinit,        "create an empty queue"},
+  {1, "queuedelete",  queuedelete,      "delete a queue"},
+  {1, "queuelist",    queuelist,        "list defined queues"},
+  {1, "queueload",    queueload,        "load queue from command"},
+  {1, "queuesize",    queuesize,        "show queue size"},
+  {1, "rd",           rd,               "load fits image"},
+  {1, "rdseg",        rdseg,            "read a segment of an image from a file"},
+  {1, "read",         read_vectors,     "read vectors from datafile"},
+  {1, "rebin",        rebin,            "rebin data by factor of N"},
+  {1, "resize",       resize,           "set graphics/image window size"},
+  {1, "roll",         roll,             "roll image to new start point"},
+  {1, "rotate",       rotate,           "rotate image"},
+  {1, "save",         save,             "save an SAOimage style overlay"},
+  {1, "section",      section,          "define section of graph"},
+  {1, "set",          set,              "vector math"},
+  {1, "shift",        shift,            "shift data in an image"},
+  {1, "sort",         sort_vectors,     "sort list of vectors"},
+  {1, "spline.apply", spline_apply_cmd, "apply spline fit to generate an image"},
+  {1, "spline.const", spline_construct_cmd, "create spline 2nd deriv. terms"},
+  {1, "stats",        stats,            "give statistics on a portion of a buffer"},
+  {1, "style",        style,            "set the style for graph plots"},
+  {1, "subraster",    subraster,        "subraster of fits image"},
+  {1, "subset",       subset,           "expand vector dimension"},
+  {1, "svd",          svd,              "singular value decomposition of a matrix"},
+  {1, "swapbytes",    swapbytes,        "byte swap thing"},
+  {1, "textline",     textline,         "write text line on graph"},
+  {1, "tv",           tv,               "display an image on the Kii window"},
+  {1, "tvchannel",    tvchannel,        "set the current tv channel"},
+  {1, "tvcolors",     tvcolors,         "set the tv colormap"},
+  {1, "tvcontour",    tvcontour,        "send contour to overlay"},
+  {1, "tvgrid",       tvgrid,           "wait until return is typed"},
+  {1, "uniq",         uniq,             "create a uniq vector subset from a vector"},
+  {1, "unsign",       unsign,           "toggle the UNSIGN status"},
+  {1, "vbin",         vbin,             "bin values in a vector to be within a range"},
+  {1, "vclip",        vclip,            "clip values in a vector to be within a range"},
+  {1, "select",       vect_select,      "selective vector assignment"},
+  {1, "vgauss",       vgauss,           ""},
+  {1, "vmaxwell",     vmaxwell,         ""},
+  {1, "vgrid",        vgrid,            ""},
+  {1, "vload",        vload,            "load vectors on Kii"},
+  {1, "vstat",        vstat,            "get info from imreg database"},
+  {1, "vsmooth",      vsmooth,          "gaussian smooth of a vector"},
+  {1, "vroll",        vroll,            "roll vector elements"},
+  {1, "vpop",         vpop,             "remove first element"},
+  {1, "wd",           wd,               "write an image to a file"},
+  {1, "write",        write_vectors,    "write vectors to datafile"},
+  {1, "zap",          zap,              "delete pixels"},
+  {1, "zplot",        zplot,            "plot x y with size scaled by z"},
+}; 
+
+void InitData () {
+  
+  int i;
+
+  InitKapa ();
+  InitQueues ();
+  InitBooks ();
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+}
+
+void FreeData () {
+
+  FreeKapa ();
+  FreeQueues ();
+  FreeBooks ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/integrate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/integrate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/integrate.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "data.h"
+
+int integrate (int argc, char **argv) {
+  
+  int i, N, VERBOSE;
+  float *X, *Y;
+  double start, end, value, range;
+  Vector *vecx, *vecy;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: integrate <x> <y> start end\n");
+    return (FALSE);
+  }
+
+  if ((vecx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[3]);
+  end   = atof (argv[4]);
+
+  X = vecx[0].elements;
+  Y = vecy[0].elements;
+
+  value = 0;
+  range = 0;
+  for (i = 0; i < vecx[0].Nelements-1; i++, X++, Y++) {
+    if ((*X >= start) && (*X <= end)) {
+      value += *Y * (X[1] - X[0]);
+      range += (X[1] - X[0]);
+    }
+  }      
+
+  set_variable ("sum", value); 
+  set_variable ("range", range);
+  if (VERBOSE) gprint (GP_LOG, "sum: %f\n", value);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/interpolate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/interpolate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/interpolate.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "data.h"
+
+int interpolate (int argc, char **argv) {
+
+  int  i, j;
+  double x0, x1, dx, dy, y0;
+  Vector *xout, *yout, *xin, *yin;
+
+  /** check basic syntax **/
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: interpolate Xi Yi Xo Yo\n");
+    gprint (GP_ERR, "  Xi Yi - sorted reference vectors\n");
+    gprint (GP_ERR, "  Xo    - output positions\n");
+    gprint (GP_ERR, "  Yo    - output values\n");
+    return (FALSE);
+  }
+
+  if ((xin  = SelectVector (argv[1],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yin  = SelectVector (argv[2],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((xout = SelectVector (argv[3],  OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yout = SelectVector (argv[4],  ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  yout[0].Nelements = xout[0].Nelements;
+  REALLOCATE (yout[0].elements, float, yout[0].Nelements);
+
+  dx = xin[0].elements[1] - xin[0].elements[0];
+  dy = yin[0].elements[1] - yin[0].elements[0];
+  x0 = xin[0].elements[0];
+  y0 = yin[0].elements[0];
+  
+  /* in vectors are sorted, out vectors are not */
+  for (j = 0; j < xin[0].Nelements - 1; j++) {
+    dx = xin[0].elements[j+1] - xin[0].elements[j];
+    dy = yin[0].elements[j+1] - yin[0].elements[j];
+    x0 = xin[0].elements[j];
+    y0 = yin[0].elements[j];
+    x1 = xin[0].elements[j+1];
+    for (i = 0; i < xout[0].Nelements; i++) {
+      if ((xout[0].elements[i] >= x0) && (xout[0].elements[i] < x1)) {
+	yout[0].elements[i] = (dy/dx)*(xout[0].elements[i] - x0) + y0;
+      }
+      if ((j == 0) && (xout[0].elements[i] < x0)) {
+	yout[0].elements[i] = (dy/dx)*(xout[0].elements[i] - x0) + y0;
+      }
+      if ((j == xin[0].Nelements - 2) && (xout[0].elements[i] >= x1)) {
+	yout[0].elements[i] = (dy/dx)*(xout[0].elements[i] - x0) + y0;
+      }
+    }    
+  }
+
+  return (TRUE);
+    
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/jpeg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/jpeg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/jpeg.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include "data.h"
+
+int jpeg (int argc, char **argv) {
+
+  char filename[1024];
+  int N, kapa, IsPNG, IsPPM;
+  char *name;
+  
+  if ((N = get_argument (argc, argv, "--help"))) {
+    gprint (GP_ERR, "USAGE: jpeg [-name file] [-g | -i] [-n device] [-ppm]\n");
+    return (FALSE);
+  }
+
+  /* image type */
+  IsPPM = IsPNG = FALSE;
+  if ((N = get_argument (argc, argv, "-ppm"))) {
+    remove_argument (N, &argc, argv);
+    IsPPM = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-png"))) {
+    remove_argument (N, &argc, argv);
+    IsPNG = TRUE;
+  }
+  if (!strcmp (argv[0], "png")) IsPNG = TRUE;
+  if (!strcmp (argv[0], "ppm")) IsPPM = TRUE;
+
+  /* file name */
+  filename[0] = 0;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (filename, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* display source */
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* XXX output png / jpeg needs to include both graph and image
+     if available.  this is a poor mix of data representations 
+     (png for image / jpeg for plots)
+  if ((N = get_argument (argc, argv, "-g"))) {
+  if ((N = get_argument (argc, argv, "-i"))) {
+  */
+
+  if (!GetGraph (NULL, &kapa, name)) return (FALSE);
+  if (!IsPNG && !IsPPM) {
+    if (!filename[0]) strcpy (filename, "kapa.jpg");
+    KiiJPEG (kapa, filename);
+  }
+  if (IsPNG) {
+    if (!filename[0]) strcpy (filename, "kapa.png");
+    KapaPNG (kapa, filename);
+  } 
+  if (IsPPM) {
+    if (!filename[0]) strcpy (filename, "kapa.ppm");
+    KapaPPM (kapa, filename);
+  }
+  return (TRUE);
+}
+
+/* jpeg converts graph to png or ppm
+   jpeg converts image to jpeg */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/kern.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/kern.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/kern.c	(revision 16632)
@@ -0,0 +1,123 @@
+# include "data.h"
+
+/** need to allow larger kernels (5x5, 7x7, etc) **/
+int kern (int argc, char **argv) {
+
+  int i, n, m;
+  int NX, NY, status;
+  FILE *f;
+  float *in_buff, *out_buff, *ib, *ob;
+  char line[256], *list;
+  double kernel[3][3], val;
+  Buffer *buf;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: kern buffer (file)\n");
+    gprint (GP_ERR, "USAGE: kern buffer (list)\n");
+    gprint (GP_ERR, "USAGE: kern buffer -\n");
+    gprint (GP_ERR, "kernel file contains a 3x3 matrix for convolution\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  /* open file to read in kernel */
+  if (!strcmp (argv[2], "-")) {
+    for (i = 0; i < 3; i++) {
+      status = scan_line (stdin, line);
+      if (status == EOF) {
+	gprint (GP_ERR, "kernel should be a 3x3 matrix...\n");
+	return (FALSE);
+      }
+      dparse (&kernel[0][i], 1, line);
+      dparse (&kernel[1][i], 2, line);
+      dparse (&kernel[2][i], 3, line);
+    }
+    goto have_kernel;
+  }
+  /* test list */
+  sprintf (line, "%s:n", argv[2]);
+  if ((list = get_variable (line)) == (char *) NULL) {
+    /* file */
+    f = fopen (argv[2], "r");
+    if (f == NULL) {
+      gprint (GP_ERR, "file not found: %s\n", argv[2]);
+      return (FALSE);
+    }
+    for (i = 0; i < 3; i++) {
+      status = scan_line (f, line);
+      if (status == EOF) {
+	gprint (GP_ERR, "kernel should be a 3x3 matrix...\n");
+	fclose (f);
+      }
+      return (FALSE);
+      dparse (&kernel[0][i], 1, line);
+      dparse (&kernel[1][i], 2, line);
+      dparse (&kernel[2][i], 3, line);
+    }
+    fclose (f);
+    goto have_kernel;
+  }
+  if (atoi (list) != 9) {
+    gprint (GP_ERR, "kernel should be a 3x3 matrix...\n");
+    return (FALSE);
+  }
+  free (list);
+  for (i = 0; i < 9; i++) {
+    sprintf (line, "%s:%d", argv[2], i);
+    list = get_variable (line);
+    if (list == (char *) NULL) {
+      gprint (GP_ERR, "kernel should be a 3x3 matrix...\n");
+      return (FALSE);
+    }
+    kernel[(int)(i/3)][i%3] = atof (list);
+    free (list);
+  }
+  goto have_kernel;
+
+ have_kernel:
+  /* normalize kernel */
+  val = 0;
+  for (n = 0; n < 3; n++) {
+    for (m = 0; m < 3; m++) {
+      val += kernel[n][m];
+    }
+  }
+  if (val == 0) {
+    gprint (GP_ERR, "kernel has zero power, not renormalizing...");
+  } else {
+    for (n = 0; n < 3; n++) {
+      for (m = 0; m < 3; m++) {
+	kernel[n][m] /= val;
+      }
+    }
+  }
+
+  gprint (GP_ERR, "working...");
+  
+  /* create output buffer */
+  NX = buf[0].header.Naxis[0];
+  NY = buf[0].header.Naxis[1];
+  in_buff = (float *)buf[0].matrix.buffer;
+  ALLOCATE (buf[0].matrix.buffer, char, sizeof(float)*NX*NY);
+  out_buff = (float *)buf[0].matrix.buffer;
+  
+  /* do the convolution (on all but outer rows) */
+  
+  for (n = 0; n < 3; n++) {
+    for (m = 0; m < 3; m++) {
+      gprint (GP_ERR, "%d", n*3 + m + 1);
+      val = kernel[n][m];
+      ob = out_buff + NX + 1;
+      ib = in_buff + m*NX + n;
+      for (i = 0; i < (NX-2)*(NY-2); i++, ob++, ib++) {
+	*ob += *ib*val;
+      }
+    }
+  }
+  gprint (GP_ERR, "(done)\n");
+
+  free (in_buff);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/keyword.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/keyword.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/keyword.c	(revision 16632)
@@ -0,0 +1,158 @@
+# include "data.h"
+
+enum {NONE, STRING, FLOAT, INT, BOOLEAN, KEYCOMMENT, COMMENT};
+
+/** WARNING: no error checking on variable validity **/
+int keyword (int argc, char **argv) {
+
+  int ivalue, status, N, ascomment, asfloat, delete, soft, Wmode;
+  char line[80];
+  double value;
+  Buffer *buf;
+
+  asfloat = FALSE;
+  if ((N = get_argument (argc, argv, "-f"))) {
+    remove_argument (N, &argc, argv);
+    asfloat = TRUE;
+  }
+  
+  ascomment = FALSE;
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    ascomment = TRUE;
+  }
+  
+  delete = FALSE;
+  if ((N = get_argument (argc, argv, "-d"))) {
+    remove_argument (N, &argc, argv);
+    delete = TRUE;
+  }
+  
+  /* return TRUE for missing keyword if soft */
+  soft = FALSE;
+  if ((N = get_argument (argc, argv, "-soft"))) {
+    remove_argument (N, &argc, argv);
+    soft = TRUE;
+  }
+  
+  /* identify write modes */
+  Wmode = NONE;
+  if ((N = get_argument (argc, argv, "-w"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = STRING;
+  }
+  if ((N = get_argument (argc, argv, "-wf"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = FLOAT;
+  }
+  if ((N = get_argument (argc, argv, "-wd"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = INT;
+  }
+  if ((N = get_argument (argc, argv, "-wc"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = KEYCOMMENT;
+  }
+  if ((N = get_argument (argc, argv, "-ws"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = COMMENT;
+  }
+  if ((N = get_argument (argc, argv, "-wb"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (line, argv[N]);
+    remove_argument (N, &argc, argv);
+    Wmode = BOOLEAN;
+  }
+
+  if (!((argc == 3) || (!N && argc == 4))) {
+    gprint (GP_ERR, "USAGE: keyword <buffer> (KEYWORD) [variable] [-d] [-w(mode) value]\n");
+    gprint (GP_ERR, " -w modes: \n");
+    gprint (GP_ERR, "  -w  - string\n");
+    gprint (GP_ERR, "  -wf - float\n");
+    gprint (GP_ERR, "  -wd - int\n");
+    gprint (GP_ERR, "  -wb - boolean\n");
+    gprint (GP_ERR, "  -wc - comment\n");
+    gprint (GP_ERR, "  -ws - full string comment\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (Wmode != NONE) {
+    switch (Wmode) {
+    case STRING:
+      gfits_modify (&buf[0].header, argv[2], "%s", 1, line);
+      return (TRUE);
+    case FLOAT:
+      value = atof(line);
+      gfits_modify (&buf[0].header, argv[2], "%lf", 1, value);
+      return (TRUE);
+    case INT:
+      gfits_modify (&buf[0].header, argv[2], "%d", 1, atoi(line));
+      return (TRUE);
+    case BOOLEAN:
+      if (strcasecmp (line, "T") && strcasecmp (line, "TRUE") && strcasecmp (line, "F") && strcasecmp (line, "FALSE")) {
+	gprint (GP_ERR, "syntax error in boolean value\n");
+	return (FALSE);
+      }
+      ivalue = !strcasecmp (line, "T");
+      gfits_modify (&buf[0].header, argv[2], "%t", 1, ivalue);
+      return (TRUE);
+    case KEYCOMMENT:
+      gfits_modify (&buf[0].header, argv[2], "%C", 1, line);
+      return (TRUE);
+    case COMMENT:
+      gfits_modify (&buf[0].header, argv[2], "%S", 0, line);
+      return (TRUE);
+    }
+  }
+  
+  if (delete) {
+    gfits_delete (&buf[0].header, argv[2], -1);
+    return (TRUE);
+  }
+  
+  /* grab the value in the given format, either a string or a digit */
+  if (asfloat) {
+    status = gfits_scan (&buf[0].header, argv[2], "%lf", 1, &value);
+    if (!status) goto failure;
+    if (argc == 4) 
+      set_variable (argv[3], value);
+    else 
+      gprint (GP_LOG, "%s: %f\n", argv[2], value);
+    return (TRUE);
+  } 
+
+  if (ascomment) {
+    status = gfits_scan (&buf[0].header, argv[2], "%C", 1, line);
+    if (!status) goto failure;
+    if (argc == 4) 
+      set_str_variable (argv[3], line);
+    else 
+      gprint (GP_LOG, "%s: %s\n", argv[2], line);
+    return (TRUE);
+  }    
+
+  /* not-specified */
+  status = gfits_scan (&buf[0].header, argv[2], "%s", 1, line);
+  if (!status) goto failure;
+  if (argc == 4) 
+    set_str_variable (argv[3], line);
+  else 
+    gprint (GP_LOG, "%s: %s\n", argv[2], line);
+  return (TRUE);
+
+ failure: 
+  if (!soft) gprint (GP_ERR, "keyword %s not found\n", argv[2]);
+  return (soft);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/labels.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/labels.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/labels.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include "data.h"
+
+int labels (int argc, char **argv) {
+  
+  char name[64];
+  int N, size, kapa;
+
+  if (!GetGraph (NULL, &kapa, NULL)) return (FALSE);
+
+  if (get_argument (argc, argv, "-h")) {
+    gprint (GP_ERR, "label options: \n");
+    gprint (GP_ERR, " -x : bottom-center\n");
+    gprint (GP_ERR, " +x : top-center\n");
+    gprint (GP_ERR, " -y : right-side\n");
+    gprint (GP_ERR, " +y : left-side\n\n");
+
+    gprint (GP_ERR, " -ul : upper-left corner\n");
+    gprint (GP_ERR, " -ll : lower-left corner\n");
+    gprint (GP_ERR, " -ur : upper-right corner\n");
+    gprint (GP_ERR, " -lr : lower-right corner\n\n");
+
+    gprint (GP_ERR, " -fn (font) (size) : set font and size\n");
+    gprint (GP_ERR, "   (font) : courier, helvetica, times, symbol\n\n");
+    gprint (GP_ERR, " label special characters:\n");
+    gprint (GP_ERR, " ^ : superscript\n");
+    gprint (GP_ERR, " _ : subscript\n");
+    gprint (GP_ERR, " | : default script \n");
+    gprint (GP_ERR, " &c, &h, &t, &s : set font\n\n");
+    return (FALSE);
+  }
+
+  if ((N = get_argument (argc, argv, "-fn"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (name, argv[N]);
+    remove_argument (N, &argc, argv);
+    size = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    KapaSetFont (kapa, name, size);
+  } 
+
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 0);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-y"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 1);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "+x"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 2);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "+y"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 3);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-ul"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 4);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-ur"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 5);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-ll"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 6);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((N = get_argument (argc, argv, "-lr"))) {
+    remove_argument (N, &argc, argv);
+    KapaSendLabel (kapa, argv[N], 7);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: labels [-x] [-y] [+x] [+y] [-ul] [-ur] [-ll] [-lr]\n");
+    return (FALSE);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/limits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/limits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/limits.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "data.h"
+
+int limits (int argc, char **argv) {
+
+  int N, APPLY;
+  int kapa;
+  char *name;
+  Graphdata graphmode;
+  Vector *xvec, *yvec;
+
+  xvec = yvec = NULL;
+
+  APPLY = FALSE;
+  if ((N = get_argument (argc, argv, "-a"))) {
+    remove_argument (N, &argc, argv);
+    APPLY = TRUE;
+  }
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if (argc == 1) {
+    gprint (GP_ERR, "limits: %f %f %f %f [-a] [-n device]\n",
+	     graphmode.xmin, graphmode.xmax,
+	     graphmode.ymin, graphmode.ymax);
+    goto success;
+  }
+
+  if (argc == 3) { /* expect to see: limits x y */
+    if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+    goto success;
+  }
+    
+  if (argc == 4) { /* expect to see: limits x num num or limits num num y */
+    if (ISNUM(argv[1][0]) && ISNUM(argv[2][0])) {
+      if ((yvec = SelectVector (argv[3], OLDVECTOR, FALSE)) == NULL) goto error;
+      graphmode.xmin = atof (argv[1]);
+      graphmode.xmax = atof (argv[2]);
+      goto success;
+    }
+    if (ISNUM(argv[2][0]) && ISNUM(argv[3][0])) {
+      if ((xvec = SelectVector (argv[1], OLDVECTOR, FALSE)) == NULL) goto error;
+      graphmode.ymin = atof (argv[2]);
+      graphmode.ymax = atof (argv[3]);
+      goto success;
+    }
+    goto error;
+  }
+  
+  if (argc == 5) {
+    graphmode.xmin = atof (argv[1]);
+    graphmode.xmax = atof (argv[2]);
+    graphmode.ymin = atof (argv[3]);
+    graphmode.ymax = atof (argv[4]);
+    goto success;
+  }
+
+  gprint (GP_ERR, "USAGE: limits [xrange] [yrange]\n");
+  gprint (GP_ERR, " [range] may be either [min max] or a vector\n");
+  return (FALSE);
+
+ error:
+  gprint (GP_ERR, "error in vectors\n");
+  return (FALSE);
+
+ success:
+  SetLimits (xvec, yvec, &graphmode);
+  if (APPLY) KapaSetLimits (kapa, &graphmode);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/line.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/line.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/line.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "data.h"
+
+int line (int argc, char **argv) {
+  
+  int kapa;
+  Graphdata graphmode;
+  float x[2], y[2];
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: line <x> <y> to <x> <y>\n");
+    return (FALSE);
+  }
+  x[0] = atof(argv[1]);
+  y[0] = atof(argv[2]);
+  x[1] = atof(argv[4]);
+  y[1] = atof(argv[5]);
+
+  /* set point style and errorbar mode (these are NOT sticky) */
+  graphmode.style = 0;
+  graphmode.etype = 0;
+
+  if (!KapaPrepPlot (kapa, 2, &graphmode)) return (FALSE);
+  KapaPlotVector (kapa, 2, x, "x");
+  KapaPlotVector (kapa, 2, y, "y");
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_buffers.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_buffers.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_buffers.c	(revision 16632)
@@ -0,0 +1,10 @@
+# include "data.h"
+
+int list_buffers (int argc, char **argv) {
+
+  if (argc == 3) PrintBuffers (TRUE);
+  else PrintBuffers (FALSE);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_header.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_header.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_header.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "data.h"
+
+int header (int argc, char **argv) {
+  
+  int j, N, nlines, nbytes, Nbytes, LOADHEAD, status, bitpix, unsign;
+  char *p, filename[128];
+  FILE *f;
+  double bscale, bzero;
+  Buffer *buf;
+
+  LOADHEAD = FALSE;
+  if ((N = get_argument (argc, argv, "-w"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (filename, argv[N]);
+    remove_argument (N, &argc, argv);
+    LOADHEAD = TRUE;
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: header <buffer> [-w filename]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (LOADHEAD) {
+    f = fopen (filename, "r");
+    if (f == (FILE *) NULL) {
+      gprint (GP_ERR, "file %s not found\n", filename);
+      return (FALSE);
+    }
+    fclose (f);
+    
+    bitpix = buf[0].header.bitpix;
+    bzero  = buf[0].header.bzero;
+    bscale = buf[0].header.bscale;
+    unsign = buf[0].header.unsign;
+    gfits_free_header (&buf[0].header);
+    
+    strcpy (filename, buf[0].file);
+    strcpy (buf[0].file, "*");
+    strcat (buf[0].file, filename);
+    status = gfits_read_header (argv[2], &buf[0].header);
+    buf[0].header.bitpix = bitpix;     
+    buf[0].header.bzero  = bzero;      
+    buf[0].header.bscale = bscale;     
+    buf[0].header.unsign = unsign;     
+    gfits_modify (&buf[0].header, "BITPIX", "%d",  1, bitpix);
+    gfits_modify (&buf[0].header, "BSCALE", "%lf", 1, bscale);
+    gfits_modify (&buf[0].header, "BZERO",  "%lf", 1, bzero);
+    gfits_modify (&buf[0].header, "UNSIGN", "%t",  1, unsign);
+    
+  } else {
+
+    f = popen ("more", "w");
+    
+    p = gfits_header_field (&buf[0].header, "END", 1);
+    nlines = (p - buf[0].header.buffer) / 80;
+    nbytes = 81*nlines;
+
+    /* duplicate the header, add in the <return> chars, send to more */
+    ALLOCATE (p, char, nbytes);
+    for (j = 0; j < nlines; j++) {
+      memcpy (&p[81*j], &buf[0].header.buffer[80*j], 80);
+      p[81*j+80] = 10;
+    }
+    Nbytes = fwrite (p, sizeof(char), nbytes, f);
+    if (Nbytes != nbytes) {
+      gprint (GP_ERR, "warning: not all printed...\n");
+    }
+    free (p);
+
+    pclose (f);
+
+  }
+
+  return (TRUE);
+
+}
+
+/* XXX this function is not written in the context of the output file/buffer */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_vectors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_vectors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/list_vectors.c	(revision 16632)
@@ -0,0 +1,8 @@
+# include "data.h"
+
+int list_vectors (int argc, char **argv) {
+
+  ListVectors ();
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/load.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/load.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/load.c	(revision 16632)
@@ -0,0 +1,144 @@
+# include "data.h"
+
+int load (int argc, char **argv) {
+  
+  int i, N, n, ISCEL;
+  int kapa, Noverlay, NOVERLAY;
+  char *c, type[10], string[128], line[1024];
+  double x, y, dx, dy, x1, y1;
+  double dra, ddec, ra1, dec1, ra, dec;
+  FILE *f;
+  char *buffer, *name;
+  Coords coords;
+  Buffer *buf;
+  KiiOverlay *overlay;
+  KapaImageData data;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImageData (&data, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  ISCEL = FALSE;
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    ISCEL = TRUE;
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: load (overlay) <filename>\n [-c] [-n]");
+    gprint (GP_ERR, "  -c: read overlay in celestial coords\n");
+    return (FALSE);
+  }
+  
+  if (!strcmp (argv[2], "-")) {
+    f = stdin;
+  } else {
+    f = fopen (argv[2], "r");
+  }
+  if (f == NULL) {
+    gprint (GP_ERR, "can't find file %s\n", argv[2]);
+    return (FALSE);
+  }
+
+  if (ISCEL) {
+    if ((buf = SelectBuffer (data.name, OLDBUFFER, TRUE)) == NULL) return (FALSE);
+    GetCoords (&coords, &buf[0].header);
+  }
+
+  Noverlay = 0;
+  NOVERLAY = 1000;
+  ALLOCATE (overlay, KiiOverlay, NOVERLAY);
+
+  ALLOCATE (buffer, char, 65536);  /* space for 512 lines of 128 bytes */
+  bzero (buffer, 65536);
+
+  dx = dy = 0;
+  for (n = 0; scan_line (f, line) != EOF;) {
+    c = strchr (line, '#');
+    if (c != (char *) NULL) 
+      *c = 0;  /* force end of line at comment! */
+    while ((c = strchr (line, '(')) != (char *) NULL) 
+      *c = ' ';
+    while ((c = strchr (line, ')')) != (char *) NULL) 
+      *c = ' ';
+    while ((c = strchr (line, ',')) != (char *) NULL) 
+      *c = ' ';
+    /* we could use some syntactial checks here */
+    /* have to get all three for this to be any valid object, if the line is commented out,
+     we should get none, so check that N == 3 before continuing: */
+    N = sscanf (line, "%s %lf %lf %lf %lf", type, &ra, &dec, &dra, &ddec);
+    switch (N) {
+    case 0:
+    case -1:
+      continue;
+    case 1:
+    case 2:
+    case 3:
+      if (strcmp (type, "TEXT")) {
+	gprint (GP_ERR, "syntax error in line:\n   %s\n", line);
+	continue;
+      }
+      sscanf (line, "%s %lf %lf %127s", type, &ra, &dec, string);
+    case 4:
+      ddec = dra;
+    case 5:
+      x = ra;
+      y = dec;
+      dx = dra;
+      dy = ddec;
+      if (ISCEL) {
+	if (!strcmp (type, "LINE")) {
+	  RD_to_XY (&x, &y, ra, dec, &coords);
+	  ra1 = ra + dra;
+	  dec1 = dec + ddec;
+	  RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+	  dy = (y1 - y);
+	  dx = (x1 - x);
+	} else {
+	  RD_to_XY (&x, &y, ra, dec, &coords);
+	  ra1 = ra;
+	  dec1 = dec + ddec;
+	  RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+	  dy = (fabs(x1 - x) + fabs(y1 - y));
+	  ra1 = ra + dra/cos(dec*RAD_DEG);;
+	  dec1 = dec;
+	  RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+	  dx = (fabs(x1 - x) + fabs(y1 - y));
+	}
+      }
+    }
+    overlay[Noverlay].type = KiiOverlayTypeByName (type);
+    if (overlay[Noverlay].type == KII_OVERLAY_TEXT) {
+      overlay[Noverlay].text = strcreate (string);
+    } else {
+      overlay[Noverlay].text = NULL;
+    }
+    overlay[Noverlay].x = x;
+    overlay[Noverlay].y = y;
+    overlay[Noverlay].dx = dx;
+    overlay[Noverlay].dy = dy;
+    Noverlay++;
+    CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000);
+  }
+
+  KiiLoadOverlay (kapa, overlay, Noverlay, argv[1]);
+
+  for (i = 0; i < Noverlay; i++) {
+    if (overlay[i].text == NULL) continue;
+    free (overlay[i].text);
+  }
+  free (overlay);
+
+  gprint (GP_ERR, "loaded %d objects\n", Noverlay);
+
+  if (f != stdin) {
+    fclose (f);
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/lookup.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/lookup.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/lookup.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "data.h"
+
+int lookup (int argc, char **argv) {
+  
+  int i, j;
+  float *ip, *op, *xp, *yp;
+  Vector *in, *out, *xv, *yv;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: lookup (input) (output) (x) (y)\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((xv  = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yv  = SelectVector (argv[4], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (xv[0].Nelements != yv[0].Nelements) {
+      gprint (GP_ERR, "unmatched lookup table lengths\n");
+      return (FALSE);
+  }
+
+  out[0].Nelements = in[0].Nelements;
+  REALLOCATE (out[0].elements, float, out[0].Nelements);
+
+  ip = in[0].elements;
+  op = out[0].elements;
+
+  for (i = 0; i < in[0].Nelements; i++, ip++, op++) {
+    // re-write this using bisection
+    xp = xv[0].elements;
+    yp = yv[0].elements;
+
+    for (j = 0; (*ip < *xp) && (j < yv[0].Nelements); j++);
+    *op = j;
+  }      
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mcreate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mcreate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mcreate.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "data.h"
+
+int mcreate (int argc, char **argv) {
+  
+  int Nx, Ny;
+  Buffer *buf;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: mcreate <buffer> Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  Nx = atof (argv[2]);
+  Ny = atof (argv[3]);
+
+  /* I should encapsulate this in a create_default_buffer */
+  gfits_free_matrix (&buf[0].matrix);
+  gfits_free_header (&buf[0].header);
+  CreateBuffer (buf, Nx, Ny, -32, 1.0, 0.0);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/medacc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/medacc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/medacc.c	(revision 16632)
@@ -0,0 +1,83 @@
+# include "data.h"
+
+int medacc (int argc, char **argv) {
+  
+  int i, j, Nbins, Nvalues, N, N0, N1;
+  double start, end, delta, k0, k1, fn;
+  float *V, *K, *V1, *K1, *O, *tmpvec, *tmpkey;
+  Vector *val, *key, *out;
+
+  if ((argc != 6) && (argc != 7)) {
+    gprint (GP_ERR, "USAGE: medacc <value> <vector> <key> start end [delta]\n");
+    return (FALSE);
+  }
+
+  if ((val = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((key = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (val[0].Nelements != key[0].Nelements) {
+    gprint (GP_ERR, "key and value don't match\n");
+    return (FALSE);
+  }
+  if ((out = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  start = atof (argv[4]);
+  end   = atof (argv[5]);
+  if (argc == 7) 
+    delta = atof (argv[6]);
+  else 
+    delta = 1;
+
+  delta = fabs (delta);
+  if (end - start < 0) {
+    delta = -1.0 * delta;
+  }
+  Nbins = 1 + (int)((end - start) / delta);
+
+  out[0].Nelements = Nbins;
+  REALLOCATE (out[0].elements, float, out[0].Nelements);
+  bzero (out[0].elements, sizeof(float)*out[0].Nelements);
+
+  /* copy vec and key to temp vectors */
+  ALLOCATE (tmpvec, float, val[0].Nelements);
+  ALLOCATE (tmpkey, float, val[0].Nelements);
+
+  V = val[0].elements;
+  K = key[0].elements;
+  V1 = tmpvec;
+  K1 = tmpkey;
+  Nvalues = val[0].Nelements;
+  for (i = 0; i < Nvalues; i++, V++, K++, V1++, K1++) {
+    *V1 = *V;
+    *K1 = *K;
+  }      
+
+  /* sort vec and key by key */
+  fsortpair (tmpkey, tmpvec, Nvalues);
+
+  O = out[0].elements;
+  /* find the start and end key for each range */
+  N0 = 0;
+  N1 = 0;
+  for (i = 0; i < Nbins; i++) {
+    k0 = i*delta + start;
+    k1 = (i+1)*delta + start;
+    for (j = N1; (j < Nvalues) && (tmpkey[j] < k0); j++);
+    N0 = j;
+    for (j = N0; (j < Nvalues) && (tmpkey[j] < k1); j++);
+    N1 = j;
+    N = N1 - N0;
+    fsort (&tmpvec[N0], N);
+    fn = O[i] = 0;
+    for (j = N0 + 0.25*N; j < N0 + 0.75*N; j++) {
+      O[i] += tmpvec[j];
+      fn += 1.0;
+    }
+    if (fn > 0) O[i] /= fn;
+  }      
+  
+  free (tmpvec);
+  free (tmpkey);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mget.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mget.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mget.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "data.h"
+
+int mget (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix, xdir, Nset;
+  float *in, *out;
+  Buffer *buf;
+  Vector *vec;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: mget <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (strcasecmp (argv[3], "-x") && strcasecmp (argv[3], "-y")) {
+    gprint (GP_ERR, "USAGE: mget <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+  xdir = TRUE;
+  if (!strcasecmp (argv[3], "-y")) xdir = FALSE;
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+  Nset = atof (argv[4]);
+  if (Nset < 0) {
+    gprint (GP_ERR, "selection out of range\n");
+    return (FALSE);
+  }
+
+  if (xdir) {
+    vec[0].Nelements = Npix = Nx;
+    REALLOCATE (vec[0].elements, float, Npix);
+    if (Nset >= Ny) {
+      gprint (GP_ERR, "row out of range\n");
+      return (FALSE);
+    }
+    in  = (float *) buf[0].matrix.buffer + Nx*Nset;
+    out = vec[0].elements;
+    for (i = 0; i < Npix; i++, in++, out++) {
+      *out = *in;
+    }
+    return (TRUE);
+  } else {
+    vec[0].Nelements = Npix = Ny;
+    REALLOCATE (vec[0].elements, float, Npix);
+    if (Nset >= Nx) {
+      gprint (GP_ERR, "column out of range\n");
+      return (FALSE);
+    }
+    in  = (float *) buf[0].matrix.buffer + Nset;
+    out = vec[0].elements;
+    for (i = 0; i < Npix; i++, in+=Nx, out++) {
+      *out = *in;
+    }
+    return (TRUE);
+  }    
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/minterpolate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/minterpolate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/minterpolate.c	(revision 16632)
@@ -0,0 +1,159 @@
+# include "data.h"
+
+int minterp (int argc, char **argv) {
+  
+  int i, j, status, nx, ny, Nx, Ny, N, Extrapolate;
+  int ic, jc, dx, dy, Npix;
+  char temp[1024];
+  double scale, scale2, dX, dY;
+  float *V00, *V01, *V10, *V11, *Vout, dV1, dV2, dV3;
+  float *buf, I, J, x, y, xs, xe, ys, ye;
+  Buffer *in, *out;
+
+  /* choose the appropriate graphing window */
+  Extrapolate = FALSE;
+  if ((N = get_argument (argc, argv, "-extrapolate"))) {
+    remove_argument (N, &argc, argv);
+    Extrapolate = TRUE;
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: minterpolate <from> <to> scale [-extrapolate]\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  gfits_free_matrix (&out[0].matrix);
+  gfits_free_header (&out[0].header);
+
+  scale  = atof (argv[3]);
+  scale2 = scale*scale;
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  nx = Nx * scale;
+  ny = Ny * scale;
+
+  /* create new matrix */
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  gfits_copy_header (&in[0].header, &out[0].header);
+
+  gfits_modify (&out[0].header, "NAXIS1", "%d", 1, nx);
+  gfits_modify (&out[0].header, "NAXIS2", "%d", 1, ny);
+  out[0].header.Naxis[0] = nx;
+  out[0].header.Naxis[1] = ny;
+  gfits_create_matrix (&out[0].header, &out[0].matrix);
+
+  /* fix astrometric terms */
+  status =  gfits_scan (&out[0].header, "CDELT1", "%lf", 1, &dX);
+  status &= gfits_scan (&out[0].header, "CDELT2", "%lf", 1, &dY);
+  dX /= scale;
+  dY /= scale;
+  if (status) {
+    gfits_modify (&out[0].header, "CDELT1", "%lf", 1, dX);
+    gfits_modify (&out[0].header, "CDELT2", "%lf", 1, dY);
+  }
+  status =  gfits_scan (&out[0].header, "CRPIX1", "%lf", 1, &dX);
+  status &= gfits_scan (&out[0].header, "CRPIX2", "%lf", 1, &dY);
+  dX *= scale;
+  dY *= scale;
+  if (status) {
+    gfits_modify (&out[0].header, "CRPIX1", "%lf", 1, dX);
+    gfits_modify (&out[0].header, "CRPIX2", "%lf", 1, dY);
+  }
+
+  /* adjust filename */
+  temp[0] = 0;
+  if ((in[0].file[0] != '*') && (in[0].file[0] != '(')) {
+    strcpy (temp, "*");
+  }
+  strcat (temp, in[0].file);
+  strcpy (out[0].file, temp);
+
+  dX = dY = scale;
+
+  buf = (float *)in[0].matrix.buffer;
+  Npix = 0;
+
+  if (Extrapolate) {
+    for (j = 0; j < Ny - 1; j++) {
+      for (i = 0; i < Nx - 1; i++) {
+	V00 = buf + i + j*Nx;
+	V10 = V00 + 1;
+	V01 = V00 + Nx;
+	V11 = V01 + 1;
+	dV1 = (*V11 + *V00 - *V01 - *V10) / scale2;
+	dV2 = (*V01 - *V00) / scale;
+	dV3 = (*V10 - *V00) / scale;
+
+	x = (i + 0.5) * scale;
+	y = (j + 0.5) * scale;
+
+	xs = ys = 0;
+	xe = ye = scale;
+
+	if (i == 0)      { xs = -0.5*scale; }
+	if (i == Nx - 2) { xe =  1.5*scale; }
+
+	if (j == 0)      { ys = -0.5*scale; }
+	if (j == Ny - 2) { ye =  1.5*scale; }
+
+	for (J = ys; J < ye; J += 1.0) {
+	  dx = (x + xs);
+	  dy = (y + J);
+	  Vout = (float *)(out[0].matrix.buffer) + dy*nx + dx;
+	  for (I = xs; I < xe; I += 1.0, Vout++) {
+	    *Vout = dV1 * (I*J) + dV2 * J + dV3 * I + *V00;
+	    Npix ++;
+	  }
+	}
+      }
+    }
+  } else {
+     for (j = -1; j < Ny; j++) {
+      for (i = -1; i < Nx; i++) {
+	ic = MIN (MAX (i, 0), Nx-1);  /* we never actually reach Nx, Ny */
+	jc = MIN (MAX (j, 0), Ny-1);
+	V00 = buf + ic + jc*Nx;
+	V10 = V00 + 1;
+	V01 = V00 + Nx;
+	V11 = V01 + 1;
+
+	if ((i == -1) || (i == Nx - 1)) { V10 = V00; } else { V10 = V00 + 1; }
+	if ((j == -1) || (j == Ny - 1)) { V01 = V00; } else { V01 = V00 + Nx; }
+	if ((i == -1) || (i == Nx - 1)) { V11 = V01; } else { V11 = V01 + 1; }
+
+	dV1 = (*V11 + *V00 - *V01 - *V10) / scale2;
+	dV2 = (*V01 - *V00) / scale;
+	dV3 = (*V10 - *V00) / scale;
+
+	x = (i + 0.5) * scale;
+	y = (j + 0.5) * scale;
+
+	xs = ys = 0;
+	xe = ye = scale;
+
+	if (i == -1)     { xs = 0.5*scale; }
+	if (i == Nx - 1) { xe = 0.5*scale; }
+
+	if (j == -1)     { ys = 0.5*scale; }
+	if (j == Ny - 1) { ye = 0.5*scale; }
+
+	for (J = ys; J < ye; J += 1.0) {
+	  dx = (x + xs);
+	  dy = (y + J);
+	  Vout = (float *)(out[0].matrix.buffer) + dy*nx + dx;
+	  for (I = xs; I < xe; I += 1.0, Vout++) {
+	    *Vout = dV1 * (I*J) + dV2 * J + dV3 * I + *V00;
+	    Npix ++;
+	  }
+	}
+      }
+    }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mkrgb.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mkrgb.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mkrgb.c	(revision 16632)
@@ -0,0 +1,78 @@
+# include "data.h"
+# include "jpeglib.h"
+
+int mkrgb (int argc, char **argv) {
+ 
+  int i, j, Nx, Ny;
+  FILE *f;
+  Buffer *red, *green, *blue;
+  float *Vr, *Vg, *Vb;
+
+  struct jpeg_compress_struct cinfo;
+  struct jpeg_error_mgr jerr;
+  JSAMPROW row_pointer[1];	/* pointer to JSAMPLE row[s] */
+  JSAMPLE *image_buffer;	/* Points to data for current line */
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: mkrgb (red) (green) (blue) (output)\n");
+    return (FALSE);
+  }
+
+  // define the input buffer and examine the shift
+  if ((red    = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((green  = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((blue   = SelectBuffer (argv[3], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = red[0].matrix.Naxis[0];
+  Ny = red[0].matrix.Naxis[1];
+  if (Nx != blue[0].matrix.Naxis[0]) return (FALSE);
+  if (Ny != blue[0].matrix.Naxis[1]) return (FALSE);
+  if (Nx != green[0].matrix.Naxis[0]) return (FALSE);
+  if (Ny != green[0].matrix.Naxis[1]) return (FALSE);
+
+  f = fopen (argv[4], "w");
+  if (f == (FILE *) NULL) {
+    fprintf (stderr, "failed to open %s for output\n", argv[4]);
+    return (FALSE);
+  }
+
+  /* set up the error handler , initialize the JPEG compression object. */
+  cinfo.err = jpeg_std_error (&jerr);
+  jpeg_create_compress (&cinfo);
+  jpeg_stdio_dest(&cinfo, f);
+  
+  // set up the basic jpeg output file
+  cinfo.image_width = Nx; 	/* image width and height, in pixels */
+  cinfo.image_height = Ny;
+  cinfo.input_components = 3;		        
+  cinfo.in_color_space = JCS_RGB; 	
+  jpeg_set_defaults (&cinfo);
+  jpeg_set_quality (&cinfo, 75, TRUE       /* limit to baseline-JPEG values */);
+  jpeg_start_compress (&cinfo, TRUE);
+
+  ALLOCATE (image_buffer, JSAMPLE, 3*Nx);
+
+  // ??
+  // && (cinfo.next_scanline < cinfo.image_height)
+
+  Vr = (float *) red[0].matrix.buffer;
+  Vg = (float *) green[0].matrix.buffer;
+  Vb = (float *) blue[0].matrix.buffer;
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++, Vr++, Vg++, Vb++) {
+      image_buffer[3*i+0] = MAX (0.0, MIN (255.0, *Vr));
+      image_buffer[3*i+1] = MAX (0.0, MIN (255.0, *Vg));
+      image_buffer[3*i+2] = MAX (0.0, MIN (255.0, *Vb));
+    }
+    row_pointer[0] = image_buffer;
+    (void) jpeg_write_scanlines (&cinfo, row_pointer, 1);
+  }
+
+  jpeg_finish_compress (&cinfo);
+  fclose (f);
+
+  jpeg_destroy_compress (&cinfo);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mset.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mset.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/mset.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "data.h"
+
+int mset (int argc, char **argv) {
+  
+  int i, Nx, Ny, Npix, xdir, Nset;
+  float *in, *out;
+  Buffer *buf;
+  Vector *vec;
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: mset <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((vec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (strcasecmp (argv[3], "-x") && strcasecmp (argv[3], "-y")) {
+    gprint (GP_ERR, "USAGE: mset <buffer> <vector> <-x/-y> <N>\n");
+    return (FALSE);
+  }
+  xdir = TRUE;
+  if (!strcasecmp (argv[3], "-y")) xdir = FALSE;
+
+  Npix = vec[0].Nelements;
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+  Nset = atof (argv[4]);
+  if (Nset < 0) {
+    gprint (GP_ERR, "selection out of range\n");
+    return (FALSE);
+  }
+
+  if (xdir) {
+    if (Nx != Npix) {
+      gprint (GP_ERR, "dimensions don't match\n");
+      return (FALSE);
+    }
+    if (Nset >= Ny) {
+      gprint (GP_ERR, "row out of range\n");
+      return (FALSE);
+    }
+    out = (float *) buf[0].matrix.buffer + Nx*Nset;
+    in = vec[0].elements;
+    for (i = 0; i < Npix; i++, in++, out++) {
+      *out = *in;
+    }
+    return (TRUE);
+  } else {
+    if (Ny != Npix) {
+      gprint (GP_ERR, "dimensions don't match\n");
+      return (FALSE);
+    }
+    if (Nset >= Nx) {
+      gprint (GP_ERR, "column out of range\n");
+      return (FALSE);
+    }
+    out = (float *) buf[0].matrix.buffer + Nset;
+    in = vec[0].elements;
+    for (i = 0; i < Npix; i++, in++, out+=Nx) {
+      *out = *in;
+    }
+    return (TRUE);
+  }    
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/peak.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/peak.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/peak.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "data.h"
+
+int peak (int argc, char **argv) {
+  
+  int i, N, imax, QUIET;
+  double start, end, xmax, ymax;
+  float *X, *Y;
+  Vector *vecx, *vecy;
+
+  QUIET = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    QUIET = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 5) && (argc != 3)) {
+    gprint (GP_ERR, "USAGE: peak <x> <y> [start end]\n");
+    return (FALSE);
+  }
+
+  if ((vecx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (argc == 5) {
+    start = atof (argv[3]);
+    end   = atof (argv[4]);
+  } else {
+    start = vecx[0].elements[0];
+    end   = vecx[0].elements[vecx[0].Nelements - 1];
+  }
+
+  X = vecx[0].elements;
+  Y = vecy[0].elements;
+
+  imax = -1;
+  xmax = *X;
+  ymax = *Y;
+  for (i = 1; i < vecx[0].Nelements-1; i++, X++, Y++) {
+    if ((*X >= start) && (*X <= end)) {
+      if ((imax == -1) || (*Y > ymax)) {
+	xmax = *X;
+	ymax = *Y;
+	imax = i;
+      }
+    }
+  }      
+
+  set_variable ("peakval", ymax);
+  set_variable ("peakpos", xmax);
+  set_variable ("peaknum", imax);
+
+  if (!QUIET) gprint (GP_LOG, "peak %f @ %f (%d)\n", ymax, xmax, imax);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/periodogram.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/periodogram.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/periodogram.c	(revision 16632)
@@ -0,0 +1,114 @@
+# include "data.h"
+
+int periodogram (int argc, char **argv) {
+  
+  int i, N, Npt, Np, NP, VERBOSE;
+  float *tv, *fv;
+  float minP, maxP, minT, maxT, dTime;
+  float mean, var, w, tau, P, Pc, Ps, Po;
+  float C, S, cs, sn, cs2, sn2, ratio;
+  Vector *time, *flux, *power, *period;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: periodogram (time) (flux) (minP) (maxP) (period) (power)\n");
+    return (FALSE);
+  }
+  
+  if ((time = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((flux = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  minP = atof(argv[3]);
+  maxP = atof(argv[4]);
+  if ((period = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((power = SelectVector (argv[6], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* find the max baseline, mean, and variance */
+  minT = maxT = time[0].elements[0];
+  Npt = time[0].Nelements;
+  tv = time[0].elements;
+  fv = flux[0].elements;
+  mean = var = 0;
+  for (i = 0; i < Npt; i++, tv++, fv++) {
+    minT = MIN (minT, *tv);
+    maxT = MAX (maxT, *tv);
+    mean += *fv;
+  }
+  mean = mean / Npt;
+  fv = flux[0].elements;
+  for (i = 0; i < Npt; i++, fv++) {
+    var += SQ(*fv - mean);
+  }
+  var = var / (Npt - 1);
+
+  if (VERBOSE) gprint (GP_ERR, "mean: %f, var: %f, minT: %f, maxT: %f\n", mean, var, minT, maxT);
+
+  dTime = maxT - minT;
+  if (dTime == 0) {
+    gprint (GP_ERR, "ERROR: time range is zero\n");
+    return (FALSE);
+  }
+
+  Np = 0;
+  NP = 100;
+  REALLOCATE (power[0].elements, float, NP);
+  REALLOCATE (period[0].elements, float, NP);
+
+  P = minP;
+  while (P < maxP) {
+    w = 2*M_PI/P;
+    
+    /* find the period offset tau  */
+    tv = time[0].elements;
+    cs = sn = 0;
+    for (i = 0; i < Npt; i++, tv++) {
+      cs += cos (*tv*w*2);
+      sn += sin (*tv*2*2);
+    }
+    tau = 0.5*atan2 (sn, cs) / w;
+      
+    /* find the power at this period */
+    tv = time[0].elements;
+    fv = flux[0].elements;
+    cs = sn = cs2 = sn2 = 0;
+    for (i = 0; i < Npt; i++, tv++, fv++) {
+      C = cos (w*(*tv-tau));
+      S = sin (w*(*tv-tau));
+      // C = cos (w**tv);
+      // S = sin (w**tv);
+      cs += (*fv - mean) * C;
+      sn += (*fv - mean) * S;
+      cs2 += SQ(C);
+      sn2 += SQ(S);
+    }
+    Pc = SQ(cs) / cs2;
+    Ps = SQ(sn) / sn2;
+    Po = (Pc + Ps) / (2*var);
+
+    power[0].elements[Np] = Po;
+    period[0].elements[Np] = P;
+    Np ++;
+    if (Np >= NP) {
+      NP += 100;
+      REALLOCATE (power[0].elements, float, NP);
+      REALLOCATE (period[0].elements, float, NP);
+    }
+
+    ratio = 1 + 0.1*P/dTime;
+
+    if (VERBOSE) gprint (GP_ERR, "tau: %f, P: %f, ratio: %f, dTime: %f, nextP: %f\n", tau, P, ratio, dTime, P*ratio);
+
+    P *= ratio;
+  }
+
+  power[0].Nelements = Np;
+  period[0].Nelements = Np;
+  REALLOCATE (power[0].elements, float, Np);
+  REALLOCATE (period[0].elements, float, Np);
+ 
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/plot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/plot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/plot.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int plot (int argc, char **argv) {
+  
+  int kapa, N, Npts;
+  Graphdata graphmode;
+  Vector *xvec, *yvec, *dxmvec, *dxpvec, *dymvec, *dypvec;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  /* decide on error bars */
+  dxmvec = dxpvec = dymvec = dypvec = NULL;
+  if ((N = get_argument (argc, argv, "-dx"))) {
+    remove_argument (N, &argc, argv);
+    if ((dxmvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "+dx"))) {
+    remove_argument (N, &argc, argv);
+    if ((dxpvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-dy"))) {
+    remove_argument (N, &argc, argv);
+    if ((dymvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "+dy"))) {
+    remove_argument (N, &argc, argv);
+    if ((dypvec = SelectVector (argv[N], OLDVECTOR, TRUE)) == NULL) return (FALSE);    
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: plot <x> <y> [style]\n");
+    return (FALSE);
+  }
+
+  /* set errorbar mode (these are NOT sticky) */
+  graphmode.etype = 0;
+  if ((dymvec != NULL) && (dypvec == NULL)) dypvec = dymvec;
+  if ((dypvec != NULL) && (dymvec == NULL)) dymvec = dypvec;
+  if ((dypvec != NULL) || (dymvec != NULL)) graphmode.etype |= 0x01;
+  if ((dxmvec != NULL) && (dxpvec == NULL)) dxpvec = dxmvec;
+  if ((dxpvec != NULL) && (dxmvec == NULL)) dxmvec = dxpvec;
+  if ((dxpvec != NULL) || (dxmvec != NULL)) graphmode.etype |= 0x02;
+  
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  Npts = xvec[0].Nelements;
+  if (Npts == 0) return (TRUE);
+
+  if (!KapaPrepPlot (kapa, Npts, &graphmode)) return (FALSE);
+  
+  KapaPlotVector (kapa, Npts, xvec[0].elements, "x");
+  KapaPlotVector (kapa, Npts, yvec[0].elements, "y");
+  if (graphmode.etype & 0x01) {
+    KapaPlotVector (kapa, Npts, dymvec[0].elements, "dym");
+    KapaPlotVector (kapa, Npts, dypvec[0].elements, "dyp");
+  }
+  if (graphmode.etype & 0x02) {
+    KapaPlotVector (kapa, Npts, dxmvec[0].elements, "dxm");
+    KapaPlotVector (kapa, Npts, dxpvec[0].elements, "dxp");
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/point.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/point.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/point.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "data.h"
+
+int point (int argc, char **argv) {
+  
+  int N, celestial, pixscale;
+  int kapa;
+  double ra, dec, dra, ddec, angle;
+  double x1, y1, ra1, dec1;
+  char *name;
+  Coords coords;
+  Buffer *buf;
+  KiiOverlay overlay;
+  KapaImageData data;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImageData (&data, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  celestial = FALSE;
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    celestial = TRUE;
+  }
+  
+  pixscale = FALSE;
+  if ((N = get_argument (argc, argv, "-pixscale"))) {
+    remove_argument (N, &argc, argv);
+    pixscale = TRUE;
+  }
+
+  angle = 0.0;
+  if ((N = get_argument (argc, argv, "-angle"))) {
+    remove_argument (N, &argc, argv);
+    angle = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: point (overlay) TYPE x y dx dy [-c]\n");
+    return (FALSE);
+  }
+  
+  if (celestial) {
+    if ((buf = SelectBuffer (data.name, OLDBUFFER, TRUE)) == NULL) return (FALSE);
+    GetCoords (&coords, &buf[0].header);
+  }
+
+  if (celestial) {
+    ra   = atof(argv[3]);
+    dec  = atof(argv[4]);
+    dra  = atof(argv[5]);
+    ddec = atof(argv[6]);
+
+    fRD_to_XY (&overlay.x, &overlay.y, ra, dec, &coords);
+    if (pixscale) {
+      overlay.dx = atof(argv[5]);
+      overlay.dy = atof(argv[6]);
+    } else {
+      ra1 = ra + dra;
+      dec1 = dec + ddec;
+      RD_to_XY (&x1, &y1, ra1, dec1, &coords);
+      overlay.dx = x1 - overlay.x;
+      overlay.dy = y1 - overlay.y;
+    }
+  }
+  else {
+    overlay.x  = atof(argv[3]);
+    overlay.y  = atof(argv[4]);
+    overlay.dx = atof(argv[5]);
+    overlay.dy = atof(argv[6]);
+  }
+  overlay.angle = angle;
+  overlay.type = KiiOverlayTypeByName (argv[2]);
+  KiiLoadOverlay (kapa, &overlay, 1, argv[1]);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/ps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/ps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/ps.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int ps (int argc, char **argv) {
+
+  char filename[1024], pagename[1024], *name;
+  int N, kapa, scaleMode, pageMode;
+  
+  if ((N = get_argument (argc, argv, "--help"))) goto help;
+  if ((N = get_argument (argc, argv, "-h"))) goto help;
+
+  pageMode = KAPA_PS_NEWPLOT;
+
+  /* new page? */
+  if ((N = get_argument (argc, argv, "-newpage"))) {
+    remove_argument (N, &argc, argv);
+    pageMode = KAPA_PS_NEWPAGE;
+  }
+  if ((N = get_argument (argc, argv, "-raw"))) {
+    remove_argument (N, &argc, argv);
+    pageMode = KAPA_PS_RAWPAGE;
+  }
+
+  /* scale image? */
+  scaleMode = TRUE;
+  if ((N = get_argument (argc, argv, "-noscale"))) {
+    remove_argument (N, &argc, argv);
+    scaleMode = TRUE;
+  }
+
+  /* what file? */
+  filename[0] = 0;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (filename, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  /* pagename ? */
+  strcpy (pagename, "default");
+  if ((N = get_argument (argc, argv, "-pagename"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (pagename, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* which tool */
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc > 1) && filename[0]) goto help;
+
+  if (argc > 1) strcpy (filename, argv[1]);
+
+  // get the connection to kapa, false if none available
+  if (!GetGraphData (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if (!filename[0]) strcpy (filename, "kapa.ps");
+  
+  /* tell Ximage/Xgraph to ps the image */
+  KiiPS (kapa, filename, scaleMode, pageMode, pagename);
+  return (TRUE);
+
+help:
+  gprint (GP_ERR, "USAGE: ps [-name file.ps] [-g | -i] [-n device] [-raw] [-noscale] [-newpage] [-pagename (name]\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuedelete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuedelete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuedelete.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "data.h"
+
+int queuedelete (int argc, char **argv) {
+  
+  Queue *queue;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: queuedelete (name)\n");
+    return (FALSE);
+  }
+
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    gprint (GP_ERR, "ERROR: queue %s not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  DeleteQueue (queue);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuedrop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuedrop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuedrop.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "data.h"
+
+int queuedrop (int argc, char **argv) {
+  
+  int N;
+  char *Key;
+  char *line;
+  char *Value;
+  Queue *queue;
+
+  Key = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    Key = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Value = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 2) || (Key == NULL)) {
+    gprint (GP_ERR, "USAGE: queuedrop (queue) [-key N value]\n");
+    return (FALSE);
+  }
+
+  /* will create a queue if none exists */
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    gprint (GP_ERR, "ERROR: queue %s not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  /* drop all matching entries, if any exist */
+  while ((line = PopQueueMatch (queue, Key, Value)) != NULL) {
+    free (line);
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueinit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueinit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueinit.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "data.h"
+
+int queueinit (int argc, char **argv) {
+
+  Queue *queue;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: queueinit (name)\n");
+    return (FALSE);
+  }
+
+  queue = CreateQueue (argv[1]);
+  InitQueue (queue);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuelist.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuelist.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuelist.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "data.h"
+
+int queuelist (int argc, char **argv) {
+  
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: queuelist\n");
+    return (FALSE);
+  }
+
+  ListQueues ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueload.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueload.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueload.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "data.h"
+
+int queueload (int argc, char **argv) {
+  
+  char *A, *B, *val;
+  int i, status;
+  int Nread, Nbytes, NBYTES;
+  FILE *f;
+  Queue *queue;
+
+  if (argc != 4) goto usage;
+  if (strcmp(argv[2], "-x")) goto usage;
+  
+  /* will create a queue if none exists */
+  queue = CreateQueue (argv[1]);
+
+  /* val will hold the result of the command */
+  NBYTES = 1024;
+  ALLOCATE (val, char, NBYTES);
+    
+  /* loop until command produces no more output,  REALLOCATE as needed. */
+  f = popen (argv[3], "r");
+  Nbytes = 0;
+  Nread = 1;
+  while (Nread > 0) {
+    Nread = fread (&val[Nbytes], 1, 1023, f);
+    if (Nread < 0) { 
+      gprint (GP_ERR, "error reading from command\n");
+    }
+    if (Nread > 0) {
+      Nbytes += Nread;
+      NBYTES = 1024 + Nbytes;
+      REALLOCATE (val, char, NBYTES);
+    }
+  }
+  val[Nbytes] = 0;
+  status = pclose (f);
+    
+  if (status) {
+    gprint (GP_ERR, "warning: exit status of command %d\n", status);
+  }
+      
+  A = B = val;
+  for (i = 0; B != (char *) NULL;) {
+    while (isspace (*A) && (*A != 0)) A++;
+    B = strchr (A, '\n');
+    if (B != (char *) NULL) { *B = 0; }
+    if (*A != 0) {
+      PushQueue (queue, A);
+      A = B + 1;
+      i++;
+    }
+  }      
+  free (val);
+    
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: queueload (queue) -x (command)\n");
+  return (FALSE);
+}
+
+
+/* 
+ * -key only needed for replace or unique : give an error otherwise
+ * -uniq searched for a match and does NOT replace if matched
+ * -replace searches for a match and replaces if matched
+ * should trigger an error if -uniq and -replace...
+ */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuepop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuepop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuepop.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int queuepop (int argc, char **argv) {
+  
+  int N;
+  char *Key;
+  char *var;
+  char *line;
+  char *Value;
+  Queue *queue;
+
+  var = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    var = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Key = NULL;
+  Value = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    Key = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Value = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: queuepop (queue) [-var variable] [-key N value]\n");
+    return (FALSE);
+  }
+
+  /* will create a queue if none exists */
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    gprint (GP_ERR, "ERROR: queue %s not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  if (Key == NULL) {
+    line = PopQueue (queue);
+  } else {
+    line = PopQueueMatch (queue, Key, Value);
+  }
+
+  if (var == NULL) {
+    if (line == NULL) {
+      gprint (GP_ERR, "queue %s is empty or match not found\n", argv[1]);
+      return (FALSE);
+    } else {
+      gprint (GP_LOG, "%s\n", line);
+      free (line);
+      return (TRUE);
+    }
+  }
+
+  if (line == NULL) {
+    set_str_variable (var, "NULL");
+  } else {
+    set_str_variable (var, line);
+    free (line);
+  }
+
+  free (var);
+  if (Key != NULL) free (Key);
+  if (Value != NULL) free (Value);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueprint.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueprint.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queueprint.c	(revision 16632)
@@ -0,0 +1,21 @@
+# include "data.h"
+
+int queueprint (int argc, char **argv) {
+  
+  Queue *queue;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: queueprint (name)\n");
+    return (FALSE);
+  }
+
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    gprint (GP_ERR, "ERROR: queue %s not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  PrintQueue (queue);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuepush.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuepush.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuepush.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "data.h"
+
+int queuepush (int argc, char **argv) {
+  
+  char *Key;
+  int N, Unique, Replace;
+  Queue *queue;
+
+  Unique = FALSE;
+  if ((N = get_argument (argc, argv, "-uniq"))) {
+    remove_argument (N, &argc, argv);
+    Unique = TRUE;
+  }
+
+  Replace = FALSE;
+  if ((N = get_argument (argc, argv, "-replace"))) {
+    remove_argument (N, &argc, argv);
+    Replace = TRUE;
+  }
+
+  Key = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+    Key = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: queuepush (queue) (value) [-key N] [-uniq] [-replace]\n");
+    return (FALSE);
+  }
+
+  /* will create a queue if none exists */
+  queue = CreateQueue (argv[1]);
+
+  if (Unique) {
+    PushQueueUnique (queue, argv[2], Key);
+  }
+  if (Replace) {
+    PushQueueReplace (queue, argv[2], Key);
+  }
+  if (!Unique && !Replace) {
+    PushQueue (queue, argv[2]);
+  }
+
+  if (Key != NULL) free (Key);
+  return (TRUE);
+}
+
+
+/* 
+ * -key only needed for replace or unique : give an error otherwise
+ * -uniq searched for a match and does NOT replace if matched
+ * -replace searches for a match and replaces if matched
+ * should trigger an error if -uniq and -replace...
+ */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuesize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuesize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/queuesize.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "data.h"
+
+int queuesize (int argc, char **argv) {
+  
+  int N;
+  char *var;
+  Queue *queue;
+
+  var = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-var"))) {
+    remove_argument (N, &argc, argv);
+    var = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: queuesize (name) [-var variable]\n");
+    return (FALSE);
+  }
+
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    gprint (GP_ERR, "ERROR: queue %s not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  if (var == (char *) NULL) {
+    gprint (GP_ERR, "Nlines: %d\n", queue[0].Nlines);
+    return (TRUE);
+  }
+
+  set_int_variable (var, queue[0].Nlines);
+  free (var);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/radial.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/radial.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/radial.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "data.h"
+
+int circstats (int argc, char **argv) {
+  
+  int i, j;
+  double Npix, S1, S2, max, min, Sum, Mean, Stdev, IgnoreValue; 
+  double xc, yc, radius, R2, r;
+  float *V;
+  int xs, ys, xe, ye;
+  int Ignore, Quiet, N, Nx, Ny;
+  Buffer *buf;
+
+  Ignore = FALSE;
+  IgnoreValue = 0;
+  if ((N = get_argument (argc, argv, "-ignore"))) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) goto usage;
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) goto missed;
+
+  xc = atof (argv[2]);
+  yc = atof (argv[3]);
+  radius = atof (argv[4]);
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  if (xc < 0) goto range;
+  if (yc < 0) goto range;
+  if (xc >= Nx) goto range;
+  if (yc >= Ny) goto range;
+
+  xs = MAX (0, xc - radius);
+  ys = MAX (0, yc - radius);
+  xe = MIN (Nx, xc + radius + 1);
+  ye = MAX (Ny, yc + radius + 1);
+  R2 = radius*radius;
+
+  S1 = S2 = Npix = 0;
+  min = max = *(float *)(buf[0].matrix.buffer) + (int)(yc)*buf[0].matrix.Naxis[0] + (int)(xc); 
+  for (j = ys; j < ye; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + xs; 
+    for (i = xs; i < xe; i++, V++) {
+      r = SQ(i - xc) + SQ(j - yc);
+      if (r > R2) continue;
+      if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+      S1 += *V;
+      S2 += (*V)*(*V);
+      Npix += 1.0;
+      max = MAX (max, *V);
+      min = MIN (min, *V);
+    }
+  }
+  Mean = S1 / Npix;
+  Sum  = Mean * M_PI * R2;
+  Stdev = sqrt (S2/Npix - Mean*Mean);
+
+  if (!Quiet) {
+    gprint (GP_LOG, "     mean     stdev       min       max    Npix     Total\n");
+    gprint (GP_LOG, "%9.4g %9.4g %9.4g %9.4g %7.0f %9.4g\n", Mean, Stdev, min, max, Npix, Sum);
+  }
+
+  set_variable ("MIN",    min);
+  set_variable ("MAX",    max);
+  set_variable ("MEAN",   Mean);
+  set_variable ("SUM",    Sum);
+  set_variable ("NPIX",   Npix);
+  set_variable ("SIGMA",  Stdev);
+
+  return (TRUE);
+
+ usage: 
+  gprint (GP_ERR, "USAGE: circstats <buffer> x y radius\n");
+  return (FALSE);
+
+ range:
+  gprint (GP_ERR, "ERROR: coordinates out of range\n");
+  return (FALSE);
+
+ missed:
+  gprint (GP_ERR, "ERROR: buffer not found\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rd.c	(revision 16632)
@@ -0,0 +1,227 @@
+# include "data.h"
+
+/* there is some confusion in this function with the several possible options */
+int rd (int argc, char **argv) {
+  
+  int i, N, status, plane, Nplane, extend, Nextend, Nskip, JustHead;
+  int ccdsel, done, Nword, IsCompressed;
+  char region[512], *ccdid, *filename;
+  FILE *f;
+  Buffer *buf;
+
+  JustHead = FALSE;
+  if ((N = get_argument (argc, argv, "-head"))) {
+    remove_argument (N, &argc, argv);
+    JustHead = TRUE;
+  }
+
+  plane = 1;
+  if ((N = get_argument (argc, argv, "-plane"))) {
+    remove_argument (N, &argc, argv);
+    plane  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  extend = FALSE;
+  Nextend = -1;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    Nextend  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    extend = TRUE;
+  }
+
+  ccdsel = FALSE;
+  ccdid = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    ccdid  = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    ccdsel = TRUE;
+  }
+
+  if (extend && ccdsel) {
+    gprint (GP_ERR, "only specify one of -n and -x\n");
+    return (FALSE);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: rd <buffer> <filename> [-head] [-plane N] [-n ccdid] [-x extnum]\n");
+    return (FALSE);
+  }
+
+  /* test if file exists */
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "file %s not found\n", argv[2]);
+    return (FALSE);
+  }
+
+  /* find matrix, free old data */
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) {
+      fclose (f);
+      return (FALSE);
+  }
+  gfits_free_matrix (&buf[0].matrix);
+  gfits_free_header (&buf[0].header);
+
+  /* save file name */
+  filename = filebasename (argv[2]);
+  strcpy (buf[0].file, filename);
+  free (filename);
+
+  status = FALSE;
+  IsCompressed = FALSE;
+
+  /*** advance to the correct FITS extension ***/
+
+  /* FITS extension by number */
+  if (extend) {
+    /* load in appropriate header */
+    Nskip = gfits_fread_Xheader (f, &buf[0].header, Nextend);
+    if (!Nskip) {
+      gprint (GP_ERR, "entry in %s not found\n", argv[2]);
+      DeleteBuffer (buf);
+      fclose (f);
+      return (FALSE);
+    }
+    if (gfits_extension_is_compressed (&buf[0].header)) {
+	IsCompressed = TRUE;
+    }
+  } 
+
+  /* FITS extension by name */
+  if (ccdsel) {
+    char *CCDKeyword, ID[64];
+
+    CCDKeyword = get_variable ("CCDKEYWORD");
+    if (CCDKeyword == (char *) NULL) {
+      // gprint (GP_ERR, "CCDKEYWORD variable is not set; ");
+      // gprint (GP_ERR, "using EXTNAME as default\n");
+      CCDKeyword = strcreate ("EXTNAME");
+    }
+    done = FALSE;
+    for (i = 0; !done; i++) {
+      Nskip = gfits_fread_Xheader (f, &buf[0].header, i);
+      if (!Nskip) {
+	gprint (GP_ERR, "extension %s in %s not found\n", ccdid, argv[2]);
+	DeleteBuffer (buf);
+	free (CCDKeyword);
+	fclose (f);
+	return (FALSE);
+      }
+
+      // for compressed data tables, EXTNAME may be duplicated, with the first one containing the
+      // word 'COMPRESSED_IMAGE'.  in this case, check the second EXTNAME, if CCDKeyword == EXTNAME 
+      // this may have to be a more obscure test specifically for 'imcopy' data...
+      // need to check each header, since file may contain a mix
+      
+      Nword = 1;
+      IsCompressed = FALSE;
+      if (gfits_extension_is_compressed (&buf[0].header)) {
+	if (!strcmp (CCDKeyword, "EXTNAME")) Nword = 1;
+	IsCompressed = TRUE;
+      }
+      if (!gfits_scan (&buf[0].header, CCDKeyword, "%s", Nword, ID)) {
+	gprint (GP_ERR, "%s not in header\n", CCDKeyword);
+	DeleteBuffer (buf);
+	free (CCDKeyword);
+	fclose (f);
+	return (FALSE);
+      }
+
+      /* compare as numbers if both are pure numbers, else as strings */
+      done = strnumcmp (ccdid, ID);
+      if (!done) gfits_free_header (&buf[0].header);
+    }
+    free (CCDKeyword);
+  }
+
+  /* fix up header, if needed */
+  if (extend || ccdsel) {
+    if (!IsCompressed) {
+      gfits_extended_to_primary (&buf[0].header, TRUE, "Standard FITS");
+    }
+  } else {
+      gfits_fread_header (f, &buf[0].header);
+  }
+
+  /* for JustHead, we skip reading the data segment */ 
+  // XXX for compressed data, we need to convert the header to the equivalent uncompressed version
+  if (JustHead) {
+    // XXX what are we doing here exactly?
+    buf[0].header.Naxes = 0;
+    ALLOCATE (buf[0].matrix.buffer, char, 1);
+    buf[0].matrix.size = 0;
+    buf[0].bitpix = 16;
+    buf[0].bzero = 0;
+    buf[0].bscale = 1;
+    buf[0].matrix.bitpix = 16;
+    buf[0].matrix.bzero = 0;
+    buf[0].matrix.bscale = 1;
+    buf[0].header.bitpix = 16;
+    buf[0].header.bzero = 0;
+    buf[0].header.bscale = 1;
+    fclose (f);
+    return (TRUE);
+  }
+
+  /* check for valid plane */
+  Nplane = buf[0].header.Naxis[2];
+  if (Nplane == 0) Nplane = 1;
+  if (plane > Nplane) {
+    gprint (GP_ERR, "-plane is too large: %d total planes\n", Nplane);
+    DeleteBuffer (buf);
+    fclose (f);
+    return (FALSE);
+  }
+
+  /* load matrix data */
+  if (IsCompressed) {
+    FTable ftable;
+    Header theader;
+    ftable.header = &theader;
+    gfits_copy_header (&buf[0].header, ftable.header);
+    status = gfits_fread_ftable_data (f, &ftable);  // this just reads the bytes (not even a SWAP)
+    status = gfits_uncompress_image (&buf[0].header, &buf[0].matrix, &ftable);
+    gfits_free_table (&ftable);
+    // XXX this currently does not work for a cube (we get a cube back, not a specific plane)
+  } else {
+    sprintf (region, "-1 -1 -1 -1 %d %d", (plane - 1), plane);
+    status = gfits_fread_matrix_segment (f, &buf[0].matrix, &buf[0].header, region);
+    fclose (f);
+  }
+
+  if (!status) {
+    gprint (GP_ERR, "problem reading file, buffer not opened\n");
+    DeleteBuffer (buf);
+    return (FALSE);
+  }
+
+  /* adjust buffer to represent 2D data */
+  if (Nplane > 1) {
+    buf[0].header.Naxis[2] = 0;
+    buf[0].header.Naxes = 2;
+    gfits_modify (&buf[0].header, "NAXIS", "%d", 1, 2);
+    gfits_delete (&buf[0].header, "NAXIS3", 1);
+  }
+
+  /* we need to return a 2D array, convert 1D images to 2D (Naxis[1] = 1) */
+  if (buf[0].header.Naxes == 1) {
+    buf[0].header.Naxes = 2;
+    buf[0].header.Naxis[1] = 1;
+    buf[0].matrix.Naxis[1] = 1;
+  }    
+
+  buf[0].bitpix = buf[0].header.bitpix;    /* store the original values */
+  buf[0].bscale = buf[0].header.bscale;    /* store the original values */
+  buf[0].bzero  = buf[0].header.bzero;     /* store the original values */
+  buf[0].unsign = buf[0].header.unsign;
+  gprint (GP_LOG, "read %d bytes from %s into buffer %s\n", 
+	   buf[0].header.size + buf[0].matrix.size, argv[2], argv[1]);
+
+  /** now - convert the matrix values to floats for internal use **/
+  gfits_convert_format (&buf[0].header, &buf[0].matrix, -32, 1.0, 0.0, gfits_get_unsign_mode());
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rdseg.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rdseg.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rdseg.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "data.h"
+
+/* there is some confusion in this function with the several possible options */
+int rdseg (int argc, char **argv) {
+  
+  int x, y, nx, ny, status;
+  char region[512], *filename;
+  FILE *f;
+  Buffer *buf;
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: rdseg <buffer> <filename> x y nx ny\n");
+    return (FALSE);
+  }
+  x = atoi (argv[3]);
+  y = atoi (argv[4]);
+  nx = atoi (argv[5]);
+  ny = atoi (argv[6]);
+
+  /* test if file exists */
+  f = fopen (argv[2], "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "file %s not found\n", argv[2]);
+    return (FALSE);
+  }
+  fclose (f);
+
+  /* find matrix, free old data */
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  gfits_free_matrix (&buf[0].matrix);
+  gfits_free_header (&buf[0].header);
+
+  /* save file name */
+  filename = filebasename (argv[2]);
+  strcpy (buf[0].file, filename);
+  free (filename);
+
+  status = gfits_read_header (argv[2], &buf[0].header);
+  sprintf (region, "%d %d %d %d 0 1", x, nx + x, y, ny + y);
+  status = gfits_read_matrix_segment (argv[2], &buf[0].matrix, region);
+  gfits_modify (&buf[0].header, "NAXIS1", "%d", 1, nx);
+  gfits_modify (&buf[0].header, "NAXIS2", "%d", 1, ny);
+  buf[0].header.Naxis[0] = nx;
+  buf[0].header.Naxis[1] = ny;
+  buf[0].matrix.Naxis[0] = nx;
+  buf[0].matrix.Naxis[1] = ny;
+
+  if (!status) {
+    gprint (GP_ERR, "problem reading file, buffer not opened\n");
+    DeleteBuffer (buf);
+    return (FALSE);
+  }
+  if (buf[0].header.Naxes == 1) {
+    /* we need to return an array, so make Naxis[1] = 1 */
+    buf[0].header.Naxes = 2;
+    buf[0].header.Naxis[1] = 1;
+    buf[0].matrix.Naxis[1] = 1;
+  }    
+
+  buf[0].bitpix = buf[0].header.bitpix;    /* store the original values */
+  buf[0].bscale = buf[0].header.bscale;    /* store the original values */
+  buf[0].bzero  = buf[0].header.bzero;     /* store the original values */
+  buf[0].unsign = buf[0].header.unsign;
+  gprint (GP_LOG, "read %d bytes from %s into buffer %s\n", 
+	   buf[0].header.size + buf[0].matrix.size, argv[2], argv[1]);
+
+  /** now - convert the matrix values to floats for internal use **/
+  gfits_convert_format (&buf[0].header, &buf[0].matrix, -32, 1.0, 0.0, gfits_get_unsign_mode());
+  
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/read_vectors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/read_vectors.c	(revision 16632)
@@ -0,0 +1,325 @@
+ # include "data.h"
+
+FILE *f = (FILE *) NULL;
+char filename[256];
+
+int datafile (int argc, char **argv) {
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: datafile (filename)\n");
+    return (FALSE);
+  }
+  
+  strcpy (filename, argv[1]);
+  if (f != (FILE *) NULL) { fclose (f); }
+  f = fopen (filename, "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "failed to open file %s\n", argv[1]);
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int read_vectors (int argc, char **argv) {
+  
+  int i, j, Nskip, Nvec, *col, done, status;
+  int Nbytes, nbytes, Nstart, NELEM, N, nread;
+  char *colstr, *c0, *c1, *buffer, *extname;
+  double value;
+  Vector **vec;
+
+  /* auto-sense table type */
+  if ((N = get_argument (argc, argv, "-fits"))) {
+    remove_argument (N, &argc, argv);
+    extname = strcreate (argv[N]);
+    if (extname == (char *) NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+    status = read_table_vectors (argc, argv, extname);
+    free (extname);
+    return (status);
+  }
+
+  Nskip = 0;
+  if ((N = get_argument (argc, argv, "-skip"))) {
+    remove_argument (N, &argc, argv);
+    Nskip = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc < 3) || !(argc % 2)) {
+    gprint (GP_ERR, "USAGE: read name N name N ...\n");
+    return (FALSE);
+  }
+  /* read name N name N  */
+
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "no open file for read\n");
+    return (FALSE);
+  }
+  fseek (f, 0, SEEK_SET);
+
+  Nvec = (argc - 1) / 2;
+  ALLOCATE (vec, Vector *, Nvec);
+  ALLOCATE (col, int, Nvec);
+
+  for (i = 0; i < Nvec; i++) {
+    if ((vec[i] = SelectVector (argv[2*i + 1], ANYVECTOR, TRUE)) == NULL) {
+      gprint (GP_ERR, "USAGE: read name N name N ...\n");
+      free (vec);
+      free (col);
+      return (FALSE);    
+    }
+    colstr = argv[2*i+2];
+    for (j = 0; j < strlen (colstr); j++) {
+      if (!isdigit(colstr[j])) {
+	gprint (GP_ERR, "USAGE: read name N name N ...\n");
+	free (vec);
+	free (col);
+	return (FALSE);    
+      }
+    }
+    col[i] = atof (colstr);
+  }
+  
+  NELEM = 1000;
+  for (i = 0; i < Nvec; i++) {
+    REALLOCATE (vec[i][0].elements, float, NELEM);
+  }
+  
+  ALLOCATE (buffer, char, 0x10001);
+  bzero (buffer, 0x10001);
+  for (i = 0; i < Nskip; i++) {
+    scan_line (f, buffer);
+  }
+
+  Nstart = 0;
+  N = 0;
+  done = FALSE;
+  while (!done) {
+    Nbytes = 0x10000 - Nstart;
+    bzero (&buffer[Nstart], Nbytes);
+    nread = fread (&buffer[Nstart], 1, Nbytes, f);
+    if (ferror (f)) {
+      perror ("error reading data file");
+      break;
+    }
+    if (nread == 0) break;
+    nbytes = nread + Nstart;
+    
+    status = TRUE;
+    c0 = buffer; 
+    while (status) {
+      c1 = strchr (c0, '\n');
+      if (c1 == (char *) NULL) {
+	Nstart = strlen (c0);
+	memmove (buffer, c0, Nstart);
+	status = FALSE;
+      } else {
+	*c1 = 0;
+      }      
+      if ((*c0 != '#') && (*c0 != '!')) {
+	for (i = 0; (i < Nvec) && status; i++) {
+	  status = dparse (&value, col[i], c0);
+	  vec[i][0].elements[N] = value;
+	  if (!status) vec[i][0].elements[N] = 0.0/0.0;
+	}
+	if (status) N++;
+      }
+      c0 = c1 + 1;
+      if (N == NELEM) {
+	NELEM += 1000;
+	for (i = 0; i < Nvec; i++) {
+	  REALLOCATE (vec[i][0].elements, float, NELEM);
+	}
+      }
+	
+    }
+  }
+  for (i = 0; i < Nvec; i++) {
+    REALLOCATE (vec[i][0].elements, float, MAX (N,1));
+    vec[i][0].Nelements = N;
+  }
+  
+  free (vec);
+  free (col);
+  free (buffer);
+  return (TRUE);
+
+}
+
+int read_table_vectors (int argc, char **argv, char *extname) {
+
+  int i, j, k, N, Nbytes, Nextend, Ny, Binary;
+  char type[16], ID[80], *CCDKeyword;
+  FTable table;
+  Header header;
+  Vector **vec;
+
+  table.buffer = NULL;
+  header.buffer = NULL;
+
+  CCDKeyword = NULL;
+  if ((N = get_argument (argc, argv, "-keyword"))) {
+    remove_argument (N, &argc, argv);
+    CCDKeyword = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Nextend = -1;
+  if ((N = get_argument (argc, argv, "-extnum"))) {
+    remove_argument (N, &argc, argv);
+    Nextend = atoi (extname);
+  }
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: read -fits extension [-extnum] [-keyword key] name name ...\n");
+    gprint (GP_ERR, "  ('extension' may be a name or number)\n");
+    goto escape;
+  }
+
+  if (f == (FILE *) NULL) goto escape;
+  fseek (f, 0, SEEK_SET);
+  table.header = &header;
+
+  /* load appropriate extension (if extname is a number, use count) */
+  if (Nextend > -1) {
+    // first extension is PHU, cannot be a table. 
+    // Nextend counts from 0 for first extension
+    if (!gfits_load_header (f, &header)) goto escape;
+    Nbytes = gfits_data_size (&header);
+    fseek (f, Nbytes, SEEK_CUR);
+    gfits_free_header (&header);
+
+    for (i = 0; i < Nextend; i++) {
+      if (!gfits_load_header (f, &header)) goto escape;
+      Nbytes = gfits_data_size (&header);
+      /* skip the prior data buffers */
+      fseek (f, Nbytes, SEEK_CUR);
+      gfits_free_header (&header);
+    }
+    if (!gfits_load_header (f, &header)) goto escape;
+    if (!gfits_fread_ftable_data (f, &table)) goto escape;
+
+  } else {
+    if (CCDKeyword == NULL) {
+      CCDKeyword = get_variable ("CCDKEYWORD");
+    }
+    if (CCDKeyword == NULL) {
+      CCDKeyword = strcreate ("EXTNAME");
+    }
+
+    while (1) {
+      if (!gfits_load_header (f, &header)) goto escape;
+      Nbytes = gfits_data_size (&header);
+
+      if (!gfits_scan (&header, CCDKeyword, "%s", 1, ID)) {
+	fseek (f, Nbytes, SEEK_CUR);
+	gfits_free_header (&header);
+	continue;
+      }
+      if (strcmp (ID, extname)) {
+	fseek (f, Nbytes, SEEK_CUR);
+	gfits_free_header (&header);
+	continue;
+      }
+      if (!gfits_fread_ftable_data (f, &table)) goto escape;
+      break;
+    }
+  }
+
+  /* identify table type (ascii / binary) */
+  Binary = FALSE;
+  gfits_scan (&header, "XTENSION", "%s", 1, type);
+  if (strcmp (type, "BINTABLE") && strcmp (type, "TABLE")) {
+    gprint (GP_ERR, "specified extension (%s) is not a table\n", extname);
+    goto escape;
+  }
+  Binary = !strcmp (type, "BINTABLE");
+  Ny = header.Naxis[1];
+
+  /* find columns which match requested vectors */
+  for (i = 1; i < argc; i++) {
+    void   *data;
+    char   *Pc;
+    short  *Ps;
+    int    *Pi;
+    float  *Pf;
+    double *Pd;
+    int Nval;
+    char name[80];
+      
+    Nval = 0;
+    if (Binary) {
+      if (!gfits_get_bintable_column_type (&header, argv[i], type, &Nval)) goto escape;
+      if (!gfits_get_bintable_column (&header, &table, argv[i], &data)) goto escape;
+    } else {
+      if (!gfits_get_table_column_type (&header, argv[i], type)) goto escape;
+      if (!gfits_get_table_column (&header, &table, argv[i], &data)) goto escape;
+    }
+    if (Nval == 0) goto escape;
+
+    ALLOCATE (vec, Vector *, Nval);
+    for (j = 0; j < Nval; j++) {
+      if (Nval == 1) 
+	sprintf (name, "%s", argv[i]);
+      else
+	sprintf (name, "%s:%d", argv[i], j);
+      if ((vec[j] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) goto escape;
+      REALLOCATE (vec[j][0].elements, float, MAX (Ny,1));
+      vec[j][0].Nelements = Ny;
+    }
+
+    if (!strcmp (type, "double")) {
+      Pd = (double *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Pd++) {
+	  vec[k][0].elements[j] = *Pd;
+	}
+      }
+    }
+    if (!strcmp (type, "float")) {
+      Pf = (float *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Pf++) {
+	  vec[k][0].elements[j] = *Pf;
+	}
+      }
+    }
+    if (!strcmp (type, "int")) {
+      Pi = (int *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Pi++) {
+	  vec[k][0].elements[j] = *Pi;
+	}
+      }
+    }
+    if (!strcmp (type, "short")) {
+      Ps = (short *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Ps++) {
+	  vec[k][0].elements[j] = *Ps;
+	}
+      }
+    }
+    if (!strcmp (type, "char")) {
+      Pc = (char *) data;
+      for (j = 0; j < Ny; j++) {
+	for (k = 0; k < Nval; k++, Pc++) {
+	  vec[k][0].elements[j] = *Pc;
+	}
+      }
+    }
+    free (data);
+    free (vec);
+  }
+  if (CCDKeyword != NULL) free (CCDKeyword);
+  gfits_free_table (&table);
+  gfits_free_header (&header);
+  return (TRUE);
+
+escape:
+  if (CCDKeyword != NULL) free (CCDKeyword);
+  gfits_free_table  (&table);
+  gfits_free_header (&header);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rebin.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rebin.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rebin.c	(revision 16632)
@@ -0,0 +1,228 @@
+# include "data.h"
+
+int rebin (int argc, char **argv) {
+  
+  int i, j, status, n, nx, ny, Nx, Ny, x, y, N, *Npix, *Vn;
+  int Ignore, IgnoreValue, VERBOSE, Normalize, ExactScale;
+  char temp[1024];
+  float *Vout, *Vin, *Out, *In;
+  double scale, scale2, fx, fy, dX, dY;
+  Buffer *in, *out;
+
+  Vn = Npix = NULL;
+  Normalize = FALSE;
+  if ((N = get_argument (argc, argv, "-norm"))) {
+    remove_argument (N, &argc, argv);
+    Normalize = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  Ignore = FALSE;
+  IgnoreValue = 0.0;
+  if ((N = get_argument (argc, argv, "-ignore"))) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: rebin <from> <to> scale \n");
+    gprint (GP_ERR, "  negative integer scale expands image\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  gfits_free_matrix (&out[0].matrix);
+  gfits_free_header (&out[0].header);
+
+  scale  = atof (argv[3]);
+  if ((scale == (int) scale) || ((1.0/scale) == (int)(1.0/scale))) {
+    ExactScale = TRUE;
+    if (scale > 0) {
+      nx = in[0].header.Naxis[0] / scale;
+      ny = in[0].header.Naxis[1] / scale;
+    } else {
+      nx = in[0].header.Naxis[0] * fabs(scale);
+      ny = in[0].header.Naxis[1] * fabs(scale);
+    }    
+  } else {
+    ExactScale = FALSE;
+    if (scale > 0) {
+      nx = (int) (in[0].header.Naxis[0] / scale) + 1;
+      ny = (int) (in[0].header.Naxis[1] / scale) + 1;
+    } else {
+      nx = (int) (in[0].header.Naxis[0] * fabs(scale)) + 1;
+      ny = (int) (in[0].header.Naxis[1] * fabs(scale)) + 1;
+    }      
+  }
+  if (VERBOSE) gprint (GP_LOG, "rebin %s to %s (%d,%d to %d,%d)\n", argv[1], argv[2], in[0].header.Naxis[0], in[0].header.Naxis[1], nx, ny);
+
+  Nx = in[0].header.Naxis[0];
+  Ny = in[0].header.Naxis[1];
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  gfits_copy_header (&in[0].header, &out[0].header);
+  gfits_modify (&out[0].header, "NAXIS1", "%d", 1, nx);
+  gfits_modify (&out[0].header, "NAXIS2", "%d", 1, ny);
+
+  status =  gfits_scan (&out[0].header, "CDELT1", "%lf", 1, &dX);
+  status &= gfits_scan (&out[0].header, "CDELT2", "%lf", 1, &dY);
+  if (scale > 0) {
+    dX *= scale;
+    dY *= scale;
+  } else {
+    dX /= fabs(scale);
+    dY /= fabs(scale);
+  }    
+  if (status) {
+    gfits_modify (&out[0].header, "CDELT1", "%lf", 1, dX);
+    gfits_modify (&out[0].header, "CDELT2", "%lf", 1, dY);
+  }
+
+  status =  gfits_scan (&out[0].header, "CRPIX1", "%lf", 1, &dX);
+  status &= gfits_scan (&out[0].header, "CRPIX2", "%lf", 1, &dY);
+  if (scale > 0) {
+    dX /= scale;
+    dY /= scale;
+  } else {
+    dX *= fabs(scale);
+    dY *= fabs(scale);
+  }    
+  if (status) {
+    gfits_modify (&out[0].header, "CRPIX1", "%lf", 1, dX);
+    gfits_modify (&out[0].header, "CRPIX2", "%lf", 1, dY);
+  }
+
+  out[0].header.Naxis[0] = nx;
+  out[0].header.Naxis[1] = ny;
+  gfits_create_matrix (&out[0].header, &out[0].matrix);
+  temp[0] = 0;
+  if ((in[0].file[0] != '*') && (in[0].file[0] != '(')) {
+    strcpy (temp, "*");
+  }
+  strcat (temp, in[0].file);
+  strcpy (out[0].file, temp);
+
+  if (Normalize) {
+    ALLOCATE (Npix, int, nx*ny);
+    bzero (Npix, nx*ny*sizeof(int));
+  }
+
+  if (ExactScale) {
+    n = scale;
+    if (n > 0) {
+      for (j = 0; j < ny; j++) {
+	for (y = 0; y < n; y++) {
+	  Vout = (float *)(out[0].matrix.buffer) + j*nx;
+	  Vin  = (float *)(in[0].matrix.buffer)  + (j*n + y)*in[0].header.Naxis[0];
+	  if (Normalize) { Vn = Npix + j*nx; }
+	  for (i = 0; i < nx; i++, Vout++) {
+	    for (x = 0; x < n; x++, Vin++) {
+	      if (Ignore && (*Vin == IgnoreValue)) continue;
+	      *Vout += *Vin;
+	      if (Normalize) {(*Vn) ++;}
+	    }
+	    if (Normalize) {Vn ++;}
+	  }
+	}
+      }
+    } else {
+      n = fabs (n);
+      for (j = 0; j < in[0].header.Naxis[1]; j++) {
+	for (y = 0; y < n; y++) {
+	  Vout = (float *)(out[0].matrix.buffer) + (j*n + y)*nx;
+	  Vin  = (float *)(in[0].matrix.buffer)  + j*in[0].header.Naxis[0];
+	  if (Normalize) { Vn = Npix + j*nx; }
+	  for (i = 0; i < in[0].header.Naxis[0]; i++, Vin++) {
+	    if (Ignore && (*Vin == IgnoreValue)) { 
+	      Vout += n; 
+	      if (Normalize) Vn += n; 
+	      continue; 
+	    }
+	    for (x = 0; x < n; x++, Vout++) {
+	      *Vout = *Vin;
+	      if (Normalize) {(*Vn) ++; Vn ++;}
+	    }
+	  }
+	}
+      }
+    }
+    if (Normalize) {
+      Vn = Npix;
+      Vout = (float *)out[0].matrix.buffer;
+      for (i = 0; i < nx*ny; i++, Vout++, Vn++) {
+	if (*Vn) { 
+	  *Vout /= *Vn; 
+	} else {
+	  *Vout = 0;
+	}
+      }
+    }
+  } else {
+    
+    /* normalization is broken.  repair please */
+    if (Normalize) { gprint (GP_ERR, "normalize not enabled for fractional scaling\n"); }
+
+    if (scale < 0) scale = 1.0 / fabs(scale);
+    In = (float *)in[0].matrix.buffer;
+    Out = (float *)out[0].matrix.buffer;
+    scale2 = scale*scale;
+    if (scale > 1) {
+      for (i = 0; i < Ny; i++) {
+	y = 0.5 + (i - 0.5) / scale;
+	fy = 0.5 + MIN (0.5, (y + 0.5) * scale - i);
+	for (j = 0; j < Nx; j++, In++) {
+	  x = 0.5 + (j - 0.5) / scale;
+	  fx = 0.5 + MIN (0.5, (x + 0.5) * scale - j);
+	  Vout = Out + y*nx + x;
+	  *Vout += fx*fy*(*In);
+	  if (fx < 1) {
+	    *(Vout+1)    += (1-fx)*fy*(*In);
+	  }
+	  if (fy < 1) {
+	    *(Vout+nx) += fx*(1-fy)*(*In);
+	  }
+	  if ((fx < 1) && (fy < 1)) {
+	    *(Vout+1+nx) += (1-fx)*(1-fy)*(*In);
+	  }
+	}
+      }
+    } else {
+      for (i = 0; i < ny; i++) {
+	y = 0.5 + (i - 0.5) * scale;
+	fy = 0.5 + MIN (0.5, (y + 0.5) / scale - i);
+	for (j = 0; j < nx; j++, Out++) {
+	  x = 0.5 + (j - 0.5) * scale;
+	  fx = 0.5 + MIN (0.5, (x + 0.5) / scale - j);
+	  Vin = In + y*Nx + x;
+	  *Out += *Vin*fx*fy;
+	  if (fx < 1) {
+	    *Out += *(Vin+1)*(1-fx)*fy;
+	  }
+	  if (fy < 1) {
+	    *Out += *(Vin+Nx)*fx*(1-fy);
+	  }
+	  if ((fx < 1) && (fy < 1)) {
+	    *Out += *(Vin+1+Nx)*(1-fx)*(1-fy);
+	  }
+	  *Out = *Out * scale2;
+	}
+      }
+    }
+  }
+
+  if (Normalize) free (Npix);
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/resize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/resize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/resize.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "data.h"
+
+int resize (int argc, char **argv) {
+
+  char *end;
+  double NX, NY;
+  int N, kapa;
+  char *name;
+  
+  /* display source */
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: resize NX NY [-n] [-g | -i]\n");
+    return (FALSE);
+  }
+
+  /* NX & NY are pixels for the screen & points for PS 
+     convert units to points (1in = 72pt, 1cm = 28pt) */
+
+  /* have kapa convert physical units to screen units 
+     for now, fixed at 96 pix / in == 38 pix / cm
+  */
+
+  NX = strtod (argv[1], &end);
+  if (!strcmp (end, "in")) { NX *= 96; }
+  if (!strcmp (end, "cm")) { NX *= 38; }
+
+  NY = strtod (argv[2], &end);
+  if (!strcmp (end, "in")) { NY *= 96; }
+  if (!strcmp (end, "cm")) { NY *= 38; }
+
+  KiiResize (kapa, NX, NY);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/roll.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/roll.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/roll.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "data.h"
+
+int roll (int argc, char **argv) {
+  
+  int Nbytes, Nextra;
+  int dX, dx, dy, nx, ny;
+  Buffer *buf;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: roll <buffer> dx dy\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  dx = atof (argv[2]);
+  dy = atof (argv[3]);
+  if (dy != 0) {
+    gprint (GP_ERR, "only x rolls implemented for now\n");
+  }
+
+  /* if (dx < 0), we are moving the start position back by dx pixels,
+     if (dx > 0), we are moving the start position forward by dx pixels */
+  
+  nx = buf[0].matrix.Naxis[0];
+  ny = buf[0].matrix.Naxis[1];
+
+  dX = abs(dx);
+  Nbytes = nx * ny * sizeof (float);
+  Nextra = (nx * ny + dX) * sizeof (float);
+
+  REALLOCATE (buf[0].matrix.buffer, char, Nextra);
+
+  if (dx < 0) {
+    memmove (buf[0].matrix.buffer, &buf[0].matrix.buffer[dX*sizeof(float)], Nbytes);
+  } else {
+    memmove (&buf[0].matrix.buffer[dX*sizeof(float)], buf[0].matrix.buffer, Nbytes);
+  }
+
+  REALLOCATE (buf[0].matrix.buffer, char, Nbytes);
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rotate.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rotate.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/rotate.c	(revision 16632)
@@ -0,0 +1,298 @@
+# include "data.h"
+
+int rotate (int argc, char **argv) {
+  
+  int i, j, NX, NY, X, Y, Lx, Ly, N, newCenter;
+  float *in_buff, *out_buff, *c;
+  double angle, CosAngle, SinAngle, Xo, Yo, dX, dY, fx, fy, x, y, X1, Y1;
+  double pc11, pc12, pc21, pc22, PC11, PC12, PC21, PC22;
+  Buffer *buf;
+
+  Xo = 0;
+  Yo = 0;
+  if ((N = get_argument (argc, argv, "-center"))) {
+    newCenter = TRUE;
+    remove_argument (N, &argc, argv);
+    Xo  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Yo  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  else 
+    newCenter  = FALSE;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: rotate <buffer> <angle>\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if ((atof (argv[1]) < -180) || (atof (argv[1]) > 180)) {
+    gprint (GP_ERR, "valid rotate angle between -180 and +180 degrees\n");
+    return (FALSE);
+  }
+
+  /* save starting values */
+  NX = buf[0].header.Naxis[0];
+  NY = buf[0].header.Naxis[1];
+  in_buff = (float *) buf[0].matrix.buffer;  /* don't lose reference */
+
+  if (!strcasecmp (argv[2], "LEFT") || (atof (argv[2]) == -90)) {
+    buf[0].header.Naxis[0] = NY;
+    buf[0].header.Naxis[1] = NX;
+    gfits_modify (&buf[0].header, "NAXIS1", "%d", 1, NY);
+    gfits_modify (&buf[0].header, "NAXIS2", "%d", 1, NX);
+    gfits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (i = NX - 1; i > -1; i--) {
+      for (j = 0; j < NY; j++, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    gfits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    gfits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = Yo;
+    Y1 = NX - Xo;
+    gfits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    gfits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    gfits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    gfits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    gfits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    gfits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = pc21;
+    PC12 = pc22;
+    PC21 = -pc11;
+    PC22 = -pc12;
+    gfits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    gfits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    gfits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    gfits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "RIGHT") || (atof (argv[2]) == 90)) {
+    buf[0].header.Naxis[0] = NY;
+    buf[0].header.Naxis[1] = NX;
+    gfits_modify (&buf[0].header, "NAXIS1", "%d", 1, NY);
+    gfits_modify (&buf[0].header, "NAXIS2", "%d", 1, NX);
+    gfits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (i = 0; i < NX; i++) {
+      for (j = NY - 1; j > -1; j--, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    gfits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    gfits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = NY - Yo;
+    Y1 = Xo;
+    gprint (GP_ERR, "%f %f -> %f %f\n", Xo, Yo, X1, Y1);
+    gfits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    gfits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    gfits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    gfits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    gfits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    gfits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = -pc21;
+    PC12 = -pc22;
+    PC21 = pc11;
+    PC22 = pc12;
+    gprint (GP_ERR, "%f %f  ->  %f %f\n", pc11, pc12, PC11, PC12);
+    gprint (GP_ERR, "%f %f  ->  %f %f\n", pc21, pc22, PC21, PC22);
+    gfits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    gfits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    gfits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    gfits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "UPSIDE") || (atof (argv[2]) == -180) || (atof (argv[2]) == 180)) {
+    gfits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (j = NY - 1; j > -1; j--) {
+      for (i = NX - 1; i > -1; i--, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    gfits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    gfits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = NX - Xo;
+    Y1 = NY - Yo;
+    gfits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    gfits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    gfits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    gfits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    gfits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    gfits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = -pc11;
+    PC12 = -pc12;
+    PC21 = -pc21;
+    PC22 = -pc22;
+    gfits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    gfits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    gfits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    gfits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "FLIPY")) {
+    gfits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (j = NY - 1; j > -1; j--) {
+      for (i = 0; i < NX; i++, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    gfits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    gfits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = Xo;
+    Y1 = NY - Yo;
+    gfits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    gfits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    gfits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    gfits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    gfits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    gfits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = pc11;
+    PC12 = -pc12;
+    PC21 = pc21;
+    PC22 = -pc22;
+    gfits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    gfits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    gfits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    gfits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[2], "FLIPX")) {
+    gfits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+    gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+    out_buff = (float *)buf[0].matrix.buffer;
+    for (j = 0; j < NY; j++) {
+      for (i = NX - 1; i > -1; i--, out_buff++) {
+	*out_buff = in_buff[i + j*NX];
+      }
+    }
+    /* fix reference pixel */
+    gfits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+    gfits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+    X1 = NX - Xo;
+    Y1 = Yo;
+    gfits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+    gfits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+    
+    /* fix rotate matrix */
+    gfits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+    gfits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+    gfits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+    gfits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+    PC11 = -pc11;
+    PC12 = pc12;
+    PC21 = -pc21;
+    PC22 = pc22;
+    gfits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+    gfits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+    gfits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+    gfits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+    free (in_buff);
+    return (TRUE);
+  }
+
+  angle = atof (argv[2]);
+  CosAngle = cos (angle*RAD_DEG);
+  SinAngle = sin (angle*RAD_DEG);
+  
+  gprint (GP_ERR, "rotating: %f %f %f\n", angle, CosAngle, SinAngle);
+
+  Lx = NX*fabs(CosAngle) + NY*fabs(SinAngle);
+  Ly = NX*fabs(SinAngle) + NY*fabs(CosAngle);
+  dX = MAX(0,NY*SinAngle);
+  dY = MAX(0,-NX*SinAngle);
+  /*
+  gprint (GP_ERR, "%f %f  -->  ", Xo, Yo);
+  X1 = Xo*CosAngle - Yo*SinAngle + dX;
+  Y1 =  Xo*SinAngle + Yo*CosAngle + dY;
+  gprint (GP_ERR, "%f %f\n", X1, Y1);
+  */
+
+  /* fix reference pixel */
+  gfits_scan (&buf[0].header, "CRPIX1", "%lf", 1, &Xo);
+  gfits_scan (&buf[0].header, "CRPIX2", "%lf", 1, &Yo);
+  /*
+  X1 = (Xo - dX)*CosAngle - (Yo - dY)*SinAngle;
+  Y1 = (dX - Xo)*SinAngle + (Yo - dY)*CosAngle;
+  */
+  X1 = Xo*CosAngle - Yo*SinAngle + dX;
+  Y1 =  Xo*SinAngle + Yo*CosAngle + dY;
+  gfits_modify (&buf[0].header, "CRPIX1", "%lf", 1, X1);
+  gfits_modify (&buf[0].header, "CRPIX2", "%lf", 1, Y1);
+
+  /* fix rotate matrix */
+  gfits_scan (&buf[0].header, "PC001001", "%lf", 1, &pc11);
+  gfits_scan (&buf[0].header, "PC001002", "%lf", 1, &pc12);
+  gfits_scan (&buf[0].header, "PC002001", "%lf", 1, &pc21);
+  gfits_scan (&buf[0].header, "PC002002", "%lf", 1, &pc22);
+  PC11 = pc11*CosAngle - pc21*SinAngle;
+  PC12 = pc12*CosAngle - pc22*SinAngle;
+  PC21 = pc21*CosAngle + pc11*SinAngle;
+  PC22 = pc22*CosAngle + pc12*SinAngle;
+  gfits_modify (&buf[0].header, "PC001001", "%le", 1, PC11);
+  gfits_modify (&buf[0].header, "PC001002", "%le", 1, PC12);
+  gfits_modify (&buf[0].header, "PC002001", "%le", 1, PC21);
+  gfits_modify (&buf[0].header, "PC002002", "%le", 1, PC22);
+
+  buf[0].header.Naxis[0] = Lx;
+  buf[0].header.Naxis[1] = Ly;
+  gfits_modify (&buf[0].header, "NAXIS1", "%d", 1, Lx);
+  gfits_modify (&buf[0].header, "NAXIS2", "%d", 1, Ly);
+  gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+  gfits_print  (&buf[0].header, "HISTORY", "%S", 1, "WARNING: rotated image!");
+  out_buff = (float *)buf[0].matrix.buffer;
+  for (j = 0; j < Ly; j++) {
+    for (i = 0; i < Lx; i++, out_buff++) {
+
+      x = (i - dX)*CosAngle + (j - dY)*SinAngle;
+      y = (dX - i)*SinAngle + (j - dY)*CosAngle;
+      X = (int) x;
+      Y = (int) y;
+
+      if (X < 0) continue;
+      if (X >= NX - 1) continue;
+      if (Y < 0) continue;
+      if (Y >= NY - 1) continue;
+
+      c = &in_buff[X * NX*Y];
+      fx = x - X;
+      fy = y - Y;
+      *out_buff = (c[0]*(1-fx) + c[1]*fx)*(1-fy) + (c[NX+1]*fx + c[NX]*(1-fx))*fy;
+    }
+  }
+  free (in_buff);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/save.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/save.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/save.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "data.h"
+
+int save (int argc, char **argv) {
+  
+  int N, celestial;
+  int kapa;
+  char *name;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  celestial = FALSE;
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    celestial = TRUE;
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: save (overlay) <filename> [-c]\n");
+    gprint (GP_ERR, "  -c: write contour in celestial coords\n");
+    return (FALSE);
+  }
+
+  KiiSaveOverlay (kapa, celestial, argv[1], argv[2]);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/section.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/section.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/section.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include "data.h"
+
+enum {NONE, LIST, UP, DOWN, TOP, BOTTOM, TOOL};
+
+int section (int argc, char **argv) {
+  
+  int N, action, kapa;
+  char *name, *location;
+  Graphdata graphmode;
+  KapaSection section;
+
+  action = NONE;
+  if ((N = get_argument (argc, argv, "-list"))) {
+    action = LIST;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-up"))) {
+    action = UP;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-down"))) {
+    action = DOWN;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-top"))) {
+    action = TOP;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-bottom"))) {
+    action = BOTTOM;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-imtool"))) {
+    action = TOOL;
+    remove_argument (N, &argc, argv);
+    location = argv[N];
+    remove_argument (N, &argc, argv);
+  }
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetGraph (&graphmode, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  /* list sections */
+  if ((argc == 1) && (action == NONE)) {
+    KapaGetSection (kapa, "*");
+    gprint (GP_ERR, "USAGE: section name [x y dx dy] [options]\n");
+    gprint (GP_ERR, "OPTIONS: -list   : show properties of all sections\n");
+    gprint (GP_ERR, "         -up     : move section up in display stack\n");
+    gprint (GP_ERR, "         -down   : move section down in display stack\n");
+    gprint (GP_ERR, "         -top    : move section to top of display stack\n");
+    gprint (GP_ERR, "         -bottom : move section to bottom of display stack\n");
+    gprint (GP_ERR, "         -imtool (position) : set location of image zoom / status box\n");
+    gprint (GP_ERR, "                 (position may be: -x, +x, -y, +y, none)\n");
+    return (TRUE);
+  } 
+  
+  if (argc == 2) {
+    /* select / show section */
+    switch (action) {
+      case NONE:
+	KapaSelectSection (kapa, argv[1]);
+	break;
+
+      case UP:
+	KapaMoveSection (kapa, argv[1], "up");
+	break;
+      case DOWN:
+	KapaMoveSection (kapa, argv[1], "down");
+	break;
+      case TOP:
+	KapaMoveSection (kapa, argv[1], "top");
+	break;
+      case BOTTOM:
+	KapaMoveSection (kapa, argv[1], "bottom");
+	break;
+
+      case TOOL:
+	if (!strcmp(location, "-x")) {
+	  KapaSetToolbox (kapa, 1);
+	  break;
+	}
+	if (!strcmp(location, "+x")) {
+	  KapaSetToolbox (kapa, 3);
+	  break;
+	}
+	if (!strcmp(location, "-y")) {
+	  KapaSetToolbox (kapa, 2);
+	  break;
+	}
+	if (!strcmp(location, "+y")) {
+	  KapaSetToolbox (kapa, 4);
+	  break;
+	}
+	if (!strcmp(location, "none")) {
+	  KapaSetToolbox (kapa, 0);
+	  break;
+	}
+	gprint (GP_ERR, "unknown toolbox location %s\n", location);
+	gprint (GP_ERR, "valid values: -x, +x, -y, +y, none\n");
+	return (FALSE);
+
+      case LIST:
+	KapaGetSection (kapa, argv[1]);
+	break;
+    }
+    return (TRUE);
+  } 
+  
+  if (argc == 6) {
+    /* set section */
+    section.name = argv[1];
+    section.x = atof (argv[2]);
+    section.y = atof (argv[3]);
+    section.dx = atof (argv[4]);
+    section.dy = atof (argv[5]);
+    KapaSetSection (kapa, &section);
+    return (TRUE);
+  }
+  gprint (GP_ERR, "USAGE: section name [x y dx dy]\n");
+  gprint (GP_ERR, "USAGE: section name [-list] [-up] [-down] [-top] [-bottom]\n");
+  return (FALSE);
+}
+
+/* should do some range checking on x y dx dy
+   should be between 0.0 and 1.0, precision of 0.001
+   is sufficient
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/select.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/select.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/select.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "data.h"
+
+int vect_select (int argc, char **argv) {
+  
+  int  i, size;
+  char *out;
+  Vector *in1, *in2, *tvec, *ovec;
+
+  out = NULL;
+  in1 = in2 = ovec = tvec = NULL;
+
+  /** check basic syntax **/
+  if ((argc != 8) || strcmp(argv[2], "=") || strcmp (argv[4], "if") || strcmp (argv[6], "else")) {
+    gprint (GP_ERR, "SYNTAX: select vec = vec if (logic expression) else vec\n");
+    return (FALSE);
+  }
+  if ((in1  = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((in2  = SelectVector (argv[7], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  out = dvomath (argc - 5, &argv[5], &size, 1);
+  if (out == NULL) {
+    print_error ();
+    goto error;
+  }
+  if ((tvec = SelectVector (out, OLDVECTOR, TRUE)) == NULL) goto error;
+  /* check size of in1, in2, tvec: must match */
+
+  REALLOCATE (ovec[0].elements, float, MAX (tvec[0].Nelements, 1));
+  for (i = 0; i < tvec[0].Nelements; i++) {
+    ovec[0].elements[i] = tvec[0].elements[i] ? in1[0].elements[i] : in2[0].elements[i];
+  }
+  ovec[0].Nelements = tvec[0].Nelements;
+  REALLOCATE (ovec[0].elements, float, MAX (ovec[0].Nelements, 1));
+  
+  DeleteVector (tvec);
+  free (out);
+  return (TRUE);
+
+ error:
+  DeleteVector (tvec);
+  DeleteVector (ovec);
+  DeleteNamedVector (out);
+  free (out);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/set.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/set.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/set.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "data.h"
+
+int set (int argc, char **argv) {
+  
+  int size;
+  char *out;
+
+  /** check basic form for line **/
+  if ((argc < 3) || strcmp(argv[2], "=")) {
+    gprint (GP_ERR, "%s = (matrix expression)\n", argv[0]);
+    return (FALSE);
+  }
+
+  out = dvomath (argc - 3, &argv[3], &size, -1);
+  if (out == NULL) {
+    print_error ();
+    return (FALSE);
+  }
+  
+  switch (size) {
+    case 0:
+      set_str_variable (argv[1], out);
+      free (out);
+      break;
+
+    case 1:
+      if (!MoveNamedVector (argv[1], out)) {
+	DeleteNamedVector (out);
+	free (out);
+	gprint (GP_ERR, "invalid output vector name\n");
+	return (FALSE);
+      }
+      free (out);
+      break;
+  
+    case 2:
+      if (!MoveNamedBuffer (argv[1], out)) {
+	DeleteNamedBuffer (out);
+	free (out);
+	gprint (GP_ERR, "invalid output matrix name\n");
+	return (FALSE);
+      }
+      free (out);
+      break;
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/shift.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/shift.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/shift.c	(revision 16632)
@@ -0,0 +1,110 @@
+# include "data.h"
+
+int shift (int argc, char **argv) {
+ 
+  int i, j, N, ROLL;
+  int nx, ny, dx, dy, DXin, DXot, DYin, DYot;
+  float *Vin, *Vot;
+  double Dx, Dy, fdx, fdy;
+  Buffer *in, *out;
+
+  ROLL = FALSE;
+  if ((N = get_argument (argc, argv, "-roll"))) {
+    remove_argument (N, &argc, argv);
+    ROLL = TRUE;
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: shift (input) (output) dx dy\n");
+    return (FALSE);
+  }
+
+  // define the input buffer and examine the shift
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Dx = atof (argv[3]);
+  Dy = atof (argv[4]);
+
+  dx = Dx;
+  dy = Dy;
+  fdx = Dx - dx;
+  fdy = Dy - dy;
+  if (fdx < -0.000001) {dx -= 1; fdx += 1;}
+  if (fdy < -0.000001) {dy -= 1; fdy += 1;}
+  // we always specify a positive fractional shift
+  // the above choice defines a minimum fractional shift of 1e-5
+
+  nx = in[0].matrix.Naxis[0];
+  ny = in[0].matrix.Naxis[1];
+
+  if ((dx > nx) || (dy > ny)) {
+    gprint (GP_ERR, "shifting data out of image\n");
+    return (FALSE);
+  }
+  
+  // define the output buffer
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  gfits_free_matrix (&out[0].matrix);
+  gfits_free_header (&out[0].header);
+  CreateBuffer (out, nx, ny, -32, 0.0, 1.0);
+
+  DXin = (dx < 0) ? -dx : 0;
+  DXot = (dx < 0) ?   0 : dx;
+  DYin = (dy < 0) ? -dy : 0;
+  DYot = (dy < 0) ?   0 : dy;
+  
+  for (j = 0; j < ny - abs(dy); j++) {
+    Vin = (float *)(in[0].matrix.buffer)  + (j + DYin)*nx + DXin;  
+    Vot = (float *)(out[0].matrix.buffer) + (j + DYot)*nx + DXot; 
+    for (i = 0; i < nx - abs(dx); i++, Vin++, Vot++) {
+      *Vot = *Vin;
+    }
+    // fill in the exposed x-border with 0.0
+    Vot = (dx > 0) ? 
+      (float *)(out[0].matrix.buffer) + (j + DYot)*nx : 
+      (float *)(out[0].matrix.buffer) + (j + DYot)*nx + nx - abs(dx);
+    for (i = 0; i < abs(dx); i++, Vot++) {
+      *Vot = 0.0;
+    }	
+  }
+
+  // fill in the exposed y-border with 0.0
+  Vot = (dy > 0) ? 
+    (float *)(out[0].matrix.buffer) :
+    (float *)(out[0].matrix.buffer) + (ny - abs(dy))*nx;
+
+  for (j = 0; j < nx * abs(dy); j++, Vot++) {
+    *Vot = 0.0;
+  }   
+
+  // apply the fractional shift 
+  gprint (GP_ERR, "%f %f\n", fdx, fdy);
+  if ((fdx > 0) || (fdy > 0)) {
+    double f00, f01, f10, f11;
+    float value;
+
+    f00 = (1-fdx)*(1-fdy);
+    f01 =    fdx *(1-fdy);
+    f10 = (1-fdx)*   fdy;
+    f11 =    fdx *   fdy;
+
+    Vin = (float *)out[0].matrix.buffer;
+    Vot = (float *)out[0].matrix.buffer;
+    for (j = 0; j < ny - 1; j++) {
+      for (i = 0; i < nx - 1; i++, Vin++, Vot++) {
+	value  = Vin[   0] * f00;
+	value += Vin[   1] * f01;
+	value += Vin[nx  ] * f10;
+	value += Vin[nx+1] * f11;
+	*Vot = value;
+      }
+      Vin ++;
+      Vot ++;
+    }
+  }   
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/sort.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/sort.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/sort.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "data.h"
+
+int sort_vectors (int argc, char **argv) {
+  
+  int i, j, Nvec, Nval;
+  float *temp, *index, *T, *V, *I;
+  Vector **vec;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: sort (vector) [vectors ...] \n");
+    gprint (GP_ERR, "  first vector is sort key for others\n");
+    return (FALSE);
+  }
+
+  Nvec = (argc - 1);
+  ALLOCATE (vec, Vector *, Nvec);
+
+  Nval = 0;
+  /* find vectors and check sizes */
+  for (i = 0; i < Nvec; i++) {
+    if ((vec[i] = SelectVector (argv[i + 1], OLDVECTOR, FALSE)) == NULL) {
+      gprint (GP_ERR, "USAGE: sort vector vector ...\n");
+      free (vec);
+      return (FALSE);    
+    }
+    if (i == 0) {
+      Nval = vec[i][0].Nelements;
+    } else {
+      if (Nval != vec[i][0].Nelements) {
+	free (vec);
+	gprint (GP_ERR, "vectors must all be same length\n");
+	return (FALSE);
+      }
+    }
+  }
+  
+  /* create index (use float to use sortpair) */
+  ALLOCATE (index, float, Nval);
+  for (i = 0; i < Nval; i++) index[i] = i;
+
+  /* sort key & index */
+  fsortpair (vec[0][0].elements, index, Nval);
+
+  ALLOCATE (temp, float, Nval);
+  for (i = 1; i < Nvec; i++) {
+    T = temp;
+    V = vec[i][0].elements;
+    I = index;
+    for (j = 0; j < Nval; j++, T++, I++) {
+      *T = V[(int)(*I)];
+    }
+    /* swap .elements (== V) and temp */ 
+    vec[i][0].elements = temp;
+    temp = V;
+  }
+  free (temp);
+  free (vec);
+  free (index);
+
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/spline_apply.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/spline_apply.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/spline_apply.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "data.h"
+
+// need to rename this as an image function
+int spline_apply_cmd (int argc, char **argv) {
+  
+  int i, j, I, J;
+  int nx, ny, Nx, Ny, xdir;
+  float rx, ry, x, y;
+  float *Tx1, *Tx2, *Txc, *Ty1, *Ty2, *Tyc, *V, *V1, *V2;
+  Buffer *out, *y1, *y2;
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: spline_apply <Y> <Y2> <out> (x/y) Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((y1  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((y2  = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[3], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  xdir = FALSE;
+  if (!strcmp (argv[4], "x")) xdir = TRUE; 
+
+  nx = atoi (argv[5]);
+  ny = atoi (argv[6]);
+
+  Nx = y1[0].matrix.Naxis[0];
+  Ny = y1[0].matrix.Naxis[1];
+
+  rx = Nx / (float) nx;
+  ry = Ny / (float) ny;
+
+  /* create an output matrix buffer with desired nx, ny */
+  gfits_free_matrix (&out[0].matrix);
+  gfits_free_header (&out[0].header);
+
+  out[0].bitpix = y1[0].bitpix;
+  out[0].unsign = y1[0].unsign;
+  out[0].bscale = y1[0].bscale;
+  out[0].bzero  = y1[0].bzero;
+  gfits_copy_header (&y1[0].header, &out[0].header);
+  gfits_modify (&out[0].header, "NAXIS1", "%d", 1, nx);
+  gfits_modify (&out[0].header, "NAXIS2", "%d", 1, ny);
+
+  out[0].header.Naxis[0] = nx;
+  out[0].header.Naxis[1] = ny;
+  gfits_create_matrix (&out[0].header, &out[0].matrix);
+  if ((y1[0].file[0] != '*') && (y1[0].file[0] != '(')) {
+    sprintf (out[0].file, "*%s", y1[0].file);
+  } else {
+    sprintf (out[0].file, "%s", y1[0].file);
+  }
+
+  ALLOCATE (Ty2, float, Ny);
+  ALLOCATE (Ty1, float, Ny);
+  ALLOCATE (Tyc, float, Ny);
+  for (i = 0; i < Ny; i++) { Tyc[i] = i; }
+
+  ALLOCATE (Tx1, float, Nx);
+  ALLOCATE (Tx2, float, Nx);
+  ALLOCATE (Txc, float, Nx);
+  for (i = 0; i < Nx; i++) { Txc[i] = i; }
+
+  V = (float *)(out[0].matrix.buffer);
+
+  for (J = 0; J < ny; J++) {
+    y = J * ry;
+
+    /* construct spline for each element in this row */
+    for (i = 0; i < Nx; i++) {
+      V1 = (float *)(y1[0].matrix.buffer) + i;
+      V2 = (float *)(y2[0].matrix.buffer) + i;
+      for (j = 0; j < Ny; j++, V1+=Nx, V2+=Nx) {
+	Ty1[j] = *V1;
+	Ty2[j] = *V2;
+      }
+      Tx1[i] = spline_apply (Tyc, Ty1, Ty2, Ny, y);
+    }
+    spline_construct (Txc, Tx1, Nx, Tx2);
+
+    /* apply x-dir spline to new image */
+    for (I = 0; I < nx; I++, V++) {
+      x = I * rx;
+      *V = spline_apply (Txc, Tx1, Tx2, Nx, x);
+    }
+  }
+
+  free (Ty1);
+  free (Ty2);
+  free (Tyc);
+  
+  free (Tx1);
+  free (Tx2);
+  free (Txc);
+  
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/spline_construct.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/spline_construct.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/spline_construct.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "data.h"
+
+// need to rename this as an image function
+int spline_construct_cmd (int argc, char **argv) {
+  
+  int i, j, Nx, Ny, xdir;
+  float *Tx, *Ty, *Ty2, *V;
+  Buffer *in, *out;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: spline_construct <in> <out> (x/y)\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  free (out[0].matrix.buffer);
+  free (out[0].header.buffer);
+  if ((in[0].file[0] != '*') && (in[0].file[0] != '(')) {
+    sprintf (out[0].file, "*%s", in[0].file);
+  } else {
+    sprintf (out[0].file, "%s", in[0].file);
+  }
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  gfits_copy_matrix_info (&in[0].matrix, &out[0].matrix);
+  gfits_copy_header (&in[0].header, &out[0].header);
+  gfits_create_matrix (&out[0].header, &out[0].matrix);
+
+  xdir = FALSE;
+  if (!strcmp (argv[3], "x")) xdir = TRUE; 
+  /* ideally, the resulting image should carry this info (in header?) */
+
+  Nx = in[0].matrix.Naxis[0];
+  Ny = in[0].matrix.Naxis[1];
+
+  ALLOCATE (Ty2, float, Ny);
+  ALLOCATE (Ty, float, Ny);
+  ALLOCATE (Tx, float, Ny);
+
+  /** for now only perform the operation for the ydir splines */
+
+  /* construct coordinate vector */
+  for (j = 0; j < Ny; j++) { Tx[j] = j; }
+  
+  for (i = 0; i < Nx; i++) {
+    
+    /* construct temp vector with values to spline */
+    V = (float *)(in[0].matrix.buffer) + i;
+    for (j = 0; j < Ny; j++, V+=Nx) {
+      Ty[j] = *V;
+    }
+  
+    spline_construct (Tx, Ty, Ny, Ty2);
+  
+    /* copy derivatives to output buffer */
+    V = (float *)(out[0].matrix.buffer) + i;
+    for (j = 0; j < Ny; j++, V+=Nx) {
+      *V = Ty2[j];
+    }
+  }
+
+  free (Tx);
+  free (Ty);
+  free (Ty2);
+  
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/stats-new.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/stats-new.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/stats-new.c	(revision 16632)
@@ -0,0 +1,259 @@
+# include "data.h"
+
+double interpolateValue (int *hist, int Nbins, float min, float binsize, int bin, float value);
+double sampleMedian (Matrix *matrix, int Nsubset);
+Stats *robustMedian (Matrix *matrix, Region *region, float minValue, float maxValue, float sigma);
+
+typedef struct {
+  int sx;
+  int sy;
+  int nx;
+  int ny;
+} Region;
+
+typedef struct {
+  float median;
+  float mean;
+  float mode;
+  float sigma;
+} Stats;
+
+int stats (int argc, char **argv) {
+  
+  int i, j, Nmode, Imode;
+  double Npix, N1, N2, max, min, range, median, mode, IgnoreValue;
+  float *V;
+  int sx, sy, nx, ny, *hist, Nhist, bin;
+  int Ignore, Quiet, N;
+  Buffer *buf;
+
+  IgnoreValue = 0;
+  Ignore = FALSE;
+  if ((N = get_argument (argc, argv, "-ignore"))) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 2) && (argc != 6)) {
+    gprint (GP_ERR, "USAGE: stats <buffer> sx sy nx ny\n");
+    gprint (GP_ERR, "OR:    stats <buffer>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (argc == 6) {
+    sx = strcmp (argv[2], "-") ? atof (argv[2]) : 0;
+    sy = strcmp (argv[3], "-") ? atof (argv[3]) : 0;
+    nx = strcmp (argv[4], "-") ? atof (argv[4]) : buf[0].matrix.Naxis[0];
+    ny = strcmp (argv[5], "-") ? atof (argv[5]) : buf[0].matrix.Naxis[1];
+  } else {
+    sx = 0;
+    sy = 0;
+    nx = buf[0].matrix.Naxis[0];
+    ny = buf[0].matrix.Naxis[1];
+  }
+
+  Npix = N1 = N2 = 0;
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+
+  max = min = *((float *)(buf[0].matrix.buffer) + sy*buf[0].matrix.Naxis[0] + sx);
+  for (j = sy; j < sy + ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+      N1 += *V;
+      N2 += (*V)*(*V);
+      Npix += 1.0;
+      max = MAX (max, *V);
+      min = MIN (min, *V);
+    }
+  }
+  N1 = N1 / Npix;
+
+  sigma = sqrt (N2/Npix - N1*N1);
+
+  if (ROBUST) {
+    stats = robustMedian (matrix, min, max, sigma);
+    if (stats->sigma 
+  } 
+  
+  if (!Quiet) {
+    gprint (GP_LOG, "  mean    stdev    min     max   median   Npix   Total\n");
+    gprint (GP_LOG, "%7.4g %7.4g %7.4g %7.4g %7.4g %7.0f %7.4g\n", N1, sqrt (N2/Npix - N1*N1), 
+	    min, max, median, Npix, Npix*N1);
+  }
+
+  set_variable ("MIN",    min);
+  set_variable ("MAX",    max);
+  set_variable ("MEDIAN", median);
+  set_variable ("MEAN",   N1);
+  set_variable ("MODE",   mode);
+  set_variable ("TOTAL",  N1*Npix);
+  set_variable ("NPIX",   Npix);
+  set_variable ("SIGMA",  sqrt (N2/Npix - N1*N1));
+
+  return (TRUE);
+}
+
+double sampleMedian (Matrix *matrix, int Nsubset) {
+
+  int i, Nsample, Npix;
+  long A, B;
+  float *values, *buffer, median;
+
+  /* Generate a vector of Nsample elements */
+  Npix = matrix[0].Naxis[0]*matrix[0].Naxis[1]
+    Nsample = Nsubset;
+  if (Nsubset == 0) {
+    Nsample = Npix;
+  }
+
+  ALLOCATE (values, float, Nsample);
+    
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+ 
+  *buffer = (float *) matrix[0].buffer;
+
+  for (i = 0; i < Nsample; i++) {
+    if (Nsubset) {
+      j = MIN(Npix - 1, MAX(0, Npix*drand48()));
+    } else {
+      j = i;
+    }
+    values[i] = buffer[j];
+  }
+    
+  fsort (values, Nsample);
+
+  if (Nsample == 0) return 0.0;
+
+  // these are all covered by the logic below
+  // if (Nsample == 1) return values[0];
+  // if (Nsample == 2) return (0.5*(values[0] + values[1]));
+  // if (Nsample == 3) return (values[1]);
+
+  if (Nsample % 2) {
+    median = 0.5*(values[(int)(0.5*Nsample)] + values[(int)(0.5*Nsample) - 1]);
+  } else {
+    median = values[(int)(0.5*Nsample)];
+  }
+  return (median);
+}
+
+Stats *robustMedian (Matrix *matrix, Region *region, float minValue, float maxValue, float sigma) {
+
+  Stats *stats;
+
+  ALLOCATE (stats, Stats, 1);
+
+  // no data range:
+  if (maxValue - minValue < FLT_EPSILON) {
+    stats->median = minValue;
+    stats->mean   = minValue;
+    stats->mode   = minValue;
+    stats->sigma  = 0.0;
+    return stats;
+  }
+
+  // generate a histogram ranging from min to max with step size of sigma / 4
+  // no more than 0x1000 bins, no less than 0x10
+
+  Nbins = 4.0 * (maxValue - minValue) / sigma;
+  Nbins = MIN (0x1000, MAX (0x10, Nbins));
+
+  ALLOCATE (hist, int, Nbins);
+  memset (hist, 0, Nbins*sizeof(int));
+  
+  delta = Nbins / (max - min);
+  binsize = 1.0 / delta;
+
+  Ntotal = 0;
+  for (j = region->sy; j < region->sy + region->ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + region->sx; 
+    for (i = 0; i < region->nx; i++, V++) {
+      if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+      bin = MIN (MAX (0, (*V - min) * delta), Nbins - 1);
+      hist[bin] ++;
+      Ntotal ++;
+    }
+  }
+
+  // generate the cumulative histogram & find mode
+  ALLOCATE (cumu, int, Nbins);
+  memset (cumu, 0, Nbins*sizeof(int));
+
+  Nhist = 0;
+  Imode = -1;
+  Vmode = 0;
+  for (i = 0; i < Nbins; i++) {
+    Nhist += hist[i];
+    cumu[i] = Nhist;
+    if (hist[i] > Vmode) {
+      Imode = i;
+      Vmode = hist[i];
+    }
+  }
+
+  Ioo = ibracket (cumu, Nbins, 0.500000*Nhist, 1);
+  Im1 = ibracket (cumu, Nbins, 0.308538*Nhist, 1);
+  Ip1 = ibracket (cumu, Nbins, 0.691462*Nhist, 1);
+  Im2 = ibracket (cumu, Nbins, 0.022481*Nhist, 1);
+  Ip2 = ibracket (cumu, Nbins, 0.977519*Nhist, 1);
+
+  Voo = interpolateValue (cumu, Nbins, min, delta, Ioo, 0.500000*Nhist);
+  Vm1 = interpolateValue (cumu, Nbins, min, delta, Im1, 0.308538*Nhist);
+  Vp1 = interpolateValue (cumu, Nbins, min, delta, Ip1, 0.691462*Nhist);
+  Vm2 = interpolateValue (cumu, Nbins, min, delta, Im2, 0.022481*Nhist);
+  Vp2 = interpolateValue (cumu, Nbins, min, delta, Ip2, 0.977519*Nhist);
+
+  sigma1 = (Vp1 - Vm1);
+  sigma2 = (Vp2 - Vm2) / 4.0;
+
+  Vs = Vn = 0;
+  for (i = Im1; i < Ip1 + 1; i++) {
+    Vn += hist[i];
+    Vs += hist[i] * (i * binsize + min);
+  }
+
+  stats->median = Voo;
+  stats->mean = Vs / Vn;
+  stats->mode = Imode * delta + min;
+  stats->sigma = MIN (sigma1, sigma2);
+
+  free (hist);
+  free (cumu);
+
+  return (stats);
+}
+
+// what is the fractional bin position for the given value
+double interpolateValue (int *hist, int Nbins, float min, float binsize, int bin, float value) {
+
+  V0 = bin * binsize + min;
+  V1 = (bin + 1) * binsize + min;
+
+  // fbin = (value - V0) / (V1 - V0) + bin;
+  fbin = (value - V0) / binsize + bin;
+
+  return fbin;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/stats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/stats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/stats.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "data.h"
+
+int stats (int argc, char **argv) {
+  
+  int i, j, Nmode, Imode;
+  double Npix, N1, N2, max, min, range, median, mode, IgnoreValue;
+  float *V;
+  int sx, sy, nx, ny, *hist, Nhist, bin;
+  int Ignore, Quiet, N;
+  Buffer *buf;
+
+  IgnoreValue = 0;
+  Ignore = FALSE;
+  if ((N = get_argument (argc, argv, "-ignore"))) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if ((argc != 2) && (argc != 6)) {
+    gprint (GP_ERR, "USAGE: stats <buffer> sx sy nx ny\n");
+    gprint (GP_ERR, "OR:    stats <buffer>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (argc == 6) {
+    sx = strcmp (argv[2], "-") ? atof (argv[2]) : 0;
+    sy = strcmp (argv[3], "-") ? atof (argv[3]) : 0;
+    nx = strcmp (argv[4], "-") ? atof (argv[4]) : buf[0].matrix.Naxis[0];
+    ny = strcmp (argv[5], "-") ? atof (argv[5]) : buf[0].matrix.Naxis[1];
+  } else {
+    sx = 0;
+    sy = 0;
+    nx = buf[0].matrix.Naxis[0];
+    ny = buf[0].matrix.Naxis[1];
+  }
+
+  Npix = N1 = N2 = 0;
+  if ((sx < 0) || (sy < 0) || 
+      (sx+nx > buf[0].matrix.Naxis[0]) || 
+      (sy+ny > buf[0].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region out of range\n");
+    return (FALSE);
+  }
+
+  max = min = *((float *)(buf[0].matrix.buffer) + sy*buf[0].matrix.Naxis[0] + sx);
+  for (j = sy; j < sy + ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) {
+      if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+      N1 += *V;
+      N2 += (*V)*(*V);
+      Npix += 1.0;
+      max = MAX (max, *V);
+      min = MIN (min, *V);
+    }
+  }
+  N1 = N1 / Npix;
+
+/* calculate mode, median */
+  median = mode = 0.5*(max + min);
+  if ((max - min) != 0) {
+    range = 0xffff / (max - min);
+    ALLOCATE (hist, int, 0x10000);
+    bzero (hist, 0x10000*sizeof(int));
+    for (j = sy; j < sy + ny; j++) {
+      V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+      for (i = 0; i < nx; i++, V++) {
+	if (Ignore && (fabs (*V - IgnoreValue) < 1e-8)) continue;
+	bin = MIN (MAX (0, (*V - min) * range), 0xffff);
+	hist[bin] ++;
+      }
+    }
+    Nhist = 0;
+    for (i = 0; (i < 0xffff) && (Nhist < 0.5*Npix); i++) 
+      Nhist += hist[i];
+    median = i / range + min;
+    Nmode = hist[0];
+    Imode = 0;
+    for (i = 1; i < 0x10000; i++) {
+      if (hist[i] > Nmode) {
+	Nmode = hist[i];
+	Imode = i;
+      }
+    }
+    mode = Imode / range + min;
+    free (hist);
+  }  
+  
+  if (!Quiet) {
+    gprint (GP_LOG, "  mean    stdev    min     max   median   Npix   Total\n");
+    gprint (GP_LOG, "%7.4g %7.4g %7.4g %7.4g %7.4g %7.0f %7.4g\n", N1, sqrt (N2/Npix - N1*N1), 
+	    min, max, median, Npix, Npix*N1);
+  }
+
+  set_variable ("MIN",    min);
+  set_variable ("MAX",    max);
+  set_variable ("MEDIAN", median);
+  set_variable ("MEAN",   N1);
+  set_variable ("MODE",   mode);
+  set_variable ("TOTAL",  N1*Npix);
+  set_variable ("NPIX",   Npix);
+  set_variable ("SIGMA",  sqrt (N2/Npix - N1*N1));
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/style.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/style.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/style.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "data.h"
+
+int style (int argc, char **argv) {
+  
+  int kapa;
+  Graphdata data;
+
+  if (!style_args (&data, &argc, argv, &kapa)) return FALSE;
+
+  if (argc > 1) {
+    gprint (GP_ERR, "USAGE: style [-n Ngraph] [-x plot style] [-c color] [-pt point type] [-lt line type] [-lw line width] [-sz size]\n");
+    return (FALSE);
+  }
+  KapaSetGraphData (kapa, &data);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/subraster.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/subraster.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/subraster.c	(revision 16632)
@@ -0,0 +1,86 @@
+# include "data.h"
+
+int subraster (int argc, char **argv) {
+  
+  int i, j;
+  float *Vin, *Vout;
+  int sx, sy, nx, ny;
+  int Sx, Sy, Nx, Ny;
+  int NX, NY;
+  Buffer *ibuf, *obuf;
+
+  if (argc != 11) {
+    gprint (GP_ERR, "USAGE: extract <from> <to> sx sy nx ny Sx Sy Nx Ny\n");
+    return (FALSE);
+  }
+
+  if ((ibuf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  NX = ibuf[0].matrix.Naxis[0];
+  NY = ibuf[0].matrix.Naxis[1];
+
+  sx = atof (argv[3]);
+  sy = atof (argv[4]);
+  nx = atof (argv[5]);
+  ny = atof (argv[6]);
+
+  Sx = atof (argv[7]);
+  Sy = atof (argv[8]);
+  Nx = atof (argv[9]);
+  Ny = atof (argv[10]);
+
+  if ((Sy + ny > Ny) || (Sx + nx > Nx)) {
+    gprint (GP_ERR, "mismatch between source and dest regions\n");
+    gprint (GP_ERR, "%d + %d > %d or %d + %d > %d\n", Sy, ny, Ny, Sx, nx, Nx);
+    return (FALSE);
+  }
+
+  /* region is not on first image */
+  if ((sx + nx < 0) || (sy + ny < 0) || 
+      (sx > ibuf[0].matrix.Naxis[0]) || 
+      (sy > ibuf[0].matrix.Naxis[1])) {
+    gprint (GP_ERR, "region outside of source image\n");
+    return (FALSE);
+  }
+
+  if ((Sx + nx > Nx) || (Sy + ny > Ny)) {
+    gprint (GP_ERR, "source region larger than dest region\n");
+    return (FALSE);
+  }
+  if ((Sx < 0) || (Sy < 0)) {
+    gprint (GP_ERR, "dest region out of range\n");
+    return (FALSE);
+  }
+
+  if ((obuf = SelectBuffer (argv[2], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  gfits_free_matrix (&obuf[0].matrix);
+  gfits_free_header (&obuf[0].header);
+
+  obuf[0].bitpix = ibuf[0].bitpix;
+  obuf[0].unsign = ibuf[0].unsign;
+  obuf[0].bscale = ibuf[0].bscale;
+  obuf[0].bzero  = ibuf[0].bzero;
+  /* strcpy (obuf[0].name, ibuf[0].name); */
+  strcpy (obuf[0].file, ibuf[0].file);
+  gfits_copy_header (&ibuf[0].header, &obuf[0].header);
+  gfits_modify (&obuf[0].header, "NAXIS1", "%d", 1, Nx);
+  gfits_modify (&obuf[0].header, "NAXIS2", "%d", 1, Ny);
+  obuf[0].header.Naxis[0] = Nx;
+  obuf[0].header.Naxis[1] = Ny;
+  gfits_create_matrix (&obuf[0].header, &obuf[0].matrix);
+
+  for (j = 0; j < ny; j++) {
+    if (j + sy < 0) continue;
+    if (j + sy >= NY) continue;
+    Vin = (float *)(ibuf[0].matrix.buffer) + (j + sy)*ibuf[0].matrix.Naxis[0] + sx;  
+    Vout = (float *)(obuf[0].matrix.buffer) + (j + Sy)*obuf[0].matrix.Naxis[0] + Sx;   
+    for (i = 0; i < nx; i++, Vin++, Vout++) {
+      if (i + sx < 0) continue;
+      if (i + sx >= NX) continue;
+      *Vout = *Vin;
+    }
+  }
+
+  return (TRUE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/subset.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/subset.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/subset.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "data.h"
+
+/* need to check dimensions of vectors */
+
+int subset (int argc, char **argv) {
+  
+  char *out;
+  int  i, j, size;
+  Vector *ivec, *ovec, *tvec;
+
+  out = NULL;
+  ivec = ovec = tvec = NULL;
+
+  if ((argc < 6) || strcmp(argv[2], "=") || strcmp (argv[4], "if")) {
+    gprint (GP_ERR, "SYNTAX: subset vec = vec if (logic expression)\n");
+    return (FALSE);
+  }
+
+  if ((ovec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) goto error;
+  if ((ivec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) goto error;
+
+  out = dvomath (argc - 5, &argv[5], &size, 1);
+  if (out == NULL) {
+    print_error ();
+    goto error;
+  }
+  if ((tvec = SelectVector (out, OLDVECTOR, TRUE)) == NULL) goto error;
+  /* check size of ivec, tvec: must match */
+
+  REALLOCATE (ovec[0].elements, float, MAX (tvec[0].Nelements, 1));
+  for (j = i = 0; i < tvec[0].Nelements; i++) {
+    if (tvec[0].elements[i]) {
+      ovec[0].elements[j] = ivec[0].elements[i];
+      j++;
+    }
+  }
+  ovec[0].Nelements = j;
+  REALLOCATE (ovec[0].elements, float, MAX (ovec[0].Nelements, 1));
+
+  DeleteVector (tvec);
+  free (out);
+  return (TRUE);
+
+ error:
+  DeleteVector (tvec);
+  DeleteVector (ovec);
+  DeleteNamedVector (out);
+  free (out);
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/svd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/svd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/svd.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "data.h"
+
+int svd (int argc, char **argv) {
+  
+  int i, Nx, Ny, status;
+  float *in, *out, *A, *U, *W, *V;
+  Vector *Vw;
+  Buffer *Ma, *Mu, *Mv;
+
+  if (argc != 6) goto usage;
+  if (strcmp (argv[2], "=")) goto usage;
+
+  if ((Ma = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Mu = SelectBuffer (argv[3], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((Vw = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((Mv = SelectBuffer (argv[5], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  Nx = Ma[0].header.Naxis[0];
+  Ny = Ma[0].header.Naxis[1];
+
+  /* U is Nx, Ny */
+  gfits_free_matrix (&Mu[0].matrix);
+  gfits_free_header (&Mu[0].header);
+  Mu[0].bitpix = Ma[0].bitpix;
+  Mu[0].unsign = Ma[0].unsign;
+  Mu[0].bscale = Ma[0].bscale;
+  Mu[0].bzero  = Ma[0].bzero;
+  gfits_copy_header (&Ma[0].header, &Mu[0].header);
+  gfits_create_matrix (&Mu[0].header, &Mu[0].matrix);
+  
+  /* V is Nx, Nx */
+  gfits_free_matrix (&Mv[0].matrix);
+  gfits_free_header (&Mv[0].header);
+  Mv[0].bitpix = Ma[0].bitpix;
+  Mv[0].unsign = Ma[0].unsign;
+  Mv[0].bscale = Ma[0].bscale;
+  Mv[0].bzero  = Ma[0].bzero;
+  gfits_copy_header (&Ma[0].header, &Mv[0].header);
+  gfits_modify (&Mv[0].header, "NAXIS2", "%d", 1, Nx);
+  Mv[0].header.Naxis[1] = Nx;
+  gfits_create_matrix (&Mv[0].header, &Mv[0].matrix);
+
+  /* w is Nx */
+  Vw[0].Nelements = Nx;
+  REALLOCATE (Vw[0].elements, float, Nx);
+
+  /* pointers to the various arrays */
+  A = (float *) Ma[0].matrix.buffer;
+  U = (float *) Mu[0].matrix.buffer;
+  W = (float *) Vw[0].elements;
+  V = (float *) Mv[0].matrix.buffer;
+
+  /* copy A to U (svdcmp replaces A with U) */
+  in  = A;
+  out = U;
+  for (i = 0; i < Nx*Ny; i++, in++, out++) *out = *in;
+  /* use a bcopy instead? */
+
+  status = svdcmp (U, W, V, Nx, Ny);
+  if (!status) {
+    gprint (GP_ERR, "error running svdcmp\n");
+    return (FALSE);
+  }
+  return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "USAGE: svd A = U w Vt\n");
+  return (FALSE);
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/swapbytes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/swapbytes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/swapbytes.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "data.h"
+
+int swapbytes (int argc, char **argv) {
+  
+  int i, nx, ny;
+  char *V, tmp;
+  Buffer *buf;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: swapbytes <buffer>\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  nx = buf[0].matrix.Naxis[0];
+  ny = buf[0].matrix.Naxis[1];
+
+  gprint (GP_ERR, "npix: %d\n", nx*ny);
+
+  V = buf[0].matrix.buffer;
+  for (i = 0; i < nx*ny; i++, V+=4) {
+    tmp = V[0]; V[0] = V[3]; V[3] = tmp;
+    tmp = V[1]; V[1] = V[2]; V[2] = tmp;
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/applyfit.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/applyfit.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/applyfit.sh	(revision 16632)
@@ -0,0 +1,51 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if applyfit works
+macro test1
+
+ $PASS = 1
+
+ $Cn = 2
+ $C0 = 4
+ $C1 = -2
+ $C2 = 1
+
+ create x 0 10
+
+ applyfit x y
+
+ if (y[5] != 19)
+  $PASS = 0
+  echo "Value mismatch: y[5]"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  applyfit x y
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/applyfit2d.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/applyfit2d.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/applyfit2d.sh	(revision 16632)
@@ -0,0 +1,55 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if applyfit2d works
+macro test1
+
+ $PASS = 1
+
+ $Cnn = 2
+ $CX0Y0 = 1
+ $CX1Y0 = -4
+ $CX2Y0 = 2
+ $CX1Y1 = -3
+ $CX0Y1 = 1.5
+ $CX0Y2 = -2.5
+
+ create x 0 5 0.01
+ set y = 3*cos(2*3.14159*x/2.25)
+
+ applyfit2d x y z
+
+ if (abs(z[300]-12.625) > 0.001)
+  $PASS = 0
+  echo "Value mismatch: z[300]"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  applyfit2d x y z
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/book.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/book.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/book.sh	(revision 16632)
@@ -0,0 +1,109 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test book commands
+macro test1
+
+ $PASS = 1
+
+ local bname01 bname02 pcheck pname01 pname02 tword01 tword02 wcheck
+
+ book create testb01
+ book create testb02
+ book getbook 0 -var bname01
+ book getbook 1 -var bname02
+
+ if (("$bname01" != "testb01") || ("$bname02" != "testb02"))
+  $PASS = 0
+  echo "Books not created/listed correctly!"
+ end
+
+ book newpage testb01 tpage01
+ book newpage testb01 tpage02
+ book npages testb01 -var pcheck
+ 
+ if ($pcheck != 2)
+  $PASS = 0
+  echo "Book pages not added/recorded correctly!"
+ end
+
+ book getpage testb01 0 -var pname01
+ book getpage testb01 1 -var pname02
+
+ if (("$pname01" != "tpage01") || ("$pname02" != "tpage02"))
+  $PASS = 0
+  echo "Pages not created/listed correctly!"
+ end
+
+ book setword testb01 tpage01 w01 tword01
+ book setword testb01 tpage01 w02 tword02
+ book getword testb01 tpage01 w01 -var wcheck
+
+ if ("$wcheck" != "tword01")
+  $PASS = 0
+  echo "Words not created/listed correctly!"
+ end
+
+ book delpage testb01 tpage02
+ book getpage testb01 1 -var pcheck
+
+ if ("$pcheck" != "NULL")
+  $PASS = 0
+  echo "Book pages not deleted correctly (by delpage)!"
+ end
+
+ book init testb01
+ book getpage testb01 0 -var pcheck
+
+ if ("$pcheck" != "NULL")
+  $PASS = 0
+  echo "Book pages not deleted correctly (by init)!"
+ end
+
+ book delete testb01
+ book delete testb02
+
+# delete bname01 bname02 pcheck pname01 pname02 tword01 tword02 wcheck
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i bcheck pcheck wcheck
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  book create testb
+  book getbook 0 -var bcheck
+  book newpage testb testp1
+  book newpage testb testp2
+  book npages testb -var pcheck
+  book getpage testb 0 -var pcheck
+  book setword testb testp1 testw tada
+  book getword testb testp1 testw -var wcheck
+  book delpage testb testp2
+  book init testb
+  book delete testb
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+#delete i bcheck pcheck wcheck
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/concat.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/concat.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/concat.sh	(revision 16632)
@@ -0,0 +1,48 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Does concat work?
+macro test1
+
+ $PASS = 1
+
+ create a 0 10
+ set b = a
+
+ concat a b
+
+ if ((b[] != 20) || (b[10] != 0))
+  $PASS = 0
+  echo "Concat failed!: nelements: b[] b(10)= b[10]"
+ end
+end
+
+
+# Memory Test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  create a 0 10
+  set b = a
+  concat a b
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/create.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/create.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/create.sh	(revision 16632)
@@ -0,0 +1,44 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test create function
+macro test1
+ 
+ $PASS = 1
+
+ create x 0 10 0.5
+
+ if ((x[1] != 0.5) || (x[9] != 4.5))
+  $PASS = 0
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  create y 0 10 0.1
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/cumulative.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/cumulative.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/cumulative.sh	(revision 16632)
@@ -0,0 +1,46 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Does cumulative work?
+macro test1
+
+ $PASS = 1
+
+ create a 5 15
+
+ cumulative a acum
+
+ if (acum[5] != 45)
+  $PASS = 0
+  echo "Cumulative failed!: nelements: acum[] acum(5)= acum[5]"
+ end
+end
+
+
+# Memory Test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  create a 5 15
+  cumulative a acum
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/cut.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/cut.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/cut.sh	(revision 16632)
@@ -0,0 +1,38 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if cut works
+macro test1
+
+ $PASS = 1
+
+ mcreate tim 100 10
+ zap tim 0 0 100 10 -v 10
+
+ cut tim xdir imx X 40 4 60 6
+ cut tim ydir imy Y 40 4 60 6
+
+ if (xdir[] != 60)
+  $PASS = 0
+ end
+ if (imx[] != 60)
+  $PASS = 0
+ end
+
+ if (ydir[] != 6)
+  $PASS = 0
+ end
+ if (imy[] != 6)
+  $PASS = 0
+ end
+
+ if (imx[0] != 10*6)
+  $PASS = 0
+ end
+ if (imy[0] != 10*60)
+  $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/delete.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/delete.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/delete.sh	(revision 16632)
@@ -0,0 +1,50 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test delete
+macro test1
+
+ $PASS = 1
+
+ $v = 7
+
+# create v 0 10
+
+ delete v
+
+ if ($?v != 0)
+  $PASS = 0
+  echo "Variable not deleted!"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  $u = testing
+  delete u
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/dimendown.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/dimendown.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/dimendown.sh	(revision 16632)
@@ -0,0 +1,60 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if dimendown works
+macro test1
+
+ $PASS = 1
+
+ mcreate timg 100 10
+ zap timg 0 0 100 10 -v 10
+ dimendown timg val
+ dimendown timg xc -x
+ dimendown timg yc -y
+
+ if (val[777] != 10)
+  $PASS = 0
+  echo "Value mismatch: val[777] (should be 10)"
+ end
+
+ if (xc[777] != 77)
+  $PASS = 0
+  echo "X Coord mismatch: xc[777] (should be 77)"
+ end
+
+ if (yc[777] != 7)
+  $PASS = 0
+  echo "Y Coord mismatch: yc[77] (should be 7)"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  dimendown timg val
+  dimendown timg xc -x
+  dimendown timg yc -y
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/dimenup.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/dimenup.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/dimenup.sh	(revision 16632)
@@ -0,0 +1,48 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if dimendown works
+macro test1
+
+ $PASS = 1
+
+ create tvec 0 1000
+
+ dimenup tvec timg 10 100
+
+ stats -q timg 6 34 1 1
+
+ if ($MEAN != 346)
+  $PASS = 0
+  echo "Value mismatch: $MEAN (should be 346)"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  dimenup tvec timg 10 100
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fft1d.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fft1d.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fft1d.sh	(revision 16632)
@@ -0,0 +1,17 @@
+
+list tests
+end
+
+macro test1
+ $PASS = 1
+ break -auto off
+
+ create t 0 4096 1.0
+ set f = dsin(20*t)
+
+ fft1d f 0 to Frn Fin
+
+ clear
+ section a 0.0 0.0 1.0 0.5
+ lim t Fro; box; plot -pt 7 -c blue t Fro; plot -pt 2 -c red t Frn
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fft2d.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fft2d.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fft2d.sh	(revision 16632)
@@ -0,0 +1,27 @@
+
+list tests
+# test1
+end
+
+macro test1
+ $PASS = 1
+ break -auto off
+
+ delete x y t f Frn Fin Fro Fio dfi dfr
+ mcreate t 2048 2048
+ set x = xramp(t)
+ set y = yramp(t)
+
+ # set f = dsin(3*x)*dcos(5*y)
+ set f = exp(-0.5*((x-1024)^2 + (y-1024)^2)*0.01)
+
+ date; fft2d f 0 to Frn Fin; date
+
+ date; fft2dold f 0 to Fro Fio; date
+
+ set dfr = Frn - Fro
+ set dfi = Fin - Fio
+
+ stats dfr
+ stats dfi
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fit.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fit.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fit.sh	(revision 16632)
@@ -0,0 +1,223 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test5
+ test6
+ test7
+ test8
+end
+
+# fit a line without errors
+macro test1
+ $PASS = 1
+ break -auto off
+
+ delete -q x y
+
+ create x 0 100
+ set y = 3 + 5*x
+ fit -q x y 1
+
+ if ($Cn != 1)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 1e-5)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 1e-5)
+   $PASS = 0
+ end
+end
+
+# fit a line with errors
+macro test2
+ $PASS = 1
+ break -auto off
+
+ delete -q x y dy
+
+ create x 0 100
+ set dy = 0.1*rnd(x) - 0.05
+ set y = 3 + 5*x + dy
+ fit -q x y 1
+
+ if ($Cn != 1)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 0.01)
+   $PASS = 0
+ end
+end
+
+# fit a line with errors and weights
+macro test3
+ $PASS = 1
+ break -auto off
+
+ delete -q x y dy
+
+ create x 0 100
+ set dy = 0.1*rnd(x) - 0.05
+ set y = 3 + 5*x + dy
+ set dy = 0.1 + zero(x)
+ fit -q x y 1 -dy dy
+
+ if ($Cn != 1)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 0.02)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 0.02)
+   $PASS = 0
+ end
+end
+
+# fit a line with errors, weights, and outliers 
+macro test4
+ $PASS = 1
+ break -auto off
+
+ delete -q x y dy
+
+ create x 0 100
+ set dy = 0.1*rnd(x) - 0.05
+ set y = 3 + 5*x + dy
+ set dy = 0.1 + zero(x)
+ y[5] = 23
+ y[20] = -10
+ y[50] = 0.0
+ fit -q x y 1 -dy dy -clip 3 3
+
+ if ($Cn != 1)
+   $PASS = 0
+ end
+ if ($Cnv != 97)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 0.02)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 0.02)
+   $PASS = 0
+ end
+end
+
+# fit a quadratic without errors
+macro test5
+ $PASS = 1
+ break -auto off
+
+ delete -q x y
+
+ create x 0 100
+ set y = 3 + 5*x - 4*x^2
+ fit -q x y 2
+
+ if ($Cn != 2)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 1e-5)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 1e-5)
+   $PASS = 0
+ end
+ if (abs($C2 + 4) > 1e-5)
+   $PASS = 0
+ end
+end
+
+# fit a quadratic with errors
+macro test6
+ $PASS = 1
+ break -auto off
+
+ delete -q x y dy
+
+ create x 0 100
+ set dy = 0.1*rnd(x) - 0.05
+ set y = 3 + 5*x - 4*x^2 + dy
+ fit -q x y 2
+
+ if ($Cn != 2)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 0.05)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 0.05)
+   $PASS = 0
+ end
+ if (abs($C2 + 4) > 0.05)
+   $PASS = 0
+ end
+end
+
+# fit a quadratic with errors and weights
+macro test7
+ $PASS = 1
+ break -auto off
+
+ delete -q x y dy
+
+ create x 0 100
+ set dy = 0.1*rnd(x) - 0.05
+ set y = 3 + 5*x - 4*x^2 + dy
+ set dy = 0.1 + zero(x)
+ fit -q x y 2 -dy dy
+
+ if ($Cn != 2)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 0.05)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 0.05)
+   $PASS = 0
+ end
+ if (abs($C2 + 4) > 0.05)
+   $PASS = 0
+ end
+end
+
+# fit a quadratic with errors, weights, and outliers 
+macro test8
+ $PASS = 1
+ break -auto off
+
+ delete -q x y dy
+
+ create x 0 100
+ set dy = 0.1*rnd(x) - 0.05
+ set y = 3 + 5*x - 4*x^2 + dy
+ set dy = 0.1 + zero(x)
+ y[5] = 23
+ y[20] = -10
+ y[50] = 0.0
+
+ # it takes 4 iterations to successfully reject the outliers above...
+ fit -q x y 2 -dy dy -clip 3 4
+
+ if ($Cn != 2)
+   $PASS = 0
+ end
+ if ($Cnv != 97)
+   $PASS = 0
+ end
+ if (abs($C0 - 3) > 0.05)
+   $PASS = 0
+ end
+ if (abs($C1 - 5) > 0.05)
+   $PASS = 0
+ end
+ if (abs($C2 + 4) > 0.05)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fit2d.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fit2d.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/fit2d.sh	(revision 16632)
@@ -0,0 +1,118 @@
+
+list tests
+ test1
+ test2
+ memtest1
+end
+
+# fit a function without errors
+macro test1
+ $PASS = 1
+ break -auto off
+
+ create x 0 5 0.01
+ set y = sin((2*3.14159*x)/2)
+ set z = 5-4*x+x^2-3*y+6*x*y-2*y^2
+
+ fit2d -q x y z 2
+
+ if ($Cnn != 2)
+   $PASS = 0
+   echo "Function Order Incorrect!"
+ end
+ if (abs($CX0Y0 - 5) > 1e-5)
+   $PASS = 0
+   echo "Term CX0Y0 Incorrect!"
+ end
+ if (abs($CX1Y0 + 4) > 1e-5)
+   $PASS = 0
+   echo "Term CX1Y0 Incorrect!"
+ end
+ if (abs($CX2Y0 - 1) > 1e-5)
+   $PASS = 0
+   echo "Term CX2Y0 Incorrect!"
+ end
+ if (abs($CX0Y1 + 3) > 1e-5)
+   $PASS = 0
+   echo "Term CX0Y1 Incorrect!"
+ end
+ if (abs($CX1Y1 - 6) > 1e-5)
+   $PASS = 0
+   echo "Term CX1Y1 Incorrect!"
+ end
+ if (abs($CX0Y2 + 2) > 1e-5)
+   $PASS = 0
+   echo "Term CX0Y2 Incorrect!"
+ end
+end
+
+# fit a function with errors
+macro test2
+ $PASS = 1
+ break -auto off
+
+ create x 0 5 0.01
+ set y = sin((2*3.14159*x)/2)
+ set dz = 0.1*rnd(x) - 0.05
+ set z = 5-4*x+x^2-3*y+6*x*y-2*y^2+dz
+
+ fit2d -q x y z 2
+
+ if ($Cnn != 2)
+   $PASS = 0
+   echo "Function Order Incorrect!"
+ end
+ if (abs($CX0Y0 - 5) > 0.01)
+   $PASS = 0
+   echo "Term CX0Y0 Incorrect!"
+ end
+ if (abs($CX1Y0 + 4) > 0.01)
+   $PASS = 0
+   echo "Term CX1Y0 Incorrect!"
+ end
+ if (abs($CX2Y0 - 1) > 0.01)
+   $PASS = 0
+   echo "Term CX2Y0 Incorrect!"
+ end
+ if (abs($CX0Y1 + 3) > 0.01)
+   $PASS = 0
+   echo "Term CX0Y1 Incorrect!"
+ end
+ if (abs($CX1Y1 - 6) > 0.01)
+   $PASS = 0
+   echo "Term CX1Y1 Incorrect!"
+ end
+ if (abs($CX0Y2 + 2) > 0.01)
+   $PASS = 0
+   echo "Term CX0Y2 Incorrect!"
+ end
+end
+
+# Memory Test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ create x 0 5 0.01
+ set y = sin((2*3.14159*x)/2)
+ set dz = 0.1*rnd(x) - 0.05
+ set z = 5-4*x+x^2-3*y+6*x*y-2*y^2+dz
+
+ for i 0 1000
+  fit2d -q x y z 2
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/gaussj.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/gaussj.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/gaussj.sh	(revision 16632)
@@ -0,0 +1,294 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test5
+end
+
+# a very simple diagonal matrix equation
+macro test1
+ $PASS = 1
+ break -auto off
+
+ mcreate A 3 3
+ create B 0 3
+
+ A[0][0] = 2
+ A[1][1] = 2
+ A[2][2] = 2
+
+ A[0][1] = -1
+ A[1][2] = -1
+ A[1][0] = -1
+ A[2][1] = -1
+
+ gaussj A B
+ if (not($STATUS))
+   $PASS = 0
+ end
+
+ if (abs(A[0][0] - 0.75) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[0][1] - 0.50) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[0][2] - 0.25) > 0.01)
+  $PASS = 0
+ end
+
+ if (abs(A[1][0] - 0.50) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[1][1] - 1.00) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[1][2] - 0.50) > 0.01)
+  $PASS = 0
+ end
+
+ if (abs(A[2][0] - 0.25) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[2][1] - 0.50) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[2][2] - 0.75) > 0.01)
+  $PASS = 0
+ end
+
+ if (abs(B[0] - 1.00) > 0.01)
+  $PASS = 0
+ end
+ if (abs(B[1] - 2.00) > 0.01)
+  $PASS = 0
+ end
+ if (abs(B[2] - 2.00) > 0.01)
+  $PASS = 0
+ end
+end
+
+# a very simple off-diagonal matrix equation
+macro test2
+ $PASS = 1
+ break -auto off
+
+ mcreate A 3 3
+ create B 0 3
+
+ A[0][1] = 2
+ A[1][0] = 2
+ A[2][2] = 2
+
+ A[0][0] = -1
+ A[1][2] = -1
+ A[1][1] = -1
+ A[2][0] = -1
+
+ gaussj A B
+ if (not($STATUS))
+   $PASS = 0
+ end
+
+ # echo A[0][0] A[0][1] A[0][2]
+ # echo A[1][0] A[1][1] A[1][2]
+ # echo A[2][0] A[2][1] A[2][2]
+
+ if (abs(A[1][0] - 0.75) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[1][1] - 0.50) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[1][2] - 0.25) > 0.01)
+  $PASS = 0
+ end
+
+ if (abs(A[0][0] - 0.50) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[0][1] - 1.00) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[0][2] - 0.50) > 0.01)
+  $PASS = 0
+ end
+
+ if (abs(A[2][0] - 0.25) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[2][1] - 0.50) > 0.01)
+  $PASS = 0
+ end
+ if (abs(A[2][2] - 0.75) > 0.01)
+  $PASS = 0
+ end
+
+ if (abs(B[1] - 1.00) > 0.01)
+  $PASS = 0
+ end
+ if (abs(B[0] - 2.00) > 0.01)
+  $PASS = 0
+ end
+ if (abs(B[2] - 2.00) > 0.01)
+  $PASS = 0
+ end
+end
+
+# a singular matrix equation
+macro test3
+ $PASS = 1
+ break -auto off
+
+ mcreate A 3 3
+ create B 0 3
+
+ A[0][0] = 2
+ A[1][0] = 2
+ A[2][2] = 2
+
+ A[0][1] = -1
+ A[1][1] = -1
+ A[2][1] = -1
+
+ gaussj -q A B
+ if ($STATUS)
+   $PASS = 0
+ end
+end
+
+# a very large matrix equation
+macro test4
+ $PASS = 1
+ break -auto off
+
+ $Ndim = 50
+ mcreate A $Ndim $Ndim
+ create B 0 $Ndim
+
+ # generate the diagonal + off-diagonal elements
+ for i 0 $Ndim
+   A[$i][$i] = 2.0
+   if ($i > 0)
+     A[$i][$i-1] = -1.0
+   end
+   if ($i < $Ndim - 1)
+     A[$i][$i+1] = -1.0
+   end
+ end
+
+ set inB = B
+ set inA = A
+
+ gaussj A B
+ if (not($STATUS))
+   $PASS = 0
+ end
+
+ set meas = zero(inB)
+ for i 0 B[]
+  for j 0 B[]
+   meas[$i] = meas[$i] + inA[$i][$j] * B[$j]
+  end
+ end
+
+ for i 0 inB[]
+  if (abs(inB[$i]-meas[$i]) > 1e-3)
+    $PASS = 0
+    echo inB[$i] meas[$i] {inB[$i]-meas[$i]}
+  end
+ end
+end
+
+# a nearly singular matrix equation
+macro test5
+ $PASS = 1
+ break -auto off
+
+ delete A B inA inB meas
+
+ mcreate A 3 3
+ create B 0 3
+
+ A[0][0] = 2
+ A[1][0] = 2.00001
+ A[2][2] = 2
+
+ A[0][1] = -1
+ A[1][1] = -1
+ A[2][1] = -1
+
+ set inB = B
+ set inA = A
+
+ gaussj A B
+ if (not($STATUS))
+   $PASS = 0
+ end
+
+ set meas = zero(inB)
+ for i 0 B[]
+  for j 0 B[]
+   meas[$i] = meas[$i] + inA[$i][$j] * B[$j]
+  end
+ end
+
+ for i 0 inB[]
+  if (abs(inB[$i]-meas[$i]) > 1e-5)
+    $PASS = 0
+  end
+ end
+end
+
+# a very large matrix equation
+# timing on my laptop: 100 : ~1sec; 300 : ~7sec; 1000 : ~88sec
+# note: at Ndim = 1000, it failed (Ax - B was in the range -2..+2)
+macro test6
+ if ($0 != 2)
+  echo "USAGE: test6 (Ndim)"
+  break
+ end
+
+ $PASS = 1
+ break -auto off
+
+ $Ndim = $1
+ mcreate A $Ndim $Ndim
+ create B 0 $Ndim
+
+ # generate the diagonal + off-diagonal elements
+ for i 0 $Ndim
+   A[$i][$i] = 2.0
+   if ($i > 0)
+     A[$i][$i-1] = -1.0
+   end
+   if ($i < $Ndim - 1)
+     A[$i][$i+1] = -1.0
+   end
+ end
+
+ set inB = B
+ set inA = A
+
+ gaussj A B
+ if (not($STATUS))
+   $PASS = 0
+ end
+
+ set meas = zero(inB)
+ for i 0 B[]
+  for j 0 B[]
+   meas[$i] = meas[$i] + inA[$i][$j] * B[$j]
+  end
+ end
+
+ for i 0 inB[]
+  if (abs(inB[$i]-meas[$i]) > 1e-3)
+    $PASS = 0
+    echo inB[$i] meas[$i] {inB[$i]-meas[$i]}
+  end
+ end
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/histogram.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/histogram.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/histogram.sh	(revision 16632)
@@ -0,0 +1,52 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if histogram works
+macro test1
+
+ $PASS = 1
+
+ local i
+
+ create x 0 10 0.1
+
+ for i 45 55
+  x[$i] = 4.5
+ end
+
+ histogram x xhis 0 10 0.1
+
+ if ((xhis[10] != 1) || (xhis[45] != 10))
+  $PASS = 0
+  echo "Value mismatch: xhis[10] xhis[45] (should be 1,10)"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  histogram x xhis 0 10 0.1
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/imhist.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/imhist.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/imhist.sh	(revision 16632)
@@ -0,0 +1,58 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if imhist works
+macro test1
+
+ $PASS = 1
+
+ local i
+
+ mcreate buff 100 10
+
+ zap buff 40 0 10 10 -v 17
+ zap buff 60 5 5 2 -v 6
+
+ imhist buff xvec yvec
+
+ if ((xvec[1024] != 17) || (yvec[1024] != 100))
+  $PASS = 0
+  echo "Value mismatch: xvec[1024] yvec[1024] (should be 17,100)"
+ end
+
+ imhist -q buff xvec yvec -region 40 0 25 10 -range 0 10
+
+ if ((xvec[1024] != 10) || (yvec[1024] != 100))
+  $PASS = 0
+  echo "Value mismatch: xvec[1024] yvec[1024] (should be 10,100)"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  imhist -q buff xvec yvec -region 40 0 25 10 -range 0 10
+ end
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/imsmooth.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/imsmooth.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/imsmooth.sh	(revision 16632)
@@ -0,0 +1,59 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if imsmooth works
+macro test1
+
+ $PASS = 1
+
+ local i j
+
+ mcreate buff 100 100
+
+ for i 0 99
+  for j 0 99
+   zap buff $i $j 1 1 -v {100*rnd($i)}
+  end
+ end
+
+ stats -q buff
+ $s1 = $SIGMA
+
+ imsmooth buff 10
+ stats -q buff
+ $s2 = $SIGMA
+
+ if ($s2/$s1 >= 0.1)
+  $PASS = 0
+  echo "Inadequate noise reduction: {$s2/$s1*100}\% (should be less than 10%)"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 100
+  imsmooth buff 10
+ end
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/100}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/integrate.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/integrate.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/integrate.sh	(revision 16632)
@@ -0,0 +1,47 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if integrate works
+macro test1
+
+ $PASS = 1
+
+ create x 0 10 0.01
+ set y = 1+2*x+3*x^2
+
+ integrate x y 1 5
+
+ if (abs ($sum-152) > 0.5)
+  $PASS = 0
+  echo "Inaccurate result (should be 152): $sum"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  integrate x y 1 5
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/interpolate.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/interpolate.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/interpolate.sh	(revision 16632)
@@ -0,0 +1,48 @@
+
+list tests
+ test1
+ memtest1
+end
+
+# Test if interpolate works
+macro test1
+
+ $PASS = 1
+
+ create x0 0 10 0.1
+ set y0 = 1+2*x0+3*x0^2
+ create x1 0 10 0.001
+ interpolate x0 y0 x1 y1
+ integrate x1 y1 1 5
+
+ if (abs ($sum-152) > 0.08)
+  $PASS = 0
+  echo "Inaccurate result (should be 152): $sum"
+ end
+
+end
+
+
+# Memory test
+macro memtest1
+
+ local i
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 1000
+  interpolate x0 y0 x1 y1
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/1000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/peak.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/peak.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/peak.sh	(revision 16632)
@@ -0,0 +1,103 @@
+
+list tests
+ test1
+ test2
+ test3
+ testmem1
+end
+
+# test using full range
+macro test1
+ $PASS = 1
+ break -auto off
+
+ create x 0 100
+ set y = zero (x)
+ y[50] = 1
+
+ peak -q x y 0 100
+
+ if ($peakpos != 50)
+   $PASS = 0
+ end
+ if ($peaknum != 51)
+   $PASS = 0
+ end
+ if ($peakval != 1)
+   $PASS = 0
+ end
+end
+
+# test using auto range
+macro test2
+ $PASS = 1
+ break -auto off
+
+ create x 0 100
+ set y = zero (x)
+ y[50] = 1
+
+ peak -q x y 
+
+ if ($peakpos != 50)
+   $PASS = 0
+ end
+ if ($peaknum != 51)
+   $PASS = 0
+ end
+ if ($peakval != 1)
+   $PASS = 0
+ end
+end
+
+# test using constrained range
+macro test3
+ $PASS = 1
+ break -auto off
+
+ create x 0 100
+ set y = zero (x)
+ y[60] = 2
+ y[50] = 1
+ y[40] = 2
+
+ peak -q x y 45 55
+
+ if ($peakpos != 50)
+   $PASS = 0
+ end
+ if ($peaknum != 51)
+   $PASS = 0
+ end
+ if ($peakval != 1)
+   $PASS = 0
+ end
+end
+
+# test memory usage
+macro testmem1
+ break -auto off
+
+ create x 0 1000
+ set y = zero (x)
+ y[500] = 100
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 10000
+   peak -q x y 400 600
+ end
+ 
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} < 10)
+   $PASS = 1
+ else
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/periodogram.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/periodogram.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/periodogram.sh	(revision 16632)
@@ -0,0 +1,143 @@
+
+list tests
+ test1
+ test2
+ test3
+ memtest1
+end
+
+# test using even samples
+macro test1
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q t f period power
+
+ create t 0 100
+ set f = sin(2*$PI*t/$P)
+ periodogram t f 5 50 period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.5)
+   $PASS = 0
+   echo "OFFSET: {$peakpos - $P}"
+ end
+end
+
+# test using random samples
+macro test2
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 0 100
+ set t = 100 * rnd(x) 
+ set f = sin(2*$PI*t/$P)
+ periodogram t f 5 50 period power
+
+ # lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+ # lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.5)
+   $PASS = 0
+ end
+end
+
+# test using random samples, higher frequency
+macro test3
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 2.0
+
+ delete -q x t f period power
+
+ create x 0 100
+ set t = 100 * rnd(x) 
+ set f = sin(2*$PI*t/$P)
+
+ periodogram t f 1 10 period power
+
+ # lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+ # lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# test using random samples, offset start
+macro test4
+ $PASS = 1
+ break -auto off
+
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set f = sin(2*$PI*t/$P)
+
+ periodogram t f 2 30 period power
+
+#  lim -n 0 t f; clear; box; plot -x 2 -pt 2 t f
+#  lim -n 1 period power; clear; box; plot period power
+
+ peak -q period power
+
+ if (abs ($peakpos - $P) > 0.05)
+   $PASS = 0
+ end
+end
+
+# Memory test
+macro memtest1
+
+ local i
+ local P PI
+ $PI = 3.14159265359
+ $P  = 15.0
+
+ delete -q x t f period power
+
+ create x 500 800
+ set t = 300 * rnd(x) + 500
+ set f = sin(2*$PI*t/$P)
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ for i 0 100
+  periodogram t f 2 30 period power
+ end
+  
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ $PASS = 1
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/100}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/queues.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/queues.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/queues.sh	(revision 16632)
@@ -0,0 +1,347 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test4.1
+ test5
+ test5.1
+ testmem1
+ testmem2
+ testmem3
+ testmem4.0
+ testmem4.1
+ testmem4.2
+ testmem4.3
+ testmem5.0
+ testmem5.1
+end
+
+# test queueinit
+macro test1
+ $PASS = 1
+ queueinit dummy
+ queuesize dummy -var N
+
+ if ($N != 0)
+   $PASS = 0
+ end
+end
+
+# test queueinit memory
+macro testmem1
+ $PASS = 1
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queueinit dummy
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# test queuesize
+macro test2
+ $PASS = 1
+ queueinit dummy
+ queuepush dummy foobar
+ queuesize dummy -var N
+
+ if ($N != 1)
+   $PASS = 0
+ end
+end
+
+# test queuesize memory
+macro testmem2
+ $PASS = 1
+ queueinit dummy
+ queuepush dummy foobar
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queuesize dummy -var N
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# test queuedelete
+macro test3
+ $PASS = 1
+ queueinit dummy
+ queuepush dummy foobar
+ queuepush dummy foobar
+ queuepush dummy foobar
+
+ queuedelete dummy
+ queuepush dummy foobar
+ queuesize dummy -var N
+
+ if ($N != 1)
+   $PASS = 0
+ end
+end
+
+# test queuedelete memory
+macro testmem3
+ $PASS = 1
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queueinit dummy
+   queuepush dummy foobar
+   queuedelete dummy
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# test queuepush / queuepop
+macro test4
+ $PASS = 1
+ queueinit dummy
+ queuepush dummy foobar
+ queuepop  dummy -var N
+
+ if ("$N" != "foobar")
+   $PASS = 0
+ end
+end
+
+# test queuepush / queuepop
+macro test4.1
+ $PASS = 1
+ queueinit dummy
+ queuepush dummy foo1
+ queuepush dummy foo2
+ queuepush dummy foo3
+
+ queuepop  dummy -var N
+ if ("$N" != "foo1")
+   $PASS = 0
+ end
+ queuepop  dummy -var N
+ if ("$N" != "foo2")
+   $PASS = 0
+ end
+ queuepop  dummy -var N
+ if ("$N" != "foo3")
+   $PASS = 0
+ end
+ queuesize dummy -var N
+ if ($N != 0)
+   $PASS = 0
+ end
+end
+
+# test queuepush / queuepop memory
+macro testmem4.0
+ $PASS = 1
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queueinit dummy
+   queuepush dummy foobar
+   queuepop dummy -var N
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# test queuepush / queuepop memory
+macro testmem4.1
+ $PASS = 1
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queueinit dummy
+   queuepush dummy foobar
+   queuepop dummy
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# test queuepush / queuepop memory
+macro testmem4.2
+ $PASS = 1
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queueinit dummy
+   queuepush dummy foobar
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# test queuepush / queuepop memory
+macro testmem4.3
+ $PASS = 1
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ queueinit dummy
+
+ output /dev/null
+ for i 0 10000
+   queuepush dummy foobar
+   queuepop dummy
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+# test queuepush / queuepop with keys
+macro test5
+ $PASS = 1
+ queueinit dummy
+ queuepush dummy "test 1 word"
+ queuepush dummy "test 2 word"
+ queuepush dummy "test 3 word"
+ queuepop  dummy -var N -key 1 2
+
+ if ("$N" != "test 2 word")
+   $PASS = 0
+ end
+end
+
+# test queuepush / queuepop with keys
+macro test5.1
+ $PASS = 1
+ queueinit dummy
+ queuepush dummy "test 1 word"
+ queuepush dummy "test 2 word"
+ queuepush dummy "bird 2 word"
+ queuepop  dummy -var N -key 0:1 test:2
+
+ if ("$N" != "test 2 word")
+   $PASS = 0
+ end
+end
+
+# memory test for queuepush / queuepop with keys
+macro testmem5.0
+ $PASS = 1
+ queueinit dummy
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queuepush dummy "test 1 word"
+   queuepush dummy "test 2 word"
+   queuepush dummy "test 3 word"
+   queuepop dummy -var N -key 1 2
+   queuepop dummy -var N -key 1 1
+   queuepop dummy -var N -key 1 3
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+   queuelist
+ end
+end
+
+# memory test for queuepush / queuepop with keys
+macro testmem5.1
+ $PASS = 1
+ queueinit dummy
+
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+
+ output /dev/null
+ for i 0 10000
+   queuepush dummy "test 1 word"
+   queuepop dummy -var N -key 1 1
+ end
+ output stdout
+
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+
+ if ({$endmem - $startmem} > 10)
+   $PASS = 0
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/stats.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/stats.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/stats.sh	(revision 16632)
@@ -0,0 +1,156 @@
+
+$skip = 0
+
+list tests
+ test1
+ test2
+ test3
+end
+
+# test using full range
+macro test1
+ $PASS = 1
+ break -auto off
+
+ gaussdev dev {100*100} 0.0 1.0
+ dimenup dev buf 100 100
+ stats -q buf 
+ $npix = 100*100
+
+ if ($STATUS == 0)
+   echo "failed command"
+   $PASS = 0
+ end
+ if ($NPIX != $npix) 
+   echo "failed npix"
+   $PASS = 0
+ end
+ if (abs($MEAN - 0.0) > (2.0/sqrt($npix))) 
+   echo "failed mean"
+   $PASS = 0
+ end
+ if (abs($MEDIAN - 0.0) > (2.0/sqrt($npix))) 
+   echo "failed median"
+   $PASS = 0
+ end
+ if (abs($SIGMA - 1.0) > (2.0/sqrt($npix))) 
+   echo "failed sigma"
+   $PASS = 0
+ end
+ if ($MIN < -4.0) 
+   echo "failed min"
+   $PASS = 0
+ end
+ if ($MAX > +4.0)
+   echo "failed max"
+   $PASS = 0
+ end
+# I don't this MODE is being correctly calculated.
+ if ($skip && (abs($MODE - 0.0) > (2.0/sqrt($npix))))
+   echo "MODE fails: known problem with mode"
+   $PASS = 0
+ end
+ if (abs($TOTAL - $MEAN*$npix) > (2.0/sqrt($npix))) 
+   echo "failed total"
+   $PASS = 0
+ end
+end
+
+# test using full range
+macro test2
+ $PASS = 1
+ break -auto off
+
+ gaussdev dev {100*100} 0.0 1.0
+ dimenup dev buf 100 100
+ stats -q buf  - - - -
+ $npix = 100*100
+
+ if ($STATUS == 0)
+   echo "failed command"
+   $PASS = 0
+ end
+ if ($NPIX != $npix) 
+   echo "failed npix"
+   $PASS = 0
+ end
+ if (abs($MEAN - 0.0) > (2.0/sqrt($npix))) 
+   echo "failed mean"
+   $PASS = 0
+ end
+ if (abs($MEDIAN - 0.0) > (2.0/sqrt($npix))) 
+   echo "failed median"
+   $PASS = 0
+ end
+ if (abs($SIGMA - 1.0) > (2.0/sqrt($npix))) 
+   echo "failed sigma"
+   $PASS = 0
+ end
+ if ($MIN < -4.0) 
+   echo "failed min"
+   $PASS = 0
+ end
+ if ($MAX > +4.0)
+   echo "failed max"
+   $PASS = 0
+ end
+# I don't this MODE is being correctly calculated.
+ if ($skip && (abs($MODE - 0.0) > (2.0/sqrt($npix))))
+   echo "MODE fails: known problem with mode"
+   $PASS = 0
+ end
+ if (abs($TOTAL - $MEAN*$npix) > (2.0/sqrt($npix))) 
+   echo $TOTAL {$MEAN*$npix} {abs($TOTAL - $MEAN*$npix) > (2.0/sqrt($npix))) 
+   echo "failed total"
+   $PASS = 0
+ end
+end
+
+# test using full range
+macro test3
+ $PASS = 1
+ break -auto off
+
+ gaussdev dev {100*100} 0.0 1.0
+ dimenup dev buf 100 100
+ stats -q buf 10 10 10 10
+ $npix = 10*10
+
+ if ($STATUS == 0)
+   echo "failed command"
+   $PASS = 0
+ end
+ if ($NPIX != $npix) 
+   echo "failed npix"
+   $PASS = 0
+ end
+ if (abs($MEAN - 0.0) > (2.0/sqrt($npix))) 
+   echo "failed mean"
+   $PASS = 0
+ end
+ if (abs($MEDIAN - 0.0) > (2.0/sqrt($npix))) 
+   echo "failed median"
+   $PASS = 0
+ end
+ if (abs($SIGMA - 1.0) > (2.0/sqrt($npix))) 
+   echo "failed sigma"
+   $PASS = 0
+ end
+ if ($MIN < -4.0) 
+   echo "failed min"
+   $PASS = 0
+ end
+ if ($MAX > +4.0)
+   echo "failed max"
+   $PASS = 0
+ end
+# I don't this MODE is being correctly calculated.
+ if ($skip && (abs($MODE - 0.0) > (2.0/sqrt($npix))))
+   echo "MODE fails: known problem with mode"
+   $PASS = 0
+ end
+ if (abs($TOTAL - $MEAN*$npix) > (2.0/sqrt($npix))) 
+   echo "failed total"
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/vgauss.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/vgauss.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/vgauss.sh	(revision 16632)
@@ -0,0 +1,99 @@
+
+list tests
+ test1
+ test2
+ test3
+end
+
+macro test1
+ $PASS = 1
+ break -auto off
+
+ create x -10 10 0.1
+ set y = 5 * exp(-0.5*x^2/3^2)
+
+ $C0 = 0.5
+ $C1 = 2
+ $C2 = 10
+ $C3 = 1
+ set dy = sqrt(y)
+
+ vgauss -q x y dy yfit
+
+ if (abs($C0 - 0.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C1 - 3.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C2 - 5.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C3 - 0.0) > 0.01)
+   $PASS = 0
+ end
+end
+
+# noise of 0.1
+macro test2
+ $PASS = 1
+ break -auto off
+
+ create x -10 10 0.1
+ set y = 1000 * exp(-0.5*x^2/3^2)
+ set dy = (rnd(y) - 0.5)/0.5
+ set y = y + dy
+
+ $C0 = 0.5
+ $C1 = 2
+ $C2 = 900
+ $C3 = 1
+
+ vgauss -q x y dy yfit
+
+ if (abs($C0 - 0.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C1 - 3.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C2 - 1000.0) > 0.1)
+   $PASS = 0
+ end
+ if (abs($C3 - 0.0) > 0.1)
+   $PASS = 0
+ end
+end
+
+# poisson-distributed noise
+macro test3
+ $PASS = 1
+ break -auto off
+
+ create x -10 10 0.1
+ set y = 1000 * exp(-0.5*x^2/3^2)
+
+ gaussdev dY y[] 0.0 1.0
+ set dy = dY * sqrt(y)
+ set y = y + dy
+
+ $C0 = 0.5
+ $C1 = 2
+ $C2 = 900
+ $C3 = 1
+
+ vgauss -q x y dy yfit
+
+ if (abs($C0 - 0.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C1 - 3.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C2 - 1000.0) > 1)
+   $PASS = 0
+ end
+ if (abs($C3 - 0.0) > 0.2)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/vmaxwell.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/vmaxwell.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/test/vmaxwell.sh	(revision 16632)
@@ -0,0 +1,103 @@
+
+list tests
+# test1
+ test2
+# test3
+end
+
+macro test1
+ $PASS = 1
+ break -auto off
+
+ create x -10 10 0.1
+ set y = 5 * exp(-0.5*x^2/3^2)
+
+ $C0 = 0.5
+ $C1 = 2
+ $C2 = 10
+ $C3 = 1
+ set dy = sqrt(y)
+
+ vgauss -q x y dy yfit
+
+ if (abs($C0 - 0.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C1 - 3.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C2 - 5.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C3 - 0.0) > 0.01)
+   $PASS = 0
+ end
+end
+
+# noise of 0.1
+macro test2
+ $PASS = 1
+ break -auto off
+
+ create x 0 1000 1
+ set y = 1000 * (x-200)^2 * exp(-0.5*(x-300)^2/30^2)
+ set dy = (rnd(y) - 0.5)/0.5
+ set y = y + dy
+
+ lim x y; clear; box; plot -x 1 -c black x y
+
+ $C0 = 250
+ $C1 = 25
+ $C2 = 900
+ $C3 = 1
+ $C4 = 190
+
+ vmaxwell x y dy yfit
+ plot x yfit -c red
+
+ if (abs($C0 - 0.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C1 - 3.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C2 - 1000.0) > 0.1)
+   $PASS = 0
+ end
+ if (abs($C3 - 0.0) > 0.1)
+   $PASS = 0
+ end
+end
+
+# poisson-distributed noise
+macro test3
+ $PASS = 1
+ break -auto off
+
+ create x -10 10 0.1
+ set y = 1000 * exp(-0.5*x^2/3^2)
+
+ gaussdev dY y[] 0.0 1.0
+ set dy = dY * sqrt(y)
+ set y = y + dy
+
+ $C0 = 0.5
+ $C1 = 2
+ $C2 = 900
+ $C3 = 1
+
+ vgauss -q x y dy yfit
+
+ if (abs($C0 - 0.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C1 - 3.0) > 0.01)
+   $PASS = 0
+ end
+ if (abs($C2 - 1000.0) > 1)
+   $PASS = 0
+ end
+ if (abs($C3 - 0.0) > 0.2)
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/teststats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/teststats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/teststats.c	(revision 16632)
@@ -0,0 +1,117 @@
+# include "data.h"
+
+int teststats (int argc, char **argv) {
+  
+  int i, N;
+  double max, min, sum, var, dvar, mean, stdev;
+  float *X, IgnoreValue;
+  int Ignore, Quiet;
+
+  int *Nval, bin, Nmode, Nmed;
+  double dx, mode, median;
+  Vector *vec;
+
+  Ignore = FALSE;
+  if (N = get_argument (argc, argv, "-ignore")) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if (N = get_argument (argc, argv, "-q")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if (N = get_argument (argc, argv, "-quiet")) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: teststats (vector)\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Mean = Stdev = 0; 
+  /* first pass: measure the sample statistics */
+  for (j = 0; j < 3; j++) {
+    /* calculate mean, npix */
+    X = vec[0].elements;
+    max = min = *X;
+    sum = N = 0;
+    for (i = 0; i < vec[0].Nelements; i++, X++) {
+      if (!finite (*X)) continue;
+      if (Ignore && (*X == IgnoreValue)) continue;
+      if ((j > 0) && (fabs (*X - Mean) > 3*stdev)) continue;
+      sum += *X;
+      N++;
+    }      
+    mean = sum / N;
+    /* calculate stdev */
+    X = vec[0].elements;
+    var = 0;
+    for (i = 0; i < vec[0].Nelements; i++, X++) {
+      if (!finite (*X)) continue;
+      if (Ignore && (*X == IgnoreValue)) continue;
+      if ((j > 0) && (fabs (*X - mean) > 3*stdev)) continue;
+      dvar = (*X - mean);
+      var += dvar*dvar;
+    }      
+    stdev = sqrt (var / N);
+    Mean = mean;
+  }
+  mean = Mean;
+  set_variable ("MEAN_C",     mean);
+  set_variable ("SIGMA_C",    stdev);
+
+  /* construct histogram with resolution of 0.1*stdev and range -1000*dx : 1000*dx centered on mean */
+  dx = 0.1*stdev;
+  min = mean - 1000*dx;
+  max = mean + 1000*dx;
+  NVAL = 1 + (int)((max - min) / dx);
+  ALLOCATE (Nval, int, NVAL);
+  bzero (Nval, NVAL*sizeof(int));
+  X = vec[0].elements;
+  for (i = 0; i < vec[0].Nelements; i++, X++) {
+    if (!finite (*X)) continue;
+    if (Ignore && (*X == IgnoreValue)) continue;
+    bin = MAX (0, MIN (NVAL, (*X - min) / dx));
+    Nval[bin] ++;
+  }      
+
+  /* find mode */
+  Nmode = 0;
+  mode = Nval[Nmode];
+  for (i = 0; i < NVAL; i++) {
+    if (mode < Nval[i]) {
+      Nmode = i;
+      mode = Nval[Nmode];
+    }
+  }
+  mode = Nmode * dx + min;
+
+  
+
+  if (!Quiet) {
+    gprint (GP_ERR, "mean: %f, stdev: %f, min: %f, max: %f, median: %f, mode: %f, Npts: %d\n", 
+	     mean, stdev, min, max, median, mode, N);
+  }
+
+  set_variable ("MIN",      min);
+  set_variable ("MAX",      max);
+  set_variable ("MEDIAN",   median);
+  set_variable ("MODE",     mode);
+  set_variable ("TOTAL",    sum);
+  set_variable ("MEAN",     mean);
+  set_variable ("SIGMA",    stdev);
+
+  set_int_variable ("NPIX", N);
+
+  free (Nval);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/textline.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/textline.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/textline.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "data.h"
+
+int textline (int argc, char **argv) {
+
+  int N, size, FracPositions;
+  char name[64];
+  double x, y, angle;
+  int kapa;
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return (FALSE);
+
+  if ((N = get_argument (argc, argv, "-fn"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (name, argv[N]);
+    remove_argument (N, &argc, argv);
+    size = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    KapaSetFont (kapa, name, size);
+  } 
+
+  /* FracPositions uses coordinates of 0-1 relative to axis range */
+  FracPositions = FALSE;
+  if ((N = get_argument (argc, argv, "-frac"))) {
+    remove_argument (N, &argc, argv);
+    FracPositions = TRUE;
+  } 
+
+  angle = 0.0;
+  if ((N = get_argument (argc, argv, "-rot"))) {
+    remove_argument (N, &argc, argv);
+    angle = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  } 
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: text x y (line) [-fn (font) size] [-rot angle]\n");
+    return (FALSE);
+  }
+
+  if (strlen (argv[3]) > 127) {
+    gprint (GP_ERR, "labels currently limited to 127 chars\n");
+    return (FALSE);
+  }
+
+  x = atof (argv[1]);
+  y = atof (argv[2]);
+  
+  if (FracPositions) {
+    x =  x * (graphmode.xmax - graphmode.xmin) + graphmode.xmin;
+    y =  y * (graphmode.ymax - graphmode.ymin) + graphmode.ymin;
+  }    
+
+  KapaSendTextline (kapa, argv[3], x, y, angle);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tv.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tv.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tv.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "data.h"
+
+int tv (int argc, char **argv) {
+  
+  int N, kapa;
+  char *name, *file;
+  Coords coords;
+  Buffer *buf;
+  KiiImage image;
+  KapaImageData data;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&data, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  /* shell exits on pipe close, FIX */
+  if ((N = get_argument (argc, argv, "-kill"))) {
+    KiiClose (kapa);
+    return (TRUE);
+  }
+
+  data.logflux = FALSE;
+  if ((N = get_argument (argc, argv, "-log"))) {
+    remove_argument (N, &argc, argv);
+    data.logflux = TRUE;
+  }
+
+  // use the currently-set zero,range values if not supplied
+  if ((argc != 2) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: tv <buffer> [zero range] [-n Nimage] [-log] [-kill]\n");
+    return (FALSE);
+  }
+
+  if (argc == 4) {
+    data.zero = atof (argv[2]);
+    data.range = atof (argv[3]);
+    if (data.range == 0.0) data.range = 0.001;
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  GetCoords (&coords, &buf[0].header);
+  
+  image.data1d = (float *) buf[0].matrix.buffer;
+  image.Nx = buf[0].matrix.Naxis[0];
+  image.Ny = buf[0].matrix.Naxis[1];
+
+  // send only the root of the file, not the full path
+  file = filerootname (buf[0].file);
+  strcpy (data.file, file);
+  free (file);
+
+  strcpy (data.name, argv[1]);
+  
+  KiiNewPicture1D (kapa, &image, &data, &coords);
+
+  set_str_variable ("TV", argv[1]);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvchannel.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvchannel.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvchannel.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "data.h"
+
+int tvchannel (int argc, char **argv) {
+  
+  int N, kapa, Nchannel;
+  char *name;
+  KapaImageData data;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&data, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  // use the currently-set zero,range values if not supplied
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: tvchannel (channel)\n");
+    return (FALSE);
+  }
+
+  Nchannel = atoi (argv[1]);
+  if (Nchannel == 0) {
+    // try the string values R/Red, G/Green, B/Blue
+    if (!strcasecmp (argv[1], "R") || !strcasecmp (argv[1], "RED")) {
+      Nchannel = 1;
+    }
+    if (!strcasecmp (argv[1], "G") || !strcasecmp (argv[1], "GREEN")) {
+      Nchannel = 2;
+    }
+    if (!strcasecmp (argv[1], "B") || !strcasecmp (argv[1], "BLUE")) {
+      Nchannel = 3;
+    }
+  }
+  if ((Nchannel < 1) || (Nchannel > 3)) {
+    gprint (GP_ERR, "invalid channel : use 1 - 3 or (R)ed, (G)reen, (B)lue\n");
+    return (FALSE);
+  }
+    
+  KiiSetChannel (kapa, Nchannel - 1);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvcolors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvcolors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvcolors.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "data.h"
+
+int tvcolors (int argc, char **argv) {
+  
+  int N, kapa;
+  char *name;
+  KapaImageData data;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (&data, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  // use the currently-set zero,range values if not supplied
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: tvcolors (colormap)\n");
+    return (FALSE);
+  }
+
+  KiiSetColormap (kapa, argv[1]);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvcontour.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvcontour.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvcontour.c	(revision 16632)
@@ -0,0 +1,287 @@
+# include "data.h"
+# define LL { \
+ dx =  d00 / (*v01 - *v00); \
+ dy = -d00 / (*v10 - *v00); \
+ x = i - 0.5; \
+ y = j - dy - 0.5; }
+
+# define UL { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = 1 - tmp; \
+ dx =  d10 / (*v11 - *v10); \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+      
+# define LR { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = 1 - tmp; \
+ dy = d01 / (*v11 - *v01); \
+ x = i + tmp - 0.5; \
+ y = j - 0.5; }
+
+# define UR { \
+ tmp = d10 / (*v11 - *v10); \
+ dx = 1 - tmp; \
+ dy = -d11 / (*v01 - *v11); \
+ x = i + tmp - 0.5; \
+ y = j + 1 - 0.5; }
+      
+# define HZ { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = d01 / (*v11 - *v01) - tmp; \
+ dx = 1; \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+
+# define VT { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = d10 / (*v11 - *v10) - tmp; \
+ x = i + tmp - 0.5; \
+ dy = 1; \
+ y = j - 0.5; }
+
+# define DUMP { \
+overlay[Noverlay].type = KII_OVERLAY_LINE; \
+overlay[Noverlay].x = Npix*x; \
+overlay[Noverlay].y = Npix*y; \
+overlay[Noverlay].dx = Npix*dx; \
+overlay[Noverlay].dy = Npix*dy; \
+Noverlay ++; \
+CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000); \
+}
+
+int tvcontour (int argc, char **argv) {
+
+  int i, j, ii, jj, Npix, Nx, Ny;
+  float level, d00, d01, d10, d11, tmp;
+  float x, y, dx, dy;
+  float *v00, *v01, *v10, *v11;
+  float *Vout, *Vin, *matrix;
+  char *name;
+  int kapa, N, Noverlay, NOVERLAY;
+  Buffer *buf;
+  KiiOverlay *overlay;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if ((argc != 4) && (argc != 5)) {
+    gprint (GP_ERR, "USAGE: contour <buffer> (overlay) level [Npix]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  level = atof (argv[3]);
+  if (argc == 5) 
+    Npix = (int) MAX (atof (argv[4]), 1); 
+  else 
+    Npix = 1;
+  level *= Npix*Npix;
+
+  /*** make rebinned image ***/
+  Nx = buf[0].header.Naxis[0]/Npix;
+  Ny = buf[0].header.Naxis[1]/Npix;
+  if (Npix != 1) {
+    gprint (GP_LOG, "rebin by a factor of %d (%d,%d)\n", Npix, Nx, Ny);
+    ALLOCATE (matrix, float, Nx*Ny);
+    bzero (matrix, Nx*Ny*sizeof(float));
+	
+    for (j = 0; j < Ny; j++) {
+      for (jj = 0; jj < Npix; jj++) {
+	Vout = matrix + j*Nx;
+	Vin  = (float *)(buf[0].matrix.buffer) + (j*Npix + jj)*buf[0].header.Naxis[0];
+	for (i = 0; i < Nx; i++, Vout++) {
+	  for (ii = 0; ii < Npix; ii++, Vin++) {
+	    *Vout += *Vin;
+	  }
+	}
+      }
+    }
+  } else {
+    gprint (GP_ERR, "using scale of 1\n");
+    matrix = (float *)(buf[0].matrix.buffer);
+  }
+
+  Noverlay = 0;
+  NOVERLAY = 1000;
+  ALLOCATE (overlay, KiiOverlay, NOVERLAY);
+
+  v00 = matrix;
+  v01 = matrix + 1;
+  v10 = matrix + Nx;
+  v11 = matrix + Nx + 1;
+  d01 = (level - *v00);
+  d11 = (level - *v10);
+  for (j = 1; j < Ny; j++) {
+    if (!(j%10)) gprint (GP_ERR, ".");
+    for (i = 1; i < Nx; i++, v00++, v01++, v10++, v11++) {
+
+      d00 = d01;
+      d10 = d11;
+      d01 = (level - *v01);
+      d11 = (level - *v11);
+
+      if (((d00 > 0) && (d01 > 0) && (d10 > 0) && (d11 > 0)) ||
+	  ((d00 < 0) && (d01 < 0) && (d10 < 0) && (d11 < 0)))
+	continue;
+
+      if ((d00 > 0) && (d10 <= 0)) { 
+	if ((d01 <= 0) && (d11 <= 0)) { /* \  */
+	  LL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) { /* /  */
+	  UL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* \\  */
+	  LL;
+	  DUMP;
+	  UR;
+	  DUMP;
+	  continue;
+	}
+      }
+
+      if ((d00 <= 0) && (d10 > 0)) {
+	if ((d01 > 0) && (d11 > 0)) { /* \  */
+	  LL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) { /* /  */
+	  UL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* //  */
+	  UL;
+	  DUMP;
+	  LR;
+	  DUMP;
+	  continue;
+	}
+      }
+      
+
+      if ((d00 <= 0) && (d10 <= 0)) { 
+	if ((d01 > 0) && (d11 <= 0)) {
+	  LR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) {
+	  UR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) {
+	  VT;
+	  DUMP;
+	  continue;
+	}
+      }
+
+      if ((d00 > 0) && (d10 > 0)) { 
+	if ((d01 <= 0) && (d11 > 0)) {
+	  LR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) {
+	  UR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) {
+	  VT;
+	  DUMP;
+	  continue;
+	}
+      }
+
+    }
+    /* skip left-hand edge */
+    v00++; v01++; v10++; v11++;
+    d01 = (level - *v00);
+    d11 = (level - *v10);
+  }
+
+  /****** bottom line *******/
+  v00 = matrix;  
+  v01 = matrix + 1;  
+  y = 0;
+  dx = 0;
+  dy = -0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP;
+    }
+  }
+
+  /********** top line *******/
+  v00 = matrix + Nx*(Ny - 1);  
+  v01 = v00 + 1;
+  y = Ny - 1;
+  dx = 0;
+  dy = 0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP;
+    }
+  }
+
+  /******** left line *********/
+  v00 = matrix; 
+  v01 = matrix + Nx;
+  x = 0;
+  dx = -0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP;
+    }
+  }
+
+  /******** right line *********/
+  v00 = matrix + Nx - 1; 
+  v01 = v00 + Nx;
+  x = Nx - 1;
+  dx = 0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP;
+    }
+  }
+  
+  KiiLoadOverlay (kapa, overlay, Noverlay, argv[2]);
+  free (overlay);
+
+  if (Npix != 1) free (matrix);
+  gprint (GP_ERR, "\n");
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvgrid.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvgrid.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/tvgrid.c	(revision 16632)
@@ -0,0 +1,152 @@
+# include "data.h"
+# define TEN(X) (pow(10.0, (double)(X)))
+
+int tvgrid (int argc, char **argv) {
+  
+  int ndig1, ndig2, NX, NY, connect;
+  int tDEC, tRA;
+  double ra, dec, ra0, dec0, ra1, dec1;
+  double x0, y0, x1, y1;
+  double dDEC, fDEC, dRA, fRA;
+  char format[16];
+  Coords coords;
+  int kapa, N, Noverlay, NOVERLAY;
+  char *name;
+  Buffer *buf;
+  KiiOverlay *overlay;
+
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: tvgrid (overlay) (buffer)\n");
+    gprint (GP_ERR, " (overlay) may be: red, green, blue, yellow\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  GetCoords (&coords, &buf[0].header);
+
+  XY_to_RD (&ra0, &dec0, 0.0, 0.0, &coords);
+  XY_to_RD (&ra1, &dec1, (double)buf[0].header.Naxis[0], (double)buf[0].header.Naxis[1], &coords);
+  gprint (GP_ERR, "%f %f  %f %f\n", ra0, dec0, ra1, dec1);
+  
+  Noverlay = 0;
+  NOVERLAY = 1000;
+  ALLOCATE (overlay, KiiOverlay, NOVERLAY);
+
+  dDEC = fabs(dec1 - dec0);
+  tDEC = log10(dDEC) - log10(5.0);
+  fDEC = log10(dDEC) - tDEC;
+  if ((fDEC > log10(0.5)) && (fDEC < log10(1.0))) {
+    dDEC = TEN (tDEC + log10(0.1));
+  }
+  if ((fDEC > log10(1.0)) && (fDEC < log10(2.0))) {
+    dDEC = TEN (tDEC + log10(0.2));
+  }
+  if ((fDEC > log10(2.0)) && (fDEC < log10(5.0))) {
+    dDEC = TEN (tDEC + log10(0.5));
+  }
+  if ((fDEC > log10(5.0)) && (fDEC < log10(10.0))) {
+    dDEC = TEN (tDEC + log10(1.0));
+  }
+  if ((fDEC > log10(10.0)) && (fDEC < log10(20.0))) {
+    dDEC = TEN (tDEC + log10(2.0));
+  }
+  if ((fDEC > log10(20.0)) && (fDEC < log10(50.0))) {
+    dDEC = TEN (tDEC + log10(5.0));
+  }
+  ndig2 = ((log10(dDEC) < 0) ? fabs(log10(dDEC)) : 0);
+  ndig1 = 3 + log10(MAX(dec0, dec1)) + ndig2;
+  sprintf (format, "%%%d.%df", ndig1, ndig2);
+  gprint (GP_ERR, "format: %s..\n", format);
+
+  NX = buf[0].header.Naxis[0];
+  NY = buf[0].header.Naxis[1];
+
+  x0 = y0 = 0;
+  dRA = MAX (fabs(ra1 - ra0) / 100.0, 0.1);
+  connect = FALSE;
+  for (dec = dDEC * ((int)(MIN(dec0,dec1)/dDEC) + 1); dec < MAX(dec0,dec1); dec += dDEC) {
+    for (ra = 0; ra < 361; ra += dRA) {
+      RD_to_XY (&x1, &y1, ra, dec, &coords);
+      if ((x1 >= 0) && (x1 < NX) && (y1 >= 0) && (y1 < NY)) {
+	if (connect) {
+	  overlay[Noverlay].type = KII_OVERLAY_LINE;
+	  overlay[Noverlay].x = x0;
+	  overlay[Noverlay].y = y0;
+	  overlay[Noverlay].dx = x1 - x0;
+	  overlay[Noverlay].dy = y1 - y0;
+	  Noverlay ++;
+	  CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000);
+	}
+	x0 = x1;
+	y0 = y1;
+	connect = TRUE;
+      } else {
+	connect = FALSE;
+      }
+    }
+  }
+
+  dRA = fabs(ra1 - ra0);
+  tRA = log10(dRA) - log10(5.0);
+  fRA = log10(dRA) - tRA;
+  if ((fRA > log10(0.5)) && (fRA < log10(1.0))) {
+    dRA = TEN (tRA + log10(0.1));
+  }
+  if ((fRA > log10(1.0)) && (fRA < log10(2.0))) {
+    dRA = TEN (tRA + log10(0.2));
+  }
+  if ((fRA > log10(2.0)) && (fRA < log10(5.0))) {
+    dRA = TEN (tRA + log10(0.5));
+  }
+  if ((fRA > log10(5.0)) && (fRA < log10(10.0))) {
+    dRA = TEN (tRA + log10(1.0));
+  }
+  if ((fRA > log10(10.0)) && (fRA < log10(20.0))) {
+    dRA = TEN (tRA + log10(2.0));
+  }
+  if ((fRA > log10(20.0)) && (fRA < log10(50.0))) {
+    dRA = TEN (tRA + log10(5.0));
+  }
+  ndig2 = ((log10(dRA) < 0) ? fabs(log10(dRA)) : 0);
+  ndig1 = 3 + log10(MAX(ra0, ra1)) + ndig2;
+  sprintf (format, "%%%d.%df", ndig1, ndig2);
+  gprint (GP_ERR, "format: %s..\n", format);
+
+  dDEC = MAX (fabs(dec1 - dec0) / 100.0, 0.1);
+  connect = FALSE;
+  for (ra = dRA * ((int)(MIN(ra0,ra1)/dRA) + 1); ra < MAX(ra0,ra1); ra += dRA) {
+    for (dec = -90; dec < 90; dec += dDEC) {
+      RD_to_XY (&x1, &y1, ra, dec, &coords);
+      if ((x1 >= 0) && (x1 < NX) && (y1 >= 0) && (y1 < NY)) {
+	if (connect) {
+	  overlay[Noverlay].type = KII_OVERLAY_LINE;
+	  overlay[Noverlay].x = x0;
+	  overlay[Noverlay].y = y0;
+	  overlay[Noverlay].dx = x1 - x0;
+	  overlay[Noverlay].dy = y1 - y0;
+	  Noverlay ++;
+	  CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000);
+	}
+	x0 = x1;
+	y0 = y1;
+	connect = TRUE;
+      } else {
+	connect = FALSE;
+      }
+    }
+  }
+
+  KiiLoadOverlay (kapa, overlay, Noverlay, argv[1]);
+  free (overlay);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/ungridify.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/ungridify.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/ungridify.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "data.h"
+
+int ungridify (int argc, char **argv) {
+
+  int i, j, n;
+  int Nx, Ny, NX, NY;
+  int Xmin, Xmax, Ymin, Ymax;
+  float *v, *x, *y, *z;
+  Buffer *bf;
+  Vector *vx, *vy, *vz;
+
+  if (argc != 9) {
+    gprint (GP_ERR, "USAGE: ungridify buffer Xmin Xmax Ymin Ymax x y z\n");
+    return (FALSE);
+  }
+  
+  if ((bf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  Xmin = atof (argv[2]);
+  Xmax = atof (argv[3]);
+  Ymin = atof (argv[4]);
+  Ymax = atof (argv[5]);
+  Nx = Xmax - Xmin;
+  Ny = Ymax - Ymin;
+  
+  NX = bf[0].matrix.Naxis[0];
+  NY = bf[0].matrix.Naxis[1];
+
+  if ((vx = SelectVector (argv[6], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vy = SelectVector (argv[7], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vz = SelectVector (argv[8], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  REALLOCATE (vx[0].elements, float, Nx*Ny);
+  REALLOCATE (vy[0].elements, float, Nx*Ny);
+  REALLOCATE (vz[0].elements, float, Nx*Ny);
+
+  x = vx[0].elements;
+  y = vy[0].elements;
+  z = vz[0].elements;
+  n = 0;
+  v = (float *)bf[0].matrix.buffer;
+  for (j = Ymin; j < Ymax; j++) {
+    for (i = Xmin; i < Xmax; i++, x++, y++, z++, n++) {
+      vx[0].elements[n] = i;
+      vy[0].elements[n] = j;
+      if (i < 0) continue;
+      if (i >= NX) continue;
+      if (j < 0) continue;
+      if (j >= NY) continue;
+      vz[0].elements[n] = v[i+j*NX];
+    }
+  }
+  if (n != Nx*Ny) {
+    gprint (GP_ERR, "error in ungrid: %d vs %d (%d x %d)\n", n, Nx*Ny, Nx, Ny);
+  }
+  vx[0].Nelements = vy[0].Nelements = vz[0].Nelements = n;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/uniq.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/uniq.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/uniq.c	(revision 16632)
@@ -0,0 +1,39 @@
+# include "data.h"
+
+int uniq (int argc, char **argv) {
+  
+  int Nnew, i, j, found;
+  float *v1, *v2;
+  Vector *ivec, *ovec;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: uniq (in) (out)\n");
+    return (FALSE);
+  }
+
+  if ((ivec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* allocate the maximum possible needed */
+  ALLOCATE (ovec[0].elements, float, ivec[0].Nelements);
+
+  Nnew = 0;
+  v1 = ivec[0].elements;
+  for (i = 0; i < ivec[0].Nelements; i++, v1++) {
+    v2 = ovec[0].elements;
+    found = FALSE;
+    for (j = 0; !found && (j < Nnew); j++, v2++) {
+      if (*v1 == *v2) found = TRUE;
+    }
+    if (!found) {
+      ovec[0].elements[Nnew] = *v1;
+      Nnew ++;
+    }
+  }
+
+  ovec[0].Nelements = Nnew;
+  REALLOCATE (ovec[0].elements, float, ovec[0].Nelements);
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/unsign.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/unsign.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/unsign.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "data.h"
+
+int unsign (int argc, char **argv) {
+  
+  if (argc == 1) {
+    if (gfits_get_unsign_mode()) 
+      gprint (GP_ERR, "mode is now UNSIGNED int \n");
+    else
+      gprint (GP_ERR, "mode is now SIGNED int \n");
+    return (TRUE);
+  }
+
+  if (argc == 2) {
+    if (!strcmp (argv[1], "1")) {
+      gfits_set_unsign_mode (TRUE);
+      set_int_variable ("UNSIGN", 1);
+      return (TRUE);
+    }
+    if (!strcmp (argv[1], "0")) {
+      gfits_set_unsign_mode (FALSE);
+      set_int_variable ("UNSIGN", 0);
+      return (TRUE);
+    }
+  }
+
+  gprint (GP_ERR, "USAGE: unsign [0/1]\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vbin.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vbin.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vbin.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "data.h"
+
+int vbin (int argc, char **argv) {
+  
+  int i, j, n, N, Nin, Nout;
+  int Normalize, Ignore;
+  float *Vout, *Vin, IgnoreValue;
+  double scale;
+  Vector *in, *out;
+
+  Normalize = FALSE;
+  if ((N = get_argument (argc, argv, "-norm"))) {
+    remove_argument (N, &argc, argv);
+    Normalize = TRUE;
+  }
+
+  Ignore = FALSE;
+  IgnoreValue = 0.0;
+  if ((N = get_argument (argc, argv, "-ignore"))) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: vbin <input> <output> scale \n");
+    gprint (GP_ERR, "  (use interpolate to expand)\n");
+    return (FALSE);
+  }
+
+  if ((in  = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((out = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  scale  = atof (argv[3]);
+  if ((int)(scale) != scale) {
+    gprint (GP_ERR, "integer binning only, please\n");
+    return (FALSE);
+  }
+
+  Nin  = in[0].Nelements;
+  Nout = Nin / scale;
+
+  REALLOCATE (out[0].elements, float, Nout);
+  out[0].Nelements = Nout;
+
+  Vin  = in[0].elements;
+  Vout = out[0].elements;
+  for (n = j = 0; j < Nout; j++, Vout++) {
+    *Vout = 0;
+    for (N = i = 0; (i < scale) && (n < Nin); n++, i++, Vin++) {
+      if (!finite (*Vin)) continue;
+      if (Ignore && (*Vin == IgnoreValue)) continue;
+      *Vout += *Vin;
+      N ++;
+    } 
+    if (Normalize) {
+      if (N > 0) { 
+	*Vout /= (float) N; 
+      } else {
+	*Vout = 0;
+      }
+    }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vclip.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vclip.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vclip.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "data.h"
+
+int vclip (int argc, char **argv) {
+
+  int i, Npix, DO_NAN, DO_INF, N;
+  double min, Vmin, max, Vmax, nan_val, inf_val;
+  float *in;
+  Vector *vec;
+
+  inf_val = nan_val = min = Vmin = max = Vmax = 0;
+
+  DO_NAN = FALSE;
+  if ((N = get_argument (argc, argv, "-nan"))) {
+    remove_argument (N, &argc, argv);
+    nan_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_NAN = TRUE;
+  }
+
+  DO_INF = FALSE;
+  if ((N = get_argument (argc, argv, "-inf"))) {
+    remove_argument (N, &argc, argv);
+    inf_val  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    DO_INF = TRUE;
+  }
+
+  if ((argc != 6) && (!(DO_INF || DO_NAN))) {
+    gprint (GP_ERR, "USAGE: vclip (vector) [min Vmin max Vmax] [-inf val] [-nan val]\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (argc == 6) {
+    min = atof (argv[2]);
+    Vmin = atof (argv[3]);
+    max = atof (argv[4]);
+    Vmax = atof (argv[5]);
+  }
+
+  Npix = vec[0].Nelements;
+  in =   vec[0].elements;
+
+  if (argc == 6) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (*in < min) 
+	*in = Vmin;
+      if (*in > max)
+	*in = Vmax;
+    }
+  }
+  in = vec[0].elements;
+  if (DO_NAN) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (isnan (*in)) {
+	*in = nan_val;
+      }
+    }
+  }
+  in = vec[0].elements;
+  if (DO_INF) {
+    for (i = 0; i < Npix; i++, in++) {
+      if (!finite (*in)) {
+	*in = inf_val;
+      }
+    }
+  }
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vcontour.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vcontour.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vcontour.c	(revision 16632)
@@ -0,0 +1,278 @@
+# include "data.h"
+# define LL { \
+ dx =  d00 / (*v01 - *v00); \
+ dy = -d00 / (*v10 - *v00); \
+ x = i - 0.5; \
+ y = j - dy - 0.5; }
+
+# define UL { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = 1 - tmp; \
+ dx =  d10 / (*v11 - *v10); \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+      
+# define LR { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = 1 - tmp; \
+ dy = d01 / (*v11 - *v01); \
+ x = i + tmp - 0.5; \
+ y = j - 0.5; }
+
+# define UR { \
+ tmp = d10 / (*v11 - *v10); \
+ dx = 1 - tmp; \
+ dy = -d11 / (*v01 - *v11); \
+ x = i + tmp - 0.5; \
+ y = j + 1 - 0.5; }
+      
+# define HZ { \
+ tmp = d00 / (*v10 - *v00); \
+ dy = d01 / (*v11 - *v01) - tmp; \
+ dx = 1; \
+ x = i - 0.5; \
+ y = j + tmp - 0.5; }
+
+# define VT { \
+ tmp = d00 / (*v01 - *v00); \
+ dx = d10 / (*v11 - *v10) - tmp; \
+ x = i + tmp - 0.5; \
+ dy = 1; \
+ y = j - 0.5; }
+
+# define DUMP { \
+overlay[Noverlay].type = KII_OVERLAY_LINE; \
+overlay[Noverlay].x = Npix*x; \
+overlay[Noverlay].y = Npix*y; \
+overlay[Noverlay].dx = Npix*dx; \
+overlay[Noverlay].dy = Npix*dy; \
+Noverlay ++; \
+CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000); \
+}
+
+int vcontour (int argc, char **argv) {
+
+  int i, j, ii, jj, n, Nbuf, Npix, Nx, Ny, Nline;
+  float level, d00, d01, d10, d11, tmp;
+  float x, y, dx, dy;
+  float *v00, *v01, *v10, *v11;
+  float *Vout, *Vin, *matrix;
+  char *buffer, line[17];
+  int Ximage, Nimage, N;
+  Vector *xvec, *yvec, *zvec;
+
+  gprint (GP_ERR, "vcontour not working yet\n");
+  return (FALSE);
+
+  if (argc != 7) {
+    gprint (GP_ERR, "USAGE: vcontour x y z Xc Yc (level)\n");
+    return (FALSE);
+  }
+  
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((foo = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((foo = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  level = atof (argv[6]);
+
+  /* convert the x,y,z vectors to a matrix */
+  *V = xvec[0].elements;
+  max = min = *V;
+  for (i = 0; i < xvec[0].Nelements; i++, V++) {
+    if (!finite (*V)) continue;
+    max = MAX (*V, max);
+    min = MIN (*V, min);
+  }      
+  Xmax = max; Xmin = min;
+
+  *V = yvec[0].elements;
+  max = min = *V;
+  for (i = 0; i < yvec[0].Nelements; i++, V++) {
+    if (!finite (*V)) continue;
+    max = MAX (*V, max);
+    min = MIN (*V, min);
+  }      
+  Ymax = max; Ymin = min;
+
+  /* not really finished */
+
+  Noverlay = 0;
+  NOVERLAY = 1000;
+  ALLOCATE (overlay, KiiOverlay, NOVERLAY);
+
+  v01 = matrix + 1;
+  v10 = matrix + Nx;
+  v11 = matrix + Nx + 1;
+  d01 = (level - *v00);
+  d11 = (level - *v10);
+  for (j = 1; j < Ny; j++) {
+    if (!(j%10)) gprint (GP_ERR, ".");
+    for (i = 1; i < Nx; i++, v00++, v01++, v10++, v11++) {
+
+      d00 = d01;
+      d10 = d11;
+      d01 = (level - *v01);
+      d11 = (level - *v11);
+
+      if (((d00 > 0) && (d01 > 0) && (d10 > 0) && (d11 > 0)) ||
+	  ((d00 < 0) && (d01 < 0) && (d10 < 0) && (d11 < 0)))
+	continue;
+
+      if ((d00 > 0) && (d10 <= 0)) { 
+	if ((d01 <= 0) && (d11 <= 0)) { /* \  */
+	  LL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) { /* /  */
+	  UL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* \\  */
+	  LL;
+	  DUMP;
+	  UR;
+	  DUMP;
+	  continue;
+	}
+      }
+
+      if ((d00 <= 0) && (d10 > 0)) {
+	if ((d01 > 0) && (d11 > 0)) { /* \  */
+	  LL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) { /* -  */
+	  HZ;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) { /* /  */
+	  UL;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) { /* //  */
+	  UL;
+	  DUMP;
+	  LR;
+	  DUMP;
+	  continue;
+	}
+      }
+      
+
+      if ((d00 <= 0) && (d10 <= 0)) { 
+	if ((d01 > 0) && (d11 <= 0)) {
+	  LR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 > 0)) {
+	  UR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 > 0)) {
+	  VT;
+	  DUMP;
+	  continue;
+	}
+      }
+
+      if ((d00 > 0) && (d10 > 0)) { 
+	if ((d01 <= 0) && (d11 > 0)) {
+	  LR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 > 0) && (d11 <= 0)) {
+	  UR;
+	  DUMP;
+	  continue;
+	}
+	if ((d01 <= 0) && (d11 <= 0)) {
+	  VT;
+	  DUMP;
+	  continue;
+	}
+      }
+
+    }
+    /* skip left-hand edge */
+    v00++; v01++; v10++; v11++;
+    d01 = (level - *v00);
+    d11 = (level - *v10);
+  }
+
+  /****** bottom line *******/
+  v00 = matrix;  
+  v01 = matrix + 1;  
+  y = 0;
+  dx = 0;
+  dy = -0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP;
+      continue;
+    }
+  }
+
+  /********** top line *******/
+  v00 = matrix + Nx*(Ny - 1);  
+  v01 = v00 + 1;
+  y = Ny - 1;
+  dx = 0;
+  dy = 0.5;
+  for (i = 1; i < Nx; i++, v00++, v01++) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      x = i + (level - *v01)/(*v01 - *v00);
+      DUMP;
+      continue;
+    }
+  }
+
+  /******** left line *********/
+  v00 = matrix; 
+  v01 = matrix + Nx;
+  x = 0;
+  dx = -0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP;
+      continue;
+    }
+  }
+
+  /******** right line *********/
+  v00 = matrix + Nx - 1; 
+  v01 = v00 + Nx;
+  x = Nx - 1;
+  dx = 0.5;
+  dy = 0;
+  for (j = 1; j < Ny; j++, v00+=Nx, v01+=Nx) { /* do the edges */
+    if (((*v00 > level) && (*v01 <= level)) || ((*v00 <= level) && (*v01 > level))) {
+      y = j + (level - *v01)/(*v01 - *v00);
+      DUMP;
+      continue;
+    }
+  }
+  
+  KiiLoadOverlay (Ximage, overlay, Noverlay, argv[2]);
+  free (overlay);
+
+  if (Npix != 1) free (matrix);
+  gprint (GP_ERR, "\n");
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vgauss.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vgauss.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vgauss.c	(revision 16632)
@@ -0,0 +1,106 @@
+# include "data.h"
+
+/* local private functions */
+float fgaussOD (float, float *, int, float *);
+
+# define GET_VAR(V,A) \
+  c = get_variable (A); \
+  if (c == NULL) { \
+    gprint (GP_ERR, "missing fit parameter A\n"); \
+    return (FALSE); \
+  } \
+  V = atof (c); \
+  free (c);
+
+int vgauss (int argc, char **argv) {
+
+  int i, N, Npts, Npar, Quiet;
+  float par[4], *v1, *v2, *dy, **covar;
+  float chisq, ochisq, dchisq;
+  Vector *xvec, *yvec, *svec, *ovec;
+  char *c, name[16];
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: vgauss <x> <y> <dy> (out)\n");
+    gprint (GP_ERR, " uses guesses: C0 (mean), C1 (sigma), C2 (norm), C3 (sky)\n");
+    return (FALSE);
+  }
+  
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((svec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Npts = xvec[0].Nelements;
+  ALLOCATE (dy, float, Npts);
+  REALLOCATE (ovec[0].elements, float, Npts);
+
+  GET_VAR (par[0], "C0");
+  GET_VAR (par[1], "C1");
+  GET_VAR (par[2], "C2");
+  GET_VAR (par[3], "C3");
+  Npar = 4;
+
+  v1 = svec[0].elements;
+  v2 = dy;
+  for (i = 0; i < Npts; i++, v1++, v2++) {
+      *v2 = (*v1 == 0.0) ? 0.0 : 1.0 / (*v1 * *v1);
+  } 
+  
+  ochisq = mrqinit (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fgaussOD, !Quiet);
+  dchisq = ochisq + 2*Npts;
+
+  for (i = 0; (i < 20) && ((dchisq > 0.1*(Npts - Npar)) || (dchisq <= 0.0)); i++) {
+    chisq = mrqmin (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fgaussOD, !Quiet);
+    dchisq = ochisq - chisq;
+    ochisq = chisq;
+    if (!Quiet) gprint (GP_ERR, "dchisq: %f, Ndof: %d\n", dchisq, Npts - Npar);
+  }  
+  if (!Quiet) gprint (GP_ERR, "%d iterations\n", i); 
+
+  for (i = 0; i < Npts; i++) {
+    ovec[0].elements[i] = fgaussOD (xvec[0].elements[i], par, Npar, dy);
+  }
+  ovec[0].Nelements = Npts;
+  /* set output *before* variable renomalization */
+
+  covar = mrqcovar (Npar);
+  for (i = 0; i < Npar; i++) {
+    sprintf (name, "C%d", i);
+    set_variable (name, par[i]);
+    if (!Quiet) gprint (GP_ERR, "%d  %f  %f\n", i, par[i], sqrt(covar[i][i]));
+    sprintf (name, "dC%d", i);
+    set_variable (name, sqrt(covar[i][i]));
+  }
+
+  free (dy);
+  mrqfree (Npar);
+  return (TRUE);
+}
+
+/* pars: x_o, sigma, I, back */
+float fgaussOD (float x, float *par, int Npar, float *dpar) {
+
+  float z, r, f;
+
+  z = (x - par[0])/par[1];
+  r = exp (-0.5*SQ(z));
+  f = par[2]*r + par[3];
+
+  dpar[0] = par[2]*r*z/par[1];
+  dpar[1] = par[2]*r*z*z/par[1];
+  dpar[2] = r;
+  dpar[3] = 1;
+  
+  return (f);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vgrid.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vgrid.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vgrid.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "data.h"
+
+int vgrid (int argc, char **argv) {
+
+  int i, Nx, Ny, Xb, Yb;
+  float Xmin, Xmax, dX, Ymin, Ymax, dY;
+  float *buf, *val, *x, *y, *z;
+  int *Nval;
+  Buffer *bf;
+  Vector *vx, *vy, *vz;
+
+  if (argc != 11) {
+    gprint (GP_ERR, "USAGE: vgrid x y z buffer Xmin Xmax dX Ymin Ymax dY\n");
+    return (FALSE);
+  }
+  
+  if ((vx = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vy = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vz = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((bf = SelectBuffer (argv[4], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (vx[0].Nelements != vy[0].Nelements) return (FALSE);
+  if (vx[0].Nelements != vz[0].Nelements) return (FALSE);
+
+  Xmin = atof (argv[5]);
+  Xmax = atof (argv[6]);
+  dX   = atof (argv[7]);
+
+  Ymin = atof (argv[8]);
+  Ymax = atof (argv[9]);
+  dY   = atof (argv[10]);
+
+  Nx = (Xmax - Xmin) / dX + 1;
+  Ny = (Ymax - Ymin) / dY + 1;
+  
+  gfits_free_matrix (&bf[0].matrix);
+  gfits_free_header (&bf[0].header);
+  CreateBuffer (bf, Nx, Ny, -32, 0.0, 1.0);
+  strcpy (bf[0].file, "(empty)");
+
+  ALLOCATE (val, float, Nx*Ny);
+  bzero (val, Nx*Ny*sizeof(float));
+  ALLOCATE (Nval, int, Nx*Ny);
+  bzero (Nval, Nx*Ny*sizeof(int));
+
+  x = vx[0].elements;
+  y = vy[0].elements;
+  z = vz[0].elements;
+  for (i = 0; i < vx[0].Nelements; i++, x++, y++, z++) {
+    Xb = (*x - Xmin) / dX;
+    Yb = (*y - Ymin) / dY;
+    if (Xb >= Nx) continue;
+    if (Yb >= Ny) continue;
+    val[Xb + Yb*Nx] = *z;
+    Nval[Xb + Yb*Nx]++;
+  }
+
+  buf = (float *) bf[0].matrix.buffer;
+  for (i = 0; i < Nx*Ny; i++) {
+    if (Nval[i] == 0) {
+      buf[i] = 0;
+      continue;
+    }
+    buf[i] = val[i] / Nval[i];
+  }
+
+  free (val);
+  free (Nval);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vload.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vload.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vload.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "data.h"
+
+int vload (int argc, char **argv) {
+  
+  int i, N, Noverlay;
+  int kapa, type;
+  char *name;
+  double dx, dy, size;
+  KiiOverlay *overlay;
+  Vector *vecx, *vecy;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  type = KII_OVERLAY_BOX;
+  if ((N = get_argument (argc, argv, "-type"))) {
+    remove_argument (N, &argc, argv);
+    type = KiiOverlayTypeByName (argv[N]);
+    remove_argument (N, &argc, argv);
+    if (!type) {
+      gprint (GP_ERR, "unknown Kii point type %s\n", argv[N]);
+      return (FALSE);
+    }
+  }
+
+  size = 1.0;
+  if ((N = get_argument (argc, argv, "-size"))) {
+    remove_argument (N, &argc, argv);
+    size = fabs(atof (argv[N]));
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: vload (overlay) (xvec) (yvec) [-n]\n");
+    return (FALSE);
+  }
+  
+  if (type == KII_OVERLAY_CIRCLE) {
+    dx = dy = size / 2;
+  } else {
+    dx = dy = size;
+  }    
+
+  if ((vecx = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (vecx[0].Nelements != vecy[0].Nelements) {
+    gprint (GP_ERR, "mismatched vector lengths\n");
+    return (FALSE);
+  }
+
+  Noverlay = vecx[0].Nelements;
+  ALLOCATE (overlay, KiiOverlay, Noverlay);
+
+  for (i = 0; i < Noverlay; i++) {
+    overlay[i].type = type;
+    overlay[i].text = NULL;
+    overlay[i].x = vecx[0].elements[i]+0.5;
+    overlay[i].y = vecy[0].elements[i]+0.5;
+    overlay[i].dx = dx;
+    overlay[i].dy = dy;
+  }
+
+  KiiLoadOverlay (kapa, overlay, Noverlay, argv[1]);
+  free (overlay);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vmaxwell.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vmaxwell.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vmaxwell.c	(revision 16632)
@@ -0,0 +1,108 @@
+# include "data.h"
+
+/* local private functions */
+float fmaxwellOD (float, float *, int, float *);
+
+# define GET_VAR(V,A) \
+  c = get_variable (A); \
+  if (c == NULL) { \
+    gprint (GP_ERR, "missing fit parameter A\n"); \
+    return (FALSE); \
+  } \
+  V = atof (c); \
+  free (c);
+
+int vmaxwell (int argc, char **argv) {
+
+  int i, N, Npts, Npar, Quiet;
+  float par[5], *v1, *v2, *dy, **covar;
+  float chisq, ochisq, dchisq;
+  Vector *xvec, *yvec, *svec, *ovec;
+  char *c, name[16];
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: vmaxwell <x> <y> <dy> (out)\n");
+    gprint (GP_ERR, " uses guesses: C0 (mean), C1 (sigma), C2 (norm), C3 (sky), C4 (ref)\n");
+    return (FALSE);
+  }
+  
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((svec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ovec = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Npts = xvec[0].Nelements;
+  ALLOCATE (dy, float, Npts);
+  REALLOCATE (ovec[0].elements, float, Npts);
+
+  GET_VAR (par[0], "C0");
+  GET_VAR (par[1], "C1");
+  GET_VAR (par[2], "C2");
+  GET_VAR (par[3], "C3");
+  GET_VAR (par[4], "C4");
+  Npar = 5;
+  /* careful of variable renomalization */
+
+  v1 = svec[0].elements;
+  v2 = dy;
+  for (i = 0; i < Npts; i++, v1++, v2++) *v2 = 1.0 / (*v1 * *v1);
+  
+  ochisq = mrqinit (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fmaxwellOD, !Quiet);
+  dchisq = ochisq + 2*Npts;
+
+  for (i = 0; (i < 20) && ((dchisq > 0.1*(Npts - Npar)) || (dchisq <= 0.0)); i++) {
+    chisq = mrqmin (xvec[0].elements, yvec[0].elements, dy, Npts, par, Npar, fmaxwellOD, !Quiet);
+    dchisq = ochisq - chisq;
+    ochisq = chisq;
+    if (!Quiet) gprint (GP_ERR, "dchisq: %f, Ndof: %d\n", dchisq, Npts - Npar);
+  }  
+  if (!Quiet) gprint (GP_ERR, "%d iterations\n", i); 
+
+  for (i = 0; i < Npts; i++) {
+    ovec[0].elements[i] = fmaxwellOD (xvec[0].elements[i], par, Npar, dy);
+  }
+  ovec[0].Nelements = Npts;
+  /* set output *before* variable renomalization */
+
+  covar = mrqcovar (Npar);
+  for (i = 0; i < Npar; i++) {
+    sprintf (name, "C%d", i);
+    set_variable (name, par[i]);
+    if (!Quiet) gprint (GP_ERR, "%d  %f  %f\n", i, par[i], sqrt(covar[i][i]));
+    sprintf (name, "dC%d", i);
+    set_variable (name, sqrt(covar[i][i]));
+  }
+
+  free (dy);
+  mrqfree (Npar);
+  return (TRUE);
+}
+
+/* pars: x_o, -0.5/sigma^2, I, back, ref */
+float fmaxwellOD (float x, float *par, int Npar, float *dpar) {
+
+  float z, r, f;
+
+  z = (x - par[0])/par[1];
+  r = SQ(x - par[4])*exp (-0.5*SQ(z));
+  f = par[2]*r + par[3];
+
+  dpar[0] = par[2]*r*z/par[1];
+  dpar[1] = par[2]*r*z*z/par[1];
+  dpar[2] = r;
+  dpar[3] = 1;
+  dpar[4] = -par[2]*(x - par[4])*exp(-0.5*SQ(z));
+  
+  return (f);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vpop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vpop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vpop.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "data.h"
+
+int vpop (int argc, char **argv) {
+
+  int Npix;
+  Vector *vec;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: vpop (vector)\n");
+    gprint (GP_ERR, "  remove first element of vector\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  Npix = vec[0].Nelements;
+  if (Npix < 1) return (TRUE);
+
+  if (Npix > 1) {
+    memmove (&vec[0].elements[0], &vec[0].elements[1], Npix*sizeof(float));
+  }
+  vec[0].Nelements = Npix - 1;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vroll.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vroll.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vroll.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "data.h"
+
+int vroll (int argc, char **argv) {
+
+  int Npix;
+  float first;
+  Vector *vec;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: vroll (vector)\n");
+    gprint (GP_ERR, "  roll vector elements (first goes to end)\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  Npix = vec[0].Nelements;
+  if (Npix < 2) return (TRUE);
+
+  first = vec[0].elements[0];
+  memmove (&vec[0].elements[0], &vec[0].elements[1], Npix*sizeof(float));
+  vec[0].elements[Npix-1] = first;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vsmooth.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vsmooth.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vsmooth.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "data.h"
+
+int vsmooth (int argc, char **argv) {
+  
+  int i, n, N, Nx, Ns, Ngauss;
+  float *vi, *vo, *gauss, *gaussnorm;
+  float g, s, sigma, Nsigma;
+  Vector *in;
+
+  Nsigma = 3;
+  if ((N = get_argument (argc, argv, "-Nsigma"))) {
+    remove_argument (N, &argc, argv);
+    Nsigma = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: vsmooth (input) sigma\n");
+    return (FALSE);
+  }
+  
+  if ((in  = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  sigma = atof (argv[2]);
+  Nx = in[0].Nelements;
+  vi = in[0].elements;
+
+  /* build a 1D gaussian */
+  Ns = (int) (Nsigma*sigma + 0.5);
+  Ngauss = 2*Ns + 1;
+  ALLOCATE (gaussnorm, float, Ngauss);
+  gauss = &gaussnorm[Ns];
+  for (i = -Ns; i < Ns + 1; i++) {
+    gauss[i] = exp ((i*i)/(-2*sigma*sigma));
+  }
+
+  ALLOCATE (vo, float, Nx);
+
+  for (i = 0; i < Nx; i++) {
+    g = s = 0;
+    for (n = -Ns; n < Ns + 1; n++) {
+      if (i+n < 0) continue;
+      if (i+n >= Nx) continue;
+      s += gauss[n]*vi[i+n];
+      g += gauss[n];
+    }
+    vo[i] = s / g;
+  }
+
+  free (in[0].elements);
+  free (gaussnorm);
+
+  in[0].elements = vo;
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vstat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vstat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/vstat.c	(revision 16632)
@@ -0,0 +1,115 @@
+# include "data.h"
+
+int vstat (int argc, char **argv) {
+  
+  int i, N;
+  double max, min, sum, var, dvar, mean, stdev;
+  float *X, IgnoreValue;
+  int Ignore, Quiet;
+
+  int *Nval, bin, Nmode, Nmed;
+  double dx, mode, median;
+  Vector *vec;
+
+  IgnoreValue = 0;
+  Ignore = FALSE;
+  if ((N = get_argument (argc, argv, "-ignore"))) {
+    Ignore = TRUE;
+    remove_argument (N, &argc, argv);
+    IgnoreValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Quiet = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-quiet"))) {
+    Quiet = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: vstat (vector)\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* we need two passes, one for max, min, mean, sum, one for median, stdev, etc */
+
+  /* calculate max, min, mean, sum, npix */
+  X = vec[0].elements;
+  max = -HUGE_VAL;
+  min = HUGE_VAL;
+  sum = N = 0;
+  for (i = 0; i < vec[0].Nelements; i++, X++) {
+    if (!finite (*X)) continue;
+    if (Ignore && (*X == IgnoreValue)) continue;
+    max = MAX (*X, max);
+    min = MIN (*X, min);
+    sum += *X;
+    N++;
+  }      
+  mean = sum / N;
+
+  /* calculate median and mode with resolution of (max - min) / 1000 */ 
+  dx = (max - min) / 1000;
+  if (dx == 0) {
+    median = mode = min;
+    stdev = 0.0;
+    goto skip;
+  }
+
+  ALLOCATE (Nval, int, 1002);
+  bzero (Nval, 1000*sizeof(int));
+  X = vec[0].elements;
+  var = 0;
+  for (i = 0; i < vec[0].Nelements; i++, X++) {
+    if (!finite (*X)) continue;
+    if (Ignore && (*X == IgnoreValue)) continue;
+    bin = MAX (0, MIN (1000, (*X - min) / dx));
+    Nval[bin] ++;
+    dvar = (*X - mean);
+    var += dvar*dvar;
+  }      
+  stdev = sqrt (var / N);
+
+  Nmode = 0;
+  mode = Nval[Nmode];
+  median = 0;
+  Nmed = -1;
+  for (i = 0; i < 1001; i++) {
+    if (Nmed == -1) {
+      median += Nval[i];
+      if (median >= N / 2.0) {
+	Nmed = i;
+	median = i * dx + min;
+      }
+    }
+    if (mode < Nval[i]) {
+      Nmode = i;
+      mode = Nval[Nmode];
+    }
+  }
+  mode = Nmode * dx + min;
+  free (Nval);
+
+skip:
+  if (!Quiet) {
+    gprint (GP_ERR, "mean: %g, stdev: %g, min: %g, max: %g, median: %g, mode: %g, Npts: %d\n", 
+	     mean, stdev, min, max, median, mode, N);
+  }
+
+  set_variable ("MIN",      min);
+  set_variable ("MAX",      max);
+  set_variable ("MEDIAN",   median);
+  set_variable ("MEAN",     mean);
+  set_variable ("MODE",     mode);
+  set_variable ("TOTAL",    sum);
+  set_int_variable ("NPIX", N);
+  set_variable ("SIGMA",    stdev);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/wd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/wd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/wd.c	(revision 16632)
@@ -0,0 +1,179 @@
+# include "data.h"
+
+int wd (int argc, char **argv) {
+  
+  int N, Extend;
+  int newUnsign, newBitpix, newScale, newZero;
+  int outUnsign, outBitpix;
+  double outScale, outZero;
+  Header temp_header;
+  Matrix temp_matrix;
+  Buffer *buf;
+
+  /* XXX I must have dropped the old 'newplane' option */
+  Extend  = FALSE;
+  if ((N = get_argument (argc, argv, "-extend"))) {
+    remove_argument (N, &argc, argv);
+    Extend  = TRUE;
+  }
+
+  outZero = 0;
+  newZero = FALSE;
+  if ((N = get_argument (argc, argv, "-bzero"))) {
+    remove_argument (N, &argc, argv);
+    outZero  = atof(argv[N]);
+    newZero  = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  outScale = 1;
+  newScale = FALSE;
+  if ((N = get_argument (argc, argv, "-bscale"))) {
+    remove_argument (N, &argc, argv);
+    outScale = atof(argv[N]);
+    newScale = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  outBitpix = 16;
+  newBitpix = FALSE;
+  if ((N = get_argument (argc, argv, "-bitpix"))) {
+    remove_argument (N, &argc, argv);
+    outBitpix = atof(argv[N]);
+    newBitpix = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  outUnsign = FALSE;
+  newUnsign = FALSE;
+  if ((N = get_argument (argc, argv, "-unsign"))) {
+    remove_argument (N, &argc, argv);
+    outUnsign = -1;
+    if (!strcasecmp (argv[N], "t") || !strcasecmp (argv[N], "true")) outUnsign = TRUE;
+    if (!strcasecmp (argv[N], "f") || !strcasecmp (argv[N], "false")) outUnsign = FALSE;
+    if (outUnsign == -1) {
+      gprint (GP_ERR, "-unsign options: t, f, true, false\n");
+      return (FALSE);
+    }
+    newUnsign = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: wd <buffer> <filename> [-bitpix N] [-bscale X] [-bzero X] [-extend] [-newplane]\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  if (!newBitpix) outBitpix = buf[0].bitpix;
+  if (!newScale) outScale = buf[0].bscale;
+  if (!newZero) outZero = buf[0].bzero;
+  if (!newUnsign) outUnsign = buf[0].unsign;
+
+  /* Convert the buffer from (float) to correct format */
+  /* save the (float) version, write out a temporary buffer */
+  temp_matrix = buf[0].matrix;
+  ALLOCATE (temp_matrix.buffer, char, MAX(1, temp_matrix.size));
+  memcpy (temp_matrix.buffer, buf[0].matrix.buffer, temp_matrix.size);
+  temp_header = buf[0].header;
+  ALLOCATE (temp_header.buffer, char, MAX(1, temp_header.size));
+  memcpy (temp_header.buffer, buf[0].header.buffer, temp_header.size);
+
+  if (temp_header.Naxes) gfits_convert_format (&temp_header, &temp_matrix, outBitpix, outScale, outZero, outUnsign);
+
+  if (Extend) {
+    Header Xhead;
+    FILE *f;
+    int status, Nextend;
+
+    /* assume failure means non-existent file */
+    if (!gfits_read_header (argv[2], &Xhead)) {
+
+      gfits_init_header (&Xhead);
+      Xhead.bitpix = 16;
+      Xhead.extend = TRUE;
+      gfits_create_header (&Xhead);
+
+      gfits_modify (&Xhead, "NEXTEND", "%d", 1, 0);
+      f = fopen (argv[2], "w");
+      fclose (f);
+    }
+
+    gfits_modify (&Xhead, "EXTEND", "%t", 1, TRUE);
+
+    Nextend = 0;
+    gfits_scan (&Xhead, "NEXTEND", "%d", 1, &Nextend);
+    Nextend ++;
+    gfits_modify (&Xhead, "NEXTEND", "%d", 1, Nextend);
+
+    /* write the main header to the start of the file */
+    f = fopen (argv[2], "r+");
+    if (f == NULL) {
+      gprint (GP_ERR, "failed to write file\n");
+      status = FALSE;
+      goto done1;
+    }
+    
+    /* position to begining of file to write header */
+    fseek (f, 0, SEEK_SET);
+    status = fwrite (Xhead.buffer, 1, Xhead.size, f);
+    if (status != Xhead.size) {
+      gprint (GP_ERR, "ERROR: failed writing data to image header\n");
+      status = FALSE;
+      goto done1;
+    }
+    
+    /* fix up header */
+    {
+      static char simple[] = "XTENSION= 'IMAGE  '            / Image extension";
+      int Ns, No;
+      Ns = strlen (simple);
+      No = 80 - Ns;
+      strncpy (temp_header.buffer, simple, Ns);
+      memset (&temp_header.buffer[Ns], ' ', No);
+    }
+
+    /* position to end of file to write new extend */
+    fseek (f, 0, SEEK_END);
+    status = fwrite (temp_header.buffer, 1, temp_header.size, f);
+    fclose (f);
+    if (status != temp_header.size) {
+      gprint (GP_ERR, "failed to write file\n");
+      status = FALSE;
+      goto done1;
+    }
+    /* write the matrix buffer (automatically goes to end of file */
+    if (!gfits_write_matrix (argv[2], &temp_matrix)) {
+      gprint (GP_ERR, "failed to write file\n");
+      status = FALSE;
+      goto done1;
+    }
+    status = TRUE;
+  done1:
+    gfits_free_header (&Xhead);
+    gfits_free_header (&temp_header);
+    gfits_free_matrix (&temp_matrix);
+    return (status);
+  }
+  
+  /* the actual write-to-disk goes here */
+  if (!gfits_write_header (argv[2], &temp_header)) {
+    gprint (GP_ERR, "failed to write header\n");
+    gfits_free_header (&temp_header);
+    gfits_free_matrix (&temp_matrix);
+    return (FALSE);
+  }
+  
+  if (!gfits_write_matrix (argv[2], &temp_matrix)) {
+    gprint (GP_ERR, "failed to write matrix\n");
+    gfits_free_header (&temp_header);
+    gfits_free_matrix (&temp_matrix);
+    return (FALSE);
+  }
+
+  gfits_free_header (&temp_header);
+  gfits_free_matrix (&temp_matrix);
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/write_vectors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/write_vectors.c	(revision 16632)
@@ -0,0 +1,151 @@
+# include "data.h"
+
+int write_vectors (int argc, char **argv) {
+  
+  int append;
+  int i, j, Nvec, Ne, N;
+  FILE *f;
+  char **fmtlist, *fmttype;
+  char *p0, *p1, *p2, *format;
+  Vector **vec;
+
+  /* look for format option */
+  format = (char *) NULL;
+  if ((N = get_argument (argc, argv, "-f"))) {
+    remove_argument (N, &argc, argv);
+    format = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  append = FALSE;
+  if ((N = get_argument (argc, argv, "-append"))) {
+    remove_argument (N, &argc, argv);
+    append = TRUE;
+  }
+
+  if (argc < 3) {
+    gprint (GP_ERR, "USAGE: write [-append] [-f \"format\"] file vector vector ...\n");
+    return (FALSE);
+  }
+
+  /* open file for outuput */
+  if (append) {
+      f = fopen (argv[1], "a");
+  } else {
+      f = fopen (argv[1], "w");
+  }
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't open file for write\n");
+    return (FALSE);
+  }
+
+  /* find number of output vectors */
+  Nvec = (argc - 2);
+  if (Nvec < 1) {
+      gprint (GP_ERR, "USAGE: write (file) vector vector ...\n");
+      fclose (f);
+      return (FALSE);
+  }
+  ALLOCATE (vec, Vector *, Nvec);
+
+  /* select/check vectors from list */
+  for (i = 0; i < Nvec; i++) {
+    if ((vec[i] = SelectVector (argv[i + 2], OLDVECTOR, FALSE)) == NULL) {
+      gprint (GP_ERR, "unknown vector %s\n", argv[i+2]);
+      gprint (GP_ERR, "USAGE: write (file) vector vector ...\n");
+      free (vec);
+      fclose (f);
+      return (FALSE);    
+    }
+  }
+  
+  /* select vector lengths */
+  Ne = vec[0][0].Nelements;
+  for (i = 0; i < Nvec; i++) {
+    if (vec[0][0].Nelements != Ne) {
+      gprint (GP_ERR, "error: vectors must all be the same size\n");
+      free (vec);
+      fclose (f);
+      return (FALSE);    
+    }
+  }
+
+  /* default output format */
+  if (format == (char *) NULL) {
+    for (i = 0; i < vec[0][0].Nelements; i++) {
+      for (j = 0; j < Nvec; j++) {
+	fprintf (f, "%.10g ", vec[j][0].elements[i]);
+      }
+      fprintf (f, "\n");
+    } 
+    fclose (f);
+    free (vec);
+    return (TRUE);
+  }
+
+  /* construct an array of format strings */
+  ALLOCATE (fmttype, char, Nvec);
+  ALLOCATE (fmtlist, char *, Nvec);
+  for (i = 0; i < Nvec; i++) {
+    ALLOCATE (fmtlist[i], char, 1024);
+    bzero (fmtlist[i], 1024);
+  }
+
+  p0 = format;
+  for (j = 0; j < Nvec; j++) {
+    /* find this format character */
+    p1 = strchr (p0, '%');
+    if (p1 == (char *) NULL) {
+      gprint (GP_ERR, "mismatch between format and values\n");
+      free (fmttype);
+      for (i = 0; i < Nvec; i++) free (fmtlist[i]);
+      free (fmtlist);
+      free (format);
+      fclose (f);
+      return (FALSE);
+    }
+    
+    /* identify type (%NNNNd %NNNNf) */
+    for (p2 = p1 + 1; (*p2 == '.') || (*p2 == '-') || (*p2 == '+') || (*p2 == ' ') || isdigit(*p2); p2++);
+    strncpy (fmtlist[j], p0, p2 - p0 + 1);
+    switch (*p2) {
+      case 'e':
+      case 'f':
+	fmttype[j] = 'f';
+	break;
+      case 'd':
+      case 'c':
+      case 'x':
+	fmttype[j] = 'd';
+	break;
+      default:
+	gprint (GP_ERR, "syntax error in format (only e,f,d,c,x allowed)\n");
+	return (FALSE);
+    }
+    p0 = p2 + 1;
+  }
+  strcat (fmtlist[Nvec-1], p0);
+  
+  for (i = 0; i < vec[0][0].Nelements; i++) {
+    for (j = 0; j < Nvec; j++) {
+      if (fmttype[j] == 'd') {
+	fprintf (f, fmtlist[j], (int)(vec[j][0].elements[i]));
+      } 
+      if (fmttype[j] == 'f') {
+	fprintf (f, fmtlist[j], (float)(vec[j][0].elements[i]));
+      } 
+    }
+    fprintf (f, "\n");
+  }
+  fclose (f);
+
+  free (fmttype);
+  for (i = 0; i < Nvec; i++) free (fmtlist[i]);
+  free (fmtlist);
+  free (format);
+  
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/zap.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/zap.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/zap.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "data.h"
+
+int zap (int argc, char **argv) {
+
+  int i, j, N;
+  int sx, sy, nx, ny;
+  float *V, value;
+  Buffer *buf;
+
+  value = 0;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    value  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: zap <buffer> sx sy nx ny [-v value]\n");
+    return (FALSE);
+  }
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+
+  sx = atof (argv[2]);
+  sy = atof (argv[3]);
+  nx = atof (argv[4]);
+  ny = atof (argv[5]);
+
+  if (sx < 0) goto error;
+  if (sy < 0) goto error;
+  if (sx + nx > buf[0].matrix.Naxis[0]) goto error;
+  if (sy + ny > buf[0].matrix.Naxis[1]) goto error;
+
+  for (j = sy; j < sy + ny; j++) {
+    V = (float *)(buf[0].matrix.buffer) + j*buf[0].matrix.Naxis[0] + sx; 
+    for (i = 0; i < nx; i++, V++) *V = value;
+  }
+  return (TRUE);
+
+ error:
+  gprint (GP_ERR, "region out of range\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/zplot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/zplot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/cmd.data/zplot.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "data.h"
+
+int zplot (int argc, char **argv) {
+  
+  int i, kapa, Npts;
+  float *in, *out;
+  double min, range;
+  Graphdata graphmode;
+  Vector *xvec, *yvec, *zvec, Zvec;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return (FALSE);
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: zplot <x> <y> <z> min max\n");
+    return (FALSE);
+  }
+
+  min = atof(argv[4]);
+  range = atof(argv[5]) - min;
+
+  /* find vectors */
+  if ((xvec = SelectVector (argv[1], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yvec = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zvec = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (xvec[0].Nelements != yvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[1], argv[2]);
+    return (FALSE);
+  }
+  if (xvec[0].Nelements != zvec[0].Nelements) {
+    gprint (GP_ERR, "vectors %s and %s not the same length\n", argv[1], argv[3]);
+    return (FALSE);
+  }
+  Zvec.Nelements = zvec[0].Nelements;
+  ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+ 
+  in = zvec[0].elements;
+  out = Zvec.elements;
+  for (i = 0; i < Zvec.Nelements; i++, in++, out++) {
+    *out = MIN (1.0, MAX (0.01, (*in - min) / range));
+  }
+
+  /* point size determined by Zvec */
+  graphmode.style = 2; /* plot points */
+  graphmode.size = -1; /* point size determined by Zvec */
+  graphmode.etype = 0; /* no errorbars */
+  Npts = xvec[0].Nelements;
+  PlotVectorTriplet (kapa, Npts, xvec[0].elements, yvec[0].elements, Zvec.elements, &graphmode);
+
+  free (Zvec.elements);
+
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Analysis.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Analysis.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Analysis.c	(revision 16632)
@@ -0,0 +1,112 @@
+# include "dimm.h"
+
+/* should this all be wrapped within an opihi implementation? */
+
+int subtractImage (Image *a, Image *b) {
+
+  if (a[0].Nx != b[0].Nx) return (FALSE);
+  if (a[0].Ny != b[0].Ny) return (FALSE);
+
+  Npix = a[0].Nx*a[0].Ny;
+  ap = (float *) a[0].buffer;
+  bp = (float *) b[0].buffer;
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    *ap -= *bp;
+  }
+  return (FALSE);
+}
+
+void statsImage (Image *image, Stats *stats) {
+
+  val = (float *)image[0].buffer;
+  max = min = val[0];
+  Npix = image[0].Nx*image[0].Ny;
+  for (i = 0; i < Npix; i++, val++) {
+    N1 += *val;
+    N2 += (*val)*(*val);
+    max = MAX (max, *val);
+    min = MIN (min, *val);
+  }
+  stats[0].mean  = N1 / Npix;
+  stats[0].sigma = sqrt (N2 / Npix - SQ(stats[0].mean));
+  stats[0].min = min;
+  stats[0].max = max;
+
+  stats[0].median = stats[0].mean;
+  range = MAX (0.5, 0xffff / (max - min));
+  if (range == 0) return;
+
+  ALLOCATE (hist, int, 0x10000);
+  bzero (hist, 0x10000*sizeof(int));
+
+  val = (float *)image[0].buffer;
+  for (i = 0; i < Npix; i++) {
+    bin = MIN (MAX (0, (*val - min) * range), 0xffff);
+    hist[bin] ++;
+  }
+
+  Nhist = 0;
+  for (i = 0; (i < 0xffff) && (Nhist < 0.5*Npix); i++) 
+    Nhist += hist[i];
+  stats[0].median = i / range + min;
+  free (hist);
+
+  return;
+}
+
+# if (0)
+void findStars (Image *image, Stars **stars, int *Nstars, double threshold) {
+
+  /* binarize @ threshold */
+
+  binimage = createImage (image[0].Nx, image[0].Ny);
+
+  Npix = image[0].Nx*image[0].Ny;
+  ap = image[0].buffer;
+  bp = binimage[0].buffer;
+  bzero (bp, Npix*sizeof (short));
+
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    if (*ap > threshold) * bp = 1;
+  }
+
+  clearpix ();
+
+  for (i = 0; i < Ny; i++) {
+    for (j = 0; j < Nx; j++) {
+      pix = j + i*Ny;
+      if (binimage.buffer[pix]) {
+	addpix (pix);
+	binimage.buffer[pix] = 0;
+	/* continue in row to end */
+	for (k = j + 1; k < Nx; k++) {
+	  pix = k + i*Nx;
+	  if (!binimage.buffer[pix]) { 
+	  }
+	}
+
+# endif
+
+/* find stars: 
+   - binarize @ threshold
+   - find all contiguous blobs
+   - find geom center of each blob
+*/
+
+
+
+/*
+
+.....................
+....x................
+...xxx...............
+....x...xxx..........
+.........xx..........
+.....................
+.....................
+.....................
+.....................
+.....................
+
+
+ */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Camera.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Camera.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Camera.c	(revision 16632)
@@ -0,0 +1,223 @@
+# include "dimm.h"
+
+static struct sbig_init info;
+
+int InitCamera (int port) {
+  
+  int i, state;
+
+  for (i = 0; i < 10; i++) {
+    state = sbig_init (port, SBIG_IMAGING_CCD, &info);
+    if (state == -6) state = 0;
+    if (state ==  0) {
+      DumpCameraInfo ();
+      return (TRUE);
+    }
+    gprint (GP_ERR, "retry...\n");
+  }
+  
+  gprint (GP_ERR, "failed to init sbig camera on %d\n", port);
+  gprint (GP_ERR, "%s\n", sbig_show_error (state));
+  return (FALSE);
+}
+
+void DumpCameraInfo () {
+
+      gprint (GP_ERR, "opened sbig camera:\n");
+      gprint (GP_ERR, "linux_version: %f\n",      info.linux_version);
+      gprint (GP_ERR, "nmbr_bad_columns: %d\n",   info.nmbr_bad_columns);
+      gprint (GP_ERR, "imaging_abg_type: %d\n",   info.imaging_abg_type);
+      gprint (GP_ERR, "serial_number: %s\n",      info.serial_number);
+      gprint (GP_ERR, "firmware_version: %d\n",   info.firmware_version);
+      gprint (GP_ERR, "camera_name: %s\n",        info.camera_name);
+      gprint (GP_ERR, "nmbr_readout_modes: %d\n", info.camera_info[0].nmbr_readout_modes);
+      gprint (GP_ERR, "mode: %d\n",               info.camera_info[0].readout_mode[0].mode);
+      gprint (GP_ERR, "width: %d\n",              info.camera_info[0].readout_mode[0].width);
+      gprint (GP_ERR, "height: %d\n",             info.camera_info[0].readout_mode[0].height);
+      gprint (GP_ERR, "gain: %d\n",               info.camera_info[0].readout_mode[0].gain);
+      gprint (GP_ERR, "pixel_width: %d\n",        info.camera_info[0].readout_mode[0].pixel_width);
+      gprint (GP_ERR, "pixel_height: %d\n",       info.camera_info[0].readout_mode[0].pixel_height);
+
+      gprint (GP_ERR, "ST5_AD_size: %d\n", info.ST5_AD_size);
+      gprint (GP_ERR, "ST5_filter_type: %d\n", info.ST5_filter_type);
+}      
+
+void CameraFullSize (int *x, int *y) {
+  *x = info.camera_info[0].readout_mode[0].width;
+  *y = info.camera_info[0].readout_mode[0].height;
+}
+
+int SetTemperature (double temp) {
+
+  int state;
+  struct sbig_cool cool;
+
+  if (temp < -50) return (FALSE);
+  if (temp > +20) return (FALSE);
+
+  cool.regulation = SBIG_TEMP_REGULATION_ON;
+  cool.temperature = (int) (10.0*temp + 0.5);
+  cool.direct_drive = 0;
+
+  state = sbig_set_cooling (&cool);
+  if (state < 0) {
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+double GetTemperature () {
+
+  int state;
+  double temp;
+  struct sbig_status status;
+
+  state = sbig_get_status (&status);
+  if (state < 0) {
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error (state));
+    return (-200.0);
+  }
+  temp = (status.ccd_temperature - 0.5) / 10.0;
+  return (temp);
+}
+
+int DumpCameraStatus () {
+
+  int state;
+  double temp;
+  struct sbig_status status;
+
+  state = sbig_get_status (&status);
+  if (state < 0) {
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+
+  gprint (GP_ERR, "imaging_ccd_status: %d\n", status.imaging_ccd_status);
+  gprint (GP_ERR, "tracking_ccd_status: %d\n", status.tracking_ccd_status);
+  gprint (GP_ERR, "fan_on: %d\n", status.fan_on);
+  gprint (GP_ERR, "shutter_state: %d\n", status.shutter_state);
+  gprint (GP_ERR, "led_state: %d\n", status.led_state);
+  gprint (GP_ERR, "shutter_edge: %d\n", status.shutter_edge);
+  gprint (GP_ERR, "plus_x_relay: %d\n", status.plus_x_relay);
+  gprint (GP_ERR, "minus_x_relay: %d\n", status.minus_x_relay);
+  gprint (GP_ERR, "plus_y_relay: %d\n", status.plus_y_relay);
+  gprint (GP_ERR, "minus_y_relay: %d\n", status.minus_y_relay);
+  gprint (GP_ERR, "pulse_active: %d\n", status.pulse_active);
+  gprint (GP_ERR, "temperature_regulation: %d\n", status.temperature_regulation);
+  gprint (GP_ERR, "temperature_setpoint: %d\n", status.temperature_setpoint);
+  gprint (GP_ERR, "cooling_power: %d\n", status.cooling_power);
+  gprint (GP_ERR, "air_temperature: %d\n", status.air_temperature);
+  gprint (GP_ERR, "ccd_temperature: %d\n", status.ccd_temperature);
+
+  return (TRUE);
+}
+
+/* block until exposure is complete */
+int Exposure (double exptime) {
+
+  int i, state;
+  struct sbig_expose expose;
+  struct sbig_status status;
+
+  expose.ccd = SBIG_IMAGING_CCD;
+  expose.exposure_time = (int)(100.0*exptime);
+  expose.abg_state = SBIG_ABG_OFF;
+  expose.shutter = SBIG_EXPOSE_SHUTTER_NORMAL;  /* shuttermode = ? */
+
+  /* drop this ? */
+  /* usleep ((int)(exptime*1000000)); */
+  state = sbig_expose (&expose);
+  if (state < 0) {
+    gprint (GP_ERR, "exposure error\n");
+    gprint (GP_ERR, "%s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  
+  for (i = 0; i < expose.exposure_time + 10; ++i) {
+    state = sbig_get_status (&status);
+    /* gprint (GP_ERR, "%d\n", state); */
+    /* gprint (GP_ERR, "%d  %d\n", status.imaging_ccd_status, status.shutter_state); */
+    /*    if (state == 0) return (TRUE); */
+    if (status.imaging_ccd_status == -SBIG_NO_EXPOSURE_IN_PROGRESS) return (TRUE);
+    if (status.imaging_ccd_status == -SBIG_EXPOSURE_IN_PROGRESS) {
+      usleep (10000);
+      continue;
+    }
+    gprint (GP_ERR, "exposure error\n");
+    gprint (GP_ERR, "%s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  gprint (GP_ERR, "exposure timeout\n");
+  return (FALSE);
+}
+
+int   readout_abort;
+float readout_percent;
+static int readout_callback (float percent) {
+  /* return 1 to continue, 0 to abort */
+  if (((int)(percent) % 10) == 0) { gprint (GP_ERR, "."); }
+  readout_percent = percent;
+  if (readout_abort) return 0;
+  return 1;
+}
+
+int ReadOut (int x, int y, int dx, int dy, int binning, unsigned short *buffer) {
+
+  int state, Nbytes;
+  static struct sbig_readout readout;
+
+  readout.x = x;
+  readout.y = y;
+  readout.width  = dx;
+  readout.height = dy;
+
+  Nbytes = readout.width*readout.height*sizeof(short);
+
+  /* for bin 2x2 or 3x3, need to adjust dx, dy above */
+  readout.ccd = SBIG_IMAGING_CCD;
+  readout.binning = SBIG_BIN_1X1;
+  readout.data = buffer;
+  readout.data_size_in_bytes = Nbytes;
+  readout.callback = readout_callback;
+    
+  gprint (GP_ERR, "%d, %d : %d x %d\n", readout.x, readout.y, readout.width, readout.height);
+  sync (); 
+  readout_abort = FALSE;
+  state = sbig_readout (&readout);
+  gprint (GP_ERR, "\n");
+  if (state < 0) {
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int OpenShutter () {
+
+  int state;
+  struct sbig_control control;
+
+  control.shutter = SBIG_OPEN_SHUTTER;
+  state = sbig_control (&control);
+  if (state < 0) {
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int CloseShutter () {
+
+  int state;
+  struct sbig_control control;
+
+  control.shutter = SBIG_CLOSE_SHUTTER;
+  state = sbig_control (&control);
+  if (state < 0) {
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error (state));
+    return (FALSE);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Image.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "dimm.h"
+
+/*** this uses an Image structure from DIMM which 
+     is different from the Image structure in DVO ***/
+
+static Image *images = (Image *) NULL;
+static int   Nimages = 0;
+
+Image *createImage (int Nx, int Ny) {
+
+  int N;
+
+  if (Nx*Ny <= 0) return ((Image *) NULL);
+
+  N = Nimages;
+  Nimages ++;
+  if (images == (Image *) NULL) {
+    ALLOCATE (images, Image, MAX (1, Nimages));
+  } else {
+    REALLOCATE (images, Image, MAX (1, Nimages));
+  }
+
+  images[N].Nx = Nx;
+  images[N].Ny = Ny;
+  images[N].Nbytes = Nx*Ny*sizeof (short);
+  ALLOCATE (images[N].buffer, char, images[N].Nbytes);
+
+  return (&images[N]);
+}
+
+int freeImage (Image *entry) {
+
+  int i, j, N;
+
+  N = -1;
+  for (i = 0; (i < Nimages) && (N == -1) ; i++) {
+    if (&images[i] == entry) N = i;
+  }
+  if (N == -1) return (FALSE);
+
+  free (images[N].buffer);
+
+  for (j = N; j < Nimages - 1; j++) {
+    images[j] = images[j+1];
+  }
+
+  Nimages --;
+  REALLOCATE (images, Image, MAX (1, Nimages));
+  return (TRUE);
+}
+
+int writeImage (char *filename, Image *image) {
+
+  Header header;
+  Matrix matrix;
+
+  gfits_init_header (&header);
+
+  header.Naxes = 2;
+  header.Naxis[0] = image[0].Nx;
+  header.Naxis[1] = image[0].Ny;
+  header.bitpix = 16;
+
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  free (matrix.buffer);
+
+  matrix.buffer = image[0].buffer;
+  
+  /* write meta-data to header */
+  gfits_print (&header, "RA", "%lf", 1, image[0].ra);
+  gfits_print (&header, "DEC", "%lf", 1, image[0].dec);
+  gfits_print (&header, "EQUINOX", "%lf", 1, 2000.0);
+
+  gfits_print (&header, "AIRMASS", "%lf", 1, image[0].airmass);
+  gfits_print (&header, "CCDTEMP", "%lf", 1, image[0].ccdtemp);
+  gfits_print (&header, "AIRTEMP", "%lf", 1, image[0].airtemp);
+  gfits_print (&header, "EXPTIME", "%lf", 1, image[0].exptime);
+
+  gfits_write_header (filename, &header);
+  gfits_write_matrix (filename, &matrix);
+  
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Makefile	(revision 16632)
@@ -0,0 +1,70 @@
+default: dimm
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SRC     =       $(HOME)/dimm
+DATA    =       $(DESTDATA)/dimm
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+LIBS1   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata -lsbig
+LIBS2   =       -ldvo -lkapa -lFITS -lohana
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(LIBS1) $(LIBS2) $(BASE_LDFLAGS)
+
+# dimm user commands and support functions #####################
+funcs = \
+$(SRC)/Camera.$(ARCH).o		\
+$(SRC)/Serial.$(ARCH).o		\
+$(SRC)/Telescope.$(ARCH).o             
+
+cmds = \
+$(SRC)/init.$(ARCH).o		  	\
+$(SRC)/dimm.$(ARCH).o		  	\
+$(SRC)/altaz.$(ARCH).o		  	\
+$(SRC)/camera.$(ARCH).o	  	\
+$(SRC)/findstars.$(ARCH).o	  	\
+$(SRC)/telescope.$(ARCH).o   \
+$(SRC)/version.$(ARCH).o
+
+libs = \
+$(DESTLIB)/libshell.a \
+$(DESTLIB)/libdata.a \
+$(DESTLIB)/libbasiccmd.a \
+$(DESTLIB)/libastrocmd.a \
+$(DESTLIB)/libdatacmd.a \
+$(DESTLIB)/libsbig.a
+
+dimm: sbig $(BIN)/dimm.$(ARCH)
+$(SRC)/dimm.$(ARCH).o : $(libs)
+$(BIN)/dimm.$(ARCH)   : $(funcs) $(cmds)
+
+install: $(DESTBIN)/dimm help modules
+
+help: cmd.basic.help cmd.data.help cmd.astro.help dimm.help
+
+modules: dimm.modules
+
+# SBIG install functions
+sbig: $(DESTINC)/sbig.h $(DESTLIB)/libsbig.a
+	@echo sbig code installed
+
+$(DESTINC)/sbig.h:	$(SRC)/sbig/sbig.h
+	cp $(SRC)/sbig/sbig.h $(DESTINC)/sbig.h
+
+$(DESTLIB)/libsbig.a:	$(SRC)/sbig/sbig.a
+	cp $(SRC)/sbig/sbig.a $(DESTLIB)/libsbig.a
+
+$(SRC)/sbig/sbig.a: $(SRC)/sbig/sbig.a.src
+	cp $(SRC)/sbig/sbig.a.src $(SRC)/sbig/sbig.a
+
+.PHONY: dimm
+
+# are these used or replaced?
+# $(SRC)/analysis.$(ARCH).o	  	\
+# $(SRC)/Analysis.$(ARCH).o            \
+# $(SRC)/Image.$(ARCH).o		\
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Serial.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Serial.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Serial.c	(revision 16632)
@@ -0,0 +1,388 @@
+# include "dimm.h"
+# include <termios.h>
+
+# define CR   0x0D
+# define LF   0x0A
+# define BEEP 0x07
+# define OPENERR    -1   /* Port could not be opened */
+# define PORTERR    -2   /* Opened port is not a serial (tty) port */
+# define BADCMDERR  -3   /* Command sent to camera is not understood */
+# define TIMEOUTERR -4   /* No response */
+ 
+# define SER_VERBOSE 0
+# define SER_DEBUG   0
+
+# ifndef SER_VERBOSE
+# define SER_VERBOSE 1           /* Be verbose? */
+# endif
+# ifndef SER_DEBUG 
+# define SER_DEBUG 1
+# endif
+
+/* Defines for Serial Port  */
+typedef struct {
+  int f;
+  int rate;
+  int parity;
+  int bits;
+  int stpbit;
+  char port[64];
+} Serial;
+
+static Serial serial = {0, 0, 0, 0, 0};
+static int SER_ECHO = 0;
+
+int SerialOpen (char *);
+
+int SerialVerbose (int mode) {
+
+  SER_ECHO = mode;
+  return (TRUE);
+
+}
+
+int SerialInit (char *port) {
+  
+  strcpy (serial.port, port);
+  serial.rate = 2400;
+  serial.rate = 9600;
+  serial.parity = 0;
+  serial.bits = 8;
+  serial.stpbit = 1;
+  
+  serial.f = SerialOpen (serial.port);
+  if (serial.f <= 0) {
+    gprint (GP_ERR, "Error opening serial port %s - error %d.\n", serial.port, serial.f);
+    return (FALSE);
+  }
+  if (SerialBaudRate (serial.f, serial.rate))   return (FALSE);
+  if (SerialParity   (serial.f, serial.parity)) return (FALSE);
+  if (SerialDataBits (serial.f, serial.bits))   return (FALSE);
+  if (SerialStopBit  (serial.f, serial.stpbit)) return (FALSE);
+  return (TRUE);
+}
+
+/********************************** Open *********************************/
+int SerialOpen (char *port) {
+  
+  int err = 0;
+  struct termios term;
+  char prefix[100];
+  int fdesc = -1;
+  int locked;
+  struct flock lock;
+   
+  /* open serial line */
+   if (SER_VERBOSE) printf ("Opening the serial port %s for read/write.\n", port);
+   fdesc = open (port, O_RDWR);
+   if (fdesc == -1) {
+     if (SER_VERBOSE) gprint (GP_ERR, "Cannot open %s for read/write.\n", port);
+     return OPENERR;
+   }
+   /* lock serial line */
+   lock.l_type = F_WRLCK;
+   lock.l_len = 0;
+   lock.l_start = 0;
+   lock.l_whence = 0;
+   locked = fcntl (fdesc, F_SETLK, &lock);
+   if (locked == -1) {
+     gprint (GP_ERR, "can't lock serial line\n");
+     close (fdesc);
+     return OPENERR;
+   }
+
+   /* Get the serial port's attributes... */
+   if (tcgetattr (fdesc, &term) == -1) {
+      if (SER_VERBOSE) gprint (GP_ERR, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   /* cfmakeraw (&term); */
+   term.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+   term.c_oflag &= ~OPOST;
+   term.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+   term.c_cflag &= ~(CSIZE|PARENB);
+   term.c_cflag |= CS8;
+   term.c_cc[VMIN] = 0;     /* MIN setting...if 0, wait only for timeout */
+   term.c_cc[VTIME] = 2;    /* TIME setting...wait at most 1 sec for response 
+		              (ignored if c_cc[VMIN]>0) */
+   tcsetattr (fdesc, TCSAFLUSH, &term);
+
+# if (0)   
+   term.c_lflag &= ~ICANON; /* Turn OFF canonical input 
+ 	                      (so it does it character by character) */
+   term.c_cc[VMIN] = 0;     /* MIN setting...if 0, wait only for timeout */
+   term.c_cc[VTIME] = 10;    /* TIME setting...wait at most 1 sec for response 
+		              (ignored if c_cc[VMIN]>0) */
+   term.c_lflag &= ~ECHO;   /* Turn OFF echoing... */
+   term.c_iflag &= ~ICRNL;   /* Don't map CR to NL on input */
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr (fdesc, TCSAFLUSH, &term);
+# endif
+
+   return fdesc;
+}
+
+/******************************* Baud Rate *******************************/
+int SerialBaudRate (int fdesc, int rate) {
+   int err = 0;
+   struct termios term;
+
+  /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's baud rate.\n");
+   if (tcgetattr (fdesc, &term) == -1) {
+      if (SER_VERBOSE) gprint (GP_ERR, "Port is not a tty\n");
+      return PORTERR;
+   }
+ 
+   /* Set the input and output baud rates to 'rate'... */
+   switch (rate) { 
+   case 1200:         /* Set speed to 1200 */ 
+      if (cfgetospeed(&term) != B1200) cfsetospeed(&term, B1200);
+      if (cfgetispeed(&term) != B1200) cfsetispeed(&term, B1200);
+      break;
+   case 2400:         /* Set speed to 2400 */ 
+      if (cfgetospeed(&term) != B2400) cfsetospeed(&term, B2400);
+      if (cfgetispeed(&term) != B2400) cfsetispeed(&term, B2400);
+      break;
+   case 9600:         /* Set speed to 9600 */
+      if (cfgetospeed(&term) != B9600) cfsetospeed(&term, B9600);
+      if (cfgetispeed(&term) != B9600) cfsetispeed(&term, B9600);
+      break;
+   case 19200:        /* Set speed to 19200 */ 
+      if (cfgetospeed(&term) != B19200) cfsetospeed(&term, B19200);
+      if (cfgetispeed(&term) != B19200) cfsetispeed(&term, B19200);
+      break;
+   default:
+      printf ("ERROR:  Unknown Baud Rate\n"); 
+      break;
+   }	
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/****************************** Parity ********************************/
+int SerialParity (int fdesc, int parity) { 
+   int err=0;
+   struct termios term;
+   char *prefix = "/dev/term/";
+
+   /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's parity.\n");
+   if (tcgetattr(fdesc, &term) == -1) {
+      if (SER_VERBOSE) gprint (GP_ERR, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   if (parity == 0)              /* Turn off parity generation... */
+      term.c_cflag &= ~PARENB;     
+   else if (parity == 1) {            
+      term.c_cflag |= PARENB;     /* Turn on parity generation... */
+      term.c_cflag |= PARODD;     /* Sets parity to odd */ 
+   }	 
+   else if (parity == 2)         /* Turn on parity generation... */
+      term.c_cflag |= PARENB;     /* Defaults parity to even */ 
+   else 
+      printf ("ERROR:  Unknown parity specification\n");
+ 
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/****************************Data Bit Size ***************************/
+int SerialDataBits(int fdesc, int bits) { 
+   int err=0;
+   struct termios term;
+
+   /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's data bit size.\n");
+   if (tcgetattr(fdesc, &term) == -1) {
+      if (SER_VERBOSE) gprint (GP_ERR, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   switch (bits) {
+   case 5:  			/* Sets data bits to 5 */
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS5;
+      break; 
+   case 6:   			/* Sets data bits to 6 */ 
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS6;
+      break; 
+   case 7:     		/* Sets data bits to 7 */ 
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS7;
+      break; 
+   case 8:  			/* Sets data bits to 8 */
+      term.c_cflag &= ~CSIZE; 
+      term.c_cflag |= CS8;
+      break; 
+   default:
+      printf ("ERROR:  Illegal data bit size\n");
+      break; 
+   }
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/****************************** Stop Bit ****************************/
+int SerialStopBit(int fdesc, int stpbit) { 
+   int err=0;
+   struct termios term;
+
+   /* Get the serial port's attributes... */
+   if (SER_VERBOSE) printf("Setting the serial port's stop bit.\n");
+   if (tcgetattr(fdesc, &term) == -1) {
+      if (SER_VERBOSE) gprint (GP_ERR, "Port is not a tty\n");
+      return PORTERR;
+   }
+
+   if (stpbit == 1) {     		/* Sets stop bit to 1 */  
+      if (term.c_cflag & CSTOPB) term.c_cflag |= CSTOPB;
+   } else { 				/* Else stop bit to 2 */ 
+      term.c_cflag & CSTOPB;
+   }
+
+   /* Set port (terminal) to reflect the change...(flush first) */
+   tcsetattr(fdesc, TCSAFLUSH, &term);
+   return (FALSE);
+}
+
+/**************************** Stop ***********************************/
+void SerialStop (int fdesc) {
+   if (SER_VERBOSE) printf("Closing the serial port.\n");
+   close(fdesc); /* Close up shop... */
+}
+
+# define D_NREAD 1024
+
+/* send a string to the serial port, wait for an answer */
+/* answer is returned on the pointer provided */
+
+/**************************** Command ***********************************/
+int SerialCommand (char *in, char **out, int wait) {
+  
+  int i, j;
+  char *line;
+  int done, Nread, Nin, NREAD;
+  
+  if (SER_ECHO) gprint (GP_ERR, "command: %s\n", in); 
+
+  if (serial.f <= 0) {
+    gprint (GP_ERR, "serial line closed\n"); 
+    if (out != (char **) NULL) {
+      *out = strcreate ("SERIAL OFF");
+      /* return (char *) NULL instead? */
+    }
+    return (FALSE);
+  }
+
+  /* flush out the line */
+  tcflush (serial.f, TCIOFLUSH);
+
+# if (0)
+  for (i = 0; i < strlen(in); i++) {
+    gprint (GP_ERR, "%d %x\n", i, in[i]);
+  }
+# endif
+
+  /* send command to serial line */
+  Nin = write (serial.f, in, strlen(in));
+  if (Nin != strlen(in)) {
+    gprint (GP_ERR, "Serial Command not sent\n");
+    return (FALSE);
+   }
+  usleep (20000);
+  /* LX200 GPS requires some lead time (10msec) to check ready state */
+  
+  /* create space to store answer */
+  NREAD = D_NREAD;
+  ALLOCATE (line, char, NREAD);
+  bzero (line, NREAD);
+  Nread = Nin = 0;
+
+  /* read data back from serial line until no response (Nin == 0) 
+     or timeout (Nin == -1) && (i == wait) */
+
+  done = FALSE;
+  for (i = 0; !done && (i < wait); i++) {
+    Nin = read (serial.f, &line[Nread], 256);
+# if (SER_DEBUG)
+    gprint (GP_ERR, "%d ", Nin);
+# endif
+    if (Nin < 0) { /* error, check value */
+      gprint (GP_ERR, "error?");
+      continue;
+    }
+    if (Nin > 0) {
+      Nread += Nin;
+      line[Nread] = 0;
+      i = 0;
+    }
+    if (Nread > D_NREAD - 257) {
+      NREAD += D_NREAD;
+      REALLOCATE (line, char, NREAD);
+    }
+    if ((i > 0) && (Nin == 0)) done = TRUE;
+    usleep (2000);
+  }
+
+  if (SER_ECHO) gprint (GP_ERR, "answer: %s\n", line);
+
+  if (out == (char **) NULL) {
+    free (line);
+  } else {
+    *out = line;
+  }
+  return (TRUE);
+}
+
+
+/* raw:
+   cfmakeraw sets the terminal attributes as follows:
+   termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);
+   termios_p->c_oflag &= ~OPOST;
+   termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);
+   termios_p->c_cflag &= ~(CSIZE|PARENB);
+   termios_p->c_cflag |= CS8;
+
+   there conditions are turned off:
+   c_iflag:
+       IGNBRK ignore BREAK condition on input
+       BRKINT If IGNBRK is not set, generate SIGINT on BREAK condition, else read BREAK as
+              character \0.
+       PARMRK if  IGNPAR  is  not  set,  prefix a character with a parity error or framing
+              error with \377 \0.  If neither IGNPAR nor PARMRK is set, read  a  character
+              with a parity error or framing error as \0.
+       (IGNPAR ignore framing errors and parity errors.)
+
+       ISTRIP strip off eighth bit
+       INLCR  translate NL to CR on input
+       IGNCR  ignore carriage return on input
+       ICRNL  translate carriage return to newline on input (unless IGNCR is set)
+       IXON   enable XON/XOFF flow control on output
+
+   c_oflag:
+       OPOST  enable implementation-defined output processing
+
+   c_lflag:
+       ECHO   echo input characters.
+       ECHONL if ICANON is also set, echo the NL character even if ECHO is not set.
+       ICANON enable canonical mode.  This enables the special characters EOF, EOL,  EOL2,
+              ERASE, KILL, REPRINT, STATUS, and WERASE, and buffers by lines.
+       ISIG   when any of the characters INTR, QUIT, SUSP, or DSUSP are received, generate
+              the corresponding signal.
+       IEXTEN enable implementation-defined input processing.
+
+   c_cflag:
+       CSIZE  character size mask.  Values are CS5, CS6, CS7, or CS8. (CS8 set).
+       PARENB enable parity generation on output and parity checking for input.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Telescope.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Telescope.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/Telescope.c	(revision 16632)
@@ -0,0 +1,361 @@
+# include "dimm.h"
+
+# define SER_TIMEOUT 10
+# define SLEW_TIMEOUT 30
+# define dCOS(A)   ((double) cos ((double)RAD_DEG*A))
+# define dSIN(A)   ((double) sin ((double)RAD_DEG*A))
+
+double distSky (double r1, double r2, double d1, double d2) {
+
+  double x1, y1, z1;
+  double x2, y2, z2;
+  double cosT, dist;
+
+  x1 = dCOS (r1) * dCOS (d1);
+  y1 = dSIN (r1) * dCOS (d1);
+  z1 = dSIN (d1);
+
+  x2 = dCOS (r2) * dCOS (d2);
+  y2 = dSIN (r2) * dCOS (d2);
+  z2 = dSIN (d2);
+
+  cosT = x1*x2 + y1*y2 + z1*z2;
+  dist = DEG_RAD * acos (cosT);
+
+  return (dist);
+}
+
+int getRD (double *r, double *d) { 
+
+  int status;
+  char *rastr, *decstr;
+
+  status = SerialCommand (":GR#", &rastr, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  status = SerialCommand (":GD#", &decstr, SER_TIMEOUT); 
+  if (!status) return (FALSE);
+
+  status = ohana_str_to_radec (r, d, rastr, decstr);
+  if (!status) return (FALSE);
+
+  free (rastr);
+  free (decstr);
+
+  return (TRUE);
+}
+
+int gotoRD (double r, double d) {
+
+  double R, D, dist;
+  int Ntry, status;
+  char *str, *answer, cmd[64];
+
+  /* error on ra, dec means coords out of range */
+
+  /* set telescope coords, send */
+  str = meade_ra_to_str (r);
+  sprintf (cmd, ":Sr%s#", str);   free (str);
+  status = SerialCommand (cmd, &answer, SER_TIMEOUT);
+  if (!status) return (FALSE); 
+  if (answer == (char *) NULL) return (FALSE); 
+  if (strcmp (answer, "1")) return (FALSE); 
+  free (answer);
+
+  str = meade_dec_to_str (d);
+  sprintf (cmd, ":Sd%s#", str);  free (str);
+  status = SerialCommand (cmd, &answer, SER_TIMEOUT);   
+  if (!status) return (FALSE); 
+  if (answer == (char *) NULL) return (FALSE); 
+  if (strcmp (answer, "1")) return (FALSE); 
+  free (answer);
+
+  Ntry = 0;
+  status = SerialCommand (":MS#", &answer, SER_TIMEOUT);   
+  if (!status) return (FALSE); 
+  if (answer == (char *) NULL) return (FALSE); 
+  if (strcmp (answer, "0")) {
+    gprint (GP_ERR, "error: %s\n", answer);
+    return (FALSE); 
+  }
+  free (answer);
+
+  /* watch for response? */
+  status = FALSE;
+  while (!status) {
+    getRD (&R, &D);
+    dist = distSky (R, r, D, d);
+    if (dist < 0.1) return (TRUE);
+    usleep (100000);
+    Ntry ++;
+    if (Ntry > SLEW_TIMEOUT) return (FALSE);
+  }
+  return (status);
+}
+
+/* actual offsets are x,y, convert to arcmin */
+int offset (char *direction, double distance) {
+
+  /* Four rate choices: 
+     slew   (RS) -  8 degree / sec : rate 1
+     find   (RM) - 30 arcmin / sec : rate 2
+     center (RC) -  4 arcmin / sec : rate 3
+     guide  (RG) - 15 arcsec / sec : rate 4
+
+     communication requires ~1.0 sec:
+     offset should use rate which gives shortest time > 2.0 sec 
+  */
+
+# define NRATE 4
+  static double delay[NRATE]  = {0.1, 0.1, 0.1, 0.1};
+  static double rate[NRATE]   = {480.0, 30.0, 4.0, 0.25};
+  static char rcmd[NRATE][16] = {"RS", "RM", "RC", "RG"};
+
+  int i, status, rsel;
+  char dir, cmd[32];
+  double tsel, dt;
+
+  dir = 0;
+  if (!strcasecmp (direction, "y")) dir = (distance > 0) ? 'n' : 's';
+  if (!strcasecmp (direction, "x")) dir = (distance > 0) ? 'w' : 'e';
+  if (!dir) return (FALSE);
+
+  /* distance is in arcmin */
+  distance = fabs (distance);
+
+  /* logic is bad -- does not catch too small distances */  
+  rsel = -1;
+  tsel = SLEW_TIMEOUT;
+  for (i = 0; i < NRATE; i++) {
+    dt = distance / rate[i] - delay[i];
+    if ((dt > 0) && (dt < tsel)) {
+      rsel = i;
+      tsel = dt;
+    }
+  }
+  if (tsel < 0) {
+    gprint (GP_ERR, "offset %f arcmin below minimum\n", distance);
+    return (FALSE);
+  }
+  if (tsel > SLEW_TIMEOUT) {
+    gprint (GP_ERR, "offset %f arcmin above maximum\n", distance);
+    return (FALSE);
+  }
+  gprint (GP_ERR, "offsetting %c for %f seconds\n", dir, tsel);
+  
+  sprintf (cmd, ":%s#", rcmd[rsel]);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  sprintf (cmd, ":M%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  usleep ((int)(tsel*1000000));
+
+  sprintf (cmd, ":Q%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  return (TRUE);
+}  
+
+/* actual offsets are x,y, convert to arcmin */
+int toffset (char *direction, char *rate, double duration) {
+
+# define NRATE 6
+  /* static char rcmd[NRATE][16] = {"RS", "RM", "RC", "RG"};*/
+  static char rcmd[NRATE][64] = {"RS", "RM", "RC", "RG", "RA0.0085", "RE0.0085"};
+
+  int i, status, rsel;
+  char dir, cmd[32];
+  double tsel, dt;
+
+  dir = 0;
+  if (!strcasecmp (direction, "x")) dir = (duration > 0) ? 'w' : 'e';
+  if (!strcasecmp (direction, "y")) dir = (duration > 0) ? 'n' : 's';
+  if (!dir) return (FALSE);
+  duration = fabs (duration);
+  
+  status = FALSE;
+  for (i = 0; i < NRATE; i++) if (!strcmp (rcmd[i], rate)) status = TRUE;
+  if (!status) {
+    gprint (GP_ERR, "bad rate: %s\n", rate);
+    return (FALSE);
+  }
+
+  sprintf (cmd, ":%s#", rate);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  sprintf (cmd, ":M%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  usleep ((int)(duration*1000000));
+
+  sprintf (cmd, ":Q%c#", dir);
+  status = SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  if (!status) return (FALSE);
+
+  return (TRUE);
+}  
+
+int getXY (double *x, double *y) {
+
+  char *answer;
+
+  SerialCommand (":GA#", &answer, SER_TIMEOUT);
+  ohana_dms_to_ddd (x, answer);
+  free (answer);
+
+  SerialCommand (":GZ#", &answer, SER_TIMEOUT);
+  ohana_dms_to_ddd (y, answer);
+  free (answer);
+
+  return (TRUE);
+}
+
+/* need error checking on these */
+int setRD (double r, double d) {
+
+  char *str, *answer, cmd[64];
+
+  /* set telescope coords, send */
+  str = meade_ra_to_str (r);
+  sprintf (cmd, ":Sr%s#", str);
+  SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  str = meade_dec_to_str (d);
+  sprintf (cmd, ":Sd%s#", str);
+  SerialCommand (cmd, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  SerialCommand (":CM#", &answer, SER_TIMEOUT);
+  gprint (GP_ERR, "result: %s\n", answer);
+  free (answer);
+  return (TRUE);
+}
+
+int setSite (char *sitename, double lon, double lat) {
+
+  struct tm *gmt;
+  struct timeval now;
+  char *str, line[32];
+
+  gprint (GP_ERR, "careful, this causes problems\n");
+  return (FALSE);
+
+  SerialCommand (":W1#", (char **) NULL, SER_TIMEOUT);
+
+  /* Set site name 1 */
+  sprintf (line, ":SM %s#", sitename); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /* Set site long */
+  str = meade_deg_to_str (lon);
+  str[6] = 0;
+  sprintf (line, ":Sg%s#", str); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  /* Set site lat */
+  str = meade_dec_to_str (lat);
+  sprintf (line, ":St%s#", str); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+  free (str);
+
+  /* set UTC offset to 0.0: offset + local = gmt */
+  sprintf (line, ":SG+00#");
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /* Set local */
+  gettimeofday (&now, (struct timezone *) NULL);
+  gmt = gmtime (&now.tv_sec);
+  sprintf (line, ":SL%02d:%02d:%02d#", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  return (TRUE);
+}
+
+int setTime (char *lst) {
+
+  struct tm *gmt;
+  struct timeval now;
+  char line[32], *answer;
+
+  /* set UTC offset to 0.0: offset + local = gmt */
+  sprintf (line, ":SG+10#");
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /* Set local */
+  gettimeofday (&now, (struct timezone *) NULL);
+  gmt = localtime (&now.tv_sec);
+  sprintf (line, ":SL%02d:%02d:%02d#", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+
+  /*
+  sprintf (line, ":SS%s#", lst);
+  SerialCommand (line, (char **) NULL, SER_TIMEOUT);
+  */
+
+  return (TRUE);
+}
+
+int getSite (double *lon, double *lat, double *lst) {
+
+  struct tm *gmt;
+  struct timeval now;
+  char *str, *answer, line[32];
+
+  /* : get latitude */
+  SerialCommand (":Gt#", &answer, SER_TIMEOUT);
+  ohana_dms_to_ddd (lat, answer);
+  free (answer);
+
+  /* : get longitude */
+  SerialCommand (":Gg#", &answer, SER_TIMEOUT);
+  ohana_dms_to_ddd (lon, answer);
+  free (answer);
+
+  /* : get LST */
+  SerialCommand (":GS#", &answer, SER_TIMEOUT);
+  ohana_dms_to_ddd (lst, answer);
+  free (answer);
+
+  return (TRUE);
+}
+
+int ParkScope() {
+
+  char *str, *answer, line[32];
+
+  SerialCommand (":hP#", &answer, SER_TIMEOUT);
+  free (answer);
+
+  return (TRUE);
+
+}
+
+int SleepScope() {
+
+  char *str, *answer, line[32];
+  
+  SerialCommand (":hN#", &answer, SER_TIMEOUT);
+  free (answer);
+  
+  return (TRUE);
+
+}
+
+int WakeScope() {
+
+  char *str, *answer, line[32];
+
+  SerialCommand (":hW#", &answer, SER_TIMEOUT);
+  free (answer);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/altaz.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/altaz.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/altaz.c	(revision 16632)
@@ -0,0 +1,88 @@
+# include "dimm.h"
+
+# define dCOS(A)   ((double) cos ((double)RAD_DEG*A))
+# define dSIN(A)   ((double) sin ((double)RAD_DEG*A))
+
+double atan2 (double y, double x);
+
+int altaz (int argc, char **argv) {
+  
+  double alt, az, lat, rot;
+  double ha, dec;
+  double sind, sinh, cosh;
+  char *latstr;
+
+  if (argc != 6) goto usage;
+
+  if (!strcmp (argv[1], "-h")) goto radec;
+  if (!strcmp (argv[1], "-c")) goto altaz;
+
+ radec:
+  /* ha/dec -> alt/az */
+  ha  = atof (argv[2]);
+  dec = atof (argv[3]);
+
+  latstr = get_variable ("LATITUDE");
+  if (latstr == (char *) NULL) {
+    gprint (GP_ERR, "please define $LATITUDE\n");
+    return (FALSE);
+  }
+  lat = atof (latstr);
+  free (latstr);
+ 
+  sind = dSIN (dec) * dSIN (lat) + dCOS (dec) * dCOS (ha) * dCOS (lat);
+  alt  = DEG_RAD * asin (sind);
+
+  sinh = - dCOS (dec) * dSIN (ha);
+  cosh =   dSIN (dec) * dCOS (lat) - dCOS (dec) * dCOS (ha) * dSIN (lat);
+
+  az = DEG_RAD * atan2 (sinh, cosh);
+  set_variable (argv[4], alt);
+  set_variable (argv[5], az);
+
+  sinh = -dCOS(az) * dSIN(alt) * dSIN(ha) * dSIN(lat) + dSIN(az) * dSIN(alt) * dCOS(ha) - dSIN(ha) * dCOS(alt) * dCOS(lat);
+  cosh = -dSIN(az) * dSIN(ha) * dSIN(lat) - dCOS(az) * dCOS(ha);
+  rot = -DEG_RAD * atan2 (sinh, cosh);
+  set_variable ("ROT", rot);
+
+  return (TRUE);
+  
+ altaz:
+  /* alt/az -> ha/dec */
+  alt = atof (argv[4]);
+  az  = atof (argv[5]);
+
+  latstr = get_variable ("LATITUDE");
+  if (latstr == (char *) NULL) {
+    gprint (GP_ERR, "please define $LATITUDE\n");
+    return (FALSE);
+  }
+  lat = atof (latstr);
+  free (latstr);
+
+  sind = dSIN (alt) * dSIN (lat) + dCOS (alt) * dCOS (az) * dCOS (lat);
+  dec  = DEG_RAD * asin (sind);
+
+  sinh = -dCOS (alt) * dSIN (az);
+  cosh =  dSIN (alt) * dCOS (lat) - dCOS (alt) * dCOS (az) * dSIN (lat);
+
+  ha = DEG_RAD * atan2 (sinh, cosh);
+  set_variable (argv[2], ha);
+  set_variable (argv[3], dec);
+
+  sinh = -dCOS(az) * dSIN(alt) * dSIN(ha) * dSIN(lat) + dSIN(az) * dSIN(alt) * dCOS(ha) - dSIN(ha) * dCOS(alt) * dCOS(lat);
+  cosh = -dSIN(az) * dSIN(ha) * dSIN(lat) - dCOS(az) * dCOS(ha);
+  rot = -DEG_RAD * atan2 (sinh, cosh);
+  set_variable ("ROT", rot);
+
+  return (TRUE);
+  
+ usage:
+  gprint (GP_ERR, "USAGE: altaz -h (ha) (dec) (alt) (az)\n");
+  gprint (GP_ERR, "USAGE: altaz -c (ha) (dec) (alt) (az)\n");
+  gprint (GP_ERR, "       -h alt/az to ha/dec, -c ha/dec to alt/az\n");
+  gprint (GP_ERR, "       returned values in variables provided\n");
+  return (FALSE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/analysis.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/analysis.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/analysis.c	(revision 16632)
@@ -0,0 +1,184 @@
+
+/* should this all be wrapped within an opihi implementation? */
+
+typedef struct {
+
+  /* image data area */
+  int Nx, Ny;
+  char *buffer;
+  int Nbytes;
+
+  /* image metadata */
+  double ccdtemp;
+  double airtemp;
+  double ra, dec, airmass;
+  double exptime;
+  int binning;
+} Image;
+
+subtractImage (Image *a, Image *b) {
+
+  if (a[0].Nx != b[0].Nx) return (FALSE);
+  if (a[0].Ny != b[0].Ny) return (FALSE);
+
+  Npix = a[0].Nx*a[0].Ny;
+  ap = (float *) a[0].buffer;
+  bp = (float *) b[0].buffer;
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    *ap -= *bp;
+  }
+  return (FALSE);
+}
+
+statsImage (Image *image, Stats *stats) {
+
+  val = (float *)image[0].buffer;
+  max = min = val[0];
+  Npix = image[0].Nx*image[0].Ny;
+  for (i = 0; i < Npix; i++, val++) {
+    N1 += *val;
+    N2 += (*val)*(*val);
+    max = MAX (max, *val);
+    min = MIN (min, *val);
+  }
+  stats[0].mean  = N1 / Npix;
+  stats[0].sigma = sqrt (N2 / Npix - SQ(stats[0].mean));
+  stats[0].min = min;
+  stats[0].max = max;
+
+  stats[0].median = stats[0].mean;
+  range = MAX (0.5, 0xffff / (max - min));
+  if (range == 0) return ();
+
+  ALLOCATE (hist, int, 0x10000);
+  bzero (hist, 0x10000*sizeof(int));
+
+  val = (float *)image[0].buffer;
+  for (i = 0; i < Npix; i++) {
+    bin = MIN (MAX (0, (*val - min) * range), 0xffff);
+    hist[bin] ++;
+  }
+
+  Nhist = 0;
+  for (i = 0; (i < 0xffff) && (Nhist < 0.5*Npix); i++) 
+    Nhist += hist[i];
+  stats[0].median = i / range + min;
+  free (hist);
+
+  return ();
+}
+
+findStars (Image *image, Stars **stars, int *Nstars, double threshold) {
+
+  /* binarize @ threshold */
+
+  binimage = createImage (image[0].Nx, image[0].Ny);
+
+  Npix = image[0].Nx*image[0].Ny;
+  ap = image[0].buffer;
+  bp = binimage[0].buffer;
+  bzero (bp, Npix*sizeof (short));
+
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    if (*ap > threshold) * bp = 1;
+  }
+
+  clearpix ();
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      if (binimage.buffer[j*Nx + i]) {
+	status = fillrow (binimage.buffer, Nx, j*Nx, i, &xs, &xe);
+	for (J = j + 1; (J < Ny) && status; J++) {
+	  for (I = xs; !binimage.buffer[J*Nx + I] && (I < xe); I++);
+	  if (binimage.buffer[J*Nx + I]) {
+	    status = fillrow (binimage.buffer, Nx, J*Nx, I, &xs, &xe);
+	  } 
+	}  
+	/* we now have a stack of pixels, convert to a single star */
+	statpix (&x, &y, image[0].buffer, Nx);
+	addstar (x, y);
+	clearpix ();
+      }
+    }
+  }
+}
+
+/* find contiguous trigger pixels in row from starting point */
+
+int fillrow (float *buffer, int Nx, int offset, int sx, int *xs, int *xe) {
+
+  trigger = FALSE;
+  for (i = sx, pix = offset + i; buffer[pix] && (i < Nx); i++, pix++) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xe = i;
+  }
+  for (i = sx - 1, pix = offset + i; (i >= 0) && buffer[pix]; i--, pix--) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xs = i;
+  }
+  return (trigger);
+}
+
+static int Npix = 0;
+static int *Pix = (int *) NULL;
+
+addpix (int pix) {
+  Npix ++;
+  if (Pix == (int *) NULL) {
+    ALLOCATE (Pix, int, MAX (1, Npix));
+  } else {
+    REALLOCATE (Pix, int, MAX (1, Npix));
+  }    
+  Pix[Npix - 1] = pix;
+}
+
+clearpix () {
+  Npix = 0;
+  REALLOCATE (Pix, int, 1);
+}
+
+statpix (double *x, double *y, float *buffer, int Nx) {
+
+  int X, Y;
+  double Sx, Sy, So;
+
+  So = Sx = Sy = 0;
+  for (i = 0; i < Npix; i++) {
+    Y = pix / Nx;
+    X = pix % Nx;
+    So += buffer[pix];
+    Sx += X * buffer[pix];
+    Sy += Y * buffer[pix];
+  }
+  *x = Sx / So;
+  *y = Sy / So;
+}
+
+/* find stars: 
+   - binarize @ threshold
+   - find all contiguous blobs
+   - find geom center of each blob
+*/
+
+
+
+/*
+
+.....................
+....x................
+...xxx...............
+..........xxx..........
+.........xx..........
+.....................
+.....................
+.....................
+.....................
+.....................
+
+
+ */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/camera.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/camera.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/camera.c	(revision 16632)
@@ -0,0 +1,130 @@
+# include "dimm.h"
+# define EXIT_STATUS(S) { seteuid (UID); return (S); }
+
+static uid_t UID, EUID;
+
+SetEUID () {
+
+  /* save the UID (ID of calling process) and EUID (should be root) */
+  UID = getuid ();
+  EUID = geteuid ();
+  seteuid (UID);
+}
+
+int camera (int argc, char **argv) {
+  
+  /* USAGE: 
+     camera init port
+     camera expose exptime
+     camera readout x y dx dy
+     camera temp set value
+     camera temp get var
+  */
+
+  if (argc < 2) goto usage;
+
+  seteuid (EUID);
+  
+  if (!strcasecmp (argv[1], "init")) {
+    int port, status;
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: camera init (port)\n");
+      EXIT_STATUS (FALSE);
+    }
+    sscanf (argv[2], "%x", &port);
+    status = InitCamera (port);
+    EXIT_STATUS (status);
+  }
+
+  if (!strcasecmp (argv[1], "expose")) {
+
+    int status;
+    double exptime;
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: camera expose (exptime)\n");
+      EXIT_STATUS (FALSE);
+    }
+    exptime = atof (argv[2]);
+    status = Exposure (exptime);
+    EXIT_STATUS (status);
+  }
+
+  if (!strcasecmp (argv[1], "temp")) {
+
+    int status;
+    double temp;
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: camera temp (temperature)\n");
+      EXIT_STATUS (FALSE);
+    }
+    temp = atof (argv[2]);
+    status = SetTemperature (temp);
+    EXIT_STATUS (status);
+  }
+
+  if (!strcasecmp (argv[1], "status")) {
+
+    int status;
+    double temp;
+
+    if (argc != 2) {
+      gprint (GP_ERR, "USAGE: camera status\n");
+      EXIT_STATUS (FALSE);
+    }
+    DumpCameraStatus ();
+    EXIT_STATUS (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "readout")) {
+
+    int Nbuf, status;
+    double temp;
+    int x, y, dx, dy, NX, NY;
+    Buffer *buf;
+
+    if ((argc != 7) && (argc != 3)) {
+      gprint (GP_ERR, "USAGE: camera readout (buffer) x y dx dy\n");
+      EXIT_STATUS (FALSE);
+    }
+
+    if ((buf = SelectBuffer (argv[2], OLDBUFFER, TRUE)) == NULL) EXIT_STATUS (FALSE);
+
+    CameraFullSize (&NX, &NY);
+    x = y = 0;
+    dx = NX;
+    dy = NY;
+    if (argc == 7) {
+      x  = atof (argv[3]);
+      y  = atof (argv[4]);
+      dx = atof (argv[5]);
+      dy = atof (argv[6]);
+    } 
+
+    /* generate a buffer to store the image */
+    gfits_free_matrix (&buf[0].matrix);
+    gfits_free_header (&buf[0].header);
+    CreateBuffer (buf, dx, dy, -32, 0.0, 1.0);
+    strcpy (buf[0].file, "(empty)");
+
+    ReadOut (x, y, dx, dy, 1, buf[0].matrix.buffer);
+
+    gfits_convert_format (&buf[0].header, &buf[0].matrix, -32, 1.0, 0.0, gfits_get_unsign_mode());
+
+    EXIT_STATUS (TRUE);
+  }
+
+usage:
+  gprint (GP_ERR, "camera init port\n");
+  gprint (GP_ERR, "camera expose exptime\n");
+  gprint (GP_ERR, "camera readout x y dx dy\n");
+  gprint (GP_ERR, "camera temp set value\n");
+  gprint (GP_ERR, "camera temp get var\n");
+  seteuid (UID);
+  return (FALSE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/dimm.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/dimm.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/dimm.c.in	(revision 16632)
@@ -0,0 +1,68 @@
+# include "opihi.h"
+
+# define opihi_name "DIMM"
+# define opihi_prompt "dimm: "
+# define opihi_description "DIMM telescope controller\n"
+# define opihi_history ".dimm"
+# define opihi_rcfile ".dimmrc"
+
+/* program-dependent initialization */
+void program_init (int *argc, char **argv) {
+  
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitDIMM ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  { 
+    char *helpdir;
+    char *modules;
+    static char *datadir = "@DATADIR@";
+    ALLOCATE (helpdir, char, strlen(datadir) + strlen("/help") + 2);
+    sprintf (helpdir, "%s/help", datadir);
+    set_str_variable ("HELPDIR", helpdir);
+    free (helpdir);
+    ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+    sprintf (modules, "%s/modules", datadir);
+    set_str_variable ("MODULES:0", modules);
+    set_int_variable ("MODULES:n", 1);
+    free (modules);
+  }
+  return;
+}
+
+/* standard welcome message */
+void welcome () {
+  gprint (GP_ERR, "\n");
+  gprint (GP_ERR, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  QuitKapa ();
+  ConfigFree ();
+
+  FreeBasic ();
+  FreeData ();
+  FreeAstro ();
+  FreeDIMM ();
+
+  return;
+}
+
+/* call to opihi shell */
+int main (int argc, char **argv) {
+  int status;
+  status = opihi (argc, argv);
+  exit (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/findstars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/findstars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/findstars.c	(revision 16632)
@@ -0,0 +1,152 @@
+# include "dimm.h"
+
+int fillrow (char *buffer, int Nx, int offset, int sx, int *xs, int *xe);
+int addpix (int pix);
+int clearpix ();
+int freepix ();
+int statpix (float *x, float *y, float *buffer, int Nx);
+int addstar (double x, double y);
+
+Vector *vecx, *vecy, *vecf, *vecn;
+
+int findstars (int argc, char **argv) {
+
+  int i, j, I, J, Npix, Nbuf, status;
+  int xs, xe, Nx, Ny;
+  char *binary, *bp;
+  float *ap, threshold, x, y;
+  Buffer *buf;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: findstars (buffer) (threshold)\n");
+    return (FALSE);
+  }
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  threshold = atof (argv[2]);
+
+  if ((vecx = SelectVector ("star_x", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector ("star_y", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecf = SelectVector ("star_f", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecn = SelectVector ("star_n", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  vecx[0].Nelements = vecy[0].Nelements = 0;
+  vecf[0].Nelements = vecn[0].Nelements = 0;
+
+  REALLOCATE (vecx[0].elements, float, 1);
+  REALLOCATE (vecy[0].elements, float, 1);
+  REALLOCATE (vecf[0].elements, float, 1);
+  REALLOCATE (vecn[0].elements, float, 1);
+
+  /* binarize @ threshold */
+  Nx = buf[0].header.Naxis[0];
+  Ny = buf[0].header.Naxis[1];
+  Npix = Nx*Ny;
+  ALLOCATE (binary, char, Npix);
+
+  ap = (float *) buf[0].matrix.buffer;
+  bp = binary;
+  bzero (bp, Npix);
+
+  for (i = 0; i < Npix; i++, ap++, bp++) {
+    if (*ap > threshold) *bp = 1;
+  }
+
+  for (j = 0; j < Ny; j++) {
+    for (i = 0; i < Nx; i++) {
+      if (binary[j*Nx + i]) {
+	clearpix ();
+	status = fillrow (binary, Nx, j*Nx, i, &xs, &xe);
+	for (J = j + 1; (J < Ny) && status; J++) {
+	  for (I = xs; !binary[J*Nx + I] && (I <= xe); I++);
+	  status = fillrow (binary, Nx, J*Nx, I, &xs, &xe);
+	}  
+	/* we now have a stack of pixels, find geometric center */
+	statpix (&x, &y, (float *)buf[0].matrix.buffer, Nx);
+      }
+    }
+  }
+  freepix ();
+  return (TRUE);
+}
+
+/* find contiguous trigger pixels in row from starting point */
+int fillrow (char *buffer, int Nx, int offset, int sx, int *xs, int *xe) {
+
+  int i, pix, trigger;
+
+  *xe = *xs = sx;
+  trigger = FALSE;
+  for (i = sx, pix = offset + i; buffer[pix] && (i < Nx); i++, pix++) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xe = i;
+  }
+  for (i = sx - 1, pix = offset + i; (i >= 0) && buffer[pix]; i--, pix--) {
+    addpix (pix);
+    buffer[pix] = 0;
+    trigger = TRUE;
+    *xs = i;
+  }
+  return (trigger);
+}
+
+static int Npixlist = 0;
+static int *pixlist = (int *) NULL;
+
+addpix (int pix) {
+  Npixlist ++;
+  if (pixlist == (int *) NULL) {
+    ALLOCATE (pixlist, int, MAX (1, Npixlist));
+  } else {
+    REALLOCATE (pixlist, int, MAX (1, Npixlist));
+  }    
+  pixlist[Npixlist - 1] = pix;
+}
+
+clearpix () {
+  Npixlist = 0;
+  REALLOCATE (pixlist, int, 1);
+}
+
+freepix () {
+  Npixlist = 0;
+  free (pixlist);
+  pixlist = (int *) NULL;
+}
+
+statpix (float *x, float *y, float *buffer, int Nx) {
+
+  int i, X, Y, pix, Nv, No;
+  double Sx, Sy, So;
+
+  So = Sx = Sy = 0;
+  for (i = 0; i < Npixlist; i++) {
+    pix = pixlist[i];
+    Y = pix / Nx;
+    X = pix % Nx;
+    So += buffer[pix];
+    Sx += X * buffer[pix];
+    Sy += Y * buffer[pix];
+  }
+  *x = Sx / So;
+  *y = Sy / So;
+  gprint (GP_ERR, "%f %f  %f %d\n", *x, *y, So, Npixlist);
+
+  No = vecx[0].Nelements;
+  Nv = No + 1;
+  vecx[0].Nelements = vecy[0].Nelements = Nv;
+  vecf[0].Nelements = vecn[0].Nelements = Nv;
+
+  REALLOCATE (vecx[0].elements, float, MAX (Nv, 1));
+  REALLOCATE (vecy[0].elements, float, MAX (Nv, 1));
+  REALLOCATE (vecf[0].elements, float, MAX (Nv, 1));
+  REALLOCATE (vecn[0].elements, float, MAX (Nv, 1));
+
+  vecx[0].elements[No] = *x;
+  vecy[0].elements[No] = *y;
+  vecf[0].elements[No] = So;
+  vecn[0].elements[No] = Npixlist;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/init.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "dimm.h"
+
+int altaz           PROTO((int, char **));
+int camera          PROTO((int, char **));
+int findstars       PROTO((int, char **));
+int telescope       PROTO((int, char **));
+int version         PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "altaz",     altaz,     "altaz / celestial coord conversions"},
+  {1, "camera",    camera,    "camera functions"},
+  {1, "findstars", findstars, "find objects on image"},
+  {1, "telescope", telescope, "telescope communications"},
+  {1, "version",   version,   "show version information"},
+}; 
+
+void InitDIMM () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
+
+void FreeDIMM () {
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/sbig/sbig.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/sbig/sbig.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/sbig/sbig.h	(revision 16632)
@@ -0,0 +1,222 @@
+#ifndef _SBIG_H
+#define _SBIG_H
+
+#define VERSION  2.0
+
+struct sbig_init {
+    float linux_version;
+    int	 nmbr_bad_columns;	/* bad columns in imaging CCD */
+    int  bad_columns[4];
+    int  imaging_abg_type;	/* 0 no ABG, 1 ABG present */
+    char serial_number[10];
+    unsigned firmware_version;
+    char  camera_name[64];
+    struct camera_info {
+	int  nmbr_readout_modes;
+	struct readout_mode {
+	    int  mode;
+	    int  width;			/* pixels */
+	    int  height;		/* height */
+	    int  gain;			/* in 0.01 e-/ADU */
+	    unsigned pixel_width;	/* in nanometers */
+	    unsigned pixel_height;	/* in nanometers */
+	} readout_mode[12];
+    } camera_info[2];
+    int ST5_AD_size;
+    int ST5_filter_type;
+};
+extern int  sbig_init(int port, int options, struct sbig_init *);
+
+#define SBIG_IMAGING_CCD 0
+#define SBIG_TRACKING_CCD 1
+
+#define SBIG_CCD_STATUS_IDLE  0
+#define SBIG_CCD_STATUS_IN_PROGRESS  2
+#define SBIG_CCD_STATUS_COMPLETE  3
+
+#define SBIG_CCD_SHUTTER_OPENED  0
+#define SBIG_CCD_SHUTTER_CLOSED  1
+#define SBIG_CCD_SHUTTER_OPENING  2
+#define SBIG_CCD_SHUTTER_CLOSING  3
+
+struct sbig_status {
+    int  imaging_ccd_status;
+    int  tracking_ccd_status;
+    int  fan_on;
+    int  shutter_state;
+    int  led_state;
+    int  shutter_edge;
+    int  plus_x_relay;
+    int  minus_x_relay;
+    int  plus_y_relay;
+    int  minus_y_relay;
+    int  pulse_active;
+    int  temperature_regulation;
+    int  temperature_setpoint;
+    int  cooling_power;
+    int  air_temperature;
+    int  ccd_temperature;
+};
+extern int  sbig_get_status(struct sbig_status *);
+
+
+#define SBIG_LEAVE_SHUTTER  0
+#define SBIG_OPEN_SHUTTER  1
+#define SBIG_CLOSE_SHUTTER  2
+#define SBIG_INITIALIZE_SHUTTER  3
+
+#define SBIG_LED_OFF  0
+#define SBIG_LED_ON  1
+#define SBIG_LED_BLINK_SLOW 2
+#define SBIG_LED_BLINK_FAST 3
+
+struct sbig_control {
+    int  fan_on;
+    int  shutter;
+    int  led;
+};
+extern int  sbig_control(struct sbig_control *);
+
+struct sbig_pulse {
+    int nmbr_pulses;		/* 0 to 255 */
+    int pulse_width;		/* microsec, min 9 */
+    int pulse_interval;		/* microsec, min 27+pulse_width */
+};
+extern int  sbig_pulse(struct sbig_pulse *);
+
+struct sbig_relay {
+    int x_plus_time;
+    int x_minus_time;
+    int y_plus_time;
+    int y_minus_time;
+};
+extern int  sbig_activate_relay(struct sbig_relay *);
+
+
+/*
+ * Shutter control.  0 for no change in shutter (i.e. control of shutter
+ * using SBigControl class), 1 normal shutter (open during exposure,
+ * closed otherwise), 2 shutter closed (for taking dark frames).
+ */
+#define SBIG_EXPOSE_SHUTTER_UNCHANGED  0
+#define SBIG_EXPOSE_SHUTTER_NORMAL  1
+#define SBIG_EXPOSE_SHUTTER_CLOSED  2
+
+struct sbig_expose {
+    int ccd;
+    int exposure_time;
+    int abg_state;
+    int shutter;
+};
+extern int  sbig_expose(struct sbig_expose *);
+
+
+/*
+ *  Terminate the image and read it out.
+ *  Use width == 0 and height == 0 to abort an image with no readout (all
+ *   params other than ccd ignored)
+ */
+#define SBIG_BIN_1X1  0
+#define SBIG_BIN_2X2  1
+#define SBIG_BIN_3X3  2
+
+struct sbig_readout {
+    int ccd;
+    int binning;
+    int x, y;
+    int width, height;
+    unsigned short *data;
+    int data_size_in_bytes;
+    int (*callback)(float percent_complete);
+};
+extern int  sbig_readout(struct sbig_readout *);
+
+#define SBIG_NO_SHUTTER_DELAY  0x0001	/* don't wait for shutter to close */
+struct sbig_readout2 {
+    int flags;				/* see immediately above */
+    int ccd;
+    int binning;
+    int x, y;
+    int width, height;
+    unsigned short *data;
+    int data_size_in_bytes;
+    int (*callback)(float percent_complete);
+};
+extern int  sbig_readout2(struct sbig_readout2 *);
+
+
+#define SBIG_TEMP_REGULATION_OFF  0
+#define SBIG_TEMP_REGULATION_ON  1
+#define SBIG_TEMP_REGULATION_DIRECT_DRIVE  2
+
+/*
+ * Antiblooming gate control values
+ */
+#define SBIG_ABG_OFF  0
+#define SBIG_ABG_LOW  1
+#define SBIG_ABG_MEDIUM  2
+#define SBIG_ABG_HIGH  3
+
+struct sbig_cool {
+    int regulation;		/* 0 off, 1 on, 2 direct_drive */
+    int temperature;		/* in 0.1 deg C, if 'on' */
+    int direct_drive;		/* power [0..255], direct_drive */
+};
+extern int  sbig_set_cooling(struct sbig_cool *);
+
+extern int  sbig_set_ao7_deflection(int x_deflection, int y_deflection);
+
+extern int  sbig_set_ao7_focus(int type);
+
+#define SBIG_AO7_FOCUS_SOFT_CENTER 4
+#define SBIG_AO7_FOCUS_HARD_CENTER  3
+#define SBIG_AO7_FOCUS_STEP_TOWARD_SCOPE 2
+#define SBIG_AO7_FOCUS_STEP_FROM_SCOPE 1
+
+/*
+ *	Return Error Codes
+ *
+ *	These are the error codes returned by the driver
+ *	function.  They are prefixed with CE_ to designate
+ *	them as camera errors.
+ *
+ *      The return codes from the sbig_xxx() routines will
+ *      be the NEGATIVE of these on an error.
+ *
+ */
+#define SBIG_CAMERA_NOT_FOUND	-1
+#define SBIG_EXPOSURE_IN_PROGRESS -2
+#define SBIG_NO_EXPOSURE_IN_PROGRESS -3
+#define SBIG_UNKNOWN_COMMAND	-4
+#define SBIG_BAD_CAMERA_COMMAND	-5
+#define SBIG_BAD_PARAMETER	-6
+#define SBIG_TX_TIMEOUT		-7
+#define SBIG_RX_TIMEOUT		-8
+#define SBIG_NAK_RESBIGIVED	-9
+#define SBIG_CAN_RESBIGIVED	-10
+#define SBIG_UNKNOWN_RESPONSE	-11
+#define SBIG_BAD_LENGTH		-12
+#define SBIG_AD_TIMEOUT		-13
+#define SBIG_CHECKSUM_ERROR	-14
+#define SBIG_EEPROM_ERROR	-15
+#define SBIG_SHUTTER_ERROR	-16
+#define SBIG_UNKNOWN_CAMERA	-17
+#define SBIG_DRIVER_NOT_FOUND	-18
+#define SBIG_DRIVER_NOT_OPEN	-19
+#define SBIG_DRIVER_NOT_CLOSED	-20
+#define SBIG_SHARE_ERROR	-21
+#define SBIG_TSBIG_NOT_FOUND	-22
+#define SBIG_NEXT_ERROR		-23
+#define SBIG_NOT_ROOT		-24
+char *sbig_show_error(int);
+
+/*
+ * IO strategy flags
+ */
+#define SBIG_DISABLE_INTERRUPTS 0x001
+#define SBIG_LOCK_ALL	0x002
+#define SBIG_SHORT_DELAYS 0x004
+#define SBIG_DEFAULT_STRATEGY (SBIG_DISABLE_INTERRUPTS|SBIG_LOCK_ALL)
+void sbig_set_linux_strategy(int);
+
+#endif /* S_BIG_H */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/sbig/sp_ccdcontrol.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/sbig/sp_ccdcontrol.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/sbig/sp_ccdcontrol.c	(revision 16632)
@@ -0,0 +1,472 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <math.h>
+#include <time.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include "sbig.h"
+#include "fh/fh.h" /* CFHT FITS Handling library */
+
+// XXX RHL claims this is not needed
+// #include <values.h>
+
+#define N_FITS_ENTRIES 33
+
+/*
+ * The following hack is needed if you want to use sbig.a w/ libc5
+ */
+#ifndef __bzero
+void __bzero(void* s, int n)
+{
+  memset(s, 0, n);
+}
+#endif
+
+static struct sbig_init info;
+
+static int write_fits(int width, int height, double etime, int binmode, unsigned short *data);
+
+static struct sbig_readout readout;
+
+/*
+ * This is the 'progress' callback
+ * passed to sbig_readout()
+ */
+static int readout_callback(float percent)
+{
+  gprint (GP_ERR, "progress: Reading %d x %d pixels (%d%%)\r",
+	  readout.width, readout.height, (int)percent);
+  /* return 1 to continue, 0 to abort */
+  return 1;
+}
+
+/*
+ *  Start an exposure, wait for it, then download from the camera
+ *  in bands.  This is somewhat complex, since it handles any size
+ *  subimage of the CCD, and bands too.
+ */
+static void take_picture(double etime, int binmode, int shuttermode, int x, int y, int w, int h)
+{
+  int  ret, i, needed;
+  static unsigned short  *buffer;
+  static int  buffer_size;
+  struct sbig_expose  expose;
+  struct sbig_status  status;
+  double  f;
+  
+  expose.ccd = 0; /* Always in imaging mode, not tracking 
+		    since CFHT PF does the tracking*/
+
+  if(binmode<0 || binmode>3){
+    gprint (GP_ERR, "Imaging binmode options: [0=1x1, *1=2x2, 2=3x3]\n");
+    exit(EXIT_FAILURE);
+  }
+  readout.binning=binmode;
+  
+  readout.x=x;
+  readout.y=y;
+  readout.width=w;
+  readout.height=h;
+  if (readout.width == 0) {
+    readout.width =
+      info.camera_info[expose.ccd].readout_mode[readout.binning].width - x;
+  } else
+    if (readout.width + x >
+	info.camera_info[expose.ccd].readout_mode[readout.binning].width) {
+    gprint (GP_ERR, "Raster X or Width parameter out of range.\n");
+    exit(EXIT_FAILURE);
+  }
+
+  if (readout.height == 0) {
+    readout.height =
+      info.camera_info[expose.ccd].readout_mode[readout.binning].height - y;
+  } else
+    if (readout.height + y >
+	info.camera_info[expose.ccd].readout_mode[readout.binning].height) {
+    gprint (GP_ERR, "Raster Y or Height parameter out of range.\n");
+    exit(EXIT_FAILURE);
+  }
+
+  f = etime;
+  expose.exposure_time = (int)(100.0*f);
+  expose.abg_state = SBIG_ABG_OFF; /* SBIG_ABG_MEDIUM */
+
+  expose.shutter = shuttermode;  /* No shutter present */
+
+  sync();
+  ret = sbig_expose(&expose);
+  if (ret < 0)
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error(ret));
+  
+  gprint (GP_ERR, "progress: Sleeping for %g seconds\r", 0.01*expose.exposure_time);
+
+  if (expose.exposure_time > 100) {
+    for (i = 0; i < expose.exposure_time; i += 100) {
+      sbig_get_status(&status);
+      gprint (GP_ERR, "progress: Exposure in progress; ccd_status=%d, shutter=%d (%d%%)\r",
+	      status.imaging_ccd_status, status.shutter_state,
+	      i * 100 / expose.exposure_time);
+      sleep(1);
+    }
+  } else
+    usleep(expose.exposure_time*10000);
+  
+  /* wait for exposure to complete */
+  gprint (GP_ERR, "progress: Waiting for controller                             (100%%)\r");
+
+  for (i = 0; i < 1000; ++i) {
+    ret = sbig_get_status(&status);
+    if (ret < 0) {
+      gprint (GP_ERR, "sbig error: %s\n", sbig_show_error(ret));
+      break;
+    }
+    if (status.imaging_ccd_status != 3)
+      gprint (GP_ERR, "logonly: ccd_status=%d\n", status.imaging_ccd_status);
+
+    if (readout.ccd == 0) {
+      if (status.imaging_ccd_status != 2)
+	break;
+    } else {
+      if (status.tracking_ccd_status != 2)
+	break;
+    }
+    usleep(50000);
+  }
+  if (i)
+    gprint (GP_ERR, "warning: Exposure took an extra %g seconds\n", 0.050*i);
+
+  if (i == 1000)
+    gprint (GP_ERR, "error: EXPOSURE DIDN'T FINISH!\n");
+  else
+    gprint (GP_ERR, "progress: Exposure complete                                  (100%%)\n");
+
+  readout.ccd = expose.ccd;
+  readout.binning = readout.binning;
+  needed = readout.height*readout.width*sizeof(short);
+  if (buffer_size < needed) {
+    if (buffer != NULL)
+      free(buffer);
+    buffer = malloc(buffer_size = needed);
+  }
+  readout.data = buffer;
+  readout.data_size_in_bytes = buffer_size;
+  readout.callback = readout_callback;
+    
+  sync();
+  if ((ret = sbig_readout(&readout)) < 0) {
+    gprint (GP_ERR, "sbig error: %s\n", sbig_show_error(ret));
+    return;
+  }
+
+  gprint (GP_ERR, "progress: Writing FITS data to stdout\n");
+
+  if(write_fits(readout.width, readout.height, etime, binmode, buffer)==-1)
+    gprint (GP_ERR, "error: Could not write FITS file to stdout.\n");
+  gprint (GP_ERR, "progress: sp_ccdcontrol done.\n");
+}
+
+static int write_fits(int w, int h, double etime, int binmode, unsigned short *data)
+{
+  HeaderUnit hu;
+  register int i;
+  double datamin = DBL_MAX, datamax = DBL_MIN;
+  unsigned short u;
+  char str[80]; /* For building string FITS headers */
+  time_t date;
+
+  int ret; /* Return value for sbig_status */
+  struct sbig_status sbstat; /* Status structure */
+  
+  /* Get status to add to FITS header */
+  sync();
+  ret = sbig_get_status(&sbstat);
+
+  if (ret < 0) {
+    gprint (GP_ERR, "error: sbig_get_status failed: %s\n", sbig_show_error(ret));
+    exit(EXIT_FAILURE);
+  }
+
+  /* shouldn't we scale this to fit, first? */
+  for (i = w*h; --i >= 0; )
+    {
+      u = data[i];
+      if (u > datamax) datamax = u;
+      if (u < datamin) datamin = u;
+      data[i] = ((u<<8)|(u>>8)) ^ 0x0080; /* -32768 */
+    }
+
+  time(&date);
+
+  hu = fh_create();
+  fh_reserve(hu, 50); /* Reserve space for 50 cards (TCS, Elixir?, etc.) */
+  fh_set_bool(hu, 0., "SIMPLE", 1, "Standard FITS");
+  fh_set_int(hu, 1.0, "BITPIX", 16,"16-bit data");
+  fh_set_int(hu, 2.0, "NAXIS", 2,  "Number of axes");
+  fh_set_int(hu, 2.1, "NAXIS1", w, "Number of pixel columns");
+  fh_set_int(hu, 2.2, "NAXIS2", h, "Number of pixel rows");
+  fh_set_int(hu, 5.0, "PCOUNT",	0, "No 'random' parameters");
+  fh_set_int(hu, 6.0, "GCOUNT",	1, "Only one group");
+
+  strftime(str, sizeof(str)-1, "%Y-%m-%dT%T", gmtime(&date));
+  fh_set_str(hu, 104, "DATE", str, "UTC Date of file creation");
+  strftime(str, sizeof(str)-1, "%a %b %d %H:%M:%S %Z %Y", localtime(&date));
+  fh_set_str(hu, 104.1, "HSTTIME", str, "Local time in Hawaii");
+
+  fh_set_str(hu, 105, "ORIGIN", "CFHT", "Canada-France-Hawaii Telescope");
+
+  fh_set_flt(hu, 141.,"BZERO",	32768.0, 6,	"Zero factor");
+  fh_set_flt(hu, 142.,"BSCALE",	1.0, 2, "Scale factor");
+  fh_set_flt(hu, 150, "DATAMIN", datamin, 6, "Minimum value of the data");
+  fh_set_flt(hu, 151, "DATAMAX", datamax, 6, "Maximum value of the data");
+  fh_set_flt(hu, 160, "SATURATE", 4016.0, 6, "Saturation value");
+
+  fh_set_flt(hu, 220, "EXPTIME", etime, 5, "Integration time (seconds)");
+  sprintf(str, "%d %d", binmode + 1, binmode + 1);
+  fh_set_str(hu, 230, "CCDSUM", str, "Binning factors");
+  fh_set_int(hu, 231, "CCDBIN1", binmode + 1, "Binning factor along first axis");
+  fh_set_int(hu, 232, "CCDBIN2", binmode + 1, "Binning factor along second axis");
+
+  fh_set_com(hu, 1400.0, "COMMENT", "");
+  fh_set_com(hu, 1400.1, "COMMENT", " SBIG status record:");
+  fh_set_com(hu, 1400.2, "COMMENT", "");
+  if (sbstat.imaging_ccd_status==0)
+    fh_set_str(hu, 1500, "DETSTAT", "ok", "(SBIG imaging_ccd_status is 0)");
+  else
+    fh_set_int(hu, 1500, "DETSTAT", sbstat.imaging_ccd_status, "SBIG error!");
+  fh_set_flt(hu, 1500.1, "DETTEM", sbstat.ccd_temperature/10., 3, "Detector temperature");
+  fh_set_int(hu, 1500.2, "DETTEMRG", sbstat.temperature_regulation, "1=set temp 0=set power");
+  fh_set_int(hu, 1500.3, "DETTEMSP", sbstat.temperature_setpoint, "Temperature setpoint");
+  fh_set_int(hu, 1500.4, "DETTEMCP", sbstat.cooling_power, "Cooling power");
+  fh_set_flt(hu, 1510,  "CAMTEM", sbstat.air_temperature/10., 3, "Outside air temperature");
+  fh_set_com(hu, 1600.0, "COMMENT", "");
+  fh_set_com(hu, 1600.1, "COMMENT", " SBIG info record:");
+  fh_set_com(hu, 1600.2, "COMMENT", "");
+  sprintf(str, "%u", info.firmware_version);
+  fh_set_str(hu, 1600.9, "CONSWV", str, "SBIG firmware version");
+  fh_set_str(hu, 1601,"DETECTOR", info.camera_name, info.serial_number);
+  fh_set_bool(hu, 1700, "ABGON", info.imaging_abg_type, "Antiblooming gate present");
+  fh_set_int(hu, 1701, "ABGMODE", info.imaging_abg_type, "Antiblooming gate control value");
+  fh_set_int(hu, 1800, "BADCOL", info.nmbr_bad_columns, "Number of bad columns");
+  for (i = 0; i < info.nmbr_bad_columns; ++i){
+    sprintf(str, "BADCOL%d", i);
+    fh_set_int(hu, 1800 + 0.1 + 0.1 * i, str, info.bad_columns[i], "Bad column");
+  }
+  fh_set_int(hu, 1901, "ST5ADSIZ", info.ST5_AD_size, "");
+  fh_set_int(hu, 1902, "ST5FLTYP", info.ST5_filter_type, "");
+
+  if (fh_write(hu, STDOUT_FILENO) != FH_SUCCESS)
+    exit(EXIT_FAILURE);
+
+  if (fh_write_padded_image(hu, STDOUT_FILENO, data, w*h*sizeof(unsigned short), FH_TYPESIZE_RAW) != FH_SUCCESS)
+    exit(EXIT_FAILURE);
+
+  gprint (GP_ERR, "logonly: Wrote %d pixels, min=%g, max=%g\n", w*h, datamin, datamax);
+  sync();
+  return 0;
+}
+
+static void show_format(void){
+  gprint (GP_ERR, "Format for sp_ccdcontrol, SkyProbe CCD controller:\n"
+	  "Writes FITS file to stdout, status messages to stderr.\n"
+	  "NOTE: -port {hex} is an option for all forms of sp_ccdcontrol,\n"
+	  "  to specify a hex adress for the parallel port.\n"
+	  "sp_ccdcontrol expose -etime {Exp time}\n"
+          "   [-binmode {Binning mode}]\n"
+          "   [-shuttermode {Shutter mode}]\n"
+          "   [-raster X Y W H]\n"
+	  "Exp time: Exposure time given in seconds.\n"
+	  "Binning mode: 0=1x1, 1=2x2, 2=3x3.  Note, 3x3 not allowed in -track mode.\n"
+	  "   OR \n"
+	  "sp_ccdcontrol cool {coolmode} [temp|power]\n"
+	  "coolmode: 0=OFF, 1=ON, 2=Direct Drive\n"
+	  "For coolmode=0: Do not specify temp or power\n"
+	  "For coolmode=1: Specify temp in deg C\n"
+	  "For coolmode=2: Specify power (0-255)\n");
+  exit(EXIT_FAILURE);
+}
+
+
+int main(int argc, char *argv[])
+{
+  /*    char buffer[80], last_command[80]; */
+  int  ret = -1, i, port;
+  int  is_small_camera;
+    
+  /* Simon Kras--command line variables */
+  char cmd[80];
+  double etime;
+  int binmode;
+  int shuttermode;
+  int coolmode;
+  int raster_x, raster_y, raster_h, raster_w;
+  double cooltemp, coolpwr;
+
+  if(argc>1) strcpy(cmd, argv[1]);
+  else show_format();
+
+  port = 1; /* 0x378 */
+  for (i = 1; i < argc; ++i) {
+    if (!strcmp(argv[i], "-port")) {
+      sscanf(argv[++i], "%x", &port);
+      gprint (GP_ERR, "port override to 0x%x\n", port);
+    }
+  }
+
+  for (i = 0; i < 4; ++i) {
+    sync();
+    /* set our verbosity to 0 (range is 0 to 5) */
+    ret = sbig_init(port, 0, &info);
+    if (ret == -6) ret = 0; /* %%% It always returns this error, but actually it worked.
+			     * Since the library is binary only, we can't fix it.
+			     */
+    if (ret == 0) break;
+    gprint (GP_ERR,"logonly: sbig_init() failed: %s\n", sbig_show_error(ret));
+    usleep(100000);
+  }
+  if (ret < 0) {
+    gprint (GP_ERR, "error: cannot open camera, giving up\n");
+    exit(EXIT_FAILURE);
+  }
+
+  is_small_camera = (strstr(info.camera_name, "237") != NULL ||
+		     index(info.camera_name, '5') != NULL);
+  for (i = 0; i < info.camera_info[0].nmbr_readout_modes; ++i) {
+    struct readout_mode  *rmp;
+    rmp = &info.camera_info[0].readout_mode[i];
+#ifdef DEBUG
+    gprint (GP_ERR, "debug: ImagingCCD mode %d: w=%d h=%d "
+	    "gain=%f "
+	    "pw=%g ph=%g\n", rmp->mode, rmp->width,
+	    rmp->height,  0.01*rmp->gain, 0.001*rmp->pixel_width, 
+	    0.001*rmp->pixel_height);
+#endif
+  }
+
+  for (i = 0; i < info.camera_info[1].nmbr_readout_modes; ++i) {
+    struct readout_mode  *rmp;
+
+    rmp = &info.camera_info[1].readout_mode[i];
+#ifdef DEBUG
+    gprint (GP_ERR, "debug: TrackingCCD mode %d: w=%d h=%d "
+	    "gain=%f "
+	    "pw=%g ph=%g\n"
+	    , rmp->mode, rmp->width, rmp->height,
+	    0.01*rmp->gain,
+	    0.001*rmp->pixel_width, 0.001*rmp->pixel_height);
+#endif
+  }
+  if(!strcmp(cmd, "expose")){
+    etime=-999.;
+    for(i=1;i<argc;++i){
+      if(!strcmp(argv[i], "-etime")){
+	if(argc>(i+1)) etime = atof(argv[++i]);
+	else
+	  gprint (GP_ERR, "No argument given to -etime\n");
+      }
+    }
+    if(etime==-999.){
+	gprint (GP_ERR, "Must specify exposure time.\n");
+	exit(EXIT_FAILURE);
+      }
+      
+      binmode=-999;
+      for(i=1;i<argc;++i){
+	if(!strcmp(argv[i], "-binmode")){
+	  if(argc>(i+1)) binmode = atoi(argv[++i]);
+	  else{
+	    gprint (GP_ERR, "No argument given for -binmode\n");
+	    exit(EXIT_FAILURE);
+	  }
+	}
+      }
+      if(binmode==-999) binmode=0;
+
+      shuttermode=0;
+      for (i=1; i<argc;++i){
+	if (!strcmp(argv[i], "-shuttermode")){
+	  if (argc>(i+1)) shuttermode = atoi(argv[++i]);
+	  else{
+	    gprint (GP_ERR, "No argument given for -shuttermode\n");
+	    exit(EXIT_FAILURE);
+	  }
+	}
+      }
+
+      raster_x=0;
+      raster_y=0;
+      raster_w=0;
+      raster_h=0;
+      for (i=1; i<argc;++i){
+	if (!strcmp(argv[i], "-raster")){
+	  if (argc>(i+4)) {
+	    raster_x = atoi(argv[++i]);
+	    raster_y = atoi(argv[++i]);
+	    raster_w = atoi(argv[++i]);
+	    raster_h = atoi(argv[++i]);
+	  }
+	  else{
+	    gprint (GP_ERR, "-raster requires 4 arguments: x y w h\n");
+	    exit(EXIT_FAILURE);
+	  }
+	}
+      }
+      
+      take_picture(etime, binmode, shuttermode, raster_x, raster_y, raster_w, raster_h);
+
+  } else if(!strcmp(cmd, "cool")){
+    double  f;
+    struct sbig_cool  cool;
+    
+    if(argc<3){
+      gprint (GP_ERR, "Too few arguments for cool mode\n");
+      exit(EXIT_FAILURE);
+    } 
+    coolmode = atoi(argv[2]);
+    
+    if(coolmode<0 || coolmode>2){
+      gprint (GP_ERR, "Cooling mode values allowed: [0 Off, 1 *On, 2 DirectDrive]\n");
+      exit(EXIT_FAILURE);
+    }
+    cool.regulation = coolmode;
+    cool.direct_drive = 0;
+    if (cool.regulation == 2){
+      if(argc<4){
+	gprint (GP_ERR, "Must specify cooling power (0-255)\n");
+	exit(EXIT_FAILURE);
+      }
+      coolpwr=atof(argv[3]);
+      if(coolpwr<0 || coolpwr>255){
+	gprint (GP_ERR, "Cooling power must be 0-255.\n");
+	exit(EXIT_FAILURE);
+      }
+      cool.direct_drive = coolpwr;
+    }
+    else if (cool.regulation == 1) {
+      if(argc<4){
+	gprint (GP_ERR, "Must specify temperature in deg C\n");
+	exit(EXIT_FAILURE);
+      }
+      cooltemp=atof(argv[3]);
+      if(cooltemp<-50 || cooltemp>20){
+	gprint (GP_ERR, "Cooling temperature must be -50 to 20 deg C.\n");
+	exit(EXIT_FAILURE);
+      }
+      f = cooltemp;
+      i = 10.0*f + 0.5;
+      cool.temperature = i;
+    }
+    sync();
+    ret = sbig_set_cooling(&cool);
+    if (ret < 0){
+      gprint (GP_ERR, "sbig error: %s\n", sbig_show_error(ret));
+    }
+  }else{
+    gprint (GP_ERR, "Illegal command: '%s'\n", cmd);
+    show_format();
+  }
+  exit(EXIT_SUCCESS);
+}
+ 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/telescope.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/telescope.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/telescope.c	(revision 16632)
@@ -0,0 +1,236 @@
+# include "dimm.h"
+
+double distSky (double r1, double r2, double d1, double d2);
+
+int telescope (int argc, char **argv) {
+  
+  if (argc < 2) goto usage;
+
+  if (!strcasecmp (argv[1], "init")) {
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: telescope init (port)\n");
+      return (FALSE);
+    }
+    if (!SerialInit (argv[2])) return (FALSE);
+    gprint (GP_ERR, "telescope on port %s\n", argv[2]);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "cmd")) {
+
+    int status;
+    char *answer = (char *) NULL;
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: telescope cmd (string)\n");
+      return (FALSE);
+    }
+    status = SerialCommand (argv[2], &answer, 10);
+    gprint (GP_ERR, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      gprint (GP_ERR, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "ack")) {
+
+    int status;
+    char line[32], *answer;
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: telescope cmd (string)\n");
+      return (FALSE);
+    }
+    line[0] = 0x06;
+    line[1] = 0;
+    status = SerialCommand (line, &answer, 10);
+    gprint (GP_ERR, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      gprint (GP_ERR, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "slew")) {
+
+    double ra, dec;
+    int status;
+
+    if (argc != 4) {
+      gprint (GP_ERR, "USAGE: telescope slew (ra) (dec)\n");
+      return (FALSE);
+    }
+
+    ra  = atof (argv[2]);
+    dec = atof (argv[3]);
+    while (ra  < 360.0) ra += 360.0;   
+    while (ra  > 360.0) ra -= 360.0;   
+
+    status = gotoRD (ra, dec);
+
+    if (!status) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "coords")) {
+
+    int status;
+    double ra, dec;
+    char line[64];
+
+    if (argc != 2) {
+      gprint (GP_ERR, "USAGE: telescope coords\n");
+      return (FALSE);
+    }
+
+    if (!getRD (&ra, &dec)) return (FALSE);
+    gprint (GP_ERR, "%f %f\n", ra, dec);
+    set_variable ("RA", ra);
+    set_variable ("DEC", dec);
+    dms_format (line, (ra/15.0));
+    set_str_variable ("Rs", line);
+    dms_format (line, dec);
+    set_str_variable ("Ds", line);
+
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "altaz")) {
+
+    int status;
+    double x, y;
+
+    if (argc != 2) {
+      gprint (GP_ERR, "USAGE: telescope altaz\n");
+      return (FALSE);
+    }
+
+    if (!getXY (&x, &y)) return (FALSE);
+    gprint (GP_ERR, "%f %f\n", x, y);
+    set_variable ("ALT", x);
+    set_variable ("AZ", y);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "site")) {
+
+    int status;
+    double lon, lat, LST;
+
+    if (argc != 2) {
+      gprint (GP_ERR, "USAGE: telescope site\n");
+      return (FALSE);
+    }
+
+    if (!getSite (&lon, &lat, &LST)) return (FALSE);
+    gprint (GP_ERR, "%f %f  %f\n", lon, lat, LST);
+    set_variable ("LON", lon);
+    set_variable ("LAT", lat);
+    set_variable ("LST", LST);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "setsite")) {
+
+    double lon, lat;
+
+    if (argc != 5) {
+      gprint (GP_ERR, "USAGE: telescope setsite (name) (longitude) (latitude)\n");
+      return (FALSE);
+    }
+
+    lon = atof (argv[3]);
+    lat = atof (argv[4]);
+    if (!setSite (argv[2], lon, lat)) return (FALSE);
+    set_variable ("LON", lon);
+    set_variable ("LAT", lat);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "settime")) {
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: telescope settime (lst)\n");
+      return (FALSE);
+    }
+
+    if (!setTime (argv[2])) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "verbose")) {
+
+    int mode;
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: telescope verbose (mode)\n");
+      return (FALSE);
+    }
+
+    mode = atoi (argv[2]);
+    SerialVerbose (mode);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "setcoords")) {
+
+    int status;
+    double ra, dec;
+
+    if (argc != 4) {
+      gprint (GP_ERR, "USAGE: telescope setcoords (ra) (dec)\n");
+      return (FALSE);
+    }
+
+    ra  = atof (argv[2]);
+    dec = atof (argv[3]);
+
+    if (!setRD (ra, dec)) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "offset")) {
+
+    int status;
+
+    if (argc != 4) {
+      gprint (GP_ERR, "USAGE: telescope offset (direction) (distance)\n");
+      gprint (GP_ERR, "  direction : x or y\n");
+      gprint (GP_ERR, "  distance  : +arcmin or -arcmin\n");
+      return (FALSE);
+    }
+    status = offset (argv[2], atof (argv[3]));
+
+    if (!status) return (FALSE);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "toffset")) {
+
+    int status;
+
+    if (argc != 5) {
+      gprint (GP_ERR, "USAGE: telescope toffset (direction) (rate) (duration)\n");
+      gprint (GP_ERR, "example: telescope toffset x RC 1.5\n");
+      return (FALSE);
+    }
+    status = toffset (argv[2], argv[3], atof(argv[4]));
+
+    if (!status) return (FALSE);
+    return (TRUE);
+  }
+
+ usage:
+  gprint (GP_ERR, "telescope init port - set serial port (eg, /dev/ttyS0)\n");
+  gprint (GP_ERR, "telescope site - get site information\n");
+  gprint (GP_ERR, "telescope altaz - g\n");
+  gprint (GP_ERR, "telescope setcoords (ra) (dec)\n");
+  gprint (GP_ERR, "telescope setsite (name) (longitute) (latitude)\n");
+  gprint (GP_ERR, "telescope coords\n");
+  gprint (GP_ERR, "telescope slew (ra) (dec)\n");
+  gprint (GP_ERR, "telescope offset (direction) (duration)\n");
+  gprint (GP_ERR, "telescope toffset (direction) (rate) (duration)\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dimm/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dimm/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dimm/version.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "dimm.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+int version (int argc, char **argv) {
+
+  char *tmp;
+
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "pclient version: %s\n", (tmp = strip_version (name))); free (tmp);
+
+  gprint (GP_LOG, "opihi version: %s\n", (tmp = strip_version (opihi_version()))); free (tmp);
+  gprint (GP_LOG, "ohana version: %s\n", (tmp = strip_version (ohana_version()))); free (tmp);
+  gprint (GP_LOG, "gfits version: %s\n", (tmp = strip_version (gfits_version()))); free (tmp);
+
+  gprint (GP_LOG, "compiled on %s %s\n", __DATE__, __TIME__);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,207 @@
+
+2006.10.04:
+  opihi-2-8    added output names, gprintGetName, '-current' to 'output'
+	       removed prototypes from old 'output' code
+	       fixed memory leak in evaluate_stack
+	       added global PID variable
+	       added quiet mode to coords
+	       added various memleak tests, other tests
+	       fixed error in buffer/vector selection for dimenup
+	       fixed counting error in fit2d (missing 1 row of matrix!)
+	       added normalization to kern
+	       cleaned CreateBuffer function, usage
+	       
+  mana-1-6     removed prototypes from old 'output' code
+	       cleaned CreateBuffer function, usage
+
+  pantasks-0-6 added TASK_STDOUT, TASK_STDERR to pantasks.h
+	       added stdout, stderr output targets for tasks/jobs
+	       cleaned CreateBuffer function, usage
+
+  dvo-0-6      cleaned CreateBuffer function, usage
+
+2006.08.23:
+  opihi-2-7    converted to gfits APIs (forces libfits 1.6)
+	       consolidated style argument parsing
+	       added style arguments to astro plotting
+	       added support for pantasks_client, pantasks_server
+	       added more complex keys to queue operations
+	       added gprint to allow buffered printing in threads
+	       updates to test framework for more flexibility
+	       added time conversions sec_to_hms, sec_to_day
+	       added SetLimitsRaw
+	       added isort_pair
+	       added VarConfigEntry
+	       added strip_version to clean version output
+	       moved gaussj to libohana
+	       moved main out of opihi to mana.c, etc
+
+  mana-1-5     converted to gfits APIs (forces libfits 1.6)
+	       added option for threaded shell/backend (not used)
+
+  dvo-0-5      converted to gfits APIs (forces libfits 1.6)
+      	       consolidated style argument parsing
+	       converted to new DVO APIs (dvo_catalog_xxx)
+	       added fitsed
+	       improvements to fitcolors
+	      
+  pantasks-0-5 converted to gfits APIs (forces libfits 1.6)
+	       added 'option' task command
+	       added limits on Njobs for time ranges
+	       fixed time ranges
+	       created client/server version
+	       added controller run/stop commands
+	       added controller help
+	       added server help
+
+  pcontrol-0-5 converted to gfits APIs (forces libfits 1.6)
+	       code re-org to make thread safe
+	       added multithread option (user/client threads)
+	       liberal use of ASSERTs
+
+  pclient-0-5  converted to gfits APIs (forces libfits 1.6)
+  dimm-0-4     converted to gfits APIs (forces libfits 1.6)
+
+2006.03.26:
+  opihi-2-6 : added 'close' function for devices
+	      added test framework  
+	      added tests to cmd.basic, cmd.data
+	      added $?var syntax (variable existence test)
+	      fixed broken a[3] = 5 assignment
+	      added PopQueueMatch function
+	      added periodogram.c
+	      improvements to dimendown, peak
+	      added fixwrap for roll-over on saturation
+
+  dvo-0-4     added proper-motion, parallax
+	      dropped _PS from Stars.R,D
+	      fixed configuration flags for readline/curses
+
+  mana-1-4     fixed configuration flags for readline/curses
+  pcontrol-0-4 fixed configuration flags for readline/curses
+  pclient-0-4  fixed configuration flags for readline/curses
+
+  pantasks-0-4 fixed configuration flags for readline/curses
+	       changed name from psched
+
+
+
+- opihi-2-5
+  * major work to switch to libkapa
+  * revised init sequence (general_init, program_init, startup)
+
+- mana 1.3
+  * changes to support new init sequence
+
+- dvo 0.3
+  * major changes to support SkyRegions
+  * changes to support libkapa
+  * changes to support new init sequence
+
+- psched 0.3
+  * changes to support new init sequence
+  * changes to support libkapa
+
+- pcontrol 0.3
+  * changes to support new init sequence
+  * changes to support libkapa
+
+- pclient 0.3
+  * changes to support new init sequence
+  * changes to support libkapa
+
+- dimm 0.2
+  * changes to support new init sequence
+  * changes to support libkapa
+
+dimm-0-1: release 2005.10.20
+  first tagged dimm release
+
+pclient-0-2: release 2005.10.20
+  minor cleanups
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+pcontrol-0-2: release 2005.10.20
+  added run/stop commands
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+psched-0-2: release 2005.10.20
+  work to improve / test throughput
+  minor cleanups
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+dvo-0-2:  release 2005.10.20
+  substantial changes to work with new dvo load functions
+  support for mode/format changes
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+mana-1-2:  release 2005.10.20
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+opihi-2-4: release 2005.10.20
+  minor changes to use new libohana (v1.5) / libfits (v1.4)
+  kapa/kii cursor interaction modified (needs kapa v1.3, kii v1.3)
+
+opihi-2-3: release 2005.08.15
+  first tagged release tarball
+  fixed up versions commands
+  added list types for psched 
+  moved to Makefile.Common method.
+
+opihi-2-2:
+  fixed up inclusion of dvo.h (conflicted names)
+  added Graph commands functions
+  added mosaic astrometry support
+  a variety of memory alloc bugfixes
+  added support for ohana_allocate functions
+  added real multicommand support (correct parsing of variables)
+  added some object modelling functions
+  added clipping to fits and stats
+  added gaussdeviate
+  added extrapolation to minterp
+  default of EXTNAME for extension keyword
+  added -cpt to various dvo functions
+  better help in dvo functions
+  fixed up lockfile APIs
+  added fitcolors
+  added lightcurve
+  some cleanups in dvo/photometry.c
+  added typefrac tests is photometry.c
+  added gain test for mrqmin
+  fixed up precedence in math
+  macro-ized binary/unary math ops
+  added modulo, erf
+
+opihi-2-1:
+  major reorg of imfit / added imfit functions
+  cleaned up get_argument calls so -Wall does not give errors
+  moved the 'elixir' command to dvo
+  tag added only to elixir implementations (mana + dvo)
+  dimm - need to coordinate with Olivier and Bernt
+  dvo2, pcontrol, pclient, sched - all under development
+
+2004.12.23
+
+  Moved typename/modename funcs to libohana.  this was motivated by
+  imregister, which would not compile cleanly using the old method.
+
+  Added library dependencies to the makefiles. previously, mana (etc)
+  would not re-build if the library was modified.
+
+  Fixed incorrect exit on non-tty.  this kept perl scripts with the
+  call "|mana" from running.
+
+  Fixed dvomath for strings.  since we moved to dvomath everywhere,
+  this broke complex string conditionals: (($a == hi) && ($b == lo)).
+  I added string types to the math functions, and tests to see if the
+  stack has strings which cannot be resolved as a vector or matrix.  
+
+2004.12.10:
+
+  fixed problem in lib.data/PlotVectors.c and lib.data/graphtools.c
+  that broke plotting for data with very large or small exponents (|x|
+  < 1e-12, |x| > 1e12).  also fixed cmd.data/vstats.c with same
+  problem.
+	
+opihi-2-0:
+  import to CVS 2004.12.03
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/changes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/changes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/changes.txt	(revision 16632)
@@ -0,0 +1,54 @@
+Oct 19  2003 misc/startup.c              . minor changes, DONE
+Oct 19  2003 misc/conversions.c		 . minor changes, DONE
+Oct 19  2003 misc/match_image.c		 . copied to dvo
+Apr 19 17:41 misc/ConfigInit.c		 . minor changes, kept dvo version
+May  6 16:13 misc/ImageOps.c		 . minor changes, DONE
+May 12 09:00 misc/photometry.c           . major changes : DONE
+
+Oct 15  2003 user/badimages.c            . no change
+Oct 15  2003 user/imlist.c		 . no change
+Oct 15  2003 user/precess.c		 . dvo version ok
+Oct 15  2003 user/delete.c		 . dvo version ok
+
+May  6 15:25 user/extract.c		 . mostly deprecated (transfer USNO/HST/etc versions)
+May 10 21:13 user/mextract.c		 . used status version + vectors
+May 11 12:06 user/avextract.c		 . used status version + vectors
+Oct 27  2003 user/imextract.c		 . used status version + vectors
+
+May 12 09:06 user/dmags.c		 . used status version + vectors
+May 12 09:12 user/dmagmeas.c		 . used status version + vectors
+May 12 09:13 user/dmagaves.c		 . used status version + vectors
+May 11 16:18 user/ddmags.c		 . used status version + vectors
+
+May  2 11:14 user/calextract.c		 . used status version + vectors 
+May  3 20:08 user/calmextract.c		 . used status version + vectors
+Oct 19  2003 user/cmd.c			 . fixed (photcodes vs vectors)
+Oct 19  2003 user/ccd.c			 . used status version + vectors
+
+Apr 19 19:48 user/gimages.c		 . minor changes, fixed
+Nov 14  2003 user/gstar.c		 . minor changes, fixed
+May  3 20:49 user/gtypes.c		 . dvo version ok
+May  6 09:37 user/images.c		 . copied to dvo
+May  3 20:49 user/imdata.c		 . dvo version ok
+May  3 20:50 user/imphot.c		 . dvo version ok
+May  3 20:51 user/imrough.c		 . dvo version ok
+May  3 20:51 user/imsearch.c		 . dvo version ok
+Nov  5  2003 user/photcodes.c		 . copied to dvo
+Nov  1  2003 user/pmeasure.c		 . dvo version ok
+Mar  3 11:25 user/showtile.c		 . copied to dvo
+Nov  1  2003 user/subpix.c		 . copied to dvo
+Oct 30  2003 user/dmt.c			 . minor changes & photcodes
+Nov  1  2003 user/lcurve.c		 . minor changes & photcodes
+
+May 18 09:50 user/cgrid.c		 . copied to dvo
+
+Nov  1  2003 user/abszero.c		 . deprecated
+May  3 20:51 user/zeropts.c		 . deprecated
+Nov 13  2003 user/resid.c		 . deprecated
+Nov 13  2003 user/photresid.c		 . deprecated
+
+May  2 11:20 user/cals.c		 . deprecated?
+May  3 20:37 user/ddmagextract.c	 . deprecated?
+May  3 20:11 user/dmagextract.c		 . deprecated?
+Oct 19  2003 user/ccdextract.c		 . deprecated?
+Oct 19  2003 user/cmdextract.c		 . deprecated?
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/command.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/command.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/command.txt	(revision 16632)
@@ -0,0 +1,24 @@
+
+readline: allocates a line and returns it; empty lines return NULL
+
+expand_vars: (recursively) expand expressions of the form $X
+	     frees the input line, allocates a new one.
+	     returns NULL on error (including NULL input)
+
+expand_vectors: expand expressions of the form $X
+	     frees the input line, allocates a new one.
+	     returns NULL on error (including NULL input)
+
+parse performs math expansion on the line, returning a new line (old one is freed)
+
+
+in newmath:
+
+isolate_elements converts argc,argv to cstack,Ncstack (argc,argv NOT freed)
+convert_to_RPN takes cstack,Nstack and converts to stack,Nstack; input cstack,Ncstack are freed
+check_stack puts pointers to data types on stack, no data allocated
+evaluate_stack 
+
+
+command parses a single input line (line) and expands
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/coords.list
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/coords.list	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/coords.list	(revision 16632)
@@ -0,0 +1,47 @@
+./cmd.astro/cgrid.c - OK (graph only)
+./cmd.astro/cplot.c  - OK (graph only)
+./cmd.astro/czplot.c - OK (graph only)
+./cmd.data/cursor.c - OK (graph only)
+./dvo/catalog.c - OK (graph only)
+./dvo/pcat.c - OK (graph)
+./dvo/pmeasure.c - OK (graph)
+./dvo/procks.c - OK (graph)
+./dvo/showtile.c - OK (graph)
+./cmd.astro/coords.c - fixed
+./dvo/gimages.c - fixed
+./dvo/ImageOps.c - fixed
+./dvo/images.c - fixed
+./dvo/imdense.c - fixed
+./dvo/imextract.c - fixed
+./dvo/imlist.c - fixed
+./dvo/imstats.c - fixed
+./dvo/photometry.c - fixed
+./dvo/subpix.c - fixed
+./dvo/get_regions.c - fixed
+
+./cmd.astro/drizzle.c - needs work
+./cmd.astro/transform.c - needs work
+./cmd.data/load.c - needs work
+./cmd.data/point.c - needs work
+./cmd.data/tvgrid.c - needs work
+./dvo/cmpread.c - needs work (single image)
+./dvo/imbox.c - needs work (single image)
+./dvo/simage.c - needs work (single image)
+
+dvo commands / functions affected by WRP / DIS astrometry
+
+LoadImage - no
+badimages.c - yes : also, use LoadImages
+get_regions.c - ? : OK if we register DIS image
+gimages.c
+ImageOps.c        : need to make association with DIS
+images.c
+imbox.c
+imdense.c
+imextract.c
+imlist.c
+imstats.c
+photometry.c
+showtile.c
+simage.c
+subpix.c
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/dmagoptions.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/dmagoptions.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/dmagoptions.txt	(revision 16632)
@@ -0,0 +1,143 @@
+
+mextract from value [options]
+avextract from value [options]
+
+imextract value [options]
+
+dmags F1 - F2 : F3 [options]
+dmagmeas F1 - F2 : value [options]
+dmagaves F1 - F2 : value [options]
+
+cmd F1 - F2 : F3 [options]
+ccd F1 - F2 : F3 - F4 [options]
+
+calextract F1 - F2 [options]
+calmextract F1 - F2 [options]
+
+options:
+
+ -photcode value
+  for avextract and dmagaves, -photcode defines the which code is used
+  to calculate certain values (mag, dmag, etc).  objects which lack a 
+  photcode return a logical NaN for that value.
+
+ -magrange min max
+
+this can apply to any photcode
+
+ -imaglim min 
+ -flag value
+ -time start stop
+ -fwhm (value)
+ -type (value)
+
+these naturally apply to the REF and DEP photcodes, but cannot apply to 
+to PRI and SEC.  (note that -type is interpretted a bit differently here
+from below. 
+
+ -chisq max
+ -errorlim max
+ -type (value)
+ -typefrac (type) (frac)
+ -nphot (value)
+ -ncode (value)
+ -fwhmfrac (value) (frac)
+
+these naturally apply to PRI and SEC photcodes, but cannot apply to
+REF.  For DEP, they could apply to the equivalent photcode.  eg
+
+  ccd I - 2MASS_J : 2MASS_J - 2MASS_K -chisq 2.0
+
+  this will exclude on chisq for the I value, and ignore the limit
+  for the 2MASS values
+
+  ccd I - CFH12K.R.00 : 2MASS_J - 2MASS_K -chisq 2.0
+
+  this will exclude on chisq for the I value, and ignore the limit
+  for the 2MASS values, and exclude on R (equiv to CFH12K.R.00).
+
+  ccd I - CFH12K.R.00 : 2MASS_J - 2MASS_K -time start stop
+
+  by default, this will filter the CFH12K.R.00 and 2MASS measurements 
+  based on
+
+we need to be able to restrict the selections to a subset of the
+extraction values.  We can use a flag like: -apply YYNN:
+
+  ccd I - CFH12K.R.00 : 2MASS_J - 2MASS_K -time start stop -apply NYNN
+
+to restrict the application to only the CFH12K.R.00 entry.
+
+measure values:
+  ra
+  dec
+  mag
+  dmag
+  airmass
+  exptime
+  photcode
+  time
+  dR
+  dD
+  fwhm
+  dophot
+  FLAGS
+  XCCD
+  YCCD
+  XMOSAIC
+  YMOSAIC
+
+average values:
+  ra
+  dec
+  dmag
+  Nmeas
+  Nmiss
+  Xp
+  Xm
+  flag
+  type
+  typefrac
+  Nphot
+  Ncode
+
+
+
+- ExtractDMag
+  - ExtractMeasuresDMag
+    - TestAverage
+  - ExtractMagnitudes
+    - ExtractAverages
+    - ExtractMeasures
+
+mextract
+ - ExtractMeasures
+avextract
+ - ExtractAverages
+dmags
+ - ExtractDMag
+ - ExtractMagnitudes
+ddmags
+ - ExtractDMag
+ - ExtractDMag
+dmagmeas
+ - ExtractDMag
+ - ExtractMeasures
+dmagaves
+ - ExtractDMag
+ - ExtractAverages
+cmd
+ - ExtractDMag
+ - ExtractMagnitudes
+ccd
+ - ExtractDMag
+calextract
+ - ExtractAverages
+calmextract
+ - ExtractMeasures
+
+
+cmd B - V : B
+dmagmeas B - V : ra
+dmagmeas B - V : time
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo-2.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo-2.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo-2.txt	(revision 16632)
@@ -0,0 +1,28 @@
+
+Region APIs
+
+Region table is a FITS table
+
+- load region data from FITS table
+- save region data to FITS table
+
+/* find region which overlaps c at given depth (-1 : max depth) */
+SkyRegion *SkyFindPoint (SkyRegion *db, SkyCoord c, int depth);
+
+/* find regions at all levels which overlap c */
+SkyRegion **SkyFindLevels (SkyRegion *db, SkyCoord c, int *Nregion);
+
+/* find regions contained within rectangular region  c1 - c2 */
+SkyRegion **SkyFindArea (SkyRegion *db, SkyCoord c1, SkyCoord c2, *nlist);
+
+- I have created table generation functions which construct a
+  collection of table entries starting with the full sky and iterating
+  down N levels.  The function also fills out the names at the
+  appropriate levels.  This is currently ok up to level 6, but runs
+  out of memory at level 7.  This should not be the case, so I suspect
+  I'm not free'ing some memory.  
+
+- I need to create a function to take the GSC table list and construct
+  a set of SkyRegions that match the layout, starting with the full
+  sky and iterating down to and past the GSC tables.  
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo-apis.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo-apis.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo-apis.txt	(revision 16632)
@@ -0,0 +1,89 @@
+
+skyregion APIs:
+
+// a single patch on the sky
+typedef struct {
+  float            Rmin;                 // 
+  float            Rmax;                 // 
+  float            Dmin;                 // 
+  float            Dmax;                 // 
+  int              childS;               // sequence number in full table of first child
+  int              childE;               // sequence number in full table of last child + 1
+  int              parent;               // sequence number in full table of parent
+  int              index;                // sequence number in full table of this entry
+  char             depth;                // depth of this entry
+  char             child;                // does this entry have children?
+  char             table;                // does this entry have a table?
+  char             name[21];             // name / filename
+} SkyRegion;
+
+/* SkyRegion : better implementation than GSCRegion */
+typedef struct {
+  int Nregions;
+  char **filename;
+  SkyRegion *regions;
+} SkyTable;
+
+typedef struct {
+  int Nregions;
+  char **filename;
+  SkyRegion **regions;
+} SkyList;
+
+SkyList *SkyRegionByPoint (SkyTable *table, int depth, double ra, double dec);
+SkyList *SkyListByName (SkyTable *table, char *name);
+SkyList *SkyListByPoint (SkyTable *table, double ra, double dec);
+SkyList *SkyListByRadius (SkyTable *table, int depth, double RA, double DEC, double radius);
+SkyList *SkyListByPatch (SkyTable *table, int depth, SkyRegion *patch);
+SkyList *SkyListByImage (SkyTable *table, int depth, Image *image);
+SkyList *SkyListByBounds (SkyTable *table, int depth, double Rmin, double Rmax, double Dmin, double Dmax);
+SkyList *SkyListChildrenByBounds (SkyTable *table, int No, int depth, double Rmin, double Rmax, double Dmin, double Dmax);
+void SetImageCorners (double *X, double *Y, Image *image);
+int SkyTableSetDepth (SkyTable *sky, int depth);
+int SkyListFree (SkyList *list, int ELEMENTS);
+int SkyTableFree (SkyTable *table);
+int SkyListMerge (SkyList **outlist, SkyList *newlist);
+
+--- db query sky region ---
+
+// options for selecting the ra,dec limits of the db selections
+typedef struct {
+  char *name;
+  char *list;
+  int useDisplay;
+  int useSkyregion;
+} SkyRegionSelection;
+
+int get_skyregion (double *Rs, double *Re, double *Ds, double *De);
+int set_skyregion (double Rs, double Re, double Ds, double De);
+
+void FreeSkyRegionSelection (SkyRegionSelection *selection);
+SkyRegionSelection *SetRegionSelection (int *argc, char **argv);
+
+
+--- photometry.c api ---
+
+* int GetTimeSelection (time_t *tz, time_t *te) {
+int GetPhotcodeInfo (char *string, PhotCode **Code, int *Mode) {
+int SetSelectionParam (int param) {
+int GetSelectionParam () {
+int GetMeasureParam (char *parname) {
+int GetAverageParam (char *parname) {
+int TestPhotSelections (PhotCode **code, int *mode, int param) {
+void GetAverageParamHelp () {
+int InitPhotcodes () {
+int ListPhotSelections () {
+int SetPhotSelections (int *argc, char **argv, int Nparams) {
+double *ExtractMeasures (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+double ExtractAverages (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int param) {
+double DetermineTypefrac (Average *average, Measure *measure, PhotCode *code) {
+int DetermineTypeCode (Average *average, Measure *measure, int code) {
+int GetMeasureTypeCode (Measure *measure) {
+int Quality (Measure *measure, int IsDophot) {
+int TestAverage (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
+double *ExtractMagnitudes (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *n) {
+double *ExtractDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist) {
+double *ExtractMeasuresDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist) {
+double *ExtractByDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+double *ExtractMeasuresByDMag (PhotCode **code, int *mode, int use_first, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+double GetMeasure (int param, Average *average, Measure *measure, double mag) {
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo.html
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo.html	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/dvo.html	(revision 16632)
@@ -0,0 +1,288 @@
+
+<h2> PA data requirements </h2>
+
+Counting the total size of the PA database for the PA survey, with
+roughly 20 pointings per location and 30 second exposures.  The depth
+for PA survey in P2 @ 20 \sigma is 21.3 (r).  Each detection uses 100
+bytes (<b>we need to flesh this out with more realistic numbers from
+our table of parameters</b>).  The access speed to a RAID disk is 100
+MB/sec.  The number density of stars in i' in the plane may be higher,
+but we reach saturation at ~1.4e6 detections per deg^2 (one object per
+100 pixels).  This is a factor of 5 higher than the raw numbers.
+
+<h3> stellar counts for PS-1 </h3>
+latitude                 90          30         0
+density (deg^{-2})      5e3         3e4       3e5
+N_det (FPA^{-1})        4e4         2e5       2e6
+Sum N_det (FPA^{-1})    8e5         4e6       4e7
+Sum Nbyte (FPA^{-1})  80 MB      400 MB      4 GB
+Nsec for 1 channel      0.8           4        40
+Nchannel for 2 sec        1           2        20
+
+The total number of bytes for the PA survey for P2 detections is ~12
+TB (30000 x 400MB).  The density of detections per FPA from P4 delta
+is roughly the same as P2 at 0 deg (2e5 vs 3e5 det deg^{-2}).  The
+total number of bytes needed to store the P4 Delta detections from all
+of PS-1 is 
+
+Fields in the plane will take longer to process
+
+<h2> addstar interactions for a distributed db </h2>
+
+addstar.client <---> addstar.daemon
+
+The sky is divided into hierarchical regions, each broken into smaller
+subregions.  Both the image and object tables are divided into
+subtables by region on the sky.  The density of image tables is
+smaller than the density of object tables.  A top-level table defines
+the distribution of the lower-level tables by defining the hierarchy
+of regions and subregions.  Each entry in this table contains:
+
+region ID  - an identifier for the subregion
+RAs, RAe   - RA range of region
+DECs, DECe - DEC range of region
+parent ID  - ID of the region which contains this region (NULL for allsky)
+Nchild     - number of children
+offset     - starting entry of first child
+images     - is this region used for images? (if FALSE, down one layer)
+objects    - is this region used for objects? (if FALSE, down one layer)
+
+use the machine name / file name as the indicator in the images and
+objects entries?
+
+The table defines the relationship between the subregions and provides
+a mechanism to find the subregions appropriate to a given sky
+location.  It also specified for a given depth if that depth is used
+for the image and/or the object table.  The image tables contain
+images whose reference coordinate is located in the given region.
+Other regions which the image overlaps contain entries in the image
+reference table which specify the primary image table in which they
+are stored.  
+
+The details of the sky region definitions do not matter for the
+structure of the region table.  The data structures can handle any
+arrangement of tables which meets the basic requirements that the
+boundaries be lines of constant RA & DEC and that each level defines
+all regions which cover the entire sky.  One implementation is as
+follows and is easy to generate:  
+
+Start with the complete sky as a single region (RAs = 0, RAe = 360;
+DECs = -90, DECe = 90).  To create a new region, always subdivide the
+region with the largest area (roughly (RAe - RAs)*(DECe -
+DECs)*cos((DECs + DECe)/2)).  To subdivide a region, define two
+possible subdivisions: RA = 0.5*(RAs + RAe) (which becomes RAs and RAe
+for the two new regions) or DEC = 0.5*(DECs + DECe).  Determine the
+length of these dividing lines (S1 = (DECe - DECs); S2 = (RAe - RAs) /
+cos (DEC)).  Choose the shorter of these two lines, and subdivide the
+region on that basis.  
+
+The number of subregions increases by a factor of 8 for
+each new level.  Approximate table size: Need at least 200,000
+lowest-level regions, leads to 2^18 regions (256k) in lowest-level.
+Total table size is roughly 300k rows.  Each row is roughly 32 bytes,
+for a table size of 10MB.
+
+There is one addstar.daemon per DVO server.  The addstar.daemons are
+responsible for serving the objects and images from the tables they
+contain.  
+
+addstar.client steps to load a new set of objects:
+- load region table (defined in config db)
+- find overlapping object regions
+- find overlapping image regions
+- identify primary image region
+- send image data to node for primary image region 
+- send image reference to nodes for secondary image regions
+- send detection data (with image ID) to corresponding object region nodes
+
+addstar.daemon responsibilities:
+- receive image data -> add to primary image table
+- receive detection data -> add to local region file
+- request objects in overlap regions from neighbor daemons
+- send detections to neighbor daemons if associated with object over
+  border
+- construct / update objects on basis of detections
+
+in DVO 1.0, addstar updates objects on every upload of the
+detections.  In fact, the construction of the objects need not be
+performed every time detections are added.  Do we need to construct
+objects for all single detections?  The current process is:
+
+- get list of new detections (from incoming image)
+- match each detection with each object
+- update object parameters
+
+another option:
+
+step 1:
+ - get list of new detections
+ - add to new.detection table
+
+step 2:
+ - match detections to object table
+ - update object parameters
+
+third option
+step 1:
+ - add new detections to new table
+
+step 2:
+ - compare detections to orphans 
+ - if found, promote to object
+ - if not, test against objects
+ - if found update object
+ - if not add to orphans
+
+<h2> DVO image organization </h2>
+
+DVO 1.0 uses a single image table to store all image data.  In this
+table, each image is a chip; that is, each entry represents a single
+astrometric system.  In principal, there is no reason this could not
+be an entire mosaic or (in the case of Pan-STARRS) an individual
+Cell. It is usually necessary to be able to define the relationship
+between the different detector / focal plane / etc coordinate
+systems.  If the data entity is a full mosaic, then it will be
+necessary to look up the chip (and cell) transformations.  If the data
+entity is the cell, the reverse conversions will be needed.  
+
+The image table should be distributed to multiple files to speed up
+the access.  One option is to do this by coordinate region.  In the
+plan for DVO 2.0, there will be a table of the region hierarchy for
+the object tables, and the image tables could be distibuted similarly,
+though with a different density.  In PS-1, for example, there will be
+around 250,000 images (FPAs).  If we store OTAs (chips) as the data
+entity in the image table, then we will have in the vicinity of 16M
+rows.  If each contains 256 bytes, the total data volume in the image
+table will be about 4 GB.  If we want to have typical access times to
+any image of 1 second, and we need to scan through the entire table to
+get to the image, then we will need to distribute the data across 40
+tables (note that they need not be distributed by machine).  If each
+table represents a region on the sky, this translates to 1000 - 500
+square degrees per table.  
+
+Some additional aspects are interesting.  First, the
+spatially-distributed tables correspond to specific regions on the
+sky, likely to be bounded by lines of constant RA and DEC, or
+something equivalent.  However, an image cannot be guaranteed to land
+in only one of these regions.  To mitigate this, each image (chip or
+FPA or whatever the data unit is) should have a single defined
+position with which the general location is identified and the choice
+of region is made.  In addition, there should be a table associated
+with each region which defines images in other tables (regions) which
+overlap the given region.  In general, these overlap tables will
+contain only a small fraction of the image entries (regions are much
+large than images) and they need only identify the image ID and the
+corresponding table.
+
+An additional accelerator table would include all images, their
+reference time and their reference coordinate, sorted by time, with an
+index for the name.
+
+The end result is three types of tables: images.db, overlaps.db,
+imagetimes.db.  images.db contains the bulk of the information (256
+byte / row).  overlaps.db contains only the image ID and the the RA
+and DEC of the reference position (not the actual table because that
+may change). imagetimes.db contains only image ID (8 byte? 16 byte?),
+time, RA, DEC, and and index.  This is a total of about 40 bytes per
+image, for a total of roughly 700 MB at the end of PS-1.
+
+<h3> Examples queries </h3>
+
+<h4> find a single, specific image by ID </h4>
+<ul>
+<li> open imagetimes.db
+<li> load block marker (ID,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+<li> determine appropriate image.db table (region)
+<li> open image.db 
+<li> load block marker (ra,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+</ul>
+
+<h4> find a single, specific image by ID </h4>
+<ul>
+<li> open imagetimes.db
+<li> load block marker (ID,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+<li> determine appropriate image.db table (region)
+<li> open image.db 
+<li> load block marker (ra,block; every 10000 blocks)
+<li> find appropriate block
+<li> load block
+<li> find appropriate image entry
+</ul>
+
+<h3> dvo / object catalog scaling to massive collections </h3>
+
+DVO divides the sky into tables which represent specific areas on the
+sky.  Currently, these are pre-defined to match the HST GSC regions,
+roughly 1 - 4 square degree patches with fixed RA and DEC boundaries.
+A future extension will provide a mechanism to increaese or decrease
+the table density on the fly.
+
+The likely data rate under Pan-STARRS PS-1 is in the vicinity of 5 x
+10<sup>5</sup> stars per square degree.  The density is likely to vary
+by a factor of 30 for the bulk of the sky.  The Pan-STARRS camera
+consists of 1.44 x 10<sup>8</sup> pixels.  The confusion limit will
+likely be reached when each object encompases 25 pixels, resulting in
+a saturation of 6 x 10<sup>6</sup> stars per square degree.  The
+Pan-STARRS camera covers a total of 7.45 square degrees, and the
+expected exposure rate is roughly 1 per minute on average.  This
+amounts to a total of 3000 square degrees covered per night of
+observation, or a total of 1.5 x 10<sup>9</sup>detections per night,
+or a total of 5 x 10<sup>11</sup> over the course of one year.  Given
+this total number of detections, and the total sky coverage of 30,000
+square degrees, the average number of detections per square degree
+will be in the vicinity of 1.7 x 10<sup>7</sup>
+
+There are two main limitations to the DVO object storage model.
+First, the large data volume translates to a finite time to read the
+data from the disk.  Second, the large number of objects limits the
+rate at which new detections may be associated with the existing
+objects.  The first of these has generally proven to be the more
+significant limitation in applications to date.  We can easily
+calculate the time needed to load the data relevant to a random image
+pointing, as well as the maximum time based on the range of data
+volumes.  A necessary assumption in this calculation is the number of
+bytes used per detection.  We generously assume 100 bytes per
+detection, 3 times the existing data structures used by DVO.  
+
+Based on the numbers above, the total data volume represented by a
+year of observations is 50 TB, assuming the detection component
+dominates the total.  The average camera footprint translates to
+roughly 13 GB worth of detections.  Since each footprint is performed
+once per minute, it will be necessary to perform the read and write in
+each 10 seconds.  This in turn corresponds to 1.3 GB per second for
+the read and write portions.  With typical local hard-drive access
+speeds for RAIDs of 100 MB/sec, the data will need to be distributed
+across more than the machines in order to achieve these average
+rates.  
+
+The existing DVO system expects only one object table to be open at a
+time.  In addition, access to the tables is not controlled through
+separate machines.  Rather, a single collection of tables is expected
+and all queries are performed independently.  In order to handle the
+above load with the DVO software, the following changes will be
+needed:
+
+<ul>
+<li> tables must be distributed across multiple machines.  This is
+mandatory regardless of the underlying database engine based on the
+data I/O analysis above.
+
+<li> the 'addstar' front end needs to send the data for each table to
+the database backends on each of the corresponding machines.  
+
+<li> the addstar update for a single image can be done in series as is
+currently done.
+
+<li> write locking should be done on the tables rather than on the
+database as a whole (currently using the image table). 
+</ul>
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/ippc_commandserver.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/ippc_commandserver.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/ippc_commandserver.c	(revision 16632)
@@ -0,0 +1,166 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <string.h>
+#include <libxml/xmlmemory.h>
+#include <libxml/parser.h>
+#include "ippc.h"
+#include "ippc_messages.h"
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include "ippc_command.h"
+
+#define MAX_KIDS    256
+#define WAIT_FOR_KIDS    5
+
+/** \file ippc_commandserver.c
+ * \brief This is basically a big fat security problem.
+ */
+
+/* global variables */
+int    kids = 0;
+
+void  decrement_kids(int sig_num);
+
+int main(int argc, char *argv[])
+{
+  int    server_sockfd, client_sockfd, server_len, client_len;
+  int    result;
+  char    buffer[STRLEN], *portString;
+  uint16_t  netSafe;
+  uint32_t  auth_token;
+  unsigned short  status;
+  struct  sockaddr_in server_address;
+  struct  sockaddr_in client_address;
+
+  if (IPPC_DEFAULT_VERBOSITY > 1) {
+    gprint (GP_ERR, "%s : THIS PROGRAM _IS_ A REMOTE EXPLOIT!!!\n", argv[0]);
+  }
+
+  if (!(portString = getenv("IPPC_COMMANDSERVER_PORT"))) {
+    portString = "1035";
+  }
+
+  server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
+        if (server_sockfd == 0) {
+                perror("socket");
+                exit(EXIT_FAILURE);
+        }
+
+  server_address.sin_family = AF_INET;
+  server_address.sin_addr.s_addr = htonl(INADDR_ANY);
+  server_address.sin_port = htons(atoi(portString));
+  server_len = sizeof(server_address);
+
+  result = bind(server_sockfd, (struct sockaddr *)&server_address, server_len); 
+        if(result == -1) {
+                perror("bind");
+                exit(EXIT_FAILURE);
+        }
+
+  result = listen(server_sockfd, 10);
+        if(result == -1) {
+                perror("listen");
+                exit(EXIT_FAILURE);
+        }
+  
+  /* decrement the kiddie count after a child exits */
+  signal(SIGCHLD, decrement_kids);
+
+  /* flush dem pesky chars outa my buffer */
+  memset(buffer, 0, sizeof(buffer));
+
+  while(1) {
+    if (IPPC_DEFAULT_VERBOSITY > 1) {
+      gprint (GP_ERR, "%s : pid: %d - waiting for connection...\n", argv[0], getpid());
+    }
+
+    if (kids < MAX_KIDS) {
+      client_len = sizeof(client_address);
+      client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);
+    } else {
+      if (IPPC_DEFAULT_VERBOSITY > 1) {
+        gprint (GP_ERR, "%s : pid: %d - kids: %d - child limit already reached, sleeping %ds...\n",
+          argv[0], getpid(), kids, WAIT_FOR_KIDS);
+      }
+      sleep(WAIT_FOR_KIDS);
+      continue;
+    }
+
+    /* increment kiddie count before forking */
+    kids++;
+
+    if (fork() == 0) {
+      if (IPPC_DEFAULT_VERBOSITY > 1) {
+        gprint (GP_ERR, "%s : pid: %d - new kid number: %d\n", argv[0], getpid(), kids);
+      }
+
+      /* a non-zero result doesn't always mean an error occured
+       * I need to find out more about how to handle error checking here
+       */
+
+      /* receive and check authentication key */
+      recv(client_sockfd, &auth_token, sizeof(auth_token), 0);
+
+      if (ntohl(auth_token) != COMMAND_KEY) {
+        if (IPPC_DEFAULT_VERBOSITY > 1) {
+          gprint (GP_ERR, "%s : pid: %d - invalid authentication key\n", argv[0], getpid());
+        }
+
+        netSafe = htons(-1);
+        send(client_sockfd, &netSafe, sizeof(status), 0);
+
+        close(client_sockfd);
+        exit(EXIT_FAILURE);
+      }
+
+      /* receive command */
+      recv(client_sockfd, buffer, STRLEN, 0);
+  
+      if (IPPC_DEFAULT_VERBOSITY > 1) {
+        gprint (GP_ERR, "%s : pid: %d - recieved: %s\n", argv[0], getpid(), buffer);
+      }
+  
+      /* oh man is this dangerous */
+      status = system(buffer);
+      if (status != 0) {
+        if (IPPC_DEFAULT_VERBOSITY > 1) {
+          gprint (GP_ERR, "%s : pid: %d - command failed - code: %d\n", argv[0], getpid(), status);
+        }
+        netSafe = htons(status);
+        send(client_sockfd, &netSafe, sizeof(netSafe), 0);
+      } else {
+        if (IPPC_DEFAULT_VERBOSITY > 1) {
+          gprint (GP_ERR, "%s : pid: %d - command successful\n", argv[0], getpid());
+        }
+        netSafe = htons(status);
+        send(client_sockfd, &netSafe, sizeof(status), 0);
+      }
+
+      status = shutdown(client_sockfd, SHUT_RDWR);
+      if (status) {
+        perror("shutdown");
+        exit(EXIT_FAILURE);
+      }
+  
+      close(client_sockfd);
+      exit(EXIT_SUCCESS);
+    } else {
+      close(client_sockfd);
+    }
+  }
+}
+
+void  decrement_kids(int sig_num)
+{
+  /* sysv requires the handler to be reinstalled */
+  signal(SIGCHLD, decrement_kids);
+
+  /* reap child exit value */
+  while (waitpid(-1, NULL, WNOHANG) > 0) { kids--; }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/libs.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/libs.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/libs.txt	(revision 16632)
@@ -0,0 +1,17 @@
+
+I have divided the (non-user) functions into classes. 
+
+- conversions can be placed in a single library
+
+- graph and image (tv) functions can be placed in a library
+
+- the opihi shell functions can go into a third library
+
+- the dvo-related functions can go into a fourth
+
+- i need to clean up the mana and dimm misc functions, and put them in libraries 
+
+- the user functions also need to go into some libraries.
+
+- how do I have the library add its functions to the command list?
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/mana.updates.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/mana.updates.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/mana.updates.txt	(revision 16632)
@@ -0,0 +1,135 @@
+
+mana functions which existed in DVO from status:
+
+applyfit2d.c         : OK - vector changes only
+applyfit.c	     : OK - vector changes only
+box.c		     : OK - no diff
+center.c	     : OK - no diff
+clear.c		     : OK - no diff
+concat.c	     : OK - vector changes only
+contour.c	     : mana version writes to Ximage, dvo version writes to vectors.  mana/contour -> tvcontour.c
+create.c	     : OK - buffer changes only
+cursor.c	     : OK - buffer & minor changes only
+delete.c	     : OK - buffer & minor changes only
+device.c	     : OK - no diff
+extract.c	     : mana extract operates on buffers / status extract is db operation
+file.c		     : OK - no diff
+fit2d.c		     : OK - vector changes only
+fit.c		     : OK - added weights and parameter errors from mana version
+gaussj.c	     : OK - buffer changes only
+grid.c		     : mana version write to Ximage, dvo version writes to Xgraph. mana/grid -> tvgrid
+histogram.c	     : OK - vector changes only
+interpolate.c	     : OK - vector changes only
+jpeg.c		     : OK - no diff
+labels.c	     : OK - no diff
+limits.c	     : OK - vector & minor changes only
+list_buffers.c	     : OK - buffer changes only
+list_vectors.c	     : OK - vector & minor changes only
+mcreate.c	     : OK - buffer changes only
+mget.c		     : OK - buffer changes only
+mset.c		     : OK - buffer changes only
+ps.c		     : OK - no diff
+rd.c		     : OK - buffer changes only
+read_vectors.c	     : OK - included reading vectors from fits tables
+region.c	     : OK - no diff
+resize.c	     : OK - no diff
+section.c	     : OK - no diff
+set.c		     : OK - mana version out of date
+sprintf.c	     : OK - no diff
+stats.c		     : OK - included threshold comparison for IgnoreValue and min == max test
+style.c		     : OK - mana version out of date
+subset.c	     : OK - mana version out of date
+textline.c	     : OK - no diff
+tv.c		     : OK - buffer changes only
+uniq.c		     : OK - vector changes only
+vcontour.c	     : mana/vcontour equiv to dvo/contour
+vstat.c		     : OK - vector changes only
+wd.c		     : OK - buffer changes only
+write_vectors.c	     : OK - vector changes only
+zap.c		     : OK - buffer changes only
+zplot.c		     : OK - vector changes only
+
+mana functions not previously in DVO from status:
+
+accum.c			: fix vectors
+adc.c			: keep - specialized
+biassub.c		: fix buffers and vectors
+clip.c			: fix buffers and vectors
+cmpload.c		: keep
+coords.c		: fix buffers and vectors
+cut.c			: fix buffers and vectors
+cval.c			: ? superceeded by 'star'?
+demux.c			: keep - specialized
+dimendown.c		: fix buffers and vectors
+dimenup.c		: fix buffers and vectors
+drawline.c		: keep - unused
+drizzle.c		: fix buffers and vectors
+erase.c			: keep
+fft1d.c			: fix buffers and vectors
+fft2d.c			: fix buffers and vectors
+flux.c			: fix buffers and vectors
+gauss.c			: fix buffers and vectors
+gaussfit.c		: ? to correct?
+getchr.c		: keep
+getvel.c		: 
+imfit.c			: 
+imhist.c		: 
+integrate.c		: 
+kern.c			: 
+keyword.c		: 
+line.c			: 
+list_header.c		: 
+load.c			: 
+medacc.c		: 
+medianmap.c		: 
+memory.c		: 
+minterpolate.c		: 
+mkgauss.c		: 
+multifit.c		: 
+nextract.c		: 
+objload.c		: 
+outline2.c		: ??
+outline.c		: ??
+pause.c			: 
+peak.c			: 
+point.c			: 
+polar.c			: 
+profile.c		: 
+rdseg.c			: 
+rebin.c			: 
+roll.c			: 
+rotate.c		: 
+rotcurve.c		: 
+save.c			: 
+scale.c			: 
+select.c		: 
+sexigesimal.c		: 
+shape.c			: 
+shift.c			: 
+simsignal.c		: 
+sort_vectors.c		: 
+spec.c			: 
+spline_apply.c		: 
+spline_construct.c	: 
+star.c			: 
+strchr.c		: 
+strlen.c		: 
+substr.c		: 
+svd.c			: 
+swapbytes.c		: 
+testfit.c		: 
+transform.c		: 
+unsign.c		: 
+usleep.c		: 
+vbin.c			: 
+vclip.c			: 
+
+outdated or unneeded functions:
+
+dummy.c
+downdimen.c
+buftovec.c
+kernel.c
+updimen.c		: 
+stupidtest.c		: 
+plot2.c			: fixed GetColor in dvo/plot.c
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.dvo-data.html
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.dvo-data.html	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.dvo-data.html	(revision 16632)
@@ -0,0 +1,166 @@
+
+<h2> data structures in DVO </h2>
+
+DVO uses several data structures, defined in <tt>loneos.h</tt> to
+represent data in the database tables.  This document attempts to
+describe the actual usage, some of which may disagree with the comment
+entries in <tt>loneos.h</tt>.
+
+<b> Image </b>
+<table> 
+<tr><th> name               </th><th> type           </th><th> value                     </th><th> units              </th>
+<tr><td> coords             </td><td> Coords         </td><td> astrometry                </td><td>                    </td>
+<tr><td> tzero              </td><td> unsigned int   </td><td> readout time row 0        </td><td> unix time          </td>
+<tr><td> nstar              </td><td> unsigned int   </td><td> number of stars on image  </td><td>                    </td>
+<tr><td> secz               </td><td> short int      </td><td> airmass                   </td><td> 1000*airmass       </td>
+<tr><td> NX                 </td><td> short int      </td><td> image size                </td><td> pixels             </td>
+<tr><td> NY                 </td><td> short int      </td><td> image size                </td><td> pixels             </td>
+<tr><td> apmifit            </td><td> short int      </td><td> aperture correction       </td><td> 1000*mag           </td>
+<tr><td> dapmifit           </td><td> short int      </td><td> error                     </td><td> 1000*mag           </td>
+<tr><td> source             </td><td> short int      </td><td> photcode                  </td><td>                    </td>
+<tr><td> Mcal               </td><td> short int      </td><td> relphot correciton        </td><td> 1000*mag           </td>
+<tr><td> dMcal              </td><td> short int      </td><td> error                     </td><td> 1000*mag           </td>
+<tr><td> Xm                 </td><td> short int      </td><td> image chi-square          </td><td> 100*log(chisq)     </td>
+<tr><td> name[32]           </td><td> char           </td><td> image name                </td><td>                    </td>
+<tr><td> detection_limit    </td><td> unsigned char  </td><td>                           </td><td> 10*mag             </td>
+<tr><td> saturation_limit   </td><td> unsigned char  </td><td>                           </td><td> 10*mag             </td>
+<tr><td> cerror             </td><td> unsigned char  </td><td> astrometric error         </td><td> 50*arcsec          </td>
+<tr><td> fwhm_x             </td><td> unsigned char  </td><td> average FWHM X            </td><td> 25*arcsec          </td>
+<tr><td> fwhm_y             </td><td> unsigned char  </td><td> average FWHM Y            </td><td> 25*arcsec          </td>
+<tr><td> trate              </td><td> unsigned char  </td><td> drift rate                </td><td> 10000*sec/pix      </td>
+<tr><td> exptime            </td><td> float          </td><td> exposure time             </td><td> seconds            </td>
+<tr><td> code               </td><td> char           </td><td> data flags                </td><td>                    </td>
+<tr><td> ccdnum             </td><td> unsigned char  </td><td> mosaic CCD ID number      </td><td>                    </td>
+<tr><td> dummy[20]          </td><td> char           </td><td> extra                     </td><td>                    </td>
+<tr><td> order              </td><td> short int      </td><td> order of Mcal function    </td><td>                    </td>
+<tr><td> Mx                 </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> My                 </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxx                </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxy                </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Myy                </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxx               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxy               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxyy               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Myyy               </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxxx              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxxy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxxyy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Mxyyy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+<tr><td> Myyyy              </td><td> short int      </td><td> Mcal polynomial term      </td><td>                    </td>
+</table>
+
+<em> apmifit, dapmifit are needed for dophot data, but not sextractor data.  are these correctly handled? </em>
+<em> skyprobe used Mxxxx for Ncal and Myyyy for sky - can this be reconciled? </em>
+
+<h3> codes in Image</h3>
+<ul>
+<li> ID_IMAGE_NOCAL = 0x04 - internal to relphot 
+<li> ID_IMAGE_POOR  = 0x02 - set by relphot
+<li> ID_IMAGE_SKIP  = 0x04 - use by relphot (!!!)
+</ul>
+
+<b> Average </b>
+<table> 
+<tr><th> name       </th><th> type           </th><th> value               </th><th> units                 </th></tr>
+<tr><td> R          </td><td> float          </td><td> RA                  </td><td> decimal degrees J2000 </td></tr>
+<tr><td> D          </td><td> float          </td><td> DEC                 </td><td> decimal degrees J2000 </td></tr>
+<tr><td> M          </td><td> short int      </td><td>                     </td><td> 1000*mag		    </td></tr>
+<tr><td> Nm         </td><td> unsigned short </td><td> N measure	    </td><td> 			    </td></tr>
+<tr><td> Nn         </td><td> unsigned short </td><td> N missing	    </td><td> 			    </td></tr>
+<tr><td> Xp         </td><td> short int      </td><td> position scatter    </td><td> 100*arcsec	    </td></tr>
+<tr><td> Xm         </td><td> short int      </td><td> mag chisq           </td><td> 100*log(chisq)	    </td></tr>
+<tr><td> code       </td><td> unsigned short </td><td> data flags	    </td><td> 			    </td></tr>
+<tr><td> offset     </td><td> signed int     </td><td> measure offset	    </td><td> 			    </td></tr>
+<tr><td> missing    </td><td> signed int     </td><td> missing offset	    </td><td> 			    </td></tr>
+<tr><td> dM         </td><td> short int      </td><td> error on M          </td><td> 1000*log(value)	    </td></tr>
+<tr><td> Xg         </td><td> short int      </td><td> best chisq value    </td><td> ??		    </td></tr>
+</table>		  
+
+<h3> codes in Average</h3>
+<li> set to 0 by addstar, etc
+<li> ID_STAR_NOCAL        = 0x0001 - set by relphot
+<li> ID_PROPER            = 0x0400 - set by addusno, used by markrock
+<li> ID_BAD_DATE          = 0x0800 - deprecate (not currently set)
+<li> ID_TRANSIENT         = 0x1000 - not currently set? 
+<li> ID_VARIABLE          = 0x2000 - not currently set? 
+<li> ID_ROCK              = 0xa000 - set by markrock
+<li> ID_GHOST             = 0xc001 - set by fixcat, markstar
+<li> ID_TRAIL             = 0xc002 - set by fixcat, markstar
+<li> ID_BLEED             = 0xc003 - set by fixcat, markstar, markrock
+<li> ID_COSMIC            = 0xc004 - set by markrock
+</ul>
+
+<b> Measure </b>
+<table> 
+<tr><th> name       </th><th> type           </th><th> value               </th><th> units             </th>
+<tr><td> dR         </td><td> short int      </td><td> RA offset           </td><td> 100*arcsec        </td>
+<tr><td> dD         </td><td> short int      </td><td> DEC offset          </td><td> 100*arcsec        </td>
+<tr><td> M          </td><td> short int      </td><td> catalog mag         </td><td> 1000*mag          </td>
+<tr><td> Mcal       </td><td> short int      </td><td> image cal mag       </td><td> 1000*mag          </td>
+<tr><td> Mgal       </td><td> short int      </td><td> 'galaxy' mag,       </td><td> 1000*mag          </td>
+<tr><td> airmass    </td><td> short int      </td><td> (airmass - 1),      </td><td> 1000*airmass      </td>
+<tr><td> FWx        </td><td> short int      </td><td> fwhm major axis     </td><td> 100*arcsec        </td>
+<tr><td> dM         </td><td> unsigned char  </td><td> mag error           </td><td> 1000*mag          </td>
+<tr><td> fwy        </td><td> unsigned char  </td><td> minor/major ratio   </td><td>                   </td>
+<tr><td> theta      </td><td> unsigned char  </td><td> angle wrt ccd X dir </td><td> degree*(256/360)  </td>
+<tr><td> dophot     </td><td> char           </td><td> dophot type         </td><td>                   </td>
+<tr><td> source     </td><td> unsigned short </td><td> photcode            </td><td>                   </td>
+<tr><td> t          </td><td> unsigned int   </td><td> time                </td><td> unix time         </td>
+<tr><td> averef     </td><td> unsigned int   </td><td> average entry       </td><td>                   </td>
+<tr><td> dt         </td><td> short int      </td><td> exposure time       </td><td> 2500*log(exptime) </td>
+<tr><td> flags      </td><td> unsigned short </td><td> data flags          </td><td>                   </td>
+</table>
+
+<h3> flags in Measure</h3>
+<ul>
+<li> ID_MEAS_POOR         = 0x0001 - set by relphot, unset?
+<li> ID_MEAS_NOCAL        = 0x0002 - set by relphot, unset?
+<li> BLEND_IMAGE          = 0x0100 - set by addstar, etc
+<li> BLEND_CATALOG        = 0x0200 - set by addstar, etc
+<li> BLEND_IMAGE_NEIGHBOR = 0x1000 - set by addstar, etc
+<li> PART_OF_TRAIL        = 0x2000 - set by markstar, fixcat, used by markrock
+<li> GHOST_DATA           = 0x4000 - set by markstar, fixcat, used by markrock
+</ul>
+
+<em> relphot flag meanings: </em>
+<b> ID_IMAGE_NOCAL </b> : completely ignore image (internal only)
+<b> ID_IMAGE_SKIP  </b> : externally marked, don't include in Mrel, calculate Mcal (?)
+<b> ID_IMAGE_POOR  </b> : internally marked, don't include in Mrel, calculate Mcal (?)
+
+<b> ID_STAR_NOCAL  </b> : poor star, don't include in Mcal, calculate Mrel
+STAR_BAD == (average.Xm > STAR_CHISQ) || (average.dM > STAR_SCATTER) || (NVALID < MEAS_TOOFEW)
+
+<b> ID_MEAS_NOCAL  </b> : skip this measurement (temporary, internal)
+<b> ID_MEAS_POOR   </b> : poor star, don't include in Mcal, calculate Mrel
+MEAS_POOR == (3 sigma outlier) || (out of detector area)
+<em> currently NOT sticky!! </em>
+
+--
+
+uniphot.h:
+# define MEAS_POOR     0x0001
+# define MEAS_NOCAL    0x0002
+# define ID_IMAGE_SKIP 0x0004
+
+relphot.h:
+# define ID_VARIABLE   0x2000
+# define ID_TRANSIENT  0x1000 /* is this mutually exclusive with USNO?  */
+# define ID_BAD_DATA   0x0800 /* stationary object with some bad data points */
+# define ID_PROPER     0x0400 /* star with large proper motion */
+
+# define MEAS_POOR     0x0001
+# define MEAS_NOCAL    0x0002
+# define ID_IMAGE_SKIP 0x0004
+
+<em> things to update, cleanup </em>
+<d> finish fix of photcode in imregister-3.0, etc </d>
+<d> move flag constants from relphot/uniphot/photdbc include -> loneos.h </d>
+<d> watch for use of Xp, Xg, code in photdbc & status.extract, status.gstar</d>
+<b> status.extract.NVALID : count !(measure.flag & MEAS_POOR) </b>
+<d> fix error with ID_IMAGE_NOCAL == ID_IMAGE_SKIP </d>
+<d> make sure ID_IMAGE_POOR is saved and ID_IMAGE_SKIP is kept, including with -mosaic </d>
+<d> should STAR_BAD be saved or not?  probably not: there is not one per photcode </d>
+<d> MEAS_POOR should be saved, MEAS_NOCAL should not </d>
+<b> recompile all dvo programs, test </b>
+
+<b> photdbc </b> <em> check on the use of flags, etc; consistent with relphot, uniphot? </em>
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.photcode.html
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.photcode.html	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.photcode.html	(revision 16632)
@@ -0,0 +1,221 @@
+
+<h2> A Primer on DVO Photcodes and Magnitude Representation </h2>
+
+<p>
+There are two types of DVO table which store magnitude data.  The
+Average table stores magnitudes which represent averages of multiple
+measurements.  The Measure table stores magnitudes which represent
+single measurements.  
+
+<p>
+Each type of entry is defined by a Photcode.  The individual Measure
+entries have their photcodes stored as part of the structure.  The
+Average entries have photcodes which are determined externally by
+their sequence.  For historical reasons, the Average photcode are
+divided into the Primary photcode (of which there may only be one) and
+Secondary (of which there may be several).  The average magnitude
+associated with the Primary photcode is stored with the Average
+structure while the Secondary photcodes are stored in a separate,
+associated table called Secfilt.  The layout of the Average and
+Secfilt tables, and the photcodes assigned to them, are defined when
+the database is created based on the layout of the photcode table.
+This table is defined with a single Primary and a number of Secondary
+photcodes.  When the database tables are created, primary photcode is
+automatically associated with the Average entry while the sequence of
+Secondary photcodes defines the sequence of the entries in the Secfilt
+table.  This is very fragile, but very fast for making the
+association.  Thus, changing the number or sequence of secondary
+photcodes would cause an existing database table to be
+mis-interpretted.  
+
+<p>
+The Measure entries are broken into two photcode types as well:
+internal and external measurements.  Internal measurements are those
+for which the data source is well understood; the instrumental
+magnitudes are available and the instrumental parameters which are
+required to determine a calibrated magnitude.  External measurements
+are provided by external sources: published catalogs, reference
+sources, etc.  For these measurements, there is no control over the
+instrumental parameters which determined the measurement, and in many
+cases the measurement represents an average of an ensemble.
+
+<p>
+The photcode table defines relationships between photcodes,
+representing different photometry systems.  Each photcode entry
+defines the target of the calibration (the equivalence), and it may
+potentially define the zero-point (Co), the airmass slope (Ko), the
+appropriate color terms (C1, C2), the reference color term (Color),
+and the polynomial coefficients of the color equation (starting with
+the 1st order term).  
+
+<p>
+I need to include operations to handle varying color terms between
+CCDs.  I have measured color terms between CCDs in the range +/- 0.1
+mag/mag.  This is an appropriate time to clean up some of the code
+that handles the photcodes, etc.  In particular, the photcode table
+should provide the relationship beween relate between filter systems.
+
+For all of the functions below, a REF photcode simply returns the
+stored magnitude without transformation.  
+
+PhotInst (measure)
+  returns the instrumental magnitude of the given Measure
+  Minst = measure[0].M - measure[0].dt - iZERO_POINT;
+
+PhotCat (measure)
+  returns the 'catalog' magnitude of the given Measure (best guess
+  given no other information like color):
+  Mcat = measure[0].M - iZERO_POINT + Klam*(measure[0].airmass - 1000) + photcodes[0].code[Np].C;
+
+PhotSys (measure, average, secfilt)
+  returns the 'system' magnitude of the given Measure (best guess
+  using existing color information, but without application of
+  relative photometry offsets):
+  Msys = Mcat + f(color)
+  color is derived from measure.photcode.c1,c2  (measure.source.c1,c2)
+
+PhotRel (measure, average, secfilt)
+  returns the 'relative' magnitude of the given Measure (best guess
+  using existing color information and current relative photometry
+  measurment for this image).  This is the same photometry system as
+  the Average (PRI/SEC) measurement equivalent to this measurement
+  photcode:
+  Mrel = Msys + measure[0].Mcal;
+  color is derived from measure.photcode.c1,c2  (measure.source.c1,c2)
+
+PhotCal (measure, average, secfilt, allmeasures, code)
+  returns the 'calibrated' magnitude of the given Measure (best guess
+  using existing color information and current relative photometry
+  measurment for this image transformed to the appropriate reference
+  photometry system):
+  Mcal = Mref + f(color)
+  color is derived from code.c1,c2
+  the provided code must be either the measure.photcode.equiv or an
+  alternate for that code.
+
+<p>
+consider two filters, B & V, and two CCDs 00 & 01.  also, reference
+data in B_L92, V_L92
+
+<pre>
+    N  photcode     type  Co      Ko       X    C1    C2    Ao     Color  Equivalent
+  100  CFH12K.B.00  dep   26.000 -0.15     -    B     V     0.1    -      B
+  101  CFH12K.B.01  dep   26.000 -0.15     -    B     V     0.0    -      B
+
+  200  CFH12K.V.00  dep   26.100 -0.15     -    B     V     0.0    -      V
+  201  CFH12K.V.01  dep   26.100 -0.15     -    B     V     0.1    -      V
+
+    1  B            pri    0.000  -        -    B_L92 V_L92 0.016  -      B_L92
+    2  V            sec    0.000  -        -    B_L92 V_L92 0.008  -      V_L92
+
+  1003 B_L92        ref    -      -        -    -     -     -      -      -
+  1004 V_L92        ref    -      -        -    -     -     -      -      -
+  
+  B = m + Co + Ko*(secz - 1) + Ao*(B - V)
+  B_L92 = B + Co + color*A0 + color^2*A1 + color^3*A2
+</pre>
+
+<b>changes I'd like to make related to photcodes</b>
+
+<li> use structure value 'photcode', not 'source' everywhere
+<li> better abstraction / conceptualization of PhotMode values (Inst, Rel, Abs, Sys)
+<li> N-order polynomial for color-fits
+
+<b> relevant programs </b>
+
+<table>
+<tr><td>* addrefs    </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* addspphot  </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* addstar    </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* delstar    </td><td> minor fixes, no conversions are used </td></tr> 
+<tr><td>* photcode   </td><td> probably ok, check is consistent with new (?) photcode structs </td></tr> 
+<tr><td>* photreg    </td><td> check consistency </td></tr> 
+<tr><td>* photsearch </td><td> check consistency, use photcode table to get Equivalent </td></tr> 
+<tr><td>* relphot    </td><td> signficant changes to handle new structures </td></tr>
+<tr><td>libohana     </td><td> update LoadPhotcodes funcs, check consistency, use photcode table to get Equivalent </td></tr> 
+<tr><td>photdbc      </td><td> signficant changes to handle new structures </td></tr>
+<tr><td>status       </td><td> signficant changes to handle new structures </td></tr>
+<tr><td>dvo          </td><td> repeat fixes in status </td></tr> 
+
+<tr><td>lightcurve </td><td> unused? </td></tr>
+</table>
+
+<b> basic photcode APIs </b>
+
+int LoadPhotcodes (char *filename);
+void SetZeroPoint (double ZP);
+
+PhotCode *GetPhotcodebyName (name);
+int       GetPhotcodeCodebyName (name);
+PhotCode *GetPhotEquivbyName (name);
+int       GetPhotEquivCodebyName (name);
+
+PhotCode *GetPhotcodebyCode (code);
+char     *GetPhotcodeNamebyCode (code);
+
+PhotCode *GetPhotEquivbyCode (code);
+int       GetPhotEquivCodebyCode (code);
+
+double PhotInst (Measure *measure);
+double PhotAbs (Measure *measure);
+double PhotCat (Measure *measure);
+double PhotSys (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotRel (Measure *measure, Average *average, SecFilt *secfilt);
+double PhotAve (PhotCode *code, Average *average, SecFilt *secfilt);
+double PhotRef (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure);
+
+<b> examples </b>
+find measures which are of photcode equivalent to X
+if (GetPhotEquivCodebyCode (measure[0].source) == N1) { } 
+
+<b> code, entry, hashcode, hashNsec </b>
+entry = 1;
+photcode[entry].code = 100 
+photcode[entry].name = B
+hashcode[100] = 1;
+
+hashNsec is only valid for type PHOT_SEC:
+hashNsec[code] = Nsec entry in SecFilt table
+
+<b> note recursion relationships </b>
+hashcode[photcode[entry].code] = entry;
+photcode[hashcode[entry]].code = entry
+
+<b> outstanding questions / issues </b>
+
+<ul>
+<li> PhotSys needs to handle missing color values
+<li> define valid range for color?
+<li> double PhotFoo functions return what on NO_MAG?
+<li> PhotFoo functions need to check for valid input types:
+  <ul> 
+  <li> PhotInst - PHOT_DEP
+  <li> PhotAbs  - PHOT_DEP, PHOT_REF
+  <li> PhotCat  - PHOT_DEP, PHOT_REF
+  <li> PhotSys  - PHOT_DEP, PHOT_REF
+  <li> PhotRel  - PHOT_DEP, PHOT_REF
+  <li> PhotAve  - PHOT_PRI, PHOT_SEC
+  <li> PhotRef  - PHOT_PRI, PHOT_SEC
+  </ul>
+</ul>
+
+<b> phot definitions </b>
+PhotInst = Measure.M - dt - ZP 
+PhotCat  = Measure.M + K*(airmass-1) + C - ZP
+PhotSys  = Measure.M + K*(airmass-1) + C - ZP + X*color
+PhotRel  = Measure.M + K*(airmass-1) + C - ZP + X*color - Mcal  -> average.m
+PhotRef  = average.M + C + X*color 
+
+C: def ~ 26.0, pri ~ 0.0
+
+PhotAbs  = deprecate (measure.M + K*(airmass-1) + C - ZP
+
+<b> alt photcodes </b>
+
+photcodes of type ALT provide alternate calibration terms for a given
+photcode.  these codes are equivalent to primary/secondary codes, but
+no data is ever saved with this type.  There are only lookups between
+the photcode name and the photcode structure, never the photcode.code
+value, since that defines the photcode for which the given structure
+is an alternate relationship.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/notes.txt	(revision 16632)
@@ -0,0 +1,103 @@
+
+opihi improvements / fixes:
+
+* single math processing system : inline shell math used one set of
+  functions (shell/math.c), while the set = () used another set, and
+  logic used part of a third set.  This has been unified into a single
+  math handling function (newmath).  The new math expression handling
+  also returns temporary in-line vectors and matrix expressions.
+
+* global user variables (Buffers, Vectors) and other global variables
+  (outfile, tv parameters, graphic and image tool parameters) have
+  been encapsulated in fuctions to avoid the global data constructs.  
+
+* improved command exit status handling : in the past, a function
+  returning FALSE would halt all script executing, returning to the
+  top level of the command stack.  we now set the variable $STATUS
+  with the exit status and allow the the user to test the exit
+  status to choose an operation.  loops, macros, and input files can
+  use the 'break' and 'continue' functions to escape from the current
+  location.  calling break returns with an exit status of FALSE,
+  calling break returns immediately with an exit status of TRUE.
+
+* more extensive use of 'outfile' 
+
+* support for opihi scripts: there is now better interpretation of
+  command-line arguments to allow for embedded opihi scripts, ie
+  scripts with the dvo or mana interpretter named on the first line
+  with the prefix #! like a shell script.  The first command-line
+  argument is interpreted as a file to input while successive ones are
+  converted to variables $argv:0 - $argv:n  WARNING: in the past,
+  multiple input files could be specified on the command-line.  this
+  now must be specified with --load file arguments.
+
+* local variables: there is now support for local (vs global) opihi
+  variables.  any macro may have a variable declared as local with the
+  command 'local (var)', which may take a list of variables.  these
+  variables are stored internally in association with the macro name.
+  the command may include the option -static, in which case the
+  variable will retain its value on successive calls to the same
+  macro.
+
+- merge of all old opihi-type programs into a single code base 
+
+- group related functions into libraries
+
+- function names, etc, should come from a single function, now a
+  global include file.
+
+- update help files
+
+- update web pages
+
+--
+
+some notes: 
+
+- new vector interpretation is now somewhat slower, due to the multiple
+  assignments.
+
+- BinaryOp does not leak memory (tested)
+
+- 55 seconds for 1000 floating-pt operations on a 4Mpix (3 GHz) -> 0.2
+  seconds per FP OP on a 4k square image
+
+- loop / list functions:
+
+  opihi.c
+  run_loop.c
+  run_if.c
+  input.c
+  for_loop.c
+  macro_exec.c
+
+  I have added continue / break functionality to all loop operations:
+
+  * the variable $STATUS is set based on the exit status of each command
+  * each loop tests for break and continue
+  * in the case of break, the loop returns a status of FALSE
+  * in the case of continue, the loop returns a status of TRUE
+  * if break -auto is set to 'on', then any exit status of FALSE escapes to  
+    the top level.
+  * interrupts are carried up to the top level.
+
+- local variables
+
+  I have added local variables.  They have names of the form
+  MacroName.VarName, where MacroName is the macro in which they are
+  local.  They are declared local with the command 'local', which
+  takes a list of variables to declare local, and the optional -static
+  flag, which requires the shell to test for the existence of the
+  variable before creating it, and only create it if it does not
+  exist.  otherwise the existing value of the variable is maintained.
+
+- math
+
+  I have removed the last instances of math interpretation being
+  performed by math, not newmath, in expand_vectors (interpreting the
+  contents of the vector square brackets: x[5]), and in the two
+  locations where logic was used in the evaluation: run_in and
+  run_while.  there are still some error in the precedence of the
+  operators: logical operators >,<,==,!=, etc need to be lower
+  priority than other binary operators.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/pantasks.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/pantasks.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/pantasks.txt	(revision 16632)
@@ -0,0 +1,52 @@
+
+- task spawning speed
+
+  I have been examining things which affect the speed of the pantasks
+  processing. I have learned some interesting things:
+
+  * pcontrol was being slammed with requests for status by pantasks.
+    this may account for Paul's controller hang-ups.  I have added a
+    long (500ms) sleep to the controller thread to limit the rate at
+    which controller checks are run
+
+  * adding even a small usleep to the task_thread or job_thread puts
+    them to sleep for a long time (>> 10ms).  it seems longer than the
+    linux time slicer.  I have removed sleeps from the task and job
+    threads.
+
+  * the job submit rate is apparently limited by two things:
+
+    * when the job is submitted (SubmitJob) the interaction with
+      the controller seems to take ~30ms or more.
+
+    * some thread (controller thread? main readline thread?) seems to
+      introduce timeouts which are very long (up to 100ms).  These
+      introduce bit delays if when they happen during the task_thread
+      loop. 
+
+- updates for queues:
+
+  -key 1:2:4 (key is string with possibly multiple columns joined)
+  string function to drop first word
+
+
+- todo:
+
+  - create the processing threads:
+    - check tasks
+    - check jobs
+    - check controller  
+    - load inputs
+
+- additional issues:
+  - server input needs to place files for input on a stack which is 
+    actually loaded by the RunScheduler loop
+  - have the client run a special multicommand function which passes 
+    any unfound commands along to the server.  the server should not 
+    be running multicommand, but it probably does not hurt.
+    (the client is not allowed to send ';' to the server)
+
+  - pantasks input: this passes an 'input' command to the server, which
+    performs the input in a different thread.  is this the same thread
+    as the scheduler loop?  another option within the scheduler loop?
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/pcontrol.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/pcontrol.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/pcontrol.txt	(revision 16632)
@@ -0,0 +1,276 @@
+
+2006.08.18
+
+ Outstanding issues related to pcontrol:
+
+ * disposition of HUNG jobs?
+ * probably should not save the history for pcontrol or pclient
+   (these will be many lines long very quickly...)
+ * need to add options to run/stop for hosts and jobs independently
+
+2006.08.11
+
+I have nearly finished the conversion of pcontrol to use a background
+thread for monitoring the remote machines.  A few questions are still
+outstanding:  
+
+- currently, we are thread-safe for interactions with the stacks.  As
+  long as an operation is only working with a single job/host, and all
+  jobs/hosts are selected by pulling them from the stacks, there will
+  never be a contention between threads for the same job/host.
+  However, are there problems for commands which require a specific
+  job or host but are unable to find it because the job/host may be in
+  flight from one stack to another.  
+
+- The CheckIdleHost command needs to join a job and a host.  In this
+  case, it is necessary to lock the job PENDING stack while searching
+  for a job to give to a host.  The host is pulled off of the IDLE
+  stack before being past to CheckIdleHost.
+
+o CheckIdleHost currently does not have a way to send a WANTHOST job
+  to any host other than the WANTHOST.  What should the rule be by
+  which a job is run on an alternative machine? (partial fix)
+
+- we are not starting any of the job or host timers?
+
+2006.08.09
+
+working on pcontrol CheckSystem background thread.  One thread runs
+the readline interaction and performs all of the user commands.  The
+second thread runs the CheckSystem loop and tests the hosts and jobs.
+We need to be sure these two do not interfere with one another.  Here
+is a list of all of the user commands and the ways in which they
+interact with the Job / Host queues:
+
+
+
+2006.08.04
+
+pcontrol gets a large delay every time it tries to connect to a host.
+this is because the readline interrupt has to wait for the connection
+to complete.  I probably need to fix this by using a threaded model
+and running CheckSystem in a background thread.
+
+-----
+
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nmaxread;
+  int   Nextra;
+  int   Nlast;
+  int   Nbuffer;
+} Fifo;
+
+typedef struct {
+  int argc; char **argv; /* a list of words that define this object */
+  struct timeval start, accum, timer;
+  int   status;
+  char *logfile;
+  char *lastproc;
+} Object;
+
+typedef struct {
+  Object **object;
+  int    Nobject;
+  int    NOBJECT;
+} Queue;
+
+typedef struct {
+  char   *hostname;
+  int     rsock, wsock;
+  int     status; /* idle, busy, etc... */
+  struct  timeval start, accum, timer;
+  Fifo    fifo;
+  int     code;
+  Object *object;
+} Machine;
+
+
+currently, the transport is /usr/bin/rsh, defined in InitMachines.c 
+
+the shell on the remote machines is /bin/tcsh, defined by rconnect.c
+
+---
+
+pcontrol.client:
+
+ - remote process initiated by pcontrol
+
+ - accepts jobs, returns status, stdout and stderr
+
+ - valid commands:
+
+   - job (argv)
+     returns PID or -1 (0?) on failure
+
+   - status
+     returns current job status:
+     BUSY
+     EXIT n 
+     CRASH n
+     
+   - stderr
+     returns the current stderr buffer:
+     NBYTES n
+     (DATA)
+
+   - stdout
+     returns the current stdout buffer:
+     NBYTES n
+     (DATA)
+
+   
+---
+
+the client needs to accept commands from the server (via
+stdin/stdout), but it also needs to monitor its process.  I can use
+the opihi structure to implement the command-line interpretation with
+readline.  I can use the readline function rl_event_hook to set the
+background functions to check and rl_set_keyboard_input_timeout to set
+the polling period.
+
+this same method can be used with the scheduler:  the command 'run'
+can set the CheckTask function to this hook (& unset it).
+
+---
+
+rl_event_hook -> CheckChild
+
+  - needs to handle the case when no child process yet exists
+  - needs to examine the child status,
+  - needs to read from child stderr and store
+  - needs to read from child stdout and store
+
+  * no warnings (will not do anything clever if buffers get too large)
+
+---
+
+ pcontrol commands:
+
+ job [options] argv0 argv1 argv2 ...
+  -host name : run job on specified host, or any other if not available
+  +host name : run job on specified host, error if not available (error when attempted, not when submitted)
+  -timeout N : seconds before controller gives up on job (once started)
+  -stdout name : redirect job stdout to file directly
+  -stderr name : redirect job stderr to file directly
+
+  * priority information?
+  * returns JobID
+  * adds job to pending queue
+
+ host (hostname) [-delete]
+ (may have multiple entries to the same machine, these are not distinguished)
+
+ stdout ID [-file name]
+ stderr ID [-file name]
+ delete ID
+
+ status -job ID
+ status -machine hostname
+ status -queues
+
+pcontrol may be given a timeout for each job.  pcontrol will monitor a
+job and kill/crash it if the timeout expires.  the timeout only
+governs how long it is allowed to execute, not how long it can sit in
+the queue.  (the scheduler / operator should decide if a job has been
+on pcontrol for too long -- this probably means there are no
+appropriate machines ).
+
+pcontrol currently does not distinguish between multiple instances of
+a single host.  all have the same name.  if you want to bring down a
+host, you need to issue N host -down commands.  perhaps this is
+silly.  a simple alternative would be for the host [-on -off -start
+-stop] commands to apply to all defined entries which match the
+hostname.  In this case, a command like 'host foo -off' would find and
+halt all connections to the machine 'foo', while 'host foo -on' would
+restart them all (or rather, given the functionality of pcontrol,
+would allow pcontrol to attempt to bring them on).
+
+It is not clear why a user should be able to execute 'start' (down ->
+idle) or 'stop' (idle -> down).  The transition down -> idle is
+automatically performed by pcontrol for any machines which are
+currently down, while the transition idle -> down is immediately
+followed by an attempt by pcontrol to move the host from down -> idle.
+This functionality can be used with non-automatic calling of
+CheckSystem to test the pcontrol host interface operations.
+
+does it makes sense to kill all jobs on a host?  this would only have
+the effect of clearing the host for a moment until pcontrol decided to
+start another job on that host.  the desired effect is gained putting
+the host to 'off'.
+ 
+currently the command 'host (hostname)' puts the host in 'down'
+state.  pcontrol then immediately tries to connect to the host, moving
+it to 'idle' state (and then 'busy' if any jobs are available).  it
+might be useful to be able to add a host in 'off' state as a starting
+point.  
+
+it is not obvious that the user should be able to run 'CheckHost',
+unless this gets expanded to return state information on the host.
+
+---
+
+Job States:
+
+PENDING
+BUSY
+EXIT
+CRASH
+NEW *
+DEL *
+
+* - invisible states 
+
+Job State Transitions:
+
+NEW     -> PENDING : AddJob
+PENDING -> BUSY    : StartJob
+PENDING -> DEL     : DelJob
+BUSY    -> DONE    : CheckBusyJob | KillJob
+DONE    -> EXIT    : CheckDoneJob
+DONE    -> CRASH   : CheckDoneJob
+BUSY    -> PENDING : CheckJob | CheckHost
+EXIT    -> DEL     : DelJob
+CRASH   -> DEL     : DelJob
+
+Host States:
+
+IDLE
+BUSY
+DOWN
+OFF
+NEW *
+DEL *
+
+* - invisible states 
+
+Host State Transitions:
+
+NEW      -> OFF      : AddHost
+OFF      -> DEL      : DelHost
+OFF      -> DOWN     : OnHost
+DOWN     -> OFF      : OffHost
+IDLE     -> OFF      : OffHost
+DOWN     -> IDLE     : StartHost
+IDLE     -> BUSY     : StartJob
+BUSY     -> IDLE     : CheckJob | KillJob
+BUSY     -> BUSY-OFF : OffHost
+BUSY     -> DOWN     : CheckJob | CheckHost
+BUSY-OFF -> OFF      : CheckJob
+
+AddJob    - U
+DelJob    - U
+StartJob  - P
+CheckJob  - P
+KillJob   - U
+
+AddHost   - U
+DelHost   - U
+OnHost    - U
+OffHost   - U
+StartHost - P
+CheckHost - P
+
+U - operation performed by the user
+P - operation performed by the program
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/psched.htm
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/psched.htm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/psched.htm	(revision 16632)
@@ -0,0 +1,161 @@
+
+This article describes the concept, design, and operation of
+<tt>psched</tt>, the Pan-STARRS IPP task scheduler.  
+
+<h2> Basic Concept </h2>
+
+  <p>
+  The purpose of <tt>psched</tt> is to manage the automatic construction
+  and execution of inter-related (often repetative) operations.
+  <tt>psched</tt> uses a set of rules to define UNIX commands, and
+  their corresponding command-line arguments, to be performed on some
+  regular, repeated basis.  The utility of <tt>psched</tt> is that it
+  can easily define an analysis system which is completely
+  state-based, as opposed to an event-driven system.  
+
+  <p>
+  Consider, for example, a telescope which obtains a collection of
+  images over the course of a night.  Every minute or two, it takes an
+  image and writes the image to some disk.  An event-driven analysis
+  system would involve having the telescope initiate a process at the
+  end of the exposure.  This process would perform an analysis, write
+  some output, then send trigger another process.  This type of
+  operation works very well for a simple set up with reliable
+  hardware.  Such a system becomes more difficult to maintain when
+  hardware failures occur or when multiple systems need to interact
+  with each other.  When failures occur, the triggering information
+  (the events) is easily lost, thus some mechanisms are needed to
+  detect these failures and either re-send the trigger or send an
+  alternative failure-mode trigger.  Or, if two systems need to
+  interact, one or the other system must block for results from the
+  first.  Stopping and restarting such an analysis system is very
+  delicate since the appropriate triggers must be set up some how, eg
+  by noticing which images have not succeeded and restarting them at
+  the appropriate stage.  All of these types of methods of handling
+  complexity and failures are essentially state-based rules.
+  <tt>psched</tt> allows the easy definition of a totally state-based
+  analysis system.
+
+  <p>
+  In a state-based system, some mechanism examines the state of the
+  system and decides which actions to perform based on the current
+  state.  In the illustration above, the mechanism could examine the
+  images available (either by examining the disk or by examining the
+  state of a data table) and decide to perform an operation based on
+  what images are available.  This makes it very easy to handle
+  complexity and errors.  If an analysis fails, the state either is
+  not successfully updated or the error state is recorded, both
+  situations being easy to detect and easy to handle.  Restarting the
+  system simply involves starting the state-monitoring mechanism.
+  Combining results from multiple input sources simply involves
+  watching for the multiple inputs to be available.  <tt>psched</tt>
+  provides a mechanism to define state monitors, and to define the
+  actions which are performed when those states occur.
+  <tt>psched</tt> action consist of initiating UNIX commands, where
+  the arguments of those commands may depend on the results of the
+  state tests.
+
+  <h3> Tasks vs Jobs </h3>
+
+  <p>
+  The primary function of <tt>psched</tt> is to repeatedly perform
+  <b>tasks</b>, and execute <b>jobs</b> on the basis of those tasks.
+  A task consists of a set of rules which describe system state tests
+  to perform on a regular time scale.  Based on the results of those
+  state tests, the task will then choose whether or not to construct a
+  job.  The task also defines actions to perform upon the completion
+  of a job, based upon the output and exit status of the job.  A task
+  thus defines the repeat period.  It may optionally define valid or
+  invalid time ranges (eg, Mon-Fri or 10:00-17:00, etc).  The task may
+  also specify that the job be run locally (ie, in the background on
+  the same computer as psched) or remotely by the parallel process
+  controller (<tt>pcontrol</tt>).  A job may even be restricted to a
+  specific computer managed by <tt>pcontrol</tt>.
+
+  An example of a simple tasks is given below.  
+
+<pre>
+  task datalist
+    command ls /data/foo
+    periods -exec 5.0
+    periods -timeout 50.0
+    periods -poll 1.0
+
+    task.exit 0
+      queueprint stdout
+      queuedelete stdout
+    end
+ 
+    task.exit 1
+      queuepush failure "task failed"
+    end
+  end
+</pre>
+
+  <p>
+  This task does not perform any system state tests; it is simply
+  constructs a new job every 5.0 seconds.  The job in this case is
+  always the same: <tt> ls /data/foo </tt>.  When the job finished,
+  if the job exit status is 0 (normal UNIX success status), the
+  resulting output is printed to the screen.  If the job returns an
+  exit status of 1 (a failure), the failure queue receives a single
+  entry.  Although they are not defined in this case, it is also
+  possible to specify the action to be taken if the job crashes (does
+  not exit normally) or if it times out (runs beyond the specified
+  timeout period).
+
+  A slightly more complex task which performs a state test and
+  constructs a command based on that test is shown below
+
+<pre>
+  task datalist
+    periods -exec 5.0
+    periods -timeout 50.0
+    periods -poll 1.0
+
+    task.exec 
+      $file = `next.file`
+      if ($file == "none")
+        break
+      end
+      command cp /data/foo/$file /data/bar
+    end
+
+    task.exit 0
+      queueprint stdout
+      queuedelete stdout
+      queuepush copied $file
+    end
+ 
+    task.exit 1
+      queuepush failure $file
+    end
+  end
+</pre>
+
+  The <tt>task.exec</tt> macro is executed by psched every 5.0
+  seconds.  This macro executes a (hypothetical user-defined) UNIX
+  command (<tt>next.file</tt>) which examines the system state, return
+  either a filename or the word "none".  If the result of this test is
+  "none", the task does nothing: no job is constructed.  Otherwise, a
+  job is constructed using the name of the file returned by the state
+  test.  Successful jobs have the filename added to the 'copied'
+  queue, while failed jobs add the filename to the 'failure' queue.
+
+  <h3> Parallel vs Local Job Processing </h3>
+
+  <h3> Task Restrictions </h3>
+
+  <h3> Inter-Task and Inter-Job Communications </h3>
+
+<h2> psched Design </h2>
+
+  <h3> The Opihi Shell </h3>
+
+  <h3> Task List </h3>
+
+  <h3> Job List </h3>
+
+  <h3> pcontrol Interface </h3>
+
+  <h3> 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/rd-upgrades.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/rd-upgrades.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/rd-upgrades.txt	(revision 16632)
@@ -0,0 +1,10 @@
+
+rd a file.fits : read from PHU
+rd a file.fits -x N : read from extension N (0 - N)
+rd a file.fits -n name : read from extension name
+
+-plane : read only slice N
+
+* this function needs to check for compressed data:
+
+  * if PHU has been compressed, 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/region-image.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/region-image.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/region-image.txt	(revision 16632)
@@ -0,0 +1,13 @@
+
+I have done some work on getting region to use the image projection
+for the dvo display.  The pieces are almost there, except:
+
+* there is apparently a small offset between the two systems?
+
+* SelectRegions relies on the values of xmax and ymax being degrees
+  from a 0,0 coordinate.  this is a little tricky: this should not
+  fail for large AITOFF projections.
+
+* kapa does not do non-linear projections
+* kapa does not do multi-level projections
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/sample.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/sample.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/sample.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include <stdio.h>
+
+main (int argc, char **argv) {
+
+  int i;
+  char line[1024];
+
+  for (i = 0; i <= argc; i++) {
+    gprint (GP_ERR, "arg %2d: %s\n", i, argv[i]);
+  }
+  while (argv[i] != NULL) {
+    gprint (GP_ERR, "env %2d: %s\n", i, argv[i]);
+    i++;
+  } 
+  while (fscanf (stdin, "%s", line) != EOF) {
+    gprint (GP_ERR, "line: ...%s...\n", line);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/scheduler.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/scheduler.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/scheduler.txt	(revision 16632)
@@ -0,0 +1,206 @@
+
+2005.07.15
+
+The controller sends messages to both stdout and stderr.  I can easily
+require the messages which are immediate responses to external
+commands (status, check, etc) go back on stdout.  other messages
+should go to stderr, or be suppressed.  I suppose i can regularly
+harvest the stderr messages?
+
+2005.07.14
+
+I am still exploring the scheduler / controller interactions.  the
+automatic interactions seem to work pretty well now.  The area of
+confusion is in the user interface, both in terms of checking on the
+status of things (both controller and scheduler) and in terms of
+having user control over aspects of the controller.
+
+I have defined user functions which execute the controller commands
+'status' and 'check'.  These are straightforeward since they simply
+send a command to the controller and echo the output (or give an error
+condition message).
+
+Should the user have the ability to define a job, independent of a
+task?  This could be implemented purely as a controller action: the
+controller commands 'job', 'kill', 'delete', 'stderr', 'stdout' would
+be available from the scheduler, and the commands simply passed
+along.  This adds a bit to the complexity: if the 'delete' command is
+passed along, nothing prevents the user from deleting a job scheduled
+by the scheduler from a task.  the scheduler may then get confused
+when it tries to interact with that job in the future from the
+automatic loop.
+
+Another option is to simply have these commands interact with the
+scheduler's job stack.  this has the advantage of limiting the
+scheduler / controller responsibility errors (scheduler, not user, is
+always responsible to sending/harvesting jobs to/from the
+controller, though we still need to handle the cases if a job is lost
+or dropped by the controller).  the diffficulty here is deciding how
+to handle the job completion.  we would need a way to define a set of
+exit macros, which could then do something useful with the output.  
+
+Another possibility is to define limits on how many times a task may
+spawn a job.  There would then be no 'job' function.  If we define
+this limitation, we will still need a way of killing and deleting a
+specific job.  Thus a 'kill' and 'delete' function would examine and
+modify the scheduler's job stack.  The stderr and stdout functions are
+then already part of the task commands.  
+
+Other task options might include: 
+
+- a list of allow / exclude time periods (which should be time-of-day
+  ranges and day-of-week ranges).
+
+- a function to delete an existing task (which would have to stop the
+  spawning of new jobs, at least until no more jobs for that task
+  remain).
+
+- allow the 'periods' command to define defaults when outside of a
+  task
+
+2005.07.05
+
+At this point, scheduler / pcontrol / pclient all work in a basic way.
+pclient is the most robust of the three, having the simplest
+responsibility.  pcontrol is generally pretty good, though I need to
+flesh out the user interface a bit and clean up the output warning / info
+messages.  scheduler will need the most attention, though it is
+already fairly reasonable.  I need to flesh out the user commands to
+check on the controller status (basically, these need to replicate the
+status commands available to the controller).  
+
+I also need to handle the case of timeout on the controller,
+independently of timeout for a local job on the scheduler.  currently,
+if a local job exceeds the timeout value, scheduler flags it.  but, it
+does not make sense to use the same timeout value for a controller
+job. I could pass the timeout to the controller when the job executes,
+in which case it has the same meaning, essentially, for the controller
+jobs as it does for the local jobs: once you start the function, it
+needs to complete within NN seconds.  However, I think I still need to
+have a scheduler concept of a job which the controller is unable to
+complete.  It should be possible to prevent a job from sitting pending
+on the controller forever.  What exactly you do if the controller is
+unwilling to execute a job is another story (possible reasons:
+controller overload, missing required host, missing any hosts,
+something hung somewhere?).  
+
+The scheduler does not do a good job of shutting down the controller
+when it (the scheduler) exits.  This works well for the
+pcontrol/pclient interface, so the solution lies there.  
+
+I need to decide how to behave if the scheduler asks for a job with a
+required host which the controller knows is currently down or
+non-existent.  Several options could be used.  The controller could
+simply hold the task until the scheduler notices it is not being
+executed (after all, the controller does not know if the machine is
+being serviced for a short time or a long time, but the scheduler
+could know).  The controller could immediately return a failure noting
+the current state of the machine (this would put the burden of
+deciding that the machine should be available on the scheduler).  The
+controller could try to execute the job a certain number of times, and
+then it could report the failure to the scheduler.  This is not so
+different from having a pending-timeout which the scheduler tracks
+(moves the timeout check to the controller, essentially).  
+
+There was some odd behavior with 'exec echo $stdout >> foo'.  This
+resulted in empty files 'foo'.  The following work fine, so something
+is just weird:
+exec echo foobar >> foo
+output foo
+echo $stdout
+output stdout
+
+Various error conditions should be checked
+
+What do we do if a task requests a host which is not available to the
+controller (ie, not defined)?  this is similar to the problem of
+requesting a host which is down.  I think the controller should either
+immediately refuse or accept in anticipation that such a host may
+eventually be defined.
+
+I need to be careful about jobs sent to the controller and not
+harvested before stopping the scheduler execution.
+
+---
+
+sched / pcontrol todo:
+
+- sched: validate task hosts with controller
+
+---
+
+scheduler commands:
+
+task (taskname)
+ - define a new task
+ - loads task-related commands from list / readline
+ - commands are parsed on load
+ - end with end (like if / for)
+
+task.exit (value)
+ - define a new task macro for this exit condition
+   (value) may be an exit status (number)
+   (value) may be 'timeout'
+   (value) may be 'crash' ?
+ - commands are parsed on execution (not on definition)
+
+task.exec
+ - define a task macro for exec condition
+ - commands are parsed on execution (not on definition)
+
+command (args) (args)
+ - defines command associated with task
+ - may be in task or in task.macro (exit/exec)
+   (in task, command line is static; in task.macro, command line is expanded for each instance)
+
+host (machine) [-required]
+ - defines preferred host
+ - may be in task or in task.macro (exit/exec)
+   (in task, value is static; in task.macro, value is defined for each instance)
+ - value of LOCAL runs job as local job (not on controller)
+ - value of NONE runs job on controller without specifying host
+
+stderr (file / variable)
+ - defines destination for stderr capture from task
+ - written to destination at end of execution?
+
+stdout (file / variable)
+ - defines destination for stdout capture from task
+ - written to destination at end of execution?
+
+periods -poll 1
+periods -exec 30
+periods -timeout 2
+ - defines relevant time-scale for the task
+
+run
+stop
+ - start or stop the scheduler loop, executing the various tasks
+
+---
+
+local jobs vs controller jobs
+
+a local job is run as background fork (ie, not on controller)
+a controller job is sent to the controller to run when it can
+
+---
+
+possible errors which the scheduler may encounter when executing a
+job:
+
+  - controller is not responding
+  - controller says machine is DOWN
+  - controller says command not found
+  - controller has too many processes
+  - controller takes to long to start job (pending timeout)
+  - controller says job timed out
+  - controller says job crashed
+  - controller says job exited with status
+
+---
+
+notes:
+
+ - watch for NFS lags / blocking.  if NFS has file visibility lags, we
+   may need to add blocking as an option to the job (-block filename)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/stds.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/stds.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/stds.txt	(revision 16632)
@@ -0,0 +1,40 @@
+
+notation:
+
+object : an astronomical source, may be observed multiple times
+measurement : a single observation of an object (one per object per exposure) 
+m_inst : instrumental magnitude measurement
+m_cat  : catalog magnitude measurement (m_inst + 25.0)
+m_sys  : nominal internal system magnitude measurement (m_inst + ZP(CCD,FILTER)
+m_rel  : transparency adjusted magnitude measurement (m_sys + offset)
+
+M_ave  : average (object) magnitude in internal system
+M_ref  : average (object) magnitude in reference system
+
+test for photometric consistency:
+
+for the output from dither.corr:
+
+M_ave - m_rel(ccd) vs x_ccd, y_ccd
+M_ave - m_rel vs x_mosaic, y_mosaic
+M_ave - m_rel vs airmass?
+
+
+
+  MEGACAM.g.00 Minst - MEGACAM.g.01 Mcal : time
+
+  MEGACAM.g.00 - g : time
+
+  MEGACAM.g.00,Mrel - MEGACAM.g.01,Mcal : MEGACAM.g.00 - MEGACAM.r.00
+
+- use relphot to flag stars in poor locations, etc
+
+- we can choose for entry if it is Minst, Mcat, Msys, Mvrel, Mcal, Mave, or Mref
+
+int GetMagnitudeType (char *name, PhotCode *code, int *MagMode);
+
+- should return photcode & value MEAS_MREL, AVE_MREF, or what ever
+- should provide an appropriate default for measures, etc
+- should check for consistency with photcode type:
+  PRI/SEC : AVE_MREF, AVE_MAVE
+  DEP     : MEAS_ETC
Index: /branches/eam_branch_20080223/Ohana/src/opihi/doc/todo.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/doc/todo.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/doc/todo.txt	(revision 16632)
@@ -0,0 +1,4 @@
+
+- convert and include all mana/dimm/status derived functions
+- local scalar variables
+- break / continue in: for, macro, 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ImageOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ImageOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ImageOps.c	(revision 16632)
@@ -0,0 +1,123 @@
+# include "dvoshell.h"
+
+void image_subset (Image *image, int Nimage, int **Subset, int *Nsubset,
+		   SkyRegionSelection *selection, 
+		   unsigned long int tzero, double trange, int TimeSelect) 
+{
+
+  int i, j, flipped, status, InPic;
+  int *subset;
+  int N, n, npts;
+  double r, d, X, Y, x[4], y[4], Rmin, Rmax, Rmid;
+  Graphdata graph;
+  SkyRegion patch;
+
+  Rmin = Rmax = Rmid = 0;
+
+  if (selection->useDisplay) {
+    if (!GetGraphData (&graph, NULL, NULL)) {
+      gprint (GP_ERR, "region display not available\n");
+      return;
+    }
+    Rmin = graph.coords.crval1 - 182.0;
+    Rmax = graph.coords.crval1 + 182.0;
+    Rmid = 0.5*(Rmin + Rmax);
+    BuildChipMatch (image, Nimage);
+  }
+
+  if (selection->useSkyregion) {
+    double Rs, Re, Ds, De;
+    get_skyregion (&Rs, &Re, &Ds, &De);
+    patch.Rmin = Rs;
+    patch.Rmax = Re;
+    patch.Dmin = Ds;
+    patch.Dmax = De;
+    Rmin = patch.Rmin - 182.0;
+    Rmax = patch.Rmax + 182.0;
+    Rmid = 0.5*(Rmin + Rmax);
+  }
+
+  if (trange < 0) {
+    tzero = tzero + trange;
+    trange = fabs (trange);
+  }
+
+  npts = 200;
+  ALLOCATE (subset, int, npts);
+  n = N = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (TimeSelect && ((image[i].tzero < tzero) || (image[i].tzero+image[i].trate*image[i].NY > tzero + trange))) continue;
+    if (selection->useDisplay) {
+      if (!FindMosaicForImage (image, Nimage, i)) continue;
+      /* project this image to screen display coords */
+      x[0] = 0;           y[0] = 0;
+      x[1] = image[i].NX; y[1] = 0;
+      x[2] = image[i].NX; y[2] = image[i].NY;
+      x[3] = 0;           y[3] = image[i].NY;
+      InPic = flipped = FALSE;
+      for (j = 0; j < 4; j++) {
+	XY_to_RD (&r, &d, x[j], y[j], &image[i].coords);
+	/* use same side of 0,360 boundary for all corners */
+	if ((j == 0) && (r < Rmin)) flipped = TRUE; 
+	if ((j == 0) && (r > Rmax)) flipped = TRUE; 
+	while (flipped && (r < Rmid)) r+= 360.0;
+	while (flipped && (r > Rmid)) r-= 360.0;
+	status = RD_to_XY (&X, &Y, r, d, &graph.coords);
+	if (!status) continue;
+	if (X < graph.xmin) continue;
+	if (X > graph.xmax) continue;
+	if (Y < graph.ymin) continue;
+	if (Y > graph.ymax) continue;
+	goto in_region;
+	/** we miss any images which surround the region.  we are also
+	    missing the DIS images for which the corners don't touch
+	    the region, but which are needed for WRP images with
+	    corners touching the region **/
+      }
+      continue;
+    }
+    if (selection->useSkyregion) {
+      if (!FindMosaicForImage (image, Nimage, i)) continue;
+      /* project this image to screen display coords */
+      x[0] = 0;           y[0] = 0;
+      x[1] = image[i].NX; y[1] = 0;
+      x[2] = image[i].NX; y[2] = image[i].NY;
+      x[3] = 0;           y[3] = image[i].NY;
+      InPic = flipped = FALSE;
+      for (j = 0; j < 4; j++) {
+	XY_to_RD (&r, &d, x[j], y[j], &image[i].coords);
+	/* use same side of 0,360 boundary for all corners */
+	if ((j == 0) && (r < Rmin)) flipped = TRUE; 
+	if ((j == 0) && (r > Rmax)) flipped = TRUE; 
+	while (flipped && (r < Rmid)) r+= 360.0;
+	while (flipped && (r > Rmid)) r-= 360.0;
+	if (r < patch.Rmin) continue;
+	if (r > patch.Rmax) continue;
+	if (d < patch.Dmin) continue;
+	if (d > patch.Dmax) continue;
+	goto in_region;
+	/** we miss any images which surround the region.  we are also
+	    missing the DIS images for which the corners don't touch
+	    the region, but which are needed for WRP images with
+	    corners touching the region **/
+      }
+      continue;
+    }
+  in_region:
+    subset[n] = i;
+    n++;
+    if (n > npts - 1) {
+      npts += 200;
+      REALLOCATE (subset, int, npts);
+    }
+  }
+
+  REALLOCATE (subset, int, MAX (n, 1));
+  *Subset = subset;
+  *Nsubset = n;
+  return;
+}
+
+/* this routine fills the subset index with the list of selected images.
+   images may be selected on the basis of the region or on a time range 
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ImageSelection.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ImageSelection.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ImageSelection.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "dvoshell.h"
+
+/* db image table */
+static Image *image = NULL;
+static int *subset = NULL;
+static int Nimage = 0;
+static int Nsubset = 0;
+static Coords mosaic;
+
+/* load images based on parameters and region, etc */
+int SetImageSelection (int mosaicMode, SkyRegionSelection *selection) {
+
+  int TimeSelect;
+  time_t tzero, tend;
+
+  image = NULL;
+  subset = NULL;
+  
+  TimeSelect = GetTimeSelection (&tzero, &tend);
+
+  if (mosaicMode) {
+      /* mosaic defines a frame with 0,0 at the mosaic center, and 1 arcsec / pixel */
+      mosaic.crpix1 = mosaic.crpix2 = 0.0;
+      mosaic.cdelt1 = mosaic.cdelt2 = 1.0 / 3600;
+      mosaic.pc1_1  = mosaic.pc2_2  = 1.0;
+      mosaic.pc1_2  = mosaic.pc2_1  = 0.0;
+      mosaic.Npolyterms = 0;
+      strcpy (mosaic.ctype, "RA---SIN");
+  }
+
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  BuildChipMatch (image, Nimage);
+  image_subset (image, Nimage, &subset, &Nsubset, selection, tzero, (double) tend - tzero, TimeSelect);
+  sort_image_subset (image, subset, Nsubset);
+  return (TRUE);
+}
+
+/* free loaded images */
+void FreeImageSelection () {
+  if (image != NULL) free (image);
+  if (subset != NULL) free (subset);
+  image = NULL;
+  subset = NULL;
+  return;
+}
+
+Image *MatchImage (unsigned int time, short int source) { 
+
+  int m;
+
+  m = match_image_subset (image, subset, Nsubset, time, source);
+  if (m == -1) return (NULL);
+  if (!FindMosaicForImage (image, Nimage, m)) return (NULL);
+  return (&image[m]);
+}
+
+Coords *MatchMosaic (unsigned int time, short int source) { 
+
+  int m;
+
+  m = match_image_subset (image, subset, Nsubset, time, source);
+  if (m == -1) return (NULL);
+  mosaic.crval1 = image[m].coords.crval1;
+  mosaic.crval2 = image[m].coords.crval2;
+  return (&mosaic);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/LoadImages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/LoadImages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/LoadImages.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "dvoshell.h"
+
+Image *LoadImages (int *nimage) {
+
+  int status;
+  char *catdir, filename[256];
+  Image *image;
+  FITS_DB db;
+  
+  /* VarConfig ("IMAGE_CATALOG", "%s", filename); */
+
+  catdir = GetCATDIR ();
+  sprintf (filename, "%s/Images.dat", catdir);
+
+  gfits_db_init (&db);
+  db.lockstate = LCK_SOFT;
+  db.timeout   = 120.0;
+
+  if (!gfits_db_lock (&db, filename)) {
+    gprint (GP_ERR, "error opening image catalog %s (1)\n", filename);
+    return (NULL);
+  }
+
+  if (db.dbstate == LCK_EMPTY) {
+    gprint (GP_ERR, "note: image catalog is empty\n");
+    ALLOCATE (image, Image, 1);
+    *nimage = 1;
+    return (image);
+  }
+
+  status = dvo_image_load (&db, TRUE, FALSE);
+  gfits_db_close (&db);
+
+  if (!status) {
+    gprint (GP_ERR, "problem loading image database table\n");
+    return (NULL);
+  }
+
+  image = gfits_table_get_Image (&db.ftable, nimage, &db.swapped);
+  return (image);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/Makefile	(revision 16632)
@@ -0,0 +1,137 @@
+default: dvo
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SRC     =       $(HOME)/dvo
+DATA    =       $(DESTDATA)/dvo
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+LIBS1   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata 
+LIBS2   =       -ldvo -lkapa -lFITS -lohana
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(LIBS1) $(LIBS2) $(BASE_LDFLAGS)
+
+# dvo user commands and support functions ########################
+funcs = \
+$(SRC)/init.$(ARCH).o            	\
+$(SRC)/ImageOps.$(ARCH).o		\
+$(SRC)/ImageSelection.$(ARCH).o	        \
+$(SRC)/LoadImages.$(ARCH).o		\
+$(SRC)/cmpReadFile.$(ARCH).o		\
+$(SRC)/compare.$(ARCH).o                \
+$(SRC)/match_image.$(ARCH).o		\
+$(SRC)/photometry.$(ARCH).o             \
+$(SRC)/dvomisc.$(ARCH).o		\
+$(SRC)/region_list.$(ARCH).o		\
+$(SRC)/dvomisc.$(ARCH).o		\
+$(SRC)/dbBooleanCond.$(ARCH).o		\
+$(SRC)/dbCheckStack.$(ARCH).o		\
+$(SRC)/dbCmdlineFields.$(ARCH).o	\
+$(SRC)/dbExtractAverages.$(ARCH).o	\
+$(SRC)/dbExtractMeasures.$(ARCH).o	\
+$(SRC)/dbFields.$(ARCH).o		\
+$(SRC)/dbRPN.$(ARCH).o			\
+$(SRC)/dbStackMath.$(ARCH).o		\
+$(SRC)/dbStackOps.$(ARCH).o		\
+$(SRC)/dvo.$(ARCH).o
+
+cmds = \
+$(SRC)/avextract.$(ARCH).o	  	\
+$(SRC)/badimages.$(ARCH).o	  	\
+$(SRC)/calextract.$(ARCH).o      	\
+$(SRC)/calmextract.$(ARCH).o     	\
+$(SRC)/catdir.$(ARCH).o             	\
+$(SRC)/ccd.$(ARCH).o             	\
+$(SRC)/cmatch.$(ARCH).o	  	\
+$(SRC)/cmd.$(ARCH).o             	\
+$(SRC)/cmpload.$(ARCH).o	  	\
+$(SRC)/cmpread.$(ARCH).o	  	\
+$(SRC)/ddmags.$(ARCH).o	  	\
+$(SRC)/detrend.$(ARCH).o	  	\
+$(SRC)/dmagaves.$(ARCH).o	  	\
+$(SRC)/dmagmeas.$(ARCH).o	  	\
+$(SRC)/dmags.$(ARCH).o		  	\
+$(SRC)/dmt.$(ARCH).o		  	\
+$(SRC)/elixir.$(ARCH).o                \
+$(SRC)/fitcolors.$(ARCH).o             \
+$(SRC)/fitsed.$(ARCH).o                \
+$(SRC)/gcat.$(ARCH).o		  	\
+$(SRC)/gimages.$(ARCH).o	  	\
+$(SRC)/gstar.$(ARCH).o		  	\
+$(SRC)/images.$(ARCH).o	  	\
+$(SRC)/imbox.$(ARCH).o		  	\
+$(SRC)/imdata.$(ARCH).o	  	\
+$(SRC)/imdense.$(ARCH).o	  	\
+$(SRC)/imextract.$(ARCH).o	  	\
+$(SRC)/imlist.$(ARCH).o	  	\
+$(SRC)/imphot.$(ARCH).o	  	\
+$(SRC)/imrough.$(ARCH).o	  	\
+$(SRC)/imsearch.$(ARCH).o	  	\
+$(SRC)/imstats.$(ARCH).o	  	\
+$(SRC)/lcat.$(ARCH).o		  	\
+$(SRC)/lcurve.$(ARCH).o	  	\
+$(SRC)/lightcurve.$(ARCH).o	  	\
+$(SRC)/mextract.$(ARCH).o	  	\
+$(SRC)/photcodes.$(ARCH).o	  	\
+$(SRC)/pmeasure.$(ARCH).o	  	\
+$(SRC)/paverage.$(ARCH).o	  	\
+$(SRC)/procks.$(ARCH).o	  	\
+$(SRC)/skycat.$(ARCH).o	  	\
+$(SRC)/skycoverage.$(ARCH).o	  	\
+$(SRC)/skyregion.$(ARCH).o	  	\
+$(SRC)/showtile.$(ARCH).o	  	\
+$(SRC)/simage.$(ARCH).o	  	\
+$(SRC)/subpix.$(ARCH).o  \
+$(SRC)/version.$(ARCH).o
+
+libs = \
+$(DESTLIB)/libshell.a \
+$(DESTLIB)/libdata.a \
+$(DESTLIB)/libbasiccmd.a \
+$(DESTLIB)/libastrocmd.a \
+$(DESTLIB)/libdatacmd.a
+
+dvo: $(BIN)/dvo.$(ARCH)
+$(SRC)/dvo.$(ARCH).o : $(libs)
+$(BIN)/dvo.$(ARCH)   : $(funcs) $(cmds)
+
+install: $(DESTBIN)/dvo help modules
+
+help: clean-help cmd.basic.help cmd.data.help cmd.astro.help dvo.help
+
+$(funcs) $(cmds) $(libs) : $(INC)/dvoshell.h
+
+modules: dvo.modules
+
+.PHONY: dvo
+
+# deprecated functions: verify & delete
+#$(SRC)/catalog.$(ARCH).o	  	\
+#$(SRC)/abszero.$(ARCH).o \
+#$(SRC)/cals.$(ARCH).o \
+#$(SRC)/dumpmags.$(ARCH).o \
+#$(SRC)/extract.$(ARCH).o \
+#$(SRC)/gtypes.$(ARCH).o \
+#$(SRC)/photresid.$(ARCH).o \
+#$(SRC)/resid.$(ARCH).o \
+#$(SRC)/zeropts.$(ARCH).o
+#$(SRC)/objload.$(ARCH).o \ - make sure we have vect to tv
+#$(SRC)/ccdextract.$(ARCH).o \
+#$(SRC)/cmdextract.$(ARCH).o \
+#$(SRC)/dmagextract.$(ARCH).o \
+#$(SRC)/ddmagextract.$(ARCH).o \
+#$(SRC)/pcat.$(ARCH).o		  	\
+
+# future functions, not fully implemented
+#$(SRC)/detrend.$(ARCH).o \
+#$(SRC)/getxtra.$(ARCH).o \
+#$(SRC)/addxtra.$(ARCH).o \
+
+# functions that need to be updated
+#$(SRC)/gregions.$(ARCH).o \
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/addxtra.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/addxtra.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/addxtra.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "dvoshell.h"
+
+typedef struct {
+  char type[64];
+  char name[64];
+  char source[256];
+  char mode[64];
+  char value[64];
+  char range[64];
+  double R, D;
+  int averef;
+} Xtras;
+
+int addxtra (int argc, char **argv) {
+  
+  Source = (char *) NULL;
+  if (N = get_argument (argc, argv, "-source")) {
+    remove_argument (N, &argc, argv);
+    Source = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Name = (char *) NULL;
+  if (N = get_argument (argc, argv, "-name")) {
+    remove_argument (N, &argc, argv);
+    Name = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Mode = (char *) NULL;
+  if (N = get_argument (argc, argv, "-mode")) {
+    remove_argument (N, &argc, argv);
+    Mode = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Range = (char *) NULL;
+  if (N = get_argument (argc, argv, "-range")) {
+    remove_argument (N, &argc, argv);
+    Range = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: addxtra R D radius (type) (value)\n");
+    return (FALSE);
+  }
+  
+  /*
+
+  validate the input values (type, defines the needed options)
+  find catalog (based on r,d)
+  load catalog (need to load measures?)
+  find the object
+  find the xtra entry (sorted by ra/dec? sorted by averef?)
+  add new entry
+  save catalog 
+  */
+}
+
+/* 
+  addxtra R D dR type value -name (name) -source (source) -mode (mode) -range (range) 
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/aregion.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/aregion.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/aregion.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "dvoshell.h"
+# include "hstgsc.h"
+
+/* find region file which contains ra, dec */
+void aregion (GSCRegion *region, FILE *f, double ra, double dec, char *path) {
+  
+  char buffer[28800], temp[50], file[50];
+  double RA0, RA1, DEC0, DEC1;
+  int i, NBigDec, NLINES, done;
+  
+  while (ra < 0) { ra += 360.0; }
+  while (ra >= 360.0) { ra -= 360.0; }
+
+  if (dec >= 86.25) {
+    sprintf (file, "%s/n8230/pole.cpt", path);
+    region[0].DEC[0] = 86.25;
+    region[0].DEC[1] = 93.75;
+    region[0].RA[0] =  0.0;
+    region[0].RA[1] =  360.0;
+    strcpy (region[0].filename, file);
+    return;
+  }
+    
+  NBigDec = -1;
+  for (i = 0; i < 12; i++) {
+    if ((dec >= BigDecBounds[i]) && (dec < BigDecBounds[i+1])) {
+      NBigDec = i;
+      break;
+    }
+  }
+  if (NBigDec < 0) {
+    for (i = 13; i < 24; i++) {
+      if ((dec < BigDecBounds[i]) && (dec >= BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    gprint (GP_ERR, "dec out of range: %f\n", dec);
+  }
+    
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      
+  done = FALSE;
+  fread (buffer, 1, 48*NDecLines[NBigDec], f);
+  for (i = 0; !done && (i < NDecLines[NBigDec]); i++) {
+    strncpy (temp, &buffer[i*48], 48);
+    temp[49] = 0;
+    hstgsc_hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+    if (RA1 < RA0) RA1 += 360.0;
+    if ((dec >= 0) && (dec >= DEC0) && (dec < DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+    if ((dec < 0) && (dec < DEC0) && (dec >= DEC1) && (ra >= RA0) && (ra < RA1)) {
+      done = TRUE;
+    }
+  }
+
+  if (!done) {
+    gprint (GP_ERR, "error in search: %f %f\n", ra, dec);
+    exit (0);
+  }
+  temp[5] = 0;
+  sprintf (file, "%s/%s/%s.cpt", path, Dec2Sections[NBigDec],&temp[1]);
+  if (DEC0 < DEC1) {
+    region[0].DEC[0] = DEC0;
+    region[0].DEC[1] = DEC1;
+  } else {
+    region[0].DEC[0] = DEC1;
+    region[0].DEC[1] = DEC0;
+  }     
+  region[0].RA[0] = RA0;
+  region[0].RA[1] = RA1;
+  strcpy (region[0].filename, file);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/avextract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/avextract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/avextract.c	(revision 16632)
@@ -0,0 +1,182 @@
+# include "dvoshell.h"
+
+int avextract (int argc, char **argv) {
+  
+  int i, j, n, m, N, Npts, NPTS, last, Nfields, Nreturn, Ncstack, Nstack;
+  int Nsecfilt, mode, VERBOSE;
+  char **cstack, name[1024];
+  float *values;
+  void *Signal;
+
+  Catalog catalog;
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+  PhotCode *code;
+  Vector **vec;
+  dbField *fields;
+  dbStack *stack;
+
+  /* defaults */
+  skylist = NULL;
+  selection = NULL;
+  code = NULL;
+  mode = MAG_AVE;
+  fields = NULL;
+  stack = NULL;
+
+  if ((N = get_argument (argc, argv, "-h"))) goto help;
+  if ((N = get_argument (argc, argv, "--help"))) goto help;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  dvo_catalog_init (&catalog, TRUE);
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+
+  // command-line is of the form: avextract field,field, field [where (field op value)...]
+
+  // parse the fields to be extracted and returned
+  fields = dbCmdlineFields (argc, argv, DVO_TABLE_AVERAGE, &last, &Nfields);
+  if (fields == NULL) return (FALSE);
+
+  // parse the remainder of the line as a boolean math expression
+  cstack = isolate_elements (argc-last, &argv[last], &Ncstack);
+  
+  // construct the db Boolean math stack (frees cstack)
+  stack = dbRPN (Ncstack, cstack, &Nstack);
+
+  // add the skyregion limits to the where statement (or create)
+  dbAstroRegionLimits (&stack, &Nstack, selection, DVO_TABLE_AVERAGE);
+
+  // parse stack elements into fields and scalars as needed
+  Nreturn = Nfields; 
+  dbCheckStack (stack, Nstack, DVO_TABLE_AVERAGE, &fields, &Nfields);
+  // XXX handle errors
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  /* create output storage vectors */
+  ALLOCATE (values, float, Nfields);
+  ALLOCATE (vec, Vector *, Nreturn);
+  for (i = 0; i < Nreturn; i++) {
+    if (ISNUM(fields[i].name[0])) {
+      sprintf (name, "v_%s", fields[i].name);
+    } else {
+      sprintf (name, "%s", fields[i].name);
+    }
+    if ((vec[i] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) goto escape;
+  }
+
+  Npts = 0;
+  NPTS = 1;
+
+  // grab data from all selected sky regions
+  Signal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+  for (i = 0; (i < skylist[0].Nregions) && !interrupt; i++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[i];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    if (VERBOSE) gprint (GP_ERR, "trying %s (%d of %d)\n", catalog.filename, i, skylist[0].Nregions);
+      
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      gprint (GP_ERR, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    for (j = 0; (j < catalog.Naverage) && !interrupt; j++) {
+      m = catalog.average[j].offset;
+      // extract the relevant values
+      // XXX for measure values, this could be optimized for one loop over measures...
+      for (n = 0; n < Nfields; n++) {
+	values[n] = dbExtractAverages (&catalog.average[j], &catalog.secfilt[j*Nsecfilt], &catalog.measure[m], &fields[n]);
+      }
+      // test the conditional statement
+      if (!dbBooleanCond (stack, Nstack, values)) continue;
+      for (n = 0; n < Nreturn; n++) {
+	vec[n][0].elements[Npts] = values[n];
+      }
+      Npts++;
+      if (Npts >= NPTS) {
+	NPTS += 2000;
+	for (n = 0; n < Nreturn; n++) {
+	  REALLOCATE (vec[n][0].elements, float, NPTS);
+	}
+      }
+    }
+    dvo_catalog_free (&catalog);
+  }
+  signal (SIGINT, Signal);
+  interrupt = FALSE;
+  for (n = 0; n < Nreturn; n++) {
+    vec[n][0].Nelements = Npts;
+    REALLOCATE (vec[n][0].elements, float, MAX(1,Npts));
+  }
+
+  dbFreeFields (fields, Nfields);
+  dbFreeStack (stack, Nstack);
+  free (stack);
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  return (TRUE);
+
+ escape:
+  dbFreeFields (fields, Nfields);
+  dbFreeStack (stack, Nstack);
+  free (stack);
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  dvo_catalog_free (&catalog);
+  return (FALSE);
+
+ help:
+  gprint (GP_ERR, "USAGE: avextract field[,field,field...] where (expression)\n");
+
+  if ((argc > N + 1) && !strcasecmp (argv[N+1], "fields")) {
+    gprint (GP_ERR, " USAGE: avextract field[,field,field...] where (expression)\n");
+    gprint (GP_ERR, "  RA : right ascension (J2000)\n");
+    gprint (GP_ERR, "  DEC : declination \n");
+    gprint (GP_ERR, "  dRA : ra scatter \n");
+    gprint (GP_ERR, "  dDEC : dec scatter\n");
+    gprint (GP_ERR, "  uRA : proper motion in ra\n");
+    gprint (GP_ERR, "  uDEC : proper motion in dec\n");
+    gprint (GP_ERR, "  duRA : proper motion error in ra\n");
+    gprint (GP_ERR, "  duDEC : proper motion error in dec\n");
+    gprint (GP_ERR, "  PAR : parallax\n");
+    gprint (GP_ERR, "  dPAR : parallax error \n");
+    gprint (GP_ERR, "  nmeas : number of measurements\n");
+    gprint (GP_ERR, "  nmiss : number of non-detections\n");
+    gprint (GP_ERR, "  xp : positional chi-square\n");
+    gprint (GP_ERR, "  flag : object flags\n");
+    gprint (GP_ERR, "  photocode:ave : average magnitude for photcode\n");
+    gprint (GP_ERR, "  photocode:ref : reference magnitude system for photcode\n");
+    gprint (GP_ERR, "  photocode:inst : first instrumental magnitude for photcode\n");
+    gprint (GP_ERR, "  photocode:cat : first catalog magnitude for photcode\n");
+    gprint (GP_ERR, "  photocode:sys : first system magnitude for photcode\n");
+    gprint (GP_ERR, "  photocode:rel : first relative magnitude for photcode\n");
+    gprint (GP_ERR, "  photocode:cal : first calibrated magnitude for photcode \n");
+    gprint (GP_ERR, "  photcode:err : magnitude error for photcode\n");
+    gprint (GP_ERR, "  photcode:chipsq : chi-square of magnitude fit\n");
+    gprint (GP_ERR, "  type : dophot type (unused)\n");
+    gprint (GP_ERR, "  typefrac : dophot type fraction (unused)\n");
+    gprint (GP_ERR, "  photcode:ncode : number of measurements in photcode \n");
+    gprint (GP_ERR, "  photcode:nphot : number of measurements used for photcode average\n");
+    return (FALSE);
+  }
+  gprint (GP_ERR, " avextract --help fields : for a complete listing of allowed fields\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/badimages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/badimages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/badimages.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "dvoshell.h"
+
+static int badim_int = FALSE;
+void badim_escape () {
+  badim_int = TRUE;
+}
+
+int badimages (int argc, char **argv) {
+  
+  int i, Nimage, entry, First, Cross;
+  float *ptr;
+  double nominal, big, small, value;
+  Image *image;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: badimages entry value\n");
+    gprint (GP_ERR, "   OR: badimages -image N\n");
+    return (FALSE);
+  }
+  
+  image = LoadImages (&Nimage);
+
+  Cross = FALSE;
+  First = FALSE;
+  nominal = 1;
+  if (!strcmp (argv[1], "-image")) {
+    First = TRUE;
+    entry = atof(argv[2]);
+  } else {
+    entry = atof(argv[1]);
+    nominal = atof(argv[2]);
+    if (!strcasecmp (argv[1], "x")) {
+      Cross = TRUE;
+    }
+  }
+  
+  if (First) {
+    ptr = &image[entry].coords.crpix1;
+    for (i = 0; i < 22; i++) {
+      gprint (GP_LOG, "%2d: %g\n", i, ptr[i]);
+    }
+    value = image[entry].coords.pc1_1*image[entry].coords.pc2_2 + image[entry].coords.pc1_2*image[entry].coords.pc2_1;
+    gprint (GP_LOG, " x: %g\n", value);
+    return (TRUE);
+  }
+  
+  big = nominal * 1.05;
+  small = nominal / 1.05;
+  if (big < small) {
+    double tmp;
+    tmp = big; big = small; small = tmp;
+  }
+  
+  badim_int = FALSE;
+  if (Cross) {
+    for (i = 0; (i < Nimage) && !badim_int; i++) {
+      value = image[i].coords.pc1_1*image[i].coords.pc2_2 + image[i].coords.pc1_2*image[i].coords.pc2_1;
+      if ((value > big) || (value < small)) {
+	gprint (GP_LOG, "%5d %s: %d %g\n", i, image[i].name, image[i].tzero, value);
+      }
+    }
+  } else {
+    for (i = 0; (i < Nimage) && !badim_int; i++) {
+      ptr = &image[i].coords.crpix1;
+      if ((ptr[entry] > big) || (ptr[entry] < small)) {
+	gprint (GP_LOG, "%5d %s: %d %g\n", i, image[i].name, image[i].tzero, ptr[entry]);
+      }
+    }
+  }
+  
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/calextract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/calextract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/calextract.c	(revision 16632)
@@ -0,0 +1,141 @@
+# include "dvoshell.h"
+
+enum {Nd, Nm, NC, NR, ND, Np, Nc, Nt, Nx, Nd1, Nd2, NVEC};
+
+int calextract (int argc, char **argv) {
+  
+  int i, N, Nr, mode[2];
+  int Nsecfilt, NSTAR;
+
+  PhotCode *code[2];
+  Catalog catalog;
+  Vector **vec;
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+
+  /* these need to be freed in the end */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  skylist = NULL;
+  selection = NULL;
+  vec = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) return (FALSE);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* command line arguments */
+  SetSelectionParam (0);
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+  if (!SetPhotSelections (&argc, argv, 2)) goto usage;
+
+  if (argc != 4) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  /* code.type must be PHOT_REF */
+
+  /* one unique value per star */
+  N = 0;
+  NSTAR = 1;
+  ALLOCATE (vec, Vector *, NVEC);
+  if ((vec[Nd] 	= SelectVector ("cal:dmag",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nm] 	= SelectVector ("cal:mag",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NC] 	= SelectVector ("cal:color",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NR] 	= SelectVector ("cal:ra",       ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[ND] 	= SelectVector ("cal:dec",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Np] 	= SelectVector ("cal:nphot",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nc] 	= SelectVector ("cal:ncode",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  // if ((vec[Nt] 	= SelectVector ("cal:ncrit",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nx] 	= SelectVector ("cal:chisq",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd1] = SelectVector ("cal:dm1",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd2] = SelectVector ("cal:dm2",      ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  for (Nr = 0; Nr < skylist[0].Nregions; Nr++) {
+    if (Nr && !(Nr % 500)) { gprint (GP_ERR, "."); }
+
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[Nr];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    # if (0)
+    /* extract values, assign to vectors */
+    for (i = 0; i < catalog.Naverage; i++) {
+      if (i && !(i % 10000)) { gprint (GP_ERR, ","); }
+      m = catalog.average[i].offset;
+
+      if (code[0][0].c1 && code[0][0].c2 && !PhotColor (&catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], code[0][0].c1, code[0][0].c2, &color)) continue;
+
+      /* find data for filter 2 (PHOT_REF) */
+      M2 = NAN;
+      dM2 = NAN;
+      for (j = 0; j < catalog.average[i].Nm; j++) {
+	if (catalog.measure[m+j].photcode != code[1][0].code) continue;
+	M2 = PhotCat  (&catalog.measure[m+j]);
+	dM2 = catalog.measure[m+j].dM;
+      }	
+      if (isnan(M2)) continue;
+
+      /* find data for filter 1 */
+      M1 = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], AVE_MAG);
+      if (isnan(M1)) continue;
+
+      vec[Nd ][0].elements[N] = M1 - M2;
+      vec[Nm ][0].elements[N] = M2;
+      vec[NC ][0].elements[N] = color;
+      vec[NR ][0].elements[N] = catalog.average[i].R;
+      vec[ND ][0].elements[N] = catalog.average[i].D;
+      vec[Nd1][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], AVE_dMAG);
+      vec[Nd2][0].elements[N] = dM2;
+      vec[Nx ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], AVE_Xm);
+      vec[Nc ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], AVE_NCODE);
+      vec[Np ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], AVE_NPHOT);
+      // vec[Nt ][0].elements[N] = ExtractAverages (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], AVE_NCRIT);
+      N ++;
+      if (N == NSTAR) {
+	NSTAR += 100;
+	for (j = 0; j < NVEC; j++) {
+	  REALLOCATE (vec[j][0].elements, float, NSTAR);
+	}
+      }
+    }
+    # endif
+    dvo_catalog_free (&catalog);
+  }
+
+  for (i = 0; i < NVEC; i++) {
+    vec[i][0].Nelements = N;
+  }
+
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  return (TRUE);
+  
+usage:
+  gprint (GP_ERR, "USAGE: calextract F - F\n");
+  return (FALSE);
+
+escape:
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  for (i = 0; i < NVEC; i++) {
+    DeleteVector (vec[i]);
+  }
+  free (vec);
+
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/calmextract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/calmextract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/calmextract.c	(revision 16632)
@@ -0,0 +1,186 @@
+# include "dvoshell.h"
+
+enum {Nd, Nm1, Nm2, Nc, Ns, Nt, Nz, NR, ND, Nxc, Nyc, Nxm, Nym, NT, NP, Nd1, Nd2, NVEC};
+int ConcatMeasures (Vector *vec, PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int param, int Nin);
+
+int calmextract (int argc, char **argv) {
+  
+  int i, k, N, Nr, mode[2];
+  int NSTAR, Nstar, Nsecfilt;
+
+  Catalog catalog;
+  PhotCode *code[2];
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+  Vector **vec;
+
+  /* these need to be freed in the end */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  skylist = NULL;
+  selection = NULL;
+  vec = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* command line arguments */
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+  if (!SetPhotSelections (&argc, argv, 2)) goto usage;
+
+  /* interpret required command-line arguments: calmextract F1 - F2 */
+  if (argc != 4) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  if (!TestPhotSelections (&code[0], &mode[0], MEAS_ZERO)) goto escape;
+
+  /* returned vectors are dmag, mag, color, time, airmass, ra, dec, x, y, exptime */
+  N = 0;
+  Nstar = 0;
+  NSTAR = 100;
+  ALLOCATE (vec, Vector *, NVEC);
+  if ((vec[Nd ] = SelectVector ("cal:dmag",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nm1] = SelectVector ("cal:mag1",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nm2] = SelectVector ("cal:mag2",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nc ] = SelectVector ("cal:color",    ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Ns ] = SelectVector ("cal:star",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nt ] = SelectVector ("cal:time",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nz ] = SelectVector ("cal:airmass",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NR ] = SelectVector ("cal:ra",       ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[ND ] = SelectVector ("cal:dec",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nxc] = SelectVector ("cal:xccd",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nyc] = SelectVector ("cal:yccd",     ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nxm] = SelectVector ("cal:xmosaic",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nym] = SelectVector ("cal:ymosaic",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NT ] = SelectVector ("cal:exptime",  ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[NP ] = SelectVector ("cal:photcode", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd1] = SelectVector ("cal:dm1",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((vec[Nd2] = SelectVector ("cal:dm2",      ANYVECTOR, TRUE)) == NULL) goto escape;
+  for (k = 0; k < NVEC; k++) {
+    REALLOCATE (vec[k][0].elements, float, NSTAR);
+    vec[k][0].Nelements = 0;
+  }
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+  if (!SetImageSelection (TRUE, selection)) goto escape;
+
+  for (Nr = 0; Nr < skylist[0].Nregions; Nr++) {
+    if (Nr && !(Nr % 500)) { gprint (GP_ERR, "."); }
+
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[Nr];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    # if (0)
+    /* extract values, assign to vectors */
+    for (i = 0; i < catalog.Naverage; i++) {
+      m = catalog.average[i].offset;
+
+      /* PRI/SEC must have data for color term */
+      if (code[0][0].c1 && code[0][0].c2 && !PhotColor (&catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], code[0][0].c1, code[0][0].c2, &color)) continue;
+
+      /* find data for filter 2 (REF) */
+      M2 = NAN;
+      dM2 = NAN;
+      for (j = 0; j < catalog.average[i].Nm; j++) {
+	if (catalog.measure[m+j].photcode != code[1][0].code) continue;
+	M2 = PhotCat  (&catalog.measure[m+j]); 
+	dM2 = catalog.measure[m+j].dM;
+      }	
+      if (isnan(M2)) continue;
+      
+      /* find data for filter 1 */
+      M1 = ExtractMeasures (code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N1, MEAS_MAG);
+      if (N1 == 0) goto skip;
+
+      /* extend storage vectors to take new data, if needed */
+      if (N + N1 >= NSTAR) {
+	NSTAR += N1 + 100;
+	for (k = 0; k < NVEC; k++) {
+	  REALLOCATE (vec[k][0].elements, float, NSTAR);
+	}
+      }
+
+      ConcatMeasures (vec[Nt ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_TIME); 
+      ConcatMeasures (vec[Nz ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_AIRMASS); 
+      ConcatMeasures (vec[NT ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_EXPTIME); 
+      ConcatMeasures (vec[NP ], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_PHOTCODE); 
+      // ConcatMeasures (vec[Nd1], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_dMAG); 
+      ConcatMeasures (vec[Nxc], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_XCCD); 
+      ConcatMeasures (vec[Nyc], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_YCCD); 
+      ConcatMeasures (vec[Nxm], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_XMOSAIC); 
+      ConcatMeasures (vec[Nym], code[0], mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], N1, MEAS_YMOSAIC); 
+
+      for (j = 0; j < N1; j++, N++) {
+	vec[Nd ][0].elements[N] = M1[j] - M2;
+	vec[Nm1][0].elements[N] = M1[j];
+	vec[Nm2][0].elements[N] = M2;
+	vec[Nd2][0].elements[N] = dM2;
+	vec[Nc ][0].elements[N] = color;
+	vec[Ns ][0].elements[N] = Nstar;
+	vec[NR ][0].elements[N] = catalog.average[i].R;
+	vec[ND ][0].elements[N] = catalog.average[i].D;
+      }
+      Nstar ++; 
+    skip:
+      if (M1 != NULL) free (M1);
+    }
+    # endif
+    dvo_catalog_free (&catalog);
+  }
+
+  for (i = 0; i < NVEC; i++) {
+    vec[i][0].Nelements = N;
+  }
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  FreeImageSelection ();
+  return (TRUE);
+  
+usage:
+  gprint (GP_ERR, "USAGE: dmags F - F : measure.param\n");
+  return (FALSE);
+
+escape:
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  FreeImageSelection ();
+  for (i = 0; i < NVEC; i++) {
+    DeleteVector (vec[i]);
+  }
+  free (vec);
+  return (FALSE);
+}
+
+int ConcatMeasures (Vector *vec, PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int Nin, int param) {
+
+  int i, Ns, N;
+  double *value;
+
+  value = ExtractMeasures (code, mode, average, secfilt, measure, &N, param); 
+  if (N != Nin) {
+    gprint (GP_ERR, "error!\n");
+    return (FALSE);
+  }
+
+  Ns = vec[0].Nelements;
+  for (i = 0; i < N; i++) {
+    vec[0].elements[Ns+i] = value[i];
+  }
+  vec[0].Nelements = Ns + N;
+
+  free (value);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/catalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/catalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/catalog.c	(revision 16632)
@@ -0,0 +1,407 @@
+# include "dvoshell.h"
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+# define MAGSCALE 0
+# define NUMSCALE 1
+# define MISSCALE 2
+
+// XXX EAM : should this function be dropped? 
+int catlog (int argc, char **argv) {
+  
+  FILE *f;
+  Catalog catalog;
+  Vector Xvec, Yvec, Zvec;
+  int i, N, Nm, Nn, NN, Nbytes, nbytes, Bytes_Star;
+  int Ar, Ad, Am, InRegion, GSC, ASCII, DVO, FIXED;
+  char filename[128];
+  double Mz, Mr, Nz, Nr;
+  int clip, mode, IDclip, IDchoice, LimExclude;
+  RegionFile *regions;
+  int j, Nregions;
+  double Radius, Rmin, Rmax;
+  Graphdata graphmode;
+  double epoch, current_epoch;
+  char gscdir[256], catdir[256];
+  int Ngraph;
+
+  if (!GetGraph (&graphmode, NULL, NULL)) return (FALSE);
+
+  VarConfig ("GSCDIR", "%s", gscdir);
+  VarConfig ("CATDIR", "%s", catdir);
+
+  Mz = 17.0;
+  Mr = -5.0;
+  mode = MAGSCALE;
+  clip = FALSE;
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  regions = (RegionFile *) NULL;
+  f = (FILE *) NULL;
+  Nz = Nr = Am = Ar = Ad = 0;
+  /* either MagScale or NumScale, whichever is first is scale */
+  Nm = get_argument (argc, argv, "-m");
+  Nn = get_argument (argc, argv, "+n");
+  NN = get_argument (argc, argv, "-n");
+  if (NN && Nn) {
+    gprint (GP_ERR, "can't mix meas and miss scaling\n");
+    return (FALSE);
+  }
+ 
+  if (Nm)
+    mode = MAGSCALE;
+  if (Nn)
+    mode = NUMSCALE;
+  if (NN)
+    mode = MISSCALE;
+    
+  if (Nm && Nn) {
+    clip = TRUE;
+    if (Nm < Nn) 
+      mode = MAGSCALE;
+    else 
+      mode = NUMSCALE;
+  }
+  if (Nm && NN) {
+    clip = TRUE;
+    if (Nm < NN) 
+      mode = MAGSCALE;
+    else 
+      mode = MISSCALE;
+  }
+   
+  current_epoch = 2000.0;
+  epoch = 2000.0;
+  if ((N = get_argument (argc, argv, "-e"))) {
+    remove_argument (N, &argc, argv);
+    epoch  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  IDchoice = 0;
+  IDclip = FALSE;
+  if ((N = get_argument (argc, argv, "-ID"))) {
+    remove_argument (N, &argc, argv);
+    IDchoice  = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    IDclip = TRUE;
+  }
+
+  LimExclude = FALSE;
+  if ((N = get_argument (argc, argv, "-x"))) {
+    remove_argument (N, &argc, argv);
+    LimExclude = TRUE;
+  }
+
+  if ((Nm = get_argument (argc, argv, "-m"))) {
+    remove_argument (Nm, &argc, argv);
+    Mr  = atof(argv[Nm]);
+    remove_argument (Nm, &argc, argv);
+    Mz = atof(argv[Nm]);
+    Mr = Mr - Mz;
+    remove_argument (Nm, &argc, argv);
+  }
+
+  if ((Nn = get_argument (argc, argv, "+n"))) {
+    remove_argument (Nn, &argc, argv);
+    Nz  = atof(argv[Nn]);
+    remove_argument (Nn, &argc, argv);
+    Nr = atof(argv[Nn]) - Nz;
+    remove_argument (Nn, &argc, argv);
+  }
+
+  if ((Nn = get_argument (argc, argv, "-n"))) {
+    remove_argument (Nn, &argc, argv);
+    Nz  = atof(argv[Nn]);
+    remove_argument (Nn, &argc, argv);
+    Nr = atof(argv[Nn]) - Nz;
+    remove_argument (Nn, &argc, argv);
+  }
+
+  InRegion = FALSE;
+  if ((N = get_argument (argc, argv, "-all"))) {
+    remove_argument (N, &argc, argv);
+    InRegion = TRUE;
+  }
+
+  Bytes_Star = 0;
+  ASCII = FALSE;
+  DVO = TRUE;
+  GSC = FALSE;
+  FIXED = FALSE;
+  if ((N = get_argument (argc, argv, "-g"))) {
+    remove_argument (N, &argc, argv);
+    GSC = TRUE;
+    ASCII = FALSE;
+    DVO = FALSE;
+  }
+
+  if ((N = get_argument (argc, argv, "-a"))) {
+    remove_argument (N, &argc, argv);
+    ASCII = TRUE;
+    GSC = FALSE;
+    DVO = FALSE;
+    Ar = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Ad = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Am = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    if ((N = get_argument (argc, argv, "-f"))) {
+      remove_argument (N, &argc, argv);
+      FIXED = TRUE;
+      ASCII = FALSE;
+      Bytes_Star = atof(argv[N]);
+      remove_argument (N, &argc, argv);
+    }
+  }
+
+  
+  if ((InRegion || (argc != 2)) && (!InRegion || (argc != 1))) {
+    gprint (GP_ERR, "USAGE: catalog (filename / -all) [-m M M] [-n N N] [-g] [-a RA DEC MAG] \n");
+    return (FALSE);
+  }
+  
+  if (InRegion) {
+    Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+    regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+  } else {
+    Nregions = 1;
+  }
+  
+  for (j = 0; j < Nregions; j++) {
+    catalog.average = 0;
+    
+    /* Load in data from an ASCII file list of ra, dec, mag */
+    if (ASCII) {
+      char *tbuffer;
+      int nstar, NSTARS;
+      double R, D, M;
+      
+      f = fopen (argv[1], "r");
+      if (f == (FILE *) NULL) {
+	gprint (GP_ERR, "ERROR: can't open catalog file: %s\n", argv[1]);
+	return (FALSE);
+      }
+      
+      nstar = 0;
+      NSTARS = DNSTARS;
+      ALLOCATE (tbuffer, char, 1024);
+      ALLOCATE (catalog.average, Average, NSTARS);
+      while (scan_line (f, tbuffer) != EOF) {
+	dparse (&R, Ar, tbuffer);
+	dparse (&D, Ad, tbuffer);
+	dparse (&M, Am, tbuffer);
+	catalog.average[nstar].R = R;
+	catalog.average[nstar].D = D;
+	catalog.average[nstar].M = M;
+	nstar++;
+	if (nstar == NSTARS - 1) {
+	  NSTARS += DNSTARS;
+	  REALLOCATE (catalog.average, Average, NSTARS);
+	}
+      }
+      fclose (f);
+      free (tbuffer);
+      REALLOCATE (catalog.average, Average, nstar);
+      catalog.Naverage = nstar;
+
+      if (epoch != current_epoch) {
+	cprecess (catalog.average, catalog.Naverage, epoch, current_epoch);
+      }
+
+    }
+    
+    /* Load in data from an ASCII file list of ra, dec, mag */
+    if (FIXED) {
+      char *tbuffer;
+      int nstar, NSTARS;
+      double R, D, M;
+      
+      f = fopen (argv[1], "r");
+      if (f == (FILE *) NULL) {
+	gprint (GP_ERR, "ERROR: can't open catalog file: %s\n", argv[1]);
+	return (FALSE);
+      }
+      
+      nstar = 0;
+      NSTARS = DNSTARS;
+      ALLOCATE (tbuffer, char, (BLOCK*Bytes_Star));
+      ALLOCATE (catalog.average, Average, NSTARS);
+      Nbytes = BLOCK*Bytes_Star;
+      while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+	for (i = 0; i < nbytes / Bytes_Star; i++) {
+	  dparse (&R, Ar, &tbuffer[i*Bytes_Star]);
+	  dparse (&D, Ad, &tbuffer[i*Bytes_Star]);
+	  dparse (&M, Am, &tbuffer[i*Bytes_Star]);
+	  catalog.average[nstar].R = R;
+	  catalog.average[nstar].D = D;
+	  catalog.average[nstar].M = M;
+	  nstar++;
+	  if (nstar == NSTARS - 1) {
+	    NSTARS += DNSTARS;
+	    REALLOCATE (catalog.average, Average, NSTARS);
+	  }
+	}
+      }
+      fclose (f);
+      free (tbuffer);
+      REALLOCATE (catalog.average, Average, nstar);
+      catalog.Naverage = nstar;
+
+      if (epoch != current_epoch) {
+	cprecess (catalog.average, catalog.Naverage, epoch, current_epoch);
+      }
+
+    }
+    
+    /* load data from the GSC files */
+    if (GSC) {
+      char *tbuffer;
+      int nstar, NSTARS;
+      double R, D, M;
+      
+      if (InRegion) {
+	sprintf (filename, "%s/%s", gscdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s", gscdir, argv[1]);
+      }
+      
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	gprint (GP_ERR, "no stars in %s, skipping\n", filename);
+	continue;
+	/* return (FALSE); */
+      }
+      
+      nstar = 0;
+      NSTARS = DNSTARS;
+      ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+      ALLOCATE (catalog.average, Average, NSTARS);
+      Nbytes = BLOCK*BYTES_STAR;
+      while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+	for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	  dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+	  dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+	  dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+	  catalog.average[nstar].R = R;
+	  catalog.average[nstar].D = D;
+	  catalog.average[nstar].M = M;
+	  nstar++;
+	  if (nstar == NSTARS - 1) {
+	    NSTARS += DNSTARS;
+	    REALLOCATE (catalog.average, Average, NSTARS);
+	  }
+	}
+      }
+      fclose (f);
+      free (tbuffer);
+      REALLOCATE (catalog.average, Average, nstar);
+      catalog.Naverage = nstar;
+    }
+  
+    /* load data from the photometry database files */
+    if (DVO) {
+      
+      if (InRegion) {
+	sprintf (filename, "%s/%s", catdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s", catdir, argv[1]);
+      }
+      
+      /* lock, load, unlock catalog */
+      catalog.filename = filename;
+      catalog.catflags = LOAD_AVES;
+
+      // an error exit status here is a significant error
+      if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+	  fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+	  exit (2);
+      }
+      dvo_catalog_unlock (&catalog);
+    }
+    
+    /* data has been loaded, get ready to plot it */
+    Xvec.Nelements = catalog.Naverage;
+    Yvec.Nelements = catalog.Naverage;
+    Zvec.Nelements = catalog.Naverage;
+    ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+    ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+    ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+    /* project stars to screen display coords */
+    Xvec.Nelements = 0;
+    switch (mode) {
+    case (MAGSCALE):
+      for (N = i = 0; i < catalog.Naverage; i++) {
+	if (clip && ((catalog.average[i].Nm < Nz) || (catalog.average[i].Nm > Nr+Nz))) 
+	  continue;
+	if (IDclip && (catalog.average[i].code != IDchoice))
+	  continue;
+	Zvec.elements[N] = MIN (1.0, MAX (0.01, (catalog.average[i].M - Mz) / Mr));
+	if (LimExclude && (Zvec.elements[N] > 0.99)) continue;
+	if (Zvec.elements[N] < 0.011) continue;
+	while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+	while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+	if (fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], catalog.average[i].R, catalog.average[i].D, &graphmode.coords)) N ++;
+      }
+      break;
+    case (NUMSCALE):
+      for (N = i = 0; i < catalog.Naverage; i++) {
+	if (clip && ((catalog.average[i].M > Mz) || (catalog.average[i].M < Mr+Mz))) 
+	  continue;
+	if (IDclip && (catalog.average[i].code != IDchoice))
+	  continue;
+	Zvec.elements[N] = MIN (1.0, MAX (0.01, (catalog.average[i].Nm - Nz) / Nr));
+	if (LimExclude && (Zvec.elements[N] == 1.0)) continue;
+	if (Zvec.elements[N] == 0.01) 
+	  continue;
+	while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+	while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+	if (fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], catalog.average[i].R, catalog.average[i].D, &graphmode.coords)) N++;
+      }
+      break;
+    case (MISSCALE):
+      for (N = i = 0; i < catalog.Naverage; i++) {
+	if (clip && ((catalog.average[i].M > Mz) || (catalog.average[i].M < Mr+Mz))) 
+	  continue;
+	if (IDclip && (catalog.average[i].code != IDchoice))
+	  continue;
+	Zvec.elements[N] = MIN (1.0, MAX (0.01, (catalog.average[i].Nn - Nz) / Nr));
+	if (LimExclude && (Zvec.elements[N] == 1.0)) continue;
+	if (Zvec.elements[N] == 0.01) 
+	  continue;
+	while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+	while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+	if (fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], catalog.average[i].R, catalog.average[i].D, &graphmode.coords)) N++;
+      }
+      break;
+    }
+
+    Zvec.Nelements = Yvec.Nelements = Xvec.Nelements = N;
+    REALLOCATE (Xvec.elements, float, MAX (Xvec.Nelements, 1));
+    REALLOCATE (Yvec.elements, float, MAX (Yvec.Nelements, 1));
+    REALLOCATE (Zvec.elements, float, MAX (Zvec.Nelements, 1));
+    
+    graphmode.style = 2; /* set style to points */
+    graphmode.size = -1; /* point size determined by Zvec */
+    graphmode.etype = 0; /* no errorbars */
+    PrepPlotting (N, &graphmode);
+    
+    PlotVector (N, Xvec.elements, "x");
+    PlotVector (N, Yvec.elements, "y");
+    PlotVector (N, Zvec.elements, "z");
+    
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+
+    if (catalog.average != 0) free (catalog.average);
+
+  }
+  return (TRUE);
+
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/catdir.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/catdir.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/catdir.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "dvoshell.h"
+
+int catdir_define (int argc, char **argv) {
+  
+  char *current;
+  int status, N, VERBOSE;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: catdir (name)\n");
+    gprint (GP_ERR, "       (name) may be a path or 'default'\n");
+    current = GetCATDIR ();
+    if (current == NULL) {
+      gprint (GP_ERR, "catdir not defined\n");
+    } else {
+      gprint (GP_ERR, "current: %s\n", current);
+    }
+    return (FALSE);
+  }
+
+  if (!strcasecmp (argv[1], "default")) {
+    status = SetCATDIR (NULL, VERBOSE);
+  } else {
+    status = SetCATDIR (argv[1], VERBOSE);
+  }
+
+  if (!status) {
+    gprint (GP_ERR, "invalid / undefined CATDIR\n");
+    return (FALSE);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ccd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ccd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ccd.c	(revision 16632)
@@ -0,0 +1,126 @@
+# include "dvoshell.h"
+
+int ccd (int argc, char **argv) {
+  
+  double *M1, *M2;
+  int i, m, k, Npts, NPTS, N;
+  int N1, N2, i1, i2, mode[4];
+  int Nsecfilt, KeepNulls;
+
+  Catalog catalog;
+  PhotCode *code[4];
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+  Vector *xvec, *yvec;
+
+  /* defaults */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  skylist = NULL;
+  selection = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+  if (!SetPhotSelections (&argc, argv, 4)) goto usage;
+
+  KeepNulls = FALSE;
+  if ((N = get_argument (argc, argv, "-nulls"))) {
+    KeepNulls = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* interpret command-line options */
+  if (argc != 8) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (strcmp (argv[6], "-")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[7], &code[3], &mode[3])) return (FALSE);
+  if (!TestPhotSelections (&code[0], &mode[0], MEAS_ZERO)) goto escape;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (k = 0; k < skylist[0].Nregions; k++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[k];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M2 = NULL;
+      m = catalog.average[i].offset;
+
+      SetSelectionParam (0);
+      M1 = ExtractDMag (&code[0], &mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      SetSelectionParam (2);
+      M2 = ExtractDMag (&code[2], &mode[2], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N2);
+      if (N2 == 0) {
+	if (KeepNulls) {
+	  ALLOCATE (M2, double, 1);
+	  N2 = 1;
+	  M2[0] = NAN;
+	} else {
+	  goto skip;
+	}
+      }
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i2 = 0; i2 < N2; i2++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M2[i2];
+	  Npts++;
+	  if (Npts >= NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M2 != NULL) free (M2);
+    }
+    dvo_catalog_free (&catalog);
+  }
+
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: ccd F - F : F - F\n");
+  return (FALSE);
+
+escape:
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  dvo_catalog_free (&catalog);
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmatch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmatch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmatch.c	(revision 16632)
@@ -0,0 +1,82 @@
+# include "dvoshell.h"
+
+int cmatch (int argc, char **argv) {
+  
+  Catalog catalog1, catalog2;
+  char filename[128];
+  double radius;
+  Vector *rvec, *dvec, *mvec, *drvec, *ddvec, *dmvec;
+
+  if (argc != 9) {
+    gprint (GP_ERR, "USAGE: cmatch file radius (RA) (DEC) (Mag) (dRA) (dDEC) (dMag)\n");
+    gprint (GP_ERR, "       match a set of object coordinates with a DVO db table\n");
+    return (FALSE);
+  }
+
+  /*** this function is not well-defined.  re-assess it and re-code it ***/
+  gprint (GP_ERR, "disabled for now\n");
+  return (FALSE);
+
+  radius = atof (argv[2]);
+
+  if ((rvec  = SelectVector (argv[3], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dvec  = SelectVector (argv[4], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((mvec  = SelectVector (argv[5], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((drvec = SelectVector (argv[6], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((ddvec = SelectVector (argv[7], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dmvec = SelectVector (argv[8], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* load data from the photometry database file */
+  catalog1.filename = filename;
+  catalog1.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog1, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog1.filename);
+      exit (2);
+  }
+  dvo_catalog_unlock (&catalog1);
+  gprint (GP_ERR, "read %d stars from phot catalog file %s\n", catalog1.Naverage, filename);
+
+  /* this is for loading from a text file, presumably hstgsc or usno
+     replace this with references to the ra and dec vectors?
+  nstar = 0;
+  NSTARS = DNSTARS;
+  ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+  ALLOCATE (catalog2.average, Average, NSTARS);
+  Nbytes = BLOCK*BYTES_STAR;
+  while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+    for (i = 0; i < nbytes / BYTES_STAR; i++) {
+      dparse (&R, 1, &tbuffer[i*BYTES_STAR]);
+      dparse (&D, 2, &tbuffer[i*BYTES_STAR]);
+      dparse (&M, 3, &tbuffer[i*BYTES_STAR]);
+      catalog2.average[nstar].R = R;
+      catalog2.average[nstar].D = D;
+      catalog2.average[nstar].M = M * 1000.0;
+      nstar++;
+      if (nstar == NSTARS - 1) {
+	NSTARS += DNSTARS;
+	REALLOCATE (catalog2.average, Average, NSTARS);
+      }
+    }
+  }
+  free (tbuffer);
+  REALLOCATE (catalog2.average, Average, MAX (nstar, 1));
+  catalog2.Naverage = nstar;
+  fclose (f);
+  */
+
+  /* sort data in order of RA */
+  sortave (catalog1.average, catalog1.Naverage);
+  sortave (catalog2.average, catalog2.Naverage);
+
+  /* data has been loaded, use gcompare algorithm to match */
+  compare (&catalog1, &catalog2, rvec, dvec, mvec, drvec, ddvec, dmvec, radius);
+
+  dvo_catalog_free (&catalog1);
+  free (catalog2.average);
+
+  return (TRUE);
+
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmd.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmd.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmd.c	(revision 16632)
@@ -0,0 +1,124 @@
+# include "dvoshell.h"
+
+int cmd (int argc, char **argv) { /* really need to think about upper limits & how to represent them */
+  
+  double *M1, *M3;
+  int i, j, m, i1, i3, N1, N3, N;
+  int Npts, NPTS, mode[3];
+  int Nsecfilt, KeepNulls;
+
+  PhotCode *code[3];
+  Catalog catalog;
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+  Vector *xvec, *yvec;
+
+  /* defaults */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  skylist = NULL;
+  selection = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+  if (!SetPhotSelections (&argc, argv, 3)) goto usage;
+
+  KeepNulls = FALSE;
+  if ((N = get_argument (argc, argv, "-nulls"))) {
+    KeepNulls = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* interpret command-line options */
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) return (FALSE);
+  if (!TestPhotSelections (&code[0], &mode[0], MEAS_ZERO)) goto escape;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (j = 0; j < skylist[0].Nregions; j++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[j];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+    
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M3 = NULL;
+      m = catalog.average[i].offset;
+
+      SetSelectionParam (0);
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      SetSelectionParam (2);
+      M3 = ExtractMagnitudes (code[2], mode[2], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N3);
+      if (N3 == 0) {
+	if (KeepNulls) {
+	  ALLOCATE (M3, double, 1);
+	  N3 = 1;
+	  M3[0] = NAN;
+	} else {
+	  goto skip;
+	}
+      }
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i3 = 0; i3 < N3; i3++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M3[i3];
+	  Npts++;
+	  if (Npts >= NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M3 != NULL) free (M3);
+    }
+    dvo_catalog_free (&catalog);
+  }
+
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: cmd F - F : F\n");
+  return (FALSE);
+
+escape:
+  dvo_catalog_free (&catalog);
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  return (FALSE);
+}
+    
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpReadFile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpReadFile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpReadFile.c	(revision 16632)
@@ -0,0 +1,125 @@
+# include "dvoshell.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+CMPstars *cmpReadFits (FILE *f, int *nstars) {
+
+  int i, Nstars;
+  Header theader;
+  FTable table;
+  CMPstars *stars;
+  SMPData *smpdata;
+
+  /* if no stars, no table */
+  if (*nstars == 0) return (NULL);
+
+  /* init & load in table data */
+  table.header   = &theader;
+  if (!gfits_fread_ftable (f, &table, "SMPFILE")) goto escape;
+
+  smpdata = gfits_table_get_SMPData (&table, &Nstars, NULL);
+
+  ALLOCATE (stars, CMPstars, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    stars[i].X      = smpdata[i].X;
+    stars[i].Y      = smpdata[i].Y;
+    stars[i].M      = smpdata[i].M;
+    stars[i].dM     = smpdata[i].dM;
+    stars[i].dophot = smpdata[i].dophot;
+
+    stars[i].Mgal   = smpdata[i].M;
+    stars[i].Map    = smpdata[i].dM;
+    stars[i].fx     = smpdata[i].fx;
+    stars[i].fy     = smpdata[i].fy;
+    stars[i].df     = smpdata[i].df;
+  }    
+  *nstars = Nstars;
+  return (stars);
+
+escape:
+  gprint (GP_ERR, "error reading file\n");
+  *nstars = 0;
+  return (NULL);
+}
+
+CMPstars *cmpReadText (FILE *f, int *nstars) {
+
+  int j, N, Nextra, Ninstar, Nskip, Nbytes, nbytes;
+  int done;
+  char *buffer, *c, *c2;
+  double tmp;
+  CMPstars *stars;
+  
+  /* load in stars by blocks of 1000 */
+  N = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+
+  ALLOCATE (stars, CMPstars, *nstars);
+
+  while (N < *nstars) {
+    /* load next data block */
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = fread (&buffer[Nextra], 1, Nbytes, f);
+    if (nbytes == 0) {
+      *nstars = N;
+      return (stars);
+    }
+    nbytes += Nextra;
+
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	/* if (VERBOSE) gprint (GP_ERR, "deleted %d extra return chars\n", Nskip); */
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+	/* if (VERBOSE) gprint (GP_ERR, "deleted line, %d extra chars\n", Nskip); */
+      } else {
+	c = c2;
+      }
+    }
+
+    /* extract data for stars */
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (j = 0; (j < Ninstar) && (N < *nstars); j++, N++) {
+      dparse (&stars[N].X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].M,  3, &buffer[j*BYTES_STAR]);
+
+      /* cmp files carry dM in millimags */
+      dparse (&tmp, 4, &buffer[j*BYTES_STAR]);
+      stars[N].dM = 0.001*tmp;
+
+      dparse (&tmp,         5, &buffer[j*BYTES_STAR]);
+      stars[N].dophot = tmp;
+
+      dparse (&stars[N].Mgal, 7, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].Map,  8, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fx,   9, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].fy,  10, &buffer[j*BYTES_STAR]);
+      dparse (&stars[N].df,  11, &buffer[j*BYTES_STAR]);
+    }
+  }
+  *nstars = N;
+  return (stars);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpload.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpload.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpload.c	(revision 16632)
@@ -0,0 +1,143 @@
+# include "dvoshell.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 66
+# define BLOCK 1000
+
+int cmpload (int argc, char **argv) {
+  
+  int i, Noverlay, NOVERLAY, Nstar, N, Nin, Nextra, Objtype, type;
+  int doneread, done, Nskip, Nbytes, nbytes, Ninstar;
+  char *c, *c2, *name;
+  double dtmp;
+  FILE *f;
+  char *buffer;
+  int kapa;
+  Header header;
+  KiiOverlay *overlay;
+  
+  name = NULL;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (!GetImage (NULL, &kapa, name)) return (FALSE);
+  FREE (name);
+
+  Objtype = 0;
+  if ((N = get_argument (argc, argv, "-t"))) {
+    remove_argument (N, &argc, argv);
+    Objtype = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: cmpload (overlay) <filename>\n");
+    return (FALSE);
+  }
+
+  if (!gfits_read_header (argv[2], &header)) {
+    gprint (GP_ERR, "ERROR: can't read header for %s\n", argv[2]);
+    return (FALSE);
+  }
+
+  /* find expected number of stars */
+  gfits_scan (&header, "NSTARS", "%d", 1, &Nstar);
+  if (Nstar == 0) {
+    gprint (GP_ERR, "ERROR: can't get NSTARS from header\n");
+    gfits_free_header (&header);
+    return (FALSE);
+  }
+
+  f = fopen (argv[2], "r");
+  if (f == NULL) {
+    gprint (GP_ERR, "ERROR: can't read data from %s\n", argv[2]);
+    gfits_free_header (&header);
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  Noverlay = 0;
+  NOVERLAY = 1000;
+  ALLOCATE (overlay, KiiOverlay, Noverlay);
+  
+  /* load in stars by blocks of 1000 */
+  Nin = 0;
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR) + 1);
+  buffer[BLOCK*BYTES_STAR] = 0;
+  Nextra = 0;
+  doneread = FALSE;
+  while (!doneread) {
+    Nbytes = BYTES_STAR * BLOCK - Nextra;
+    nbytes = fread (&buffer[Nextra], 1, Nbytes, f);
+    if (nbytes == 0) {
+      doneread = TRUE;
+      continue;
+    }
+    nbytes += Nextra;
+    /* check line-by-line integrity */
+    c = buffer;
+    done = FALSE;
+    while ((c < buffer + nbytes) && (!done)) { 
+      for (c2 = c; *c2 == '\n'; c2++);
+      if (c2 > c) { /* extra return chars */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+      }
+      c2 = strchr (c, '\n');
+      if (c2 == (char *) NULL) {
+	done = TRUE;	
+	continue;
+      }
+      c2++;
+      if ((c2 - c) != BYTES_STAR) { /* bad line, delete it */
+	memmove (c, c2, (int)(buffer + nbytes - c2));
+	Nskip = c2 - c;
+	nbytes -= Nskip;
+	bzero (buffer + nbytes, Nskip);
+      } else {
+	c = c2;
+      }
+    }
+    Ninstar = nbytes / BYTES_STAR;
+    Nextra = nbytes % BYTES_STAR;
+    for (i = 0; i < Ninstar; i++) {
+      if (Objtype) {
+	dparse (&dtmp, 5, &buffer[i*BYTES_STAR]);
+	type = dtmp;
+	if (type != Objtype) continue;
+      }
+      # if (0)
+      if (scale) {
+	dparse (&mag,  3, &buffer[i*BYTES_STAR]);
+	overlay[Noverlay].dx = mzero + mscale * mag;
+	overlay[Noverlay].dy = mzero + mscale * mag;
+      } else {
+	overlay[Noverlay].dx = 5.0;
+	overlay[Noverlay].dy = 5.0;
+      }      
+      # endif 
+
+      fparse (&overlay[Noverlay].x,  1, &buffer[i*BYTES_STAR]);
+      fparse (&overlay[Noverlay].y,  2, &buffer[i*BYTES_STAR]);
+      overlay[Noverlay].type = KII_OVERLAY_BOX;
+      overlay[Noverlay].dx = 5.0;
+      overlay[Noverlay].dy = 5.0;
+      Noverlay ++;
+      CHECK_REALLOCATE (overlay, KiiOverlay, NOVERLAY, Noverlay, 1000);
+    }
+  }
+  fclose (f);
+
+  KiiLoadOverlay (kapa, overlay, Noverlay, argv[1]);
+  free (overlay);
+
+  gfits_free_header (&header);
+  free (buffer);
+
+  gprint (GP_ERR, "loaded %d objects\n", Noverlay);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpread.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpread.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/cmpread.c	(revision 16632)
@@ -0,0 +1,143 @@
+# include "dvoshell.h"
+
+/* add others as needed */
+enum {F_NONE, F_RA, F_DEC, F_X, F_Y, F_MAG, F_DMAG, F_TYPE, F_SKY, F_FX, F_FY, F_APMAG, F_GALMAG};
+
+int cmpread (int argc, char **argv) {
+  
+  int i, field, Naxis, Nbytes, Nstars;
+  double tR, tD;
+  float value;
+  FILE *f;
+  Vector *vec;
+  Header header;
+  Coords coords;
+  CMPstars *stars;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: cmpread field <filename>\n");
+    return (FALSE);
+  }
+
+  field = F_NONE;
+  if (!strcasecmp (argv[1], "ra"))   field = F_RA;
+  if (!strcasecmp (argv[1], "dec"))  field = F_DEC;
+  if (!strcasecmp (argv[1], "mag"))  field = F_MAG;
+  if (!strcasecmp (argv[1], "dmag")) field = F_DMAG;
+  if (!strcasecmp (argv[1], "x"))    field = F_X;
+  if (!strcasecmp (argv[1], "y"))    field = F_Y;
+  if (!strcasecmp (argv[1], "type")) field = F_TYPE;
+  if (!strcasecmp (argv[1], "sky"))  field = F_SKY;
+  if (!strcasecmp (argv[1], "fx"))   field = F_FX;
+  if (!strcasecmp (argv[1], "fy"))   field = F_FY;
+  if (!strcasecmp (argv[1], "apmag"))  field = F_APMAG;
+  if (!strcasecmp (argv[1], "galmag"))  field = F_GALMAG;
+  if (field == F_NONE) {
+    gprint (GP_ERR, "invalid cmp field: %s\n", argv[1]);
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1],  ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* load FITS header */
+  if (!gfits_read_header (argv[2], &header)) {
+    gprint (GP_ERR, "ERROR: can't read header for %s\n", argv[2]);
+    return (FALSE);
+  }
+
+  if ((field == F_RA) || (field == F_DEC)) {
+    if (!GetCoords (&coords, &header)) {
+      gprint (GP_ERR, "can't get WCS info from header\n");
+      gfits_free_header (&header);
+      return (FALSE);
+    }
+  }
+
+  /* re-open file to load data */
+  f = fopen (argv[2], "r");
+  if (f == NULL) {
+    gprint (GP_ERR, "ERROR: can't read data from %s\n", argv[2]);
+    gfits_free_header (&header);
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* find expected number of stars */
+  if (!gfits_scan (&header, "NSTARS", "%d", 1, &Nstars)) {
+    gprint (GP_ERR, "ERROR: can't get NSTARS from header\n");
+    gfits_free_header (&header);
+    return (FALSE);
+  }
+
+  /* read from FITS table or from text table */
+  Naxis = 0;
+  gfits_scan (&header, "NAXIS",  "%d", 1, &Naxis);
+  if (Naxis == 2) {
+    /* allocate space for stars */
+    gprint (GP_ERR, "reading from TEXT cmp file %s\n", argv[2]);
+    if (!gfits_scan (&header, "NSTARS", "%d", 1, &Nstars)) {
+      gprint (GP_ERR, "ERROR: failed to find NSTARS\n");
+      exit (1);
+    }
+    stars = cmpReadText (f, &Nstars);
+  } else {
+    gprint (GP_ERR, "reading from FITS cmp file %s\n", argv[2]);
+    Nbytes = gfits_data_size (&header);
+    fseek (f, Nbytes, SEEK_CUR); 
+    stars = cmpReadFits (f, &Nstars);
+  }
+  fclose (f);
+
+  REALLOCATE (vec[0].elements, float, Nstars);
+  vec[0].Nelements = Nstars;
+  bzero (vec[0].elements, Nstars*sizeof(float));
+
+  value = 0;
+  for (i = 0; i < Nstars; i++) {
+    switch (field) {
+      case F_RA:
+	XY_to_RD (&tR, &tD, stars[i].X, stars[i].Y, &coords);
+	value = tR;
+	break;
+      case F_DEC:
+	XY_to_RD (&tR, &tD, stars[i].X, stars[i].Y, &coords);
+	value = tD;
+	break;
+      case F_X:
+	value = stars[i].X;
+	break;
+      case F_Y:
+	value = stars[i].Y;
+	break;
+      case F_MAG:
+	value = stars[i].M;
+	break;
+      case F_APMAG:
+	value = stars[i].Map;
+	break;
+      case F_GALMAG:
+	value = stars[i].Mgal;
+	break;
+      case F_DMAG:
+	value = stars[i].dM;
+	break;
+      case F_TYPE:
+	value = stars[i].dophot;
+	break;
+      case F_SKY:
+	value = stars[i].sky;
+	break;
+      case F_FX:
+	value = stars[i].fx;
+	break;
+      case F_FY:
+	value = stars[i].fy;
+	break;
+    }
+    vec[0].elements[i] = value;
+  }      
+  free (stars);
+  gfits_free_header (&header);
+  gprint (GP_ERR, "loaded %d objects\n", Nstars);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/compare.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/compare.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/compare.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "dvoshell.h"
+# define D_NMATCH 500;
+
+void compare (Catalog *catlog1, Catalog *catlog2, 
+	      Vector *rvec,  Vector *dvec,  Vector *mvec, Vector *drvec, Vector *ddvec, Vector *dmvec, double radius) {
+
+  int i, j, first_j, Nmatch, NMATCH;
+  double dX, dY, dR;
+
+  Nmatch = 0;
+  NMATCH = D_NMATCH;
+  REALLOCATE (rvec[0].elements, float, NMATCH);
+  REALLOCATE (dvec[0].elements, float, NMATCH);
+  REALLOCATE (mvec[0].elements, float, NMATCH);
+  REALLOCATE (drvec[0].elements, float, NMATCH);
+  REALLOCATE (ddvec[0].elements, float, NMATCH);
+  REALLOCATE (dmvec[0].elements, float, NMATCH);
+
+  for (i = j = 0; (i < catlog1[0].Naverage) && (j < catlog2[0].Naverage);) {
+    
+    dX = catlog1[0].average[i].R - catlog2[0].average[j].R;
+
+    if (!(i % 100))
+      gprint (GP_ERR, ".");
+    
+    if (dX <= -radius)
+      i++;
+    if (dX >= radius)
+      j++;
+
+    if (fabs (dX) < radius) {
+      first_j = j;
+      for (j = first_j; (fabs (dX) < radius) && (j < catlog2[0].Naverage); j++) {
+	dX = catlog1[0].average[i].R - catlog2[0].average[j].R;
+	dY = catlog1[0].average[i].D - catlog2[0].average[j].D;
+	dR = hypot (dX, dY);
+	if (dR < radius) {
+	  rvec[0].elements[Nmatch] = catlog1[0].average[i].R;
+	  dvec[0].elements[Nmatch] = catlog1[0].average[i].D;
+	  // mvec[0].elements[Nmatch] = catlog1[0].average[i].M;
+	  drvec[0].elements[Nmatch] = dX;
+	  ddvec[0].elements[Nmatch] = dY;
+	  // dmvec[0].elements[Nmatch] = catlog1[0].average[i].M - catlog2[0].average[j].M;
+	  Nmatch ++;
+	  if (Nmatch == NMATCH - 1) {
+	    NMATCH += D_NMATCH;
+	    REALLOCATE ( rvec[0].elements, float, NMATCH);
+	    REALLOCATE ( dvec[0].elements, float, NMATCH);
+	    REALLOCATE ( mvec[0].elements, float, NMATCH);
+	    REALLOCATE (drvec[0].elements, float, NMATCH);
+	    REALLOCATE (ddvec[0].elements, float, NMATCH);
+	    REALLOCATE (dmvec[0].elements, float, NMATCH);
+	  }
+	}
+      }
+      j = first_j;
+      i++;
+    }
+  }
+
+  REALLOCATE ( rvec[0].elements, float, Nmatch);
+  REALLOCATE ( dvec[0].elements, float, Nmatch);
+  REALLOCATE ( mvec[0].elements, float, Nmatch);
+  REALLOCATE (drvec[0].elements, float, Nmatch);
+  REALLOCATE (ddvec[0].elements, float, Nmatch);
+  REALLOCATE (dmvec[0].elements, float, Nmatch);
+  
+  rvec[0].Nelements = Nmatch;
+  dvec[0].Nelements = Nmatch;
+  mvec[0].Nelements = Nmatch;
+  drvec[0].Nelements = Nmatch;
+  ddvec[0].Nelements = Nmatch;
+  dmvec[0].Nelements = Nmatch;
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbBooleanCond.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbBooleanCond.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbBooleanCond.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "dvoshell.h"
+
+// evaluate the expression in inStack as a boolean; necessary db field values are
+// supplied by fields, in order 0 - Nfields (validate before calling)
+int dbBooleanCond (dbStack *inStack, int NinStack, float *fields) {
+  
+  float value;
+  int i, j, N, Nstack;
+  dbStack **stack, *output;
+
+  // 'no stack' means 'no where statement'
+  if (NinStack == 0) return (TRUE);
+
+  Nstack = NinStack;
+  ALLOCATE (stack, dbStack *, NinStack);
+  for (i = 0; i < NinStack; i++) {
+    stack[i] = &inStack[i];
+  }
+
+  for (i = 0; i < Nstack; i++) {
+
+    /***** binary operators *****/
+    if ((stack[i][0].type >= 3) && (stack[i][0].type <= 8)) {
+
+      // pre-test that op and entries match
+      output = dbBinary (stack[i-2], stack[i-1], stack[i][0].name, fields); 
+
+      // free temporary stack items, drop external items
+      dbFreeTempEntry (stack[i-2]);
+      dbFreeTempEntry (stack[i-1]);
+
+      stack[i-2] = output;
+      for (j = i + 1; j < Nstack; j++) {
+	stack[j-2] = stack[j];
+      }
+
+      Nstack -= 2;
+      i -= 2;
+      continue;
+    }
+
+    /***** unary operators **/
+    if (stack[i][0].type == 9) {
+
+      // pre-test that op and entries match
+      output = dbUnary (stack[i-1], stack[i][0].name, fields); 
+
+      // free temporary stack items, drop external items
+      dbFreeTempEntry (stack[i-1]);
+
+      stack[i-1] = output;
+      for (j = i + 1; j < Nstack; j++) {
+	stack[j-1] = stack[j];
+      }
+
+      Nstack -= 1;
+      i -= 1;
+      continue;
+    } 
+  }
+
+  // the result here is a single stack entry with a value:
+  if (stack[0][0].type == 'F') {
+    N = stack[0][0].field;
+    value = fields[N];
+  } else {
+    value = stack[0][0].Float;
+  }
+    
+  for (i = 0; i < Nstack; i++) {
+    dbFreeEntry (stack[i]);
+  }
+  free (stack);
+
+  // XXX fix this limit
+  if (fabs(value) > 1e-7) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+
+  // pre-test that op and entries match
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbCheckStack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbCheckStack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbCheckStack.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "dvoshell.h"
+
+int dbCheckStack (dbStack *stack, int Nstack, int table, dbField **inFields, int *inNfields) {
+
+  int i, j, status, NFIELDS, Nfields;
+  char *c;
+  dbField *fields;
+
+  fields = *inFields;
+  Nfields = *inNfields;
+
+  NFIELDS = Nfields + 10;
+  REALLOCATE (fields, dbField, NFIELDS);
+
+  for (i = 0; i < Nstack; i++) {
+    if (stack[i].type == 'X') {
+
+      /** if this is a number, put it on the list of scalers and move on **/
+      stack[i].Float = strtod (stack[i].name, &c);
+      if (c == stack[i].name + strlen (stack[i].name)) {
+	stack[i].type  = 'S';
+	continue;
+      } 
+
+      // this must be a field : is it already in the list?
+      for (j = 0; (j < Nfields) && strcasecmp (stack[i].name, fields[j].name); j++);
+      if (j < Nfields) {
+	stack[i].field = j;
+	stack[i].type  = 'F';
+	stack[i].name  = NULL;
+	stack[i].Float = 0.0;
+	continue;
+      }
+
+      // this must be a field : is it a valid name?
+      if (table == DVO_TABLE_MEASURE) {
+	status = ParseMeasureField (&fields[Nfields], stack[i].name);
+      } 
+      if (table == DVO_TABLE_AVERAGE) {
+	status = ParseAverageField (&fields[Nfields], stack[i].name);
+      } 
+      if (!status) {
+	gprint (GP_ERR, "unknown database field %s\n", stack[i].name);
+	return (FALSE);
+      }
+      stack[i].field = Nfields;
+      stack[i].type  = 'F';
+      stack[i].name  = NULL;
+      stack[i].Float = 0.0;
+
+      Nfields ++;
+      CHECK_REALLOCATE (fields, dbField, NFIELDS, Nfields, 10);
+    }
+  }
+
+  *inNfields = Nfields;
+  *inFields = fields;
+
+  return (TRUE);
+}
+
+/* check stack identifies the data elements as plain scalars or table fields
+   operators have already been identified.  
+   check stack returns the total stack dimensionality (0,1,2)
+   on error, check stack returns FALSE
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbCmdlineFields.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbCmdlineFields.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbCmdlineFields.c	(revision 16632)
@@ -0,0 +1,180 @@
+# include "dvoshell.h"
+
+// identify the fields to be extracted (test for where, check syntax)
+dbField *dbCmdlineFields (int argc, char **argv, int table, int *last, int *nfields) {
+
+  int i, status, Nfields, NFIELDS;
+  char *p, *q, *field;
+  dbField *fields;
+
+  *nfields = 0;
+  Nfields = 0;
+  NFIELDS = 10;
+  ALLOCATE (fields, dbField, NFIELDS);
+  dbInitField (&fields[0]);
+
+  // examine each argv[i] entry until we reach a where 
+  for (i = 1; (i < argc) && strcasecmp (argv[i], "where"); i++) {
+    // split the word by ","
+    p = argv[i];
+    while (*p) {
+      q = strchr (p, ',');
+      if (q == NULL) {
+	field = strcreate (p);
+	p = p + strlen(p);
+      } else {
+	field = strncreate (p, q-p);
+	p = q + 1;
+      }
+      // identify field for word
+      // need to know which type of fields to look for...
+      // xxx extend this more generally later
+      if (table == DVO_TABLE_MEASURE) {
+	status = ParseMeasureField (&fields[Nfields], field);
+      } 
+      if (table == DVO_TABLE_AVERAGE) {
+	status = ParseAverageField (&fields[Nfields], field);
+      } 
+      if (!status) {
+	gprint (GP_ERR, "unknown database field %s\n", field);
+	free (field);
+	dbFreeFields (fields, Nfields);
+	return (NULL);
+      }
+      free (field);
+
+      Nfields ++;
+      CHECK_REALLOCATE (fields, dbField, NFIELDS, Nfields, 10);
+      dbInitField (&fields[Nfields]);
+    }
+  }
+
+  // require 'where' before boolean math
+  if (i != argc) {
+    if (strcasecmp(argv[i], "where")) {
+      gprint (GP_ERR, "syntax error\n");
+      free (fields);
+      return (NULL);
+    }
+    if (i > argc - 2) {
+      gprint (GP_ERR, "missing boolean expression\n");
+      free (fields);
+      return (NULL);
+    }
+    i++; // skip over the 'where'
+  }
+
+  *last = i;
+  *nfields = Nfields;
+
+  return (fields);
+}
+
+char *strfloat (float value) {
+
+  int Nbyte;
+  char *output;
+  char tmp;
+
+  Nbyte = snprintf (&tmp, 0, "%f", value);
+  ALLOCATE (output, char, Nbyte + 1);
+  snprintf (output, Nbyte + 1, "%f", value);
+  return output;
+}
+
+// identify the fields to be extracted (test for where, check syntax)
+int dbAstroRegionLimits (dbStack **stack, int *nstack, SkyRegionSelection *selection, int table) {
+  
+  int N;
+  double Rmin, Rmax, Dmin, Dmax;
+  char *Rname, *Dname;
+
+  if (!selection->useDisplay && !selection->useSkyregion) return (TRUE);
+
+  // get the ra,dec limits...
+  if (selection->useDisplay) {
+    return (TRUE);
+    // XXX fix this: be more careful with the projection & limits
+
+    Graphdata graphsky;
+    if (!GetGraphData (&graphsky, NULL, NULL)) {
+      gprint (GP_ERR, "region display not available\n");
+      return (FALSE);
+    }
+    
+    // XXX the ra and dec range depend on the projection. 
+    // XXX this is wrong...
+    int status;
+    status = XY_to_RD (&Rmin, &Dmin, graphsky.xmin, graphsky.ymin, &graphsky.coords);
+    status = XY_to_RD (&Rmax, &Dmax, graphsky.xmax, graphsky.ymax, &graphsky.coords);
+  }
+
+  if (selection->useSkyregion) {
+    get_skyregion (&Rmin, &Rmax, &Dmin, &Dmax);
+  }    
+
+  N = *nstack;
+  REALLOCATE (*stack, dbStack, N + 20);
+
+  if (table == DVO_TABLE_AVERAGE) {
+    Rname = strcreate ("RA");
+    Dname = strcreate ("DEC");
+  } else {
+    Rname = strcreate ("RA:AVE");
+    Dname = strcreate ("DEC:AVE");
+  }
+
+  // add: ((ra > rmin) && (ra < rmax) && (dec > dmin) && (dec < dmax))
+  // prepend with && if *nstack > 0
+
+  stack[0][N +  0].name = strcreate (Rname);
+  stack[0][N +  0].type = 'X';
+  stack[0][N +  1].name = strfloat (Rmin);
+  stack[0][N +  1].type = 'X';
+  stack[0][N +  2].name = strcreate (">");
+  stack[0][N +  2].type = 4;
+  // stack[0][N +  3].name = strcreate ("A");
+  // stack[0][N +  3].type = 3;
+
+  stack[0][N +  3].name = strcreate (Rname);
+  stack[0][N +  3].type = 'X';
+  stack[0][N +  4].name = strfloat (Rmax);
+  stack[0][N +  4].type = 'X';
+  stack[0][N +  5].name = strcreate ("<");
+  stack[0][N +  5].type = 4;
+  stack[0][N +  6].name = strcreate ("A");
+  stack[0][N +  6].type = 3;
+
+  stack[0][N +  7].name = strcreate (Dname);
+  stack[0][N +  7].type = 'X';
+  stack[0][N +  8].name = strfloat (Dmin);
+  stack[0][N +  8].type = 'X';
+  stack[0][N +  9].name = strcreate (">");
+  stack[0][N +  9].type = 4;
+  stack[0][N + 10].name = strcreate ("A");
+  stack[0][N + 10].type = 3;
+
+  stack[0][N + 11].name = strcreate (Dname);
+  stack[0][N + 11].type = 'X';
+  stack[0][N + 12].name = strfloat (Dmax);
+  stack[0][N + 12].type = 'X';
+  stack[0][N + 13].name = strcreate ("<");
+  stack[0][N + 13].type = 4;
+  stack[0][N + 14].name = strcreate ("A");
+  stack[0][N + 14].type = 3;
+
+  if (N == 0) {
+    N += 15;
+  } else {
+    stack[0][N + 15].name = strcreate ("A");
+    stack[0][N + 15].type = 3;
+    N += 16;
+  }    
+
+  free (Rname);
+  free (Dname);
+
+  *nstack = N;
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbExtractAverages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbExtractAverages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbExtractAverages.c	(revision 16632)
@@ -0,0 +1,135 @@
+# include "dvoshell.h"
+
+/* return average.field based on the selection */
+double dbExtractAverages (Average *average, SecFilt *secfilt, Measure *measure, dbField *field) {
+
+  int i, Nsec;
+  double value;
+
+  value = NAN;
+
+  /* assign vector values */
+  switch (field->ID) {
+    case AVE_RA:
+      value = average[0].R;
+      break;
+    case AVE_DEC:
+      value = average[0].D;
+      break;
+    case AVE_RA_ERR:
+      value = average[0].dR;
+      break;
+    case AVE_DEC_ERR:
+      value = average[0].dD;
+      break;
+
+    case AVE_U_RA:
+      value = average[0].uR;
+      break;
+    case AVE_U_DEC:
+      value = average[0].uD;
+      break;
+    case AVE_U_RA_ERR:
+      value = average[0].duR;
+      break;
+    case AVE_U_DEC_ERR:
+      value = average[0].duD;
+      break;
+
+    case AVE_PAR:
+      value = average[0].P;
+      break;
+    case AVE_PAR_ERR:
+      value = average[0].dP;
+      break;
+
+    case AVE_NMEAS:
+      value = average[0].Nm;
+      break;
+    case AVE_NMISS:
+      value = average[0].Nn;
+      break;
+    case AVE_Xp:
+      value = 0.01*average[0].Xp;
+      break;
+    case AVE_FLAG:
+      value = average[0].code;
+      break;
+
+    case AVE_MAG:
+      switch (field->magMode) {
+	case MAG_AVE:
+	  value = PhotAve  (field->photcode, average, secfilt);
+	  break;
+	case MAG_REF:
+	  value = PhotRef  (field->photcode, average, secfilt, measure);
+	  break;
+	case MAG_INST:
+	case MAG_CAT:
+	case MAG_SYS:
+	case MAG_REL:
+	case MAG_CAL:
+	  // XXX need to code this correctly: this returns just the first matching value
+	  value = NAN;
+	  for (i = 0; i < average[0].Nm; i++) {
+	    if (field->photcode->code != measure[i].photcode) continue;
+	    value = measure[i].M;
+	    break;
+	  }
+	  break;
+	case MAG_CHISQ:
+	  // GetPhotcodeEquivCodebyCode (field->photcode)
+	  value = PhotXm (field->photcode, average, secfilt);
+	  break;
+	case MAG_ERR:
+	  // GetPhotcodeEquivCodebyCode (field->photcode)
+	  value = PhotdM (field->photcode, average, secfilt);
+	  break;
+	case MAG_NCODE:
+	  // XXX push these into dvo_photcode_ops APIs
+	  // XXX do I need to allow for conversion to equiv?
+	  Nsec = GetPhotcodeNsec (field->photcode->code);
+	  if (Nsec == -1) break;
+	  value = secfilt[Nsec].Ncode;
+	  break;
+	case MAG_NPHOT:
+	  Nsec = GetPhotcodeNsec (field->photcode->code);
+	  if (Nsec == -1) break;
+	  value = secfilt[Nsec].Nused;
+	  break;
+
+      }
+      break;
+    case AVE_dMAG:
+      value = PhotdM (field->photcode, average, secfilt);
+      break;
+    case AVE_Xm:
+      value = PhotXm (field->photcode, average, secfilt);
+      break;
+    case AVE_TYPE:
+      break;
+    case AVE_TYPEFRAC:
+      break;
+      /*
+    case AVE_NCODE:
+      value = 0;
+      for (i = 0; i < average[0].Nm; i++) {
+	if (field->photcode->code != GetPhotcodeEquivCodebyCode (measure[i].photcode)) continue;
+	value ++;
+      }
+      break;
+    case AVE_NPHOT:
+      value = 0;
+      for (i = 0; i < average[0].Nm; i++) {
+	if (field->photcode->code != GetPhotcodeEquivCodebyCode (measure[i].photcode)) continue;
+	if (measure[i].flags & (ID_MEAS_POOR | ID_MEAS_SKIP)) continue;
+	value ++;
+      }
+      break;
+    case AVE_NCRIT:
+      break;
+      */
+  }
+  return (value);
+}  
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbExtractMeasures.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbExtractMeasures.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbExtractMeasures.c	(revision 16632)
@@ -0,0 +1,251 @@
+# include "dvoshell.h"
+
+/* time concepts */
+static time_t TimeReference;
+static int TimeFormat;
+
+void dbExtractMeasuresInit () {
+  GetTimeFormat (&TimeReference, &TimeFormat);
+}
+
+/* return measure.field based on the selection */
+double dbExtractMeasures (Average *average, SecFilt *secfilt, Measure *measure, dbField *field) {
+
+  int Nsec;
+  double value;
+  double ra, dec, x, y;
+
+  Image *image;
+  Coords *mosaic;
+
+  value = NAN;
+
+  switch (field->ID) {
+    case MEAS_MAG: /* magnitudes are already determined above */
+      // we return the magnitude for this measure if:
+      if (field->photcode->type == PHOT_MAG) goto valid_photcode;
+      if ((field->photcode->type == PHOT_REF) && (measure[0].photcode == field->photcode->code)) goto valid_photcode;
+      if ((field->photcode->type == PHOT_DEP) && (measure[0].photcode == field->photcode->code)) goto valid_photcode;
+      if ((field->photcode->type == PHOT_SEC) && (GetPhotcodeEquivCodebyCode (measure[0].photcode) == field->photcode->code)) goto valid_photcode;
+      break;
+
+  valid_photcode:
+      switch (field->magMode) {
+	case MAG_INST:
+	  value = PhotInst (measure);  
+	  break;
+	case MAG_CAT:
+	  value = PhotCat  (measure); 
+	  break;
+	case MAG_SYS:
+	  value = PhotSys  (measure, average, secfilt); 
+	  break;
+	case MAG_REL:
+	  value = PhotRel  (measure, average, secfilt); 
+	  break;
+	case MAG_CAL:
+	  value = PhotCal  (measure, average, secfilt, measure, GetPhotcodeEquivbyCode (measure[0].photcode)); 
+	  break;
+	case MAG_AVE:
+	  value = PhotAve  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt); 
+	  break;
+	case MAG_REF:
+	  value = PhotRef  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt, measure); 
+	  break;
+	case MAG_ERR:
+	  value = PhotdM  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt); 
+	  break;
+	case MAG_CHISQ:
+	  value = PhotXm  (GetPhotcodeEquivbyCode (measure[0].photcode), average, secfilt); 
+	  break;
+	case MAG_NCODE:
+	  Nsec = GetPhotcodeNsec (GetPhotcodeEquivCodebyCode (measure[0].photcode));
+	  if (Nsec == -1) break;
+	  value = secfilt[Nsec].Ncode;
+	  break;
+	case MAG_NPHOT:
+	  Nsec = GetPhotcodeNsec (GetPhotcodeEquivCodebyCode (measure[0].photcode));
+	  if (Nsec == -1) break;
+	  value = secfilt[Nsec].Nused;
+	  break;
+      }
+      break;
+    case MEAS_RA: /* OK */
+      value = average[0].R - measure[0].dR / 3600.0;
+      break;
+    case MEAS_DEC: /* OK */
+      value = average[0].D - measure[0].dD / 3600.0;
+      break;
+    case MEAS_RA_AVE: /* OK */
+      value = average[0].R;
+      break;
+    case MEAS_DEC_AVE: /* OK */
+      value = average[0].D;
+      break;
+    case MEAS_RA_AVE_ERR: /* OK */
+      value = average[0].dR;
+      break;
+    case MEAS_DEC_AVE_ERR: /* OK */
+      value = average[0].dD;
+      break;
+    case MEAS_U_RA: /* OK */
+      value = average[0].uR;
+      break;
+    case MEAS_U_DEC: /* OK */
+      value = average[0].uD;
+      break;
+    case MEAS_U_RA_ERR: /* OK */
+      value = average[0].duR;
+      break;
+    case MEAS_U_DEC_ERR: /* OK */
+      value = average[0].duD;
+      break;
+    case MEAS_PAR: /* OK */
+      value = average[0].R;
+      break;
+    case MEAS_PAR_ERR: /* OK */
+      value = average[0].D;
+      break;
+    case MEAS_XP: /* OK */
+      value = average[0].Xp;
+      break;
+    case MEAS_NMEAS: /* OK */
+      value = average[0].Nm;
+      break;
+    case MEAS_NMISS: /* OK */
+      value = average[0].Nn;
+      break;
+    case MEAS_OBJFLAGS: /* OK */
+      value = average[0].code;
+      break;
+    // note that these represent the ra displacement relative to the average, not 
+    // the error.
+    case MEAS_RA_OFFSET: /* OK */
+      value = measure[0].dR;
+      break;
+    case MEAS_DEC_OFFSET: /* OK */
+      value = measure[0].dD;
+      break;
+    case MEAS_RA_OFFSET_ERR: /* OK */
+      value = NAN;
+      break;
+    case MEAS_DEC_OFFSET_ERR: /* OK */
+      value = NAN;
+      break;
+    case MEAS_AIRMASS: /* OK */
+      value = measure[0].airmass;
+      break;
+    case MEAS_AZ: /* OK */
+      value = measure[0].az;
+      break;
+    case MEAS_EXPTIME: /* OK */
+      value = pow (10.0, measure[0].dt * 0.4);
+      break;
+    case MEAS_PHOTCODE: /* OK */
+      value = measure[0].photcode;
+      break;
+    case MEAS_TIME: /* OK */
+      value = TimeValue (measure[0].t, TimeReference, TimeFormat);
+      break;
+    case MEAS_FWHM: /* OK */
+      value = 0.01*(measure[0].FWx + measure[0].FWy);
+      break;
+    case MEAS_FWHM_MAJ: /* OK */
+      value = 0.01*measure[0].FWx;
+      break;
+    case MEAS_FWHM_MIN: /* OK */
+      value = 0.01*measure[0].FWy;
+      break;
+    case MEAS_THETA: /* OK */
+      value = measure[0].theta;
+      break;
+    case MEAS_DOPHOT: /* OK */
+      value = measure[0].dophot;
+      break;
+    case MEAS_DB_FLAGS: /* ? */
+      value = measure[0].dbFlags;
+      break;
+    case MEAS_PHOT_FLAGS: /* ? */
+      value = measure[0].photFlags;
+      break;
+    case MEAS_XCCD: /* OK */
+/* I need to perform this conversion for ELIXIR and LONEOS formats on load */      
+# if 0
+      value = measure[0].Xccd;
+# else
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      image = MatchImage (measure[0].t, measure[0].photcode);
+      if (image == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, &image[0].coords);
+      value = x;
+# endif
+      break;
+    case MEAS_YCCD: /* OK */
+/* I need to perform this conversion for ELIXIR and LONEOS formats on load */      
+# if 0
+      value = measure[0].Yccd;
+# else
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      image = MatchImage (measure[0].t, measure[0].photcode);
+      if (image == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, &image[0].coords);
+      value = y;
+# endif
+      break;
+    case MEAS_XMOSAIC: /* OK */
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      mosaic = MatchMosaic (measure[0].t, measure[0].photcode);
+      if (mosaic == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, mosaic);
+      value = x;
+      break;
+    case MEAS_YMOSAIC: /* OK */
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      mosaic = MatchMosaic (measure[0].t, measure[0].photcode);
+      if (mosaic == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, mosaic);
+      value = y;
+      break;
+
+    case MEAS_SKY: /* OK */
+      value = measure[0].Sky;
+      break;
+    case MEAS_dSKY: /* OK */
+      value = measure[0].dSky;
+      break;
+    case MEAS_DET_ID: /* OK */
+      value = measure[0].detID;
+      break;
+    case MEAS_OBJ_ID: /* OK */
+      value = measure[0].averef;
+      break;
+    case MEAS_IMAGE_ID: /* OK */
+      value = measure[0].imageID;
+      break;
+    case MEAS_PSF_QF: /* OK */
+      value = measure[0].qPSF;
+      break;
+    case MEAS_PSF_PROB: /* OK */
+      value = measure[0].psfProb;
+      break;
+    case MEAS_CR_NSIGMA: /* OK */
+      value = measure[0].crNsigma;
+      break;
+    case MEAS_EXT_NSIGMA: /* OK */
+      value = measure[0].extNsigma;
+      break;
+    case MEAS_STARGAL: /* OK */
+      value = measure[0].stargal;
+      break;
+  }
+  return (value);
+}
+
+/** the mosaic entries do not use the registered mosaic found 
+    by MatchImage (via FindMosaicForImage).  Rather, they use
+    a coordinate frame saved by SetImageSelection 
+**/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbFields.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbFields.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbFields.c	(revision 16632)
@@ -0,0 +1,209 @@
+# include "dvoshell.h"
+
+void dbFreeFields (dbField *fields, int Nfields) {
+
+  int i;
+
+  if (fields == NULL) return;
+
+  for (i = 0; i < Nfields; i++) {
+    if (fields[i].name != NULL) free (fields[i].name);
+    if (fields[i].photcode != NULL) {
+      if (fields[i].photcode[0].type == PHOT_MAG) {
+	free (fields[i].photcode);
+      }
+    }
+  }
+  free (fields);
+}
+
+void dbInitField (dbField *field) {
+  field->name = NULL;
+  field->extract = FALSE;
+  field->table = 0;
+  field->ID = 0;
+  field->magMode = 0;
+  field->photcode = NULL;
+}
+
+int GetMagMode (char *string) {
+
+  if (!strcasecmp (string, "inst"))  return (MAG_INST);
+  if (!strcasecmp (string, "cat"))   return (MAG_CAT);
+  if (!strcasecmp (string, "sys"))   return (MAG_SYS);
+  if (!strcasecmp (string, "rel"))   return (MAG_REL);
+  if (!strcasecmp (string, "cal"))   return (MAG_CAL);
+  if (!strcasecmp (string, "ave"))   return (MAG_AVE);
+  if (!strcasecmp (string, "ref"))   return (MAG_REF);
+  if (!strcasecmp (string, "err"))   return (MAG_ERR);
+  if (!strcasecmp (string, "chisq")) return (MAG_CHISQ);
+  if (!strcasecmp (string, "ncode")) return (MAG_NCODE);
+  if (!strcasecmp (string, "nphot")) return (MAG_NPHOT);
+  return (MAG_NONE);
+}
+
+PhotCode *ParsePhotcodeField (char *field, int *mode, int defMode) {
+
+  int useDefault;
+  char *tmpstring, *p;
+  PhotCode *code;
+
+  *mode = defMode;
+  useDefault = TRUE;
+
+  p = strchr (field, ':');
+  if (p != NULL) {
+    *mode = GetMagMode (p + 1);
+    useDefault = FALSE;
+    if (*mode == MAG_NONE) return (NULL);
+    tmpstring = strncreate (field, p - field);
+  } else {
+    tmpstring = strcreate (field);
+  }
+  if (!strcasecmp (tmpstring, "MAG")) {
+    ALLOCATE (code, PhotCode, 1);
+    code[0].code = 0;
+    strcpy (code[0].name, "MAG");
+    code[0].type = PHOT_MAG;
+    free (tmpstring);
+    return (code);
+  }
+  code = GetPhotcodebyName (tmpstring);
+  if (!code) {
+      return NULL;
+  }
+
+
+  // enforce compatibility
+  // XXX this is kind of poorly done
+  if ((code[0].type == PHOT_REF) && (*mode != MAG_ERR)) {
+    *mode = MAG_CAT;
+  }
+  if (code[0].type == PHOT_DEP) {
+    if (useDefault) {
+      *mode = MAG_REL;
+    }
+  } 
+  free (tmpstring);
+  return (code);
+}
+
+# define ESCAPE(F,M) { \
+  field->ID = (F); \
+  field->magMode = (M); \
+  field->photcode = NULL; \
+  return (TRUE); }
+
+int ParseMeasureField (dbField *field, char *fieldName) {
+
+  int mode;
+  PhotCode *code;
+
+  field->table = DVO_TABLE_MEASURE;
+  field->name  = strcreate (fieldName);
+
+  if (!strcasecmp (fieldName, "RA"))         ESCAPE (MEAS_RA,   	MAG_NONE);
+  if (!strcasecmp (fieldName, "DEC"))        ESCAPE (MEAS_DEC,  	MAG_NONE);
+  if (!strcasecmp (fieldName, "RA:AVE"))     ESCAPE (MEAS_RA_AVE,      	MAG_NONE);
+  if (!strcasecmp (fieldName, "DEC:AVE"))    ESCAPE (MEAS_DEC_AVE,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "RA:ERR"))     ESCAPE (MEAS_RA_AVE_ERR,  	MAG_NONE);
+  if (!strcasecmp (fieldName, "DEC:ERR"))    ESCAPE (MEAS_DEC_AVE_ERR, 	MAG_NONE);
+  if (!strcasecmp (fieldName, "uRA"))        ESCAPE (MEAS_U_RA,        	MAG_NONE);
+  if (!strcasecmp (fieldName, "uDEC"))       ESCAPE (MEAS_U_DEC,       	MAG_NONE);
+  if (!strcasecmp (fieldName, "duRA"))       ESCAPE (MEAS_U_RA_ERR,    	MAG_NONE);
+  if (!strcasecmp (fieldName, "duDEC"))      ESCAPE (MEAS_U_DEC_ERR,   	MAG_NONE);
+  if (!strcasecmp (fieldName, "PAR"))        ESCAPE (MEAS_PAR,         	MAG_NONE);
+  if (!strcasecmp (fieldName, "dPAR"))       ESCAPE (MEAS_PAR_ERR,      MAG_NONE);
+  if (!strcasecmp (fieldName, "dR"))         ESCAPE (MEAS_RA_OFFSET,   	MAG_NONE);
+  if (!strcasecmp (fieldName, "dD"))         ESCAPE (MEAS_DEC_OFFSET,  	MAG_NONE);
+  if (!strcasecmp (fieldName, "dR:ERR"))     ESCAPE (MEAS_RA_OFFSET_ERR,  MAG_NONE);
+  if (!strcasecmp (fieldName, "dD:ERR"))     ESCAPE (MEAS_DEC_OFFSET_ERR, MAG_NONE);
+  if (!strcasecmp (fieldName, "xp"))         ESCAPE (MEAS_XP,          	MAG_NONE);
+  if (!strcasecmp (fieldName, "nmeas"))      ESCAPE (MEAS_NMEAS,       	MAG_NONE);
+  if (!strcasecmp (fieldName, "nmiss"))      ESCAPE (MEAS_NMISS,       	MAG_NONE);
+  if (!strcasecmp (fieldName, "objflags"))   ESCAPE (MEAS_OBJFLAGS,     MAG_NONE);
+  if (!strcasecmp (fieldName, "AIRMASS"))    ESCAPE (MEAS_AIRMASS,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "ALT"))        ESCAPE (MEAS_ALT,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "AZ"))         ESCAPE (MEAS_AZ,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "EXPTIME"))    ESCAPE (MEAS_EXPTIME,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "PHOTCODE"))   ESCAPE (MEAS_PHOTCODE,    	MAG_NONE);
+  if (!strcasecmp (fieldName, "TIME"))       ESCAPE (MEAS_TIME,        	MAG_NONE);
+  if (!strcasecmp (fieldName, "FWHM"))       ESCAPE (MEAS_FWHM,        	MAG_NONE);
+  if (!strcasecmp (fieldName, "FWHM_MAJ"))   ESCAPE (MEAS_FWHM_MAJ,    	MAG_NONE);
+  if (!strcasecmp (fieldName, "FWHM_MIN"))   ESCAPE (MEAS_FWHM_MIN,    	MAG_NONE);
+  if (!strcasecmp (fieldName, "THETA"))      ESCAPE (MEAS_THETA,       	MAG_NONE);
+  if (!strcasecmp (fieldName, "DOPHOT"))     ESCAPE (MEAS_DOPHOT,      	MAG_NONE);
+  if (!strcasecmp (fieldName, "DB_FLAGS"))   ESCAPE (MEAS_DB_FLAGS,    	MAG_NONE);
+  if (!strcasecmp (fieldName, "PHOT_FLAGS")) ESCAPE (MEAS_PHOT_FLAGS, 	MAG_NONE);
+  if (!strcasecmp (fieldName, "XCCD"))       ESCAPE (MEAS_XCCD, 	MAG_NONE);
+  if (!strcasecmp (fieldName, "YCCD"))       ESCAPE (MEAS_YCCD, 	MAG_NONE);
+  if (!strcasecmp (fieldName, "XMOSAIC"))    ESCAPE (MEAS_XMOSAIC,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "YMOSAIC"))    ESCAPE (MEAS_YMOSAIC,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "XCHIP"))      ESCAPE (MEAS_XCCD, 	MAG_NONE);
+  if (!strcasecmp (fieldName, "YCHIP"))      ESCAPE (MEAS_YCCD, 	MAG_NONE);
+  if (!strcasecmp (fieldName, "XFPA"))       ESCAPE (MEAS_XMOSAIC,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "YFPA"))       ESCAPE (MEAS_YMOSAIC,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "DETID"))      ESCAPE (MEAS_DET_ID,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "OBJID"))      ESCAPE (MEAS_OBJ_ID,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "IMAGEID"))    ESCAPE (MEAS_IMAGE_ID,     MAG_NONE);
+  if (!strcasecmp (fieldName, "PSF_QF"))     ESCAPE (MEAS_PSF_QF,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "PSF_PROB"))   ESCAPE (MEAS_PSF_PROB,     MAG_NONE);
+  if (!strcasecmp (fieldName, "CR_NSIGMA"))  ESCAPE (MEAS_CR_NSIGMA,    MAG_NONE);
+  if (!strcasecmp (fieldName, "EXT_NSIGMA")) ESCAPE (MEAS_EXT_NSIGMA,   MAG_NONE);
+  if (!strcasecmp (fieldName, "SKY"))        ESCAPE (MEAS_SKY,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "SKY_ERR"))    ESCAPE (MEAS_dSKY,     	MAG_NONE);
+  if (!strcasecmp (fieldName, "STARGAL"))    ESCAPE (MEAS_STARGAL,     	MAG_NONE);
+
+  // for words that don't parse, try a photcode
+
+  // check for code:mode in photcode name 
+  code = ParsePhotcodeField (fieldName, &mode, MAG_REL);
+  if (code == NULL) return (FALSE);
+
+  field->ID = MEAS_MAG;
+  field->magMode = mode;
+  field->photcode = code;
+  return (TRUE);
+}
+  
+int ParseAverageField (dbField *field, char *fieldName) {
+
+  int mode;
+  PhotCode *code;
+
+  field->table = DVO_TABLE_AVERAGE;
+  field->name  = strcreate (fieldName);
+
+  if (!strcasecmp (fieldName, "RA"))    ESCAPE (AVE_RA,        MAG_NONE);
+  if (!strcasecmp (fieldName, "DEC"))   ESCAPE (AVE_DEC,       MAG_NONE);
+  if (!strcasecmp (fieldName, "dRA"))   ESCAPE (AVE_RA_ERR,    MAG_NONE);
+  if (!strcasecmp (fieldName, "dDEC"))  ESCAPE (AVE_DEC_ERR,   MAG_NONE);
+  if (!strcasecmp (fieldName, "uRA"))   ESCAPE (AVE_U_RA,      MAG_NONE);
+  if (!strcasecmp (fieldName, "uDEC"))  ESCAPE (AVE_U_DEC,     MAG_NONE);
+  if (!strcasecmp (fieldName, "duRA"))  ESCAPE (AVE_U_RA_ERR,  MAG_NONE);
+  if (!strcasecmp (fieldName, "duDEC")) ESCAPE (AVE_U_DEC_ERR, MAG_NONE);
+  if (!strcasecmp (fieldName, "PAR"))   ESCAPE (AVE_PAR,       MAG_NONE);
+  if (!strcasecmp (fieldName, "dPAR"))  ESCAPE (AVE_PAR_ERR,   MAG_NONE);
+  if (!strcasecmp (fieldName, "Xp"))    ESCAPE (AVE_Xp,        MAG_NONE);
+  if (!strcasecmp (fieldName, "NMEAS")) ESCAPE (AVE_NMEAS,     MAG_NONE);
+  if (!strcasecmp (fieldName, "NMISS")) ESCAPE (AVE_NMISS,     MAG_NONE);
+  if (!strcasecmp (fieldName, "FLAG"))  ESCAPE (AVE_FLAG,      MAG_NONE);
+  if (!strcasecmp (fieldName, "TYPE"))  ESCAPE (AVE_TYPE,      MAG_NONE);
+  if (!strcasecmp (fieldName, "OBJID")) ESCAPE (AVE_OBJID,     MAG_NONE);
+
+  // for words that don't parse, try a photcode
+
+  // check for code:mode in photcode name 
+  code = ParsePhotcodeField (fieldName, &mode, MAG_AVE);
+  if (code == NULL) return (FALSE);
+  if (code[0].type == PHOT_MAG) {
+    gprint (GP_ERR, "'mag' is ambiguous for avextract\n");
+    free (code);
+    return (FALSE);
+  }
+
+  field->ID = AVE_MAG;
+  field->magMode = mode;
+  field->photcode = code;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbRPN.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbRPN.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbRPN.c	(revision 16632)
@@ -0,0 +1,210 @@
+# include "dvoshell.h"
+# define DUMPSTACK 0
+
+dbStack *dbRPN (int argc, char **argv, int *nstack) {
+  
+  int type, Nx, Ny;
+  int i, j, Nstack, Nop_stack, NSTACK;
+  dbStack *stack, *op_stack;
+
+  /* max total stack size is argc, though should be less, this is safe */
+  NSTACK = argc + 5;
+  ALLOCATE (stack, dbStack, NSTACK);
+  ALLOCATE (op_stack, dbStack, NSTACK);
+  for (i = 0; i < NSTACK; i++) {
+    dbInitStack (&stack[i]);
+    dbInitStack (&op_stack[i]);
+  }
+  
+  Nx = Ny = Nstack = Nop_stack = 0;
+  for (i = 0; i < argc; i++) {
+    
+    /* decide on priority of object */
+    type = 0;
+    /* unary operations */
+    if (!strcmp (argv[i], "abs"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "int"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "exp"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ten"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "log"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ln"))     { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "sqrt"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "erf"))    { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "sinh"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "cosh"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "asinh"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "acosh"))  { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "sin"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "cos"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "tan"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dsin"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dcos"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dtan"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "asin"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "acos"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "atan"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dasin"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dacos"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "datan"))  { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "lgamma")) { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "rnd"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "xramp"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "yramp"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ramp"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "zero"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "--"))     { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "not"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "isinf"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "isnan"))  { type = 9; goto gotit; }
+
+    /* binary operations */
+    if (!strcmp (argv[i], "^"))      { type = 8; goto gotit; }
+
+    if (!strcmp (argv[i], "@"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "/"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "*"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "%"))      { type = 7; goto gotit; }
+
+    if (!strcmp (argv[i], "+"))      { type = 6; goto gotit; }
+    if (!strcmp (argv[i], "-"))      { type = 6; goto gotit; }
+	
+    if (!strcmp (argv[i], "&"))      { type = 5; goto gotit; }
+    if (!strcmp (argv[i], "|"))      { type = 5; goto gotit; }
+
+    if (!strcmp (argv[i], "<"))      { type = 4; goto gotit; }
+    if (!strcmp (argv[i], ">"))      { type = 4; goto gotit; }
+    if (!strcmp (argv[i], "=="))     { type = 4; strcpy (argv[i], "E"); goto gotit; }
+    if (!strcmp (argv[i], "!="))     { type = 4; strcpy (argv[i], "N"); goto gotit; }
+    if (!strcmp (argv[i], "<="))     { type = 4; strcpy (argv[i], "L"); goto gotit; }
+    if (!strcmp (argv[i], ">="))     { type = 4; strcpy (argv[i], "G"); goto gotit; }
+    if (!strcmp (argv[i], ">>"))     { type = 4; strcpy (argv[i], "U"); goto gotit; }
+    if (!strcmp (argv[i], "<<"))     { type = 4; strcpy (argv[i], "D"); goto gotit; }
+
+    if (!strcmp (argv[i], "&&"))     { type = 3; strcpy (argv[i], "A"); goto gotit; }
+    if (!strcmp (argv[i], "||"))     { type = 3; strcpy (argv[i], "O"); goto gotit; }
+
+    if (!strcmp (argv[i], "("))      { type = 2; goto gotit; }
+    if (!strcmp (argv[i], ")"))      { type = 1; goto gotit; }
+
+  gotit:
+    /* choose how to deal with object */
+    switch (type) {
+      case 8:  /* exponentiation: 2^2^3 = 64 != 256 (precedence is right-to-left, not left-to-right!) */
+	/* pop previous, higher operators from OP stack to stack */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type > type); j--) {
+	  stack[Nstack] = op_stack[j];
+	  op_stack[j].name = NULL;
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	/* push operator on OP stack */
+	op_stack[Nop_stack].name = strcreate (argv[i]);
+	op_stack[Nop_stack].type = type;
+	Nop_stack ++;
+	break;
+      case 9: /* unary OPs */
+      case 7: /* binary OPs */
+      case 6:
+      case 5: 
+      case 4: 
+      case 3: 
+	/* pop previous, higher or equal operators from OP stack to stack */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type >= type); j--) {
+	  stack[Nstack] = op_stack[j];
+	  op_stack[j].name = NULL;
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	/* push operator on OP stack */
+	op_stack[Nop_stack].name = strcreate (argv[i]);
+	op_stack[Nop_stack].type = type;
+	Nop_stack ++;
+	break;
+      case 2:  
+	/* push operator on OP stack */
+	op_stack[Nop_stack].name = strcreate (argv[i]);
+	op_stack[Nop_stack].type = type;
+	Nop_stack ++;
+	break;
+      case 1: 
+	/* pop rest of operators from OP stack to stack, looking for '(' */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type != 2); j--) {
+	  stack[Nstack] = op_stack[j];
+	  op_stack[j].name = NULL;
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	if ((j == -1) || (op_stack[j].type != 2)) {
+	  push_error ("syntax error: mismatched parenthesis");
+	  Nstack = 0;
+	  goto cleanup;
+	}
+	Nop_stack --;
+	break;
+      case 0:
+	/* place the value (number or vector/matrix name) on stack */
+	/* value of 'X' is used as sentinel until we sort out values */
+	stack[Nstack].name = strcreate (argv[i]);
+	stack[Nstack].type = 'X';
+	Nstack ++;
+	break;
+    }
+  }
+
+  /* dump remaining operators on stack, checking for ')' */
+  for (j = Nop_stack - 1; j >= 0; j--) {
+    if (op_stack[j].type == 2) {
+      push_error ("syntax error: mismatched parenthesis");
+      Nstack = 0;
+      goto cleanup;
+    }
+    stack[Nstack] = op_stack[j];
+    op_stack[j].name = NULL;
+    Nstack ++;
+  }
+
+cleanup: 
+  /*** free up unused stack space ***/
+  dbFreeStack (op_stack, NSTACK);
+  free (op_stack);
+  dbFreeStack (&stack[Nstack], NSTACK - Nstack);
+  REALLOCATE (stack, dbStack, MAX (Nstack, 1));
+  *nstack = Nstack;
+
+  for (i = 0; i < argc; i++) {
+    free (argv[i]);
+  }
+  free (argv);
+
+# if (DUMPSTACK)
+  for (i = 0; i < Nstack; i++) {
+    gprint (GP_ERR, "%s ", stack[i].name);
+  }
+  if (Nstack > 0) gprint (GP_ERR, "\n");
+  for (i = 0; i < Nstack; i++) {
+    gprint (GP_ERR, "%d ", stack[i].type);
+  }
+  if (Nstack > 0) gprint (GP_ERR, "\n");
+# endif
+
+  return (stack);
+
+}
+
+/* here are the rules for parsing a math AOL expression to RPN:
+
+1) if object is a number, push on stack
+2) if object is a third order operand (exp, sin, cos), push on op stack
+3) if object is an open paren, push on op stack,
+4) if object is a second order operand, push on stack
+5) if object is a first order operand, pop all second order operands from stack 
+until paren, push on stack
+6) if object is an end paren, pop all objects from stack until paren, 
+pop next stack, if third order op
+7) if end of line, pop all remaining objects, second order first, etc.
+   
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbStackMath.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbStackMath.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbStackMath.c	(revision 16632)
@@ -0,0 +1,161 @@
+# include "dvoshell.h"
+
+static int NallocBinary = 0;
+static int NallocUnary = 0;
+
+dbStack *dbBinary (dbStack *V1, dbStack *V2, char *op, float *fields) {
+
+  int N;
+  float M1, M2;
+  dbStack *OUT;
+  
+  if (V1->type == 'F') {
+    N = V1->field;
+    M1 = fields[N];
+  } else {
+    M1 = V1->Float;
+  }
+  
+  if (V2->type == 'F') {
+    N = V2->field;
+    M2 = fields[N];
+  } else {
+    M2 = V2->Float;
+  }
+
+  NallocBinary ++;
+  ALLOCATE (OUT, dbStack, 1);
+  OUT->type = 'T';
+  OUT->name = NULL;
+
+  // use an enum for the op...
+  switch (op[0]) { 
+  case '+': 
+    OUT->Float = M1 + M2;
+    break; 
+  case '-': 
+    OUT->Float = M1 - M2;
+    break; 
+  case '*': 
+    OUT->Float = M1 * M2;
+    break; 
+  case '/': 
+    OUT->Float = M1 / M2;
+    break; 
+  case '%': 
+    OUT->Float = (int) M1 % (int) M2;
+    break; 
+  case 0x5e: 
+    OUT->Float = pow (M1, M2);
+    break; 
+  case 'D': 
+    OUT->Float = MIN (M1, M2);
+    break; 
+  case 'U': 
+    OUT->Float = MAX (M1, M2);
+    break; 
+  case '<': 
+    OUT->Float = (M1 < M2) ? 1 : 0;
+    break; 
+  case '>': 
+    OUT->Float = (M1 > M2) ? 1 : 0;
+    break; 
+  case '&': 
+    OUT->Float = ((int)M1 & (int)M2);
+    break; 
+  case '|': 
+    OUT->Float = ((int)M1 | (int)M2);
+    break; 
+  case 'E': 
+    OUT->Float = (M1 == M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    OUT->Float = (M1 != M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    OUT->Float = (M1 <= M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    OUT->Float = (M1 >= M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    OUT->Float = (M1 && M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    OUT->Float = (M1 || M2) ? 1 : 0;
+    break; 
+  default:
+    return (NULL);
+  }
+
+  return (OUT);
+}
+
+dbStack *dbUnary (dbStack *V1, char *op, float *fields) {
+
+  int N;
+  float M1;
+  dbStack *OUT;
+
+  if (V1->type == 'F') {
+    N = V1->field;
+    M1 = fields[N];
+  } else {
+    M1 = V1->Float;
+  }
+  
+  NallocUnary ++;
+  ALLOCATE (OUT, dbStack, 1);
+  OUT->type = 'T';
+  OUT->name = NULL;
+
+  if (!strcmp (op, "="))      {   OUT->Float = M1;                 }
+  if (!strcmp (op, "abs"))    {   OUT->Float = fabs(M1);           }
+  if (!strcmp (op, "int"))    {   OUT->Float = (float)(int)(M1);   }
+  if (!strcmp (op, "exp"))    {   OUT->Float = exp (M1);           }
+  if (!strcmp (op, "ten"))    {   OUT->Float = pow (10.0,M1);      }
+  if (!strcmp (op, "log"))    {   OUT->Float = log10 (M1);         }
+  if (!strcmp (op, "ln"))     {   OUT->Float = log (M1);           }
+  if (!strcmp (op, "sqrt"))   {   OUT->Float = sqrt (M1);          }
+  if (!strcmp (op, "erf"))    {   OUT->Float = erf (M1);           }
+			      			      
+  if (!strcmp (op, "sinh"))   {   OUT->Float = sinh (M1);          }
+  if (!strcmp (op, "cosh"))   {   OUT->Float = cosh (M1);          }
+  if (!strcmp (op, "asinh"))  {   OUT->Float = asinh (M1);         }
+  if (!strcmp (op, "acosh"))  {   OUT->Float = acosh (M1);         }
+  if (!strcmp (op, "lgamma")) {   OUT->Float = lgamma (M1);        }
+
+  if (!strcmp (op, "sin"))    {   OUT->Float = sin (M1);           }
+  if (!strcmp (op, "cos"))    {   OUT->Float = cos (M1);           }
+  if (!strcmp (op, "tan"))    {   OUT->Float = tan (M1);           }
+  if (!strcmp (op, "dsin"))   {   OUT->Float = sin (M1*RAD_DEG);   }
+  if (!strcmp (op, "dcos"))   {   OUT->Float = cos (M1*RAD_DEG);   }
+  if (!strcmp (op, "dtan"))   {   OUT->Float = tan (M1*RAD_DEG);   }
+  if (!strcmp (op, "asin"))   {   OUT->Float = asin (M1);          }
+  if (!strcmp (op, "acos"))   {   OUT->Float = acos (M1);          }
+  if (!strcmp (op, "atan"))   {   OUT->Float = atan (M1);          }
+  if (!strcmp (op, "dasin"))  {   OUT->Float = asin (M1)*DEG_RAD;  }
+  if (!strcmp (op, "dacos"))  {   OUT->Float = acos (M1)*DEG_RAD;  }
+  if (!strcmp (op, "datan"))  {   OUT->Float = atan (M1)*DEG_RAD;  }
+  if (!strcmp (op, "rnd"))    {   OUT->Float = drand48();          }
+  if (!strcmp (op, "not"))    {   OUT->Float = !(M1);              }
+  if (!strcmp (op, "--"))     {   OUT->Float = - (M1);             }
+  if (!strcmp (op, "isinf"))  {   OUT->Float = !finite(M1);        }
+  if (!strcmp (op, "isnan"))  {   OUT->Float = isnan(M1);          } 
+
+  return (OUT);
+}
+
+int dbStackAllocPrint () {
+
+  fprintf (stderr, "dbAllocBinary: %d\n", NallocBinary);
+  fprintf (stderr, "dbAllocUnary:  %d\n", NallocUnary);
+  return (TRUE);
+}
+
+int dbStackAllocReset () {
+
+  NallocBinary = 0;
+  NallocUnary = 0;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbStackOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbStackOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dbStackOps.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "dvoshell.h"
+
+void dbInitStack (dbStack *stack) {
+  stack[0].type   = 0;
+  stack[0].name   = NULL;
+}
+
+// free data for stack entries (free stack explicitly)
+void dbFreeStack (dbStack *stack, int Nstack) {
+
+  int i;
+
+  if (stack == NULL) return;
+
+  for (i = 0; i < Nstack; i++) {
+    if (stack[i].name != NULL) {
+      free (stack[i].name);
+      stack[i].name = NULL;
+    }
+  }
+}
+
+static int NfreeStack = 0;
+
+/* delete name and data */
+void dbFreeEntry (dbStack *stack) {
+
+  if (stack[0].name != NULL)  free (stack[0].name);
+  free (stack);
+  NfreeStack ++;
+}
+
+/* delete name and data */
+void dbFreeTempEntry (dbStack *stack) {
+
+  if (stack->type != 'T') return;
+
+  if (stack[0].name != NULL)  free (stack[0].name);
+  free (stack);
+  NfreeStack ++;
+}
+
+void dbStackFreePrint () {
+
+  fprintf (stderr, "dbFreeStack: %d\n", NfreeStack);
+}
+
+void dbStackFreeReset () {
+
+  NfreeStack = 0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/db_check_stack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/db_check_stack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/db_check_stack.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "opihi.h"
+
+int db_check_stack (dvoStack *stack, int Nstack, int table, dvoField *fields, int *Nfields) {
+
+  int i, Nx, Ny, Nv, size;
+  char *c;
+
+  NFIELDS = *Nfields + 10;
+  REALLOCATE (fields, dvoField, NFIELDS);
+
+  for (i = 0; i < Nstack; i++) {
+    if (stack[i].type == 'X') {
+
+      /** if this is a number, put it on the list of scalers and move on **/
+      stack[i].Float = strtod (stack[i].name, &c);
+      if (c == stack[i].name + strlen (stack[i].name)) {
+	stack[i].type  = 'S';
+	continue;
+      } 
+
+      // this must be a field : is it already in the list?
+      for (j = 0; (j < *Nfields) && strcasecmp (stack[i].name, fields[j].name); j++);
+      if (j < *Nfields) {
+	stack[i].field = j;
+	stack[i].type  = 'F';
+	continue;
+      }
+
+      // this must be a field : is it a valid name?
+      if (table == DVO_TABLE_MEASURE) {
+	status = ParseMeasureField (&fields[*Nfields], stack[i].name);
+      } 
+      if (table == DVO_TABLE_AVERAGE) {
+	status = ParseAverageField (&fields[*Nfields], stack[i].name);
+      } 
+      if (!status) {
+	gprint (GP_ERR, "unknown database field %s\n", stack[i].name);
+	return (FALSE);
+      }
+      stack[i].field = *Nfields;
+      stack[i].type  = 'F';
+
+      *Nfields ++;
+      CHECK_REALLOCATE (fields, dvoField, NFIELDS, *Nfields, 10);
+    }
+  }
+  return (TRUE);
+}
+
+/* check stack identifies the data elements as plain scalars or table fields
+   operators have already been identified.  
+   check stack returns the total stack dimensionality (0,1,2)
+   on error, check stack returns FALSE
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/db_convert_to_RPN.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/db_convert_to_RPN.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/db_convert_to_RPN.c	(revision 16632)
@@ -0,0 +1,210 @@
+# include "opihi.h"
+# define DUMPSTACK 0
+
+dvoStack *convert_to_RPN (int argc, char **argv, int *nstack) {
+  
+  int type, Nx, Ny;
+  int i, j, Nstack, Nop_stack, NSTACK;
+  dvoStack *stack, *op_stack;
+
+  /* max total stack size is argc, though should be less, this is safe */
+  NSTACK = argc + 5;
+  ALLOCATE (stack, dvoStack, NSTACK);
+  ALLOCATE (op_stack, dvoStack, NSTACK);
+  for (i = 0; i < NSTACK; i++) {
+    init_stack (&stack[i]);
+    init_stack (&op_stack[i]);
+  }
+  
+  Nx = Ny = Nstack = Nop_stack = 0;
+  for (i = 0; i < argc; i++) {
+    
+    /* decide on priority of object */
+    type = 0;
+    /* unary operations */
+    if (!strcmp (argv[i], "abs"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "int"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "exp"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ten"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "log"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ln"))     { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "sqrt"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "erf"))    { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "sinh"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "cosh"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "asinh"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "acosh"))  { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "sin"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "cos"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "tan"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dsin"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dcos"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dtan"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "asin"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "acos"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "atan"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dasin"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dacos"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "datan"))  { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "lgamma")) { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "rnd"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "xramp"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "yramp"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ramp"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "zero"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "--"))     { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "not"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "isinf"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "isnan"))  { type = 9; goto gotit; }
+
+    /* binary operations */
+    if (!strcmp (argv[i], "^"))      { type = 8; goto gotit; }
+
+    if (!strcmp (argv[i], "@"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "/"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "*"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "%"))      { type = 7; goto gotit; }
+
+    if (!strcmp (argv[i], "+"))      { type = 6; goto gotit; }
+    if (!strcmp (argv[i], "-"))      { type = 6; goto gotit; }
+	
+    if (!strcmp (argv[i], "&"))      { type = 5; goto gotit; }
+    if (!strcmp (argv[i], "|"))      { type = 5; goto gotit; }
+
+    if (!strcmp (argv[i], "<"))      { type = 4; goto gotit; }
+    if (!strcmp (argv[i], ">"))      { type = 4; goto gotit; }
+    if (!strcmp (argv[i], "=="))     { type = 4; strcpy (argv[i], "E"); goto gotit; }
+    if (!strcmp (argv[i], "!="))     { type = 4; strcpy (argv[i], "N"); goto gotit; }
+    if (!strcmp (argv[i], "<="))     { type = 4; strcpy (argv[i], "L"); goto gotit; }
+    if (!strcmp (argv[i], ">="))     { type = 4; strcpy (argv[i], "G"); goto gotit; }
+    if (!strcmp (argv[i], ">>"))     { type = 4; strcpy (argv[i], "U"); goto gotit; }
+    if (!strcmp (argv[i], "<<"))     { type = 4; strcpy (argv[i], "D"); goto gotit; }
+
+    if (!strcmp (argv[i], "&&"))     { type = 3; strcpy (argv[i], "A"); goto gotit; }
+    if (!strcmp (argv[i], "||"))     { type = 3; strcpy (argv[i], "O"); goto gotit; }
+
+    if (!strcmp (argv[i], "("))      { type = 2; goto gotit; }
+    if (!strcmp (argv[i], ")"))      { type = 1; goto gotit; }
+
+  gotit:
+    /* choose how to deal with object */
+    switch (type) {
+      case 8:  /* exponentiation: 2^2^3 = 64 != 256 (precedence is right-to-left, not left-to-right!) */
+	/* pop previous, higher operators from OP stack to stack */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type > type); j--) {
+	  strcpy (stack[Nstack].name, op_stack[j].name);
+	  stack[Nstack].type = op_stack[j].type;
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	/* push operator on OP stack */
+	strcpy (op_stack[Nop_stack].name, argv[i]);
+	op_stack[Nop_stack].type = type;
+	Nop_stack ++;
+	break;
+      case 9: /* unary OPs */
+      case 7: /* binary OPs */
+      case 6:
+      case 5: 
+      case 4: 
+      case 3: 
+	/* pop previous, higher or equal operators from OP stack to stack */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type >= type); j--) {
+	  strcpy (stack[Nstack].name, op_stack[j].name);
+	  stack[Nstack].type = op_stack[j].type;
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	/* push operator on OP stack */
+	strcpy (op_stack[Nop_stack].name, argv[i]);
+	op_stack[Nop_stack].type = type;
+	Nop_stack ++;
+	break;
+      case 2:  
+	/* push operator on OP stack */
+	strcpy (op_stack[Nop_stack].name, argv[i]);
+	op_stack[Nop_stack].type = type;
+	Nop_stack ++;
+	break;
+      case 1: 
+	/* pop rest of operators from OP stack to stack, looking for '(' */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type != 2); j--) {
+	  strcpy (stack[Nstack].name, op_stack[j].name);
+	  stack[Nstack].type = op_stack[j].type;
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	if ((j == -1) || (op_stack[j].type != 2)) {
+	  push_error ("syntax error: mismatched parenthesis");
+	  Nstack = 0;
+	  goto cleanup;
+	}
+	Nop_stack --;
+	break;
+      case 0:
+	/* place the value (number or vector/matrix name) on stack */
+	/* value of 'X' is used as sentinel until we sort out values */
+	strcpy (stack[Nstack].name, argv[i]);
+	stack[Nstack].type = 'X';
+	Nstack ++;
+	break;
+    }
+  }
+
+  /* dump remaining operators on stack, checking for ')' */
+  for (j = Nop_stack - 1; j >= 0; j--) {
+    if (op_stack[j].type == 2) {
+      push_error ("syntax error: mismatched parenthesis");
+      Nstack = 0;
+      goto cleanup;
+    }
+    strcpy (stack[Nstack].name, op_stack[j].name);
+    stack[Nstack].type = op_stack[j].type;
+    Nstack ++;
+  }
+
+cleanup: 
+  /*** free up unused stack space ***/
+  clean_stack (op_stack, NSTACK);
+  free (op_stack);
+  clean_stack (&stack[Nstack], NSTACK - Nstack);
+  REALLOCATE (stack, dvoStack, MAX (Nstack, 1));
+  *nstack = Nstack;
+
+  for (i = 0; i < argc; i++) {
+    free (argv[i]);
+  }
+  free (argv);
+
+# if (DUMPSTACK)
+  for (i = 0; i < Nstack; i++) {
+    gprint (GP_ERR, "%s ", stack[i].name);
+  }
+  if (Nstack > 0) gprint (GP_ERR, "\n");
+  for (i = 0; i < Nstack; i++) {
+    gprint (GP_ERR, "%d ", stack[i].type);
+  }
+  if (Nstack > 0) gprint (GP_ERR, "\n");
+# endif
+
+  return (stack);
+
+}
+
+/* here are the rules for parsing a math AOL line to RPN:
+
+1) if object is a number, push on stack
+2) if object is a third order operand (exp, sin, cos), push on op stack
+3) if object is an open paren, push on op stack,
+4) if object is a second order operand, push on stack
+5) if object is a first order operand, pop all second order operands from stack 
+until paren, push on stack
+6) if object is an end paren, pop all objects from stack until paren, 
+pop next stack, if third order op
+7) if end of line, pop all remaining objects, second order first, etc.
+   
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ddmags.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ddmags.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/ddmags.c	(revision 16632)
@@ -0,0 +1,136 @@
+# include "dvoshell.h"
+
+int ddmags (int argc, char **argv) {
+  
+  gprint (GP_ERR, "this function is deprecated\n");
+  return (FALSE);
+
+} 
+
+# if (0) 
+  char *RegionName, *RegionList;
+  double *M1, *M2;
+  int i, m, k, N, Npts, NPTS;
+  int N1, N2, i1, i2, mode[4];
+  int Nsecfilt, KeepNulls;
+
+  Catalog catalog;
+  PhotCode *code[4];
+  SkyList *skylist;
+  Vector *xvec, *yvec;
+
+  /* defaults */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  RegionName = NULL;
+  RegionList = NULL;
+  skylist = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if (!SetRegionSelection (&argc, argv, &RegionName, &RegionList)) goto escape;
+  if (!SetPhotSelections (&argc, argv, 4)) goto usage;
+
+  KeepNulls = FALSE;
+  if ((N = get_argument (argc, argv, "-nulls"))) {
+    KeepNulls = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* interpret command-line options */
+  if (argc != 8) goto usage;
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (strcmp (argv[6], "-")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) return (FALSE);
+  if (!GetPhotcodeInfo (argv[7], &code[3], &mode[3])) return (FALSE);
+  if (!TestPhotSelections (&code[0], &mode[0], MEAS_ZERO)) goto escape;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (RegionName, RegionList)) == NULL) goto escape;
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (k = 0; k < skylist[0].Nregions; k++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[k];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    // gprint (GP_ERR, "seaching %s with %d stars\n", catalog.filename, catalog.Naverage);
+    // ListPhotSelections ();
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M2 = NULL;
+      m = catalog.average[i].offset;
+
+      SetSelectionParam (0);
+      M1 = ExtractDMag (&code[0], &mode[0], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      SetSelectionParam (2);
+      M2 = ExtractDMag (&code[2], &mode[2], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N2);
+      if (N2 == 0) {
+	if (KeepNulls) {
+	  ALLOCATE (M2, double, 1);
+	  N2 = 1;
+	  M2[0] = NAN;
+	} else {
+	  goto skip;
+	}
+      }
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i2 = 0; i2 < N2; i2++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M2[i2];
+	  Npts++;
+	  if (Npts >= NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M2 != NULL) free (M2);
+    }
+    // gprint (GP_ERR, "selected %d stars\n", Npts);
+    dvo_catalog_free (&catalog);
+  }
+  SkyListFree (skylist);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: ddmags F - F : measure.param\n");
+
+escape:
+  SkyListFree (skylist);
+  dvo_catalog_free (&catalog);
+  if (RegionName != NULL) free (RegionName);
+  if (RegionList != NULL) free (RegionList);
+  return (FALSE);
+}
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/detrend.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/detrend.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/detrend.c	(revision 16632)
@@ -0,0 +1,207 @@
+# include "dvoshell.h"
+
+/* qualities to be extracted */
+enum {ZERO, DTIME, SKY, BIAS, FWHM, AIRM, TIME, TEMP};
+
+int detrend (int argc, char **argv) {
+ 
+  FILE *f;
+  int i, Nimage, status, N, TimeSelect;
+  char DataBase[256];
+  time_t tzero, tend;
+  double trange;
+  int TypeSelect, CCDSelect, FilterSelect;
+  char *Filter;
+  int Type, mode, CCD;
+  int NVALUE;
+  float *value;
+  time_t TimeReference;
+  int TimeFormat;
+  Header header;
+  RegImage *pimage;
+  Vector *vec;
+
+  VarConfig ("REGISTRATION_DATABASE", "%s", DataBase);
+
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-trange"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tend)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  Type = 0;
+  TypeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-type"))) {
+    remove_argument (N, &argc, argv);
+    Type = get_image_type (argv[N]);
+    if (Type == T_UNDEF) {
+      gprint (GP_ERR, "ERROR: invalid image type %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TypeSelect = TRUE;
+  }
+
+  CCD = 0;
+  CCDSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-ccd"))) {
+    remove_argument (N, &argc, argv);
+    CCD = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    CCDSelect = TRUE;
+  }
+ 
+  Filter = NULL;
+  FilterSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-filter"))) {
+    remove_argument (N, &argc, argv);
+    Filter = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FilterSelect = TRUE;
+    if (!strcasecmp (Filter, "X")) {
+      FilterSelect = FALSE;
+    }
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: imrough (value)\n");
+    return (FALSE);
+  }
+  gprint (GP_ERR, "  this function is not well-defined.  re-work and re-code\n");
+  return (FALSE);
+  
+  /* identify selection */
+  mode = ZERO;
+  if (!strcasecmp (argv[1], "exptime")) mode = DTIME;
+  if (!strcasecmp (argv[1], "sky")) mode = SKY;
+  if (!strcasecmp (argv[1], "bias")) mode = BIAS;
+  if (!strcasecmp (argv[1], "fwhm")) mode = FWHM;
+  if (!strcasecmp (argv[1], "airmass")) mode = AIRM;
+  if (!strcasecmp (argv[1], "time")) mode = TIME;
+  if (!strcasecmp (argv[1], "temp")) mode = TEMP;
+  if (mode == ZERO) {
+    gprint (GP_ERR, "value may be one of the following:\n");
+    gprint (GP_ERR, " exptime, sky, bias, fwhm, airmass, time\n");
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  /* load in database header */
+  if (!gfits_read_header (DataBase, &header)) {
+    gprint (GP_ERR, "ERROR: trouble reading database header\n");
+    return (FALSE);
+  }
+
+  /* open database */
+  f = fopen (DataBase, "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "ERROR: can't open Registration Database\n");
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET);
+
+  /* load existing data from database */
+  gfits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  ALLOCATE (pimage, RegImage, Nimage);
+  status = fread (pimage, sizeof(RegImage), Nimage, f);
+  fclose (f);
+
+  if (status != Nimage) {
+    gprint (GP_ERR, "ERROR: header and data in dB don't match (%d vs %d)\n", Nimage, status);
+    gfits_free_header (&header);
+    free (pimage);
+    return (FALSE);
+  }
+  gfits_convert_RegImage (pimage, sizeof (RegImage), Nimage);
+
+  N = 0;
+  NVALUE = 1000;
+  REALLOCATE (vec[0].elements, float, NVALUE);
+  value = vec[0].elements;
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+  gprint (GP_ERR, "%ld %d\n", TimeReference, TimeFormat);
+
+  /* get data */
+  for (i = 0; i < Nimage; i++) {
+    /* skip unmatched selections */
+    if (TimeSelect && ((pimage[i].obstime < tzero) || (pimage[i].obstime > tzero + trange))) continue;
+    if (TimeSelect && ((pimage[i].obstime < tzero) || (pimage[i].obstime > tzero + trange))) continue;
+    if (FilterSelect && (strcasecmp (pimage[i].filter, Filter))) continue;
+    if (CCDSelect && (pimage[i].ccd != CCD)) continue;
+    if (TypeSelect && (pimage[i].type != Type)) continue;
+
+    /* assign correct value */
+    switch (mode) {
+    case (DTIME):
+      value[N] = pimage[i].exptime;
+      break;
+    case (TIME):
+      value[N] = TimeValue (pimage[i].obstime, TimeReference, TimeFormat);
+      break;
+    case (SKY):
+      value[N] = pimage[i].sky;
+      break;
+    case (BIAS):
+      value[N] = pimage[i].bias;
+      break;
+    case (FWHM):
+      value[N] = pimage[i].fwhm;
+      break;
+    case (AIRM):
+      value[N] = pimage[i].airmass;
+      break;
+    case (TEMP):
+      value[N] = pimage[i].teltemp_0;
+      break;
+    }
+    N++;
+    if (N >= NVALUE - 1) {
+      NVALUE += 1000;
+      REALLOCATE (vec[0].elements, float, NVALUE);
+      value = vec[0].elements;
+    }
+  }
+
+  REALLOCATE (vec[0].elements, float, MAX (1,N));
+  vec[0].Nelements = N;
+
+  free (pimage);
+  gfits_free_header (&header);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmagaves.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmagaves.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmagaves.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "dvoshell.h"
+
+int dmagaves (int argc, char **argv) {
+  
+  gprint (GP_ERR, "this function is deprecated\n");
+  return (FALSE);
+
+} 
+
+# if (0) 
+  char *RegionName, *RegionList;
+  double *M1, M2;
+  int i, j, k, m, N1;
+  int Npts, NPTS, param, mode[3];
+  int Nsecfilt;
+
+  PhotCode *code[3];
+  Catalog catalog;
+  SkyList *skylist;
+  Vector *xvec, *yvec;
+
+  /* defaults */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  RegionName = NULL;
+  RegionList = NULL;
+  skylist = NULL;
+  code[2] = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if (!SetRegionSelection (&argc, argv, &RegionName, &RegionList)) goto escape;
+  if (!SetPhotSelections (&argc, argv, 3)) goto usage;
+
+  /* interpret command-line options: dmagaves F1 - F2 : (value) */
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  if ((param = GetAverageParam (argv[5])) == AVE_ZERO) goto usage;
+  if (!TestPhotSelections (&code[2], &mode[2], param)) goto escape;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (RegionName, RegionList)) == NULL) goto escape;
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  for (j = 0; j < skylist[0].Nregions; j++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[j];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = NULL;
+      m = catalog.average[i].offset;
+
+      SetSelectionParam (0);
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      SetSelectionParam (2);
+      M2 = ExtractAverages (code[2], mode[2], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], param);
+
+      for (k = 0; k < N1; k++) {
+	xvec[0].elements[Npts] = M1[k];
+	yvec[0].elements[Npts] = M2;
+	Npts++;
+	if (Npts >= NPTS) {
+	  NPTS += 2000;
+	  REALLOCATE (xvec[0].elements, float, NPTS);
+	  REALLOCATE (yvec[0].elements, float, NPTS);
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+    }
+    dvo_catalog_free (&catalog);
+  }
+  SkyListFree (skylist);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: dmagaves F - F : average.param\n");
+  return (FALSE);
+
+escape:
+  SkyListFree (skylist);
+  dvo_catalog_free (&catalog);
+  if (RegionName != NULL) free (RegionName);
+  if (RegionList != NULL) free (RegionList);
+  return (FALSE);
+}
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmagmeas.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmagmeas.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmagmeas.c	(revision 16632)
@@ -0,0 +1,135 @@
+# include "dvoshell.h"
+
+int dmagmeas (int argc, char **argv) {
+  
+  gprint (GP_ERR, "this function is deprecated\n");
+  return (FALSE);
+
+} 
+
+# if (0) 
+  char *RegionName, *RegionList;
+  double *M1, *M3;
+  int i, j, m, i1, i3, N1, N3, N;
+  int Npts, NPTS, param, mode[3];
+  int Nsecfilt, KeepNulls;
+
+  Catalog catalog;
+  PhotCode *code[3];
+  SkyList *skylist;
+  Vector *xvec, *yvec;
+
+  /* defaults */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  RegionName = NULL;
+  RegionList = NULL;
+  skylist = NULL;
+  code[2] = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if (!SetRegionSelection (&argc, argv, &RegionName, &RegionList)) goto escape;
+  if (!SetPhotSelections (&argc, argv, 3)) goto usage;
+
+  KeepNulls = FALSE;
+  if ((N = get_argument (argc, argv, "-nulls"))) {
+    KeepNulls = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* interpret command-line arguments: dmagmeas F1 - F2 : (value) */
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  if ((param = GetMeasureParam (argv[5])) == MEAS_ZERO) goto usage;
+  if (!TestPhotSelections (&code[2], &mode[2], MEAS_ZERO)) goto escape;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (RegionName, RegionList)) == NULL) goto escape;
+  if (!SetImageSelection (((param == MEAS_XMOSAIC) || (param == MEAS_YMOSAIC)), ((RegionName == NULL) && (RegionList == NULL)))) goto escape;
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (j = 0; j < skylist[0].Nregions; j++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[j];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M3 = NULL;
+      m = catalog.average[i].offset;
+
+      SetSelectionParam (0);
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      SetSelectionParam (2);
+      M3 = ExtractMeasures (code[2], mode[2], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N3, param);
+      if (N3 == 0) {
+	if (KeepNulls) {
+	  ALLOCATE (M3, double, 1);
+	  N3 = 1;
+	  M3[0] = NAN;
+	} else {
+	  goto skip;
+	}
+      }
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i3 = 0; i3 < N3; i3++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M3[i3];
+	  Npts++;
+	  if (Npts >= NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M3 != NULL) free (M3);
+    }
+    dvo_catalog_free (&catalog);
+  }
+  FreeImageSelection ();
+  SkyListFree (skylist);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: dmagmeas F - F : measure.param\n");
+  return (FALSE);
+
+escape:
+  FreeImageSelection ();
+  SkyListFree (skylist);
+  dvo_catalog_free (&catalog);
+  if (RegionName != NULL) free (RegionName);
+  if (RegionList != NULL) free (RegionList);
+  return (FALSE);
+}
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmags.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmags.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmags.c	(revision 16632)
@@ -0,0 +1,136 @@
+# include "dvoshell.h"
+
+int dmags (int argc, char **argv) {
+  
+  gprint (GP_ERR, "this function is deprecated\n");
+  return (FALSE);
+
+} 
+
+# if (0) 
+  char *RegionName, *RegionList;
+  double *M1, *M3;
+  int i, j, m, i1, i3, N1, N3, N;
+  int Npts, NPTS, mode[3];
+  int Nsecfilt, KeepNulls;
+
+  PhotCode *code[3];
+  Catalog catalog;
+  SkyList *skylist;
+  Vector *xvec, *yvec;
+
+  /* defaults */
+  catalog.average = NULL; 
+  catalog.secfilt = NULL;
+  catalog.measure = NULL;
+  RegionName = NULL;
+  RegionList = NULL;
+  skylist = NULL;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if (!SetRegionSelection (&argc, argv, &RegionName, &RegionList)) goto escape;
+  if (!SetPhotSelections (&argc, argv, 3)) goto usage;
+
+  KeepNulls = FALSE;
+  if ((N = get_argument (argc, argv, "-nulls"))) {
+    KeepNulls = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  /* interpret required command-line arguments: dmags F1 - F2 : F3 */
+  if (argc != 6) { goto usage; }
+  if (strcmp (argv[2], "-")) goto usage;
+  if (strcmp (argv[4], ":")) goto usage;
+  if (!GetPhotcodeInfo (argv[1], &code[0], &mode[0])) goto usage;
+  if (!GetPhotcodeInfo (argv[3], &code[1], &mode[1])) goto usage;
+  if (!GetPhotcodeInfo (argv[5], &code[2], &mode[2])) goto usage;
+  if (!TestPhotSelections (&code[0], &mode[0], MEAS_ZERO)) goto escape;
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (RegionName, RegionList)) == NULL) goto escape;
+
+  /* init vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("xv", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("yv", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  for (j = 0; j < skylist[0].Nregions; j++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[j];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    /* get correct mags, convert to X,Y */
+    for (i = 0; i < catalog.Naverage; i++) {
+      M1 = M3 = NULL;
+      m = catalog.average[i].offset;
+
+      SetSelectionParam (0);
+      M1 = ExtractDMag (code, mode, &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N1);
+      if (N1 == 0) goto skip;
+
+      SetSelectionParam (2);
+      M3 = ExtractMagnitudes (code[2], mode[2], &catalog.average[i], &catalog.secfilt[i*Nsecfilt], &catalog.measure[m], &N3);
+      if (N3 == 0) {
+	if (KeepNulls) {
+	  ALLOCATE (M3, double, 1);
+	  N3 = 1;
+	  M3[0] = NAN;
+	} else {
+	  goto skip;
+	}
+      }
+
+      for (i1 = 0; i1 < N1; i1++) {
+	for (i3 = 0; i3 < N3; i3++) {
+	  xvec[0].elements[Npts] = M1[i1];
+	  yvec[0].elements[Npts] = M3[i3];
+	  Npts++;
+	  if (Npts >= NPTS) {
+	    NPTS += 2000;
+	    REALLOCATE (xvec[0].elements, float, NPTS);
+	    REALLOCATE (yvec[0].elements, float, NPTS);
+	  }
+	}
+      }
+    skip:
+      if (M1 != NULL) free (M1);
+      if (M3 != NULL) free (M3);
+    }
+    dvo_catalog_free (&catalog);
+  }
+
+  /* need to free SkyList / or free all regions as well */
+  SkyListFree (skylist);
+  xvec[0].Nelements = yvec[0].Nelements = Npts;
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: dmags F - F : F\n");
+  gprint (GP_ERR, "    F : any photcodes with matched qualifiers:\n");
+  gprint (GP_ERR, "    pri: F:inst, F:cat, F:sys, F:rel, F:cal, F:ave, F:ref\n");
+  gprint (GP_ERR, "    sec: F:inst, F:cat, F:sys, F:rel, F:cal, F:ave, F:ref\n");
+  gprint (GP_ERR, "    dep: F:inst, F:cat, F:sys, F:rel, F:cal\n");
+  gprint (GP_ERR, "    ref: F:cat\n");
+
+escape:
+  SkyListFree (skylist);
+  dvo_catalog_free (&catalog);
+  if (RegionName != NULL) free (RegionName);
+  if (RegionList != NULL) free (RegionList);
+  return (FALSE);
+}
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmt.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmt.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dmt.c	(revision 16632)
@@ -0,0 +1,157 @@
+# include "dvoshell.h"
+
+/* extract vectors giving delta mags for multiple measurements */ 
+int dmt (int argc, char **argv) {
+  
+  // XXX this needs to be fixed: how to access different graphs at once?
+  gprint (GP_ERR, "ERROR: this function is currently disabled\n");
+  return (FALSE);
+
+# if (0)
+
+  int i, m, k, N, kapa, SaveVectors;
+  int Nsec, Nsecfilt, NPTS;
+  double Radius;
+  float dt1, dt2, dmt1, dmt2;
+  float M0, M1, M2, M3;
+  PhotCode *code;
+  Catalog catalog;
+  Graphdata graphmode, graphsky;
+  SkyTable *sky;
+  SkyList *skylist;
+  Vector Xvec, Yvec, Zvec, Rvec, Dvec;
+  Vector *vec1, *vec2, *vec3, *vec4, *vec5;
+
+  Dvec.elements = Rvec.elements = Zvec.elements = NULL;
+
+  if (!InitPhotcodes ()) return (FALSE);
+
+  vec1 = vec2 = vec3 = vec4 = vec5 = NULL;
+  SaveVectors = FALSE;
+  if ((N = get_argument (argc, argv, "-vect"))) {
+    remove_argument (N, &argc, argv);
+    if ((vec1 = SelectVector ("dmtdmt", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec2 = SelectVector ("dmtvar", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec3 = SelectVector ("dmtmag", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec4 = SelectVector ("dmtra",  ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec5 = SelectVector ("dmtdec", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    SaveVectors = TRUE;
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: dmags filter\n");
+    return (FALSE);
+  }
+
+  if (!GetGraphData (&graphsky, &kapa, NULL)) return (FALSE);
+  if (!GetGraph (&graphmode, NULL, NULL)) return (FALSE);
+
+  if ((code = GetPhotcodebyName (argv[1])) == NULL) {
+    gprint (GP_ERR, "ERROR: photcode not found in photcode table\n");
+    return (FALSE);
+  }
+  if (code[0].type != PHOT_SEC) {
+    gprint (GP_ERR, "first filter must be a average photometry type\n");
+    return (FALSE);
+  }
+  Nsecfilt = GetPhotcodeNsecfilt();
+  Nsec = GetPhotcodeNsec (code[0].code);
+
+  Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, graphsky.coords.crval1, graphsky.coords.crval2, Radius);
+  
+  N = 0;
+  NPTS = catalog.Nmeasure;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  if (SaveVectors) {
+    ALLOCATE (Zvec.elements, float, NPTS);
+    ALLOCATE (Rvec.elements, float, NPTS);
+    ALLOCATE (Dvec.elements, float, NPTS);
+  }
+
+  for (k = 0; k < skylist[0].Nregions; k++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[k];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    for (i = 0; i < catalog.Naverage; i++) {
+      if (catalog.average[i].Nm != 3) continue;
+      m = catalog.average[i].offset;
+      M0 = catalog.secfilt[i*Nsecfilt+Nsec].M;
+      M1 = PhotCat (&catalog.measure[m+0]);
+      M2 = PhotCat (&catalog.measure[m+1]);
+      M3 = PhotCat (&catalog.measure[m+2]);
+
+      dt1 = (catalog.measure[m+0].t < catalog.measure[m+1].t) ? catalog.measure[m+1].t - catalog.measure[m+0].t : -1 * ((float)(catalog.measure[m+1].t - catalog.measure[m+0].t));
+      dt2 = (catalog.measure[m+1].t < catalog.measure[m+2].t) ? catalog.measure[m+2].t - catalog.measure[m+1].t : -1 * ((float)(catalog.measure[m+2].t - catalog.measure[m+1].t));
+      dmt1 = (M2 - M1) / dt1;
+      dmt2 = (M3 - M2) / dt2;
+      Xvec.elements[N] = (dmt1 - dmt2) / (dmt1 + dmt2);
+      Yvec.elements[N] = (dmt1 + dmt2) / 2.0;
+      if (SaveVectors) {
+	Rvec.elements[N] = catalog.average[i].R;
+	Dvec.elements[N] = catalog.average[i].D;
+	Zvec.elements[N] = M0;
+      }
+      N++;
+      if (N == NPTS - 1) {
+	NPTS += 2000;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+	if (SaveVectors) {
+	  REALLOCATE (Zvec.elements, float, NPTS);
+	  REALLOCATE (Rvec.elements, float, NPTS);
+	  REALLOCATE (Dvec.elements, float, NPTS);
+	}
+      }
+    }
+    dvo_catalog_free (&catalog);
+  }
+  Yvec.Nelements = Xvec.Nelements = N;
+  REALLOCATE (Xvec.elements, float, MAX (1, N));
+  REALLOCATE (Yvec.elements, float, MAX (1, N));
+  if (SaveVectors) {
+    Rvec.Nelements = Dvec.Nelements = Zvec.Nelements = N;
+    REALLOCATE (Zvec.elements, float, MAX (1, N));
+    REALLOCATE (Rvec.elements, float, MAX (1, N));
+    REALLOCATE (Dvec.elements, float, MAX (1, N));
+  }
+
+  if (SaveVectors) {
+    free (vec1[0].elements);
+    vec1[0].elements = Yvec.elements;
+    vec1[0].Nelements = Yvec.Nelements;
+    free (vec2[0].elements);
+    vec2[0].elements = Xvec.elements;
+    vec2[0].Nelements = Xvec.Nelements;
+    free (vec3[0].elements);
+    vec3[0].elements = Zvec.elements;
+    vec3[0].Nelements = Zvec.Nelements;
+    free (vec4[0].elements);
+    vec4[0].elements = Rvec.elements;
+    vec4[0].Nelements = Rvec.Nelements;
+    free (vec5[0].elements);
+    vec5[0].elements = Dvec.elements;
+    vec5[0].Nelements = Dvec.Nelements;
+  } else {
+    graphmode.style = 2; /* set style to points */
+    PlotVector (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+  }
+  return (TRUE);
+# endif 
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvo.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvo.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvo.c.in	(revision 16632)
@@ -0,0 +1,73 @@
+# include "dvoshell.h"
+
+# define opihi_name "DVO"
+# define opihi_prompt "dvo: "
+# define opihi_description "desktop virtual observatory\n"
+# define opihi_history ".dvo"
+# define opihi_rcfile ".dvorc"
+
+/* program-dependent initialization */
+void program_init (int *argc, char **argv) {
+  
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitDVO ();
+
+  // XXX don't open the catdir until needed
+  // if (!SetCATDIR (NULL, FALSE)) {
+  //  gprint (GP_ERR, "CATDIR is not defined\n");
+  // }
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  {
+    char *helpdir;
+    char *modules;
+    static char *datadir = "@DATADIR@";
+    ALLOCATE (helpdir, char, strlen(datadir) + strlen("/help") + 2);
+    sprintf (helpdir, "%s/help", datadir);
+    set_str_variable ("HELPDIR", helpdir);
+    free (helpdir);
+    ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+    sprintf (modules, "%s/modules", datadir);
+    set_str_variable ("MODULES:0", modules);
+    set_int_variable ("MODULES:n", 1);
+    free (modules);
+  }
+
+  return;
+}
+
+/* standard welcome message */
+void welcome () {
+  gprint (GP_ERR, "\n");
+  gprint (GP_ERR, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  QuitKapa ();
+  ConfigFree ();
+
+  FreeBasic ();
+  FreeData ();
+  FreeAstro ();
+  FreeDVO ();
+  return;
+}
+
+/* call to opihi shell */
+int main (int argc, char **argv) {
+  int status;
+  status = opihi (argc, argv);
+  exit (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvoBooleanElements.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvoBooleanElements.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvoBooleanElements.c	(revision 16632)
@@ -0,0 +1,158 @@
+# include "opihi.h"
+
+/* local private functions */
+void InsertValue (char c);
+void EndOfString (void);
+int IsAnOp (char *c);
+int IsTwoOp (char *c);
+
+/* local private static variables */
+int Nchar, Nout, NOUT;
+char **out;
+
+// split up the input arguments into appropriate blocks
+char **dvoBooleanElements (int Nin, char **in, int *nout) {
+  
+  int i, j, minus, negate, plus, posate, OpStat, SciNotation;
+
+  NOUT = Nin;
+  Nchar = Nout = 0;
+  ALLOCATE (out, char *, NOUT);
+  ALLOCATE (out[Nout], char, NCHARS);
+
+  for (i = 0; i < Nin; i++) {
+    for (j = 0; j < strlen(in[i]); j++) {
+      SciNotation = FALSE;
+      /* identify 'negate' or 'minus' ops */
+      negate = minus = FALSE;
+      if (in[i][j] == '-') { 
+	minus = TRUE;  
+	/* if - is first thing on line, must be a negator */
+	if ((Nout == 0) && (Nchar == 0)) {  
+	  minus = FALSE;
+	  negate = TRUE;
+	  goto skip1;
+	}
+	/* check previous entry on line */
+	if (Nchar) {
+	  OpStat = IsAnOp (out[Nout]);
+	  if (out[Nout][0] == ')') OpStat = FALSE;
+	} else {
+	  OpStat = IsAnOp (out[Nout-1]);
+	  if (out[Nout-1][0] == ')') OpStat = FALSE;
+	}
+	/* if - follows an operator, must be negator */
+	if (OpStat) {
+	  minus = FALSE;
+	  negate = TRUE;
+	  goto skip1;
+	}
+	/* if - follows 'e' is part of 1e-5 */
+	if (j == 0) goto skip1;
+	if ((in[i][j-1] == 'e') || (in[i][j-1] == 'E')) {
+	  SciNotation = TRUE;
+	  negate = minus = FALSE;
+	}
+      }
+    skip1:
+      /* idenfity 'posate' or 'plus' ops */
+      posate = plus = FALSE;
+      if (in[i][j] == '+') { 
+	plus = TRUE;  
+	/* if + is first thing on line, must be a posator */
+	if ((Nout == 0) && (Nchar == 0)) {  
+	  plus = FALSE;
+	  posate = TRUE;
+	  goto skip2;
+	}
+	/* check previous entry on line */
+	if (Nchar) {
+	  OpStat = IsAnOp (out[Nout]);
+	  if (out[Nout][0] == ')') OpStat = FALSE;
+	} else {
+	  OpStat = IsAnOp (out[Nout-1]);
+	  if (out[Nout-1][0] == ')') OpStat = FALSE;
+	}
+	/* if + follows an operator, must be posator */
+	if (OpStat) {
+	  plus = FALSE;
+	  posate = TRUE;
+	  goto skip2;
+	}
+	/* if + follows 'e' is part of 1e+5 */
+	if (j == 0) goto skip2;
+	if ((in[i][j-1] == 'e') || (in[i][j-1] == 'E')) {
+	  SciNotation = TRUE;
+	  posate = plus = FALSE;
+	}
+      }
+    skip2:
+      /* operators */
+      if (negate || minus || posate || plus || (IsAnOp (&in[i][j]) && !SciNotation)) {
+	if (posate) continue;
+	EndOfString ();
+	/* copy operator to out[Nout] */
+	InsertValue (in[i][j]);
+	if (negate) InsertValue ('-');
+
+	if (IsTwoOp (&in[i][j])) {
+	  InsertValue (in[i][j+1]);
+	  j++;
+	} 
+	EndOfString ();
+	continue;
+      }
+      /* quoted string */
+      if (in[i][j] == '"') {
+	InsertValue (in[i][j]);
+	j++;
+	while ((j < strlen(in[i])) && (in[i][j] != '"')) {
+	  InsertValue (in[i][j]);
+	  j++;
+	}
+	if (in[i][j] != '"') continue;
+	/* 
+	  gprint (GP_ERR, "mismatched quotes\n");
+	  return (FALSE);
+	}
+	*/
+	InsertValue (in[i][j]);
+	EndOfString ();
+	continue;
+      }
+      /* not an operator, not a quoted string */
+      if (!OHANA_WHITESPACE (in[i][j])) {
+	InsertValue (in[i][j]);
+      } else {
+	EndOfString ();
+      }
+    }
+    EndOfString ();
+  }
+
+  /* one extra entry is allocated, free here */
+  free (out[Nout]);
+  *nout = Nout;
+  return (out);
+
+}
+
+void InsertValue (char c) {
+  out[Nout][Nchar] = c;
+  Nchar ++;
+  out[Nout][Nchar] = 0;
+}
+
+void EndOfString () {
+  if (Nchar > 0) {
+    out[Nout][Nchar] = 0;
+    Nout ++;
+    Nchar = 0;
+    
+    if (Nout >= NOUT - 1) {
+      NOUT += 10; 
+      REALLOCATE (out, char *, NOUT); 
+    } 
+    ALLOCATE (out[Nout], char, NCHARS); 
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvoEvaluateStack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvoEvaluateStack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvoEvaluateStack.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "opihi.h"
+
+int CheckBooleanCondition (dvoStack dbStack, int NdbStack, float *values, dvoFields *fields, int Nfields) {
+  
+  int i, j, Nstack;
+  dvoStack **stack, *output;
+
+  Nstack = NdbStack;
+  ALLOCATE (stack, dvoStack *, NdbStack);
+  for (i = 0; i < NdbStack; i++) {
+    stack[i] = &dbStack[i];
+  }
+
+  for (i = 0; i < Nstack; i++) {
+
+    /***** binary operators *****/
+    if ((stack[i].type >= 3) && (stack[i].type <= 8)) {
+
+      // pre-test that op and entries match
+      output = db_binary (stack[i-2], stack[i-1], stack[i].name, fields, Nfields); 
+
+      // free temporary stack items, drop external items
+      clear_stack (stack[i-2]);
+      clear_stack (stack[i-1]);
+
+      stack[i-2] = output;
+      for (j = i + 1; j < Nstack; j++) {
+	stack[j-2] = stack[j];
+      }
+
+      Nstack -= 2;
+      i -= 2;
+      continue;
+    }
+
+    /***** unary operators **/
+    if (stack[i].type == 9) {
+
+      // pre-test that op and entries match
+      output = db_unary (&stack[i-1], stack[i].name, fields, Nfields); 
+
+      // free temporary stack items, drop external items
+      clear_stack (stack[i-2]);
+      clear_stack (stack[i-1]);
+
+      for (j = i + 1; j < Nstack; j++) {
+	stack[j-1] = stack[j];
+      }
+
+      Nstack -= 1;
+      i -= 1;
+      continue;
+    } 
+  }
+
+  // pre-test that op and entries match
+  return (TRUE);
+}
+
+/* delete name and data */
+void clear_stack (dvoStack *stack) {
+
+  if (stack->type != 'T') return;
+  free (stack);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvodb.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvodb.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvodb.c	(revision 16632)
@@ -0,0 +1,77 @@
+
+/* dvo fields and boolean expressions
+   - evaluate the command line:
+     * avextract ra,dec,g,r,i where (uRA < 0.1)
+     1) identify all fields in extraction list
+     2) parse boolean expression
+     3) identify additional fields from expression
+*/
+
+enum {DVO_TABLE_AVERAGE, DVO_TABLE_MEASURE};
+
+// a single db field 
+typedef struct {
+  char *name;
+  int extract;
+  int table;
+  int ID;
+  int magMode;
+  PhotCode *photcode;
+} dvoField;
+
+// db boolean operations
+typedef struct {
+  char   *name;
+  char    type;
+  int     field;
+  float   Float;
+} dvoStack;
+
+dvoField *ParseCmdlineFields (int argc, char **argv, int table, int *last, int *nfields) {
+
+  int i, Nfields, NFIELDS, 
+
+  *nfields = 0;
+  Nfields = 0;
+  NFIELDS = 10;
+  ALLOCATE (fields, dvoField, NFIELDS);
+
+  // examine each argv[i] entry until we reach a where 
+  for (i = 1; (i < argc) && strcasecmp (argv[i], "where"); i++) {
+    // split the word by ","
+    p = argv[i];
+    while (*p) {
+      q = strchr (p, ',');
+      if (q == NULL) {
+	field = strcreate (p);
+	p = p + strlen(p);
+      } else {
+	field = strncreate (p, q-p);
+	p = q + 1;
+      }
+      // identify field for word
+      // need to know which type of fields to look for...
+      // xxx extend this more generally later
+      if (table == DVO_TABLE_MEASURE) {
+	status = ParseMeasureField (&fields[Nfields], field);
+      } 
+      if (table == DVO_TABLE_AVERAGE) {
+	status = ParseAverageField (&fields[Nfields], field);
+      } 
+      if (!status) {
+	gprint (GP_ERR, "unknown database field %s\n", field);
+	free (field);
+	free (fields);
+	return (NULL);
+      }
+      free (field);
+
+      Nfields ++;
+      CHECK_REALLOCATE (fields, dvoField, NFIELDS, Nfields, 10);
+    }
+  }
+
+  *last = i;
+  *nfields = Nfields;
+  return (fields);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvofields.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvofields.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvofields.c	(revision 16632)
@@ -0,0 +1,129 @@
+
+int GetMagMode (char *string) {
+
+  if (!strcasecmp (string, "inst"))  return (MAG_INST);
+  if (!strcasecmp (string, "cat"))   return (MAG_CAT);
+  if (!strcasecmp (string, "sys"))   return (MAG_SYS);
+  if (!strcasecmp (string, "rel"))   return (MAG_REL);
+  if (!strcasecmp (string, "cal"))   return (MAG_CAL);
+  if (!strcasecmp (string, "ave"))   return (MAG_AVE);
+  if (!strcasecmp (string, "ref"))   return (MAG_REF);
+  if (!strcasecmp (string, "err"))   return (MAG_ERR);
+  if (!strcasecmp (string, "chisq")) return (MAG_CHISQ);
+  return (MAG_NONE);
+}
+
+PhotCode *ParsePhotcodeField (char *field, int *mode, int default) {
+
+  char *tmpstring, *p;
+  PhotCode *code;
+
+  *mode = default;
+
+  p = strchr (field, ':');
+  if (p != NULL) {
+    *mode = GetMagMode (p + 1);
+    if (*mode == MAG_NONE) return (NULL);
+    tmpstring = strncreate (field, p - field);
+  } else {
+    tmpstring = strcreate (field);
+  }
+  code = GetPhotcodebyName (tmpstring);
+  free (tmpstring);
+
+  return (code);
+}
+
+# define ESCAPE(F,M) { \
+  field->ID = (F); \
+  field->magMode = (M); \
+  field->photcode = NULL; \
+  return (TRUE);
+
+int ParseMeasureField (dvoField *field, char *fieldName) {
+
+  PhotCode *code;
+
+  field->table = DVO_TABLE_MEASURE;
+  field->name  = strcreate (fieldName);
+
+  if (!strcasecmp (fieldName, "RA"))       ESCAPE (MEAS_RA,   	  MAG_NONE);
+  if (!strcasecmp (fieldName, "DEC"))      ESCAPE (MEAS_DEC,  	  MAG_NONE);
+  if (!strcasecmp (fieldName, "MAG"))      ESCAPE (MEAS_MAG,  	  MAG_REL);
+  if (!strcasecmp (fieldName, "dMAG"))     ESCAPE (MEAS_dMAG, 	  MAG_ERR);
+  if (!strcasecmp (fieldName, "AIRMASS"))  ESCAPE (MEAS_AIRMASS,  MAG_NONE);
+  if (!strcasecmp (fieldName, "EXPTIME"))  ESCAPE (MEAS_EXPTIME,  MAG_NONE);
+  if (!strcasecmp (fieldName, "PHOTCODE")) ESCAPE (MEAS_PHOTCODE, MAG_NONE);
+  if (!strcasecmp (fieldName, "TIME"))     ESCAPE (MEAS_TIME,     MAG_NONE);
+  if (!strcasecmp (fieldName, "dR"))       ESCAPE (MEAS_dR, 	  MAG_NONE);
+  if (!strcasecmp (fieldName, "dD"))       ESCAPE (MEAS_dD, 	  MAG_NONE);
+  if (!strcasecmp (fieldName, "FWHM"))     ESCAPE (MEAS_FWHM,     MAG_NONE);
+  if (!strcasecmp (fieldName, "DOPHOT"))   ESCAPE (MEAS_DOPHOT,   MAG_NONE);
+  if (!strcasecmp (fieldName, "FLAGS"))    ESCAPE (MEAS_FLAGS,    MAG_NONE);
+  if (!strcasecmp (fieldName, "XCCD"))     ESCAPE (MEAS_XCCD, 	  MAG_NONE);
+  if (!strcasecmp (fieldName, "YCCD"))     ESCAPE (MEAS_YCCD, 	  MAG_NONE);
+  if (!strcasecmp (fieldName, "XMOSAIC"))  ESCAPE (MEAS_XMOSAIC,  MAG_NONE);
+  if (!strcasecmp (fieldName, "YMOSAIC"))  ESCAPE (MEAS_YMOSAIC,  MAG_NONE);
+
+  // for words that don't parse, try a photcode
+
+  // check for code:mode in photcode name 
+  code = ParsePhotcodeField (&mode, MAG_REL);
+  if (code == NULL) return (FALSE);
+
+  if (mode == MAG_ERR) {
+    field->ID = MEAS_dMAG;
+  } else {
+    field->ID = MEAS_MAG;
+  }    
+  
+  field->magMode = mode;
+  field->photcode = code;
+  return (TRUE);
+}
+  
+int ParseAverageField (char *fieldName) {
+
+  PhotCode *code;
+
+  field->table = DVO_TABLE_AVERAGE;
+
+  if (!strcasecmp (fieldName, "RA"))    ESCAPE (AVE_RA,        MAG_NONE);
+  if (!strcasecmp (fieldName, "DEC"))   ESCAPE (AVE_DEC,       MAG_NONE);
+  if (!strcasecmp (fieldName, "dRA"))   ESCAPE (AVE_RA_ERR,    MAG_NONE);
+  if (!strcasecmp (fieldName, "dDEC"))  ESCAPE (AVE_DEC_ERR,   MAG_NONE);
+  if (!strcasecmp (fieldName, "uRA"))   ESCAPE (AVE_U_RA,      MAG_NONE);
+  if (!strcasecmp (fieldName, "uDEC"))  ESCAPE (AVE_U_DEC,     MAG_NONE);
+  if (!strcasecmp (fieldName, "duRA"))  ESCAPE (AVE_U_RA_ERR,  MAG_NONE);
+  if (!strcasecmp (fieldName, "duDEC")) ESCAPE (AVE_U_DEC_ERR, MAG_NONE);
+  if (!strcasecmp (fieldName, "PAR"))   ESCAPE (AVE_PAR,       MAG_NONE);
+  if (!strcasecmp (fieldName, "dPAR"))  ESCAPE (AVE_PAR_ERR,   MAG_NONE);
+  if (!strcasecmp (fieldName, "MAG"))   ESCAPE (AVE_MAG,       MAG_AVE);
+  if (!strcasecmp (fieldName, "dMAG"))  ESCAPE (AVE_dMAG,      MAG_AVE_ERR);
+  if (!strcasecmp (fieldName, "NMEAS")) ESCAPE (AVE_NMEAS,     MAG_NONE);
+  if (!strcasecmp (fieldName, "NMISS")) ESCAPE (AVE_NMISS,     MAG_NONE);
+  if (!strcasecmp (fieldName, "Xp"))    ESCAPE (AVE_Xp,        MAG_NONE);
+  if (!strcasecmp (fieldName, "Xm"))    ESCAPE (AVE_Xm,        MAG_CHISQ);
+  if (!strcasecmp (fieldName, "FLAG"))  ESCAPE (AVE_FLAG,      MAG_NONE);
+  if (!strcasecmp (fieldName, "TYPE"))  ESCAPE (AVE_TYPE,      MAG_NONE);
+  if (!strcasecmp (fieldName, "NPHOT")) ESCAPE (AVE_NPHOT,     MAG_NONE);
+  if (!strcasecmp (fieldName, "NCODE")) ESCAPE (AVE_NCODE,     MAG_NONE);
+  if (!strcasecmp (fieldName, "NCRIT")) ESCAPE (AVE_NCRIT,     MAG_NONE);
+
+  // for words that don't parse, try a photcode
+
+  // check for code:mode in photcode name 
+  code = ParsePhotcodeField (&mode, MAG_AVE);
+  if (code == NULL) return (FALSE);
+
+  // need to distinguish phot, sys errors and scatter
+  if (mode == MAG_ERR) {
+    field->ID = MEAS_dMAG;
+  } else {
+    field->ID = MEAS_MAG;
+  }    
+  
+  field->magMode = mode;
+  field->photcode = code;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvomisc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvomisc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/dvomisc.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "dvoshell.h"
+
+void cprecess (Average *average, int Naverage, double in_epoch, double out_epoch) {
+
+  int i;
+  double T;
+  double A, D, RA, DEC, zeta, z, theta;
+  double SA, CA, SD, CD;
+  
+  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;
+  
+  for (i = 0; i < Naverage; i++) {
+    A = average[i].R;
+    D = average[i].D;
+    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;
+    
+    average[i].R = RA;
+    average[i].D = DEC; 
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/elixir.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/elixir.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/elixir.c	(revision 16632)
@@ -0,0 +1,145 @@
+# include "dvoshell.h"
+
+int WriteMsg (char *fifo, char *message);
+int ReadMsg (char *fifo, char **message);
+
+int elixir (int argc, char **argv) {
+  
+  char message[256], cmd[256], ElixirBase[256];
+  char fifo[256], fifodir[256], msgfile[256];
+  char *answer;
+  int N;
+
+  sprintf (cmd, "STATUS");
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "TIMES");
+  }
+  if ((N = get_argument (argc, argv, "-live"))) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "ALIVE");
+  }
+  if ((N = get_argument (argc, argv, "-stop"))) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "STOP");
+  }
+  if ((N = get_argument (argc, argv, "-kill"))) {
+    remove_argument (N, &argc, argv);
+    sprintf (cmd, "ABORT");
+  }
+ 
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: elixir (elixir) [-time] [-live]\n");
+    return (FALSE);
+  }
+
+  if (!VarConfig (argv[1], "%s", ElixirBase)) {
+    gprint (GP_ERR, "elixir %s not in config file\n", argv[1]);
+    return (FALSE);
+  }
+  sprintf (fifo, "%s.msg", ElixirBase);
+  if (!VarConfig ("FIFOS", "%s", fifodir)) {
+    gprint (GP_ERR, "FIFOS not in config, using local /tmp\n");
+    strcpy (fifodir, "/tmp");
+  }
+  sprintf (fifo, "%s.msg", ElixirBase);
+
+  sprintf (msgfile, "%s/EMsg.XXXXXX", fifodir);
+  mkstemp (msgfile);
+  sprintf (message, "%s %s", cmd, msgfile);
+  unlink (msgfile);
+
+  if (!WriteMsg (fifo, message)) {
+    gprint (GP_ERR, "can't access fifo %s\n", fifo);
+    return (FALSE);
+  }
+
+  if (ReadMsg (msgfile, &answer)) {
+    gprint (GP_ERR, "%s\n", answer);
+  } 
+  unlink (msgfile);
+  return (TRUE);
+  
+}
+
+int WriteMsg (char *fifo, char *message) {
+
+  int state, mode;
+  FILE *f;
+
+  /* check lockfile */
+  f = fsetlockfile (fifo, 2.0, LCK_XCLD, &state);
+  if (f == NULL) return (0);
+
+  /* write message to end of file */
+  fseek (f, 0, SEEK_END);
+  fprintf (f, "%s\n", message);
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (fifo, mode);
+
+  fclearlockfile (fifo, f, LCK_XCLD, &state);
+  return (1);
+}
+
+int ReadMsg (char *fifo, char **message) {
+
+  int i, nbytes, Nbytes, NBYTES;
+  char *buffer;
+  int state, mode;
+  FILE *f;
+  struct stat filestat;
+
+  /* wait (2 sec) for file to exist, then try to read it */
+  for (i = 0; (stat (fifo, &filestat) == -1) && (i < 20); i++) {
+    usleep (100000);
+  }
+  if (i >= 20) {
+    gprint (GP_ERR, "no response\n");
+    return (0);
+  }
+
+  /* check lockfile */
+  f = fsetlockfile (fifo, 2.0, LCK_XCLD, &state);
+  if (f == NULL) {
+    gprint (GP_ERR, "message locked (%d)\n", state);
+    return (0);
+  }
+
+  /* if file is empty, return 0 */
+  if (state == LCK_EMPTY) {
+    mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+    chmod (fifo, mode);
+    fclearlockfile (fifo, f, LCK_XCLD, &state);
+    return (0);
+  }  
+
+  Nbytes = 0;
+  NBYTES = 0x1000;
+  ALLOCATE (buffer, char, NBYTES);
+  while (TRUE) {
+    nbytes = fread (&buffer[Nbytes], 1, 0x1000, f);
+    if (nbytes < 0) { 
+      gprint (GP_ERR, "error in ReadMsg -- got -1 bytes\n");
+      return (0);
+    }
+    if (nbytes == 0) break;
+    Nbytes += nbytes;
+    NBYTES += 0x1000;
+    REALLOCATE (buffer, char, NBYTES);
+  }
+  buffer[Nbytes] = 0;
+
+  mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+  chmod (fifo, mode);
+  fclearlockfile (fifo, f, LCK_XCLD, &state);
+
+  if (Nbytes == 0) {
+    free (buffer);
+    return (0);
+  }
+
+  *message = buffer;
+  return (1);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/extract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/extract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/extract.c	(revision 16632)
@@ -0,0 +1,450 @@
+# include "dvoshell.h"
+// XXX EAM : this function is deprecated
+
+enum {ZERO, RA, DEC, MAG, dMAG, Xm, Xp, NMEAS, NMISS, REF, TYPE, NPHOT, NCODE, FLAG};
+
+# define NBYTES 160000
+# define BYTES_STAR 23
+# define BLOCK 1000
+# define DNSTARS 1000
+
+int extract (int argc, char **argv) {
+  
+  FILE *f;
+  int i, Col, N, Nbytes, nbytes, NPTS;
+  int InRegion, GSC, ASCII, LONEOS, mode, loadmode;
+  int j, k, m, Nregions;
+  float M0, m0;
+  char filename[128];
+  float Radius;
+  char catdir[256], gscdir[256];
+  int PhotcodeSelect;
+  char PhotCodeFile[256], code[64];
+  double ZERO_POINT;
+  int Ns, N1, n1, Nsec;
+  int Ngraph;
+  int value;
+  Vector *vec;
+  PhotCodeData photcodes;
+  Graphdata graphmode;
+  Catalog catalog;
+  RegionFile *regions;
+
+  if (!GetGraphData (&graphmode, NULL, NULL)) return (FALSE);
+  if (!InitPhotcodes ()) return (FALSE);
+
+  VarConfig ("GSCDIR", "%s", gscdir);
+  VarConfig ("CATDIR", "%s", catdir);
+
+  regions = (RegionFile *) NULL;
+  ASCII = FALSE;
+  LONEOS = TRUE;
+  GSC = FALSE;
+  if (N = get_argument (argc, argv, "-g")) {
+    remove_argument (N, &argc, argv);
+    GSC = TRUE;
+    ASCII = FALSE;
+    LONEOS = FALSE;
+  }
+
+  Col = 1;
+  if (N = get_argument (argc, argv, "-a")) {
+    remove_argument (N, &argc, argv);
+    ASCII = TRUE;
+    GSC = FALSE;
+    LONEOS = FALSE;
+    Col = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* check for region-based selection */
+  code = NULL;
+  PhotcodeSelect = FALSE;
+  if (N = get_argument (argc, argv, "-photcode")) {
+    PhotcodeSelect = True;
+    remove_argument (N, &argc, argv);
+    if ((code = GetPhotcodebyName (argv[N])) == NULL) {
+      gprint (GP_ERR, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: extract (filename) (value) [-g / -a Ncol] \n");
+    return (FALSE);
+  }
+  
+  InRegion = FALSE;
+  if (!strcmp (argv[1], "-all")) {
+    InRegion = TRUE;
+  }
+
+  /* identify selection */
+  if (LONEOS) {
+    mode = ZERO;
+    if (!strcasecmp (argv[2], "ra")) mode = RA;
+    if (!strcasecmp (argv[2], "dec")) mode = DEC;
+    if (!strcasecmp (argv[2], "mag")) mode = MAG;
+    if (!strcasecmp (argv[2], "Nmeas")) mode = NMEAS;
+    if (!strcasecmp (argv[2], "Nmiss")) mode = NMISS;
+    if (!strcasecmp (argv[2], "Xp")) mode = Xp;
+    if (!strcasecmp (argv[2], "Xm")) mode = Xm;
+    if (!strcasecmp (argv[2], "dM")) mode = dMAG;
+    if (!strcasecmp (argv[2], "flag")) mode = FLAG;
+    if (!strcasecmp (argv[2], "ref")) mode = REF;
+    if (!strcasecmp (argv[2], "type")) mode = TYPE;
+    if (!strcasecmp (argv[2], "Nphot")) mode = NPHOT;
+    if (!strcasecmp (argv[2], "Ncode")) mode = NCODE;
+    if (mode == ZERO) {
+      gprint (GP_ERR, "value may be one of the following:\n");
+      gprint (GP_ERR, " ra dec mag Nmeas Nmiss Xp Xm ID\n");
+      return (FALSE);
+    }
+  }
+
+  if ((mode == REF) && !PhotcodeSelect) {
+    gprint (GP_ERR, "must specify photcode for Reference\n");
+    return (FALSE);
+  }
+  if ((mode == TYPE) && !PhotcodeSelect) {
+    gprint (GP_ERR, "must specify photcode for Type\n");
+    return (FALSE);
+  }
+
+  /* check photcode data / selection validity */
+  Ns = -1;
+  Nsec = GetPhotcodeNsecfilt ();
+  if (PhotcodeSelect) {
+    Ns = GetPhotcodeNsec (code[0].code);
+    if ((mode != REF) && (code[0].type != PHOT_SEC)) {
+      gprint (GP_ERR, "filter must be a average photometry type\n");
+      return (FALSE);
+    }
+    if ((mode == REF) && (code[0].type != PHOT_REF)) {
+      gprint (GP_ERR, "filter must be a REFERENCE photometry type\n");
+      return (FALSE);
+    }
+  }
+
+  if (GSC) {
+    mode = ZERO;
+    if (!strcasecmp (argv[2], "ra")) 
+      mode = RA;
+    if (!strcasecmp (argv[2], "dec")) 
+      mode = DEC;
+    if (!strcasecmp (argv[2], "mag")) 
+      mode = MAG;
+    if (mode == ZERO) {
+      gprint (GP_ERR, "for GSC, value may be one of the following:\n");
+      gprint (GP_ERR, " ra dec mag\n");
+      return (FALSE);
+    }
+  }
+
+  if ((vec = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if (InRegion) {
+    Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+    regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+  } else {
+    Nregions = 1;
+  }
+  
+  /* create storage vector */
+  NPTS = 1000;
+  REALLOCATE (vec[0].elements, float, NPTS);
+  vec[0].Nelements = N = 0;
+
+  /* we loop over Nregions, but for ASCII Nregions = 1 */
+  for (j = 0; j < Nregions; j++) {
+    
+    /* Load in data from an ASCII file list of ra, dec, mag */
+    if (ASCII) {
+      char *tbuffer;
+      double tmp;
+      float *V;
+      
+      f = fopen (argv[1], "r");
+      if (f == (FILE *) NULL) {
+	gprint (GP_ERR, "ERROR: can't open data file: %s\n", argv[1]);
+	/* delete new vector! */
+	return (FALSE);
+      }
+      ALLOCATE (tbuffer, char, 1024);
+      
+      V = vec[0].elements;
+      while (scan_line (f, tbuffer) != EOF) {
+	dparse (&tmp, Col, tbuffer);
+	*V = tmp;
+	V++;
+	N++;
+	if (N == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (vec[0].elements, float, NPTS);
+	  V = &vec[0].elements[N];
+	}
+      }
+      free (tbuffer);
+      vec[0].Nelements = N;
+      REALLOCATE (vec[0].elements, float, MAX(1,N));
+      fclose (f);
+      return (TRUE);
+    }
+    
+    /* load data from the GSC files */
+    if (GSC) {
+      char *tbuffer;
+      double tmp;
+      float *V;
+      
+      if (InRegion) {
+	sprintf (filename, "%s/%s\0", gscdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s\0", gscdir, argv[1]);
+      }
+      
+      f = fopen (filename, "r");
+      if (f == (FILE *) NULL) {
+	gprint (GP_ERR, "no stars in %s, skipping\n", filename);
+	continue;
+      }
+      ALLOCATE (tbuffer, char, (BLOCK*BYTES_STAR));
+      
+      V = &vec[0].elements[N];
+      Nbytes = BLOCK*BYTES_STAR;
+      while ((nbytes = fread (tbuffer, 1, Nbytes, f)) > 0) {
+	for (i = 0; i < nbytes / BYTES_STAR; i++) {
+	  if (mode == RA) {
+	    dparse (&tmp, 1, &tbuffer[i*BYTES_STAR]);
+	    *V = tmp;
+	  }
+	  if (mode == DEC) {
+	    dparse (&tmp, 2, &tbuffer[i*BYTES_STAR]);
+	    *V = tmp;
+	  }
+	  if (mode == MAG) {
+	    dparse (&tmp, 3, &tbuffer[i*BYTES_STAR]);
+	    *V = tmp;
+	  }
+	  V++;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	    V = &vec[0].elements[N];
+	  }
+	}
+      }
+      free (tbuffer);
+      fclose (f);
+    }
+  
+    /* load data from the photometry database files */
+    if (LONEOS) {
+      /* find and open correct file */
+      if (InRegion) {
+	sprintf (filename, "%s/%s\0", catdir, regions[j].name);
+      } else {
+	sprintf (filename, "%s/%s\0", catdir, argv[1]);
+      }
+      catalog.average = (Average *) NULL;
+      catalog.measure = (Measure *) NULL;
+      catalog.secfilt = (SecFilt *) NULL;
+      loadmode = LOAD_AVES | LOAD_SECF;
+      if ((mode == REF) || (mode == TYPE) || (mode == NPHOT) || (mode == NCODE)) 
+	loadmode = loadmode | LOAD_MEAS;
+
+      /* lock, load, unlock catalog */
+      catalog.filename = filename;
+      switch (lock_catalog (&catalog, LCK_SOFT)) {
+      case 2:
+	unlock_catalog (&catalog);
+      case 0:
+	continue;
+      }
+      catalog.catflags = loadmode;
+      if (!load_catalog (&catalog, TRUE)) {
+	unlock_catalog (&catalog);
+	continue;
+      }
+      unlock_catalog (&catalog);
+
+      /* assign vector values */
+      switch (mode) {
+      case (RA):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].R;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (DEC):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].D;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (MAG):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  M0 = (Ns == -1) ? catalog.average[i].M : catalog.secfilt[i*Nsec+Ns].M;
+	  vec[0].elements[N] = M0 / 1000.0;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NMEAS):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].Nm;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NMISS):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].Nn;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (Xp):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  /* Xp is scatter in 1/100 arcsec */
+	  vec[0].elements[N] = 0.01*catalog.average[i].Xp;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NCODE):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  Ncode = 0;
+	  for (k = 0; k < catalog.average[i].Nm; k++, m++) {
+	    if (code[0].code != GetPhotcodeEquivCodebyCode (catalog.measure[m].photcode)) continue;
+	    Ncode ++;
+	  }
+	  vec[0].elements[N] = Ncode;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (NPHOT):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  Ncode = 0;
+	  for (k = 0; k < catalog.average[i].Nm; k++, m++) {
+	    if (code[0].code != GetPhotcodeEquivCodebyCode (catalog.measure[m].photcode)) continue;
+	    if (catalog.measure[m].photcode & (ID_MEAS_POOR | ID_MEAS_SKIP)) continue;
+	    Ncode ++;
+	  }
+	  vec[0].elements[N] = Ncode;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (Xm):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  M0 = (Ns == -1) ? catalog.average[i].Xm : catalog.secfilt[i*Nsec+Ns].Xm;
+	  vec[0].elements[N] = (M0 == NO_MAG) ? -1.0 : pow (10.0, 0.01*M0);
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (dMAG):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  /* dM is 1000.0 * error */
+	  M0 = (Ns == -1) ? catalog.average[i].dM : catalog.secfilt[i*Nsec+Ns].dM;
+	  vec[0].elements[N] = (M0 == NO_MAG) ? -1.0 : 0.001*M0;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (FLAG):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  vec[0].elements[N] = catalog.average[i].code;
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (REF):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  vec[0].elements[N] = -32;
+	  for (k = 0; k < catalog.average[i].Nm; k++) {
+	    if (catalog.measure[m+k].photcode == N1) {
+	      vec[0].elements[N] = PhotCat (&catalog.measure[m+k]);
+	      k = catalog.average[i].Nm;
+	    }
+	  }
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      case (TYPE):
+	for (i = 0; i < catalog.Naverage; i++) {
+	  m = catalog.average[i].offset;
+	  vec[0].elements[N] = DetermineTypeCode (&catalog.average[i], &catalog.measure[m], &photcodes, N1);
+	  N++;
+	  if (N == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (vec[0].elements, float, NPTS);
+	  }
+	}
+	break;
+      }
+      if (catalog.average != 0) free (catalog.average);
+      if (catalog.measure != 0) free (catalog.measure);
+      if (catalog.secfilt != 0) free (catalog.secfilt);
+    }
+  }
+
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, MAX(1,N));
+  return (TRUE);
+
+}
+  
+  /* USAGE: extract (what) (where) (from) [option] */
+  /* examples:
+     extract n0000/n0001 mag m 
+     extract -g n0000/n0020 ra r 
+     extract -all Xm xm
+     extract fred dec d -a 2 */
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/find_regions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/find_regions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/find_regions.c	(revision 16632)
@@ -0,0 +1,156 @@
+# include "dvoshell.h"
+# include "hstgsc.h"
+
+/* returns a list of region files within the desired RA, DEC region */
+RegionFile *find_regions (double Ra, double Dec, double radius, int *Nregions) {
+  
+  char filename[256];
+  char buffer[28800], temp[50];
+  RegionFile *regions;
+  FILE *f;
+  double minRa, maxRa, minDec, maxDec, rad;
+
+  double RA0, RA1, DEC0, DEC1;
+  int i, j, NBigDec;
+  int NLINES, done, NREGIONS, nregion;
+  
+  VarConfig ("GSCFILE", "%s", filename);
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    gprint (GP_ERR, "ERROR: can't find regions file %s\n", filename);
+    *Nregions = 0;
+    return ((RegionFile *) NULL);
+  }
+  
+  NREGIONS = 50;
+  ALLOCATE (regions, RegionFile, NREGIONS);
+  nregion = 0;
+
+  while (Ra < 0) Ra += 360.0;
+  while (Ra >= 360) Ra -= 360.0;
+
+  minDec = Dec - radius;
+  maxDec = Dec + radius;
+
+  if ((minDec <= -90) || (maxDec >= 90)) {
+    minRa = 0;
+    maxRa = 360;
+  } else {
+    rad = MAX (radius / (cos(minDec*RAD_DEG)), radius / (cos(maxDec*RAD_DEG)));
+    minRa = Ra - rad;
+    maxRa = Ra + rad;
+  }
+  
+  /* use the pole regions, if near pole */
+  if (maxDec > 86.25) {
+    sprintf (regions[nregion].name, "n8230/pole.cpt");
+    regions[nregion].RA0 = 0;
+    regions[nregion].RA1 = 360;
+    regions[nregion].DEC0 = 86.25;
+    regions[nregion].DEC1 = 90.0;
+    nregion ++;
+    if (nregion == NREGIONS) {
+      NREGIONS += 50;
+      REALLOCATE (regions, RegionFile, NREGIONS);
+    }
+  }
+
+  if (minDec > 86.25) {
+    return (regions);
+  }
+    
+  if ((minDec < 0) && (maxDec > 0)) {
+    /* Search Both Sides */
+    NBigDec = 0;
+  } else {
+    /* find large DEC region (directory) */
+    NBigDec = -1;
+    for (i = 0; i < 12; i++) {
+      if ((minDec >= BigDecBounds[i]) && (minDec < BigDecBounds[i+1])) {
+	NBigDec = i;
+	break;
+      }
+    }
+    if (NBigDec < 0) {
+      for (i = 13; i < 24; i++) {
+	if ((maxDec < BigDecBounds[i]) && (maxDec >= BigDecBounds[i+1])) {
+	  NBigDec = i;
+	  break;
+	}
+      }
+    }
+  }
+  if (NBigDec < 0) {
+    gprint (GP_ERR, "ERROR: Dec out of range: %f\n", minDec);
+    *Nregions = 0;
+    return ((RegionFile *) NULL);
+  }
+  
+  /* count lines before section */
+  NLINES = 0;
+  for (i = 0; i < NBigDec; i++) {
+    NLINES += NDecLines[i];
+  }
+  fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+  
+  /* should be in this section.  if not, there is a problem counting... */
+  /* careful with the 0,360.0 boundary **/
+  done = FALSE;
+  for (j = 0; !done && (NBigDec + j < 25); j++) {
+    fread (buffer, 48*NDecLines[NBigDec + j], 1, f);
+    for (i = 0; (i < NDecLines[NBigDec + j]); i++) {
+      strncpy (temp, &buffer[i*48], 48);
+      temp[49] = 0;
+      hstgsc_hms_to_deg (&RA0, &RA1, &DEC0, &DEC1, &temp[7]);
+      if (RA1 < RA0) RA1 += 360.0;
+      if ((DEC1 > 0) && (minDec < DEC1) && (maxDec > DEC0) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregion].name, "%s/%s.cpt", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregion].RA0 = RA0;
+	regions[nregion].RA1 = RA1;
+	regions[nregion].DEC0 = DEC0;
+	regions[nregion].DEC1 = DEC1;
+	nregion ++;
+	if (nregion == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, RegionFile, NREGIONS);
+	}
+      }
+      if ((DEC1 < 0) && (minDec < DEC0) && (maxDec > DEC1) && (minRa < RA1) && (maxRa > RA0)) {
+	temp[5] = 0;
+	sprintf (regions[nregion].name, "%s/%s.cpt", Dec2Sections[NBigDec + j], &temp[1]);
+	regions[nregion].RA0 = RA0;
+	regions[nregion].RA1 = RA1;
+	regions[nregion].DEC0 = DEC0;
+	regions[nregion].DEC1 = DEC1;
+	nregion ++;
+	if (nregion == NREGIONS) {
+	  NREGIONS += 50;
+	  REALLOCATE (regions, RegionFile, NREGIONS);
+	}
+      }
+      if (((DEC1 > 0) && (maxDec <= DEC1)) || ((DEC1 < 0) && (minDec >= DEC1))) {
+	done = TRUE;
+      }
+    }
+    if (done && (minDec < 0) && (maxDec > 0) && (BigDecBounds[NBigDec + j + 1] > 0)) {
+      /* skip remaining north sections, try south sections */
+      /* count lines before section */
+      NLINES = 0;
+      for (i = 0; i < 13; i++) { 
+	NLINES += NDecLines[i];
+      }
+      fseek (f, 5*2880 + 48*NLINES, SEEK_SET);
+      done = FALSE;
+      j = 12;
+    }
+  }
+
+  REALLOCATE (regions, RegionFile, MAX(1,nregion));
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (regions);
+  
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/fitcolors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/fitcolors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/fitcolors.c	(revision 16632)
@@ -0,0 +1,390 @@
+# include "dvoshell.h"
+# define NMIN_PTS 100
+
+static void free_catalog (Catalog *catalog, int Ncatalog);
+
+/* this function takes a photcode (and camera name?) and measures the  *
+ * chip-to-chip slopes for all DEP photcodes equiv to the PRI/SEC code */
+
+int fitcolors (int argc, char **argv) {
+  
+  int *list, Nlist;
+  int i, k, m, N, NP1, NP2, NP, Np, Npts, NPTS;
+  int N1, N2, i1, i2, mode[4];
+  int Nsecfilt, status;
+  void *oldsignal;
+  char *cmd, *outcmd, *camera;
+  char name[64], filename[64], plotname[64], label[64];
+  double *M1, *M2;
+  float *out, *colorFit, *deltaFit, dColor, C0, C1;
+  float minDelta, maxDelta, minColor, maxColor;
+  int kapa, Npx, Npy, NPX, NPY, Nplot, PLOT;
+  Graphdata graphdata;
+  KapaSection section;
+
+  Catalog *catalog;
+  PhotCode **codelist, *tcode, *code[4];
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+  Vector *xvec, *yvec;
+  Buffer *buf;
+
+  /* defaults */
+  catalog  = NULL;
+  skylist  = NULL;
+  selection = NULL;
+  codelist = NULL;
+  xvec = yvec = NULL;
+  colorFit = NULL;
+  deltaFit = NULL;
+
+  oldsignal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+  if (!SetPhotSelections (&argc, argv, 4)) goto usage;
+
+  // range for valid data points (exclude extreme outliers)
+  minDelta = -0.2;
+  maxDelta = +0.2;
+  minColor = -1.0;
+  maxColor = +3.0;
+  if ((N = get_argument (argc, argv, "-color-range"))) {
+    remove_argument (N, &argc, argv);
+    minColor = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    maxColor = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-delta-range"))) {
+    remove_argument (N, &argc, argv);
+    minDelta = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    maxDelta = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  PLOT = FALSE;
+  NPX = NPY = 0;
+  if ((N = get_argument (argc, argv, "-plot"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (plotname, argv[N]);
+    remove_argument (N, &argc, argv);
+    NPX = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    NPY = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    PLOT = TRUE;
+  }
+
+  /* interpret command-line options */
+  if (argc != 4) goto usage;
+
+  if (PLOT) {
+    if (!GetGraph (&graphdata, &kapa, NULL)) return (FALSE);
+    Nplot = 0;
+    Npx = Npy = 0;
+    graphdata.xmin = minColor;
+    graphdata.xmax = maxColor;
+    graphdata.ymin = minDelta;
+    graphdata.ymax = maxDelta;
+    graphdata.style = 2;
+    graphdata.ptype = 2;
+    KapaClearSections (kapa);
+    KapaSetFont (kapa, "helvetica", 14);
+
+    ALLOCATE (colorFit, float, 11);
+    ALLOCATE (deltaFit, float, 11);
+    dColor = (maxColor - minColor) / 10.0;
+    for (i = 0; i < 11; i++) {
+      colorFit[i] = minColor + i*dColor;
+    }
+  }
+
+  /* determine relevant photcodes, colors */
+  if (!(Np = GetPhotcodeCodebyName (argv[2]))) {
+    gprint (GP_ERR, "ERROR: photcode not found in photcode table\n");
+    goto usage;
+  }
+  camera = argv[3];
+
+  /* reduce the list of codes */
+  list = GetPhotcodeEquivList (Np, &Nlist);
+  ALLOCATE (codelist, PhotCode *, Nlist);
+  for (i = NP = 0; i < Nlist; i++) {
+    tcode = GetPhotcodebyCode (list[i]);
+    if (strncmp (tcode[0].name, camera, strlen(camera))) continue;
+    codelist[NP] = tcode;
+    NP++;
+  }
+  mode[0] = mode[1] = MAG_REL;  /* we should be applying any relative photometry corrections here */
+  mode[2] = mode[3] = MAG_AVE;
+
+  /* set the reference colors */
+  code[2] = GetPhotcodebyCode (codelist[0][0].c1);
+  code[3] = GetPhotcodebyCode (codelist[0][0].c2);
+  if ((code[2] == NULL) || (code[3] == NULL)) goto color_missing;
+
+  /* all codes must have the same colors (validate) */
+  for (i = 0; i < NP; i++) {
+    if (codelist[i][0].c1 != codelist[0][0].c1) goto color_mismatch;
+    if (codelist[i][0].c2 != codelist[0][0].c2) goto color_mismatch;
+  }
+  gprint (GP_ERR, "using %d photcodes\n", NP);
+
+  /* output is a named buffer */
+  if ((buf = SelectBuffer (argv[1], ANYVECTOR, TRUE)) == NULL) goto usage;
+
+  gfits_free_matrix (&buf[0].matrix);
+  gfits_free_header (&buf[0].header);
+  CreateBuffer (buf, NP, NP, -32, 0.0, 1.0);
+  strcpy (buf[0].file, "(empty)");
+
+  out = (float *) buf[0].matrix.buffer;
+  /* we set a default flag value of -1 */
+  for (i = 0; i < NP*NP; i++) {
+    out[i] = -1;
+  }
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  ALLOCATE (catalog, Catalog, skylist[0].Nregions);
+  for (k = 0; k < skylist[0].Nregions; k++) {
+    /* lock, load, unlock catalog */
+    catalog[k].filename = skylist[0].filename[k];
+    catalog[k].catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog[k].Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog[k], NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog[k].filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog[k]);
+    // XXX make a subset catalog consisting of only Average and Measure values which meet
+    // the selection criteria
+  }
+  gprint (GP_ERR, "using %d possible regions\n", skylist[0].Nregions);
+
+  /* vectors to save data */
+  Npts = 0;
+  NPTS = 1;
+  if ((xvec = SelectVector ("tmp_x", ANYVECTOR, TRUE)) == NULL) goto escape;
+  if ((yvec = SelectVector ("tmp_y", ANYVECTOR, TRUE)) == NULL) goto escape;
+
+  // set up basic windows
+  if (PLOT) {
+    Nplot = 0;
+    Npx = Npy = 0;
+    NPX = NPY = 6;
+    KapaInitGraph (&graphdata);
+    graphdata.xmin = minColor;
+    graphdata.xmax = maxColor;
+    graphdata.ymin = minDelta;
+    graphdata.ymax = maxDelta;
+    graphdata.style = 2;
+    graphdata.ptype = 2;
+  }
+
+  /*** generate the color-color vectors for the pairs ***/
+  // XXXX this function also needs to check for interrupts
+  // XXX exclude obvious outliers (eg, fabs(dM) > 0.2)
+  /* loop over chip photcode pairs */
+  for (NP1 = 0; NP1 < NP; NP1++) {
+    for (NP2 = NP1 + 1; NP2 < NP; NP2++) {
+      code[0] = codelist[NP1];
+      code[1] = codelist[NP2];
+      
+      /* extract all magnitude pairs from catalog tables */
+      Npts = 0;
+      for (k = 0; k < skylist[0].Nregions; k++) {
+	if (catalog[k].Naverage == 0) continue;
+
+	// gprint (GP_ERR, "seaching %s with %d stars\n", catalog[k].filename, catalog[k].Naverage);
+	// ListPhotSelections ();
+
+	/* get correct mags, convert to X,Y */
+	for (i = 0; i < catalog[k].Naverage; i++) {
+	  if (interrupt) goto escape;
+
+	  M1 = M2 = NULL;
+	  m = catalog[k].average[i].offset;
+
+	  SetSelectionParam (0);
+	  M1 = ExtractDMag (&code[0], &mode[0], &catalog[k].average[i], &catalog[k].secfilt[i*Nsecfilt], &catalog[k].measure[m], &N1);
+	  if (N1 == 0) goto skip_star;
+
+	  SetSelectionParam (2);
+	  M2 = ExtractDMag (&code[2], &mode[2], &catalog[k].average[i], &catalog[k].secfilt[i*Nsecfilt], &catalog[k].measure[m], &N2);
+	  if (N2 == 0) goto skip_star;
+
+	  for (i1 = 0; i1 < N1; i1++) {
+	    for (i2 = 0; i2 < N2; i2++) {
+	      if (M1[i1] < minDelta) continue;
+	      if (M1[i1] > maxDelta) continue;
+	      if (M2[i2] < minColor) continue;
+	      if (M2[i2] > maxColor) continue;
+	      yvec[0].elements[Npts] = M1[i1];
+	      xvec[0].elements[Npts] = M2[i2];
+	      Npts++;
+	      if (Npts >= NPTS) {
+		NPTS += 2000;
+		REALLOCATE (xvec[0].elements, float, NPTS);
+		REALLOCATE (yvec[0].elements, float, NPTS);
+	      }
+	    }
+	  }
+	skip_star:
+	  if (M1 != NULL) free (M1);
+	  if (M2 != NULL) free (M2);
+	}
+	// gprint (GP_ERR, "selected %d stars\n", Npts);
+      }
+
+      if (Npts < NMIN_PTS) continue;
+      xvec[0].Nelements = Npts;
+      yvec[0].Nelements = Npts;
+
+      /* perform robust fit on dmag vs color */
+      cmd = strcreate ("fit tmp_x tmp_y 1 -clip 3 3 -quiet");
+      status = command (cmd, &outcmd, TRUE);
+      if (outcmd != NULL) free (outcmd);
+      
+      C0 = get_double_variable ("C0", &status);
+      C1 = get_double_variable ("C1", &status);
+      
+      /* do something useful with the results (stored in Cn, C0, C1, etc) */
+      gprint (GP_LOG, "%s - %s : ", code[0][0].name, code[1][0].name);
+      gprint (GP_LOG, "%7.4f %7.4f   %7.4f   ", 
+	       C0, C1, get_double_variable ("dC", &status));
+      gprint (GP_LOG, "%5s of %5d\n", get_variable ("Cnv"), Npts);
+      out[NP1 + NP2*NP] = C1;
+
+      // make an illustrating plot of each chip vs each other chip
+      // each page should have, say, a 6x6 grid of plots. each one should show a single chip pair
+      // as the page fills up, it gets written and a new one created.  
+      if (PLOT) {
+	sprintf (name, "s%02d.%02d", Npx, Npy);
+	section.name = strcreate (name);
+	if (Npx || Npy) {
+	  section.dx = 0.9 / NPX;
+	  section.dy = 0.9 / NPY;
+	  section.x = 0.1 + Npx * section.dx;
+	  section.y = 0.1 + Npy * section.dy;
+	  strcpy (graphdata.labels, "0000");
+	} 
+	if (Npx == 0) {
+	  section.dx = 0.9 / NPX + 0.1;
+	  section.dy = 0.9 / NPY;
+	  section.x = 0.0;
+	  section.y = 0.1 + Npy * section.dy;
+	  strcpy (graphdata.labels, "0100");
+	}
+	if (Npy == 0) {
+	  section.dx = 0.9 / NPX;
+	  section.dy = 0.9 / NPY + 0.1;
+	  section.x = 0.1 + Npx * section.dx;
+	  section.y = 0.0;
+	  strcpy (graphdata.labels, "1000");
+	}
+	if (!Npx && !Npy) {
+	  section.dx = 0.9 / NPX + 0.1;
+	  section.dy = 0.9 / NPY + 0.1;
+	  section.x = 0.0;
+	  section.y = 0.0;
+	  strcpy (graphdata.labels, "1100");
+	}
+	KapaSetSection (kapa, &section);
+	KapaSetLimits (kapa, &graphdata);
+	KapaBox (kapa, &graphdata);
+	KapaPrepPlot (kapa, Npts, &graphdata);
+	KapaPlotVector (kapa, Npts, xvec[0].elements, "x");
+	KapaPlotVector (kapa, Npts, yvec[0].elements, "y");
+
+	for (i = 0; i < 11; i++) {
+	  deltaFit[i] = C0 + C1*colorFit[i];
+	}
+	graphdata.style = 0;
+	graphdata.color = KapaColorByName ("red");
+	KapaPrepPlot (kapa, 11, &graphdata);
+	KapaPlotVector (kapa, 11, colorFit, "x");
+	KapaPlotVector (kapa, 11, deltaFit, "y");
+
+	KapaSetFont (kapa, "helvetica", 8);
+	sprintf (label, "%s", code[0][0].name);
+	KapaSendTextline (kapa, label, 0.2*maxColor + 0.8*minColor, 0.8*maxDelta + 0.2*minDelta, 0.0);
+	sprintf (label, "%s", code[1][0].name);
+	KapaSendTextline (kapa, label, 0.2*maxColor + 0.8*minColor, 0.2*maxDelta + 0.8*minDelta, 0.0);
+	KapaSetFont (kapa, "helvetica", 14);
+
+	graphdata.style = 2;
+	graphdata.color = KapaColorByName ("black");
+
+	free (section.name);
+
+	Npx++;
+	if (Npx == NPX) {
+	  Npx = 0;
+	  Npy ++;
+	  if (Npy == NPY) {
+	    Npy = 0;
+	    sprintf (filename, "%s.%02d.png", plotname, Nplot);
+	    KapaPNG (kapa, filename);
+	    KapaClearSections (kapa);
+	    Nplot++;
+	  }
+	}
+      }	
+    }
+  }
+  if (skylist != NULL) free_catalog (catalog, skylist[0].Nregions);
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  if (codelist != NULL) free (codelist);
+  if (colorFit != NULL) free (colorFit);
+  if (deltaFit != NULL) free (deltaFit);
+  signal (SIGINT, oldsignal);
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: chipcolors (output) (photcode) (camera)\n");
+  goto escape;
+
+color_missing:
+  gprint (GP_ERR, "error: chips are missing a color reference\n");
+  goto escape;
+
+color_mismatch:
+  gprint (GP_ERR, "error: all chips must have the same colors\n");
+  goto escape;
+
+escape:
+  if (skylist != NULL) free_catalog (catalog, skylist[0].Nregions);
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  if (codelist != NULL) free (codelist);
+  if (colorFit != NULL) free (colorFit);
+  if (deltaFit != NULL) free (deltaFit);
+  DeleteVector (xvec);
+  DeleteVector (yvec);
+  signal (SIGINT, oldsignal);
+  return (FALSE);
+}
+
+static void free_catalog (Catalog *catalog, int Ncatalog) {
+
+  int i;
+
+  if (catalog == NULL) return;
+  for (i = 0; i < Ncatalog; i++) {
+    dvo_catalog_free (&catalog[i]);
+  }
+  free (catalog);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/fitsed.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/fitsed.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/fitsed.c	(revision 16632)
@@ -0,0 +1,458 @@
+# include "dvoshell.h"
+
+typedef struct {
+  float *mags;
+  float color;
+  float Temp;
+  float Av;
+} SEDtableRow;
+
+typedef struct {
+  float chisq;
+  float Md;
+  int row;
+} SEDfit;
+
+SEDtableRow **sort_SEDtable (SEDtableRow *raw, int N);
+int SEDcolorBracket (SEDtableRow **table, int Ntable, float color);
+SEDfit SEDchisq (SEDtableRow *ref, SEDtableRow *data, SEDtableRow *error, int Nfilter);
+
+/* this function takes a photcode (and camera name?) and measures the  *
+ * chip-to-chip slopes for all DEP photcodes equiv to the PRI/SEC code */
+
+int fitsed (int argc, char **argv) {
+  
+  int *hashcode;
+  int i, j, k, m, N, done, Nfit;
+  int Nsecfilt, status;
+  void *oldsignal;
+  char name[64], line[1024], key[20];
+  float *fitmags, *fiterrs, *wavecode, *vegaToAB;
+  float color;
+  double X, Y, ZP, RA, DEC;
+  int kapa, PLOT;
+  int Nrow, NROW, idx, Nfilter, start, row;
+  unsigned short colorP, colorM, code, USNOred, USNOblu;
+  int codeP, codeM;
+  FILE *f;
+
+  Graphdata graphdata;
+  KapaSection magSection, resSection;
+
+  Catalog catalog, outcat;
+  SkyList *skylist;
+  SkyRegionSelection *selection;
+
+  SEDtableRow *SEDtableRaw, **SEDtable;
+  SEDtableRow sourceValue, sourceError;
+  SEDfit minFit, testFit;
+
+  /* defaults */
+  skylist  = NULL;
+  selection = NULL;
+
+  catalog.average = NULL;
+  catalog.measure = NULL;
+  catalog.secfilt = NULL;
+
+  outcat.average = NULL;
+  outcat.measure = NULL;
+  outcat.secfilt = NULL;
+
+  SEDtable = NULL;
+  SEDtableRaw = NULL;
+  sourceValue.mags = NULL;
+  sourceError.mags = NULL;
+  wavecode = NULL;
+  hashcode = NULL;
+  magSection.name = NULL;
+  resSection.name = NULL;
+
+  Nrow = 0;
+
+  fiterrs = NULL;
+  fitmags = NULL;
+
+  oldsignal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  /* interpret command-line options */
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+  if (!SetPhotSelections (&argc, argv, 4)) goto usage;
+
+  PLOT = FALSE;
+  if ((N = get_argument (argc, argv, "-plot"))) {
+    remove_argument (N, &argc, argv);
+    PLOT = TRUE;
+  }
+
+  /* interpret command-line options */
+  if (argc != 6) goto usage;
+
+  Nfit = 0;
+  colorP = GetPhotcodeCodebyName (argv[3]);
+  colorM = GetPhotcodeCodebyName (argv[5]);
+  if (!colorP || !colorM) goto color_undefined;
+
+  // artificially set USNOred and blu errors to 0.3
+  USNOred = GetPhotcodeCodebyName ("USNO_RED");
+  USNOblu = GetPhotcodeCodebyName ("USNO_BLUE");
+
+  // load SED table
+  f = fopen (argv[1], "r");
+  if (f == NULL) goto table_missing;
+
+  // XXX add error checks for header data
+  scan_line (f, line);
+  sscanf (line, "%*s %*s %d", &Nfilter);
+
+  // load SED table photcodes, generate the photcode hashtable
+  ALLOCATE (hashcode, int, 0x10000);
+  ALLOCATE (wavecode, float, Nfilter);
+  ALLOCATE (vegaToAB, float, Nfilter);
+
+  for (i = 0; i < 0x10000; i++) hashcode[i] = -1;
+  for (i = 0; i < Nfilter; i++) {
+    scan_line (f, line);
+    sscanf (line, "%*s %s %f %f", name, &wavecode[i], &vegaToAB[i]);
+    code = GetPhotcodeCodebyName (name);
+    if (code == 0) goto code_missing;
+    hashcode[code] = i;
+  }
+  codeP = hashcode[colorP];
+  codeM = hashcode[colorM];
+  if ((codeP == -1) || (codeM == -1)) goto color_missing;
+    
+  // skip remaining header lines
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  scan_line (f, line);
+  
+  // load the SED table data
+  Nrow = 0;
+  NROW = 100;
+  ALLOCATE (SEDtableRaw, SEDtableRow, NROW);
+  while (scan_line(f, line) != EOF) {
+    fparse (&SEDtableRaw[Nrow].Temp, 1, line);
+    fparse (&SEDtableRaw[Nrow].Av, 2, line);
+    ALLOCATE (SEDtableRaw[Nrow].mags, float, Nfilter);
+    for (i = 0; i < Nfilter; i++) {
+      fparse (&SEDtableRaw[Nrow].mags[i], i + 3, line);
+    }
+    SEDtableRaw[Nrow].color = SEDtableRaw[Nrow].mags[codeP] - SEDtableRaw[Nrow].mags[codeM];
+    Nrow ++;
+    CHECK_REALLOCATE (SEDtableRaw, SEDtableRow, NROW, Nrow, 100);
+  }      
+
+  // sort the SEDtable by the reference colors
+  SEDtable = sort_SEDtable (SEDtableRaw, Nrow);
+
+  // create holder for the source data
+  ALLOCATE (sourceValue.mags, float, Nfilter);
+  ALLOCATE (sourceError.mags, float, Nfilter);
+
+  if (PLOT) {
+    if (!GetGraph (&graphdata, &kapa, NULL)) return (FALSE);
+    SetLimitsRaw (wavecode, NULL, Nfilter, &graphdata);
+    graphdata.style = 2;
+    graphdata.ptype = 2;
+    KapaClearSections (kapa);
+    magSection.name = strcreate ("mag");
+    magSection.x  = 0;
+    magSection.dx = 1;
+    magSection.y  = 0.5;
+    magSection.dy = 0.5;
+    resSection.name = strcreate ("res");
+    resSection.x  = 0.0;
+    resSection.dx = 1.0;
+    resSection.y  = 0.0;
+    resSection.dy = 0.5;
+    
+    KapaSetFont (kapa, "helvetica", 14);
+    ALLOCATE (fitmags, float, Nfilter);
+    ALLOCATE (fiterrs, float, Nfilter);
+  }
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  /* loop over regions, extract data for each region */
+  // XXX add interrupt checks
+  gprint (GP_ERR, "using %d possible regions\n", skylist[0].Nregions);
+  for (k = 0; k < skylist[0].Nregions; k++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[k];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    // perform the fit to all sources
+    for (i = 0; i < catalog.Naverage; i++) {
+
+      // blank out the source array
+      for (j = 0; j < Nfilter; j++) {
+	sourceValue.mags[j] = 100;
+      }	
+
+      // load the measurements for this source
+      m = catalog.average[i].offset;
+      for (j = 0; j < catalog.average[i].Nm; j++) {
+	idx = hashcode[catalog.measure[m+j].photcode];
+	if (idx == -1) continue;
+	// XXX do something more clever if more than one value exists per photcode
+	sourceValue.mags[idx] = catalog.measure[m+j].M + vegaToAB[idx];
+	sourceError.mags[idx] = catalog.measure[m+j].dM;
+	if ((catalog.measure[m+j].photcode == USNOred) || (catalog.measure[m+j].photcode == USNOblu)) {
+	  sourceError.mags[idx] = 0.3;
+	}
+      }
+
+      // XXX for the moment, skip sources without ref color
+      if (sourceValue.mags[codeP] > 50) continue;
+      if (sourceValue.mags[codeM] > 50) continue;
+      color = sourceValue.mags[codeP] - sourceValue.mags[codeM];
+
+      // XXX find tableRow within 0.1 mag of color
+      start = SEDcolorBracket (SEDtable, Nrow, color);
+      minFit = SEDchisq (SEDtable[start], &sourceValue, &sourceError, Nfilter);
+      minFit.row = start;
+
+      // search for min chisq backwards
+      done = FALSE;
+      row = start - 1;
+      while (!done && (row > 0)) {
+	testFit = SEDchisq (SEDtable[row], &sourceValue, &sourceError, Nfilter);
+	if (testFit.chisq < minFit.chisq) {
+	  minFit = testFit;
+	  minFit.row = row;
+	}
+	if (fabs(SEDtable[row][0].color - color) > 0.5) done = TRUE;
+	row --;
+      }
+
+      // search for min chisq forwards
+      done = FALSE;
+      row = start + 1;
+      while (!done && (row < Nrow)) {
+	testFit = SEDchisq (SEDtable[row], &sourceValue, &sourceError, Nfilter);
+	if (testFit.chisq < minFit.chisq) {
+	  minFit = testFit;
+	  minFit.row = row;
+	}
+	if (fabs(SEDtable[row][0].color - color) > 0.5) done = TRUE;
+	row ++;
+      }
+
+      Nfit ++;
+      // create the vectors for the example plots
+      if (PLOT) {
+	// find plot range
+	SetLimitsRaw (NULL, SEDtable[minFit.row][0].mags, Nfilter, &graphdata);
+	SWAP (graphdata.ymin, graphdata.ymax);
+
+	KapaClearSections (kapa);
+	KapaSetSection (kapa, &magSection);
+    	KapaSetLimits (kapa, &graphdata);
+	KapaBox (kapa, &graphdata);
+	graphdata.color = KapaColorByName ("blue");
+	graphdata.etype = 0;
+	KapaPrepPlot (kapa, Nfilter, &graphdata);
+	KapaPlotVector (kapa, Nfilter, wavecode, "x");
+	KapaPlotVector (kapa, Nfilter, SEDtable[minFit.row][0].mags, "y");
+	graphdata.color = KapaColorByName ("red");
+	graphdata.etype = 1;
+	for (j = 0; j < Nfilter; j++) {
+	  fitmags[j] = 100;
+	  fiterrs[j] = 0;
+	  if (sourceValue.mags[j] > 50) continue;
+	  fitmags[j] = sourceValue.mags[j] - minFit.Md;
+	  fiterrs[j] = sourceError.mags[j];
+	}
+	KapaPrepPlot (kapa, Nfilter, &graphdata);
+	KapaPlotVector (kapa, Nfilter, wavecode, "x");
+	KapaPlotVector (kapa, Nfilter, fitmags, "y");
+	KapaPlotVector (kapa, Nfilter, fiterrs, "dym");
+	KapaPlotVector (kapa, Nfilter, fiterrs, "dyp");
+	KapaSendLabel (kapa, "model,fit (mags)", 1);
+
+	sprintf (line, "star: %10.6f %10.6f  T: %5.0fK  A_V|: %4.2f  M_D|: %5.2f  &sc&h^2|: %5.2f", 
+		 catalog.average[i].R, catalog.average[i].D, 
+		 SEDtable[minFit.row][0].Temp, SEDtable[minFit.row][0].Av, minFit.Md, minFit.chisq);
+	KapaSendLabel (kapa, line, 2);
+	KapaSendLabel (kapa, "model,fit (mags)", 1);
+
+	KapaSetSection (kapa, &resSection);
+	graphdata.ymin = -1.0;
+	graphdata.ymax = +1.0;
+    	KapaSetLimits (kapa, &graphdata);
+	KapaBox (kapa, &graphdata);
+	graphdata.color = KapaColorByName ("red");
+	graphdata.etype = 1;
+
+	for (j = 0; j < Nfilter; j++) {
+	  fitmags[j] = 100;
+	  fiterrs[j] = 0;
+	  if (sourceValue.mags[j] > 50) continue;
+	  fitmags[j] = sourceValue.mags[j] - minFit.Md - SEDtable[minFit.row][0].mags[j];
+	  fiterrs[j] = sourceError.mags[j];
+	}
+	KapaPrepPlot (kapa, Nfilter, &graphdata);
+	KapaPlotVector (kapa, Nfilter, wavecode, "x");
+	KapaPlotVector (kapa, Nfilter, fitmags, "y");
+	KapaPlotVector (kapa, Nfilter, fiterrs, "dym");
+	KapaPlotVector (kapa, Nfilter, fiterrs, "dyp");
+	KapaSendLabel (kapa, "wavelength (nm)", 0);
+	KapaSendLabel (kapa, "resid (mags)", 1);
+
+	KiiCursorOn (kapa);
+	while (KiiCursorRead (kapa, &X, &Y, &ZP, &RA, &DEC, key)) {
+	  gprint (GP_ERR, "window: %f %f (%s)\n", X, Y, key);
+	  if (!strcasecmp (key, "Q")) {
+	    KiiCursorOff (kapa);
+	    break;
+	  }
+	  if (!strcasecmp (key, "ESCAPE")) {
+	    KiiCursorOff (kapa);
+	    goto escape;
+	  }
+	}
+      }
+      // we now have the min chisq row. use this to supply the other filter values....
+    }
+    dvo_catalog_free (&catalog);
+  }
+  gprint (GP_ERR, "fitted %d stars\n", Nfit);
+  status = TRUE;
+  goto finish;
+  
+usage:
+  gprint (GP_ERR, "USAGE: fitset (sedtable) : (F) - (F)\n");
+  goto escape;
+
+table_missing:
+  gprint (GP_ERR, "ERROR: can't open the SED table\n");
+  goto escape;
+
+color_missing:
+  gprint (GP_ERR, "ERROR: reference color not in SED table\n");
+  goto escape;
+
+color_undefined:
+  gprint (GP_ERR, "ERROR: undefined photcode in reference color\n");
+  goto escape;
+
+code_missing:
+  gprint (GP_ERR, "ERROR: undefined photcode in SED table\n");
+  goto escape;
+
+escape:
+  status = FALSE;
+  goto finish;
+
+finish:
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  if (wavecode != NULL) free (wavecode);
+  if (hashcode != NULL) free (hashcode);
+  if (SEDtableRaw != NULL) {
+    for (i = 0; i < Nrow; i++) {
+      free (SEDtableRaw[i].mags);
+    }
+    free (SEDtableRaw);
+  }
+  if (SEDtable != NULL) free (SEDtable);
+  if (sourceValue.mags != NULL) free (sourceValue.mags);
+  if (sourceError.mags != NULL) free (sourceError.mags);
+
+  signal (SIGINT, oldsignal);
+  return (status);
+}
+
+// fit the data (with errors) to the given table row
+SEDfit SEDchisq (SEDtableRow *ref, SEDtableRow *data, SEDtableRow *error, int Nfilter) {
+
+  int i;
+  double Sm, Sd, S2, wt, dM;
+  SEDfit fit;
+
+  Sm = Sd = S2 = 0.0;
+
+  for (i = 0; i < Nfilter; i++) {
+    if (data[0].mags[i] > 50.0) continue;
+
+    if (error[0].mags[i] == 0.0) {
+      wt = 1.0;
+    } else {
+      wt = 1.0 / SQ(error[0].mags[i]);
+    }
+
+    dM = data[0].mags[i] - ref[0].mags[i];
+    S2 += SQ(dM) * wt;
+    Sm += dM * wt;
+    Sd += wt;
+  }
+    
+  // row is assigned after fit
+  fit.row = -1;
+  fit.Md = Sm / Sd;
+  fit.chisq = S2 + SQ(fit.Md) * Sd - 2*fit.Md*Sm;
+
+  return (fit);
+}
+
+// find the first table row within 0.1 mag of the requested color (or within 10)
+int SEDcolorBracket (SEDtableRow **table, int Ntable, float color) {
+
+  int Nlo, Nhi, N;
+  float tcolor;
+
+  N = Nlo = 0; Nhi = Ntable;
+  tcolor = table[Nlo][0].color;
+  while ((Nhi - Nlo > 10) && (fabs(tcolor-color) > 0.1)) {
+    N = 0.5*(Nlo + Nhi);
+    N = MAX (N, 0);
+    N = MIN (N, Ntable - 1);
+    tcolor = table[N][0].color;
+    if (tcolor < color) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  return (N);
+}
+
+SEDtableRow **sort_SEDtable (SEDtableRow *raw, int N) {
+
+  int i;
+  SEDtableRow **value;
+  
+  if (N <= 0) return (NULL);
+
+  ALLOCATE (value, SEDtableRow *, N);
+  for (i = 0; i < N; i++) {
+    value[i] = &raw[i];
+  }
+
+# define SWAPFUNC(A,B){ SEDtableRow *temp = value[A]; value[A] = value[B]; value[B] = temp; }
+# define COMPARE(A,B)(value[A][0].color < value[B][0].color)
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+  return (value);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gcat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gcat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gcat.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "dvoshell.h"
+
+int gcat (int argc, char **argv) {
+  
+  int i;
+  struct stat filestat;
+  double Ra, Dec, Radius;
+  SkyTable *sky;
+  SkyList *skylist;
+
+  if ((argc != 3) && (argc != 4)) {
+    gprint (GP_ERR, "USAGE: gcat RA DEC [Radius]\n");
+    return (FALSE);
+  }
+
+  /* load sky from correct table */
+  Ra = atof (argv[1]);
+  Dec = atof (argv[2]);
+  if (argc == 4) 
+    Radius = atof(argv[3]);
+  else 
+    Radius = 0.0001;
+
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, Ra, Dec, Radius);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    if (stat (skylist[0].filename[i], &filestat) != -1) {
+      gprint (GP_ERR, "%3d %s *\n", i, skylist[0].regions[i][0].name);
+    } else {
+      gprint (GP_ERR, "%3d %s\n", i, skylist[0].regions[i][0].name);
+    } 
+    set_str_variable ("CATNAME", skylist[0].filename[i]);
+  }
+
+  return (TRUE);
+  SkyListFree (skylist);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/get_regions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/get_regions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/get_regions.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "dvoshell.h"
+
+/* return region files containing given image */
+GSCRegion *get_regions (Image *image, int *Nregions) {
+  
+  GSCRegion *region;
+  FILE *f;
+  double x, y;
+  double dec, ra;
+  int j, done, nregion, NREGION;
+  char filename[256], path[256];
+  
+  VarConfig ("CATDIR", "%s", path);
+  VarConfig ("GSCFILE", "%s", filename);
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    gprint (GP_ERR, "ERROR: can't find GSC region file %s\n", filename);
+    exit (0);
+  }
+  
+  /* find regions at image corners */
+  NREGION = 10;
+  ALLOCATE (region, GSCRegion, NREGION);
+  nregion = 0;
+
+  /* look for new regions on grid across image */ 
+  for (x = 0.0; x <= 1.0; x+=0.25) {
+    for (y = 0.0; y <= 1.0; y+=0.25) {
+      XY_to_RD (&ra, &dec, image[0].NX*(1.1*x - 0.05), image[0].NY*(1.1*y - 0.05), &image[0].coords);
+      aregion (&region[nregion], f, ra, dec, path);
+      done = FALSE;
+      for (j = 0; (j < nregion) && !done; j++) {
+	if (!strcmp (region[nregion].filename, region[j].filename)) {
+	  nregion --;
+	  done = TRUE;
+	}
+      }
+      nregion ++;
+      if (nregion == NREGION) {
+	NREGION += 10;
+	REALLOCATE (region, GSCRegion, NREGION);
+      }
+    }
+  }
+  *Nregions = nregion;
+  
+  fclose (f);
+  return (region);
+  
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/getxtra.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/getxtra.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/getxtra.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "dvoshell.h"
+
+int getxtra (int argc, char **argv) {
+  
+  SelectXtra = (char *) NULL;
+  if (N = get_argument (argc, argv, "-xtra")) {
+    SelectXtra = TRUE;
+    remove_argument (N, &argc, argv);
+    XtraType = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+    XtraValue = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  SelectRegion = (char *) NULL;
+  if (N = get_argument (argc, argv, "-region")) {
+    SelectRegion = TRUE;
+    remove_argument (N, &argc, argv);
+    RA = atof (atof[N]);
+    remove_argument (N, &argc, argv);
+    Dec = atof (atof[N]);
+    remove_argument (N, &argc, argv);
+    Radius = atof (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Mode = (char *) NULL;
+  if (N = get_argument (argc, argv, "-mode")) {
+    remove_argument (N, &argc, argv);
+    Mode = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Range = (char *) NULL;
+  if (N = get_argument (argc, argv, "-range")) {
+    remove_argument (N, &argc, argv);
+    Range = strcreate (atof[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 6) {
+    gprint (GP_ERR, "USAGE: addxtra R D radius (type) (value)\n");
+    return (FALSE);
+  }
+  
+  
+
+  /*
+
+  validate the input values (type, defines the needed options)
+  find catalog (based on r,d)
+  load catalog (need to load measures?)
+  find the object
+  find the xtra entry (sorted by ra/dec? sorted by averef?)
+  add new entry
+  save catalog 
+  */
+}
+
+/* 
+   get specified values for specified objects 
+
+   getxtra type -xtra name K01.01 
+   getxtra type -region R D radius 
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gimages.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gimages.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gimages.c	(revision 16632)
@@ -0,0 +1,184 @@
+# include "dvoshell.h"
+
+// XXX this needs some help: it should define the region for image_subset or otherwise
+// limit the input selection
+int gimages (int argc, char **argv) {
+  
+  int i, j, N, Nimage, Nfound, *subset, Nsubset, status;
+  double ra, dec, Ra, Dec, X, Y, Yo;
+  double trange, t;
+  int TimeSelect, PixelCoords, TimeFormat, PhotCodeSelect;
+  time_t tzero, TimeReference;
+  char name[64], *date;
+  int typehash;
+  SkyRegionSelection *selection;
+
+  PhotCode *code;
+  Image *image;
+
+  if (!InitPhotcodes ()) return (FALSE);
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) {
+    gprint (GP_ERR, "invalid sky region selection\n");
+    return FALSE;
+  }
+
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-tref"))) {
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+
+    t = atof (argv[N]);
+    tzero = TimeRef (t, TimeReference, TimeFormat);
+    remove_argument (N, &argc, argv);
+
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  code = NULL;
+  PhotCodeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    if ((code = GetPhotcodebyName (argv[N])) == NULL) {
+      gprint (GP_ERR, "ERROR: photcode not found in photcode table\n");
+      return (FALSE);
+    }
+    PhotCodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PixelCoords = FALSE;
+  if ((N = get_argument (argc, argv, "-pix"))) {
+    remove_argument (N, &argc, argv);
+    PixelCoords = TRUE;
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: gimages RA DEC [-time t dt] [-pix]\n");
+    return (FALSE);
+  }
+
+  if (!ohana_str_to_radec (&Ra, &Dec, argv[1], argv[2])) return (FALSE);
+
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  image_subset (image, Nimage, &subset, &Nsubset, selection, tzero, trange, TimeSelect);
+  BuildChipMatch (image, Nimage);
+
+  int DistortImage = wordhash ("-DIS");
+  int TriangleUp   = wordhash ("TRP-");
+  int TriangleDn   = wordhash ("TRM-");
+
+  Nfound = 0;
+  for (j = 0; j < Nsubset; j++) {
+    i = subset[j];
+    if (PhotCodeSelect) {
+      if ((code[0].type == PHOT_REF) || (code[0].type == PHOT_DEP)) {
+	if (code[0].code != image[i].photcode) continue;
+      } 
+      if (code[0].type == PHOT_SEC) {
+	if (code[0].code != GetPhotcodeEquivCodebyCode (image[i].photcode)) continue;
+      } 
+    }      
+    if (!FindMosaicForImage (image, Nimage, i)) continue;
+
+    status = RD_to_XY (&X, &Y, Ra, Dec, &image[i].coords);
+    if (!finite(X)) continue;
+    if (!finite(Y)) continue;
+    if (!status) continue;
+
+    typehash = wordhash (&image[i].coords.ctype[4]);
+
+    if (typehash == DistortImage) {
+      if (X < -0.5*image[i].NX) continue;
+      if (Y < -0.5*image[i].NY) continue;
+      if (X > +0.5*image[i].NX) continue;
+      if (Y > +0.5*image[i].NY) continue;
+      goto got_spot;
+    } 
+
+    typehash = wordhash (image[i].coords.ctype);
+    if (typehash == TriangleUp) {
+      if (Y < -0.5*image[i].NY) continue;
+      Yo = +0.5*image[i].NY + 2.0*(image[i].NY/image[i].NX)*X;
+      if (Y > Yo) continue;
+      Yo = +0.5*image[i].NY - 2.0*(image[i].NY/image[i].NX)*X;
+      if (Y > Yo) continue;
+      goto got_spot;
+    }
+    if (typehash == TriangleDn) {
+      if (Y > +0.5*image[i].NY) continue;
+      Yo = -0.5*image[i].NY + 2.0*(image[i].NY/image[i].NX)*X;
+      if (Y < Yo) continue;
+      Yo = -0.5*image[i].NY - 2.0*(image[i].NY/image[i].NX)*X;
+      if (Y < Yo) continue;
+      goto got_spot;
+    }
+
+    {
+      if (X < 0) continue;
+      if (Y < 0) continue;
+      if (X > image[i].NX) continue;
+      if (Y > image[i].NY) continue;
+    }
+
+    /*** XXX we need to re-introduce the use of applyMcal
+    Mcal = applyMcal (&image[i], 2048.0, 2048.0);
+    ***/
+
+  got_spot:
+    date = ohana_sec_to_date (image[i].tzero);
+
+    if (PixelCoords) {
+      gprint (GP_LOG, "%3d %s %6.1f %6.1f %20s %5d %2d %4.2f %6.3f %5.3f %5.3f %4x\n", 
+	       Nfound, image[i].name, X, Y, date, image[i].nstar, image[i].photcode, image[i].secz, image[i].Mcal, image[i].dMcal, image[i].exptime, image[i].code);
+    } else {
+      XY_to_RD (&ra, &dec, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+      gprint (GP_LOG, "%3d %s %8.4f %8.4f %20s %5d %2d %4.2f %6.3f %5.3f %5.3f %4x\n", 
+	       Nfound, image[i].name, ra, dec, date, image[i].nstar, image[i].photcode, image[i].secz, image[i].Mcal, image[i].dMcal, image[i].exptime, image[i].code);
+    }
+    sprintf (name, "IMAGEx:%d", Nfound);
+    set_variable     (name, X);
+    sprintf (name, "IMAGEy:%d", Nfound);
+    set_variable     (name, Y);
+    sprintf (name, "IMAGEt:%d", Nfound);
+    set_str_variable (name, date);
+    sprintf (name, "IMAGEccd:%d", Nfound);
+    set_int_variable (name, image[i].ccdnum);
+    sprintf (name, "IMAGEname:%d", Nfound);
+    set_str_variable (name, image[i].name);
+    Nfound ++;
+    free (date);
+  }
+  set_int_variable ("IMAGEx:n", Nfound);
+  set_int_variable ("IMAGEy:n", Nfound);
+  set_int_variable ("IMAGEt:n", Nfound);
+  set_int_variable ("IMAGEccd:n", Nfound);
+  set_int_variable ("IMAGEname:n", Nfound);
+
+  free (image);
+  free (subset);
+
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gstar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gstar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/gstar.c	(revision 16632)
@@ -0,0 +1,356 @@
+# include "dvoshell.h"
+
+void initPhotcodeSequence (int Nsecfilt);
+void freePhotcodeSequence ();
+void printPhotcodeSequence (Average *average, SecFilt *secfilt, int entry, int type);
+
+int gstar (int argc, char **argv) {
+  
+  char *date;
+  double Ra, Dec, Radius, Radius2, r, dec0, dec1;
+  double Mcat, Mrel;
+  double *RA, *DEC;
+  int i, j, k, m, N, *N1, Nsecfilt, NPTS, QUIET, FULL_OUTPUT;
+  int Nstars, found, GetMeasures, Nlo, Nhi;
+  int SaveVectors;
+  Vector *vec1, *vec2, *vec3, *vec4;
+  SkyTable *sky;
+  SkyList *skylist;
+  Catalog catalog;
+  int TimeFormat;
+  time_t TimeReference;
+
+  if (!InitPhotcodes ()) return (FALSE);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  QUIET = FALSE;
+  if ((N = get_argument (argc, argv, "-q"))) {
+    QUIET = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  NPTS = 0;
+  vec1 = vec2 = vec3 = vec4 = NULL;
+  SaveVectors = FALSE;
+  if ((N = get_argument (argc, argv, "-save"))) {
+    remove_argument (N, &argc, argv);
+    SaveVectors = TRUE;
+    if ((vec1 = SelectVector ("gs:m", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec2 = SelectVector ("gs:t", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec3 = SelectVector ("gs:z", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    if ((vec4 = SelectVector ("gs:f", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  }
+
+  FULL_OUTPUT = FALSE;
+  if ((N = get_argument (argc, argv, "-full"))) {
+    FULL_OUTPUT = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  GetMeasures = FALSE;
+  if ((N = get_argument (argc, argv, "-m"))) {
+    GetMeasures = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+  if ((N = get_argument (argc, argv, "-meas"))) {
+    GetMeasures = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: gstar RA DEC Radius [-m]\n");
+    return (FALSE);
+  }
+  
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  Ra = atof (argv[1]);
+  Dec = atof (argv[2]);
+  Radius = atof (argv[3]);
+
+  while (Ra < 0.0) Ra += 360.0;
+  while (Ra > 360.0) Ra -= 360.0;
+  
+  /* load sky from correct table */
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, Ra, Dec, Radius);
+
+  if (skylist[0].Nregions > 1) {
+    gprint (GP_ERR, "warning, radius overlaps region boundary, not yet implemented\n");
+  }
+
+  /* lock, load, unlock catalog */
+  catalog.filename = skylist[0].filename[0];
+  catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+  catalog.Nsecfilt = 0;
+
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+  }
+  dvo_catalog_unlock (&catalog);
+
+  Nstars = catalog.Naverage;
+  ALLOCATE (RA, double, Nstars);
+  ALLOCATE (DEC, double, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  /* find star(s) in RA, DEC list -- use a dumb algorithm for now, improve later */
+  /* stars are not guaranteed to be sorted in RA or in DEC, so first sort the list */
+  for (i = 0; i < Nstars; i++) {
+    RA[i] = catalog.average[i].R;
+    DEC[i] = catalog.average[i].D;
+    N1[i] = i;
+  }
+  /* sort list by DEC */
+  if (Nstars > 1) sort_coords_index (DEC, RA, N1, Nstars);
+  /* at this point, RA, DEC, and N1 are sorted by DEC.  
+     catalog.average[N1[i]].R = RA[i] */
+
+  /* bracket the RA range of interest */
+  dec0 = Dec - Radius;
+  dec1 = Dec + Radius;
+
+  Nlo = 0; Nhi = catalog.Naverage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (DEC[N] < dec0) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  /* DEC[Nlo] is guaranteed to be just lower than dec0 */
+
+  Radius2 = Radius*Radius;
+  found = FALSE;
+
+  /* data has been loaded, get ready to plot it */
+  if (SaveVectors) {
+    N = 0;
+    NPTS = 1000;
+    ALLOCATE (vec1[0].elements, float, NPTS);
+    ALLOCATE (vec2[0].elements, float, NPTS);
+    ALLOCATE (vec3[0].elements, float, NPTS);
+    ALLOCATE (vec4[0].elements, float, NPTS);
+  }
+
+  initPhotcodeSequence (Nsecfilt);
+
+  for (i = Nlo; (i < catalog.Naverage) && !found; i++) {
+
+    if (dec0 > DEC[i]) continue;
+    if (dec1 < DEC[i]) found = TRUE;
+    
+    r = SQ(Dec - DEC[i]) + SQ(Ra - RA[i]);
+    if (r < Radius2) {
+      k = N1[i];
+      if (!QUIET) {
+	gprint (GP_LOG, "star: %d\n", k);
+	gprint (GP_LOG, "%11.7f ", catalog.average[k].R);
+	gprint (GP_LOG, "%11.7f ", catalog.average[k].D);
+	gprint (GP_LOG, "%3d   ",  catalog.average[k].Nm);
+	gprint (GP_LOG, "%4.1f ",  0.01*catalog.average[k].Xp);
+	gprint (GP_LOG, "%5d",     catalog.average[k].code);
+
+	if (FULL_OUTPUT) {
+	    gprint (GP_LOG, "%f",     catalog.average[k].dR);
+	    gprint (GP_LOG, "%f",     catalog.average[k].dD);
+	    gprint (GP_LOG, "%f",     catalog.average[k].uR);
+	    gprint (GP_LOG, "%f",     catalog.average[k].uD);
+	    gprint (GP_LOG, "%f",     catalog.average[k].duR);
+	    gprint (GP_LOG, "%f",     catalog.average[k].duD);
+	    gprint (GP_LOG, "%f",     catalog.average[k].P);
+	    gprint (GP_LOG, "%f",     catalog.average[k].dP);
+	    gprint (GP_LOG, "%x",     catalog.average[k].objID_hi);
+	    gprint (GP_LOG, "%x",     catalog.average[k].objID_lo);
+	}
+
+	gprint (GP_LOG, "\n");
+      
+	/* filter names */
+	for (j = 0; j < Nsecfilt; j++) printPhotcodeSequence (&catalog.average[k], &catalog.secfilt[Nsecfilt*k], j, 3);
+	gprint (GP_LOG, "\n");
+
+	/* average mags */
+	for (j = 0; j < Nsecfilt; j++) printPhotcodeSequence (&catalog.average[k], &catalog.secfilt[Nsecfilt*k], j, 0);
+	gprint (GP_LOG, "\n");
+
+	/* average mag errors */
+	for (j = 0; j < Nsecfilt; j++) printPhotcodeSequence (&catalog.average[k], &catalog.secfilt[Nsecfilt*k], j, 1);
+	gprint (GP_LOG, "\n");
+
+	/* average mag chisq */
+	for (j = 0; j < Nsecfilt; j++) printPhotcodeSequence (&catalog.average[k], &catalog.secfilt[Nsecfilt*k], j, 2);
+	gprint (GP_LOG, "\n");
+      }
+
+      if (GetMeasures || SaveVectors) {
+	m = catalog.average[k].offset;
+	for (j = 0; j < catalog.average[k].Nm; j++, m++) {
+
+	  Mcat = PhotCat (&catalog.measure[m]);
+	  Mrel = PhotRel (&catalog.measure[m], &catalog.average[k], &catalog.secfilt[k*Nsecfilt]);
+
+	  if (GetMeasures && !QUIET) {
+	    date = ohana_sec_to_date (catalog.measure[m].t);
+	    gprint (GP_LOG, "%6.3f ",  Mcat);
+	    gprint (GP_LOG, "%6.3f ",  Mrel);
+	    gprint (GP_LOG, "%5.3f  ", catalog.measure[m].dM);
+	    gprint (GP_LOG, "%20s  ",  date);
+	    gprint (GP_LOG, "%7.4f ",  catalog.measure[m].dR);
+	    gprint (GP_LOG, "%7.4f",   catalog.measure[m].dD);
+	    gprint (GP_LOG, "%2d ",    catalog.measure[m].dophot);
+	    gprint (GP_LOG, "%3x ",    catalog.measure[m].dbFlags);
+	    gprint (GP_LOG, "%3d ",    catalog.measure[m].photcode);
+	    gprint (GP_LOG, "%-20s  ", GetPhotcodeNamebyCode (catalog.measure[m].photcode));
+
+	    if (FULL_OUTPUT) {
+		gprint (GP_LOG, "%f", catalog.measure[m].Mcal);
+		gprint (GP_LOG, "%f", catalog.measure[m].Mgal);
+		gprint (GP_LOG, "%f", pow(10.0, 0.4*catalog.measure[m].dt));
+		gprint (GP_LOG, "%f", 1.0 + catalog.measure[m].airmass);
+		gprint (GP_LOG, "%f", catalog.measure[m].az);
+		gprint (GP_LOG, "%f", catalog.measure[m].Xccd);
+		gprint (GP_LOG, "%f", catalog.measure[m].Yccd);
+		gprint (GP_LOG, "%d", catalog.measure[m].dXccd);
+		gprint (GP_LOG, "%d", catalog.measure[m].dYccd);
+		gprint (GP_LOG, "%f", catalog.measure[m].Sky);
+		gprint (GP_LOG, "%f", catalog.measure[m].dSky);
+		gprint (GP_LOG, "%d", catalog.measure[m].averef);
+		gprint (GP_LOG, "%d", catalog.measure[m].detID);
+		gprint (GP_LOG, "%d", catalog.measure[m].imageID);
+		gprint (GP_LOG, "%f", catalog.measure[m].qPSF);
+		gprint (GP_LOG, "%f", catalog.measure[m].psfProb);
+		gprint (GP_LOG, "%f", catalog.measure[m].crNsigma);
+		gprint (GP_LOG, "%f", catalog.measure[m].extNsigma);
+		gprint (GP_LOG, "%f", 0.01*catalog.measure[m].FWx);
+		gprint (GP_LOG, "%f", 0.01*catalog.measure[m].FWy);
+		gprint (GP_LOG, "%f", (360.0/(float)0xffff)*catalog.measure[m].theta);
+
+		gprint (GP_LOG, "%x", catalog.measure[m].photFlags);
+		gprint (GP_LOG, "%d", catalog.measure[m].stargal);
+	    }
+	    gprint (GP_LOG, "\n");
+
+	    free (date);
+	  }
+	  
+	  if (SaveVectors) {
+	    vec1[0].elements[N] = Mcat;
+	    vec2[0].elements[N] = TimeValue (catalog.measure[m].t, TimeReference, TimeFormat);
+	    vec3[0].elements[N] = catalog.measure[m].airmass;
+	    vec4[0].elements[N] = catalog.measure[m].photcode;
+	    N ++;
+	    if (N == NPTS - 1) {
+	      NPTS += 2000;
+	      REALLOCATE (vec1[0].elements, float, NPTS);
+	      REALLOCATE (vec2[0].elements, float, NPTS);
+	      REALLOCATE (vec3[0].elements, float, NPTS);
+	      REALLOCATE (vec4[0].elements, float, NPTS);
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  if (SaveVectors) {
+    vec1[0].Nelements = N;
+    vec2[0].Nelements = N;
+    vec3[0].Nelements = N;
+    vec4[0].Nelements = N;
+  }
+
+  free (RA);
+  free (DEC);
+  free (N1);
+  dvo_catalog_free (&catalog);
+
+  freePhotcodeSequence ();
+  return (TRUE);
+
+}
+
+void print_double (double value) {
+  if (isnan(value)) 
+    gprint (GP_LOG, "NaN    ");
+  else 
+    gprint (GP_LOG, "%6.3f ", value);
+}
+
+void print_short (double value, short int ival) {
+  if (ival == NAN_S_SHORT) 
+    gprint (GP_LOG, "NaN    ");
+  else 
+    gprint (GP_LOG, "%6.3f ", value);
+}
+
+// XXX fix printing to be in photcode numerical order for PRI/SEC data
+static int *sequence = NULL;
+
+void initPhotcodeSequence (int Nsecfilt) {
+
+  int j;
+  int *codeNumber;
+  PhotCode *code;
+
+  // sequence contains, in desired order, secfilt number (0 == pri)
+  ALLOCATE (sequence, int, Nsecfilt);
+  ALLOCATE (codeNumber, int, Nsecfilt);
+  
+  /* filter names -- primary code is 0 in this function */
+  for (j = 0; j < Nsecfilt; j++) {
+    code = GetPhotcodebyNsec (j);
+    codeNumber[j] = code[0].code;
+    sequence[j] = j;
+  }
+
+  isortpair (codeNumber, sequence, Nsecfilt);
+  free (codeNumber);
+}
+
+void freePhotcodeSequence () {
+  free (sequence);
+}
+
+
+void printPhotcodeSequence (Average *average, SecFilt *secfilt, int entry, int type) {
+
+  int seq;
+  PhotCode *code;
+
+  seq = sequence[entry];
+
+  switch (type) {
+    case 0: /* average mags */
+      if (seq == -1) {
+	print_double (NAN);
+      } else {
+	print_double (secfilt[seq].M);
+      }
+      break;
+
+    case 1: /* average mags errors */
+      if (seq == -1) {
+	print_double (NAN);
+      } else {
+	print_double (secfilt[seq].dM);
+      }
+      break;
+
+    case 2: /* average mag chisq */
+      if (seq == -1) {
+	print_short (NAN_S_SHORT, NAN_S_SHORT);
+      } else {
+	print_short (pow (10.0, 0.01*secfilt[seq].Xm), secfilt[seq].Xm);
+      }
+      break;
+
+    case 3: /* filter names */
+      code = GetPhotcodebyNsec (seq);
+      gprint (GP_LOG, "%-6s ", code[0].name);
+      break;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/Photometry
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/Photometry	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/Photometry	(revision 16632)
@@ -0,0 +1,26 @@
+
+cals: Plot residuals for reference stars. 
+
+ This function takes the currently displayed region and looks for all
+ stars which have 'reference' photometry and plots the difference
+ between the reference magnitude (in the given filter) and the
+ observed magnitude (same filter) versus one of several options:  the
+ star color (based on the 'reference' photometry), the star magnitude,
+ the airmass, time, secqunce, etc.
+
+ These plots can use one of two options for the 'observed' magnitude.
+ Either, the magnitude for individual measurement, using the currently
+ set values for the CCD zeropoints (from the photometry database), or
+ using the relative photometry determined for the particular star.  
+
+
+dmags: plot difference between two measured magnitudes
+
+resid: 
+
+abszero
+
+zeropts
+
+cmd
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/catalog
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/catalog	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/catalog	(revision 16632)
@@ -0,0 +1,74 @@
+
+  catalog (filename/-all) [many options!]
+
+  plot the star positions from any of several possible catalogs.  By
+default, the photometry database (see Database) is used, but the HST
+Guide Star Catalog and a simple ASCII file may also be used.  The
+plotting is done on window 0, with the current point type.  The point
+size can be scaled by the magnitude of the star or by the number
+of observations (-n).  
+
+There are many options to this function.  Here they are all:
+
+-e epoch: given ASCII catalog has this epoch, plot in J2000
+
+-ID ID: plot only measurements with this ID number
+ ID may be one of:
+	0 - star
+	4 - variable
+	5 - transient
+      100 - ghost image
+      101 - trail (satellite)
+      102 - bright star garbage	
+      note that numbers < 50 are static objects, 
+	and numbers > 100 are bad data.
+
+-all:  plot all data for the current display region
+
+-g: use the HST GSC instead of the photometry database
+
+-a RA DEC MAG:  the given file is an ASCII file with 
+	RA, DEC, and MAG in columns given by the three numbers
+
+-v ra dec scale: save the values in vectors with the three names given
+	the ra and dec are always used, but the third is the size of 
+	the points plotted, based on whatever the scaling is.
+
+-m m1 m2: scale points by magnitude, with smallest points having
+	magnitude m2.
+
++n n1 n2: scale points by number of measurements, with smallest points
+	having number n1.
+
+-n n1 n2: scale points by number of missing values, with smallest points
+	having number n1.
+
+Note that if two of -m, -n, +n are given, the first determines the
+ scaling of the points.  the second provides an allowed range, so
+ points are only plotted if the second parameter has a value in the
+ given range.
+
+Examples: 
+
+  catalog -all -m 12 18  
+    plot all stars in current region with magnitude 12 having the
+    biggest points and magnitude 18 having the smallest.
+   
+  catalog -all -m 12 18 +n 2 4
+    plot all stars in current region with magnitude 12 having the
+    biggest points and magnitude 18 having the smallest, but only
+    if the stars have 2-4 measurements each
+   
+  catalog -all -m 12 18 +n 0 1 -ID 101
+    plot all stars in current region with magnitude 12 having the
+    biggest points and magnitude 18 having the smallest, but only
+    if the stars have 1 measurements each, and if the object is 
+    found to be a trail.
+   
+  catalog n2230/1819.cpt -n 2 8  
+    plot all stars in catalog n2230/1819.cpt with the biggest points
+    having 8 measurements and the smallest having only 2.
+
+  See Also: lcat, pcat, style, region
+
+   
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/images
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/images	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/images	(revision 16632)
@@ -0,0 +1,9 @@
+
+  images 
+
+  plot the outlines of images in the photometry database and list
+  along with relevant information.  An example of relevant data is the
+  image time, which can be used in other functions to define a specific
+  image or a range of images relevant for the function.
+
+  See also: Database, lcat, pcat
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/imstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/imstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/imstats	(revision 16632)
@@ -0,0 +1,5 @@
+
+  imstats 
+
+  list interesting statistics for a set of images.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/lcat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/lcat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/lcat	(revision 16632)
@@ -0,0 +1,10 @@
+
+  lcat [-all]
+
+  list photometry database files in the current region.  if the option
+  -all is given, all database in the region are listed, along with a
+  comment to show if there is data in the file or not.  if the option
+  is not given, only those files with data are listed.
+
+  See also: region, pcat
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/lcurve
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/lcurve	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/lcurve	(revision 16632)
@@ -0,0 +1,8 @@
+
+  lcurve RA DEC Radius [-l]
+
+  plot light curves for all stars within Radius of the given
+  coordinates.  The units for all three are decimal degrees.  
+  The option -l autoscales the limits of the plot.  
+
+  See also: limits
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/mextract
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/mextract	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/mextract	(revision 16632)
@@ -0,0 +1,12 @@
+
+ mextract (filename) (value) [-g / -a Ncol]
+
+ extracts a vector from the photometry database.  The name also
+ specifies the type of data extracted (and is case insensitive).  Only
+ certain names may be used.
+
+ The possible values are:
+ ra, dec, mag, dmag, Mcal, Mrel, source, time, dR, dD
+
+
+ Note: this routine extracts the individual measurements.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/pcat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/pcat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/pcat	(revision 16632)
@@ -0,0 +1,9 @@
+
+  pcat [-all]
+
+  plot outlines of photometry database files in the current region.
+  if the option -all is given, all database in the region are listed.
+  if the option is not given, only those files with data are listed.
+
+  See also: region, lcat
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/resid
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/resid	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/resid	(revision 16632)
@@ -0,0 +1,12 @@
+
+  resid [-im time] [-X] [-l] (photometry file)
+
+  plot the photometry residuals for a photometry database file. 
+  For every star in the database, the average magnitude is plotted 
+  vs the difference between the average magnitude and each existing 
+  measurement for that star.  
+
+  -l		automatically set the plot limits.
+  -X		plot residual divided by photometric error
+  -im time	only plot the residuals for one of the images 
+		in the database, specified by the obseravation time.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/simage
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/simage	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/help/simage	(revision 16632)
@@ -0,0 +1,7 @@
+
+  simage (filename)
+
+  plot the positions of stars in a CMP file.  This function is a
+  useful test for image comparisons, and astrometry must be determined
+  before the function is run.
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/images.c	(revision 16632)
@@ -0,0 +1,301 @@
+# include "dvoshell.h"
+# define BETA 0.41421
+
+int wordhash (char *word) {
+  int value;
+
+  value = *(int *)word;
+  return value;
+}
+
+int images (int argc, char **argv) {
+
+  int i, j, Nimage, status, InPic, leftside, *plist, TimeSelect, ByName;
+  int WITH_MOSAIC, SOLO_MOSAIC, HIDDEN;
+  time_t tzero, tend;
+  int N, NPTS, n, npts, Npts, kapa;
+  Vector Xvec, Yvec;
+  double r[8], d[8], x[8], y[8], Rmin, Rmax, Rmid, trange, Radius;
+  Image *image;
+  Graphdata graphmode;
+  char name[256];
+  int typehash;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) goto usage;
+
+  WITH_MOSAIC = FALSE;
+  if ((N = get_argument (argc, argv, "+mosaic"))) {
+    remove_argument (N, &argc, argv);
+    WITH_MOSAIC = TRUE;
+  }
+
+  SOLO_MOSAIC = FALSE;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    remove_argument (N, &argc, argv);
+    SOLO_MOSAIC = TRUE;
+    WITH_MOSAIC = TRUE;
+  }
+
+  HIDDEN = FALSE;
+  if ((N = get_argument (argc, argv, "-hidden"))) {
+    remove_argument (N, &argc, argv);
+    HIDDEN = TRUE;
+  }
+
+  ByName = FALSE;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (name, argv[N]);
+    remove_argument (N, &argc, argv);
+    ByName = TRUE;
+  }
+
+  Radius = 45;
+  if ((N = get_argument (argc, argv, "-radius"))) {
+    remove_argument (N, &argc, argv);
+    Radius = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) {
+      gprint (GP_ERR, "syntax error\n");
+      goto usage;
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      goto usage;
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-trange"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      goto usage;
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tend)) { 
+      gprint (GP_ERR, "syntax error\n");
+      goto usage;
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  if (argc != 1) goto usage;
+  
+  /* it is not an error for the database not to have any images */
+  if ((image = LoadImages (&Nimage)) == NULL) return (TRUE);
+  BuildChipMatch (image, Nimage);
+
+  Rmin = graphmode.coords.crval1 - 180.0;
+  Rmax = graphmode.coords.crval1 + 180.0;
+  Rmid = 0.5*(Rmin + Rmax);
+  
+  int DistortImage = wordhash ("-DIS");
+  int TriangleUp   = wordhash ("TRP-");
+  int TriangleDn   = wordhash ("TRM-");
+  int TrianglePts  = wordhash ("TRI-");
+
+  npts = NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  ALLOCATE (plist, int, NPTS);
+  n = N = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (ByName && strncmp (image[i].name, name, strlen(name))) continue;
+    if (TimeSelect && ((image[i].tzero < tzero) || (image[i].tzero+image[i].trate*image[i].NY > tzero + trange))) continue;
+    if (!FindMosaicForImage (image, Nimage, i)) continue;
+
+    Npts = 4;
+    status = TRUE;
+    leftside = FALSE;
+
+    typehash = wordhash (&image[i].coords.ctype[4]);
+
+    /* DIS images represent a field, not a chip */
+    if ((typehash == DistortImage) && !WITH_MOSAIC) continue;
+    if ((typehash != DistortImage) &&  SOLO_MOSAIC) continue;
+    if (typehash == DistortImage) {
+      x[0] = -0.5*image[i].NX; y[0] = -0.5*image[i].NY;
+      x[1] = +0.5*image[i].NX; y[1] = -0.5*image[i].NY;
+      x[2] = +0.5*image[i].NX; y[2] = +0.5*image[i].NY;
+      x[3] = -0.5*image[i].NX; y[3] = +0.5*image[i].NY;
+      goto got_type;
+    }
+
+    typehash = wordhash (image[i].coords.ctype);
+    if (typehash == TriangleUp) {
+      Npts = 3;
+      x[0] =                0; y[0] = +0.5*image[i].NY;
+      x[1] = +0.5*image[i].NX; y[1] = -0.5*image[i].NY;
+      x[2] = -0.5*image[i].NX; y[2] = -0.5*image[i].NY;
+      goto got_type;
+    }
+    if (typehash == TriangleDn) {
+      Npts = 3;
+      x[0] =                0; y[0] = -0.5*image[i].NY;
+      x[1] = +0.5*image[i].NX; y[1] = +0.5*image[i].NY;
+      x[2] = -0.5*image[i].NX; y[2] = +0.5*image[i].NY;
+      goto got_type;
+    }
+    // For 'TrianglePts' (TRI-), we are using the Mx,My, etc terms to save the coordinates
+    // this means triangular images cannot carry photometric zero-point variations
+    if (typehash == TrianglePts) {
+      Npts = 3;
+      x[0] = image[i].Mx;   y[0] = image[i].My;
+      x[1] = image[i].Mxxx; y[1] = image[i].Mxyy;
+      x[2] = image[i].Mxxy; y[2] = image[i].Myyy;
+      goto got_type;
+    }
+
+    // default layout
+    {
+      x[0] = 0;           y[0] = 0;
+      x[1] = image[i].NX; y[1] = 0;
+      x[2] = image[i].NX; y[2] = image[i].NY;
+      x[3] = 0;           y[3] = image[i].NY;
+    }
+
+  got_type:
+
+    /* project this image to screen display coords */
+    // check for boundary overlap?
+    for (j = 0; j < Npts; j++) {
+      status = XY_to_RD (&r[j], &d[j], x[j], y[j], &image[i].coords);
+      if (!status) break;
+      while (r[j] < Rmin) { r[j] += 360.0; }
+      while (r[j] > Rmax) { r[j] -= 360.0; }
+      if (j == 0) {
+	leftside = (r[j] < Rmid);
+      } 
+      if (j > 0) { 
+	if ( leftside && (r[j] > Rmid + 90)) { r[j] -= 360.0; }
+	if (!leftside && (r[j] < Rmid - 90)) { r[j] += 360.0; }
+      }
+    }
+
+    // extremely large-scale images with certain projections will have odd boundaries.
+    // eg, the ASCA images are essentially circles of radius ~60 degrees.  plot these as 
+    // octagons with some dummy size.
+    if (!status) {
+      int jp, xo, yo;
+      double rc, dc;
+      xo = 0.5*image[i].NX;
+      yo = 0.5*image[i].NY;
+      // is the image center on the screen?
+      status = XY_to_RD (&rc, &dc, 0.5*x[2], 0.5*y[2], &image[i].coords);
+      if (status && (image[i].NX * image[i].coords.cdelt2 > 90)) {
+	// draw an octagon with radius 45 degrees
+	double dX = Radius / image[i].coords.cdelt2;
+	x[0] = xo+dX;      y[0] = yo+BETA*dX;
+	x[1] = xo+BETA*dX; y[1] = yo+dX;
+	x[2] = xo-BETA*dX; y[2] = yo+dX;
+	x[3] = xo-dX;      y[3] = yo+BETA*dX;
+	x[4] = xo-dX;      y[4] = yo-BETA*dX;
+	x[5] = xo-BETA*dX; y[5] = yo-dX;
+	x[6] = xo+BETA*dX; y[6] = yo-dX;
+	x[7] = xo+dX;      y[7] = yo-BETA*dX;
+	Npts = 8;
+	j = 0;
+	for (jp = 0; jp < 8; jp++) {
+	  status = XY_to_RD (&r[j], &d[j], x[jp], y[jp], &image[i].coords);
+	  if (!status) continue;
+	  while (r[j] < Rmin) { r[j] += 360.0; }
+	  while (r[j] > Rmax) { r[j] -= 360.0; }
+	  if (j == 0) {
+	    leftside = (r[j] < Rmid);
+	  } 
+	  if (j > 0) { 
+	    if ( leftside && (r[j] > Rmid + 90)) { r[j] -= 360.0; }
+	    if (!leftside && (r[j] < Rmid - 90)) { r[j] += 360.0; }
+	  }
+	  j++;
+	}
+	Npts = j;
+      } else {
+	continue;
+      }
+    }
+    if (Npts == 0) continue;
+
+    status = FALSE;
+    for (j = 0; j < Npts; j++) {
+      status |= fRD_to_XY (&Xvec.elements[N+2*j], &Yvec.elements[N+2*j], r[j], d[j], &graphmode.coords);
+      if (j > 0) {
+	Xvec.elements[N+2*j - 1] = Xvec.elements[N+2*j];
+	Yvec.elements[N+2*j - 1] = Yvec.elements[N+2*j];
+      }
+    }
+    Xvec.elements[N+2*Npts-1] = Xvec.elements[N];
+    Yvec.elements[N+2*Npts-1] = Yvec.elements[N];
+    if (!status) continue;
+    // if none of the points are on the visible side of the projection, do not plot the image
+
+    InPic = FALSE;
+    for (j = 0; j < 2*Npts; j+=2) {
+      if ((Xvec.elements[N+j] >= graphmode.xmin) && 
+	  (Xvec.elements[N+j] <= graphmode.xmax) && 
+	  (Yvec.elements[N+j] >= graphmode.ymin) && 
+	  (Yvec.elements[N+j] <= graphmode.ymax))
+	InPic = TRUE;
+    }
+    // if (!status && HIDDEN) status = TRUE;
+    if (!InPic) continue;
+
+    plist[n] = i;
+    n++;
+    if (n > npts - 1) {
+      npts += 200;
+      REALLOCATE (plist, int, npts);
+    }
+    N+=2*Npts;
+    if (N + 16 >= NPTS) {  /* need to leave room for 8 point image */
+      NPTS += 400;
+      REALLOCATE (Xvec.elements, float, NPTS);
+      REALLOCATE (Yvec.elements, float, NPTS);
+    }
+  }
+
+  gprint (GP_ERR, "plotting %d images\n", n);
+  Xvec.Nelements = Xvec.Nelements = N;
+  if (N > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.etype = 0;
+    PlotVectorPair (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (image);
+  return (TRUE);
+
+
+ usage:
+  gprint (GP_ERR, "USAGE: image [options]\n");
+  gprint (GP_ERR, "  +mosaic : show mosaic outline\n");
+  gprint (GP_ERR, "  -mosaic : only mosaic outline\n");
+  gprint (GP_ERR, "  -hidden : (deprecated)\n");
+  gprint (GP_ERR, "  -name   : only names matching (start of name)\n");
+  gprint (GP_ERR, "  -radius : display all-sky images with given radius octagon\n");
+  gprint (GP_ERR, "  -time (start) (range)  : show images for time and interval\n");
+  gprint (GP_ERR, "  -trange (start) (stop) : show images within time range\n");
+  return (FALSE);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imbox.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imbox.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imbox.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "dvoshell.h"
+
+int imbox (int argc, char **argv) {
+  
+  int j, kapa, Nskip, status, InPic, flipped, N, SOLO_PHU;
+  Vector Xvec, Yvec;
+  double r, d, x[4], y[4], Rmin, Rmax, Rmid;
+  Header header;
+  Coords coords;
+  Coords mosaic;
+  Graphdata graphmode;
+  FILE *f;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  SOLO_PHU = FALSE;
+  if ((N = get_argument (argc, argv, "-phu"))) {
+    SOLO_PHU = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: imbox (filename)\n");
+    return (FALSE);
+  }
+
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    gprint (GP_ERR, "file not found\n");
+    return (FALSE);
+  }
+  
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+  Rmid = 0.5*(Rmin + Rmax);
+  
+  /* project this image to screen display coords */
+  ALLOCATE (Xvec.elements, float, 8);
+  ALLOCATE (Yvec.elements, float, 8);
+
+  while (gfits_fread_header (f, &header)) {
+    if (!GetCoords (&coords, &header)) goto skip;
+    if (!SOLO_PHU && !strcmp (&coords.ctype[4], "-DIS")) {
+      mosaic = coords;
+      RegisterMosaic (&mosaic);
+      goto skip;
+    }
+    x[0] = 0;               y[0] = 0;
+    x[1] = header.Naxis[0]; y[1] = 0;
+    x[2] = header.Naxis[0]; y[2] = header.Naxis[1];
+    x[3] = 0;               y[3] = header.Naxis[1];
+    status = FALSE;
+    flipped = FALSE;
+    for (j = 0; j < 4; j++) {
+      XY_to_RD (&r, &d, x[j], y[j], &coords);
+      while ((j == 0) && (r < Rmin)) { flipped = TRUE; r += 360.0; }
+      while ((j == 0) && (r > Rmax)) { flipped = TRUE; r -= 360.0; }
+      if ((j > 0) && flipped) {
+	while (r < Rmid) r+= 360.0;
+	while (r > Rmid) r-= 360.0;
+      }
+      status |= fRD_to_XY (&Xvec.elements[2*j], &Yvec.elements[2*j], r, d, &graphmode.coords);
+      if (j > 0) {
+	Xvec.elements[2*j - 1] = Xvec.elements[2*j];
+	Yvec.elements[2*j - 1] = Yvec.elements[2*j];
+      }
+    }
+    Xvec.elements[7] = Xvec.elements[0];
+    Yvec.elements[7] = Yvec.elements[0];
+    InPic = FALSE;
+    for (j = 0; j < 8; j+=2) {
+      if ((Xvec.elements[j] >= graphmode.xmin) && 
+	  (Xvec.elements[j] <= graphmode.xmax) && 
+	  (Yvec.elements[j] >= graphmode.ymin) && 
+	  (Yvec.elements[j] <= graphmode.ymax))
+	InPic = TRUE;
+    }
+
+    Xvec.Nelements = Xvec.Nelements = 8;
+    if (InPic) {
+      graphmode.style = 2; /* points */
+      graphmode.ptype = 100; /* connect pairs of points */
+      graphmode.etype = 0;
+      PlotVectorPair (kapa, 8, Xvec.elements, Yvec.elements, &graphmode);
+    }
+  skip:
+    Nskip = gfits_data_size (&header);
+    fseek (f, Nskip, SEEK_CUR); 
+    gfits_free_header (&header);
+  }
+  fclose (f);
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imdata.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imdata.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imdata.c	(revision 16632)
@@ -0,0 +1,219 @@
+# include "dvoshell.h"
+
+int imdata (int argc, char **argv) {
+  
+  int i, j, k, I;
+  int Nimage, N, NPTS, found, mode, TimeSelect;
+  int n, Nregions, NREGIONS, TimeFormat;
+  int *subset, Nsubset;
+  double trange;
+  time_t tzero, start, stop, TimeReference;
+  Image *image;
+  Catalog catalog;
+  SkyTable *sky;
+  SkyList *skylist, *skyset;
+  Vector *vec;
+  SkyRegionSelection *selection;
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) {
+    gprint (GP_ERR, "invalid sky region selection\n");
+    return FALSE;
+  }
+
+  start = stop = 0;
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+    gprint (GP_ERR, "searching in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
+    if (trange > 0) {
+      start = tzero;
+      stop  = tzero + trange;
+    } else {
+      stop = tzero;
+      start  = tzero + trange;
+    }      
+  }
+
+  gprint (GP_ERR, "function is poorly defined; disabled and may be removed\n");
+  return (FALSE);
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: imdata (value) [-time t dt]\n");
+    return (FALSE);
+  }
+
+  /* identify selection */
+  mode = 0;
+  if (!strcasecmp (argv[1], "ra")) 
+    mode = 1;
+  if (!strcasecmp (argv[1], "dec")) 
+    mode = 2;
+  if (!strcasecmp (argv[1], "mag")) 
+    mode = 3;
+  if (!strcasecmp (argv[1], "dmag")) 
+    mode = 4;
+  if (!strcasecmp (argv[1], "Mcal")) 
+    mode = 5;
+  if (!strcasecmp (argv[1], "Mrel")) 
+    mode = 6;
+  if (!strcasecmp (argv[1], "source")) 
+    mode = 7;
+  if (!strcasecmp (argv[1], "x")) 
+    mode = 8;
+  if (!strcasecmp (argv[1], "y")) 
+    mode = 9;
+  if (!strcasecmp (argv[1], "time")) 
+    mode = 10;
+  if (mode == 0) {
+    gprint (GP_ERR, "value may be one of the following:\n");
+    gprint (GP_ERR, " ra dR dec dD mag dmag Mrel Mcal source time\n");
+    return (FALSE);
+  }
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  image_subset (image, Nimage, &subset, &Nsubset, selection, tzero, trange, TimeSelect);
+  BuildChipMatch (image, Nimage);
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  /* load sky from correct table */
+  sky = GetSkyTable ();
+
+  Nregions = 0;
+  NREGIONS = 10;
+  ALLOCATE (skylist, SkyList, 1);
+  ALLOCATE (skylist[0].regions, SkyRegion *, NREGIONS);
+  skylist[0].ownElements = FALSE;
+
+  /* for each image of interest, find the appropriate region files */
+  for (i = 0; i < Nsubset; i++) {
+    I = subset[i];
+
+    if (!FindMosaicForImage (image, Nimage, I)) continue;
+    skyset = SkyListByImage (sky, -1, &image[I]);
+
+    for (j = 0; j < skyset[0].Nregions; j++) {
+      found = FALSE;
+      for (k = 0; (k < skylist[0].Nregions) && !found; k++) {
+	found = !strcmp (skylist[0].regions[k][0].name, skyset[0].regions[j][0].name);
+      }
+      if (found) continue;
+      skylist[0].regions[Nregions] = skyset[0].regions[j];
+      Nregions ++;
+      CHECK_REALLOCATE (skylist[0].regions, SkyRegion *, NREGIONS, Nregions, 10);
+    }
+    SkyListFree (skyset);
+  }	
+  free (subset);
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    gprint (GP_ERR, "try %s\n", skylist[0].regions[i][0].name);
+  } 
+  
+  /* create output vector */
+  NPTS = 1000;
+  REALLOCATE (vec[0].elements, float, NPTS);
+  vec[0].Nelements = N = 0;
+
+  /* for each region file, extract the data of interest in the right time range */
+  for (j = 0; j < skylist[0].Nregions; j++) {
+
+    /* get file name and open */
+    catalog.filename = skylist[0].filename[j];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    /* assign vector values */
+    switch (mode) {
+      case (1):  /* ra */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  n = catalog.measure[i].averef;
+	  vec[0].elements[N] = catalog.average[n].R - catalog.measure[i].dR / 3600.0;
+	  N++;
+	  CHECK_REALLOCATE (vec[0].elements, float, NPTS, N, 1000);
+	}
+	break;
+      case (2):  /* dec */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  n = catalog.measure[i].averef;
+	  vec[0].elements[N] = catalog.average[n].D - catalog.measure[i].dD / 3600.0;
+	  N++;
+	  CHECK_REALLOCATE (vec[0].elements, float, NPTS, N, 1000);
+	}
+	break;
+      case (3):  /* mag */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  vec[0].elements[N] = catalog.measure[i].M;
+	  N++;
+	  CHECK_REALLOCATE (vec[0].elements, float, NPTS, N, 1000);
+	}
+	break;
+      case (4):  /* dmag */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  vec[0].elements[N] = catalog.measure[i].dM;
+	  N++;
+	  CHECK_REALLOCATE (vec[0].elements, float, NPTS, N, 1000);
+	}
+	break;
+      case (5):  /* Mcal */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  vec[0].elements[N] = catalog.measure[i].Mcal;
+	  N++;
+	  CHECK_REALLOCATE (vec[0].elements, float, NPTS, N, 1000);
+	}
+	break;
+      case (6):  /* Mrel */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  n = catalog.measure[i].averef;
+	  // vec[0].elements[N] = catalog.average[n].M;
+	  N++;
+	}
+	break;
+      case (7):  /* source */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  vec[0].elements[N] = catalog.measure[i].photcode;
+	  N++;
+	  CHECK_REALLOCATE (vec[0].elements, float, NPTS, N, 1000);
+	}
+	break;
+      case (10):  /* time */
+	for (i = 0; i < catalog.Nmeasure; i++) {
+	  if ((catalog.measure[i].t < start) || (catalog.measure[i].t > stop)) continue;
+	  vec[0].elements[N] = TimeValue (catalog.measure[i].t, TimeReference, TimeFormat);
+	  N++;
+	  CHECK_REALLOCATE (vec[0].elements, float, NPTS, N, 1000);
+	}
+	break;
+    }
+    dvo_catalog_free (&catalog);
+  }
+  
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, MAX(1,N));
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imdense.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imdense.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imdense.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "dvoshell.h"
+extern double drand48();
+
+int imdense (int argc, char **argv) {
+  
+  long A, B;
+  int i, kapa, N, Nimage, status, NPTS;
+  double r, d, x, y, Rmin, Rmax;
+  Vector Xvec, Yvec;
+  Image *image;
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  /* need options to list only images in region and only images in a time range */
+  /* also, option to list and not plot or plot and not list images */
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: image\n");
+    return (FALSE);
+  }
+
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  BuildChipMatch (image, Nimage);
+
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+  
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+
+  NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  N = 0;
+  for (i = 0; i < Nimage; i++) {
+    /* choose a position for point within image box */
+    x = (0.1 + 0.9*drand48()) * image[i].NX;
+    y = (0.1 + 0.9*drand48()) * image[i].NY;
+    /* project this image to screen display coords */
+    status = FALSE;
+    if (!FindMosaicForImage (image, Nimage, i)) continue;
+    XY_to_RD (&r, &d, x, y, &image[i].coords);
+    while (r < Rmin) r += 360.0; 
+    while (r > Rmax) r -= 360.0; 
+    status |= fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], r, d, &graphmode.coords);
+    if ((Xvec.elements[N] >= graphmode.xmin) && 
+	(Xvec.elements[N] <= graphmode.xmax) && 
+	(Yvec.elements[N] >= graphmode.ymin) && 
+	(Yvec.elements[N] <= graphmode.ymax) && status) {
+      N++;
+      if (N > NPTS - 1) { 
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+
+  Xvec.Nelements = Xvec.Nelements = N;
+  if (N > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.etype = 0;
+    PlotVectorPair (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (image);
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imextract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imextract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imextract.c	(revision 16632)
@@ -0,0 +1,223 @@
+# include "dvoshell.h"
+
+enum {ZERO, RA, DEC, Xm, AIRMASS, MCAL, dMCAL, PHOTCODE, TIME, FWHM, EXPTIME, NSTAR, SKY, NCAL, FLAG, NX_PIX, NY_PIX, THETA, SKEW, SCALE, DSCALE};
+
+int imextract (int argc, char **argv) {
+  
+  int i, j, Nimage, mode, N, PhotcodeSelect;
+  int TimeSelect, *subset, Nsubset, TimeFormat, FlagSelect, FlagValue;
+  double x, y, ra, dec, t, trange;
+  time_t tzero, TimeReference;
+  SkyRegionSelection *selection;
+
+  PhotCode *code;
+  Image *image;
+  Vector *vec;
+
+  if (!InitPhotcodes ()) return (FALSE);
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) {
+    gprint (GP_ERR, "invalid sky region selection\n");
+    return FALSE;
+  }
+
+  /* check for time-based selection */
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+
+  /* check for region-based selection */
+  FlagValue = 0;
+  FlagSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-flag"))) {
+    remove_argument (N, &argc, argv);
+    FlagValue = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    FlagSelect = TRUE;
+  }
+
+  /* check for photcode-based selection */
+  code = NULL;
+  PhotcodeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    PhotcodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    if ((code = GetPhotcodebyName (argv[N])) == NULL) {
+      gprint (GP_ERR, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+      return (FALSE);
+    }
+    if ((code[0].type != PHOT_SEC) && (code[0].type != PHOT_DEP)) {
+      gprint (GP_ERR, "photcode must be primary, secondary, or dependent code\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: imextract (value) [-region] [-time start range] [-photcode photcode]\n");
+    return (FALSE);
+  }
+  
+  /* identify selection */
+  mode = ZERO;
+  if (!strcasecmp (argv[1], "ra")) mode = RA;
+  if (!strcasecmp (argv[1], "dec")) mode = DEC;
+  if (!strcasecmp (argv[1], "Xm")) mode = Xm;
+  if (!strcasecmp (argv[1], "airmass")) mode = AIRMASS;
+  if (!strcasecmp (argv[1], "Mcal")) mode = MCAL;
+  if (!strcasecmp (argv[1], "dMcal")) mode = dMCAL;
+  if (!strcasecmp (argv[1], "photcode")) mode = PHOTCODE;
+  if (!strcasecmp (argv[1], "time")) mode = TIME;
+  if (!strcasecmp (argv[1], "FWHM")) mode = FWHM;
+  if (!strcasecmp (argv[1], "exptime")) mode = EXPTIME;
+  if (!strcasecmp (argv[1], "nstar")) mode = NSTAR;
+  if (!strcasecmp (argv[1], "ncal")) mode = NCAL;
+  if (!strcasecmp (argv[1], "sky")) mode = SKY;
+  if (!strcasecmp (argv[1], "flag")) mode = FLAG;
+  if (!strcasecmp (argv[1], "NX")) mode = NX_PIX;
+  if (!strcasecmp (argv[1], "NY")) mode = NY_PIX;
+  if (!strcasecmp (argv[1], "theta")) mode = THETA;
+  if (!strcasecmp (argv[1], "skew")) mode = SKEW;
+  if (!strcasecmp (argv[1], "scale")) mode = SCALE;
+  if (!strcasecmp (argv[1], "dscale")) mode = DSCALE;
+  if (mode == ZERO) {
+    gprint (GP_ERR, "value may be one of the following:\n");
+    gprint (GP_ERR, " ra dec airmass Mcal dMcal Xm photcode time fwhm exptime nstar ncal sky flag\n");
+    return (FALSE);
+  }
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  image_subset (image, Nimage, &subset, &Nsubset, selection, tzero, trange, TimeSelect);
+  if ((mode == RA) || (mode == DEC)) BuildChipMatch (image, Nimage);
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  /* create storage vector */
+  REALLOCATE (vec[0].elements, float, Nimage);
+  vec[0].Nelements = Nimage;
+  
+  N = 0;
+  /* assign vector values */
+  for (i = 0; i < Nsubset; i++) {
+    j = subset[i];
+    if (PhotcodeSelect) {
+      if (code[0].type == PHOT_DEP) {
+	if (code[0].code != image[j].photcode) continue;
+      } else {
+	if (code[0].code != GetPhotcodeEquivCodebyCode (image[j].photcode)) continue;
+      }
+    }
+    if (FlagSelect && (FlagValue != image[j].code)) continue;
+    switch (mode) {
+      case RA:
+	if (!FindMosaicForImage (image, Nimage, j)) continue;
+	x = 0.5*image[j].NX;
+	y = 0.5*image[j].NY;
+	XY_to_RD (&ra, &dec, x, y, &image[j].coords);
+	vec[0].elements[N] = ra;
+	break;
+      case DEC:
+	if (!FindMosaicForImage (image, Nimage, j)) continue;
+	x = 0.5*image[j].NX;
+	y = 0.5*image[j].NY;
+	XY_to_RD (&ra, &dec, x, y, &image[j].coords);
+	vec[0].elements[N] = dec;
+	break;
+      case Xm:
+	vec[0].elements[N] = pow(10.0, 0.01*image[j].Xm);
+	break;
+      case AIRMASS:
+	vec[0].elements[N] = image[j].secz;
+	break;
+      case MCAL:
+	vec[0].elements[N] = image[j].Mcal;
+	break;
+      case dMCAL:
+	vec[0].elements[N] = image[j].dMcal;
+	break;
+      case PHOTCODE:
+	vec[0].elements[N] = image[j].photcode;
+	break;
+      case TIME:
+	t = image[j].tzero + 0.5*image[j].NY * image[j].trate / 10000;
+	vec[0].elements[N] = TimeValue (t, TimeReference, TimeFormat);
+	break;
+      case FWHM:
+	vec[0].elements[N] = image[j].fwhm_x / 25.0;
+	break;
+      case EXPTIME:
+	vec[0].elements[N] = image[j].exptime;
+	break;
+      case NSTAR:
+	vec[0].elements[N] = image[j].nstar;
+	break;
+      case NCAL:
+	vec[0].elements[N] = image[j].Mxxxx;
+	break;
+      case SKY:
+	vec[0].elements[N] = image[j].Myyyy + 0x8000;
+	break;
+      case FLAG:
+	vec[0].elements[N] = image[j].code;
+	break;
+      case NX_PIX:
+	vec[0].elements[N] = image[j].NX;
+	break;
+      case NY_PIX:
+	vec[0].elements[N] = image[j].NY;
+	break;
+      case THETA: {
+	double theta1, theta2, s1, s2;
+	s1 = SIGN(image[j].coords.pc1_1);
+	s2 = SIGN(image[j].coords.pc2_2);
+	theta1 = DEG_RAD*atan2 (+s1*image[j].coords.pc1_2, s1*image[j].coords.pc1_1);
+	theta2 = DEG_RAD*atan2 (-s2*image[j].coords.pc2_1, s2*image[j].coords.pc2_2);
+	vec[0].elements[N] = 0.5*(theta1+theta2);
+	break; }
+      case SKEW: {
+	double theta1, theta2, s1, s2;
+	s1 = SIGN(image[j].coords.pc1_1);
+	s2 = SIGN(image[j].coords.pc2_2);
+	theta1 = DEG_RAD*atan2 (+s1*image[j].coords.pc1_2, s1*image[j].coords.pc1_1);
+	theta2 = DEG_RAD*atan2 (-s2*image[j].coords.pc2_1, s2*image[j].coords.pc2_2);
+	vec[0].elements[N] = (theta1-theta2);
+	break; }
+      case SCALE: {
+	double scale1, scale2;
+	scale1 = fabs(image[j].coords.cdelt1);
+	scale2 = fabs(image[j].coords.cdelt2);
+	vec[0].elements[N] = 0.5*(scale1+scale2);
+	break; }
+      case DSCALE: {
+	double scale1, scale2;
+	scale1 = fabs(image[j].coords.cdelt1);
+	scale2 = fabs(image[j].coords.cdelt2);
+	vec[0].elements[N] = (scale1-scale2);
+	break; }
+	  }
+    N++;
+  }
+  
+  vec[0].Nelements = N;
+  REALLOCATE (vec[0].elements, float, N);
+
+  free (subset);
+  free (image);
+  return (TRUE);
+  
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imlist.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imlist.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imlist.c	(revision 16632)
@@ -0,0 +1,100 @@
+# include "dvoshell.h"
+
+int imlist (int argc, char **argv) {
+  
+  int i, j, N, Nimage, *subset, Nsubset, TimeSelect, RegionSelect, TimeFormat, NameSelect;
+  int PhotcodeSelect;
+  time_t tzero, TimeReference;
+  double r, d, trange, t;
+  char *name;
+  Image *image;
+  PhotCode *PhotcodeValue;
+  SkyRegionSelection *selection;
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) {
+    gprint (GP_ERR, "invalid sky region selection\n");
+    return FALSE;
+  }
+
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+    gprint (GP_ERR, "plotting in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
+  }
+
+  RegionSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    RegionSelect = TRUE;
+  }
+
+  PhotcodeValue = NULL;
+  PhotcodeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    PhotcodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    PhotcodeValue = GetPhotcodebyName (argv[N]);
+    if (PhotcodeValue == NULL) {
+      gprint (GP_ERR, "photcode not found in photcode table\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  name = NULL;
+  NameSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    name = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    NameSelect = TRUE;
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: image [-time start range] [-region] [-name string]\n");
+    return (FALSE);
+  }
+  
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  image_subset (image, Nimage, &subset, &Nsubset, selection, tzero, trange, TimeSelect);
+  BuildChipMatch (image, Nimage);
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  for (j = 0; j < Nsubset; j++) {
+    i = subset[j];
+    if (NameSelect && (strstr (image[i].name, name) == (char *) NULL)) continue;
+    if (PhotcodeSelect) {
+      if (PhotcodeValue[0].type == PHOT_DEP) {
+	if (PhotcodeValue[0].code != image[i].photcode) continue;
+      } else {
+	if (PhotcodeValue[0].code != GetPhotcodeEquivCodebyCode (image[i].photcode)) continue;
+      }
+    }
+    if (!FindMosaicForImage (image, Nimage, i)) continue;
+    t = TimeValue (image[i].tzero, TimeReference, TimeFormat);
+    if (!strcmp(&image[i].coords.ctype[4], "-DIS")) {
+      XY_to_RD (&r, &d, 0.0, 0.0, &image[i].coords);
+    } else {
+      XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+    }
+    gprint (GP_LOG, "%3d %s %8.4f %8.4f %f %5d %2d %4.2f %5.3f %5.3f\n", 
+	     i, image[i].name, r, d, t, image[i].nstar, image[i].photcode, image[i].secz, image[i].Mcal, image[i].dMcal);
+  }
+
+  free (subset);
+  free (image);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imphot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imphot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imphot.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "dvoshell.h"
+
+int imphot (int argc, char **argv) {
+  
+  time_t tzero;
+  double trange;
+  int N, GreyScale;
+  int i, j, Nimage, Nsubset, *subset;
+  char bufname[64];
+  float *p;
+  double fx, fy, x, y, applyMcal();
+  Image *image;
+  Buffer *buf;
+  SkyRegionSelection *selection;
+
+  GreyScale = FALSE;
+  if ((N = get_argument (argc, argv, "-g"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (bufname, argv[N]);
+    remove_argument (N, &argc, argv);
+    GreyScale = TRUE;
+  }
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) {
+    gprint (GP_ERR, "invalid sky region selection\n");
+    return FALSE;
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: imphot tzero trange [-g buffer]\n");
+    return (FALSE);
+  }
+
+  buf = NULL;
+  if (GreyScale) {
+    if ((buf = SelectBuffer (bufname, ANYBUFFER, TRUE)) == NULL) return (FALSE);
+    CreateBuffer (buf, 100, 200, -32, 0.0, 1.0);
+  }
+
+  /* load image(s) in time range given */
+  if (!ohana_str_to_time (argv[1], &tzero)) { 
+    gprint (GP_ERR, "syntax error\n");
+    return (FALSE);
+  }
+  if (!ohana_str_to_dtime (argv[2], &trange)) { 
+    gprint (GP_ERR, "syntax error\n");
+    return (FALSE);
+  }    
+  gprint (GP_ERR, "searching in range %ds - %ds (%f seconds)\n", (int)tzero, (int)(tzero + trange), trange);
+  
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  image_subset (image, Nimage, &subset, &Nsubset, selection, tzero, trange, TRUE);
+
+  if ((Nsubset > 1) && GreyScale) {
+    gprint (GP_ERR, "more than one image selected, making GreyScale of first only\n");
+  }
+
+  if (GreyScale && Nsubset) {
+    fx = image[subset[0]].NX / 100;
+    fy = image[subset[0]].NY / 200;
+    p = (float *) buf[0].matrix.buffer;
+    for (y = 0; y < 200; y+=1.0) {
+      for (x = 0; x < 100; x+=1.0, p++) {
+	*p = applyMcal (&image[subset[0]], (fx*x), (fy*y));
+      }
+    }
+  }
+
+  for (j = 0; j < Nsubset; j++) {
+    i = subset[j];
+    switch (image[i].order) {
+    case 0:
+      gprint (GP_ERR, "%s: %d - %f\n", image[i].name, image[i].order, image[i].Mcal);
+      break;
+    case 1:
+      gprint (GP_ERR, "%s: %d - %f, %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My);
+      break;
+    case 2:
+      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, image[i].Mxx, image[i].Mxy, image[i].Myy);
+      break;
+    case 3:
+      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d, %d %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, 
+	       image[i].Mxx, image[i].Mxy, image[i].Myy, image[i].Mxxx, image[i].Mxxy, image[i].Mxyy, image[i].Myyy);
+      break;
+    case 4:
+      gprint (GP_ERR, "%s: %d - %f, %d %d, %d %d %d, %d %d %d %d, %d %d %d %d %d\n", image[i].name, image[i].order, image[i].Mcal, image[i].Mx, image[i].My, 
+	       image[i].Mxx, image[i].Mxy, image[i].Myy, image[i].Mxxx, image[i].Mxxy, image[i].Mxyy, image[i].Myyy,
+	       image[i].Mxxxx, image[i].Mxxxy, image[i].Mxxyy, image[i].Mxyyy, image[i].Myyyy);
+      break;
+    }
+  }
+
+  free (image);
+  free (subset);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imrough.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imrough.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imrough.c	(revision 16632)
@@ -0,0 +1,310 @@
+# include "dvoshell.h"
+RegImage *load_imreg (char *DataBase, int *nimage);
+
+# define NVALUE 22
+enum {V_NONE, V_EXPTIME, V_CCDN, V_SKY, V_BIAS, V_FILTER, V_FWHM, V_AIRM, V_TIME, V_TEMP0, V_TEMP1, V_TEMP2, V_TEMP3, V_TELFOCUS, V_XPROBE, V_YPROBE, V_ZPROBE, V_RA, V_DEC, V_DETTEMP, V_ROTANGLE, V_REGTIME};
+static char valuename[NVALUE][32] = {"none", "exptime", "ccd", "sky", "bias", "filter", "fwhm", "airmass", "time", "temp0", "temp1", "temp2", "temp3", "telfocus", "xprobe", "yprobe", "zprobe", "ra", "dec", "dettemp", "rotangle", "regtime"};
+
+int imrough (int argc, char **argv) {
+ 
+  int i, N, Nimage, TimeSelect;
+  int ModeSelect, TypeSelect, CCDSelect, FilterSelect, TimeFormat;
+  int type, value, mode, CCD, NVEC;
+  char DataBase[256], *Filter;
+  double trange;
+  float *Vec;
+  time_t tzero, tend, TimeReference;
+  RegImage *image;
+  Vector *vec;
+
+  VarConfig ("REGISTRATION_DATABASE", "%s", DataBase);
+
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-trange"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tend)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  type = T_UNDEF;
+  TypeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-type"))) {
+    TypeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    type = get_image_type (argv[N]);
+    if (type == T_UNDEF) {
+      gprint (GP_ERR, "ERROR: invalid image type %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  mode = M_NONE;
+  ModeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-mode"))) {
+    ModeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+    mode = get_image_mode (argv[N]);
+    if (mode == M_UNDEF) {
+      gprint (GP_ERR, "ERROR: invalid image mode %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  CCD = 0;
+  CCDSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-ccd"))) {
+    remove_argument (N, &argc, argv);
+    CCD = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    CCDSelect = TRUE;
+  }
+ 
+  Filter = NULL;
+  FilterSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-filter"))) {
+    remove_argument (N, &argc, argv);
+    Filter = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FilterSelect = TRUE;
+    if (!strcasecmp (Filter, "X")) {
+      FilterSelect = FALSE;
+    }
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: imrough (value)\n");
+    gprint (GP_ERR, "       value options:\n");
+    for (i = 1; i < NVALUE; i++) {
+      gprint (GP_ERR, "%s\n", valuename[i]);
+    }
+    return (FALSE);
+  }
+ 
+  /* identify selection */
+  value = V_NONE;
+  for (i = 0; (i < NVALUE) && (value == V_NONE); i++) {
+    if (!strncasecmp (argv[1], valuename[i], strlen(argv[1]))) value = i;
+  }
+  if (value == V_NONE) {
+    gprint (GP_ERR, "ERROR: invalid image value %s\n", argv[1]);
+    return (FALSE);
+  }
+
+  if ((vec = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  image = load_imreg (DataBase, &Nimage);
+  if (image == (RegImage *) NULL) return (FALSE);
+
+  N = 0;
+  NVEC = 1000;
+  REALLOCATE (vec[0].elements, float, NVEC);
+  Vec = vec[0].elements;
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  /* get data */
+  for (i = 0; i < Nimage; i++) {
+    /* skip unmatched selections */
+    if (TimeSelect && ((image[i].obstime < tzero) || (image[i].obstime > tzero + trange))) continue;
+    if (TimeSelect && ((image[i].obstime < tzero) || (image[i].obstime > tzero + trange))) continue;
+    if (FilterSelect && (strcasecmp (image[i].filter, Filter))) continue;
+    if (CCDSelect && (image[i].ccd != CCD)) continue;
+    if (TypeSelect && (image[i].type != type)) continue;
+    if (ModeSelect && (image[i].mode != mode)) continue;
+
+    /* assign correct value */
+    switch (value) {
+    case (V_EXPTIME):
+      Vec[N] = image[i].exptime;
+      break;
+    case (V_CCDN):
+      Vec[N] = image[i].ccd;
+      break;
+    case (V_SKY):
+      Vec[N] = image[i].sky;
+      break;
+    case (V_BIAS):
+      Vec[N] = image[i].bias;
+      break;
+    case (V_FILTER):
+      Vec[N] = image[i].filter[0];
+      break;
+    case (V_FWHM):
+      Vec[N] = image[i].fwhm;
+      break;
+    case (V_AIRM):
+      Vec[N] = image[i].airmass;
+      break;
+    case (V_TIME):
+      Vec[N] = TimeValue (image[i].obstime, TimeReference, TimeFormat);
+      break;
+    case (V_TEMP0):
+      Vec[N] = image[i].teltemp_0;
+      break;
+    case (V_TEMP1):
+      Vec[N] = image[i].teltemp_1;
+      break;
+    case (V_TEMP2):
+      Vec[N] = image[i].teltemp_2;
+      break;
+    case (V_TEMP3):
+      Vec[N] = image[i].teltemp_3;
+      break;
+    case (V_TELFOCUS):
+      Vec[N] = image[i].telfocus;
+      break;
+    case (V_XPROBE):
+      Vec[N] = image[i].xprobe;
+      break;
+    case (V_YPROBE):
+      Vec[N] = image[i].yprobe;
+      break;
+    case (V_ZPROBE):
+      Vec[N] = image[i].zprobe;
+      break;
+    case (V_RA):
+      Vec[N] = image[i].ra;
+      break;
+    case (V_DEC):
+      Vec[N] = image[i].dec;
+      break;
+    case (V_DETTEMP):
+      Vec[N] = image[i].dettemp;
+      break;
+    case (V_ROTANGLE):
+      Vec[N] = image[i].rotangle;
+      break;
+    case (V_REGTIME):
+      Vec[N] = TimeValue (image[i].regtime, TimeReference, TimeFormat);
+      break;
+    }
+    N++;
+    if (N >= NVEC - 1) {
+      NVEC += 1000;
+      REALLOCATE (vec[0].elements, float, NVEC);
+      Vec = vec[0].elements;
+    }
+  }
+
+  REALLOCATE (vec[0].elements, float, MAX (1,N));
+  vec[0].Nelements = N;
+
+  free (image);
+  return (TRUE);
+
+}
+
+RegImage *load_imreg (char *DataBase, int *nimage) {
+
+  int Nimage, status;
+  char line[80];
+  FILE *f;
+  Header header, theader;
+  Matrix matrix;
+  FTable table;
+  RegImage *image;
+
+  *nimage = 0;
+
+  /* open database */
+  f = fopen (DataBase, "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "ERROR: can't open Registration Database\n");
+    return ((RegImage *) NULL);
+  }
+
+  /* load in database header */
+  if (!gfits_fread_header (f, &header)) {
+    fclose (f);
+    gfits_free_header (&header);
+    gprint (GP_ERR, "ERROR: trouble reading database header\n");
+    return ((RegImage *) NULL);
+  }
+
+  /* check for database v1, v2 */
+  gfits_scan (&header, "ORIGIN", "%s", 1, line);
+  if (!strcmp (line, "MDM Observatory")) {
+
+    fseek (f, header.size, SEEK_SET);
+    
+    /* load existing data from database */
+    gfits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+    ALLOCATE (image, RegImage, Nimage);
+    status = fread (image, sizeof(RegImage), Nimage, f);
+    fclose (f);
+    
+    if (status != Nimage) {
+      gprint (GP_ERR, "ERROR: header and data in dB don't match (%d vs %d)\n", Nimage, status);
+      gfits_free_header (&header);
+      free (image);
+      return ((RegImage *) NULL);
+    }
+    gfits_convert_RegImage (image, sizeof (RegImage), Nimage);
+
+    *nimage = Nimage;
+    return (image);
+  }
+
+  /* we probably have v3 */
+  if (!gfits_fread_matrix (f, &matrix, &header)) {
+    fclose (f);
+    gfits_free_header (&header);
+    gfits_free_matrix (&matrix);
+    gprint (GP_ERR, "ERROR: trouble reading database matrix\n");
+    return ((RegImage *) NULL);
+  }
+
+  table.header = &theader;
+  if (!gfits_fread_ftable  (f, &table, "IMAGE_DATABASE")) {
+    fclose (f);
+    gfits_free_header (&header);
+    gfits_free_matrix (&matrix);
+    gprint (GP_ERR, "ERROR: trouble reading database table\n");
+    return ((RegImage *) NULL);
+  }
+
+  /* convert to internal format */
+  image = (RegImage *) table.buffer;
+  gfits_scan (table.header, "NAXIS2", "%d", 1, &Nimage);
+  gfits_convert_RegImage (image, sizeof (RegImage), Nimage);
+
+  gfits_free_header (&header);
+  gfits_free_matrix (&matrix);
+
+  *nimage = Nimage;
+  return (image);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imsearch.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imsearch.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imsearch.c	(revision 16632)
@@ -0,0 +1,154 @@
+# include "dvoshell.h"
+
+int imsearch (int argc, char **argv) {
+ 
+  char DataBase[256], name[64];
+  FILE *f;
+  Header header;
+  RegImage *pimage;
+  int i, Nimage, status, N, TimeSelect, SaveNames;
+  int ModeSelect, TypeSelect, CCDSelect, FilterSelect;
+  char *Filter, *obstime;
+  int Type, Mode, CCD;
+  time_t tzero, obstime_sec;
+  double trange;
+   
+  VarConfig ("REGISTRATION_DATABASE", "%s", DataBase);
+
+  SaveNames = FALSE;
+  if ((N = get_argument (argc, argv, "-save"))) {
+    remove_argument (N, &argc, argv);
+    SaveNames = TRUE;
+  }
+ 
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+ 
+  Type = 0;
+  TypeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-type"))) {
+    remove_argument (N, &argc, argv);
+    Type = get_image_type (argv[N]);
+    if (Type == T_UNDEF) {
+      gprint (GP_ERR, "ERROR: invalid image type %s\n", argv[N]);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    TypeSelect = TRUE;
+  }
+ 
+  Mode = 0;
+  ModeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-mode"))) {
+    remove_argument (N, &argc, argv);
+    Mode = get_image_mode (argv[N]);
+    if (Mode == M_UNDEF) {
+      gprint (GP_ERR, "ERROR: invalid image mode %s\n", argv[N]);
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    ModeSelect = TRUE;
+  }
+ 
+  CCD = 0;
+  CCDSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-ccd"))) {
+    remove_argument (N, &argc, argv);
+    CCD = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+    CCDSelect = TRUE;
+  }
+ 
+  Filter = NULL;
+  FilterSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-filter"))) {
+    remove_argument (N, &argc, argv);
+    Filter = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    FilterSelect = TRUE;
+    if (!strcasecmp (Filter, "X")) {
+      FilterSelect = FALSE;
+    }
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: imsearch [-time start range] [-type type] [-mode mode] [-ccd N] [-filter name]\n");
+    exit (1);
+  }
+
+  /* load in database header */
+  if (!gfits_read_header (DataBase, &header)) {
+    gprint (GP_ERR, "ERROR: trouble reading database header\n");
+    return (FALSE);
+  }
+
+  /* open database */
+  f = fopen (DataBase, "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "ERROR: can't open Registration Database\n");
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET);
+
+  /* load existing data from database */
+  gfits_scan (&header, "NIMAGES", "%d", 1, &Nimage);
+  ALLOCATE (pimage, RegImage, Nimage);
+  status = fread (pimage, sizeof(RegImage), Nimage, f);
+  fclose (f);
+  if (status != Nimage) {
+    gprint (GP_ERR, "ERROR: header and data in dB don't match (%d vs %d)\n", Nimage, status);
+    gfits_free_header (&header);
+    free (pimage);
+    return (FALSE);
+  }
+  gfits_convert_RegImage (pimage, sizeof (RegImage), Nimage);
+
+  /* print out all data */
+  N = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (TimeSelect && ((pimage[i].obstime < tzero) || (pimage[i].obstime > tzero + trange))) continue;
+    if (FilterSelect && (strcasecmp (pimage[i].filter, Filter))) continue;
+    if (ModeSelect && (pimage[i].mode != Mode)) continue;
+    if (CCDSelect && (pimage[i].ccd != CCD)) continue;
+    if (TypeSelect && (pimage[i].type != Type)) continue;
+
+    obstime_sec = (time_t) pimage[i].obstime;
+    obstime = ctime (&obstime_sec);
+    obstime[strlen(obstime)-1] = 0;
+
+    gprint (GP_LOG, "%5d %6s %6s %2d %2d   ", i, get_type_name(pimage[i].type), get_mode_name(pimage[i].mode), pimage[i].ccd, pimage[i].type);
+    gprint (GP_LOG, "%s %s  ", pimage[i].pathname, pimage[i].filename);
+    gprint (GP_LOG, "%s %s %f %s\n", pimage[i].filter, pimage[i].instrument, pimage[i].exptime, obstime);
+
+    if (SaveNames) {
+      sprintf (name, "IMAGEpath:%d", N);
+      set_str_variable (name, pimage[i].pathname);
+      sprintf (name, "IMAGEfile:%d", N);
+      set_str_variable (name, pimage[i].filename);
+      sprintf (name, "IMAGEmode:%d", N);
+      set_int_variable (name, pimage[i].mode);
+    }
+    N++;
+  }
+  if (SaveNames) {
+    set_int_variable ("IMAGEpath:n", N);
+    set_int_variable ("IMAGEfile:n", N);
+  }
+
+  free (pimage);
+  gfits_free_header (&header);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imstats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imstats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/imstats.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "dvoshell.h"
+
+int imstats (int argc, char **argv) {
+  
+  int i, kapa, Nimage, N;
+  int Mcal, AutoLimits;
+  double r, d;
+  Image *image;
+  Vector Xvec, Yvec;  
+  Graphdata graphmode;
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return (FALSE);
+
+  Mcal = TRUE;
+  if ((N = get_argument (argc, argv, "-dM"))) {
+    remove_argument (N, &argc, argv);
+    Mcal = FALSE;
+  }
+
+  AutoLimits = FALSE;
+  if ((N = get_argument (argc, argv, "-l"))) {
+    remove_argument (N, &argc, argv);
+    AutoLimits = TRUE;
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: imstats [-dM] [-l]\n");
+    return (FALSE);
+  }
+
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  BuildChipMatch (image, Nimage);
+
+  /* assign vector values */
+  Xvec.Nelements = Nimage;
+  Yvec.Nelements = Nimage;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  gprint (GP_LOG, "seq  ra (J2000) dec    time (s)   Nstars\n");
+  for (i = 0; i < Nimage; i++) {
+    Xvec.elements[i] = image[i].secz;
+    if (Mcal) 
+      Yvec.elements[i] = image[i].Mcal;
+    else 
+      Yvec.elements[i] = image[i].dMcal;
+    if (!FindMosaicForImage (image, Nimage, i)) continue;
+    XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NY, &image[i].coords);
+    gprint (GP_ERR, "%d %8.4f %8.4f %10d %6d  %5.3f %6.3f %6.3f\n", 
+	     i, r, d, image[i].tzero, image[i].nstar, Xvec.elements[i], 
+	     image[i].Mcal, image[i].dMcal);
+  } 
+  if (AutoLimits) SetLimits (&Xvec, &Yvec, &graphmode);
+
+  graphmode.style = 2;
+  graphmode.etype = 0;
+  PlotVectorPair (kapa, Nimage, Xvec.elements, Yvec.elements, &graphmode);
+  
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/init.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "dvoshell.h"
+
+int avextract       PROTO((int, char **));
+int badimages       PROTO((int, char **));
+int calextract      PROTO((int, char **));
+int calmextract     PROTO((int, char **));
+int catlog          PROTO((int, char **));
+int catdir_define   PROTO((int, char **));
+int ccd             PROTO((int, char **));
+int cmatch          PROTO((int, char **));
+int cmd             PROTO((int, char **));
+int cmpload         PROTO((int, char **));
+int cmpread         PROTO((int, char **));
+int ddmags          PROTO((int, char **));
+int detrend         PROTO((int, char **));
+int dmagaves        PROTO((int, char **));
+int dmagmeas        PROTO((int, char **));
+int dmags           PROTO((int, char **));
+int dmt             PROTO((int, char **));
+int elixir          PROTO((int, char **));
+int fitcolors       PROTO((int, char **));
+int fitsed          PROTO((int, char **));
+int gcat            PROTO((int, char **));
+int getxtra         PROTO((int, char **));
+int gimages         PROTO((int, char **));
+int gstar           PROTO((int, char **));
+int gtypes          PROTO((int, char **));
+int images          PROTO((int, char **));
+int imbox           PROTO((int, char **));
+int imdata          PROTO((int, char **));
+int imdense         PROTO((int, char **));
+int imextract       PROTO((int, char **));
+int imlist          PROTO((int, char **));
+int imphot          PROTO((int, char **));
+int imrough         PROTO((int, char **));
+int imsearch        PROTO((int, char **));
+int imstats         PROTO((int, char **));
+int lcat            PROTO((int, char **));
+int lcurve          PROTO((int, char **));
+int lightcurve      PROTO((int, char **));
+int mextract        PROTO((int, char **));
+int pcat            PROTO((int, char **));
+int photcodes       PROTO((int, char **));
+int pmeasure        PROTO((int, char **));
+int paverage        PROTO((int, char **));
+int procks          PROTO((int, char **));
+int showtile        PROTO((int, char **));
+int skycat          PROTO((int, char **));
+int skycoverage     PROTO((int, char **));
+int skyregion       PROTO((int, char **));
+int simage          PROTO((int, char **));
+int subpix          PROTO((int, char **));
+int version         PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "avextract",   avextract,    "extract average data values"},
+  {1, "badimages",   badimages,    "look for images with anomalous astrometry"},
+  {1, "calextract",  calextract,   "extract photometry calibration"},
+  {1, "calmextract", calmextract,  "extract photometry calibration"},
+  {1, "catdir",      catdir_define,"re-define CATDIR"},
+  {1, "ccd",         ccd,          "plot color-color diagram"},
+  {1, "cmatch",      cmatch,       "match two catalogs"},
+  {1, "cmd",         cmd,          "plot cmd of stars in current region"},
+  {1, "cmpload",     cmpload,      "load cmp file into ?"},
+  {1, "cmpread",     cmpread,      "read data from cmp format files"},
+  {1, "ddmags",      ddmags,       "plot magnitude differences"},
+  {1, "detrend",     detrend,      "extract from detrend database?"},
+  {1, "dmagaves",    dmagaves,     "foo"},
+  {1, "dmagmeas",    dmagmeas,     "foo"},
+  {1, "dmags",       dmags,        "plot differential magnitudes between filters"},
+  {1, "dmt",         dmt,          "plot mag scatter"},
+  {1, "elixir",      elixir,       "talk to elixir"},
+  {1, "fitcolors",   fitcolors,    "fit chip-to-chip color terms"},
+  {1, "fitsed",      fitsed,       "fit stellar SEDs to objects"},
+  {1, "gcat",        gcat,         "get catalog at location"},
+  {1, "gimages",     gimages,      "get images at location"},
+  {1, "gstar",       gstar,        "get star statistics"},
+  {1, "images",      images,       "plot image boxes"},
+  {1, "imbox",       imbox,        "plot expected image box"},
+  {1, "imdata",      imdata,       "extract data for specific images"},
+  {1, "imdense",     imdense,      "image density plot"},
+  {1, "imextract",   imextract,    "extract vectors from catalogs"},
+  {1, "imlist",      imlist,       "list image info"},
+  {1, "imphot",      imphot,       "image photometry info"},
+  {1, "imrough",     imrough,      "get info from imruf database"},
+  {1, "imsearch",    imsearch,     "get info from imreg database"},
+  {1, "imstats",     imstats,      "plot image statistics"},
+  {1, "lcat",        lcat,         "list catalogs in region"},
+  {1, "lcurve",      lcurve,       "plot lightcurve for a star"},
+  {1, "lightcurve",  lightcurve,   "extract lightcurve for a star"},
+  {1, "mextract",    mextract,     "extract measure data values"},
+  {1, "pcat",        skycat,       "plot catalog boundaries"},
+  {1, "photcodes",   photcodes,    "list photometry codes"},
+  {1, "pmeasure",    pmeasure,     "plot individual measurements"},
+  {1, "paverage",    paverage,     "plot average magnitude"},
+  {1, "procks",      procks,       "plot rocks"},
+  {1, "showtile",    showtile,     "plot tile pattern"},
+  {1, "skycat",      skycat,       "show sky catalog boundaries"},
+  {1, "skycoverage", skycoverage,  "measure image union on sky"},
+  {1, "skyregion",   skyregion,    "set sky region for db queries"},
+  {1, "simage",      simage,       "plot stars in an image"},
+  {1, "subpix",      subpix,       "get subpixel positions"},
+  {1, "version",     version,      "show version information"},
+//{1, "addxtra",     addxtra,      "add extra data to object"},
+//{1, "getxtra",     getxtra,      "get extra data from object"},
+}; 
+
+/* move to astro */
+
+void InitDVO () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+}
+
+void FreeDVO () {
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lcat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lcat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lcat.c	(revision 16632)
@@ -0,0 +1,46 @@
+# include "dvoshell.h"
+
+int lcat (int argc, char **argv) {
+  
+  double Radius;
+  int i, N, ShowAll;
+  char exists;
+  struct stat filestat;
+  Graphdata graphmode;
+  SkyTable *sky;
+  SkyList *skylist;
+
+  if (!GetGraphData (&graphmode, NULL, NULL)) return (FALSE);
+
+  ShowAll = FALSE;
+  if ((N = get_argument (argc, argv, "-all"))) {
+    remove_argument (N, &argc, argv);
+    ShowAll = TRUE;
+  }
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: lcat [-all]\n");
+    return (FALSE);
+  }
+
+  Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+
+  /* load sky from correct table */
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, graphmode.coords.crval1, graphmode.coords.crval2, Radius);
+
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    exists = 'Y';
+    if (stat (skylist[0].filename[i], &filestat) == -1) exists = 'N';
+    if (ShowAll) {
+      gprint (GP_ERR, "%3d %s  %c\n", i, skylist[0].regions[i][0].name, exists);
+    } else {
+      if (exists == 'Y') {
+	gprint (GP_ERR, "%3d %s\n", i, skylist[0].regions[i][0].name);
+      }
+    }
+  }
+
+  SkyListFree (skylist);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lcurve.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lcurve.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lcurve.c	(revision 16632)
@@ -0,0 +1,192 @@
+# include "dvoshell.h"
+
+int lcurve (int argc, char **argv) {
+  
+  char string[128], *p;
+  double Ra, Dec, Radius, Radius2, r;
+  double *RA, *DEC;
+  int kapa, TimeFormat;
+  int Nstars, found, AutoLimits, ErrorBars, GalMag, AbsPhot, SaveVectors;
+  int i, j, m, N, NPTS, *N1;
+  time_t TimeReference;
+  struct tm *timeptr;
+  Vector *xvec, *yvec;
+  Vector Xvec, Yvec, dYvec;
+  Catalog catalog;
+  Graphdata graphmode;
+  SkyTable *sky;
+  SkyList *skylist;
+
+  if (!InitPhotcodes ()) return (FALSE);
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return (FALSE);
+
+  AutoLimits = FALSE;
+  if ((N = get_argument (argc, argv, "-l"))) {
+    remove_argument (N, &argc, argv);
+    AutoLimits = TRUE;
+  }
+
+  xvec = yvec = NULL;
+  SaveVectors = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    SaveVectors = TRUE;
+    if ((xvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+    if ((yvec = SelectVector (argv[N], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+    remove_argument (N, &argc, argv);
+  }
+
+  AbsPhot = FALSE;
+  if ((N = get_argument (argc, argv, "-abs"))) {
+    remove_argument (N, &argc, argv);
+    AbsPhot = TRUE;
+  }
+
+  GalMag = FALSE;
+  if ((N = get_argument (argc, argv, "-gal"))) {
+    gprint (GP_ERR, "galaxy magnitudes currently disabled\n");
+    return (FALSE);
+  }
+
+  ErrorBars = FALSE;
+  if ((N = get_argument (argc, argv, "-d"))) {
+    remove_argument (N, &argc, argv);
+    ErrorBars = TRUE;
+  }
+
+  if (argc < 4) {
+    gprint (GP_ERR, "USAGE: lcurve RA DEC Radius\n");
+    return (FALSE);
+  }
+  
+  Ra = atof (argv[1]);
+  Dec = atof (argv[2]);
+  Radius = atof (argv[3]);
+
+  /* load sky from correct table */
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, Ra, Dec, Radius);
+
+  if (skylist[0].Nregions > 1) {
+    gprint (GP_ERR, "warning, radius overlaps region boundary, not yet implemented\n");
+  }
+
+  /* set filename, read in header */
+  catalog.filename = skylist[0].filename[0];
+  catalog.catflags = LOAD_AVES | LOAD_MEAS;
+  catalog.Nsecfilt = 0;
+
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+  }
+  dvo_catalog_unlock (&catalog);
+
+  Nstars = catalog.Naverage;
+  ALLOCATE (RA, double, Nstars);
+  ALLOCATE (DEC, double, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  /* find star(s) in RA, DEC list -- use a dumb algorithm for now, improve later */
+  /* stars are not guaranteed to be sorted in RA or in DEC, so first sort the list */
+  for (i = 0; i < Nstars; i++) {
+    RA[i] = catalog.average[i].R;
+    DEC[i] = catalog.average[i].D;
+    N1[i] = i;
+  }
+  /* sort list by DEC */
+  if (Nstars > 1) sort_coords_index (DEC, RA, N1, Nstars);
+  /* at this point, RA, DEC, and N1 are sorted by DEC.  
+     catalog.average[N1[i]].R = RA[i] */
+
+  NPTS = 100;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  dYvec.elements = NULL;
+  if (ErrorBars) { ALLOCATE (dYvec.elements, float, NPTS); }
+  N = 0;
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  Radius2 = Radius*Radius;
+  found = FALSE;
+  for (i = 0; (i < catalog.Naverage) && !found; i++) {
+
+    /* this can be improved by using a couple of jumps to get within range */
+    if (Dec > DEC[i] + Radius)
+      continue;
+    
+    r = SQ(Dec - DEC[i]) + SQ(Ra - RA[i]);
+    if (r < Radius2) {
+      /* found star, extract measurements */
+      m = catalog.average[N1[i]].offset;
+      for (j = 0; j < catalog.average[N1[i]].Nm; j++, m++) {
+	if (ErrorBars) dYvec.elements[N] = catalog.measure[m].dM;
+	Xvec.elements[N] = TimeValue (catalog.measure[m].t, TimeReference, TimeFormat);
+	Yvec.elements[N] = PhotCat (&catalog.measure[m]);
+	/**** need to use PhotRel optionally here ****/
+	N++; 
+	if (N == NPTS) {
+	  NPTS += 100;
+	  REALLOCATE (Xvec.elements, float, NPTS);
+	  REALLOCATE (Yvec.elements, float, NPTS);
+	  if (ErrorBars) { REALLOCATE (dYvec.elements, float, NPTS); }
+	}
+      }      
+    }
+  }
+  Xvec.Nelements = Yvec.Nelements = N;
+  if (ErrorBars) dYvec.Nelements = N;
+  
+  if (ErrorBars)
+    fsortthree (Xvec.elements, Yvec.elements, dYvec.elements, N);
+  else
+    fsortpair (Xvec.elements, Yvec.elements, N);
+
+  /* autoscale the plot */
+  if (AutoLimits) SetLimits (&Xvec, &Yvec, &graphmode);
+
+  if (ErrorBars) 
+    graphmode.etype = 1;  /* y errors only in lcurves */
+  else
+    graphmode.etype = 0;  
+
+  KapaPrepPlot (kapa, N, &graphmode);
+  KapaPlotVector (kapa, N, Xvec.elements, "x");
+  KapaPlotVector (kapa, N, Yvec.elements, "y");
+  if (ErrorBars) {
+    KapaPlotVector (kapa, N, dYvec.elements, "dym");
+    KapaPlotVector (kapa, N, dYvec.elements, "dyp");
+  }
+
+  timeptr = gmtime ((time_t *)&TimeReference);
+
+  if ((p = get_variable ("TIMEFORMAT")) == (char *) NULL) p = strcreate ("days");
+  sprintf (string, "%s since %02d/%02d/%02d UT", p,
+	   timeptr[0].tm_year, timeptr[0].tm_mon+1, timeptr[0].tm_mday);
+  free (p);
+  KapaSendLabel (kapa, string, 0);
+
+  free (RA);
+  free (DEC);
+  free (N1);
+
+  if (SaveVectors) {
+    free (xvec[0].elements);
+    free (yvec[0].elements);
+    xvec[0].elements = Xvec.elements;
+    yvec[0].elements = Yvec.elements;
+    xvec[0].Nelements = yvec[0].Nelements = Xvec.Nelements;
+  } else {
+    free (Xvec.elements);
+    free (Yvec.elements);
+  }
+
+  if (ErrorBars) free (dYvec.elements);
+  dvo_catalog_free (&catalog);
+
+  SkyListFree (skylist);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lightcurve.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lightcurve.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/lightcurve.c	(revision 16632)
@@ -0,0 +1,145 @@
+# include "dvoshell.h"
+
+int lightcurve (int argc, char **argv) {
+  
+  double Ra, Dec, Radius, Radius2, r;
+  double *RA, *DEC;
+  int Nstars, found, PhotCodeSelect;
+  int i, j, k, m, N, NPTS, Nsecfilt, RELPHOT, *N1, TimeFormat;
+  time_t TimeReference;
+
+  PhotCode *code;
+  Catalog catalog;
+  SkyTable *sky;
+  SkyList *skylist;
+  Vector *tvec, *mvec, *dmvec;
+
+  if (!InitPhotcodes ()) return (FALSE);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  if ((tvec = SelectVector ("tc", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((mvec = SelectVector ("mc", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((dmvec = SelectVector ("dmc", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  RELPHOT = FALSE;
+  if ((N = get_argument (argc, argv, "-rel"))) {
+    remove_argument (N, &argc, argv);
+    RELPHOT = TRUE;
+  }
+
+  code = NULL;
+  PhotCodeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    if ((code = GetPhotcodebyName (argv[N])) == NULL) {
+      gprint (GP_ERR, "ERROR: photcode not found in photcode table\n");
+      return (FALSE);
+    }
+    PhotCodeSelect = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 4) {
+    gprint (GP_ERR, "USAGE: lightcurve RA DEC Radius\n");
+    return (FALSE);
+  }
+  
+  Ra = atof (argv[1]);
+  Dec = atof (argv[2]);
+  Radius = atof (argv[3]);
+
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, Ra, Dec, Radius);
+
+  if (skylist[0].Nregions > 1) {
+    gprint (GP_ERR, "warning, radius overlaps region boundary, not yet implemented\n");
+  }
+
+  /* set filename, read in header */
+  catalog.filename = skylist[0].filename[0];
+  catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+  catalog.Nsecfilt = 0;
+
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+  }
+  dvo_catalog_unlock (&catalog);
+
+  Nstars = catalog.Naverage;
+  ALLOCATE (RA, double, Nstars);
+  ALLOCATE (DEC, double, Nstars);
+  ALLOCATE (N1, int, Nstars);
+
+  /* find star(s) in RA, DEC list -- use a dumb algorithm for now, improve later */
+  /* stars are not guaranteed to be sorted in RA or in DEC, so first sort the list */
+  for (i = 0; i < Nstars; i++) {
+    RA[i] = catalog.average[i].R;
+    DEC[i] = catalog.average[i].D;
+    N1[i] = i;
+  }
+  /* sort list by DEC */
+  if (Nstars > 1) sort_coords_index (DEC, RA, N1, Nstars);
+  /* at this point, RA, DEC, and N1 are sorted by DEC.  
+     catalog.average[N1[i]].R = RA[i] */
+
+  N = 0;
+  NPTS = 100;
+  REALLOCATE (tvec[0].elements, float, NPTS);
+  REALLOCATE (mvec[0].elements, float, NPTS);
+  REALLOCATE (dmvec[0].elements, float, NPTS);
+  
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  Radius2 = Radius*Radius;
+  found = FALSE;
+  for (i = 0; (i < catalog.Naverage) && !found; i++) {
+
+    /* this can be improved by using a couple of jumps to get within range */
+    if (Dec > DEC[i] + Radius)
+      continue;
+    
+    r = SQ(Dec - DEC[i]) + SQ(Ra - RA[i]);
+    if (r < Radius2) {
+      k = N1[i];
+      /* found star, extract measurements */
+      m = catalog.average[k].offset;
+      for (j = 0; j < catalog.average[k].Nm; j++, m++) {
+
+	if (PhotCodeSelect) {
+	  if ((code[0].type == PHOT_REF) || (code[0].type == PHOT_DEP)) {
+	    if (code[0].code != catalog.measure[m].photcode) continue;
+	  } 
+	  if (code[0].type == PHOT_SEC) {
+	    if (code[0].code != GetPhotcodeEquivCodebyCode (catalog.measure[m].photcode)) continue;
+	  } 
+	}      
+
+	tvec[0].elements[N] = TimeValue (catalog.measure[m].t, TimeReference, TimeFormat);
+	dmvec[0].elements[N] = catalog.measure[m].dM;
+	if (RELPHOT) {
+	  mvec[0].elements[N] = PhotCat (&catalog.measure[m]);
+	} else {
+	  mvec[0].elements[N] = PhotRel (&catalog.measure[m], &catalog.average[k], &catalog.secfilt[k*Nsecfilt]);
+	}
+	N++; 
+	if (N == NPTS) {
+	  NPTS += 100;
+	  REALLOCATE (tvec[0].elements, float, NPTS);
+	  REALLOCATE (mvec[0].elements, float, NPTS);
+	  REALLOCATE (dmvec[0].elements, float, NPTS);
+	}
+      }      
+    }
+  }
+  fsortthree (tvec[0].elements, mvec[0].elements, dmvec[0].elements, N);
+  tvec[0].Nelements = mvec[0].Nelements = dmvec[0].Nelements = N;
+
+  free (RA);
+  free (DEC);
+  free (N1);
+  dvo_catalog_free (&catalog);
+  SkyListFree (skylist);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/match_image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/match_image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/match_image.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "dvoshell.h"
+
+int match_image (Image *image, int Nimage, unsigned int T, short int S) {
+
+  int N, Nlo, Nhi, N1, N2;
+
+  /* bracket first value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].tzero < T) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  N1 = Nlo;
+
+  /* bracket last value of interest */
+  Nlo = 0; Nhi = Nimage;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[N].tzero > T) {
+      Nhi = N;
+    } else {
+      Nlo = N - 1;
+    }
+  }
+  N2 = Nhi;
+
+  for (N = N1; N < N2; N++) {
+    if ((image[N].tzero == T) && (image[N].photcode == S)) {
+      return (N);
+    }
+  }
+  return (-1);
+}
+
+int match_image_subset (Image *image, int *subset, int Nsubset, unsigned int T, short int S) {
+
+  int N, Nlo, Nhi, N1, N2;
+
+  /* bracket first value of interest */
+  Nlo = 0; Nhi = Nsubset;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[subset[N]].tzero < T) {
+      Nlo = N;
+    } else {
+      Nhi = N + 1;
+    }
+  }
+  N1 = Nlo;
+
+  /* bracket last value of interest */
+  Nlo = 0; Nhi = Nsubset;
+  while (Nhi - Nlo > 10) {
+    N = 0.5*(Nlo + Nhi);
+    if (image[subset[N]].tzero > T) {
+      Nhi = N;
+    } else {
+      Nlo = N - 1;
+    }
+  }
+  N2 = Nhi;
+
+  for (N = N1; N < N2; N++) {
+    if ((image[subset[N]].tzero == T) && (image[subset[N]].photcode == S)) {
+      return (subset[N]);
+    }
+  }
+  return (-1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/mextract.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/mextract.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/mextract.c	(revision 16632)
@@ -0,0 +1,233 @@
+# include "dvoshell.h"
+
+int mextract (int argc, char **argv) {
+  
+  int i, j, k, m, n, N, Npts, NPTS, last, Nfields, Nreturn, Ncstack, Nstack;
+  int Nsecfilt, VERBOSE, loadImages, mosaicMode;
+  char **cstack, name[1024];
+  float *values;
+  void *Signal;
+
+  Catalog catalog;
+  SkyList *skylist;
+  PhotCode *code;
+  Vector **vec;
+  dbField *fields;
+  dbStack *stack;
+  SkyRegionSelection *selection;
+
+  /* defaults */
+  skylist = NULL;
+  code = NULL;
+  fields = NULL;
+  stack = NULL;
+
+  if ((N = get_argument (argc, argv, "-h"))) goto help;
+  if ((N = get_argument (argc, argv, "--help"))) goto help;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  dvo_catalog_init (&catalog, TRUE);
+
+  /* load photcode information */
+  if (!InitPhotcodes ()) goto escape;
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  
+  // init locally static variables (time refs)
+  dbExtractMeasuresInit();
+
+  // parse skyregion options
+  if ((selection = SetRegionSelection (&argc, argv)) == NULL) goto escape;
+
+  // command-line is of the form: avextract field,field, field [where (field op value)...]
+
+  // parse the fields to be extracted and returned
+  fields = dbCmdlineFields (argc, argv, DVO_TABLE_MEASURE, &last, &Nfields);
+  if (fields == NULL) return (FALSE);
+
+  // XXX add the skyregion limits as if it were a where statement
+
+  // parse the remainder of the line as a boolean math expression
+  cstack = isolate_elements (argc-last, &argv[last], &Ncstack);
+  
+  // construct the db Boolean math stack (frees cstack)
+  stack = dbRPN (Ncstack, cstack, &Nstack);
+  if ((Ncstack > 0) && (Nstack < 1)) {
+    print_error ();
+    goto escape;
+  }
+
+  // add the skyregion limits to the where statement (or create)
+  dbAstroRegionLimits (&stack, &Nstack, selection, DVO_TABLE_MEASURE);
+
+  // parse stack elements into fields and scalars as needed
+  Nreturn = Nfields; 
+  dbCheckStack (stack, Nstack, DVO_TABLE_MEASURE, &fields, &Nfields);
+  // XXX handle errors
+
+  /* load region corresponding to selection above */
+  if ((skylist = SelectRegions (selection)) == NULL) goto escape;
+
+  // load image data if needed (for fields listed below)
+  loadImages = FALSE;
+  mosaicMode = FALSE;
+  for (i = 0; !loadImages && (i < Nfields); i++) {
+    if (fields[i].ID == MEAS_XCCD) loadImages = TRUE;
+    if (fields[i].ID == MEAS_YCCD) loadImages = TRUE;
+    if (fields[i].ID == MEAS_XMOSAIC) loadImages = mosaicMode = TRUE;
+    if (fields[i].ID == MEAS_YMOSAIC) loadImages = mosaicMode = TRUE;
+  }
+  if (loadImages && !SetImageSelection (mosaicMode, selection)) goto escape;
+
+  /* create storage vector */
+  ALLOCATE (values, float, Nfields);
+  ALLOCATE (vec, Vector *, Nreturn);
+  for (i = 0; i < Nreturn; i++) {
+    if (ISNUM(fields[i].name[0])) {
+      sprintf (name, "v_%s", fields[i].name);
+    } else {
+      sprintf (name, "%s", fields[i].name);
+    }
+    if ((vec[i] = SelectVector (name, ANYVECTOR, TRUE)) == NULL) goto escape;
+  }
+
+  Npts = 0;
+  NPTS = 1;
+
+  // grab data from all selected sky regions
+  Signal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+  for (i = 0; (i < skylist[0].Nregions) && !interrupt; i++) {
+    /* lock, load, unlock catalog */
+    catalog.filename = skylist[0].filename[i];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+    catalog.Nsecfilt = Nsecfilt;
+
+    if (VERBOSE) gprint (GP_ERR, "trying %s (%d of %d)\n", catalog.filename, i, skylist[0].Nregions);
+      
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      gprint (GP_ERR, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    /* XXX need to call dvo_catalog_chipcoords here passing the loaded images */
+
+    for (j = 0; (j < catalog.Naverage) && !interrupt; j++) {
+      m = catalog.average[j].offset;
+      for (k = 0; (k < catalog.average[j].Nm); k++, m++) {
+
+	// extract the relevant values for this measurement
+	for (n = 0; n < Nfields; n++) {
+	  values[n] = dbExtractMeasures (&catalog.average[j], &catalog.secfilt[j*Nsecfilt], &catalog.measure[m], &fields[n]);
+	}
+	// fprintf (stderr, "object: ave: %f, cat: %f, averef %d\n", fields[n].name, values[2], values[3], catalog.measure[m].averef);
+
+	// test the conditional statement
+	if (!dbBooleanCond (stack, Nstack, values)) continue;
+	for (n = 0; n < Nreturn; n++) {
+	  vec[n][0].elements[Npts] = values[n];
+	  // fprintf (stderr, "keep : field: %s, value: %f\n", fields[n].name, values[n]);
+	}
+	Npts++;
+	if (Npts >= NPTS) {
+	  NPTS += 2000;
+	  for (n = 0; n < Nreturn; n++) {
+	    REALLOCATE (vec[n][0].elements, float, NPTS);
+	  }
+	}
+      }
+    }
+    dvo_catalog_free (&catalog);
+    // dbStackAllocPrint ();
+    // dbStackAllocReset ();
+    // dbStackFreePrint ();
+    // dbStackFreeReset ();
+  }
+  signal (SIGINT, Signal);
+  interrupt = FALSE;
+
+  for (n = 0; n < Nreturn; n++) {
+    vec[n][0].Nelements = Npts;
+    REALLOCATE (vec[n][0].elements, float, MAX(1,Npts));
+  }
+
+  dbFreeFields (fields, Nfields);
+  dbFreeStack (stack, Nstack);
+  free (stack);
+  FreeImageSelection ();
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  return (TRUE);
+
+escape:
+  dbFreeFields (fields, Nfields);
+  dbFreeStack (stack, Nstack);
+  free (stack);
+  FreeImageSelection ();
+  SkyListFree (skylist);
+  FreeSkyRegionSelection (selection);
+  dvo_catalog_free (&catalog);
+  return (FALSE);
+
+ help:
+  gprint (GP_ERR, "USAGE: mextract field[,field,field...] where (expression)\n");
+
+  if ((argc > N + 1) && !strcasecmp (argv[N+1], "fields")) {
+    gprint (GP_ERR, " USAGE: avextract field[,field,field...] where (expression)\n");
+    gprint (GP_ERR, "  RA : right ascension (J2000) for detection\n");
+    gprint (GP_ERR, "  DEC : declination for detection\n");
+    gprint (GP_ERR, "  RA:ave : average right ascension (J2000) for object\n");
+    gprint (GP_ERR, "  DEC:ave : average declination for object\n");
+    gprint (GP_ERR, "  RA:err : ra scatter \n");
+    gprint (GP_ERR, "  DEC:err : dec scatter\n");
+    gprint (GP_ERR, "  uRA : proper motion in ra\n");
+    gprint (GP_ERR, "  uDEC : proper motion in dec\n");
+    gprint (GP_ERR, "  duRA : proper motion error in ra\n");
+    gprint (GP_ERR, "  duDEC : proper motion error in dec\n");
+    gprint (GP_ERR, "  PAR : parallax\n");
+    gprint (GP_ERR, "  dPAR : parallax error \n");
+    gprint (GP_ERR, "  nmeas : number of measurements\n");
+    gprint (GP_ERR, "  nmiss : number of non-detections\n");
+    gprint (GP_ERR, "  xp : positional chi-square\n");
+    gprint (GP_ERR, "  objflag : object flags\n");
+    gprint (GP_ERR, "  photcode:ave : average magnitude for photcode (or equivalent)\n");
+    gprint (GP_ERR, "  photcode:ref : reference magnitude system for photcode (or equivalent)\n");
+    gprint (GP_ERR, "  photcode:inst : instrumental magnitude for photcode\n");
+    gprint (GP_ERR, "  photcode:cat :  catalog magnitude for photcode\n");
+    gprint (GP_ERR, "  photcode:sys :  system magnitude for photcode\n");
+    gprint (GP_ERR, "  photcode:rel :  relative magnitude for photcode\n");
+    gprint (GP_ERR, "  photcode:cal :  calibrated magnitude for photcode \n");
+    gprint (GP_ERR, "  photcode:err : magnitude error for photcode\n");
+    gprint (GP_ERR, "  photcode:chisq : chi-square of magnitude fit\n");
+    gprint (GP_ERR, "  photcode:ncode : number of measurements in photcode\n");
+    gprint (GP_ERR, "  photcode:nphot : number of measurements used for average magnitude\n");
+    gprint (GP_ERR, "  airmass : airmass of detection\n");
+    gprint (GP_ERR, "  exptime : exposure time\n");
+    gprint (GP_ERR, "  photcode : photcode \n");
+    gprint (GP_ERR, "  time : time of exposure\n");
+    gprint (GP_ERR, "  dR : ra offset\n");
+    gprint (GP_ERR, "  dD : dec offset\n");
+    gprint (GP_ERR, "  fwhm : fwhm (average)\n");
+    gprint (GP_ERR, "  fwhm_maj : fwhm (major axis)\n");
+    gprint (GP_ERR, "  fwhm_min : fwhm (minor axis)\n");
+    gprint (GP_ERR, "  theta : position angle\n");
+    gprint (GP_ERR, "  flags : detection flags\n");
+    gprint (GP_ERR, "  xccd : ccd x position\n");
+    gprint (GP_ERR, "  yccd : ccd y position\n");
+    gprint (GP_ERR, "  xmosaic : mosaic x position\n");
+    gprint (GP_ERR, "  ymosaic : mosaic y position\n");
+    gprint (GP_ERR, "  xchip : chip x position\n");
+    gprint (GP_ERR, "  ychip : chip y position\n");
+    gprint (GP_ERR, "  xfpa : fpa x position\n");
+    gprint (GP_ERR, "  yfpa : fpa y position\n");
+    return (FALSE);
+  }
+  gprint (GP_ERR, " mextract --help fields : for a complete listing of allowed fields\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/notes.txt	(revision 16632)
@@ -0,0 +1,10 @@
+
+avextract ra,dec,g,r,i where (ra > 5) && (dec < 3)
+
+
+U db_check_stack.c
+U db_convert_to_RPN.c
+U dvoBooleanElements.c
+U dvoEvaluateStack.c
+U dvodb.c
+U dvofields.c
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/paverage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/paverage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/paverage.c	(revision 16632)
@@ -0,0 +1,157 @@
+# include "dvoshell.h"
+# define NCHUNK 10000
+
+int paverage (int argc, char **argv) {
+  
+  FILE *f;
+  int i, j, kapa, Narg, Npts, NPTS, status, VERBOSE;
+  int Nsecfilt, Nsec;
+  double Mz, Mr, mag;
+  double Radius, Rmin, Rmax, R, D;
+  unsigned IDclip, IDchoice, LimExclude;
+  float *Xvec, *Yvec, *Zvec;
+
+  PhotCode *photcode;
+  SkyTable *sky;
+  SkyList *skylist;
+  Catalog catalog;
+  Graphdata graphmode;
+  Average *average;
+  SecFilt *secfilt;
+
+  if (!InitPhotcodes ()) return (FALSE);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  f = (FILE *) NULL;
+  Mz = 17.0;
+  Mr = -5.0;
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  // require a photcode?  default to 0?
+  Nsec = 0;
+  if ((Narg = get_argument (argc, argv, "-p"))) {
+    remove_argument (Narg, &argc, argv);
+    photcode = GetPhotcodebyName (argv[Narg]);
+    if (!photcode) {
+	fprintf (stderr, "unknown photcode %s\n", argv[Narg]);
+	return (FALSE);
+    }
+    remove_argument (Narg, &argc, argv);
+    Nsec = GetPhotcodeNsec (photcode[0].code);
+    if (Nsec == -1) {
+	fprintf (stderr, "photcode %s is not an AVERAGE photcode\n", argv[Narg]);
+	return (FALSE);
+    }
+  }
+
+  IDchoice = 0;
+  IDclip = FALSE;
+  if ((Narg = get_argument (argc, argv, "-ID"))) {
+    remove_argument (Narg, &argc, argv);
+    IDchoice  = atoi(argv[Narg]);
+    remove_argument (Narg, &argc, argv);
+    IDclip = TRUE;
+  }
+
+  LimExclude = FALSE;
+  if ((Narg = get_argument (argc, argv, "-x"))) {
+    remove_argument (Narg, &argc, argv);
+    LimExclude = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((Narg = get_argument (argc, argv, "-v"))) {
+    remove_argument (Narg, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  if ((Narg = get_argument (argc, argv, "-m"))) {
+    remove_argument (Narg, &argc, argv);
+    Mr  = atof(argv[Narg]);
+    remove_argument (Narg, &argc, argv);
+    Mz = atof(argv[Narg]);
+    Mr = Mr - Mz;
+    remove_argument (Narg, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: paverage (-all) [-m M M] [-p photcode] [-ID ID] [-flag value] [-x]\n");
+    return (FALSE);
+  }
+  graphmode.style = 2; /* set style to points */
+  graphmode.size = -1; /* point size determined by Zvec */
+  graphmode.etype = 0; /* no errorbars */
+
+  Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+
+  /* load sky from correct table */
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, graphmode.coords.crval1, graphmode.coords.crval2, Radius);
+  
+  /* storage for plotting the points */
+  Npts = 0;
+  NPTS = 1000;
+  ALLOCATE (Xvec, float, NPTS);
+  ALLOCATE (Yvec, float, NPTS);
+  ALLOCATE (Zvec, float, NPTS);
+
+  for (j = 0; j < skylist[0].Nregions; j++) {
+    catalog.filename = skylist[0].filename[j];
+    catalog.catflags = LOAD_AVES | LOAD_SECF;
+    catalog.Nsecfilt = Nsecfilt;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, VERBOSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    average = catalog.average;
+    secfilt = catalog.secfilt;
+
+    /* project stars to screen display coords */
+    for (i = 0; i < catalog.Naverage; i++) {
+      if (IDclip && (average[i].code != IDchoice)) continue;
+      while (average[i].R < Rmin) average[i].R += 360.0;
+      while (average[i].R > Rmax) average[i].R -= 360.0;
+
+      mag = secfilt[i*Nsecfilt+Nsec].M;
+      Zvec[Npts] = MIN (1.0, MAX (0.01, (mag - Mz) / Mr));
+      if (LimExclude && (Zvec[Npts] > 0.99)) continue;
+      if (Zvec[Npts] < 0.011) continue;
+      R = average[i].R;
+      D = average[i].D;
+      status = fRD_to_XY (&Xvec[Npts], &Yvec[Npts], R, D, &graphmode.coords);
+      if (!status) {
+	  fprintf (stderr, ".");
+	  continue;
+      }
+      Npts ++;
+
+      if (Npts == NPTS - 1) {
+	  NPTS += 1000;
+	  REALLOCATE (Xvec, float, NPTS);
+	  REALLOCATE (Yvec, float, NPTS);
+	  REALLOCATE (Zvec, float, NPTS);
+      }
+      if (Npts > NCHUNK) {
+	  PlotVectorTriplet (kapa, Npts, Xvec, Yvec, Zvec, &graphmode);
+	  Npts = 0;
+      }
+    }
+    dvo_catalog_free (&catalog);
+  }
+  if (Npts > 0) PlotVectorTriplet (kapa, Npts, Xvec, Yvec, Zvec, &graphmode);
+
+  free (Xvec);
+  free (Yvec);
+  free (Zvec);
+
+  return (TRUE);
+
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/pcat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/pcat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/pcat.c	(revision 16632)
@@ -0,0 +1,111 @@
+# include "dvoshell.h"
+int RD_to_XYpic (double *x, double *y, double r, double d, Coords *coords, double Rmin, double Rmax, double Rmid, int *leftside);
+
+// XXX EAM : this function is deprecated (now points at skycat)
+int pcat (int argc, char **argv) {
+  
+  double Radius;
+  int i, j, kapa, N, Nregions, ShowAll, NPTS, Npts, leftside;
+  RegionFile *regions;
+  char filename[128];
+  struct stat filestat;
+  Vector Xvec, Yvec;
+  Graphdata graphmode;
+  double X[4], Y[4], Rmin, Rmax, Rmid;
+  char catdir[256];
+  int VERBOSE;
+
+  VarConfig ("CATDIR", "%s", catdir);
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  ShowAll = FALSE;
+  if ((N = get_argument (argc, argv, "-all"))) {
+    remove_argument (N, &argc, argv);
+    ShowAll = TRUE;
+  }
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: pcat [-all]\n");
+    return (FALSE);
+  }
+  if (!GetGraph (&graphmode, &kapa, NULL)) return (FALSE);
+  
+  Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+  regions = find_regions (graphmode.coords.crval1, graphmode.coords.crval2, Radius, &Nregions);
+
+  Rmin = graphmode.coords.crval1 - 180.0;
+  Rmax = graphmode.coords.crval1 + 180.0;
+  Rmid = 0.5*(Rmin + Rmax);
+
+  NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  Npts = 0;
+   
+  for (i = 0; i < Nregions; i++) {
+    sprintf (filename, "%s/%s", catdir, regions[i].name);
+    if (ShowAll || (stat (filename, &filestat) != -1)) {
+      if (VERBOSE) gprint (GP_ERR, "%3d %s\n", i, regions[i].name);
+
+      leftside = -1;
+      RD_to_XYpic (&X[0], &Y[0], regions[i].RA0, regions[i].DEC0, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+      RD_to_XYpic (&X[1], &Y[1], regions[i].RA0, regions[i].DEC1, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+      RD_to_XYpic (&X[2], &Y[2], regions[i].RA1, regions[i].DEC1, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+      RD_to_XYpic (&X[3], &Y[3], regions[i].RA1, regions[i].DEC0, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+
+      Xvec.elements[Npts] = X[0];
+      Yvec.elements[Npts] = Y[0];
+      for (j = 1; j < 4; j++) {
+	Xvec.elements[Npts + j*2 - 0] = X[j];
+	Yvec.elements[Npts + j*2 - 0] = Y[j];
+	Xvec.elements[Npts + j*2 - 1] = X[j];
+	Yvec.elements[Npts + j*2 - 1] = Y[j];
+      }
+      Xvec.elements[Npts+7] = Xvec.elements[Npts];
+      Yvec.elements[Npts+7] = Yvec.elements[Npts];
+      Npts += 8;
+      if (Npts > NPTS - 1) {  /* this is OK because NPTS is made always a multiple of 8 */
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+
+  gprint (GP_ERR, "plotting %d catalogs\n", Npts/8);
+  Xvec.Nelements = Xvec.Nelements = Npts;
+  if (Npts > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.etype = 0;
+    PlotVectorPair (kapa, Npts, Xvec.elements, Yvec.elements, &graphmode);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (regions);
+
+  return (TRUE);
+
+}
+
+int RD_to_XYpic (double *x, double *y, double r, double d, Coords *coords, double Rmin, double Rmax, double Rmid, int *leftside) {
+
+  while (r < Rmin) { r += 360.0; }
+  while (r > Rmax) { r -= 360.0; }
+
+  if (*leftside == -1) {
+    *leftside = (r < Rmid);
+  } else {
+    if (  *leftside && (r > Rmid + 90)) { r -= 360.0; }
+    if (! *leftside && (r < Rmid - 90)) { r += 360.0; }
+  }
+
+  RD_to_XY (x, y, r, d, coords);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/photcodes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/photcodes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/photcodes.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "dvoshell.h"
+
+/* list or return all photcodes equivalent to the given filter */
+int photcodes (int argc, char **argv) {
+  
+  int i, Np;
+  int *list, Nlist;
+  char name[64];
+  PhotCode *code;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: photcodes (photcode)\n");
+    return (FALSE);
+  }
+
+  /* load photcodes, convert name to code */
+  if (!InitPhotcodes ()) return (FALSE);
+
+  if (!(Np = GetPhotcodeCodebyName (argv[1]))) {
+    gprint (GP_ERR, "ERROR: photcode not found in photcode table\n");
+    return (FALSE);
+  }
+
+  list = GetPhotcodeEquivList (Np, &Nlist);
+  
+  for (i = 0; i < Nlist; i++) {
+    code = GetPhotcodebyCode (list[i]);
+
+    sprintf (name, "photcode:name:%d", i);
+    set_str_variable (name, code[0].name);
+
+    sprintf (name, "photcode:C:%d", i);
+    set_variable (name, 0.001*code[0].C);
+
+    sprintf (name, "photcode:K:%d", i);
+    set_variable (name, code[0].K);
+
+    sprintf (name, "photcode:X:%d", i);
+    set_variable (name, code[0].X[0]);
+
+    sprintf (name, "photcode:dX:%d", i);
+    set_variable (name, 0.001*code[0].dX);
+
+    sprintf (name, "photcode:code:%d", i);
+    set_int_variable (name, code[0].code);
+
+    sprintf (name, "photcode:filter:%d", i);
+    set_str_variable (name, GetPhotcodeNamebyCode (code[0].equiv));
+
+    sprintf (name, "photcode:c1:%d", i);
+    set_str_variable (name, GetPhotcodeNamebyCode (code[0].c1));
+
+    sprintf (name, "photcode:c2:%d", i);
+    set_str_variable (name, GetPhotcodeNamebyCode (code[0].c2));
+
+    gprint (GP_ERR, "%5d %s %7.4f %7.4f %7.4f\n", 
+	     code[0].code, code[0].name, 0.001*code[0].C, code[0].K, code[0].X[0]);
+  }
+  set_int_variable ("photcode:n", Nlist);
+  free (list);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/photometry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/photometry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/photometry.c	(revision 16632)
@@ -0,0 +1,1220 @@
+# include "dvoshell.h"
+
+/* match code to measure  */
+# define TESTCODE(C,M) \
+  if (C != NULL) { \
+    switch (C[0].type) { \
+    case PHOT_DEP: \
+    case PHOT_REF: \
+      if (C[0].code != M.photcode) continue; \
+      break; \
+    case PHOT_SEC: \
+      if (C[0].code != GetPhotcodeEquivCodebyCode (M.photcode)) continue; \
+      break; \
+    default: \
+      break; \
+  } }
+
+/* exclusions based on measure.params  */
+# define TESTMEASURE(M) \
+  if (ApplySelections[SelectionParam]) { \
+    if (TimeSelect && (M.t < tzero)) continue; \
+    if (TimeSelect && (M.t > tend)) continue; \
+    if (ErrSelect  && (M.dM > ErrValue)) continue; \
+    if (TypeSelect && (TypeValue != GetMeasureTypeCode (&M))) continue; \
+    if (iMagSelect && (PhotInst (&M) < iMagMin)) continue; \
+    if (FlagSelect && (M.dbFlags != FlagValue)) continue; \
+  }
+
+# define SETMAG(MOUT,MEAS,MODE) \
+  MOUT = NAN; \
+  if (MODE == MAG_INST) MOUT = PhotInst (&MEAS);  \
+  if (MODE == MAG_CAT)  MOUT = PhotCat  (&MEAS); \
+  if (MODE == MAG_SYS)  MOUT = PhotSys  (&MEAS, average, secfilt); \
+  if (MODE == MAG_REL)  MOUT = PhotRel  (&MEAS, average, secfilt); \
+  if (MODE == MAG_CAL)  MOUT = PhotCal  (&MEAS, average, secfilt, measure, GetPhotcodeEquivbyCode (MEAS.photcode)); \
+  if (MODE == MAG_AVE)  MOUT = PhotAve  (GetPhotcodeEquivbyCode (MEAS.photcode), average, secfilt); \
+  if (MODE == MAG_REF)  MOUT = PhotRef  (GetPhotcodeEquivbyCode (MEAS.photcode), average, secfilt, measure); \
+  if (ApplySelections[SelectionParam]) { \
+    if (MagSelect && (MOUT > MagMax)) continue; \
+    if (MagSelect && (MOUT < MagMin)) continue; \
+  }
+
+/* selection criteria */
+/* selections based on Measure quantities */
+static int TimeSelect;
+static time_t tzero, tend;
+static int MagSelect;
+static double MagMax, MagMin;
+static int TypeSelect, TypeValue;
+static int ErrSelect;
+static double ErrValue;
+static int iMagSelect;
+static double iMagMin;
+static int FlagSelect, FlagValue;
+static int TypefracSelect, TypefracType, TypefracSign;
+static double TypefracValue;
+
+/* apply selections or not */
+static int ApplySelections[4];
+static int SelectionParam;
+
+/* applied to Average quantities */
+static int PhotcodeSelect;
+static PhotCode *PhotcodeValue;
+static int PhotcodeMode;
+
+/* selections based on Average quantities */
+static int ChiSelect;
+static float ChiLimit;
+
+/* selections based on ensemble quantities */
+static int NphotSelect, NphotSign, NphotValue;
+static int NcodeSelect, NcodeSign, NcodeValue;
+static int FWHMSelect, FWHMsign;
+static double FWHMvalue, FWHMfrac;
+
+/* time concepts */
+static time_t TimeReference;
+static int TimeFormat;
+
+int GetTimeSelection (time_t *tz, time_t *te) {
+  *tz = tzero;
+  *te = tend;
+  return (TimeSelect);
+}
+
+int GetPhotcodeInfo (char *string, PhotCode **Code, int *Mode) {
+
+  PhotCode *code;
+  int mode, status;
+  char *p, *tmpstring;
+
+  /* save local copy */
+  tmpstring = strcreate (string);
+
+  /* check for code:mode in photcode name */
+  mode = MAG_NONE;
+  p = strchr (tmpstring, ':');
+  if (p != NULL) {
+    mode = GetMagMode (p + 1);
+    if (mode == MAG_NONE) {
+      gprint (GP_ERR, "syntax error in magnitude mode\n");
+      free (tmpstring);
+      return (FALSE);
+    }
+    *p = 0;
+  }
+
+  /* how do we handle this elsewhere? */
+  if (!strcasecmp (tmpstring, "mag")) {
+    /* need to validate mode */
+    *Mode = mode;
+    *Code = NULL;
+    free (tmpstring);
+    return (TRUE);
+  }
+
+  code = GetPhotcodebyName (tmpstring);
+  if (code == NULL) {
+    gprint (GP_ERR, "photcode not found in photcode table\n");
+    free (tmpstring);
+    return (FALSE);
+  }
+
+  /* test allowable cases and/or set default values */
+  status = FALSE;
+  if (code[0].type == PHOT_DEP) {
+    if (mode == MAG_NONE) mode = MAG_REL;
+    if (mode == MAG_INST) status = TRUE;
+    if (mode == MAG_CAT)  status = TRUE;
+    if (mode == MAG_SYS)  status = TRUE;
+    if (mode == MAG_REL)  status = TRUE;
+    if (mode == MAG_CAL)  status = TRUE;
+  }  
+  if (code[0].type == PHOT_SEC) {
+    if (mode == MAG_NONE) mode  = MAG_AVE;
+    if (mode == MAG_INST) status = TRUE;
+    if (mode == MAG_CAT)  status = TRUE;
+    if (mode == MAG_SYS)  status = TRUE;
+    if (mode == MAG_REL)  status = TRUE;
+    if (mode == MAG_CAL)  status = TRUE;
+    if (mode == MAG_AVE)  status = TRUE;
+    if (mode == MAG_REF)  status = TRUE;
+  }  
+  if (code[0].type == PHOT_ALT) {
+    if (mode == MAG_NONE) mode  = MAG_AVE;
+    if (mode == MAG_AVE)  status = TRUE;
+    if (mode == MAG_REF)  status = TRUE;
+  }
+
+  if (code[0].type == PHOT_REF) {
+    if (mode == MAG_NONE) mode  = MAG_CAT;
+    if (mode == MAG_CAT)  status = TRUE;
+  }
+
+  if (!status) {
+    gprint (GP_ERR, "mismatch in photcode and magmode\n");
+    free (tmpstring);
+    return (FALSE);
+  }
+  *Code = code;
+  *Mode = mode;
+  free (tmpstring);
+  return (TRUE);
+}
+ 
+int SetSelectionParam (int param) {
+  SelectionParam = param;
+  return (TRUE);
+}
+
+int GetSelectionParam () {
+  return (SelectionParam);
+}
+
+int GetMeasureParam (char *parname) {
+
+  int param;
+
+  param = MEAS_ZERO;
+  if (!strcasecmp (parname, "ra"))   	 param = MEAS_RA;
+  if (!strcasecmp (parname, "dec"))  	 param = MEAS_DEC;
+  if (!strcasecmp (parname, "mag")) 	 param = MEAS_MAG;
+  // if (!strcasecmp (parname, "dmag")) 	 param = MEAS_dMAG;
+  if (!strcasecmp (parname, "airmass"))  param = MEAS_AIRMASS;
+  if (!strcasecmp (parname, "exptime"))  param = MEAS_EXPTIME;
+  if (!strcasecmp (parname, "photcode")) param = MEAS_PHOTCODE;
+  if (!strcasecmp (parname, "time"))     param = MEAS_TIME;
+  if (!strcasecmp (parname, "dR")) 	 param = MEAS_RA_OFFSET;
+  if (!strcasecmp (parname, "dD")) 	 param = MEAS_DEC_OFFSET;
+  if (!strcasecmp (parname, "fwhm"))   	 param = MEAS_FWHM;
+  // if (!strcasecmp (parname, "dophot")) 	 param = MEAS_DOPHOT;
+  if (!strcasecmp (parname, "FLAGS"))    param = MEAS_DB_FLAGS;
+  if (!strcasecmp (parname, "XCCD"))   	 param = MEAS_XCCD;
+  if (!strcasecmp (parname, "YCCD"))   	 param = MEAS_YCCD;
+  if (!strcasecmp (parname, "XMOSAIC"))  param = MEAS_XMOSAIC;
+  if (!strcasecmp (parname, "YMOSAIC"))  param = MEAS_YMOSAIC;
+  if (!strcasecmp (parname, "help")) {
+    gprint (GP_ERR, "value may be one of the following:\n");
+    gprint (GP_ERR, " ra dR dec dD mag dmag Mrel Mcal photcode time fwhm dophot xccd yccd xmosaic ymosaic flags\n");
+    gprint (GP_ERR, "value may also be a valid photcode\n");
+    gprint (GP_ERR, "photcodes or 'mag' may have optional magnitude type: mag,[Minst, Mcat, Msys, Mrel, Mcal]\n");
+  }
+  return (param);
+}
+  
+int GetAverageParam (char *parname) {
+
+  int param;
+
+  param = AVE_ZERO;
+  if (!strcasecmp (parname, "RA"))    param = AVE_RA;
+  if (!strcasecmp (parname, "DEC"))   param = AVE_DEC;
+
+  if (!strcasecmp (parname, "dRA"))   param = AVE_RA_ERR;
+  if (!strcasecmp (parname, "dDEC"))  param = AVE_DEC_ERR;
+
+  if (!strcasecmp (parname, "uRA"))   param = AVE_U_RA;
+  if (!strcasecmp (parname, "uDEC"))  param = AVE_U_DEC;
+  if (!strcasecmp (parname, "duRA"))  param = AVE_U_RA_ERR;
+  if (!strcasecmp (parname, "duDEC")) param = AVE_U_DEC_ERR;
+
+  if (!strcasecmp (parname, "par"))   param = AVE_PAR;
+  if (!strcasecmp (parname, "dpar"))  param = AVE_PAR_ERR;
+
+  if (!strcasecmp (parname, "dmag"))  param = AVE_dMAG;
+  if (!strcasecmp (parname, "mag"))   param = AVE_MAG;
+  if (!strcasecmp (parname, "Nmeas")) param = AVE_NMEAS;
+  if (!strcasecmp (parname, "Nmiss")) param = AVE_NMISS;
+  if (!strcasecmp (parname, "Xp"))    param = AVE_Xp;
+  if (!strcasecmp (parname, "Xm"))    param = AVE_Xm;
+  if (!strcasecmp (parname, "flag"))  param = AVE_FLAG;
+  if (!strcasecmp (parname, "type"))  param = AVE_TYPE;
+  if (!strcasecmp (parname, "typefrac")) {
+    if (!TypefracType) {
+      gprint (GP_ERR, "typefrac needs to specify type to use\n");
+      return (param);
+    }
+    param = AVE_TYPEFRAC;
+  }
+  if (!strcasecmp (parname, "Nphot")) param = AVE_NPHOT;
+  if (!strcasecmp (parname, "Ncode")) param = AVE_NCODE;
+  // if (!strcasecmp (parname, "Ncrit")) param = AVE_NCRIT;
+  return (param);
+}
+
+/* I've set some selections - if these require a photcode, check if I set one */
+int TestPhotSelections (PhotCode **code, int *mode, int param) {
+
+  int NeedPhotcode, Needcode;
+
+  /* if i've supplied a photcode (code != NULL), i'm not allowed to restrict it */
+  if (code[0] != NULL) {
+    if (PhotcodeSelect) {
+      gprint (GP_ERR, "photcode selection rules violated: cannot restrict photcode with a photcode\n");
+      return (FALSE);
+    } else {
+      return (TRUE);
+    }
+  }
+
+  /* for measure tests, supply MEAS_ZERO */
+
+  /* if I have an average or ensemble restriction, I must have a PRI/SEC photcode */
+  NeedPhotcode = FALSE;
+  NeedPhotcode |= ChiSelect;
+  NeedPhotcode |= NphotSelect;
+  NeedPhotcode |= ErrSelect;
+  NeedPhotcode |= TypeSelect;
+  NeedPhotcode |= TypefracSelect;
+  
+  NeedPhotcode |= (param == AVE_Xm);
+  NeedPhotcode |= (param == AVE_MAG);
+  NeedPhotcode |= (param == AVE_dMAG);
+  NeedPhotcode |= (param == AVE_TYPE);
+  NeedPhotcode |= (param == AVE_NPHOT);
+  Needcode = (param == AVE_NCODE);
+
+  if (NeedPhotcode || Needcode || NcodeSelect || PhotcodeSelect) {
+    if (!PhotcodeSelect) {
+      gprint (GP_ERR, "photcode selection problem: value requires photcode\n");
+      return (FALSE);
+    }
+    code[0] = PhotcodeValue;
+    mode[0] = PhotcodeMode;
+  }
+  if (NeedPhotcode) {
+    if (code[0][0].type == PHOT_SEC) return (TRUE);
+    if (code[0][0].type == PHOT_REF) return (TRUE);
+    gprint (GP_ERR, "photcode selection problem: average value requires average photcode\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+void GetAverageParamHelp () {
+  gprint (GP_ERR, "value may be one of the following:\n");
+  gprint (GP_ERR, " ra dec dmag Nmeas Nmiss Xm Xp Nphot Ncode flag type typefrac\n\n");
+  gprint (GP_ERR, "value may also be a valid photcode\n");
+  gprint (GP_ERR, "photcodes or 'mag' may have optional magnitude mode: mag,[Mave, Mref]\n");
+  return;
+}
+
+/* (re)load photcodes from photcode table */
+int InitPhotcodes () {
+
+  double ZERO_POINT;
+  char MasterPhotcodeFile[256];
+  char CatdirPhotcodeFile[256];
+  char *catdir;
+
+  if (VarConfig ("ZERO_PT", "%lf", &ZERO_POINT) == (char *) NULL) {
+      gprint (GP_ERR, "ZERO_PT undefined in config\n");
+      return (FALSE);
+  }
+  SetZeroPoint (ZERO_POINT);
+
+  catdir = GetCATDIR();
+  if (catdir == NULL) {
+    CatdirPhotcodeFile[0] = 0;
+  } else {
+    sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", catdir);
+  }
+
+  if (VarConfig ("PHOTCODE_FILE", "%s", MasterPhotcodeFile) == (char *) NULL) {
+      gprint (GP_ERR, "PHOTCODE_FILE undefined in config\n");
+      return (FALSE);
+  }
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    gprint (GP_ERR, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+int ListPhotSelections () {
+
+  gprint (GP_ERR, "TimeSelect: %d, %d - %d\n",      TimeSelect, tzero, tend);
+  gprint (GP_ERR, "MagSelect: %d, %f - %f\n",       MagSelect, MagMax, MagMin);
+  gprint (GP_ERR, "TypeSelect: %d, %d\n",           TypeSelect, TypeValue);
+  gprint (GP_ERR, "ErrSelect: %d, %f\n",            ErrSelect, ErrValue);
+  gprint (GP_ERR, "iMagSelect: %d, %f\n",           iMagSelect, iMagMin);
+  gprint (GP_ERR, "FlagSelect: %d, %x\n",           FlagSelect, FlagValue);
+  gprint (GP_ERR, "TypefracSelect: %d, %d %d %f\n", TypefracSelect, TypefracType, TypefracSign, TypefracValue);
+  gprint (GP_ERR, "ApplySelections: %d,%d,%d,%d : %d\n", ApplySelections[0], ApplySelections[1], ApplySelections[2], ApplySelections[3], SelectionParam);
+  if (PhotcodeSelect) {
+    gprint (GP_ERR, "PhotcodeSelect: %d, %s\n",       PhotcodeSelect, PhotcodeValue[0].name);
+  } else {
+    gprint (GP_ERR, "PhotcodeSelect: %d, none\n",       PhotcodeSelect);
+  }
+  gprint (GP_ERR, "ChiSelect: %d, %f\n",            ChiSelect, ChiLimit);
+  gprint (GP_ERR, "NphotSelect: %d, %d - %d\n",     NphotSelect, NphotSign, NphotValue);
+  gprint (GP_ERR, "NcodeSelect: %d, %d - %d\n",     NcodeSelect, NcodeSign, NcodeValue);
+  gprint (GP_ERR, "FWHMSelect: %d, %d %f %f\n",     FWHMSelect, FWHMsign, FWHMvalue, FWHMfrac);
+  return (TRUE);
+}
+
+/* remove standard photometry filtering options, set selections */
+/* not all functions respect all selections... */
+int SetPhotSelections (int *argc, char **argv, int Nparams) {
+
+  int i, N;
+  double trange;
+
+  if ((N = get_argument (*argc, argv, "-phothelp"))) {
+    gprint (GP_ERR, "optional photometry selection criteria:\n");
+    gprint (GP_ERR, " -magrange min max\n");
+    gprint (GP_ERR, " -imaglim min\n");
+    gprint (GP_ERR, " -flag value\n");
+    gprint (GP_ERR, " -chisq value\n");
+    gprint (GP_ERR, " -photcode code\n");
+    gprint (GP_ERR, " -time start range\n");
+    gprint (GP_ERR, " -errorlim value\n");
+    gprint (GP_ERR, " -type type\n");
+    gprint (GP_ERR, " -nmeas [+/-]N\n");
+    gprint (GP_ERR, " -fwhm [+/-]fraction\n");
+    return (FALSE);
+  }
+
+  /* select based on measured mag (MEASURE ONLY) */
+  MagSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-magrange"))) {
+    MagSelect = TRUE;
+    remove_argument (N, argc, argv);
+    MagMin = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    MagMax = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select based on instrument mag (MEASURE ONLY) */
+  iMagSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-imaglim"))) {
+    iMagSelect = TRUE;
+    remove_argument (N, argc, argv);
+    iMagMin = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on value of flag (MEASURE ONLY) */
+  FlagSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-flag"))) {
+    FlagSelect = TRUE;
+    remove_argument (N, argc, argv);
+    FlagValue = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on value of Chisq (AVERAGE ONLY) */
+  SelectionParam = 0;
+  for (i = 0; i < 4; i++) ApplySelections[i] = TRUE;
+  if ((N = get_argument (*argc, argv, "-apply"))) {
+    remove_argument (N, argc, argv);
+    if (strlen(argv[N]) != Nparams) {
+      gprint (GP_ERR, "-apply selection must define all parameter choices\n");
+      return (FALSE);
+    }
+    for (i = 0; i < Nparams; i++) {
+      if (toupper(argv[N][i]) == 'Y') {
+	ApplySelections[i] = TRUE;
+      } else {
+	ApplySelections[i] = FALSE;
+      }
+    }
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on value of photcode */
+  PhotcodeSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-photcode"))) {
+    PhotcodeSelect = TRUE;
+    remove_argument (N, argc, argv);
+    GetPhotcodeInfo (argv[N], &PhotcodeValue, &PhotcodeMode);
+    if (PhotcodeValue == NULL) {
+      gprint (GP_ERR, "photcode not found in photcode table\n");
+      return (FALSE);;
+    }
+    remove_argument (N, argc, argv);
+  }
+
+  /* selection on basis of time range (MEASURE only) */
+  TimeSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-time"))) {
+    remove_argument (N, argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, argc, argv);
+    TimeSelect = TRUE;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tend = tzero;
+      tzero -= trange;
+    } else {
+      tend = tzero + trange;
+    }
+  }
+
+  /* select by error (on measure or average) */
+  ErrSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-errorlim"))) {
+    remove_argument (N, argc, argv);
+    ErrValue = atof (argv[N]);
+    remove_argument (N, argc, argv);
+    ErrSelect = TRUE;
+  }
+
+  /* select on value of Chisq (AVERAGE ONLY) */
+  ChiSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-chisq"))) {
+    ChiSelect = TRUE;
+    remove_argument (N, argc, argv);
+    ChiLimit = atof (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on measurement type: 1,2,3 (AVERAGE ONLY) */
+  TypeSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-type"))) {
+    remove_argument (N, argc, argv);
+    TypeValue = atoi (argv[N]);
+    remove_argument (N, argc, argv);
+    TypeSelect = TRUE;
+  }
+
+  /* select on measurement type: 1,2,3 (AVERAGE ONLY) */
+  TypefracType = 0;
+  if ((N = get_argument (*argc, argv, "-usetype"))) {
+    remove_argument (N, argc, argv);
+    TypefracType = atoi (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  /* select on measurement type: 1,2,3 (AVERAGE ONLY) */
+  TypefracSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-typefrac"))) {
+    remove_argument (N, argc, argv);
+    TypefracType  = atoi (argv[N]);
+    remove_argument (N, argc, argv);
+    TypefracValue = fabs (atof (argv[N]));
+    TypefracSign = 0;
+    if (argv[N][0] == '-') TypefracSign = -1;
+    if (argv[N][0] == '+') TypefracSign = +1;
+    remove_argument (N, argc, argv);
+    TypefracSelect = TRUE;
+  }
+
+  /* select by number of measurements (AVERAGE ONLY) */
+  NphotSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-nphot"))) {
+    remove_argument (N, argc, argv);
+    NphotValue = abs (atoi (argv[N]));
+    NphotSign = 0;
+    if (argv[N][0] == '-') NphotSign = -1;
+    if (argv[N][0] == '+') NphotSign = +1;
+    remove_argument (N, argc, argv);
+    NphotSelect = TRUE;
+  }
+
+  /* select by number of measurements (AVERAGE ONLY) */
+  NcodeSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-ncode"))) {
+    remove_argument (N, argc, argv);
+    NcodeValue = abs (atoi (argv[N]));
+    NcodeSign = 0;
+    if (argv[N][0] == '-') NcodeSign = -1;
+    if (argv[N][0] == '+') NcodeSign = +1;
+    remove_argument (N, argc, argv);
+    NcodeSelect = TRUE;
+  }
+
+  /* -fwhm value frac (AVERAGE ONLY) */
+  FWHMSelect = FALSE;
+  if ((N = get_argument (*argc, argv, "-fwhm"))) {
+    remove_argument (N, argc, argv);
+    FWHMvalue = abs (atof (argv[N]));
+    FWHMsign = 0;
+    if (argv[N][0] == '-') FWHMsign = -1;
+    if (argv[N][0] == '+') FWHMsign = +1;
+    remove_argument (N, argc, argv);
+    FWHMSelect = TRUE;
+    remove_argument (N, argc, argv);
+    FWHMfrac = atof (argv[N]);
+  }
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+  return (TRUE);
+}
+
+/* extract a list of measure parameters from the specified average entry based on the pre-set selections */
+double *ExtractMeasures (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+
+  int i, Nlist, NLIST;
+  double M, *list;
+  
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+
+  /* check selections based on averages & ensembles: chisq, Nphot, etc */
+  if (!TestAverage (code, average, secfilt, measure)) return (list); 
+
+  /* look for measures */
+  for (i = 0; i < average[0].Nm; i++) {
+    TESTCODE (code, measure[i]);  /* skip measurements not matching photcode */
+    TESTMEASURE (measure[i]);     /* exclusions based on measure.params  */
+    SETMAG (M, measure[i], mode); /* set appropriate magnitude (also does MagSelect) */ 
+
+    /* assign value */
+    list[Nlist] = GetMeasure (param, &average[0], &measure[i], M);
+    Nlist ++;
+  }
+  *nlist = Nlist;
+  return (list);
+}
+
+/* return average.param based on the selection */
+double ExtractAverages (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int param) {
+
+  int i;
+  double value;
+
+  value = NAN;
+
+  /* this function requires code set for certain value of param.  
+     use TestPhotSelectionsAverage to validate code/param choices */
+
+  /* filter by average quantities (eg, chisq, Nphot, etc) */
+  if (!TestAverage (code, average, secfilt, measure)) return (NAN);
+
+  /* assign vector values */
+  switch (param) {
+    case AVE_RA:
+      value = average[0].R;
+      break;
+    case AVE_DEC:
+      value = average[0].D;
+      break;
+    case AVE_RA_ERR:
+      value = average[0].dR;
+      break;
+    case AVE_DEC_ERR:
+      value = average[0].dD;
+      break;
+
+    case AVE_U_RA:
+      value = average[0].uR;
+      break;
+    case AVE_U_DEC:
+      value = average[0].uD;
+      break;
+    case AVE_U_RA_ERR:
+      value = average[0].duR;
+      break;
+    case AVE_U_DEC_ERR:
+      value = average[0].duD;
+      break;
+
+    case AVE_PAR:
+      value = average[0].P;
+      break;
+    case AVE_PAR_ERR:
+      value = average[0].dP;
+      break;
+
+
+    case AVE_NMEAS:
+      value = average[0].Nm;
+      break;
+    case AVE_NMISS:
+      value = average[0].Nn;
+      break;
+    case AVE_Xp:
+      value = 0.01*average[0].Xp;
+      break;
+    case AVE_FLAG:
+      value = average[0].code;
+      break;
+    case AVE_MAG:
+      switch (mode) {
+	case MAG_AVE:
+	  value = PhotAve  (code, average, secfilt);
+	  break;
+	case MAG_REF:
+	  value = PhotRef  (code, average, secfilt, measure);
+	  break;
+	case MAG_INST:
+	case MAG_CAT:
+	case MAG_SYS:
+	case MAG_REL:
+	case MAG_CAL:
+	  value = NAN;
+	  for (i = 0; i < average[0].Nm; i++) {
+	      if (code[0].code != measure[i].photcode) continue;
+	      value = measure[i].M;
+	  }
+	  break;
+      }
+      break;
+    case AVE_dMAG:
+      value = PhotdM (code, average, secfilt);
+      break;
+    case AVE_Xm:
+      value = PhotXm (code, average, secfilt);
+      break;
+    case AVE_TYPE:
+      value = DetermineTypeCode (average, measure, code[0].code);
+      break;
+    case AVE_TYPEFRAC:
+      value = DetermineTypefrac (average, measure, code);
+      break;
+    case AVE_NCODE:
+      value = 0;
+      for (i = 0; i < average[0].Nm; i++) {
+	if (code[0].code != GetPhotcodeEquivCodebyCode (measure[i].photcode)) continue;
+	value ++;
+      }
+      break;
+    case AVE_NPHOT:
+      value = 0;
+      for (i = 0; i < average[0].Nm; i++) {
+	if (code[0].code != GetPhotcodeEquivCodebyCode (measure[i].photcode)) continue;
+	if (measure[i].dbFlags & (ID_MEAS_POOR | ID_MEAS_SKIP)) continue;
+	value ++;
+      }
+      break;
+# if (0)
+    case AVE_NCRIT:
+      value = 0;
+      for (i = 0; i < average[0].Nm; i++) {
+	if ((code != NULL) && (code[0].code != GetPhotcodeEquivCodebyCode (measure[i].photcode))) continue;
+	if (ErrSelect && (measure[i].dM > ErrValue)) continue;
+	if (FlagSelect && (measure[i].dbFlags != FlagValue)) continue;
+	if (TypeSelect && (TypeValue != GetMeasureTypeCode (&measure[i]))) continue;
+	if (iMagSelect && (PhotInst (&measure[i]) < iMagMin)) continue;
+	value ++;
+      }
+      break;
+# endif
+  }
+  return (value);
+}  
+
+/* return fraction of measures (matching code) which have requested type */
+double DetermineTypefrac (Average *average, Measure *measure, PhotCode *code) {
+
+  double frac;
+  int k, Nc, Nt;
+  
+  Nt = Nc = 0;
+  for (k = 0; k < average[0].Nm; k++) {
+    if ((code != NULL) && (code[0].code != GetPhotcodeEquivCodebyCode (measure[k].photcode))) continue;
+    Nc ++;
+    if (measure[k].dophot != TypefracType) continue;
+    Nt ++;
+  }
+  frac = (double) Nt / (double) Nc;
+  return (frac);
+}
+
+/* determine the representative dophot type for this photcode (must be PRI/SEC) */
+int DetermineTypeCode (Average *average, Measure *measure, int code) {
+
+  int k, N, Nt[3];
+  
+  Nt[0] = Nt[1] = Nt[2] = 0;
+  for (k = 0; k < average[0].Nm; k++) {
+    if (code != GetPhotcodeEquivCodebyCode (measure[k].photcode)) continue;
+    N = GetMeasureTypeCode (&measure[k]);
+    Nt[N] ++;
+  }
+  if (Nt[0]) return (0);
+  if (Nt[1]) return (1);
+  if (Nt[2]) return (2);
+  return (3);
+}
+
+int GetMeasureTypeCode (Measure *measure) {
+  switch (measure[0].dophot) {
+    case 0:
+    case 1:
+    case 2:
+      return (0);
+      break;
+    case 3:
+    case 4:
+    case 5:
+    case 7:
+    case 9:
+      return (1);
+      break;
+    case 10:
+    default:
+      return (2);
+  }
+  return (2);
+}  
+
+int Quality (Measure *measure, int IsDophot) {
+
+  return (TRUE);
+  
+  if (IsDophot) {
+    
+    if (measure[0].dophot == 4) return (FALSE);
+    return (TRUE);
+  
+  } else {
+    
+    if (0.01 * measure[0].FWx < 3.0) return (FALSE);
+    if (0.01 * measure[0].FWx > 10.0) return (FALSE);
+
+    return (TRUE);
+
+  }
+}
+
+/* test if this average object meets the specified selection criteria.
+   for photcode-dependent quantities, only test for PRI/SEC photcodes */
+int TestAverage (PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure) {
+
+  int i, Nm, Type, Select;
+  double fwhm, typefrac, dM, Xm;
+
+  /** temporary special case for Jen Katz: exclude REF with Ncode > 1 */
+  if ((code != NULL) && (code[0].type == PHOT_REF)) {
+    Nm = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      TESTCODE (code, measure[i]);
+      Nm++;
+    }
+    if (Nm > 1) return (FALSE);
+  }
+
+  if (!ApplySelections[SelectionParam]) return (TRUE);
+
+  /* pass objects with more than FWHMfrac points with FWHM above / below FWHMvalue */ 
+  if (FWHMSelect) {
+    Nm = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      fwhm = measure[i].FWx / 100.0;
+      switch (FWHMsign) {
+	case 0:
+	  if (fwhm == FWHMvalue) break;
+	  continue;
+	case +1:
+	  if (fwhm >= FWHMvalue) break;
+	  continue;
+	case -1:
+	  if (fwhm <= FWHMvalue) break;
+	  continue;
+      }
+      Nm++;
+    }
+    if (average[0].Nm * FWHMfrac > Nm) return (FALSE);
+  }
+
+  /* all selections below require a valid photcode */
+  Select = ChiSelect || ErrSelect || NcodeSelect || NphotSelect || TypeSelect || TypefracSelect;
+  if (!Select) return (TRUE);
+
+  /* must have a valid code of some kind */
+  if (code == NULL) return (FALSE);
+
+  /* for NcodeSelect, count Nmeas for appropriate photcode */
+  if (NcodeSelect) {
+    Nm = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      TESTCODE (code, measure[i]);
+      Nm++;
+    }
+    switch (NcodeSign) {
+      case 0:
+	if (Nm == NcodeValue) break;
+	return (FALSE);
+      case 1:
+	if (Nm >= NcodeValue) break;
+	return (FALSE);
+      case -1:
+	if (Nm <= NcodeValue) break;
+	return (FALSE);
+      default:
+	return (FALSE);
+    }
+  }
+
+  /* only PRI/SEC photcodes apply the filter */
+  if (code[0].type == PHOT_DEP) return (TRUE);
+  if (code[0].type == PHOT_REF) return (TRUE);
+
+  /* exclusions based on average.params  */
+  if (ChiSelect) {
+    Xm = PhotXm (code, average, secfilt);
+    if (Xm == -1) return (FALSE);
+    if (Xm > ChiLimit) return (FALSE);
+  }
+  
+  /* for ErrSelect, check average errors */
+  if (ErrSelect) {
+    dM = PhotdM (code, average, secfilt);
+    if (dM > ErrValue) return (NAN);
+  }
+  
+  /* for NphotSelect, count Nmeas for appropriate photcode */
+  if (NphotSelect) {
+    Nm = 0;
+    for (i = 0; i < average[0].Nm; i++) {
+      TESTCODE (code, measure[i]);
+      if (measure[i].dbFlags && ID_MEAS_SKIP) continue;
+      Nm++;
+    }
+    switch (NphotSign) {
+      case 0:
+	if (Nm == NphotValue) break;
+	return (FALSE);
+      case 1:
+	if (Nm >= NphotValue) break;
+	return (FALSE);
+      case -1:
+	if (Nm <= NphotValue) break;
+	return (FALSE);
+      default:
+	return (FALSE);
+    }
+  }
+
+  /* for TypeSelect, check on TypeCode for this object */
+  if (TypeSelect) {
+    Type = DetermineTypeCode (average, measure, code[0].code);
+    if (Type != TypeValue) return (FALSE);
+  }
+
+  /* for TypeSelect, check on TypeCode for this object */
+  if (TypefracSelect) {
+    typefrac = DetermineTypefrac (average, measure, code);
+    switch (TypefracSign) {
+      case 0:
+	if (typefrac == TypefracValue) break;
+	return (FALSE);	
+      case +1:
+	if (typefrac >= TypefracValue) break;
+	return (FALSE);	
+      case -1:
+	if (typefrac <= TypefracValue) break;
+	return (FALSE);	
+      default:
+	return (FALSE);
+    }
+  }
+
+  return (TRUE);
+}
+
+/* for this function, we don't need to call PhotRel, etc, but we
+   do need to multiply by 0.001:
+   average[].M is stored as 1000*mag where mag is PhotAbs
+   measure[].M for PHOT_REL is the same 
+   XXX EAM : note that we are transitioning away from millimag internal storage 
+*/ 
+
+/* send in:
+   Nphot - photcode number
+   Tphot - photcode type
+   Ns    - secfilt entry (-1 for PRI)
+   &catalog.average[i], 
+   &catalog.measure[catalog.average[i].offset], 
+   &catalog.secfilt[i*Nsec] 
+*/
+
+
+double *ExtractMagnitudes (PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *n) {
+  
+  double *M, mag;
+  int N;
+
+  if ((mode == MAG_AVE) || (mode == MAG_REF)) {
+    ALLOCATE (M, double, 1);
+    mag = ExtractAverages (code, mode, average, secfilt, measure, AVE_MAG);
+    if (isnan(mag)) {
+      N = 0;
+    } else {
+      N = 1;
+      M[0] = mag;
+    }
+  } else {
+    M = ExtractMeasures (code, mode, average, secfilt, measure, &N, MEAS_MAG);
+  }
+  
+  *n = N;
+  return (M);
+}
+
+/* extract delta-mag pairs applying specified selections */
+double *ExtractDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist) {
+
+  int i, j, A1, A2, N1, N2, Np, Nlist, NLIST;
+  double *M1, *M2, *list;
+
+  /* check for special case of measure-measure - this is needed to drop self-matches */
+  A1 = ((mode[0] == MAG_AVE) || (mode[0] == MAG_REF));
+  A2 = ((mode[1] == MAG_AVE) || (mode[1] == MAG_REF));
+  if (!A1 && !A2) {
+    list = ExtractMeasuresDMag (code, mode, average, secfilt, measure, nlist);
+    return (list);
+  }
+
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm*average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+  M1 = M2 = NULL;
+
+  /* one of the two is an average, must do independently */
+  M1 = ExtractMagnitudes (code[0], mode[0], average, secfilt, measure, &N1);
+  if (N1 == 0) goto skip;
+  
+  Np = GetSelectionParam ();
+  SetSelectionParam (Np + 1);
+  M2 = ExtractMagnitudes (code[1], mode[1], average, secfilt, measure, &N2);
+  if (N2 == 0) goto skip;
+
+  /* magnitudes may be NAN : set delta to NAN */
+  for (i = 0; i < N1; i++) {
+    for (j = 0; j < N2; j++) {
+      if (isnan(M1[i]) || isnan(M2[j])) {
+	list[Nlist] = NAN;
+      } else {
+	list[Nlist] = M1[i] - M2[j];
+      }
+      Nlist ++;
+    }
+  }
+
+skip: 
+  if (M1 != NULL) free (M1);
+  if (M2 != NULL) free (M2);
+  *nlist = Nlist;
+  return (list);
+}
+  
+/* extract a list of delta-measure-mags from the specified average entry based on the 
+   pre-set selections - does not return self-matched measurements */
+double *ExtractMeasuresDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist) {
+
+  int i, j, Np0, Np1, Nlist, NLIST;
+  double *list, M1, M2;
+  
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm*average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+
+  /* must have two code values - drop this test? this is programming case, not a user case */
+  if (code == NULL) return (list);
+  if (code[0] == NULL) return (list);
+  if (code[1] == NULL) return (list);
+
+  /* exclude based on average parameters for both codes  */
+  if (!TestAverage (code[0], average, secfilt, measure)) return (list);
+  if (!TestAverage (code[1], average, secfilt, measure)) return (list);
+
+  Np0 = GetSelectionParam ();
+  Np1 = Np0 + 1;
+
+  /* loop twice over all measures */
+  for (i = 0; i < average[0].Nm; i++) {
+    SetSelectionParam (Np0);
+    TESTCODE (code[0], measure[i]);
+    TESTMEASURE (measure[i]);
+    SETMAG(M1, measure[i], mode[0]);
+    for (j = 0; j < average[0].Nm; j++) {
+      if (i == j) continue;
+      SetSelectionParam (Np1);
+      TESTCODE (code[1], measure[j]);
+      TESTMEASURE (measure[j]);
+      SETMAG(M2, measure[j], mode[1]);
+      if (isnan(M1) || isnan(M2)) {
+	list[Nlist] = NAN;
+      } else {
+	list[Nlist] = M1 - M2;
+      }
+      Nlist ++;
+    }
+  }
+  *nlist = Nlist;
+  return (list);
+}
+
+/* extract a measurement list matching the number of dmag entries */
+double *ExtractByDMag (PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+
+  int A1, A2, N1;
+  double *list;
+
+  /* check for special case of measure-measure */
+  A1 = ((mode[0] == MAG_AVE) || (mode[0] == MAG_REF));
+  A2 = ((mode[1] == MAG_AVE) || (mode[1] == MAG_REF));
+  if (!A1 && !A2) {
+    list = ExtractMeasuresByDMag (code, mode, 1, average, secfilt, measure, nlist, param);
+    return (list);
+  }
+
+  /* one of the two entries results in a single element. extract the other */
+  if (A1) {
+    list = ExtractMeasures (code[1], mode[1], average, secfilt, measure, &N1, param);
+  } else {
+    list = ExtractMeasures (code[0], mode[0], average, secfilt, measure, &N1, param);
+  }
+  *nlist = N1;
+  return (list);
+}
+  
+/* extract a list of delta-measure-mags from the specified average entry based on the pre-set selections */
+double *ExtractMeasuresByDMag (PhotCode **code, int *mode, int use_first, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param) {
+
+  int i, j, n, Nlist, NLIST;
+  double *list, M1, M2;
+  
+  *nlist = 0; 
+  Nlist = 0;
+  NLIST = MAX (1, average[0].Nm*average[0].Nm);
+  ALLOCATE (list, double, NLIST);
+
+  /* must have two code values */
+  if (code == NULL) return (list);
+  if (code[0] == NULL) return (list);
+  if (code[1] == NULL) return (list);
+
+  /* chisq, fwhm, Nphot, Ncode */
+  if (!TestAverage (code[0], average, secfilt, measure)) return (list);
+  if (!TestAverage (code[1], average, secfilt, measure)) return (list);
+
+  /* loop twice over all measures */
+  for (i = 0; i < average[0].Nm; i++) {
+    TESTCODE (code[0], measure[i]);
+    TESTMEASURE (measure[i]);
+    SETMAG(M1, measure[i], mode[0]);
+    for (j = 0; j < average[0].Nm; j++) {
+      if (i == j) continue;
+      TESTCODE (code[1], measure[j]);
+      TESTMEASURE (measure[j]);
+      SETMAG(M2, measure[j], mode[1]);
+      n = (use_first) ? i : j;
+
+      /* assign value */
+      list[Nlist] = GetMeasure (param, &average[0], &measure[n], (use_first ? M1 : M2));
+      Nlist ++;
+    }
+  }
+  *nlist = Nlist;
+  return (list);
+}
+
+double GetMeasure (int param, Average *average, Measure *measure, double mag) {
+
+  double ra, dec, x, y;
+  double value;
+  Image *image;
+  Coords *mosaic;
+
+  value = 0;
+  switch (param) {
+    case MEAS_MAG: /* magnitudes are already determined above */
+      value = mag;
+      break;
+    case MEAS_RA: /* OK */
+      value = average[0].R - measure[0].dR / 3600.0;
+      break;
+    case MEAS_DEC: /* OK */
+      value = average[0].D - measure[0].dD / 3600.0;
+      break;
+# if (0)
+    case MEAS_dMAG: /* OK */
+      value = measure[0].dM;
+      break;
+    case MEAS_DOPHOT: /* OK */
+      value = measure[0].dophot;
+      break;
+# endif
+    case MEAS_AIRMASS: /* OK */
+      value = measure[0].airmass;
+      break;
+    case MEAS_EXPTIME: /* OK */
+      value = pow (10.0, measure[0].dt * 0.4);
+      break;
+    case MEAS_PHOTCODE: /* OK */
+      value = measure[0].photcode;
+      break;
+    case MEAS_TIME: /* OK */
+      value = TimeValue (measure[0].t, TimeReference, TimeFormat);
+      break;
+    case MEAS_RA_OFFSET: /* OK */
+      value = measure[0].dR;
+      break;
+    case MEAS_DEC_OFFSET: /* OK */
+      value = measure[0].dD;
+      break;
+    case MEAS_FWHM: /* OK */
+      value = 0.01*measure[0].FWx;
+      break;
+    case MEAS_DB_FLAGS: /* ? */
+      value = measure[0].dbFlags;
+      break;
+    case MEAS_XCCD: /* OK */
+/* I need to perform this conversion for ELIXIR and LONEOS formats on load */      
+# if 0
+      value = measure[0].Xccd;
+# else
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      image = MatchImage (measure[0].t, measure[0].photcode);
+      if (image == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, &image[0].coords);
+      value = x;
+# endif
+      break;
+    case MEAS_YCCD: /* OK */
+/* I need to perform this conversion for ELIXIR and LONEOS formats on load */      
+# if 0
+      value = measure[0].Yccd;
+# else
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      image = MatchImage (measure[0].t, measure[0].photcode);
+      if (image == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, &image[0].coords);
+      value = y;
+# endif
+      break;
+    case MEAS_XMOSAIC: /* OK */
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      mosaic = MatchMosaic (measure[0].t, measure[0].photcode);
+      if (mosaic == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, mosaic);
+      value = x;
+      break;
+    case MEAS_YMOSAIC: /* OK */
+      ra  = average[0].R - measure[0].dR / 3600.0;
+      dec = average[0].D - measure[0].dD / 3600.0;
+      mosaic = MatchMosaic (measure[0].t, measure[0].photcode);
+      if (mosaic == NULL) break;
+      RD_to_XY (&x, &y, ra, dec, mosaic);
+      value = y;
+      break;
+  }
+  return (value);
+}
+
+/** the mosaic entries do not use the registered mosaic found 
+    by MatchImage (via FindMosaicForImage).  Rather, they use
+    a coordinate frame saved by SetImageSelection 
+**/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/pmeasure.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/pmeasure.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/pmeasure.c	(revision 16632)
@@ -0,0 +1,163 @@
+# include "dvoshell.h"
+# define NCHUNK 10000
+
+int pmeasure (int argc, char **argv) {
+  
+  FILE *f;
+  int i, j, k, m, kapa, Narg, Npts, NPTS, status, VERBOSE;
+  double Mz, Mr, mag;
+  double Radius, Rmin, Rmax, R, D;
+  unsigned IDclip, IDchoice, LimExclude;
+  unsigned FlagChoice, FlagClip, flags;
+  int PhotcodeClip;
+  float *Xvec, *Yvec, *Zvec;
+
+  SkyTable *sky;
+  SkyList *skylist;
+  Catalog catalog;
+  Graphdata graphmode;
+
+  if (!InitPhotcodes ()) return (FALSE);
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  f = (FILE *) NULL;
+  Mz = 17.0;
+  Mr = -5.0;
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  PhotcodeClip = -1;
+  if ((Narg = get_argument (argc, argv, "-p"))) {
+    remove_argument (Narg, &argc, argv);
+    PhotcodeClip = GetPhotcodeCodebyName (argv[Narg]);
+    remove_argument (Narg, &argc, argv);
+  }
+  IDchoice = 0;
+  IDclip = FALSE;
+  if ((Narg = get_argument (argc, argv, "-ID"))) {
+    remove_argument (Narg, &argc, argv);
+    IDchoice  = atoi(argv[Narg]);
+    remove_argument (Narg, &argc, argv);
+    IDclip = TRUE;
+  }
+  FlagChoice = 0;
+  FlagClip = FALSE;
+  if ((Narg = get_argument (argc, argv, "-flag"))) {
+    remove_argument (Narg, &argc, argv);
+    FlagChoice  = atoi(argv[Narg]);
+    remove_argument (Narg, &argc, argv);
+    FlagClip = TRUE;
+  }
+
+  // XXX Add time restrictions
+
+  LimExclude = FALSE;
+  if ((Narg = get_argument (argc, argv, "-x"))) {
+    remove_argument (Narg, &argc, argv);
+    LimExclude = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((Narg = get_argument (argc, argv, "-v"))) {
+    remove_argument (Narg, &argc, argv);
+    VERBOSE = TRUE;
+  }
+
+  if ((Narg = get_argument (argc, argv, "-m"))) {
+    remove_argument (Narg, &argc, argv);
+    Mr  = atof(argv[Narg]);
+    remove_argument (Narg, &argc, argv);
+    Mz = atof(argv[Narg]);
+    Mr = Mr - Mz;
+    remove_argument (Narg, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: pmeasure (-all) [-m M M] [-p photcode] [-ID ID] [-flag value] [-x]\n");
+    return (FALSE);
+  }
+  graphmode.style = 2; /* set style to points */
+  graphmode.size = -1; /* point size determined by Zvec */
+  graphmode.etype = 0; /* no errorbars */
+
+  Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+
+  /* load sky from correct table */
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, graphmode.coords.crval1, graphmode.coords.crval2, Radius);
+  
+  /* storage for plotting the points */
+  Npts = 0;
+  NPTS = 1000;
+  ALLOCATE (Xvec, float, NPTS);
+  ALLOCATE (Yvec, float, NPTS);
+  ALLOCATE (Zvec, float, NPTS);
+
+  for (j = 0; j < skylist[0].Nregions; j++) {
+    catalog.filename = skylist[0].filename[j];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS;
+    catalog.Nsecfilt = 0;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, VERBOSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    dvo_catalog_unlock (&catalog);
+
+    /* project stars to screen display coords */
+    for (i = 0; i < catalog.Naverage; i++) {
+      if (IDclip && (catalog.average[i].code != IDchoice)) continue;
+      while (catalog.average[i].R < Rmin) catalog.average[i].R += 360.0;
+      while (catalog.average[i].R > Rmax) catalog.average[i].R -= 360.0;
+      m = catalog.average[i].offset;
+      for (k = 0; k < catalog.average[i].Nm; k++) {
+	if (FlagClip) {
+	  flags = catalog.measure[m+k].dbFlags;
+	  if (!(flags & FlagChoice)) continue;
+	}
+	if ((PhotcodeClip != -1) && (catalog.measure[m+k].photcode != PhotcodeClip)) continue;
+	mag = PhotCat (&catalog.measure[m+k]);
+	Zvec[Npts] = MIN (1.0, MAX (0.01, (mag - Mz) / Mr));
+	if (LimExclude && (Zvec[Npts] > 0.99)) continue;
+	if (Zvec[Npts] < 0.011) continue;
+	R = catalog.average[i].R - catalog.measure[m+k].dR/3600.0;
+	D = catalog.average[i].D - catalog.measure[m+k].dD/3600.0;
+	// XXX drop this check
+	if ((R < Rmin) || (R > Rmax) || (D < -90.0) || (D > 90.0)) {
+	  char *date;
+	  date = ohana_sec_to_date (catalog.measure[m+k].t);
+	  gprint (GP_LOG, "out: %f, %f : %s : (%f, %f) + (%f, %f)\n", R, D, date, catalog.average[i].R, catalog.average[i].D, catalog.measure[m+k].dR/3600.0, catalog.measure[m+k].dD/3600.0);
+	  free (date);
+	}
+	status = fRD_to_XY (&Xvec[Npts], &Yvec[Npts], R, D, &graphmode.coords);
+	if (!status) {
+	  fprintf (stderr, ".");
+	  continue;
+	}
+	Npts ++;
+
+	if (Npts == NPTS - 1) {
+	    NPTS += 1000;
+	    REALLOCATE (Xvec, float, NPTS);
+	    REALLOCATE (Yvec, float, NPTS);
+	    REALLOCATE (Zvec, float, NPTS);
+	}
+	if (Npts > NCHUNK) {
+	    PlotVectorTriplet (kapa, Npts, Xvec, Yvec, Zvec, &graphmode);
+	    Npts = 0;
+	}
+      }
+    }
+    dvo_catalog_free (&catalog);
+  }
+  if (Npts > 0) PlotVectorTriplet (kapa, Npts, Xvec, Yvec, Zvec, &graphmode);
+
+  free (Xvec);
+  free (Yvec);
+  free (Zvec);
+
+  return (TRUE);
+
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/procks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/procks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/procks.c	(revision 16632)
@@ -0,0 +1,153 @@
+# include "dvoshell.h"
+
+typedef struct {
+  double ra[3];
+  double dec[3];
+  double X[3];
+  double Y[3];
+  unsigned int t[3];
+  double mag[3];
+} Rocks;
+static Rocks *rocks = (Rocks *) NULL;
+static int   Nrocks;
+
+int procks (int argc, char **argv) {
+  
+  FILE *f;
+  Vector Xvec, Yvec;
+  int kapa, i, j, N, NROCKS;
+  int N0, N1, SpeedClip, Reload;
+  unsigned int t0, t1;
+  double Mz, Mr, S0, S1;
+  double Rmin, Rmax;
+  Graphdata graphmode;
+  char rockcat[256];
+
+  VarConfig ("ROCK_CATALOG", "%s", rockcat);
+  if (!GetGraph (&graphmode, &kapa, NULL)) return (FALSE);
+
+  f = (FILE *) NULL;
+  Mz = 17.0;
+  Mr = -5.0;
+  Rmin = graphmode.coords.crval1 - 182.0;
+  Rmax = graphmode.coords.crval1 + 182.0;
+
+  if ((N = get_argument (argc, argv, "-m"))) {
+    remove_argument (N, &argc, argv);
+    Mr  = 1000*atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    Mz = 1000*atof(argv[N]);
+    Mr = Mr - Mz;
+    remove_argument (N, &argc, argv);
+  }
+
+  S0 = S1 = 0;
+  SpeedClip = FALSE;
+  if ((N = get_argument (argc, argv, "-speed"))) {
+    SpeedClip = TRUE;
+    remove_argument (N, &argc, argv);
+    S0 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    S1 = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  Reload = FALSE;
+  if ((N = get_argument (argc, argv, "-reload"))) {
+    Reload = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: procks [-m M M] [-speed s s] \n");
+    return (FALSE);
+  }
+  
+  f = fopen (rockcat, "r");
+  if (f == (FILE *) NULL) {
+    gprint (GP_ERR, "can't open rock catalog\n");
+    return (TRUE);
+  }
+
+  if ((rocks == (Rocks *) NULL) || Reload) {
+    if (rocks != (Rocks *) NULL) free (rocks);
+    NROCKS = 100;
+    ALLOCATE (rocks, Rocks, NROCKS);
+    for (i = 0; fscanf (f, "%lf %lf %d%lf%lf%lf %d%lf%lf%lf %d%lf%lf%lf", 
+			&rocks[i].X[0], &rocks[i].Y[0], 
+			&rocks[i].t[0], &rocks[i].ra[0], &rocks[i].dec[0], &rocks[i].mag[0], 
+			&rocks[i].t[1], &rocks[i].ra[1], &rocks[i].dec[1], &rocks[i].mag[1], 
+			&rocks[i].t[2], &rocks[i].ra[2], &rocks[i].dec[2], &rocks[i].mag[2]
+			) != EOF; i++) {
+      if (i == NROCKS - 1) {
+	NROCKS += 100;
+	REALLOCATE (rocks, Rocks, NROCKS);
+      }
+    }
+    Nrocks = i;
+  }
+      
+  if (Nrocks == 0) {
+    free (rocks);
+    gprint (GP_ERR, "no rocks in datafile\n");
+    return (TRUE);
+  }
+
+  /* data has been loaded, get ready to plot it */
+  Yvec.Nelements = Xvec.Nelements = 3*Nrocks;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  
+  /* project stars to screen display coords */
+  for (N = i = 0; i < Nrocks; i++) {
+    if (SpeedClip && ((rocks[i].Y[0] < S0) || (rocks[i].Y[0] > S1))) continue;
+    for (j = 0; j < 3; j++) {
+      while (rocks[i].ra[j] < Rmin) rocks[i].ra[j] += 360.0;
+      while (rocks[i].ra[j] > Rmax) rocks[i].ra[j] -= 360.0;
+      fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], rocks[i].ra[j], rocks[i].dec[j], &graphmode.coords);
+      N ++;
+    }
+  }
+  Yvec.Nelements = Xvec.Nelements = N;
+  
+  graphmode.style = 2; /* set style to points */
+  graphmode.etype = 0; /* no errorbars */
+  PlotVectorPair (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+
+  /* now plot vectors between two extrema */
+  Yvec.Nelements = Xvec.Nelements = 2*Nrocks;
+  REALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  REALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  
+  /* project stars to screen display coords */
+  for (N = i = 0; i < Nrocks; i++) {
+    if (SpeedClip && ((rocks[i].Y[0] < S0) || (rocks[i].Y[0] > S1))) continue;
+    N0 = N1 = 0;
+    t0 = t1 = rocks[i].t[0];
+    for (j = 1; j < 3; j++) {
+      if (rocks[i].t[j] < t0) { N0 = j; t0 = rocks[i].t[j]; }
+      if (rocks[i].t[j] > t1) { N1 = j; t1 = rocks[i].t[j]; }
+    }
+    while (rocks[i].ra[N0] < Rmin) rocks[i].ra[N0] += 360.0;
+    while (rocks[i].ra[N0] > Rmax) rocks[i].ra[N0] -= 360.0;
+    while (rocks[i].ra[N1] < Rmin) rocks[i].ra[N1] += 360.0;
+    while (rocks[i].ra[N1] > Rmax) rocks[i].ra[N1] -= 360.0;
+    fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], rocks[i].ra[N0], rocks[i].dec[N0], &graphmode.coords);
+    N ++;
+    fRD_to_XY (&Xvec.elements[N], &Yvec.elements[N], rocks[i].ra[N1], rocks[i].dec[N1], &graphmode.coords);
+    N ++;
+  }
+  Yvec.Nelements = Xvec.Nelements = N;
+  
+  graphmode.style = 2; /* set style to points */
+  graphmode.ptype = 100; /* connect pairs */
+  graphmode.etype = 0; /* no errorbars */
+
+  PlotVectorPair (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/region_list.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/region_list.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/region_list.c	(revision 16632)
@@ -0,0 +1,215 @@
+# include "dvoshell.h"
+
+/* XXX note : for RegionName or RegionList, we need to free the skylist
+   elements, but not in the case of radius selection - this implies 
+   information carried back up */
+
+static char *CATDIR  = NULL;
+static SkyTable *sky = NULL;
+
+int SetCATDIR (char *path, int verbose) {
+
+  char *newpath;
+  char catdir_config[256];
+  char gscfile[256];
+  char skyfile[256];
+  int  skydepth;
+
+  /* find CATDIR in config system */
+  if (path == NULL) {
+    if (VarConfig ("CATDIR", "%s", catdir_config) == NULL) return (FALSE);
+    newpath = catdir_config;
+  } else {
+    newpath = path;
+  }
+
+  if (CATDIR != NULL) free (CATDIR);
+  CATDIR = strcreate (newpath);
+
+  if (VarConfig ("GSCFILE",  "%s", gscfile) == NULL) gscfile[0] = 0;
+  if (VarConfig ("SKYFILE",  "%s", skyfile) == NULL) skyfile[0] = 0;
+  if (VarConfig ("SKYDEPTH", "%d", &skydepth) == NULL) skydepth = 2;
+
+  if (verbose) {
+      gprint (GP_ERR, "CATDIR %s\n", CATDIR);
+      gprint (GP_ERR, "GSCFILE %s\n", gscfile);
+      gprint (GP_ERR, "SKYFILE %s\n", skyfile);
+      gprint (GP_ERR, "SKYDEPTH %d\n", skydepth);
+  }
+
+  /* load the SkyTable at this point */
+  /* set the image path as well */
+
+  if (sky != NULL) SkyTableFree (sky);
+  sky = SkyTableLoadOptimal (CATDIR, skyfile, gscfile, skydepth, verbose);
+  if (sky == NULL) return FALSE;
+
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+
+  return (TRUE);
+}
+
+char *GetCATDIR () {
+  if (CATDIR == NULL) {
+    SetCATDIR (NULL, FALSE);
+  }
+  return (CATDIR);
+}
+
+SkyTable *GetSkyTable () {
+  if (sky == NULL) {
+    SetCATDIR (NULL, FALSE);
+  }
+  return (sky);
+}
+
+void FreeSkyRegionSelection (SkyRegionSelection *selection) {
+
+  if (selection == NULL) return;
+  if (selection[0].name != NULL) free (selection[0].name);
+  if (selection[0].list != NULL) free (selection[0].list);
+  free (selection);
+}
+
+SkyRegionSelection *SetRegionSelection (int *argc, char **argv) {
+  
+  int N;
+  SkyRegionSelection *selection;
+
+  ALLOCATE (selection, SkyRegionSelection, 1);
+  selection[0].name = NULL;
+  selection[0].list = NULL;
+  selection[0].useDisplay = FALSE;
+  selection[0].useSkyregion = FALSE;
+
+  /* check for Region selection (named dvo catalog file) */
+  if ((N = get_argument (*argc, argv, "-cpt"))) {
+    remove_argument (N, argc, argv);
+    selection[0].name = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    return selection;
+  }    
+
+  /* check for Region list (file containing dvo catalog file list)*/
+  if ((N = get_argument (*argc, argv, "-cptlist"))) {
+    remove_argument (N, argc, argv);
+    selection[0].list = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+    return selection;
+  } 
+
+  /* check for Region selection from display */
+  if ((N = get_argument (*argc, argv, "-region"))) {
+    remove_argument (N, argc, argv);
+    selection[0].useDisplay = TRUE;
+    return selection;
+  }    
+
+  /* check for Region selection from display */
+  if ((N = get_argument (*argc, argv, "-skyregion"))) {
+    if (N + 5 >= *argc) {
+      gprint (GP_ERR, "USAGE: -skyregion (RA) (RA) (DEC) (DEC)\n");
+      FreeSkyRegionSelection (selection);
+      return NULL;
+    }
+    remove_argument (N, argc, argv);
+    selection[0].useSkyregion = TRUE;
+    set_skyregion (atof(argv[N]), atof(argv[N+1]), atof(argv[N+2]), atof(argv[N+3]));
+    remove_argument (N, argc, argv);
+    remove_argument (N, argc, argv);
+    remove_argument (N, argc, argv);
+    remove_argument (N, argc, argv);
+    return selection;
+  }    
+
+  /* default to pre-defined sky region */
+  selection[0].useSkyregion = TRUE;
+  return selection;
+}
+
+/* given possible options (by name, by list, by graph region), select SkyRegions */
+SkyList *SelectRegions (SkyRegionSelection *selection) {
+
+  SkyList *skylist;
+
+  /* determine region-file names */
+  if (selection->name != NULL) {
+    char filename[256];
+
+    ALLOCATE (skylist, SkyList, 1);
+    ALLOCATE (skylist[0].regions, SkyRegion *, 1);
+    ALLOCATE (skylist[0].regions[0], SkyRegion, 1);
+    ALLOCATE (skylist[0].filename, char *, 1);
+    skylist[0].ownElements = TRUE; // free these elements when freeing the list
+    
+    strcpy (skylist[0].regions[0][0].name, selection->name);
+    sprintf (filename, "%s/%s.cpt", CATDIR, selection->name);
+    skylist[0].filename[0] = strcreate (filename);
+    return (skylist);
+  } 
+
+  if (selection->list != NULL) {
+    skylist = SkyListLoadFile (selection->list);
+    return (skylist);
+  }
+
+  if (selection->useDisplay) {
+    double Radius;
+    Graphdata graphsky;
+
+    if (!GetGraphData (&graphsky, NULL, NULL)) {
+      gprint (GP_ERR, "region display not available\n");
+      return (NULL);
+    }
+
+    Radius = MAX (fabs(graphsky.xmax), fabs(graphsky.ymax));
+    skylist = SkyListByRadius (sky, -1, graphsky.coords.crval1, graphsky.coords.crval2, Radius);
+    return (skylist);
+  }
+
+  if (selection->useSkyregion) {
+    double Rmin, Rmax, Dmin, Dmax;
+
+    get_skyregion (&Rmin, &Rmax, &Dmin, &Dmax);
+    skylist = SkyListByBounds (sky, -1, Rmin, Rmax, Dmin, Dmax);
+    return (skylist);
+  }    
+
+  return NULL;
+}
+
+/* returns a list of region files names from file */
+SkyList *SkyListLoadFile (char *filename) {
+  
+  FILE *f;
+  int NREGIONS, Nregions;
+  SkyList *skylist;
+
+  ALLOCATE (skylist, SkyList, 1);
+
+  f = fopen (filename, "r");
+  if (f == NULL) {
+    gprint (GP_ERR, "ERROR: can't find region list file %s\n", filename);
+    skylist[0].Nregions = 0;
+    skylist[0].regions = NULL;
+    return (skylist);
+  }
+  
+  Nregions = 0;
+  NREGIONS = 50;
+  ALLOCATE (skylist[0].regions, SkyRegion *, NREGIONS);
+  ALLOCATE (skylist[0].filename, char *, NREGIONS);
+  skylist[0].ownElements = TRUE; // free these elements when freeing the list
+
+  while (fscanf (f, "%s", filename) != EOF) {
+    ALLOCATE (skylist[0].regions[Nregions], SkyRegion, 1);
+    strcpy (skylist[0].regions[Nregions][0].name, filename);
+    sprintf (filename, "%s/%s.cpt", CATDIR, skylist[0].regions[Nregions][0].name);
+    skylist[0].filename[Nregions] = strcreate (filename);
+    Nregions ++;
+    CHECK_REALLOCATE (skylist[0].regions, SkyRegion *, NREGIONS, Nregions, 50);
+  }
+  skylist[0].Nregions = Nregions;
+  return (skylist);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/scripts/navigate
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/scripts/navigate	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/scripts/navigate	(revision 16632)
@@ -0,0 +1,623 @@
+# -*- perl -*-
+
+macro navigate
+  style -n 0
+  limits
+  $DRAWSTARS  = -1
+  $DRAWIMAGES =  1
+  $DRAWGRID   = -1
+  $ZOOM = 180 / ($YMAX - $YMIN)
+  #this should be changed to a while loop, except 'while' is broken for some reason
+  $KEY = "none"
+  while ("$KEY" != "q")
+    cursor 1
+
+    # help list
+    if ("$KEY" == "h")
+     echo "Arrow Keys - pan in that direction"
+     echo "PgUp,PgDn - zoom in/out a factor of 1.2"
+     echo "Home,End  - zoom in/out a factor of 2"
+     echo "1 - zoom in factor of 2 at the cursor"
+     echo "2 - zoom in factor of 1.2 at the cursor"
+     echo "3 - recenter at cursor"
+     echo "4 - zoom out factor of 1.2 at the cursor"
+     echo "5 - zoom out factor of 2 at the cursor"
+     echo "6 - zoom out factor of 10 at the cursor"
+     echo "z - zoom to radius (requires 2nd keystroke)"
+     echo "f - show full sky"
+     echo ""
+     echo "q - quit"
+     echo "S - toggle auto-plotting of stars"
+     echo "A - toggle auto-plotting of image borders"
+     echo "g - toggle skygrid on/off"
+     echo "c - plot status catalog boundaries"
+     echo "C - list catalog at cursor location"
+     echo "i - list info about images touching cursor location" 
+     echo "I - list info about images, with pixel coords of cursor position"
+     echo "j - adjust mag scale, +0.5"
+     echo "k - adjust mag scale, -0.5"
+     echo "J - adjust dmag scale, /1.25"
+     echo "K - adjust dmag scale, *1.25"
+     echo "r - plot detected asteroids (rocks)"
+     echo "l - plot HST GSC"
+     echo "L - plot Landolt stars"
+     echo "m - list measurements for stars within 1 pixel of cursor"
+     echo "M - list measurements for stars within 1.8 arcsec of cursor"
+     echo "p - ****(don't know what this does)"
+     echo "s - ****(don't know what this does)"
+     echo "t - plot light curve for star within 2 arcsec of cursor position"
+     echo "T - plot 'galaxy' light curve for star within 2 arcsec of cursor position"
+     echo "u - ****(don't know what this does)"
+     echo "x - plot stars scaled by magnitude Chisq"
+     echo "X - plot stars by magnitude scatter"
+     echo "y - ****(don't know what this does)"
+     echo ""
+     echo "@ - execute macro `user_macro`"
+     echo ": - ****input a line and execute (not yet implemented)"
+    end
+
+    # quit from navigate
+    if ("$KEY" == "q") continue
+
+    #pan controls
+    if (("$KEY" == "Left") || ("$KEY" == "Right") || ("$KEY" == "Up") || ("$KEY" == "Down"))
+      $SHIFT = 0.2
+      $R$KEY  = $RMAX-$XMAX  
+      $D$KEY  = $DMAX-$YMAX
+      #assumes standard sky orientation!! (N up, E left)
+      if ("$KEY"=="Left")
+        $R$KEY = $R$KEY + $SHIFT*$XMAX
+      end
+      if ("$KEY"=="Right")
+        $R$KEY = $R$KEY + $SHIFT*$XMIN
+      end
+      if ("$KEY"=="Up")
+        $D$KEY = $D$KEY + $SHIFT*$YMAX
+      end
+      if ("$KEY"=="Down")
+        $D$KEY = $D$KEY + $SHIFT*$YMIN
+      end
+      #pretend like I hit '3' in the place to recenter it
+      nav_zoom 1      
+    end
+
+    # NEW zoom controls
+    if (("$KEY" == "Prior") || ("$KEY" == "Next") || ("$KEY" == "Home") || ("$KEY" == "End") || ("$KEY" == "Button4") || ("$KEY" == "Button5"))    
+      #move where key was hit to center      
+      $R$KEY  = $RMAX-$XMAX  
+      $D$KEY  = $DMAX-$YMAX
+      if ("$KEY" == "Prior")
+        $zfac=1.2
+      end
+      if ("$KEY" == "Next")
+        $zfac={1/1.2}
+      end
+      if ("$KEY" == "Home")
+        $zfac=2
+      end
+      if ("$KEY" == "End")
+        $zfac={1/2.}
+      end
+      if ("$KEY"=="Button4")
+        $zfac=1.6
+      end
+      if ("$KEY"=="Button5")
+        $zfac={1/1.6}
+      end
+      nav_zoom $zfac
+    end
+
+    if ("$KEY"=="Button1")
+      nav_zoom 1
+    end
+    if ("$KEY"=="Button2")
+      nav_zoom {1/2.}
+    end
+    if ("$KEY"=="Button3")
+      nav_zoom 2
+    end
+
+
+
+    # zoom controls
+    if ("$KEY" == "1")
+      nav_zoom 2
+    end
+    if ("$KEY" == "2")
+      nav_zoom 1.2
+    end
+    if ("$KEY" == "3")
+      nav_zoom 1
+    end
+    if ("$KEY" == "4")
+      nav_zoom {1/1.2}
+    end
+    if ("$KEY" == "5")
+      nav_zoom {1/2.}
+    end
+    if ("$KEY" == "6")
+      nav_zoom {1/20.}
+    end
+
+ 
+   # measure distance
+    if ("$KEY" == "d")
+      $r0 = $R$KEY
+      $d0 = $D$KEY
+      $ok = $KEY
+      echo "type 'd' again at endpoint"
+      cursor 1
+      $r1 = $R$KEY
+      $d1 = $D$KEY
+      $dr = 3600*((dcos($d0)*($r0-$r1))^2 + ($d0-$d1)^2)^0.5
+      echo "$dr arcsec"
+    end
+    # show ra, dec
+    if ("$KEY" == "w")
+      $tmp = $R$KEY
+      if ($tmp < 0) 
+        $tmp = $R$KEY + 360.0
+      end
+      echo "$tmp $D$KEY" 
+      exec echo $tmp $D$KEY | radec -hh
+    end
+    # zoom to radius
+    if ("$KEY" == "z")
+      $r0 = $R$KEY
+      $d0 = $D$KEY
+      $ok = $KEY
+      echo "type 'z' again at radius"
+      cursor 1
+      $r1 = $R$KEY
+      $d1 = $D$KEY
+      $dr = (($r0-$r1)^2 + ($d0-$d1)^2)^0.5
+      $ZOOM = $RAD / $dr
+      nav_recenter
+      nav_redraw
+      $KEY = $ok
+      $R$KEY = $r0
+      $D$KEY = $d0
+    end
+
+    # adjust mag scaling
+    if ("$KEY" == "J")
+      $MAG = $MAG - 0.5
+      nav_redraw
+    end
+    if ("$KEY" == "K")
+      $MAG = $MAG + 0.5
+      nav_redraw
+    end
+    if ("$KEY" == "j")
+      $dMAG = $dMAG * 0.8
+      nav_redraw
+    end
+    if ("$KEY" == "k")
+      $dMAG = $dMAG * 1.25
+      nav_redraw
+    end
+    echo "mag, dmag: $MAG, $dMAG"
+
+
+
+    # plot full sky
+    if ("$KEY" == "f") 
+      echo "full"
+      $ZOOM = 1
+      resize 1150 600		      
+      region 0 0 90 ait
+      $RMIN = 0
+      $RMAX = 360
+      $DMIN = -90
+      $DMAX = +90
+      style -c red; cgrid
+      style -c black
+      images
+    end
+
+    # plot rocks
+    if ("$KEY" == "r") 
+#      plot.rocks
+      style -c blue   -pt 1; procks -speed 0.0041 1
+      style -c red    -pt 1; procks -speed 0.00041 0.0041
+      style -c indigo -pt 1; procks -speed 0 0.00041
+      style -c black -lw 0;
+    end
+    # plot HST-GSC
+    if ("$KEY" == "l") 
+      style -c blue -pt 7; cat -all -g -m 9 16
+      style -c black
+    end
+    # plot Landolt
+    if ("$KEY" == "L") 
+#      style -c red  -lw 2 -pt 3; cat -a 1 2 3 /data/elixir/srcdir/refs/stetson/stetsonBn.txt -m 9 18
+#      style -c blue -lw 2 -pt 3; cat -a 25 26 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.fix -m 9 18
+      style -c red -lw 2 -pt 7; cat -a 1 2 3 /data/elixir/srcdir/refs/sdss/g_SDSS.dat -m 9 14
+#      style -c red -lw 2 -pt 3; cat -a 25 26 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.hq -m 9 18
+#      style -c red -lw 2 -pt 3; cat -a 22 23 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.unfix -m 9 18
+#      style -c blue -lw 2 -pt 7; cat -a 1 2 4 /data/elixir/srcdir/refs/landolt/extreme/extreme.match -m 0 20
+#      style -x 2 -c red -pt 7 ; cplot RA DEC
+      style -c black -lw 0
+    end
+
+    # list star measurements
+    if ("$KEY" == "m") 
+        $dR = $RAD/$ZOOM/300
+        if ($dR < 0.0005)
+	 $dR = 0.0005
+        end
+	gstar $R$KEY $D$KEY $dR -m
+    end
+
+    # plot mag residuals
+    if ("$KEY" == "R") 
+      echo "filter: "
+      cursor 1
+      clear -n 1 -s; lim 10 22 -0.2 0.2; clear; box
+      dmags $KEY\:rel - $KEY : $KEY -type 0
+      plot -x 2 -pt 0 -sz 0.3 -c red yv xv
+      dmags $KEY\:rel - $KEY : $KEY -type 0 -flag 0 -nphot +3 -chisq 2.0
+      plot -x 2 -pt 2 -sz 0.5 -c black yv xv
+      $KEY = R
+      style -n 0
+    end
+
+    if ("$KEY" == "M") 
+	gstar $R$KEY $D$KEY 0.0005 -m
+    end
+    # list images
+    if ("$KEY" == "i") 
+	gimages $R$KEY $D$KEY
+    end
+    if ("$KEY" == "I") 
+	gimages $R$KEY $D$KEY -pix
+    end
+
+    #toggle images on / off
+    if ("$KEY" == "A")
+      $DRAWIMAGES = $DRAWIMAGES * -1
+      if ($DRAWIMAGES == 1)
+        images
+      end
+    end
+    # toggle stars on / off
+    if ("$KEY" == "S")
+      $DRAWSTARS = $DRAWSTARS * -1
+      if (($ZOOM > 20) && ($DRAWSTARS == 1))
+       style -pt 7
+       pmeasure -all -m $MAG {$MAG + $dMAG}
+      end
+    end
+    # turn grid on / off
+    if ("$KEY" == "g")
+      $DRAWGRID = $DRAWGRID * -1
+      if (($ZOOM > 20) && ($DRAWGRID==1))
+        style -c black; cgrid
+      end
+      if (($ZOOM > 20) && ($DRAWGRID==-1))
+        nav_redraw
+      end
+    end
+
+    # plot light-curve interactive
+    if ("$KEY" == "t")
+      style -n 1 -pt 2 -x 2
+      clear
+      if ($R$KEY < 0) 
+       $R$KEY = $R$KEY + 360
+      end
+      lcurve -l $R$KEY $D$KEY {30/3600} -d -v time mag
+      box
+      lcv
+      style -n 0
+    end
+    # plot light-curve 
+    if ("$KEY" == "T")
+      style -n 1 -pt 1 -c red -x 2
+      lcurve $R$KEY $D$KEY {30/3600} -d
+      style -c black
+      style -n 0 
+    end
+    # plot catalogs
+    if ("$KEY" == "c")
+      style -c blue; pcat; style -c black
+    end
+    # list catalogs
+    if ("$KEY" == "C")
+      gcat $R$KEY $D$KEY
+    end
+
+    # plot image chisqs
+    if ("$KEY" == "x") 
+       gcat $R$KEY $D$KEY
+       extract $CATNAME Xm -photcode R
+       extract $CATNAME ra
+       extract $CATNAME dec
+       style -x 2 -pt 7 -c blue
+       czplot ra dec Xm 3 30
+       style -c black -pt 1
+    end
+    # plot meas errors
+    if ("$KEY" == "X") 
+       gcat $R$KEY $D$KEY
+       extract $CATNAME dM -photcode R
+       extract $CATNAME ra
+       extract $CATNAME dec
+       style -x 2 -pt 7 -c red
+       czplot ra dec dM 0 30
+       style -c black -pt 1
+    end
+
+
+    # temp plot for skyprobe
+    if ("$KEY" == "u") 
+      imextract -region time
+      imextract -region mcal
+      imextract -region airmass
+      imextract -region nstar
+      vstat time
+      clear -n 1;
+      section a 0 0.00 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3} -0.8 -0.5; box; plot time mcal
+      section b 0 0.33 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3}  0.95 3.0; box; plot time airmass
+      section c 0 0.66 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3} 0 3000; box; plot time nstar
+      style -n 0
+    end
+    if ("$KEY" == "s")
+      $tmp = $R$KEY
+      if ($tmp < 0) 
+        $tmp = $R$KEY + 360.0
+      end
+      $line = `echo $tmp $D$KEY | radec -hh`
+      imextract -region photcode
+      imextract -region time
+     
+      subset t = time if (int(photcode/100) == 1)
+      uniq t T
+      $Bn = t[]
+      $BN = T[]
+      
+      subset t = time if (int(photcode/100) == 2)
+      uniq t T
+      $Vn = t[]
+      $VN = T[]
+      
+      subset t = time if (int(photcode/100) == 3)
+      uniq t T
+      $Rn = t[]
+      $RN = T[]
+      
+      subset t = time if (int(photcode/100) == 4)
+      uniq t T
+      $In = t[]
+      $IN = T[]
+     
+      echo "$line  $Bn $BN  $Vn $VN  $Rn $RN  $In $IN"
+    end
+
+    if ("$KEY" == "p") 
+      echo "P - new coords; p - old coords"
+      cursor 1
+      exec echo $Rp $Dp $RP $DP >> fix.coords
+    end
+
+    if ("$KEY" == "y")
+      ccd I - 2MASS_J : 2MASS_J - 2MASS_K
+      lim -n 1 -1 10 -1 3; clear; box; plot -x 2 -pt 2 -sz 0.5 xv yv
+      dev -n 0 -g
+    end
+
+    #  User-defined macro
+    if ("$KEY" == "at")
+      user_macro
+    end
+
+    if ("$KEY" == "colon")
+      #make this work similar to ':' in vi or iraf
+      #does not work correctly now.
+      scan stdin line
+      $line
+    end
+
+  end
+end
+
+#define this so navigate doesn't crash if you try to call it.
+#If you define a user_macro, be sure to do so AFTER this in .dvorc.
+macro user_macro
+  #echo "success!"
+  $do_nothing=0
+end
+    
+
+macro nav_zoom
+  $ZOOM = $ZOOM * $1
+  nav_recenter
+  nav_redraw
+  $Rnum = $R$KEY		      
+  $Dnum = $D$KEY
+  $KEY = num
+end
+
+macro nav_recenter
+  region $R$KEY $D$KEY {$RAD/$ZOOM} sin
+  #assumes standard sky orientation!! (N up, E left)
+  $RMIN = $R$KEY + $XMIN
+  $RMAX = $R$KEY + $XMAX
+  $DMIN = $D$KEY + $YMIN
+  $DMAX = $D$KEY + $YMAX
+end
+
+macro nav_redraw
+  clear
+  if ($ZOOM <= 20) 
+    style -c red; cgrid
+  end
+  if (($ZOOM > 20) && ($DRAWGRID==1))
+    style -c black; cgrid
+  end
+  if (($ZOOM > 20) && ($DRAWSTARS == 1))
+    pmeasure -all -m $MAG {$MAG + $dMAG}
+  end    
+  style -c black
+  if ($DRAWIMAGES == 1)
+    images
+  end
+end
+
+
+
+#==================================================
+#=================   END BSNAV   ==================
+#==================================================
+
+
+macro sigclip
+  if ("$0" == "1")
+    echo ""
+    echo "sigclip <clipvector> <N_iterations> <N_sigma> [other vectors ..]"
+    echo ""
+  end
+
+  #required parameters
+  $CLIPVECT = $1
+  $NITERATE = $2
+  $NSIGCLIP = $3
+  
+  for i 0 $NITERATE
+    vstat -q $CLIPVECT
+    #clip boundaries
+    $top = $MEAN + ($NSIGCLIP*$SIGMA)
+    $bot = $MEAN - ($NSIGCLIP*$SIGMA)
+    
+    #clip it good.
+    subset temp = $CLIPVECT if (($CLIPVECT < $top) && ($CLIPVECT > $bot))
+    
+    #if you specify other vectors, clip the same elements from them too.
+    #they must all be the same length, of course!!
+    if ($0>4)
+      for j 4 $0
+        subset $$j = $$j if (($CLIPVECT < $top) && ($CLIPVECT > $bot))
+      end
+    end
+    
+    #copy temp back to $CLIPVECT and reiterate!
+    delete $CLIPVECT
+    concat temp $CLIPVECT  
+  end
+end
+
+
+macro binvec
+  if ("$0" == "1")
+    echo ""
+    echo "binvec <vec> <Nbins> [other vectors...]"
+    echo ""
+    echo "Bin the vector 'vec' into Nbin bins.  Listing other vectors will"
+    echo "put the corresponding elements of those into other vectors which"
+    echo "are the subset of the vector in that bin.  (That can probably be"
+    echo "stated better.)  This macro makes lots of new vectors.  Hooray!"
+    echo ""
+    echo "Creates"
+  end
+
+  #REQUIRED PARAMS
+  $binvect = $1
+  $NBINS   = $2
+
+  vstat -q $binvect
+  $step = ($MAX-$MIN)/$NBINS
+  $vmin = $MIN
+  $vmax = $MAX
+  delete -q $binvect\_bins
+  delete -q $binvect\_num
+  for i 1 {$NBINS+1}
+    $top = $vmin + ( $i   *$step)
+    $bot = $vmin + (($i-1)*$step)
+    #      sightly different behavior for last bin    -------v
+    if ($i != $NBINS)
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect< $top))
+    else
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect<=$top))
+    end
+    set $binvect\_bin$i = temp
+    set temp2 = temp
+    delete temp
+    #if you specify other vectors, grab the same elements from them too.
+    #they must all be the same length, of course!!
+
+    if ($0>3)
+      for j 3 $0
+        if ($i != $NBINS)
+          subset temp = $$j if (($binvect>=$bot)&&($binvect< $top))
+        else 
+          subset temp = $$j if (($binvect>=$bot)&&($binvect<=$top))
+        end
+        set $$j\_bin$i = temp
+        delete temp
+      end
+    end
+
+
+    concat {$bot+($step/2)} $binvect\_bins
+    concat temp2[] $binvect\_num
+    #dvo didn't like me saying 'concat $binvect\_bin$i[] $binvect\_num
+    delete temp2
+  end
+end
+
+macro binvec.2
+  if ("$0" == "1")
+    echo ""
+    echo "binvec.2 <vec> <min> <max> <binsize> [other vectors...]"
+    echo ""
+    echo ""
+    echo "see also 'binvec'"
+  end
+
+  #REQUIRED PARAMS
+  $binvect = $1
+  $vmin    = $2
+  $vmax    = $3
+  $step    = $4
+
+  $NBINS = ($MAX-$MIN)/$step
+
+  delete -q $binvect\_bins
+  delete -q $binvect\_num
+  for i 1 {$NBINS+1}
+    $top = $vmin + ( $i   *$step)
+    $bot = $vmin + (($i-1)*$step)
+    #      sightly different behavior for last bin    -------v
+    if ($i != $NBINS)
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect< $top))
+    else
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect<=$top))
+    end
+    set $binvect\_bin$i = temp
+    set temp2 = temp
+    delete temp
+    #if you specify other vectors, grab the same elements from them too.
+    #they must all be the same length, of course!!
+
+    if ($0>5)
+      for j 5 $0
+        if ($i != $NBINS)
+          subset temp = $$j if (($binvect>=$bot)&&($binvect< $top))
+        else 
+          subset temp = $$j if (($binvect>=$bot)&&($binvect<=$top))
+        end
+        set $$j\_bin$i = temp
+        delete temp
+      end
+    end
+
+
+    concat {$bot+($step/2)} $binvect\_bins
+    concat temp2[] $binvect\_num
+    #dvo didn't like me saying 'concat $binvect\_bin$i[] $binvect\_num
+    delete temp2
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/showtile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/showtile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/showtile.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include "dvoshell.h"
+static float dr[] = {0.0, 1.0, 1.0, 0.0};
+static float dd[] = {0.0, 0.0, 1.0, 1.0};
+
+int showtile (int argc, char **argv) {
+
+  int kapa, Nd, N, NPTS, status, i, InPic;
+  Graphdata graphmode;
+  Coords coords;
+  Vector Xvec, Yvec;
+  float r, d, R, D;
+  float Ro[90], Do[90];
+
+  /* show tile pattern in viewed region */
+  if (!GetGraph (&graphmode, &kapa, NULL)) return (FALSE);
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: showtile [option]\n");
+    return (FALSE);
+  }
+  
+  N = 0;
+  NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+
+  /* starting position */
+
+  /* reference for coords is this image */
+  coords.crpix1 = coords.crpix2 = 0.0;
+  coords.crval1 = coords.crval2 = 0.0;
+  coords.cdelt1 = coords.cdelt2 = 1.0;
+  coords.pc1_1  = coords.pc2_2  = 1.0;
+  coords.pc1_2  = coords.pc2_1  = 0.0;
+  coords.Npolyterms = 0;
+  strcpy (coords.ctype, "RA---TAN");
+  
+  /* fill in top-left region */
+  for (r = 0; r < 3; r += 1.0) {
+    gprint (GP_ERR, "r: %f\n", r);
+    for (Nd = d = 0; d < 90; Nd ++, d += 1.0) {
+      if (r == 0) {
+	coords.crval1 = r;
+	coords.crval2 = d;
+      } else {
+	coords.crval1 = Ro[Nd];
+	coords.crval2 = Do[Nd];
+      }
+      for (i = 0; i < 4; i++) {
+	fXY_to_RD (&R, &D, dr[i], dd[i], &coords);
+	status |= fRD_to_XY (&Xvec.elements[N+2*i], &Yvec.elements[N+2*i], R, D, &graphmode.coords);
+	if (i > 0) {
+	  Xvec.elements[N+2*i - 1] = Xvec.elements[N+2*i];
+	  Yvec.elements[N+2*i - 1] = Yvec.elements[N+2*i];
+	}
+	if (i == 1) {
+	  Ro[Nd] = R;
+	  Do[Nd] = D;
+	}
+      }
+      Xvec.elements[N+7] = Xvec.elements[N];
+      Yvec.elements[N+7] = Yvec.elements[N];
+
+      /* check if any corner is in plotting region */
+      InPic = FALSE;
+      for (i = 0; i < 8; i+=2) {
+	if ((Xvec.elements[N+i] >= graphmode.xmin) && 
+	    (Xvec.elements[N+i] <= graphmode.xmax) && 
+	    (Yvec.elements[N+i] >= graphmode.ymin) && 
+	    (Yvec.elements[N+i] <= graphmode.ymax))
+	  InPic = TRUE;
+      }
+      if (!InPic) continue;
+      N+=8;
+      if (N > NPTS - 1) {  /* this is OK because NPTS is made always a multiple of 8 */
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+  
+  Xvec.Nelements = Xvec.Nelements = N;
+  if (N > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.etype = 0;
+    PlotVectorPair (kapa, N, Xvec.elements, Yvec.elements, &graphmode);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/simage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/simage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/simage.c	(revision 16632)
@@ -0,0 +1,168 @@
+# include "dvoshell.h"
+# define D_NSTARS 1000
+# define BYTES_STAR 31
+# define BLOCK 1000
+
+int simage (int argc, char **argv) {
+
+  char *buffer;
+  Vector Xvec, Yvec, Zvec;
+  double R, D, X, Y, M, zero, range;
+  FILE *f;
+  Header header;
+  Coords coords;
+  int i, j, kapa, Nstars, nstars, Nbytes, nbytes, Npts, N;
+  Graphdata graphmode;
+
+  if (!GetGraph (&graphmode, &kapa, NULL)) return (FALSE);
+
+  zero = 17.0;
+  range = -5.0;
+  if ((N = get_argument (argc, argv, "-m"))) {
+    remove_argument (N, &argc, argv);
+    range = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    zero  = atof(argv[N]);
+    range = range - zero;
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: image (filename)\n");
+    return (FALSE);
+  }
+
+  gprint (GP_ERR, "not working at the moment (cmp format)\n");
+  return (FALSE);
+  
+  /* read header */
+  if (!gfits_read_header (argv[1], &header)) {
+    gprint (GP_ERR, "ERROR: can't find image file %s\n", argv[1]);
+    return (FALSE);
+  }
+  /* get astrometry information */
+  strcpy (coords.ctype, "NONE");
+  gfits_scan (&header, "CTYPE1",   "%s",  1, coords.ctype);
+  if (strcmp (coords.ctype, "RA---PLY")) {
+    gprint (GP_ERR, "ERROR: wrong astrometric info in header\n");
+    return (FALSE);
+  }
+  gfits_scan (&header, "CDELT1",   "%f", 1, &coords.cdelt1); 
+  gfits_scan (&header, "CDELT2",   "%f", 1, &coords.cdelt2);
+  gfits_scan (&header, "CRVAL1",   "%lf", 1, &coords.crval1);
+  gfits_scan (&header, "CRVAL2",   "%lf", 1, &coords.crval2);  
+  gfits_scan (&header, "CRPIX1",   "%f", 1, &coords.crpix1);
+  gfits_scan (&header, "CRPIX2",   "%f", 1, &coords.crpix2);
+  gfits_scan (&header, "PC001001", "%f", 1, &coords.pc1_1);
+  gfits_scan (&header, "PC001002", "%f", 1, &coords.pc1_2);
+  gfits_scan (&header, "PC002001", "%f", 1, &coords.pc2_1);
+  gfits_scan (&header, "PC002002", "%f", 1, &coords.pc2_2);
+  /* RA Terms */
+  gfits_scan (&header, "PCA1X2Y0", "%f", 1, &coords.polyterms[0][0]);
+  gfits_scan (&header, "PCA1X1Y1", "%f", 1, &coords.polyterms[1][0]);
+  gfits_scan (&header, "PCA1X0Y2", "%f", 1, &coords.polyterms[2][0]);
+  gfits_scan (&header, "PCA1X3Y0", "%f", 1, &coords.polyterms[3][0]);
+  gfits_scan (&header, "PCA1X2Y1", "%f", 1, &coords.polyterms[4][0]);
+  gfits_scan (&header, "PCA1X1Y2", "%f", 1, &coords.polyterms[5][0]);
+  gfits_scan (&header, "PCA1X0Y3", "%f", 1, &coords.polyterms[6][0]);
+  /* Dec Terms */			    
+  gfits_scan (&header, "PCA2X2Y0", "%f", 1, &coords.polyterms[0][1]);
+  gfits_scan (&header, "PCA2X1Y1", "%f", 1, &coords.polyterms[1][1]);
+  gfits_scan (&header, "PCA2X0Y2", "%f", 1, &coords.polyterms[2][1]);
+  gfits_scan (&header, "PCA2X3Y0", "%f", 1, &coords.polyterms[3][1]);
+  gfits_scan (&header, "PCA2X2Y1", "%f", 1, &coords.polyterms[4][1]);
+  gfits_scan (&header, "PCA2X1Y2", "%f", 1, &coords.polyterms[5][1]);
+  gfits_scan (&header, "PCA2X0Y3", "%f", 1, &coords.polyterms[6][1]);
+  coords.Npolyterms = 2; /* how many do we use? */
+
+  /* find number of stars */
+  gfits_scan (&header, "NSTARS", "%d", 1, &Nstars);
+  if (Nstars == 0) {
+    gprint (GP_ERR, "no stars in file\n");
+    return (FALSE);
+  }
+
+  /* open file data */
+  f = fopen (argv[1], "r");
+  if (f == NULL) {
+    gprint (GP_ERR, "can't find data in file %s\n", argv[1]);
+    return (FALSE);
+  }
+  fseek (f, header.size, SEEK_SET); 
+
+  /* set up storage buffers */
+  Xvec.Nelements = Nstars;
+  Yvec.Nelements = Nstars;
+  Zvec.Nelements = Nstars;
+  ALLOCATE (Xvec.elements, float, Xvec.Nelements);
+  ALLOCATE (Yvec.elements, float, Yvec.Nelements);
+  ALLOCATE (Zvec.elements, float, Zvec.Nelements);
+  ALLOCATE (buffer, char, (BLOCK*BYTES_STAR));
+
+  /* load in stars by blocks of 1000 */
+  nstars = 0;
+  Nbytes = Nstars*BYTES_STAR;
+  for (i = 0; i < (int)(Nbytes / (BLOCK*BYTES_STAR)); i++) {
+    nbytes = fread (buffer, 1, (BLOCK*BYTES_STAR), f);
+    if (nbytes != BLOCK*BYTES_STAR) {
+      gprint (GP_ERR, "failed to read in stars (1)\n");
+      free (Xvec.elements);
+      free (Yvec.elements);
+      free (Zvec.elements);
+      free (buffer);
+      return (FALSE);
+    }
+    for (j = 0; j < BLOCK; j++, nstars++) {
+      dparse (&X,  1, &buffer[j*BYTES_STAR]);
+      dparse (&Y,  2, &buffer[j*BYTES_STAR]);
+      dparse (&M,  3, &buffer[j*BYTES_STAR]);
+      XY_to_RD (&R, &D, X, Y, &coords);
+      fRD_to_XY (&Xvec.elements[nstars], &Yvec.elements[nstars], R, D, &graphmode.coords);
+      Zvec.elements[nstars] = MIN (1.0, MAX (0.01, (M - zero) / range));
+    }
+  }
+  /* left over fraction of a block */
+  nbytes = fread (buffer, 1, (Nbytes % (BLOCK*BYTES_STAR)), f);
+  if (nbytes != (Nbytes % (BLOCK*BYTES_STAR))) {
+    gprint (GP_ERR, "ERROR: failed to read in stars (2)\n");
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+    free (buffer);
+    return (FALSE);
+  }
+  for (j = 0; j < nbytes / BYTES_STAR; j++, nstars++) {
+    dparse (&X,  1, &buffer[j*BYTES_STAR]);
+    dparse (&Y,  2, &buffer[j*BYTES_STAR]);
+    dparse (&M,  3, &buffer[j*BYTES_STAR]);
+    XY_to_RD (&R, &D, X, Y, &coords);
+    fRD_to_XY (&Xvec.elements[nstars], &Yvec.elements[nstars], R, D, &graphmode.coords);
+    Zvec.elements[nstars] = MIN (1.0, MAX (0.01, (M - zero) / range));
+  }
+  
+  if (nstars != Nstars) {
+    gprint (GP_ERR, "ERROR: failed to read in all stars (%d of %d)\n", nstars, Nstars);
+    free (Xvec.elements);
+    free (Yvec.elements);
+    free (Zvec.elements);
+    free (buffer);
+    return (FALSE);
+  }
+
+  graphmode.style = 2;
+  graphmode.size = -1;
+  graphmode.etype = 0;
+  Npts = Xvec.Nelements;
+
+  PlotVectorTriplet (kapa, Npts, Xvec.elements, Yvec.elements, Zvec.elements, &graphmode);
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (Zvec.elements);
+  free (buffer);
+
+  return (TRUE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skycat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skycat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skycat.c	(revision 16632)
@@ -0,0 +1,125 @@
+# include "dvoshell.h"
+
+int RD_to_XYpic (double *x, double *y, double r, double d, Coords *coords, double Rmin, double Rmax, double Rmid, int *leftside);
+
+int skycat (int argc, char **argv) {
+  
+  double Radius;
+  int i, j, N, Nregions, kapa, ShowAll, NPTS, Npts, leftside, Depth, VERBOSE;
+  struct stat filestat;
+  Vector Xvec, Yvec;
+  Graphdata graphmode;
+  double X[4], Y[4], Rmin, Rmax, Rmid;
+  SkyTable *sky;
+  SkyList *skylist;
+  SkyRegion **regions;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    remove_argument (N, &argc, argv);
+    VERBOSE = TRUE;
+  }
+  ShowAll = FALSE;
+  if ((N = get_argument (argc, argv, "-all"))) {
+    remove_argument (N, &argc, argv);
+    ShowAll = TRUE;
+  }
+  Depth = -1;
+  if ((N = get_argument (argc, argv, "-depth"))) {
+    remove_argument (N, &argc, argv);
+    Depth = atoi (argv[N]);
+    remove_argument (N, &argc, argv);    
+  }
+
+  if (!style_args (&graphmode, &argc, argv, &kapa)) return FALSE;
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: skycat [-all]\n");
+    return (FALSE);
+  }
+
+  Radius = MAX (fabs(graphmode.xmax), fabs(graphmode.ymax));
+
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, Depth, graphmode.coords.crval1, graphmode.coords.crval2, Radius);
+  
+  if (VERBOSE) gprint (GP_ERR, "region: %6.2f - %6.2f, %6.2f - %6.2f\n", 
+			graphmode.coords.crval1 - Radius, graphmode.coords.crval1 + Radius, 
+			graphmode.coords.crval2 - Radius, graphmode.coords.crval2 + Radius);
+
+  Rmin = graphmode.coords.crval1 - 180.0;
+  Rmax = graphmode.coords.crval1 + 180.0;
+  Rmid = 0.5*(Rmin + Rmax);
+
+  NPTS = 200;
+  ALLOCATE (Xvec.elements, float, NPTS);
+  ALLOCATE (Yvec.elements, float, NPTS);
+  Npts = 0;
+   
+  regions = skylist[0].regions;
+  Nregions = skylist[0].Nregions;
+
+  for (i = 0; i < Nregions; i++) {
+    if (ShowAll || (stat (skylist[0].filename[i], &filestat) != -1)) {
+      if (VERBOSE) gprint (GP_ERR, "%3d %s %6.2f - %6.2f, %6.2f - %6.2f\n", i, regions[i][0].name, 
+			    regions[i][0].Rmin, regions[i][0].Rmax, regions[i][0].Dmin, regions[i][0].Dmax);
+
+      leftside = -1;
+      RD_to_XYpic (&X[0], &Y[0], regions[i][0].Rmin, regions[i][0].Dmin, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+      RD_to_XYpic (&X[1], &Y[1], regions[i][0].Rmin, regions[i][0].Dmax, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+      RD_to_XYpic (&X[2], &Y[2], regions[i][0].Rmax, regions[i][0].Dmax, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+      RD_to_XYpic (&X[3], &Y[3], regions[i][0].Rmax, regions[i][0].Dmin, &graphmode.coords, Rmin, Rmax, Rmid, &leftside);
+
+      Xvec.elements[Npts] = X[0];
+      Yvec.elements[Npts] = Y[0];
+      for (j = 1; j < 4; j++) {
+	Xvec.elements[Npts + j*2 - 0] = X[j];
+	Yvec.elements[Npts + j*2 - 0] = Y[j];
+	Xvec.elements[Npts + j*2 - 1] = X[j];
+	Yvec.elements[Npts + j*2 - 1] = Y[j];
+      }
+      Xvec.elements[Npts+7] = Xvec.elements[Npts];
+      Yvec.elements[Npts+7] = Yvec.elements[Npts];
+      Npts += 8;
+      if (Npts > NPTS - 1) {  /* this is OK because NPTS is made always a multiple of 8 */
+	NPTS += 200;
+	REALLOCATE (Xvec.elements, float, NPTS);
+	REALLOCATE (Yvec.elements, float, NPTS);
+      }
+    }
+  }
+
+  gprint (GP_ERR, "plotting %d catalogs\n", Npts/8);
+  Xvec.Nelements = Xvec.Nelements = Npts;
+  if (Npts > 0) {
+    graphmode.style = 2; /* points */
+    graphmode.ptype = 100; /* connect pairs of points */
+    graphmode.etype = 0;
+    PlotVectorPair (kapa, Npts, Xvec.elements, Yvec.elements, &graphmode);
+  }
+
+  free (Xvec.elements);
+  free (Yvec.elements);
+  free (regions);
+
+  return (TRUE);
+
+}
+
+
+int RD_to_XYpic (double *x, double *y, double r, double d, Coords *coords, double Rmin, double Rmax, double Rmid, int *leftside) {
+
+  while (r < Rmin) { r += 360.0; }
+  while (r > Rmax) { r -= 360.0; }
+
+  if (*leftside == -1) {
+    *leftside = (r < Rmid);
+  } else {
+    if (  *leftside && (r > Rmid + 90)) { r -= 360.0; }
+    if (! *leftside && (r < Rmid - 90)) { r += 360.0; }
+  }
+
+  RD_to_XY (x, y, r, d, coords);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skycoverage.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skycoverage.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skycoverage.c	(revision 16632)
@@ -0,0 +1,146 @@
+# include "dvoshell.h"
+
+int skycoverage (int argc, char **argv) {
+
+  int i, N, Nimage, status, TimeSelect, ByName, xs, ys;
+  time_t tzero, tend;
+  double pixscale, dPix, r, d, Xi, Yi, Xs, Ys, x[2], y[2], trange;
+  Image *image;
+  char name[256];
+  float *V;
+  int Nx, Ny;
+  Buffer *buf;
+  Coords coords;
+
+  ByName = FALSE;
+  if ((N = get_argument (argc, argv, "-name"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (name, argv[N]);
+    remove_argument (N, &argc, argv);
+    ByName = TRUE;
+  }
+
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+  if ((N = get_argument (argc, argv, "-trange"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tzero)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &tend)) { 
+      gprint (GP_ERR, "syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    trange = tend - tzero;
+    if (trange < 0) {
+      trange = fabs (trange);
+      tzero -= trange;
+    }
+    TimeSelect = TRUE;
+  }
+ 
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: skycoverage (buffer) (pixscale) (dPix) [-time start range] [-name name]\n");
+    gprint (GP_ERR, "       (buffer) saves bitmapped AIT plot\n");
+    gprint (GP_ERR, "       (pixscale) specifies the pixel size in degrees\n");
+    gprint (GP_ERR, "       note: we need 64800 / (pixscale)^2 pixels to represent the sky\n");
+    return (FALSE);
+  }
+  
+  if ((buf = SelectBuffer (argv[1], ANYBUFFER, TRUE)) == NULL) return (FALSE);
+  pixscale = atof(argv[2]);
+  dPix     = atof(argv[3]);
+
+  Nx = 360/pixscale;
+  Ny = 180/pixscale;
+
+  gfits_free_matrix (&buf[0].matrix);
+  gfits_free_header (&buf[0].header);
+  CreateBuffer (buf, Nx, Ny, -32, 0.0, 1.0);
+  strcpy (buf[0].file, "(empty)");
+
+  coords.crval1 = 180;
+  coords.crval2 = 0;
+  coords.crpix1 = 0.5*Nx;
+  coords.crpix2 = 0.5*Ny;
+  strcpy (coords.ctype, "DEC--AIT");
+  coords.pc1_1 = coords.pc2_2 = 1;
+  coords.pc1_2 = coords.pc2_1 = 0;
+  coords.cdelt1 = coords.cdelt2 = pixscale;
+  coords.Npolyterms = 0;
+
+  PutCoords (&coords, &buf[0].header);
+
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  BuildChipMatch (image, Nimage);
+
+  V = (float *)buf[0].matrix.buffer;
+  bzero (V, Nx*Ny*sizeof(float));
+
+  for (ys = 0; ys < Ny; ys++) {
+    for (xs = 0; xs < Nx; xs++) {
+      status = XY_to_RD (&r, &d, (double)(xs), (double)(ys), &coords);
+      status &= (r > 0);
+      status &= (r < 360);
+      if (status) {
+	V[ys*Nx + xs] = 2;
+      }
+    }
+  }
+
+  for (i = 0; i < Nimage; i++) {
+    if (ByName && strcmp (name, image[i].name)) continue;
+    if (TimeSelect && ((image[i].tzero < tzero) || (image[i].tzero+image[i].trate*image[i].NY > tzero + trange))) continue;
+    if (!FindMosaicForImage (image, Nimage, i)) continue;
+
+    /* project this image to screen display coords */
+    /* DIS images represent a field, not a chip */
+    if (!strcmp(&image[i].coords.ctype[4], "-DIS")) {
+      x[0] = -0.5*image[i].NX; y[0] = -0.5*image[i].NY;
+      x[1] = +0.5*image[i].NX; y[1] = +0.5*image[i].NY;
+    } else {
+      x[0] = 0;                y[0] = 0;
+      x[1] = image[i].NX;      y[1] = image[i].NY;
+    }
+    status = FALSE;
+    
+    for (Yi = y[0] + 0.5*dPix; Yi < y[1]; Yi += dPix) {
+      for (Xi = x[0] + 0.5*dPix; Xi < x[1]; Xi += dPix) {
+	XY_to_RD (&r, &d, Xi, Yi, &image[i].coords);
+	while (r <   0.0) { r += 360.0; }
+	while (r > 360.0) { r -= 360.0; }
+	status = RD_to_XY (&Xs, &Ys, r, d, &coords);
+	if (status) {
+	  xs = (int)Xs;
+	  ys = (int)Ys;
+	  V[ys*Nx + xs] = 1;
+	}
+      }
+    }
+  }
+
+  free (image);
+  return (TRUE);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skydbtile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skydbtile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skydbtile.c	(revision 16632)
@@ -0,0 +1,283 @@
+# include "dvo2.h"
+SkyRegion *SkyDivideList (SkyRegion *list, int Nlist);
+
+/* region names:
+
+ depth Ntables  Name 
+ 0     1      	fullsky.cpt
+ 1     16     	n????.cpt, s????.cpt
+ 2     256    	n????/r????.cpt
+ 3     4096   	n????/t????.cpt
+ 4     65536  	n????/r????/r????.cpt
+ 5     1.0+06  	n????/t????/t????.cpt
+ 6     1.7+07  	n????/r????/r????/r????.cpt
+
+ depth Ntables  Name 
+ 0     1      	fullsky
+ 1     16     	d%02
+ 2     256    	d%02/r%03d
+ 3     4096   	d%02/t%04d
+ 4     65536  	d%02/r%03d/r%03d
+ 5     1.0+06  	d%02/t%04d/t%04d
+ 6     1.7+07  	d%02/r%03d/r%03d/r%03d
+ 7     2.7+08  	d%02/t%04d/t%04d/t%04d
+
+*/
+
+/* a valid SkyRegion set must always start with the fullsky as the first entry, 
+   with the sequence of entries ordered primarily by depth, followed by parent 
+*/
+
+int SkyMakeNames (SkyRegion *db, SkyRegion *ref, int depth) {
+
+  int i, j, N, Ns, Ne, ns, ne;
+
+  if (db == NULL) return (FALSE);
+  if (depth == 0) {
+    if (db[0].depth != 0) return (FALSE);
+    strcpy (db[0].name, "fullsky");
+    Ns = db[0].childS;
+    Ne = db[0].childE;
+    for (i = Ns; i < Ne; i++) {
+      sprintf (db[i].name, "d%02d", i - 1);
+      if (!SkyMakeNames (db, &db[i], 2)) return (FALSE);
+      if (!SkyMakeNames (db, &db[i], 3)) return (FALSE);
+    }
+    return (TRUE);
+  }
+
+  if (ref == NULL) return (FALSE);
+  
+  if (depth == 2) {
+    if (!ref[0].child) return (TRUE);
+    Ns = ref[0].childS;
+    Ne = ref[0].childE;
+    N = 0;
+    for (i = Ns; i < Ne; i++, N++) {
+      sprintf (db[i].name, "%s/r%02d", ref[0].name, N);
+      if (!SkyMakeNames (db, &db[i], depth + 2)) return (FALSE);
+    }
+  }
+  
+  if (depth > 2) {
+    Ns = ref[0].childS;
+    Ne = ref[0].childE;
+    N = 0;
+    for (i = Ns; i < Ne; i++) {
+      if (!ref[0].child) continue;
+      ns = db[i].childS;
+      ne = db[i].childE;
+      for (j = ns; j < ne; j++, N++) {
+	if (depth % 2) {
+	  sprintf (db[j].name, "%s/t%03d", ref[0].name, N);
+	} else {				      			    
+	  sprintf (db[j].name, "%s/r%02d", ref[0].name, N);
+	}
+	if (!SkyMakeNames (db, &db[j], depth + 2)) return (FALSE);
+      }
+    }  
+  }
+}
+
+SkyRegion *SkyMakeRegions (int Nlevels, int *nlist) {
+
+  int Nlist, Nnext, Ncurr, i, j;
+  SkyRegion *list, *curr, *next;
+
+  Nlist = 0;
+  Nnext = 1;
+  Ncurr = 1;
+  ALLOCATE (list, SkyRegion, Ncurr);
+  ALLOCATE (curr, SkyRegion, Ncurr);
+
+  curr[0].Rmin =   0;
+  curr[0].Rmax = 360;
+  curr[0].Dmin = -90;
+  curr[0].Dmax =  90;
+  curr[0].depth = 0;
+  curr[0].object = FALSE;
+  curr[0].image = FALSE;
+  curr[0].child = FALSE;
+  curr[0].childS = 0;
+  curr[0].childE = 0;
+
+  for (i = 1; i < Nlevels; i++) {
+    next  = SkyDivideRegions (curr, &Nnext);
+    for (j = 0; j < Nnext; j++) {
+      next[j].depth = i;
+    }   
+    REALLOCATE (list, SkyRegion, Nlist + Ncurr);
+    memcpy (&list[Nlist], curr, Ncurr*sizeof(SkyRegion));
+    for (j = Nlist; j < Nlist + Ncurr; j++) {
+      list[j].childS += Nlist + Ncurr;
+      list[j].childE += Nlist + Ncurr;
+    }
+    Nlist += Ncurr;
+    free (curr);
+    curr = next;
+    Ncurr = Nnext;
+  }
+  REALLOCATE (list, SkyRegion, Nlist + Ncurr);
+  memcpy (&list[Nlist], curr, Ncurr*sizeof(SkyRegion));
+  Nlist += Ncurr;
+  free (curr);
+
+  list[0].object = TRUE;
+  list[0].image = TRUE;
+  *nlist = Nlist;
+  return (list);
+}
+
+SkyRegion *SkyDivideRegions (SkyRegion *parents, int *N) {
+
+  int i, Nchildren, Nparents, Np;
+  SkyRegion *children, *temp;
+  float *child, *index;
+
+  Nchildren = Nparents = *N;
+
+  /* copy input list to a new list, set child to be sequence number */
+  ALLOCATE (children, SkyRegion, Nchildren);
+  memcpy (children, parents, Nchildren*sizeof(SkyRegion));
+  for (i = 0; i < Nchildren; i++) {
+    children[i].childS = i;
+    parents[i].childS = i;
+  }
+
+  /* double the number of children, dividing only the largest in half each pass */
+  for (i = 0; i < 4; i++) {
+    temp = SkyDivideList (children, Nchildren);
+    free (children);
+    children = temp;
+    Nchildren *= 2;
+  }
+
+  /* sort children by childS (currently is parent entry) */
+  ALLOCATE (child, float, Nchildren);
+  ALLOCATE (index, float, Nchildren);
+  for (i = 0; i < Nchildren; i++) {
+    index[i] = i;
+    child[i] = children[i].childS;
+  }
+  fsortpair (child, index, Nchildren);
+  ALLOCATE (temp, SkyRegion, Nchildren);
+  for (i = 0; i < Nchildren; i++) {
+    temp[i] = children[(int)index[i]];
+  }
+  free (children);
+  free (child);
+  free (index);
+  children = temp;
+  
+  /* look for all matching values of childS, setup parent values of childS, childE */
+  Np = children[0].childS;
+  parents[Np].childS = 0;
+  parents[Np].child = TRUE;
+  for (i = 0; i < Nchildren; i++) {
+    if (children[i].childS != Np) {
+      parents[Np].childE = i;
+      Np = children[i].childS;
+      parents[Np].childS = i;
+      parents[Np].child = TRUE;
+    }
+    children[i].childS = 0;
+    children[i].childE = 0;
+    children[i].child = FALSE;
+  }
+  parents[Np].childE = i;
+  *N = Nchildren;
+  return (children);
+}
+
+/* always break the region with the largest area */
+SkyRegion *SkyDivideBiggest (SkyRegion *list, int *nlist) {
+
+  int i, N, Nlist;
+  float *area, *indx, dec;
+  SkyRegion *out, save;
+
+  Nlist = *nlist;
+  ALLOCATE (area, float, Nlist);
+  ALLOCATE (indx, float, Nlist);
+  for (i = 0; i < Nlist; i++) {
+    dec = 0.5*(list[i].Dmax + list[i].Dmin);
+    area[i] = (list[i].Rmax - list[i].Rmin)*(list[i].Dmax - list[i].Dmin)*cos(RAD_DEG*dec);
+    indx[i] = i;
+  }
+  fsortpair (area, indx, Nlist);
+
+  N = indx[Nlist - 1];
+  out = SkyDivide (&list[N]);
+  
+  REALLOCATE (list, SkyRegion, Nlist + 1);
+  list[N] = out[0];
+  list[Nlist] = out[1];
+
+  *nlist = Nlist + 1;
+  free (out);
+  free (area);
+  free (indx);
+  return (list);
+}
+
+SkyRegion *SkyDivide (SkyRegion *in) {
+
+  SkyRegion *out;
+  double RA, DEC, R_div, D_div;
+
+  ALLOCATE (out, SkyRegion, 2);
+
+  out[0] = in[0];
+  out[1] = in[0];
+
+  RA  = 0.5*(in[0].Rmin + in[0].Rmax);
+  DEC = 0.5*(in[0].Dmin + in[0].Dmax);
+  if ((DEC >= 90) || (DEC <= -90)) {
+    gprint (GP_ERR, "error in Dmin");
+    return (NULL);
+  }
+ 
+  D_div = (in[0].Rmax - in[0].Rmin) * cos (RAD_DEG*DEC);
+  R_div = (in[0].Dmax - in[0].Dmin);
+  if (R_div < D_div) {
+    /* divide RA range */
+    out[0].Rmax = RA;
+    out[1].Rmin = RA;
+  } else {
+    out[0].Dmax = DEC;
+    out[1].Dmin = DEC;
+  }
+
+  return (out);
+}
+
+/* return a list with 2x as many entries, each split in two */
+SkyRegion *SkyDivideList (SkyRegion *in, int Nin) {
+
+  SkyRegion *out;
+  double RA, DEC, R_div, D_div;
+  int i;
+
+  ALLOCATE (out, SkyRegion, 2*Nin);
+
+  for (i = 0; i < Nin; i++) {
+    /* inherit properties from parent */
+    out[2*i + 0] = in[i];
+    out[2*i + 1] = in[i];
+
+    RA  = 0.5*(in[i].Rmin + in[i].Rmax);
+    DEC = 0.5*(in[i].Dmin + in[i].Dmax);
+    
+    /* split along longest axis */
+    D_div = (in[i].Rmax - in[i].Rmin) * cos (RAD_DEG*DEC);
+    R_div = (in[i].Dmax - in[i].Dmin);
+    if (R_div < D_div) {
+      out[2*i + 0].Rmax = RA;
+      out[2*i + 1].Rmin = RA;
+    } else {
+      out[2*i + 0].Dmax = DEC;
+      out[2*i + 1].Dmin = DEC;
+    }
+  }
+  return (out);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skyregion.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skyregion.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/skyregion.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "dvoshell.h"
+
+static double RAs = 0.0;
+static double RAe = 0.0;
+static double DECs = 0.0;
+static double DECe = 0.0;
+
+// define the sky region for which extractions are limited
+int skyregion (int argc, char **argv) {
+  
+  if (argc == 1) {
+    gprint (GP_ERR, "current skyregion: %f - %f : %f - %f\n", RAs, RAe, DECs, DECe);
+    gprint (GP_ERR, "USAGE:  skyregion (min RA) (max RA) (min DEC) (max DEC)\n");
+    return (FALSE);
+  }
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: skyregion (min RA) (max RA) (min DEC) (max DEC)\n");
+    return (FALSE);
+  }
+
+  set_skyregion (atof(argv[1]), atof(argv[2]), atof(argv[3]), atof(argv[4]));
+
+  return (TRUE);
+}
+
+int get_skyregion (double *Rs, double *Re, double *Ds, double *De) {
+
+  *Rs = RAs;
+  *Re = RAe;
+  *Ds = DECs;
+  *De = DECe;
+
+  return TRUE;
+}
+
+int set_skyregion (double Rs, double Re, double Ds, double De) {
+
+  RAs  = Rs;
+  RAe  = Re;
+  DECs = Ds;
+  DECe = De;
+
+  return TRUE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/subpix.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/subpix.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/subpix.c	(revision 16632)
@@ -0,0 +1,154 @@
+# include "dvoshell.h"
+
+int subpix (int argc, char **argv) {
+  
+  int i, j, I, Nlo, Nhi, Nentry, Nstars, Nimage, Nmeasure;
+  int *index, *entry;
+  int Nmin, Nsub, NSUB, status;
+  int TimeFormat;
+  time_t Timage, TimeReference;
+  double X, Y, Mabs, t;
+  double Ra, Dec, Radius, Radius2, r, Rmin;
+  double *RA, *DEC;
+  
+  SkyTable *sky;
+  SkyList *skylist;
+  Measure *measure;
+  Image *image;
+  Catalog catalog;
+
+  if (!InitPhotcodes ()) return (FALSE);
+
+  GetTimeFormat (&TimeReference, &TimeFormat);
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: subpix ra dec radius\n");
+    return (FALSE);
+  }
+  if (!ohana_str_to_radec (&Ra, &Dec, argv[1], argv[2])) return (FALSE);
+  if (Ra < 0) Ra += 360.0;
+  if (Ra > 360.0) Ra -= 360.0;
+  Radius = atof (argv[3]);
+
+  /* load star nearest position */
+  sky = GetSkyTable ();
+  skylist = SkyListByRadius (sky, -1, Ra, Dec, Radius);
+  if (skylist[0].Nregions > 1) {
+    gprint (GP_ERR, "warning, radius overlaps region boundary, not yet implemented\n");
+  }
+
+  /* lock, load, unlock catalog */
+  catalog.filename = skylist[0].filename[0];
+  catalog.catflags = LOAD_AVES | LOAD_MEAS;
+  catalog.Nsecfilt = 0;
+
+  // an error exit status here is a significant error
+  if (!dvo_catalog_open (&catalog, NULL, FALSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open catalog file %s\n", catalog.filename);
+      exit (2);
+  }
+  dvo_catalog_unlock (&catalog);
+
+  /* quick search of star list for Ra, Dec */
+  Nstars = catalog.Naverage;
+  ALLOCATE (RA, double, Nstars);
+  ALLOCATE (DEC, double, Nstars);
+  ALLOCATE (index, int, Nstars);
+  for (i = 0; i < Nstars; i++) {
+    RA[i] = catalog.average[i].R;
+    DEC[i] = catalog.average[i].D;
+    index[i] = i;
+  }
+  if (Nstars > 1) sort_coords_index (DEC, RA, index, Nstars);
+
+  /* bracket the DEC range of interest */
+  Nlo = bracket (DEC, Nstars, FALSE, Dec - Radius);
+  Nhi = bracket (DEC, Nstars, TRUE,  Dec + Radius);
+  ALLOCATE (entry, int, MAX (Nhi - Nlo, 1));
+  Nentry = 0;
+
+  /* find the list of stars */
+  Radius2 = Radius*Radius;
+  for (i = Nlo; i < Nhi; i++) {
+    r = SQ(Dec - DEC[i]) + SQ(Ra - RA[i]);
+    if (r < Radius2) {
+      entry[Nentry] = i;
+      Nentry ++;
+    }
+  }
+  if (!Nentry) {
+    gprint (GP_ERR, "no stars found\n");
+    free (RA);
+    free (DEC);
+    free (entry);
+    free (index);
+    dvo_catalog_free (&catalog);
+    SkyListFree (skylist);
+    return (TRUE);
+  }
+
+  /* find the closest star */
+  Nmin = 0;
+  Rmin = SQ(Dec - DEC[entry[0]]) + SQ(Ra - RA[entry[0]]);
+  for (i = 1; i < Nentry; i++) {
+    r = SQ(Dec - DEC[entry[i]]) + SQ(Ra - RA[entry[i]]);
+    if (r < Rmin) {
+      Rmin = r;
+      Nmin = i;
+    }
+  }
+  Nentry = index[entry[Nmin]];
+  Ra = RA[entry[Nmin]];
+  Dec = DEC[entry[Nmin]];
+  gprint (GP_ERR, "finding subpix values for star @ %f %f\n", Ra, Dec);
+
+  free (RA);
+  free (DEC);
+  free (entry);
+  free (index);
+
+  /* storage for the image references */
+  Nsub = 0;
+  NSUB = 100;
+  ALLOCATE (index, int, NSUB);
+
+  /* load all images, extract those touching Ra, Dec */
+  if ((image = LoadImages (&Nimage)) == NULL) return (FALSE);
+  BuildChipMatch (image, Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+    if (!FindMosaicForImage (image, Nimage, i)) continue;
+    status = RD_to_XY (&X, &Y, Ra, Dec, &image[i].coords);
+    if (!status || (X < 0) || (X > image[i].NX) || (Y < 0) || (Y > image[i].NY)) continue;
+    index[Nsub] = i;
+    Nsub ++;
+    if (Nsub == NSUB - 1) {
+      NSUB += 100;
+      REALLOCATE (index, int, NSUB);
+    }
+  }
+
+  /* only print the entries for existing measurements of this star */ 
+  measure = &catalog.measure[catalog.average[Nentry].offset];
+  Nmeasure = catalog.average[Nentry].Nm;
+  for (i = 0; i < Nsub; i++) {
+    I = index[i];
+    if (!FindMosaicForImage (image, Nimage, I)) continue;
+    Timage = image[I].tzero;
+    for (j = 0; j < Nmeasure; j++) {
+      if (measure[j].t == Timage) { 
+	Mabs = PhotCat (&measure[j]);
+	RD_to_XY (&X, &Y, Ra, Dec, &image[I].coords);
+	t = TimeValue (measure[j].t, TimeReference, TimeFormat);
+	gprint (GP_LOG, "%f %6.3f %7.2f %7.2f %5.3f\n", t, Mabs, X, Y, image[I].secz);
+      } 
+    }
+  }
+
+  dvo_catalog_free (&catalog);
+  free (image);
+  free (index);
+  SkyListFree (skylist);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/dvo/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/dvo/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/dvo/version.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "dvoshell.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+int version (int argc, char **argv) {
+
+  char *tmp;
+
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "dvo version: %s\n", (tmp = strip_version (name))); free (tmp);
+
+  gprint (GP_LOG, "opihi version: %s\n", (tmp = strip_version (opihi_version()))); free (tmp);
+  gprint (GP_LOG, "libohana version: %s\n", (tmp = strip_version (ohana_version()))); free (tmp);
+  gprint (GP_LOG, "libdvo version: %s\n", (tmp = strip_version (libdvo_version()))); free (tmp);
+  gprint (GP_LOG, "libfits version: %s\n", (tmp = strip_version (gfits_version()))); free (tmp);
+
+  gprint (GP_LOG, "compiled on %s %s\n", __DATE__, __TIME__);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/astro.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/astro.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/astro.h	(revision 16632)
@@ -0,0 +1,13 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+# include "data.h"
+
+# ifndef ASTRO_H
+# define ASTRO_H
+
+void InitAstro ();
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/basic.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/basic.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/basic.h	(revision 16632)
@@ -0,0 +1,7 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+
+void cleanup ();
+void InitBasic ();
+void InitBasic_PantasksClient ();
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/convert.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/convert.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/convert.h	(revision 16632)
@@ -0,0 +1,25 @@
+# include "external.h"
+
+# ifndef CONVERT_H
+# define CONVERT_H
+
+/*** time/coord conversion functions not supplied by libohana ***/
+time_t        TimeRef               PROTO((double time, time_t TimeReference, int TimeFormat));
+double        TimeValue             PROTO((time_t time, time_t TimeReference, int TimeFormat));
+
+int           hh_hms                PROTO((double hh, int *hr, int *mn, double *sc));
+int           dd_dms                PROTO((double dd, int *dg, int *mn, double *sc));
+int           hms_format            PROTO((char *line, double value));
+int           dms_format            PROTO((char *line, double value));
+int           hh_hm                 PROTO((double hh, int *hr, double *mn));
+int           day_to_sec            PROTO((char *string, time_t *second));
+int           hms_to_sec            PROTO((char *string, time_t *second));
+char         *ohana_sec_to_hms      PROTO((time_t second));
+char         *ohana_sec_to_day      PROTO((time_t second));
+
+char         *meade_deg_to_str      PROTO((double deg));
+char         *meade_ra_to_str       PROTO((double deg));
+char         *meade_dec_to_str      PROTO((double deg));
+char         *strptime              PROTO((const char *s, const char *format, struct tm *tm));
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/data.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/data.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/data.h	(revision 16632)
@@ -0,0 +1,156 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+
+# ifndef DATA_H
+# define DATA_H
+
+/*** typedef structs used by math functions ***/
+typedef struct {
+  int   NLINES;
+  int   Nlines;
+  char **lines;
+  char  *name;
+} Queue;
+
+typedef struct {
+  char *name;
+  int NWORDS;
+  int Nwords;
+  char **words;
+  char **value;
+} Page;
+
+typedef struct {
+  char *name;
+  int NPAGES;
+  int Npages;
+  Page **pages;
+  // int *index; (why did I define this?  is it not used?)
+  char **pageIDs;
+} Book;
+
+void InitData ();
+
+/* in book.c */
+void InitBooks ();
+void InitBook (Book *book, char *name);
+void FreeBook (Book *book);
+Book *FindBook (char *name);
+Book *GetBook (int where);
+Book *CreateBook (char *name);
+int DeleteBook (Book *book);
+void ListBooks ();
+
+/* in page.c */
+void InitPage (Page *page, char *name);
+void FreePage (Page *page);
+Page *FindPage (Book *book, char *name);
+Page *GetPage (Book *book, int where);
+Page *GetPageRestricted (Book *book, int where, char *keyName, char *keyValue);
+Page *CreatePage (Book *book, char *name);
+int ShufflePages (Book *book);
+int DeletePage (Book *book, Page *page);
+void ListPages (Book *book);
+void ListWords (Page *page);
+int BookSetWord (Page *page, char *word, char *value);
+char *BookGetWord (Page *page, char *word);
+
+/* in queues.c */
+void InitQueues ();
+void ListQueues ();
+Queue *FindQueue (char *name);
+Queue *CreateQueue (char *name);
+void PushQueue (Queue *queue, char *line);
+void PushNamedQueue (char *name, char *line);
+char *PopQueue (Queue *queue);
+char *PopQueueMatch (Queue *queue, char *Key, char *value);
+void PushQueueUnique (Queue *queue, char *line, char *Key);
+void PushQueueReplace (Queue *queue, char *line, char *Key);
+int InitQueue (Queue *queue);
+int DeleteQueue (Queue *queue);
+int PrintQueue (Queue *queue);
+
+/* in fft.c */
+void fft1D (float *dataRe, float *dataIm, int N, int Nbit, int forward);
+int fftND (float *dataRe, float *dataIm, int Ndim, int *Nsize, int forward);
+int IsBinary (int N, int *Nbit);
+
+/* in spline.c */
+void spline_construct (float *x, float *y, int N, float *y2);
+float spline_apply (float *x, float *y, float *y2, int N, float X);
+
+/* in svdcmp.c */
+int svdcmp (float *a, float *w, float *v, int Nx, int Ny);
+
+/* mrqmin.c */
+float mrqcof (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, float **ta, float **tb, 
+	      float (funcs)(float, float *, int, float *));
+
+float mrqmin (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float *, int, float *), int VERBOSE);
+
+float mrqinit (float *x, float *y, float *dy, int Npts, 
+	       float *par, int Npar, 
+	       float (funcs)(float, float *, int, float *), int VERBOSE);
+
+float **mrqcovar (int Npar);
+
+void mrqfree (int Npar);
+
+/* mrq2dmin.c */
+float mrq2dcof (float *x, float *t, float *y, float *dy, int Npts, 
+		float *par, int Npar, float **ta, float **tb, 
+		float (funcs)(float, float, float *, int, float *));
+
+float mrq2dmin (float *x, float *t, float *y, float *dy, int Npts, 
+		float *par, int Npar, 
+		float (funcs)(float, float, float *, int, float *), int VERBOSE);
+
+float mrq2dinit (float *x, float *t, float *y, float *dy, int Npts, 
+		 float *par, int Npar, 
+		 float (funcs)(float, float, float *, int, float *), int VERBOSE);
+
+float mrq2dchi (float *x, float *t, float *y, float *dy, int Npts, 
+		float *par, int Npar, 
+		float (funcs)(float, float, float *, int, float *));
+
+int mrq2dlimits (float *pmin, float *pmax, int Npar);
+
+float **mrq2dcovar (int Npar);
+
+void mrq2dfree (int Npar);
+
+/* gaussian.c */
+double gaussian (double x, double mean, double sigma);
+void gauss_init (int Nbin);
+double rnd_gauss (double mean, double sigma);
+
+/* starfuncs.c */
+double get_aperture_stats (Matrix *matrix, int X, int Y, int Npix, int Nborder, double max);
+int set_rough_radii (double Ra, double Ri, double Ro);
+int get_rough_star (float *data, int Nx, int Ny, int x, int y, float *xc, float *yc, float *sx, float *sy, float *sxy, float *zs, float *zp, float *sk);
+
+/* precess.c */
+double BtoJ (double in_epoch);
+double get_epoch (char *in_epoch, char mode);
+
+/* graphtools.c */
+void          SetLimits             PROTO((Vector *xvec, Vector *yvec, Graphdata *graphmode));
+void          SetLimitsRaw          PROTO((float *xvec, float *yvec, int Npts, Graphdata *graphmode));
+void          ApplyLimits           PROTO((int Xgraph, Graphdata *graphmode, int apply));
+int           style_args            PROTO((Graphdata *graphmode, int *argc, char **argv, int *kapa));
+
+int read_table_vectors (int argc, char **argv, char *extname);
+
+void *db_getConnection ();
+
+int bracket (double *list, int Nlist, int mode, double value);
+int ibracket (int *list, int Nlist, int mode, double value);
+
+# endif
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/dimm.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/dimm.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/dimm.h	(revision 16632)
@@ -0,0 +1,71 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
+# include "sbig.h"
+
+void InitDIMM ();
+
+/* telescope.c */
+double distSky (double r1, double r2, double d1, double d2);
+int getRD (double *r, double *d) ;
+int gotoRD (double r, double d);
+int offset (char *direction, double distance);
+int toffset (char *direction, char *rate, double duration);
+int getXY (double *x, double *y);
+int setRD (double r, double d);
+int setSite (char *sitename, double lon, double lat);
+int setTime (char *lst);
+int getSite (double *lon, double *lat, double *lst);
+int ParkScope();
+int SleepScope();
+int WakeScope();
+
+/* Serial.c */
+int SerialVerbose (int mode);
+int SerialInit (char *port);
+int SerialOpen (char *port);
+int SerialBaudRate (int fdesc, int rate);
+int SerialParity (int fdesc, int parity); 
+int SerialDataBits(int fdesc, int bits); 
+int SerialStopBit(int fdesc, int stpbit); 
+void SerialStop (int fdesc);
+int SerialCommand (char *in, char **out, int wait);
+
+/* camera.c */
+int InitCamera (int port);
+void DumpCameraInfo ();
+void CameraFullSize (int *x, int *y);
+int SetTemperature (double temp);
+double GetTemperature ();
+int DumpCameraStatus ();
+int Exposure (double exptime);
+static int readout_callback (float percent);
+int ReadOut (int x, int y, int dx, int dy, int binning, unsigned short *buffer);
+int OpenShutter ();
+int CloseShutter ();
+
+  /* this image structure stuff is considered for further development */ 
+# if (0)
+/** this Image is incompatible with the DVO Image struct */
+typedef struct {
+
+  /* image data area */
+  int Nx, Ny;
+  char *buffer;
+  int Nbytes;
+
+  /* image metadata */
+  double ccdtemp;
+  double airtemp;
+  double ra, dec, airmass;
+  double exptime;
+  int binning;
+} Image;
+
+/* analysis.c */
+int subtractImage (Image *a, Image *b);
+void statsImage (Image *image, Stats *stats);
+void findStars (Image *image, Stars **stars, int *Nstars, double threshold);
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/display.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/display.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/display.h	(revision 16632)
@@ -0,0 +1,39 @@
+# include "external.h"
+# include "kapa.h"
+
+# ifndef DISPLAY_H
+# define DISPLAY_H
+
+/*** kapa graph functions ***/
+int           PlotVectorPair        PROTO((int kapa, int Npts, float *xValues, float *yValues, Graphdata *graphmode));
+int           PlotVectorTriplet     PROTO((int kapa, int Npts, float *xValues, float *yValues, float *zValues, Graphdata *graphmode));
+int           GetGraphData          PROTO((Graphdata *data, int *kapa, char *name));
+int           GetGraph              PROTO((Graphdata *data, int *kapa, char *name));
+int           SetGraph              PROTO((Graphdata *data));
+
+/*** kapa image functions */
+int           GetImageData          PROTO((KapaImageData *data, int *kapa, char *name));
+int           GetImage              PROTO((KapaImageData *data, int *kapa, char *name));
+int           SetImage              PROTO((KapaImageData *data));
+
+void	      QuitKapa              PROTO(());
+void	      InitKapa		    PROTO(());
+int 	      open_kapa		    PROTO((int entry));
+int 	      close_kapa	    PROTO((char *name));
+int 	      AddKapaDevice	    PROTO((char *name));
+int 	      DelKapaDevice	    PROTO((char *name));
+int 	      FindKapaDevice	    PROTO((char *name));
+char	     *GetKapaName	    PROTO(());
+
+/* calling program need to define a function 'get_variable' which
+ * returns the name of the executable for each of KAPA and KII
+ */
+char         *get_variable          PROTO((char *name));
+
+int SendLabel (char *string, int Xgraph, int mode);
+
+int SendGraphMessage (int device, char *format, ...);
+int SendGraphCommand (int device, int length, char *format, ...);
+int SendGraphCommandV (int device, int length, char *format, va_list argp);
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/dvomath.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/dvomath.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/dvomath.h	(revision 16632)
@@ -0,0 +1,120 @@
+/*** dvomath.h ***/
+
+# ifndef DVOMATH_H
+# define DVOMATH_H
+
+# define NCHARS 256
+
+enum {ANYVECTOR, NEWVECTOR, OLDVECTOR};
+enum {ANYBUFFER, NEWBUFFER, OLDBUFFER};
+
+typedef struct {			/* representation of a variable (0-D) */
+  char     *name;
+  char     *value;
+} Variable;
+
+typedef struct {			/* representation of a vector (1-D) */
+  char name[1024];
+  float *elements;
+  int Nelements;
+} Vector;
+
+typedef struct {			/* representation of buffer (image) */
+  char name[1024];
+  char file[1024];
+  Header header;
+  Matrix matrix;
+  int  bitpix, unsign;
+  double bscale, bzero;
+} Buffer;
+
+typedef struct {			/* math stack structure */
+  char   *name;
+  char    type;
+  float  *ptr;
+  Buffer *buffer;
+  Vector *vector;
+  float   Float;
+} StackVar;
+
+/* math functions */
+char         *dvomath               PROTO((int argc, char **argv, int *size, int maxsize));
+char        **isolate_elements      PROTO((int argc, char **argv, int *nstack));
+StackVar     *convert_to_RPN        PROTO((int argc, char **argv, int *nstack));
+int           check_stack           PROTO((StackVar *stack, int Nstack, int validsize));
+int           evaluate_stack        PROTO((StackVar *stack, int *Nstack));
+void          init_stack            PROTO((StackVar *stack));
+void          copy_stack	    PROTO((StackVar *stack1, StackVar *stack2));
+void          move_stack	    PROTO((StackVar *stack1, StackVar *stack2));
+void          clean_stack	    PROTO((StackVar *stack, int Nstack));
+void          delete_stack	    PROTO((StackVar *stack, int Nstack));
+void          clear_stack 	    PROTO((StackVar *stack));
+void          assign_stack 	    PROTO((StackVar *stack, char *name, int type));
+
+int           VV_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           SV_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           VS_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           MV_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           VM_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           MM_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           MS_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           SM_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           SS_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           WW_binary             PROTO((StackVar *OUT, StackVar *V1, StackVar *V2, char *op));
+int           S_unary               PROTO((StackVar *OUT, StackVar *V1, char *op));
+int           V_unary               PROTO((StackVar *OUT, StackVar *V1, char *op));
+int           M_unary               PROTO((StackVar *OUT, StackVar *V1, char *op));
+
+/* variable handling */
+char         *get_variable          PROTO((char *name));
+char         *get_variable_ptr      PROTO((char *name));
+char         *get_local_variable_ptr PROTO((char *name));
+double        get_double_variable   PROTO((char *name, int *found));
+int           get_int_variable      PROTO((char *name, int *found));
+int           DeleteNamedScalar     PROTO((char *name));
+int           IsScalar              PROTO((char *name));
+int           set_variable          PROTO((char *name, double dvalue));
+int           set_int_variable      PROTO((char *name, int ivalue));
+int           set_str_variable      PROTO((char *name, char *value));
+int           set_local_variable    PROTO((char *name, char *value));
+void          InitVariables         PROTO((void));
+void          ListVariables         PROTO((void));
+float         get_variable_default  PROTO((char *name, float dvalue));
+int           SelectScalar          PROTO((char *string, double *value));
+
+/* vector handling */
+Vector       *InitVector            PROTO((void));
+void          InitVectors           PROTO((void));
+int           CopyVector            PROTO((Vector *out, Vector *in));
+int           MoveVector            PROTO((Vector *out, Vector *in));
+int           DeleteVector          PROTO((Vector *vec));
+int           CopyNamedVector       PROTO((char *out, char *in));
+int           MoveNamedVector       PROTO((char *out, char *in));
+int           DeleteNamedVector     PROTO((char *name));
+int           IsVector              PROTO((char *name));
+int           IsVectorPtr           PROTO((Vector *vec));
+int           ListVectors           PROTO((void));
+Vector       *SelectVector          PROTO((char *name, int mode, int verbose));
+
+/* buffer handling */
+Buffer       *InitBuffer            PROTO((void));
+void          InitBuffers           PROTO((void));
+int           CopyBuffer            PROTO((Buffer *out, Buffer *in));
+int           MoveBuffer            PROTO((Buffer *out, Buffer *in));
+int           DeleteBuffer          PROTO((Buffer *buf));
+int           CopyNamedBuffer       PROTO((char *out, char *in));
+int           MoveNamedBuffer       PROTO((char *out, char *in));
+int           DeleteNamedBuffer     PROTO((char *name));
+int           IsBuffer              PROTO((char *name));
+int           IsBufferPtr           PROTO((Buffer *buf));
+int           PrintBuffers          PROTO((int Long));
+int           CreateBuffer          PROTO((Buffer *buf, int Nx, int Ny, int bitpix, float bzero, float bscale));
+Buffer       *SelectBuffer          PROTO((char *name, int mode, int verbose));
+void          dump_buffers          PROTO((int n));  /* deprecated? */
+int           SelectOverlay         PROTO((char *name, int *number));
+
+/* why are these in here? */
+int           gfits_copy_matrix_info (Matrix *matrix1, Matrix *matrix2);
+int           GetTimeFormat         PROTO((time_t *TimeReference, int *TimeFormat));
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/dvoshell.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/dvoshell.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/dvoshell.h	(revision 16632)
@@ -0,0 +1,243 @@
+# include "data.h"
+# include "basic.h"
+# include "astro.h"
+
+# ifndef DVOSHELL_H
+# define DVOSHELL_H
+
+/* magnitude types */
+enum {MAG_NONE, 
+      MAG_INST, 
+      MAG_CAT, 
+      MAG_SYS, 
+      MAG_REL, 
+      MAG_CAL, 
+      MAG_AVE, 
+      MAG_REF, 
+      MAG_ERR, 
+      MAG_CHISQ,
+      MAG_NCODE,
+      MAG_NPHOT,
+};
+
+/* measure fields */
+enum {MEAS_ZERO, 
+      MEAS_RA, 
+      MEAS_DEC, 
+      MEAS_RA_AVE, 
+      MEAS_DEC_AVE,
+      MEAS_RA_AVE_ERR, 
+      MEAS_DEC_AVE_ERR, 
+      MEAS_U_RA, 
+      MEAS_U_DEC, 
+      MEAS_U_RA_ERR, 
+      MEAS_U_DEC_ERR, 
+      MEAS_PAR, 
+      MEAS_PAR_ERR, 
+      MEAS_RA_OFFSET, 
+      MEAS_DEC_OFFSET, 
+      MEAS_RA_OFFSET_ERR, 
+      MEAS_DEC_OFFSET_ERR, 
+      MEAS_XP, 
+      MEAS_NMEAS, 
+      MEAS_NMISS, 
+      MEAS_OBJFLAGS, 
+      MEAS_MAG, 
+      MEAS_MINST, 
+      MEAS_MCAT, 
+      MEAS_MSYS, 
+      MEAS_MREL, 
+      MEAS_MCAL, 
+      MEAS_EXPTIME, 
+      MEAS_AIRMASS, 
+      MEAS_ALT, 
+      MEAS_AZ, 
+      MEAS_PHOTCODE, 
+      MEAS_TIME, 
+      MEAS_FWHM, 
+      MEAS_FWHM_MAJ, 
+      MEAS_FWHM_MIN, 
+      MEAS_THETA, 
+      MEAS_DOPHOT, 
+      MEAS_DB_FLAGS, 
+      MEAS_PHOT_FLAGS, 
+      MEAS_XCCD, 
+      MEAS_YCCD, 
+      MEAS_XMOSAIC, 
+      MEAS_YMOSAIC, 
+      MEAS_SKY, 
+      MEAS_dSKY, 
+      MEAS_DET_ID, 
+      MEAS_OBJ_ID, 
+      MEAS_IMAGE_ID, 
+      MEAS_PSF_QF, 
+      MEAS_PSF_PROB, 
+      MEAS_CR_NSIGMA, 
+      MEAS_EXT_NSIGMA, 
+      MEAS_STARGAL, 
+};
+
+/* average fields */
+enum {AVE_ZERO, 
+      AVE_RA, 
+      AVE_DEC, 
+      AVE_RA_ERR, 
+      AVE_DEC_ERR, 
+      AVE_U_RA, 
+      AVE_U_DEC, 
+      AVE_U_RA_ERR, 
+      AVE_U_DEC_ERR, 
+      AVE_PAR, 
+      AVE_PAR_ERR, 
+      AVE_Xp, 
+      AVE_NMEAS, 
+      AVE_NMISS, 
+      AVE_NPHOT, 
+      AVE_NCODE, 
+      AVE_MAG, 
+      AVE_dMAG, 
+      AVE_Xm, 
+      AVE_FLAG, 
+      AVE_TYPE, 
+      AVE_TYPEFRAC,
+      AVE_OBJID
+};
+
+enum {DVO_TABLE_AVERAGE, DVO_TABLE_MEASURE};
+
+// options for selecting the ra,dec limits of the db selections
+typedef struct {
+  char *name;
+  char *list;
+  int useDisplay;
+  int useSkyregion;
+} SkyRegionSelection;
+
+// a single db field 
+typedef struct {
+  char *name;
+  int extract;
+  int table;
+  int ID;
+  int magMode;
+  PhotCode *photcode;
+} dbField;
+
+// db boolean operations
+typedef struct {
+  char   *name;
+  char    type;
+  int     field;
+  float   Float;
+} dbStack;
+
+typedef struct {
+  char name[64];
+  double RA0, RA1, DEC0, DEC1;
+} RegionFile;
+
+typedef struct {
+  double X;
+  double Y;
+  double R;
+  double D;
+  double M, dM;
+  char   dophot;
+  double sky;
+  double fx, fy, df;
+  double Mgal, Map;
+  int found;
+  short int code;
+  e_time t;
+} CMPstars;
+
+/*** dvo prototypes ***/
+int           DetermineTypeCode     PROTO((Average *average, Measure *measure, int code));
+double        DetermineTypefrac     PROTO((Average *average, Measure *measure, PhotCode *code));
+double        ExtractAverages       PROTO((PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int param));
+double       *ExtractByDMag         PROTO((PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param));
+double       *ExtractDMag           PROTO((PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist));
+double       *ExtractMagnitudes     PROTO((PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *n));
+double       *ExtractMeasures       PROTO((PhotCode *code, int mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param));
+double       *ExtractMeasuresByDMag PROTO((PhotCode **code, int *mode, int use_first, Average *average, SecFilt *secfilt, Measure *measure, int *nlist, int param));
+double       *ExtractMeasuresDMag   PROTO((PhotCode **code, int *mode, Average *average, SecFilt *secfilt, Measure *measure, int *nlist));
+void          FreeImageSelection    PROTO(());
+void          FreeImageSelection    PROTO(());
+int           GetAverageParam       PROTO((char *parname));
+void          GetAverageParamHelp   PROTO(());
+int           GetMagMode            PROTO((char *string));
+double        GetMeasure            PROTO((int param, Average *average, Measure *measure, double mag));
+int           GetMeasureParam       PROTO((char *parname));
+int           GetMeasureTypeCode    PROTO((Measure *measure));
+int           GetPhotcodeInfo       PROTO((char *string, PhotCode **Code, int *Mode));
+int           GetSelectionParam     PROTO(());
+int           GetTimeSelection      PROTO((time_t *tz, time_t *te));
+void          InitDVO               PROTO(());
+int           InitPhotcodes         PROTO(());
+Image        *LoadImages            PROTO((int *Nimage));
+Image        *MatchImage            PROTO((unsigned int time, short int source));
+Coords       *MatchMosaic           PROTO((unsigned int time, short int source));
+int           Quality               PROTO((Measure *measure, int IsDophot));
+int           SelectMags            PROTO((int Nphot, int Tphot, int Ns, Average *average, Measure *measure, SecFilt *secfilt, int UL));
+
+SkyList      *SelectRegions         PROTO((SkyRegionSelection *selection));
+SkyList      *SkyListLoadFile       PROTO((char *filename));
+int           SetCATDIR             PROTO((char *path, int verbose));
+char *        GetCATDIR             PROTO(());
+SkyTable     *GetSkyTable           PROTO(());
+SkyList      *SkyListFromFile       PROTO((char *filename));
+SkyRegionSelection *SetRegionSelection    PROTO((int *argc, char **argv));
+
+int           SetImageSelection     PROTO((int mode, SkyRegionSelection *selection));
+int           SetPhotSelections     PROTO((int *argc, char **argv, int Nparams));
+int           SetSelectionParam     PROTO((int param));
+int           TestAverage           PROTO((PhotCode *code, Average *average, SecFilt *secfilt, Measure *measure));
+int           TestPhotSelections    PROTO((PhotCode **code, int *mode, int param));
+void          compare               PROTO((Catalog *catlog1, Catalog *catlog2, Vector *rvec,  Vector *dvec,  Vector *mvec, Vector *drvec, Vector *ddvec, Vector *dmvec, double radius));
+void          cprecess              PROTO((Average *average, int Naverage, double in_epoch, double out_epoch));
+void          image_subset          PROTO((Image *image, int Nimage, int **Subset, int *Nsubset, SkyRegionSelection *selection, unsigned long int tzero, double trange, int TimeSelect));
+int           match_image           PROTO((Image *image, int Nimage, unsigned int T, short int S));
+int           match_image_subset    PROTO((Image *image, int *subset, int Nsubset, unsigned int T, short int S));
+void          print_value           PROTO((double value, short int ival));
+void          sort_image_subset     PROTO((Image *image, int *subset, int N));
+void          sort_images           PROTO((Image *image, int N));
+void          sortave               PROTO((Average *ave, int N));
+CMPstars     *cmpReadFits           PROTO((FILE *f, int *nstars));
+CMPstars     *cmpReadText           PROTO((FILE *f, int *nstars));
+int           RD_to_XYpic           PROTO((double *x, double *y, double r, double d, Coords *coords, double Rmin, double Rmax, double Rmid, int *leftside));
+
+// dvo DB field functions
+dbField     *dbCmdlineFields        PROTO((int argc, char **argv, int table, int *last, int *nfields));
+dbStack     *dbRPN                  PROTO((int argc, char **argv, int *nstack));
+int          dbCheckStack           PROTO((dbStack *stack, int Nstack, int table, dbField **inFields, int *Nfields));
+int          dbBooleanCond          PROTO((dbStack *inStack, int NinStack, float *fields));
+void         dbInitStack            PROTO((dbStack *stack));
+void 	     dbFreeStack            PROTO((dbStack *stack, int Nstack));
+void 	     dbFreeEntry            PROTO((dbStack *stack));
+void         dbFreeTempEntry        PROTO((dbStack *stack));
+
+dbStack     *dbBinary               PROTO((dbStack *V1, dbStack *V2, char *op, float *fields));
+dbStack     *dbUnary                PROTO((dbStack *V1, char *op, float *fields));
+
+int          GetMagMode             PROTO((char *string));
+PhotCode    *ParsePhotcodeField     PROTO((char *field, int *mode, int def));
+int          ParseMeasureField      PROTO((dbField *field, char *fieldName));
+int          ParseAverageField      PROTO((dbField *field, char *fieldName));
+
+double       dbExtractAverages      PROTO((Average *average, SecFilt *secfilt, Measure *measure, dbField *field));
+double       dbExtractMeasures      PROTO((Average *average, SecFilt *secfilt, Measure *measure, dbField *field));
+void         dbExtractMeasuresInit  PROTO(());
+
+void 	     dbInitField            PROTO((dbField *field));
+void 	     dbFreeFields           PROTO((dbField *fields, int Nfields));
+int          dbAstroRegionLimits    PROTO((dbStack **stack, int *nstack, SkyRegionSelection *selection, int table));
+char        *strfloat               PROTO((float value));
+
+int get_skyregion (double *Rs, double *Re, double *Ds, double *De);
+int set_skyregion (double Rs, double Re, double Ds, double De);
+void FreeImageSelection ();
+
+void FreeSkyRegionSelection (SkyRegionSelection *selection);
+int wordhash (char *word);
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/external.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/external.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/external.h	(revision 16632)
@@ -0,0 +1,30 @@
+# include <signal.h>
+# include <unistd.h>
+# include <sys/uio.h>
+# include <fcntl.h>
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <sys/socket.h>
+# include <sys/un.h>
+# include <sys/time.h>
+# include <time.h>
+# include <errno.h>
+# include <pthread.h>
+
+# include <netinet/ip.h>
+# include <netdb.h>
+# include <arpa/inet.h>
+
+# include <ohana.h>
+# include <dvo.h>
+
+/* provide missing external defines */
+# ifdef MISSING_SOCKET_INFO
+#   define F_SETFL         4   
+#   define O_NONBLOCK       0200000  
+#   define AF_UNIX         1          
+#   define SOCK_STREAM     1          
+#   define ENOENT          2 
+# endif
+
+# define strlen(A) ((int)strlen(A))
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/hstgsc.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/hstgsc.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/hstgsc.h	(revision 16632)
@@ -0,0 +1,27 @@
+
+static double BigDecBounds[] = {0.0, 7.5, 15.0, 22.5, 30.0, 37.5, 45.0, 
+				52.5, 60.0, 67.5, 75.0, 82.5, 90.0,
+				0.0, -7.5, -15.0, -22.5, -30.0, -37.5, -45.0, 
+				-52.5, -60.0, -67.5, -75.0, -82.5, -90.0};
+static char *Dec2Sections[] = {"n0000", "n0730", "n1500", "n2230", "n3000", "n3730", "n4500", 
+			       "n5230", "n6000", "n6730", "n7500", "n8230", "weirdness", 
+			       "s0000", "s0730", "s1500", "s2230", "s3000", "s3730", "s4500", 
+			       "s5230", "s6000", "s6730", "s7500", "s8230", "weirdness"};
+
+static int NDecLines[] = {593, 584, 551, 530, 522, 465, 406, 362, 280, 198, 123, 24, 
+			  0, 597, 578, 574, 577, 534, 499, 442, 376, 294, 212, 144, 48};
+
+/** older data layout concepts 
+static char *DecSections[] = {"N0000", "N0730", "N1500", "N2230", "N3000", "N3730", "N4500", 
+			      "N5230", "N6000", "N6730", "N7500", "N8230", "weirdness", 
+			      "S0000", "S0730", "S1500", "S2230", "S3000", "S3730", "S4500", 
+			      "S5230", "S6000", "S6730", "S7500", "S8230", "weirdness"};
+
+static char *disk[] = {"disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", 
+		       "disk 1", "disk 1", "disk 1", "disk 1", "disk 1", "weirdness", 
+		       "disk 1", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", 
+		       "disk 2", "disk 2", "disk 2", "disk 2", "disk 2", "weirdness"};
+
+static int NBigRASections [] = {48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3, 48, 47, 45, 43, 40, 36, 32, 28, 21, 15, 9, 3, 3};
+
+**/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/imfit.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/imfit.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/imfit.h	(revision 16632)
@@ -0,0 +1,20 @@
+# include "astro.h"
+
+int Npar;
+int Nfpar;
+float *par;
+float *fpar;
+float *sky;
+
+float (*fitfunc)(float, float, float *, int, float *);
+void (*imfit_cleanup)();
+
+void fgauss_setup (char *name);
+void pgauss_setup (char *name);
+void sgauss_setup (char *name);
+void qgauss_setup (char *name);
+void qfgauss_setup (char *name);
+void qrgauss_setup (char *name);
+void pgauss_psf_setup (char *name);
+void qgauss_psf_setup (char *name);
+void sgauss_psf_setup (char *name);
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/mana.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/mana.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/mana.h	(revision 16632)
@@ -0,0 +1,10 @@
+# include "data.h"
+# include "basic.h"
+# include "astro.h"
+
+# ifndef MANA_H
+
+void InitMana ();
+int *findrowpeaks (float *row, int Nrow, float threshold, int *npeaks);
+
+# endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/opihi.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/opihi.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/opihi.h	(revision 16632)
@@ -0,0 +1,5 @@
+# include "external.h"
+# include "shell.h"
+# include "dvomath.h"
+# include "convert.h"
+# include "display.h"
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/pantasks.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/pantasks.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/pantasks.h	(revision 16632)
@@ -0,0 +1,268 @@
+# include "data.h"
+# include "basic.h"
+# include "astro.h"
+
+# include <sys/time.h>
+# include <time.h>
+# include <zlib.h>
+
+# define DEBUG 0
+
+typedef enum {
+  JOB_NONE,
+  JOB_BUSY, 
+  JOB_EXIT, 
+  JOB_HUNG,
+  JOB_CRASH,
+  JOB_PENDING,
+} JobStat;
+
+typedef enum {
+  JOB_LOCAL, 
+  JOB_CONTROLLER, 
+} JobMode;
+
+typedef enum {
+  CONTROLLER_HUNG = -1,
+  CONTROLLER_DOWN = 0,
+  CONTROLLER_GOOD = 1,
+} ControllerStat;
+
+enum {RANGE_ABS, RANGE_DAY, RANGE_WEEK};
+enum {TIMER_ALLJOBS, TIMER_SUCCESS, TIMER_FAILURE};
+
+enum {TASK_NONE, 
+      TASK_EMPTY, 
+      TASK_COMMENT, 
+      TASK_NMAX, 
+      TASK_ACTIVE, 
+      TASK_TRANGE, 
+      TASK_END, 
+      TASK_HOST, 
+      TASK_STDOUT, 
+      TASK_STDERR, 
+      TASK_COMMAND, 
+      TASK_OPTIONS, 
+      TASK_PERIODS, 
+      TASK_NPENDING, 
+      TASK_EXIT, 
+      TASK_EXEC
+} TaskHashResults;
+
+typedef struct {
+  time_t start;
+  time_t stop;
+  char type;
+  char include;
+  int Nmax;
+  int Nrun;
+} TimeRange;
+
+/* a task is a description of the wrapping of a job */
+typedef struct {
+  Macro  *exec;				/* name is 'exec' */
+  Macro  *crash;			/* name is 'crash' */
+  Macro  *timeout;
+  Macro  *defexit;
+
+  int     NEXIT;
+  int     Nexit;
+  Macro **exit;				/* name is exit status */
+
+  int     argc;
+  char  **argv;
+
+  int     optc;
+  char  **optv;
+
+  char   *host;
+  int     host_required;
+
+  char   *name;
+
+  char   *stdout_dump;
+  char   *stderr_dump;
+
+  int       Nranges;
+  TimeRange *ranges;
+
+  int     Nmax;  // only construct Ntotal jobs for this task
+  int     Njobs;
+
+  int     Npending;  // number of currently pending jobs
+  int     NpendingMax;  // max number of pending jobs allowed
+
+  float   poll_period;
+  float   exec_period;
+  float   timeout_period;
+
+  struct timeval last;
+
+  int Nsuccess;
+  int Nfailure;
+  int Ntimeout;
+
+  double dtimeAve_alljobs, dtimeMin_alljobs, dtimeMax_alljobs;
+  double dtimeAve_success, dtimeMin_success, dtimeMax_success;
+  double dtimeAve_failure, dtimeMin_failure, dtimeMax_failure;
+
+  int active;
+
+} Task;
+
+// time period include/exclude periods: 
+// date ranges (e_time - e_time) 
+// time ranges (e_time - e_time) (use e_time % 86400)
+// time-of-week ranges  (e_time - e_time
+// -trange Mon Fri (inclusive on days -- end defaults to Fri@23:59:59)
+// -trange 08:00 - 17:00
+// -trange 2005/12/24 2005/12/31
+// be careful of HST!
+// type: day, week, date
+// keep: TRUE: perform action within this time period
+// keep: FALSE: do not perform action within this time period
+  
+typedef struct {
+  int JobID;				/* internal ID for job */
+  int pid;				/* external ID for job */
+
+  struct timeval last;
+  struct timeval start;
+  int state;
+  int exit_status;
+
+  int     argc;
+  char  **argv;
+
+  int     optc;
+  char  **optv;
+
+  Task   *task;
+
+  /* this cries out for another structure... */
+  IOBuffer    stdout_buff;    /* stdout storage buffer */
+  char       *stdout_dump;    // output target file for stdout
+  int         stdout_size;    /* size of pending stdout buffer (controller) */
+  int         stdout_fd;      /* stdout pipe (local only) */
+
+  IOBuffer    stderr_buff;    /* stderr storage buffer */
+  char       *stderr_dump;    // output target file for stderr
+  int         stderr_size;    /* size of pending stderr buffer (controller) */
+  int         stderr_fd;      /* stderr pipe (local only) */
+
+  JobMode     mode;			/* local or controller? */
+  char   *realhost;
+
+  double dtime;
+} Job;
+
+# define CONTROLLER_PROMPT "pcontrol:"
+
+/* scheduler prototypes */
+
+void InitPantasks ();
+void InitPantasksServer ();
+void InitPantasksClient ();
+void InitTasks ();
+Task *NextTask ();
+Task *FindTask (char *name);
+void ListTasks (int verbose);
+int ShowTask (char *name);
+int FreeTask (Task *task);
+Task *CreateTask (char *name);
+int ValidateTask (Task *task, int RequireStatic);
+int RegisterNewTask ();
+int DeleteNewTask ();
+Task *GetNewTask ();
+Task *GetActiveTask ();
+void SetTaskTimer (struct timeval *timer);
+double GetTaskTimer (struct timeval start, int verbose);
+void InitTaskTimers ();
+int TaskHash (char *input);
+int RemoveTask (Task *task);
+Task *SetNewTask (Task *task);
+void ListTaskStats (char *regex);
+void ResetTaskStats (char *regex);
+void UpdateTaskTimerStats (Task *task, int mode, double dtime);
+
+int NextJobID ();
+int InitJobIDs ();
+int FreeJobID (int ID);
+
+void InitJobs ();
+Job *NextJob ();
+Job *FindJob (int JobID);
+void ListJobs ();
+Job *CreateJob (Task *task);
+int SubmitJob (Job *job);
+int CheckJob (Job *job);
+int DeleteJob (Job *job);
+void FreeJob (Job *job);
+
+float CheckJobs ();
+float CheckTasks ();
+int CheckSystem ();
+int CheckController ();
+int CheckTimeRanges (TimeRange *ranges, int Nranges);
+int BumpTimeRanges (TimeRange *ranges, int Nranges);
+
+int GetJobOutput (char *channel, int pid, IOBuffer *buffer, int Nbytes);
+int CheckControllerJob (Job *job);
+int CheckControllerJobStatus (Job *job);
+int SubmitControllerJob (Job *job);
+int DeleteControllerJob (Job *job);
+Job *FindControllerJob (int JobID);
+int StartController ();
+int ControllerCommand (char *command, char *response, IOBuffer *buffer);
+int SubmitLocalJob (Job *job);
+int CheckLocalJob (Job *job);
+int CheckLocalJobStatus (Job *job);
+void InitTaskTimers ();
+CommandF *FindControllerCommand (char *cmd);
+int QuitController ();
+int StopController ();
+int VerboseMode ();
+int KillLocalJob (Job *job);
+int CheckControllerOutput ();
+int PrintControllerOutput ();
+
+int KillControllerJob (Job *job);
+int CheckControllerStatus ();
+void gotsignal (int signum);
+int client_shell (int argc, char **argv);
+
+void InitClients ();
+void AddNewClient (int client);
+int  DeleteClient (int client);
+void *ListenClients (void *data);
+
+// functions related to the server threads
+void CheckTasksSetState (int state);
+int CheckTasksGetState ();
+void *CheckTasksThread (void *data);
+
+void CheckJobsSetState (int state);
+int CheckJobsGetState ();
+void *CheckJobsThread (void *data);
+
+void CheckControllerSetState (int state);
+int CheckControllerGetState ();
+void *CheckControllerThread (void *data);
+
+void CheckInputsSetState (int state);
+int CheckInputsGetState ();
+void *CheckInputsThread (void *data);
+
+// functions related to the queue of input files
+void InitInputs ();
+void AddNewInput (char *input);
+int DeleteInput (char *input);
+void CheckInputs ();
+
+void SerialThreadLock ();
+void SerialThreadUnlock ();
+
+int InitPassword ();
+int CheckPassword (int BindSocket);
+
+int FlushJobs ();
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/pclient.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/pclient.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/pclient.h	(revision 16632)
@@ -0,0 +1,53 @@
+# include "data.h"
+# include "basic.h"
+
+/** pclient global data **/
+
+/** child status values **/
+enum {
+  PCLIENT_NONE,
+  PCLIENT_BUSY,  
+  PCLIENT_EXIT,
+  PCLIENT_CRASH,
+};
+
+int ChildPID;				/** current child PID **/
+int ChildStatus;			/** current status of child **/
+int ChildExitStatus;			/** recent exit status of child **/
+
+/** child may be in the following states:
+    
+PCLIENT_NONE
+PCLIENT_BUSY
+PCLIENT_EXIT
+PCLIENT_CRASH
+
+allowed transitions:
+
+PCLIENT_NONE  ->    PCLIENT_BUSY  (start a job)
+
+PCLIENT_BUSY  ->    PCLIENT_EXIT  (job complete)
+PCLIENT_BUSY  ->    PCLIENT_CRASH (job crashed)
+
+PCLIENT_EXIT  ->    PCLIENT_NONE  (cleanup)
+PCLIENT_CRASH ->    PCLIENT_NONE  (cleanup)
+
+**/
+
+/** file descriptors for child I/O **/
+int child_stdin_fd[2];
+int child_stdout_fd[2];
+int child_stderr_fd[2];
+
+/** buffers for I/O storage **/
+IOBuffer child_stdout;
+IOBuffer child_stderr;
+
+int InitChild ();
+int CheckChild ();
+void CheckChildStatus ();
+
+void InitPclient ();
+void gotsignal (int signum);
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/pcontrol.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/pcontrol.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/pcontrol.h	(revision 16632)
@@ -0,0 +1,225 @@
+# include "data.h"
+# include "basic.h"
+# define THREADED
+
+typedef struct timeval Ptime;
+typedef unsigned long long IDtype;
+
+/** job status values **/
+typedef enum {
+  PCONTROL_JOB_PENDING,
+  PCONTROL_JOB_BUSY,  
+  PCONTROL_JOB_HUNG,  
+  PCONTROL_JOB_DONE,  
+  PCONTROL_JOB_KILL,  
+  PCONTROL_JOB_EXIT,
+  PCONTROL_JOB_CRASH,
+} JobStat;
+
+/** job status values **/
+typedef enum {
+  PCONTROL_JOB_ANYHOST,
+  PCONTROL_JOB_WANTHOST,
+  PCONTROL_JOB_NEEDHOST,
+} JobMode;
+
+/** host status values **/
+typedef enum {
+  PCONTROL_HOST_IDLE,
+  PCONTROL_HOST_BUSY,  
+  PCONTROL_HOST_DOWN,
+  PCONTROL_HOST_DONE,
+  PCONTROL_HOST_OFF,
+} HostStat;
+
+typedef enum {
+  PCONTROL_RUN_UNKNOWN,
+  PCONTROL_RUN_NONE,
+  PCONTROL_RUN_HOSTS,
+  PCONTROL_RUN_REAP,
+  PCONTROL_RUN_ALL,
+} RunLevels;
+
+/* stack special positions */
+typedef enum {
+  STACK_TOP = 0,
+  STACK_BOTTOM = -1,
+} StackWhere;
+
+typedef enum {
+  PCLIENT_HUNG = -1,
+  PCLIENT_DOWN = 0,
+  PCLIENT_GOOD = 1,
+} PclientStat;
+
+typedef struct {
+  char *buffer;
+  int   Nalloc;
+  int   Nmaxread;
+  int   Nextra;
+  int   Nlast;
+  int   Nbuffer;
+} Fifo;
+
+/* data to define a job */
+typedef struct {
+  int          argc; 
+  char       **argv;
+  char        *hostname;
+  char        *realhost;
+  int          exit_status;
+  int          Reset;
+  int          stdout_size;
+  int          stderr_size;
+  JobMode      mode;
+  JobStat      state;
+  JobStat      stack;
+  IOBuffer     stdout_buff;
+  IOBuffer     stderr_buff;
+  Ptime        start;
+  Ptime        stop;
+  double       dtime;
+  int          pid;
+  IDtype       JobID;
+  struct Host *host;
+} Job;
+
+/* data to define a host machine */
+typedef struct {
+  char       *hostname;
+  int         stdin_fd;
+  int         stdout_fd;
+  int         stderr_fd;
+  int         markoff;
+  int         pid;
+  HostStat    stack;
+  Ptime       lasttry;
+  Ptime       nexttry;
+  IDtype      HostID;
+  struct Job *job;
+} Host;
+
+typedef struct {
+  void **object;
+  char **name;
+  int   *id;
+  int    Nobject;
+  int    NOBJECT;
+# ifdef THREADED    
+  pthread_mutex_t mutex;
+# endif
+} Stack;
+
+/* XXX if this is hard-wired, we can't change shell name in StartHost */
+# define PCLIENT_PROMPT "pclient:"
+
+// # define FREE(X) if (X != NULL) { free (X); }
+# define CLOSE(FD) { if (FD) close (FD); FD = 0; }
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+# define ZTIME(A) ((A.tv_sec == 0) && (A.tv_usec == 0))
+
+# define ASSERT(TEST,STRING) { if (!(TEST)) { gprint (GP_ERR, "programming error: %s\n", STRING); abort (); }}
+# define ABORT(STRING) { gprint (GP_ERR, "programming error: %s\n", STRING); abort (); }
+// # define ASSERT(TEST,STRING) { if (!(TEST)) { gprint (GP_ERR, "programming error: %s\n", STRING); raise (SIGINT); exit (2); }}
+// # define ABORT(STRING) { gprint (GP_ERR, "programming error: %s\n", STRING); raise (SIGINT); exit (2); }
+
+void InitPcontrol ();
+
+/*** StackOps.c ***/
+Stack *InitStack ();
+int    PushStack (Stack *stack, int where, void *object, int id, char *name);
+void  *PullStackByLocation (Stack *stack, int where);
+void  *PullStackByName (Stack *stack, char *name);
+void  *PullStackByID (Stack *stack, int id);
+int    RemoveStackEntry (Stack *stack, int where);
+void  *RemoveStackByID (Stack *stack, int id);
+void   LockStack (Stack *stack);
+void   UnlockStack (Stack *stack);
+
+// void  *FindStackByID (Stack *stack, int id);
+// void  *FindStackByName (Stack *stack, char *name);
+
+/*** CheckSystem.c ***/
+int   CheckSystem ();
+void *CheckSystem_Threaded (void *data);
+int   CheckBusyJobs (float delay);
+int   CheckDoneJobs (float delay);
+int   CheckKillJobs (float delay);
+int   CheckDoneHosts (float delay);
+int   CheckDownHosts (float delay);
+int   CheckIdleHosts (float delay);
+int   CheckLiveHosts (float delay);
+int   SetRunSystem (int state);
+RunLevels SetRunLevel (RunLevels level);
+
+/*** own files ***/
+int CheckHost (Host *host);
+int StartHost (Host *host);
+int CheckIdleHost (Host *host);
+int CheckDoneHost (Host *host);
+int CheckBusyJob (Job *job, Host *host);
+int CheckDoneJob (Job *job, Host *host);
+int KillJob (Job *job, Host *host);
+int StartJob (Job *job, Host *host);
+int ResetJob (Job *job);
+int GetJobOutput (char *command, Host *host, IOBuffer *buffer, int Nbytes);
+int PclientCommand (Host *host, char *command, char *response, IOBuffer *buffer);
+int rconnect (char *command, char *hostname, char *shell, int *stdio);
+
+/*** misc files ***/
+int    VerboseMode ();  // in verbose.c
+void   gotsignal (int signum); // in pcontrol.c
+
+/*** IDops.c ***/
+void InitIDs ();
+IDtype NextJobID ();
+IDtype NextHostID ();
+void PrintID (gpDest dest, IDtype ID);
+
+/*** CheckPoint.c ***/
+int SetCheckPoint ();
+int ClearCheckPoint ();
+int TestCheckPoint ();
+
+/*** HostOps.c ***/
+void   InitHostStacks ();
+Stack *GetHostStack (int StackID);
+char  *GetHostStackName (int StackID);
+Stack *GetHostStackByName (char *name);
+int    PutHost (Host *host, int StackID, int where);
+Host  *PullHostByID (IDtype HostID, int *StackID);
+Host  *PullHostByName (char *name, int *StackID);
+Host  *PullHostFromStackByID (int StackID, IDtype ID);
+Host  *PullHostFromStackByName (int StackID, char *name);
+IDtype AddHost (char *hostname);
+void   DelHost (Host *host);
+
+/*** StopHosts.c ***/
+void   DownHost (Host *host);
+void   OffHost (Host *host);
+int    DownHosts ();
+int    StopHost (Host *host);
+int    HarvestHost (int pid);
+
+/*** JobOps.c ***/
+void   InitJobStacks ();
+Stack *GetJobStack (int StackID);
+char  *GetJobStackName (int StackID);
+Stack *GetJobStackByName (char *name);
+int    PutJob (Job *job, int StackID, int where);
+int    PutJobSetState (Job *job, int StackID, int where, int state);
+Job   *PullJobByID (IDtype JobID, int *StackID);
+Job   *PullJobFromStackByID (int StackID, int ID);
+IDtype AddJob (char *hostname, JobMode mode, int timeout, int argc, char **argv);
+void   DelJob (Job *job);
+Host  *UnlinkJobAndHost (Job *job);
+void   LinkJobAndHost (Job *job, Host *host);
+
+void pcontrol_exit (int n);
+
+// Job   *FindJobByID (IDtype JobID, int *StackID);
+// Job   *FindJobInStackByID (int StackID, int ID);
+// Host  *FindHostByID (IDtype HostID, int *StackID);
+// Host  *FindHostByName (char *name, int *StackID);
+// Host  *FindHostInStackByID (int StackID, IDtype ID);
+// Host  *FindHostInStackByName (int StackID, char *name);
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/shell.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/shell.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/shell.h	(revision 16632)
@@ -0,0 +1,173 @@
+/*** shell.h ***/
+# include "external.h"
+
+# ifndef SHELL_H
+# define SHELL_H
+
+# define ISVAR(a) (isalnum (a) || (a == ':') || (a == '_'))
+# define ISWORD(a,q) ((q) ? (a != '"') : (isalnum(a) || (a == '/') || (a == '.') || (a == '_') || (a == '-')))
+# define ISNUM(c) (isdigit(c) || (c == '-') || (c == '.'))
+
+# define MACRO_STRING(s) #s
+# define MACRO_NAME(s) MACRO_STRING(s)
+
+/* enums used by gprint functions */
+typedef enum {GP_FILE, GP_BUFF} gpMode;
+typedef enum {GP_LOG, GP_ERR} gpDest;
+
+typedef int CommandF ();
+
+typedef struct sockaddr_in SockAddress;
+
+/*** typedef structs used by shell functions ***/
+typedef struct {			/* basic opihi command structure */
+  char      real;
+  char     *name;
+  CommandF *func;    
+  char     *help;
+} Command;
+
+typedef struct {			/* a macro (collection of commands) */
+  char   *name;
+  char  **line;
+  int     Nlines;
+} Macro;
+
+typedef struct {			/* a list (macro/loop currently being executed) */
+  char **line;
+  int    n;
+  int    Nlines;
+  int    Nalloc;
+} List;
+
+/* structure used to represent the gprint i/o stream */
+typedef struct {
+  FILE *file;
+  char *name;
+  IOBuffer *buffer;
+  gpMode mode;
+  gpDest dest;
+  pthread_t thread;
+} gpStream;
+
+/*** globals used to track the shell language concepts  ***/
+int 	     interrupt;			/* true if C-C has been pressed */
+int 	     auto_break;		/* if true, zero exit status forces macros to escape */
+int 	     loop_next; 		/* set to true when next (or continue) is called */
+int 	     loop_last; 		/* set to true when last (or return) is called */
+int 	     loop_break;		/* set to true when break is called */
+int          is_script;                 /* being run within a shell script */
+
+/*** basic opihi shell functions ***/
+void          general_init            	PROTO((int *argc, char **argv));
+void          program_init            	PROTO((int *argc, char **argv));
+void          startup               	PROTO((int *argc, char **argv));
+int           opihi                     PROTO((int argc, char **argv));
+int           multicommand          	PROTO((char *line));
+void          multicommand_InitServer   PROTO((void));
+int           command               	PROTO((char *line, char **outline, int VERBOSE));
+char         *expand_vars           	PROTO((char *line));
+char         *expand_vectors        	PROTO((char *line));
+char         *parse                 	PROTO((char *line));
+char        **parse_commands        	PROTO((char *, int *));
+void          welcome                   PROTO(());
+
+int           add_listentry             PROTO((int ThisList, char *line));
+int           is_for_loop           	PROTO((char *line));
+int           is_if_block           	PROTO((char *line));
+int           is_list               	PROTO((char *line));
+int           is_loop               	PROTO((char *line));
+int           is_task               	PROTO((char *line));
+int           is_task_exit             	PROTO((char *line));
+int           is_task_exec             	PROTO((char *line));
+int           is_macro_create       	PROTO((char *line));
+void          InitLists                 PROTO(());
+int current_list_depth ();
+int increase_list_depth ();
+int decrease_list_depth ();
+char *get_next_listentry (int ThisList);
+
+void          InitCommands              PROTO(());
+void          AddCommand                PROTO((Command *new));
+int           DeleteCommand             PROTO((Command *command));
+Command      *MatchCommand              PROTO((char *name, int VERBOSE, int EXACT));
+void          sort_commands             PROTO((int *seq));
+
+void          SetCurrentMacroData	PROTO((char *name, int depth));
+Macro        *NewMacro			PROTO((char *name));
+int           DeleteMacro		PROTO((Macro *macro));
+Macro        *MatchMacro		PROTO((char *name, int VERBOSE, int EXACT));
+void          InitMacros                PROTO((void));
+char         *GetMacroName              PROTO((void));
+int           GetMacroDepth             PROTO((void));
+void          ListMacro                 PROTO((Macro *macro));
+void          ListMacros                PROTO(());
+void          FreeMacro                 PROTO((Macro *macro));
+CommandF     *find_macro_command        PROTO((char *name));
+
+int           exec_loop                 PROTO((Macro *loop));
+/* char         *get_next_listentry    	PROTO((int ThisList)); */
+/* char         *remove_listentry      	PROTO((int current)); */
+
+int           ConfigInit            	PROTO((int *argc, char **argv));
+char         *VarConfig             	PROTO((char *keyword, char *mode, void *ptr));
+char         *VarConfigEntry           	PROTO((char *keyword, char *mode, int entry, void *ptr));
+
+int           init_error                PROTO((void));
+int           push_error                PROTO((char *line));
+int           print_error               PROTO((void));
+void          handle_interrupt      	PROTO((int));
+char        **command_completer     	PROTO((const char *, int, int));
+char         *command_generator     	PROTO((const char *text, int state));
+char        **completion_matches    	PROTO((char *, rl_compentry_func_t *));
+void          print_commands            PROTO((FILE *f));
+void          InitCommands              PROTO((void));
+
+/* command line parsing */
+char         *thisword              	PROTO((char *));
+char         *nextword              	PROTO((char *));
+char         *lastword              	PROTO((char *, char *));
+char         *thisvar               	PROTO((char *));
+char         *aftervar              	PROTO((char *));
+char         *lastvar               	PROTO((char *, char *));
+char         *thiscomm              	PROTO((char *));
+char         *nextcomm              	PROTO((char *));
+char         *opihi_append              PROTO((char *output, int *Noutput, char *start, char *stop));
+void          interpolate_slash         PROTO((char *line));
+
+/* macro functions (mapped to commands) */
+int 	      macro_create 		PROTO((int, char **)); 
+int 	      macro_delete 		PROTO((int, char **)); 
+int 	      macro_edit   		PROTO((int, char **));
+int 	      macro_exec   		PROTO((int, char **));
+int 	      macro_list_f 		PROTO((int, char **));  /* "macro_list" is a readline func */
+int 	      macro_read   		PROTO((int, char **));
+int 	      macro_write   		PROTO((int, char **));
+
+char 	     *memstr        		PROTO((char *m1, char *m2, int n));
+int  	      write_fmt     		PROTO((int fd, char *format, ...));
+char 	     *opihi_version 		PROTO(());
+char 	     *strip_version 		PROTO((char *input));
+
+/* gprint functions */
+void          gprintInit      		PROTO(());
+gpStream     *gprintGetStream 		PROTO((gpDest dest));
+void          gprintSetBuffer 		PROTO((gpDest dest));
+IOBuffer     *gprintGetBuffer 		PROTO((gpDest dest));
+void          gprintSetFileAllThreads   PROTO((gpDest dest, char *filename));
+void          gprintSetFileThisThread   PROTO((gpDest dest, char *filename));
+void          gprintSetFile   		PROTO((gpStream *stream, gpDest dest, char *filename));
+FILE         *gprintGetFile   		PROTO((gpDest dest));
+char         *gprintGetName   		PROTO((gpDest dest));
+int           gprint          		PROTO((gpDest dest, char *format, ...));
+int           gwrite          		PROTO((char *buffer, int size, int N, gpDest dest));
+
+/* socket functions */
+int InitServerSocket (SockAddress *Address);
+int WaitServerSocket (int InitSocket, SockAddress *Address);
+int GetClientSocket (char *hostname);
+int InitServerSocket_Named (char *hostname, SockAddress *Address);
+int DefineValidIP ();
+
+# endif
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/include/user.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/include/user.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/include/user.h	(revision 16632)
@@ -0,0 +1,260 @@
+int abszero         PROTO((int, char **));
+int applyfit        PROTO((int, char **));
+int applyfit2d      PROTO((int, char **));
+int badimages       PROTO((int, char **));
+int box             PROTO((int, char **));
+int calextract      PROTO((int, char **));
+int calmextract     PROTO((int, char **));
+int cals            PROTO((int, char **));
+int catlog          PROTO((int, char **));
+int ccd             PROTO((int, char **));
+int ccdextract      PROTO((int, char **));
+int center          PROTO((int, char **));
+int cgrid           PROTO((int, char **));
+int clear           PROTO((int, char **));
+int cmatch          PROTO((int, char **));
+int cmd             PROTO((int, char **));
+int cmdextract      PROTO((int, char **));
+int cmpread         PROTO((int, char **));
+int concat          PROTO((int, char **));
+int contour         PROTO((int, char **));
+int cplot           PROTO((int, char **));
+int create          PROTO((int, char **));
+int csystem         PROTO((int, char **));
+int ctimes          PROTO((int, char **));
+int cursor          PROTO((int, char **));
+int czplot          PROTO((int, char **));
+int datafile        PROTO((int, char **));
+int date            PROTO((int, char **));
+int ddmagextract    PROTO((int, char **));
+int ddmags          PROTO((int, char **));
+int delete          PROTO((int, char **));
+int device          PROTO((int, char **));
+int dmagaves        PROTO((int, char **));
+int dmagextract     PROTO((int, char **));
+int dmagmeas        PROTO((int, char **));
+int dmags           PROTO((int, char **));
+int dmt             PROTO((int, char **));
+int dumpmags        PROTO((int, char **));
+int elixir          PROTO((int, char **));
+int extract         PROTO((int, char **));
+int file            PROTO((int, char **));
+int fit             PROTO((int, char **));
+int fit2d           PROTO((int, char **));
+int gaussjordan     PROTO((int, char **));
+int gcat            PROTO((int, char **));
+int gimages         PROTO((int, char **));
+int grid            PROTO((int, char **));
+int gstar           PROTO((int, char **));
+int gtypes          PROTO((int, char **));
+int histogram       PROTO((int, char **));
+int images          PROTO((int, char **));
+int imbox           PROTO((int, char **));
+int imdata          PROTO((int, char **));
+int imdense         PROTO((int, char **)); 
+int imextract       PROTO((int, char **));
+int imlist          PROTO((int, char **));
+int imphot          PROTO((int, char **));
+int imrough         PROTO((int, char **));
+int imsearch        PROTO((int, char **));
+int imstats         PROTO((int, char **));
+int interpolate     PROTO((int, char **));
+int jpeg            PROTO((int, char **));
+int labels          PROTO((int, char **));
+int lcat            PROTO((int, char **));
+int lcurve          PROTO((int, char **));
+int limits          PROTO((int, char **));
+int list_buffers    PROTO((int, char **));
+int list_vectors    PROTO((int, char **));
+int mcreate         PROTO((int, char **));
+int mextract        PROTO((int, char **));
+int mget            PROTO((int, char **));
+int mset            PROTO((int, char **));
+int pcat            PROTO((int, char **));
+int photcodes       PROTO((int, char **));
+int photresid       PROTO((int, char **));
+int plot            PROTO((int, char **));
+int pmeasure        PROTO((int, char **));
+int precess         PROTO((int, char **));
+int print           PROTO((int, char **));
+int procks          PROTO((int, char **));
+int ps              PROTO((int, char **));
+int rd              PROTO((int, char **));
+int read_vectors    PROTO((int, char **));
+int region          PROTO((int, char **));
+int resid           PROTO((int, char **));
+int resize          PROTO((int, char **));
+int section         PROTO((int, char **));
+int set             PROTO((int, char **));
+int simage          PROTO((int, char **));
+int sort_vectors    PROTO((int, char **));
+int sprintf_opihi   PROTO((int, char **));
+int stats           PROTO((int, char **));
+int style           PROTO((int, char **));
+int subpix          PROTO((int, char **));
+int subraster       PROTO((int, char **));
+int subset          PROTO((int, char **));
+int textline        PROTO((int, char **));
+int tv              PROTO((int, char **));
+int uniq            PROTO((int, char **));
+int vectobuf        PROTO((int, char **));
+int vstat           PROTO((int, char **));
+int wd              PROTO((int, char **));
+int write_vectors   PROTO((int, char **));
+int zap             PROTO((int, char **));
+int zeropts         PROTO((int, char **));
+int zplot           PROTO((int, char **));
+
+static Command user[] = {  
+  {"abszero", 	   abszero,       "find filter zeropts"},
+  {"applyfit",     applyfit,      "apply fit to new vector"},
+  {"applyfit2d",   applyfit2d,    "apply 2-d fit to new vector"},
+  {"badimages",    badimages,     "look for images with anomalous astrometry"},
+  {"badimages",    badimages,     "look for images with anomalous astrometry"},
+  {"box",     	   box,           "draw a box on the plot"},
+  {"calextract",   calextract,    "extract dmags"},
+  {"calextract",   calextract,    "extract dmags"},
+  {"calmextract",  calmextract,   "extract dmags"},
+  {"cals",    	   cals,          "plot calibration data"},
+  {"catalog", 	   catlog,        "plot catalog stars"},
+  {"catalog", 	   catlog,        "plot catalog stars"},
+  {"ccd",     	   ccd,           "plot color-color diagram"},
+  {"ccd",     	   ccd,           "plot color-color diagram"},
+  {"ccdextract",   ccdextract,    "extract star coords from color-color diagram"},
+  {"center",       center,        "center image on coords"},
+  {"center",       center,        "center image on coords"},
+  {"cgrid",   	   cgrid,         "plot sky coordinate grid"},
+  {"cgrid",   	   cgrid,         "plot sky coordinate grid"},
+  {"clear",   	   clear,         "erase plot"},
+  {"cmatch",  	   cmatch,        "match two catalogs"},
+  {"cmatch",  	   cmatch,        "match two catalogs"},
+  {"cmd",     	   cmd,           "plot cmd of stars in current region"},
+  {"cmd",     	   cmd,           "plot cmd of stars in current region"},
+  {"cmdextract",   cmdextract,    "extract stars based on cmd regions"},
+  {"cmpread",      cmpread,       "read data from cmp format files"},
+  {"cmpread",      cmpread,       "read data from cmp format files"},
+  {"concat",  	   concat,        "reduce vector dimension"},
+  {"contour", 	   contour,       "create contour from image"},
+  {"cplot",   	   cplot,         "plot vectors in sky coordinates"},
+  {"cplot",   	   cplot,         "plot vectors in sky coordinates"},
+  {"create",  	   create,        "create a new vector"},
+  {"csystem", 	   csystem,       "convert between coordinate systems"},
+  {"csystem", 	   csystem,       "convert between coordinate systems"},
+  {"ctimes",  	   ctimes,        "convert between time formats"},
+  {"ctimes",  	   ctimes,        "convert between time formats"},
+  {"cursor",  	   cursor,        "get coords from cursor"},
+  {"czplot",  	   czplot,        "plot scaled vectors in sky coordinates"},
+  {"czplot",  	   czplot,        "plot scaled vectors in sky coordinates"},
+  {"datafile",     datafile,      "define file to read vectors"},
+  {"date",    	   date,          "get current date"},
+  {"ddmagextr",    ddmagextract,  "plot magnitude differences"},
+  {"ddmags",       ddmags,        "plot magnitude differences"},
+  {"ddmags",       ddmags,        "plot magnitude differences"},
+  {"delete",  	   delete,        "delete vectors or matrices"},
+  {"device",  	   device,        "set / get current graphics device"},
+  {"dmagaves",     dmagaves,      "plot differential magnitudes between filters"},
+  {"dmagextract",  dmagextract,   "extract stars based on differential magnitudes between filters"},
+  {"dmagmeas",     dmagmeas,      "plot differential magnitudes between filters"},
+  {"dmags",   	   dmags,         "plot differential magnitudes between filters"},
+  {"dmags",   	   dmags,         "plot differential magnitudes between filters"},
+  {"dmt",          dmt,           "plot mag scatter"},
+  {"dmt",          dmt,           "plot mag scatter"},
+  {"dumpmags",     dumpmags,      "custom dB dumping thingy"},
+  {"dumpmags",     dumpmags,      "custom dB dumping thingy"},
+  {"elixir",       elixir,        "get status info from elixir"},
+  {"elixir",       elixir,        "get status info from elixir"},
+  {"extract", 	   extract,       "extract vectors from catalogs"},
+  {"file",    	   file,          "test for a file"},
+  {"fit",     	   fit,           "fit polynomial to vector pair"},
+  {"fit2d",        fit2d,         "fit 2-d polynomial to vector triplet"},
+  {"gaussj",  	   gaussjordan,   "solve Ax = B (N-D)"},
+  {"gcat",         gcat,          "get catalog at location"},
+  {"gcat",         gcat,          "get catalog at location"},
+  {"gimages",      gimages,       "get images at location"},
+  {"gimages",      gimages,       "get images at location"},
+  {"grid",    	   grid,          "plot cartesian grid"},
+  {"gstar",   	   gstar,         "get star statistics"},
+  {"gstar",   	   gstar,         "get star statistics"},
+  {"gtypes",       gtypes,        "get type fractions"},
+  {"gtypes",       gtypes,        "get type fractions"},
+  {"histogram",    histogram,     "generate histogram from vector"},
+  {"images",  	   images,        "plot image boxes"},
+  {"images",  	   images,        "plot image boxes"},
+  {"imbox",   	   imbox,         "plot expected image box"},
+  {"imbox",   	   imbox,         "plot expected image box"},
+  {"imdata",  	   imdata,        "extract data for specific images"},
+  {"imdata",  	   imdata,        "extract data for specific images"},
+  {"imdense", 	   imdense,       "image density plot"},
+  {"imdense", 	   imdense,       "image density plot"},
+  {"imextract",    imextract,     "extract vectors from catalogs"},
+  {"imextract",    imextract,     "extract vectors from catalogs"},
+  {"imlist",  	   imlist,        "list image info"},
+  {"imlist",  	   imlist,        "list image info"},
+  {"imphot",  	   imphot,        "image photometry info"},
+  {"imphot",  	   imphot,        "image photometry info"},
+  {"imrough",      imrough,       "get info from imruf database"},
+  {"imrough",      imrough,       "get info from imruf database"},
+  {"imsearch",     imsearch,      "get info from imreg database"},
+  {"imsearch",     imsearch,      "get info from imreg database"},
+  {"imstats", 	   imstats,       "plot image statistics"},
+  {"imstats", 	   imstats,       "plot image statistics"},
+  {"interpolate",  interpolate,   "interpolate between vector pairs"},
+  {"jpeg",         jpeg,          "write text line on graph"},
+  {"labels",  	   labels,        "define labels for plot"},
+  {"lcat",    	   lcat,          "list catalogs in region"},
+  {"lcat",    	   lcat,          "list catalogs in region"},
+  {"lcurve",  	   lcurve,        "plot lightcurve for a star"},
+  {"lcurve",  	   lcurve,        "plot lightcurve for a star"},
+  {"limits",  	   limits,        "define plot limits"},
+  {"buffers",      list_buffers,  "list the currently allocated buffers"},
+  {"vectors", 	   list_vectors,  "list vectors"},
+  {"local",  	   local,         "define local variables"},
+  {"mcreate", 	   mcreate,       "create a matrix"},
+  {"mextract",	   mextract,      "extract vectors from catalogs"},
+  {"mextract",	   mextract,      "extract vectors from catalogs"},
+  {"mget",    	   mget,          "extract a vector from a matrix"},
+  {"mset",    	   mset,          "insert a vector in a matrix"},
+  {"pcat",    	   pcat,          "plot catalog boundaries"},
+  {"pcat",    	   pcat,          "plot catalog boundaries"},
+  {"photcodes",    photcodes,     "list photometry codes"},
+  {"photcodes",    photcodes,     "list photometry codes"},
+  {"photresid",    photresid,     "plot photometry residuals"},
+  {"plot",    	   plot,          "plot a pair of vectors"},
+  {"pmeasure",	   pmeasure,      "plot individual measurements"},
+  {"pmeasure",	   pmeasure,      "plot individual measurements"},
+  {"precess", 	   precess,       "precess coordinates"},
+  {"precess", 	   precess,       "precess coordinates"},
+  {"print",   	   print,         "write vectors to file"},
+  {"print",   	   print,         "write vectors to file"},
+  {"procks",  	   procks,        "plot rocks"},
+  {"procks",  	   procks,        "plot rocks"},
+  {"ps",      	   ps,            "define labels for plot"},
+  {"rd",           rd,            "load fits image"},
+  {"read",         read_vectors,  "read vectors from datafile"},
+  {"region",  	   region,        "define sky region for plot"},
+  {"region",  	   region,        "define sky region for plot"},
+  {"resid",   	   resid,         "plot residuals"},
+  {"resize",  	   resize,        "set graphics/image window size"},
+  {"section", 	   section,       "define section of graph"},
+  {"set",     	   set,           "vector math"},
+  {"simage",  	   simage,        "plot stars in an image"},
+  {"simage",  	   simage,        "plot stars in an image"},
+  {"sort",    	   sort_vectors,  "sort list of vectors"},
+  {"sprintf", 	   sprintf_opihi, "formated print to variable"},
+  {"stats",   	   stats,         "give statistics on a portion of a buffer"},
+  {"style",   	   style,         "set the style for graph plots"},
+  {"subpix",  	   subpix,        "get subpixel positions"},
+  {"subpix",  	   subpix,        "get subpixel positions"},
+  {"subraster",    subraster,     "subraster of fits image"},
+  {"subset",  	   subset,        "expand vector dimension"},
+  {"textline",     textline,      "write text line on graph"},
+  {"tv",      	   tv,            "display an image on the Kii window"},
+  {"uniq",    	   uniq,          "create a uniq vector subset from a vector"},
+  {"vectobuf",     vectobuf,      "convert vector triplet to buffer"},
+  {"vstat",        vstat,         "get info from imreg database"},
+  {"wd",      	   wd,            "write an image to a file"},
+  {"write",   	   write_vectors, "write vectors to datafile"},
+  {"zap",     	   zap,           "delete pixels"},
+  {"zeropts", 	   zeropts,       "show filter zeropts"},
+  {"zplot",   	   zplot,         "plot x y with size scaled by z"},
+}; 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/Makefile	(revision 16632)
@@ -0,0 +1,60 @@
+default: libdata
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SDIR    =       $(HOME)/lib.data
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+# general numerical functions (libdata) #####################
+srcs = \
+$(SDIR)/book.$(ARCH).o                  \
+$(SDIR)/page.$(ARCH).o                  \
+$(SDIR)/fft.$(ARCH).o			\
+$(SDIR)/svdcmp.$(ARCH).o		\
+$(SDIR)/convert.$(ARCH).o		\
+$(SDIR)/bracket.$(ARCH).o		\
+$(SDIR)/spline.$(ARCH).o		\
+$(SDIR)/mrqmin.$(ARCH).o		\
+$(SDIR)/mrq2dmin.$(ARCH).o		\
+$(SDIR)/precess.$(ARCH).o		\
+$(SDIR)/starfuncs.$(ARCH).o		\
+$(SDIR)/gaussian.$(ARCH).o		\
+$(SDIR)/graphtools.$(ARCH).o            \
+$(SDIR)/queues.$(ARCH).o		\
+$(SDIR)/PlotVectors.$(ARCH).o		\
+$(SDIR)/open_kapa.$(ARCH).o             \
+$(SDIR)/style_args.$(ARCH).o
+
+#$(SDIR)/open_graph.$(ARCH).o            \
+#$(SDIR)/open_image.$(ARCH).o            \
+
+# dependancy rules for include files ########################
+incs = \
+$(INC)/opihi.h \
+$(INC)/external.h \
+$(INC)/shell.h \
+$(INC)/dvomath.h \
+$(INC)/convert.h \
+$(INC)/display.h 
+
+$(srcs): $(incs)
+
+$(LIB)/libdata.$(ARCH).a: $(srcs)
+$(LIB)/libdata.$(ARCH).$(DLLTYPE): $(srcs)
+
+$(DESTLIB)/libdata.a: $(LIB)/libdata.$(ARCH).a
+$(DESTLIB)/libdata.$(DLLTYPE): $(LIB)/libdata.$(ARCH).$(DLLTYPE)
+
+libdata: $(DESTLIB)/libdata.a $(DESTLIB)/libdata.$(DLLTYPE)
+
+uninstall:
+	rm -f $(DESTLIB)/libdata.a
+	rm -f $(DESTLIB)/libdata.$(DLLTYPE)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/PlotVectors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/PlotVectors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/PlotVectors.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "display.h"
+
+int PlotVectorPair (int kapa, int Npts, float *xValues, float *yValues, Graphdata *graphmode) {
+
+  KapaPrepPlot (kapa, Npts, graphmode);
+  KapaPlotVector (kapa, Npts, xValues, "x");
+  KapaPlotVector (kapa, Npts, yValues, "y");
+
+  return (TRUE);
+}
+
+int PlotVectorTriplet (int kapa, int Npts, float *xValues, float *yValues, float *zValues, Graphdata *graphmode) {
+
+  KapaPrepPlot   (kapa, Npts, graphmode);
+  KapaPlotVector (kapa, Npts, xValues, "x");
+  KapaPlotVector (kapa, Npts, yValues, "y");
+  KapaPlotVector (kapa, Npts, zValues, "z");
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/book.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/book.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/book.c	(revision 16632)
@@ -0,0 +1,127 @@
+# include "data.h"
+
+Book **books;   /* book to store the list of all books */
+int    Nbooks;   /* number of currently defined books */
+int    NBOOKS;   /* number of currently allocated books */
+
+void InitBooks () {
+  Nbooks = 0;
+  NBOOKS = 16;
+  ALLOCATE (books, Book *, NBOOKS); 
+}
+
+void FreeBooks () {
+
+  int i;
+
+  for (i = 0; i < Nbooks; i++) {
+    FreeBook (books[i]);
+  }
+  free (books);
+}
+
+void InitBook (Book *book, char *name) {
+
+    book[0].name = strcreate (name);
+
+    book[0].Npages = 0;
+    book[0].NPAGES = 16;
+    ALLOCATE (book[0].pages, Page *, book[0].NPAGES);
+    ALLOCATE (book[0].pageIDs, char *, book[0].NPAGES);
+    // ALLOCATE (book[0].index, int, book[0].NPAGES);
+}
+
+void FreeBook (Book *book) {
+
+    int i;
+
+    free (book[0].name);
+    for (i = 0; i < book[0].Npages; i++) {
+	FreePage (book[0].pages[i]);
+	free (book[0].pageIDs[i]);
+    }
+    free (book[0].pages);
+    free (book[0].pageIDs);
+    // free (book[0].index);
+    free (book);
+}
+
+/* return the given book */
+Book *GetBook (int where) {
+
+  if (where < 0) where += Nbooks;
+  if (where < 0) return NULL;
+  if (where >= Nbooks) return NULL;
+  return (books[where]);
+}
+
+/* return the given book */
+Book *FindBook (char *name) {
+
+  int i;
+
+  for (i = 0; i < Nbooks; i++) {
+    if (!strcmp (books[i][0].name, name)) {
+      return (books[i]);
+    }
+  }
+  return (NULL);
+}
+
+/* make a new named book */
+Book *CreateBook (char *name) {
+
+  int N;
+  Book *book;
+
+  book = FindBook (name);
+  if (book != NULL) return (book);
+
+  N = Nbooks;
+  Nbooks ++;
+  CHECK_REALLOCATE (books, Book *, NBOOKS, Nbooks, 16);
+  ALLOCATE (book, Book, 1);
+  InitBook (book, name);
+  books[N] = book;
+  return (book);
+}
+
+/* delete a book */
+int DeleteBook (Book *book) {
+
+  int i, N, NBOOKS_2;
+
+  /* find book in book list */
+  N = -1;
+  for (i = 0; i < Nbooks; i++) {
+    if (books[i] == book) {
+      N = i;
+      break;
+    }
+  }
+  if (N == -1) return (FALSE);
+
+  for (i = N; i < Nbooks - 1; i++) {
+    books[i] = books[i + 1];
+  }
+  Nbooks --;
+  NBOOKS_2 = MAX (16, NBOOKS / 2);
+  if (Nbooks < NBOOKS_2) {
+    NBOOKS = NBOOKS_2;
+    REALLOCATE (books, Book *, NBOOKS);
+  }
+
+  FreeBook (book);
+  return (TRUE);
+}
+
+/* list known books */
+void ListBooks () {
+
+  int i;
+
+  for (i = 0; i < Nbooks; i++) {
+    gprint (GP_ERR, "%-15s %3d\n", books[i][0].name, books[i][0].Npages);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/bracket.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/bracket.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/bracket.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "data.h"
+
+/* fast operation to find an entry just below (0) or above (1) value */
+/* input list must be sorted */
+int bracket (double *list, int Nlist, int mode, double value) {
+
+  int Nlo, Nhi, N;
+
+  if (mode == 0) {
+    Nlo = 0; Nhi = Nlist;
+    while (Nhi - Nlo > 10) {
+      N = 0.5*(Nlo + Nhi);
+      if (list[N] < value) {
+	Nlo = N;
+      } else {
+	Nhi = N + 1;
+      }
+    }
+    return (Nlo);
+  }
+  if (mode == 1) {
+    Nlo = 0; Nhi = Nlist;
+    while (Nhi - Nlo > 10) {
+      N = 0.5*(Nlo + Nhi);
+      if (list[N] > value) {
+	Nhi = N;
+      } else {
+	Nlo = N - 1;
+      }
+    }
+    return (Nhi);
+  }
+  return (0);
+}
+
+int ibracket (int *list, int Nlist, int mode, double value) {
+
+  int Nlo, Nhi, N;
+
+  if (mode == 0) {
+    Nlo = 0; Nhi = Nlist;
+    while (Nhi - Nlo > 10) {
+      N = 0.5*(Nlo + Nhi);
+      if (list[N] < value) {
+	Nlo = N;
+      } else {
+	Nhi = N + 1;
+      }
+    }
+    return (Nlo);
+  }
+  if (mode == 1) {
+    Nlo = 0; Nhi = Nlist;
+    while (Nhi - Nlo > 10) {
+      N = 0.5*(Nlo + Nhi);
+      if (list[N] > value) {
+	Nhi = N;
+      } else {
+	Nlo = N - 1;
+      }
+    }
+    return (Nhi);
+  }
+  return (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/convert.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/convert.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/convert.c	(revision 16632)
@@ -0,0 +1,295 @@
+# include "convert.h"
+# define _XOPEN_SOURCE /* glibc2 (strptime) needs this */
+# include <time.h>
+
+/** additional time / coordinate conversions not supplied by libohana **/
+
+int hh_hms (double hh, int *hr, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh *= flag;
+  hh = 24.0*(hh/24.0 - (int)(hh/24.0));
+  *sc = 60.0*(60.0*hh - (int)(60.0*hh));
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+  return (TRUE);
+}
+ 
+int dd_dms (double dd, int *dg, int *mn, double *sc) {
+
+  int flag;
+
+  flag = SIGN(dd);
+  dd = fabs (dd);
+  *dg = (int) dd;
+  *mn = (int) 60*(dd - *dg);
+  *sc = 3600.0*(dd - *dg - *mn/60.0);
+  if (*sc > 59.99) {
+    *sc = 0;
+    *mn += 1.0;
+  }
+  *dg *= flag;
+  return (TRUE);
+}
+ 
+int hms_format (char *line, double value) {
+
+  int hr, mn;
+  double sc;
+
+  hh_hms (value, &hr, &mn, &sc);
+  hr = (int) value;
+  if (isnan (value))
+    sprintf (line, "xx:xx:xx.xx");
+  else {
+    if (value < 0) {
+      sprintf (line, "-%02d:%02d:%05.2f", abs(hr), mn, sc);
+    } else {
+      sprintf (line, "%02d:%02d:%05.2f", hr, mn, sc);
+    }
+  }      
+  return (TRUE);
+}
+
+int dms_format (char *line, double value) {
+
+  int dg, mn;
+  double sc;
+
+  dd_dms (value, &dg, &mn, &sc);
+  if (value < 0) {
+    sprintf (line, "-%02d:%02d:%05.2f", abs(dg), mn, sc);
+  } else {
+    sprintf (line, "%02d:%02d:%05.2f", dg, mn, sc);
+  }
+  return (TRUE);
+}
+
+/***** convert 00:00:00 or 00:00 to 0 - 86400 ****/
+int hms_to_sec (char *string, time_t *second) {
+  
+  char *p;
+  struct tm time;
+
+  p = strptime (string, "%H:%M:%S", &time);
+  if (p != NULL) goto valid;
+
+  p = strptime (string, "%H:%M", &time);
+  if (p != NULL) goto valid;
+
+  return (FALSE);
+    
+valid:
+  if (*p) return (FALSE);
+  *second = time.tm_hour*3600 + time.tm_min*60 + time.tm_sec;
+  return (TRUE);
+}
+
+/***** convert Mon[@00:00:00] or 00:00 to 0 - 86400*7 ****/
+int day_to_sec (char *string, time_t *second) {
+  
+  char *p;
+  struct tm time;
+
+  bzero (&time, sizeof(time));
+  p = strptime (string, "%A@%H:%M:%S", &time);
+  if (p != NULL) goto valid;
+
+  p = strptime (string, "%A@%H:%M", &time);
+  if (p != NULL) goto valid;
+
+  p = strptime (string, "%A@%H", &time);
+  if (p != NULL) goto valid;
+
+  p = strptime (string, "%A", &time);
+  if (p != NULL) goto valid;
+
+  return (FALSE);
+
+valid:
+  if (*p) return (FALSE);
+  *second = time.tm_wday*86400 + time.tm_hour*3600 + time.tm_min*60 + time.tm_sec;
+  return (TRUE);
+}
+
+/***** convert seconds to HH:MM:SS ****/
+char *ohana_sec_to_hms (time_t second) {
+  
+  struct tm *gmt;
+  char *line;
+
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+}
+
+/***** convert seconds to Day@HH:MM:SS ****/
+char *ohana_sec_to_day (time_t second) {
+  
+  struct tm *gmt;
+  char *line;
+
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  switch (gmt[0].tm_wday) {
+    case 0:
+      sprintf (line, "Sun@%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+      break;
+    case 1:
+      sprintf (line, "Mon@%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+      break;
+    case 2:
+      sprintf (line, "Tue@%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+      break;
+    case 3:
+      sprintf (line, "Wed@%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+      break;
+    case 4:
+      sprintf (line, "Thu@%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+      break;
+    case 5:
+      sprintf (line, "Fri@%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+      break;
+    case 6:
+      sprintf (line, "Sat@%02d:%02d:%02d", gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+      break;
+  }
+  return (line);
+}
+
+int hh_hm (double hh, int *hr, double *mn) {
+
+  int flag;
+
+  flag = SIGN(hh);
+  hh = fabs (hh);
+
+  *mn = 60.0*(hh - (int)hh);
+  *hr = (int) hh;
+  *hr *= flag;
+  return (TRUE);
+}
+
+char *meade_deg_to_str (double deg) {
+
+  int hr;
+  double mn;
+  char *line;
+
+  ALLOCATE (line, char, 16);
+
+  hh_hm (deg, &hr, &mn);
+
+  sprintf (line, "%03d:%04.1f", abs(hr), mn);
+  return (line);
+}
+
+char *meade_ra_to_str (double deg) {
+
+  int hr;
+  double mn;
+  char *line;
+
+  ALLOCATE (line, char, 16);
+
+  hh_hm (deg/15.0, &hr, &mn);
+
+  sprintf (line, "%02d:%04.1f", abs(hr), mn);
+  return (line);
+}
+
+char *meade_dec_to_str (double deg) {
+
+  int hr;
+  double mn;
+  char *line;
+
+  ALLOCATE (line, char, 16);
+
+  hh_hm (deg, &hr, &mn);
+
+  if (deg < 0) {
+    sprintf (line, "-%02d:%04.1f", abs(hr), mn);
+  } else {
+    sprintf (line, "+%02d:%04.1f", hr, mn);
+  }      
+  return (line);
+}
+
+/* convert UNIX time to a value referenced to the TimeReference in the given unit */
+double TimeValue (time_t time, time_t TimeReference, int TimeFormat) {
+
+  double value, dt;
+
+  dt = (time > TimeReference) ? (time - TimeReference) : -1 * (double)(TimeReference - time);
+  switch (TimeFormat) {
+  case TIME_JD:
+    value = time / 86400.0 + 2440587.5;
+    break;
+  case TIME_MJD:
+    value = time / 86400.0 + 40587.0;
+    break;
+  case TIME_DAYS:
+    value = dt / 86400.0;
+    break;
+  case TIME_HOURS:
+    value = dt / 3600.0;
+    break;
+  case TIME_MINUTES:
+    value = dt / 60.0;
+    break;
+  case TIME_SECONDS:
+  default:
+    value = dt;
+    break;
+  }
+  return (value);
+}
+  
+/* convert time value referenced to the TimeReference in the given unit to UNIX time */
+time_t TimeRef (double value, time_t TimeReference, int TimeFormat) {
+
+  int dt;
+  time_t time;
+
+  switch (TimeFormat) {
+  case TIME_JD:
+    time = (value -  2440587.5) * 86400.0;
+    return (time);
+    break;
+  case TIME_MJD:
+    time = (value -  40587.0) * 86400.0;
+    return (time);
+    break;
+  case TIME_DAYS:
+    dt = value * 86400.0;
+    break;
+  case TIME_HOURS:
+    dt = value * 3600.0;
+    break;
+  case TIME_MINUTES:
+    dt = value * 60.0;
+    break;
+  case TIME_SECONDS:
+  default:
+    dt = value;
+    break;
+  }
+
+  time = TimeReference + dt;
+  return (time);
+}
+
+/* times may be in forms as:
+ * 20040200450s (N seconds since 1970.0)
+ * 2440900.232j (julian date)
+ * 99/02/23,03:22:18 (date string)
+ * (separators may be anything except space, +, -)
+ * 99:02:15:12:23:30
+ * 99:02:15:12h23m30s
+ */
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/fft.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/fft.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/fft.c	(revision 16632)
@@ -0,0 +1,171 @@
+# include "data.h"
+
+// fft based on code by Douglas L. Jones (see note at EOF). modified for Ohana C style
+void fft1D (float *x, float *y, int n, int Nbit, int forward) {
+
+  int i,j,k,n1,n2;
+  float c,s,e,a,t1,t2;        
+  double factor;
+         
+  // bit-reverse
+  j = 0; 
+  n2 = n/2;
+  for (i = 1; i < n - 1; i++) {
+    n1 = n2;
+    while ( j >= n1 ) {
+      j -= n1;
+      n1 /= 2;
+    }
+    j += n1;
+               
+    if (i < j) {
+      t1 = x[i];
+      x[i] = x[j];
+      x[j] = t1;
+      t1 = y[i];
+      y[i] = y[j];
+      y[j] = t1;
+    }
+  }
+                                          
+  n1 = 0; /* FFT */
+  n2 = 1;
+                                             
+  if (forward) {
+    factor = +2.0*M_PI;
+  } else {
+    factor = -2.0*M_PI;
+  }
+
+  for (i=0; i < Nbit; i++) {
+    n1 = n2;
+    n2 = n2 + n2;
+    e = factor/n2;
+    a = 0.0;
+                                             
+    for (j=0; j < n1; j++) {
+      c = cos(a);
+      s = sin(a);
+      a = a + e;
+                                            
+      for (k=j; k < n; k=k+n2) {
+	t1 = c*x[k+n1] - s*y[k+n1];
+	t2 = s*x[k+n1] + c*y[k+n1];
+	x[k+n1] = x[k] - t1;
+	y[k+n1] = y[k] - t2;
+	x[k] = x[k] + t1;
+	y[k] = y[k] + t2;
+      }
+    }
+  }
+                                      
+  // re-normalize
+  for (i = 0; i < n; i++) {
+    x[i] /= n;
+    y[i] /= n;
+  }
+
+  return;
+}                          
+
+// This implementation uses the 1-D fft above for each of the vectors in each dimension.
+// This requires 2(Nx*Ny*...) mem copies, but the fft operations are likely to happen in
+// cache.
+int fftND (float *x, float *y, int Ndim, int *Nsize, int forward) {
+
+  int i, nIndex, minor, major, iDim;
+  int step, Nmajor, Nminor, Nmax, Ntotal;
+  int *Nbit;
+  float *tmpX, *tmpY;
+
+  ALLOCATE (Nbit, int, Ndim);
+
+  // find the longest axis and allocate storage for that length
+  Nmax = 0;
+  Ntotal = 1;
+  for (i = 0; i < Ndim; i++) {
+    Nmax = MAX(Nmax, Nsize[i]);
+    Ntotal *= Nsize[i];
+    if (!IsBinary (Nsize[i], &Nbit[i])) {
+      free (Nbit);
+      return (FALSE);
+    }
+  }
+  ALLOCATE (tmpX, float, Nmax);
+  ALLOCATE (tmpY, float, Nmax);
+  
+  step = 1;
+  Nminor = 1;
+  Nmajor = Ntotal;
+  for (iDim = 0; iDim < Ndim; iDim++) {
+    step *= Nsize[iDim];
+    Nmajor /= Nsize[iDim];
+
+    // we perform the FFT along all other dimensions 
+    for (major = 0; major < Nmajor; major++) {
+      for (minor = 0; minor < Nminor; minor++) {
+	// nIndex = minor + i*Nminor + major*step;
+	// extract the data values to the temp vector
+	nIndex = minor + major*step;
+	for (i = 0; i < Nsize[iDim]; i++) {
+	  tmpX[i] = x[nIndex];
+	  tmpY[i] = y[nIndex];
+	  nIndex += Nminor;
+	}
+
+	fft1D (tmpX, tmpY, Nsize[iDim], Nbit[iDim], forward);
+
+	// replace the result vectors
+	nIndex = minor + major*step;
+	for (i = 0; i < Nsize[iDim]; i++) {
+	  x[nIndex] = tmpX[i];
+	  y[nIndex] = tmpY[i];
+	  nIndex += Nminor;
+	}
+      }
+    }
+    Nminor *= Nsize[iDim];
+  }
+  free (tmpX);
+  free (tmpY);
+  return (TRUE);
+}
+
+// check that a number is binary (2^Nbit).  returns int(log_2(N)) in Nbit
+int IsBinary (int N, int *Nbit) {
+
+  int i, Nset;
+
+  if (Nbit != NULL) *Nbit = 0;
+  Nset = 0;
+  for (i = 0; i < 8*sizeof(int); i++) {
+    if (N & 0x01) {
+      Nset ++;
+      if (Nbit != NULL) *Nbit = i;
+    }
+    N >>= 1;
+  }
+  if (Nset > 1) return (FALSE);
+  return (TRUE);  
+}
+
+/**********************************************************/
+/* fft.c                                                  */
+/* (c) Douglas L. Jones                                   */
+/* University of Illinois at Urbana-Champaign             */
+/* January 19, 1992                                       */
+/*                                                        */
+/*   fft: in-place radix-2 DIT DFT of a complex input     */
+/*                                                        */
+/*   input:                                               */
+/* n: length of FFT: must be a power of two               */
+/* m: n = 2**m                                            */
+/*   input/output                                         */
+/* x: float array of length n with real part of data     */
+/* y: float array of length n with imag part of data     */
+/*                                                        */
+/*   Permission to copy and use this program is granted   */
+/*   under a Creative Commons "Attribution" license       */
+/*   http://creativecommons.org/licenses/by/1.0/          */
+/**********************************************************/
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/gaussian.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/gaussian.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/gaussian.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "data.h"
+
+static int Ngaussint = 0;
+static double *gaussint;
+
+extern double drand48();
+
+double gaussian (double x, double mean, double sigma) {
+
+  double f;
+
+  f = exp (-0.5 * SQ(x - mean) / SQ(sigma)) / sqrt(2 * M_PI * SQ(sigma));
+
+  return (f);
+
+}
+
+/* integrate a gaussian from -5 sigma to +5 sigma */
+void gauss_init (int Nbin) {
+ 
+  int i;
+  long A, B;
+  double val, x, dx, dx1, dx2, dx3, df;
+  double mean, sigma;
+ 
+  /* no need to generate this if it already exists */
+  if (Ngaussint == Nbin) return;
+
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+ 
+  Ngaussint = Nbin;
+  ALLOCATE (gaussint, double, Ngaussint + 1);
+
+  val = 0;
+  dx = 1.0 / Ngaussint;
+  dx1 = dx / 3.0;
+  dx2 = 2.0*dx/3.0;
+  dx3 = dx;
+  mean = 0.0;
+  sigma = 1.0;
+ 
+  for (i = 0, x = -7.0; (i < Ngaussint) && (x < 7.0); x += dx)  {
+    df = (3.0*gaussian(x    , mean, sigma) + 
+          9.0*gaussian(x+dx1, mean, sigma) +
+          9.0*gaussian(x+dx2, mean, sigma) + 
+          3.0*gaussian(x+dx3, mean, sigma)) * (dx1/8.0);
+    val += df;
+    if (val > (i + 0.5) / (double) Ngaussint) {
+      gaussint[i] = x + dx / 2.0;
+      i++;
+    }
+  }
+}
+
+double rnd_gauss (double mean, double sigma) {
+ 
+  int i;
+  double y;
+ 
+  y = drand48();
+  i = Ngaussint*y;
+  y = gaussint[i]*sigma + mean;
+ 
+  return (y);
+ 
+}
+ 
+double int_gauss (int i) {
+  double y;
+  y = gaussint[i];
+  return (y);
+}
+ 
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/graphtools.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/graphtools.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/graphtools.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "data.h"
+
+void SetLimits (Vector *xvec, Vector *yvec, Graphdata *graphmode) {
+
+  double maxX, minX, maxY, minY, range;
+  int i;
+
+  if (xvec != NULL) {
+    maxX = minX = xvec[0].elements[0];
+    for (i = 1; i < xvec[0].Nelements; i++) {
+      if (!finite(xvec[0].elements[i])) continue;
+      maxX = MAX (maxX, xvec[0].elements[i]);
+      minX = MIN (minX, xvec[0].elements[i]);
+    }
+    range = maxX - minX;
+    if (range == 0) range = 0.001 * maxX;
+    if (range == 0) range = 0.001;
+    graphmode[0].xmin = minX - 0.05*range;
+    graphmode[0].xmax = maxX + 0.05*range;
+  }
+
+  if (yvec != NULL) {
+    maxY = minY = yvec[0].elements[0];
+    for (i = 1; i < yvec[0].Nelements; i++) {
+      if (!finite(yvec[0].elements[i])) continue;
+      maxY = MAX (maxY, yvec[0].elements[i]);
+      minY = MIN (minY, yvec[0].elements[i]);
+    }
+    range = maxY - minY;
+    if (range == 0) range = 0.0011 * maxY;
+    if (range == 0) range = 0.0011;
+    graphmode[0].ymin = minY - 0.05*range;
+    graphmode[0].ymax = maxY + 0.05*range;
+  }
+  SetGraph (graphmode);
+
+  set_variable ("XMIN", graphmode[0].xmin);
+  set_variable ("XMAX", graphmode[0].xmax);
+  set_variable ("YMIN", graphmode[0].ymin);
+  set_variable ("YMAX", graphmode[0].ymax);
+}
+
+void SetLimitsRaw (float *xvec, float *yvec, int Nelements, Graphdata *graphmode) {
+
+  double maxX, minX, maxY, minY, range;
+  int i;
+
+  if (xvec != NULL) {
+    maxX = minX = xvec[0];
+    for (i = 1; i < Nelements; i++) {
+      if (!finite(xvec[i])) continue;
+      maxX = MAX (maxX, xvec[i]);
+      minX = MIN (minX, xvec[i]);
+    }
+    range = maxX - minX;
+    if (range == 0) range = 0.001 * maxX;
+    if (range == 0) range = 0.001;
+    graphmode[0].xmin = minX - 0.05*range;
+    graphmode[0].xmax = maxX + 0.05*range;
+  }
+
+  if (yvec != NULL) {
+    maxY = minY = yvec[0];
+    for (i = 1; i < Nelements; i++) {
+      if (!finite(yvec[i])) continue;
+      maxY = MAX (maxY, yvec[i]);
+      minY = MIN (minY, yvec[i]);
+    }
+    range = maxY - minY;
+    if (range == 0) range = 0.0011 * maxY;
+    if (range == 0) range = 0.0011;
+    graphmode[0].ymin = minY - 0.05*range;
+    graphmode[0].ymax = maxY + 0.05*range;
+  }
+  SetGraph (graphmode);
+
+  set_variable ("XMIN", graphmode[0].xmin);
+  set_variable ("XMAX", graphmode[0].xmax);
+  set_variable ("YMIN", graphmode[0].ymin);
+  set_variable ("YMAX", graphmode[0].ymax);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/hashes.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/hashes.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/hashes.c	(revision 16632)
@@ -0,0 +1,49 @@
+
+/* I need a structure which will be appropriate to carry the psMetadataConfig data.  the main 
+   requirements are:
+
+   - name-based components
+   - string-indexing on columns
+
+   basic elements:
+
+   container->item->element->value
+
+   element: name, value (type?)
+   item->name, Nelement, elements
+   container->items, Nitems
+
+   user interactions
+
+   blob list
+   blob listitems (blob)
+   blob create (blob)
+   blob delete (blob)
+   blob listkeys (blob.item)
+
+   blob getvalue (blob.item.key) -var word
+   blob setvalue (blob.item.key) value
+
+   blob getitem (blob.item)  : list all key/value pairs
+   blob newitem (blob.item)
+   blob delitem (blob.item)
+   blob popitem (blob)
+
+   blob readqueue (queue)    : convert queue in MDC format to blob
+   *** this needs to be able to match by keys against existing items
+   
+   need equivalents to:
+   queuepush -uniq key
+   queuepop -
+   queuesize
+   
+
+   items should be sorted by name so we can lookup an item quickly
+
+
+
+   other related opihi data concepts
+   
+   $a = @function (output of function set to value?)
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/mrq2dmin.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/mrq2dmin.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/mrq2dmin.c	(revision 16632)
@@ -0,0 +1,210 @@
+# include "data.h"  /* only needed for the ALLOCATE def */
+
+/* need to pass in a function of the form:
+   funcs (x, t, a, Npar, dy/da) 
+   returns y (x,t) for Npar parameters a along with dy/da at (x,t)
+   dy carries 1/sig^2 
+*/
+
+# define VERY_VERBOSE 0
+
+static float **alpha, **talpha;
+static float **beta, **tbeta;
+static float *partry, *dyda;
+static float ochisq, lambda;
+
+static float *parmin = NULL;
+static float *parmax = NULL;
+
+float mrq2dcof (float *x, float *t, float *y, float *dy, int Npts, 
+	      float *par, int Npar, float **ta, float **tb, 
+	      float (funcs)(float, float, float *, int, float *)) {
+
+  int k, j, i;
+  float ydiff, wt, chisq;
+
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k <= j; k++) ta[j][k] = 0.0;
+    tb[j][0] = 0.0;
+  }
+
+  chisq = 0.0;
+  for (i = 0; i < Npts; i++) {
+
+    ydiff = funcs (x[i], t[i], par, Npar, dyda) - y[i];
+    chisq += SQ(ydiff) * dy[i];
+    
+    for (j = 0; j < Npar; j++) {
+      wt = dyda[j] * dy[i];
+      for (k = 0; k <= j; k++) ta[j][k] += wt * dyda[k];
+      tb[j][0] += wt * ydiff;
+    }
+  }
+
+  for (j = 1; j < Npar; j++)
+    for (k = 0; k < j; k++)
+      ta[k][j] = ta[j][k];
+      
+# if (VERY_VERBOSE)
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k < Npar; k++) {
+      gprint (GP_ERR, "%9.3e  ", ta[j][k]);
+    }
+    gprint (GP_ERR, "    :   %9.3e  ", tb[j][0]);
+    gprint (GP_ERR, "\n");
+  }
+# endif
+
+  return (chisq);
+
+}
+
+float mrq2dchi (float *x, float *t, float *y, float *dy, int Npts, 
+		float *par, int Npar, 
+		float (funcs)(float, float, float *, int, float *)) {
+
+  int i;
+  float ydiff, chisq;
+
+  chisq = 0.0;
+  for (i = 0; i < Npts; i++) {
+    ydiff = funcs (x[i], t[i], par, Npar, dyda) - y[i];
+    chisq += SQ(ydiff) * dy[i];
+  }
+  return (chisq);
+}
+
+float mrq2dmin (float *x, float *t, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float, float *, int, float *), int VERBOSE) {
+
+  int j, k;
+  float chisq;
+
+  /* set up test matrixes for this run */
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k < Npar; k++) talpha[j][k] = alpha[j][k];
+    talpha[j][j] = alpha[j][j] * (1.0 + lambda);
+    tbeta[j][0] = beta[j][0];
+  }
+
+  /* keep this test in here? */
+  if (!fgaussjordan (talpha, tbeta, Npar, 1)) {
+    lambda *= 10.0;
+    return (ochisq);
+  }
+
+  for (j = 0; j < Npar; j++) {
+    partry[j] = par[j] - tbeta[j][0];
+    /*
+    if (parmin != NULL) partry[j] = MAX (parmin[j], partry[j]);
+    if (parmax != NULL) partry[j] = MIN (parmax[j], partry[j]);
+    */
+  }
+
+  chisq = mrq2dcof (x, t, y, dy, Npts, partry, Npar, talpha, tbeta, funcs);
+  if (VERBOSE) { 
+    gprint (GP_ERR, "chisq: %f  ", chisq);
+    gprint (GP_ERR, "lambda: %f  ", lambda);
+    for (j = 0; j < Npar; j++) {
+      gprint (GP_ERR, "%f ", partry[j]);
+    }
+    gprint (GP_ERR, "\n");
+  }
+
+  /* if good, save temp values */
+  if (chisq < ochisq) {
+    lambda *= 0.1;
+    ochisq = chisq;
+    for (j = 0; j < Npar; j++) {
+      for (k = 0; k < Npar; k++) alpha[j][k] = talpha[j][k];
+      beta[j][0] = tbeta[j][0];
+      par[j] = partry[j];
+    }
+  } else {
+    lambda *= 10.0;
+    chisq = ochisq;
+  }
+
+  return (chisq);
+
+}
+
+int mrq2dlimits (float *pmin, float *pmax, int Npar) {
+
+  int i;
+
+  ALLOCATE (parmin, float, Npar);
+  ALLOCATE (parmax, float, Npar);
+  for (i = 0; i < Npar; i++) {
+    parmin[i] = pmin[i];
+    parmax[i] = pmax[i];
+  }
+  return (TRUE);
+}
+
+float mrq2dinit (float *x, float *t, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float, float *, int, float *), int VERBOSE) {
+
+  int i;
+
+  ALLOCATE (dyda, float, Npar);
+  ALLOCATE (partry, float, Npar);
+  ALLOCATE (alpha, float *, Npar);
+  ALLOCATE (beta, float *, Npar);
+  ALLOCATE (talpha, float *, Npar);
+  ALLOCATE (tbeta, float *, Npar);
+  for (i = 0; i < Npar; i++) {
+    ALLOCATE (alpha[i], float, Npar);
+    ALLOCATE (beta[i], float, Npar);
+    ALLOCATE (talpha[i], float, Npar);
+    ALLOCATE (tbeta[i], float, Npar);
+  }
+
+  
+  lambda = 0.001;
+  
+  ochisq = mrq2dcof (x, t, y, dy, Npts, par, Npar, alpha, beta, funcs);
+  if (VERBOSE) {
+    gprint (GP_ERR, "chisq: %f  ", ochisq);
+    gprint (GP_ERR, "lambda: %f  ", lambda);
+    for (i = 0; i < Npar; i++) {
+      gprint (GP_ERR, "%f ", par[i]);
+    }
+    gprint (GP_ERR, "\n");
+  }
+
+  return (ochisq);
+
+}
+
+/* don't invoke this in the middle of a run, only near the end */ 
+float **mrq2dcovar (int Npar) {
+
+  fgaussjordan (alpha, beta, Npar, 1);
+  return (alpha);
+
+} 
+
+void mrq2dfree (int Npar) {
+
+  int i;
+
+  for (i = 0; i < Npar; i++) {
+    free (alpha[i]);
+    free (talpha[i]);
+    free (beta[i]);
+    free (tbeta[i]);
+  }
+  free (alpha);
+  free (talpha);
+  free (beta);
+  free (tbeta);
+  free (partry);
+  free (dyda);
+
+  if (parmin != NULL) free (parmin);
+  if (parmax != NULL) free (parmax);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/mrqmin.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/mrqmin.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/mrqmin.c	(revision 16632)
@@ -0,0 +1,159 @@
+# include "data.h"  /* only needed for the ALLOCATE def */
+
+/* need to pass in a function of the form:
+   funcs (x, a, Npar, dyda) 
+   returns f (x) for Npar parameters a, also df/da at x 
+   dy carries 1/sig^2 
+*/
+
+static float **alpha, **talpha;
+static float **beta, **tbeta;
+static float *partry, *dyda;
+static float ochisq, lambda;
+
+float mrqcof (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, float **ta, float **tb, 
+	      float (funcs)(float, float *, int, float *)) {
+
+  int k, j, i;
+  float ydiff, wt, chisq;
+
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k <= j; k++) ta[j][k] = 0.0;
+    tb[j][0] = 0.0;
+  }
+
+  chisq = 0.0;
+  for (i = 0; i < Npts; i++) {
+
+    ydiff = funcs (x[i], par, Npar, dyda) - y[i];
+    chisq += SQ(ydiff) * dy[i];
+
+    for (j = 0; j < Npar; j++) {
+      wt = dyda[j] * dy[i];
+      for (k = 0; k <= j; k++) ta[j][k] += wt * dyda[k];
+      tb[j][0] += wt * ydiff;
+    }
+  }
+
+  for (j = 1; j < Npar; j++)
+    for (k = 0; k < j; k++) 
+      ta[k][j] = ta[j][k];
+
+  return (chisq);
+
+}
+
+float mrqmin (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float *, int, float *), int VERBOSE) {
+
+  int j, k;
+  float chisq;
+  float rho, dX, dL;
+
+  /* set up test matrixes for this run */
+  for (j = 0; j < Npar; j++) {
+    for (k = 0; k < Npar; k++) talpha[j][k] = alpha[j][k];
+    talpha[j][j] = alpha[j][j] * (1.0 + lambda);
+    tbeta[j][0] = beta[j][0];
+  }
+
+  fgaussjordan (talpha, tbeta, Npar, 1);
+
+  for (j = 0; j < Npar; j++) partry[j] = par[j] - tbeta[j][0];
+
+  /* get linear model prediction */
+  dL = 0;
+  for (j = 0; j < Npar; j++) {
+      dL += 0.5*lambda*SQ(tbeta[j][0]) + tbeta[j][0]*beta[j][0];
+  }
+
+  chisq = mrqcof (x, y, dy, Npts, partry, Npar, talpha, tbeta, funcs);
+  if (VERBOSE) { 
+    gprint (GP_ERR, "chisq: %f  ", chisq);
+    gprint (GP_ERR, "lambda: %f  ", lambda);
+    for (j = 0; j < Npar; j++) {
+      gprint (GP_ERR, "%f ", partry[j]);
+    }
+    gprint (GP_ERR, "\n");
+  }
+
+  /* compare linear model with actual */
+  dX = ochisq - chisq;
+  rho = dX / dL;
+
+  /* if good, save temp values */
+  if (rho > 0) {
+    lambda *= 0.1;
+    ochisq = chisq;
+    for (j = 0; j < Npar; j++) {
+      for (k = 0; k < Npar; k++) alpha[j][k] = talpha[j][k];
+      beta[j][0] = tbeta[j][0];
+      par[j] = partry[j];
+    }
+  } else {
+    lambda *= 10.0;
+    chisq = ochisq;
+  }
+
+  return (chisq);
+
+}
+
+float mrqinit (float *x, float *y, float *dy, int Npts, 
+	      float *par, int Npar, 
+	      float (funcs)(float, float *, int, float *), int VERBOSE) {
+
+  int i;
+
+  ALLOCATE (dyda, float, Npar);
+  ALLOCATE (partry, float, Npar);
+  ALLOCATE (alpha, float *, Npar);
+  ALLOCATE (beta, float *, Npar);
+  ALLOCATE (talpha, float *, Npar);
+  ALLOCATE (tbeta, float *, Npar);
+  for (i = 0; i < Npar; i++) {
+    ALLOCATE (alpha[i], float, Npar);
+    ALLOCATE (beta[i], float, Npar);
+    ALLOCATE (talpha[i], float, Npar);
+    ALLOCATE (tbeta[i], float, Npar);
+  }
+  
+  lambda = 0.01;
+  
+  ochisq = mrqcof (x, y, dy, Npts, par, Npar, alpha, beta, funcs);
+  if (VERBOSE) {
+    gprint (GP_ERR, "chisq: %f  ", ochisq);
+    gprint (GP_ERR, "lambda: %f  ", lambda);
+    for (i = 0; i < Npar; i++) {
+      gprint (GP_ERR, "%f ", par[i]);
+    }
+    gprint (GP_ERR, "\n");
+  }
+  return (ochisq);
+}
+
+/* don't invoke this in the middle of a run, only near the end */ 
+float **mrqcovar (int Npar) {
+  fgaussjordan (alpha, beta, Npar, 1);
+  return (alpha);
+} 
+
+void mrqfree (int Npar) {
+
+  int i;
+
+  for (i = 0; i < Npar; i++) {
+    free (alpha[i]);
+    free (talpha[i]);
+    free (beta[i]);
+    free (tbeta[i]);
+  }
+  free (alpha);
+  free (talpha);
+  free (beta);
+  free (tbeta);
+  free (partry);
+  free (dyda);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_graph.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_graph.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_graph.c	(revision 16632)
@@ -0,0 +1,176 @@
+# include "display.h"
+# include "shell.h"
+# define DEBUG 0
+
+/* we have space for several kapa windows */
+# define NXGRAPH 5
+
+static int       Active;
+static int       Xgraph[NXGRAPH];  
+static Graphdata graphdata[NXGRAPH];
+
+void QuitGraph () {
+
+  int i;
+  
+  for (i = 0; i < NXGRAPH; i++) {
+    KiiClose (Xgraph[i]);
+  }
+}
+
+void InitGraph () {
+
+  int i;
+
+  Active = 0;
+  for (i = 0; i < NXGRAPH; i++) {
+    Xgraph[i] = -1;
+
+    graphdata[i].xmin = graphdata[i].ymin = 0.0;
+    graphdata[i].xmax = graphdata[i].ymax = 1.0;
+    graphdata[i].style = graphdata[i].ptype = 0;
+    graphdata[i].ltype = graphdata[i].color = 0;
+    graphdata[i].etype = graphdata[i].ebar = 0;
+    graphdata[i].lweight = graphdata[i].size = 1.0;
+    
+    graphdata[i].coords.pc1_1 = graphdata[i].coords.pc2_2 = 1.0;
+    graphdata[i].coords.pc1_2 = graphdata[i].coords.pc2_1 = 0.0;
+    strcpy (graphdata[i].coords.ctype, "RA---LIN");
+    graphdata[i].coords.crval1 = 0.0;
+    graphdata[i].coords.crval2 = 0.0;
+    graphdata[i].coords.crpix1 = 0.0;
+    graphdata[i].coords.crpix2 = 0.0;
+    graphdata[i].coords.cdelt1 = graphdata[i].coords.cdelt2 = 1.0;
+    graphdata[i].flipeast = TRUE;
+    graphdata[i].flipnorth = FALSE;
+    strcpy (graphdata[i].axis, "2222");
+    strcpy (graphdata[i].ticks, "2222");
+    strcpy (graphdata[i].labels, "2222");
+  }
+}
+
+/* set SIGPIPE to this function to close cleanly */ 
+void XGraphDead (int input) {
+  signal (SIGPIPE, XGraphDead);
+  gprint (GP_ERR, "kapa is dead, must restart\n");
+  Xgraph[Active] = -1;
+}
+
+/** start socketed connection */
+int open_graph (int N) {
+
+  int fd;
+  char *kapa_exec, name[16];
+  
+  kapa_exec = get_variable ("KAPA");
+  if (kapa_exec == (char *) NULL) {
+    gprint (GP_ERR, "variable KAPA not found\n");
+    return (FALSE);
+  }
+
+  snprintf (name, 16, "[%d]", N);
+  fd = KiiOpen (kapa_exec, name);
+  free (kapa_exec);
+
+  if (fd < 0) {
+    gprint (GP_ERR, "error starting kapa\n");
+    return (FALSE);
+  } 
+
+  Xgraph[N] = fd;
+  return (TRUE);
+}
+
+int close_graph (int N) {
+
+  if (N <  0) return (FALSE);
+  if (N >= NXGRAPH) return (FALSE);
+
+  KiiClose (Xgraph[N]); 
+  Xgraph[N] = -1;
+  return (TRUE);
+}
+
+/* return pointers for current Xgraph, set if desired, test, open if needed */
+int GetGraph (Graphdata *data, int *socket, int *N) {
+
+  int i, n;
+  char buffer[70];
+
+  SetImageDevice (FALSE);
+  if (N == (int *) NULL) {
+    n = Active;
+  } else {
+    if (*N >= NXGRAPH) {
+      gprint (GP_ERR, "invalid Xgraph window %d\n", *N); 
+      return (FALSE);
+    }
+    if (*N < 0) {
+      *N = n = Active;
+    } else {
+      Active = n = *N;
+    }
+  }
+  
+  /* test Xgraph[0], flush junk from pipe */
+  signal (SIGPIPE, XGraphDead);
+  fcntl (Xgraph[n], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[n], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[n], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[n] < 1) {
+    if (!open_graph(n)) {
+      return (FALSE);
+    }
+  }
+
+  if (data != (Graphdata *) NULL) *data  = graphdata[n];
+  if (socket != (int *) NULL) *socket = Xgraph[n];
+
+  return (TRUE);
+
+}
+
+/* return pointers for given Xgraph, don't set or open */
+int GetGraphData (Graphdata *data, int *sock, int *N) {
+
+  int n;
+
+  if (N == (int *) NULL) {
+    n = Active;
+  } else {
+    if (*N >= NXGRAPH) {
+      gprint (GP_ERR, "invalid Xgraph window %d\n", *N); 
+      return (FALSE);
+    }
+    if (*N < 0) {
+      n = Active;
+    } else {
+      n = *N;
+    }
+  }
+  
+  if (data != (Graphdata *) NULL) *data  = graphdata[n];
+  if (sock != (int *) NULL) *sock = Xgraph[n];
+
+  return (TRUE);
+
+}
+
+/* assign given values to current Xgraph */
+void SetGraph (Graphdata data) {
+  graphdata[Active] = data;
+}
+
+/** internal tracking of current active device type **/
+
+static int       IsImage = FALSE;
+
+int GetCurrentDevice () {
+  return (IsImage);
+}
+
+void SetImageDevice (int state) {
+  IsImage = state;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_image.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_image.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_image.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include "display.h"
+# include "shell.h"
+# define DEBUG 0
+
+/* we have space for several kii windows */
+# define NXIMAGE 5
+
+static int       Active;
+static int       Ximage[NXIMAGE];  
+static char      Ximbuffer[NXIMAGE][512];
+static double    Xzero[NXIMAGE];
+static double    Xrange[NXIMAGE];
+
+void QuitImage () {
+
+  int i;
+  
+  for (i = 0; i < NXIMAGE; i++) {
+    KiiClose (Ximage[i]);
+  }
+}
+
+void InitImage () {
+
+  int i;
+
+  Active = 0;
+  for (i = 0; i < NXIMAGE; i++) {
+    Ximage[i] = -1;
+    Xzero[i] = 0;
+    Xrange[i] = 1024;
+    strcpy (Ximbuffer[i], "none");
+  }
+}
+
+/* set SIGPIPE to this function to close cleanly */ 
+void XImageDead (int input) {
+  signal (SIGPIPE, XImageDead);
+  gprint (GP_ERR, "kii is dead, must restart\n");
+  Ximage[Active] = -1;
+}
+
+/** start socketed connection */
+int open_image (int N) {
+
+  int fd;
+  char *kii_exec, name[16];
+
+  kii_exec = get_variable ("KII");
+  if (kii_exec == (char *) NULL) {
+    gprint (GP_ERR, "variable KII not found\n");
+    return (FALSE);
+  }
+
+  snprintf (name, 16, "[%d]", N);
+  fd = KiiOpen (kii_exec, name);
+  free (kii_exec);
+
+  if (fd < 0) {
+    gprint (GP_ERR, "error starting kii\n");
+    return (FALSE);
+  } 
+
+  Ximage[N] = fd;
+  return (TRUE);
+}
+
+int close_image (int N) {
+
+  if (N <  0) return (FALSE);
+  if (N >= NXIMAGE) return (FALSE);
+
+  KiiClose (Ximage[N]); 
+  Ximage[N] = -1;
+  return (TRUE);
+}
+
+/* return pointers for current Ximage, set if desired, test, open if needed */
+int GetImage (int *socket, int *N) {
+
+  int i, n;
+  char buffer[70];
+
+  SetImageDevice (TRUE);
+  if (N == (int *) NULL) {
+    n = Active;
+  } else {
+    if (*N >= NXIMAGE) {
+      gprint (GP_ERR, "invalid Ximage window %d\n", *N); 
+      return (FALSE);
+    }
+    if (*N < 0) {
+      *N = n = Active;
+    } else {
+      Active = n = *N;
+    }
+  }
+  
+  /* test Ximage[0], flush junk from pipe */
+  signal (SIGPIPE, XImageDead);
+  fcntl (Ximage[n], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Ximage[n], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Ximage[n], F_SETFL, !O_NONBLOCK); 
+  
+  if (Ximage[n] < 1) {
+    if (!open_image(n)) {
+      return (FALSE);
+    }
+  }
+
+  if (socket != (int *) NULL) *socket = Ximage[n];
+
+  return (TRUE);
+
+}
+
+void SetImageName (char *name) {
+  strcpy (Ximbuffer[Active], name);
+}
+
+char *GetImageName () {
+  return (Ximbuffer[Active]);
+}
+ 
+// leave this information on kapa, request when needed? 
+void SetImageScale (double zero, double range) {
+  Xzero[Active] = zero;
+  Xrange[Active] = range;
+}
+void GetImageScale (double *zero, double *range) {
+  *zero = Xzero[Active];
+  *range = Xrange[Active];
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_kapa.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_kapa.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/open_kapa.c	(revision 16632)
@@ -0,0 +1,292 @@
+# include "display.h"
+# include "shell.h"
+# include <assert.h>
+
+
+/* kapa support for the new version of kapa (v2.0), which has both graph and image
+ * elements merged into a single display device.  The user may now open an arbitrary
+ * number of kapa windows, and the display information is retrieved from kapa across the
+ * socket when it is needed.  Communication is now via an INET socket (not a UNIX socket).
+ */
+
+/* list of available socket connections */
+static int        Active;        // currently active socket entry (index value, not socket value)
+static int       *Socket = NULL; // list of available sockets
+static char     **Device = NULL; // list of device names for each socket
+static int       Ndevice = 0;    // number of available sockets / devices
+
+void InitKapa () {
+
+  Active  = -1;					  // -1 is the INVALID entry
+  Ndevice = 0;					  // number of defined sockets
+  ALLOCATE (Device, char *, 1);			  // for future REALLOCATE calls
+  ALLOCATE (Socket, int, 1);			  // for future REALLOCATE calls
+}
+
+void FreeKapa () {
+  
+  free (Device);
+  free (Socket);
+}
+
+// add new device name if not found
+int AddKapaDevice (char *name) {
+
+  int N;
+
+  N = FindKapaDevice (name);
+  if (N != -1) return (N);
+  N = Ndevice;
+  Ndevice ++;
+  REALLOCATE (Device, char *, Ndevice);
+  REALLOCATE (Socket, int, Ndevice);
+  Device[N] = strcreate (name);
+  Socket[N] = -1;
+  return (N);
+}
+
+// delete device by name, close if not closed
+int DelKapaDevice (char *name) {
+
+  int i, N;
+
+  N = FindKapaDevice (name);
+  if (N == -1) return (FALSE);
+
+  if (Socket[N] != -1) close (Socket[N]);
+  free (Device[N]);
+  for (i = N; i < Ndevice - 1; i++) {
+    Device[i] = Device[i+1];
+    Socket[i] = Socket[i+1];
+  }
+
+  if (N == Active) {
+    Active = -1;
+  }
+
+  Ndevice --;
+  REALLOCATE (Device, char *, Ndevice);
+  REALLOCATE (Socket, int, Ndevice);
+
+  return (TRUE);
+}
+
+// returns the entry of the requested device, or -1 if not found
+int FindKapaDevice (char *name) {
+
+  int i;
+
+  if (name == NULL) return (-1); 
+
+  for (i = 0; i < Ndevice; i++) {
+    if (!strcmp(Device[i], name)) return (i);
+  }
+  return (-1);
+}
+
+// set the active device to the given device, open if needed
+int open_kapa (int entry) {
+
+  int fd;
+  char *kapa_exec, *kapa_name;
+
+  // find the given device number, or create. set this to active
+  assert (entry >= 0);
+  assert (entry <  Ndevice);
+
+  // if the (now) active socket is not open, open it
+  if (Socket[entry] < 0) {
+    kapa_exec = get_variable ("KAPA");
+    if (kapa_exec == (char *) NULL) {
+      gprint (GP_ERR, "variable KAPA not found\n");
+      return (FALSE);
+    }
+
+    // KAPA may be either kapa://host or /path/to/program
+    ALLOCATE (kapa_name, char, strlen(Device[entry]) + 5);
+    snprintf (kapa_name, strlen(Device[entry]) + 5, "[%s]", Device[entry]);
+
+    if (!strncmp (kapa_exec, "unix://", 7)) {
+        fd = KapaOpenNamedSocket (&kapa_exec[7], "psphot");
+    } else {
+	fd = KapaOpen (kapa_exec, kapa_name);
+    }
+
+    free (kapa_exec);
+    free (kapa_name);
+
+    if (fd < 0) {
+      gprint (GP_ERR, "error starting kapa device %s\n", Device[entry]);
+      return (FALSE);
+    } 
+    Socket[entry] = fd;
+  } 
+  Active = entry;
+  return (TRUE);
+}
+
+/**************** graph specific ops *******************/
+
+// return the current device name, if set 
+char *GetKapaName () {
+  if (Active < 0) return NULL;
+  return Device[Active];
+}
+
+/* return pointers for named device or current; open if needed */
+// if fd == NULL, don't return the value
+// if name == NULL, use the currently active device
+int GetGraph (Graphdata *data, int *fd, char *name) {
+
+  int entry;
+
+  if (name == NULL) {
+    if (Active < 0) {
+      entry = AddKapaDevice ("0");
+    } else {
+      entry = Active;
+    }
+  } else {
+    entry = AddKapaDevice (name);
+  }
+  
+  if (!open_kapa (entry)) {
+    return (FALSE);
+  }
+  
+  if (data != NULL) KapaGetGraphData (Socket[Active], data);
+  if (fd != NULL) *fd = Socket[Active];
+
+  return (TRUE);
+}
+
+/* return pointers for given kapa, don't set or open */
+int GetGraphData (Graphdata *data, int *fd, char *name) {
+
+  int entry;
+
+  if (name == NULL) {
+    if (Active < 0) {
+      gprint (GP_ERR, "no active kapa window\n"); 
+      return (FALSE);
+    }
+    entry = Active;
+  } else {
+    entry = FindKapaDevice (name);
+    if (entry < 0) {
+      gprint (GP_ERR, "invalid kapa window %s\n", name); 
+      return (FALSE);
+    }
+  }
+
+  if (fd != NULL) *fd = Socket[entry];
+  if (data != NULL) KapaGetGraphData (Socket[entry], data);
+  return (TRUE);
+}
+
+/* assign given values to current kapa */
+int SetGraph (Graphdata *data) {
+  if (Active < 0) {
+    gprint (GP_ERR, "no active kapa window\n"); 
+    return (FALSE);
+  }
+  if (Socket[Active] == -1) {
+    gprint (GP_ERR, "no active kapa window\n"); 
+    return (FALSE);
+  }
+  KapaSetGraphData (Socket[Active], data);
+  return (TRUE);
+}
+
+/************* image ops ***********/
+
+/* return pointers for current Ximage, set if desired, test, open if needed */
+int GetImage (KapaImageData *data, int *fd, char *name) {
+
+  int entry;
+
+  if (name == NULL) {
+    if (Active < 0) {
+      entry = AddKapaDevice ("0");
+    } else {
+      entry = Active;
+    }
+  } else {
+    entry = AddKapaDevice (name);
+  }
+  
+  if (!open_kapa (entry)) {
+    return (FALSE);
+  }
+  
+  if (data != NULL) KapaGetImageData (Socket[Active], data);
+  if (fd != NULL) *fd = Socket[Active];
+
+  return (TRUE);
+}
+
+/* return pointers for given kapa, don't set or open */
+int GetImageData (KapaImageData *data, int *fd, char *name) {
+
+  int entry;
+
+  if (name == NULL) {
+    if (Active < 0) {
+      gprint (GP_ERR, "no active kapa window\n"); 
+      return (FALSE);
+    }
+    entry = Active;
+  } else {
+    entry = FindKapaDevice (name);
+    if (entry < 0) {
+      gprint (GP_ERR, "invalid kapa window %s\n", name); 
+      return (FALSE);
+    }
+  }
+
+  if (fd != NULL) *fd = Socket[entry];
+  if (data != NULL) KapaGetImageData (Socket[entry], data);
+  return (TRUE);
+}
+
+/* assign given values to current kapa */
+int SetImage (KapaImageData *data) {
+  if (Active < 0) {
+    gprint (GP_ERR, "no active kapa window\n"); 
+    return (FALSE);
+  }
+  if (Socket[Active] == -1) {
+    gprint (GP_ERR, "no active kapa window\n"); 
+    return (FALSE);
+  }
+  KapaSetImageData (Socket[Active], data);
+  return (TRUE);
+}
+
+int close_kapa (char *name) {
+
+  int N;
+
+  N = FindKapaDevice (name);
+  if (N == -1) {
+    if (Active < 0) return (FALSE);
+    name = Device[Active];
+  }
+  DelKapaDevice (name);
+  return (TRUE);
+}
+
+void QuitKapa () {
+
+  int i;
+  
+  for (i = 0; i < Ndevice; i++) {
+    if (Socket[i] != -1) close (Socket[i]);
+    if (Device[i] != NULL) free (Device[i]);
+  }
+  REALLOCATE (Socket, int, 1);
+  REALLOCATE (Device, char *, 1);
+
+  Ndevice = 0;
+  Active = -1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/page.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/page.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/page.c	(revision 16632)
@@ -0,0 +1,245 @@
+# include "data.h"
+
+void InitPage (Page *page, char *name) {
+
+    page[0].name = strcreate (name);
+
+    page[0].Nwords = 0;
+    page[0].NWORDS = 16;
+    ALLOCATE (page[0].words, char *, page[0].NWORDS);
+    ALLOCATE (page[0].value, char *, page[0].NWORDS);
+}
+
+void FreePage (Page *page) {
+
+    int i;
+
+    free (page[0].name);
+    for (i = 0; i < page[0].Nwords; i++) {
+      free (page[0].words[i]);
+      free (page[0].value[i]);
+    }
+    free (page[0].words);
+    free (page[0].value);
+    free (page);
+}
+
+/* return the given page */
+Page *GetPage (Book *book, int where) {
+
+  if (where < 0) where += book[0].Npages;
+  if (where < 0) return NULL;
+  if (where >= book[0].Npages) return NULL;
+  return (book[0].pages[where]);
+}
+
+/* return the given page with key restrictions */
+Page *GetPageRestricted (Book *book, int where, char *keyName, char *keyValue) {
+
+  int i;
+  int N, Nout;
+  char *value;
+
+  if (where < 0) where += book[0].Npages;
+  if (where < 0) return NULL;
+  if (where >= book[0].Npages) return NULL;
+
+  Nout = -1;
+  if (where >= 0) {
+    N = -1;
+    for (i = 0; (i < book[0].Npages) && (N < where); i++) {
+      value = BookGetWord (book[0].pages[i], keyName);
+      if ((value == NULL) && !strcmp (keyValue, "NULL")) {
+	N++;
+	Nout = i;
+      } 
+      if ((value != NULL) && !strcmp (keyValue, value)) {
+	N++;
+	Nout = i;
+      }
+    }
+  } else {
+    N = 0;
+    for (i = book[0].Npages - 1; (i >= 0) && (N > where); i--) {
+      value = BookGetWord (book[0].pages[i], keyName);
+      if ((value == NULL) && !strcmp (keyValue, "NULL")) {
+	N--;
+      } 
+      if ((value != NULL) && !strcmp (keyValue, value)) {
+	N--;
+      }
+    }
+  }
+
+  if (N != where) return NULL;
+
+  return (book[0].pages[Nout]);
+}
+
+/* return the given page */
+/* XXX use index to find more quickly */
+Page *FindPage (Book *book, char *name) {
+
+  int i;
+
+  for (i = 0; i < book[0].Npages; i++) {
+    if (!strcmp (book[0].pages[i][0].name, name)) {
+      return (book[0].pages[i]);
+    }
+  }
+  return (NULL);
+}
+
+/* make a new named page */
+Page *CreatePage (Book *book, char *name) {
+
+  int N;
+  Page *page;
+
+  page = FindPage (book, name);
+  if (page != NULL) return (page);
+
+  N = book[0].Npages;
+  book[0].Npages ++;
+  if (book[0].Npages >= book[0].NPAGES) {
+    book[0].NPAGES += 16;
+    REALLOCATE (book[0].pages, Page *, book[0].NPAGES);
+    REALLOCATE (book[0].pageIDs, char *, book[0].NPAGES);
+    // REALLOCATE (book[0].index, int, book[0].NPAGES);
+  }
+  ALLOCATE (page, Page, 1);
+  InitPage (page, name);
+  book[0].pages[N] = page;
+  book[0].pageIDs[N] = strcreate(name);
+  // book[0].index[N] = N;
+  
+  /* at this point, I should sort the index */
+
+  return (page);
+}
+
+void sortpages (int *seq, Page **pages, char **pageIDs, int N) {
+
+# define SWAPFUNC(A,B){ Page *tmpPage; char *tmpID; \
+  tmpPage = pages[A];   pages[A]   = pages[B];   pages[B] = tmpPage; \
+  tmpID   = pageIDs[A]; pageIDs[A] = pageIDs[B]; pageIDs[B] = tmpID; \
+}
+# define COMPARE(A,B)(seq[A] < seq[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+}
+
+/* make a new named page */
+int ShufflePages (Book *book) {
+
+  int i, N, *seq;
+  Page *page;
+
+  N = book[0].Npages;
+
+  // generate a random index
+  ALLOCATE (seq, int, N);
+  for (i = 0; i < N; i++) {
+    seq[i] = N * drand48();
+  }
+
+  // sort the pages by the random index
+  sortpages (seq, book[0].pages, book[0].pageIDs, N);
+  free (seq);
+
+  return (page);
+}
+
+/* delete a page in a book */
+int DeletePage (Book *book, Page *page) {
+
+  char *pageID;
+  int i, N, NPAGES_2;
+
+  /* find page in page list */
+  N = -1;
+  for (i = 0; i < book[0].Npages; i++) {
+    if (book[0].pages[i] == page) {
+      N = i;
+      break;
+    }
+  }
+  if (N == -1) return (FALSE);
+
+  pageID = book[0].pageIDs[i];
+
+  for (i = N; i < book[0].Npages - 1; i++) {
+    book[0].pages[i] = book[0].pages[i + 1];
+    book[0].pageIDs[i] = book[0].pageIDs[i + 1];
+    // book[0].index[i] = book[0].index[i + 1];
+  }
+  book[0].Npages --;
+  NPAGES_2 = MAX (16, book[0].NPAGES / 2);
+  if (book[0].Npages < NPAGES_2) {
+    book[0].NPAGES = NPAGES_2;
+    REALLOCATE (book[0].pages, Page *, book[0].NPAGES);
+    REALLOCATE (book[0].pageIDs, char *, book[0].NPAGES);
+    // REALLOCATE (book[0].index, int, book[0].NPAGES);
+  }
+
+  FreePage (page);
+  free (pageID);
+  return (TRUE);
+}
+
+void ListPages (Book *book) {
+
+  int i;
+
+  for (i = 0; i < book[0].Npages; i++) {
+    gprint (GP_ERR, "%-15s %3d\n", book[0].pages[i][0].name, book[0].pages[i][0].Nwords);
+  }
+  return;
+}
+
+void ListWords (Page *page) {
+
+  int i;
+
+  for (i = 0; i < page[0].Nwords; i++) {
+    gprint (GP_ERR, "%-15s %15s\n", page[0].words[i], page[0].value[i]);
+  }
+  return;
+}
+
+int BookSetWord (Page *page, char *word, char *value) {
+
+  int i;
+
+  for (i = 0; i < page[0].Nwords; i++) {
+    if (!strcmp (page[0].words[i], word)) {
+      free (page[0].value[i]);
+      page[0].value[i] = strcreate (value);
+      return TRUE;
+    }
+  }
+
+  page[0].Nwords ++;
+  if (page[0].Nwords >= page[0].NWORDS) {
+    page[0].NWORDS += 16;
+    REALLOCATE (page[0].words, char *, page[0].NWORDS);
+    REALLOCATE (page[0].value, char *, page[0].NWORDS);
+  }      
+  page[0].words[i] = strcreate (word);
+  page[0].value[i] = strcreate (value);
+  return (TRUE);
+}
+
+char *BookGetWord (Page *page, char *word) {
+  int i;
+
+  for (i = 0; i < page[0].Nwords; i++) {
+    if (!strcmp (page[0].words[i], word)) {
+      return (page[0].value[i]);
+    }
+  }
+  return NULL;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/precess.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/precess.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/precess.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "data.h"
+    
+double get_epoch (char *in_epoch, char mode) {
+
+  int done;
+  double epoch;
+
+  epoch = 2000.0;
+  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) {
+    gprint (GP_ERR, "error finding epoch %s\n", in_epoch);
+    return FALSE;
+  }
+  
+  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);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/queues.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/queues.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/queues.c	(revision 16632)
@@ -0,0 +1,399 @@
+# include "data.h"
+# define DEBUG 0
+
+Queue **queues;   /* queue to store the list of all queues */
+int    Nqueues;   /* number of currently defined queues */
+int    NQUEUES;   /* number of currently allocated queues */
+
+void InitQueues () {
+  Nqueues = 0;
+  NQUEUES = 16;
+  ALLOCATE (queues, Queue *, NQUEUES); 
+}
+
+void FreeQueues () {
+
+  int i, j;
+
+  for (i = 0; i < Nqueues; i++) {
+    for (j = 0; j < queues[i][0].Nlines; j++) {
+      free (queues[i][0].lines[j]);
+    }
+    free (queues[i][0].lines);
+    free (queues[i][0].name);
+    free (queues[i]);
+  }
+  free (queues);
+}
+
+/* list known queues */
+void ListQueues () {
+
+  int i;
+
+  for (i = 0; i < Nqueues; i++) {
+    gprint (GP_LOG, "%-15s %3d\n", queues[i][0].name, queues[i][0].Nlines);
+  }
+  return;
+}
+
+/* return the given queue */
+Queue *FindQueue (char *name) {
+
+  int i;
+
+  for (i = 0; i < Nqueues; i++) {
+    if (!strcmp (queues[i][0].name, name)) {
+      return (&queues[i][0]);
+    }
+  }
+  return (NULL);
+}
+
+/* make a new named queue */
+int InitQueue (Queue *queue) {
+
+  int i;
+
+  for (i = 0; i < queue[0].Nlines; i++) {
+    free (queue[0].lines[i]);
+  }
+  queue[0].Nlines = 0;
+  queue[0].NLINES = 16;
+  REALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+
+  if (DEBUG) fprintf (stderr, "init: %s (%zx) : %d of %d\n", queue[0].name, (size_t) queue, queue[0].Nlines, queue[0].NLINES);
+  
+  return (TRUE);
+}
+
+/* make a new named queue */
+Queue *CreateQueue (char *name) {
+
+  int N;
+  Queue *queue;
+
+  queue = FindQueue (name);
+  if (queue != NULL) return (queue);
+
+  N = Nqueues;
+  Nqueues ++;
+  CHECK_REALLOCATE (queues, Queue *, NQUEUES, Nqueues, 16);
+  ALLOCATE (queue, Queue, 1);
+  queue[0].Nlines = 0;
+  queue[0].NLINES = 16;
+  queue[0].name = strcreate (name);
+  ALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+  queues[N] = queue;
+  return (queue);
+}
+
+/* delete a queue */
+int DeleteQueue (Queue *queue) {
+
+  int i, N, NQUEUES_2;
+
+  /* find queue in queue list */
+  N = -1;
+  for (i = 0; i < Nqueues; i++) {
+    if (queues[i] == queue) {
+      N = i;
+      break;
+    }
+  }
+  if (N == -1) return (FALSE);
+
+  for (i = N; i < Nqueues - 1; i++) {
+    queues[i] = queues[i + 1];
+  }
+  Nqueues --;
+  NQUEUES_2 = MAX (16, NQUEUES / 2);
+  if (Nqueues < NQUEUES_2) {
+    NQUEUES = NQUEUES_2;
+    REALLOCATE (queues, Queue *, NQUEUES);
+  }
+
+  free (queue[0].name);
+  for (i = 0; i < queue[0].Nlines; i++) {
+    free (queue[0].lines[i]);
+  }
+  free (queue[0].lines);
+  free (queue);
+  return (TRUE);
+}
+
+void PushNamedQueue (char *name, char *line) {
+
+  Queue *queue;
+  
+  queue = FindQueue (name);
+  if (queue == NULL) {
+    queue = CreateQueue (name);
+  }
+  PushQueue (queue, line);
+  return;
+}
+
+/* push line onto queue.  return chars create new lines */
+void PushQueue (Queue *queue, char *line) {
+
+  int N;
+  char *p, *q;
+
+  p = line;
+  q = strchr (line, '\n');
+  N = queue[0].Nlines;
+  while (q != NULL) {
+    queue[0].lines[N] = strncreate (p, q - p);
+    N++;
+    CHECK_REALLOCATE (queue[0].lines, char *, queue[0].NLINES, N, 16);
+    p = q + 1;
+    q = strchr (p, '\n');
+  }    
+  if (*p) {
+    queue[0].lines[N] = strcreate (p);
+    N++;
+    CHECK_REALLOCATE (queue[0].lines, char *, queue[0].NLINES, N, 16);
+  }
+  queue[0].Nlines = N;
+  return;
+}
+
+// return a newly allocated string containing the requested key value
+char *ChooseSingleKey (char *line, int Key) {
+
+  int i;
+  char *key, *p;
+
+  if (Key == -1) {
+    key = strcreate (line);
+    return (key);
+  }
+
+  key = line;
+  for (i = 0; (i < Key) && (key != NULL); i++) {
+    p = nextword (key);
+    key = p;
+  }
+  key = thisword (key);
+  return (key);
+}
+
+/* construct merged key given keylist of the form K:N:M */ 
+char *ChooseKey (char *line, char *keylist) {
+
+  char *output, *entry, *key, *p, *q;
+  int first, keynum;
+
+  if (line == NULL) return (NULL);
+  if (keylist == NULL) return (line);
+
+  ALLOCATE (output, char, strlen(line) + 1);
+  memset (output, 0, strlen(line) + 1);
+
+  first = TRUE;
+  p = q = keylist;
+  while (q != NULL) {
+    q = strchr (p, ':');
+    if (q == NULL) {
+      entry = strcreate (p);
+    } else {
+      entry = strncreate (p, q - p);
+    }
+    keynum = atoi (entry);
+    free (entry);
+
+    key = ChooseSingleKey (line, keynum);
+
+    if (!first) strcat (output, ":");
+    if (key) {
+	strcat (output, key);
+	free (key);
+    }
+
+    if (q != NULL) p = q + 1;
+    first = FALSE;
+  }
+  return (output);
+}
+
+/* push line onto queue, skipping existing matches (optionally by key) */
+void PushQueueUnique (Queue *queue, char *line, char *Key) {
+
+  int i, j, N, found;
+  char *p, *q, *key1, *key2;
+  Queue tmp;
+
+  /* init tmp queue */
+  tmp.Nlines = 0;
+  tmp.NLINES = 16;
+  ALLOCATE (tmp.lines, char *, tmp.NLINES);
+
+  /* push entries on tmp queue */
+  p = line;
+  q = strchr (line, '\n');
+  N = tmp.Nlines;
+  while (q != NULL) {
+    tmp.lines[N] = strncreate (p, q - p);
+    N++;
+    CHECK_REALLOCATE (tmp.lines, char *, tmp.NLINES, N, 16);
+    p = q + 1;
+    q = strchr (p, '\n');
+  }    
+  if (*p) {
+    tmp.lines[N] = strcreate (p);
+    N++;
+    CHECK_REALLOCATE (tmp.lines, char *, tmp.NLINES, N, 16);
+  }
+  tmp.Nlines = N;
+
+  /* add unique entries in tmp to queue */
+  for (i = 0; i < tmp.Nlines; i++) {
+    key1 = ChooseKey (tmp.lines[i], Key);
+    if (key1 == NULL) continue;
+    found = FALSE;
+    for (j = 0; !found && (j < queue[0].Nlines); j++) {
+      key2 = ChooseKey (queue[0].lines[j], Key);
+      if (key2 == NULL) continue;
+      found = !strcmp (key1, key2);
+      free (key2);
+    }      
+    if (!found) PushQueue (queue, tmp.lines[i]);
+    free (key1);
+  }
+  for (i = 0; i < tmp.Nlines; i++) {
+    free (tmp.lines[i]);
+  } 
+  free (tmp.lines);
+  return;
+}
+
+/* push line onto queue, replacing matches (optionally by Key) */
+void PushQueueReplace (Queue *queue, char *line, char *Key) {
+
+  int i, j, N, found;
+  char *p, *q, *key1, *key2;
+  Queue tmp;
+
+  /* init tmp queue */
+  tmp.Nlines = 0;
+  tmp.NLINES = 16;
+  ALLOCATE (tmp.lines, char *, tmp.NLINES);
+
+  /* push entries on tmp queue */
+  p = line;
+  q = strchr (line, '\n');
+  N = tmp.Nlines;
+  while (q != NULL) {
+    tmp.lines[N] = strncreate (p, q - p);
+    N++;
+    CHECK_REALLOCATE (tmp.lines, char *, tmp.NLINES, N, 16);
+    p = q + 1;
+    q = strchr (p, '\n');
+  }    
+  if (*p) {
+    tmp.lines[N] = strcreate (p);
+    N++;
+    CHECK_REALLOCATE (tmp.lines, char *, tmp.NLINES, N, 16);
+  }
+  tmp.Nlines = N;
+
+  /* add unique entries in tmp to queue */
+  for (i = 0; i < tmp.Nlines; i++) {
+    key1 = ChooseKey (tmp.lines[i], Key);
+    if (key1 == NULL) continue;
+    found = FALSE;
+    for (j = 0; !found && (j < queue[0].Nlines); j++) {
+      key2 = ChooseKey (queue[0].lines[j], Key);
+      if (key2 == NULL) continue;
+      found = !strcmp (key1, key2);
+      if (found) {
+	// XXX do I need to free queue[0].lines[j]??
+	queue[0].lines[j] = strcreate (tmp.lines[i]);
+      }
+      free (key2);
+    }      
+    if (!found) PushQueue (queue, tmp.lines[i]);
+    free (key1);
+  }
+  for (i = 0; i < tmp.Nlines; i++) {
+    free (tmp.lines[i]);
+  } 
+  free (tmp.lines);
+  return;
+}
+
+char *PopQueue (Queue *queue) {
+
+  int i, NLINES_2;
+  char *line;
+
+  if (queue[0].Nlines == 0) return (NULL);
+  line = queue[0].lines[0];
+
+  for (i = 0; i < queue[0].Nlines - 1; i++) {
+    queue[0].lines[i] = queue[0].lines[i+1];
+  }
+  queue[0].Nlines --;
+
+  /* shrink queue allocation if small enough */
+  NLINES_2 = MAX (16, queue[0].NLINES / 2);
+  if (queue[0].Nlines < NLINES_2) {
+    queue[0].NLINES = NLINES_2;
+    REALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+  }    
+  return (line);
+}
+
+/* pop the first entry which for which the key matches */
+char *PopQueueMatch (Queue *queue, char *Key, char *value) {
+
+  int i, choice, NLINES_2;
+  char *line, *test;
+
+  if (queue[0].Nlines == 0) return (NULL);
+
+  /* find the matching key */
+  choice = -1;
+  for (i = 0; (i < queue[0].Nlines) && (choice == -1); i++) {
+      test = ChooseKey (queue[0].lines[i], Key);
+      if (test == NULL) continue;
+      if (strcmp (value, test)) { 
+	free (test);
+	continue;
+      }
+      free (test);
+      choice = i;
+  }
+  if (choice == -1) return NULL;
+
+  line = queue[0].lines[choice];
+
+  for (i = choice; i < queue[0].Nlines - 1; i++) {
+    queue[0].lines[i] = queue[0].lines[i+1];
+  }
+  queue[0].Nlines --;
+
+  /* shrink queue allocation if small enough */
+  NLINES_2 = MAX (16, queue[0].NLINES / 2);
+  if (queue[0].Nlines < NLINES_2) {
+    queue[0].NLINES = NLINES_2;
+    REALLOCATE (queue[0].lines, char *, queue[0].NLINES);
+  }    
+  return (line);
+}
+
+int PrintQueue (Queue *queue) {
+
+  int i;
+
+  if (queue[0].Nlines == 0) return (TRUE);
+
+  if (DEBUG) fprintf (stderr, "print: %s (%zx) : %d of %d\n", queue[0].name, (size_t) queue, queue[0].Nlines, queue[0].NLINES);
+
+  for (i = 0; i < queue[0].Nlines; i++) {
+    gprint (GP_LOG, "%s\n", queue[0].lines[i]);
+  }
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/spline.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/spline.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/spline.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "data.h"
+
+/* construct the natural spline for x, y in y2 */
+void spline_construct (float *x, float *y, int N, float *y2) {
+
+  int i;
+  float dy, dx, *tmp;
+  
+  ALLOCATE (tmp, float, N);
+
+  y2[0] = tmp[0] = 0.0;
+  
+  for (i = 1; i < N-1; i++) {
+    dx = (x[i+0] - x[i-1]) / (x[i+1] - x[i-1]);
+    dy = dx * y2[i-1] + 2.0;
+    y2[i] = (dx - 1.0) / dy;
+    tmp[i] = (y[i+1] - y[i+0]) / (x[i+1] - x[i+0]) - (y[i+0] - y[i-1]) / (x[i+0] - x[i-1]);
+    tmp[i] = (6.0 * tmp[i] / (x[i+1] - x[i-1]) - dx*tmp[i-1]) / dy;
+  }
+  
+  y2[N-1] = 0;
+  for (i = N-2; i >= 1; i--)
+    y2[i] = y2[i]*y2[i+1] + tmp[i];
+
+  free (tmp);
+}
+
+/* evaluate spline for x, y, y2 at X */
+float spline_apply (float *x, float *y, float *y2, int N, float X) {
+
+  int i, lo, hi;
+  float dx, a, b, value;
+  
+  /* find correct element in array (x must be sorted) */
+  lo = 0;
+  hi = N-1;
+  while (hi - lo > 1) {
+    i = 0.5*(hi+lo);
+    if (x[i] > X) {
+      hi = i;
+    } else {
+      lo = i;
+    }
+  }
+
+  /* error condition: duplicate abssisca */
+  dx = x[hi] - x[lo];
+  if (dx == 0.0) {
+    return (HUGE_VAL);
+  }
+
+  /* evaluate spline */
+  a = (x[hi] - X) / dx;
+  b = (X - x[lo]) / dx;
+
+  value = a*y[lo] + b*y[hi] + ((a*a*a - a)*y2[lo] + (b*b*b - b)*y2[hi])*(dx*dx) / 6.0;
+  return (value);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/starfuncs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/starfuncs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/starfuncs.c	(revision 16632)
@@ -0,0 +1,251 @@
+# include "data.h"
+
+double get_aperture_stats (Matrix *matrix, int X, int Y, int Npix, int Nborder, double max) {
+
+  double *ring;
+  double x, y, x2, y2, xy, I, sky, FWHMx, FWHMy, value, mag, Sxy;
+  int i, j, n, Npix2, Nring, Nmax;
+  double Npts, gain, dsky2, dmag, peak, offset;
+  char *string;
+  
+  string = get_variable ("GAIN");
+  if (string == (char *) NULL) {
+    gprint (GP_ERR, "assuming a value of 1.0\n");
+    gain = 1.0;
+  } else {
+    gain = atof (string);
+  }
+  Nborder = MAX (1, Nborder);
+  Nborder = MIN (1000, Nborder);
+  
+  Npix2 = (int)(0.5*Npix);
+  Npix = 2 * Npix2 + 1;
+  Nring = 4*Nborder*(Nborder + Npix);
+  ALLOCATE (ring, double, Nring);
+  bzero (ring, sizeof(double)*Nring);
+
+  n = 0;  
+  for (j = 0; j < Nborder; j++) {
+    for (i = X - Npix2 - Nborder; i < X + Npix2 + Nborder + 1; i++, n+=2) {
+      ring[n]   = gfits_get_matrix_value (matrix, i, (int)(Y - Npix2 - j));
+      ring[n+1] = gfits_get_matrix_value (matrix, i, (int)(Y + Npix2 + j));
+    }
+    for (i = Y - Npix2; i < Y + Npix2 + 1; i++, n+=2) {
+      ring[n]   = gfits_get_matrix_value (matrix, (int)(X - Npix2 - j), i);
+      ring[n+1] = gfits_get_matrix_value (matrix, (int)(X + Npix2 + j), i);
+    }
+  }
+  dsort (ring, Nring);
+  for (Npts = sky = dsky2 = 0, i = 0.25*Nring; i < 0.75*Nring; i++, Npts += 1.0) {
+    sky += ring[i];
+    dsky2 += ring[i]*ring[i];
+  }
+  sky = sky / Npts;
+  dsky2 = dsky2 / Npts - sky*sky;
+  free (ring);
+
+  peak = 0;
+  Npts = Nmax = 0;
+  x = y = x2 = y2 = xy = I = 0;
+  for (i = X - Npix2; i < X + Npix2 + 1; i++) {
+    for (j = Y - Npix2; j < Y + Npix2 + 1; j++) {
+      value = gfits_get_matrix_value (matrix, i, j);
+      offset = value - sky;
+      x  += i*offset;
+      y  += j*offset;
+      x2 += i*i*offset;
+      y2 += j*j*offset;
+      xy += i*j*offset;
+      I  += offset;
+      Npts ++;
+      if (value > max) {
+	Nmax ++;
+      }
+      if (value > peak) peak = value;
+    }
+  }
+
+  x = x / I;
+  y = y / I;
+  FWHMx = 2.355*sqrt (fabs(x2 / I - x*x));
+  FWHMy = 2.355*sqrt (fabs(y2 / I - y*y));
+  Sxy   = xy / I - x*y;
+  mag = -2.5*log10(I);
+  dmag = sqrt (fabs(1.0 / (gain*I) + Npts*dsky2 / (I*I)));
+  x = x + 1;
+  y = y + 1;
+  
+  set_variable ("Xg", x);
+  set_variable ("Yg", y);
+  set_variable ("SXg", FWHMx);
+  set_variable ("SYg", FWHMy);
+  set_variable ("SXYg", Sxy);
+  set_variable ("Sg", sky);
+  set_variable ("dSg", sqrt (fabs (dsky2)));
+  set_variable ("Zg", mag);
+  set_variable ("dZg", dmag);
+  set_variable ("Zcg", I);
+  set_variable ("Zpk", peak);
+  set_int_variable ("Nsat", Nmax);
+  
+  gprint (GP_LOG, "%f %f %f %f %f %f %f %f\n", x, y, FWHMx, FWHMy, sky, I, mag, dmag);
+
+  return (mag);
+
+}
+
+static double Raper  =  5;
+static double Rinner = 10;
+static double Router = 15;
+static double *sky = NULL;
+
+int set_rough_radii (double Ra, double Ri, double Ro) {
+
+  Raper = Ra;
+  Rinner = Ri;
+  Router = Ro;
+  if (sky == NULL) {
+    ALLOCATE (sky, double, SQ(2*Router + 1));
+  } else {
+    REALLOCATE (sky, double, SQ(2*Router + 1));
+  }
+  return (TRUE);
+}
+
+/* use a circular aperture */
+int get_rough_star (float *data, int Nx, int Ny, int x, int y,
+		    float *xc, float *yc, 
+		    float *sx, float *sy, float *sxy,
+		    float *zs, float *zp, float *sk) {
+
+  double Ra2, Ri2, Ro2, rad2;
+  int i, j, Npts, Nsky;
+  int Xs, Xe, Ys, Ye, off, Xc, Yc;
+  double peak, fsky, value;
+  double Sx, Sy, Sx2, Sy2, Sxy, Sum;
+  
+  /* define circular boundaries */
+  Ra2 = SQ(Raper);
+  Ri2 = SQ(Rinner);
+  Ro2 = SQ(Router);
+
+  /* measure the sky level */
+  /* boundaries for the outer sky region */
+  Xs = MAX (x - Router, 0);
+  Xe = MIN (x + Router + 1, Nx);
+  Ys = MAX (y - Router, 0);
+  Ye = MIN (y + Router + 1, Ny);
+
+/* this sample uses a circular aperture */
+# if (0)
+  Nsky = 0;  
+  for (j = Ys; j < Ye; j++) {
+    off = j*Nx;
+    for (i = Xs; i < Xe; i++) { 
+      rad2 = SQ(i - x) + SQ(j - y);
+      if (rad2 > Ro2) continue;
+      if (rad2 < Ri2) continue;
+      sky[Nsky] = data[i+off];
+      Nsky ++;
+    }
+  }
+  dsort (sky, Nsky);
+  for (Npts = fsky = 0, i = 0.25*Nsky; i < 0.75*Nsky; i++, Npts += 1.0) {
+    fsky += sky[i];
+  }
+  fsky = fsky / Npts;
+# else
+
+/* this sample uses a square outer annulus, without loop if tests */
+  Nsky = 0;  
+  Xs = MAX (x - Router, 0);
+  Xe = MIN (x - Rinner + 1, Nx);
+  Ys = MAX (y - Rinner, 0);
+  Ye = MIN (y + Rinner + 1, Ny);
+  for (j = Ys; j < Ye; j++) {
+    off = j*Nx;
+    for (i = Xs; i < Xe; i++) { 
+      sky[Nsky] = data[i+off];
+      Nsky ++;
+    }
+  }
+  Xs = MAX (x + Rinner, 0);
+  Xe = MIN (x + Router + 1, Nx);
+  for (j = Ys; j < Ye; j++) {
+    off = j*Nx;
+    for (i = Xs; i < Xe; i++) { 
+      sky[Nsky] = data[i+off];
+      Nsky ++;
+    }
+  }
+  Xs = MAX (x - Rinner, 0);
+  Xe = MIN (x - Rinner + 1, Nx);
+  Ys = MAX (y - Router, 0);
+  Ye = MIN (y - Rinner + 1, Ny);
+  for (j = Ys; j < Ye; j++) {
+    off = j*Nx;
+    for (i = Xs; i < Xe; i++) { 
+      sky[Nsky] = data[i+off];
+      Nsky ++;
+    }
+  }
+  Ys = MAX (y + Rinner, 0);
+  Ye = MIN (y + Router + 1, Ny);
+  for (j = Ys; j < Ye; j++) {
+    off = j*Nx;
+    for (i = Xs; i < Xe; i++) { 
+      sky[Nsky] = data[i+off];
+      Nsky ++;
+    }
+  }
+  dsort (sky, Nsky);
+  for (Npts = fsky = 0, i = 0.25*Nsky; i < 0.75*Nsky; i++, Npts += 1.0) {
+    fsky += sky[i];
+  }
+  fsky = fsky / Npts;
+# endif
+
+  /* boundaries for the star region */
+  Xs = MAX (x - Raper, 0);
+  Xe = MIN (x + Raper + 1, Nx);
+  Ys = MAX (y - Raper, 0);
+  Ye = MIN (y + Raper + 1, Ny);
+
+  /** note that this will fail on negative flux objects */
+  peak = Npts = 0;
+  Sx = Sy = Sx2 = Sy2 = Sxy = Sum = 0;
+  for (j = Ys; j < Ye; j++) {
+    off = j*Nx;
+    Yc = j - y;
+    for (i = Xs; i < Xe; i++) {
+      Xc = i - x;
+      rad2 = SQ(Xc) + SQ(Yc);
+      if (rad2 > Ro2) continue;
+      value = data[i+off] - fsky;
+      Sx  += Xc*value;
+      Sy  += Yc*value;
+      Sx2 += Xc*Xc*value;
+      Sy2 += Yc*Yc*value;
+      Sxy += Xc*Yc*value;
+      Sum += value;
+      Npts ++;
+      if (value > peak) peak = value;
+    }
+  }
+
+  *xc = Sx / Sum;
+  *yc = Sy / Sum;
+  *sx = sqrt (fabs (Sx2 / Sum - SQ(*xc)));
+  *sy = sqrt (fabs (Sy2 / Sum - SQ(*yc)));
+  *sxy = Sxy / Sum;
+  *xc += x;
+  *yc += y;
+  *zs = Sum;
+  *zp = peak;
+  *sk = fsky;
+  /* note sigma is rough: round-off errors can introduce errors */
+  /* using values relative to x,y should minimize this effect */
+
+  return (Npts);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/style_args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/style_args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/style_args.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "data.h"
+# include "display.h"
+
+int style_args (Graphdata *graphmode, int *argc, char **argv, int *kapa) {
+  
+  int N;
+  char *colorName;
+  char *kapaName;
+
+  kapaName = NULL;
+  if ((N = get_argument (*argc, argv, "-n"))) {
+    remove_argument (N, argc, argv);
+    kapaName = strcreate (argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  if (!GetGraph (graphmode, kapa, kapaName)) return (FALSE);
+  FREE (kapaName);
+
+  if (*argc == 1) {
+    kapaName = GetKapaName();
+    colorName = KapaColorName (graphmode[0].color);
+    gprint (GP_ERR, "current style (%s): -x %d -c %s -pt %d -lt %d -lw %f -sz %f\n", kapaName,
+	     graphmode[0].style, colorName, graphmode[0].ptype, 
+	     graphmode[0].ltype, graphmode[0].lweight,
+	     graphmode[0].size);
+    return (TRUE);
+  }
+
+  if ((N = get_argument (*argc, argv, "-lt"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].ltype = atof(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-lw"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].lweight = atof(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-pt"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].ptype = atof(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "+eb"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].ebar = TRUE;
+  }
+  if ((N = get_argument (*argc, argv, "-eb"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].ebar = FALSE;
+  }
+  if ((N = get_argument (*argc, argv, "-sz"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].size = atof(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-c"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].color = KapaColorByName (argv[N]);
+    if (graphmode[0].color == -1) return (FALSE);
+    remove_argument (N, argc, argv);
+  }
+  if ((N = get_argument (*argc, argv, "-x"))) {
+    remove_argument (N, argc, argv);
+    graphmode[0].style = atof(argv[N]);
+    remove_argument (N, argc, argv);
+  }
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/svdcmp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/svdcmp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.data/svdcmp.c	(revision 16632)
@@ -0,0 +1,211 @@
+# include "data.h"
+
+/*
+  static float at,bt,ct;
+  #define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
+  (ct=bt/at,at*sqrt(1.0+ct*ct)) : (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
+  pythag -> hypot (check on roundoff errors) 
+*/
+
+/* use simple max? */
+#define FSIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
+
+/* n == Nx, m == Ny */
+int svdcmp (float *a, float *w, float *v, int Nx, int Ny) {
+
+  int flag, i, its, j, jj, k, l, nm, status;
+  float c, f, h, s, x, y, z;
+  float anorm=0.0, g = 0.0, scale = 0.0;
+  float *rv1;
+
+  if (Ny < Nx) return (0);
+
+  l = nm = 0;
+  ALLOCATE (rv1, float, Nx);
+  for (i = 0; i < Nx; i++) {
+    l = i + 1;
+    rv1[i] = scale*g;
+    g = s = scale = 0.0;
+    if (i < Ny) {
+      for (k = i; k < Ny; k++) scale += fabs(a[k*Nx + i]);
+      if (scale) {
+	for (k = i; k < Ny; k++) {
+	  a[k*Nx + i] /= scale;
+	  s += a[k*Nx + i]*a[k*Nx + i];
+	}
+	f = a[i*Nx + i];
+	g  = -FSIGN(sqrt(s), f);
+	h = f*g - s;
+	a[i*Nx + i] = f-g;
+	if (i != Nx - 1) {
+	  for (j = l; j < Nx; j++) {
+	    for (s = 0.0, k = i; k < Ny; k++) s += a[k*Nx + i]*a[k*Nx + j];
+	    f = s/h;
+	    for (k = i; k < Ny; k++) a[k*Nx + j] += f*a[k*Nx + i];
+	  }
+	}
+	for (k = i; k < Ny; k++) a[k*Nx + i] *= scale;
+      }
+    }
+    w[i] = scale*g;
+    g = s = scale = 0.0;
+    if ((i < Ny) && (i != (Nx - 1))) {
+      for (k = l; k < Nx; k++) scale += fabs(a[i*Nx + k]);
+      if (scale) {
+	for (k = l; k < Nx; k++) {
+	  a[i*Nx + k] /= scale;
+	  s += a[i*Nx + k]*a[i*Nx + k];
+	}
+	f = a[i*Nx + l];
+	g = -FSIGN(sqrt(s), f);
+	h = f*g - s;
+	a[i*Nx + l] = f-g;
+	for (k = l; k < Nx; k++) rv1[k] = a[i*Nx + k]/h;
+	if (i != Ny - 1) {
+	  for (j = l; j < Ny; j++) {
+	    for (s = 0.0, k = l; k < Nx; k++) s += a[j*Nx + k]*a[i*Nx + k];
+	    for (k = l; k < Nx; k++) a[j*Nx + k] += s*rv1[k];
+	  }
+	}
+	for (k = l; k < Nx; k++) a[i*Nx + k] *= scale;
+      }
+    }
+    anorm = MAX(anorm, (fabs(w[i]) + fabs(rv1[i])));
+  }
+
+  for (i = Nx - 1; i >= 0; i--) {
+    if (i < Nx - 1) {
+      if (g) {
+	/* isn't l == n to start?? */
+	for (j = l; j < Nx; j++) v[j*Nx + i] = (a[i*Nx + j]/a[i*Nx + l])/g;
+	for (j = l; j < Nx; j++) {
+	  for (s = 0.0, k = l; k < Nx; k++) s += a[i*Nx + k]*v[k*Nx + j];
+	  for (k = l; k < Nx; k++) v[k*Nx + j] += s*v[k*Nx + i];
+	}
+      }
+      for (j = l; j < Nx; j++) v[i*Nx + j] = v[j*Nx + i] = 0.0;
+    }
+    v[i*Nx + i] = 1.0;
+    g = rv1[i];
+    l = i;
+  }
+  for (i = Nx - 1; i >= 0; i--) {
+    l = i + 1;
+    g = w[i];
+    if (i < Nx - 1)
+      for (j = l; j < Nx; j++) a[i*Nx + j] = 0.0;
+    if (g) {
+      g = 1.0/g;
+      if (i != Nx - 1) {
+	for (j = l; j < Nx; j++) {
+	  for (s = 0.0, k = l; k < Ny; k++) s += a[k*Nx + i]*a[k*Nx + j];
+	  f = (s/a[i*Nx + i])*g;
+	  for (k = i; k < Ny; k++) a[k*Nx + j] += f*a[k*Nx + i];
+	}
+      }
+      for (j = i; j < Ny; j++) a[j*Nx + i] *= g;
+    } else {
+      for (j = i; j < Ny; j++) a[j*Nx + i] = 0.0;
+    }
+    ++a[i*Nx + i];
+  }
+
+  status = 1;
+  for (k = Nx - 1; k >= 0; k--) {
+    for (its = 0; its < 30; its++) {
+      flag = 1;
+      for (l = k; l >= 0; l--) {
+	nm = l - 1;
+	if (fabs(rv1[l])+anorm == anorm) {
+	  flag = 0;
+	  break;
+	}
+	if (fabs(w[nm])+anorm == anorm) break;
+      }
+      if (flag) {
+	c = 0.0;
+	s = 1.0;
+	for (i = l; i < k; i++) {
+	  f = s*rv1[i];
+	  if (fabs(f)+anorm != anorm) {
+	    g = w[i];
+	    h = hypot (f, g);
+	    w[i] = h;
+	    h = 1.0/h;
+	    c = g*h;
+	    s = (-f*h);
+	    for (j = 0; j < Ny; j++) {
+	      y = a[j*Nx + nm];
+	      z = a[j*Nx + i];
+	      a[j*Nx + nm] = y*c + z*s;
+	      a[j*Nx + i] = z*c - y*s;
+	    }
+	  }
+	}
+      }
+      z = w[k];
+      if (l == k) {
+	if (z < 0.0) {
+	  w[k] = -z;
+	  for (j = 0; j < Nx; j++) v[j*Nx + k] = (-v[j*Nx + k]);
+	}
+	break;
+      }
+      if (its == 29) status = 0;
+      x = w[l];
+      nm = k-1;
+      y = w[nm];
+      g = rv1[nm];
+      h = rv1[k];
+      f = ((y-z)*(y+z) + (g-h)*(g+h))/(2.0*h*y);
+      g = hypot (f, 1.0);
+      f = ((x-z)*(x+z) + h*((y/(f+FSIGN(g, f)))-h))/x;
+      c = s = 1.0;
+      for (j = l; j < nm; j++) {
+	i = j+1;
+	g = rv1[i];
+	y = w[i];
+	h = s*g;
+	g = c*g;
+	z = hypot (f, h);
+	rv1[j] = z;
+	c = f/z;
+	s = h/z;
+	f = x*c+g*s;
+	g = g*c-x*s;
+	h = y*s;
+	y = y*c;
+	for (jj = 0; jj < Nx; jj++) {
+	  x = v[jj*Nx + j];
+	  z = v[jj*Nx + i];
+	  v[jj*Nx + j] = x*c+z*s;
+	  v[jj*Nx + i] = z*c-x*s;
+	}
+	z = hypot(f, h);
+	w[j] = z;
+	if (z) {
+	  z = 1.0/z;
+	  c = f*z;
+	  s = h*z;
+	}
+	f = (c*g) + (s*y);
+	x = (c*y) - (s*g);
+	for (jj = 0; jj < Ny; jj++) {
+	  y = a[jj*Nx + j];
+	  z = a[jj*Nx + i];
+	  a[jj*Nx + j] = y*c+z*s;
+	  a[jj*Nx + i] = z*c-y*s;
+	}
+      }
+      rv1[l] = 0.0;
+      rv1[k] = f;
+      w[k] = x;
+    }
+  }
+  free(rv1);
+  return (1);
+}
+
+#undef FSIGN
+#undef MAX
+#undef PYTHAG
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/BufferOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/BufferOps.c	(revision 16632)
@@ -0,0 +1,248 @@
+# include "opihi.h"
+
+static Buffer **buffers;
+static int     Nbuffers;
+
+void InitBuffers () {
+  Nbuffers = 0;
+  ALLOCATE (buffers, Buffer *, 1);
+}
+
+void FreeBuffers () {
+
+  int i;
+
+  for (i = 0; i < Nbuffers; i++) {
+    gfits_free_header (&buffers[i][0].header);
+    gfits_free_matrix (&buffers[i][0].matrix);
+    free (buffers[i]);
+  }
+  free (buffers);
+}
+
+Buffer *InitBuffer () {
+  Buffer *buf;
+
+  ALLOCATE (buf, Buffer, 1);
+  bzero (buf[0].name, 1024);
+  bzero (buf[0].file, 1024);
+  ALLOCATE (buf[0].matrix.buffer, char, 1);
+  ALLOCATE (buf[0].header.buffer, char, 1);
+  return (buf);
+}
+
+int IsBuffer (char *name) {
+ 
+  int i;
+
+  if (name == NULL) return (FALSE);
+
+  for (i = 0; (i < Nbuffers) && (strcmp(buffers[i][0].name, name)); i++);
+  if (i == Nbuffers) return (FALSE);
+  return (TRUE);
+}
+
+int IsBufferPtr (Buffer *buf) {
+ 
+  int i;
+
+  if (buf == NULL) return (FALSE);
+
+  for (i = 0; (i < Nbuffers) && (buffers[i] != buf); i++);
+  if (i == Nbuffers) return (FALSE);
+  return (TRUE);
+}
+
+Buffer *SelectBuffer (char *name, int mode, int verbose) {
+
+  int i;
+
+  if (name == NULL) goto error;
+  if (ISNUM(name[0])) goto error;
+  if (IsVector(name)) goto error;
+
+  for (i = 0; (i < Nbuffers) && (strcmp(buffers[i][0].name, name)); i++);
+  /* is a new buffer */
+  if (i == Nbuffers) { 
+    if (mode == OLDBUFFER) goto error;
+    Nbuffers += 1;
+    REALLOCATE (buffers, Buffer *, Nbuffers);
+    buffers[i] = InitBuffer ();
+    strcpy (buffers[i][0].name, name);
+    return (buffers[i]);
+  } 
+  /* is an old buffer */
+  if (mode == NEWBUFFER) goto error;
+  return (buffers[i]);
+
+ error:
+  if (verbose) gprint (GP_ERR, "invalid matrix %s\n", name);
+  return (NULL);
+}
+
+int CreateBuffer (Buffer *buf, int Nx, int Ny, int bitpix, float bzero, float bscale) {
+
+  /* store the default output values */
+  gfits_init_header (&buf[0].header);
+
+  /* assign the necessary internal values */
+  buf[0].header.bitpix   = -32;
+  buf[0].header.Naxes = 2;
+  buf[0].header.Naxis[0] = Nx;
+  buf[0].header.Naxis[1] = Ny;
+
+  buf[0].bitpix = bitpix;
+  buf[0].bzero  = bzero;
+  buf[0].bscale = bscale;
+  
+  /* make some test of the validity of the values */
+
+  /* create the appropriate header and matrix */
+  gfits_create_header (&buf[0].header);
+  gfits_create_matrix (&buf[0].header, &buf[0].matrix);
+
+  return (TRUE);
+}
+  
+/* copy data from in to out - new memory space */
+int CopyNamedBuffer (char *out, char *in) {
+  Buffer *In, *Out;
+  if ((In  = SelectBuffer (in,  OLDBUFFER, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectBuffer (out, ANYBUFFER, FALSE)) == NULL) return (FALSE);
+  CopyBuffer (Out, In);
+  return (TRUE);
+}
+
+int CopyBuffer (Buffer *out, Buffer *in) {
+  free (out[0].matrix.buffer);
+  free (out[0].header.buffer);
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  strcpy (out[0].file, in[0].file);
+  gfits_copy_matrix (&in[0].matrix, &out[0].matrix);
+  gfits_copy_header (&in[0].header, &out[0].header);
+  return (TRUE);
+}
+
+/* move data from in to out - use old memory space */
+int MoveNamedBuffer (char *out, char *in) {
+  Buffer *In, *Out;
+  if ((In  = SelectBuffer (in,  OLDBUFFER, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectBuffer (out, ANYBUFFER, FALSE)) == NULL) return (FALSE);
+  MoveBuffer (Out, In);
+  return (TRUE);
+}
+int MoveBuffer (Buffer *out, Buffer *in) {
+  int i, j;
+
+  free (out[0].matrix.buffer);
+  free (out[0].header.buffer);
+  out[0].bitpix = in[0].bitpix;
+  out[0].unsign = in[0].unsign;
+  out[0].bscale = in[0].bscale;
+  out[0].bzero  = in[0].bzero;
+  out[0].matrix = in[0].matrix;
+  out[0].header = in[0].header;
+  strcpy (out[0].file, in[0].file);
+
+  /* delete buffer entry from buffer list, if it exists */
+  for (i = 0; (i < Nbuffers) && (in != buffers[i]); i++);
+  if (i == Nbuffers) {
+    free (in);
+    return (TRUE);
+  }
+
+  free (in);
+  for (j = i; j < Nbuffers - 1; j++) buffers[j] = buffers[j + 1];
+  Nbuffers -= 1;
+  REALLOCATE (buffers, Buffer *, MAX (Nbuffers, 1));
+  return (TRUE);
+}
+
+/* delete by ptr */
+int DeleteBuffer (Buffer *buf) {
+
+  int i, j;
+
+  if (buf == NULL) return (FALSE);
+  for (i = 0; (i < Nbuffers) && (buf != buffers[i]); i++);
+  if (i == Nbuffers) return (FALSE);
+
+  gfits_free_header (&buffers[i][0].header);
+  gfits_free_matrix (&buffers[i][0].matrix);
+  free (buffers[i]);
+
+  for (j = i; j < Nbuffers - 1; j++) buffers[j] = buffers[j + 1];
+
+  Nbuffers -= 1;
+  REALLOCATE (buffers, Buffer *, MAX (Nbuffers, 1));
+  return (TRUE);
+}
+  
+/* delete by name */
+int DeleteNamedBuffer (char *name) {
+
+  int i, j;
+
+  if (name == NULL) return (FALSE);
+  for (i = 0; (i < Nbuffers) && (strcmp(buffers[i][0].name, name)); i++);
+  if (i == Nbuffers) return (FALSE);
+
+  gfits_free_header (&buffers[i][0].header);
+  gfits_free_matrix (&buffers[i][0].matrix);
+  free (buffers[i]);
+
+  for (j = i; j < Nbuffers - 1; j++) buffers[j] = buffers[j + 1];
+
+  Nbuffers -= 1;
+  REALLOCATE (buffers, Buffer *, MAX (Nbuffers, 1));
+  return (TRUE);
+}
+
+void dump_buffers (int n) {
+
+  int i;
+
+  gprint (GP_ERR, "try %d\n", n);
+  for (i = 0; i < Nbuffers; i++) {
+    gprint (GP_ERR, "%d  %lx\n", i, (long) buffers[i]);
+    gprint (GP_ERR, "%d  %lx  %s\n", i, (long) buffers[i][0].name, buffers[i][0].name);
+    gprint (GP_ERR, "%d  %lx  %s\n", i, (long) buffers[i][0].file, buffers[i][0].file);
+    gprint (GP_ERR, "%d  %lx  %lx\n", i, (long) &buffers[i][0].header, (long) buffers[i][0].header.buffer);
+    gprint (GP_ERR, "%d  %lx  %lx\n", i, (long) &buffers[i][0].matrix, (long) buffers[i][0].matrix.buffer);
+    gprint (GP_ERR, "%d  %d  %d  %f %f\n", i, buffers[i][0].bitpix, buffers[i][0].unsign, buffers[i][0].bscale, buffers[i][0].bzero);
+  }
+}
+
+int PrintBuffers (int Long) {
+
+  int i;
+
+  if (Nbuffers == 0) {
+    gprint (GP_ERR, "No allocated buffers\n");
+    return (TRUE);
+  }
+  
+  if (Long) {
+    gprint (GP_LOG, "    N       name                      file     X     Y    bytes BP  U   bzero     bscale  \n");
+    for (i = 0; i < Nbuffers; i++) {
+      gprint (GP_LOG, "%5d %10s %25s %5d %5d %10d %3d %1d %10.4e %10.4e\n",
+	       i, buffers[i][0].name, buffers[i][0].file, 
+	       buffers[i][0].header.Naxis[0], buffers[i][0].header.Naxis[1],
+	       buffers[i][0].header.size + buffers[i][0].matrix.size, buffers[i][0].bitpix, 
+	       buffers[i][0].unsign, buffers[i][0].bzero, buffers[i][0].bscale);
+    }
+    return (TRUE);
+  }
+
+  gprint (GP_LOG, "    N       name                      file     X     Y    bytes\n");
+  for (i = 0; i < Nbuffers; i++) {
+    gprint (GP_LOG, "%5d %10s %25s %5d %5d %10d\n",
+	     i, buffers[i][0].name, buffers[i][0].file, 
+	     buffers[i][0].header.Naxis[0], buffers[i][0].header.Naxis[1],
+	     buffers[i][0].header.size + buffers[i][0].matrix.size);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/CommandOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/CommandOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/CommandOps.c	(revision 16632)
@@ -0,0 +1,171 @@
+# include "opihi.h"
+
+// if the user has installed the libedit version of readline, we need to modify a couple symbols:
+# ifndef RL_READLINE_VERSION
+# define rl_completion_matches(A,B) completion_matches(A,B)
+# endif
+
+static Command  *commands;
+static int      Ncommands;
+static int      NCOMMANDS;
+
+void InitCommands () {
+  NCOMMANDS = 20;
+  Ncommands = 0;
+  ALLOCATE (commands, Command, NCOMMANDS);
+}
+
+void FreeCommands () {
+  int i;
+
+  for (i = 0; i < Ncommands; i++) {
+    if (commands[i].real) continue;
+    free (commands[i].name);
+    free (commands[i].help);
+  }
+  free (commands);
+}
+
+void AddCommand (Command *new) {
+  
+  commands[Ncommands] = *new;
+  Ncommands ++;
+  if (Ncommands == NCOMMANDS) {
+    NCOMMANDS += 20;
+    REALLOCATE (commands, Command, NCOMMANDS);
+  }
+}
+
+int DeleteCommand (Command *command) {
+
+  int i, Nc;
+
+  Nc = -1;
+  for (i = 0; i < Ncommands; i++) {
+    if (command == &commands[i]) {
+      Nc = i;
+      break;
+    }
+  }
+  if (Nc == -1) {
+    gprint (GP_ERR, "programming error: command not found\n");
+    return (FALSE);
+  }
+
+  free (commands[Nc].name);
+  for (i = Nc + 1; i < Ncommands; i++)
+    commands[i - 1] = commands[i];
+  Ncommands --;
+  REALLOCATE (commands, Command, Ncommands);
+  return (TRUE);
+}
+
+/* return command which unambiguously matches name */
+Command *MatchCommand (char *name, int VERBOSE, int EXACT) {
+
+  int i, match[10], Nmatch;
+
+  /* try for an exact match first */
+  for (i = 0; i < Ncommands; i++) {
+    if (!strcmp (commands[i].name, name)) {
+      return (&commands[i]);
+    }
+  }
+  if (EXACT) {
+    if (VERBOSE) gprint (GP_ERR, "no exact match to %s\n", name);
+    return (NULL);
+  }
+
+  /* not found as complete command, try partial */
+  Nmatch = 0;
+  for (i = 0; (Nmatch < 10) && (i < Ncommands); i++) {
+    if (!strncmp (commands[i].name, name, strlen(name))) {  /* found a command */
+      match[Nmatch] = i;
+      Nmatch ++;
+    }
+  }
+  if (Nmatch == 1) return (&commands[match[0]]);
+
+  if (Nmatch > 1) {
+    if (VERBOSE) {
+      gprint (GP_ERR, "ambiguous command: %s ( ", name);
+      for (i = 0; i < Nmatch; i++) {
+	gprint (GP_ERR, "%s ", commands[match[i]].name);
+      }
+      gprint (GP_ERR, ")\n");
+    }
+    return (NULL);
+  }
+  if (VERBOSE) gprint (GP_ERR, "%s: Command not found.\n", name);
+  return (NULL);
+}  
+
+/* generate a command completion list for readline */
+/**** these probably do not interact well with OHANA memory!!! ****/
+char *command_generator (const char *text, int state) {
+
+  /* i must be remembered from call to call */
+  static int i, len;
+
+  /* On first call, state is set to 0: initial the state */
+  if (!state) {
+    i = -1;  
+    len = strlen (text);
+  }
+
+  /* Return the next partial match from the command list */
+  for (i++; i < Ncommands; i++) {
+    if (!len) 
+      return (strcreate(commands[i].name));
+    if (!strncmp (commands[i].name, text, len)) {
+      return (strcreate(commands[i].name));
+    }
+  }
+
+  /* If no names matched, then return NULL. */
+  return ((char *)NULL);
+}
+
+/* tell readline to use out command_generator rather than basic completion */
+char **command_completer (const char *text, int start, int end) {
+  
+  char **matches;
+
+  matches = (char **) NULL;
+  
+  if (start == 0) {
+    matches = rl_completion_matches (text, command_generator);
+  }
+
+  return (matches);
+}
+
+void sort_commands (int *seq) {
+
+  int i;
+
+  for (i = 0; i < Ncommands; i++) seq[i] = i;
+
+# define SWAPFUNC(A,B){ int tmp = seq[A]; seq[A] = seq[B]; seq[B] = tmp; }
+# define COMPARE(A,B)(strcmp (commands[seq[A]].name, commands[seq[B]].name) < 0)
+
+  OHANA_SORT (Ncommands, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+  
+}
+
+void print_commands (FILE *f) {
+
+  int i, *seq;
+
+  ALLOCATE (seq, int, Ncommands);
+  sort_commands (seq);
+  for (i = 0; i < Ncommands; i++) {
+    fprintf (f, "%-25s -- %s\n", commands[seq[i]].name, commands[seq[i]].help);
+  }
+  free (seq);
+
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/ConfigInit.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "opihi.h"
+
+static char *GlobalConfig;
+
+int ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  config = LoadConfigFile (file);
+  if (config == (char *) NULL) {
+    if (file != (char *) NULL) free (file);
+    return (FALSE);
+  }
+
+  GlobalConfig = config;
+
+  free (file);
+  return (TRUE);
+}
+
+char *VarConfig (char *keyword, char *mode, void *ptr) {
+
+  char *answer;
+
+  answer = get_variable (keyword);
+  if (answer == (char *) NULL) {
+    answer = ScanConfig (GlobalConfig, keyword, mode, 0, ptr);
+    return (answer);
+  }
+
+  if (!strcmp (mode, "%s"))  strcpy ((char *) ptr, answer);
+  if (!strcmp (mode, "%d"))  *(int *) ptr       = atoi (answer);
+  if (!strcmp (mode, "%u"))  *(unsigned *) ptr  = atoi (answer);
+  if (!strcmp (mode, "%ld")) *(long *) ptr      = atoi (answer);
+  if (!strcmp (mode, "%hd")) *(short *) ptr     = atoi (answer);
+  if (!strcmp (mode, "%f"))  *(float *) ptr     = atof (answer);
+  if (!strcmp (mode, "%lf")) *(double *) ptr    = atof (answer);
+
+  free (answer);
+  return (ptr);
+}
+
+char *VarConfigEntry (char *keyword, char *mode, int entry, void *ptr) {
+
+  char *answer;
+
+  answer = get_variable (keyword);
+  if (answer == (char *) NULL) {
+    answer = ScanConfig (GlobalConfig, keyword, mode, entry, ptr);
+    return (answer);
+  }
+
+  if (!strcmp (mode, "%s"))  strcpy ((char *) ptr, answer);
+  if (!strcmp (mode, "%d"))  *(int *) ptr       = atoi (answer);
+  if (!strcmp (mode, "%u"))  *(unsigned *) ptr  = atoi (answer);
+  if (!strcmp (mode, "%ld")) *(long *) ptr      = atoi (answer);
+  if (!strcmp (mode, "%hd")) *(short *) ptr     = atoi (answer);
+  if (!strcmp (mode, "%f"))  *(float *) ptr     = atof (answer);
+  if (!strcmp (mode, "%lf")) *(double *) ptr    = atof (answer);
+
+  free (answer);
+  return (ptr);
+}
+
+void ConfigFree () {
+  if (GlobalConfig) free (GlobalConfig);
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/ListOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/ListOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/ListOps.c	(revision 16632)
@@ -0,0 +1,270 @@
+# include "opihi.h"
+# include "macro.h"
+
+/*** local static variables used to track the command lists  ***/
+static List *lists;			/* variable to store the list of all lists */
+static int  Nlists;			/* number of currently available lists */
+
+void InitLists () {
+  Nlists = 0;
+  ALLOCATE (lists, List, 1); 
+  return;
+}
+
+void FreeLists () {
+
+  int i, j;
+
+  for (i = 0; i < Nlists; i++) {
+    for (j = 0; j < lists[i].Nlines; j++) {
+      free (lists[i].line[j]);
+    }
+    free (lists[i].line);
+  }
+  free (lists);
+}
+
+int current_list_depth () {
+  return Nlists;
+}
+
+int increase_list_depth () {
+  Nlists ++;
+  REALLOCATE (lists, List, MAX (Nlists + 1, 0) + 1);
+  ALLOCATE (lists[Nlists].line, char *, 16);
+  lists[Nlists].Nalloc = 16;
+  lists[Nlists].Nlines = 0;
+  lists[Nlists].n = 0;
+  return Nlists;
+}
+
+int decrease_list_depth () {
+  
+  int i;
+
+  for (i = 0; i < lists[Nlists].Nlines; i++) {
+    free (lists[Nlists].line[i]);
+  }
+  free (lists[Nlists].line);
+  Nlists --;
+  REALLOCATE (lists, List, MAX (Nlists + 1, 0) + 1);
+  return Nlists;
+}
+
+/* return a new string consisting of the next line in the current list */
+char *get_next_listentry (int ThisList) {
+
+  int Nline;
+  char *output;
+
+  Nline = lists[ThisList].n;
+
+  if (Nline >= lists[ThisList].Nlines) return (NULL);
+
+  output = strcreate (lists[ThisList].line[Nline]);
+  lists[ThisList].n ++;
+  
+  return (output);
+}
+
+# if (0)
+char *remove_listentry (int current) {
+
+  int i;
+  char *output;
+
+  if ((current + 1) >= lists[Nlists].Nlines) 
+    return ((char *) NULL);
+
+  output = lists[Nlists].line[current + 1];
+  
+  for (i = current + 1; i < lists[Nlists].Nlines - 1; i++) {
+    lists[Nlists].line[i] = lists[Nlists].line[i + 1];
+  }
+
+  lists[Nlists].Nlines --;
+  return (output);
+
+}
+# endif 
+
+int add_listentry (int ThisList, char *line) {
+
+  int Nlines;
+
+  Nlines = lists[ThisList].Nlines;
+  lists[ThisList].line[Nlines] = strcreate (line);
+  lists[ThisList].Nlines ++;
+
+  if (lists[ThisList].Nlines == lists[ThisList].Nalloc) {
+    lists[ThisList].Nalloc += 16;
+    REALLOCATE (lists[ThisList].line, char *, lists[ThisList].Nalloc);
+  }
+    
+  return (lists[ThisList].Nlines);
+}
+
+int is_for_loop (char *line) {
+
+  int status;
+  char *comm;
+
+  comm = thisword (line);
+  if (comm == (char *) NULL) return (FALSE);
+  
+  status = !strcmp (comm, "for");
+  free (comm);
+  return (status);
+}
+
+int is_macro_create (char *line) {
+
+  int status;
+  char *comm;
+  char *this_macro;
+  CommandF *cmd;
+
+  comm = thisword (line);
+  if (comm == NULL) return (FALSE);
+
+  status = !strcmp (comm, "macro");
+  free (comm);
+  if (!status) return (FALSE);
+  
+  this_macro = thisword (nextword (line));
+  if (this_macro == NULL) return (FALSE);
+
+  cmd = find_macro_command (this_macro);
+  free (this_macro);
+
+  if (cmd == NULL) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+}
+
+int is_if_block (char *line) {
+
+  char *comm, *temp;
+
+  temp = thisword (nextword (nextword (line)));
+  comm = thisword (line);
+
+  if (comm == NULL) goto escape;
+
+  if (strcmp (comm, "if")) goto escape;
+
+  /* if (cond) (command) does not define a complete block */
+  if (temp != NULL) goto escape;
+
+  if (temp != NULL) free (temp);
+  if (comm != NULL) free (comm);
+  return (TRUE);
+
+escape: 
+  if (comm != NULL) free (comm);
+  if (temp != NULL) free (temp);
+  return (FALSE);
+}
+
+// list (word) : nested list
+// list (word) -x : not nested list
+// list (word) -split : not nested list
+int is_list_data (char *line) {
+
+  char *comm, *temp;
+
+  temp = thisword (nextword (nextword (line)));
+  comm = thisword (line);
+
+  if (comm == NULL) goto escape;
+
+  if (strcmp (comm, "list")) goto escape;
+
+  /* if (cond) (command) does not define a complete block */
+  if (temp != NULL) {
+      if (!strcmp (temp, "-x")) goto escape;
+      if (!strcmp (temp, "-split")) goto escape;
+      if (!strcmp (temp, "-add")) goto escape;
+      if (!strcmp (temp, "-del")) goto escape;
+  }
+
+  if (temp != NULL) free (temp);
+  if (comm != NULL) free (comm);
+  return (TRUE);
+
+escape: 
+  if (comm != NULL) free (comm);
+  if (temp != NULL) free (temp);
+  return (FALSE);
+}
+
+int is_loop (char *line) {
+
+  int status;
+  char *comm;
+
+  comm = thisword (line);
+  if (comm == (char *) NULL) return (FALSE);
+
+  status = !strcmp (comm, "while");
+  free (comm);
+  return (status);
+}
+
+int is_task (char *line) {
+
+  int status;
+  char *comm;
+
+  comm = thisword (line);
+  if (comm == (char *) NULL) return (FALSE);
+
+  status = !strcmp (comm, "task");
+  free (comm);
+  return (status);
+}
+
+int is_task_exit (char *line) {
+
+  int status;
+  char *comm;
+
+  comm = thisword (line);
+  if (comm == (char *) NULL) return (FALSE);
+
+  status = !strcmp (comm, "task.exit");
+  free (comm);
+  return (status);
+}
+
+int is_task_exec (char *line) {
+
+  int status;
+  char *comm;
+
+  comm = thisword (line);
+  if (comm == (char *) NULL) return (FALSE);
+
+  status = !strcmp (comm, "task.exec");
+  free (comm);
+  return (status);
+}
+
+int is_list (char *line) {
+  
+  int status;
+
+  status = is_if_block (line);
+  status |= is_macro_create (line);
+  status |= is_for_loop (line);
+  status |= is_list_data (line);
+  status |= is_loop (line);
+  status |= is_task (line);
+  status |= is_task_exit (line);
+  status |= is_task_exec (line);
+
+  return (status);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/MacroOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/MacroOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/MacroOps.c	(revision 16632)
@@ -0,0 +1,153 @@
+# include "opihi.h"
+
+static char dot[] = ".";
+
+static Macro *macros;
+static int   Nmacros;
+static int   NMACROS;
+
+static char *MacroName = dot;
+static int   MacroDepth = 0;
+
+void InitMacros () {
+  NMACROS = 20;
+  Nmacros = 0;
+  ALLOCATE (macros, Macro, NMACROS);
+  MacroName = dot;
+  MacroDepth = 0;
+}
+
+void FreeMacros () {
+
+  int i;
+
+  for (i = 0; i < Nmacros; i++) {
+    FreeMacro (&macros[i]);
+  }
+  free (macros);
+}
+
+void SetCurrentMacroData (char *name, int depth) {
+  MacroName = name;
+  MacroDepth = depth;
+}
+
+char *GetMacroName () {
+  return (MacroName);
+}
+
+int GetMacroDepth () {
+  return (MacroDepth);
+}
+
+Macro *NewMacro (char *name) {
+  
+  macros[Nmacros].name = strcreate (name);;
+  macros[Nmacros].Nlines = 0;
+  ALLOCATE (macros[Nmacros].line, char *, 1);
+  Nmacros ++;
+  if (Nmacros == NMACROS) {
+    NMACROS += 20;
+    REALLOCATE (macros, Macro, NMACROS);
+  }
+  return (&macros[Nmacros-1]);
+}
+
+void ListMacro (Macro *macro) {
+
+  int i;
+
+  if ((macro == NULL) || (macro[0].Nlines == 0)) {
+    gprint (GP_ERR, "  macro not defined\n");
+    return;
+  }
+  for (i = 0; i < macro[0].Nlines; i++) {
+    gprint (GP_ERR, "  %s\n", macro[0].line[i]);
+  }
+  return;
+}
+
+void ListMacros () {
+  int i;
+  for (i = 0; i < Nmacros; i++) {
+    gprint (GP_ERR, "%s\n", macros[i].name);
+  }
+}
+
+void FreeMacro (Macro *macro) {
+  
+  int i;
+
+  if (macro == NULL) return;
+
+  for (i = 0; i < macro[0].Nlines; i++) {
+    free (macro[0].line[i]);
+  }
+  free (macro[0].line);
+  free (macro[0].name);
+  return;
+}
+
+int DeleteMacro (Macro *macro) {
+
+  int i, Nm;
+
+  Nm = -1;
+  for (i = 0; i < Nmacros; i++) {
+    if (macro == &macros[i]) {
+      Nm = i;
+      break;
+    }
+  }
+  if (Nm == -1) {
+    gprint (GP_ERR, "programming error: macro not found\n");
+    return (FALSE);
+  }
+
+  FreeMacro (&macros[Nm]);
+  for (i = Nm + 1; i < Nmacros; i++)
+    macros[i - 1] = macros[i];
+  Nmacros --;
+  return (TRUE);
+}
+
+/* return macro which unambiguously matches name */
+Macro *MatchMacro (char *name, int VERBOSE, int EXACT) {
+
+  int i, match[10], Nmatch;
+
+  /* try for an exact match first */
+  for (i = 0; i < Nmacros; i++) {
+    if (!strcmp (macros[i].name, name)) {
+      return (&macros[i]);
+    }
+  }
+  if (EXACT) {
+    if (VERBOSE) gprint (GP_ERR, "no exact match to %s\n", name);
+    return (NULL);
+  }
+      
+  /* not found as complete macro, try partial */
+  Nmatch = 0;
+  for (i = 0; (Nmatch < 10) && (i < Nmacros); i++) {
+    if (!strncmp (macros[i].name, name, strlen(name))) {  /* found a macro */
+      match[Nmatch] = i;
+      Nmatch ++;
+    }
+  }
+  if (Nmatch == 1) return (&macros[match[0]]);
+
+  if (Nmatch > 1) {
+    if (VERBOSE) {
+      gprint (GP_ERR, "ambiguous macro: %s ( ", name);
+      for (i = 0; i < Nmatch; i++) {
+	gprint (GP_ERR, "%s ", macros[match[i]].name);
+      }
+      gprint (GP_ERR, ")\n");
+    }
+    return (NULL);
+  }
+  if (VERBOSE) gprint (GP_ERR, "%s: Macro not found.\n", name);
+  return (NULL);
+}  
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/Makefile	(revision 16632)
@@ -0,0 +1,78 @@
+default: libshell
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SDIR    =       $(HOME)/lib.shell
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS) -fPIC
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+# opihi shell functions (libopihi) ########################
+shell = \
+$(SDIR)/ConfigInit.$(ARCH).o		\
+$(SDIR)/ListOps.$(ARCH).o	   	\
+$(SDIR)/command.$(ARCH).o               \
+$(SDIR)/CommandOps.$(ARCH).o		\
+$(SDIR)/errors.$(ARCH).o		\
+$(SDIR)/expand_vars.$(ARCH).o           \
+$(SDIR)/expand_vectors.$(ARCH).o        \
+$(SDIR)/exec_loop.$(ARCH).o             \
+$(SDIR)/interrupt.$(ARCH).o	        \
+$(SDIR)/MacroOps.$(ARCH).o		\
+$(SDIR)/macro_create.$(ARCH).o          \
+$(SDIR)/macro_delete.$(ARCH).o          \
+$(SDIR)/macro_edit.$(ARCH).o            \
+$(SDIR)/macro_funcs.$(ARCH).o           \
+$(SDIR)/macro_exec.$(ARCH).o            \
+$(SDIR)/macro_list.$(ARCH).o            \
+$(SDIR)/macro_read.$(ARCH).o            \
+$(SDIR)/macro_write.$(ARCH).o		\
+$(SDIR)/memstr.$(ARCH).o                \
+$(SDIR)/multicommand.$(ARCH).o          \
+$(SDIR)/parse.$(ARCH).o                 \
+$(SDIR)/parse_commands.$(ARCH).o	\
+$(SDIR)/startup.$(ARCH).o		\
+$(SDIR)/string.$(ARCH).o                \
+$(SDIR)/timeformat.$(ARCH).o            \
+$(SDIR)/BufferOps.$(ARCH).o             \
+$(SDIR)/SocketOps.$(ARCH).o             \
+$(SDIR)/VectorOps.$(ARCH).o             \
+$(SDIR)/check_stack.$(ARCH).o           \
+$(SDIR)/convert_to_RPN.$(ARCH).o	\
+$(SDIR)/evaluate_stack.$(ARCH).o  	\
+$(SDIR)/isolate_elements.$(ARCH).o 	\
+$(SDIR)/dvomath.$(ARCH).o               \
+$(SDIR)/stack_math.$(ARCH).o		\
+$(SDIR)/variable.$(ARCH).o	   	\
+$(SDIR)/version.$(ARCH).o	   	\
+$(SDIR)/gprint.$(ARCH).o		\
+$(SDIR)/opihi.$(ARCH).o
+
+# dependancy rules for include files ########################
+incs = \
+$(INC)/opihi.h \
+$(INC)/external.h \
+$(INC)/shell.h \
+$(INC)/dvomath.h \
+$(INC)/convert.h \
+$(INC)/display.h 
+
+$(shell) : $(incs)
+
+$(LIB)/libshell.$(ARCH).a: $(shell)
+$(LIB)/libshell.$(ARCH).$(DLLTYPE): $(shell)
+
+$(DESTLIB)/libshell.a: $(LIB)/libshell.$(ARCH).a
+$(DESTLIB)/libshell.$(DLLTYPE): $(LIB)/libshell.$(ARCH).$(DLLTYPE)
+
+libshell: $(DESTLIB)/libshell.a $(DESTLIB)/libshell.$(DLLTYPE)
+
+uninstall:
+	rm -f $(DESTLIB)/libshell.a
+	rm -f $(DESTLIB)/libshell.$(DLLTYPE)
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/SocketOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/SocketOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/SocketOps.c	(revision 16632)
@@ -0,0 +1,287 @@
+# include "shell.h"
+
+# define MY_PORT 2000
+# define MY_WAIT 500
+# define DEBUG 0
+
+static int NVALID;
+static int Nvalid;
+static int *VALID;
+
+int InitServerSocket (SockAddress *Address) {
+
+  int status, InitSocket, length;
+
+# if (0)
+  struct hostent  *host;
+  char tmpline[80], hostip[80];
+
+  host = gethostbyname (hostname);
+  bzero (hostip, 80);
+  for (i = 0; i < host[0].h_length; i++) {
+    sprintf (tmpline, "%u", (0xff & host[0].h_addr[i]));
+    strcat (hostip, tmpline);
+    if (i < host[0].h_length - 1) strcat (hostip, ".");
+  }
+# endif
+  
+  Address[0].sin_family = AF_INET;
+  Address[0].sin_port   = MY_PORT;
+  Address[0].sin_addr.s_addr = INADDR_ANY; // use this line to bind any address / port?
+
+retry_server:
+
+# if (0)  
+  status = inet_aton (hostip, &Address[0].sin_addr);
+  if (!status) {
+    gprint (GP_ERR, "invalid address\n");
+    exit (4);
+  }
+# endif
+
+  length = sizeof(Address[0]);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (5);
+  }
+
+  if (DEBUG) gprint (GP_ERR, "init sock: %d, len: %d\n", InitSocket, length);
+  status = bind (InitSocket, (struct sockaddr *) Address, length);
+  if (status == -1) {
+
+# if 0
+    fprintf (stderr, "errno: %d\n", errno);
+    fprintf (stderr, "EACCES: %d\n", EACCES);
+    fprintf (stderr, "EBADF: %d\n", EBADF);
+    fprintf (stderr, "EINVAL: %d\n", EINVAL);
+    fprintf (stderr, "ENOTSOCK: %d\n", ENOTSOCK);
+    fprintf (stderr, "EFAULT: %d\n", EFAULT);
+    fprintf (stderr, "ELOOP: %d\n", ELOOP);
+    fprintf (stderr, "ENAMETOOLONG: %d\n", ENAMETOOLONG);
+    fprintf (stderr, "ENOENT: %d\n", ENOENT);
+    fprintf (stderr, "ENOMEM: %d\n", ENOMEM);
+    fprintf (stderr, "ENOTDIR: %d\n", ENOTDIR);
+    fprintf (stderr, "EROFS: %d\n", EROFS);
+    fprintf (stderr, "EADDRNOTAVAIL: %d\n", EADDRNOTAVAIL);
+    fprintf (stderr, "EADDRINUSE: %d\n", EADDRINUSE);
+    fprintf (stderr, "ENOSR: %d\n", ENOSR);
+# endif
+
+    if (errno == EADDRINUSE) {
+	Address[0].sin_port ++;
+	if (Address[0].sin_port > MY_PORT + 10) {
+	  fprintf (stderr, "failed to find a usable port\n");
+	  exit (6);
+	}
+	goto retry_server;
+    }
+    perror ("bind: ");
+    exit (7);
+  }
+  /* repeated starts of the server are limited by xinetd or something:
+     requires 60sec timeout of the selected socket */
+
+  fprintf (stderr, "bound to port: %d\n", Address[0].sin_port);
+  status = listen (InitSocket, 10);
+  if (status == -1) {
+    perror ("listen: ");
+    exit (8);
+  }
+  return (InitSocket);
+}
+
+int WaitServerSocket (int InitSocket, SockAddress *Address) {
+
+  int i, BindSocket;
+  SockAddress Address_in;
+  socklen_t length;
+  u_int32_t addr;
+
+  Address_in = Address[0];
+
+  length = sizeof(Address_in);
+
+  /* this is a blocking wait; use in a separate thread */
+  fcntl (InitSocket, F_SETFL, !O_NONBLOCK); 
+
+  if (DEBUG) gprint (GP_ERR, "init sock: %d, len: %d\n", InitSocket, length);
+  BindSocket = accept (InitSocket, (struct sockaddr *) &Address_in, &length);
+  if (DEBUG) gprint (GP_ERR, "bind sock: %d\n", BindSocket);
+  if (BindSocket == -1) {
+    perror ("accept: ");
+    exit (9);
+  }
+
+  addr = Address_in.sin_addr.s_addr;
+  if (DEBUG) {
+    gprint (GP_ERR, "incoming connection from: ");
+    gprint (GP_ERR, " %u", (0xff & (addr >>  0)));
+    gprint (GP_ERR, ".%u", (0xff & (addr >>  8)));
+    gprint (GP_ERR, ".%u", (0xff & (addr >> 16)));
+    gprint (GP_ERR, ".%u", (0xff & (addr >> 24)));
+    gprint (GP_ERR, "\n");
+  }
+
+  if (Nvalid == 0) goto accepted;
+
+  for (i = 0; i < Nvalid; i++) {
+    /* valid IP addresses may be machines (120.90.121.142) or 
+       class C networks (120.90.121.0) */
+       
+    /* for machine, address must match */
+    if ((0xff & (VALID[i] >> 24)) != 0) {
+      if (addr == VALID[i]) goto accepted;
+    }
+
+    /* for network, lower three bytes of address must match */
+    if ((0xff & (VALID[i] >> 24)) == 0) {
+      if ((0x00ffffff & addr) == VALID[i]) goto accepted;
+    }
+  }
+
+  if (DEBUG) gprint (GP_ERR, "connection rejected\n");
+  close (BindSocket);
+  return (-1);
+
+accepted:
+  if (DEBUG) gprint (GP_ERR, "connection accepted\n");
+  fcntl (BindSocket, F_SETFL, O_NONBLOCK); 
+  return (BindSocket);
+}
+
+int GetClientSocket (char *hostname) {
+
+  int i, status, InitSocket, length;
+  SockAddress Address;
+  struct hostent  *host;
+  char tmpline[80], hostip[80];
+
+  host = gethostbyname (hostname);
+  bzero (hostip, 80);
+  for (i = 0; i < host[0].h_length; i++) {
+    sprintf (tmpline, "%u", (0xff & host[0].h_addr[i]));
+    strcat (hostip, tmpline);
+    if (i < host[0].h_length - 1) strcat (hostip, ".");
+  }
+
+  if (DEBUG) {
+    gprint (GP_ERR, "trying %s (%s:%d)...", host[0].h_name, hostip, MY_PORT);
+  }
+
+  Address.sin_family = AF_INET;
+  Address.sin_port   = MY_PORT;
+
+retry_client:
+  status = inet_aton (hostip, &Address.sin_addr);
+  if (!status) {
+    gprint (GP_ERR, "invalid address\n");
+    exit (10);
+  }
+
+  length = sizeof(Address);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (11);
+  }
+
+  status = connect (InitSocket, (struct sockaddr *) &Address, length);
+  if (status == -1) {
+    if (errno == ECONNREFUSED) {
+      Address.sin_port ++;
+      if (Address.sin_port > MY_PORT + 10) exit (12);
+      goto retry_client;
+    }
+    perror ("connect: ");
+    exit (13);
+  }
+
+  if (DEBUG) gprint (GP_ERR, "connected on port: %d\n", Address.sin_port);
+  if (DEBUG) gprint (GP_ERR, "connected\n");
+  fcntl (InitSocket, F_SETFL, O_NONBLOCK); 
+  return (InitSocket);
+}
+
+int InitServerSocket_Named (char *hostname, SockAddress *Address) {
+
+  int i, status, InitSocket, length;
+  struct hostent  *host;
+  char tmpline[80], hostip[80];
+
+  host = gethostbyname (hostname);
+  bzero (hostip, 80);
+  for (i = 0; i < host[0].h_length; i++) {
+    sprintf (tmpline, "%u", (0xff & host[0].h_addr[i]));
+    strcat (hostip, tmpline);
+    if (i < host[0].h_length - 1) strcat (hostip, ".");
+  }
+  
+  Address[0].sin_family = AF_INET;
+  Address[0].sin_port   = MY_PORT;
+  status = inet_aton (hostip, &Address[0].sin_addr);
+  if (!status) {
+    gprint (GP_ERR, "invalid address\n");
+    exit (14);
+  }
+
+  length = sizeof(Address[0]);
+
+  InitSocket = socket (PF_INET, SOCK_STREAM, 0);
+  if (InitSocket == -1) {
+    perror ("socket: ");
+    exit (15);
+  }
+
+  if (DEBUG) gprint (GP_ERR, "init sock: %d, len: %d\n", InitSocket, length);
+  status = bind (InitSocket, (struct sockaddr *) Address, length);
+  if (status == -1) {
+    perror ("bind: ");
+    exit (16);
+  }
+
+  status = listen (InitSocket, 10);
+  if (status == -1) {
+    perror ("listen: ");
+    exit (17);
+  }
+
+  if (DEBUG) gprint (GP_ERR, "socket listening on %s (%s:%d)\n", host[0].h_name, hostip, MY_PORT);
+  return (InitSocket);
+}
+
+/* load valid ip list */
+int DefineValidIP () {
+
+  int i, Nvalid, ip1, ip2, ip3, ip4, test, status;
+  char string[80];
+
+  Nvalid = 0;
+  NVALID = 10;
+  ALLOCATE (VALID, int, NVALID);
+  for (i = 0; VarConfigEntry ("VALID_IP", "%s", i, string) != NULL; i++) {
+    status = sscanf (string, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
+    test = TRUE;
+    test &= (status == 4);
+    test &= ((ip1 > 0) && (ip1 < 256)); 
+    test &= ((ip2 > 0) && (ip2 < 256)); 
+    test &= ((ip3 > 0) && (ip3 < 256)); 
+    test &= ((ip4 >=0) && (ip4 < 256)); 
+    if (!test) {
+      gprint (GP_ERR, "invalid IP address %s\n", string);
+      exit (18);
+    }
+    VALID[Nvalid] = ip1 | (ip2 << 8) | (ip3 << 16) | (ip4 << 24);
+    Nvalid ++;
+    CHECK_REALLOCATE (VALID, int, NVALID, Nvalid, 10);
+  }
+  NVALID = Nvalid;
+  REALLOCATE (VALID, int, NVALID);
+  if (NVALID == 0) {
+    free (VALID);
+    VALID = NULL;
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/VectorOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/VectorOps.c	(revision 16632)
@@ -0,0 +1,179 @@
+# include "opihi.h"
+
+static Vector **vectors;
+static int     Nvectors;
+  
+void InitVectors () {
+  Nvectors = 0;
+  ALLOCATE (vectors, Vector *, 1);
+}
+
+void FreeVectors () {
+
+  int i;
+
+  for (i = 0; i < Nvectors; i++) {
+    free (vectors[i][0].elements);
+    free (vectors[i]);
+  }
+  free (vectors);
+}
+
+Vector *InitVector () {
+  Vector *vec;
+
+  ALLOCATE (vec, Vector, 1);
+  ALLOCATE (vec[0].elements, float, 1);
+  bzero (vec[0].name, 1024);
+  vec[0].Nelements = 0;
+  return (vec);
+}
+
+int IsVector (char *name) {
+ 
+  int i;
+
+  if (name == NULL) return (FALSE);
+
+  for (i = 0; (i < Nvectors) && (strcmp(vectors[i][0].name, name)); i++);
+  if (i == Nvectors) return (FALSE);
+  return (TRUE);
+}
+
+int IsVectorPtr (Vector *vec) {
+ 
+  int i;
+
+  if (vec == NULL) return (FALSE);
+
+  for (i = 0; (i < Nvectors) && (vectors[i] != vec); i++);
+  if (i == Nvectors) return (FALSE);
+  return (TRUE);
+}
+
+Vector *SelectVector (char *name, int mode, int verbose) {
+
+  int i;
+
+  if (name == NULL) goto error;
+  if (ISNUM(name[0])) goto error;
+  if (IsBuffer(name)) goto error;
+
+  for (i = 0; (i < Nvectors) && (strcmp(vectors[i][0].name, name)); i++);
+  /* is a new vector */
+  if (i == Nvectors) { 
+    if (mode == OLDVECTOR) goto error;
+    Nvectors += 1;
+    REALLOCATE (vectors, Vector *, Nvectors);
+    vectors[i] = InitVector ();
+    strcpy (vectors[i][0].name, name);
+    return (vectors[i]);
+  } 
+  /* is an old vector */
+  if (mode == NEWVECTOR) goto error;
+  return (vectors[i]);
+
+ error:
+  if (verbose) gprint (GP_ERR, "invalid vector %s\n", name);
+  return (NULL);
+}
+  
+/* delete by pointer */
+int DeleteVector (Vector *vec) {
+
+  int i, j;
+
+  if (vec == NULL) return (FALSE);
+
+  for (i = 0; (i < Nvectors) && (vec != vectors[i]); i++);
+  if (i == Nvectors) return (FALSE);
+
+  free (vectors[i][0].elements);
+  free (vectors[i]);
+  for (j = i; j < Nvectors - 1; j++) vectors[j] = vectors[j + 1];
+
+  Nvectors -= 1;
+  REALLOCATE (vectors, Vector *, MAX (Nvectors, 1));
+  return (TRUE);
+}
+  
+/* delete by name */
+int DeleteNamedVector (char *name) {
+
+  int i, j;
+
+  if (name == NULL) return (FALSE);
+  for (i = 0; (i < Nvectors) && (strcmp(vectors[i][0].name, name)); i++);
+  if (i == Nvectors) return (FALSE);
+
+  free (vectors[i][0].elements);
+  free (vectors[i]);
+  for (j = i; j < Nvectors - 1; j++) vectors[j] = vectors[j + 1];
+
+  Nvectors -= 1;
+  REALLOCATE (vectors, Vector *, MAX (Nvectors, 1));
+  return (TRUE);
+}
+
+/* copy data from in to out - new memory space */
+int CopyNamedVector (char *out, char *in) {
+  Vector *In, *Out;
+  if ((In  = SelectVector (in,  OLDVECTOR, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectVector (out, ANYVECTOR, FALSE)) == NULL) return (FALSE);
+  CopyVector (Out, In);
+  return (TRUE);
+}
+int CopyVector (Vector *out, Vector *in) {
+  free (out[0].elements);
+  out[0].Nelements = in[0].Nelements;
+  ALLOCATE (out[0].elements, float, out[0].Nelements);
+  memcpy (out[0].elements, in[0].elements, out[0].Nelements*sizeof(float));
+  return (TRUE);
+}
+
+/* move data from in to out - use old memory space */
+int MoveNamedVector (char *out, char *in) {
+  Vector *In, *Out;
+  if ((In  = SelectVector (in,  OLDVECTOR, FALSE)) == NULL) return (FALSE);
+  if ((Out = SelectVector (out, ANYVECTOR, FALSE)) == NULL) return (FALSE);
+  MoveVector (Out, In);
+  return (TRUE);
+}
+int MoveVector (Vector *out, Vector *in) {
+  int i, j;
+
+  free (out[0].elements);
+  out[0].Nelements = in[0].Nelements;
+  out[0].elements =  in[0].elements;
+
+  /* delete vector entry from vector list, if it exists */
+  for (i = 0; (i < Nvectors) && (in != vectors[i]); i++);
+  if (i == Nvectors) {
+    free (in);
+    return (TRUE);
+  }
+
+  for (j = i; j < Nvectors - 1; j++) vectors[j] = vectors[j + 1];
+  Nvectors -= 1;
+  REALLOCATE (vectors, Vector *, MAX (Nvectors, 1));
+  free (in);
+  return (TRUE);
+}
+
+int ListVectors () {
+
+  int i;
+
+  if (Nvectors == 0) {
+    gprint (GP_ERR, "No defined vectors\n");
+    return (FALSE);
+  }
+
+  gprint (GP_LOG, "    N       name      size\n");
+  for (i = 0; i < Nvectors; i++) {
+    gprint (GP_LOG, "%5d %10s %10d\n",
+	     i, vectors[i][0].name, vectors[i][0].Nelements);
+  }
+  return (TRUE);
+}
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/check_stack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/check_stack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/check_stack.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "opihi.h"
+
+int check_stack (StackVar *stack, int Nstack, int validsize) {
+
+  int i, Nx, Ny, Nv, size;
+  char *c;
+
+  Nv = Nx = Ny = -1;
+
+  for (i = 0; i < Nstack; i++) {
+    if (stack[i].type == 'X') {
+
+      /** if this is a number, put it on the list of scalers and move on **/
+      stack[i].Float = strtod (stack[i].name, &c);
+      if (c == stack[i].name + strlen (stack[i].name)) {
+	stack[i].ptr   = &(stack[i].Float);
+	stack[i].type  = 'S';
+	continue;
+      } 
+
+      /** if this is a matrix, find the dimensions and check with existing values **/
+      if (IsBuffer (stack[i].name)) {
+	stack[i].buffer = SelectBuffer (stack[i].name, OLDBUFFER, TRUE);
+	stack[i].ptr    = (float *) stack[i].buffer[0].matrix.buffer;
+	stack[i].type   = 'M';
+	if (Nx == -1) {
+	  Nx = stack[i].buffer[0].matrix.Naxis[0];
+	  Ny = stack[i].buffer[0].matrix.Naxis[1];
+	} 
+	if ((Nx != stack[i].buffer[0].matrix.Naxis[0]) && (Ny != stack[i].buffer[0].matrix.Naxis[1])) {
+	  push_error ("dimensions don't match");
+	  return (-1);
+	}	
+	if (Nv != -1) {
+	  if ((Nv != Nx) && (Nv != Ny)) {
+	    push_error ("dimensions don't match");
+	    return (-1);
+	  }
+	}	
+	continue;
+      }
+
+      /** if this is a vector, find the dimensions and check with existing values **/
+      if (IsVector (stack[i].name)) {
+	stack[i].vector = SelectVector (stack[i].name, OLDVECTOR, FALSE);
+	stack[i].ptr    = (float *) stack[i].vector[0].elements;
+	stack[i].type   = 'V';
+
+	if (Nv == -1) Nv = stack[i].vector[0].Nelements;
+	if (Nv != stack[i].vector[0].Nelements) {
+	  push_error ("dimensions don't match");
+	  return (-1);
+	}
+	if (Nx != -1) {
+	  if ((Nx != Nv) && (Ny != Nv)) {
+	    push_error ("dimensions don't match");
+	    return (-1);
+	  }
+	}	
+	continue;
+      }
+
+      /* this is not a scalar, vector, or matrix.  must be string */
+      stack[i].type  = 'W';
+    }
+  }
+
+  /* return object dimensions */
+  size = 0;
+  if (Nv != -1) size = 1;
+  if (Nx != -1) size = 2;
+  if (validsize == -1)   return (size);
+  if (validsize != size) return (-1);
+  return (size);
+}
+
+/* check stack identifies the data elements as scalar, vector, matrix, or word.
+   operators have already been identified.  
+   check stack returns the total stack dimensionality (0,1,2)
+   on error, check stack returns -1
+   possible errors:
+     - mismatch with requested dimensionality
+     - mismatch in data dimensions
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/command.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/command.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/command.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "opihi.h"
+# define DEBUG 0
+
+int command (char *line, char **outline, int VERBOSE) {
+
+  int i, status, argc;
+  char **argv, **targv;
+  Command *cmd;
+
+  /* force a space between ! and first word: !ls becomes ! ls */
+  if (line[0] == '!') {
+    REALLOCATE (line, char, strlen(line) + 5);
+    memmove (&line[2], &line[1], strlen(&line[1]) + 1);
+    line[1] = ' ';
+  }
+
+  /* expand anything of the form $fred or $fred$sam, etc */ 
+  line = expand_vars (line);     /* line is freed here, new one allocated */
+  /* expand anything of the form fred[N] */ 
+  line = expand_vectors (line);  /* line is freed here, new one allocated */
+  /* solve math expresions, assign variable, if needed */
+  line = parse (line);        /* line is freed here, new one allocated */
+  /* any entry in line of the form {foo} returns value or tmp vector / buffer */
+
+  /* we may have reallocated line, return new pointer */
+  *outline = line;
+  
+  # if (DEBUG) 
+  fprintf (stderr, "line: %s\n", line);
+  # endif
+
+  argv = parse_commands (line, &argc);
+  if (argc == 0) return (TRUE);  /* empty command or assignment */
+
+  /* save the original values of argv since command may modify the array */
+  ALLOCATE (targv, char *, argc);
+  for (i = 0; i < argc; i++) targv[i] = argv[i];
+
+  cmd = MatchCommand (argv[0], VERBOSE, FALSE);
+  if (cmd == NULL) {
+    status = -1;
+  } else {
+    free (argv[0]);
+    argv[0] = strcreate (cmd[0].name);
+    targv[0] = argv[0];
+    status = (*cmd[0].func) (argc, argv);
+  }
+  for (i = 0; i < argc; i++) free (targv[i]);
+  free (targv);
+  free (argv);
+
+  if (!status) {
+    char *msg;
+    msg = get_variable_ptr ("ERRORMSG");
+    if (msg != (char *) NULL) gprint (GP_ERR, "%s\n", msg);
+  }
+
+  set_int_variable ("STATUS", status);
+
+  # if (DEBUG) 
+  gprint (GP_ERR, "command: %s, status: %d\n", line, status);
+  # endif
+
+  return (status);
+}
+
+/* parse the input line, search for the corresponding command, and execute it
+   if no match is found, return -1; this is used above to distinguish between
+   a command error and an unknown command.  if VERBOSE is true, unknown commands
+   result in an error message.  The input line is freed and the resulting parsed
+   line is returned on 'outline'
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/convert_to_RPN.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/convert_to_RPN.c	(revision 16632)
@@ -0,0 +1,208 @@
+# include "opihi.h"
+# define DUMPSTACK 0
+
+StackVar *convert_to_RPN (int argc, char **argv, int *nstack) {
+  
+  int type, Nx, Ny;
+  int i, j, Nstack, Nop_stack, NSTACK;
+  StackVar *stack, *op_stack;
+
+  /* max total stack size is argc, though should be less, this is safe */
+  NSTACK = argc + 5;
+  ALLOCATE (stack, StackVar, NSTACK);
+  ALLOCATE (op_stack, StackVar, NSTACK);
+  for (i = 0; i < NSTACK; i++) {
+    init_stack (&stack[i]);
+    init_stack (&op_stack[i]);
+  }
+  
+  Nx = Ny = Nstack = Nop_stack = 0;
+  for (i = 0; i < argc; i++) {
+    
+    /* decide on priority of object */
+    type = 0;
+    /* unary operations */
+    if (!strcmp (argv[i], "abs"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "int"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "exp"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ten"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "log"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ln"))     { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "sqrt"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "erf"))    { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "sinh"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "cosh"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "asinh"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "acosh"))  { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "sin"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "cos"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "tan"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dsin"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dcos"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dtan"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "asin"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "acos"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "atan"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dasin"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "dacos"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "datan"))  { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "lgamma")) { type = 9; goto gotit; }
+
+    if (!strcmp (argv[i], "rnd"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "xramp"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "yramp"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "ramp"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "zero"))   { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "--"))     { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "not"))    { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "isinf"))  { type = 9; goto gotit; }
+    if (!strcmp (argv[i], "isnan"))  { type = 9; goto gotit; }
+
+    /* binary operations */
+    if (!strcmp (argv[i], "^"))      { type = 8; goto gotit; }
+
+    if (!strcmp (argv[i], "@"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "/"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "*"))      { type = 7; goto gotit; }
+    if (!strcmp (argv[i], "%"))      { type = 7; goto gotit; }
+
+    if (!strcmp (argv[i], "+"))      { type = 6; goto gotit; }
+    if (!strcmp (argv[i], "-"))      { type = 6; goto gotit; }
+	
+    if (!strcmp (argv[i], "&"))      { type = 5; goto gotit; }
+    if (!strcmp (argv[i], "|"))      { type = 5; goto gotit; }
+
+    if (!strcmp (argv[i], "<"))      { type = 4; goto gotit; }
+    if (!strcmp (argv[i], ">"))      { type = 4; goto gotit; }
+    if (!strcmp (argv[i], "=="))     { type = 4; strcpy (argv[i], "E"); goto gotit; }
+    if (!strcmp (argv[i], "!="))     { type = 4; strcpy (argv[i], "N"); goto gotit; }
+    if (!strcmp (argv[i], "<="))     { type = 4; strcpy (argv[i], "L"); goto gotit; }
+    if (!strcmp (argv[i], ">="))     { type = 4; strcpy (argv[i], "G"); goto gotit; }
+    if (!strcmp (argv[i], ">>"))     { type = 4; strcpy (argv[i], "U"); goto gotit; }
+    if (!strcmp (argv[i], "<<"))     { type = 4; strcpy (argv[i], "D"); goto gotit; }
+
+    if (!strcmp (argv[i], "&&"))     { type = 3; strcpy (argv[i], "A"); goto gotit; }
+    if (!strcmp (argv[i], "||"))     { type = 3; strcpy (argv[i], "O"); goto gotit; }
+
+    if (!strcmp (argv[i], "("))      { type = 2; goto gotit; }
+    if (!strcmp (argv[i], ")"))      { type = 1; goto gotit; }
+
+  gotit:
+    /* choose how to deal with object */
+    switch (type) {
+      case 8:  /* exponentiation: 2^2^3 = 64 != 256 (precedence is right-to-left, not left-to-right!) */
+	/* pop previous, higher operators from OP stack to stack */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type > type); j--) {
+	  move_stack (&stack[Nstack], &op_stack[j]);
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	/* push operator on OP stack */
+	assign_stack (&op_stack[Nop_stack], argv[i], type);
+	Nop_stack ++;
+	break;
+      case 9: /* unary OPs */
+      case 7: /* binary OPs */
+      case 6:
+      case 5: 
+      case 4: 
+      case 3: 
+	/* pop previous, higher or equal operators from OP stack to stack */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type >= type); j--) {
+	  move_stack (&stack[Nstack], &op_stack[j]);
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	/* push operator on OP stack */
+	assign_stack (&op_stack[Nop_stack], argv[i], type);
+	Nop_stack ++;
+	break;
+      case 2:  
+	/* push operator on OP stack */
+	assign_stack (&op_stack[Nop_stack], argv[i], type);
+	Nop_stack ++;
+	break;
+      case 1: 
+	/* pop rest of operators from OP stack to stack, looking for '(' */
+	for (j = Nop_stack - 1; (j >= 0) && (op_stack[j].type != 2); j--) {
+	  move_stack (&stack[Nstack], &op_stack[j]);
+	  Nstack ++;
+	  Nop_stack --;
+	}
+	if ((j == -1) || (op_stack[j].type != 2)) {
+	  push_error ("syntax error: mismatched parenthesis");
+	  Nstack = 0;
+	  goto cleanup;
+	}
+	Nop_stack --;
+	break;
+      case 0:
+	/* place the value (number or vector/matrix name) on stack */
+	/* value of 'X' is used as sentinel until we sort out values */
+	assign_stack (&stack[Nstack], argv[i], 'X');
+	Nstack ++;
+	break;
+    }
+  }
+
+  /* dump remaining operators on stack, checking for ')' */
+  for (j = Nop_stack - 1; j >= 0; j--) {
+    if (op_stack[j].type == 2) {
+      push_error ("syntax error: mismatched parenthesis");
+      Nstack = 0;
+      goto cleanup;
+    }
+    move_stack (&stack[Nstack],  &op_stack[j]);
+    Nstack ++;
+  }
+
+cleanup: 
+  /*** free up unused stack space ***/
+
+  // If we parsed everything above, there should not be any un-freed op_stacks at this
+  // point.  However, if we had a syntax error, we will have op_stack entries left behind.
+  delete_stack (op_stack, NSTACK);
+  free (op_stack);
+
+  // XXX there should not be any data on higher stack entries
+  // clean_stack (&stack[Nstack], NSTACK - Nstack);
+  REALLOCATE (stack, StackVar, MAX (Nstack, 1));
+  *nstack = Nstack;
+
+  for (i = 0; i < argc; i++) {
+    free (argv[i]);
+  }
+  free (argv);
+
+# if (DUMPSTACK)
+  for (i = 0; i < Nstack; i++) {
+    gprint (GP_ERR, "%s ", stack[i].name);
+  }
+  if (Nstack > 0) gprint (GP_ERR, "\n");
+  for (i = 0; i < Nstack; i++) {
+    gprint (GP_ERR, "%d ", stack[i].type);
+  }
+  if (Nstack > 0) gprint (GP_ERR, "\n");
+# endif
+
+  return (stack);
+
+}
+
+/* here are the rules for parsing a math AOL line to RPN:
+
+1) if object is a number, push on stack
+2) if object is a third order operand (exp, sin, cos), push on op stack
+3) if object is an open paren, push on op stack,
+4) if object is a second order operand, push on stack
+5) if object is a first order operand, pop all second order operands from stack 
+until paren, push on stack
+6) if object is an end paren, pop all objects from stack until paren, 
+pop next stack, if third order op
+7) if end of line, pop all remaining objects, second order first, etc.
+   
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/dvomath.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/dvomath.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/dvomath.c	(revision 16632)
@@ -0,0 +1,103 @@
+# include "opihi.h"
+
+/* return value on success is temp vector/buffer name or scalar value return value on error is NULL, all
+   internals freed.  errors are sent to error stack.  may be printed by calling function */
+
+/* XXX this function breaks the elements of the line into objects, numbers, and operators.  it
+ * then converts the list to an RPN expresssion.  it then evaluates the expression.  if an
+ * expression is not a valid math expression (string - string), it results in an error.  The
+ * problem is that elements of a valid expression may be invalid as expressions on their own
+ * (eg, string consisting of word-word).  this function probably should be somewhat smarter
+ * about breaking down items into strings and objects.  for the time being, the user must
+ * protect string items with double quotes for safety.
+ */
+   
+char *dvomath (int argc, char **argv, int *size, int validsize) {
+  
+  int  i, Nstack, Ncstack;
+  char   **cstack, *outname;
+  StackVar *stack;
+  Buffer *buf;
+  Vector *vec;
+
+  buf = NULL;
+  vec = NULL;
+  ALLOCATE (outname, char, 256);
+
+  /* take char array with expression, convert to important elements */
+  cstack = isolate_elements (argc, argv, &Ncstack); 
+
+  /* generate RPN stack from cstack arguments */
+  stack = convert_to_RPN (Ncstack, cstack, &Nstack);
+  if (Nstack < 1) goto error;
+
+  /* distinguish scalar, vector, matrix, check dimensions */
+  *size = check_stack (stack, Nstack, validsize);
+  if (*size < 0) goto error;
+
+  switch (*size) {
+    case 0:
+      break;
+    case 1:  /* allocate temp vector */
+      vec = NULL;
+      for (i = 0; (i < 1000) && (vec == NULL); i++) {
+	sprintf (outname, "tmp%03d", i);
+	vec = SelectVector (outname, NEWVECTOR, FALSE);
+      }
+      if (vec == NULL) { 
+	push_error ("too many tmp vectors");
+	goto error;
+      }
+      break;
+    case 2:  /* allocate temp buffer */
+      buf = NULL;
+      for (i = 0; (i < 1000) && (buf == NULL); i++) {
+	sprintf (outname, "tmp%03d", i);
+	buf = SelectBuffer (outname, NEWBUFFER, FALSE);
+      }
+      if (buf == NULL) {
+	push_error ("too many tmp buffers");
+	goto error;
+      }
+      break;
+    default:
+      goto error;
+  }
+
+  /* evaluate operations, free stack on error */
+  Ncstack = Nstack;
+  if (!evaluate_stack (stack, &Nstack)) {
+    if (*size == 1) DeleteVector (vec);
+    if (*size == 2) DeleteBuffer (buf);
+    goto error;
+  }
+
+  switch (*size) {
+    case 0:
+      if (Ncstack == 1) {
+	  /* use exact input work */
+	  sprintf (outname, "%s", stack[0].name);
+      } else {
+	  sprintf (outname, "%.12g", stack[0].Float);
+      }
+      break;
+
+    case 1:
+      MoveVector (vec, stack[0].vector);
+      break;
+  
+    case 2:
+      MoveBuffer (buf, stack[0].buffer);
+      break;
+  }
+
+  clean_stack (stack, Nstack);
+  free (stack);
+  return (outname);
+
+error:  
+  clean_stack (stack, Nstack);
+  free (stack);
+  free (outname);
+  return (NULL);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/errors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/errors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/errors.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "opihi.h"
+
+static char errorline[1024];
+
+int init_error () {
+
+  bzero (errorline, 1024);
+  return (TRUE);
+}
+
+int push_error (char *line) {
+
+  bzero (errorline, 1024);
+  strncpy (errorline, line, 1023);
+  return (TRUE);
+}
+
+int print_error () {
+
+  gprint (GP_ERR, "%s\n", errorline);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/evaluate_stack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/evaluate_stack.c	(revision 16632)
@@ -0,0 +1,209 @@
+# include "opihi.h"
+# define VERBOSE 0
+
+# define TWO_OP(A,B,FUNC) \
+  if (!strncasecmp (&stack[i - 2].type, A, 1) && !strncasecmp (&stack[i - 1].type, B, 1)) \
+    status = FUNC (&tmp_stack, &stack[i - 2], &stack[i - 1], stack[i].name); 
+
+# define ONE_OP(A,FUNC) \
+  if (!strncasecmp (&stack[i - 1].type, A, 1)) \
+    status = FUNC (&tmp_stack, &stack[i - 1], stack[i].name); 
+
+int evaluate_stack (StackVar *stack, int *Nstack) {
+  
+  int i, j, Nvar, Nout, status;
+  char line[512];
+  StackVar tmp_stack;
+  Nout = Nvar = 0;
+
+  status = TRUE;
+  init_stack (&tmp_stack);
+
+  if (*Nstack == 1) {
+    if (stack[0].type == 'S') {
+      clear_stack (&tmp_stack);
+      return (TRUE);
+    }
+    if (stack[0].type == 'V') {
+      /* need to make a copy so we set output value? */
+      V_unary (&tmp_stack, &stack[0], "=");
+      move_stack (&stack[0], &tmp_stack);
+      return (TRUE);
+    }
+    if (stack[0].type == 'M') {
+      /* need to make a copy so we set output value? */
+      M_unary (&tmp_stack, &stack[0], "=");
+      move_stack (&stack[0], &tmp_stack);
+      return (TRUE);
+    }
+    push_error ("syntax error: not a math expression");
+    clear_stack (&tmp_stack);
+    return (FALSE);
+  }      
+    
+  for (i = 0; i < *Nstack; i++) {
+
+    if (VERBOSE) {
+      gprint (GP_ERR, "%d: ", i);
+      for (j = 0; j < *Nstack; j++) {
+	gprint (GP_ERR, "%s ", stack[j].name);
+      }
+      if (*Nstack > 0) gprint (GP_ERR, "\n");
+      gprint (GP_ERR, "%d: ", i);
+      for (j = 0; j < *Nstack; j++) {
+	gprint (GP_ERR, "%d ", stack[j].type);
+      }
+      if (*Nstack > 0) gprint (GP_ERR, "\n");
+    }
+
+    /***** binary operators *****/
+    if ((stack[i].type >= 3) && (stack[i].type <= 8)) {
+
+      if (i < 2) {  /* need two variables to operate on */
+	sprintf (line, "syntax error: binary operator with one operand: %s\n", stack[i].name);
+	push_error (line);
+	clear_stack (&tmp_stack);
+	return (FALSE);
+      }
+
+      status = FALSE;
+      TWO_OP ("M","M",MM_binary);
+      TWO_OP ("M","V",MV_binary);
+      TWO_OP ("M","S",MS_binary);
+      TWO_OP ("V","M",VM_binary);
+      TWO_OP ("V","V",VV_binary);
+      TWO_OP ("V","S",VS_binary);
+      TWO_OP ("S","M",SM_binary);
+      TWO_OP ("S","V",SV_binary);
+      TWO_OP ("S","S",SS_binary);      
+      TWO_OP ("W","W",WW_binary);      
+      TWO_OP ("W","S",WW_binary);      
+      TWO_OP ("S","W",WW_binary);      
+      
+      if (!status) {
+	sprintf (line, "syntax error: invalid operand for binary operation: %s or %s\n", stack[i-1].name, stack[i-2].name);
+	push_error (line);
+	clear_stack (&tmp_stack);
+	return (FALSE);
+      }
+      move_stack (&stack[i-2], &tmp_stack);
+      delete_stack (&stack[i-1], 2);
+      for (j = i + 1; j < *Nstack; j++) {
+	move_stack (&stack[j - 2], &stack[j]);
+      }
+      *Nstack -= 2;
+      i -= 2;
+      init_stack (&tmp_stack);
+      continue;
+    }
+
+    /***** unary operators **/
+    if (stack[i].type == 9) {
+
+      if (i < 1) {  /* need one variable to operate on */
+	push_error ("syntax error: unary operator with no operand");
+	clear_stack (&tmp_stack);
+	return (FALSE);
+      }
+
+      ONE_OP ("M", M_unary);
+      ONE_OP ("V", V_unary);
+      ONE_OP ("S", S_unary);
+
+      /* there are no valid unary string operators */
+      if (!strncasecmp (&stack[i - 1].type, "W", 1)) {
+	push_error ("syntax error: no valid string unary ops");
+	clear_stack (&tmp_stack);
+	return (FALSE);
+      }
+
+      move_stack (&stack[i-1], &tmp_stack);
+      delete_stack (&stack[i], 1);
+      for (j = i + 1; j < *Nstack; j++) {
+	move_stack (&stack[j - 1], &stack[j]);
+      }
+      init_stack (&tmp_stack);
+      *Nstack -= 1;
+      i -= 1;
+      continue;
+    } 
+  }
+  clear_stack (&tmp_stack);
+
+  if (*Nstack > 1) {
+    push_error ("syntax error in evaluation");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+/* copy data to new stack variable */
+void copy_stack (StackVar *stack1, StackVar *stack2) {
+  stack1[0].name   = stack2[0].name  ;
+  stack1[0].type   = stack2[0].type  ;
+  stack1[0].ptr    = stack2[0].ptr   ;
+  stack1[0].buffer = stack2[0].buffer;
+  stack1[0].vector = stack2[0].vector;
+  stack1[0].Float  = stack2[0].Float ;
+  if (!strncasecmp (&stack1[0].type, "S", 1)) {
+    stack1[0].ptr    = &stack1[0].Float;
+  }
+}
+
+/* replace data with new stack variable */
+void move_stack (StackVar *stack1, StackVar *stack2) {
+  clear_stack (stack1);
+  copy_stack (stack1, stack2);
+  stack2[0].name = NULL;
+}
+
+/* delete name and data */
+void clean_stack (StackVar *stack, int Nstack) {
+
+  int i;
+
+  for (i = 0; i < Nstack; i++) {
+    if (IsBufferPtr (stack[i].buffer) && (stack[i].type == 'm')) {
+      if (VERBOSE) gprint (GP_ERR, "free %s (buff) (%lx)\n", stack[i].name, (long) stack[i].buffer);
+      free (stack[i].buffer[0].header.buffer);
+      free (stack[i].buffer[0].matrix.buffer);
+      free (stack[i].buffer);
+      stack[i].buffer = NULL;
+    }	
+    if (IsVectorPtr (stack[i].vector) && (stack[i].type == 'v')) {
+      if (VERBOSE) gprint (GP_ERR, "free %s (vect) (%lx)\n", stack[i].name, (long) stack[i].vector);
+      free (stack[i].vector[0].elements);
+      free (stack[i].vector);
+      stack[i].vector = NULL;
+    }	
+    if (VERBOSE) gprint (GP_ERR, "free %s (name) (%d) (%lx)\n", stack[i].name, i, (long) stack[i].name);
+    clear_stack (&stack[i]);
+  }
+
+}
+
+/* delete name only, not data */
+void delete_stack (StackVar *stack, int Nstack) {
+  int i;
+  for (i = 0; i < Nstack; i++) {
+    clear_stack (&stack[i]);
+  }
+}
+
+void init_stack (StackVar *stack) {
+  stack[0].buffer = NULL;
+  stack[0].vector = NULL;
+  stack[0].name = NULL;
+}
+
+void assign_stack (StackVar *stack, char *name, int type) {
+  stack->name = strcreate (name);
+  stack->type = type;
+}
+
+void clear_stack (StackVar *stack) {
+  if (stack->name == NULL) return;
+  free (stack->name);
+  stack->name = NULL;
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/exec_loop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/exec_loop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/exec_loop.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "opihi.h"
+
+int exec_loop (Macro *loop) {
+
+  void *Signal;
+  int j, status, ThisList;
+  char *line;
+  
+  /* increase the shell level (Nlists) by one */
+  ThisList = increase_list_depth();
+  if (ThisList == 0) abort();
+
+  /* copy the macro to the current list */
+  for (j = 0; j < loop[0].Nlines; j++) {
+    add_listentry (ThisList, loop[0].line[j]);
+  }
+
+  /* set up interrupts */
+  Signal = signal (SIGINT, handle_interrupt);
+  interrupt = FALSE;
+
+  /* process the list */
+  loop_next = loop_break = loop_last = FALSE;
+  status = TRUE;
+
+  while (!interrupt) {
+    line = get_next_listentry (ThisList);
+    if (line == NULL) break;
+    status = multicommand (line);
+    free (line);
+    if (auto_break && !status) loop_break = TRUE;
+    if (loop_break || loop_last || loop_next) break;
+  }
+  signal (SIGINT, Signal);
+
+  /* free remaining lines on the list, free the list, decrement the shell level */
+  /*** can we free a list which is not the bottom lists? */
+  decrease_list_depth();
+
+  if (loop_break) return (FALSE);
+  return (TRUE);
+}
+
+/** note that the list number runs from 1 - Nlists+1 **/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/expand_vars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/expand_vars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/expand_vars.c	(revision 16632)
@@ -0,0 +1,145 @@
+# include "opihi.h"
+
+char *expand_vars (char *line) {
+
+  char *L, *N, *V0, *V1, *Val, *newline, *c, found;
+  int done, MacroDepth, NLINE, Noff;
+
+  if (line == NULL) return (NULL);
+  MacroDepth = GetMacroDepth ();
+
+  found = FALSE;
+  NLINE = MAX (128, strlen(line));
+  ALLOCATE (newline, char, NLINE);  /* WARNING: this limits the length of the input line */
+
+  V0 = thiscomm (line);
+  if (V0 && !strncmp ("while", V0, strlen(V0))) {
+      // special case: don't expand variables in while () statement
+      strcpy (newline, line);
+      free (line);
+      return (newline);
+  }
+  free (V0);
+
+  /* look for form $a$b..$n and expand only the last ones */
+  for (L = line, N = newline; *L != 0; N++, L++) {  /* loop until end of line */
+    for (done = FALSE; !done;) {
+      if (*L == 0) done = TRUE;
+      if (*L == '$') {
+	V1 = aftervar(L);
+	if ((V1 != NULL) && (*V1 != '$')) done = TRUE;
+	if (V1 == NULL) done = TRUE;
+      }
+      if (!done) { 
+	*N = *L;
+	 L++; 
+	 N++;
+	 if (N - newline >= NLINE - 5) {
+	   Noff = N - newline;
+	   NLINE += 128;
+	   REALLOCATE (newline, char, NLINE);
+	   N = newline + Noff;
+	 }
+      }
+    }
+
+    if (*L == 0) break;
+
+    V1 = aftervar (L);           /* V1 points to the first non-WHITESPACE after the variable */
+    V0 = thisvar (L);            /* V0 points to the name of the var */
+    /* note: V1 points to a fraction of L, it does not need to be freed */
+
+    /* no variable name */
+    if (V0 == NULL) {
+      *N = *L;
+      if (N - newline >= NLINE - 5) {
+	Noff = N - newline;
+	NLINE += 128;
+	REALLOCATE (newline, char, NLINE);
+	N = newline + Noff;
+      }
+      continue;
+    }
+
+    /* variable assignment (skip these variables) */
+    if ((L == line) && (V1 != NULL)) {
+      if ((*V1 == '=') || !strcmp (V1, "++") || !strcmp (V1, "--")) {
+	*N = *L;
+	free (V0);
+	if (N - newline >= NLINE - 5) {
+	  Noff = N - newline;
+	  NLINE += 128;
+	  REALLOCATE (newline, char, NLINE);
+	  N = newline + Noff;
+	}
+	continue;
+      }
+    }
+
+    found = TRUE;
+    for (c = V0; isdigit(*c); c++); /* test if this is a macro argument variable (ie, $1.2) */
+    if (*c == 0) {  /* all digit var == macro parameter */
+      if (!MacroDepth) {
+	gprint (GP_ERR, "not in a macro\n");
+	goto error;
+      } else { /* if we are executing a macro, attach the list depth to the front, pass on down the line */
+	// XXX this is limiting!!!
+	ALLOCATE (c, char, 1024);
+	sprintf (c, "%d.%s", MacroDepth, V0);
+	free (V0);
+	V0 = c;
+      }
+    }
+
+    Val = get_variable_ptr (V0);
+    if (Val == NULL) {   /* var was not found! */
+      gprint (GP_ERR, "variable %s not found\n", V0);
+      goto error;
+    }
+    for (; *Val != 0; N++, Val++)  {
+      *N = *Val; /* place the value of the variable in the newline */
+      if (N - newline >= NLINE - 5) {
+	Noff = N - newline;
+	NLINE += 128;
+	REALLOCATE (newline, char, NLINE);
+	N = newline + Noff;
+      }
+    }
+    N--; /* we overshoot on last loop */
+
+    /* skip past the variable in the source line */
+    /* L currently points at $ */
+    L++;
+    if (*L == '?') L++;  /* skip past ? in $?name */
+
+    while (ISVAR(*L)) L++;
+    L--; /* we overshoot */
+
+    if (V0 != NULL) free (V0);
+  }
+
+  *N = 0;
+  free (line);
+  REALLOCATE (newline, char, strlen (newline) + 1);
+  if (found) { /* try again for new variables */
+    newline = expand_vars (newline);
+  }
+  return (newline);
+
+error:
+  free (line);
+  free (V0);
+  free (newline);
+  return (NULL);
+}
+
+
+  /************************
+    we go through the line looking for the dollar signs ($) marking the 
+    variables.  We don't expand a variable if it is the first thing on the line 
+    AND it is followed by an equals sign.  
+    that is, don't expand if:
+    V0 = NULL ($ is last non-blank char on line -- no variable) or
+    V1[0] is = (assignment of variable value), AND L == line (ie, at beginning of line)
+    *************************/
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/expand_vectors.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/expand_vectors.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/expand_vectors.c	(revision 16632)
@@ -0,0 +1,176 @@
+# include "opihi.h"
+
+char *expand_vectors (char *line) {
+
+  char *newline, *tmpline, strValue[128], *val;
+  char *L, *N, *p, *q, *p2, *w;
+  int n, I, J, size, showLength, NLINE, Noff, isBuffer, inRange;
+  float *ptr;
+  double f1;
+  Vector *vec;
+  Buffer *buf;
+
+  if (line == NULL) return (NULL);
+
+  NLINE = MAX (128, strlen(line));
+  ALLOCATE (newline, char, NLINE);
+
+  /* look for form fred[stuff] */
+  /* skip first word (command) */
+  L = nextword (line);
+  if (L == NULL) {
+    free (newline);
+    return (line);
+  }
+
+  n = L - line;
+  strncpy (newline, line, n);
+  N = newline + n;
+  while (1) {
+    /* find square-bracket pair [..] */
+    p = strchr (L, '[');
+    q = strchr (L, ']');
+    if ((p == NULL) && (q != NULL)) goto dumpline;
+    if ((p != NULL) && (q == NULL)) goto dumpline;
+    if ((p == NULL) && (q == NULL)) goto dumpline;
+    if (p > q) goto dumpline; /* odd state: unmatched pair: ][ */
+
+    /* find vector subscript */
+    n = (int) (q - p - 1);
+    val = NULL;
+    showLength = FALSE;
+    if (n == 0) {
+      showLength = TRUE;
+    } else {
+      tmpline = strncreate (p+1, n);
+      val = dvomath (1, &tmpline, &size, 0);
+      free (tmpline);
+      if (val == NULL) goto dumpline; /* not a valid vector subscript */
+    }
+    I = 0; 
+    if (val != NULL) {
+      I = atoi (val);
+      free (val);
+    }      
+
+    /* if a second [..] immediately follows, we are a buffer, not a vector */
+    isBuffer = FALSE;
+    if (*(q + 1) == '[') {
+      p2 = strchr (q + 1, ']');
+      if (p2 != NULL) {
+	if (showLength) {
+	  gprint (GP_ERR, "unsupported : name[][..]\n"); 
+	  goto asVector;
+	}
+
+	isBuffer = TRUE;
+
+	/* find buffer second subscript */
+	n = (int) (p2 - q - 2);
+	val = NULL;
+	if (n == 0) {
+	  gprint (GP_ERR, "unsupported : name[..][]\n"); 
+	  isBuffer = FALSE;
+	  goto asVector;
+	} 
+	tmpline = strncreate (q+2, n);
+	val = dvomath (1, &tmpline, &size, 0);
+	free (tmpline);
+	if (val == NULL) {
+	  isBuffer = FALSE;
+	  goto asVector; /* not a valid vector subscript */
+	}
+	J = 0; 
+	if (val != NULL) {
+	  J = atoi (val);
+	  free (val);
+	}      
+      }
+      q = p2;
+    }
+
+  asVector:
+    /* find vector/buffer name */
+    for (w = p - 1; (w >= line) && !OHANA_WHITESPACE(*w) && (isalnum(*w) || (*w == ':') || (*w == '_')); w--);
+    w ++;
+    n = (int)(p - w);
+    tmpline = strncreate (w, n);
+
+    if (isBuffer) {
+      if ((buf = SelectBuffer (tmpline, OLDBUFFER, TRUE)) == NULL) goto dumpline;
+
+      /* find buffer element */
+      inRange = TRUE;
+      inRange &= (I <  +1*buf[0].header.Naxis[0]);
+      inRange &= (I >= -1*buf[0].header.Naxis[0]);
+      inRange &= (J <  +1*buf[0].header.Naxis[1]);
+      inRange &= (J >= -1*buf[0].header.Naxis[1]);
+      if (!inRange) {
+	gprint (GP_ERR, "buffer subscript out of range\n"); 
+	goto escape;
+      }
+      if (I < 0) I += buf[0].header.Naxis[0];
+      if (J < 0) J += buf[0].header.Naxis[1];
+      ptr = (float *) buf[0].matrix.buffer;
+      f1 = ptr[I + J*buf[0].header.Naxis[0]];
+    } else {
+      if ((vec = SelectVector (tmpline, OLDVECTOR, TRUE)) == NULL) goto dumpline;
+
+      /* find vector element */
+      if ((I >= vec[0].Nelements) || (I < -1*vec[0].Nelements)) {
+	gprint (GP_ERR, "vector subscript out of range\n"); 
+	goto escape;
+      }
+      if (showLength) {
+	f1 = vec[0].Nelements;
+      } else {
+	if (I < 0) I += vec[0].Nelements;
+	f1 = vec[0].elements[I];
+      }
+    }
+
+    free (tmpline);
+    if ((int)f1 == f1) 
+      snprintf (strValue, 128, "%.0f", f1);
+    else
+      snprintf (strValue, 128, "%.9g", f1);
+
+    /* interpolate vector element into newline (being accumulated) */
+    size = (N - newline) + (w - L) + strlen(strValue);
+    if (size >= NLINE) {
+      Noff = N - newline;
+      NLINE += 128 + strlen(strValue) + (w - L);
+      REALLOCATE (newline, char, NLINE);
+      N = newline + Noff;
+    }
+
+    n = (int) (w - L);
+    strncpy (N, L, n);
+    N += n;
+    n = strlen (strValue);
+    strncpy (N, strValue, n);
+    N += n;
+    L = q + 1;
+  }
+
+dumpline:
+  size = (N - newline) + strlen(L);
+  if (size >= NLINE) {
+    Noff = N - newline;
+    NLINE += 128 + strlen(L);
+    REALLOCATE (newline, char, NLINE);
+    N = newline + Noff;
+  }
+
+  n = strlen (L);
+  strncpy (N, L, n);
+  N[n] = 0;
+  free (line);
+  return (newline);
+  
+escape:
+  free (line);
+  free (newline);
+  return (NULL);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/gprint.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/gprint.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/gprint.c	(revision 16632)
@@ -0,0 +1,269 @@
+# include "shell.h"
+
+/* we need to control the output destinations a bit carefully
+   in the pantasks_server mode.  The server needs to be able to 
+   send the output to a specific output device (eg, logging file)
+   of to save it within an internal buffer */
+
+/* further notes:
+   gprintf (int destination, char *format, ...);
+
+   the destination may be GP_LOG or GP_ERR.  by default, these go to stdout and
+   stderr.  either one may be redirected to another file or to a buffer.  as a
+   stand-along program, the outfile command redirects the GP_LOG output to an
+   alternate output file.  in the server mode, we redirect LOG to a standard log
+   file and ERR to a standard error file for server messages.  Commands executed
+   by the client have both streams returned to the client in turn, and are in
+   turn sent to stderr or the current stdout destination.
+
+   each thread has an independently set output destination.
+
+   option 1: NULL for invalid element:
+
+     a stream is either set to a FILE or an IOBuffer.  when it is set to a FILE,
+     the IOBuffer is freed and set to NULL.  when it is an IOBuffer, the file
+     pointer is closed and set to NULL.  setting a new FILE results in the 
+     IObuffer being freed and an already opened FILE to be flushed and closed.
+*/
+
+static gpStream *streams = NULL;
+static int Nstreams = 0;
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void gprintInit () {
+
+  int N;
+  pthread_t id;
+
+  /* need to use a mutex to prevent two threads from initing simultaneously */
+  pthread_mutex_lock (&mutex);
+
+  if (streams == NULL) {
+    Nstreams = 2;
+    ALLOCATE (streams, gpStream, Nstreams);
+  } else {
+    Nstreams += 2;
+    REALLOCATE (streams, gpStream, Nstreams);
+  }
+
+  /* create two output streams for this thread: LOG and ERR */
+  id = pthread_self();
+
+  N = Nstreams - 2;
+  streams[N].dest = GP_LOG;
+  streams[N].file = stdout;
+  streams[N].name = strcreate ("stdout");
+
+  ALLOCATE (streams[N].buffer, IOBuffer, 1);
+  InitIOBuffer (streams[N].buffer, 64);
+  streams[N].mode = GP_FILE;
+  streams[N].thread = id;
+
+  N = Nstreams - 1;
+  streams[N].dest = GP_ERR;
+  streams[N].file = stderr;
+  streams[N].name = strcreate ("stderr");
+
+  ALLOCATE (streams[N].buffer, IOBuffer, 1);
+  InitIOBuffer (streams[N].buffer, 64);
+  streams[N].mode = GP_FILE;
+  streams[N].thread = id;
+
+  pthread_mutex_unlock (&mutex);
+}
+
+gpStream *gprintGetStream (gpDest dest) {
+
+  int i;
+  pthread_t id;
+
+  id = pthread_self();
+
+  /* find the existing output stream which matches */
+  for (i = 0; i < Nstreams; i++) {
+    if (streams[i].dest != dest) continue;
+    if (!pthread_equal (streams[i].thread, id)) continue;
+    return (&streams[i]);
+  }
+  fprintf (stderr, "programming error: gprintInit not called for thread\n");
+  abort ();
+}
+
+void gprintSetBuffer (gpDest dest) {
+
+  gpStream *stream;
+
+  stream = gprintGetStream (dest);
+
+  /* if we have an open file: flush it, close it, null it */
+  if (stream[0].file != NULL) {
+    fflush (stream[0].file);
+    if (stream[0].file == stdout) goto skip_close;
+    if (stream[0].file == stderr) goto skip_close;
+    fclose (stream[0].file);
+
+  skip_close:
+    stream[0].file = NULL;
+  }
+  
+  if (stream[0].buffer == NULL) {
+    ALLOCATE (stream[0].buffer, IOBuffer, 1);
+    InitIOBuffer (stream[0].buffer, 64);
+  } else {
+    FlushIOBuffer (stream[0].buffer);
+  }
+  
+  /* this element may be redundant with the NULL state of file and buffer */
+  stream[0].mode = GP_BUFF;
+}
+
+IOBuffer *gprintGetBuffer (gpDest dest) {
+
+  gpStream *stream;
+  stream = gprintGetStream (dest);
+  return (stream[0].buffer);
+}
+
+void gprintSetFileAllThreads (gpDest dest, char *filename) {
+
+  int i;
+
+  for (i = 0; i < Nstreams; i++) {
+    if (streams[i].dest != dest) continue;
+    gprintSetFile (&streams[i], dest, filename);
+  }
+  return;
+}
+
+void gprintSetFileThisThread (gpDest dest, char *filename) {
+
+  gpStream *stream;
+  stream = gprintGetStream (dest);
+
+  gprintSetFile (stream, dest, filename);
+  return;
+}
+
+void gprintSetFile (gpStream *stream, gpDest dest, char *filename) {
+
+  /* if we have an open buffer, free it and null it */
+  if (stream[0].buffer != NULL) {
+    FreeIOBuffer (stream[0].buffer);
+    free (stream[0].buffer);
+    stream[0].buffer = NULL;
+  }
+
+  /* if we have an open file, flush it and close it */
+  if (stream[0].file != NULL) {
+    fflush (stream[0].file);
+    if (stream[0].file == stdout) goto skip_close;
+    if (stream[0].file == stderr) goto skip_close;
+    fclose (stream[0].file);
+  }
+skip_close:
+
+  // if NULL, reuse exising stream name
+  if (filename != NULL) {
+    free (stream[0].name);
+    stream[0].name = strcreate (filename);
+  }
+
+  /* we allow the user to set stdout to ERR and stderr to LOG if they want */
+  if (!strcmp (stream[0].name, "stdout")) {
+    stream[0].file = stdout;
+    goto skip_open;
+  }
+  if (!strcmp (stream[0].name, "stderr")) {
+    stream[0].file = stderr;
+    goto skip_open;
+  }
+  
+  /* open the file */
+  stream[0].file = fopen (stream[0].name, "a");
+  if (stream[0].file == NULL) {
+    fprintf (stderr, "cannot open file %s\n", stream[0].name);
+    free (stream[0].name);
+    stream[0].file = (dest == GP_LOG) ? stdout : stderr;
+    stream[0].name = (dest == GP_LOG) ? strcreate ("stdout") : strcreate("stderr");
+  }
+
+skip_open:
+  stream[0].mode = GP_FILE;
+  return;
+}
+
+FILE *gprintGetFile (gpDest dest) {
+
+  gpStream *stream;
+  stream = gprintGetStream (dest);
+  return (stream[0].file);
+}
+
+char *gprintGetName (gpDest dest) {
+
+  gpStream *stream;
+  stream = gprintGetStream (dest);
+  return (stream[0].name);
+}
+
+int gprint (gpDest dest, char *format, ...) {
+
+  int status;
+  gpStream *stream;
+  va_list argp;  
+
+  stream = gprintGetStream (dest);
+
+  va_start (argp, format);
+  
+  // gprint (GP_ERR, "GP_FILE: %d\n", GP_FILE);
+  // gprint (GP_ERR, "GP_BUFF: %d\n", GP_BUFF);
+  // gprint (GP_ERR, "mode: %d\n", stream[0].mode);
+
+  if (stream[0].mode == GP_FILE) {
+    // gprint (GP_ERR, "printing to FILE\n");
+    status = vfprintf (stream[0].file, format, argp);
+    if (status < 0) {
+      abort();
+    }
+  } else {
+    // gprint (GP_ERR, "printing to BUFFER\n");
+    vPrintIOBuffer (stream[0].buffer, format, argp);
+  }
+  va_end (argp);
+  return (TRUE);
+}
+
+int gwrite (char *buffer, int size, int N, gpDest dest) {
+
+  int Nbyte;
+  IOBuffer *outbuff;
+  gpStream *stream;
+
+  stream = gprintGetStream (dest);
+
+  if (stream[0].mode == GP_FILE) {
+    fwrite (buffer, size, N, stream[0].file);
+  } else {
+    outbuff = stream[0].buffer;
+    Nbyte = size * N;
+    if (outbuff[0].Nbuffer + Nbyte >= outbuff[0].Nalloc) {
+      outbuff[0].Nalloc = outbuff[0].Nbuffer + Nbyte + 64;
+      REALLOCATE (outbuff[0].buffer, char, outbuff[0].Nalloc);
+    }
+    memcpy (&outbuff[0].buffer[outbuff[0].Nbuffer], buffer, Nbyte);
+    outbuff[0].Nbuffer += Nbyte;
+  }
+  return (TRUE);
+}
+
+/* I'm going to need to have different output targets for different threads
+   we can do this with these functions:
+
+   pthread_t pthread_self(void);
+   int pthread_equal(pthread_t thread1, pthread_t thread2);
+   // returns TRUE if equal, FALSE if not
+   
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/interrupt.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/interrupt.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/interrupt.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "opihi.h"
+
+static int Nint = 0;
+
+/* return FALSE if we are called many times in a row 
+   without a valid answer or any answer */
+
+void handle_interrupt (int input) {
+  
+  char string[64];
+  int Nask;
+
+  signal (SIGINT, SIG_IGN);
+
+  Nask = 0;
+  Nint ++;
+
+  // 3 ctrl-c in a row will interrupt regardless
+  if (Nint > 3) { 
+    interrupt = TRUE;
+    return;
+  }
+  if (Nint > 100) { 
+    exit (3);
+  }
+  
+  while (1) {
+    gprint (GP_ERR, "operation halted, continue? (y/n) ");
+    fscanf (stdin, "%s", string);
+    
+    if ((string[0] == 'y') || (string[0] == 'Y')) {
+      interrupt = FALSE;
+      signal (SIGINT, handle_interrupt);
+      Nint = 0;
+      return;
+    }
+
+    if ((string[0] == 'n') || (string[0] == 'N')) {
+      interrupt = TRUE;
+      signal (SIGINT, handle_interrupt);
+      Nint = 0;
+      return;
+    }
+    Nask ++;
+    if (Nask > 3) {
+      interrupt = TRUE;
+      signal (SIGINT, handle_interrupt);
+      Nint = 0;
+      return;
+    }
+  }  
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/isolate_elements.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/isolate_elements.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/isolate_elements.c	(revision 16632)
@@ -0,0 +1,206 @@
+# include "opihi.h"
+
+/* local private functions */
+void InsertValue (char c);
+void EndOfString (void);
+int IsAnOp (char *c);
+int IsTwoOp (char *c);
+
+/* local private static variables */
+int NCHAR, Nchar, Nout, NOUT;
+char **myOutput;
+
+char **isolate_elements (int Nin, char **in, int *nout) {
+  
+  int i, j, minus, negate, plus, posate, OpStat, SciNotation;
+
+  NOUT = Nin;
+  Nchar = Nout = 0;
+  NCHAR = 256;
+  ALLOCATE (myOutput, char *, NOUT);
+  ALLOCATE (myOutput[Nout], char, NCHAR);
+
+  for (i = 0; i < Nin; i++) {
+    for (j = 0; j < strlen(in[i]); j++) {
+      SciNotation = FALSE;
+      /* identify 'negate' or 'minus' ops */
+      negate = minus = FALSE;
+      if (in[i][j] == '-') { 
+	minus = TRUE;  
+	/* if - is first thing on line, must be a negator */
+	if ((Nout == 0) && (Nchar == 0)) {  
+	  minus = FALSE;
+	  negate = TRUE;
+	  goto skip1;
+	}
+	/* check previous entry on line */
+	if (Nchar) {
+	  OpStat = IsAnOp (myOutput[Nout]);
+	  if (myOutput[Nout][0] == ')') OpStat = FALSE;
+	} else {
+	  OpStat = IsAnOp (myOutput[Nout-1]);
+	  if (myOutput[Nout-1][0] == ')') OpStat = FALSE;
+	}
+	/* if - follows an operator, must be negator */
+	if (OpStat) {
+	  minus = FALSE;
+	  negate = TRUE;
+	  goto skip1;
+	}
+	/* if - follows 'e' is part of 1e-5 */
+	if (j == 0) goto skip1;
+	if ((in[i][j-1] == 'e') || (in[i][j-1] == 'E')) {
+	  SciNotation = TRUE;
+	  negate = minus = FALSE;
+	}
+      }
+    skip1:
+      /* idenfity 'posate' or 'plus' ops */
+      posate = plus = FALSE;
+      if (in[i][j] == '+') { 
+	plus = TRUE;  
+	/* if + is first thing on line, must be a posator */
+	if ((Nout == 0) && (Nchar == 0)) {  
+	  plus = FALSE;
+	  posate = TRUE;
+	  goto skip2;
+	}
+	/* check previous entry on line */
+	if (Nchar) {
+	  OpStat = IsAnOp (myOutput[Nout]);
+	  if (myOutput[Nout][0] == ')') OpStat = FALSE;
+	} else {
+	  OpStat = IsAnOp (myOutput[Nout-1]);
+	  if (myOutput[Nout-1][0] == ')') OpStat = FALSE;
+	}
+	/* if + follows an operator, must be posator */
+	if (OpStat) {
+	  plus = FALSE;
+	  posate = TRUE;
+	  goto skip2;
+	}
+	/* if + follows 'e' is part of 1e+5 */
+	if (j == 0) goto skip2;
+	if ((in[i][j-1] == 'e') || (in[i][j-1] == 'E')) {
+	  SciNotation = TRUE;
+	  posate = plus = FALSE;
+	}
+      }
+    skip2:
+      /* operators */
+      if (negate || minus || posate || plus || (IsAnOp (&in[i][j]) && !SciNotation)) {
+	if (posate) continue;
+	EndOfString ();
+	/* copy operator to myOutput[Nout] */
+	InsertValue (in[i][j]);
+	if (negate) InsertValue ('-');
+
+	if (IsTwoOp (&in[i][j])) {
+	  InsertValue (in[i][j+1]);
+	  j++;
+	} 
+	EndOfString ();
+	continue;
+      }
+      /* quoted string */
+      if (in[i][j] == '"') {
+	InsertValue (in[i][j]);
+	j++;
+	while ((j < strlen(in[i])) && (in[i][j] != '"')) {
+	  InsertValue (in[i][j]);
+	  j++;
+	}
+	if (in[i][j] != '"') continue;
+	/* 
+	  gprint (GP_ERR, "mismatched quotes\n");
+	  return (FALSE);
+	}
+	*/
+	InsertValue (in[i][j]);
+	EndOfString ();
+	continue;
+      }
+      /* not an operator, not a quoted string */
+      if (!OHANA_WHITESPACE (in[i][j])) {
+	InsertValue (in[i][j]);
+      } else {
+	EndOfString ();
+      }
+    }
+    EndOfString ();
+  }
+
+  /* one extra entry is allocated, free here */
+  free (myOutput[Nout]);
+  *nout = Nout;
+  return (myOutput);
+
+}
+
+void InsertValue (char c) {
+  myOutput[Nout][Nchar] = c;
+  Nchar ++;
+  if (Nchar >= NCHAR - 2) {
+    NCHAR += 256;
+    REALLOCATE (myOutput[Nout], char, NCHAR);
+  }
+  myOutput[Nout][Nchar] = 0;
+}
+
+void EndOfString () {
+  if (Nchar > 0) {
+    myOutput[Nout][Nchar] = 0;
+    Nout ++;
+    Nchar = 0;
+    
+    if (Nout >= NOUT - 1) {
+      NOUT += 10; 
+      REALLOCATE (myOutput, char *, NOUT); 
+    } 
+    NCHAR = 256;
+    ALLOCATE (myOutput[Nout], char, NCHAR); 
+  }
+}
+
+int IsAnOp (char *c) {
+
+  if (!strncmp (c, "*",  1)) return (TRUE);
+  if (!strncmp (c, "/",  1)) return (TRUE);
+  if (!strncmp (c, "+",  1)) return (TRUE);
+  if (!strncmp (c, "-",  1)) return (TRUE);
+  if (!strncmp (c, "^",  1)) return (TRUE);
+  if (!strncmp (c, "@",  1)) return (TRUE);
+  if (!strncmp (c, "(",  1)) return (TRUE);
+  if (!strncmp (c, ")",  1)) return (TRUE);
+  if (!strncmp (c, "&",  1)) return (TRUE);
+  if (!strncmp (c, "|",  1)) return (TRUE);
+  if (!strncmp (c, ">",  1)) return (TRUE);
+  if (!strncmp (c, "<",  1)) return (TRUE);
+  if (!strncmp (c, "<",  1)) return (TRUE);
+  if (!strncmp (c, "<<", 2)) return (TRUE);
+  if (!strncmp (c, ">>", 2)) return (TRUE);
+  if (!strncmp (c, "&&", 2)) return (TRUE);
+  if (!strncmp (c, "||", 2)) return (TRUE);
+  if (!strncmp (c, "==", 2)) return (TRUE);
+  if (!strncmp (c, "!=", 2)) return (TRUE);
+  if (!strncmp (c, "<=", 2)) return (TRUE);
+  if (!strncmp (c, ">=", 2)) return (TRUE);
+
+  return (FALSE);
+
+}
+
+int IsTwoOp (char *c) {
+
+  if (!strncmp (c, "<<", 2)) return (TRUE);
+  if (!strncmp (c, ">>", 2)) return (TRUE);
+  if (!strncmp (c, "&&", 2)) return (TRUE);
+  if (!strncmp (c, "||", 2)) return (TRUE);
+  if (!strncmp (c, "==", 2)) return (TRUE);
+  if (!strncmp (c, "!=", 2)) return (TRUE);
+  if (!strncmp (c, "<=", 2)) return (TRUE);
+  if (!strncmp (c, ">=", 2)) return (TRUE);
+
+  return (FALSE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_create.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_create.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_create.c	(revision 16632)
@@ -0,0 +1,113 @@
+# include "opihi.h"
+# define D_NLINES 100
+# define prompt "> "
+int macro_exec   PROTO((int, char **));
+
+int macro_create (int argc, char **argv) {
+
+  int ThisList, depth, i, done, NLINES, N;
+  char *input, *help;
+  Command *cmd;
+  Macro *macro;
+
+  if ((N = get_argument (argc, argv, "-c"))) {
+    remove_argument (N, &argc, argv);
+    help = strcreate(argv[N]);
+    remove_argument (N, &argc, argv);
+  } else {
+    help = strcreate ("(macro)");
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: macro <name> [-c \"comment line\"]\n");
+    gprint (GP_ERR, "  (enter commands, end with the word 'END')\n");
+    return (FALSE);
+  }
+
+  /**** Check for existence of this macro ****/
+  cmd = MatchCommand (argv[1], FALSE, TRUE);
+  macro = MatchMacro (argv[1], FALSE, TRUE);
+  
+  if ((macro == NULL) && (cmd != NULL)) {
+    gprint (GP_ERR, "cannot redefine inherent command %s\n", argv[1]);
+    return (FALSE);
+  }
+  if ((macro != NULL) && (cmd == NULL)) {
+    gprint (GP_ERR, "programming error: macro not in command list (%s)\n", argv[1]);
+    return (FALSE);
+  }
+
+  if (macro == NULL) { /**** New Macro ****/
+    ALLOCATE (cmd, Command, 1);
+    cmd[0].real = FALSE;
+    cmd[0].name = strcreate (argv[1]);
+    cmd[0].help = help;
+    cmd[0].func = macro_exec;
+    AddCommand (cmd);
+    free (cmd);
+    macro = NewMacro (argv[1]);
+  } else { /**** Old Macro ****/
+    /* replace existing command help with new value */
+    free (cmd[0].help);
+    cmd[0].help = help;
+  }
+
+  /* reallocate space for macro lines */
+  NLINES = D_NLINES;
+  for (i = 0; i < macro[0].Nlines; i++) free (macro[0].line[i]);
+  REALLOCATE (macro[0].line, char *, NLINES);
+
+  /* read in macro
+     If we are entering at the keyboard (ThisList == 0), use readline.
+     Otherwise, read from the current list
+     End when we hit the final "END" (the true END -- we count macro defines!!) */
+     
+  depth = 0;
+  ThisList = current_list_depth();
+  for (i = 0, done = FALSE; !done; ) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+
+    if ((ThisList == 0) && (input == (char *) NULL)) {
+      gprint (GP_ERR, "end macro with 'END'\n");
+      continue;
+    }
+    if (ThisList == 0) ohana_memregister (input);
+
+    if ((ThisList > 0) && (input == (char *) NULL)) {
+      gprint (GP_ERR, "missing 'END' in macro definition\n");
+      input = strcreate ("end");
+    }
+
+    stripwhite (input);
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { /* we hit the last "END", macro is done */
+	free (input);
+	macro[0].Nlines = i;
+	if (macro[0].Nlines == 0) i = 1;
+	REALLOCATE (macro[0].line, char *, i);
+	return (TRUE);
+      }
+    }
+
+    if (*input) { 
+      macro[0].line[i] = input;
+      i++;
+      if (i == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (macro[0].line, char *, NLINES);
+      }
+    }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_delete.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "opihi.h"
+
+int macro_delete (int argc, char **argv) {
+
+  Command *cmd;
+  Macro *macro;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: macro delete <macro>\n");
+    return (FALSE);
+  }
+
+  macro = MatchMacro (argv[1], FALSE, TRUE);
+  if (macro == NULL) {
+    gprint (GP_ERR, "Macro %s not found\n", argv[1]);
+    return (FALSE);
+  }
+  cmd = MatchCommand (argv[1], FALSE, TRUE);
+  if (cmd == NULL) {
+    gprint (GP_ERR, "programming error: macro exists but not command\n");
+    return (FALSE);
+  }
+
+  DeleteMacro (macro);
+  DeleteCommand (cmd);
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_edit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_edit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_edit.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "opihi.h"
+
+int macro_edit (int argc, char **argv) {
+
+  gprint (GP_ERR, "this function is not implemented yet\n");
+  return (FALSE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_exec.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_exec.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_exec.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "opihi.h"
+
+int macro_exec (int argc, char **argv) {
+
+  int i, status, MacroDepth;
+  char *PreviousName, **params, tmp[1024];
+  Macro *macro;
+  
+  macro = MatchMacro (argv[0], FALSE, TRUE);
+  if (macro == NULL) {
+    gprint (GP_ERR, "%s: Command not found.\n", argv[0]);
+    return (FALSE);
+  }
+
+  /* increase MacroDepth by one - governs macro args */
+  PreviousName = GetMacroName ();
+  MacroDepth = GetMacroDepth ();
+  MacroDepth ++;
+  SetCurrentMacroData (macro[0].name, MacroDepth);
+
+  ALLOCATE (params, char *, argc);
+  sprintf (tmp, "%d.%d", MacroDepth, 0);
+  params[0] = strcreate (tmp);
+  sprintf (tmp, "%d", argc);
+  set_str_variable (params[0], tmp);
+  for (i = 1; i < argc; i++) {
+    sprintf (tmp, "%d.%d", MacroDepth, i);
+    params[i] = strcreate (tmp);
+    set_str_variable (params[i], argv[i]);
+  }
+
+  /* process this list */
+  status = exec_loop (&macro[0]);
+  loop_last = loop_next = FALSE; 
+  /* 'last' and 'next' should only affect one loop */
+
+  /* clear out the command line variables */
+  for (i = 0; i < argc; i++) {
+    DeleteNamedScalar (params[i]);
+    free (params[i]);
+  }
+  free (params);
+  
+  MacroDepth --;
+  SetCurrentMacroData (PreviousName, MacroDepth);
+  return (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_funcs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_funcs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_funcs.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "basic.h"
+
+static Command macro_command[] = {
+  {1, "create", macro_create, "create a macro *"},
+  {1, "delete", macro_delete, "delete a macro *"},
+  {1, "list",   macro_list_f, "list a macro *"},
+  {1, "edit",   macro_edit,   "edit a macro <not working yet!> *"},
+  {1, "read",   macro_read,   "read a macro from a file <not working yet!> *"},
+  {1, "write",  macro_write,  "write a macro to a file <not working yet!> *"}
+};
+
+CommandF *find_macro_command (char *name) {
+
+  int i, N;
+
+  N = sizeof (macro_command) / sizeof (Command);
+
+  /* find the macro sub-command which matches from the list. */
+  for (i = 0; i < N; i++) {
+    if (!strcmp (macro_command[i].name, name)) {
+      return (macro_command[i].func);
+    }
+  }
+
+  return NULL;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_list.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_list.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_list.c	(revision 16632)
@@ -0,0 +1,23 @@
+# include "opihi.h"
+
+int macro_list_f (int argc, char **argv) {
+
+  int i;
+  Macro *macro;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: macro list <macro>\n");
+    return (FALSE);
+  }
+
+  macro = MatchMacro (argv[0], FALSE, TRUE);
+  if (macro == NULL) {
+    gprint (GP_ERR, "%s: Macro not found\n", argv[1]);
+    return (FALSE);
+  }
+
+  for (i = 0; i < macro[0].Nlines; i++) {
+    gprint (GP_ERR, "%s\n", macro[0].line[i]);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_read.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_read.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_read.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "opihi.h"
+
+int macro_read (int argc, char **argv) {
+
+  gprint (GP_ERR, "this function is not implemented yet\n");
+  return (FALSE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_write.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_write.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/macro_write.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "opihi.h"
+
+int macro_write (int argc, char **argv) {
+
+  gprint (GP_ERR, "this function is not implemented yet\n");
+  return (FALSE);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/memstr.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/memstr.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/memstr.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "shell.h"
+
+/* memstr returns a view, not an allocated string : don't free */
+/* returns pointer to start of m2 in m1, or NULL if failure */ 
+char *memstr (char *m1, char *m2, int n) {
+
+  int i, N;
+
+  N = strlen (m2);
+  for (i = 0; (i < n - N + 1) && memcmp (m1, m2, N); i++, m1++);
+  if (memcmp (m1, m2, N)) return (NULL);
+  return (m1);
+
+}
+
+/* formatted write statement, with intelligent allocation */
+int write_fmt (int fd, char *format, ...) {
+
+  int Nbyte, status;
+  char tmp, *line;
+  va_list argp;  
+
+  va_start (argp, format);
+  Nbyte = vsnprintf (&tmp, 0, format, argp);
+  va_end (argp);
+
+  va_start (argp, format);
+  ALLOCATE (line, char, Nbyte + 1);
+  vsnprintf (line, Nbyte + 1, format, argp);
+  status = write (fd, line, strlen(line));
+  va_end (argp);
+
+  free (line);
+  return (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/multicommand.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/multicommand.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/multicommand.c	(revision 16632)
@@ -0,0 +1,146 @@
+# include "opihi.h"
+
+static int server = 0;
+static int bufferPending = FALSE;
+
+// XXX this is rather pantasks-specific...
+void multicommand_InitServer () {
+
+  char hostname[256], PASSWORD[256];
+
+  if (server != 0) {
+    /* check if down? */
+    fprintf (stderr, "error: server fd already defined\n");
+    exit (30);
+  }
+
+  /* find the defined server hostname */
+  if (VarConfig ("PANTASKS_SERVER", "%s", hostname) == NULL) {
+    gprint (GP_ERR, "pantasks server host undefined\n");
+    exit (31);
+  }
+
+  /* attempt to connect to the server */
+  server = GetClientSocket (hostname);
+
+  /* here we can perform the security handshaking */
+  VarConfig ("PASSWORD", "%s", PASSWORD);
+  SendCommand (server, strlen(PASSWORD), PASSWORD);
+  
+  return;
+}
+
+/* take input line and split into multiple lines
+   at the semi-colons.  send these to 'command' */
+
+int multicommand (char *line) {
+ 
+  int done, status, verbose;
+  char *p, *q, *tmpline, *outline;
+  IOBuffer message;
+
+  /* if no server is defined, use 'verbose' mode for 'command' */ 
+  verbose = (server == 0);
+
+  p = line; 
+  done = FALSE;
+  status = TRUE;
+  while (!done) {
+    q = strchr (p, ';');
+    if (q == NULL) {
+      q = p + strlen(p);
+      done = TRUE;
+    }
+    tmpline = strncreate (p, q - p);
+    stripwhite (tmpline);
+    if (*tmpline) {
+
+      if (bufferPending) {
+	// flush old messages
+	while (ExpectMessage (server, 0.2, &message));
+	bufferPending = FALSE;
+      }
+
+      status = command (tmpline, &outline, verbose);
+
+      if (status == -1) {
+	if (server) {
+	  // send the command to the server instead
+	  if (!SendMessage (server, outline)) {
+	    switch (errno) {
+	      case EPIPE:
+		gprint (GP_ERR, "server connection has died\n");
+		exit (32);
+	      default:
+		gprint (GP_ERR, "server is busy...\n");
+		bufferPending = TRUE;
+		goto escape;
+	    }
+	  }
+
+	  // receive the command exit status
+	  if (ExpectMessage (server, 2.0, &message)) {
+	    switch (errno) {
+	      case EPIPE:
+		gprint (GP_ERR, "server connection has died\n");
+		exit (33);
+	      default:
+		gprint (GP_ERR, "server is busy...\n");
+		bufferPending = TRUE;
+		goto escape;
+	    }
+	  } else {
+	    sscanf (message.buffer, "STATUS %d", &status);
+	  }
+
+	  // receive the resulting stderr
+	  if (ExpectMessage (server, 2.0, &message)) {
+	    switch (errno) {
+	      case EPIPE:
+		gprint (GP_ERR, "server connection has died\n");
+		exit (34);
+	      default:
+		gprint (GP_ERR, "server is busy...\n");
+		bufferPending = TRUE;
+		goto escape;
+	    }
+	  } else {
+	    gwrite (message.buffer, 1, message.Nbuffer, GP_ERR);
+	  }
+
+	  // receive the resulting stdout
+	  if (ExpectMessage (server, 2.0, &message)) {
+	    switch (errno) {
+	      case EPIPE:
+		gprint (GP_ERR, "server connection has died\n");
+		exit (35);
+	      default:
+		gprint (GP_ERR, "server is busy...\n");
+		bufferPending = TRUE;
+		goto escape;
+	    }
+	  } else {
+	    gwrite (message.buffer, 1, message.Nbuffer, GP_LOG);
+	  }
+	} else {
+	  // if no server is defined, we treat an unknown command as an error
+	  status = FALSE;
+	}	
+      }
+    escape:
+      if (outline != NULL) free (outline);
+      if (!status && auto_break) done = TRUE;
+    }
+    p = q + 1;
+  }
+  return (status);
+}
+
+/* should skip ; surrounded by "" */
+
+/* commands which are not found are sent to the server socket if 
+   defined. commands executed by the server return their stderr
+   and stdout streams.  server commands should probably not block
+   the server for very long or multiple clients will interfere
+   with each other.  
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/opihi.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/opihi.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/opihi.c	(revision 16632)
@@ -0,0 +1,64 @@
+# include "opihi.h"
+
+/******************/
+int opihi (int argc, char **argv) {
+
+  int Nbad, status;
+  char *line, *prompt, *history;
+  pid_t ppid;
+
+  general_init (&argc, argv);
+  program_init (&argc, argv);
+  startup (&argc, argv);
+  prompt = get_variable("PROMPT");
+  history = get_variable("HISTORY");
+  welcome ();
+
+  Nbad = 0;
+  while (1) {  /** must exit with command "exit" or "quit" */
+    if (Nbad == 10) exit (20);
+
+    line = readline (prompt);
+
+    if (line == NULL) { 
+      
+      ppid = getppid();
+      if (ppid == 1) {
+	signal (SIGPIPE, SIG_IGN);
+	gprint (GP_ERR, "caught parent shutdown\n");
+	exit (21);
+      }
+      if (!isatty (STDIN_FILENO)) exit (21);
+      gprint (GP_LOG, "Use \"quit\" to exit\n");
+      Nbad ++;
+      continue;
+    }
+
+    Nbad = 0;
+    ohana_memregister (line);
+
+    stripwhite (line);
+    if (*line) {
+      status = multicommand (line);
+      add_history (line);
+
+// the libedit version of readline does not support an incremental write to history file
+# ifdef RL_READLINE_VERSION
+      if (history != NULL) append_history (1, history);
+# endif
+
+    }
+    free (line);
+    line = (char *) NULL;
+  }
+}
+
+/* 
+   startup sequence:
+
+   - general_init
+   - program_init
+   - startup (exit if non-interactive)
+   - welcome
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/parse.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/parse.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/parse.c	(revision 16632)
@@ -0,0 +1,308 @@
+# include "opihi.h"
+
+char *parse (char *line) {
+
+  double fval;
+  float *fptr;
+  char *newline, *N, *L, *val, *B, *V, *V0, *V1, *c1, *c2, *p;
+  int Nx, Ny, Nbytes, status, size, NLINE, isBuffer, inRange;
+  FILE *f;
+  Vector *vec;
+  Buffer *buf;
+
+  val = V0 = NULL;
+
+  if (line == (char *) NULL) goto error;
+
+  /* case 1: $var = expression */
+  if (line[0] == '$') {  
+    /* find the target variable name and the rest of the line */
+    interpolate_slash (line);
+    V0 = thisvar (line);
+    if (V0 == NULL) goto error;
+    V1 = aftervar (line);
+    if (V1 == NULL) goto error;
+ 
+    /* increment operator */
+    if (!strcmp (V1, "++")) {
+      val = get_variable (V0);
+      if (val == NULL) {
+	fval = 1.0;
+      } else {
+	fval = atof (val) + 1.0;
+      }
+      set_variable (V0, fval);
+      goto escape;
+    }
+
+    /* decrement operator */
+    if (!strcmp (V1, "--")) {
+      val = get_variable (V0);
+      if (val == NULL) {
+	fval = -1.0;
+      } else {
+	fval = atof (val) - 1.0;
+      }
+      set_variable (V0, fval);
+      goto escape;
+    }
+
+    /* not an assignement, syntax error */
+    if (*V1 != '=') goto error;
+
+    /* find first non-WHITESPACE character after = */
+    V1 ++;
+    while (isspace (*V1)) V1++;
+    if (*V1 == 0) goto error;
+
+    /* command replacement.  execute the line, place answer in val. */
+    if (*V1 == '`') {
+
+      /* look for end of line, must be ` */
+      B = V1 + strlen (V1) - 1;
+      if (*B != '`') goto error;
+
+      /* val will hold the result */
+      // XXX this is limiting!!!
+      ALLOCATE (val, char, 1024);
+
+      /* B is the command to be executed */
+      B = strncreate (V1 + 1, strlen(V1) - 2);
+      f = popen (B, "r");
+      Nbytes = fread (val, 1, 1023, f);
+      val[Nbytes] = 0;
+      status = pclose (f);
+      free (B);
+
+      if (status) gprint (GP_ERR, "warning: exit status of command %d\n", status);
+
+      /* convert all but last return to ' '.  drop last return */
+      for (B = val; *B != 0; B++) {
+	if (*B == '\n') {
+	  if (B[1]) {
+	    *B = ' ';
+	  } else {
+	    *B = 0;
+	  }
+	}
+      }
+    } 
+
+    /* simple variable assignment */
+    if (*V1 != '`') {
+      /* dvomath returns a new string, or NULL, with the result of the expression */
+      val = dvomath (1, &V1, &size, 0);
+      if (val == NULL) { 
+	while (OHANA_WHITESPACE (*V1)) V1++;
+	val = strcreate (V1);
+      } 
+    }
+    /* both dvomath and command replacement create (char *) val */
+    set_str_variable (V0, val);
+    goto escape;  /* frees temp variables */
+  }
+
+  /* case 2: vect[N] = value or buff[N][M] = value */
+  V0 = thiscomm (line);
+  if (strchr(V0, '[') != (char *) NULL) { 
+    /* get vector name (left in V0) */
+    N = strchr (V0, '[');
+    if (N == V0) goto error;
+
+    /* get bracket contents (left in V) */
+    L = strchr (V0, ']');
+    if (L == (char *) NULL) goto error;
+
+    *N = 0;
+    V = strncreate (N+1, L - N - 1);
+
+    /* expand value in brackets */
+    val = dvomath (1, &V, &size, 0);
+    if (val == NULL) {
+      print_error ();
+      goto error;
+    }
+    Nx = atoi (val);
+    free (val); val = NULL;
+    free (V);
+
+    isBuffer = FALSE;
+    N = L + 1;
+    if (*N == '[') {
+      isBuffer = TRUE;
+      L = strchr (N, ']');
+
+      V = strncreate (N+1, L - N - 1);
+
+      /* expand value in brackets */
+      val = dvomath (1, &V, &size, 0);
+      if (val == NULL) {
+	print_error ();
+	goto error;
+      }
+      Ny = atoi (val);
+      free (val); val = NULL;
+      free (V);
+    }
+
+    /* find value for assignment */
+    V1 = nextcomm (line);
+    if (V1 == (char *) NULL) goto error;
+    if (V1[0] != '=') goto error;
+    V1 ++;
+
+    /*** assign vector element to value ***/
+    val = dvomath (1, &V1, &size, 0); 
+    if (val == (char *) NULL) {
+      print_error ();
+      goto error;
+    }
+
+    /* find vector */
+    if (isBuffer) {
+      if ((buf = SelectBuffer (V0, OLDBUFFER, TRUE)) == NULL) goto error;
+      free (V0); V0 = (char *) NULL;
+
+      inRange = TRUE;
+      inRange &= (Nx <  +1*buf[0].header.Naxis[0]);
+      inRange &= (Nx >= -1*buf[0].header.Naxis[0]);
+      inRange &= (Ny <  +1*buf[0].header.Naxis[1]);
+      inRange &= (Ny >= -1*buf[0].header.Naxis[1]);
+      if (!inRange) {
+	gprint (GP_ERR, "no element %d,%d\n", Nx, Ny);
+	goto escape;
+      }
+      if (Nx < 0) Nx += buf[0].header.Naxis[0];
+      if (Ny < 0) Ny += buf[0].header.Naxis[1];
+
+      fptr = (float *) buf[0].matrix.buffer;
+      fptr[Nx + Ny*buf[0].header.Naxis[0]] = atof (val);
+    } else {
+      if ((vec = SelectVector (V0, OLDVECTOR, TRUE)) == NULL) goto error;
+      free (V0); V0 = (char *) NULL;
+
+      inRange = TRUE;
+      inRange &= (Nx <  +1*vec[0].Nelements);
+      inRange &= (Nx >= -1*vec[0].Nelements);
+      if (!inRange) {
+	gprint (GP_ERR, "no element %d\n", Nx);
+	goto escape;
+      }
+      if (Nx < 0) Nx += vec[0].Nelements;
+      vec[0].elements[Nx] = atof (val);
+    }
+
+    goto escape;
+  }
+  free (V0); V0 = (char *) NULL;
+
+  /* case 3: {expression} */
+  NLINE = MAX (128, strlen (line));
+  ALLOCATE (newline, char, NLINE);
+  memset (newline, 0, NLINE);
+  for (L = line; *L != 0; ) { 
+
+    // copy elements from L (line) to newline up to first '{'
+    p = strchr (L, '{');
+    newline = opihi_append (newline, &NLINE, L, p);
+    if (p == NULL) break;
+    L = p + 1;
+
+    // check for \{ at this point, replace \ in newline with {
+    if ((p > line) && (*(p - 1) == 0x5c)) {
+      N = newline + strlen(newline) - 1;
+      *N = '{'; // replace \ with {
+      continue;
+    }
+
+    /* check on the syntax of the line */
+    L = p + 1;
+    c1 = strchr (L, '}');
+    if (c1 == NULL) {
+      gprint (GP_ERR, "no close brackets!\n");
+      goto escape;
+    }
+    c2 = strchr (L, '{');
+    if ((c2 != NULL) && (c2 < c1)) {
+      gprint (GP_ERR, "can't nest brackets!\n");
+      goto escape;
+    }
+    *c1 = 0;
+
+    /* value in brackets must be a math expression of some sort.
+       isolated words are not valid here */
+    val = dvomath (1, &L, &size, -1);
+    if (val == NULL) {
+      print_error ();
+      goto escape;
+    } 
+
+    /* interpolate vector element into newline (being accumulated) */
+    newline = opihi_append (newline, &NLINE, val, NULL);
+
+    /* copy val to outline */
+    L = c1 + 1;
+    free (val); val = (char *) NULL;
+  }
+
+  free (line); line = (char *) NULL;
+
+  /* \ protects next character */
+  interpolate_slash (newline);
+  
+  REALLOCATE (newline, char, strlen (newline) + 1);
+  return (newline); 
+
+error:
+  gprint (GP_ERR, "syntax error\n");
+
+escape:
+  if (line != (char *) NULL) free (line);
+  if (val != (char *) NULL) free (val);
+  if (V0 != (char *) NULL) free (V0);
+  return (NULL);
+}
+
+/* this routine looks for math and/or logic expressions that 
+   need to be evaluated and passes them on to "parenthesis",
+   which evaluates the expression */
+
+/* There are two situations now which define an expression to 
+   be evaluated:
+   1) $var = expression   -- everything after the = must be a math expression or a string
+   2) {expression}        -- everything within the {} must be a math expression
+*/
+
+/* case 1: $var = expression.  test that
+   a) there is a $ as the first character
+   b) the variable defined by that $ is not null
+   c) there is an = sign following the variable
+   d) there is something following the = sign
+*/
+  
+/* case 2: vect[N] = expression. check syntax:
+   a) last char must be ]
+   b) word must contain [
+   c) between [ & ] must be an integer
+   d) vector must exist
+   e) there is an = sign following the first word
+   f) there is something following the = sign
+*/
+     
+
+/* case 3: we hunt for '{', and then the first '}' and pass everything
+   inbetween.  no nested {{}}s are allowed! */
+  
+/* thisword ALLOCATES
+   thisvar  ALLOCATES
+   thiscomm ALLOCATES
+   
+   nextword !ALLOCATE
+   nextcomm !ALLOCATE
+   
+   lastword !ALLOCATE
+   lastvar !ALLOCATE
+   
+   aftervar !ALLOCATE
+*/   
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/parse_commands.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/parse_commands.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/parse_commands.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "opihi.h"
+# define D_NARG 10
+
+char **parse_commands (char *line, int *argc) {
+
+  int i, NARG;
+  char *c;
+  char **argv;
+
+  NARG = D_NARG;
+  ALLOCATE (argv, char *, NARG);
+
+  argv[0] = thisword (line);
+  if (argv[0] == (char *) NULL) {
+    free (argv);
+    *argc = 0;
+    return ((char **) NULL);
+  }
+
+  c = nextword (line);
+  for (i = 1; c != (char *) NULL; i++) {
+    argv[i] = thisword (c);
+
+    /* if one of the words does not parse (eg, ""), skip it */
+    if (argv[i] == NULL) i--;
+
+    c = nextword (c);
+    if (i == NARG - 1) {
+      NARG += D_NARG;
+      REALLOCATE (argv, char *, NARG);
+    }
+  }
+  REALLOCATE (argv, char *, i);
+  *argc = i;
+
+  return (argv);
+
+}
+
+  /* parse out the command line into (char **argv).  line looks like:
+     command word word word ... */
+
+  /* argv[0] and argv[1..argc-1] are handled differently because
+     the syntax of a valid command and a valid word are slighly 
+     different (not that this is obviously wanted...) */
+
+
+
+/* old code:
+      for (j = 0; j < i; j++) 
+	free (argv[i]);
+      free (argv);
+      *argc = 0;
+      return (argv);
+    }
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/stack_math.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/stack_math.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/stack_math.c	(revision 16632)
@@ -0,0 +1,1454 @@
+# include "opihi.h"
+
+/* the result of a matrix operation must go into a temp variable,
+   labeled by "m". if one of the input matrices is already a temp variable, we 
+   can continue using it this round 
+   */
+
+int VV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx;
+  float *out, *M1, *M2;
+  char line[512];
+  
+  Nx = V1[0].vector[0].Nelements;
+  if (Nx != V2[0].vector[0].Nelements) {
+    return (FALSE);
+  }
+
+  if (V1[0].type == 'v') {  /** use V1 as temp buffer **/
+    OUT[0].vector = V1[0].vector;
+    V1[0].type = 'V'; /* prevent it from being freed below */
+  } else {
+    if (V2[0].type == 'v') { /** use V2 as temp buffer, but header of V1 **/
+      OUT[0].vector = V2[0].vector;
+      V2[0].type = 'V'; /* prevent it from being freed below */
+    } else {  /* no spare temp buffer */
+      OUT[0].vector = InitVector ();
+      CopyVector (OUT[0].vector, V1[0].vector);
+    }
+  }
+  OUT[0].type = 'v'; /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case '@': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = DEG_RAD*atan2 (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx; i++, out++, M1++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+  }
+  if (V2[0].type == 'v') {
+    free (V2[0].vector[0].elements);
+    free (V2[0].vector);
+  }
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+
+  clear_stack (V1);
+  clear_stack (V2);
+  return (TRUE);
+
+}
+
+int SV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx;
+  float *out, *M1, *M2;
+  char line[512];
+  
+  Nx = V2[0].vector[0].Nelements;
+
+  if (V2[0].type == 'v') { /** use V2 as temp buffer, but header of V1 **/
+    OUT[0].vector = V2[0].vector;
+    V2[0].type = 'V'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].vector = InitVector ();
+    CopyVector (OUT[0].vector, V2[0].vector);
+  }
+  OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx; i++, out++, M2++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case '@': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = DEG_RAD*atan2 (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx; i++, out++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  /** free up any temporary buffers: **/
+  if (V2[0].type == 'v') {
+    free (V2[0].vector[0].elements);
+    free (V2[0].vector);
+  }
+
+  clear_stack (V1);
+  clear_stack (V2);
+
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+int VS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx;
+  float *out, *M1, *M2;
+  char line[512];
+  
+  Nx = V1[0].vector[0].Nelements;
+
+  if (V1[0].type == 'v') { /** use V1 as temp buffer **/
+    OUT[0].vector = V1[0].vector;
+    V1[0].type = 'V'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].vector = InitVector ();
+    CopyVector (OUT[0].vector, V1[0].vector);
+  }
+  OUT[0].type = 'v';   /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx; i++, out++, M1++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case '@': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = DEG_RAD*atan2 (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx; i++, out++, M1++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+  }
+
+  clear_stack (V1);
+  clear_stack (V2);
+
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+int MV_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, j, Nx, Ny;
+  float *out, *M1, *M2;
+  char line[512];
+ 
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+  if (Ny != V2[0].vector[0].Nelements) {
+    push_error ("dimension mismatch");
+    return (FALSE);
+  }
+
+  /* if possible, use V1 as temp buffer, otherwise create new one */
+  if (V1[0].type == 'm') {  
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {  
+    /* do buffer.matrix.buffer and buffer.header.buffer get correctly zeroed? */
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V1[0].buffer);
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 + *M2;
+    }
+    break; 
+  case '-': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 - *M2;
+    }
+    break; 
+  case '*': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 * *M2;
+    }
+    break; 
+  case '/': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = *M1 / *M2;
+    }
+    break; 
+  case '%': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++)
+        *out = (int) *M1 % (int) *M2;
+    }
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = pow (*M1, *M2);
+    }
+    break; 
+  case '@': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = DEG_RAD*atan2 (*M1, *M2);
+    }
+    break; 
+  case 'D': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = MIN (*M1, *M2);
+    }
+    break; 
+  case 'U': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = MAX (*M1, *M2);
+    }
+    break; 
+  case '<': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 < *M2) ? 1 : 0;
+    }
+    break; 
+  case '>': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 > *M2) ? 1 : 0;
+    }
+    break; 
+  case '&': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = ((int)*M1 & (int)*M2);
+    }
+    break; 
+  case '|': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = ((int)*M1 | (int)*M2);
+    }
+    break; 
+  case 'E': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 == *M2) ? 1 : 0;
+    }
+    break; 
+  case 'N': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 != *M2) ? 1 : 0;
+    }
+    break; 
+  case 'L': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 <= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'G': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 >= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'A': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 && *M2) ? 1 : 0;
+    }
+    break; 
+  case 'O': 
+    for (i = 0; i < Ny; i++, M2++) {
+      for (j = 0; j < Nx; j++, out++, M1++) 
+        *out = (*M1 || *M2) ? 1 : 0;
+    }
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+  if (V2[0].type == 'v') {
+    free (V2[0].vector[0].elements);
+    free (V2[0].vector);
+  }
+
+  clear_stack (V1);
+  clear_stack (V2);
+
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+
+int VM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, j, Nx, Ny;
+  float *out, *M1, *M2;
+  char line[512];
+  
+  Nx = V2[0].buffer[0].matrix.Naxis[0];
+  Ny = V2[0].buffer[0].matrix.Naxis[1];
+  if (Nx != V1[0].vector[0].Nelements) {
+    return (FALSE);
+  }
+
+  /* if possible, use V2 as temp buffer, otherwise create new one */
+  if (V2[0].type == 'm') {
+    OUT[0].buffer = V2[0].buffer;
+    V2[0].type = 'M'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V2[0].buffer);
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 + *M2;
+    }
+    break; 
+  case '-': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 - *M2;
+    }
+    break; 
+  case '*': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 * *M2;
+    }
+    break; 
+  case '/': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = *M1 / *M2;
+    }
+    break; 
+  case '%': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++)
+        *out = (int) *M1 % (int) *M2;
+    }
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = pow (*M1, *M2);
+    }
+    break; 
+  case '@': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = DEG_RAD*atan2 (*M1, *M2);
+    }
+    break; 
+  case 'D': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = MIN (*M1, *M2);
+    }
+    break; 
+  case 'U': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = MAX (*M1, *M2);
+    }
+    break; 
+  case '<': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 < *M2) ? 1 : 0;
+    }
+    break; 
+  case '>': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 > *M2) ? 1 : 0;
+    }
+    break; 
+  case '&': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = ((int)*M1 & (int)*M2);
+    }
+    break; 
+  case '|': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = ((int)*M1 | (int)*M2);
+    }
+    break; 
+  case 'E': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 == *M2) ? 1 : 0;
+    }
+    break; 
+  case 'N': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 != *M2) ? 1 : 0;
+    }
+    break; 
+  case 'L': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 <= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'G': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 >= *M2) ? 1 : 0;
+    }
+    break; 
+  case 'A': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 && *M2) ? 1 : 0;
+    }
+    break; 
+  case 'O': 
+    for (i = 0; i < Ny; i++) {
+      M1 = V1[0].ptr;
+      for (j = 0; j < Nx; j++, out++, M1++, M2++) 
+        *out = (*M1 || *M2) ? 1 : 0;
+    }
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+  }
+  if (V2[0].type == 'm') {
+    free (V2[0].buffer[0].header.buffer);
+    free (V2[0].buffer[0].matrix.buffer);
+    free (V2[0].buffer);
+  }
+
+  clear_stack (V1);
+  clear_stack (V2);
+
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+int MM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx, Ny;
+  float *out, *M1, *M2;
+  char line[512];
+  
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+
+  if (V1[0].type == 'm') {  /** use V1 as temp buffer **/
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    if (V2[0].type == 'm') { /** use V2 as temp buffer, but header of V1 **/
+      OUT[0].buffer = V2[0].buffer;
+      V2[0].type = 'M'; /* prevent it from being freed below */
+    } else {  /* no spare temp buffer */
+      OUT[0].buffer = InitBuffer ();
+      CopyBuffer (OUT[0].buffer, V1[0].buffer);
+    }
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case '@': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = DEG_RAD*atan2 (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  /** free up any temporary buffers: **/
+
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+  if (V2[0].type == 'm') {
+    free (V2[0].buffer[0].header.buffer);
+    free (V2[0].buffer[0].matrix.buffer);
+    free (V2[0].buffer);
+  }
+
+  clear_stack (V1);
+  clear_stack (V2);
+
+  /* at the end, V1 and V2 are deleted only if they were temporary */
+  return (TRUE);
+
+}
+
+
+int MS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx, Ny;
+  float *out, *M1, *M2;
+  char line[512];
+  
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+
+  /* if possible, use V1 as temp buffer, otherwise create new one */
+  if (V1[0].type == 'm') {
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V1[0].buffer);
+  }
+  OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = pow (*M1, *M2);
+    break; 
+  case '@': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = DEG_RAD*atan2 (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx*Ny; i++, out++, M1++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+  clear_stack (V1);
+  clear_stack (V2);
+
+  return (TRUE);
+
+}
+
+
+int SM_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int i, Nx, Ny;
+  float *out, *M1, *M2;
+  char line[512];
+  
+  Nx = V2[0].buffer[0].matrix.Naxis[0];
+  Ny = V2[0].buffer[0].matrix.Naxis[1];
+
+  if (V2[0].type == 'm') {  /* V2[0] is NOT temporary, we can't use it for storage */
+    OUT[0].buffer = V2[0].buffer;
+    V2[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V2[0].buffer);
+  }
+  OUT[0].type = 'm'; /*** <<--- says this is a temporary matrix ***/
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  switch (op[0]) { 
+  case '+': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 + *M2;
+    break; 
+  case '-': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 - *M2;
+    break; 
+  case '*': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 * *M2;
+    break; 
+  case '/': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = *M1 / *M2;
+    break; 
+  case '%': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = (int) *M1 % (int) *M2;
+    break; 
+  case 0x5e: 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++)
+      *out = pow (*M1, *M2);
+    break; 
+  case '@': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = DEG_RAD*atan2 (*M1, *M2);
+    break; 
+  case 'D': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    for (i = 0; i < Nx*Ny; i++, out++, M2++) 
+      *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  if (V2[0].type == 'm') {
+    free (V2[0].buffer[0].header.buffer);
+    free (V2[0].buffer[0].matrix.buffer);
+    free (V2[0].buffer);
+  }
+  clear_stack (V1);
+  clear_stack (V2);
+
+  return (TRUE);
+
+}
+
+
+int SS_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  float *M1, *M2, *out;
+  char line[512];
+
+  M1  = V1[0].ptr;
+  M2  = V2[0].ptr;
+  OUT[0].ptr = V1[0].ptr;
+  out = OUT[0].ptr;
+
+
+  switch (op[0]) { 
+  case '+': 
+    *out = *M1 + *M2;
+    break;    
+  case '-': 
+    *out = *M1 - *M2;
+    break;    
+  case '*': 
+    *out = *M1 * *M2;
+    break;    
+  case '/': 
+    *out = *M1 / *M2;
+    break; 
+  case '%': 
+    *out = (int) *M1 % (int) *M2;
+    break; 
+  case 0x5e: 
+    *out = pow (*M1, *M2);
+    break; 
+  case '@': 
+    *out = DEG_RAD*atan2 (*M1, *M2);
+    break; 
+  case 'D': 
+    *out = MIN (*M1, *M2);
+    break; 
+  case 'U': 
+    *out = MAX (*M1, *M2);
+    break; 
+  case '<': 
+    *out = (*M1 < *M2) ? 1 : 0;
+    break; 
+  case '>': 
+    *out = (*M1 > *M2) ? 1 : 0;
+    break; 
+  case '&': 
+    *out = ((int)*M1 & (int)*M2);
+    break; 
+  case '|': 
+    *out = ((int)*M1 | (int)*M2);
+    break; 
+  case 'E': 
+    *out = (*M1 == *M2) ? 1 : 0;
+    break; 
+  case 'N': 
+    *out = (*M1 != *M2) ? 1 : 0;
+    break; 
+  case 'L': 
+    *out = (*M1 <= *M2) ? 1 : 0;
+    break; 
+  case 'G': 
+    *out = (*M1 >= *M2) ? 1 : 0;
+    break; 
+  case 'A': 
+    *out = (*M1 && *M2) ? 1 : 0;
+    break; 
+  case 'O': 
+    *out = (*M1 || *M2) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+  OUT[0].Float = *(OUT[0].ptr);
+  OUT[0].type = 'S';
+
+  clear_stack (V1);
+  clear_stack (V2);
+
+  return (TRUE);
+
+}
+
+int WW_binary (StackVar *OUT, StackVar *V1, StackVar *V2, char *op) {
+
+  int value;
+  char line[512];
+
+  /* only 'N' and 'E' are allowed for WW_binary operations. anything else is either a
+   syntax error or is a string which looks like a math expression. */
+
+  if ((op[0] != 'N') && (op[0] != 'E')) {
+    sprintf (line, "error: op %c not defined for string operations!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+  /* evaluate stack will only call WW_binary with one numerical value,
+     and only in the case that the string did not parse to a number 
+     thus: string == number -> false */
+
+  if (!strncasecmp (&V1[0].type, "S", 1)) {
+    value = (op[0] == 'N');
+    goto escape;
+  }
+  if (!strncasecmp (&V2[0].type, "S", 1)) {
+    value = (op[0] == 'N');
+    goto escape;
+  }
+
+  switch (op[0]) { 
+  case 'E': 
+    value = strcmp (V1[0].name, V2[0].name) ? 0 : 1;
+    break; 
+  case 'N': 
+    value = strcmp (V1[0].name, V2[0].name) ? 1 : 0;
+    break; 
+  default:
+    sprintf (line, "error: op %c not defined for string operations!", op[0]);
+    push_error (line);
+    return (FALSE);
+  }
+
+escape:
+  OUT[0].Float = value;
+  OUT[0].type = 'S';
+  OUT[0].ptr = &OUT[0].Float;
+
+  clear_stack (V1);
+  clear_stack (V2);
+  return (TRUE);
+
+}
+
+
+int S_unary (StackVar *OUT, StackVar *V1, char *op) {
+
+  float *out, *M1;
+  
+  out = OUT[0].ptr = V1[0].ptr;
+  M1  = V1[0].ptr;
+
+  if (!strcmp (op, "="))     {    }
+  if (!strcmp (op, "abs"))   {    *out = fabs(*M1);           }
+  if (!strcmp (op, "int"))   {    *out = (float)(int)(*M1);   }
+  if (!strcmp (op, "exp"))   {    *out = exp (*M1);           }
+  if (!strcmp (op, "ten"))   {    *out = pow (10.0,*M1);      }
+  if (!strcmp (op, "log"))   {    *out = log10 (*M1);         }
+  if (!strcmp (op, "ln"))    {    *out = log (*M1);           }
+  if (!strcmp (op, "sqrt"))  {    *out = sqrt (*M1);          }
+  if (!strcmp (op, "erf"))   {    *out = erf (*M1);           }
+
+  if (!strcmp (op, "sinh"))  {    *out = sinh (*M1);          }
+  if (!strcmp (op, "cosh"))  {    *out = cosh (*M1);          }
+  if (!strcmp (op, "asinh")) {    *out = asinh (*M1);         }
+  if (!strcmp (op, "acosh")) {    *out = acosh (*M1);         }
+  if (!strcmp (op, "lgamma")) {   *out = lgamma (*M1);        }
+
+  if (!strcmp (op, "sin"))   {    *out = sin (*M1);           }
+  if (!strcmp (op, "cos"))   {    *out = cos (*M1);           }
+  if (!strcmp (op, "tan"))   {    *out = tan (*M1);           }
+  if (!strcmp (op, "dsin"))  {    *out = sin (*M1*RAD_DEG);   }
+  if (!strcmp (op, "dcos"))  {    *out = cos (*M1*RAD_DEG);   }
+  if (!strcmp (op, "dtan"))  {    *out = tan (*M1*RAD_DEG);   }
+  if (!strcmp (op, "asin"))  {    *out = asin (*M1);          }
+  if (!strcmp (op, "acos"))  {    *out = acos (*M1);          }
+  if (!strcmp (op, "atan"))  {    *out = atan (*M1);          }
+  if (!strcmp (op, "dasin")) {    *out = asin (*M1)*DEG_RAD;  }
+  if (!strcmp (op, "dacos")) {    *out = acos (*M1)*DEG_RAD;  }
+  if (!strcmp (op, "datan")) {    *out = atan (*M1)*DEG_RAD;  }
+  if (!strcmp (op, "rnd"))   {    *out = drand48();           }
+  if (!strcmp (op, "not"))   {    *out = !(*M1);              }
+  if (!strcmp (op, "--"))    {    *out = - (*M1);             }
+  if (!strcmp (op, "isinf")) {    *out = !finite(*M1);        }
+  if (!strcmp (op, "isnan")) {    *out = isnan(*M1);          } 
+
+  OUT[0].Float = *out;
+  OUT[0].type = 'S';
+
+  clear_stack (V1);
+  return (TRUE);
+
+}
+
+int V_unary (StackVar *OUT, StackVar *V1, char *op) {
+
+  int i, Nx;
+  float *out, *M1;
+  
+  Nx = V1[0].vector[0].Nelements;
+ 
+  if (V1[0].type == 'v') {  /** use V1 as temp buffer **/
+    OUT[0].vector = V1[0].vector;
+    V1[0].type = 'V'; /* prevent it from being freed below */
+  } else {  /* no spare temp buffer */
+    OUT[0].vector = InitVector ();
+    CopyVector (OUT[0].vector, V1[0].vector);
+  }
+  OUT[0].type = 'v'; /*** <<--- says this is a temporary matrix ***/
+  M1  = V1[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].vector[0].elements;
+
+  if (!strcmp (op, "="))     { } /* already set equal */
+  if (!strcmp (op, "abs"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = fabs(*M1);         }}
+  if (!strcmp (op, "int"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = (float)(int)(*M1); }}
+  if (!strcmp (op, "exp"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = exp(*M1);          }}
+  if (!strcmp (op, "ten"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
+  if (!strcmp (op, "log"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = log10(*M1);        }}
+  if (!strcmp (op, "ln"))    { for (i = 0; i < Nx; i++, out++, M1++) { *out = log(*M1);          }}
+  if (!strcmp (op, "sqrt"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = sqrt(*M1);         }}
+  if (!strcmp (op, "erf"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = erf(*M1);          }}
+
+  if (!strcmp (op, "sinh"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = sinh(*M1);        }}
+  if (!strcmp (op, "cosh"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = cosh(*M1);        }}
+  if (!strcmp (op, "asinh"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = asinh(*M1);       }}
+  if (!strcmp (op, "acosh"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = acosh(*M1);       }}
+  if (!strcmp (op, "lgamma")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = lgamma(*M1);      }}
+
+  if (!strcmp (op, "sin"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = sin(*M1);          }}
+  if (!strcmp (op, "cos"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = cos(*M1);          }}
+  if (!strcmp (op, "tan"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = tan(*M1);          }}
+  if (!strcmp (op, "dsin"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = sin(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dcos"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = cos(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dtan"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = tan(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "asin"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = asin(*M1);         }}
+  if (!strcmp (op, "acos"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = acos(*M1);         }}
+  if (!strcmp (op, "atan"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = atan(*M1);         }}
+  if (!strcmp (op, "dasin")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = asin(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "dacos")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = acos(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "datan")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = atan(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "rnd"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = drand48();         }}
+  if (!strcmp (op, "ramp"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = i;                 }}
+  if (!strcmp (op, "zero"))  { for (i = 0; i < Nx; i++, out++, M1++) { *out = 0;                 }}
+  if (!strcmp (op, "not"))   { for (i = 0; i < Nx; i++, out++, M1++) { *out = !(*M1);            }}
+  if (!strcmp (op, "--"))    { for (i = 0; i < Nx; i++, out++, M1++) { *out = -(*M1);            }}
+  if (!strcmp (op, "isinf")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = !finite(*M1);      }}
+  if (!strcmp (op, "isnan")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = isnan(*M1);        }}
+
+  /* xramp and yramp only make sense in for matrices. for vectors, xramp = ramp, yramp = zero */
+  if (!strcmp (op, "xramp")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = i;                 }}
+  if (!strcmp (op, "yramp")) { for (i = 0; i < Nx; i++, out++, M1++) { *out = 0;                 }}
+
+  if (V1[0].type == 'v') {
+    free (V1[0].vector[0].elements);
+    free (V1[0].vector);
+    V1[0].vector = NULL;
+  }  
+
+  clear_stack (V1);
+  return (TRUE);
+
+}
+
+int M_unary (StackVar *OUT, StackVar *V1, char *op) {
+
+  int i, j, Nx, Ny;
+  float *out, *M1;
+  
+  Nx = V1[0].buffer[0].matrix.Naxis[0];
+  Ny = V1[0].buffer[0].matrix.Naxis[1];
+
+  if (V1[0].type == 'm') {
+    OUT[0].buffer = V1[0].buffer;
+    V1[0].type = 'M'; /* prevent it from being freed below */
+  } else {
+    OUT[0].buffer = InitBuffer ();
+    CopyBuffer (OUT[0].buffer, V1[0].buffer);
+  }
+  OUT[0].type = 'm';      /*** <<--- says this is a temporary matrix ***/
+  M1  = V1[0].ptr;
+  out = OUT[0].ptr = (float *)OUT[0].buffer[0].matrix.buffer;
+
+  if (!strcmp (op, "="))     { }
+  if (!strcmp (op, "abs"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = fabs(*M1);         }}
+  if (!strcmp (op, "int"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = (float)(int)(*M1); }}
+  if (!strcmp (op, "exp"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = exp(*M1);          }}
+  if (!strcmp (op, "ten"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = pow(10.0,*M1);     }}
+  if (!strcmp (op, "log"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = log10(*M1);        }}
+  if (!strcmp (op, "ln"))    { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = log(*M1);          }}
+  if (!strcmp (op, "sqrt"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sqrt(*M1);         }}
+  if (!strcmp (op, "erf"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = erf(*M1);          }}
+
+  if (!strcmp (op, "sinh"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sinh(*M1);         }}
+  if (!strcmp (op, "cosh"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cosh(*M1);         }}
+  if (!strcmp (op, "asinh")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asinh(*M1);        }}
+  if (!strcmp (op, "acosh")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acosh(*M1);        }}
+  if (!strcmp (op, "lgamma")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = lgamma(*M1);      }}
+
+  if (!strcmp (op, "sin"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sin(*M1);          }}
+  if (!strcmp (op, "cos"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cos(*M1);          }}
+  if (!strcmp (op, "tan"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = tan(*M1);          }}
+  if (!strcmp (op, "dsin"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = sin(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dcos"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = cos(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "dtan"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = tan(*M1*RAD_DEG);  }}
+  if (!strcmp (op, "asin"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asin(*M1);         }}
+  if (!strcmp (op, "acos"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acos(*M1);         }}
+  if (!strcmp (op, "atan"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = atan(*M1);         }}
+  if (!strcmp (op, "dasin")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = asin(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "dacos")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = acos(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "datan")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = atan(*M1)*DEG_RAD; }}
+  if (!strcmp (op, "not"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = !(*M1);            }}
+  if (!strcmp (op, "--"))    { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = -(*M1);            }}
+  if (!strcmp (op, "rnd"))   { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = drand48();         }}
+  if (!strcmp (op, "ramp"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = i;                 }}
+  if (!strcmp (op, "zero"))  { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = 0;                 }}
+  if (!strcmp (op, "isinf")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = !finite(*M1);      }}
+  if (!strcmp (op, "isnan")) { for (i = 0; i < Nx*Ny; i++, out++, M1++) { *out = isnan(*M1);        }}
+
+  /* xrm and yrm only make sense in for matrices. see special meaning for vectors */
+  if (!strcmp (op, "xramp")) {
+    for (j = 0; j < Ny; j++) {
+      for (i = 0; i < Nx; i++, out++, M1++) {
+        *out = i;
+      }
+    }
+  }
+  if (!strcmp (op, "yramp")) {
+    for (j = 0; j < Ny; j++) {
+      for (i = 0; i < Nx; i++, out++, M1++) {
+        *out = j;
+      }
+    }
+  }
+  
+  if (V1[0].type == 'm') {
+    free (V1[0].buffer[0].header.buffer);
+    free (V1[0].buffer[0].matrix.buffer);
+    free (V1[0].buffer);
+  }
+
+  clear_stack (V1);
+  return (TRUE);
+
+}
+
+/*********************** fits copy header ***********************************/
+int gfits_copy_matrix_info (Matrix *matrix1, Matrix *matrix2) {
+
+  int i;
+
+  /* copy all but the matrix */
+
+  matrix2[0].unsign = matrix1[0].unsign;
+  matrix2[0].bitpix = matrix1[0].bitpix;
+  matrix2[0].size   = matrix1[0].size;
+  matrix2[0].bzero  = matrix1[0].bzero;
+  matrix2[0].bscale = matrix1[0].bscale;
+  matrix2[0].Naxes  = matrix1[0].Naxes;
+  for (i = 0; i < FT_MAX_NAXES; i++) 
+    matrix2[0].Naxis[i] = matrix1[0].Naxis[i];
+
+
+  return (TRUE);
+}       
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/startup.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/startup.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/startup.c	(revision 16632)
@@ -0,0 +1,160 @@
+# include "opihi.h"
+
+/* program-independent initialization
+ * these steps do not depend on the opihi implementation
+ * (ie, the supplied commands or data structures)
+ */
+
+void general_init (int *argc, char **argv) {
+
+  /* init srand for rnd numbers elsewhere */
+  long A, B;
+  A = time(NULL);
+  for (B = 0; A == time(NULL); B++);
+  srand48(B);
+ 
+  /* set signals */
+  signal (SIGINT, SIG_IGN);
+
+  /* init for main (or only) thread */
+  gprintInit ();
+
+  init_error ();
+
+  /* load config data (.ptolemyrc) */
+  if (!ConfigInit (argc, argv)) {
+    gprint (GP_ERR, "can't find config file. some functions will be unavailable\n");
+  }
+
+  return;
+}
+
+void startup (int *argc, char **argv) {
+    
+    int i, N, status, ONLY_INPUT, LOAD_RC;
+    char *line, *home, *outline, *varname;
+    char *rcfile, **list;
+    int Nlist, NLIST;
+   
+    /* load in interesting environment variables */
+    ALLOCATE (line, char, 1024);
+    
+    home = getenv ("HOME");
+    if (home == NULL) 
+      set_str_variable ("HOME", ".");
+    else 
+      set_str_variable ("HOME", home);
+    set_str_variable ("KAPA", "kapa");
+    set_variable ("PID", getpid());
+
+    set_int_variable ("UNSIGN", 0);
+    gfits_set_unsign_mode (FALSE);
+    
+  /* check history file permission */
+  {
+    FILE *f;
+    char *opihi_history;
+
+    opihi_history = get_variable ("HISTORY");
+    if (opihi_history && *opihi_history) {
+      f = fopen (opihi_history, "a");
+      if (f == NULL) /* no current history file here */
+	gprint (GP_ERR, "can't save history.\n");
+      else
+	fclose (f);
+      stifle_history (200);
+      read_history (opihi_history);
+    }
+    if (opihi_history) free (opihi_history);
+  }
+
+  if (0) {
+    /* fix the history list to remove the timestamp */
+    char *c;
+    int i;
+    HIST_ENTRY **entry;
+    
+    entry = history_list ();
+    if (entry != (HIST_ENTRY **) NULL) {
+      for (i = 0; entry[i]; i++) {
+	if ((strlen (entry[i][0].line) > 19) &&
+	    (entry[i][0].line[2] == '/') && 
+	    (entry[i][0].line[5] == '/') && 
+	    (entry[i][0].line[11] == ':') && 
+	    (entry[i][0].line[14] == ':') && 
+	    (entry[i][0].line[17] == ':')) {
+	  c = entry[i][0].line + 19;
+	  memmove (entry[i][0].line, c, strlen(c) + 1);
+	}
+      }
+    }
+  }
+
+    LOAD_RC = TRUE;
+    if ((N = get_argument (*argc, argv, "--norc"))) {
+      remove_argument (N, argc, argv);
+      LOAD_RC = FALSE;
+    }
+    
+    ONLY_INPUT = FALSE;
+    if ((N = get_argument (*argc, argv, "--only"))) {
+      remove_argument (N, argc, argv);
+      ONLY_INPUT = TRUE;
+    }
+
+    /* load cmdline files */
+    Nlist = 0;
+    NLIST = 10;
+    ALLOCATE (list, char *, NLIST);
+    while ((N = get_argument (*argc, argv, "--load"))) {
+      remove_argument (N, argc, argv);
+      list[Nlist] = strcreate (argv[N]);
+      remove_argument (N, argc, argv);
+      Nlist++;
+      if (Nlist == NLIST) {
+	NLIST += 10;
+	REALLOCATE (list, char *, NLIST);
+      }
+    }
+
+    is_script = TRUE;
+    if (*argc == 1) is_script = FALSE;
+    set_int_variable ("SCRIPT", is_script);
+
+    if (LOAD_RC && !is_script) {
+      rcfile = get_variable ("RCFILE");
+      sprintf (line, "input %s/%s", home, rcfile);
+      status = command (line, &outline, TRUE);
+      if (outline != (char *) NULL) free (outline);
+      if (rcfile) free (rcfile);
+    }
+      
+    set_int_variable ("argv:n", 0);
+    if (is_script) {
+      /* first argument in input script, rest are argv */
+      list[Nlist] = strcreate (argv[1]);
+      Nlist ++;
+      /* generate list argv:0 - argv:n from arguments */
+      ALLOCATE (varname, char, 256);
+      for (i = 2; i < *argc; i++) {
+	sprintf (varname, "argv:%d", i - 2);
+	set_str_variable (varname, argv[i]);
+      }
+      set_int_variable ("argv:n", i - 2);
+      free (varname);
+    }
+
+    /* execute command-line entries */
+    for (i = 0; i < Nlist; i++) {
+      ALLOCATE (line, char, 1024);
+      sprintf (line, "input %s", list[i]);
+      status = command (line, &outline, TRUE);
+      if (outline != (char *) NULL) free (outline);
+    }
+    free (list);
+
+    /* if this is not an interactive session, exit here */
+    if (ONLY_INPUT) exit (40);
+    if (is_script) exit (41);
+    return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/string.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/string.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/string.c	(revision 16632)
@@ -0,0 +1,289 @@
+# include "opihi.h"
+
+/**********************************************************************/
+/* returns a pointer to an isolated string containing the first word,
+   removing leading WHITESPACE.  A "word" is a contiguous set of 
+   characters from the set: alphanumerics, and any of: / . _ -
+   Any other single, non-WHITESPACE characters are considered to be 
+   complete words in themselves.  Any characters surrounded by quotes 
+   make a single word 
+*/
+
+char *thisword (char *string) {
+
+  int i, j, N;
+  char *word;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (i = 0; OHANA_WHITESPACE (string[i]); i++);
+  if (string[i] == 0) return ((char *)NULL);
+  if (string[i] == ';') {
+    word = strncreate (&string[i], 1);
+    return (word);
+  }
+
+  /* a string of characters contained within double quotes is 
+      a single entry.  check that there are pairs of quotes,
+      return only the string between the quotes */
+  if (string[i] == '"') { 
+    i++;
+    if (string[i] == 0) return ((char *) NULL);
+    for (j = i; (string[j] != 0) && (string[j] != '"'); j++);
+    if (string[j] == 0) {
+      gprint (GP_ERR, "misbalanced quotes\n");
+      return ((char *)NULL);
+    }
+    //    for (; (string[j] != 0) && (!OHANA_WHITESPACE(string[j])); j++);
+    word = strncreate (&string[i], j - i);
+    return (word);
+  } 
+
+  /* a string of characters contained within parentheses is 
+      a single entry.  check that there are matched pairs of
+      parentheses, return string, including exterior parentheses */
+  if (string[i] == '(') { 
+    i++;
+    N = 1;
+    if (string[i] == 0) return ((char *) NULL);
+    for (j = i; (string[j] != 0) && (N > 0); j++) {
+      if (string[j] == '(') {
+	N++;
+      }
+      if (string[j] == ')') {
+	N--;
+      }
+    }
+    if ((string[j] == 0) && (N != 0)) {
+      gprint (GP_ERR, "misbalanced parenthesis\n");
+      return ((char *)NULL);
+    }
+    word = strncreate (&string[i-1], j - i + 1);
+    return (word);
+  } 
+
+
+  for (j = i; (string[j] != 0) && (string[j] != ';') && !OHANA_WHITESPACE(string[j]); j++);
+  word = strncreate (&string[i], j - i);
+  return (word);
+
+}
+
+/* returns a pointer to an isolated string containing the first command,
+   removing leading WHITESPACE.  A command ends with the first non WHITESPACE */
+char *thiscomm (char *string) {
+
+  int i, j;
+  char *word;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (i = 0; OHANA_WHITESPACE (string[i]); i++);
+  if (string[i] == 0) return ((char *)NULL);
+
+  for (j = i; ((string[j] != 0) && !OHANA_WHITESPACE (string[j])); j++);
+  if (i == j) return ((char *) NULL);
+
+  word = strncreate (&string[i], j - i);
+  return (word);
+
+}
+
+/* take a pointer to the beginning of a variable (ie $foo)
+and extract only the variable name (eg, foo) */
+
+char *thisvar (char *string) {
+
+  int i, start;
+  char *word;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (string[0] != '$') return ((char *) NULL);
+
+  /* special case $?name : check that name is valid */
+  start = 1;
+  if (string[1] == '?') start = 2;
+
+  for (i = start; ISVAR(string[i]); i++);
+  if (i == start) return ((char *) NULL);
+
+  /* the ? is part of the variable */
+  word = strncreate (&string[1], i - 1);
+  return (word);
+
+}
+
+
+/**********************************************************************/
+/* returns a pointer to the next word, or (char *) NULL if there is not a next word */
+char *nextword (char *string) {
+
+  int i, j;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+
+  for (i = 0; OHANA_WHITESPACE (string[i]); i++);
+  if (string[i] == 0) return ((char *)NULL);
+
+  if (string[i] == '"') { 
+    i++;
+    if (string[i] == 0) return ((char *) NULL);
+    for (; (string[i] != 0) && (string[i] != '"'); i++);
+    if (string[i] == 0) {
+      gprint (GP_ERR, "misbalanced quotes\n");
+      return ((char *)NULL);
+    }
+    i++;
+    for (; (string[i] != 0) && OHANA_WHITESPACE (string[i]); i++);
+    if (string[i] == 0) return ((char *) NULL);
+    return (&string[i]);
+  } 
+
+  if (string[i] == '(') { 
+    i++; 
+    j = 1;
+    if (string[i] == 0) return ((char *) NULL);
+    for (; (string[i] != 0) && (j > 0); i++) {
+      if (string[i] == '(') {
+	j++;
+      }
+      if (string[i] == ')') {
+	j--;
+      }
+    }
+    if ((string[i] == 0) && (j != 0)) {
+      gprint (GP_ERR, "misbalanced parenthesis\n");
+      return ((char *)NULL);
+    }
+    for (; (string[i] != 0) && OHANA_WHITESPACE (string[i]); i++);
+    if (string[i] == 0) return ((char *) NULL);
+    return (&string[i]);
+  } 
+
+  if (string[i] == ';') i++;
+  for (; (string[i] != 0) && (string[i] != ';') && !OHANA_WHITESPACE(string[i]); i++);
+  for (; (string[i] != 0) && OHANA_WHITESPACE (string[i]); i++);
+  if (string[i] == 0) return ((char *) NULL);
+
+  return (&string[i]);
+}
+
+/* returns a pointer to the next command, or (char *) NULL 
+   if there is not a next command.  A command is bounded by WHITESPACE */
+char *nextcomm (char *string) {
+
+  int i;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  
+  for (i = 0; (string[i] != 0) && !OHANA_WHITESPACE (string[i]); i++);
+  if (string[i] == 0) return ((char *) NULL);
+  
+  for (; OHANA_WHITESPACE (string[i]); i++);
+  if (string[i] == 0) return ((char *) NULL);
+
+  return (&string[i]);
+}
+
+/* returns a pointer to the previous word,
+   or (char *) NULL if there is not a previous word
+*/
+char *lastword (char *string, char *c) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (c == (char *) NULL) return ((char *) NULL);
+
+  for (; !OHANA_WHITESPACE(*c) && (c >= string); c--);
+  if (c < string) return ((char *)NULL);
+
+  for (; OHANA_WHITESPACE(*c) && (c >= string); c--);
+  if (c < string)
+    return ((char *)NULL);
+  for (; !OHANA_WHITESPACE(*c) && (c >= string); c--);
+  c++;
+  return (c);
+}
+
+
+
+/* take a pointer to the beginning of a variable (ie $fred) and return
+   a pointer to the next thing (non WHITESPACE) which is not part of the
+   variable extract only the variable name */
+
+char *aftervar (char *string) {
+
+  int i, j, start;
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (string[0] != '$') return ((char *) NULL);
+
+  /* special case: $?name : test only name */
+  start = 1;
+  if (string[1] == '?') start = 2;
+
+  for (i = start; ISVAR(string[i]); i++);
+  if (i == start) return ((char *) NULL);
+
+  for (j = i; OHANA_WHITESPACE (string[j]); j++);
+  if (string[j] == 0) return ((char *)NULL);
+
+  return (&string[j]);
+
+}
+
+
+/* returns a pointer to the previous var, 
+   or (char *) NULL if there is not a previous word
+*/
+char *lastvar (char *string, char *c) {
+
+  if (string == (char *) NULL) return ((char *) NULL);
+  if (c == (char *) NULL) return ((char *) NULL);
+
+  for (; (c >= string) && OHANA_WHITESPACE(*c); c--);
+  if (c < string) return ((char *)NULL);
+
+  for (; (c >= string) && ISVAR(*c) ; c--);
+  if ((c < string) || (*c != '$')) return ((char *)NULL);
+
+  return (c);
+}
+
+// append string defined by range start - stop to the end of output, which
+// currently has an allocated size of Noutput.  if this operation would overshoot Noutput, 
+// output is reallocated to a sufficiently large size
+char *opihi_append (char *output, int *Noutput, char *start, char *stop) {
+
+  int N1, N2, outlen;
+
+  // a NULL end pointer means 'go to end of line'
+  if (stop == NULL) {
+    stop = start + strlen(start);
+  }
+
+  // enough space?
+  N1 = strlen(output);
+  N2 = stop - start;
+  outlen = N1 + N2;
+  if (outlen >= *Noutput) {
+    *Noutput = outlen + 128;
+    REALLOCATE (output, char, *Noutput);
+    memset (&output[N1], 0, N2 + 128);
+  }
+
+  strncat (output, start, stop - start);
+  return output;
+}
+
+/* replace all instances of \A with A in line */
+void interpolate_slash (char *line) {
+
+  char *in, *out;
+
+  for (in = out = line; *in != 0; in++, out++) {
+    if (*in == 0x5c) in++;
+    *out = *in;
+    if (*in == 0) return;
+  }
+  *out = *in;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/timeformat.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/timeformat.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/timeformat.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "opihi.h"
+
+int GetTimeFormat (time_t *TimeReference, int *TimeFormat) {
+
+  char *p;
+
+  *TimeReference = 0;
+  if ((p = get_variable ("TIMEREF")) != (char *) NULL) {
+    if (!ohana_str_to_time (p, TimeReference)) {
+      gprint (GP_ERR, "error in TIME_REF format\n");
+      return (FALSE);
+    }
+    free (p);
+  }
+  *TimeFormat = FALSE;
+  if ((p = get_variable ("TIMEFORMAT")) != (char *) NULL) {
+    if (!strcasecmp (p, "JD")) *TimeFormat     = TIME_JD;
+    if (!strcasecmp (p, "MJD")) *TimeFormat    = TIME_MJD;
+    if (!strcasecmp (p, "date")) *TimeFormat   = TIME_DATE;
+    if (!strcasecmp (p, "days")) *TimeFormat   = TIME_DAYS;
+    if (!strcasecmp (p, "hours")) *TimeFormat  = TIME_HOURS;
+    if (!strcasecmp (p, "min")) *TimeFormat    = TIME_MINUTES;
+    if (!strcasecmp (p, "sec")) *TimeFormat    = TIME_SECONDS;
+    if (!*TimeFormat) gprint (GP_ERR, "unknown TIME_FORMAT\n");
+    free (p);
+    return (FALSE);
+  }
+  if (!*TimeFormat) *TimeFormat = TIME_SECONDS;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/variable.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/variable.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/variable.c	(revision 16632)
@@ -0,0 +1,370 @@
+# include "opihi.h"
+
+Variable *variables;   /* variable to store the list of all variables */
+int      Nvariables;   /* number of currently available variables */
+
+void InitVariables () {
+  Nvariables = 0;
+  ALLOCATE (variables, Variable, 1); 
+}
+
+void FreeVariables () {
+
+  int i; 
+
+  for (i = 0; i < Nvariables; i++) {
+    free (variables[i].name);
+    free (variables[i].value);
+  }
+  free (variables);
+}
+
+int set_local_variable (char *name, char *value) {
+
+  int i;
+  char *local, *MacroName;
+
+  /* a local variable has the form (macroname).(varname) */
+  MacroName = GetMacroName ();
+
+  /* look for global variable (warning or error)
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) {
+      gprint (GP_ERR, "warning: local variable overrides global name\n");
+    }
+  } */
+
+  /* look for existing local variable */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (local, variables[i].name)) {
+      free (variables[i].value);
+      free (local);
+      variables[i].value = strcreate (value);
+      return (TRUE);
+    }
+  }
+  /* NEW variable */
+  Nvariables ++;
+  REALLOCATE (variables, Variable, Nvariables);
+  variables[Nvariables - 1].name = local;
+  variables[Nvariables - 1].value = strcreate (value);
+  return (TRUE);
+}
+
+int set_str_variable (char *name, char *value) {
+
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (local, variables[i].name)) {
+      free (variables[i].value);
+      free (local);
+      variables[i].value = strcreate (value);
+      return (TRUE);
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) {
+      free (variables[i].value);
+      variables[i].value = strcreate (value);
+      return (TRUE);
+    }
+  }
+  /* NEW variable */
+  Nvariables ++;
+  REALLOCATE (variables, Variable, Nvariables);
+  variables[Nvariables - 1].name = strcreate (name);
+  variables[Nvariables - 1].value = strcreate (value);
+  return (TRUE);
+}
+
+int set_variable (char *name, double dvalue) {
+
+  char value[1024];
+
+  sprintf (value, "%.12g", dvalue);
+  set_str_variable (name, value);
+  return (TRUE);
+}
+
+int set_int_variable (char *name, int ivalue) {
+
+  char value[1024];
+
+  sprintf (value, "%d", ivalue);
+  set_str_variable (name, value);
+  return (TRUE);
+}
+
+static char variable_true[] = "1";
+static char variable_false[] = "0";
+
+char *get_variable_ptr (char *name) {
+  
+  int i;
+  char *local, *MacroName, *value;
+
+  if (name == NULL) return (NULL);
+  if (*name == 0) return (NULL);
+
+  /* check for the existence of the given name (after ?) */
+  /* return a string which should not be freed */
+  if (*name == '?') {
+    value = get_variable_ptr (&name[1]);
+    if (value == NULL) {
+      return variable_false;
+    }
+    return variable_true;
+  }
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (variables[i].value);
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      return (variables[i].value);
+    }
+  }
+  return (NULL);
+}
+
+char *get_variable (char *name) {
+  
+  int i;
+  char *local, *MacroName;
+  char *value;
+
+  if (name == NULL) return (NULL);
+  if (*name == 0) return (NULL);
+
+  /* check for the existence of the given name (after ?) */
+  /* return a string which can be freed */
+  if (*name == '?') {
+    value = get_variable_ptr (&name[1]);
+    if (value == NULL) {
+      value = strcreate (variable_false);
+      return value;
+    }
+    value = strcreate (variable_true);
+    return value;
+  }
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (strcreate (variables[i].value));
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      return (strcreate (variables[i].value));
+    }
+  }
+  return (NULL);
+}
+
+/* return TRUE / FALSE if name is an existant variable */
+int get_variable_exists (char *name) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (TRUE);
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      return (TRUE);
+    }
+  }
+  return (FALSE);
+}
+
+char *get_local_variable_ptr (char *name) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      return (variables[i].value);
+    }
+  }
+  free (local);
+  return (NULL);
+}
+
+float get_variable_default (char *name, float dvalue) {
+
+  char *value;
+  float fvalue;
+
+  value = get_variable (name);
+  if (value == NULL) {
+    return (dvalue);
+  }
+  fvalue = atof (value);
+  return (fvalue);
+}
+
+double get_double_variable (char *name, int *found) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      free (local);
+      *found = TRUE;
+      return (atof (variables[i].value));
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      *found = TRUE;
+      return (atof (variables[i].value));
+    }
+  }
+  *found = FALSE;
+  return (0.0);
+}
+
+int get_int_variable (char *name, int *found) {
+  
+  int i;
+  char *local, *MacroName;
+
+  MacroName = GetMacroName ();
+
+  /* look for local variable first */
+  ALLOCATE (local, char, strlen(name) + strlen(MacroName) + 2);
+  sprintf (local, "%s.%s", MacroName, name);
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(local, variables[i].name)) {
+      *found = TRUE;
+      free (local);
+      return (atof (variables[i].value));
+    }
+  }
+  free (local);
+
+  /* look for global variable */
+  for (i = 0; i < Nvariables; i++) { /* find the variable mentioned */
+    if (!strcmp(name, variables[i].name)) {
+      *found = TRUE;
+      return (atof (variables[i].value));
+    }
+  }
+  *found = FALSE;
+  return (0.0);
+}
+
+int DeleteNamedScalar (char *name) {
+
+  int i, j;
+
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) {
+      free (variables[i].name);
+      free (variables[i].value);
+      for (j = i; j < Nvariables - 1; j++) {
+	variables[j] = variables[j + 1];
+      }
+      Nvariables --;
+      REALLOCATE (variables, Variable, MAX (Nvariables, 1));
+      return (TRUE);
+    }
+  }
+  return (FALSE);
+}
+
+int IsScalar (char *name) { 
+
+  int i;
+
+  for (i = 0; i < Nvariables; i++) {
+    if (!strcmp (name, variables[i].name)) return (TRUE);
+  }
+  return (FALSE);
+}
+
+void ListVariables () {
+
+  int i;
+
+  if (Nvariables == 0) {
+    gprint (GP_ERR, "No defined variables\n");
+    return;
+  }
+
+  for (i = 0; i < Nvariables; i++) {
+    gprint (GP_ERR, "%s = %s\n", variables[i].name, variables[i].value);
+  }
+  return;
+}
+
+int SelectScalar (char *string, double *value) {
+
+  char *end;
+
+  /* if string is a number, return TRUE */
+  *value = strtod (string, &end);
+  if (end == string + strlen(string)) return (TRUE);
+
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/lib.shell/version.c	(revision 16632)
@@ -0,0 +1,6 @@
+# include "shell.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+char *opihi_version () {
+  return (name);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/Makefile	(revision 16632)
@@ -0,0 +1,49 @@
+default: mana
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+SRC     =       $(HOME)/mana
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+DATA    =       $(DESTDATA)/mana
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+LIBS1   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata 
+LIBS2   =       -ldvo -lkapa -lFITS -lohana
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(LIBS1) $(LIBS2) $(BASE_LDFLAGS)
+
+# mana user commands and support functions ########################
+funcs = \
+$(SRC)/init.$(ARCH).o \
+$(SRC)/mana.$(ARCH).o \
+$(SRC)/findrowpeaks.$(ARCH).o 
+
+cmds = \
+$(SRC)/rawstars.$(ARCH).o \
+$(SRC)/fitcontour.$(ARCH).o \
+$(SRC)/starcontour.$(ARCH).o \
+$(SRC)/version.$(ARCH).o \
+$(SRC)/findpeaks.$(ARCH).o 
+
+libs = \
+$(DESTLIB)/libshell.a \
+$(DESTLIB)/libdata.a \
+$(DESTLIB)/libbasiccmd.a \
+$(DESTLIB)/libastrocmd.a \
+$(DESTLIB)/libdatacmd.a
+
+mana: $(BIN)/mana.$(ARCH)
+$(SRC)/mana.$(ARCH).o : $(libs)
+$(BIN)/mana.$(ARCH)   : $(cmds) $(funcs)
+
+install: $(DESTBIN)/mana help modules
+
+help: clean-help cmd.basic.help cmd.data.help cmd.astro.help
+
+modules: mana.modules
+
+.PHONY: mana
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/adc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/adc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/adc.c	(revision 16632)
@@ -0,0 +1,117 @@
+# include "dimm.h"
+
+# define DIGITAL_OUT 0x40
+# define ANALOG_IN_INIT 0x00
+# define ANALOG_IN_HIGH 0xa1
+# define ANALOG_IN_LOW  0x91
+
+static char SerialConnected = FALSE;
+static unsigned char DigitalOutState = 0x00;
+static struct timeval reftime; 
+static char reftimeset = FALSE;
+
+# define DTIME(A,B) ((A.tv_sec - B.tv_sec) + 1e-6*(A.tv_usec - B.tv_usec))
+
+int adc (int argc, char **argv) {
+  
+  struct timeval now;
+  int i, N, mode, hi, lo, value;
+  unsigned char setbit, output[5], *input;
+  double dtime;
+
+  if (N = get_argument (argc, argv, "-reset")) {
+    remove_argument (N, &argc, argv);
+    gettimeofday (&reftime, (struct timeval *) NULL);
+    reftimeset = TRUE;
+    return (TRUE);
+  }
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: adc ai N (variable)\n");
+    gprint (GP_ERR, "USAGE: adc di N (variable)\n");
+    gprint (GP_ERR, "USAGE: adc do N mode\n");
+    return (FALSE);
+  }
+
+  if (!SerialConnected) {
+    if (!SerialInit ('b')) {
+      gprint (GP_ERR, "error opening serial line\n");
+      return (FALSE);
+    }
+    SerialConnected = TRUE;
+  }
+
+  if (!reftimeset) {
+    gettimeofday (&reftime, (struct timeval *) NULL);
+    reftimeset = TRUE;
+  }      
+
+  gettimeofday (&now, (struct timeval *) NULL);
+  dtime = DTIME (now, reftime);
+  set_variable ("TIME", dtime);
+  
+  /* set the digital outputs */
+  if (!strcmp (argv[1], "do")) {
+    N = atof (argv[2]);
+    if ((N < 1) || (N > 6)) {
+      gprint (GP_ERR, "digital output is between 1 and 6\n");
+      return (FALSE);
+    }
+    if (!strcasecmp (argv[3], "on")) {
+      mode = TRUE;
+    } else {
+      mode = FALSE;
+    }
+    setbit = (0x01 << N-1);
+    if (mode) {
+      DigitalOutState |= setbit;
+    } else {
+      DigitalOutState &= ~setbit;
+    }      
+    output[0] = (DIGITAL_OUT | DigitalOutState);
+    output[1] = 0;
+    SerialCommand (output, &input, 50);
+    gprint (GP_ERR, "%x (%x, %x) -> %x (%d, %d)\n", 
+	     output[0], setbit, DigitalOutState, input[0], 
+	     strlen(input), strlen(output));
+    free (input);
+    return (TRUE);
+  }
+  /* read the analog inputs */
+  if (!strcmp (argv[1], "ai")) {
+    N = atof (argv[2]);
+    if ((N < 2) || (N > 16)) {
+      gprint (GP_ERR, "analog input is between 2 and 16\n");
+      gprint (GP_ERR, " (problem with 1 for the moment...)\n");
+      return (FALSE);
+    }
+    /* init A/D converter */
+    output[0] = (ANALOG_IN_INIT | (N-1));
+    output[1] = 0;
+    SerialCommand (output, &input, 50);
+    free (input);
+
+    usleep (10000);
+    /* get high byte */
+    output[0] = ANALOG_IN_HIGH;
+    output[1] = 0;
+    do {
+      SerialCommand (output, &input, 50);
+      hi = input[0];
+      free (input);
+    } while (hi & 0x80);
+
+    output[0] = ANALOG_IN_LOW;
+    output[1] = 0;
+    SerialCommand (output, &input, 50);
+    /* gprint (GP_ERR, "%x -> %x\n", output[0], input[0]); */
+    lo = input[0];
+    free (input);
+    value = ((hi & 0x0f) << 8) | lo;
+    if (hi & 0x10) { value = -value; }
+    set_variable (argv[3], 0.0001*value);
+    return (TRUE);
+  }
+
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/demux.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/demux.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/demux.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "dimm.h"
+
+int demux (int argc, char **argv) {
+  
+  int i, j, k, N;
+  float *out, *in, *inptr, **outptr;
+  int nx, ny, Nx, Ny, NX, NY, Nmux, Nbuf;
+
+  if (argc != 4) {
+    gprint (GP_ERR, "USAGE: demux <buffer> nx ny\n");
+    return (FALSE);
+  }
+
+  if (!SelectBuffer (&Nbuf, argv[1], OLDBUFFER)) return (FALSE);
+
+  nx = atof (argv[2]);
+  ny = atof (argv[3]);
+  Nmux = nx*ny;
+
+  Nx = buffers[Nbuf].matrix.Naxis[0];
+  Ny = buffers[Nbuf].matrix.Naxis[1];
+
+  NX = Nx / nx;
+  NY = Ny / ny;
+
+  inptr = in = (float *) buffers[Nbuf].matrix.buffer;  /* don't lose reference */
+
+  ALLOCATE (out, float, Nx*Ny);
+  ALLOCATE (outptr, float *, Nmux);
+  
+  for (N = i = 0; i < nx; i++) {
+    for (j = 0; j < ny; j++, N++) {
+      outptr[N] = &out[i*NX + j*NX*NY*nx];
+    }
+  }
+
+  for (N = j = 0; j < NY; j++) {
+    for (i = 0; i < NX; i++) {
+      for (k = 0; k < Nmux; k++) {
+	*outptr[k] = *inptr;
+	outptr[k] ++;
+	inptr ++;
+      }
+    }
+    for (k = 0; k < Nmux; k++) outptr[k] += NX;
+  }
+
+  /*
+  for (X = Y = x = y = i = 0; i < NX*NY; i++) {
+    out[X + Y*NX + x*NX*(Y+1) + y*NX*NY*nx] = *in;
+    X++;
+    if (X == NX) {
+      X = 0;
+      Y++;
+    }
+    if (Y == NY) {
+      Y = 0;
+      x++;
+    }
+    if (x == nx) {
+      x = 0;
+      y++;
+    }
+  }
+  */
+
+  free (in);
+  buffers[Nbuf].matrix.buffer = (char *) out;
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/findpeaks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/findpeaks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/findpeaks.c	(revision 16632)
@@ -0,0 +1,106 @@
+# include "mana.h"
+
+int findpeaks (int argc, char **argv) {
+  
+  int i, j, n, N, Nx, Ny;
+  int xo, yo;
+  int Npeak, NPEAK, Npeaks;
+  float *v;
+  int *peaks, *keep, *xp, *yp, *zp;
+  float threshold, vt, vo;
+  Vector *vecx, *vecy, *vecz;
+  Buffer *buf;
+
+  if (argc < 3) goto usage;
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  threshold = atof (argv[2]);
+
+  if ((vecx = SelectVector ("xp", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector ("yp", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecz = SelectVector ("zp", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+
+  Npeak = 0;
+  NPEAK = Nx;
+  ALLOCATE (xp, int, NPEAK);
+  ALLOCATE (yp, int, NPEAK);
+  ALLOCATE (zp, int, NPEAK);
+
+  /* find peaks for each row */
+  v = (float *) buf[0].matrix.buffer;
+  for (j = 0; j < Ny; j++) {
+    peaks = findrowpeaks (&v[j*Nx], Nx, threshold, &Npeaks);
+
+    if (Npeak + Npeaks >= NPEAK) {
+      NPEAK = Npeak + Npeaks + Nx;
+      REALLOCATE (xp, int, NPEAK);
+      REALLOCATE (yp, int, NPEAK);
+      REALLOCATE (zp, int, NPEAK);
+    }
+    for (i = 0; i < Npeaks; i++) {
+      xp[Npeak + i] = peaks[i];
+      yp[Npeak + i] = j;
+      zp[Npeak + i] = v[peaks[i] + j*Nx];
+    }
+    Npeak += Npeaks;
+    free (peaks);
+  }
+  
+  /* identify non-local peaks */
+  ALLOCATE (keep, int, MAX (Npeak, 1));
+  v = (float *) buf[0].matrix.buffer;
+  for (n = 0; n < Npeak; n++) {
+    xo = xp[n];
+    yo = yp[n];
+    vo = v[xo + yo*Nx];
+    keep[n] = TRUE;
+    for (i = xo - 1; i <= xo + 1; i++) {
+      if (i < 0) continue;
+      if (i >= Nx) continue;
+      for (j = yo - 1; j <= yo + 1; j++) {
+	if ((i == xo) && (j == yo)) continue;
+	if (j < 0) continue;
+	if (j >= Ny) continue;
+	vt = v[i + j*Nx];
+	if (vt > vo) {
+	  keep[n] = FALSE;
+	  goto next_peak;
+	}
+      }
+    }
+  next_peak:
+    continue;
+  }
+
+  REALLOCATE (vecx[0].elements, float, MAX (Npeak, 1));
+  REALLOCATE (vecy[0].elements, float, MAX (Npeak, 1));
+  REALLOCATE (vecz[0].elements, float, MAX (Npeak, 1));
+  /* eliminate non-local peaks */
+  for (N = n = 0; n < Npeak; n++) {
+    if (!keep[n]) continue;
+    vecx[0].elements[N] = xp[n];
+    vecy[0].elements[N] = yp[n];
+    vecz[0].elements[N] = zp[n];
+    N ++;
+  }
+  free (xp);
+  free (yp);
+  free (zp);
+  free (keep);
+
+  REALLOCATE (vecx[0].elements, float, MAX (N, 1));
+  REALLOCATE (vecy[0].elements, float, MAX (N, 1));
+  REALLOCATE (vecz[0].elements, float, MAX (N, 1));
+  vecx[0].Nelements = vecy[0].Nelements = vecz[0].Nelements = N;
+
+  return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "findpeaks (buffer) (threshold)\n");
+  return (FALSE);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/findrowpeaks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/findrowpeaks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/findrowpeaks.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "mana.h"
+
+int *findrowpeaks (float *row, int Nrow, float threshold, int *npeaks) {
+  
+  int i;
+  int Npeaks, NPEAKS;
+  int *peaks;
+
+  Npeaks = 0;
+  NPEAKS = 100;
+  ALLOCATE (peaks, int, NPEAKS);
+
+  if (Nrow < 3) {
+    *npeaks = Npeaks;
+    return (peaks);
+  }
+    
+  /* special case for first pixel in row */
+  if ((row[0] > row[1]) && (row[0] > threshold)) {
+    peaks[Npeaks] = 0;
+    Npeaks ++;
+  }    
+
+  for (i = 1; i < Nrow - 1; i++) {
+    if (row[i] < threshold) continue;
+    if (row[i] < row[i-1]) continue;
+    if (row[i] <= row[i+1]) continue;
+
+    peaks[Npeaks] = i;
+    Npeaks ++;
+    if (Npeaks >= NPEAKS) {
+      NPEAKS += 100;
+      REALLOCATE (peaks, int, NPEAKS);
+    }
+  }      
+
+  /* special case for last pixel in row */
+  if ((row[Nrow-1] >= row[Nrow-2]) && (row[Nrow-1] > threshold)) {
+    peaks[Npeaks] = Nrow-1;
+    Npeaks ++;
+  }    
+
+  *npeaks = Npeaks;
+  return (peaks);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/fitcontour.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/fitcontour.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/fitcontour.c	(revision 16632)
@@ -0,0 +1,139 @@
+# include "mana.h"
+# define NTERM 3
+
+int fitcontour (int argc, char **argv) {
+  
+  int i;
+  double **C, **B;
+  float cs1, sn1, cs, sn, x, y, r, xo, yo;
+  float dR, Rmin, Rmaj, Theta, Rx, Ry, Rxy, R1, R2, R3;
+  Vector *vecx, *vecy;
+
+  /* USAGE fitcontour x y Xo Yo */
+  if (argc < 5) goto usage;
+
+  if ((vecx = SelectVector (argv[1], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector (argv[2], ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  xo = atof (argv[3]);
+  yo = atof (argv[4]);
+
+  ALLOCATE (B, double *, NTERM);
+  ALLOCATE (C, double *, NTERM);
+  for (i = 0; i < NTERM; i++) {
+    ALLOCATE (C[i], double, NTERM);
+    bzero (C[i], NTERM*sizeof(double));
+    ALLOCATE (B[i], double, 1);
+    bzero (B[i], sizeof(double));
+  }
+
+  /* we are fitting r = ro + rs*sin(2theta) + rc*cos(2theta) */
+  /* sin(2t) = 2cos(t)sin(t)
+     cos(2t) = cos^2(t) - sin^2(t)
+  */
+  for (i = 0; i < vecx[0].Nelements; i++) {
+    x = vecx[0].elements[i] - xo;
+    y = vecy[0].elements[i] - yo;
+    r = hypot (x, y);
+
+    /* calculate sin(2t), cos(2t) using 1/2 angle tri relationship above */
+    sn1 = y / r;
+    cs1 = x / r;
+    sn = 2*sn1*cs1;
+    cs = cs1*cs1 - sn1*sn1;
+
+    C[0][0] += 1.0;
+    C[1][0] += sn;
+    C[1][1] += SQ(sn);
+    C[2][0] += cs; 
+    C[2][1] += cs*sn; 
+    C[2][2] += SQ(cs);
+
+    B[0][0] += r;
+    B[1][0] += r*sn;
+    B[2][0] += r*cs; 
+  }
+  C[0][1] = C[1][0];
+  C[0][2] = C[2][0];
+  C[1][2] = C[2][1];
+    
+  dgaussjordan (C, B, NTERM, 1);
+  
+  /** this is somewhat weak: if the object is too elongated, Rmin can be < 0 **/
+  dR = hypot (B[1][0], B[2][0]);
+  Rmaj = B[0][0] + dR;
+  Rmin = B[0][0] - dR;
+  Theta = DEG_RAD*atan2 (B[1][0], B[2][0]) / 2;
+
+  sn = B[1][0] / dR;
+  cs = B[2][0] / dR;
+
+  R1 = SQ(Rmaj) + SQ(Rmin);
+  R2 = SQ(Rmaj) - SQ(Rmin);
+  R3 = Rmaj*Rmin;
+
+  Rx = R3 / sqrt (R1 - R2*cs);
+  Ry = R3 / sqrt (R1 + R2*cs);
+  Rxy = -sn*R2 / SQ(R3);
+
+  set_variable ("Rx", Rx);
+  set_variable ("Ry", Ry);
+  set_variable ("Rxy", Rxy);
+
+  set_variable ("Rmin", Rmin);
+  set_variable ("Rmaj", Rmaj);
+  set_variable ("Theta", Theta);
+
+  for (i = 0; i < NTERM; i++) {
+    free (B[i]);
+    free (C[i]);
+  }
+  free (B);
+  free (C);
+
+  return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "fitcontour x y (xo) (yo)\n");
+  return (FALSE);
+}
+
+
+/* this routine fits a single sine and cosine to the value of dr as a function of the angle around the central
+ * point, theta.  this is NOT an exact fit, an is increasingly in error for more eccentric ellipses.  however,
+ * it does a reasonable job of approximating the value of the major and minor axes, and it gets the angle of
+ * orientation right at well.  We then assume the values of major and minor axis and angle are correct to get
+ * the parameters for the elliptical gaussian fit:
+ 
+ z = (x^2) / (2 Rx^2) + (y^2) / (2 Ry^2) + Rxy x y
+
+ the functions above give the correct relationship between these:
+
+   R1 = SQ(Rmaj) + SQ(Rmin);
+   R2 = SQ(Rmaj) - SQ(Rmin);
+   R3 = Rmaj*Rmin;
+
+   Rx = R3 / sqrt (R1 - R2*cs);
+   Ry = R3 / sqrt (R1 + R2*cs);
+   Rxy = -sn*R2 / SQ(R3);
+
+ to derive these relationships, write the equation for an ellipse with major axis in the x-dir and minor in
+ the y-dir:
+
+ z = (x^2) / (2 Rmaj^2) + (y^2) / (2 Rmin^2)
+
+ apply the rotation matrix:
+
+ (x)' = (cos, -sin)(x,y)
+ (y)' = (sin, +cos)(x,y)  (modulo the sign on the sine)
+
+ then group the x^2 terms, the y^2 terms, and the xy terms to find the three coeffs.
+
+ NOTE: I spent a while having trouble deriving this from the polar form of an ellipse:
+
+ x = Rmaj*cos(theta)
+ y = Rmin*sin(theta)
+
+ it turns out that 'theta' above is NOT the angle (0,1)-(0,0)-(x,y). rather, it should be viewed as a
+ paraterization of the ellipse.  
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/focus.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/focus.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/focus.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "dimm.h"
+
+int focus (int argc, char **argv) {
+  
+  if (argc < 2) goto usage;
+
+  if (!strcasecmp (argv[1], "init")) {
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: focus init (port)\n");
+      return (FALSE);
+    }
+    if (!SerialInit (argv[2])) return (FALSE);
+    gprint (GP_ERR, "focus on port %s\n", argv[2]);
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "pos")) {
+
+    int status, servo, angle;
+    char *answer = (char *) NULL;
+    char line[64];
+
+    if (argc != 4) {
+      gprint (GP_ERR, "USAGE: focus pos Nservo (angle)\n");
+      return (FALSE);
+    }
+
+    servo = atoi (argv[2]);
+    angle = atoi (argv[3]);
+
+    sprintf (line, "%c%c%c\n", 0xff, servo, angle);
+    status = SerialCommand (line, &answer, 10);
+    gprint (GP_ERR, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      gprint (GP_ERR, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "raw")) {
+
+    int status, value;
+    char *answer = (char *) NULL;
+    char line[64];
+
+    if (argc != 3) {
+      gprint (GP_ERR, "USAGE: focus raw value\n");
+      return (FALSE);
+    }
+
+    value = atoi (argv[2]);
+
+    sprintf (line, "%c", value);
+    status = SerialCommand (line, &answer, 10);
+    gprint (GP_ERR, "status: %d\n", status);
+    if (answer != (char *) NULL) {
+      gprint (GP_ERR, "answer: ..%s..\n", answer);
+    }
+    return (TRUE);
+  }
+
+ usage:
+  gprint (GP_ERR, "focus init port\n");
+  gprint (GP_ERR, "focus pos (string)\n");
+  gprint (GP_ERR, "focus raw (value)\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/init.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "opihi.h"
+
+int findpeaks	    PROTO((int, char **));
+int fitcontour	    PROTO((int, char **));
+int starcontour	    PROTO((int, char **));
+int rawstars	    PROTO((int, char **));
+int version	    PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "findpeaks",   findpeaks,    "find image peaks"},
+  {1, "fitcontour",  fitcontour,   "fit ellipse contour"},
+  {1, "starcontour", starcontour,  "object contour"},
+  {1, "rawstars",    rawstars,     "find raw star stats"},
+  {1, "version",     version,      "show version information"},
+}; 
+
+void InitMana () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
+
+void FreeMana () {
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/mana.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/mana.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/mana.c.in	(revision 16632)
@@ -0,0 +1,69 @@
+# include "mana.h"
+
+# define opihi_name "MANA"
+# define opihi_prompt "mana: "
+# define opihi_description "an image manipulation tool\n"
+# define opihi_history ".mana"
+# define opihi_rcfile ".manarc"
+
+/* program-dependent initialization */
+void program_init (int *argc, char **argv) {
+  
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitMana ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  {
+    char *helpdir;
+    char *modules;
+    static char *datadir = "@DATADIR@";
+    ALLOCATE (helpdir, char, strlen(datadir) + strlen("/help") + 2);
+    sprintf (helpdir, "%s/help", datadir);
+    set_str_variable ("HELPDIR", helpdir);
+    free (helpdir);
+    ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+    sprintf (modules, "%s/modules", datadir);
+    set_str_variable ("MODULES:0", modules);
+    set_int_variable ("MODULES:n", 1);
+    free (modules);
+  }
+
+  return;
+}
+
+/* standard welcome message */
+void welcome () {
+  gprint (GP_ERR, "\n");
+  gprint (GP_ERR, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  QuitKapa ();
+  ConfigFree ();
+  
+  FreeBasic ();
+  FreeData ();
+  FreeAstro ();
+  FreeMana ();
+
+  return;
+}
+
+/* call to opihi shell */
+int main (int argc, char **argv) {
+  int status;
+  status = opihi (argc, argv);
+  exit (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/opihi.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/opihi.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/opihi.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "opihi.h"
+
+# define opihi_name "Opihi"
+# define opihi_prompt "opihi: "
+# define opihi_description "Opihi - test shell\n"
+# define opihi_history ".opihi"
+# define opihi_rcfile ".opihirc"
+
+void InitBasic ();
+
+void welcome () {
+  gprint (GP_ERR, "\n");
+  gprint (GP_ERR, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* program-dependent initialization */
+void initialize (int argc, char **argv) {
+  
+  FILE *f;
+
+  auto_break = TRUE;
+
+  /* init functions required by libraries */
+  /* -libopihi */
+  InitCommands ();
+  InitMacros ();
+  InitBuffers ();
+  InitVectors ();
+  InitVariables ();
+
+  /* -libdisplay
+  InitGraph ();
+  InitImage (); */
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  /* here we open the history file for append.  it this fails, we
+     won't be able to write to it, warn the user.  otherwise, this
+     creates the file readline will write to, if it did not exist */  
+
+  /* check history file */
+  /* rewrite with fstat or stat */
+  f = fopen (opihi_history, "a");
+  if (f == NULL) /* no current history file here */
+    gprint (GP_ERR, "can't save history.\n");
+  else
+    fclose (f);
+  
+  stifle_history (200);
+  read_history (opihi_history);
+
+  signal (SIGINT, SIG_IGN);
+  return;
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  QuitKapa ();
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/rawstars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/rawstars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/rawstars.c	(revision 16632)
@@ -0,0 +1,95 @@
+# include "mana.h"
+
+int rawstars (int argc, char **argv) {
+  
+  int i, x, y, N, Nx, Ny, Np;
+  float *v;
+  double Raper, Rinner, Router;
+  Vector *xp, *yp;
+  Vector *xc, *yc, *sx, *sy, *sxy, *zs, *zc, *sk;
+  Buffer *buff;
+
+  Raper = 5;
+  if ((N = get_argument (argc, argv, "-Raper"))) {
+    remove_argument (N, &argc, argv);
+    Raper = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Rinner = 10;
+  if ((N = get_argument (argc, argv, "-Rinner"))) {
+    remove_argument (N, &argc, argv);
+    Rinner = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  Router = 15;
+  if ((N = get_argument (argc, argv, "-Router"))) {
+    remove_argument (N, &argc, argv);
+    Router = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 4) goto usage;
+
+  if ((buff = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  if ((xp = SelectVector (argv[2], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yp = SelectVector (argv[3], OLDVECTOR, TRUE)) == NULL) return (FALSE);
+  if (xp[0].Nelements != yp[0].Nelements) {
+    gprint (GP_ERR, "vectors are not the same length\n");
+    return (FALSE);
+  }
+
+  set_rough_radii (Raper, Rinner, Router);
+
+  /* output vectors */
+  if ((xc = SelectVector ("xc", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((yc = SelectVector ("yc", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zc = SelectVector ("zc", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((zs = SelectVector ("zs", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((sk = SelectVector ("sk", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((sx = SelectVector ("sx", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((sy = SelectVector ("sy", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((sxy = SelectVector ("sxy", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  Nx = buff[0].matrix.Naxis[0];
+  Ny = buff[0].matrix.Naxis[1];
+  Np = xp[0].Nelements;
+
+  REALLOCATE (xc[0].elements, float, Np);
+  REALLOCATE (yc[0].elements, float, Np);
+  REALLOCATE (sx[0].elements, float, Np);
+  REALLOCATE (sy[0].elements, float, Np);
+  REALLOCATE (sxy[0].elements, float, Np);
+  REALLOCATE (zs[0].elements, float, Np);
+  REALLOCATE (zc[0].elements, float, Np);
+  REALLOCATE (sk[0].elements, float, Np);
+  xc[0].Nelements = yc[0].Nelements = sx[0].Nelements = Np;
+  sy[0].Nelements = zs[0].Nelements = zc[0].Nelements = Np;
+  sxy[0].Nelements = sk[0].Nelements = Np;
+
+  v = (float *) buff[0].matrix.buffer;
+  for (i = 0; i < Np; i++) {
+    x = xp[0].elements[i];
+    y = yp[0].elements[i];
+    if (x < 0) continue;
+    if (x >= Nx) continue;
+    if (y < 0) continue;
+    if (y >= Ny) continue;
+
+    get_rough_star (v, Nx, Ny, x, y, 
+		    &xc[0].elements[i], 
+		    &yc[0].elements[i], 
+		    &sx[0].elements[i], 
+		    &sy[0].elements[i], 
+		    &sxy[0].elements[i], 
+		    &zs[0].elements[i], 
+		    &zc[0].elements[i],
+		    &sk[0].elements[i]);
+  }
+
+  return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "rawstars (buffer) (xp) (yp)\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/simsignal.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/simsignal.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/simsignal.c	(revision 16632)
@@ -0,0 +1,50 @@
+# include "dimm.h"
+
+int simsignal (int argc, char **argv) {
+  
+  int Nvect, Nbin, Nbit, i, ivalue, jvalue, Nshift, mask, scale;
+  float *buf;
+  double cvalue, dvalue, sigma, SN, period;
+  double rnd_gauss ();
+
+  if (argc != 5) {
+    gprint (GP_ERR, "USAGE: simsignal (vector) Nbin Nbits period\n");
+    return (FALSE);
+  }
+
+  if (!SelectVector (&Nvect, argv[1], ANYVECTOR)) return (FALSE);
+  Nbin = atof (argv[2]);
+  Nbit = atof (argv[3]);
+  /* SN = atof (argv[4]); */
+  period = atof (argv[4]);
+
+  vectors[Nvect].Nelements = Nbin;
+  REALLOCATE (vectors[Nvect].elements, float, vectors[Nvect].Nelements);
+
+  scale = (0x1 << Nbit) - 1;
+
+  buf = vectors[Nvect].elements;
+  for (i = 0; i < Nbin; i++, buf++) {
+    ivalue = scale * 0.5 * (sin (i*2*M_PI/period) + 1) + 0.5;
+    /*
+    dvalue = rnd_gauss (cvalue, sigma);
+    cvalue = (dvalue + range) / (2.0*range);
+    dvalue = MAX (0, MIN (0.99999, cvalue));
+    ivalue = scale * dvalue;
+    *buf = (2.0 * range * ((double) ivalue + 0.5)) / scale - range; 
+    */
+    *buf = ivalue;
+  }
+
+  return (TRUE);
+}
+
+/* 
+
+8 bit = 2^8
+
+  gauss_init (2*scale);
+  sigma = 2.0 / SN;
+  range = 1 + 5*sigma;
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/starcontour.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/starcontour.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/starcontour.c	(revision 16632)
@@ -0,0 +1,130 @@
+# include "mana.h"
+
+int starcontour (int argc, char **argv) {
+  
+  int x, y, xs, xp, yp;
+  int Nx, Ny, N, Npts, min, max;
+  float *v;
+  float zt, zo, xmin, xmax;
+  Vector *vecx, *vecy;
+  Buffer *buf;
+
+  if (argc < 5) goto usage;
+
+  if ((buf = SelectBuffer (argv[1], OLDBUFFER, TRUE)) == NULL) return (FALSE);
+  xp = atof (argv[2]);
+  yp = atof (argv[3]);
+  zo = atof (argv[4]);
+
+  if ((vecx = SelectVector ("xo", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+  if ((vecy = SelectVector ("yo", ANYVECTOR, TRUE)) == NULL) return (FALSE);
+
+  N = 0;
+  Npts = 100;
+  REALLOCATE (vecx[0].elements, float, MAX (Npts, 1));
+  REALLOCATE (vecy[0].elements, float, MAX (Npts, 1));
+
+  Nx = buf[0].matrix.Naxis[0];
+  Ny = buf[0].matrix.Naxis[1];
+  v = (float *)buf[0].matrix.buffer;
+
+  /* find transition below (limit range?) */
+  xmin = xmax = 0;
+  xs = xp;
+  for (y = yp; (y >= 0) && (v[xs + y*Nx] > zo); y--) {
+    /* find transition below (limit range?) */
+    min = max = FALSE;
+    for (x = xs; (x >= 0) && !min; x--) {
+      min = FALSE;
+      zt = v[x + y*Nx];
+      if (zt < zo) {
+	min = TRUE;
+	xmin = x + (zo - zt)/(v[x + 1 + y*Nx] - zt);
+	vecx[0].elements[N] = xmin;
+	vecy[0].elements[N] = y;
+	N ++;
+	if (N >= Npts) {
+	  Npts += 100;
+	  REALLOCATE (vecx[0].elements, float, MAX (Npts, 1));
+	  REALLOCATE (vecy[0].elements, float, MAX (Npts, 1));
+	}
+      }
+      /* ignore edge cases? */
+    }
+    /* find transition above (limit range?) */
+    for (x = xs; (x < Nx) && !max; x++) {
+      max = FALSE;
+      zt = v[x + y*Nx];
+      if (zt < zo) {
+	max = TRUE;
+	xmax = x - (zo - zt)/(v[x - 1 + y*Nx] - zt);
+	vecx[0].elements[N] = xmax;
+	vecy[0].elements[N] = y;
+	N ++;
+	if (N >= Npts) {
+	  Npts += 100;
+	  REALLOCATE (vecx[0].elements, float, MAX (Npts, 1));
+	  REALLOCATE (vecy[0].elements, float, MAX (Npts, 1));
+	}
+      }
+      /* ignore edge cases? */
+    }
+    if (min && max) {
+      xs = 0.5*(xmin + xmax);
+    }
+  }
+
+  /* find transition above (limit range?) */
+  xs = xp;
+  for (y = yp; (y < Ny) && (v[xs + y*Nx] > zo); y++) {
+    /* find transition below (limit range?) */
+    min = max = FALSE;
+    for (x = xs; (x >= 0) && !min; x--) {
+      min = FALSE;
+      zt = v[x + y*Nx];
+      if (zt < zo) {
+	min = TRUE;
+	xmin = x + (zo - zt)/(v[x + 1 + y*Nx] - zt);
+	vecx[0].elements[N] = xmin;
+	vecy[0].elements[N] = y;
+	N ++;
+	if (N >= Npts) {
+	  Npts += 100;
+	  REALLOCATE (vecx[0].elements, float, MAX (Npts, 1));
+	  REALLOCATE (vecy[0].elements, float, MAX (Npts, 1));
+	}
+      }
+      /* ignore edge cases? */
+    }
+    /* find transition above (limit range?) */
+    for (x = xs; (x < Nx) && !max; x++) {
+      max = FALSE;
+      zt = v[x + y*Nx];
+      if (zt < zo) {
+	max = TRUE;
+	xmax = x - (zo - zt)/(v[x - 1 + y*Nx] - zt);
+	vecx[0].elements[N] = xmax;
+	vecy[0].elements[N] = y;
+	N ++;
+	if (N >= Npts) {
+	  Npts += 100;
+	  REALLOCATE (vecx[0].elements, float, MAX (Npts, 1));
+	  REALLOCATE (vecy[0].elements, float, MAX (Npts, 1));
+	}
+      }
+      /* ignore edge cases? */
+    }
+    if (min && max) {
+      xs = 0.5*(xmin + xmax);
+    }
+  }
+  vecx[0].Nelements = N;
+  vecy[0].Nelements = N;
+
+  return (TRUE);
+
+ usage:
+  gprint (GP_ERR, "starcontour (buffer) (xpeak) (ypeak) (level)\n");
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/tests.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/tests.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/tests.c	(revision 16632)
@@ -0,0 +1,108 @@
+# include "opihi.h"
+
+run_tests () {
+
+  /* test1 ();
+     test1b ();
+     test2 ();
+     test3 (); */
+  test4 (); 
+  test5 ();
+}
+
+test1 () {
+
+  int i, size;
+  char *test, *line;
+
+  gprint (GP_ERR, "starting test 1...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "100");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  gprint (GP_ERR, "done with test 1\n");
+  sleep (1);
+}
+
+test1b () {
+
+  int i, size;
+  char *test, *line;
+
+  gprint (GP_ERR, "starting test 1b...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "dsin(45)");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  gprint (GP_ERR, "done with test 1b\n");
+  sleep (1);
+}
+
+test2 () {
+
+  int i, size;
+  char *test, *line;
+
+  gprint (GP_ERR, "starting test 2...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "5 * 100");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  gprint (GP_ERR, "done with test 2\n");
+  sleep (1);
+}
+
+test3 () {
+
+  int i, size;
+  char *test, *line;
+
+  gprint (GP_ERR, "starting test 3...  ");
+  ALLOCATE (test, char, 256);
+  sprintf (test, "5 * dsin(45)");
+  for (i = 0; i < 1000000; i++) {
+    line = dvomath (1, &test, &size, 0);
+    if (line != NULL) free (line);
+  }
+  gprint (GP_ERR, "done with test 3\n");
+  sleep (1);
+}
+
+test4 () {
+
+  int i;
+  char *test, *line;
+
+  gprint (GP_ERR, "starting test 4...  ");
+  for (i = 0; i < 1000000; i++) {
+    ALLOCATE (test, char, 256);
+    sprintf (test, "$N = 100");
+    line = parse (test);
+    if (line != NULL) free (line);
+  }
+  gprint (GP_ERR, "done with test 4\n");
+  sleep (1);
+}
+
+test5 () {
+
+  int i;
+  char *test, *line;
+
+  gprint (GP_ERR, "starting test 5...  ");
+  for (i = 0; i < 1000000; i++) {
+    ALLOCATE (test, char, 256);
+    sprintf (test, "echo {100 * 800}");
+    line = parse (test);
+    if (line != NULL) free (line);
+  }
+  gprint (GP_ERR, "done with test 5\n");
+  sleep (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/mana/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/mana/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/mana/version.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "mana.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+int version (int argc, char **argv) {
+
+  char *tmp;
+
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "mana version: %s\n", (tmp = strip_version (name))); free (tmp);
+
+  gprint (GP_LOG, "opihi version: %s\n", (tmp = strip_version (opihi_version()))); free (tmp);
+  gprint (GP_LOG, "libohana version: %s\n", (tmp = strip_version (ohana_version()))); free (tmp);
+  gprint (GP_LOG, "libfits version: %s\n", (tmp = strip_version (gfits_version()))); free (tmp);
+
+  gprint (GP_LOG, "compiled on %s %s\n", __DATE__, __TIME__);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/modules/dvo/navigate
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/modules/dvo/navigate	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/modules/dvo/navigate	(revision 16632)
@@ -0,0 +1,623 @@
+# -*- perl -*-
+
+macro navigate
+  style -n 0
+  limits
+  $DRAWSTARS  = -1
+  $DRAWIMAGES =  1
+  $DRAWGRID   = -1
+  $ZOOM = 180 / ($YMAX - $YMIN)
+  #this should be changed to a while loop, except 'while' is broken for some reason
+  $KEY = "none"
+  while ("$KEY" != "q")
+    cursor -g 1
+
+    # help list
+    if ("$KEY" == "h")
+     echo "Arrow Keys - pan in that direction"
+     echo "PgUp,PgDn - zoom in/out a factor of 1.2"
+     echo "Home,End  - zoom in/out a factor of 2"
+     echo "1 - zoom in factor of 2 at the cursor"
+     echo "2 - zoom in factor of 1.2 at the cursor"
+     echo "3 - recenter at cursor"
+     echo "4 - zoom out factor of 1.2 at the cursor"
+     echo "5 - zoom out factor of 2 at the cursor"
+     echo "6 - zoom out factor of 10 at the cursor"
+     echo "z - zoom to radius (requires 2nd keystroke)"
+     echo "f - show full sky"
+     echo ""
+     echo "q - quit"
+     echo "S - toggle auto-plotting of stars"
+     echo "A - toggle auto-plotting of image borders"
+     echo "g - toggle skygrid on/off"
+     echo "c - plot status catalog boundaries"
+     echo "C - list catalog at cursor location"
+     echo "i - list info about images touching cursor location" 
+     echo "I - list info about images, with pixel coords of cursor position"
+     echo "j - adjust mag scale, +0.5"
+     echo "k - adjust mag scale, -0.5"
+     echo "J - adjust dmag scale, /1.25"
+     echo "K - adjust dmag scale, *1.25"
+     echo "r - plot detected asteroids (rocks)"
+     echo "l - plot HST GSC"
+     echo "L - plot Landolt stars"
+     echo "m - list measurements for stars within 1 pixel of cursor"
+     echo "M - list measurements for stars within 1.8 arcsec of cursor"
+     echo "p - ****(don't know what this does)"
+     echo "s - ****(don't know what this does)"
+     echo "t - plot light curve for star within 2 arcsec of cursor position"
+     echo "T - plot 'galaxy' light curve for star within 2 arcsec of cursor position"
+     echo "u - ****(don't know what this does)"
+     echo "x - plot stars scaled by magnitude Chisq"
+     echo "X - plot stars by magnitude scatter"
+     echo "y - ****(don't know what this does)"
+     echo ""
+     echo "@ - execute macro `user_macro`"
+     echo ": - ****input a line and execute (not yet implemented)"
+    end
+
+    # quit from navigate
+    if ("$KEY" == "q") continue
+
+    #pan controls
+    if (("$KEY" == "Left") || ("$KEY" == "Right") || ("$KEY" == "Up") || ("$KEY" == "Down"))
+      $SHIFT = 0.2
+      $R$KEY  = $RMAX-$XMAX  
+      $D$KEY  = $DMAX-$YMAX
+      #assumes standard sky orientation!! (N up, E left)
+      if ("$KEY"=="Left")
+        $R$KEY = $R$KEY + $SHIFT*$XMAX
+      end
+      if ("$KEY"=="Right")
+        $R$KEY = $R$KEY + $SHIFT*$XMIN
+      end
+      if ("$KEY"=="Up")
+        $D$KEY = $D$KEY + $SHIFT*$YMAX
+      end
+      if ("$KEY"=="Down")
+        $D$KEY = $D$KEY + $SHIFT*$YMIN
+      end
+      #pretend like I hit '3' in the place to recenter it
+      nav_zoom 1      
+    end
+
+    # NEW zoom controls
+    if (("$KEY" == "Prior") || ("$KEY" == "Next") || ("$KEY" == "Home") || ("$KEY" == "End") || ("$KEY" == "Button4") || ("$KEY" == "Button5"))    
+      #move where key was hit to center      
+      $R$KEY  = $RMAX-$XMAX  
+      $D$KEY  = $DMAX-$YMAX
+      if ("$KEY" == "Prior")
+        $zfac=1.2
+      end
+      if ("$KEY" == "Next")
+        $zfac={1/1.2}
+      end
+      if ("$KEY" == "Home")
+        $zfac=2
+      end
+      if ("$KEY" == "End")
+        $zfac={1/2.}
+      end
+      if ("$KEY"=="Button4")
+        $zfac=1.6
+      end
+      if ("$KEY"=="Button5")
+        $zfac={1/1.6}
+      end
+      nav_zoom $zfac
+    end
+
+    if ("$KEY"=="Button1")
+      nav_zoom 1
+    end
+    if ("$KEY"=="Button2")
+      nav_zoom {1/2.}
+    end
+    if ("$KEY"=="Button3")
+      nav_zoom 2
+    end
+
+
+
+    # zoom controls
+    if ("$KEY" == "1")
+      nav_zoom 2
+    end
+    if ("$KEY" == "2")
+      nav_zoom 1.2
+    end
+    if ("$KEY" == "3")
+      nav_zoom 1
+    end
+    if ("$KEY" == "4")
+      nav_zoom {1/1.2}
+    end
+    if ("$KEY" == "5")
+      nav_zoom {1/2.}
+    end
+    if ("$KEY" == "6")
+      nav_zoom {1/20.}
+    end
+
+ 
+   # measure distance
+    if ("$KEY" == "d")
+      $r0 = $R$KEY
+      $d0 = $D$KEY
+      $ok = $KEY
+      echo "type 'd' again at endpoint"
+      cursor -g 1
+      $r1 = $R$KEY
+      $d1 = $D$KEY
+      $dr = 3600*((dcos($d0)*($r0-$r1))^2 + ($d0-$d1)^2)^0.5
+      echo "$dr arcsec"
+    end
+    # show ra, dec
+    if ("$KEY" == "w")
+      $tmp = $R$KEY
+      if ($tmp < 0) 
+        $tmp = $R$KEY + 360.0
+      end
+      echo "$tmp $D$KEY" 
+      exec echo $tmp $D$KEY | radec -hh
+    end
+    # zoom to radius
+    if ("$KEY" == "z")
+      $r0 = $R$KEY
+      $d0 = $D$KEY
+      $ok = $KEY
+      echo "type 'z' again at radius"
+      cursor -g 1
+      $r1 = $R$KEY
+      $d1 = $D$KEY
+      $dr = (($r0-$r1)^2 + ($d0-$d1)^2)^0.5
+      $ZOOM = $RAD / $dr
+      nav_recenter
+      nav_redraw
+      $KEY = $ok
+      $R$KEY = $r0
+      $D$KEY = $d0
+    end
+
+    # adjust mag scaling
+    if ("$KEY" == "J")
+      $MAG = $MAG - 0.5
+      nav_redraw
+    end
+    if ("$KEY" == "K")
+      $MAG = $MAG + 0.5
+      nav_redraw
+    end
+    if ("$KEY" == "j")
+      $dMAG = $dMAG * 0.8
+      nav_redraw
+    end
+    if ("$KEY" == "k")
+      $dMAG = $dMAG * 1.25
+      nav_redraw
+    end
+    echo "mag, dmag: $MAG, $dMAG"
+
+
+
+    # plot full sky
+    if ("$KEY" == "f") 
+      echo "full"
+      $ZOOM = 1
+      resize 1150 600		      
+      region 0 0 90 ait
+      $RMIN = 0
+      $RMAX = 360
+      $DMIN = -90
+      $DMAX = +90
+      style -c red; cgrid
+      style -c black
+      images
+    end
+
+    # plot rocks
+    if ("$KEY" == "r") 
+#      plot.rocks
+      style -c blue   -pt 1; procks -speed 0.0041 1
+      style -c red    -pt 1; procks -speed 0.00041 0.0041
+      style -c indigo -pt 1; procks -speed 0 0.00041
+      style -c black -lw 0;
+    end
+    # plot HST-GSC
+    if ("$KEY" == "l") 
+      style -c blue -pt 7; cat -all -g -m 9 16
+      style -c black
+    end
+    # plot Landolt
+    if ("$KEY" == "L") 
+#      style -c red  -lw 2 -pt 3; cat -a 1 2 3 /data/elixir/srcdir/refs/stetson/stetsonBn.txt -m 9 18
+#      style -c blue -lw 2 -pt 3; cat -a 25 26 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.fix -m 9 18
+      style -c red -lw 2 -pt 7; cat -a 1 2 3 /data/elixir/srcdir/refs/sdss/g_SDSS.dat -m 9 14
+#      style -c red -lw 2 -pt 3; cat -a 25 26 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.hq -m 9 18
+#      style -c red -lw 2 -pt 3; cat -a 22 23 8 /data/elixir/srcdir/refs/landolt/new/Landolt92.unfix -m 9 18
+#      style -c blue -lw 2 -pt 7; cat -a 1 2 4 /data/elixir/srcdir/refs/landolt/extreme/extreme.match -m 0 20
+#      style -x 2 -c red -pt 7 ; cplot RA DEC
+      style -c black -lw 0
+    end
+
+    # list star measurements
+    if ("$KEY" == "m") 
+        $dR = $RAD/$ZOOM/300
+        if ($dR < 0.0005)
+	 $dR = 0.0005
+        end
+	gstar $R$KEY $D$KEY $dR -m
+    end
+
+    # plot mag residuals
+    if ("$KEY" == "R") 
+      echo "filter: "
+      cursor 1
+      clear -n 1 -s; lim 10 22 -0.2 0.2; clear; box
+      dmags $KEY\:rel - $KEY : $KEY -type 0
+      plot -x 2 -pt 0 -sz 0.3 -c red yv xv
+      dmags $KEY\:rel - $KEY : $KEY -type 0 -flag 0 -nphot +3 -chisq 2.0
+      plot -x 2 -pt 2 -sz 0.5 -c black yv xv
+      $KEY = R
+      style -n 0
+    end
+
+    if ("$KEY" == "M") 
+	gstar $R$KEY $D$KEY 0.0005 -m
+    end
+    # list images
+    if ("$KEY" == "i") 
+	gimages $R$KEY $D$KEY
+    end
+    if ("$KEY" == "I") 
+	gimages $R$KEY $D$KEY -pix
+    end
+
+    #toggle images on / off
+    if ("$KEY" == "A")
+      $DRAWIMAGES = $DRAWIMAGES * -1
+      if ($DRAWIMAGES == 1)
+        images
+      end
+    end
+    # toggle stars on / off
+    if ("$KEY" == "S")
+      $DRAWSTARS = $DRAWSTARS * -1
+      if (($ZOOM > 20) && ($DRAWSTARS == 1))
+       style -pt 7
+       pmeasure -all -m $MAG {$MAG + $dMAG}
+      end
+    end
+    # turn grid on / off
+    if ("$KEY" == "g")
+      $DRAWGRID = $DRAWGRID * -1
+      if (($ZOOM > 20) && ($DRAWGRID==1))
+        style -c black; cgrid
+      end
+      if (($ZOOM > 20) && ($DRAWGRID==-1))
+        nav_redraw
+      end
+    end
+
+    # plot light-curve interactive
+    if ("$KEY" == "t")
+      style -n 1 -pt 2 -x 2
+      clear
+      if ($R$KEY < 0) 
+       $R$KEY = $R$KEY + 360
+      end
+      lcurve -l $R$KEY $D$KEY {30/3600} -d -v time mag
+      box
+      lcv
+      style -n 0
+    end
+    # plot light-curve 
+    if ("$KEY" == "T")
+      style -n 1 -pt 1 -c red -x 2
+      lcurve $R$KEY $D$KEY {30/3600} -d
+      style -c black
+      style -n 0 
+    end
+    # plot catalogs
+    if ("$KEY" == "c")
+      style -c blue; pcat; style -c black
+    end
+    # list catalogs
+    if ("$KEY" == "C")
+      gcat $R$KEY $D$KEY
+    end
+
+    # plot image chisqs
+    if ("$KEY" == "x") 
+       gcat $R$KEY $D$KEY
+       extract $CATNAME Xm -photcode R
+       extract $CATNAME ra
+       extract $CATNAME dec
+       style -x 2 -pt 7 -c blue
+       czplot ra dec Xm 3 30
+       style -c black -pt 1
+    end
+    # plot meas errors
+    if ("$KEY" == "X") 
+       gcat $R$KEY $D$KEY
+       extract $CATNAME dM -photcode R
+       extract $CATNAME ra
+       extract $CATNAME dec
+       style -x 2 -pt 7 -c red
+       czplot ra dec dM 0 30
+       style -c black -pt 1
+    end
+
+
+    # temp plot for skyprobe
+    if ("$KEY" == "u") 
+      imextract -region time
+      imextract -region mcal
+      imextract -region airmass
+      imextract -region nstar
+      vstat time
+      clear -n 1;
+      section a 0 0.00 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3} -0.8 -0.5; box; plot time mcal
+      section b 0 0.33 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3}  0.95 3.0; box; plot time airmass
+      section c 0 0.66 1 0.33
+      lim {$MEDIAN-0.3} {$MEDIAN+0.3} 0 3000; box; plot time nstar
+      style -n 0
+    end
+    if ("$KEY" == "s")
+      $tmp = $R$KEY
+      if ($tmp < 0) 
+        $tmp = $R$KEY + 360.0
+      end
+      $line = `echo $tmp $D$KEY | radec -hh`
+      imextract -region photcode
+      imextract -region time
+     
+      subset t = time if (int(photcode/100) == 1)
+      uniq t T
+      $Bn = t[]
+      $BN = T[]
+      
+      subset t = time if (int(photcode/100) == 2)
+      uniq t T
+      $Vn = t[]
+      $VN = T[]
+      
+      subset t = time if (int(photcode/100) == 3)
+      uniq t T
+      $Rn = t[]
+      $RN = T[]
+      
+      subset t = time if (int(photcode/100) == 4)
+      uniq t T
+      $In = t[]
+      $IN = T[]
+     
+      echo "$line  $Bn $BN  $Vn $VN  $Rn $RN  $In $IN"
+    end
+
+    if ("$KEY" == "p") 
+      echo "P - new coords; p - old coords"
+      cursor -g 1
+      exec echo $Rp $Dp $RP $DP >> fix.coords
+    end
+
+    if ("$KEY" == "y")
+      ccd I - 2MASS_J : 2MASS_J - 2MASS_K
+      lim -n 1 -1 10 -1 3; clear; box; plot -x 2 -pt 2 -sz 0.5 xv yv
+      dev -n 0 -g
+    end
+
+    #  User-defined macro
+    if ("$KEY" == "at")
+      user_macro
+    end
+
+    if ("$KEY" == "colon")
+      #make this work similar to ':' in vi or iraf
+      #does not work correctly now.
+      scan stdin line
+      $line
+    end
+
+  end
+end
+
+#define this so navigate doesn't crash if you try to call it.
+#If you define a user_macro, be sure to do so AFTER this in .dvorc.
+macro user_macro
+  #echo "success!"
+  $do_nothing=0
+end
+    
+
+macro nav_zoom
+  $ZOOM = $ZOOM * $1
+  nav_recenter
+  nav_redraw
+  $Rnum = $R$KEY		      
+  $Dnum = $D$KEY
+  $KEY = num
+end
+
+macro nav_recenter
+  region $R$KEY $D$KEY {$RAD/$ZOOM} sin
+  #assumes standard sky orientation!! (N up, E left)
+  $RMIN = $R$KEY + $XMIN
+  $RMAX = $R$KEY + $XMAX
+  $DMIN = $D$KEY + $YMIN
+  $DMAX = $D$KEY + $YMAX
+end
+
+macro nav_redraw
+  clear
+  if ($ZOOM <= 20) 
+    style -c red; cgrid
+  end
+  if (($ZOOM > 20) && ($DRAWGRID==1))
+    style -c black; cgrid
+  end
+  if (($ZOOM > 20) && ($DRAWSTARS == 1))
+    pmeasure -all -m $MAG {$MAG + $dMAG}
+  end    
+  style -c black
+  if ($DRAWIMAGES == 1)
+    images
+  end
+end
+
+
+
+#==================================================
+#=================   END BSNAV   ==================
+#==================================================
+
+
+macro sigclip
+  if ("$0" == "1")
+    echo ""
+    echo "sigclip <clipvector> <N_iterations> <N_sigma> [other vectors ..]"
+    echo ""
+  end
+
+  #required parameters
+  $CLIPVECT = $1
+  $NITERATE = $2
+  $NSIGCLIP = $3
+  
+  for i 0 $NITERATE
+    vstat -q $CLIPVECT
+    #clip boundaries
+    $top = $MEAN + ($NSIGCLIP*$SIGMA)
+    $bot = $MEAN - ($NSIGCLIP*$SIGMA)
+    
+    #clip it good.
+    subset temp = $CLIPVECT if (($CLIPVECT < $top) && ($CLIPVECT > $bot))
+    
+    #if you specify other vectors, clip the same elements from them too.
+    #they must all be the same length, of course!!
+    if ($0>4)
+      for j 4 $0
+        subset $$j = $$j if (($CLIPVECT < $top) && ($CLIPVECT > $bot))
+      end
+    end
+    
+    #copy temp back to $CLIPVECT and reiterate!
+    delete $CLIPVECT
+    concat temp $CLIPVECT  
+  end
+end
+
+
+macro binvec
+  if ("$0" == "1")
+    echo ""
+    echo "binvec <vec> <Nbins> [other vectors...]"
+    echo ""
+    echo "Bin the vector 'vec' into Nbin bins.  Listing other vectors will"
+    echo "put the corresponding elements of those into other vectors which"
+    echo "are the subset of the vector in that bin.  (That can probably be"
+    echo "stated better.)  This macro makes lots of new vectors.  Hooray!"
+    echo ""
+    echo "Creates"
+  end
+
+  #REQUIRED PARAMS
+  $binvect = $1
+  $NBINS   = $2
+
+  vstat -q $binvect
+  $step = ($MAX-$MIN)/$NBINS
+  $vmin = $MIN
+  $vmax = $MAX
+  delete -q $binvect\_bins
+  delete -q $binvect\_num
+  for i 1 {$NBINS+1}
+    $top = $vmin + ( $i   *$step)
+    $bot = $vmin + (($i-1)*$step)
+    #      sightly different behavior for last bin    -------v
+    if ($i != $NBINS)
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect< $top))
+    else
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect<=$top))
+    end
+    set $binvect\_bin$i = temp
+    set temp2 = temp
+    delete temp
+    #if you specify other vectors, grab the same elements from them too.
+    #they must all be the same length, of course!!
+
+    if ($0>3)
+      for j 3 $0
+        if ($i != $NBINS)
+          subset temp = $$j if (($binvect>=$bot)&&($binvect< $top))
+        else 
+          subset temp = $$j if (($binvect>=$bot)&&($binvect<=$top))
+        end
+        set $$j\_bin$i = temp
+        delete temp
+      end
+    end
+
+
+    concat {$bot+($step/2)} $binvect\_bins
+    concat temp2[] $binvect\_num
+    #dvo didn't like me saying 'concat $binvect\_bin$i[] $binvect\_num
+    delete temp2
+  end
+end
+
+macro binvec.2
+  if ("$0" == "1")
+    echo ""
+    echo "binvec.2 <vec> <min> <max> <binsize> [other vectors...]"
+    echo ""
+    echo ""
+    echo "see also 'binvec'"
+  end
+
+  #REQUIRED PARAMS
+  $binvect = $1
+  $vmin    = $2
+  $vmax    = $3
+  $step    = $4
+
+  $NBINS = ($MAX-$MIN)/$step
+
+  delete -q $binvect\_bins
+  delete -q $binvect\_num
+  for i 1 {$NBINS+1}
+    $top = $vmin + ( $i   *$step)
+    $bot = $vmin + (($i-1)*$step)
+    #      sightly different behavior for last bin    -------v
+    if ($i != $NBINS)
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect< $top))
+    else
+      subset temp = $binvect if (($binvect>=$bot)&&($binvect<=$top))
+    end
+    set $binvect\_bin$i = temp
+    set temp2 = temp
+    delete temp
+    #if you specify other vectors, grab the same elements from them too.
+    #they must all be the same length, of course!!
+
+    if ($0>5)
+      for j 5 $0
+        if ($i != $NBINS)
+          subset temp = $$j if (($binvect>=$bot)&&($binvect< $top))
+        else 
+          subset temp = $$j if (($binvect>=$bot)&&($binvect<=$top))
+        end
+        set $$j\_bin$i = temp
+        delete temp
+      end
+    end
+
+
+    concat {$bot+($step/2)} $binvect\_bins
+    concat temp2[] $binvect\_num
+    #dvo didn't like me saying 'concat $binvect\_bin$i[] $binvect\_num
+    delete temp2
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/modules/mana/plots
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/modules/mana/plots	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/modules/mana/plots	(revision 16632)
@@ -0,0 +1,41 @@
+
+macro cvplot 
+  if ($0 != 6)
+    echo "USAGE: cvplot r d ur ud scale"
+    break
+  end
+ 
+  local i
+  delete -q _tmpr _tmpd
+
+  for i 0 $1[]
+   concat $1[$i] _tmpr
+   concat $2[$i] _tmpd
+   concat {$1[$i]+$3[$i]*$5} _tmpr
+   concat {$2[$i]+$4[$i]*$5} _tmpd
+  end
+  style -pt 100
+  cplot _tmpr _tmpd
+  style -pt 7
+end
+
+macro vplot 
+  if ($0 != 6)
+    echo "USAGE: cvplot r d ur ud scale"
+    break
+  end
+ 
+  local i
+  delete -q _tmpr _tmpd
+
+  for i 0 $1[]
+   concat $1[$i] _tmpr
+   concat $2[$i] _tmpd
+   concat {$1[$i]+$3[$i]*$5} _tmpr
+   concat {$2[$i]+$4[$i]*$5} _tmpd
+  end
+  style -pt 100
+  plot _tmpr _tmpd
+  style -pt 7
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/.cvsignore	(revision 16632)
@@ -0,0 +1,3 @@
+pantasks.c
+pantasks_client.c
+pantasks_server.c
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckController.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckController.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckController.c	(revision 16632)
@@ -0,0 +1,116 @@
+# include "pantasks.h"
+
+static struct timeval start;
+void TimerMark ();
+float TimerElapsed (int reset);
+
+int CheckController () {
+
+  char *p, *q;
+  int i, Njobs, status, JobID;
+  Job *job;
+  IOBuffer buffer;
+
+  /* get the list of completed jobs (exit / crash), update the job status */
+  if (!CheckControllerStatus()) return (TRUE);
+
+  /*** check EXIT jobs ***/
+  InitIOBuffer (&buffer, 0x100);
+  // TimerMark ();
+  // status = ControllerCommand ("stop", CONTROLLER_PROMPT, &buffer); 
+  // if (VerboseMode()) gprint (GP_ERR, "stop controller %f\n", TimerElapsed(TRUE));
+
+  TimerMark ();
+  FlushIOBuffer (&buffer);
+  status = ControllerCommand ("jobstack exit", CONTROLLER_PROMPT, &buffer);
+  if (VerboseMode()) gprint (GP_ERR, "check exit stack %f\n", TimerElapsed(TRUE));
+  if (!status) goto escape;
+
+  /** programming error **/
+  p = memstr (buffer.buffer, "USAGE: jobstack", buffer.Nbuffer);
+  if (p != NULL) goto escape;
+
+  /** parse job list **/
+  status = sscanf (buffer.buffer, "%*s %d", &Njobs);
+  if (status != 1) goto escape;
+  if (VerboseMode()) gprint (GP_ERR, "parse %d jobs on stack %f\n", Njobs, TimerElapsed(TRUE));
+
+  p = buffer.buffer;
+  for (i = 0; i < Njobs; i++) {
+    q = strchr (p, '\n');
+    if (q == NULL) {
+      gprint (GP_ERR, "controller message error: incomplete job list\n");
+      break;
+    }
+    p = q + 1;
+    status = sscanf (p, "%d", &JobID);
+
+    job = FindControllerJob (JobID);
+    if (job == NULL) {
+      gprint (GP_ERR, "misplaced job? %d not in EXIT job list\n", JobID);
+      continue;
+    }
+    /* this checks the individual job status, grabs stdout/stderr */
+    CheckControllerJob (job);
+  }
+  if (VerboseMode()) gprint (GP_ERR, "clear %d exit jobs %f\n", i, TimerElapsed(TRUE));
+
+  /*** check CRASH jobs ***/
+  FlushIOBuffer (&buffer);
+  status = ControllerCommand ("jobstack crash", CONTROLLER_PROMPT, &buffer);
+  if (!status) goto escape;
+
+  p = memstr (buffer.buffer, "USAGE: jobstack", buffer.Nbuffer);
+  if (p != NULL) goto escape;
+
+  /** parse job list **/
+  status = sscanf (buffer.buffer, "%*s %d", &Njobs);
+  if (status != 1) goto escape;
+  if (VerboseMode()) gprint (GP_ERR, "check crash stack %f\n", TimerElapsed(TRUE)); 
+
+  p = buffer.buffer;
+  for (i = 0; i < Njobs; i++) {
+    q = strchr (p, '\n');
+    if (q == NULL) {
+      gprint (GP_ERR, "controller message error: incomplete job list\n");
+      break;
+    }
+    p = q + 1;
+    
+    status = sscanf (p, "%d", &JobID);
+    job = FindControllerJob (JobID);
+    if (job == NULL) {
+      gprint (GP_ERR, "misplaced job? %d not in CRASH job list\n", JobID);
+      continue;
+    }
+    /* this checks the individual job status, grabs stdout/stderr */
+    CheckControllerJob (job);
+  }
+  if (VerboseMode()) gprint (GP_ERR, "clear %d crash jobs %f\n", i, TimerElapsed(TRUE)); 
+
+  FlushIOBuffer (&buffer);
+  // status = ControllerCommand ("run", CONTROLLER_PROMPT, &buffer);
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+
+ escape:
+  FlushIOBuffer (&buffer);
+  // status = ControllerCommand ("run", CONTROLLER_PROMPT, &buffer); 
+  FreeIOBuffer (&buffer);
+  return (FALSE);
+}
+
+void TimerMark () {
+    gettimeofday (&start, (void *) NULL);
+}
+
+float TimerElapsed (int reset) {
+
+  float dtime;
+  struct timeval stop;
+
+  gettimeofday (&stop, (void *) NULL);
+  dtime = DTIME (stop, start);
+  if (reset) gettimeofday (&start, (void *) NULL);
+  return (dtime);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckJobs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckJobs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckJobs.c	(revision 16632)
@@ -0,0 +1,230 @@
+# include "pantasks.h"
+
+float CheckJobs () {
+
+  FILE *f;
+  Job *job;
+  Task *task;
+  Macro *macro;
+  int i, status;
+  char varname[64];
+  Queue *queue;
+  float time_running, next_timeout;
+
+  // int Ncheck;
+  // Ncheck = 0;
+
+  // actual maximum delay is controlled in job_threads.c
+  next_timeout = 1.0;
+
+  /** test all jobs: ready to test?  finished? **/
+  while ((job = NextJob ()) != NULL) {
+    // Ncheck ++;
+
+    task = job[0].task;
+    // XXX we need to guarantee that the task exists
+    // if we delete a task, we need to keep a copy until all task jobs are
+    // removed
+
+    /* check poll period (ready to ask for status?) */
+    time_running = GetTaskTimer(job[0].last, FALSE);
+    // fprintf (stderr, "next: %f, poll: %f, run: %f\n", next_timeout, task[0].poll_period, time_running);
+    if (time_running < task[0].poll_period) {
+      next_timeout = MIN (next_timeout, task[0].poll_period - time_running);
+      continue;
+    }
+    next_timeout = 0.0;
+
+    /* check current status */
+    status = CheckJob (job);
+    switch (status) {
+      case JOB_PENDING:
+	/* if (VerboseMode()) gprint (GP_LOG, "job %s (%d) pending\n", task[0].name, job[0].JobID); */
+	break;
+
+      case JOB_BUSY:
+	/* if (VerboseMode()) gprint (GP_LOG, "job %s (%d) busy\n", task[0].name, job[0].JobID); */
+	break;
+
+      case JOB_CRASH:
+      case JOB_EXIT:
+	/* push output buffer data to the stdout and stderr queues */
+	/* XXX this will break on 0 values in output streams */
+	if (DEBUG) fprintf (stderr, "job: (%zx) %d of %d\n", (size_t) job[0].stdout_buff.buffer, job[0].stdout_buff.Nbuffer, job[0].stdout_buff.Nalloc); 
+	PushNamedQueue ("stdout", job[0].stdout_buff.buffer);
+	PushNamedQueue ("stderr", job[0].stderr_buff.buffer);
+
+	/* save the stdout and stderr if desired */
+	if ((job[0].stdout_dump != NULL) && strcasecmp(job[0].stdout_dump, "NULL")) {
+	  f = fopen (job[0].stdout_dump, "a");
+	  if (f == NULL) {
+	    gprint (GP_ERR, "unable to open stdout dump file %s\n", job[0].stdout_dump);
+	  } else {
+	    fwrite (job[0].stdout_buff.buffer, 1, job[0].stdout_buff.Nbuffer, f);
+	    fclose (f);
+	  }
+	}
+	if ((job[0].stderr_dump != NULL) && strcasecmp(job[0].stderr_dump, "NULL")) {
+	  f = fopen (job[0].stderr_dump, "a");
+	  if (f == NULL) {
+	    gprint (GP_ERR, "unable to open stderr dump file %s\n", job[0].stderr_dump);
+	  } else {
+	    fwrite (job[0].stderr_buff.buffer, 1, job[0].stderr_buff.Nbuffer, f);
+	    fclose (f);
+	  }
+	}
+
+	/* set taskarg variables */
+	for (i = 0; i < job[0].argc; i++) {
+	    sprintf (varname, "taskarg:%d", i);
+	    set_str_variable (varname, job[0].argv[i]);
+	}
+	set_int_variable ("taskarg:n", job[0].argc);
+
+	/* set options variables */
+	for (i = 0; i < job[0].optc; i++) {
+	    sprintf (varname, "options:%d", i);
+	    set_str_variable (varname, job[0].optv[i]);
+	}
+	set_int_variable ("options:n", job[0].optc);
+
+	set_variable ("JOB_DTIME", job[0].dtime);
+
+	if (job[0].realhost == NULL) {
+	  set_str_variable ("JOB_HOSTNAME", "localhost");
+	} else {
+	  set_str_variable ("JOB_HOSTNAME", job[0].realhost);
+	}	    
+
+	if (status == JOB_CRASH) {
+	  /* XXX add an Ncrash element? */
+	  task[0].Nfailure ++;
+	  UpdateTaskTimerStats (task, TIMER_FAILURE, job[0].dtime);
+
+	  /* run task[0].crash macro, if it exists */
+	  /* perhaps define PushNamedQueueBuffer */
+
+	  set_str_variable ("JOB_STATUS", "CRASH");
+
+	  if (VerboseMode()) gprint (GP_LOG, "job %s (%d) crash\n", task[0].name, job[0].JobID);
+	  if (task[0].crash != NULL) {
+	    exec_loop (task[0].crash);
+	  }
+	}
+	if (status == JOB_EXIT) {
+	  /* update the exit status counters */
+	  if (job[0].exit_status) {
+	    task[0].Nfailure ++;
+	    UpdateTaskTimerStats (task, TIMER_FAILURE, job[0].dtime);
+	  } else {
+	    task[0].Nsuccess ++;
+	    UpdateTaskTimerStats (task, TIMER_SUCCESS, job[0].dtime);
+	  }
+
+	  set_int_variable ("JOB_STATUS", job[0].exit_status);
+
+	  /* run corresponding task[0].exit macro, if it exists */
+	  if (VerboseMode()) gprint (GP_LOG, "job %s (%d) exit\n", task[0].name, job[0].JobID);
+	  macro = task[0].defexit;
+	  for (i = 0; i < task[0].Nexit; i++) {
+	    if (job[0].exit_status == atoi(task[0].exit[i][0].name)) {
+	      macro = task[0].exit[i];
+	      break;
+	    }
+	  }
+	  if (macro != NULL) exec_loop (macro);
+	}
+
+	/* flush the stderr and stdout queues */
+	queue = FindQueue ("stdout");
+	if (queue) InitQueue (queue);
+	queue = FindQueue ("stderr");
+	if (queue) InitQueue (queue);
+
+	UpdateTaskTimerStats (task, TIMER_ALLJOBS, job[0].dtime);
+
+	DeleteJob (job);
+	continue;
+	break;
+
+      default:
+	if (VerboseMode()) gprint (GP_LOG, "unknown exit status: %d\n", status);
+	/** do something more useful here ?? **/
+	break;
+    }
+
+    /* check for timeout - (local jobs only) 
+       we only check timeout after a poll (forces at least one poll)
+     */
+    if (job[0].mode == JOB_LOCAL) {
+      if (GetTaskTimer(job[0].start, FALSE) < task[0].timeout_period) { 
+	/* reset polling clock */
+	SetTaskTimer (&job[0].last);
+	continue;
+      }
+      if (VerboseMode()) gprint (GP_LOG, "timeout on %s\n", task[0].name);
+
+      // XXX harvest STDERR and STDOUT from timeout job (should be available...)
+      // XXX add this to controller as well
+
+      /* update the timeout counter */
+      task[0].Ntimeout ++;
+
+      if (!KillLocalJob (job)) {
+	job[0].state = JOB_HUNG;
+	if (VerboseMode()) gprint (GP_LOG, "child process %d is hung, cannot kill\n", job[0].pid);
+	continue;
+      }
+
+      /* set taskarg variables */
+      for (i = 0; i < job[0].argc; i++) {
+	  sprintf (varname, "taskarg:%d", i);
+	  set_str_variable (varname, job[0].argv[i]);
+      }
+      set_int_variable ("taskarg:n", job[0].argc);
+
+      /* set options variables */
+      for (i = 0; i < job[0].optc; i++) {
+	sprintf (varname, "options:%d", i);
+	set_str_variable (varname, job[0].optv[i]);
+      }
+      set_int_variable ("options:n", job[0].optc);
+
+      /* run task[0].timeout macro, if it exists */
+      if (task[0].timeout != NULL) {
+	exec_loop (task[0].timeout);
+      }
+
+      task[0].Npending --;
+      DeleteJob (job);
+      continue;
+    }
+
+    /* reset polling clock */
+    SetTaskTimer (&job[0].last);
+  }
+  // fprintf (stderr, "check %d jobs\n", Ncheck);
+  return (next_timeout);
+}
+
+/* 
+
+  job / task timeline:
+
+  task:
+  0           exec     
+  start       create
+  task clock  new job
+
+  job:
+  0           1xpoll     2xpoll     3xpoll
+  start       check      check      check 
+  job clock   status     status     status
+
+  .           .          .          timeout
+                                    run
+				    timeout
+
+  must be at least one poll before timeout 
+  (timeout >= poll)
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckPassword.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckPassword.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckPassword.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "pantasks.h"
+# define DEBUG 0
+
+static char PASSWORD[256];
+
+int InitPassword () {
+
+  VarConfig ("PASSWORD", "%s", PASSWORD);
+  return (TRUE);
+}
+
+int CheckPassword (int BindSocket) {
+
+  IOBuffer message;
+  int status;
+
+  if (DEBUG) gprint (GP_ERR, "waiting for password %s\n", PASSWORD);
+
+  status = ExpectCommand (BindSocket, strlen(PASSWORD), 0.1, &message);
+  if (status != 0) {
+    if (DEBUG) gprint (GP_ERR, "failed connection\n");
+    FreeIOBuffer (&message);
+    close (BindSocket);
+    return (FALSE);
+  }
+  if (strncmp (message.buffer, PASSWORD, strlen(PASSWORD))) {
+    if (DEBUG) gprint (GP_ERR, "invalid password\n");
+    close (BindSocket);
+    return (FALSE);
+  }
+  if (DEBUG) gprint (GP_ERR, "accepted password (%s)\n", message.buffer);
+  
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckTasks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckTasks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckTasks.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "pantasks.h"
+
+float CheckTasks () {
+
+  Job *job;
+  Task *task;
+  int status;
+  float time_running, next_timeout, fuzz;
+  // struct timeval now;
+
+  // actual maximum delay is controlled in job_threads.c
+  next_timeout = 1.0;
+
+  /** test all tasks: ready to test? ready to run? **/
+  while ((task = NextTask ()) != NULL) {
+
+    /*** test for all reasons we should skip this task ***/
+
+    /* task has been de-activated by the user */
+    if (!task[0].active) {
+      continue;
+    }
+    /* current time is not within valid/invalid periods */
+    if (!CheckTimeRanges (task[0].ranges, task[0].Nranges)) {
+      continue;
+    }
+    /* all allowed tasks have been run in this period */
+    if (task[0].Nmax && (task[0].Njobs >= task[0].Nmax)) {
+      continue;
+    }
+    /* too many outstanding jobs */
+    if (task[0].NpendingMax && (task[0].Npending >= task[0].NpendingMax)) {
+      continue;
+    }
+
+    /* ready to test? : check time since last exec */
+    time_running = GetTaskTimer(task[0].last, FALSE);
+    if (time_running < task[0].exec_period) {
+      // is we are to ready to run, set time to timeout, if shortest of all tasks
+      next_timeout = MIN (next_timeout, task[0].exec_period - time_running);
+      continue;
+    }
+
+    /* ready to try running the task : reset the timer */
+    next_timeout = 0.0;
+    gettimeofday (&task[0].last, (void *) NULL);
+
+    // add random offset between 0 and 5% of exec_period
+    // XXX this should be optional
+    fuzz = 0.05*task[0].exec_period*drand48() + 1e-6*task[0].last.tv_usec; 
+    task[0].last.tv_usec = 1e6*(fuzz - (int)fuzz);
+    task[0].last.tv_sec += (int) fuzz;
+
+    /* ready to run? : run task.exec macro */
+    if (task[0].exec != NULL) {
+      status = exec_loop (task[0].exec);
+      if (!status) {
+	continue;
+      }
+    }
+
+    // gettimeofday (&now, (void *) NULL);
+    // fprintf (stderr, "t1: %d %6d  - \n", now.tv_sec, now.tv_usec);
+
+    /* check if there are errors with this task */
+    if (!ValidateTask (task, TRUE)) { 
+      continue;
+    }
+    
+    // gettimeofday (&now, (void *) NULL);
+    // fprintf (stderr, "t2: %d %6d  - \n", now.tv_sec, now.tv_usec);
+
+    /* construct job from task */
+    job = CreateJob (task);
+    if (DEBUG) fprintf (stderr, "create job: (%zx) %d of %d\n", (size_t) job[0].stdout_buff.buffer, job[0].stdout_buff.Nbuffer, job[0].stdout_buff.Nalloc); 
+
+    // gettimeofday (&now, (void *) NULL);
+    // fprintf (stderr, "t3: %d %6d  - \n", now.tv_sec, now.tv_usec);
+
+    /* execute job - XXX add status test */
+    SubmitJob (job);
+
+    // fprintf (stderr, "nl: %d %6d  - ",
+    // task[0].last.tv_sec, task[0].last.tv_usec);
+
+    /* increment job counters */
+    task[0].Njobs ++;
+    task[0].Npending ++;
+
+    // fprintf (stderr, "%d %6d\n", 
+    // task[0].last.tv_sec, task[0].last.tv_usec);
+
+    /* increment Nrun for inclusive ranges with Nmax */
+    BumpTimeRanges (task[0].ranges, task[0].Nranges);
+  }
+  return (next_timeout);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckTimeRanges.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckTimeRanges.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/CheckTimeRanges.c	(revision 16632)
@@ -0,0 +1,97 @@
+# include "pantasks.h"
+
+/* the tested time is saved by CheckTimeRanges for a following BumpTimeRanges
+   otherwise we could have an inconsistency between valid ranges and Nrun */
+static time_t daytime, weektime, abstime;
+
+/* test if we meet all time range qualifications */
+int CheckTimeRanges (TimeRange *ranges, int Nranges) {
+
+  int i, intime, Ninclude, include, exclude, valid;
+  time_t testtime;
+  struct timeval now;
+  struct tm Now;
+
+  /* get the current time */
+  gettimeofday (&now, NULL);
+  gmtime_r (&now.tv_sec, &Now);
+  daytime  = Now.tm_sec + Now.tm_min*60 + Now.tm_hour*3600;
+  weektime = Now.tm_sec + Now.tm_min*60 + Now.tm_hour*3600 + Now.tm_wday*86400;
+  abstime  = now.tv_sec;
+
+  Ninclude = 0;
+  include = FALSE;
+  exclude = FALSE;
+  
+  for (i = 0; i < Nranges; i++) {
+    if (ranges[i].include) Ninclude ++;
+
+    switch (ranges[i].type) {
+      /* set the testtime */
+      case RANGE_ABS:
+	testtime = abstime;
+	break;
+      case RANGE_DAY:
+	testtime = daytime;
+	break;
+      case RANGE_WEEK:
+	testtime = weektime;
+	break;
+      default:
+	abort ();
+    }
+    intime = (testtime >= ranges[i].start) && (testtime <= ranges[i].stop);
+
+    /* check for more than max runs in time range */
+    if (ranges[i].include && intime && ranges[i].Nmax) {
+      if (ranges[i].Nrun >= ranges[i].Nmax) return (FALSE);
+    }
+    /* reset Nrun if we are outside of intime */
+    if (ranges[i].include && !intime && ranges[i].Nmax && ranges[i].Nrun) {
+      ranges[i].Nrun = 0;
+    }
+
+    /* is this a valid time? */
+    if ( ranges[i].include &&  intime) include = TRUE;
+    if (!ranges[i].include && !intime) exclude = TRUE;
+  }
+
+  if (Ninclude == 0) include = TRUE;
+  valid = include && !exclude;
+
+  return (valid);
+}  
+
+/* increment the number of runs for all inclusive time ranges with Nmax > 0
+   (only call when we execute a task -- after CheckTimeRanges) */
+int BumpTimeRanges (TimeRange *ranges, int Nranges) {
+
+  int i, intime;
+  time_t testtime;
+
+  /* only increment the counter for ranges which are valid */
+  for (i = 0; i < Nranges; i++) {
+    if (!ranges[i].Nmax) continue;
+    if (!ranges[i].include) continue;
+
+    switch (ranges[i].type) {
+      /* set the testtime */
+      case RANGE_ABS:
+	testtime = abstime;
+	break;
+      case RANGE_DAY:
+	testtime = daytime;
+	break;
+      case RANGE_WEEK:
+	testtime = weektime;
+	break;
+      default:
+	abort ();
+    }
+    intime = (testtime >= ranges[i].start) && (testtime <= ranges[i].stop);
+
+    /* reset Nrun if we are outside of intime */
+    if (intime) ranges[i].Nrun ++;
+  }
+  return (TRUE);
+}  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ControllerOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ControllerOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ControllerOps.c	(revision 16632)
@@ -0,0 +1,494 @@
+# include "pantasks.h"
+/* adding a new host can delay controller up to a second or so */
+# define CONTROLLER_TIMEOUT 1000
+# define CONNECT_TIMEOUT 300
+
+/* local static variables to hold the connection to the controller */
+static int ControllerStatus = FALSE;
+static int stdin_cntl, stdout_cntl, stderr_cntl;
+static IOBuffer stdout_buffer;
+static IOBuffer stderr_buffer;
+static int ControllerPID = 0;
+
+/* test if the controller is running */
+int CheckControllerStatus () {
+  return (ControllerStatus);
+}
+
+/* check job / get output if done */
+int CheckControllerJob (Job *job) {
+  struct timeval start, stop;
+  float dtime;
+
+  gettimeofday (&start, (void *) NULL);
+  CheckControllerJobStatus (job);
+  gettimeofday (&stop, (void *) NULL);
+  dtime = DTIME (stop, start);
+  /* if (VerboseMode()) gprint (GP_ERR, "check job status %f\n", dtime); */
+
+  if ((job[0].state == JOB_EXIT) || (job[0].state == JOB_CRASH)) {
+    gettimeofday (&start, (void *) NULL);
+    GetJobOutput ("stdout", job[0].pid, &job[0].stdout_buff, job[0].stdout_size);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+    /* if (VerboseMode()) gprint (GP_ERR, "get stdout %f\n", dtime); */
+
+    gettimeofday (&start, (void *) NULL);
+    GetJobOutput ("stderr", job[0].pid, &job[0].stderr_buff, job[0].stderr_size);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+    /* if (VerboseMode()) gprint (GP_ERR, "get stderr %f\n", dtime); */
+
+    gettimeofday (&start, (void *) NULL);
+    DeleteControllerJob (job);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+    /* if (VerboseMode()) gprint (GP_ERR, "delete job %f\n", dtime); */
+  }  
+  return (TRUE);
+}
+
+int DeleteControllerJob (Job *job) {
+
+  int status;
+  char cmd[128]; 
+  IOBuffer buffer;
+
+  sprintf (cmd, "delete %d", job[0].pid);
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (cmd, CONTROLLER_PROMPT, &buffer);
+  FreeIOBuffer (&buffer);
+  return (status);
+}
+  
+/* ask controller about job status */
+int CheckControllerJobStatus (Job *job) {
+
+  int outstate, status;
+  char cmd[128], status_string[64], string[128];
+  char *p;
+  IOBuffer buffer;
+
+  sprintf (cmd, "check job %d", job[0].pid);
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (cmd, CONTROLLER_PROMPT, &buffer);
+  if (!status) {
+    FreeIOBuffer (&buffer);
+    return (FALSE);
+  }
+
+  /** was this a valid job? **/
+  p = memstr (buffer.buffer, "job not found", buffer.Nbuffer);
+  if (p != NULL) {
+    gprint (GP_ERR, "unknown job %d\n", job[0].pid);
+    FreeIOBuffer (&buffer);
+    return (FALSE);
+  }
+
+  /** parse status message **/
+  p = memstr (buffer.buffer, "STATUS",   buffer.Nbuffer);
+  sscanf (p, "%*s %s", status_string);
+  p = memstr (buffer.buffer, "EXITST",   buffer.Nbuffer);
+  sscanf (p, "%*s %d", &job[0].exit_status);
+  p = memstr (buffer.buffer, "STDOUT",   buffer.Nbuffer);
+  sscanf (p, "%*s %d", &job[0].stdout_size);
+  p = memstr (buffer.buffer, "STDERR",   buffer.Nbuffer);
+  sscanf (p, "%*s %d", &job[0].stderr_size);
+  p = memstr (buffer.buffer, "DTIME",    buffer.Nbuffer);
+  sscanf (p, "%*s %lf", &job[0].dtime);
+  p = memstr (buffer.buffer, "HOSTNAME", buffer.Nbuffer);
+  sscanf (p, "%*s %s", string);
+  job[0].realhost = strcreate (string);
+  FreeIOBuffer (&buffer);
+
+  /* possible exit status values */
+  outstate = -1;
+  if (!strcmp(status_string, "BUSY"))    outstate = JOB_BUSY;
+  if (!strcmp(status_string, "DONE"))    outstate = JOB_BUSY;
+  if (!strcmp(status_string, "PENDING")) outstate = JOB_PENDING;
+  if (!strcmp(status_string, "EXIT"))    outstate = JOB_EXIT;
+  if (!strcmp(status_string, "CRASH"))   outstate = JOB_CRASH;
+  if (outstate == -1) {
+    gprint (GP_ERR, "programming error?\n");
+    exit (1);
+  }
+  job[0].state = outstate;
+  return (TRUE);
+}
+
+/* we read Nbytes from the host, then watch for the prompt */ 
+int GetJobOutput (char *cmd, int pid, IOBuffer *buffer, int Nbytes) {
+  
+  int i, status, Nstart;
+  char *line;
+  struct timespec request, remain;
+
+  /* avoid blocking on waitpid, test every 100 usec, up to 50 msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 100000;
+
+  /* flush any earlier messages */
+  ReadtoIOBuffer (buffer, stdout_cntl);
+  FlushIOBuffer (buffer);
+  Nstart = buffer[0].Nbuffer;
+
+  /* send command to get appropriate channel */
+  status = write_fmt (stdin_cntl, "%s %d\n", cmd, pid);
+
+  /* is pipe still open? */
+  if ((status == -1) && (errno == EPIPE)) return (CONTROLLER_DOWN);
+
+  /* read at least Nbytes, then watch for CONTROLLER_PROMPT */
+  line = NULL;
+  status = -1;
+  for (i = 0; (i < CONTROLLER_TIMEOUT) && (status != 0) && (line == NULL); i++) {
+    status = ReadtoIOBuffer (buffer, stdout_cntl);
+    if ((buffer[0].Nbuffer - Nstart) >= Nbytes) {
+      line = memstr (buffer[0].buffer, CONTROLLER_PROMPT, buffer[0].Nbuffer);
+    }
+    if (status == -1) nanosleep (&request, &remain);
+  }
+  if (status ==  0) return (CONTROLLER_DOWN);
+  if (status == -1) return (CONTROLLER_HUNG);
+
+  /* if (VerboseMode()) gprint (GP_ERR, "message received (GetJobOutput : %s)\n", cmd);   */
+  /* drop extra bytes from pcontrol (not pclient:job) */
+  buffer[0].Nbuffer = Nstart + Nbytes;
+  if (buffer[0].Nalloc > buffer[0].Nbuffer) {
+    bzero (buffer[0].buffer + buffer[0].Nbuffer, buffer[0].Nalloc - buffer[0].Nbuffer);
+  }
+  return (CONTROLLER_GOOD);
+}
+
+/* submitting a job to the controller automatically starts controller */
+int SubmitControllerJob (Job *job) {
+
+  int i, Nchar, status;
+  char *cmd, *p, string[64];
+  IOBuffer buffer;
+
+  if (job[0].task[0].host == NULL) return (FALSE); 
+
+  if (!StartController ()) {
+    gprint (GP_ERR, "failure to start pcontrol\n");
+    return (FALSE);
+  }
+
+  /** construct the line to be sent to the controller **/
+
+  /* determine the total line length */
+  Nchar = 0;
+  for (i = 0; i < job[0].argc; i++) {
+    Nchar += strlen (job[0].argv[i]) + 1;
+  }
+  if (job[0].task[0].host) {
+    Nchar += strlen (job[0].task[0].host) + 1;
+  }
+  Nchar += 10;
+  ALLOCATE (cmd, char, Nchar);
+  bzero (cmd, Nchar);
+
+  /* construct the controller command portion */
+  if (!strcasecmp (job[0].task[0].host, "ANYHOST")) {
+    sprintf (cmd, "job");
+  } else {
+    if (job[0].task[0].host_required) {
+      sprintf (cmd, "job +host %s", job[0].task[0].host);
+    } else {
+      sprintf (cmd, "job -host %s", job[0].task[0].host);
+    }
+  }
+
+  /* add the command arguments */
+  for (i = 0; i < job[0].task[0].argc; i++) {
+    strcat (cmd, " ");
+    strcat (cmd, job[0].task[0].argv[i]);
+  }
+
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (cmd, CONTROLLER_PROMPT, &buffer);
+  free (cmd);
+
+  /* extract the job PID from the controller response */
+  p = memstr (buffer.buffer, "JobID", buffer.Nbuffer);
+  if (p == NULL) {
+    gprint (GP_ERR, "missing PID in pcontrol message : programming error\n");
+    gprint (GP_ERR, "ControllerCommand returns: %d\n", status);
+    gprint (GP_ERR, "ControllerCommand response: %s\n", buffer.buffer);
+    exit (1);
+  }
+  sscanf (p, "%*s %s", string);
+  job[0].pid = atoi (string);
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+}
+
+int StartController () {
+
+  char *p;
+  char **argv, cmd[128];
+  int i, pid, status;
+  int stdin_fd[2], stdout_fd[2], stderr_fd[2];
+  IOBuffer buffer;
+
+  if (ControllerStatus) return (TRUE);
+
+  if (VarConfig ("CONTROLLER", "%s", cmd) == NULL) strcpy (cmd, "pcontrol");
+
+  bzero (stdin_fd,  2*sizeof(int));
+  bzero (stdout_fd, 2*sizeof(int));
+  bzero (stderr_fd, 2*sizeof(int));
+
+  if (pipe (stdin_fd)  < 0) goto pipe_error;
+  if (pipe (stdout_fd) < 0) goto pipe_error;
+  if (pipe (stderr_fd) < 0) goto pipe_error;
+
+  ALLOCATE (argv, char *, 2);
+  argv[0] = cmd;
+  argv[1] = 0;
+
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    gprint (GP_LOG, "starting controller connection\n");
+
+    /* close the other ends of the pipes */
+    close (stdin_fd[1]);
+    close (stdout_fd[0]);
+    close (stderr_fd[0]);
+
+    /* tie our ends of the pipes to stdin, stdout, stderr */
+    dup2 (stdin_fd[0],  STDIN_FILENO);
+    dup2 (stdout_fd[1], STDOUT_FILENO);
+    dup2 (stderr_fd[1], STDERR_FILENO);
+
+    /* set all three unblocking */
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    status = execvp (argv[0], argv); 
+    exit (1);
+  }
+  free (argv);
+
+  /* close the other ends of the pipes */
+  close (stdin_fd[0]);  stdin_fd[0]  = 0;
+  close (stdout_fd[1]); stdout_fd[1] = 0;
+  close (stderr_fd[1]); stderr_fd[1] = 0;
+
+  /* make the pipes non-blocking */
+  fcntl (stdin_fd[1],  F_SETFL, O_NONBLOCK);
+  fcntl (stdout_fd[0], F_SETFL, O_NONBLOCK);
+  fcntl (stderr_fd[0], F_SETFL, O_NONBLOCK);
+
+  /* perform handshake with controller to verify alive & running */
+  /** this handshake is similar to ControllerCommand, but has important differences **/
+  InitIOBuffer (&buffer, 0x100);
+
+  /* send handshake command */
+  status = write_fmt (stdin_fd[1], "echo CONNECTED\n");
+  if ((status == -1) && (errno == EPIPE)) goto pipe_error;
+
+  /* try to get evidence connection is alive - wait upto a few seconds */
+  /* connection is likely slow; don't bother with nanosleep here */
+  p = NULL;
+  status = -1;
+  for (i = 0; (i < CONNECT_TIMEOUT) && (status != 0) && (p == NULL); i++) {
+    status = ReadtoIOBuffer (&buffer, stdout_fd[0]);
+    p = memstr (buffer.buffer, "CONNECTED", buffer.Nbuffer);
+    usleep (10000); // wait for controller to start up
+  }
+  if (status == 0) goto pipe_error;
+  if (status == -1) goto io_error;
+  FreeIOBuffer (&buffer);
+
+  /* set local static vars to pipe connections */
+  stdin_cntl  = stdin_fd[1];
+  stdout_cntl = stdout_fd[0];
+  stderr_cntl = stderr_fd[0];
+
+  InitIOBuffer (&stdout_buffer, 0x100);
+  InitIOBuffer (&stderr_buffer, 0x100);
+
+  ControllerPID = pid;
+  ControllerStatus = TRUE;
+  gprint (GP_LOG, "Connected\n");
+  return (TRUE);
+
+pipe_error:
+  perror ("pipe error:");
+  goto close_pipes;
+
+io_error:
+  gprint (GP_ERR, "timeout while connecting\n");
+  goto close_pipes;
+
+close_pipes:
+  if (stdin_fd[0]  != 0) close (stdin_fd[0]);
+  if (stdin_fd[1]  != 0) close (stdin_fd[1]);
+  if (stdout_fd[0] != 0) close (stdout_fd[0]);
+  if (stdout_fd[1] != 0) close (stdout_fd[1]);
+  if (stderr_fd[0] != 0) close (stderr_fd[0]);
+  if (stderr_fd[1] != 0) close (stderr_fd[1]);
+  return (FALSE);
+}
+
+int ControllerCommand (char *cmd, char *response, IOBuffer *buffer) {
+
+  int i, j, status;
+  char *line;
+  struct timespec request, remain;
+
+  /* avoid blocking on waitpid, test every 100 usec, up to 50 msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 100000;
+
+  ReadtoIOBuffer (buffer, stdout_cntl);
+  FlushIOBuffer (buffer);
+
+  /* send command, is pipe still open? */
+  status = write_fmt (stdin_cntl, "%s\n", cmd);
+  if ((status == -1) && (errno == EPIPE)) {
+    StopController ();
+    gprint (GP_ERR, "controller is down\n");
+    return (FALSE);
+  }
+  
+  /* for commands which don't return a prompt, don't look for one */
+  if (response == NULL) {
+      return (TRUE);
+  }
+
+  /* watch for response - wait up to 1 second */
+  line = NULL;
+  status = -1;
+  for (j = 0; (status == -1) && (j < 10); j++) {
+      for (i = 0; (i < CONTROLLER_TIMEOUT) && (status != 0) && (line == NULL); i++) {
+	  status = ReadtoIOBuffer (buffer, stdout_cntl);
+	  line = memstr (buffer[0].buffer, response, buffer[0].Nbuffer);
+	  if (status == -1) nanosleep (&request, &remain);
+      }
+      if (status ==  0) {
+	  StopController ();
+	  gprint (GP_ERR, "controller is down\n");
+	  return (FALSE);
+      }
+      if (status == -1) {
+	  gprint (GP_ERR, "controller is not responding (%d tries)\n", j);
+	  gwrite (buffer[0].buffer, 1, buffer[0].Nbuffer, GP_ERR);
+      }
+  }
+  if (status == -1) {
+      gprint (GP_ERR, "controller still not responding, giving up\n");
+      return (FALSE);
+  }
+
+  /* need to strip off the prompt */
+  line = memstr (buffer[0].buffer, response, buffer[0].Nbuffer);
+  if (line != NULL) {
+    buffer[0].Nbuffer = line - buffer[0].buffer;
+    bzero (buffer[0].buffer + buffer[0].Nbuffer, buffer[0].Nalloc - buffer[0].Nbuffer);
+  }
+  /* if (VerboseMode()) gprint (GP_ERR, "message received, %d cycles\n", i); */
+  return (TRUE);
+}
+
+int CheckControllerOutput () {
+
+  int Nread;
+
+  if (!ControllerStatus) return (TRUE);
+
+  /* read stdout buffer */
+  Nread = ReadtoIOBuffer (&stdout_buffer, stdout_cntl);
+  switch (Nread) {
+    case -2:  /* error in read (programming error?  system level error?) */
+      gprint (GP_ERR, "serious IO error\n");
+      exit (2);
+    case -1:  /* no data in pipe */
+    case 0:   /* pipe is closed, change child state? **/
+    default:  /* data in pipe */
+      break;
+  }
+  
+  /* read stderr buffer */
+  Nread = ReadtoIOBuffer (&stderr_buffer, stderr_cntl);
+  switch (Nread) {
+    case -2:  /* error in read (programming error?  system level error?) */
+      gprint (GP_ERR, "serious IO error\n");
+      exit (2);
+    case -1:  /* no data in pipe */
+    case 0:   /* pipe is closed, change child state? **/
+    default:  /* data in pipe */
+      break;
+  }
+  return (TRUE);
+}
+
+int PrintControllerOutput () {
+
+  gprint (GP_LOG, "--- stdout ---\n");
+  gwrite (stdout_buffer.buffer, 1, stdout_buffer.Nbuffer, GP_LOG);
+  gprint (GP_LOG, "--- stderr ---\n");
+  gwrite (stderr_buffer.buffer, 1, stderr_buffer.Nbuffer, GP_LOG);
+  gprint (GP_LOG, "---  done  ---\n");
+  return (TRUE);
+}
+
+
+int KillControllerJob (Job *job) {
+
+  int status;
+  char cmd[128];
+  IOBuffer buffer;
+
+  if (!ControllerStatus) return (TRUE);
+
+  sprintf (cmd, "kill %d", job[0].pid);
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (cmd, CONTROLLER_PROMPT, &buffer);
+  FreeIOBuffer (&buffer);
+  return (status);
+
+  /** need to interpret output message & free things **/
+}
+
+int QuitController () {
+
+  int status;
+  char cmd[128];
+  IOBuffer buffer;
+
+  if (!ControllerStatus) return (TRUE);
+
+  sprintf (cmd, "quit");
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (cmd, NULL, &buffer);
+  FreeIOBuffer (&buffer);
+
+  /* the quit command does not return a prompt, 
+     check that the controller exited */
+  StopController ();
+  return (TRUE);
+}
+
+int StopController () {
+
+  int i, waitstatus, result;
+
+  if (!ControllerStatus) return (TRUE);
+
+  ControllerStatus = FALSE;
+  result = waitpid (ControllerPID, &waitstatus, WNOHANG);
+  for (i = 0; (i < 10) && (result == 0); i++) {
+    usleep (10000);  // wait for controller to exit
+    result = waitpid (ControllerPID, &waitstatus, WNOHANG);
+  }
+  ControllerPID = 0;
+  close (stdin_cntl);
+  close (stdout_cntl);
+  close (stderr_cntl);
+  FreeIOBuffer (&stdout_buffer);
+  FreeIOBuffer (&stderr_buffer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/InputQueue.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/InputQueue.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/InputQueue.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include "pantasks.h"
+
+static int Ninputs = 0;
+static int NINPUTS = 0;
+static char **inputs;
+
+void InitInputs () {
+
+  Ninputs = 0;
+  NINPUTS = 10;
+  ALLOCATE (inputs, char *, NINPUTS);
+}
+
+void FreeInputs () {
+  int i;
+  for (i = 0; i < Ninputs; i++) {
+    free (inputs[i]);
+  }
+  free (inputs);
+}
+
+/* add this input to the inputs table */
+void AddNewInput (char *input) {
+
+  SerialThreadLock ();
+  if (DEBUG) gprint (GP_LOG, "adding a new input (%s)\n", input);
+  inputs[Ninputs] = input;
+  Ninputs ++;
+  if (Ninputs >= NINPUTS - 1) {
+    NINPUTS += 10;
+    REALLOCATE (inputs, char *, NINPUTS);
+  }
+  if (DEBUG) gprint (GP_LOG, "done new input (%s)\n", input);
+  SerialThreadUnlock ();
+}
+
+/* remove this input from the inputs table */
+int DeleteInput (char *input) {
+
+  int i, j;
+
+  if (DEBUG) gprint (GP_LOG, "deleting an input (%s)\n", input);
+  for (i = 0; i < Ninputs; i++) {
+    if (inputs[i] == input) {
+      free (inputs[i]);
+      for (j = i; j < Ninputs - 1; j++) {
+	inputs[j] = inputs[j+1];
+      }
+      Ninputs --;
+      if ((Ninputs > 10) && (Ninputs / 2 < NINPUTS)) {
+	NINPUTS = Ninputs + 10;
+	REALLOCATE (inputs, char *, NINPUTS);
+      }
+      if (DEBUG) gprint (GP_LOG, "deleted an input\n");
+      return TRUE;
+    }
+  }
+  // did not find the input
+  return FALSE;
+}
+
+/* if any inputs are pending, run one */
+void CheckInputs () {
+
+  int Nbytes, status;
+  char *input, *line, *outline, tmp;
+
+  if (Ninputs < 1) return;
+
+  input = inputs[0];
+  if (DEBUG) gprint (GP_LOG, "got an input (%s)\n", input);
+  
+  Nbytes = snprintf (&tmp, 0, "input %s", input);
+  ALLOCATE (line, char, Nbytes + 1);
+  snprintf (line, Nbytes + 1, "input %s", input);
+
+  status = command (line, &outline, TRUE);
+  free (outline);
+  
+  DeleteInput (input);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/JobIDOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/JobIDOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/JobIDOps.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "pantasks.h"
+
+# define MAX_N_JOBS 1000
+static char *JobIDList;
+static int   JobIDPtr;
+
+int InitJobIDs () {
+
+  JobIDPtr = 0;
+  ALLOCATE (JobIDList, char, MAX_N_JOBS);
+  bzero (JobIDList, MAX_N_JOBS*sizeof(char));
+  return (TRUE);
+}  
+
+int FreeJobIDs () {
+  free (JobIDList);
+}
+
+/* return next unique ID, recycle every MAX_N_JOBS */
+int NextJobID () {
+
+  int Ntry;
+
+  JobIDPtr ++;
+  if (JobIDPtr >= MAX_N_JOBS) JobIDPtr = 0;
+
+  Ntry = 0;
+  while (JobIDList[JobIDPtr]) {
+    Ntry ++;
+    JobIDPtr ++;
+    if (JobIDPtr >= MAX_N_JOBS) JobIDPtr = 0;
+    if (Ntry == MAX_N_JOBS) return (-1);
+  }
+  JobIDList[JobIDPtr] = TRUE;
+  return (JobIDPtr);
+}
+
+int FreeJobID (int JobID) {
+
+  if (JobID < 0) return (FALSE);
+  if (JobID >= MAX_N_JOBS) return (FALSE);
+
+  JobIDList[JobID] = FALSE;
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/JobOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/JobOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/JobOps.c	(revision 16632)
@@ -0,0 +1,285 @@
+# include "pantasks.h"
+
+static Job **jobs;
+static int   Njobs;
+static int   NJOBS;
+
+/* counter marking job being visited by the run loop */
+static int   ActiveJob;
+
+/* set up the jobs list */
+void InitJobs () {
+  NJOBS = 20;
+  Njobs = 0;
+  ALLOCATE (jobs, Job *, NJOBS);
+  ActiveJob = -1;
+}
+
+void FreeJobs () {
+  int i;
+  for (i = 0; i < Njobs; i++) {
+    FreeJob (jobs[i]);
+  }
+  free (jobs);
+}
+
+/* provide a mechanism to loop over the list of jobs */
+Job *NextJob () {
+  
+  Job *job;
+
+  ActiveJob ++;
+  if (ActiveJob < 0) ActiveJob = 0;
+  if (ActiveJob >= Njobs) {
+    ActiveJob = -1;
+    return (NULL);
+  }
+  job = jobs[ActiveJob];
+  return (job);
+}
+
+/* return job with given ID */
+Job *FindJob (int JobID) {
+
+  int i;
+
+  /* return job with matching JobID */
+  for (i = 0; i < Njobs; i++) {
+    if (jobs[i][0].JobID == JobID) {
+      return (jobs[i]);
+    }
+  }
+  return (NULL);
+}  
+
+/* return job with given controller Job ID */
+Job *FindControllerJob (int JobID) {
+
+  int i;
+
+  /* return job with matching JobID */
+  for (i = 0; i < Njobs; i++) {
+    if (jobs[i][0].mode == JOB_LOCAL) continue;
+    if (jobs[i][0].pid  == JobID) {
+      return (jobs[i]);
+    }
+  }
+  return (NULL);
+}  
+
+/* list known jobs */
+void ListJobs () {
+
+  int i;
+  int status;
+  char command[1024];
+  IOBuffer buffer;
+
+  gprint (GP_LOG, "\n");
+  if (Njobs == 0) {
+    gprint (GP_LOG, " no defined jobs\n");
+    return;
+  }
+
+  gprint (GP_LOG, " Jobs in Pantasks Queue\n");
+  for (i = 0; i < Njobs; i++) {
+    gprint (GP_LOG, " %d: %-15s %5d %20s (%lx)\n", Njobs, jobs[i][0].task[0].name, jobs[i][0].JobID, jobs[i][0].argv[0], (long) jobs[i][0].argv);
+  }
+
+  /* check if controller is running */
+  status = CheckControllerStatus ();
+  if (!status) {
+    return;
+  }
+
+  sprintf (command, "jobstack busy");
+  InitIOBuffer (&buffer, 0x100);
+
+  SerialThreadLock ();
+  status = ControllerCommand (command, CONTROLLER_PROMPT, &buffer);
+  SerialThreadUnlock ();
+
+  if (status) {
+    gprint (GP_LOG, " jobs currently running remotely:\n");
+    gwrite (buffer.buffer, 1, buffer.Nbuffer, GP_LOG);
+  } else {
+    gprint (GP_LOG, "controller is not responding\n");
+  }
+  FreeIOBuffer (&buffer);
+  return;
+}
+
+/* make a new job from a task */
+Job *CreateJob (Task *task) {
+  
+  int i;
+  Job *job;
+  
+  ALLOCATE (job, Job, 1);
+
+  job[0].JobID = NextJobID ();
+  job[0].pid = 0;
+  job[0].mode = JOB_LOCAL;
+  if (task[0].host != NULL) {
+    job[0].mode = JOB_CONTROLLER;
+  }
+
+  /* we need our own copy of task[0].argv argc is the number of valid args, like the usual command line.  we
+   *  allocate one extra element, with value 0 to be passed to execvp
+   */
+  job[0].argc = task[0].argc;
+  ALLOCATE (job[0].argv, char *, MAX (task[0].argc + 1, 1));
+  for (i = 0; i < task[0].argc; i++) {
+    job[0].argv[i] = strcreate (task[0].argv[i]);
+  }
+  job[0].argv[i] = 0;
+
+  /* we need our own copy of task[0].optv: optc is the number of valid opts.  */
+  job[0].optc = task[0].optc;
+  ALLOCATE (job[0].optv, char *, MAX (task[0].optc, 1));
+  for (i = 0; i < job[0].optc; i++) {
+    job[0].optv[i] = strcreate (task[0].optv[i]);
+  }
+
+  /* Other data from the task is needed by the job. We carry a pointer back to the task.  Changes to an
+     executing task are applied to the existing jobs (exit macros, poll_period, timeout) */
+
+  job[0].task = task;
+  job[0].realhost = NULL;
+  
+  /* if we decide we need to be able to dynamically set task qualities (like host, timeouts, etc), the we will
+     need to have matched entries to these quantites in the job structure */
+
+  InitIOBuffer (&job[0].stdout_buff, 0x100);
+  InitIOBuffer (&job[0].stderr_buff, 0x100);
+
+  job[0].stdout_dump = NULL;
+  job[0].stderr_dump = NULL;
+  if (task[0].stdout_dump != NULL) job[0].stdout_dump = strcreate (task[0].stdout_dump);
+  if (task[0].stderr_dump != NULL) job[0].stderr_dump = strcreate (task[0].stderr_dump);
+
+  jobs[Njobs] = job;
+  Njobs ++;
+  if (Njobs == NJOBS) {
+    NJOBS += 20;
+    REALLOCATE (jobs, Job *, NJOBS);
+  }
+  return (jobs[Njobs-1]);
+}
+
+void FreeJob (Job *job) {
+  
+  int i;
+
+  if (job == NULL) return;
+  
+  FreeJobID (job[0].JobID);
+
+  for (i = 0; i < job[0].argc; i++) {
+    free (job[0].argv[i]);
+  }
+  free (job[0].argv);
+
+  for (i = 0; i < job[0].optc; i++) {
+    free (job[0].optv[i]);
+  }
+  free (job[0].optv);
+
+  if (job[0].stdout_dump != NULL) free (job[0].stdout_dump);
+  if (job[0].stderr_dump != NULL) free (job[0].stderr_dump);
+  if (job[0].realhost != NULL) free (job[0].realhost);
+
+  FreeIOBuffer (&job[0].stdout_buff);
+  FreeIOBuffer (&job[0].stderr_buff);
+  free (job);
+  return;
+}
+
+/* delete the job from the job list & adjust ActiveJob counter */
+int DeleteJob (Job *job) {
+
+  int i, Nm;
+
+  Nm = -1;
+  for (i = 0; i < Njobs; i++) {
+    if (job == jobs[i]) {
+      Nm = i;
+      break;
+    }
+  }
+  if (Nm == -1) {
+    gprint (GP_ERR, "programming error: job not found\n");
+    return (FALSE);
+  }
+
+  FreeJob (jobs[Nm]);
+  for (i = Nm; i < Njobs - 1; i++) {
+    jobs[i] = jobs[i + 1];
+  }
+  Njobs --;
+
+  /* adjust active job number */
+  if (ActiveJob >= Nm) {
+    ActiveJob --;
+  }
+
+  job[0].task[0].Npending --;
+  return (TRUE);
+}
+
+int FlushJobs () {
+
+  int i;
+
+  // kill outstanding jobs
+  for (i = 0; i < Njobs; i++) {
+    if (jobs[i][0].mode == JOB_LOCAL) {
+      if (!KillLocalJob (jobs[i])) {
+	jobs[i][0].state = JOB_HUNG;
+	if (VerboseMode()) gprint (GP_LOG, "child process %d is hung, cannot kill\n", jobs[i][0].pid);
+      }
+    } else {
+      if (!KillControllerJob (jobs[i])) {
+	jobs[i][0].state = JOB_HUNG;
+	if (VerboseMode()) gprint (GP_LOG, "child process %d is hung, cannot kill\n", jobs[i][0].pid);
+      }
+    }    
+    jobs[i][0].task[0].Npending = 0;
+    FreeJob (jobs[i]);
+  }
+    
+  Njobs = 0;
+  NJOBS = 20;
+  REALLOCATE (jobs, Job *, NJOBS);
+  ActiveJob = -1;
+  return (TRUE);
+}
+
+int SubmitJob (Job *job) {
+
+  if (job[0].mode == JOB_LOCAL) {
+    if (DEBUG) fprintf (stderr, "submit job: (%zx) %d of %d\n", (size_t) job[0].stdout_buff.buffer, job[0].stdout_buff.Nbuffer, job[0].stdout_buff.Nalloc); 
+    SubmitLocalJob (job);
+  } else {
+    SubmitControllerJob (job);
+  }
+
+  /* reset clock for start and poll-test */
+  gettimeofday (&job[0].start, (void *) NULL);
+  job[0].last = job[0].start;
+  job[0].state = JOB_PENDING;
+  return (TRUE);
+}
+
+int CheckJob (Job *job) {
+
+  /* add checks for timeouts */
+
+  if (job[0].mode == JOB_LOCAL) {
+    CheckLocalJob (job);
+  } else {
+    /* controller jobs are now checked en masse by CheckController */
+    /* CheckControllerJob (job); */
+  }
+  return (job[0].state);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ListenClients.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ListenClients.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ListenClients.c	(revision 16632)
@@ -0,0 +1,182 @@
+# include "pantasks.h"
+# define DEBUG 0
+
+static int NCLIENTS;
+static int Nclients;
+static int *clients;
+static IOBuffer **buffers;
+
+void InitClients () {
+
+  Nclients = 0;
+  NCLIENTS = 10;
+  ALLOCATE (clients, int, NCLIENTS);
+  ALLOCATE (buffers, IOBuffer *, NCLIENTS);
+}
+
+/* add this client to the client table, create an IOBuffer for it */
+void AddNewClient (int client) {
+
+  if (DEBUG) gprint (GP_LOG, "adding a new client (%d)\n", client);
+  clients[Nclients] = client;
+  ALLOCATE (buffers[Nclients], IOBuffer, 1);
+  InitIOBuffer(buffers[Nclients], 256);
+  Nclients ++;
+  if (Nclients >= NCLIENTS - 1) {
+    NCLIENTS += 10;
+    REALLOCATE (clients, int, NCLIENTS);
+    REALLOCATE (buffers, IOBuffer *, NCLIENTS);
+  }
+}
+
+/* add this client to the client table, create an IOBuffer for it */
+int DeleteClient (int client) {
+
+  int i, j;
+
+  if (DEBUG) gprint (GP_LOG, "deleting a client (%d)\n", client);
+  for (i = 0; i < Nclients; i++) {
+    if (clients[i] == client) {
+      FreeIOBuffer (buffers[i]);
+      free (buffers[i]);
+      close (clients[i]);
+      for (j = i; j < Nclients - 1; j++) {
+	clients[j] = clients[j+1];
+	buffers[j] = buffers[j+1];
+      }
+      Nclients --;
+      if ((Nclients > 10) && (Nclients / 2 < NCLIENTS)) {
+	NCLIENTS = Nclients + 10;
+	REALLOCATE (clients, int, NCLIENTS);
+	REALLOCATE (buffers, IOBuffer *, NCLIENTS);
+      }
+      return TRUE;
+    }
+  }
+  // did not find the client
+  return FALSE;
+}
+
+/* select for messages from the current clients; wait for 0.5s before updating client list */
+void *ListenClients (void *data) {
+  
+  int i, Ncurrent, Nmax, status, Nread;
+  char *line, log_stdout[128], log_stderr[128];
+  fd_set fdSet;
+  struct timeval timeout;
+  IOBuffer *outbuffer;
+
+  InitClients ();
+  gprintInit ();  // each thread needs to init the printing system
+
+  // define server output log files
+  if (VarConfig ("PANTASKS_SERVER_STDOUT", "%s", log_stdout) != NULL) {
+    gprintSetFileThisThread (GP_LOG, log_stdout);
+  } else {
+    strcpy (log_stdout, "stdout");
+  }
+  if (VarConfig ("PANTASKS_SERVER_STDERR", "%s", log_stderr) != NULL) {
+    gprintSetFileThisThread (GP_ERR, log_stderr);
+  } else {
+    strcpy (log_stderr, "stderr");
+  }
+
+  while (1) {
+
+    /* Wait up to 0.5 second - need to timeout to update client list */
+    /* timeout gets mucked: need to reset before each select */
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 500000;
+
+    /* place all of the clients in the fdSet */
+    Ncurrent = Nclients;
+    Nmax = 0;
+    FD_ZERO (&fdSet);
+    for (i = 0; i < Ncurrent; i++) {
+      Nmax = MAX (Nmax, clients[i]);
+      FD_SET (clients[i], &fdSet);
+    }    
+    Nmax ++;
+
+    /* block until we have some data on the pipes (or timeout) */
+    if (DEBUG) gprint (GP_ERR, "listening to %d clients\n", Ncurrent);
+    status = select (Nmax, &fdSet, NULL, NULL, &timeout);
+    if (status == -1) {
+      perror("select()");
+      return (FALSE);
+    }
+
+    /* if no data, update client list, wait for another select */
+    if (status <= 0) continue;
+
+    /* loop over the clients with data */
+    for (i = 0; i < Ncurrent; i++) {
+      /* if client has no data, skip it */
+      if (!FD_ISSET(clients[i], &fdSet)) continue;
+
+      /* read until the pipe is empty: 0 is closed, -1 is empty, -2 is error */
+      Nread = 1;
+      while (Nread > 0) {
+	Nread = ReadtoIOBuffer (buffers[i], clients[i]);	
+      }
+      if ((Nread == 0) || (Nread == -2)) {
+	/* error: do something */
+	if (DEBUG && (Nread == 0)) gprint (GP_ERR, "socket is closed\n");
+	if (DEBUG && (Nread == -2)) gprint (GP_ERR, "error reading from socket\n");
+	DeleteClient (clients[i]);
+	continue;
+      }
+
+      if (DEBUG) gprint (GP_ERR, "read %d total bytes\n", buffers[i][0].Nbuffer);
+
+      /* see if we have a complete message waiting; if not, keep waiting for messages */
+      line = CheckForMessage (buffers[i]);
+      if (line == NULL) continue;
+
+      /* we now have a possible command from the client: run it */
+      /* in this thread, we set the print output destination to be an
+	 internal buffer, which we dump at the end of the execution */
+      /* the commands sent to the server should not have ; */
+      stripwhite (line);
+      if (*line) {
+
+	/* set buffers for the output for this client */
+	gprintSetBuffer (GP_LOG);
+	gprintSetBuffer (GP_ERR);
+
+	/* run the command, return the exit status */
+	status = multicommand (line);
+	SendMessage (clients[i], "STATUS %d", status);
+
+	// return the stderr messages first
+	outbuffer = gprintGetBuffer (GP_ERR);
+	if (outbuffer) {
+	  SendMessageFixed (clients[i], outbuffer[0].Nbuffer, outbuffer[0].buffer);
+	} else {
+	  SendMessageFixed (clients[i], 0, "");
+	}	  
+
+	// return the stdout messages first
+	outbuffer = gprintGetBuffer (GP_LOG);
+	if (outbuffer) {
+	  SendMessageFixed (clients[i], outbuffer[0].Nbuffer, outbuffer[0].buffer);
+	} else {
+	  SendMessageFixed (clients[i], 0, "");
+	}	  
+	
+	/* clear and reset the output buffers to their last output file names */
+	gprintSetFileAllThreads (GP_LOG, NULL);
+	gprintSetFileAllThreads (GP_ERR, NULL);
+      }
+      free (line);
+    }
+    /* if Nread == -2, we probably need to drop the client */
+    /* check if we need to drop / remove any clients */
+    /* check if we need to shut down the thread */
+  }
+}
+
+/* the AddClient commands are issued by the parent thread
+   the value of Nclients may increase after we check it here. 
+   only this thread is allowed to decrease Nclients and remove
+   a client from the table */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/LocalJob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/LocalJob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/LocalJob.c	(revision 16632)
@@ -0,0 +1,222 @@
+# include "pantasks.h"
+
+/* local jobs are forked in the background 
+   we might need to limit the maximum number of local jobs.
+   should we have a queue/stack of pending local jobs, much
+   like controller? */
+
+/* update current state, drain stdout/stderr buffers */
+int CheckLocalJob (Job *job) {
+
+  int Nread;
+
+  // XXX do something useful with exit status?
+  CheckLocalJobStatus (job);
+
+  if ((job[0].state == JOB_EXIT) || (job[0].state == JOB_CRASH)) {
+    if (DEBUG) fprintf (stderr, "empty buffer 0: (%zx) %d of %d\n", (size_t) job[0].stdout_buff.buffer, job[0].stdout_buff.Nbuffer, job[0].stdout_buff.Nalloc); 
+    EmptyIOBuffer (&job[0].stdout_buff, 10, job[0].stdout_fd);
+    EmptyIOBuffer (&job[0].stderr_buff, 10, job[0].stderr_fd);
+    if (DEBUG) fprintf (stderr, "empty buffer 1: (%zx) %d of %d\n", (size_t) job[0].stdout_buff.buffer, job[0].stdout_buff.Nbuffer, job[0].stdout_buff.Nalloc); 
+    close (job[0].stdout_fd);
+    close (job[0].stderr_fd);
+  } else {
+    /* read stdout buffer */
+    if (DEBUG) fprintf (stderr, "read buffer 0: (%zx) %d of %d\n", (size_t) job[0].stdout_buff.buffer, job[0].stdout_buff.Nbuffer, job[0].stdout_buff.Nalloc); 
+    while ((Nread = ReadtoIOBuffer (&job[0].stdout_buff, job[0].stdout_fd)) > 0);
+    switch (Nread) {
+      case -2:  /* error in read (programming error?  system level error?) */
+	gprint (GP_ERR, "serious IO error\n");
+	exit (2);
+      case -1:  /* no data in pipe */
+      case 0:   /* pipe is closed, change child state? **/
+      default:  /* data in pipe */
+	// fprintf (stderr, "read %d bytes (Nblock: %d, Nbuffer: %d)\n", Nread, job[0].stdout.Nblock, job[0].stdout.Nbuffer);
+	break;
+    }
+    if (DEBUG) fprintf (stderr, "read buffer 1: (%zx) %d of %d\n", (size_t) job[0].stdout_buff.buffer, job[0].stdout_buff.Nbuffer, job[0].stdout_buff.Nalloc); 
+  
+    /* read stderr buffer */
+    while ((Nread = ReadtoIOBuffer (&job[0].stderr_buff, job[0].stderr_fd)) > 0);
+    switch (Nread) {
+      case -2:  /* error in read (programming error?  system level error?) */
+	gprint (GP_ERR, "serious IO error\n");
+	exit (2);
+      case -1:  /* no data in pipe */
+      case 0:   /* pipe is closed, change child state? **/
+      default:  /* data in pipe */
+	break;
+    }
+  }
+  return (TRUE);
+}
+
+int CheckLocalJobStatus (Job *job) {
+
+  int result, waitstatus;
+
+  /* check local job status */
+  result = waitpid (job[0].pid, &waitstatus, WNOHANG);
+  switch (result) {
+    case -1:  /* error with waitpid */
+      switch (errno) {
+	case ECHILD:
+	  gprint (GP_ERR, "unknown PID, not a child proc\n");
+	  gprint (GP_ERR, "did process already exit?  programming error?\n");
+	  job[0].state = JOB_NONE;
+	  job[0].exit_status = 0;
+	  return (FALSE);
+	case EINVAL:
+	  gprint (GP_ERR, "error EINVAL (waitpid): programming error\n");
+	  exit (1);
+	case EINTR:
+	  gprint (GP_ERR, "error EINTR (waitpid): programming error\n");
+	  exit (1);
+	default:
+	  gprint (GP_ERR, "unknown error for waitpid (%d): programming error\n", errno);
+	  exit (1);
+      }
+      break;
+      
+    case 0:  /* process not exited */
+      job[0].state = JOB_BUSY;
+      job[0].exit_status = 0;
+      return (TRUE);
+
+    default:
+      if (result != job[0].pid) {
+	gprint (GP_ERR, "waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, job[0].pid);
+	exit (1);
+      }
+      if (WIFEXITED(waitstatus)) {
+	job[0].state = JOB_EXIT;
+	job[0].exit_status = WEXITSTATUS(waitstatus);
+      }
+      if (WIFSIGNALED(waitstatus)) {
+	job[0].state = JOB_CRASH;
+	job[0].exit_status = WTERMSIG(waitstatus);
+      }
+      if (WIFSTOPPED(waitstatus)) {
+	gprint (GP_ERR, "waitpid returns 'stopped': programming error\n");
+	exit (1);
+      }
+      job[0].dtime = GetTaskTimer (job[0].start, FALSE);
+      break;
+  }
+  return (FALSE);
+}
+
+/* this could be written a just a one-way pipe */
+int SubmitLocalJob (Job *job) {
+
+  int status, pid;
+  int stdout_fd[2], stderr_fd[2];
+
+  bzero (stdout_fd, 2*sizeof(int));
+  bzero (stderr_fd, 2*sizeof(int));
+
+  if (pipe (stdout_fd) < 0) goto pipe_error;
+  if (pipe (stderr_fd) < 0) goto pipe_error;
+
+  // XXX nothing to be read at this point
+  // other threads are already halted here.
+  fflush (stdout);
+  fflush (stderr);
+
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    if (VerboseMode()) gprint (GP_ERR, "starting local job\n");
+
+    /* close the other ends of the pipes */
+    close (stdout_fd[0]);
+    close (stderr_fd[0]);
+
+    // XXX neither of these work to empty the child stdout buffer
+    // fflush (stdout);
+    // fflush (stderr);
+    // close (STDOUT_FILENO);
+    // close (STDERR_FILENO);
+
+    /* tie our ends of the pipes to stdin, stdout, stderr */
+    dup2 (stdout_fd[1], STDOUT_FILENO);
+    dup2 (stderr_fd[1], STDERR_FILENO);
+
+    /* set all three unblocking */
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    // XXX allow the parent time to read the stdout/stderr buffers
+    usleep (10000);
+
+    status = execvp (job[0].argv[0], job[0].argv); 
+    exit (1);
+  }
+  if (VerboseMode()) gprint (GP_ERR, "local job launched\n");
+
+  /* close the other ends of the pipes */
+  close (stdout_fd[1]); stdout_fd[1] = 0;
+  close (stderr_fd[1]); stderr_fd[1] = 0;
+
+  /* make the pipes non-blocking */
+  fcntl (stdout_fd[0], F_SETFL, O_NONBLOCK);
+  fcntl (stderr_fd[0], F_SETFL, O_NONBLOCK);
+
+  // XXX There seems to always be extra data on the pipe, specifically the 
+  // stdout buffer from the parent.  If I read it here, then it clears out that data.
+  // But, how can I be sure I will not start reading data from the exec-ed process?
+
+  { // test read of the stdout buffer
+    int Nread;
+    char buffer[0x1000];
+
+    Nread = read (stdout_fd[0], buffer, 0x1000);
+    if (DEBUG) fprintf (stderr, "read from stdout before exec: %d bytes\n", Nread);
+
+    Nread = read (stderr_fd[0], buffer, 0x1000);
+    if (DEBUG) fprintf (stderr, "read from stderr before exec: %d bytes\n", Nread);
+  }
+
+  job[0].stdout_fd = stdout_fd[0];
+  job[0].stderr_fd = stderr_fd[0];
+  job[0].pid = pid;
+
+  return (TRUE);
+
+pipe_error:
+  perror ("pipe error:");
+  if (stdout_fd[0] != 0) close (stdout_fd[0]);
+  if (stdout_fd[1] != 0) close (stdout_fd[1]);
+  if (stderr_fd[0] != 0) close (stderr_fd[0]);
+  if (stderr_fd[1] != 0) close (stderr_fd[1]);
+  return (FALSE);
+}
+
+/* should this function close the fd's? */
+int KillLocalJob (Job *job) {
+
+  int i, result, waitstatus;
+
+  if (job[0].state != JOB_BUSY) return (TRUE);
+
+  /* send SIGTERM signal to job */
+  kill (job[0].pid, SIGTERM);
+  result = 0;
+  for (i = 0; (i < 10) && (result == 0); i++) {
+    usleep (10000);  // wait for job to exit
+    result = waitpid (job[0].pid, &waitstatus, WNOHANG);
+  }
+  if (result) return (TRUE);
+
+  /* send SIGKILL signal to job */
+  kill (job[0].pid, SIGKILL);
+  result = 0;
+  for (i = 0; (i < 10) && (result == 0); i++) {
+    usleep (10000);  // wait for job to exit
+    result = waitpid (job[0].pid, &waitstatus, WNOHANG);
+  }
+  if (result) return (TRUE);
+
+  /* total failure, don't reset */
+  return (FALSE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/Makefile	(revision 16632)
@@ -0,0 +1,124 @@
+default: pantasks pantasks_client pantasks_server
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+SRC     =       $(HOME)/pantasks
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+DATA    =       $(DESTDATA)/pantasks
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+LIBS1   =       -lbasiccmd -ldatacmd -lastrocmd -lshell -ldata 
+LIBS2   =       -ldvo -lkapa -lFITS -lohana
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(LIBS1) $(LIBS2) $(BASE_LDFLAGS)
+
+# sched user commands and support functions ########################
+
+client = \
+$(SRC)/pantasks_client.$(ARCH).o \
+$(SRC)/client_shell.$(ARCH).o \
+$(SRC)/invalid.$(ARCH).o \
+$(SRC)/init_client.$(ARCH).o
+
+single = \
+$(SRC)/init.$(ARCH).o \
+$(SRC)/run.$(ARCH).o \
+$(SRC)/stop.$(ARCH).o \
+$(SRC)/pantasks.$(ARCH).o \
+$(SRC)/thread_locks.$(ARCH).o \
+$(SRC)/job_threads.$(ARCH).o \
+$(SRC)/task_threads.$(ARCH).o \
+$(SRC)/controller_threads.$(ARCH).o 
+
+server = \
+$(SRC)/pantasks_server.$(ARCH).o \
+$(SRC)/server_run.$(ARCH).o \
+$(SRC)/server_load.$(ARCH).o \
+$(SRC)/InputQueue.$(ARCH).o \
+$(SRC)/ListenClients.$(ARCH).o \
+$(SRC)/server.$(ARCH).o \
+$(SRC)/status_server.$(ARCH).o \
+$(SRC)/init_server.$(ARCH).o \
+$(SRC)/CheckPassword.$(ARCH).o \
+$(SRC)/thread_locks.$(ARCH).o \
+$(SRC)/job_threads.$(ARCH).o \
+$(SRC)/task_threads.$(ARCH).o \
+$(SRC)/controller_threads.$(ARCH).o \
+$(SRC)/input_threads.$(ARCH).o
+
+funcs = \
+$(SRC)/CheckJobs.$(ARCH).o \
+$(SRC)/CheckController.$(ARCH).o \
+$(SRC)/CheckTasks.$(ARCH).o \
+$(SRC)/CheckTimeRanges.$(ARCH).o \
+$(SRC)/ControllerOps.$(ARCH).o \
+$(SRC)/LocalJob.$(ARCH).o \
+$(SRC)/JobOps.$(ARCH).o \
+$(SRC)/JobIDOps.$(ARCH).o \
+$(SRC)/TaskOps.$(ARCH).o
+
+cmds = \
+$(SRC)/pulse.$(ARCH).o \
+$(SRC)/status.$(ARCH).o \
+$(SRC)/flush.$(ARCH).o \
+$(SRC)/showtask.$(ARCH).o \
+$(SRC)/kill.$(ARCH).o \
+$(SRC)/delete.$(ARCH).o \
+$(SRC)/verbose.$(ARCH).o \
+$(SRC)/controller.$(ARCH).o \
+$(SRC)/controller_host.$(ARCH).o \
+$(SRC)/controller_exit.$(ARCH).o \
+$(SRC)/controller_check.$(ARCH).o \
+$(SRC)/controller_status.$(ARCH).o \
+$(SRC)/controller_jobstack.$(ARCH).o \
+$(SRC)/controller_run.$(ARCH).o \
+$(SRC)/controller_output.$(ARCH).o \
+$(SRC)/controller_pulse.$(ARCH).o \
+$(SRC)/task.$(ARCH).o \
+$(SRC)/task_host.$(ARCH).o \
+$(SRC)/task_nmax.$(ARCH).o \
+$(SRC)/task_active.$(ARCH).o \
+$(SRC)/task_macros.$(ARCH).o \
+$(SRC)/task_trange.$(ARCH).o \
+$(SRC)/task_stdout.$(ARCH).o \
+$(SRC)/task_periods.$(ARCH).o \
+$(SRC)/task_command.$(ARCH).o \
+$(SRC)/task_options.$(ARCH).o \
+$(SRC)/version.$(ARCH).o \
+$(SRC)/ipptool2book.$(ARCH).o
+
+libs = \
+$(DESTLIB)/libshell.a \
+$(DESTLIB)/libdata.a \
+$(DESTLIB)/libbasiccmd.a \
+$(DESTLIB)/libastrocmd.a \
+$(DESTLIB)/libdatacmd.a
+
+pantasks: $(BIN)/pantasks.$(ARCH)
+$(SRC)/pantasks.$(ARCH).o : $(libs)
+$(BIN)/pantasks.$(ARCH) : $(single) $(funcs) $(cmds)
+
+pantasks_client: $(BIN)/pantasks_client.$(ARCH)
+$(SRC)/pantasks_client.$(ARCH).o : $(libs)
+$(BIN)/pantasks_client.$(ARCH) : $(client)
+
+pantasks_server: $(BIN)/pantasks_server.$(ARCH)
+$(SRC)/pantasks_server.$(ARCH).o : $(libs)
+$(BIN)/pantasks_server.$(ARCH) : $(server) $(funcs) $(cmds)
+
+pantasks_client.install: $(DESTBIN)/pantasks_client
+pantasks_server.install: $(DESTBIN)/pantasks_server
+
+$(single) $(client) $(server) $(funcs) $(cmds) : $(INC)/pantasks.h
+
+install: $(DESTBIN)/pantasks $(DESTBIN)/pantasks_client $(DESTBIN)/pantasks_server help modules
+
+help: clean-help cmd.basic.help cmd.data.help cmd.astro.help pantasks.help
+
+modules: pantasks.modules
+
+.PHONY: pantasks pantasks_client pantasks_server
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/TaskOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/TaskOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/TaskOps.c	(revision 16632)
@@ -0,0 +1,675 @@
+# include "pantasks.h"
+# include <regex.h>
+
+static Task **tasks;
+static int    Ntasks;
+static int    NTASKS;
+
+/* counter marking task being visited by the run loop */
+static int   ActiveTask;
+
+/* temporary holder for a new task */
+static Task *NewTask = NULL;
+
+/* set up the task list system */
+void InitTasks () {
+  NTASKS = 20;
+  Ntasks = 0;
+  ALLOCATE (tasks, Task *, NTASKS);
+  ActiveTask = -1;
+}
+
+void FreeTasks () {
+  int i;
+  for (i = 0; i < Ntasks; i++) {
+    FreeTask (tasks[i]);
+  }
+  free (tasks);
+}
+
+/* provide a mechanism to loop over the list of tasks */
+Task *NextTask () {
+  
+  Task *task;
+
+  /* move to the next task and return it */
+  ActiveTask ++;
+  if (ActiveTask < 0) ActiveTask = 0;
+  if (ActiveTask >= Ntasks) {
+    ActiveTask = -1;
+    return (NULL);
+  }
+  task = tasks[ActiveTask];
+  return (task);
+}
+
+/* return task with given name */
+Task *FindTask (char *name) {
+
+  int i;
+
+  /* try for an exact match first */
+  for (i = 0; i < Ntasks; i++) {
+    if (!strcmp (tasks[i][0].name, name)) {
+      return (tasks[i]);
+    }
+  }
+  return (NULL);
+}  
+
+/* list known tasks */
+void ListTasks (int verbose) {
+
+  int i, j, valid, nameLength, cmdLength;
+  char *start, *stop;
+  char format[128];
+
+  gprint (GP_LOG, "\n");
+  if (Ntasks == 0) {
+    gprint (GP_LOG, " no defined tasks\n");
+    return;
+  }
+
+  /* find string lengths */
+  nameLength = cmdLength = 0;
+  for (i = 0; i < Ntasks; i++) {
+    nameLength = MAX (nameLength, strlen(tasks[i][0].name));
+    if (tasks[i][0].argv == NULL) {
+      cmdLength = MAX (nameLength, strlen("(dynamic)"));
+    } else {
+      cmdLength = MAX (nameLength, strlen(tasks[i][0].argv[0]));
+    }
+  }
+
+  gprint (GP_LOG, " Task Status\n");
+
+  snprintf (format, 128, "  AV %%-%ds %5s  %5s %5s %5s %%-%ds\n", nameLength, "Njobs", "Ngood", "Nfail", "Ntime", cmdLength);
+  gprint (GP_LOG, format, "Name", "Command");
+
+  snprintf (format, 128, "%%-%ds %%5d  %%5d %%5d %%5d %%-%ds\n", nameLength, cmdLength);
+  for (i = 0; i < Ntasks; i++) {
+    valid = CheckTimeRanges (tasks[i][0].ranges, tasks[i][0].Nranges);
+    if (verbose) gprint (GP_LOG, "\n");
+    if (tasks[i][0].active) {
+      gprint (GP_LOG, "  +");
+    } else {
+      gprint (GP_LOG, "  -");
+    }
+    if (valid) {
+      gprint (GP_LOG, "+ ");
+    } else {
+      gprint (GP_LOG, "- ");
+    }
+    if (tasks[i][0].argv == NULL) {
+      gprint (GP_LOG, format, tasks[i][0].name, tasks[i][0].Njobs, tasks[i][0].Nsuccess, tasks[i][0].Nfailure, tasks[i][0].Ntimeout, "(dynamic)");
+    } else {
+      gprint (GP_LOG, format, tasks[i][0].name, tasks[i][0].Njobs, tasks[i][0].Nsuccess, tasks[i][0].Nfailure, tasks[i][0].Ntimeout, tasks[i][0].argv[0]);
+    }
+    if (verbose) {
+      gprint (GP_LOG, "    spawn period: %f, polling period: %f, timeout period: %f\n", 
+	       tasks[i][0].exec_period, tasks[i][0].poll_period, tasks[i][0].timeout_period);
+      for (j = 0; j < tasks[i][0].Nranges; j++) {
+	switch (tasks[i][0].ranges[j].type) {
+	  case RANGE_ABS:
+	    start = ohana_sec_to_date (tasks[i][0].ranges[j].start);
+	    stop  = ohana_sec_to_date (tasks[i][0].ranges[j].stop);
+	    break;
+	  case RANGE_DAY:
+	    start = ohana_sec_to_hms (tasks[i][0].ranges[j].start);
+	    stop  = ohana_sec_to_hms (tasks[i][0].ranges[j].stop);
+	    break;
+	  case RANGE_WEEK:
+	    start = ohana_sec_to_day (tasks[i][0].ranges[j].start);
+	    stop  = ohana_sec_to_day (tasks[i][0].ranges[j].stop);
+	    break;
+	  default:
+	    abort ();
+	}
+	if (tasks[i][0].ranges[j].include) {
+	  gprint (GP_LOG, "     active : %s - %s", start, stop);
+	  if (tasks[i][0].ranges[j].Nmax) gprint (GP_LOG, " (%d of %d)", tasks[i][0].ranges[j].Nrun, tasks[i][0].ranges[j].Nmax);
+	  gprint (GP_LOG, "\n");
+	} else {
+	  gprint (GP_LOG, "     avoid  : %s - %s\n", start, stop);
+	}
+	free (start);
+	free (stop);
+      }
+      if (tasks[i][0].host == NULL) {
+	gprint (GP_LOG, "    task runs locally\n");
+	continue;
+      }
+      if (!strcasecmp(tasks[i][0].host, "ANYHOST")) {
+	gprint (GP_LOG, "    task host selected by controller\n");
+	continue;
+      }
+      if (tasks[i][0].host_required) {
+	gprint (GP_LOG, "    host %s (required)\n", tasks[i][0].host);
+      } else {
+	gprint (GP_LOG, "    host %s (desired)\n", tasks[i][0].host);
+      }
+    }
+  }
+  return;
+}
+
+/* list known tasks */
+void ListTaskStats (char *regex) {
+
+  int i, valid, nameLength;
+  char format[128];
+  regex_t preg;
+
+  gprint (GP_LOG, "\n");
+  if (Ntasks == 0) {
+    gprint (GP_LOG, " no defined tasks\n");
+    return;
+  }
+
+  if (regex != NULL) {
+    regcomp (&preg, regex, REG_EXTENDED);
+  }
+
+  /* find string lengths */
+  nameLength = 0;
+  for (i = 0; i < Ntasks; i++) {
+    nameLength = MAX (nameLength, strlen(tasks[i][0].name));
+  }
+
+  gprint (GP_LOG, " Task Statistics\n");
+
+  snprintf (format, 128, "     %%-%ds |           alljobs          |           success          |           failure          |\n", nameLength);
+  gprint (GP_LOG, format, "");
+  snprintf (format, 128, "  AV %%-%ds | Njobs   Tmin   Tave   Tmax | Njobs   Tmin   Tave   Tmax | Njobs   Tmin   Tave   Tmax |\n", nameLength);
+  gprint (GP_LOG, format, "Name");
+
+  snprintf (format, 128, "%%-%ds", nameLength);
+  for (i = 0; i < Ntasks; i++) {
+      
+    if ((regex != NULL) && regexec (&preg, tasks[i][0].name, 0, NULL, 0)) continue;
+
+    valid = CheckTimeRanges (tasks[i][0].ranges, tasks[i][0].Nranges);
+    if (tasks[i][0].active) {
+      gprint (GP_LOG, "  +");
+    } else {
+      gprint (GP_LOG, "  -");
+    }
+    if (valid) {
+      gprint (GP_LOG, "+ ");
+    } else {
+      gprint (GP_LOG, "- ");
+    }
+    if (tasks[i][0].argv == NULL) {
+      gprint (GP_LOG, format, tasks[i][0].name);
+    } else {
+      gprint (GP_LOG, format, tasks[i][0].name);
+    }
+    if (tasks[i][0].dtimeMin_alljobs < 0) {
+      gprint (GP_LOG, " | %5d %6s %6.2f %6.2f",     tasks[i][0].Njobs,    "NONE",                       tasks[i][0].dtimeAve_alljobs, tasks[i][0].dtimeMax_alljobs);
+    } else {
+      gprint (GP_LOG, " | %5d %6.2f %6.2f %6.2f",   tasks[i][0].Njobs,    tasks[i][0].dtimeMin_alljobs, tasks[i][0].dtimeAve_alljobs, tasks[i][0].dtimeMax_alljobs);
+    }      
+    if (tasks[i][0].dtimeMin_success < 0) {
+      gprint (GP_LOG, " | %5d %6s %6.2f %6.2f",     tasks[i][0].Nsuccess, "NONE",                       tasks[i][0].dtimeAve_success, tasks[i][0].dtimeMax_success);
+    } else {
+      gprint (GP_LOG, " | %5d %6.2f %6.2f %6.2f",   tasks[i][0].Nsuccess, tasks[i][0].dtimeMin_success, tasks[i][0].dtimeAve_success, tasks[i][0].dtimeMax_success);
+    }
+    if (tasks[i][0].dtimeMin_failure < 0) {
+      gprint (GP_LOG, " | %5d %6s %6.2f %6.2f |\n",   tasks[i][0].Nfailure, "NONE",                       tasks[i][0].dtimeAve_failure, tasks[i][0].dtimeMax_failure);
+    } else {
+      gprint (GP_LOG, " | %5d %6.2f %6.2f %6.2f |\n", tasks[i][0].Nfailure, tasks[i][0].dtimeMin_failure, tasks[i][0].dtimeAve_failure, tasks[i][0].dtimeMax_failure);
+    }
+  }
+  return;
+}
+
+/* list known tasks */
+void ResetTaskStats (char *regex) {
+
+  int i, nameLength;
+  regex_t preg;
+
+  if (Ntasks == 0) {
+    return;
+  }
+
+  if (regex != NULL) {
+    regcomp (&preg, regex, REG_EXTENDED);
+  }
+
+  /* find string lengths */
+  nameLength = 0;
+  for (i = 0; i < Ntasks; i++) {
+    nameLength = MAX (nameLength, strlen(tasks[i][0].name));
+  }
+
+  for (i = 0; i < Ntasks; i++) {
+      
+    if ((regex != NULL) && regexec (&preg, tasks[i][0].name, 0, NULL, 0)) continue;
+
+    tasks[i][0].Njobs = 0;
+    tasks[i][0].dtimeMin_alljobs = 0;
+    tasks[i][0].dtimeAve_alljobs = 0;
+    tasks[i][0].dtimeMax_alljobs = 0;
+
+    tasks[i][0].Nsuccess = 0;
+    tasks[i][0].dtimeMin_success = 0;
+    tasks[i][0].dtimeAve_success = 0;
+    tasks[i][0].dtimeMax_success = 0;
+
+    tasks[i][0].Nfailure = 0;
+    tasks[i][0].dtimeMin_failure = 0;
+    tasks[i][0].dtimeAve_failure = 0;
+    tasks[i][0].dtimeMax_failure = 0;
+  }
+  return;
+}
+
+/* show details of a task */
+int ShowTask (char *name) {
+
+  int i, j;
+  char *start, *stop;
+  Task *task;
+
+  task = FindTask (name);
+  if (task == NULL) {
+    gprint (GP_LOG, "task %s not found\n", name);
+    return (FALSE);
+  }
+
+  gprint (GP_LOG, "\n macro %s\n", task[0].name);
+
+  gprint (GP_LOG, "\n command: ");
+  for (i = 0; i < task[0].argc; i++) {
+    gprint (GP_LOG, "%s ", task[0].argv[i]);
+  }
+  gprint (GP_LOG, "\n\n");
+
+  gprint (GP_LOG, "\n options: ");
+  for (i = 0; i < task[0].optc; i++) {
+    gprint (GP_LOG, "%s ", task[0].optv[i]);
+  }
+  gprint (GP_LOG, "\n\n");
+
+  if (task[0].host == NULL) {
+    gprint (GP_LOG, " task runs locally\n");
+    goto periods;
+  }
+  if (!strcasecmp(task[0].host, "ANYHOST")) {
+    gprint (GP_LOG, " task host selected by controller\n");
+    goto periods;
+  }
+  if (task[0].host_required) {
+    gprint (GP_LOG, " host %s (required)\n", task[0].host);
+  } else {
+    gprint (GP_LOG, " host %s (desired)\n", task[0].host);
+  }
+
+periods:
+  gprint (GP_LOG, " time periods: exec: %f  poll: %f  timeout: %f\n", 
+	  task[0].exec_period, task[0].poll_period, task[0].timeout_period);
+
+  for (j = 0; j < tasks[i][0].Nranges; j++) {
+    switch (tasks[i][0].ranges[j].type) {
+      case RANGE_ABS:
+	start = ohana_sec_to_date (tasks[i][0].ranges[j].start);
+	stop  = ohana_sec_to_date (tasks[i][0].ranges[j].stop);
+	break;
+      case RANGE_DAY:
+	start = ohana_sec_to_hms (tasks[i][0].ranges[j].start);
+	stop  = ohana_sec_to_hms (tasks[i][0].ranges[j].stop);
+	break;
+      case RANGE_WEEK:
+	start = ohana_sec_to_day (tasks[i][0].ranges[j].start);
+	stop  = ohana_sec_to_day (tasks[i][0].ranges[j].stop);
+	break;
+      default:
+	abort ();
+    }
+    if (tasks[i][0].ranges[j].include) {
+      gprint (GP_LOG, "     active : %s - %s", start, stop);
+      if (tasks[i][0].ranges[j].Nmax) gprint (GP_LOG, " (%d of %d)", tasks[i][0].ranges[j].Nrun, tasks[i][0].ranges[j].Nmax);
+      gprint (GP_LOG, "\n");
+    } else {
+      gprint (GP_LOG, "     avoid  : %s - %s\n", start, stop);
+    }
+    free (start);
+    free (stop);
+  }
+
+  gprint (GP_LOG, "\n pre-execute macro\n");
+  ListMacro (task[0].exec);
+
+  gprint (GP_LOG, "\n timeout macro\n");
+  ListMacro (task[0].timeout);
+
+  gprint (GP_LOG, "\n crash macro\n");
+  ListMacro (task[0].crash);
+
+  gprint (GP_LOG, "\n default exit macro\n");
+  ListMacro (task[0].defexit);
+
+  for (i = 0; i < task[0].Nexit; i++) {
+    gprint (GP_LOG, "\n exit macro (status == %d)\n", atoi(task[0].exit[i][0].name));
+    ListMacro (task[0].exit[i]);
+  }
+
+  return (TRUE);
+}
+
+/* make a new named task */
+int FreeTask (Task *task) {
+  
+  int i;
+
+  if (task == NULL) return (FALSE);
+  
+  if (task[0].name != NULL) free (task[0].name);
+  if (task[0].host != NULL) free (task[0].host);
+  if (task[0].argv != NULL) {
+    for (i = 0; i < task[0].argc; i++) {
+      free (task[0].argv[i]);
+    }
+    free (task[0].argv);
+  }
+  if (task[0].optv != NULL) {
+    for (i = 0; i < task[0].optc; i++) {
+      free (task[0].optv[i]);
+    }
+    free (task[0].optv);
+  }
+  if (task[0].exec != NULL) {
+    FreeMacro (task[0].exec);
+    free (task[0].exec);
+  }
+  if (task[0].crash != NULL) {
+    FreeMacro (task[0].crash);
+    free (task[0].crash);
+  }
+  if (task[0].timeout != NULL) {
+    FreeMacro (task[0].timeout);
+    free (task[0].timeout);
+  }
+  for (i = 0; i < task[0].Nexit; i++) {
+    if (task[0].exit[i] != NULL) {
+      FreeMacro (task[0].exit[i]);
+    }
+    free (task[0].exit[i]);
+  }
+  free (task[0].exit);
+
+  if (task[0].ranges != NULL) {
+    free (task[0].ranges);
+  }
+  return (TRUE);
+}
+
+/**** new task functions ***/
+
+/* make a new named task */
+Task *CreateTask (char *name) {
+  
+  ALLOCATE (NewTask, Task, 1);
+
+  NewTask[0].name = strcreate (name);;
+
+  NewTask[0].host = NULL;
+  NewTask[0].host_required = FALSE;
+
+  NewTask[0].argc = 0;
+  NewTask[0].argv = NULL;
+
+  NewTask[0].optc = 0;
+  NewTask[0].optv = NULL;
+
+  NewTask[0].stdout_dump = NULL;
+  NewTask[0].stderr_dump = NULL;
+
+  NewTask[0].exec = NULL;
+  NewTask[0].crash = NULL;
+  NewTask[0].timeout = NULL;
+  NewTask[0].defexit = NULL;
+
+  NewTask[0].Nexit = 0;
+  NewTask[0].NEXIT = 10;
+  ALLOCATE (NewTask[0].exit, Macro *, NewTask[0].NEXIT);
+  /* don't free tasks[0].exit, keep at least 1 allocated */
+
+  NewTask[0].exec_period = 1.0;
+  NewTask[0].poll_period = 1.0;
+  NewTask[0].timeout_period = 1.0;
+
+  NewTask[0].Nranges = 0;
+  ALLOCATE (NewTask[0].ranges, TimeRange, 1);
+
+  /* init task timer (is reset by 'run') */  
+  gettimeofday (&NewTask[0].last, (void *) NULL);
+  NewTask[0].Nmax = 0;  /* default value means 'no limit' */
+
+  NewTask[0].NpendingMax = 0;  /* default value means 'no limit' */
+  NewTask[0].Npending = 0;  /* default value means 'no limit' */
+
+  NewTask[0].Njobs = 0;
+  NewTask[0].Nsuccess = 0;
+  NewTask[0].Nfailure = 0;
+  NewTask[0].Ntimeout = 0;
+
+  /* jobs timing statistics */
+  NewTask[0].dtimeAve_alljobs =  0.0;
+  NewTask[0].dtimeMin_alljobs = -1.0;
+  NewTask[0].dtimeMax_alljobs =  0.0;
+
+  NewTask[0].dtimeAve_success =  0.0;
+  NewTask[0].dtimeMin_success = -1.0;
+  NewTask[0].dtimeMax_success =  0.0;
+
+  NewTask[0].dtimeAve_failure =  0.0;
+  NewTask[0].dtimeMin_failure = -1.0;
+  NewTask[0].dtimeMax_failure =  0.0;
+
+  NewTask[0].active = TRUE;
+  return (NewTask);
+}
+
+/* remove the task from the task list */
+int RemoveTask (Task *task) {
+  
+  int i, Nt;
+
+  /* find task in task list */
+  Nt = -1;
+  for (i = 0; i < Ntasks; i++) {
+    if (task == tasks[i]) {
+      Nt = i;
+      break;
+    }
+  }
+  if (Nt == -1) {
+    gprint (GP_ERR, "programming error: task not found\n");
+    return (FALSE);
+  }
+  for (i = Nt; i < Ntasks - 1; i++) {
+    tasks[i] = tasks[i+1];
+  }
+  Ntasks --;
+  return (TRUE);
+}
+
+int ValidateTask (Task *task, int RequireStatic) {
+
+  int i, hash;
+
+  /* is a static command defined? */
+  if (task[0].argc != 0) {
+    if (task[0].argv == NULL) {
+      gprint (GP_ERR, "task command arguments not defined (programming error)\n");
+      return (FALSE);
+    }
+    return (TRUE);
+  }
+  if (RequireStatic) {
+    gprint (GP_ERR, "task command not defined\n");
+    return (FALSE);
+  }
+
+  /* no static command; dynamic command? */
+  if (task[0].exec != NULL) {
+    for (i = 0; i < task[0].exec[0].Nlines; i++) {
+      hash = TaskHash (task[0].exec[0].line[i]);
+      if (hash == TASK_COMMAND) return (TRUE);
+    }
+  }
+  gprint (GP_ERR, "task command not defined\n");
+  return (FALSE);
+}
+
+int RegisterNewTask () {
+  
+  int N;
+
+  N = Ntasks;
+  Ntasks ++;
+  if (Ntasks == NTASKS) {
+    NTASKS += 20;
+    REALLOCATE (tasks, Task *, NTASKS);
+  }
+  tasks[N] = NewTask;
+  NewTask = NULL;
+  return (TRUE);
+}
+
+int DeleteNewTask () {
+  if (NewTask != NULL) {
+    FreeTask (NewTask);
+    free (NewTask);
+    NewTask = NULL;
+  }
+  return (TRUE);
+}
+
+Task *SetNewTask (Task *task) {
+  NewTask = task;
+  return (task);
+}
+
+Task *GetNewTask () {
+  return (NewTask);
+}
+
+Task *GetActiveTask () {
+  Task *task;
+  if (ActiveTask < 0) return (NULL);
+  task = tasks[ActiveTask];
+  return (task);
+}
+
+int TaskHash (char *input) {
+  
+  int hash;
+  char *command;
+
+  hash = TASK_NONE;
+
+  command = thisword (input);
+  if (command == NULL) return (TASK_EMPTY);
+
+  if (command[0] == '#')                  hash = TASK_COMMENT;
+  if (!strcasecmp (command, "END"))       hash = TASK_END;
+  if (!strcasecmp (command, "HOST"))      hash = TASK_HOST;
+  if (!strcasecmp (command, "NMAX"))      hash = TASK_NMAX;
+  if (!strcasecmp (command, "ACTIVE"))    hash = TASK_ACTIVE;
+  if (!strcasecmp (command, "TRANGE"))    hash = TASK_TRANGE;
+  if (!strcasecmp (command, "STDOUT"))    hash = TASK_STDOUT;
+  if (!strcasecmp (command, "STDERR"))    hash = TASK_STDERR;
+  if (!strcasecmp (command, "COMMAND"))   hash = TASK_COMMAND;
+  if (!strcasecmp (command, "OPTIONS"))   hash = TASK_OPTIONS;
+  if (!strcasecmp (command, "PERIODS"))   hash = TASK_PERIODS;
+  if (!strcasecmp (command, "NPENDING"))  hash = TASK_NPENDING;
+  if (!strcasecmp (command, "TASK.EXIT")) hash = TASK_EXIT;
+  if (!strcasecmp (command, "TASK.EXEC")) hash = TASK_EXEC;
+
+  free (command);
+  return (hash);
+}
+
+/*** task timer functions ***/
+
+double GetTaskTimer (struct timeval start, int verbose) {
+
+  double dtime;
+  struct timeval now;
+  
+  gettimeofday (&now, (void *) NULL);
+  dtime = DTIME (now, start);
+  
+  if (verbose) {
+      fprintf (stderr, "tt: %d %6d  - %d %6d : %f\n", 
+	       (int) now.tv_sec, (int) now.tv_usec, 
+	       (int) start.tv_sec, (int) start.tv_usec, dtime);
+  }
+
+  return (dtime);
+}
+
+void SetTaskTimer (struct timeval *timer) {
+  gettimeofday (timer, (void *) NULL);
+}
+
+/* start the clock for all tasks */
+void InitTaskTimers () {
+
+  Task *task;
+  double isec, fsec;
+
+  while ((task = NextTask ()) != NULL) {
+    gettimeofday (&task[0].last, (void *) NULL);
+    fsec = modf (task[0].exec_period, &isec);
+    task[0].last.tv_sec -= isec;
+    task[0].last.tv_usec -= 1e6*fsec;
+ }
+}
+
+/* must call this after updating the corresponding counter */
+void UpdateTaskTimerStats (Task *task, int mode, double dtime) {
+
+  double total;
+
+  switch (mode) {
+    case TIMER_ALLJOBS:
+      total = task[0].dtimeAve_alljobs * (task[0].Njobs - 1);
+      total += dtime;
+      task[0].dtimeAve_alljobs = total / (float) task[0].Njobs;
+      if (task[0].dtimeMin_alljobs < 0) {
+	task[0].dtimeMin_alljobs = dtime;
+      } else {
+	task[0].dtimeMin_alljobs = MIN (task[0].dtimeMin_alljobs, dtime);
+      }
+      task[0].dtimeMax_alljobs = MAX (task[0].dtimeMax_alljobs, dtime);
+      break;
+    case TIMER_SUCCESS:
+      total = task[0].dtimeAve_success * (task[0].Nsuccess - 1);
+      total += dtime;
+      task[0].dtimeAve_success = total / (float) task[0].Nsuccess;
+      if (task[0].dtimeMin_success < 0) {
+	task[0].dtimeMin_success = dtime;
+      } else {
+	task[0].dtimeMin_success = MIN (task[0].dtimeMin_success, dtime);
+      }
+      task[0].dtimeMax_success = MAX (task[0].dtimeMax_success, dtime);
+      break;
+    case TIMER_FAILURE:
+      total = task[0].dtimeAve_failure * (task[0].Nfailure - 1);
+      total += dtime;
+      task[0].dtimeAve_failure = total / (float) task[0].Nfailure;
+      if (task[0].dtimeMin_failure < 0) {
+	task[0].dtimeMin_failure = dtime;
+      } else {
+	task[0].dtimeMin_failure = MIN (task[0].dtimeMin_failure, dtime);
+      }
+      task[0].dtimeMax_failure = MAX (task[0].dtimeMax_failure, dtime);
+      break;
+    default:
+      abort();
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/client_shell.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/client_shell.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/client_shell.c	(revision 16632)
@@ -0,0 +1,99 @@
+# include "opihi.h"
+
+/******************/
+int client_shell (int argc, char **argv) {
+
+  int Nbad, status;
+  char *line, *prompt, *history;
+  pid_t ppid;
+
+  general_init (&argc, argv);
+  program_init (&argc, argv);
+  startup (&argc, argv);
+  prompt = get_variable("PROMPT");
+  history = get_variable("HISTORY");
+  welcome ();
+
+  /* attempt to connect to the pantasks server (exit on failure) */
+  multicommand_InitServer ();
+
+  Nbad = 0;
+  while (1) {  /** must exit with command "exit" or "quit" */
+    if (Nbad == 10) exit (3);
+
+    line = readline (prompt);
+
+    if (line == NULL) { 
+      
+      ppid = getppid();
+      if (ppid == 1) {
+	gprint (GP_ERR, "caught parent shutdown\n");
+	exit (2);
+      }
+      if (!isatty (STDIN_FILENO)) exit (2);
+      gprint (GP_ERR, "Use \"quit\" to exit\n");
+      Nbad ++;
+      continue;
+    }
+    Nbad = 0;
+    ohana_memregister (line);
+
+    stripwhite (line);
+
+    if (*line) {
+	status = multicommand (line);
+	add_history (line);
+	append_history (1, history);
+    }
+    free (line);
+  }
+}
+
+/* 
+   startup sequence:
+
+   - general_init
+   - program_init
+   - startup (exit if non-interactive)
+   - welcome
+
+*/
+
+/* client issues and questions:
+
+- need to identify the commands to be caught by the client
+- pass each input line through the command parser first, then
+  send to server if not identified as a valid command
+- this raises the question of variables: do we parse variables
+  at the client level?  I would not think so.  what about input?
+  if the input is to be parsed by the client, but executed on the server, 
+  I'll need to re-work the input parsing system.  would be better 
+  for the server to parse the input command.  in this case, the client 
+  user needs to have access to the directories with input scripts.
+  this may be an advantage: it would allow some limitation on who can 
+  install server scripts.
+- variables, vectors and buffers: where are they valid (client or server?)
+  it seems they should all be defined locally on the server.  this makes
+  graphics plotting a server-side action as well.  this is probably easier,
+  but we do need to be careful about multiple clients trying to make plots
+  on the same window at the same time.  Exporting the window can be done 
+  for one client with the $KII variable, but could be tricky for more 
+  complex interactions
+- list of commands which clearly must be parsed by the client:
+  - quit / exit
+  - exec / !
+  - ?
+
+- i may need an alternative version of command, modified to avoid parsing the 
+  variables and vectors.  I also need an alternative version of the Init commands
+  to just list the blocked ones.
+
+- the client now executes all of the basic opihi commands, and only passes
+  through the pantasks commands.  The pantasks server interface should only
+  accept functions which immediately return, sending back the result to be
+  printed by the client.  
+
+  The server should not accept the 'task' commands from the client command-line.
+  To define and run macros or tasks on the server, these need to be added to 
+  a script which is loaded with a varient on the input command.  
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "pantasks.h"
+
+int controller_host    	PROTO((int, char **));
+int controller_exit    	PROTO((int, char **));
+int controller_status  	PROTO((int, char **));
+int controller_jobstack PROTO((int, char **));
+int controller_run     	PROTO((int, char **));
+int controller_stop    	PROTO((int, char **));
+int controller_check   	PROTO((int, char **));
+int controller_output  	PROTO((int, char **));
+int controller_pulse   	PROTO((int, char **));
+
+static Command controller_cmds[] = {
+  {1, "exit",     controller_exit,     "shutdown controller"},
+  {1, "host",     controller_host,     "define host for controller"},
+  {1, "check",    controller_check,    "check controller host/job"},
+  {1, "run",      controller_run,      "start controller operation / set run levels"},
+  {1, "stop",     controller_run,      "stop controller (no disconnect)"},
+  {1, "status",   controller_status,   "check controller status"},
+  {1, "jobstack", controller_jobstack, "check controller status"},
+  {1, "output",   controller_output,   "print controller output"},
+  {1, "pulse",    controller_pulse,    "set controller pulse"},
+};
+
+int controller (int argc, char **argv) {
+
+  int i, N, status;
+  CommandF *func;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: controller (command) ... \n");
+    return (FALSE);
+  }
+
+  if (!strcasecmp (argv[1], "help")) {
+    N = sizeof (controller_cmds) / sizeof (Command);
+
+    for (i = 0; i < N; i++) {
+      gprint (GP_LOG, "%-15s %s\n", controller_cmds[i].name, controller_cmds[i].help);
+    }
+    return (TRUE);
+  }
+
+  func = FindControllerCommand (argv[1]);
+  if (func == NULL) {
+    gprint (GP_ERR, "invalid controller command\n");
+    return (FALSE);
+  }
+
+  status = (*func)(argc - 1, argv + 1);
+  return (status);
+}
+
+CommandF *FindControllerCommand (char *cmd) {
+
+  int i, N;
+
+  N = sizeof (controller_cmds) / sizeof (Command);
+
+  for (i = 0; i < N; i++) {
+    if (!strcmp (controller_cmds[i].name, cmd)) {
+      return (controller_cmds[i].func);
+    }
+  }
+  return (NULL);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_check.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_check.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_check.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "pantasks.h"
+
+int controller_check (int argc, char **argv) {
+
+  int status;
+  char command[1024];
+  IOBuffer buffer;
+
+  if (argc != 3) goto usage;
+  if (strcasecmp (argv[1], "JOB") && 
+      strcasecmp (argv[1], "HOST")) goto usage;
+
+  /* check if controller is running */
+  status = CheckControllerStatus ();
+  if (!status) {
+    gprint (GP_LOG, "controller is not running\n");
+    return (TRUE);
+  }
+
+  sprintf (command, "check %s %s", argv[1], argv[2]);
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (command, CONTROLLER_PROMPT, &buffer);
+  if (VerboseMode()) {
+    gprint (GP_LOG, "controller command sent\n");  
+    gprint (GP_LOG, "\n Nbytes received: %d\n", buffer.Nbuffer);  
+  }
+  gwrite (buffer.buffer, 1, buffer.Nbuffer, GP_LOG);
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: controller check job (jobID)\n");
+  gprint (GP_ERR, "USAGE: controller check host (hostID)\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_exit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_exit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_exit.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "pantasks.h"
+
+int controller_exit (int argc, char **argv) {
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: controller exit TRUE\n");
+    return (FALSE);
+  }
+
+  if (strcasecmp (argv[1], "TRUE")) return (FALSE);
+
+  QuitController ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_host.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_host.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_host.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "pantasks.h"
+
+int controller_host (int argc, char **argv) {
+
+  int status;
+  char command[1024];
+  IOBuffer buffer;
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: controller host (command) (hostname)\n");
+    return (FALSE);
+  }
+
+  /* start controller connection (if needed) */
+  if (!StartController ()) {
+    gprint (GP_ERR, "failure to start pcontrol\n");
+    return (FALSE);
+  }
+
+  sprintf (command, "host %s %s", argv[1], argv[2]);
+  InitIOBuffer (&buffer, 0x100);
+
+  SerialThreadLock ();
+  status = ControllerCommand (command, CONTROLLER_PROMPT, &buffer);
+  SerialThreadUnlock ();
+
+  if (status) gwrite (buffer.buffer, 1, buffer.Nbuffer, GP_LOG);
+
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+}
+
+/* should I keep an internal host table so I can reload the 
+   hosts if the controller exits?
+
+   alternatively, that could be a user-level choice
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_jobstack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_jobstack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_jobstack.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "pantasks.h"
+
+int controller_jobstack (int argc, char **argv) {
+
+  int status;
+  char command[1024];
+  IOBuffer buffer;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: controller jobstack (jobstack)\n");
+    gprint (GP_ERR, "       (jobstack) : pending, busy, exit, crash, hung, done\n");
+    return (FALSE);
+  }
+
+  /* check if controller is running */
+  status = CheckControllerStatus ();
+  if (!status) {
+    gprint (GP_LOG, "controller is not active\n");
+    return (TRUE);
+  }
+
+  // XXX this has an error?  test this out...
+  sprintf (command, "jobstack %s", argv[2]);
+  InitIOBuffer (&buffer, 0x100);
+
+  SerialThreadLock ();
+  status = ControllerCommand (command, CONTROLLER_PROMPT, &buffer);
+  SerialThreadUnlock ();
+
+  if (status) {
+    gwrite (buffer.buffer, 1, buffer.Nbuffer, GP_LOG);
+  } else {
+    gprint (GP_LOG, "controller is not communicating\n");
+  }
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_output.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_output.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_output.c	(revision 16632)
@@ -0,0 +1,13 @@
+# include "pantasks.h"
+
+int controller_output (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: controller status\n");
+    return (FALSE);
+  }
+
+  CheckControllerOutput ();
+  PrintControllerOutput ();
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_pulse.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_pulse.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_pulse.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "pantasks.h"
+
+int controller_pulse (int argc, char **argv) {
+
+  int status;
+  char command[1024];
+  IOBuffer buffer;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: controller pulse (usec)\n");
+    return (FALSE);
+  }
+
+  /* start controller connection (if needed) */
+  if (!StartController ()) {
+    gprint (GP_ERR, "failure to start pcontrol\n");
+    return (FALSE);
+  }
+
+  sprintf (command, "pulse %d", atoi(argv[1]));
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (command, CONTROLLER_PROMPT, &buffer);
+  if (status) gwrite (buffer.buffer, 1, buffer.Nbuffer, GP_LOG);
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_run.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_run.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_run.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "pantasks.h"
+
+int controller_run (int argc, char **argv) {
+
+  int status;
+  char command[1024];
+  IOBuffer buffer;
+
+  if ((argc > 2) ||
+      get_argument (argc, argv, "help") ||
+      get_argument (argc, argv, "-h") ||
+      get_argument (argc, argv, "--help")) 
+  {
+    if (!strcmp (argv[0], "run")) {
+      gprint (GP_ERR, "USAGE: controller run [level]\n");
+      gprint (GP_ERR, "  allowed levels:\n");
+      gprint (GP_ERR, "  all (default) : manage machines, spawn jobs, harvest jobs\n");
+      gprint (GP_ERR, "  reap          : manage machines, harvest jobs\n");
+      gprint (GP_ERR, "  hosts         : manage machines, not jobs\n");
+      gprint (GP_ERR, "  none          : all stop\n");
+    } else {
+      gprint (GP_ERR, "USAGE: controller stop (immediate processing halt)\n");
+    }
+    return (FALSE);
+  }
+
+  /* check if controller is running */
+  status = CheckControllerStatus ();
+  if (!status) {
+    gprint (GP_LOG, "controller is not active\n");
+    return (TRUE);
+  }
+
+  if (argc == 1) {
+    strcpy (command, argv[0]);
+  } else {
+    sprintf (command, "run %s", argv[1]);
+  }
+
+  InitIOBuffer (&buffer, 0x100);
+  status = ControllerCommand (command, CONTROLLER_PROMPT, &buffer);
+  if (status) {
+    gwrite (buffer.buffer, 1, buffer.Nbuffer, GP_LOG);
+  } else {
+    gprint (GP_LOG, "controller is not responding\n");
+  }
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_status.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_status.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_status.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "pantasks.h"
+
+int controller_status (int argc, char **argv) {
+
+  int status;
+  char command[1024];
+  IOBuffer buffer;
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: controller status\n");
+    return (FALSE);
+  }
+
+  /* check if controller is running */
+  status = CheckControllerStatus ();
+  if (!status) {
+    gprint (GP_LOG, "controller is not active\n");
+    return (TRUE);
+  }
+
+
+  sprintf (command, "status");
+  InitIOBuffer (&buffer, 0x100);
+
+  SerialThreadLock ();
+  status = ControllerCommand (command, CONTROLLER_PROMPT, &buffer);
+  SerialThreadUnlock ();
+
+  if (status) {
+    gwrite (buffer.buffer, 1, buffer.Nbuffer, GP_LOG);
+  } else {
+    gprint (GP_LOG, "controller is not communicating\n");
+  }
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_threads.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_threads.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/controller_threads.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "pantasks.h"
+
+/** things related to CheckController **/
+
+static int CheckControllerRun = FALSE;
+
+void CheckControllerSetState (int state) {
+  CheckControllerRun = state;
+}
+int CheckControllerGetState () {
+  return (CheckControllerRun);
+}
+
+void *CheckControllerThread (void *data) {
+
+  char log_stdout[128], log_stderr[128];
+
+  gprintInit ();  // each thread needs to init the printing system
+  // define server output log files
+  if (VarConfig ("PANTASKS_SERVER_STDOUT", "%s", log_stdout) != NULL) {
+      gprintSetFileThisThread (GP_LOG, log_stdout);
+  }
+  if (VarConfig ("PANTASKS_SERVER_STDERR", "%s", log_stderr) != NULL) {
+      gprintSetFileThisThread (GP_ERR, log_stderr);
+  }
+
+  while (1) {
+
+    // check for thread suspend
+    if (!CheckControllerRun) {
+      usleep (100000); // idle if thread action is suspended
+      continue;
+    }
+
+    // one run of the task checker
+    SerialThreadLock ();
+    CheckController ();
+    CheckControllerOutput ();
+    SerialThreadUnlock ();
+    if (VerboseMode() == 2) fprintf (stderr, "C");
+    // fprintf (stderr, "**** C ****");
+    usleep (500000); // allow other threads a chance to run
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/delete.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include "pantasks.h"
+
+int delete_job (int argc, char **argv) {
+
+  Job *job;
+  int JobID;
+
+  if (argc != 3) goto usage;
+
+  if (!strcasecmp (argv[1], "job")) {
+    JobID = atoi (argv[2]);
+
+    job = FindJob (JobID);
+    if (job == NULL) {
+      gprint (GP_LOG, "job not found\n");
+      return (TRUE);
+    }
+
+    if (job[0].mode == JOB_LOCAL) {
+      if (!KillLocalJob (job)) {
+	job[0].state = JOB_HUNG;
+	if (VerboseMode()) gprint (GP_LOG, "child process %d is hung, cannot kill\n", job[0].pid);
+	return (FALSE);
+      }
+    } else {
+      if (!KillControllerJob (job)) {
+	job[0].state = JOB_HUNG;
+	if (VerboseMode()) gprint (GP_LOG, "child process %d is hung, cannot kill\n", job[0].pid);
+	return (FALSE);
+      }
+    }    
+    DeleteJob (job);
+    gprint (GP_LOG, "job removed\n");
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "task")) {
+    gprint (GP_ERR, "delete task not implemented yet\n");
+    return (FALSE);
+  }
+
+usage:
+    gprint (GP_ERR, "USAGE: delete job (JobID)\n");
+    gprint (GP_ERR, "USAGE: delete task (TaskName)\n");
+    return (FALSE);
+}
+
+/* find job from jobID, kill and delete */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/flush.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/flush.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/flush.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "pantasks.h"
+
+int flush_jobs (int argc, char **argv) {
+
+  if (argc != 2) goto usage;
+
+  if (!strcasecmp (argv[1], "jobs")) {
+    FlushJobs ();
+    return (TRUE);
+  }
+  
+usage:
+  gprint (GP_ERR, "USAGE: flush jobs\n");
+  return (FALSE);
+}
+
+/* find job from jobID, kill and delete */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/controller
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/controller	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/controller	(revision 16632)
@@ -0,0 +1,29 @@
+
+   controller (command) ...
+
+   Interact with the parallel controller 'pcontrol'.  This command
+   groups together several controller sub-commands, listed below.
+
+
+   controller host (hostname)
+
+   Define a new machine available to the parallel controller.  
+
+
+   controller check (host) (HostID)
+   controller check (job) (JobID)
+
+   Check on the status of a specific host or job known to the parallel
+   controller.
+
+
+   controller status
+
+   Query the parallel controller for its current status
+
+
+   controller output
+
+   Dump the contents of the parallel controller message buffers.
+   These are the messages from the controller itself, rather than the
+   messages generated by jobs run by the controller.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task	(revision 16632)
@@ -0,0 +1,27 @@
+
+   task (name)
+
+   Define or modify a task.  A task is defined by issuing a series of
+   task commands, listed below (see their individual help pages).  A
+   task describes the rules for constructing jobs.  At a minimum, a
+   task must include a command, defining the UNIX command to run for
+   each job.  Other task commands define optional concepts for the
+   task.  These include: 
+
+   - a macro to be run before the job is constructed (task.exec).
+   - a set of macros to be run when the job is completed (task.exit)
+   - time ranges in which the task should be run (or not) (trange) 
+   - required / desired parallel controller hosts (host)
+   - job contruction time interval (periods -exec)
+   - job polling time interval (periods -poll)
+   - job timeouts (periods -timeout)
+   - maximum number of jobs to construct
+
+   See also:
+   task.command
+   task.exit
+   task.exec
+   task.trange
+   task.nmax
+   task.host
+   task.periods
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task.command
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task.command	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task.command	(revision 16632)
@@ -0,0 +1,15 @@
+
+   command (arg0) (arg1) ...
+
+   Define the rule for constructing a job command for a task.  The
+   arguments are UNIX command and the collection of command arguments.
+   The arguments may include references to Opihi variables.  The task
+   command may be included at the top level of the task, or it may be
+   defined within the task exec macro.  In the latter case, the
+   command is constructed only when the exec macro is run, every job
+   construction interval.  Thus, the command arguments may depend on
+   the result of the exec macro operation.   
+
+   See also:
+   task
+   task.exec
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task.exec
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task.exec	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/help/task.exec	(revision 16632)
@@ -0,0 +1,17 @@
+
+   task.exec
+
+   A special macro to be executed before constructing the job command.
+   The macro is defined by commands following the 'task.exec' command,
+   ending with the word 'end'.  If the exit status of the task.exec
+   macro is FALSE, then the job is NOT constructed.  This allows the
+   construction of a job to be conditional on other, external
+   quantites.  (Note: the exit status of the macro is false if 'break'
+   is called).  The task command may be defined within the task.exec
+   macro, in which case the command is constructed only when the exec
+   macro is run, every job construction interval.  Thus, the command
+   arguments may depend on the result of the exec macro operation.
+
+   See also:
+   task
+   task.command
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "pantasks.h"
+
+int controller      PROTO((int, char **));
+int task            PROTO((int, char **));
+int task_host       PROTO((int, char **));
+int task_nmax       PROTO((int, char **));
+int task_npending   PROTO((int, char **));
+int task_active     PROTO((int, char **));
+int task_trange     PROTO((int, char **));
+int task_macros     PROTO((int, char **));
+int task_command    PROTO((int, char **));
+int task_options    PROTO((int, char **));
+int task_periods    PROTO((int, char **));
+int task_stdout     PROTO((int, char **));
+int task_stderr     PROTO((int, char **));
+int run             PROTO((int, char **));
+int stop            PROTO((int, char **));
+int halt            PROTO((int, char **));
+int flush_jobs      PROTO((int, char **));
+int pulse           PROTO((int, char **));
+int showtask        PROTO((int, char **));
+int status_sys      PROTO((int, char **));
+int kill_job        PROTO((int, char **));
+int delete_job      PROTO((int, char **));
+int verbose         PROTO((int, char **));
+int version         PROTO((int, char **));
+int ipptool2book    PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "active",     task_active,   "set the active state of a task"},
+  {1, "command",    task_command,  "define executed command for a task"},
+  {1, "controller", controller,    "controller commands"},
+  {1, "delete",     delete_job,    "delete job"},
+  {1, "halt",       halt,          "halt the scheduler (no job harvesting)"},
+  {1, "host",       task_host,     "define host machine for a task"},
+  {1, "ipptool2book", ipptool2book, "convert queue with ipptool output to book"},
+  {1, "kill",       kill_job,      "kill job"},
+  {1, "nmax",       task_nmax,     "define maximum number of jobs for a task"},
+  {1, "npending",   task_npending, "define maximum number of outstanding jobs for a task"},
+  {1, "options",    task_options,  "define optional variables associated with the job task"},
+  {1, "periods",    task_periods,  "define time scales for a task"},
+  {1, "pulse",      pulse,         "set the scheduler update period"},
+  {1, "run",        run,           "run the scheduler"},
+  {1, "flush",      flush_jobs,    "flush all jobs from the queue"},
+  {1, "showtask",   showtask,      "list a task"},
+  {1, "status",     status_sys,    "get system or task status"},
+  {1, "stderr",     task_stderr,   "define a file for the job stderr dump"},
+  {1, "stdout",     task_stdout,   "define a file for the job stdout dump"},
+  {1, "stop",       stop,          "stop the scheduler (continue job harvesting)"},
+  {1, "task",       task,          "define a schedulable task"},
+  {1, "task.exec",  task_macros,   "define pre-exec macro for a task"},
+  {1, "task.exit",  task_macros,   "define exit macros for a task"},
+  {1, "trange",     task_trange,   "define valid/invalid time periods for a task"},
+  {1, "verbose",    verbose,       "set/toggle verbose mode"},
+  {1, "version",    version,       "show version information"},
+}; 
+
+void InitPantasks () {
+  
+  int i;
+
+  InitTasks ();
+  InitJobs ();
+  InitJobIDs ();
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+}
+
+void FreePantasks () {
+  FreeTasks ();
+  FreeJobs ();
+  FreeJobIDs ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init_client.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init_client.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init_client.c	(revision 16632)
@@ -0,0 +1,26 @@
+# include "pantasks.h"
+
+int invalid         PROTO((int, char **));
+
+/* we list here commands which are not valid for the client, 
+   but represent valid pantasks commands.  these are caught 
+   by the client and sent to the 'invalid' function */
+
+static Command cmds[] = {  
+  {1, "task",       invalid,  "define a schedulable task"},
+  {1, "task.exit",  invalid,  "define exit macros for a task"},
+  {1, "task.exec",  invalid,  "define pre-exec macro for a task"},
+}; 
+
+void InitPantasksClient () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+
+}
+
+void FreePantasksClient () {
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init_server.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init_server.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/init_server.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "pantasks.h"
+
+int controller      PROTO((int, char **));
+int task            PROTO((int, char **));
+int task_host       PROTO((int, char **));
+int task_nmax       PROTO((int, char **));
+int task_npending   PROTO((int, char **));
+int task_active     PROTO((int, char **));
+int task_trange     PROTO((int, char **));
+int task_macros     PROTO((int, char **));
+int task_command    PROTO((int, char **));
+int task_options    PROTO((int, char **));
+int task_periods    PROTO((int, char **));
+int task_stdout     PROTO((int, char **));
+int task_stderr     PROTO((int, char **));
+int pulse           PROTO((int, char **));
+int flush_jobs      PROTO((int, char **));
+int status_server   PROTO((int, char **));
+int showtask        PROTO((int, char **));
+int kill_job        PROTO((int, char **));
+int delete_job      PROTO((int, char **));
+int verbose         PROTO((int, char **));
+int version         PROTO((int, char **));
+int server          PROTO((int, char **));
+int ipptool2book    PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "active",     task_active,   "set the active state of a task"},
+  {1, "command",    task_command,  "define executed command for a task"},
+  {1, "controller", controller,    "controller commands"},
+  {1, "delete",     delete_job,    "delete job"},
+  {1, "host",       task_host,     "define host machine for a task"},
+  {1, "ipptool2book", ipptool2book, "convert queue with ipptool output to book"},
+  {1, "kill",       kill_job,      "kill job"},
+  {1, "nmax",       task_nmax,     "define maximum number of jobs for a task"},
+  {1, "options",    task_options, "define optional variables associated with the job task"},
+  {1, "npending",   task_npending, "define maximum number of outstanding jobs for a task"},
+  {1, "periods",    task_periods,  "define time scales for a task"},
+  {1, "pulse",      pulse,         "set the scheduler update period"},
+  {1, "flush",      flush_jobs,    "flush all jobs from the queue"},
+  {1, "server",     server,        "server-specific commands"},
+  {1, "showtask",   showtask,      "list a task"},
+  {1, "status",     status_server, "get system status"},
+  {1, "stderr",     task_stderr,   "define a file for the job stderr dump"},
+  {1, "stdout",     task_stdout,   "define a file for the job stdout dump"},
+  {1, "task",       task,          "define a schedulable task"},
+  {1, "task.exec",  task_macros,   "define pre-exec macro for a task"},
+  {1, "task.exit",  task_macros,   "define exit macros for a task"},
+  {1, "trange",     task_trange,   "define valid/invalid time periods for a task"},
+  {1, "verbose",    verbose,       "set/toggle verbose mode"},
+  {1, "version",    version,       "show version information"},
+}; 
+
+void InitPantasksServer () {
+  
+  int i;
+
+  InitTasks ();
+  InitJobs ();
+  InitJobIDs ();
+  InitInputs ();
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+}
+
+void FreePantasksServer () {
+  FreeTasks ();
+  FreeJobs ();
+  FreeJobIDs ();
+  FreeInputs ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/input_threads.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/input_threads.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/input_threads.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "pantasks.h"
+
+/** things related to CheckInputs **/
+
+static int CheckInputsRun = TRUE;
+
+void CheckInputsSetState (int state) {
+  CheckInputsRun = state;
+}
+int CheckInputsGetState () {
+  return (CheckInputsRun);
+}
+
+void *CheckInputsThread (void *data) {
+
+  char log_stdout[128], log_stderr[128];
+
+  gprintInit ();  // each thread needs to init the printing system
+
+  // define server output log files
+  if (VarConfig ("PANTASKS_SERVER_STDOUT", "%s", log_stdout) != NULL) {
+      gprintSetFileThisThread (GP_LOG, log_stdout);
+  }
+  if (VarConfig ("PANTASKS_SERVER_STDERR", "%s", log_stderr) != NULL) {
+      gprintSetFileThisThread (GP_ERR, log_stderr);
+  }
+
+  while (1) {
+
+    // check for thread suspend
+    if (!CheckInputsRun) {
+      usleep (100000); // idle if thread action is suspended
+      continue;
+    }
+
+    // one run of the task checker
+    SerialThreadLock ();
+    CheckInputs ();
+    SerialThreadUnlock ();
+    if (VerboseMode() == 2) fprintf (stderr, "I");
+    usleep (10000); // allow other threads a chance to run
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/invalid.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/invalid.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/invalid.c	(revision 16632)
@@ -0,0 +1,8 @@
+# include "pantasks.h"
+
+int invalid (int argc, char **argv) {
+
+  gprint (GP_ERR, "%s is not valid for the pantasks client\n", argv[0]);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ipptool2book.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ipptool2book.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/ipptool2book.c	(revision 16632)
@@ -0,0 +1,249 @@
+# include "pantasks.h"
+
+# define FREEKEYS \
+  if (keys) { for (i = 0; i < Nkeys; i++) { free (keys[i]); } free (keys); } \
+  for (i = 0; i < setWordN; i++) { free (setWordList[i]); free (setWordValue[i]); } \
+  free (setWordValue); free (setWordList);
+
+// convert the named queue with ipptool metadata output into book format
+int ipptool2book (int argc, char **argv) {
+
+  int i, N, onPage, found, Unique, Nkeys, NKEYS;
+  char *line, *tmpword, *tmpvalue;
+  char pagename[512], *bookName, **keys, *p, *q;
+  char **setWordList;
+  char **setWordValue;
+  int setWordN, setWordNalloc;
+
+  Page *page = NULL;
+  Book *book = NULL;
+  Queue *queue = NULL;
+
+  /* supply additional constant words */
+  setWordN = 0;
+  setWordNalloc = 10;
+  ALLOCATE (setWordList, char *, setWordNalloc);
+  ALLOCATE (setWordValue, char *, setWordNalloc);
+  while ((N = get_argument (argc, argv, "-setword"))) {
+    remove_argument (N, &argc, argv);
+    setWordList[setWordN] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    setWordValue[setWordN] = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    setWordN ++;
+    if (setWordN >= setWordNalloc) {
+      setWordNalloc += 10;
+      REALLOCATE (setWordList, char *, setWordNalloc);
+      REALLOCATE (setWordValue, char *, setWordNalloc);
+    }      
+  }
+
+  Unique = FALSE;
+  if ((N = get_argument (argc, argv, "-uniq"))) {
+    remove_argument (N, &argc, argv);
+    Unique = TRUE;
+  }
+
+  Nkeys = 0;
+  keys = NULL;
+  if ((N = get_argument (argc, argv, "-key"))) {
+    remove_argument (N, &argc, argv);
+
+    /* parse the key (word:word:word) into constituents */
+    NKEYS = 10;
+    ALLOCATE (keys, char *, NKEYS);
+    
+    p = q = argv[N];
+    while (q != NULL) {
+      q = strchr (p, ':');
+      keys[Nkeys] = (q == NULL) ? strcreate (p) : strncreate (p, q - p);
+      p = q + 1;
+      Nkeys ++;
+      CHECK_REALLOCATE (keys, char *, NKEYS, Nkeys, 10);
+    }
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 3) {
+    gprint (GP_ERR, "USAGE: ipptool2book (queue) (book) [-uniq] [-key key[:key..]]\n");
+    FREEKEYS;
+    return (FALSE);
+  }
+
+  queue = FindQueue (argv[1]);
+  if (queue == NULL) {
+    gprint (GP_ERR, "queue %s not found\n", argv[1]);
+    FREEKEYS;
+    return (FALSE);
+  }
+    
+  book = CreateBook (argv[2]);
+
+  /* the first non-whitespace line of the queue should contain:
+     BookName MULTI
+  */
+
+  /* scan for first non-emtpy line */
+  while (TRUE) {
+    line = PopQueue (queue);
+    if (!line) {
+      FREEKEYS;
+      return (TRUE); // no output in queue - not an error?
+    }
+    stripwhite (line);
+    if (line[0] == '#') {
+      free (line);
+      continue;
+    }
+    if (*line) break;
+    free (line);
+  }
+  bookName = thisword (line);
+  tmpword = nextword (line);
+
+  if (strcmp(tmpword, "MULTI")) {
+    gprint (GP_ERR, "ERROR: missing metadata output name on first line\n");
+    free (bookName);
+    free (line);
+    FREEKEYS;
+    return FALSE;
+  }
+  if (strcmp(bookName, argv[2])) {
+    gprint (GP_ERR, "WARNING: metadata output name %s does not match expected bookname %s\n", bookName, argv[2]);
+  }
+  free (line);
+  
+  onPage = FALSE;
+  while (TRUE) {
+    line = PopQueue (queue);
+    if (!line) {
+      free (bookName);
+      if (onPage) {
+	gprint (GP_ERR, "ERROR: unterminated metadata\n");
+	FREEKEYS;
+	return (FALSE);
+      }
+      FREEKEYS;
+      return (TRUE);
+    }
+    stripwhite (line);
+    if (!*line) {
+      free (line);
+      continue;
+    }
+    if (line[0] == '#') {
+      free (line);
+      continue;
+    }
+    
+    tmpword = thisword (line);
+    if (tmpword == NULL) abort(); // should not happen if line exists
+
+    if (!onPage) {
+      if (strcmp(tmpword, bookName)) {
+	gprint (GP_ERR, "ERROR: unexpected metadata name %s\n", tmpword);
+	free (line);
+	free (tmpword);
+	free (bookName);
+	FREEKEYS;
+	return (FALSE);
+      }
+      free (tmpword);
+      tmpword = thisword (nextword (line));
+      if (strcmp(tmpword, "METADATA")) {
+	gprint (GP_ERR, "ERROR: missing METADATA tag\n");
+	free (line);
+	free (tmpword);
+	free (bookName);
+	FREEKEYS;
+	return FALSE;
+      }
+      onPage = TRUE;
+      // we don't know the page name until we load its data?
+      sprintf (pagename, "page.%03d", book[0].Npages);
+      page = CreatePage (book, pagename);
+      free (line);
+      free (tmpword);
+      continue;
+    } 
+
+    /* close out the page */
+    if (!strcmp(tmpword, "END")) {
+      // XXX set the page name based on the contents
+      free (tmpword);
+      free (line);
+
+      if (keys) {
+	memset (pagename, 0, 512);
+	for (i = 0; i < Nkeys; i++) {
+	  tmpword = BookGetWord (page, keys[i]);
+	  if (tmpword == NULL) {
+	    gprint (GP_ERR, "ERROR: missing key %s for ID\n", keys[i]);
+	    FREEKEYS;
+	    return (FALSE);
+	  }
+	  if (i > 0) strcat (pagename, ":");
+	  strcat (pagename, tmpword);
+	}
+	free (page[0].name);
+	page[0].name = strcreate (pagename);
+      }
+
+      // add the fixed words to the page
+      for (i = 0; i < setWordN; i++) {
+	BookSetWord (page, setWordList[i], setWordValue[i]);
+      }
+
+      if (Unique) {
+	/* search for an existing page with this name
+	   delete this one if one is found */
+	/* XXX don't attach this page to the book until this step is passed */	
+
+	found = FALSE;
+	for (i = 0; !found && (i < book[0].Npages); i++) {
+	  if (book[0].pages[i] == page) continue;
+	  if (!strcmp (book[0].pages[i][0].name, page[0].name)) {
+	    found = TRUE;
+	  }
+	}
+	if (found) {
+	  DeletePage (book, page);
+	}
+      }
+
+      onPage = FALSE;
+      continue;
+    }
+
+    tmpvalue = thisword (nextword(nextword(line)));
+    if (tmpvalue == NULL) {
+      gprint (GP_ERR, "ERROR: missing value for %s\n", tmpword);
+      free (tmpword);
+      free (line);
+      free (bookName);
+      FREEKEYS;
+      return (FALSE);
+    }
+    BookSetWord (page, tmpword, tmpvalue);
+    free (tmpword);
+    free (tmpvalue);
+    free (line);
+  }    
+  FREEKEYS;
+  return (FALSE);
+}
+
+/* scan through the queue lines.  these should look like:  
+
+bookName METADATA
+key type value
+key type value
+...
+END
+
+bookName METADATA
+key type value
+key type value
+...
+END
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/job.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/job.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/job.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "pantasks.h"
+
+/* this will require a bit of care: to define a job, we need
+   to specify:
+   - the command 
+     this is defined in the job command: job argv0 argv1 argv2...
+   - timeout (an option to the command)
+   - exit macros?
+     do nothing by default?
+   - stderr / stdout disposal?
+     save in a specific buffer by default?
+     send to a file?
+
+   the command can look just like the controller equivalent one:
+   job [-host host] [-timeout timeout] args...
+
+*/
+
+int job (int argc, char **argv) {
+
+  char *Host, **targv;
+  int i, N, Mode, targc, Timeout;
+  IDtype JobID;
+
+  Host = NULL;
+  Mode = PCONTROL_JOB_ANYHOST;
+  if ((N = get_argument (argc, argv, "-host"))) {
+    remove_argument (N, &argc, argv);
+    Host = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Mode = PCONTROL_JOB_WANTHOST;
+  }
+  if ((N = get_argument (argc, argv, "+host"))) {
+    if (Mode == PCONTROL_JOB_WANTHOST) {
+      gprint (GP_ERR, "ERROR: -host and +host are incompatible\n");
+      FREE (Host);
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    Host = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Mode = PCONTROL_JOB_NEEDHOST;
+  }
+  if (Host == NULL) Host = strcreate ("anyhost");
+ 
+  Timeout = 100;
+  if ((N = get_argument (argc, argv, "-timeout"))) {
+    remove_argument (N, &argc, argv);
+    Timeout = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: job [options] (arg0) (arg1) ... (argN)\n");
+    FREE (Host);
+    return (FALSE);
+  }
+  
+  targc = argc - 1;
+  ALLOCATE (targv, char *, targc);
+  for (i = 1; i < argc; i++) {
+    targv[i-1] = strcreate (argv[i]);
+  }
+
+  JobID = AddJob (Host, Mode, Timeout, targc, targv);
+  gprint (GP_LOG, "JobID: %d\n", JobID);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/job_threads.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/job_threads.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/job_threads.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include "pantasks.h"
+
+/** things related to CheckJobs **/
+
+static int CheckJobsRun = FALSE;
+
+void CheckJobsSetState (int state) {
+  CheckJobsRun = state;
+}
+int CheckJobsGetState () {
+  return (CheckJobsRun);
+}
+
+void *CheckJobsThread (void *data) {
+
+  char log_stdout[128], log_stderr[128];
+  float next_timeout;
+
+  gprintInit ();  // each thread needs to init the printing system
+
+  // define server output log files
+  if (VarConfig ("PANTASKS_SERVER_STDOUT", "%s", log_stdout) != NULL) {
+      gprintSetFileThisThread (GP_LOG, log_stdout);
+  }
+  if (VarConfig ("PANTASKS_SERVER_STDERR", "%s", log_stderr) != NULL) {
+      gprintSetFileThisThread (GP_ERR, log_stderr);
+  }
+
+  while (1) {
+
+    // check for thread suspend
+    if (!CheckJobsRun) {
+      usleep (100000); // idle if thread action is suspended
+      continue;
+    }
+
+    // one run of the task checker
+    SerialThreadLock ();
+    next_timeout = CheckJobs ();
+    SerialThreadUnlock ();
+    if (VerboseMode() == 2) fprintf (stderr, "J");
+
+    next_timeout = MIN (next_timeout, 0.1);
+    if (next_timeout > 0.001) {
+      usleep ((int)(1000000*next_timeout)); // allow other threads a chance to run
+    }      
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/kill.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/kill.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/kill.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "pantasks.h"
+
+int kill_job (int argc, char **argv) {
+
+  Job *job;
+  int JobID;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: kill (JobID)\n");
+    return (FALSE);
+  }
+  JobID = atoi (argv[1]);
+
+  job = FindJob (JobID);
+  if (job == NULL) {
+    gprint (GP_LOG, "job not found\n");
+    return (TRUE);
+  }
+
+  if (job[0].mode == JOB_LOCAL) {
+    if (!KillLocalJob (job)) {
+      job[0].state = JOB_HUNG;
+      if (VerboseMode()) gprint (GP_LOG, "child process %d is hung, cannot kill\n", job[0].pid);
+      return (FALSE);
+    }
+  } else {
+    if (!KillControllerJob (job)) {
+      job[0].state = JOB_HUNG;
+      if (VerboseMode()) gprint (GP_LOG, "child process %d is hung, cannot kill\n", job[0].pid);
+      return (FALSE);
+    }
+  }    
+  DeleteJob (job);
+  gprint (GP_LOG, "job removed\n");
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/notes.txt	(revision 16632)
@@ -0,0 +1,36 @@
+
+PanTasks Client / Server design
+
+Client
+
+client uses readline to parse the incoming commands commands are only
+validated by the client before being sent to the server:
+
+client loop:
+
+   line = readline ()
+   validate argv[0]
+   send to server
+   wait for response?
+
+Server
+
+Server does not use readline at all.  server has two threads.  first
+thread listens for commands from the clients.  how many clients?  use
+poll to wait for data?  can we manage enough clients with a single
+thread?
+
+the second thread runs the scheduler loop: this is the same background
+check that is being run by the current model on the timeouts.
+
+server loop:
+
+  check socket for new incoming client connection
+  check known clients for new messages
+    execute new command
+    send response to the client
+  run the scheduler for a single loop
+
+client / server communication is modelled after addstar client /
+server?
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks.c.in	(revision 16632)
@@ -0,0 +1,94 @@
+# include "pantasks.h"
+
+# define opihi_name "pantasks"
+# define opihi_prompt "pantasks: "
+# define opihi_description "parallel task scheduler\n"
+# define opihi_history ".pantasks"
+# define opihi_rcfile ".pantasksrc"
+
+/* program-dependent initialization */
+void program_init (int *argc, char **argv) {
+  
+  pthread_t jobsThread;
+  pthread_t tasksThread;
+  pthread_t controllerThread;
+
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitPantasks ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+  rl_event_hook = NULL;
+  rl_set_keyboard_input_timeout (1000); 
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  { 
+    char *helpdir;
+    char *modules;
+    static char *datadir = "@DATADIR@";
+    ALLOCATE (helpdir, char, strlen(datadir) + strlen("/help") + 2);
+    sprintf (helpdir, "%s/help", datadir);
+    set_str_variable ("HELPDIR", helpdir);
+    free (helpdir);
+    ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+    sprintf (modules, "%s/modules", datadir);
+    set_str_variable ("MODULES:0", modules);
+    set_int_variable ("MODULES:n", 1);
+    free (modules);
+  }
+
+  signal (SIGPIPE, gotsignal);
+  signal (SIGTSTP, gotsignal);
+  signal (SIGTTIN, gotsignal);
+
+  /* start up the background threads here */
+  pthread_create (&tasksThread,      NULL, &CheckTasksThread, 	   NULL);
+  pthread_create (&jobsThread,       NULL, &CheckJobsThread, 	   NULL);
+  pthread_create (&controllerThread, NULL, &CheckControllerThread, NULL);
+  return;
+}
+
+/* standard welcome message */
+void welcome () {
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  QuitKapa ();
+  QuitController ();
+  ConfigFree ();
+
+  FreeBasic ();
+  FreeData ();
+  FreePantasks ();
+
+  return;
+}
+
+void gotsignal (int signum) {
+  gprint (GP_ERR, "got signal : %d\n", signum);
+  return;
+}
+
+/* call to opihi shell */
+int main (int argc, char **argv) {
+  int status;
+  status = opihi (argc, argv);
+  exit (status);
+}
+
+/* pantasks runs three (or four) threads:
+   - one thread parses commands from the connected clients
+   - one thread runs the scheduler loop
+   - one thread may run the controller loop independently
+   - the main thread runs readline and accepts user input
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks_client.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks_client.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks_client.c.in	(revision 16632)
@@ -0,0 +1,78 @@
+# include "pantasks.h"
+
+# define opihi_name "pantasks client shell"
+# define opihi_prompt "pantasks: "
+# define opihi_description "parallel task scheduler\n"
+# define opihi_history ".pantasks"
+# define opihi_rcfile ".pantasksrc"
+
+/* program-dependent initialization */
+void program_init (int *argc, char **argv) {
+  
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitAstro ();
+  InitPantasksClient ();
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+
+  set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  {
+      char *helpdir;
+      char *modules;
+      static char *datadir = "@DATADIR@";
+      ALLOCATE (helpdir, char, strlen(datadir) + strlen("/help") + 2);
+      sprintf (helpdir, "%s/help", datadir);
+      set_str_variable ("HELPDIR", helpdir);
+      free (helpdir);
+      ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+      sprintf (modules, "%s/modules", datadir);
+      set_str_variable ("MODULES:0", modules);
+      set_int_variable ("MODULES:n", 1);
+      free (modules);
+  }
+
+  signal (SIGPIPE, gotsignal);
+  signal (SIGTSTP, gotsignal);
+  signal (SIGTTIN, gotsignal);
+  return;
+}
+
+/* standard welcome message */
+void welcome () {
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  QuitKapa ();
+  ConfigFree ();
+
+  FreeBasic ();
+  FreeData ();
+  FreeAstro ();
+  FreePantasksClient ();
+  return;
+}
+
+/* default signal handling */
+void gotsignal (int signum) {
+  gprint (GP_ERR, "got signal : %d\n", signum);
+  return;
+}
+
+/* call to client_shell: this opihi tool uses a slightly different
+   shell function from the standard tools */
+int main (int argc, char **argv) {
+  int status;
+  status = client_shell (argc, argv);
+  exit (status);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks_server.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks_server.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pantasks_server.c.in	(revision 16632)
@@ -0,0 +1,110 @@
+# include "pantasks.h"
+
+/* pantasks-server is not a readline program.
+   it runs three (or four) threads:
+   - one thread listens on the socket for incomming connections 
+     and performs client validation
+   - one thread parses commands from the connected clients
+   - one thread runs the scheduler loop
+   - one thread may run the controller loop independently
+   
+   * note: the client shell traps certain commands and performs them
+   locally. at a minimum: help.  perhaps: input, other I/O commands?
+*/
+
+/* program-dependent initialization */
+int main (int argc, char **argv) {
+  
+  char log_stdout[128], log_stderr[128];
+  pthread_t jobsThread;
+  pthread_t tasksThread;
+  pthread_t inputsThread;
+  pthread_t clientsThread;
+  pthread_t controllerThread;
+  int InitSocket, BindSocket;
+  SockAddress Address;
+
+  general_init (&argc, argv);
+
+  // define server output log files
+  if (VarConfig ("PANTASKS_SERVER_STDOUT", "%s", log_stdout) != NULL) {
+      gprintSetFileThisThread (GP_LOG, log_stdout);
+  }
+  if (VarConfig ("PANTASKS_SERVER_STDERR", "%s", log_stderr) != NULL) {
+      gprintSetFileThisThread (GP_ERR, log_stderr);
+  }
+
+  DefineValidIP ();
+
+  /* XXX not sure what is a good setting for this in the server */
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitData ();
+  InitPantasksServer ();
+
+  { 
+    char *modules;
+    static char *datadir = "@DATADIR@";
+    ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+    sprintf (modules, "%s/modules", datadir);
+    set_str_variable ("MODULES:0", modules);
+    set_int_variable ("MODULES:n", 1);
+    free (modules);
+  }
+
+  signal (SIGPIPE, gotsignal);
+  // signal (SIGTSTP, gotsignal);
+  // signal (SIGTTIN, gotsignal);
+  signal (SIGINT, SIG_DFL);
+
+  startup (&argc, argv);
+
+  /* start up the background threads here */
+  pthread_create (&clientsThread,    NULL, &ListenClients,    	   NULL);
+  pthread_create (&tasksThread,      NULL, &CheckTasksThread, 	   NULL);
+  pthread_create (&jobsThread,       NULL, &CheckJobsThread,  	   NULL);
+  pthread_create (&controllerThread, NULL, &CheckControllerThread, NULL);
+  pthread_create (&inputsThread,     NULL, &CheckInputsThread,     NULL);
+
+  /* in this loop, we listen for incoming connections, validate, and
+     pass them to the ListenClient thread */
+
+  /* create the listening socket */
+  InitSocket = InitServerSocket (&Address);
+  
+  InitPassword ();
+
+  while (1) {
+
+    /* wait for clients to make connection */
+    BindSocket = WaitServerSocket (InitSocket, &Address);
+    if (BindSocket == -1) continue;
+
+    /* validate : wait for password */
+    if (!CheckPassword (BindSocket)) continue;
+    
+    AddNewClient (BindSocket);
+  }
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  QuitKapa ();
+  QuitController ();
+  ConfigFree ();
+  InitBasic ();
+  InitData ();
+  InitPantasksServer ();
+  return;
+}
+
+void gotsignal (int signum) {
+  gprint (GP_ERR, "got signal : %d\n", signum);
+  return;
+}
+
+/* these are needed to resolve symbols expected by libshell.so */
+void welcome () { }
+void program_init (int *argc, char **argv) {}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pulse.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pulse.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/pulse.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "pantasks.h"
+
+int pulse (int argc, char **argv) {
+
+  int Nusec;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: pulse (microseconds)\n");
+    return (FALSE);
+  }
+
+  Nusec = atoi (argv[1]);
+  rl_set_keyboard_input_timeout (Nusec); 
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/run.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/run.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/run.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "pantasks.h"
+
+// XXX for client/server, we need to simply start or stop the
+// appropriate threads
+// with one thread for each of the major actions, this would
+// make it easy to keep the controller running and stop the 
+// scheduler (don't run CheckTasks, but run everything else 
+// until nothing is left...
+
+int run (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: run\n");
+    return (FALSE);
+  }
+
+  CheckTasksSetState (TRUE);
+  CheckControllerSetState (TRUE);
+  CheckJobsSetState (TRUE);
+
+  // InitTaskTimers ();
+  // rl_event_hook = CheckSystem;
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "pantasks.h"
+
+/* most of these are defined in cmd.basic */
+int quit            PROTO((int, char **));
+int input      	    PROTO((int, char **));
+int module     	    PROTO((int, char **));
+int server_load	    PROTO((int, char **));
+int server_run	    PROTO((int, char **));
+int server_stop	    PROTO((int, char **));
+int server_halt	    PROTO((int, char **));
+int cd              PROTO((int, char **));
+int pwd        	    PROTO((int, char **));
+int output     	    PROTO((int, char **));
+
+CommandF *FindServerCommand (char *cmd);
+
+static Command server_cmds[] = {
+  {1, "exit",   quit,   "shutdown server"},
+  {1, "quit",   quit,   "shutdown server"},
+  {1, "input",  input,  "load input file on server"},
+  {1, "module", module, "load module file on server"},
+  {1, "load",   server_load, "load input file on server"},
+  {1, "run",    server_run,  "run scheduler"},
+  {1, "stop",   server_stop, "stop scheduler"},
+  {1, "halt",   server_halt, "halt scheduler"},
+  {1, "cd",     cd,     "set local directory"},
+  {1, "pwd",    pwd,    "check local directory"},
+  {1, "output", output, "set server output destinations"},
+};
+
+int server (int argc, char **argv) {
+
+  int i, N, status;
+  CommandF *func;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: server (command) ... \n");
+    return (FALSE);
+  }
+
+  if (!strcasecmp (argv[1], "help")) {
+    N = sizeof (server_cmds) / sizeof (Command);
+
+    for (i = 0; i < N; i++) {
+      gprint (GP_LOG, "%-15s %s\n", server_cmds[i].name, server_cmds[i].help);
+    }
+    return (TRUE);
+  }
+
+  func = FindServerCommand (argv[1]);
+  if (func == NULL) {
+    gprint (GP_ERR, "invalid server command\n");
+    return (FALSE);
+  }
+
+  status = (*func)(argc - 1, argv + 1);
+  return (status);
+}
+
+CommandF *FindServerCommand (char *cmd) {
+
+  int i, N;
+
+  N = sizeof (server_cmds) / sizeof (Command);
+
+  for (i = 0; i < N; i++) {
+    if (!strcmp (server_cmds[i].name, cmd)) {
+      return (server_cmds[i].func);
+    }
+  }
+  return (NULL);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server_load.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server_load.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server_load.c	(revision 16632)
@@ -0,0 +1,18 @@
+# include "pantasks.h"
+
+int server_load (int argc, char **argv) {
+
+  char *input;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: server load (file)\n");
+    return (FALSE);
+  }
+
+  // the allocated input string is eventually freed 
+  // by the InputQueue system
+  input = strcreate (argv[1]);
+  AddNewInput (input);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server_run.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server_run.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/server_run.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "pantasks.h"
+
+int server_run (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: server run\n");
+    return (FALSE);
+  }
+
+  CheckTasksSetState (TRUE);
+  CheckJobsSetState (TRUE);
+  CheckControllerSetState (TRUE);
+  CheckInputsSetState (TRUE);
+  return (TRUE);
+}
+
+int server_stop (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: server stop\n");
+    return (FALSE);
+  }
+
+  CheckTasksSetState (FALSE);
+  // CheckJobsSetState (FALSE);
+  // CheckControllerSetState (FALSE);
+  CheckInputsSetState (FALSE);
+  return (TRUE);
+}
+
+int server_halt (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: server halt\n");
+    return (FALSE);
+  }
+
+  CheckTasksSetState (FALSE);
+  CheckJobsSetState (FALSE);
+  CheckControllerSetState (FALSE);
+  CheckInputsSetState (FALSE);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/showtask.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/showtask.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/showtask.c	(revision 16632)
@@ -0,0 +1,12 @@
+# include "pantasks.h"
+
+int showtask (int argc, char **argv) {
+
+  if (argc != 2) {
+    gprint (GP_LOG, "USAGE: showtask (task)\n");
+    return (FALSE);
+  }
+
+  ShowTask (argv[1]);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/status.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/status.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/status.c	(revision 16632)
@@ -0,0 +1,70 @@
+# include "pantasks.h"
+
+int status_sys (int argc, char **argv) {
+
+  int N;
+
+  if (get_argument (argc, argv, "-h")) goto help;
+  if (get_argument (argc, argv, "-help")) goto help;
+  if (get_argument (argc, argv, "--help")) goto help;
+
+  if ((N = get_argument (argc, argv, "-tasks"))) {
+    remove_argument (N, &argc, argv);
+    ListTasks (FALSE);
+    return (TRUE);
+  }
+
+  if ((N = get_argument (argc, argv, "-taskinfo"))) {
+    remove_argument (N, &argc, argv);
+    ListTasks (TRUE);
+    return (TRUE);
+  }
+
+  if ((N = get_argument (argc, argv, "-taskstats"))) {
+    remove_argument (N, &argc, argv);
+    if (argc == 2) {
+      ListTaskStats (argv[N]);
+    } else {
+      ListTaskStats (NULL);
+    }      
+    return (TRUE);
+  }
+
+  if ((N = get_argument (argc, argv, "-taskstatsreset"))) {
+    remove_argument (N, &argc, argv);
+    if (argc == 2) {
+      ResetTaskStats (argv[N]);
+    } else {
+      ResetTaskStats (NULL);
+    }      
+    return (TRUE);
+  }
+
+  gprint (GP_LOG, "\n");
+  if (CheckTasksGetState()) {
+    gprint (GP_LOG, " Scheduler is running\n");
+  } else {
+    if (CheckJobsGetState()) {
+      gprint (GP_LOG, " Scheduler is stopped, harvesting jobs\n");
+    } else {
+      gprint (GP_LOG, " Scheduler is stopped\n");
+    }
+  }
+  if (CheckControllerStatus()) {
+    gprint (GP_LOG, " Controller is running\n");
+  } else {
+    gprint (GP_LOG, " Controller is stopped\n");
+  }
+  ListTasks (FALSE);
+  ListJobs ();
+  return (TRUE);
+
+help:
+  gprint (GP_LOG, "USAGE: status [options]\n");
+  gprint (GP_LOG, "       (without options: over system status)\n");
+  gprint (GP_LOG, "       -tasks     : list defined tasks\n");
+  gprint (GP_LOG, "       -taskinfo  : details for tasks\n");
+  gprint (GP_LOG, "       -taskstats : processing statistics for tasks\n");
+  gprint (GP_LOG, "       -taskstatsreset : reset processing statistics for tasks\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/status_server.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/status_server.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/status_server.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "pantasks.h"
+
+int status_server (int argc, char **argv) {
+
+  int N;
+
+  if (get_argument (argc, argv, "-h")) goto help;
+  if (get_argument (argc, argv, "-help")) goto help;
+  if (get_argument (argc, argv, "--help")) goto help;
+
+  if ((N = get_argument (argc, argv, "-tasks"))) {
+    remove_argument (N, &argc, argv);
+    ListTasks (FALSE);
+    return (TRUE);
+  }
+
+  if ((N = get_argument (argc, argv, "-taskinfo"))) {
+    remove_argument (N, &argc, argv);
+    ListTasks (TRUE);
+    return (TRUE);
+  }
+
+  if ((N = get_argument (argc, argv, "-taskstats"))) {
+    remove_argument (N, &argc, argv);
+    if (argc == 2) {
+      ListTaskStats (argv[N]);
+    } else {
+      ListTaskStats (NULL);
+    }      
+    return (TRUE);
+  }
+
+  if ((N = get_argument (argc, argv, "-taskstatsreset"))) {
+    remove_argument (N, &argc, argv);
+    if (argc == 2) {
+      ResetTaskStats (argv[N]);
+    } else {
+      ResetTaskStats (NULL);
+    }      
+    return (TRUE);
+  }
+
+  gprint (GP_LOG, "\n");
+  if (CheckTasksGetState()) {
+    gprint (GP_LOG, " Scheduler is running\n");
+  } else {
+    if (CheckJobsGetState()) {
+      gprint (GP_LOG, " Scheduler is stopped, harvesting jobs\n");
+    } else {
+      gprint (GP_LOG, " Scheduler is stopped\n");
+    }
+  }
+  if (CheckControllerStatus()) {
+    gprint (GP_LOG, " Controller is running\n");
+  } else {
+    gprint (GP_LOG, " Controller is stopped\n");
+  }
+  ListTasks (FALSE);
+  ListJobs ();
+  return (TRUE);
+
+help:
+  gprint (GP_LOG, "USAGE: status [options]\n");
+  gprint (GP_LOG, "       (without options: over system status)\n");
+  gprint (GP_LOG, "       -tasks     : list defined tasks\n");
+  gprint (GP_LOG, "       -taskinfo  : details for tasks\n");
+  gprint (GP_LOG, "       -taskstats : processing statistics for tasks\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/stop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/stop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/stop.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "pantasks.h"
+
+int stop (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: stop\n");
+    return (FALSE);
+  }
+
+  CheckTasksSetState (FALSE);
+  // CheckControllerSetState (FALSE);
+  // CheckJobsSetState (FALSE);
+
+  return (TRUE);
+}
+
+int halt (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: halt\n");
+    return (FALSE);
+  }
+
+  CheckTasksSetState (FALSE);
+  CheckControllerSetState (FALSE);
+  CheckJobsSetState (FALSE);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task.c	(revision 16632)
@@ -0,0 +1,100 @@
+# include "pantasks.h"
+# define prompt "> "
+
+int task (int argc, char **argv) {
+
+  int hash;
+  int ThisList, status;
+  char *input, *outline;
+  Task *task;
+
+  if (argc != 2) goto usage;
+
+  task = FindTask (argv[1]);
+  if (task == NULL) { /**** new task ****/
+    task = CreateTask (argv[1]);
+  } else {
+    RemoveTask (task);
+    SetNewTask (task);
+  }
+  /* While a task is being defined, it is removed from the task list.  The new task is added to the task list
+     when the definition process is complete.  
+     XXX If an outstanding job has a task deleted, it will not be able to complete... */
+
+  /* read in task from appropriate source (keyboard or list) until end */
+
+  /* allowed tokens: command, host, stderr, periods, trange, nmax, task.exit, task.exec, end */
+
+  ThisList = current_list_depth();
+  while (1) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+
+    if ((ThisList == 0) && (input == (char *) NULL)) {
+      gprint (GP_ERR, "end task with 'END'\n");
+      continue;
+    }
+    if ((ThisList > 0) && (input == (char *) NULL)) {
+      gprint (GP_ERR, "missing 'END' in task definition\n");
+      input = strcreate ("end");
+    }
+    if (ThisList == 0) ohana_memregister (input);
+
+    stripwhite (input);
+    hash = TaskHash (input);
+    switch (hash) {
+
+      case TASK_EMPTY:
+      case TASK_COMMENT:
+	free (input);
+	break;
+
+      case TASK_END:
+	/* I need to add in a test here to see if all task elements 
+	   have been defined.  delete the task if not */
+	free (input);
+	/* validate the new task: all mandatory elements defined? */ 
+	if (!ValidateTask (task, FALSE)) {
+	  DeleteNewTask ();
+	  return (FALSE);
+	}
+	RegisterNewTask ();
+	return (TRUE);
+	break;
+
+      case TASK_TRANGE:
+      case TASK_NMAX:
+      case TASK_HOST:
+      case TASK_EXIT:
+      case TASK_EXEC:
+      case TASK_STDOUT:
+      case TASK_STDERR:
+      case TASK_COMMAND:
+      case TASK_OPTIONS:
+      case TASK_PERIODS:
+      case TASK_NPENDING:
+      case TASK_ACTIVE:
+	status = command (input, &outline, TRUE);
+	if (outline != NULL) free (outline);
+	/* what to do if command is invalid?
+	   if (!status) return (FALSE); */
+	break;
+
+      case TASK_NONE:
+	gprint (GP_ERR, "unknown task command %s\n", input);
+	break;
+    }
+  }
+
+usage:
+  gprint (GP_ERR, "USAGE: task -list\n");
+  gprint (GP_ERR, "USAGE: task -longlist\n");
+  gprint (GP_ERR, "USAGE: task -show (task)\n");
+  gprint (GP_ERR, "USAGE: task <name>\n");
+  gprint (GP_ERR, "  (enter commands & task functions; end with the word 'END')\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_active.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_active.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_active.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "pantasks.h"
+
+int task_active (int argc, char **argv) {
+
+  Task *task;
+
+  if (argc != 2) goto usage;
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    gprint (GP_ERR, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+
+  if (!strcasecmp (argv[1], "true")) {
+    task[0].active = TRUE;
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "false")) {
+    task[0].active = FALSE;
+    return (TRUE);
+  }
+
+  gprint (GP_ERR, "ERROR: invalid option: %s\n", argv[1]);
+  return (FALSE);
+
+usage:
+  gprint (GP_ERR, "USAGE: active (true|false)\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_command.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_command.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_command.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "pantasks.h"
+
+int task_command (int argc, char **argv) {
+
+  int i;
+  Task *task;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: command <command> <arg>. ..\n");
+    gprint (GP_ERR, "  (define command for this task)\n");
+    return (FALSE);
+  }
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    task = GetActiveTask ();
+    if (task == NULL) {
+      gprint (GP_ERR, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
+  }
+
+  /* free existing memory used by argv */
+  if (task[0].argc != 0) {
+    for (i = 0; i < task[0].argc; i++) {
+      if (task[0].argv[i] != NULL) free (task[0].argv[i]);
+    }
+    free (task[0].argv);
+  }
+
+  /* create new memory for argv */
+  task[0].argc = argc - 1;
+  ALLOCATE (task[0].argv, char *, MAX (task[0].argc, 1));
+  for (i = 0; i < task[0].argc; i++) {
+    task[0].argv[i] = strcreate (argv[i+1]);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_host.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_host.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_host.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include "pantasks.h"
+
+int task_host (int argc, char **argv) {
+
+  int N, RequiredHost;
+  Task *task;
+
+  RequiredHost = FALSE;
+  if ((N = get_argument (argc, argv, "-required"))) {
+    remove_argument (N, &argc, argv);
+    RequiredHost = TRUE;
+  }
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: host <name> [-required]\n");
+    gprint (GP_ERR, "  define host machine for this task\n");
+    gprint (GP_ERR, "  -required flags indicates controller must use this host\n");
+    gprint (GP_ERR, "  value of 'local' for host indicates process not using controller\n");
+    gprint (GP_ERR, "  value of 'anyhost' for host indicates controller may assign at will\n");
+    return (FALSE);
+  }
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    task = GetActiveTask ();
+    if (task == NULL) {
+      gprint (GP_ERR, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
+  }
+  task[0].host_required = RequiredHost;
+
+  if (task[0].host != NULL) free (task[0].host);
+  task[0].host = NULL;
+
+  if (!strcasecmp (argv[1], "LOCAL")) return (TRUE);
+
+  task[0].host = strcreate (argv[1]);
+  return (TRUE);
+}
+
+/* apparently, local is the default! */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_macros.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_macros.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_macros.c	(revision 16632)
@@ -0,0 +1,151 @@
+# include "pantasks.h"
+# define D_NLINES 100
+# define prompt "> "
+
+int task_macros (int argc, char **argv) {
+
+  int i, N, NLINES, done, depth, ThisList;
+  char *input;
+  Macro *macro;
+  Task *task;
+
+  if (!strcmp (argv[0], "task.exec") && (argc != 1)) {
+    gprint (GP_ERR, "USAGE: task.exec\n");
+    gprint (GP_ERR, "  (define pre-exec macro for this task)\n");
+    return (FALSE);
+  }
+
+  if (!strcmp (argv[0], "task.exit") && (argc != 2)) {
+    gprint (GP_ERR, "USAGE: task.exit (state)\n");
+    gprint (GP_ERR, "  (define exit state macro for this task)\n");
+    return (FALSE);
+  }
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    gprint (GP_ERR, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+
+  macro = NULL;
+
+  /*** identify which Macro in Task this particular macro goes with ***/ 
+  if (!strcmp (argv[0], "task.exec")) {
+    if (task[0].exec != NULL) {
+      FreeMacro (task[0].exec);
+      free (task[0].exec);
+    }
+    ALLOCATE (task[0].exec, Macro, 1);
+    macro = task[0].exec;
+    macro[0].name = strcreate ("exec");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit") && !strcmp (argv[1], "timeout")) {
+    if (task[0].timeout != NULL) {
+      FreeMacro (task[0].timeout);
+      free (task[0].timeout);
+    }
+    ALLOCATE (task[0].timeout, Macro, 1);
+    macro = task[0].timeout;
+    macro[0].name = strcreate ("timeout");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit") && !strcmp (argv[1], "crash")) {
+    if (task[0].crash != NULL) {
+      FreeMacro (task[0].crash);
+      free (task[0].crash);
+    }
+    ALLOCATE (task[0].crash, Macro, 1);
+    macro = task[0].crash;
+    macro[0].name = strcreate ("crash");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit") && !strcmp (argv[1], "default")) {
+    if (task[0].defexit != NULL) {
+      FreeMacro (task[0].defexit);
+      free (task[0].defexit);
+    }
+    ALLOCATE (task[0].defexit, Macro, 1);
+    macro = task[0].defexit;
+    macro[0].name = strcreate ("default");
+    goto found;
+  }
+  if (!strcmp (argv[0], "task.exit")) {	/* generic exit function */
+    for (i = 0; i < task[0].Nexit; i++) { /* find exiting exit function with same name */
+      if (!strcmp (task[0].exit[i][0].name, argv[1])) {	/*** replace this one ***/
+	FreeMacro (task[0].exit[i]);
+	free (task[0].exit[i]);
+	ALLOCATE (task[0].exit[i], Macro, 1);
+	macro = task[0].exit[i];
+	macro[0].name = strcreate (argv[1]);
+	goto found;
+      }
+    }
+    /** create a new exit status macro **/
+    N = task[0].Nexit;
+    ALLOCATE (task[0].exit[N], Macro, 1);
+    task[0].Nexit ++;
+    if (task[0].Nexit == task[0].NEXIT) {
+      task[0].NEXIT += 10;
+      REALLOCATE (task[0].exit, Macro *, task[0].NEXIT);
+    }
+    macro = task[0].exit[N];
+    macro[0].name = strcreate (argv[1]);
+    goto found;
+  }
+
+found:
+
+  macro[0].Nlines = 0;
+  NLINES = D_NLINES;
+  ALLOCATE (macro[0].line, char *, NLINES);
+
+  /* load macro lines from appropriate source (readline / list) */
+
+  depth = 0;
+  done = FALSE;
+  ThisList = current_list_depth();
+  while (!done) {
+
+    /* get the next line (from correct place) */
+    if (ThisList == 0) 
+      input = readline (prompt);
+    else 
+      input = get_next_listentry (ThisList);
+
+    if ((ThisList == 0) && (input == (char *) NULL)) {
+      gprint (GP_ERR, "end macro with 'END'\n");
+      continue;
+    }
+    if ((ThisList > 0) && (input == (char *) NULL)) {
+      gprint (GP_ERR, "missing 'END' in macro definition\n");
+      input = strcreate ("end");
+    }
+    if (ThisList == 0) ohana_memregister (input);
+
+    stripwhite (input);
+
+    /* test for new macro (or other list, in the future?) */
+    if (is_list (input)) depth ++;
+
+    /* test for end of nested list -- if not nested, END refers to this macro */
+    if (!strncasecmp (input, "END", 3)) {
+      depth --;
+      if (depth < 0) { /* we hit the last "END", macro is done */
+	free (input);
+	REALLOCATE (macro[0].line, char *, MAX (1, macro[0].Nlines));
+	return (TRUE);
+      }
+    }
+
+    if (*input) { 
+      macro[0].line[macro[0].Nlines] = input;
+      macro[0].Nlines ++;
+      if (macro[0].Nlines == NLINES - 1) {
+	NLINES += D_NLINES;
+	REALLOCATE (macro[0].line, char *, NLINES);
+      }
+    }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_nmax.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_nmax.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_nmax.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "pantasks.h"
+
+int task_nmax (int argc, char **argv) {
+
+  Task *task;
+
+  if (argc != 2) goto usage;
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    gprint (GP_ERR, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+
+  task[0].Nmax = atoi (argv[1]);
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: nmax N\n");
+  return (FALSE);
+}
+
+int task_npending (int argc, char **argv) {
+
+  Task *task;
+
+  if (argc != 2) goto usage;
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    gprint (GP_ERR, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+
+  task[0].NpendingMax = atoi (argv[1]);
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: npending N\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_options.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_options.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_options.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "pantasks.h"
+
+int task_options (int argc, char **argv) {
+
+  int i;
+  Task *task;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: options <opt>. ..\n");
+    gprint (GP_ERR, "  (define options for this task)\n");
+    return (FALSE);
+  }
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    task = GetActiveTask ();
+    if (task == NULL) {
+      gprint (GP_ERR, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
+  }
+
+  /* free existing memory used by optv */
+  if (task[0].optc != 0) {
+    for (i = 0; i < task[0].optc; i++) {
+      if (task[0].optv[i] != NULL) free (task[0].optv[i]);
+    }
+    free (task[0].optv);
+  }
+
+  /* create new memory for optv */
+  task[0].optc = argc - 1;
+  ALLOCATE (task[0].optv, char *, MAX (task[0].optc, 1));
+  for (i = 0; i < task[0].optc; i++) {
+    task[0].optv[i] = strcreate (argv[i+1]);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_periods.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_periods.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_periods.c	(revision 16632)
@@ -0,0 +1,56 @@
+# include "pantasks.h"
+
+int task_periods (int argc, char **argv) {
+
+  int N, Poll, Exec, Timeout;
+  float PollValue, ExecValue, TimeoutValue;
+  Task *task;
+
+  PollValue = 0;
+  Poll = FALSE;
+  if ((N = get_argument (argc, argv, "-poll"))) {
+    Poll = TRUE;
+    remove_argument (N, &argc, argv);
+    PollValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  ExecValue = 0;
+  Exec = FALSE;
+  if ((N = get_argument (argc, argv, "-exec"))) {
+    Exec = TRUE;
+    remove_argument (N, &argc, argv);
+    ExecValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  TimeoutValue = 0;
+  Timeout = FALSE;
+  if ((N = get_argument (argc, argv, "-timeout"))) {
+    Timeout = TRUE;
+    remove_argument (N, &argc, argv);
+    TimeoutValue = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: periods [-poll value] [-exec value] [-timeout value]\n");
+    gprint (GP_ERR, "  define time periods for this task\n");
+    return (FALSE);
+  }
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    task = GetActiveTask ();
+    if (task == NULL) {
+      gprint (GP_ERR, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
+  }
+
+  if (Poll) task[0].poll_period = PollValue;
+  if (Exec) task[0].exec_period = ExecValue;
+  if (Timeout) task[0].timeout_period = TimeoutValue;
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_stdout.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_stdout.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_stdout.c	(revision 16632)
@@ -0,0 +1,49 @@
+# include "pantasks.h"
+
+int task_stdout (int argc, char **argv) {
+
+  Task *task;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: stdout <name>\n");
+    gprint (GP_ERR, "  define dump file for job stdout for this task\n");
+    return (FALSE);
+  }
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    task = GetActiveTask ();
+    if (task == NULL) {
+      gprint (GP_ERR, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
+  }
+  if (task[0].stdout_dump != NULL) free (task[0].stdout_dump);
+  task[0].stdout_dump = strcreate (argv[1]);
+  return (TRUE);
+}
+
+int task_stderr (int argc, char **argv) {
+
+  Task *task;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: stderr <name>\n");
+    gprint (GP_ERR, "  define dump file for job stderr for this task\n");
+    return (FALSE);
+  }
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    task = GetActiveTask ();
+    if (task == NULL) {
+      gprint (GP_ERR, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
+  }
+  if (task[0].stderr_dump != NULL) free (task[0].stderr_dump);
+  task[0].stderr_dump = strcreate (argv[1]);
+  return (TRUE);
+}
+
+/* apparently, local is the default! */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_threads.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_threads.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_threads.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "pantasks.h"
+
+/** things related to CheckTasks **/
+
+static int CheckTasksRun = FALSE;
+
+void CheckTasksSetState (int state) {
+  CheckTasksRun = state;
+}
+int CheckTasksGetState () {
+  return (CheckTasksRun);
+}
+
+void *CheckTasksThread (void *data) {
+
+  float next_timeout;
+  char log_stdout[128], log_stderr[128];
+
+  gprintInit ();  // each thread needs to init the printing system
+
+  // define server output log files
+  if (VarConfig ("PANTASKS_SERVER_STDOUT", "%s", log_stdout) != NULL) {
+      gprintSetFileThisThread (GP_LOG, log_stdout);
+  }
+  if (VarConfig ("PANTASKS_SERVER_STDERR", "%s", log_stderr) != NULL) {
+      gprintSetFileThisThread (GP_ERR, log_stderr);
+  }
+
+  while (1) {
+
+    // check for thread suspend
+    if (!CheckTasksRun) {
+      usleep (100000); // idle if thread action is suspended
+      continue;
+    }
+
+    // one run of the task checker
+    SerialThreadLock ();
+    next_timeout = CheckTasks ();
+    SerialThreadUnlock ();
+    if (VerboseMode() == 2) fprintf (stderr, "T");
+
+    next_timeout = MIN (next_timeout, 0.1);
+    if (next_timeout > 0.001) {
+      usleep ((int)(1000000*next_timeout)); // allow other threads a chance to run
+    }      
+  }
+}
+
+// I sleep for a small amount of time here, based on how long until the next expected
+// timeout.  this enforces a certain granularity in the task creation, but prevents the task
+// thread from driving the load up to silly levels.
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_trange.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_trange.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/task_trange.c	(revision 16632)
@@ -0,0 +1,96 @@
+# include "pantasks.h"
+
+int task_trange (int argc, char **argv) {
+
+  int N;
+  Task *task;
+  TimeRange range;
+
+  /* reset the tranges for the current task */
+  if ((N = get_argument (argc, argv, "-reset"))) {
+    remove_argument (N, &argc, argv);
+    if (argc != 1) goto usage;
+
+    task = GetNewTask ();
+    if (task == NULL) {
+      gprint (GP_ERR, "ERROR: not defining or running a task\n");
+      return (FALSE);
+    }
+
+    task[0].Nranges = 0;
+    REALLOCATE (task[0].ranges, TimeRange, 1);
+    return (TRUE);
+  } 
+
+  range.Nmax = 0;
+  range.Nrun = 0;
+  if ((N = get_argument (argc, argv, "-nmax"))) {
+    remove_argument (N, &argc, argv);
+    range.Nmax = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* keep = true means the time range defines a valid time range
+     keep = false means the time range defines an invalid range */
+  range.include = TRUE;
+  if ((N = get_argument (argc, argv, "-exclude"))) {
+    remove_argument (N, &argc, argv);
+    range.include = FALSE;
+  }
+
+  if (argc != 3) goto usage;
+
+  task = GetNewTask ();
+  if (task == NULL) {
+    gprint (GP_ERR, "ERROR: not defining or running a task\n");
+    return (FALSE);
+  }
+
+  /* test for Mon[@HH:MM:SS] - both must match */
+  if (day_to_sec (argv[1], &range.start)) {
+    if (!day_to_sec (argv[2], &range.stop)) {
+      gprint (GP_ERR, "invalid day/time %s\n", argv[2]);
+      goto usage;
+    }
+    range.type = RANGE_WEEK;
+    goto valid;
+  }
+
+  /* allow a syntax which means something like "every hour at MM:SS"
+     this could by something like *:MM:SS ? */
+
+  /* test for HH:MM:SS */
+  if (hms_to_sec (argv[1], &range.start)) {
+    if (!hms_to_sec (argv[2], &range.stop)) {
+      gprint (GP_ERR, "invalid time %s\n", argv[2]);
+      goto usage;
+    }
+    range.type = RANGE_DAY;
+    goto valid;
+  }
+
+  /* this test does not fail sufficiently robustly for invalid inputs */
+  /* test for YYYY/MM/DD - both must match */
+  if (ohana_str_to_time (argv[1], &range.start)) {
+    if (!ohana_str_to_time (argv[2], &range.stop)) {
+      gprint (GP_ERR, "invalid date/time %s\n", argv[2]);
+      goto usage;
+    }
+    range.type = RANGE_ABS;
+    goto valid;
+  }
+  goto usage;
+
+valid:
+  N = task[0].Nranges;
+  task[0].Nranges ++;
+  REALLOCATE (task[0].ranges, TimeRange, task[0].Nranges);
+  
+  task[0].ranges[N] = range;
+  return (TRUE);
+
+usage:
+  gprint (GP_ERR, "USAGE: trange start end [-nmax N]\n");
+  gprint (GP_ERR, "USAGE: trange -reset\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/iotest.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/iotest.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/iotest.sh	(revision 16632)
@@ -0,0 +1,57 @@
+
+$BLOCK = 0
+
+macro testloop
+  queuepush stdout start
+  for i 0 5
+    echo $i
+    queueprint stdout
+  end
+end
+
+# a basic task which just runs 'echo foobar'
+task	       basic
+  command      echo foobar
+  host         local
+
+  periods      -poll 0.1
+  periods      -exec 1.0
+  periods      -timeout 20
+  npending 5
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    if ($BLOCK) break
+    queuepush stdout start
+    echo "command start"
+    queuelist
+    queueprint stdout
+    queueinit stdout
+    queuelist
+    echo "command stop"
+  end
+
+  # success
+  task.exit    0
+    $BLOCK = 1
+    echo "exit start"
+    queuelist
+    queueprint stdout
+    queueinit stdout
+    queuelist
+    echo "exit stop"
+    $BLOCK = 0
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "failure: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "timeout"
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/joberror.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/joberror.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/joberror.sh	(revision 16632)
@@ -0,0 +1,29 @@
+
+# a basic task which just runs 'echo'
+task	       basic
+  host         local
+
+  periods      -poll 0.005
+  periods      -exec 0.005
+  periods      -timeout 2
+  command      ls -l /usr/bin /tmp/foobar
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $JOB_STATUS"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/load.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/load.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/load.sh	(revision 16632)
@@ -0,0 +1,37 @@
+
+# a basic task which just runs 'sleep'
+task	       newtask
+  # command      sleep 1
+  command      echo hi
+  host         local
+
+  periods      -poll 0.01
+  periods      -exec 0.01
+  periods      -timeout 20
+  npending 5
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    # echo "create command"
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+    # echo done sleep
+    # status
+    # halt
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local.sh	(revision 16632)
@@ -0,0 +1,78 @@
+
+## a basic test of memory allocation
+
+exec rm -f tmp.txt
+verbose off
+$Npass = 0
+
+# a basic task which just runs 'echo'
+task	       basic
+  command      echo "a test line"
+  host         local
+
+  periods      -poll 0.1
+  periods      -exec 0.2
+  periods      -timeout 2
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
+macro memcheck.init
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+end
+macro memcheck
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+ # echo growth: {$endmem - $startmem}
+end
+
+macro done
+ stop
+ date -var dtime -seconds -reftime $start
+ if ($VERBOSE > 3)
+  status
+  exec wc -l tmp.txt
+ end
+
+ $answer = `wc -l tmp.txt`
+ list word -split $answer
+ if ($word:0 != $Npass) 
+   echo "missing lines in tmp.txt: $word:0"
+ end
+ if ($Npass/$dtime < 4.2) 
+   echo "tasks running too slow: {$Npass/$dtime}"
+ end
+
+ memcheck
+
+ if ($endmem - $startmem > 10)
+   $PASS = 0
+   echo "failed memcheck"
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+memcheck.init
+echo "starting memcheck"
+echo "wait a few seconds and type 'done'"
+
+run
+date -var start -seconds
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local2.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local2.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local2.sh	(revision 16632)
@@ -0,0 +1,79 @@
+
+## a basic test of memory allocation
+
+exec rm -f tmp.txt
+verbose off
+$Npass = 0
+
+# a basic task which just runs 'echo'
+task	       basic
+  command      echo "a test line"
+  host         local
+
+  periods      -poll 0.1
+  periods      -exec 0.2
+  periods      -timeout 2
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
+macro memcheck.init
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+end
+macro memcheck
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+ echo growth: {$endmem - $startmem}
+end
+
+macro done
+ stop
+ date -var dtime -seconds -reftime $start
+ if ($VERBOSE > 3)
+  status
+  exec wc -l tmp.txt
+ end
+
+ $answer = `wc -l tmp.txt`
+ list word -split $answer
+ if ($word:0 != $Npass) 
+   echo "missing lines in tmp.txt: $word:0"
+ end
+ if ($Npass/$dtime < 4.2) 
+   echo "tasks running too slow: {$Npass/$dtime}"
+ end
+
+ memcheck
+
+ if ($endmem - $startmem > 30)
+   $PASS = 0
+   echo "failed memcheck"
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+
+memcheck.init
+echo "starting memcheck"
+echo "wait a few seconds and type 'done'"
+
+run
+date -var start -seconds
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local3.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local3.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local3.sh	(revision 16632)
@@ -0,0 +1,88 @@
+
+## a basic test of memory allocation
+
+exec rm -f tmp.txt
+verbose off
+$Npass = 0
+if ($?VERBOSE == 0)
+  $VERBOSE = 4
+end
+
+# a basic task which just runs 'echo'
+task	       basic
+  command      echo "a test line"
+  host         local
+
+  periods      -poll 0.005
+  periods      -exec 0.005
+  periods      -timeout 2
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
+macro memcheck.init
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+end
+macro memcheck
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+ if ($VERBOSE > 3)
+   echo growth: {$endmem - $startmem}
+ end
+end
+
+macro done
+ stop
+ date -var dtime -seconds -reftime $start
+ if ($VERBOSE > 3)
+  status
+  exec wc -l tmp.txt
+ end
+
+ $answer = `wc -l tmp.txt`
+ list word -split $answer
+ if ($word:0 != $Npass) 
+   echo "missing lines in tmp.txt: $word:0"
+ end
+ if ($VERBOSE > 3)
+   echo "task speed: {$dtime/$Npass} sec/tasks"
+ end
+ ### this test depends on the value of periods -exec above
+ if ($dtime/$Npass > 0.010) 
+   echo "tasks running too slow: {$dtime/$Npass}"
+ end
+
+ memcheck
+
+ if ($endmem - $startmem > 30)
+   $PASS = 0
+   echo "failed memcheck"
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+
+memcheck.init
+echo "starting memcheck"
+echo "wait a few seconds and type 'done'"
+
+run
+date -var start -seconds
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local4.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local4.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local4.sh	(revision 16632)
@@ -0,0 +1,93 @@
+
+## a basic test of memory allocation
+## task.exec test
+
+exec rm -f tmp.txt
+verbose off
+$Npass = 0
+if ($?VERBOSE == 0)
+  $VERBOSE = 4
+end
+
+# a basic task which just runs 'echo'
+task	       basic
+  command      echo "a test line"
+  host         local
+
+  periods      -poll 0.005
+  periods      -exec 0.005
+  periods      -timeout 2
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    $Nrun = 1
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
+macro memcheck.init
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+end
+macro memcheck
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+ if ($VERBOSE > 3)
+   echo growth: {$endmem - $startmem}
+ end
+end
+
+macro done
+ stop
+ date -var dtime -seconds -reftime $start
+ if ($VERBOSE > 3)
+  status
+  exec wc -l tmp.txt
+ end
+
+ $answer = `wc -l tmp.txt`
+ list word -split $answer
+ if ($word:0 != $Npass) 
+   echo "missing lines in tmp.txt: $word:0"
+ end
+ if ($VERBOSE > 3)
+   echo "task speed: {$dtime/$Npass} sec/tasks"
+ end
+ ### this test depends on the value of periods -exec above
+ if ($dtime/$Npass > 0.010) 
+   echo "tasks running too slow: {$dtime/$Npass}"
+ end
+
+ memcheck
+
+ if ($endmem - $startmem > 30)
+   $PASS = 0
+   echo "failed memcheck"
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+
+memcheck.init
+echo "starting memcheck"
+echo "wait a few seconds and type 'done'"
+
+run
+date -var start -seconds
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local5.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local5.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local5.sh	(revision 16632)
@@ -0,0 +1,93 @@
+
+## a basic test of memory allocation
+## dynamic command
+
+exec rm -f tmp.txt
+verbose off
+$Npass = 0
+if ($?VERBOSE == 0)
+  $VERBOSE = 4
+end
+
+# a basic task which just runs 'echo'
+task	       basic
+  host         local
+
+  periods      -poll 0.005
+  periods      -exec 0.005
+  periods      -timeout 2
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    $Nrun = 1
+    command echo "$Npass : test line"
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
+macro memcheck.init
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+end
+macro memcheck
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+ if ($VERBOSE > 3)
+   echo growth: {$endmem - $startmem}
+ end
+end
+
+macro done
+ stop
+ date -var dtime -seconds -reftime $start
+ if ($VERBOSE > 3)
+  status
+  exec wc -l tmp.txt
+ end
+
+ $answer = `wc -l tmp.txt`
+ list word -split $answer
+ if ($word:0 != $Npass) 
+   echo "missing lines in tmp.txt: $word:0"
+ end
+ if ($VERBOSE > 3)
+   echo "task speed: {$dtime/$Npass} sec/tasks"
+ end
+ ### this test depends on the value of periods -exec above
+ if ($dtime/$Npass > 0.010) 
+   echo "tasks running too slow: {$dtime/$Npass}"
+ end
+
+ memcheck
+
+ if ($endmem - $startmem > 30)
+   $PASS = 0
+   echo "failed memcheck"
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+
+memcheck.init
+echo "starting memcheck"
+echo "wait a few seconds and type 'done'"
+
+run
+date -var start -seconds
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local6.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local6.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local6.sh	(revision 16632)
@@ -0,0 +1,94 @@
+
+## a basic test of memory allocation
+## test of 'options'
+
+exec rm -f tmp.txt
+verbose off
+$Npass = 0
+if ($?VERBOSE == 0)
+  $VERBOSE = 4
+end
+
+# a basic task which just runs 'echo'
+task	       basic
+  host         local
+
+  periods      -poll 0.005
+  periods      -exec 0.005
+  periods      -timeout 2
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    $Nrun = 1
+    options "test options line"
+    command echo "$Npass : test line"
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
+macro memcheck.init
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+end
+macro memcheck
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+ if ($VERBOSE > 3)
+   echo growth: {$endmem - $startmem}
+ end
+end
+
+macro done
+ stop
+ date -var dtime -seconds -reftime $start
+ if ($VERBOSE > 3)
+  status
+  exec wc -l tmp.txt
+ end
+
+ $answer = `wc -l tmp.txt`
+ list word -split $answer
+ if ($word:0 != $Npass) 
+   echo "missing lines in tmp.txt: $word:0"
+ end
+ if ($VERBOSE > 3)
+   echo "task speed: {$dtime/$Npass} sec/tasks"
+ end
+ ### this test depends on the value of periods -exec above
+ if ($dtime/$Npass > 0.010) 
+   echo "tasks running too slow: {$dtime/$Npass}"
+ end
+
+ memcheck
+
+ if ($endmem - $startmem > 30)
+   $PASS = 0
+   echo "failed memcheck"
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+
+memcheck.init
+echo "starting memcheck"
+echo "wait a few seconds and type 'done'"
+
+run
+date -var start -seconds
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local7.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local7.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/local7.sh	(revision 16632)
@@ -0,0 +1,127 @@
+
+## a basic test of memory allocation
+## test of 'exec failure'
+
+exec rm -f tmp.txt
+verbose off
+$Npass = 0
+$Ntry = 0
+if ($?VERBOSE == 0)
+  $VERBOSE = 4
+end
+
+# a basic task which just runs 'echo'
+task	       basic
+  host         local
+
+  periods      -poll 0.005
+  periods      -exec 0.005
+  periods      -timeout 2
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    $Ntry ++
+    if ($Ntry > -1) break
+
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+    echo "this is a line in the task exec code"
+
+    command echo "$Npass : test line"
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
+
+macro memcheck.init
+ list word -x "ps -p $PID -o rss"
+ $startmem = $word:1
+end
+macro memcheck
+ list word -x "ps -p $PID -o rss"
+ $endmem = $word:1
+ if ($VERBOSE > 3)
+   echo growth: {$endmem - $startmem}
+ end
+end
+
+macro done
+ stop
+ date -var dtime -seconds -reftime $start
+ if ($VERBOSE > 3)
+  status
+ end
+
+ # this task generates no output files
+ if ($VERBOSE > 3)
+   echo "task test speed: {$dtime/$Ntry} sec/tasks"
+ end
+ ### this test depends on the value of periods -exec above
+ if ($dtime/$Ntry > 0.010) 
+   echo "tasks tests running too slow: {$dtime/$Ntry}"
+ end
+
+ memcheck
+
+ if ($endmem - $startmem > 30)
+   $PASS = 0
+   echo "failed memcheck"
+   echo "growth: {$endmem-$startmem}"
+   echo "kB/loop: {($endmem-$startmem)/10000}"
+ end
+end
+
+
+memcheck.init
+echo "starting memcheck"
+echo "wait a few seconds and type 'done'"
+
+run
+date -var start -seconds
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep.sh	(revision 16632)
@@ -0,0 +1,34 @@
+
+# a basic task which just runs 'sleep'
+task	       basic
+  command      sleep 10
+  host         local
+
+  periods      -poll 0.1
+  periods      -exec 0.2
+  periods      -timeout 20
+  npending 5
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    echo "create command"
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+    echo done sleep
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep2.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep2.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep2.sh	(revision 16632)
@@ -0,0 +1,39 @@
+
+$hostname = `hostname`
+
+controller exit true
+controller host add $hostname
+
+# a basic task which just runs 'sleep'
+task	       basic
+  command      sleep 1
+  host         anyhost
+
+  periods      -poll 0.01
+  periods      -exec 0.02
+  periods      -timeout 20
+  npending 100
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    # echo "create command"
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+    # echo done sleep
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep3.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep3.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/test/sleep3.sh	(revision 16632)
@@ -0,0 +1,47 @@
+
+$hostname = `hostname`
+
+controller exit true
+controller host add po02
+controller host add po03
+controller host add po04
+controller host add po05
+controller host add po06
+controller host add po07
+controller host add po08
+controller host add po09
+controller host add po10
+
+# a basic task which just runs 'sleep'
+task	       basic
+  command      sleep 1
+  host         anyhost
+
+  periods      -poll 0.01
+  periods      -exec 0.02
+  periods      -timeout 20
+  npending 100
+  
+  stdout tmp.txt
+  stderr tmp.txt
+
+  task.exec
+    # echo "create command"
+  end
+
+  # success
+  task.exit    0
+    $Npass ++
+    # echo done sleep
+  end
+
+  # default exit status
+  task.exit    default
+    echo       "basic: exit status: $EXIT"
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "basic: timeout"
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/thread_locks.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/thread_locks.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/thread_locks.c	(revision 16632)
@@ -0,0 +1,14 @@
+# include "pantasks.h"
+
+/* this mutex is used by the serialized threads */
+
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+
+void SerialThreadLock () {
+    pthread_mutex_lock (&mutex);
+}
+
+void SerialThreadUnlock () {
+    pthread_mutex_unlock (&mutex);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/verbose.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/verbose.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/verbose.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "pantasks.h"
+
+static int VERBOSE = FALSE;
+
+int verbose (int argc, char **argv) {
+
+  if (argc == 1) {
+    if (VERBOSE) {
+      gprint (GP_LOG, "verbose mode ON\n");
+    } else {
+      gprint (GP_LOG, "verbose mode OFF\n");
+    }
+    return (TRUE);
+  }
+
+  if (argc == 2) {
+    if (!strcasecmp (argv[1], "ON")) {
+      VERBOSE = TRUE;
+      return (TRUE);
+    }
+    if (!strcasecmp (argv[1], "OFF")) {
+      VERBOSE = FALSE;
+      return (TRUE);
+    }
+    if (!strcasecmp (argv[1], "THREADS")) {
+      VERBOSE = 2;
+      return (TRUE);
+    }
+    if (!strcasecmp (argv[1], "TOGGLE")) {
+      VERBOSE = ~VERBOSE;
+      return (TRUE);
+    }
+  }
+
+  gprint (GP_ERR, "USAGE: verbose (on/off/threads/toggle)\n");
+  return (FALSE);
+}
+
+int VerboseMode () {
+  return (VERBOSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pantasks/version.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "pantasks.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+int version (int argc, char **argv) {
+
+  char *tmp;
+
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "pantasks version: %s\n", (tmp = strip_version (name))); free (tmp);
+
+  gprint (GP_LOG, "opihi version: %s\n", (tmp = strip_version (opihi_version()))); free (tmp);
+  gprint (GP_LOG, "ohana version: %s\n", (tmp = strip_version (ohana_version()))); free (tmp);
+  gprint (GP_LOG, "gfits version: %s\n", (tmp = strip_version (gfits_version()))); free (tmp);
+
+  gprint (GP_LOG, "compiled on %s %s\n", __DATE__, __TIME__);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/ChildOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/ChildOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/ChildOps.c	(revision 16632)
@@ -0,0 +1,145 @@
+# include "pclient.h"
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <unistd.h>
+// #include <stropts.h>
+
+static int Nbad = 0;
+static struct timeval last = {0, 0};
+
+int InitChild () {
+
+  ChildPID         = 0;                /** current child PID **/
+  ChildStatus      = PCLIENT_NONE;     /** current status of child **/
+  ChildExitStatus  = 0;                /** recent exit status of child **/
+  
+  child_stdin_fd[0]  = 0;
+  child_stdin_fd[1]  = 0;
+  child_stdout_fd[0] = 0;
+  child_stdout_fd[1] = 0;
+  child_stderr_fd[0] = 0;
+  child_stderr_fd[1] = 0;
+
+  InitIOBuffer (&child_stdout, 1024);
+  InitIOBuffer (&child_stderr, 1024);
+  return (TRUE);
+}
+
+int FreeChild () {
+
+  FreeIOBuffer (&child_stdout);
+  FreeIOBuffer (&child_stderr);
+  return (TRUE);
+}
+
+int CheckChild () {
+
+  int Nread;
+  double dtime;
+  struct timeval now;
+
+  /* runaway test - if pcontrol is killed, pclient starts running away.  this test is a bit
+     dangerous: the choice of dtime probably depends on the processor and the value provided to
+     pclient.c:rl_set_keyboard_input_timeout (1000); note that we cannot use getppid == 1 as a test
+     because the parent of pclient is the ssh process on the pclient host, not pcontrol.  in any
+     case, the opihi shell catches if the ssh dies using getppid
+   */
+  gettimeofday (&now, (void *) NULL);
+  dtime = 1e6*DTIME (now, last);
+  if (dtime < 50) {
+    Nbad ++;
+    if (Nbad > 100) {
+      gprint (GP_ERR, "serious IO error\n");
+      abort ();
+    }
+  }
+  if (dtime > 950) Nbad = 0;
+  last = now;
+
+  CheckChildStatus ();
+  
+  /* read stdout buffer */
+  Nread = ReadtoIOBuffer (&child_stdout, child_stdout_fd[0]);
+  switch (Nread) {
+    case -2:  /* error in read (programming error?  system level error?) */
+      gprint (GP_ERR, "serious IO error\n");
+      abort ();
+    case -1:  /* no data in pipe */
+      break;
+    case 0:   /* pipe is closed */
+      /** change child state? **/
+      break;
+    default:  /* data in pipe */
+      break;
+  }
+  
+  /* read stderr buffer */
+  Nread = ReadtoIOBuffer (&child_stderr, child_stderr_fd[0]);
+  switch (Nread) {
+    case -2:  /* error in read (programming error?  system level error?) */
+      gprint (GP_ERR, "serious IO error\n");
+      abort ();
+    case -1:  /* no data in pipe */
+      break;
+    case 0:   /* pipe is closed */
+      /** change child state? **/
+      break;
+    default:  /* data in pipe */
+      break;
+  }
+  return (TRUE);
+}
+
+void CheckChildStatus () {
+
+  int result, waitstatus;
+
+  if (ChildStatus != PCLIENT_BUSY) return;
+
+  /* check current child status */
+  result = waitpid (ChildPID, &waitstatus, WNOHANG);
+  switch (result) {
+    case -1:  /* error with waitpid */
+      switch (errno) {
+	case ECHILD:
+	  gprint (GP_ERR, "unknown PID, not a child proc\n");
+	  gprint (GP_ERR, "did process already exit?  programming error?\n");
+	  ChildStatus = PCLIENT_NONE;
+	  break;
+	case EINVAL:
+	  gprint (GP_ERR, "error EINVAL (waitpid): programming error\n");
+	  exit (1);
+	case EINTR:
+	  gprint (GP_ERR, "error EINTR (waitpid): programming error\n");
+	  exit (1);
+	default:
+	  gprint (GP_ERR, "unknown error for waitpid (%d): programming error\n", errno);
+	  exit (1);
+      }
+      break;
+      
+    case 0:  /* process not exited */
+      ChildStatus = PCLIENT_BUSY;
+      break;
+
+    default:
+      if (result != ChildPID) {
+	gprint (GP_ERR, "waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, ChildPID);
+	exit (1);
+      }
+      
+      if (WIFEXITED(waitstatus)) {
+	ChildStatus = PCLIENT_EXIT;
+	ChildExitStatus = WEXITSTATUS(waitstatus);
+      }
+      if (WIFSIGNALED(waitstatus)) {
+	ChildStatus = PCLIENT_CRASH;
+	ChildExitStatus = WTERMSIG(waitstatus);
+      }
+      if (WIFSTOPPED(waitstatus)) {
+	gprint (GP_ERR, "waitpid returns 'stopped': programming error\n");
+	exit (1);
+      }
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/Makefile	(revision 16632)
@@ -0,0 +1,46 @@
+default: pclient
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SDIR    =       $(HOME)/pclient
+DATA    =       $(DESTDATA)/pclient
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+LIBS1         = -lbasiccmd -lshell -ldata 
+LIBS2         = -ldvo -lkapa -lFITS -lohana
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(LIBS1) $(LIBS2) $(BASE_LDFLAGS)
+
+# pclient user commands and support functions ########################
+funcs = \
+$(SDIR)/init.$(ARCH).o \
+$(SDIR)/pclient.$(ARCH).o \
+$(SDIR)/ChildOps.$(ARCH).o \
+
+cmds = \
+$(SDIR)/job.$(ARCH).o \
+$(SDIR)/reset.$(ARCH).o \
+$(SDIR)/check.$(ARCH).o \
+$(SDIR)/status.$(ARCH).o \
+$(SDIR)/stdout.$(ARCH).o  \
+$(SDIR)/version.$(ARCH).o
+
+libs = \
+$(DESTLIB)/libbasiccmd.a \
+$(DESTLIB)/libshell.a \
+$(DESTLIB)/libdata.a
+
+pclient: $(BIN)/pclient.$(ARCH)
+$(SRC)/pclient.$(ARCH).o : $(libs)
+$(BIN)/pclient.$(ARCH)   : $(funcs) $(cmds)
+
+install: $(DESTBIN)/pclient help
+
+help: clean-help cmd.basic.help pclient.help
+
+.PHONY: pclient
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/check.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/check.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/check.c	(revision 16632)
@@ -0,0 +1,9 @@
+# include "pclient.h"
+
+int check (int argc, char **argv) {
+
+  /* force a check */
+  CheckChild ();
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/help/job
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/help/job	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/help/job	(revision 16632)
@@ -0,0 +1,1 @@
+0
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/init.c	(revision 16632)
@@ -0,0 +1,33 @@
+# include "opihi.h"
+
+int job	            PROTO((int, char **));
+int reset           PROTO((int, char **));
+int check           PROTO((int, char **));
+int status	    PROTO((int, char **));
+int stdout_pclient  PROTO((int, char **));
+int stderr_pclient  PROTO((int, char **));
+int version         PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "job",       job,      "start job"},
+  {1, "reset",     reset,    "reset job"},
+  {1, "check",     check,    "check job"},
+  {1, "status",    status,   "check job status"},
+  {1, "stdout",    stdout_pclient,   "get stdout buffer"},
+  {1, "stderr",    stderr_pclient,   "get stderr buffer"},
+  {1, "version",   version,      "show version information"},
+}; 
+
+void InitPclient () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+  InitChild ();
+}
+
+void FreePclient () {
+  FreeChild ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/job.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/job.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/job.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "pclient.h"
+
+int job (int argc, char **argv) {
+
+  int i, pid, status;
+  char **targv;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: job (arg0) (arg1) ... (argN)\n");
+    gprint (GP_LOG, "STATUS %d\n", -2);
+    return (FALSE);
+  }
+  
+  if (ChildStatus != PCLIENT_NONE) {
+    gprint (GP_ERR, "need to clear existing child\n");
+    gprint (GP_LOG, "STATUS %d\n", -3);
+    return (FALSE);
+  }
+
+  if (pipe (child_stdin_fd)  < 0) goto pipe_error;
+  if (pipe (child_stdout_fd) < 0) goto pipe_error;
+  if (pipe (child_stderr_fd) < 0) goto pipe_error;
+
+  /* need to define arg list with NULL termination */
+  ALLOCATE (targv, char *, argc);
+  for (i = 1; i < argc; i++) {
+    targv[i-1] = strcreate (argv[i]);
+  }
+  targv[i-1] = 0;
+
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    /* gprint (GP_ERR, "starting child process %s...\n", targv[0]); */
+
+    /* close the other ends of the pipes */
+    close (child_stdin_fd[1]);
+    close (child_stdout_fd[0]);
+    close (child_stderr_fd[0]);
+
+    /* tie our ends of the pipes to stdin, stdout, stderr */
+    dup2 (child_stdin_fd[0],  STDIN_FILENO);
+    dup2 (child_stdout_fd[1], STDOUT_FILENO);
+    dup2 (child_stderr_fd[1], STDERR_FILENO);
+
+    /* set all three unblocking */
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    /* exec job */ 
+    status = execvp (targv[0], targv); 
+    gprint (GP_ERR, "error starting child process: %d\n", status);
+    exit (1);
+  }
+
+  /* free temporary arg list */
+  for (i = 0; i < argc - 1; i++) {
+    free (targv[i]);
+  }
+  free (targv);
+
+  /* close the other ends of the pipes */
+  close (child_stdin_fd[0]);
+  close (child_stdout_fd[1]);
+  close (child_stderr_fd[1]);
+
+  /* make the pipes non-blocking */
+  fcntl (child_stdin_fd[1],  F_SETFL, O_NONBLOCK);
+  fcntl (child_stdout_fd[0], F_SETFL, O_NONBLOCK);
+  fcntl (child_stderr_fd[0], F_SETFL, O_NONBLOCK);
+  
+  ChildStatus = PCLIENT_BUSY;
+  ChildPID = pid;
+
+  gprint (GP_LOG, "STATUS %d\n", ChildPID);
+  return (TRUE);
+
+pipe_error:
+  perror ("pipe error:");
+  if (child_stdin_fd[0]  != 0) close (child_stdin_fd[0]);
+  if (child_stdin_fd[1]  != 0) close (child_stdin_fd[1]);
+  if (child_stdout_fd[0] != 0) close (child_stdout_fd[0]);
+  if (child_stdout_fd[1] != 0) close (child_stdout_fd[1]);
+  if (child_stderr_fd[0] != 0) close (child_stderr_fd[0]);
+  if (child_stderr_fd[1] != 0) close (child_stderr_fd[1]);
+
+  gprint (GP_LOG, "STATUS %d\n", -1);
+  return (FALSE);
+}
+
+/* possible responses:
+
+STATUS -1 - pipe error
+STATUS -2 - syntax error
+STATUS -3 - existing child
+STATUS >0 - success (PID)
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/notes.txt	(revision 16632)
@@ -0,0 +1,17 @@
+
+pclient special commands:
+
+ job 
+
+ reset
+
+ check
+
+ status
+
+ stdout
+
+ stderr
+
+- communication with pclient should search for the pclient prompt:
+  pclient:
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/outline.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/outline.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/outline.txt	(revision 16632)
@@ -0,0 +1,12 @@
+
+init stage:
+
+  - set child 
+
+readline loop:
+
+  - wait for commands
+
+
+
+  
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/pclient.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/pclient.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/pclient.c.in	(revision 16632)
@@ -0,0 +1,79 @@
+# include "pclient.h"
+
+# define opihi_name "PCLIENT"
+# define opihi_prompt "pclient: "
+# define opihi_description "pcontrol client shell\n"
+# define opihi_history ""
+# define opihi_rcfile ".pcontrolrc"
+
+void dummy_prep_term (int flag) {
+}
+
+/* program-dependent initialization */
+void program_init (int *argc, char **argv) {
+  
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitPclient ();
+
+  rl_prep_term_function = dummy_prep_term;
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+  rl_event_hook = CheckChild;
+  rl_set_keyboard_input_timeout (1000); 
+  /* 1 ms seems to be the minimum valid number */
+
+  // set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  {
+    char *helpdir;
+    char *modules;
+    static char *datadir = "@DATADIR@";
+    ALLOCATE (helpdir, char, strlen(datadir) + strlen("/help") + 2);
+    sprintf (helpdir, "%s/help", datadir);
+    set_str_variable ("HELPDIR", helpdir);
+    free (helpdir);
+    ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+    sprintf (modules, "%s/modules", datadir);
+    set_str_variable ("MODULES:0", modules);
+    set_int_variable ("MODULES:n", 1);
+    free (modules);
+  }
+
+  /* ignore the history file.  to change this, see, eg, mana.c */
+  signal (SIGPIPE, gotsignal);
+  signal (SIGTSTP, gotsignal);
+  signal (SIGTTIN, gotsignal);
+  return;
+}
+
+/* standard welcome message */
+void welcome () {
+  gprint (GP_ERR, "\n");
+  gprint (GP_ERR, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  ConfigFree ();
+  FreeBasic ();
+  FreePclient ();
+  return;
+}
+
+void gotsignal (int signum) {
+  gprint (GP_ERR, "got signal : %d\n", signum);
+  return;
+}
+
+/* call to opihi shell */
+int main (int argc, char **argv) {
+  int status;
+  status = opihi (argc, argv);
+  exit (status);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/reset.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/reset.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/reset.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "pclient.h"
+
+int reset (int argc, char **argv) {
+
+  int i, result, waitstatus;
+  struct timespec request, remain;
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: reset\n");
+    gprint (GP_LOG, "STATUS -1\n");
+    return (FALSE);
+  }
+  
+  if (ChildStatus == PCLIENT_NONE) {
+    gprint (GP_ERR, "no child process, cannot reset\n");
+    gprint (GP_LOG, "STATUS 2\n");
+    return (TRUE);
+  }
+
+  /* avoid blocking on waitpid, test every 100 usec, up to 50 msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 100000;
+
+  if (ChildStatus == PCLIENT_BUSY) {
+    /* job is still running, send SIGTERM signal to job */
+    kill (ChildPID, SIGTERM);
+    result = waitpid (ChildPID, &waitstatus, WNOHANG);
+    for (i = 0; (i < 500) && (result == 0); i++) {
+      nanosleep (&request, &remain);
+      result = waitpid (ChildPID, &waitstatus, WNOHANG);
+    }
+    if (result) goto reset_job;
+
+    /* job did not exit, send SIGKILL signal to job */
+    kill (ChildPID, SIGKILL);
+    result = waitpid (ChildPID, &waitstatus, WNOHANG);
+    for (i = 0; (i < 500) && (result == 0); i++) {
+      nanosleep (&request, &remain);
+      result = waitpid (ChildPID, &waitstatus, WNOHANG);
+    }
+    if (result) goto reset_job;
+
+    /* total failure, don't reset */
+    gprint (GP_ERR, "child process %d is hung, cannot reset\n", ChildPID);
+    gprint (GP_LOG, "STATUS 0\n");
+    return (FALSE);
+  }
+
+reset_job:
+  /* close out ends of the pipes */
+  close (child_stdin_fd[1]);
+  close (child_stdout_fd[0]);
+  close (child_stderr_fd[0]);
+  child_stdin_fd[1] = 0;
+  child_stdout_fd[0] = 0;
+  child_stderr_fd[0] = 0;
+
+  FlushIOBuffer (&child_stdout);
+  FlushIOBuffer (&child_stderr);
+  ChildStatus = PCLIENT_NONE;
+  ChildPID = 0;
+  ChildExitStatus = 0;
+
+  gprint (GP_LOG, "STATUS 1\n");
+  return (TRUE);
+}
+
+/* exit conditions:
+   -1 - usage message / syntax error
+    2 - unknown job
+    0 - process hung
+    1 - successful resetn
+*/
+
+/* the linux kernel timer sticks in a 10ms lag between kill and the harvest */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/status.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/status.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/status.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "pclient.h"
+
+int status (int argc, char **argv) {
+
+  char status_string[64];
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: status\n");
+    return (FALSE);
+  }
+  
+  if (ChildStatus == PCLIENT_NONE)  strcpy (status_string, "NONE");
+  if (ChildStatus == PCLIENT_BUSY)  strcpy (status_string, "BUSY");
+  if (ChildStatus == PCLIENT_EXIT)  strcpy (status_string, "EXIT");
+  if (ChildStatus == PCLIENT_CRASH) strcpy (status_string, "CRASH");
+
+  gprint (GP_LOG, "STATUS %s\n", status_string);
+  gprint (GP_LOG, "EXITST %d\n", ChildExitStatus);
+  gprint (GP_LOG, "STDOUT %d\n", child_stdout.Nbuffer);
+  gprint (GP_LOG, "STDERR %d\n", child_stderr.Nbuffer);
+
+  set_str_variable ("JOBSTATUS", status_string);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/stdout.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/stdout.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/stdout.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "pclient.h"
+
+int stdout_pclient (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: stdout\n");
+    gprint (GP_LOG, "STATUS %d\n", -1);
+    return (FALSE);
+  }
+  
+  fwrite (child_stdout.buffer, 1, child_stdout.Nbuffer, stdout);
+  gprint (GP_LOG, "STATUS %d\n", 0);
+  return (TRUE);
+
+}
+
+int stderr_pclient (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: stderr\n");
+    gprint (GP_LOG, "STATUS %d\n", -1);
+    return (FALSE);
+  }
+  
+  fwrite (child_stderr.buffer, 1, child_stderr.Nbuffer, stdout);
+  gprint (GP_LOG, "STATUS %d\n", 0);
+  return (TRUE);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/test/status.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/test/status.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/test/status.sh	(revision 16632)
@@ -0,0 +1,64 @@
+
+list tests
+ test1
+ test2
+end
+
+# check status without any jobs
+macro test1
+ $PASS = 1
+ break -auto off
+
+ output -err /dev/null
+ reset
+ exec rm -f test.txt
+ output -err stderr
+
+ output test.txt
+ status
+ output stdout
+
+ # this test requires a specific set of output
+ list line -x "cat test.txt"
+ if ($line:n != 4)
+   $PASS = 0
+ end
+ if ("$line:0" != "STATUS NONE")
+   $PASS = 0
+ end
+ if ("$line:1" != "EXITST 0")
+   $PASS = 0
+ end
+ if ("$line:2" != "STDOUT 0")
+   $PASS = 0
+ end
+ if ("$line:3" != "STDERR 0")
+   $PASS = 0
+ end
+end
+
+# check status with a basic job
+macro test2
+ $PASS = 1
+ break -auto off
+
+ output -err /dev/null
+ reset
+ exec rm -f test.txt
+ job ls 
+ usleep 500000
+ output -err stderr
+
+ output test.txt
+ status
+ output stdout
+
+ # this test requires a specific set of output
+ list line -x "cat test.txt"
+ if ($line:n != 4)
+   $PASS = 0
+ end
+ if ("$line:0" != "STATUS EXIT")
+   $PASS = 0
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/test/version.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/test/version.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/test/version.sh	(revision 16632)
@@ -0,0 +1,106 @@
+
+list tests
+ test1
+ test2
+ test3
+ test4
+ test5
+ test6
+ test7
+end
+
+## these tests check that the version command reports the versions
+## they do not validate the actual versions themselves
+
+# set up the version output file
+macro test1
+ $PASS = 1
+ break -auto off
+ exec rm test.txt
+ output -err test.txt
+ version
+ output -err stderr
+ file test.txt found
+ if ($found != 1)
+   $PASS = 0
+ end
+end
+
+# test for the correct number of version lines
+macro test2
+ $PASS = 1
+ break -auto off
+ 
+ $line = `wc -l test.txt`
+
+ list word -split $line
+ if ($word:0 != 6)
+   $PASS = 0
+ end
+end
+
+# test for pclient version name
+macro test3
+ $PASS = 1
+ break -auto off
+ 
+ list line -x "cat test.txt"
+ list word -split $line:0
+
+ if ("$word:0" != "pclient")
+   $PASS = 0
+ end
+end
+
+# test for opihi version name
+macro test4
+ $PASS = 1
+ break -auto off
+ 
+ list line -x "cat test.txt"
+ list word -split $line:1
+
+ if ("$word:0" != "opihi")
+   $PASS = 0
+ end
+end
+
+# test for ohana version name
+macro test5
+ $PASS = 1
+ break -auto off
+ 
+ list line -x "cat test.txt"
+ list word -split $line:2
+
+ if ("$word:0" != "ohana")
+   $PASS = 0
+ end
+end
+
+# test for gfits version name
+macro test6
+ $PASS = 1
+ break -auto off
+ 
+ list line -x "cat test.txt"
+ list word -split $line:3
+
+ if ("$word:0" != "gfits")
+   $PASS = 0
+ end
+end
+
+# test for compilation date/time
+macro test7
+ $PASS = 1
+ break -auto off
+ 
+ list line -x "cat test.txt"
+ list word -split $line:4
+
+ if ("$word:0" != "compiled")
+   $PASS = 0
+ end
+end
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pclient/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pclient/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pclient/version.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "pclient.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+int version (int argc, char **argv) {
+
+  char *tmp;
+
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "pclient version: %s\n", (tmp = strip_version (name))); free (tmp);
+
+  gprint (GP_LOG, "opihi version: %s\n", (tmp = strip_version (opihi_version()))); free (tmp);
+  gprint (GP_LOG, "ohana version: %s\n", (tmp = strip_version (ohana_version()))); free (tmp);
+  gprint (GP_LOG, "gfits version: %s\n", (tmp = strip_version (gfits_version()))); free (tmp);
+
+  gprint (GP_LOG, "compiled on %s %s\n", __DATE__, __TIME__);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckBusyJob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckBusyJob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckBusyJob.c	(revision 16632)
@@ -0,0 +1,104 @@
+# include "pcontrol.h"
+# define DEBUG 0
+
+int CheckBusyJob (Job *job, Host *host) {
+
+  int      status;
+  int      outstate;
+  char    *p;
+  char     string[64];
+  IOBuffer buffer;
+
+  /* we are checking a job which is currently busy.  it has been pulled from the
+     JOB_BUSY stack, and is linked to a host in the HOST_BUSY stack.  
+     XXX need to check on state of HOST on return */
+
+  ASSERT (job, "job not set");
+  ASSERT (host, "host not set");
+
+  ASSERT (host == (Host *) job[0].host, "invalid host");
+  ASSERT (job  == (Job *) host[0].job, "invalid job");
+
+  InitIOBuffer (&buffer, 0x100);
+
+  status = PclientCommand (host, "status", PCLIENT_PROMPT, &buffer);
+
+  /* check on success of pclient command */
+  switch (status) {
+    case PCLIENT_DOWN:
+      HarvestHost (host[0].pid);
+      // unlink host & job
+      job[0].host = NULL;
+      host[0].job = NULL;
+      if (job[0].realhost) free (job[0].realhost);
+      job[0].realhost = NULL;
+      PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+      PutJob (job, PCONTROL_JOB_PENDING, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    case PCLIENT_HUNG:
+      // don't do anything drastic, just keep trying
+      if (DEBUG || VerboseMode()) gprint (GP_ERR, "client is busy, not responding");
+      PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
+      PutJob (job, PCONTROL_JOB_BUSY, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (TRUE);
+
+    case PCLIENT_GOOD:
+      if (DEBUG || VerboseMode()) gprint (GP_ERR, "message received (CheckBusyJob)");
+      break;
+
+    default:
+      ABORT ("unknown status for pclient command");  
+  }
+
+  /** host is up, need to parse message **/
+  p = memstr (buffer.buffer, "STATUS", buffer.Nbuffer);
+  // this condition means the message is garbage.  toss it and try again
+  if (p == NULL) {
+    PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
+    PutJob (job, PCONTROL_JOB_BUSY, STACK_BOTTOM);
+    FreeIOBuffer (&buffer);
+    return (FALSE);
+  }
+
+  sscanf (p, "%*s %s", string);
+  ASSERT (strcmp(string, "NONE"), "no current job\n");
+
+  /** no status change, return to BUSY stack **/
+  if (!strcmp(string, "BUSY")) {
+    PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
+    PutJob (job, PCONTROL_JOB_BUSY, STACK_BOTTOM);
+    FreeIOBuffer (&buffer);
+    return (TRUE);
+  }
+
+  /* exit status better be either EXIT or CRASH */
+  outstate = PCONTROL_JOB_BUSY;
+  if (!strcmp(string, "EXIT")) outstate = PCONTROL_JOB_EXIT;
+  if (!strcmp(string, "CRASH")) outstate = PCONTROL_JOB_CRASH;
+  ASSERT (outstate != PCONTROL_JOB_BUSY, "should not reach here (CheckJob)");
+
+  /* parse the exit status and sizes of output buffers */
+  p = memstr (buffer.buffer, "EXITST", buffer.Nbuffer);
+  sscanf (p, "%*s %d", &job[0].exit_status);
+  p = memstr (buffer.buffer, "STDOUT", buffer.Nbuffer);
+  sscanf (p, "%*s %d", &job[0].stdout_size);
+  p = memstr (buffer.buffer, "STDERR", buffer.Nbuffer);
+  sscanf (p, "%*s %d", &job[0].stderr_size);
+
+  // XXX runaway job if output too large?
+  if (job[0].stdout_size > 0x100000) abort();
+  if (job[0].stderr_size > 0x100000) abort();
+
+  // job has exited : move to DONE stack 
+  // the host is still BUSY until job output is gathered (int CheckDoneJob)
+  // don't unlink job and host yet
+  PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
+  PutJobSetState (job, PCONTROL_JOB_DONE, STACK_BOTTOM, outstate);
+  gettimeofday (&job[0].stop, (void *) NULL);
+  job[0].dtime = DTIME(job[0].stop, job[0].start);
+  FreeIOBuffer (&buffer);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckDoneHost.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckDoneHost.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckDoneHost.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "pcontrol.h"
+# define DEBUG 0
+
+int CheckDoneHost (Host *host) {
+  
+  int       status;
+  char     *p;
+  IOBuffer  buffer;
+
+  ASSERT (host, "host not set");
+
+  InitIOBuffer (&buffer, 0x100);
+  
+  status = PclientCommand (host, "reset", PCLIENT_PROMPT, &buffer);
+
+  /* check on success of pclient command */
+  switch (status) {
+    case PCLIENT_DOWN:
+      if (DEBUG || VerboseMode()) gprint (GP_ERR, "host %s is down\n", host[0].hostname);
+      /* DONE host does not have an incomplete job */
+      HarvestHost (host[0].pid);
+      PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+      // XXX do we need to close the connection?
+
+    case PCLIENT_HUNG:
+      // don't do anything drastic, just try again later
+      PutHost (host, PCONTROL_HOST_DONE, STACK_BOTTOM);
+      if (DEBUG || VerboseMode()) gprint (GP_ERR, "host %s is not responding\n", host[0].hostname);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    case PCLIENT_GOOD:
+      if (VerboseMode()) gprint (GP_ERR, "message received (CheckDoneHost)\n");  
+      break;
+
+    default:
+      ABORT ("unknown status for pclient command");  
+  }
+
+  /** successful command, examine result **/
+  p = memstr (buffer.buffer, "STATUS", buffer.Nbuffer);
+  ASSERT (p != NULL, "missing STATUS in pclient message (CheckDoneHost)");
+
+  sscanf (p, "%*s %d", &status);
+  switch (status) {
+    case -1:
+      ABORT ("reset syntax error");
+      
+    case 0:
+      if (DEBUG || VerboseMode()) gprint (GP_ERR, "reset failed\n");
+      PutHost (host, PCONTROL_HOST_DONE, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+      
+    case 1:
+    case 2:
+      if (DEBUG || VerboseMode()) gprint (GP_ERR, "successful reset\n");
+      PutHost (host, PCONTROL_HOST_IDLE, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    default:
+      ABORT ("should not reach here (CheckDoneHost)");
+  }
+  ABORT ("should not reach here (CheckDoneHost)");
+}
+
+/** probably need to flush the buffer before the command **/
+/** need to add timeout check here **/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckDoneJob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckDoneJob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckDoneJob.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "pcontrol.h"
+
+int CheckDoneJob (Job *job, Host *host) {
+  
+  int success;
+
+  ASSERT (job, "job not set");
+  ASSERT (host, "host not set");
+
+  ASSERT (host == (Host *) job[0].host, "invalid host");
+  ASSERT (job == (Job *) host[0].job, "invalid job");
+
+  success = TRUE;
+  success &= GetJobOutput ("stdout", host, &job[0].stdout_buff, job[0].stdout_size);
+  success &= GetJobOutput ("stderr", host, &job[0].stderr_buff, job[0].stderr_size);
+
+  if (!success) {
+    // XXX some kind of error?
+    // XXX try again later?
+    PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
+    PutJob (job, PCONTROL_JOB_DONE, STACK_BOTTOM);
+    return (FALSE);
+  }
+
+  /* job's state is either EXIT or CRASH (verify?) */
+  // unlink host & job
+  job[0].host = NULL;
+  host[0].job = NULL;
+  PutHost (host, PCONTROL_HOST_DONE, STACK_BOTTOM);
+  PutJob (job, job[0].state, STACK_BOTTOM);
+
+  return (TRUE);
+}
+
+/** need to add timeout check here **/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckHost.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckHost.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckHost.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "pcontrol.h"
+
+int CheckHost (Host *host) {
+  
+  int status;
+  IOBuffer buffer;
+
+  ASSERT (host, "host not set");
+
+  if (host[0].job != NULL) return (TRUE);
+
+  /* if this host has been marked to be turned off, do that and return */
+  if (host[0].markoff) {
+    host[0].markoff = FALSE;
+    StopHost (host);
+    OffHost (host);
+    return (TRUE);
+  }
+
+  InitIOBuffer (&buffer, 0x100);
+
+  status = PclientCommand (host, "echo OK", PCLIENT_PROMPT, &buffer);
+  switch (status) {
+    case 0:
+      if (VerboseMode()) gprint (GP_ERR, "host %s is down\n", host[0].hostname);
+      HarvestHost (host[0].pid);
+      PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+      
+    case -1:
+      if (VerboseMode()) gprint (GP_ERR, "host %s is not responding\n", host[0].hostname);
+      /*** do we mark this in some way (HUNG) ? ***/
+      PutHost (host, host[0].stack, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    default:
+      PutHost (host, host[0].stack, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (TRUE);
+  }
+  ABORT ("should not reach here (Check Host)"); 
+}
+
+// if the host has a job, we skip it (down or crash state will be caught elsewhere)
+// in fact, just touch the IDLE hosts, not the BUSY hosts?
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckIdleHost.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckIdleHost.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckIdleHost.c	(revision 16632)
@@ -0,0 +1,102 @@
+# include "pcontrol.h"
+
+/* the supplied host is not on a stack: it cannot be taken by the other thread */
+int CheckIdleHost (Host *host) {
+
+  int i;
+  Stack *stack;
+  Job *job;
+
+  ASSERT (host, "host not set");
+
+  /* if this host has been marked to be turned off, do that and return */
+  if (host[0].markoff) {
+    host[0].markoff = FALSE;
+    StopHost (host);
+    OffHost (host);
+    return (TRUE);
+  }
+    
+  /* search the JOB_PENDING stack for an appropriate job */
+  stack = GetJobStack (PCONTROL_JOB_PENDING);
+  LockStack (stack);
+  
+  /* look for first NEEDHOST matching this host */
+  for (i = 0; i < stack[0].Nobject; i++) {
+    job = (Job *) stack[0].object[i];
+    if (job[0].mode != PCONTROL_JOB_NEEDHOST) continue;
+    ASSERT (job[0].hostname != NULL, "NEEDHOST hostname missing");
+    if (strcasecmp (job[0].hostname, host[0].hostname)) continue;
+
+    /* we have found an appropriate job; link it to the host and send to StartJob */
+    job[0].host = (struct Host *) host;
+    host[0].job = (struct Job *) job;
+
+    /* take the job off the stack and unlock the stack */
+    RemoveStackEntry (stack, i);
+    UnlockStack (stack);
+    StartJob (job, host);
+    return (TRUE);
+  }
+
+  /* no NEEDHOST entry, look for first WANTHOST matching this host */
+  for (i = 0; i < stack[0].Nobject; i++) {
+    job = (Job *) stack[0].object[i];
+    if (job[0].mode != PCONTROL_JOB_WANTHOST) continue;
+    ASSERT (job[0].hostname != NULL, "WANTHOST hostname missing");
+    if (strcasecmp (job[0].hostname, host[0].hostname)) continue;
+
+    /* we have found an appropriate job; link it to the host and send to StartJob */
+    job[0].host = (struct Host *) host;
+    host[0].job = (struct Job *) job;
+
+    /* take the job off the stack and unlock the stack */
+    RemoveStackEntry (stack, i);
+    UnlockStack (stack);
+    StartJob (job, host);
+    return (TRUE);
+  }
+
+  /* no WANTHOST entry, look for first ANYHOST matching this host */
+  for (i = 0; i < stack[0].Nobject; i++) {
+    job = (Job *) stack[0].object[i];
+    if (job[0].mode != PCONTROL_JOB_ANYHOST) continue;
+
+    /* we have found an appropriate job; link it to the host and send to StartJob */
+    job[0].host = (struct Host *) host;
+    host[0].job = (struct Job *) job;
+
+    /* take the job off the stack and unlock the stack */
+    RemoveStackEntry (stack, i);
+    UnlockStack (stack);
+    StartJob (job, host);
+    return (TRUE);
+  }
+
+  /* no ANYHOST entry, look for first WANTHOST with old time */
+  /* XXX perhaps I should add this to the conditions for ANYHOST instead of
+     running a separate loop?  ie, WANTHOST && time > X == ANYHOST */
+  for (i = 0; i < stack[0].Nobject; i++) {
+    job = (Job *) stack[0].object[i];
+    if (job[0].mode != PCONTROL_JOB_WANTHOST) continue;
+    // XXX test the job age and skip if too young
+
+    /* we have found an appropriate job; link it to the host and send to StartJob */
+    job[0].host = (struct Host *) host;
+    host[0].job = (struct Job *) job;
+
+    /* take the job off the stack and unlock the stack */
+    RemoveStackEntry (stack, i);
+    UnlockStack (stack);
+    StartJob (job, host);
+    return (TRUE);
+  }
+  UnlockStack (stack);
+
+  /* no jobs for host, put it back on IDLE stack */
+  PutHost (host, PCONTROL_HOST_IDLE, STACK_BOTTOM);
+  return (TRUE);
+}
+
+/** note : host and job popped off IDLE and PENDING stacks, 
+    unless no job is available **/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckPoint.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckPoint.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckPoint.c	(revision 16632)
@@ -0,0 +1,69 @@
+# include "pcontrol.h"
+
+// one thread (user) interacts with the user and blocks for long periods on input.
+// one thread (client) spins continuously and monitors the hosts and jobs
+// in some cases, the user thread needs to set a check point on the client thread 
+// to ensure the all HOSTs and JOBs are on one of the stacks (nothing 'in flight').
+// these are not symmetric: the client thread should not call Set/Clear, the user 
+// thread should not call Test
+
+# ifdef THREADED
+static pthread_mutex_t client = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t user = PTHREAD_MUTEX_INITIALIZER;
+# endif
+
+// The user thread calls this to stop the client thread from shuffling the Host/Job stacks
+int SetCheckPoint () {
+
+# ifdef THREADED
+  int status;
+  int Nwait;
+
+  // set my lock
+  pthread_mutex_lock (&user);
+
+  // wait until client thread sets its lock
+  Nwait = 0;
+  while (1) {
+    status = pthread_mutex_trylock (&client);
+    if (status == EBUSY) {
+      // client has reached the check-point
+      return (TRUE);
+    }
+    pthread_mutex_unlock (&client);
+    usleep (10000); // wait for client thread to set lock
+    Nwait ++;
+  }
+  // put in a timeout?  (client thread not spinning...)
+  return (FALSE);
+# else
+  return (TRUE);
+# endif
+}
+
+// The user thread calls this to allow the client thread to continue
+int ClearCheckPoint () {
+  // clear my lock
+# ifdef THREADED
+  pthread_mutex_unlock (&user);
+# endif
+  return (TRUE);
+}
+
+// The client thread calls in the thread loop somewhere the stacks are stable
+// (ie, no jobs or hosts currently in flight)
+int TestCheckPoint () {
+
+# ifdef THREADED
+  // set my lock
+  pthread_mutex_lock (&client);
+  
+  // try the user-thread lock
+  pthread_mutex_lock (&user);
+  pthread_mutex_unlock (&user);
+
+  // clear my lock
+  pthread_mutex_unlock (&client);
+# endif
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckSystem.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckSystem.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/CheckSystem.c	(revision 16632)
@@ -0,0 +1,390 @@
+# include "pcontrol.h"
+# define DEBUG 0
+
+static struct timeval lastlive = {0, 0};
+static RunLevels RunLevel = PCONTROL_RUN_NONE;
+
+RunLevels SetRunLevel (RunLevels level) {
+  RunLevels oldlevel;
+  oldlevel = RunLevel;
+  RunLevel = level;
+  return oldlevel;
+}
+
+RunLevels GetRunLevel () {
+  return RunLevel;
+}
+
+int CheckSystem () {
+
+  struct timeval now;
+  float dtime;
+
+  /* we want to give each block a maximum allowed time */
+  CheckIdleHosts(0.020); /* submit a new job */
+
+  CheckBusyJobs(0.020);  /* get job status */
+  CheckDoneJobs(0.020);  /* harvest job stdout/stderr */
+  CheckKillJobs(0.020);  /* harvest job stdout/stderr */
+
+  CheckDoneHosts(0.020); /* reset the host */
+  CheckDownHosts(0.100); /* launch the host */
+
+  /* always allow at least one test */
+  /* most tests require about 2ms per host.  
+     CheckDoneJobs must depend on the size of the output buffer */
+
+  gettimeofday (&now, (void *) NULL);
+  dtime = DTIME (now, lastlive);
+  if (dtime > 1.0) {
+    CheckLiveHosts(0.040);
+    lastlive = now;
+  } 
+
+  if (DEBUG) { 
+    Stack *stack;
+    int Nidle, Ndown, Nbusy;
+    stack = GetHostStack (PCONTROL_HOST_IDLE);
+    Nidle = stack[0].Nobject;
+    stack = GetHostStack (PCONTROL_HOST_DOWN);
+    Ndown = stack[0].Nobject;
+    stack = GetHostStack (PCONTROL_HOST_BUSY);
+    Nbusy = stack[0].Nobject;
+    gprint (GP_ERR, "busy, idle, down: %2d %2d %2d\n", Nbusy, Nidle, Ndown);
+  }
+
+  return (TRUE);
+}
+
+void *CheckSystem_Threaded (void *data) {
+
+  int Njobchecks, Nhostchecks, Nlivechecks, Ndonejobs;
+
+  Nlivechecks = 0;
+
+  gprintInit ();
+
+  while (1) {
+    // stop here if the user-thread requests (no objects in flight) 
+    TestCheckPoint ();
+
+    // don't run the system checks if RunLevel is FALSE
+    // XXX stop should not suspend all checks: we should continue
+    // to harvest completed jobs and migrate idle machines to down
+    if (RunLevel == PCONTROL_RUN_NONE) {
+      usleep (100000); // idle if we are running nothing
+      continue;
+    }
+
+    /* always allow at least one test */
+    /* most tests require about 2ms per host.  
+       CheckDoneJobs must depend on the size of the output buffer */
+    /* the max delay times are fairly arbitrary and do not impact
+       the user interface.
+     */
+
+    Njobchecks = 0;
+    Nhostchecks = 0;
+    Ndonejobs = 0;
+
+    if ((RunLevel == PCONTROL_RUN_ALL) || (RunLevel == PCONTROL_RUN_REAP)) {
+      Njobchecks  += CheckBusyJobs(0.020);  /* get job status (PCLIENT) */
+      TestCheckPoint ();
+      Ndonejobs    = CheckDoneJobs(0.020);  /* harvest job stdout/stderr (!PCLIENT) */
+      Njobchecks  += Ndonejobs;
+      TestCheckPoint ();
+      Njobchecks  += CheckKillJobs(0.020);  /* harvest job stdout/stderr (PCLIENT) */
+      TestCheckPoint ();
+    }
+
+    if (RunLevel != PCONTROL_RUN_NONE) {
+      Nhostchecks += CheckDoneHosts(0.020); /* reset the host */
+      TestCheckPoint ();
+      Nhostchecks += CheckDownHosts(0.100); /* launch the host */
+      TestCheckPoint ();
+    }
+
+    if (RunLevel == PCONTROL_RUN_ALL) {
+      // we want to give each block a maximum allowed time
+      Nhostchecks += CheckIdleHosts(0.020); /* submit a new job (PCLIENT) */
+      TestCheckPoint ();
+    }
+
+    // there is nothing on the stacks.  test the hosts and wait a bit
+    if (!Njobchecks && !Nhostchecks && (RunLevel != PCONTROL_RUN_NONE)) {
+      CheckLiveHosts(0.040);
+      usleep (100000); // idle if no jobs are waiting
+    } else {
+      // if we only have busy jobs, pause a moment before trying again
+      if (!Ndonejobs) {
+	usleep (100000);
+      }
+    }
+
+    if (DEBUG) { 
+      Stack *stack;
+      int Nidle, Ndown, Nbusy;
+      stack = GetHostStack (PCONTROL_HOST_IDLE);
+      Nidle = stack[0].Nobject;
+      stack = GetHostStack (PCONTROL_HOST_DOWN);
+      Ndown = stack[0].Nobject;
+      stack = GetHostStack (PCONTROL_HOST_BUSY);
+      Nbusy = stack[0].Nobject;
+      gprint (GP_ERR, "Njobchecks: %d, busy, idle, down: %2d %2d %2d\n", Njobchecks, Nbusy, Nidle, Ndown);
+    }
+  }
+  return (NULL);
+}
+
+int CheckBusyJobs (float MaxDelay) {
+
+  struct timeval start, stop;
+  int i, Nobject;
+  Stack *hoststack;
+  Stack *jobstack;
+  Job   *job;
+  Host  *host;
+  float dtime;
+
+  /* Loop through objects on the stack, no more than once.  Note that it is not important if the
+     stack size is modified by other threads or is changed by any of the actions performed during
+     this loop: the Nobject value is only used to get a rough number for the number of iterations.
+   */
+
+  hoststack = GetHostStack (PCONTROL_HOST_BUSY);
+  jobstack  = GetJobStack (PCONTROL_JOB_BUSY);
+  Nobject   = jobstack[0].Nobject;
+
+  /* always allow at least one test */
+  gettimeofday (&start, (void *) NULL);
+  dtime = 0.0;
+  for (i = 0; (i < Nobject) && (dtime < MaxDelay); i++) {
+    // pull both job and host from their stacks
+    LockStack (hoststack);
+    job = PullStackByLocation (jobstack, STACK_TOP);
+    if (job == NULL) {
+      UnlockStack (hoststack);
+      break;
+    }
+    host = (Host *) job[0].host;
+    ASSERT (host != NULL, "host is NULL");
+    RemoveStackByID (hoststack, host[0].HostID);
+    UnlockStack (hoststack);
+
+    CheckBusyJob (job, host);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+  }
+  if (DEBUG && (Nobject > 0)) gprint (GP_ERR, "checked %d of %d jobs\n", i, Nobject);
+  return (i);
+}
+
+int CheckDoneJobs (float MaxDelay) {
+
+  struct timeval start, stop;
+  int i, Nobject;
+  Stack *hoststack;
+  Stack *jobstack;
+  Job   *job;
+  Host  *host;
+  float dtime;
+
+  /* Loop through objects on the stack, no more than once. see note above */
+  hoststack = GetHostStack (PCONTROL_HOST_BUSY);
+  jobstack  = GetJobStack (PCONTROL_JOB_DONE);
+  Nobject   = jobstack[0].Nobject;
+
+  /* always allow at least one test */
+  gettimeofday (&start, (void *) NULL);
+  dtime = 0.0;
+  for (i = 0; (i < Nobject) && (dtime < MaxDelay); i++) {
+    LockStack (hoststack);
+    job = PullStackByLocation (jobstack, STACK_TOP);
+    if (job == NULL) {
+      UnlockStack (hoststack);
+      break;
+    }
+    host = (Host *) job[0].host;
+    ASSERT (host, "host is NULL");
+
+    RemoveStackByID (hoststack, host[0].HostID);
+    UnlockStack (hoststack);
+
+    CheckDoneJob (job, host);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+  }
+  if (DEBUG && (Nobject > 0)) gprint (GP_ERR, "checked %d of %d jobs\n", i, Nobject);
+  return (i);
+}
+
+int CheckKillJobs (float MaxDelay) {
+
+  struct timeval start, stop;
+  int i, Nobject;
+  Stack *hoststack;
+  Stack *jobstack;
+  Job   *job;
+  Host  *host;
+  float dtime;
+
+  /* Loop through objects on the stack, no more than once. see note above */
+  hoststack = GetHostStack (PCONTROL_HOST_BUSY);
+  jobstack = GetJobStack (PCONTROL_JOB_KILL);
+  Nobject = jobstack[0].Nobject;
+
+  /* always allow at least one test */
+  gettimeofday (&start, (void *) NULL);
+  dtime = 0.0;
+  for (i = 0; (i < Nobject) && (dtime < MaxDelay); i++) {
+    LockStack (hoststack);
+    job = PullStackByLocation (jobstack, STACK_TOP);
+    if (job == NULL) {
+      UnlockStack (hoststack);
+      break;
+    }
+    host = (Host *) job[0].host;
+    ASSERT (host, "host is NULL");
+
+    RemoveStackByID (hoststack, host[0].HostID);
+    UnlockStack (hoststack);
+
+    KillJob (job, host);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+  }
+  if (DEBUG && (Nobject > 0)) gprint (GP_ERR, "checked %d of %d jobs\n", i, Nobject);
+  return (i);
+}
+
+int CheckDoneHosts (float MaxDelay) {
+
+  struct timeval start, stop;
+  int i, Nobject;
+  Stack *stack;
+  Host  *host;
+  float dtime;
+
+  /* Loop through objects on the stack, no more than once. see note above */
+  stack = GetHostStack (PCONTROL_HOST_DONE);
+  Nobject = stack[0].Nobject;
+
+  /* always allow at least one test */
+  gettimeofday (&start, (void *) NULL);
+  dtime = 0.0;
+  for (i = 0; (i < Nobject) && (dtime < MaxDelay); i++) {
+    host = PullStackByLocation (stack, STACK_TOP);
+    if (host == NULL) break;
+    CheckDoneHost (host);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+  }
+  if (DEBUG) gprint (GP_ERR, "checked %d hosts\n", i);
+  return (i);
+}
+
+int CheckDownHosts (float MaxDelay) {
+
+  int i, Nobject;
+  Stack *stack;
+  Host  *host;
+  struct timeval start, stop;
+  float dtime;
+
+  /* Loop through objects on the stack, no more than once. see note above */
+  stack = GetHostStack (PCONTROL_HOST_DOWN);
+  Nobject = stack[0].Nobject;
+
+  /* always allow at least one test */
+  gettimeofday (&start, (void *) NULL);
+  dtime = 0.0;
+  for (i = 0; (i < Nobject) && (dtime < MaxDelay); i++) {
+    host = PullStackByLocation (stack, STACK_TOP);
+    if (host == NULL) break;
+    if (host[0].markoff) {
+      host[0].markoff = FALSE;
+      OffHost (host);
+      return (TRUE);
+    }
+    dtime = DTIME (host[0].nexttry, start);
+    if (dtime > 0) {
+      PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+    } else {
+      StartHost (host);
+    }
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+  }
+  if (DEBUG) gprint (GP_ERR, "checked %d hosts\n", i);
+  return (i);
+}
+
+int CheckIdleHosts (float MaxDelay) {
+
+  struct timeval start, stop;
+  int i, Nobject;
+  Stack *stack;
+  Host  *host;
+  float dtime;
+
+  /* check if there are any pending jobs, otherwise skip step */
+  stack = GetJobStack (PCONTROL_JOB_PENDING);
+  if (!stack[0].Nobject) return (0);
+
+  /* Loop through objects on the stack, no more than once. see note above */
+  stack = GetHostStack (PCONTROL_HOST_IDLE);
+  Nobject = stack[0].Nobject;
+
+  /* always allow at least one test */
+  gettimeofday (&start, (void *) NULL);
+  dtime = 0.0;
+  for (i = 0; (i < Nobject) && (dtime < MaxDelay); i++) {
+    host = PullStackByLocation (stack, STACK_TOP);
+    if (host == NULL) break;
+    CheckIdleHost (host);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+  }
+  if (DEBUG) gprint (GP_ERR, "checked %d hosts\n", i);
+  return (i);
+}
+
+/* this is just a heartbeat check (only IDLE hosts) */
+int CheckLiveHosts (float MaxDelay) {
+
+  struct timeval start, stop;
+  int i, Nobject;
+  Stack *stack;
+  Host  *host;
+  float dtime;
+
+  /* Loop through objects on the stack, no more than once. see note above */
+  stack = GetHostStack (PCONTROL_HOST_IDLE);
+  Nobject = stack[0].Nobject;
+
+  gettimeofday (&start, (void *) NULL);
+
+  dtime = 0.0;
+  for (i = 0; (i < Nobject) && (dtime < MaxDelay); i++) {
+    host = PullStackByLocation (stack, STACK_TOP);
+    if (host == NULL) break;
+    CheckHost (host);
+    gettimeofday (&stop, (void *) NULL);
+    dtime = DTIME (stop, start);
+  }
+  if (DEBUG) gprint (GP_ERR, "checked %d idle hosts\n", i);
+  return (TRUE);
+}
+
+/*
+
+  gettimeofday (&stop, (void *) NULL);
+  dtime = DTIME (stop, start);
+  if (VerboseMode()) gprint (GP_ERR, "check 4: %f seconds\n", dtime);
+
+  gettimeofday (&start, (void *) NULL);
+*/
+
+/** All of the CheckFooBar entries cycle though their respective queues, popping from the top and
+    pushing to the bottom.  if we stop before the loop is done there is no tendancy for bias because
+    we continue where we left off next round **/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/GetJobOutput.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/GetJobOutput.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/GetJobOutput.c	(revision 16632)
@@ -0,0 +1,65 @@
+# include "pcontrol.h"
+# define PCLIENT_TIMEOUT 500
+
+/* we read Nbytes from the host, then watch for the prompt */ 
+int GetJobOutput (char *cmd, Host *host, IOBuffer *buffer, int Nbytes) {
+  
+  int i, status, Nstart;
+  char *line;
+  struct timespec request, remain;
+
+  ASSERT (cmd, "cmd missing");
+  ASSERT (host, "host missing");
+  ASSERT (buffer, "buffer missing");
+
+  /* flush any earlier messages */
+  ReadtoIOBuffer (buffer, host[0].stdout_fd);
+  FlushIOBuffer (buffer);
+  Nstart = buffer[0].Nbuffer;
+
+  /* avoid blocking on waitpid, test every 100 usec, up to 50 msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 100000;
+
+  /* send cmd (stdout / stderr) */
+  status = write_fmt (host[0].stdin_fd, "%s\n", cmd);
+
+  /* is pipe still open? */
+  if ((status == -1) && (errno == EPIPE)) return (PCLIENT_DOWN);
+
+  /* read at least Nbytes, then watch for PCLIENT_PROMPT */
+  line = NULL;
+  status = -1;
+  for (i = 0; (i < PCLIENT_TIMEOUT) && (status != 0) && (line == NULL); i++) {
+    status = ReadtoIOBuffer (buffer, host[0].stdout_fd);
+    if ((buffer[0].Nbuffer - Nstart) >= Nbytes) {
+      line = memstr (buffer[0].buffer, PCLIENT_PROMPT, buffer[0].Nbuffer);
+    }
+    if (status == -1) nanosleep (&request, &remain);
+  }
+  if (status ==  0) return (PCLIENT_DOWN);
+  if (status == -1) return (PCLIENT_HUNG);
+
+  /* check on success of pclient command */
+  switch (status) {
+    case -1:
+      if (VerboseMode()) gprint (GP_ERR, "host %s is not responding\n", host[0].hostname);
+      return (FALSE);
+
+    case 0:
+      if (VerboseMode()) gprint (GP_ERR, "host %s is down\n", host[0].hostname);
+      return (FALSE);
+
+    default:
+      if (VerboseMode()) gprint (GP_ERR, "message received (GetJobOutput : %s)\n", cmd);  
+      /* drop extra bytes from pclient (not pclient:job) */
+      buffer[0].Nbuffer = Nstart + Nbytes;
+      if (buffer[0].Nalloc > buffer[0].Nbuffer) {
+	bzero (buffer[0].buffer + buffer[0].Nbuffer, buffer[0].Nalloc - buffer[0].Nbuffer);
+      }
+      return (TRUE);
+  }
+
+  gprint (GP_ERR, "programming error: should not reach here (GetJobOutput)\n");
+  pcontrol_exit (50);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/HostOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/HostOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/HostOps.c	(revision 16632)
@@ -0,0 +1,192 @@
+# include "pcontrol.h"
+
+Stack *HostPool_Idle;
+Stack *HostPool_Busy;
+Stack *HostPool_Done;
+Stack *HostPool_Down;
+Stack *HostPool_Off;
+
+void InitHostStacks () {
+  HostPool_Idle = InitStack ();
+  HostPool_Busy = InitStack ();
+  HostPool_Done = InitStack ();
+  HostPool_Down = InitStack ();
+  HostPool_Off  = InitStack ();
+}
+
+void FreeHostStack (Stack *stack) {
+  Host *host;
+  while ((host = PullStackByLocation (stack, stack[0].Nobject - 1)) != NULL) {
+    DelHost (host);
+  }
+  FreeStack (stack);
+}
+
+void FreeHostStacks () {
+  FreeHostStack (HostPool_Idle);
+  FreeHostStack (HostPool_Busy);
+  FreeHostStack (HostPool_Done);
+  FreeHostStack (HostPool_Down);
+  FreeHostStack (HostPool_Off );
+}
+
+char *GetHostStackName (int StackID) {
+  switch (StackID) {
+    case PCONTROL_HOST_IDLE: return ("IDLE");
+    case PCONTROL_HOST_DOWN: return ("DOWN");
+    case PCONTROL_HOST_DONE: return ("DONE");
+    case PCONTROL_HOST_BUSY: return ("BUSY");
+    case PCONTROL_HOST_OFF:  return ("OFF");
+  }
+  gprint (GP_ERR, "error: unknown host stack : programming error\n");
+  pcontrol_exit (51);
+  return (NULL);
+}
+
+Stack *GetHostStack (int StackID) {
+  switch (StackID) {
+    case PCONTROL_HOST_IDLE: return (HostPool_Idle);
+    case PCONTROL_HOST_DOWN: return (HostPool_Down);
+    case PCONTROL_HOST_DONE: return (HostPool_Done);
+    case PCONTROL_HOST_BUSY: return (HostPool_Busy);
+    case PCONTROL_HOST_OFF:  return (HostPool_Off);
+  }
+  gprint (GP_ERR, "error: unknown host stack : programming error\n");
+  pcontrol_exit (52);
+  return (NULL);
+}
+
+Stack *GetHostStackByName (char *name) {
+  if (!strcasecmp (name, "idle")) return (HostPool_Idle);
+  if (!strcasecmp (name, "down")) return (HostPool_Down);
+  if (!strcasecmp (name, "done")) return (HostPool_Done);
+  if (!strcasecmp (name, "busy")) return (HostPool_Busy);
+  if (!strcasecmp (name, "off"))  return (HostPool_Off);
+  return (NULL);
+}
+
+/* add host to position in stack */
+int PutHost (Host *host, int StackID, int where) {
+
+  int stat;
+  Stack *stack;
+
+  stack = GetHostStack (StackID);
+  if (stack == NULL) return (FALSE);
+
+  host[0].stack = StackID;
+  stat = PushStack (stack, where, host, host[0].HostID, host[0].hostname);
+  // XXX need to handle the error conditions, or we drop the host & leak memory
+  return (stat);
+}
+  
+/* find the host by ID in the defined host stacks */
+Host *PullHostByID (IDtype HostID, int *StackID) {
+
+  Host *host;
+
+  *StackID = PCONTROL_HOST_IDLE;
+  host = PullHostFromStackByID (*StackID, HostID);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_DOWN;
+  host = PullHostFromStackByID (*StackID, HostID);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_DONE;
+  host = PullHostFromStackByID (*StackID, HostID);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_BUSY;
+  host = PullHostFromStackByID (*StackID, HostID);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_OFF;
+  host = PullHostFromStackByID (*StackID, HostID);
+  if (host != NULL) return (host);
+
+  *StackID = -1;
+  return (NULL);
+}
+
+/* find the host by ID in the defined host stacks */
+Host *PullHostByName (char *name, int *StackID) {
+
+  Host *host;
+
+  *StackID = PCONTROL_HOST_IDLE;
+  host = PullHostFromStackByName (*StackID, name);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_DOWN;
+  host = PullHostFromStackByName (*StackID, name);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_DONE;
+  host = PullHostFromStackByName (*StackID, name);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_BUSY;
+  host = PullHostFromStackByName (*StackID, name);
+  if (host != NULL) return (host);
+
+  *StackID = PCONTROL_HOST_OFF;
+  host = PullHostFromStackByName (*StackID, name);
+  if (host != NULL) return (host);
+
+  *StackID = -1;
+  return (NULL);
+}
+
+Host *PullHostFromStackByID (int StackID, IDtype ID) {
+
+  Host *host;
+  Stack *stack;
+
+  stack = GetHostStack (StackID);
+  if (stack == NULL) return (NULL);
+
+  host = PullStackByID (stack, ID);
+  return (host);
+}
+
+Host *PullHostFromStackByName (int StackID, char *name) {
+
+  Host *host;
+  Stack *stack;
+
+  stack = GetHostStack (StackID);
+  if (stack == NULL) return (NULL);
+
+  host = PullStackByName (stack, name);
+  return (host);
+}
+
+IDtype AddHost (char *hostname) {
+
+  Host *host;
+
+  ALLOCATE (host, Host, 1);
+
+  host[0].hostname  = strcreate (hostname);
+  host[0].stdin_fd  = 0;
+  host[0].stdout_fd = 0;
+  host[0].stderr_fd = 0;
+  host[0].HostID    = NextHostID();
+
+  host[0].lasttry.tv_sec = 0;
+  host[0].lasttry.tv_usec = 0;
+  host[0].nexttry.tv_sec = 0;
+  host[0].nexttry.tv_usec = 0;
+
+  host[0].markoff  = FALSE;
+  host[0].job      = NULL;
+  PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+  return (host[0].HostID);
+}
+
+void DelHost (Host *host) {
+  FREE (host[0].hostname);
+  FREE (host[0].job);
+  FREE (host);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/IDops.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/IDops.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/IDops.c	(revision 16632)
@@ -0,0 +1,42 @@
+# include "pcontrol.h"
+
+static IDtype CurrentJobID  = 0;
+static IDtype CurrentHostID = 0;
+
+/* for now, no persistence : we could use the date/time to seed the upper byte(s) if needed */
+void InitIDs () {
+  CurrentJobID = 0;
+  CurrentHostID = 0;
+}
+
+IDtype NextJobID () {
+
+  IDtype ID;
+
+  ID = CurrentJobID;
+  CurrentJobID ++;
+  return (ID);
+}
+
+/* only used by the User thread */
+IDtype NextHostID () {
+
+  IDtype ID;
+
+  ID = CurrentHostID;
+  CurrentHostID ++;
+  return (ID);
+}
+
+void PrintID (gpDest dest, IDtype ID) {
+
+  unsigned short int word0, word1, word2, word3;
+
+  word0 = 0xffff & ID;
+  word1 = 0xffff & (ID >> 16);
+  word2 = 0xffff & (ID >> 32);
+  word3 = 0xffff & (ID >> 48);
+
+  gprint (dest, "%x.%x.%x.%x", word3, word2, word1, word0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/JobID.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/JobID.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/JobID.c	(revision 16632)
@@ -0,0 +1,41 @@
+# include "pcontrol.h"
+
+static IDtype CurrentJobID  = 0;
+static IDtype CurrentHostID = 0;
+
+/* for now, no persistence : we could use the date/time to seed the upper byte(s) if needed */
+void InitIDs () {
+  CurrentJobID = 0;
+  CurrentHostID = 0;
+}
+
+IDtype NextJobID () {
+
+  IDtype ID;
+
+  ID = CurrentJobID;
+  CurrentJobID ++;
+  return (ID);
+}
+
+IDtype NextHostID () {
+
+  IDtype ID;
+
+  ID = CurrentHostID;
+  CurrentHostID ++;
+  return (ID);
+}
+
+void PrintID (gpDest dest, IDtype ID) {
+
+  unsigned short int word0, word1, word2, word3;
+
+  word0 = 0xffff & ID;
+  word1 = 0xffff & (ID >> 16);
+  word2 = 0xffff & (ID >> 32);
+  word3 = 0xffff & (ID >> 48);
+
+  gprint (dest, "%x.%x.%x.%x", word3, word2, word1, word0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/JobOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/JobOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/JobOps.c	(revision 16632)
@@ -0,0 +1,192 @@
+# include "pcontrol.h"
+
+Stack *JobPool_Pending;
+Stack *JobPool_Busy;
+Stack *JobPool_Done;
+Stack *JobPool_Kill;
+Stack *JobPool_Exit;
+Stack *JobPool_Crash;
+
+void InitJobStacks () {
+  JobPool_Pending = InitStack ();
+  JobPool_Busy    = InitStack ();
+  JobPool_Done    = InitStack ();
+  JobPool_Kill    = InitStack ();
+  JobPool_Exit    = InitStack ();
+  JobPool_Crash   = InitStack ();
+}
+
+void FreeJobStack (Stack *stack) {
+  Job *job;
+  while ((job = PullStackByLocation (stack, stack[0].Nobject - 1)) != NULL) {
+    DelJob (job);
+  }
+  FreeStack (stack);
+}
+
+void FreeJobStacks () {
+  FreeJobStack (JobPool_Pending);
+  FreeJobStack (JobPool_Busy   );
+  FreeJobStack (JobPool_Done   );
+  FreeJobStack (JobPool_Kill   );
+  FreeJobStack (JobPool_Exit   );
+  FreeJobStack (JobPool_Crash  );
+}
+
+char *GetJobStackName (int StackID) {
+  switch (StackID) {
+    case PCONTROL_JOB_PENDING: return ("PENDING");
+    case PCONTROL_JOB_BUSY:    return ("BUSY");
+    case PCONTROL_JOB_DONE:    return ("DONE");
+    case PCONTROL_JOB_KILL:    return ("KILL");
+    case PCONTROL_JOB_EXIT:    return ("EXIT");
+    case PCONTROL_JOB_CRASH:   return ("CRASH");
+  }
+  gprint (GP_ERR, "error: unknown host stack : programming error\n");
+  pcontrol_exit (53);
+  return (NULL);
+}
+
+Stack *GetJobStack (int StackID) {
+  switch (StackID) {
+    case PCONTROL_JOB_PENDING: return (JobPool_Pending);
+    case PCONTROL_JOB_BUSY:    return (JobPool_Busy);
+    case PCONTROL_JOB_DONE:    return (JobPool_Done);
+    case PCONTROL_JOB_KILL:    return (JobPool_Kill);
+    case PCONTROL_JOB_EXIT:    return (JobPool_Exit);
+    case PCONTROL_JOB_CRASH:   return (JobPool_Crash);
+  }
+  gprint (GP_ERR, "error: unknown job stack : programming error\n");
+  pcontrol_exit (54);
+  return (NULL);
+}
+
+Stack *GetJobStackByName (char *name) {
+
+  if (!strcasecmp (name, "pending")) return (JobPool_Pending);
+  if (!strcasecmp (name, "busy"))    return (JobPool_Busy);
+  if (!strcasecmp (name, "done"))    return (JobPool_Done);
+  if (!strcasecmp (name, "exit"))    return (JobPool_Exit);
+  if (!strcasecmp (name, "crash"))   return (JobPool_Crash);
+  return (NULL);
+}
+
+/* add job to position in stack, use StackID as default state */
+int PutJob (Job *job, int StackID, int where) {
+
+  int stat;
+  Stack *stack;
+
+  stack = GetJobStack (StackID);
+  if (stack == NULL) return (FALSE);
+
+  /* by default, these are both the same - to override, use PutJobSetState */
+  job[0].state = StackID;
+  job[0].stack = StackID;
+  stat = PushStack (stack, where, job, job[0].JobID, job[0].argv[0]);
+  // XXX need to handle the error conditions, or we drop the host & leak memory
+  return (stat);
+}
+  
+/* add job to position in stack.  set state to 'state' */
+int PutJobSetState (Job *job, int StackID, int where, int state) {
+
+  int stat;
+  Stack *stack;
+
+  stack = GetJobStack (StackID);
+  if (stack == NULL) return (FALSE);
+
+  /* alternate state specified by user */
+  job[0].state = state;
+  job[0].stack = StackID;
+  stat = PushStack (stack, where, job, job[0].JobID, job[0].argv[0]);
+  // XXX need to handle the error conditions, or we drop the host & leak memory
+  return (stat);
+}
+  
+Job *PullJobByID (IDtype JobID, int *StackID) {
+
+  Job *job;
+
+  *StackID = PCONTROL_JOB_PENDING;
+  job = PullJobFromStackByID (*StackID, JobID);
+  if (job != NULL) return (job);
+
+  *StackID = PCONTROL_JOB_BUSY;
+  job = PullJobFromStackByID (*StackID, JobID);
+  if (job != NULL) return (job);
+
+  *StackID = PCONTROL_JOB_EXIT;
+  job = PullJobFromStackByID (*StackID, JobID);
+  if (job != NULL) return (job);
+
+  *StackID = PCONTROL_JOB_CRASH;
+  job = PullJobFromStackByID (*StackID, JobID);
+  if (job != NULL) return (job);
+
+  *StackID = PCONTROL_JOB_DONE;
+  job = PullJobFromStackByID (*StackID, JobID);
+  if (job != NULL) return (job);
+
+  *StackID = PCONTROL_JOB_KILL;
+  job = PullJobFromStackByID (*StackID, JobID);
+  if (job != NULL) return (job);
+
+  return (NULL);
+}
+
+/* remove job from position in stack */
+Job *PullJobFromStackByID (int StackID, int ID) {
+
+  Job *job;
+  Stack *stack;
+
+  stack = GetJobStack (StackID);
+  if (stack == NULL) return (NULL);
+
+  job = PullStackByID (stack, ID);
+  return (job);
+}
+
+IDtype AddJob (char *hostname, JobMode mode, int timeout, int argc, char **argv) {
+
+  int JobID;
+  Job *job;
+
+  ALLOCATE (job, Job, 1);
+
+  job[0].argc     = argc;
+  job[0].argv     = argv;
+  job[0].hostname = hostname;
+  job[0].mode     = mode;
+  job[0].host     = NULL;
+  job[0].JobID    = NextJobID();
+  job[0].Reset    = FALSE;
+  job[0].realhost = NULL;
+
+  /* do this step on start? */
+  InitIOBuffer (&job[0].stdout_buff, 0x1000);
+  InitIOBuffer (&job[0].stderr_buff, 0x1000);
+
+  JobID = job[0].JobID;
+  PutJob (job, PCONTROL_JOB_PENDING, STACK_BOTTOM);
+  if (VerboseMode()) gprint (GP_ERR, "added new job\n");
+  return (JobID);
+}
+
+void DelJob (Job *job) {
+
+  int i;
+
+  FREE (job[0].hostname);
+  for (i = 0; i < job[0].argc; i++) {
+    FREE (job[0].argv[i]);
+  }
+  FREE (job[0].argv);
+
+  FreeIOBuffer (&job[0].stdout_buff);
+  FreeIOBuffer (&job[0].stderr_buff);
+
+  FREE (job);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/KillJob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/KillJob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/KillJob.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "pcontrol.h"
+
+int KillJob (Job *job, Host *host) {
+  
+  IOBuffer buffer;
+  int status;
+  char *p;
+
+  ASSERT (host != NULL, "host missing");
+  ASSERT (job != NULL, "job missing");
+
+  ASSERT (host == (Host *) job[0].host, "invalid host");
+  ASSERT (job  == (Job *) host[0].job, "invalid job");
+
+  InitIOBuffer (&buffer, 0x100);
+
+  status = PclientCommand (host, "reset", PCLIENT_PROMPT, &buffer);
+
+  /* check on success of pclient command */
+  switch (status) {
+    case PCLIENT_DOWN:
+      HarvestHost (host[0].pid);
+      // unlink host & job
+      job[0].host = NULL;
+      host[0].job = NULL;
+      PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+      PutJob (job, PCONTROL_JOB_CRASH, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    case PCLIENT_HUNG:
+      // don't do anything drastic, just keep trying
+      // XXX move to which stack??
+      gprint (GP_ERR, "client is busy, not responding (KillJob)");
+      FreeIOBuffer (&buffer);
+      return (TRUE);
+
+    case PCLIENT_GOOD:
+      if (VerboseMode()) gprint (GP_ERR, "message received (KillJob)\n");  
+      break;
+
+    default:
+      ABORT ("unknown status for pclient command");  
+  }
+
+  /** host is up, need to parse message **/
+  p = memstr (buffer.buffer, "STATUS", buffer.Nbuffer);
+  ASSERT (p != NULL, "missing STATUS in pclient message");
+  if (VerboseMode()) gprint (GP_ERR, "client message: %s\n", buffer.buffer);
+
+  sscanf (p, "%*s %d", &status);
+  FreeIOBuffer (&buffer);
+  gprint (GP_ERR, "client status: %d\n", status);
+
+  switch (status) {
+    case -1:
+      ABORT ("syntax error to pclient");
+    case 0:
+      gprint (GP_ERR, "failure to kill child process\n");
+      PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
+      PutJob (job, PCONTROL_JOB_KILL, STACK_BOTTOM);
+      return (FALSE);
+    case 1:
+      gprint (GP_ERR, "killing job %s on %s\n", job[0].argv[0], host[0].hostname);
+      // unlink host & job
+      job[0].host = NULL;
+      host[0].job = NULL;
+      PutHost (host, PCONTROL_HOST_IDLE, STACK_BOTTOM);
+      PutJob (job, PCONTROL_JOB_CRASH, STACK_BOTTOM);
+      return (TRUE);
+    case 2:
+      ABORT ("client has no job");
+  }
+  ABORT ("should not reach here (KillJob)");
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/Makefile	(revision 16632)
@@ -0,0 +1,76 @@
+default: pcontrol
+
+include ../../../Makefile.System
+HOME    =       $(ROOT)/src/opihi
+BIN     =       $(HOME)/bin
+LIB     =       $(HOME)/lib
+INC     =       $(HOME)/include
+SRC     =       $(HOME)/pcontrol
+DATA    =       $(DESTDATA)/pcontrol
+include ../Makefile.Common
+
+# programs may add their own internal requirements here
+LIBS1         = -lkapa -lFITS -lohana
+LIBS2         = -lbasiccmd -lshell -ldata 
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(LIBS1) $(LIBS2) $(BASE_LDFLAGS)
+
+# to build the non-threaded version, remove -lpthread and comment out
+# the THREADED line in include/pcontrol.h
+
+# pcontrol user commands and support functions ########################
+funcs = \
+$(SRC)/init.$(ARCH).o \
+$(SRC)/pcontrol.$(ARCH).o \
+$(SRC)/rconnect.$(ARCH).o \
+$(SRC)/CheckBusyJob.$(ARCH).o \
+$(SRC)/CheckDoneHost.$(ARCH).o \
+$(SRC)/CheckDoneJob.$(ARCH).o \
+$(SRC)/CheckHost.$(ARCH).o \
+$(SRC)/CheckIdleHost.$(ARCH).o \
+$(SRC)/CheckPoint.$(ARCH).o \
+$(SRC)/CheckSystem.$(ARCH).o \
+$(SRC)/GetJobOutput.$(ARCH).o \
+$(SRC)/HostOps.$(ARCH).o \
+$(SRC)/IDops.$(ARCH).o \
+$(SRC)/JobOps.$(ARCH).o \
+$(SRC)/StackOps.$(ARCH).o \
+$(SRC)/PclientCommand.$(ARCH).o \
+$(SRC)/ResetJob.$(ARCH).o \
+$(SRC)/StartHost.$(ARCH).o \
+$(SRC)/StopHosts.$(ARCH).o \
+$(SRC)/KillJob.$(ARCH).o \
+$(SRC)/StartJob.$(ARCH).o
+
+cmds = \
+$(SRC)/check.$(ARCH).o \
+$(SRC)/delete.$(ARCH).o \
+$(SRC)/host.$(ARCH).o \
+$(SRC)/job.$(ARCH).o \
+$(SRC)/jobstack.$(ARCH).o \
+$(SRC)/hoststack.$(ARCH).o \
+$(SRC)/kill.$(ARCH).o \
+$(SRC)/pulse.$(ARCH).o \
+$(SRC)/run.$(ARCH).o \
+$(SRC)/status.$(ARCH).o \
+$(SRC)/stdout.$(ARCH).o \
+$(SRC)/version.$(ARCH).o \
+$(SRC)/verbose.$(ARCH).o
+
+libs = \
+$(DESTLIB)/libbasiccmd.a \
+$(DESTLIB)/libshell.a \
+$(DESTLIB)/libdata.a
+
+pcontrol: $(BIN)/pcontrol.$(ARCH)
+$(SRC)/pcontrol.$(ARCH).o : $(libs)
+$(BIN)/pcontrol.$(ARCH)   : $(cmds) $(funcs)
+
+$(cmds) $(funcs) : $(INC)/pcontrol.h
+
+install: $(DESTBIN)/pcontrol help
+
+help: clean-help cmd.basic.help pcontrol.help
+
+.PHONY: pcontrol
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/PclientCommand.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/PclientCommand.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/PclientCommand.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "pcontrol.h"
+# define PCLIENT_TIMEOUT 5000
+
+int PclientCommand (Host *host, char *command, char *response, IOBuffer *buffer) {
+
+  int i;
+  int status;
+  char *line;
+  struct timespec request, remain;
+
+  ASSERT (host != NULL, "host missing");
+  ASSERT (buffer != NULL, "buffer missing");
+  ASSERT (command != NULL, "command missing");
+  ASSERT (response != NULL, "response missing");
+
+  /* avoid blocking on read, test every 100 usec, up to 50 msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 100000;
+
+  // flush the stdout and stderr buffers here
+  ReadtoIOBuffer (buffer, host[0].stdout_fd);
+  FlushIOBuffer (buffer);
+  ReadtoIOBuffer (buffer, host[0].stderr_fd);
+  FlushIOBuffer (buffer);
+
+  /* send command to client (adding on \n) */
+  status = write_fmt (host[0].stdin_fd, "%s\n", command);
+
+  /* is pipe still open? */
+  if ((status == -1) && (errno == EPIPE)) {
+    gprint (GP_ERR, "pclient read gives pipe error for %s\n", command);
+    return (PCLIENT_DOWN);
+  }
+  
+  /* watch for response - wait up to 1 second */
+  line = NULL;
+  status = -1;
+  for (i = 0; (i < PCLIENT_TIMEOUT) && (status != 0) && (line == NULL); i++) {
+    status = ReadtoIOBuffer (buffer, host[0].stdout_fd);
+    line = memstr (buffer[0].buffer, response, buffer[0].Nbuffer);
+    if (status == -1) nanosleep (&request, &remain);
+  }
+  if (status ==  0) {
+    gprint (GP_ERR, "pclient read returns 0 for %s\n", command);
+    return (PCLIENT_DOWN);
+  }
+  if (status == -1) return (PCLIENT_HUNG);
+  /* gprint (GP_ERR, "buffer.buffer: %s\n", buffer[0].buffer); */
+  return (PCLIENT_GOOD);
+}
+
+/* memstr returns a view, not an allocated string : don't free */
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/QueueOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/QueueOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/QueueOps.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include "pcontrol.h"
+
+/* get object from point in stack (negative == distance from end) */
+void *GetStack (Stack *stack, int where) {
+
+  int i;
+  void *object;
+  
+  ASSERT (stack != NULL, "stack missing");
+
+  /* STACK_TOP == 0, STACK_BOTTOM == -1 */
+  /* this code correctly handles the negative 'where' and Nobject == 0 */
+  if (where < 0) where += stack[0].Nobject;
+  if (where < 0) return (NULL);
+  if (where >= stack[0].Nobject) return (NULL);
+
+  object = stack[0].object[where];
+  stack[0].Nobject --;
+  for (i = where; i < stack[0].Nobject; i++) {
+    stack[0].object[i] = stack[0].object[i+1];
+  }
+  return (object);
+}
+
+/* push object on top of stack */
+int PutStack (Stack *stack, int where, void *object) {
+
+  int i;
+
+  ASSERT (stack != NULL, "stack missing");
+
+  /* STACK_TOP == 0, STACK_BOTTOM == -1 */
+  /* this code correctly handles the negative 'where' and Nobject == 0 */
+  if (where < 0) where += stack[0].Nobject + 1;
+  if (where < 0) return (FALSE);
+  if (where > stack[0].Nobject) return (FALSE);
+
+  /* extend stack as needed */
+  if (stack[0].Nobject >= stack[0].NOBJECT) {
+    stack[0].NOBJECT += 100;
+    REALLOCATE (stack[0].object, void *, stack[0].NOBJECT);
+  }
+
+  for (i = stack[0].Nobject; i > where; i--) {
+    stack[0].object[i] = stack[0].object[i-1];
+  }
+  stack[0].object[where] = object;
+  stack[0].Nobject ++;
+  return (TRUE);
+}
+
+/* allocate stack, setup with default values, allocate data */
+Stack *InitStack () {
+
+  Stack *stack;
+
+  ALLOCATE (stack, Stack, 1);
+
+  stack[0].Nobject = 0;
+  stack[0].NOBJECT = 50;
+  ALLOCATE (stack[0].object, void *, stack[0].NOBJECT);
+  return (stack);
+}
+
+/* these stacks are not super efficient, and should probably be replaced with linked lists, 
+   but I find these easier to get my brain around
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/ResetJob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/ResetJob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/ResetJob.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "pcontrol.h"
+
+int ResetJob (Job *job) {
+  
+  int       status;
+  IOBuffer  buffer;
+  Host     *host;
+
+  /** must have a valid host : if not, move to pending? **/
+  ASSERT (job != NULL, "job missing");
+
+  host = (Host *) job[0].host;
+  ASSERT (job != NULL, "host missing");
+
+  InitIOBuffer (&buffer, 0x100);
+  
+  /* we have tried to reset the job; may not get status */
+  job[0].Reset = TRUE;
+
+  status = PclientCommand (host, "reset", PCLIENT_PROMPT, &buffer);
+
+  /* check on success of pclient command */
+  switch (status) {
+    case PCLIENT_DOWN:
+      /*** different behavior for ANYHOST, WANTHOST, NEEDHOST? ***/
+      gprint (GP_ERR, "host %s is down\n", host[0].hostname);
+      HarvestHost (host[0].pid);
+      PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    case PCLIENT_HUNG:
+      /*** should we consider a HUNG host DOWN? ***/
+      gprint (GP_ERR, "host %s is not responding (ResetJob)\n", host[0].hostname);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    case PCLIENT_GOOD:
+      gprint (GP_ERR, "message received (ResetJob)\n");  
+      FreeIOBuffer (&buffer);
+      return (TRUE);
+
+    default:
+      gprint (GP_ERR, "unknown status for pclient command: programming error\n");  
+      pcontrol_exit (55);
+  }
+
+  gprint (GP_ERR, "programming error in ResetJob (should not reach here)\n");
+  FreeIOBuffer (&buffer);
+  pcontrol_exit (56);
+  return (FALSE);
+}
+
+/* if machine is down, return FALSE
+   this will place job back in BUSY state,
+   next check of job will catch state and
+   put machine down correctly
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StackOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StackOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StackOps.c	(revision 16632)
@@ -0,0 +1,224 @@
+# include "pcontrol.h"
+
+/* these stacks are not super efficient, and should probably be replaced with linked lists, 
+   but I find these easier to get my brain around.
+*/
+
+/* Stacks and thread locks: interacting with the Stacks needs to be thread-safe so that the user may
+ * perform operations which interact with the stacks at the same time that the background loops
+ * check the current status of the jobs and hosts in the different stacks.  The simplest way in
+ * which the stacks are made thread safe is to lock them with a mutex before every interaction
+ */
+
+# define DEBUG 0
+
+void PrintStackInfo (Stack *stack, const char *func) {
+
+  if (!DEBUG) return;
+  fprintf (stderr, "%s: %p  ", func, stack);
+  fprintf (stderr, "objects: %p  ", stack[0].object);
+  fprintf (stderr, "Nobjects: %d, NOBJECTS: %d\n", stack[0].Nobject, stack[0].NOBJECT);
+}
+
+/* allocate stack, setup with default values, allocate data */
+Stack *InitStack () {
+
+  Stack *stack;
+
+  ALLOCATE (stack, Stack, 1);
+
+  stack[0].Nobject = 0;
+  stack[0].NOBJECT = 50;
+
+  ALLOCATE (stack[0].object, void *, stack[0].NOBJECT);
+  ALLOCATE (stack[0].name,   char *, stack[0].NOBJECT);
+  ALLOCATE (stack[0].id,     int,    stack[0].NOBJECT);
+
+# ifdef THREADED
+  pthread_mutex_init (&stack[0].mutex, NULL);
+# endif
+  return (stack);
+}
+
+void FreeStack (Stack *stack) {
+
+  free (stack[0].object);
+  free (stack[0].name);
+  free (stack[0].id);
+  free (stack);
+}
+
+/* STACK_TOP == 0, STACK_BOTTOM == -1 */
+/* this code correctly handles the negative 'where' and Nobject == 0 */
+
+/* push object on stack at given location */
+int PushStack (Stack *stack, int where, void *object, int id, char *name) {
+
+  int i;
+
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+  LockStack (stack);
+
+  if (where < 0) where += stack[0].Nobject + 1;
+  if (where < 0) {
+    UnlockStack (stack);
+    return (FALSE);
+  }
+  if (where > stack[0].Nobject) {
+    UnlockStack (stack);
+    return (FALSE);
+  }
+
+  /* extend stack as needed */
+  if (stack[0].Nobject >= stack[0].NOBJECT) {
+    stack[0].NOBJECT += 100;
+    REALLOCATE (stack[0].object, void *, stack[0].NOBJECT);
+    REALLOCATE (stack[0].name,   char *, stack[0].NOBJECT);
+    REALLOCATE (stack[0].id,     int, stack[0].NOBJECT);
+  }
+
+  for (i = stack[0].Nobject; i > where; i--) {
+    stack[0].object[i] = stack[0].object[i-1];
+    stack[0].name[i]   = stack[0].name[i-1];
+    stack[0].id[i]     = stack[0].id[i-1];
+  }
+  stack[0].object[where] = object;
+  stack[0].name[where]   = name;
+  stack[0].id[where]     = id;
+  stack[0].Nobject ++;
+
+  UnlockStack (stack);
+  return (TRUE);
+}
+
+/* get object from specified point in stack (negative == distance from end) */
+void *PullStackByLocation (Stack *stack, int where) {
+
+  void *object;
+  
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+  LockStack (stack);
+
+  if (where < 0) where += stack[0].Nobject;
+  if (where < 0) { 
+    UnlockStack (stack); 
+    return (NULL); 
+  }
+  if (where >= stack[0].Nobject) {
+    UnlockStack (stack); 
+    return (NULL);
+  }
+
+  object = stack[0].object[where];
+  RemoveStackEntry (stack, where);
+  UnlockStack (stack); 
+  return (object);
+}
+
+/* get object from stack which matches name */
+void *PullStackByName (Stack *stack, char *name) {
+
+  int i;
+  void *object;
+
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+  LockStack (stack);
+
+  for (i = 0; i < stack[0].Nobject; i++) {
+    if (strcasecmp (stack[0].name[i], name)) continue;
+
+    /* here is the element of interest */
+    object = stack[0].object[i];
+    RemoveStackEntry (stack, i);
+    UnlockStack (stack); 
+    return (object);
+  }
+  UnlockStack (stack); 
+  return (NULL);
+}
+
+/* get object from point in stack (negative == distance from end) */
+void *PullStackByID (Stack *stack, int id) {
+
+  int i;
+  void *object;
+  
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+  LockStack (stack);
+
+  for (i = 0; i < stack[0].Nobject; i++) {
+    if (stack[0].id[i] != id) continue;
+
+    /* here is the element of interest */
+    object = stack[0].object[i];
+    RemoveStackEntry (stack, i);
+    UnlockStack (stack); 
+    return (object);
+  }
+  UnlockStack (stack); 
+  return (NULL);
+}
+
+/* should only be called if you know where is a valid entry */
+int RemoveStackEntry (Stack *stack, int where) {
+
+  int i;
+
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+
+  if (where < 0) abort();
+  if (where >= stack[0].Nobject) abort();
+  if (stack[0].Nobject < 1) abort();
+
+  /* shift the remaining entries by one */
+  /* XXX free associated memory */
+  stack[0].Nobject --;
+  for (i = where; i < stack[0].Nobject; i++) {
+    stack[0].object[i] = stack[0].object[i+1];
+    stack[0].name[i]   = stack[0].name[i+1];
+    stack[0].id[i]     = stack[0].id[i+1];
+  }
+  return (TRUE);
+}
+
+/* should only be called if you manually lock the stack */
+void *RemoveStackByID (Stack *stack, int id) {
+
+  int i;
+  void *object;
+  
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+  for (i = 0; i < stack[0].Nobject; i++) {
+    if (stack[0].id[i] != id) continue;
+
+    /* here is the element of interest */
+    object = stack[0].object[i];
+    RemoveStackEntry (stack, i);
+    return (object);
+  }
+  return (NULL);
+}
+
+void LockStack (Stack *stack) {
+# ifdef THREADED
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+  pthread_mutex_lock (&stack[0].mutex);
+# endif
+  return;
+}
+
+void UnlockStack (Stack *stack) {
+# ifdef THREADED
+  PrintStackInfo (stack, __func__);
+  ASSERT (stack != NULL, "stack not set");
+  pthread_mutex_unlock (&stack[0].mutex);
+# endif
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StartHost.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StartHost.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StartHost.c	(revision 16632)
@@ -0,0 +1,47 @@
+# include "pcontrol.h"
+# define RETRY_BASE 10.0
+
+int StartHost (Host *host) {
+
+  int pid;
+  int stdio[3];
+  char command[64], shell[64];
+  struct timeval now;
+  float delta;
+
+  /* perhaps change the name of these config variables... */
+  if (VarConfig ("COMMAND", "%s", command) == NULL) strcpy (command, "ssh");
+  if (VarConfig ("SHELL", "%s", shell)     == NULL) strcpy (shell, "pclient");
+
+  if (VerboseMode()) gprint (GP_ERR, "starting host within thread %d\n", pthread_self());
+
+  pid = rconnect (command, host[0].hostname, shell, stdio);
+  if (!pid) {     
+    /** failure to start: extend retry period **/
+    if (VerboseMode()) gprint (GP_ERR, "failure to start %s\n", host[0].hostname);
+    gettimeofday (&now, (void *) NULL);
+    if (ZTIME(host[0].nexttry) || ZTIME(host[0].lasttry)) {
+      /* reset retry period if either is zero */
+      delta = RETRY_BASE;
+    } else {
+      delta = 2*DTIME (host[0].nexttry, host[0].lasttry);
+    }
+    host[0].nexttry.tv_sec  = now.tv_sec  + delta;
+    host[0].nexttry.tv_usec = now.tv_usec;
+    host[0].lasttry.tv_sec  = now.tv_sec;
+    host[0].lasttry.tv_usec = now.tv_usec;
+    PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+    return (FALSE);
+  }
+  host[0].nexttry.tv_sec  = 0;
+  host[0].nexttry.tv_usec = 0;
+  host[0].lasttry.tv_sec  = 0;
+  host[0].lasttry.tv_usec = 0;
+
+  host[0].stdin_fd  = stdio[0];
+  host[0].stdout_fd = stdio[1];
+  host[0].stderr_fd = stdio[2];
+  host[0].pid       = pid;
+  PutHost (host, PCONTROL_HOST_IDLE, STACK_BOTTOM);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StartJob.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StartJob.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StartJob.c	(revision 16632)
@@ -0,0 +1,102 @@
+# include "pcontrol.h"
+
+int StartJob (Job *job, Host *host) {
+
+  int  i, Nline, status;
+  char *line, *p;
+  IOBuffer buffer;
+
+  InitIOBuffer (&buffer, 0x100);
+
+  /* job must have assigned host */
+  ASSERT (job != NULL, "missing job");
+  ASSERT (host != NULL, "missing host");
+  ASSERT (host == (Host *) job[0].host, "invalid host");
+  ASSERT (job  == (Job *) host[0].job, "invalid job");
+
+  /* construct command line : job arg0 arg1 ... argN\n */
+  Nline = 10 + job[0].argc;
+  for (i = 0; i < job[0].argc; i++) {
+    Nline += strlen (job[0].argv[i]);
+  }
+  ALLOCATE (line, char, Nline);
+  bzero (line, Nline);
+  strcpy (line, "job");
+  for (i = 0; i < job[0].argc; i++) {
+    strcat (line, " ");
+    strcat (line, job[0].argv[i]);
+  }
+
+  status = PclientCommand (host, line, PCLIENT_PROMPT, &buffer);
+  free (line);
+
+  /* check on success of pclient command */
+  switch (status) {
+    case PCLIENT_DOWN:
+      if (VerboseMode()) gprint (GP_ERR, "host %s is down\n", host[0].hostname);
+      goto failure;
+
+    case PCLIENT_HUNG:
+      // we need the job start to return a valid Job ID, 
+      // give up on jobs which don't get started.
+      // XXX we are sensitive here to the time it takes pclient
+      // to fork the job.  if this is slow, the client may appear to hang.
+      gprint (GP_ERR, "host %s is not responding (StartJob)\n", host[0].hostname);
+      if (VerboseMode()) gprint (GP_ERR, "host %s is not responding\n", host[0].hostname);
+
+      // unlink host & job
+      job[0].host = NULL;
+      host[0].job = NULL;
+      if (job[0].realhost) free (job[0].realhost);
+      job[0].realhost = NULL;
+      PutHost (host, PCONTROL_HOST_DONE, STACK_BOTTOM);
+      PutJob (job, PCONTROL_JOB_PENDING, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      return (FALSE);
+
+    case PCLIENT_GOOD:
+      if (VerboseMode()) gprint (GP_ERR, "message received (StartJob)\n");  
+      break;
+
+    default:
+      ABORT ("unknown status for pclient command");  
+  }
+
+  /* check on result of pclient command */
+  p = memstr (buffer.buffer, "STATUS", buffer.Nbuffer);
+  ASSERT (p != NULL, "missing STATUS in pclient message");
+
+  sscanf (p, "%*s %d", &status);
+  switch (status) {
+    case -1:
+      if (VerboseMode()) gprint (GP_ERR, "error in pclient child\n");
+      goto failure;
+
+    case -2:
+      ABORT ("syntax error in pclient command");
+
+    case -3:
+      ABORT ("existing child on pclient");
+
+    default:
+      job[0].realhost = strcreate (host[0].hostname);
+      job[0].pid = status;
+      PutHost (host, PCONTROL_HOST_BUSY, STACK_BOTTOM);
+      PutJob (job, PCONTROL_JOB_BUSY, STACK_BOTTOM);
+      FreeIOBuffer (&buffer);
+      gettimeofday (&job[0].start, (void *) NULL);
+      return (TRUE);
+  }
+  /* we should never reach here */
+  ABORT ("should not reach here (StartJob)");
+
+failure:
+  // unlink host & job
+  job[0].host = NULL;
+  host[0].job = NULL;
+  HarvestHost (host[0].pid);
+  PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+  PutJob (job, PCONTROL_JOB_PENDING, STACK_BOTTOM);
+  FreeIOBuffer (&buffer);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StopHosts.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StopHosts.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/StopHosts.c	(revision 16632)
@@ -0,0 +1,157 @@
+# include "pcontrol.h"
+
+void DownHost (Host *host) {
+  CLOSE (host[0].stdin_fd);
+  CLOSE (host[0].stdout_fd);
+  CLOSE (host[0].stderr_fd);
+  host[0].job = NULL;
+  PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+}
+
+void OffHost (Host *host) {
+  CLOSE (host[0].stdin_fd);
+  CLOSE (host[0].stdout_fd);
+  CLOSE (host[0].stderr_fd);
+  host[0].job = NULL;
+  PutHost (host, PCONTROL_HOST_OFF, STACK_BOTTOM);
+}
+
+/* for use by shutdown: force machines which are up to go down
+   wait for a little while for the client thread to take care 
+   of them
+*/
+   
+int DownHosts () {
+
+  int i, Nobject, Nwait;
+  Stack *stack;
+  Host  *host;
+
+  SetCheckPoint (); // ensure we can find the specified host
+  stack = GetHostStack (PCONTROL_HOST_IDLE);
+  ASSERT (stack != NULL, "stack missing");
+  Nobject = stack[0].Nobject;
+  for (i = 0; i < Nobject; i++) {
+    host = PullStackByLocation (stack, STACK_TOP);
+    if (host == NULL) continue;
+    host[0].markoff = TRUE;
+    PutHost (host, PCONTROL_HOST_IDLE, STACK_BOTTOM);
+  }
+
+  stack = GetHostStack (PCONTROL_HOST_BUSY);
+  ASSERT (stack != NULL, "stack missing");
+  Nobject = stack[0].Nobject;
+  for (i = 0; i < Nobject; i++) {
+    host = PullStackByLocation (stack, STACK_TOP);
+    if (host == NULL) continue;
+    host[0].markoff = TRUE;
+    PutHost (host, PCONTROL_HOST_IDLE, STACK_BOTTOM);
+  }
+  ClearCheckPoint ();
+
+  Nwait = 0;
+  stack = GetHostStack (PCONTROL_HOST_IDLE);
+  ASSERT (stack != NULL, "stack missing");
+
+  gprint (GP_ERR, "waiting for clients to exit");
+  while ((Nwait < 15) && stack[0].Nobject) {
+    gprint (GP_ERR, ".");
+    usleep (100000); // wait for clients to exit
+    Nwait++;
+  }
+  gprint (GP_ERR, "\n");
+  if (stack[0].Nobject) {
+    gprint (GP_ERR, "trouble shutting down all pclient instances: %d still alive\n", stack[0].Nobject);
+  } else {
+    gprint (GP_ERR, "done\n");
+  }
+  return (TRUE);
+}
+
+int StopHost (Host *host) {
+
+  int       status;
+  IOBuffer  buffer;
+
+  InitIOBuffer (&buffer, 0x100);
+  status = PclientCommand (host, "exit", "Goodbye", &buffer);
+  FreeIOBuffer (&buffer);
+
+  /* check on success of pclient command */
+  switch (status) {
+    case PCLIENT_DOWN:
+      break;
+
+    case PCLIENT_HUNG:
+      gprint (GP_ERR, "host %s is not responding\n", host[0].hostname);
+      break;
+
+    case PCLIENT_GOOD:
+      break;
+
+    default:
+      gprint (GP_ERR, "unknown status for pclient command: programming error\n");  
+      pcontrol_exit (57);
+  }
+  HarvestHost (host[0].pid);
+  return (TRUE);
+}
+
+/* the host is thought to be down; check for child exit status */
+int HarvestHost (int pid) {
+  
+  int i, result, waitstatus;
+
+  gprint (GP_ERR, "harvesting within thread %d\n", pthread_self());
+  gprint (GP_ERR, "child process %d is down, wait for exit status\n", pid);
+  
+  // Loop a few times waiting for child to exit
+  for (i = 0; i < 50; i++) {
+    result = waitpid (pid, &waitstatus, WNOHANG);
+    if ((result == -1) && (errno == ECHILD)) {
+      usleep (10000); // wait for child to exit
+      continue;
+    } else {
+      break;
+    }
+  }
+  switch (result) {
+    case -1:  /* error with waitpid */
+      switch (errno) {
+	case ECHILD:
+	  gprint (GP_ERR, "unknown PID, not a child proc\n");
+	  gprint (GP_ERR, "did process already exit?  programming error?\n");
+	  break;
+	case EINTR:
+	case EINVAL:
+	default:
+	  perror ("unexpected error");
+	  ABORT ("(HarvestHost)");
+      }
+      break;
+      
+    case 0:
+      gprint (GP_ERR, "child did not exit??");
+      abort ();
+      /** put back in IDLE state? **/
+      break;
+
+    default:
+      if (result != pid) {
+	gprint (GP_ERR, "waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, pid);
+	pcontrol_exit (58);
+      }
+      
+      if (WIFEXITED(waitstatus)) {
+	if (VerboseMode()) gprint (GP_ERR, "child exited with status %d\n", WEXITSTATUS(waitstatus));
+      }
+      if (WIFSIGNALED(waitstatus)) {
+	if (VerboseMode()) gprint (GP_ERR, "child crashed with status %d\n", WTERMSIG(waitstatus));
+      }
+      if (WIFSTOPPED(waitstatus)) {
+        gprint (GP_ERR, "waitpid returns 'stopped': programming error\n");
+	pcontrol_exit (59);
+      }
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/check.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/check.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/check.c	(revision 16632)
@@ -0,0 +1,58 @@
+# include "pcontrol.h"
+
+int check (int argc, char **argv) {
+
+  Job *job;
+  Host *host;
+  int JobID, HostID, StackID;
+
+  if (argc != 3) {
+    gprint (GP_LOG, "USAGE: check job (JobID)\n");
+    gprint (GP_LOG, "USAGE: check host (HostID)\n");
+    return (FALSE);
+  }
+
+  if (!strcasecmp (argv[1], "JOB")) {
+    JobID = atoi (argv[2]);
+
+    SetCheckPoint ();  // ensure the JOB is on one of the stacks
+    job = PullJobByID (JobID, &StackID);
+    if (job == NULL) {
+      gprint (GP_LOG, "job not found\n");
+      ClearCheckPoint ();
+      return (FALSE);
+    }
+    gprint (GP_LOG, "STATUS %s\n", GetJobStackName(StackID));
+    gprint (GP_LOG, "EXITST %d\n", job[0].exit_status);
+    gprint (GP_LOG, "STDOUT %d\n", job[0].stdout_size);
+    gprint (GP_LOG, "STDERR %d\n", job[0].stderr_size);
+    gprint (GP_LOG, "DTIME %lf\n", job[0].dtime);
+    if (job[0].realhost) {
+	gprint (GP_LOG, "HOSTNAME %s\n", job[0].realhost);
+    } else {
+	gprint (GP_LOG, "HOSTNAME NONE\n");
+    }
+    PutJob (job, StackID, STACK_BOTTOM);
+    ClearCheckPoint ();
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "HOST")) {
+    HostID = atoi (argv[2]);
+
+    SetCheckPoint ();  // ensure the HOST is on one of the stacks
+    host = PullHostByID (HostID, &StackID);
+    if (host == NULL) {
+      gprint (GP_LOG, "host not found\n");
+      ClearCheckPoint ();
+      return (FALSE);
+    }
+    gprint (GP_LOG, "host %s\n", GetHostStackName(StackID));
+    PutHost (host, StackID, STACK_BOTTOM);
+    ClearCheckPoint ();
+    return (TRUE);
+  }
+
+  gprint (GP_LOG, "unknown item to check\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/delete.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/delete.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/delete.c	(revision 16632)
@@ -0,0 +1,45 @@
+# include "pcontrol.h"
+
+int delete (int argc, char **argv) {
+
+  Job *job;
+  int JobID;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: delete (JobID)\n");
+    return (FALSE);
+  }
+  JobID = atoi (argv[1]);
+  /* use a string interp to convert JobIDs to ints ? */
+
+  job = PullJobFromStackByID (PCONTROL_JOB_PENDING, JobID);
+  if (job != NULL) goto found;
+
+  job = PullJobFromStackByID (PCONTROL_JOB_CRASH, JobID);
+  if (job != NULL) goto found;
+
+  job = PullJobFromStackByID (PCONTROL_JOB_EXIT, JobID);
+  if (job != NULL) goto found;
+
+  gprint (GP_ERR, "job %s not PENDING, CRASH, EXIT\n", argv[1]);
+  return (FALSE);
+  
+found:
+  {
+    int j;
+    gprint (GP_LOG, "deleting job  %s  %d  ", job[0].hostname, job[0].argc);
+    for (j = 0; j < job[0].argc; j++) {
+      gprint (GP_LOG, "%s ", job[0].argv[j]);
+    }
+    PrintID (GP_LOG, job[0].JobID);
+    gprint (GP_LOG, "\n");
+  }  
+  DelJob (job);
+
+  return (TRUE);
+}
+
+/**** at the moment, this function requires the job to be in the correct state
+      to be deleted.  This should be changed to kill, then delete job if it is 
+      not in the correct state 
+****/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/help/host
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/help/host	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/help/host	(revision 16632)
@@ -0,0 +1,1 @@
+empty
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/host.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/host.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/host.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "pcontrol.h"
+
+// we use CheckPoints in this function to prevent objects in flight from being missing.
+int host (int argc, char **argv) {
+
+  int StackID;
+  IDtype HostID;
+  Host *host;
+
+  if (argc != 3) goto usage;
+
+  if (!strcasecmp (argv[1], "ADD")) {
+    HostID = AddHost (argv[2]);
+    gprint (GP_LOG, "HostID: %d\n", (int) HostID);
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "ON")) {
+    host = PullHostFromStackByName (PCONTROL_HOST_OFF, argv[2]);
+    if (!host) {
+      gprint (GP_LOG, "host %s is not OFF\n", argv[2]);
+      return (FALSE);
+    }
+    host[0].markoff = FALSE;
+    DownHost (host);
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "RETRY")) {
+    // no need to use a check point [thief: CheckDownHost (DOWN->IDLE)]
+    host = PullHostFromStackByName (PCONTROL_HOST_DOWN, argv[2]);
+    if (!host) {
+      gprint (GP_LOG, "host %s is not DOWN\n", argv[2]);
+      return (FALSE);
+    }
+    /* reset time, place back on DOWN stack */
+    host[0].nexttry.tv_sec  = 0;
+    host[0].nexttry.tv_usec = 0;
+    host[0].lasttry.tv_sec  = 0;
+    host[0].lasttry.tv_usec = 0;
+    PutHost (host, PCONTROL_HOST_DOWN, STACK_BOTTOM);
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "CHECK")) {
+    SetCheckPoint ();  // ensure the host is on one of the stacks
+    host = PullHostByName (argv[2], &StackID);
+    if (host == NULL) {
+      gprint (GP_LOG, "host %s not found\n", argv[2]);
+      ClearCheckPoint ();
+      return (FALSE);
+    }
+    PutHost (host, StackID, STACK_BOTTOM);
+    ClearCheckPoint ();
+
+    gprint (GP_LOG, "host %s is %s\n", argv[2], GetHostStackName (StackID));
+    return (TRUE);
+  }
+  if (!strcasecmp (argv[1], "OFF")) {
+    SetCheckPoint (); // ensure we can find the specified host
+    host = PullHostByName (argv[2], &StackID);
+    if (host == NULL) {
+      gprint (GP_LOG, "host %s not found\n", argv[2]);
+      ClearCheckPoint ();
+      return (FALSE);
+    }
+    host[0].markoff = TRUE;
+    PutHost (host, StackID, STACK_BOTTOM);
+    ClearCheckPoint ();
+    return (TRUE);
+  }
+
+  if (!strcasecmp (argv[1], "DELETE")) {
+    // a check point is not required: no possible thief
+    host = PullHostFromStackByName (PCONTROL_HOST_OFF, argv[2]);
+    if (!host) {
+      gprint (GP_LOG, "host %s is not OFF\n", argv[2]);
+      return (FALSE);
+    }
+    DelHost (host);
+    return (TRUE);
+  }
+  
+usage:
+  gprint (GP_LOG, "USAGE: host (command) (hostname)\n");
+  gprint (GP_ERR, "  valid commands: add, on, retry, check, off, delete\n");
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/hoststack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/hoststack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/hoststack.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "pcontrol.h"
+
+int hoststack (int argc, char **argv) {
+
+  int i;
+  Stack *stack;
+  Host *host;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: hoststack (hoststack)\n");
+    gprint (GP_ERR, "       (hoststack) : idle, busy, done, down, off\n");
+    return (FALSE);
+  }
+
+  /* select hoststack */
+  stack = GetHostStackByName (argv[1]);
+  if (stack == NULL) {
+    gprint (GP_ERR, "hoststack not found\n");
+    return (FALSE);
+  }
+
+  /* print list */
+  LockStack (stack);
+  gprint (GP_LOG, "Nhosts: %d\n", stack[0].Nobject);
+  for (i = 0; i < stack[0].Nobject; i++) {
+    host = stack[0].object[i];
+    gprint (GP_LOG, "%lld %s\n", host[0].HostID, host[0].hostname);
+  }
+  UnlockStack (stack);
+
+  return (TRUE);
+}
+
+// Safe with PTHREAD_MUTEX_INITIALIZER lock
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/init.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/init.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/init.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "pcontrol.h"
+
+int check       PROTO((int, char **));
+int delete      PROTO((int, char **));
+int host        PROTO((int, char **));
+int hoststack   PROTO((int, char **));
+int job	        PROTO((int, char **));
+int jobstack    PROTO((int, char **));
+int kill_pc     PROTO((int, char **));
+int status      PROTO((int, char **));
+int run         PROTO((int, char **));
+int stderr_pc   PROTO((int, char **));
+int stdout_pc   PROTO((int, char **));
+int verbose     PROTO((int, char **));
+int version     PROTO((int, char **));
+
+// pulse is only available in the un-threaded version
+int pulse       PROTO((int, char **));
+
+static Command cmds[] = {  
+  {1, "host",      host,      "add / delete / modify host"},
+  {1, "hoststack", hoststack, "list hosts for a single stack"},
+  {1, "status",    status,    "get system status"},
+  {1, "stop",      run,       "stop controller processing"},
+  {1, "run",       run,       "set controller runlevel"},
+  {1, "verbose",   verbose,   "set the verbose mode for job"},
+  {1, "version",   version,   "show version information"},
+  {1, "job",       job,       "add job"},
+  {1, "jobstack",  jobstack,  "list jobs for a single stack"},
+  {1, "check",     check,     "get job or host status"},
+  {1, "delete",    delete,    "delete job"},
+  {1, "kill",      kill_pc,   "kill job"},
+  {1, "stderr",    stderr_pc, "get stderr buffer for job"},
+  {1, "stdout",    stdout_pc, "get stdout buffer for job"},
+# ifndef THREADED
+  {1, "pulse",     pulse,     "set system pulse"},
+# endif
+}; 
+
+void InitPcontrol () {
+  
+  int i;
+
+  for (i = 0; i < sizeof (cmds) / sizeof (Command); i++) {
+    AddCommand (&cmds[i]);
+  }
+  InitJobStacks ();
+  InitHostStacks ();
+}
+
+void FreePcontrol () {
+  FreeJobStacks ();
+  FreeHostStacks ();
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/job.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/job.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/job.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "pcontrol.h"
+
+int job (int argc, char **argv) {
+
+  char *Host, **targv;
+  int i, N, Mode, targc, Timeout;
+  IDtype JobID;
+
+  if (get_argument (argc, argv, "-host") && get_argument (argc, argv, "+host")) {
+      gprint (GP_ERR, "ERROR: -host and +host are incompatible\n");
+      return (FALSE);
+  }    
+
+  Host = NULL;
+  Mode = PCONTROL_JOB_ANYHOST;
+  if ((N = get_argument (argc, argv, "-host"))) {
+    remove_argument (N, &argc, argv);
+    Host = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Mode = PCONTROL_JOB_WANTHOST;
+  }
+  if ((N = get_argument (argc, argv, "+host"))) {
+    remove_argument (N, &argc, argv);
+    Host = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+    Mode = PCONTROL_JOB_NEEDHOST;
+  }
+  if (Host == NULL) Host = strcreate ("anyhost");
+ 
+  Timeout = 100;
+  if ((N = get_argument (argc, argv, "-timeout"))) {
+    remove_argument (N, &argc, argv);
+    Timeout = atoi (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: job [options] (arg0) (arg1) ... (argN)\n");
+    FREE (Host);
+    return (FALSE);
+  }
+  
+  targc = argc - 1;
+  ALLOCATE (targv, char *, targc);
+  for (i = 1; i < argc; i++) {
+    targv[i-1] = strcreate (argv[i]);
+  }
+
+  JobID = AddJob (Host, Mode, Timeout, targc, targv);
+  gprint (GP_LOG, "JobID: %d\n", (int) JobID);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/jobstack.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/jobstack.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/jobstack.c	(revision 16632)
@@ -0,0 +1,40 @@
+# include "pcontrol.h"
+
+int jobstack (int argc, char **argv) {
+
+  int i;
+  Stack *stack;
+  Job *job;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: jobstack (jobstack)\n");
+    gprint (GP_ERR, "       (jobstack) : pending, busy, exit, crash, hung, done\n");
+    return (FALSE);
+  }
+
+  /* select jobstack */
+  stack = GetJobStackByName (argv[1]);
+  if (stack == NULL) {
+    gprint (GP_ERR, "jobstack not found\n");
+    return (FALSE);
+  }
+
+  /* print list */
+  LockStack (stack);
+  gprint (GP_LOG, "Njobs: %d\n", stack[0].Nobject);
+  for (i = 0; i < stack[0].Nobject; i++) {
+    job = stack[0].object[i];
+    /* PrintID (GP_LOG, job[0].JobID); */
+    gprint (GP_LOG, "%lld ", job[0].JobID);
+    if (job[0].realhost) {
+	gprint (GP_LOG, "%s   %s\n", job[0].argv[0], job[0].realhost);
+    } else {
+	gprint (GP_LOG, "%s  (%s)\n", job[0].argv[0], job[0].hostname);
+    }
+  }
+  UnlockStack (stack);
+
+  return (TRUE);
+}
+
+// Safe with PTHREAD_MUTEX_INITIALIZER lock
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/kill.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/kill.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/kill.c	(revision 16632)
@@ -0,0 +1,24 @@
+# include "pcontrol.h"
+
+int kill_pc (int argc, char **argv) {
+
+  Job *job;
+  int JobID;
+
+  if (argc < 2) {
+    gprint (GP_ERR, "USAGE: kill (JobID)\n");
+    return (FALSE);
+  }
+  JobID = atoi (argv[1]);
+
+  /* XXX this function should only fail if a process is hung */
+  job = PullJobFromStackByID (PCONTROL_JOB_BUSY, JobID);
+  if (job == NULL) {
+    gprint (GP_ERR, "job %s not BUSY\n", argv[1]);
+    /* make output message more readable by scheduler */
+    return (FALSE);
+  }
+
+  PutJob (job, PCONTROL_JOB_KILL, STACK_BOTTOM);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/pcontrol.c.in
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/pcontrol.c.in	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/pcontrol.c.in	(revision 16632)
@@ -0,0 +1,96 @@
+# include "pcontrol.h"
+
+# define opihi_name "PCONTROL"
+# define opihi_prompt "pcontrol: "
+# define opihi_description "pcontrol client shell\n"
+# define opihi_history ".pcontrol"
+# define opihi_rcfile ".pcontrolrc"
+
+/* program-dependent initialization */
+void program_init (int *argc, char **argv) {
+  
+# ifdef THREADED  
+  pthread_t clientsThread;
+# endif
+
+  auto_break = TRUE;
+
+  /* load the commands used by this implementation */
+  InitBasic ();
+  InitPcontrol ();
+
+  /* set global signal masks (these apply to all threads launched below) */
+  signal (SIGPIPE, SIG_IGN); // must ignore SIGPIPE or we get in an infinite loop when pantasks exits
+  signal (SIGTSTP, gotsignal);
+  signal (SIGTTIN, gotsignal);
+
+  rl_readline_name = opihi_name;
+  rl_attempted_completion_function = command_completer;
+# ifdef THREADED
+  SetRunLevel (PCONTROL_RUN_ALL);
+  pthread_create (&clientsThread, NULL, &CheckSystem_Threaded, NULL);
+  rl_event_hook = NULL;
+  rl_set_keyboard_input_timeout (1000); 
+# else
+  rl_event_hook = CheckSystem;
+  rl_set_keyboard_input_timeout (1000); 
+# endif  
+
+  // set_str_variable ("HISTORY", opihi_history);
+  set_str_variable ("PROMPT", opihi_prompt);
+  set_str_variable ("RCFILE", opihi_rcfile);
+
+  {
+    char *helpdir;
+    char *modules;
+    static char *datadir = "@DATADIR@";
+    ALLOCATE (helpdir, char, strlen(datadir) + strlen("/help") + 2);
+    sprintf (helpdir, "%s/help", datadir);
+    set_str_variable ("HELPDIR", helpdir);
+    free (helpdir);
+    ALLOCATE (modules, char, strlen(datadir) + strlen("/modules") + 2);
+    sprintf (modules, "%s/modules", datadir);
+    set_str_variable ("MODULES:0", modules);
+    set_int_variable ("MODULES:n", 1);
+    free (modules);
+  }
+
+  /* ignore the history file.  to change this, see, eg, mana.c */
+  return;
+}
+
+/* standard welcome message */
+void welcome () {
+  gprint (GP_ERR, "\n");
+  gprint (GP_ERR, "Welcome to %s - %s\n\n", opihi_name, opihi_description);
+}
+
+/* add program-dependent exit functions here */
+void cleanup () {
+  DownHosts ();
+  ConfigFree ();
+
+  FreeBasic ();
+  FreePcontrol ();
+
+  return;
+}
+
+void gotsignal (int signum) {
+  // this message is lost if we are connected to a pantasks
+  fprintf (stderr, "got signal : %d\n", signum);
+  return;
+}
+
+/* call to opihi shell */
+int main (int argc, char **argv) {
+  int status;
+  status = opihi (argc, argv);
+  abort ();	
+  exit (status);
+}
+
+void pcontrol_exit (int n) {
+  abort ();
+  exit (n);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/pulse.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/pulse.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/pulse.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "pantasks.h"
+
+int pulse (int argc, char **argv) {
+
+  int Nusec;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: pulse (microseconds)\n");
+    return (FALSE);
+  }
+
+  Nusec = atoi (argv[1]);
+  rl_set_keyboard_input_timeout (Nusec); 
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/rconnect.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/rconnect.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/rconnect.c	(revision 16632)
@@ -0,0 +1,148 @@
+# include "pcontrol.h"
+
+/* connection can take a while, allow up to 2 sec */
+# define CONNECT_TIMEOUT 500
+
+/* connect to host, start the shell: ssh hostname pclient -> command hostname shell
+   stdio is an array of file descriptors (stdio[3]) 
+*/
+
+int rconnect (char *command, char *hostname, char *shell, int *stdio) {
+
+  int i, stdin_fd[2], stdout_fd[2], stderr_fd[2], status;
+  int result, waitstatus;
+  pid_t pid;
+  char *p;
+  char **argv;
+  IOBuffer buffer;
+  struct timespec request, remain;
+
+  ASSERT (command != NULL, "command is NULL");
+  ASSERT (hostname != NULL, "hostname is NULL");
+  ASSERT (shell != NULL, "shell is NULL");
+  ASSERT (stdio != NULL, "stdio is NULL");
+
+  bzero (stdin_fd,  2*sizeof(int));
+  bzero (stdout_fd, 2*sizeof(int));
+  bzero (stderr_fd, 2*sizeof(int));
+
+  if (pipe (stdin_fd)  < 0) goto pipe_error;
+  if (pipe (stdout_fd) < 0) goto pipe_error;
+  if (pipe (stderr_fd) < 0) goto pipe_error;
+
+  ALLOCATE (argv, char *, 4);
+  argv[0] = command;
+  argv[1] = hostname;
+  argv[2] = shell;
+  argv[3] = 0;
+
+  pid = fork ();
+  if (!pid) { /* must be child process */
+    if (VerboseMode()) gprint (GP_ERR, "starting remote connection to %s...", hostname);
+
+    /* close the other ends of the pipes */
+    close (stdin_fd[1]);
+    close (stdout_fd[0]);
+    close (stderr_fd[0]);
+
+    /* tie our ends of the pipes to stdin, stdout, stderr */
+    dup2 (stdin_fd[0],  STDIN_FILENO);
+    dup2 (stdout_fd[1], STDOUT_FILENO);
+    dup2 (stderr_fd[1], STDERR_FILENO);
+
+    /* set all three unblocking */
+    setvbuf (stdin,  (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stdout, (char *) NULL, _IONBF, BUFSIZ);
+    setvbuf (stderr, (char *) NULL, _IONBF, BUFSIZ);
+
+    status = execvp (argv[0], argv); 
+    gprint (GP_ERR, "error starting remote shell process\n");
+    pcontrol_exit (60);
+  }
+  free (argv);
+
+  /* close the other ends of the pipes */
+  close (stdin_fd[0]);  stdin_fd[0]  = 0;
+  close (stdout_fd[1]); stdout_fd[1] = 0;
+  close (stderr_fd[1]); stderr_fd[1] = 0;
+
+  /* make the pipes non-blocking */
+  fcntl (stdin_fd[1],  F_SETFL, O_NONBLOCK);
+  fcntl (stdout_fd[0], F_SETFL, O_NONBLOCK);
+  fcntl (stderr_fd[0], F_SETFL, O_NONBLOCK);
+
+  /* perform handshake with pclient to verify alive & running */
+  /** this handshake is similar to PclientCommand, but has important differences **/
+  InitIOBuffer (&buffer, 0x100);
+
+  /* send handshake command */
+  status = write_fmt (stdin_fd[1], "echo CONNECTED\n");
+  if ((status == -1) && (errno == EPIPE)) goto connect_error;
+
+  /* try to get evidence connection is alive - wait upto a few seconds */
+  p = NULL;
+  status = -1;
+  for (i = 0; (i < CONNECT_TIMEOUT) && (status != 0) && (p == NULL); i++) {
+    status = ReadtoIOBuffer (&buffer, stdout_fd[0]);
+    p = memstr (buffer.buffer, "CONNECTED", buffer.Nbuffer);
+    usleep (10000); // wait for client to be connected
+  }
+  if (status == 0) goto connect_error;
+  if (status == -1) goto connect_error;
+  if (VerboseMode()) gprint (GP_ERR, "%d cycles to connect\n", i);
+  FreeIOBuffer (&buffer);
+
+  if (VerboseMode()) gprint (GP_ERR, "Connected\n");
+
+  stdio[0] = stdin_fd[1];
+  stdio[1] = stdout_fd[0];
+  stdio[2] = stderr_fd[0];
+
+  return (pid);
+
+pipe_error:
+  perror ("pipe error:");
+  goto close_pipes;
+
+connect_error:
+  if (VerboseMode()) gprint (GP_ERR, "error while connecting\n");
+
+  /* avoid blocking on waitpid, test every 100 usec, up to 50 msec */
+  request.tv_sec = 0;
+  request.tv_nsec = 100000;
+
+  /* harvest the child process: kill & wait (< 100 ms) for exit */
+  kill (pid, SIGKILL);
+  result = waitpid (pid, &waitstatus, WNOHANG);
+  for (i = 0; (i < 50) && (result == 0); i++) {
+    nanosleep (&request, &remain);
+    result = waitpid (pid, &waitstatus, WNOHANG);
+  }
+
+  if ((result == -1) && (errno != ECHILD)) {
+    gprint (GP_ERR, "unexpected error from waitpid (%d): programming error\n", errno);
+    pcontrol_exit (61);
+  }
+  if (result == 0) {
+    if (VerboseMode()) gprint (GP_ERR, "child did not exit (rconnect)??");
+  }
+  if (result > 0) {
+    if (result != pid) {
+      gprint (GP_ERR, "waitpid error: mis-matched PID (%d vs %d).  programming error\n", result, pid);
+      pcontrol_exit (62);
+    }
+    if (WIFSTOPPED(waitstatus)) {
+      gprint (GP_ERR, "waitpid returns 'stopped': programming error\n");
+      pcontrol_exit (63);
+    }
+  }
+
+close_pipes:
+  if (stdin_fd[0]  != 0) close (stdin_fd[0]);
+  if (stdin_fd[1]  != 0) close (stdin_fd[1]);
+  if (stdout_fd[0] != 0) close (stdout_fd[0]);
+  if (stdout_fd[1] != 0) close (stdout_fd[1]);
+  if (stderr_fd[0] != 0) close (stderr_fd[0]);
+  if (stderr_fd[1] != 0) close (stderr_fd[1]);
+  return (FALSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/run.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/run.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/run.c	(revision 16632)
@@ -0,0 +1,66 @@
+# include "pcontrol.h"
+
+int run (int argc, char **argv) {
+
+  RunLevels level;
+
+  if ((argc > 2) ||
+      get_argument (argc, argv, "help") ||
+      get_argument (argc, argv, "-h") ||
+      get_argument (argc, argv, "--help")) 
+  {
+    if (!strcmp (argv[0], "run")) {
+      gprint (GP_ERR, "USAGE: run [level]\n");
+      gprint (GP_ERR, "  allowed levels:\n");
+      gprint (GP_ERR, "  all (default) : manage machines, spawn jobs, harvest jobs\n");
+      gprint (GP_ERR, "  reap          : manage machines, harvest jobs\n");
+      gprint (GP_ERR, "  hosts         : manage machines, not jobs\n");
+      gprint (GP_ERR, "  none          : all stop\n");
+    } else {
+      gprint (GP_ERR, "USAGE: stop (immediate processing halt)\n");
+    }
+    return (FALSE);
+  }
+
+  level = PCONTROL_RUN_UNKNOWN;
+  if (argc == 1) {
+    if (!strcasecmp (argv[0], "run")) level = PCONTROL_RUN_ALL;
+    if (!strcasecmp (argv[0], "stop")) level = PCONTROL_RUN_NONE;
+  } else {
+    if (!strcasecmp (argv[1], "all")) level = PCONTROL_RUN_ALL;
+    if (!strcasecmp (argv[1], "reap")) level = PCONTROL_RUN_REAP;
+    if (!strcasecmp (argv[1], "host")) level = PCONTROL_RUN_HOSTS;
+    if (!strcasecmp (argv[1], "hosts")) level = PCONTROL_RUN_HOSTS;
+    if (!strcasecmp (argv[1], "none")) level = PCONTROL_RUN_NONE;
+  }
+
+  if (level == PCONTROL_RUN_UNKNOWN) {
+    gprint (GP_ERR, "  unknown run level %s\n", argv[1]);
+    gprint (GP_ERR, "  allowed levels:\n");
+    gprint (GP_ERR, "  all (default) : manage machines, spawn jobs, harvest jobs\n");
+    gprint (GP_ERR, "  reap          : manage machines, harvest jobs\n");
+    gprint (GP_ERR, "  hosts         : manage machines, not jobs\n");
+    gprint (GP_ERR, "  none          : all stop\n");
+    return (FALSE);
+  }
+
+# ifdef THREADED
+  SetRunLevel (level);
+# else
+  if (level == PCONTROL_RUN_NONE) {
+    rl_event_hook = NULL;
+  } else {
+    rl_event_hook = CheckSystem;
+  }
+# endif
+
+  return (TRUE);
+}
+
+/* 
+   run levels:
+   all (manage machines, spawn jobs, harvest jobs)
+   reap (manage machines, harvest jobs)
+   hosts (manage machines, not jobs)
+   none (all stop)
+*/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/status.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/status.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/status.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "pcontrol.h"
+
+int PrintJobStack (int Nstack);
+int PrintHostStack (int Nstack);
+
+int status (int argc, char **argv) {
+
+  SetCheckPoint ();
+  PrintJobStack (PCONTROL_JOB_PENDING);
+  PrintJobStack (PCONTROL_JOB_BUSY);
+  PrintJobStack (PCONTROL_JOB_DONE);
+  PrintJobStack (PCONTROL_JOB_KILL);
+  PrintJobStack (PCONTROL_JOB_EXIT);
+  PrintJobStack (PCONTROL_JOB_CRASH);
+
+  PrintHostStack (PCONTROL_HOST_OFF);
+  PrintHostStack (PCONTROL_HOST_DOWN);
+  PrintHostStack (PCONTROL_HOST_IDLE);
+  PrintHostStack (PCONTROL_HOST_BUSY);
+  PrintHostStack (PCONTROL_HOST_DONE);
+  ClearCheckPoint ();
+  return (TRUE);
+}
+
+int PrintJobStack (int Nstack) {
+
+  int i, j, Nobject;
+  Stack *stack;
+  Job *job;
+
+  stack = GetJobStack (Nstack);
+  ASSERT (stack != NULL, "programming error");
+
+  LockStack (stack);
+  Nobject = stack[0].Nobject;
+  gprint (GP_LOG, "job stack %s:  %d objects\n", GetJobStackName(Nstack), Nobject);
+
+  for (i = 0; i < Nobject; i++) {
+    job = stack[0].object[i];
+    ASSERT (job != NULL, "programming error");
+    gprint (GP_LOG, "%d  %s  %d  ", i, job[0].hostname, job[0].argc);
+    for (j = 0; j < job[0].argc; j++) {
+      gprint (GP_LOG, "%s ", job[0].argv[j]);
+    }
+    PrintID (GP_LOG, job[0].JobID);
+    gprint (GP_LOG, "\n");
+  }
+  UnlockStack (stack);
+
+  return (TRUE);
+}
+
+int PrintHostStack (int Nstack) {
+
+  int i, Nobject;
+  Stack *stack;
+  Host *host;
+
+  stack = GetHostStack (Nstack);
+
+  LockStack (stack);
+  Nobject = stack[0].Nobject;
+  gprint (GP_LOG, "host stack %s:  %d objects\n", GetHostStackName(Nstack), Nobject);
+
+  for (i = 0; i < Nobject; i++) {
+    host = stack[0].object[i];
+    gprint (GP_LOG, "%d  %s  ", i, host[0].hostname);
+    PrintID (GP_LOG, host[0].HostID);
+    gprint (GP_LOG, "\n");
+  }
+  UnlockStack (stack);
+
+  return (TRUE);
+}
+
+// Safe with PTHREAD_MUTEX_INITIALIZER lock
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/stdout.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/stdout.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/stdout.c	(revision 16632)
@@ -0,0 +1,71 @@
+# include "pcontrol.h"
+
+int stdout_pc (int argc, char **argv) {
+
+  int JobID, StackID;
+  Job *job;
+  IOBuffer *buffer;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: stdout (JobID)\n");
+    gprint (GP_LOG, "STATUS %d\n", -1);
+    return (FALSE);
+  }
+  
+  /* find Job of interest (must be EXIT or CRASH) */
+  JobID = atoi (argv[1]);
+
+  StackID = PCONTROL_JOB_EXIT;
+  job = PullJobFromStackByID (StackID, JobID);
+  if (job != NULL) goto found_stdout;
+
+  StackID = PCONTROL_JOB_CRASH;
+  job = PullJobFromStackByID (StackID, JobID);
+  if (job != NULL) goto found_stdout;
+
+  gprint (GP_ERR, "job not found in EXIT or CRASH\n");
+  gprint (GP_LOG, "STATUS %d\n", -2);
+  return (FALSE);
+
+found_stdout:
+  buffer = &job[0].stdout_buff;
+  fwrite (buffer[0].buffer, 1, buffer[0].Nbuffer, stdout);
+  gprint (GP_LOG, "STATUS %d\n", 0);
+  PutJob (job, StackID, STACK_BOTTOM);
+  return (TRUE);
+}
+
+int stderr_pc (int argc, char **argv) {
+
+  int JobID, StackID;
+  Job *job;
+  IOBuffer *buffer;
+
+  if (argc != 2) {
+    gprint (GP_ERR, "USAGE: stderr (JobID)\n");
+    gprint (GP_LOG, "STATUS %d\n", -1);
+    return (FALSE);
+  }
+  
+  /* find Job of interest (must be EXIT or CRASH) */
+  JobID = atoi (argv[1]);
+
+  StackID = PCONTROL_JOB_EXIT;
+  job = PullJobFromStackByID (StackID, JobID);
+  if (job != NULL) goto found_stderr;
+
+  StackID = PCONTROL_JOB_CRASH;
+  job = PullJobFromStackByID (StackID, JobID);
+  if (job != NULL) goto found_stderr;
+
+  gprint (GP_ERR, "job not found in EXIT or CRASH\n");
+  gprint (GP_LOG, "STATUS %d\n", -2);
+  return (FALSE);
+
+found_stderr:
+  buffer = &job[0].stderr_buff;
+  fwrite (buffer[0].buffer, 1, buffer[0].Nbuffer, stdout);
+  gprint (GP_LOG, "STATUS %d\n", 0);
+  PutJob (job, StackID, STACK_BOTTOM);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/stop.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/stop.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/stop.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "pcontrol.h"
+
+int stop (int argc, char **argv) {
+
+  if (argc != 1) {
+    gprint (GP_ERR, "USAGE: stop\n");
+    return (FALSE);
+  }
+
+# ifdef THREADED
+  SetRunSystem (FALSE);
+# else
+  rl_event_hook = NULL;
+# endif
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/verbose.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/verbose.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/verbose.c	(revision 16632)
@@ -0,0 +1,37 @@
+# include "pcontrol.h"
+
+static int VERBOSE = FALSE;
+
+int verbose (int argc, char **argv) {
+
+  if (argc == 1) {
+    if (VERBOSE) {
+      gprint (GP_ERR, "verbose mode ON\n");
+    } else {
+      gprint (GP_ERR, "verbose mode OFF\n");
+    }
+    return (TRUE);
+  }
+
+  if (argc == 2) {
+    if (!strcasecmp (argv[1], "ON")) {
+      VERBOSE = TRUE;
+      return (TRUE);
+    }
+    if (!strcasecmp (argv[1], "OFF")) {
+      VERBOSE = FALSE;
+      return (TRUE);
+    }
+    if (!strcasecmp (argv[1], "TOGGLE")) {
+      VERBOSE = ~VERBOSE;
+      return (TRUE);
+    }
+  }
+
+  gprint (GP_ERR, "USAGE: verbose (on/off/toggle)\n");
+  return (FALSE);
+}
+
+int VerboseMode () {
+  return (VERBOSE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/version.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/version.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/pcontrol/version.c	(revision 16632)
@@ -0,0 +1,17 @@
+# include "pcontrol.h"
+static char *name = "$Name: not supported by cvs2svn $";
+
+int version (int argc, char **argv) {
+
+  char *tmp;
+
+  gprint (GP_LOG, "\n");
+  gprint (GP_LOG, "pcontrol version: %s\n", (tmp = strip_version (name))); free (tmp);
+
+  gprint (GP_LOG, "opihi version: %s\n", (tmp = strip_version (opihi_version()))); free (tmp);
+  gprint (GP_LOG, "ohana version: %s\n", (tmp = strip_version (ohana_version()))); free (tmp);
+  gprint (GP_LOG, "gfits version: %s\n", (tmp = strip_version (gfits_version()))); free (tmp);
+
+  gprint (GP_LOG, "compiled on %s %s\n", __DATE__, __TIME__);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copy.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copy.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copy.pro	(revision 16632)
@@ -0,0 +1,136 @@
+
+# identify the images ready for copy 
+task	       new.images
+  command      new.images
+  host         local
+
+  periods      -poll 1
+  periods      -exec 30
+  periods      -timeout 2
+
+  # success
+  task.exit    0
+    push new.images $stdout
+    $new.image.failure = 0
+  end
+
+  # locked list
+  task.exit    1
+    echo       "new.images: exec failure"
+    $new.image.failure ++
+  end
+
+  # default exit status
+  task.exit    -
+    echo       "new.images: unknown exit status: $EXIT"
+    $new.image.failure ++
+  end
+
+  # operation times out?
+  task.exit    timeout
+    echo       "new.images: timeout"
+    $new.image.failure ++
+  end
+end
+
+# copy specific images from the summit
+task           copy.images
+
+  # these define task properties which are fixed
+
+  period       -exec 2
+  period       -poll 1
+  period       -timeout 50
+
+  # these commands are executed at the start of a new task
+  task.exec
+    local        RemoteName
+    local        FileID
+    local        Host
+
+    queuesize  NewImages -var N
+    if ($N > 0) break
+    if ($network == 0) break
+    if ($filesystem == 1) break
+
+    pop NewImages -var line
+    list tmp -split $line
+    $RemoteName = $tmp:0
+    $FileID     = $tmp:1
+    $Host       = $tmp:2
+    $Ntry       = $tmp:3
+
+    stderr       /data/logfiles/copy/$FileID.log
+    stdout       -queue $FileIDlog
+
+    echo $TaskID
+    echo $TaskName
+    spawn copy.images $RemoteName $FileID $Host -host $Host
+  end
+
+  # success
+  task.exit      0
+    $new.image.failure --
+  end
+
+  # summmit connection failed
+  task.exit      1
+    echo         "copy.images: copy failed $RemoteName $FileID"
+    push         NewImages "$RemoteName $FileID $Host 0"
+    $copy.image.failure ++
+  end
+
+  # target disk full
+  task.exit      2
+    echo         "copy.images: disk full"
+    push         NewImages "$RemoteName $FileID $Host 0"
+    $copy.image.failure ++
+  end
+
+  # file not found
+  task.exit      3
+    echo         "copy.images: missing file"
+    # send a message to OTIS?
+  end
+
+  # task timed out
+  task.exit      timeout
+    echo        "copy.images: timeout"
+    push        NewImages "$RemoteName $FileID $Host 0"
+    $copy.image.failure ++
+  end
+end
+
+# identify the images ready for copy 
+TASK	       new.images
+  COMMAND      new.images
+  HOST         -
+  STDERR       /data/logfiles/new.images.log
+  STDOUT       $stdout
+  EXEC_PERIOD  30
+  POLL_PERIOD  1
+
+  # success
+  EXIT         0
+    STDOUT     @new.images
+    $new.image.failure = 0
+  END
+
+  # locked list
+  EXIT         1
+    MESSAGE    "new.images: exec failure"
+    $new.image.failure ++
+  END
+
+  # default exit status
+  EXIT         -
+    MESSAGE    "new.images: unknown exit status: $EXIT"
+    $new.image.failure ++
+  END
+
+  # operation times out?
+  TIMEOUT      2
+    MESSAGE    "new.images: timeout"
+    $new.image.failure ++
+  END
+END
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copypool.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copypool.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copypool.pro	(revision 16632)
@@ -0,0 +1,117 @@
+
+## A test task to demonstrate cycled copying using pending and done pools (directories)
+##   and pending queues
+
+queueinit stdout
+queueinit stderr
+queueinit pending
+
+$indir = dir.01
+$outdir = dir.02
+
+# set the test rate to be 1ms
+pulse 1000
+
+macro init
+  exec rm -r dir.*
+  exec mkdir $indir
+  exec mkdir $outdir
+end
+
+$Nfile = 0
+task pool.create
+  periods -exec 0.02
+  periods -poll 0.02
+
+  task.exec
+    sprintf filename "foo.%04d.dat" $Nfile
+    $Nfile ++
+    host local
+    command copypool.sh -create $indir $filename
+  end
+
+  task.exit  default
+    queueinit stdout
+    queueinit stderr
+  end
+end
+
+task pool.pending
+  command copypool.sh -pending $indir
+  host local
+
+  periods -exec 5
+  periods -poll 1
+
+  # success
+  task.exit    0
+    local i Nstdout
+
+    # keep only new, unique entries (name is key)
+    queuesize stdout -var Nstdout
+    for i 0 $Nstdout
+      queuepop stdout -var line
+      queuepush pending -uniq -key 0 "$line new"
+    end
+    queueprint pending
+  end
+end
+
+task pool.copy
+  host local
+
+  periods -exec 1
+  periods -poll 1
+
+  task.exec
+    local Npending
+    queuesize pending -var Npending
+    if ($Npending == 0) 
+      periods -exec 1
+      periods -poll 1
+      break
+    end
+
+    # if data is available, run fast to clear it out
+    periods -exec 0.002
+    periods -poll 0.002
+
+    # this step grabs and entry by key and updates a field
+    # can we do this in one step?
+    queuepop pending -var line -key 1 new
+    if ("$line" == "NULL") break
+
+    list tmp -split $line
+    $name = $tmp:0
+
+    queuepush pending "$name run"
+
+    host local
+    command copypool.sh -copy $outdir $name
+  end
+
+  # success
+  task.exit 0
+    echo "done with $taskarg:3"
+    queueinit stdout
+    queueinit stderr
+    queuepop pending -key 0 $taskarg:3 -var line
+    # echo "got line: $line"
+
+    if ("$line" == "NULL") 
+      echo "missing entry in pending queue?"
+      break
+    end
+  end
+end
+
+task pool.list
+  host local
+  periods -exec 3
+  command queueprint pending
+
+  task.exit default
+    queueinit stdout
+    queueinit stderr
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copypool.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copypool.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/copypool.sh	(revision 16632)
@@ -0,0 +1,31 @@
+#!/bin/csh -f
+
+# copypool.sh -pending (indir)
+# copypool.sh -copy (outdir) (path)
+# copypool.sh -create (outdir) (name)
+
+if ($#argv < 2) then
+  echo "USAGE: copypool.sh -pending (indir)"
+  echo "USAGE: copypool.sh -copy (outdir) (path)"
+  echo "USAGE: copypool.sh -create (outdir) (name)"
+  exit 2
+endif
+
+if ("$1" == "-pending") then
+  set n = `ls $2 | wc -l`
+  if ($n == 0) exit 0
+  ls $2/* | cat
+  exit 0
+endif
+
+if ("$1" == "-copy") then
+  set name = `basename $3`
+  rm $3
+  touch $2/$name
+  exit 0
+endif
+
+if ("$1" == "-create") then
+  touch $2/$3
+  exit 0
+endif
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/diff-opihi
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/diff-opihi	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/diff-opihi	(revision 16632)
@@ -0,0 +1,38 @@
+#!/bin/csh -f
+
+# this just organizes the tagging of the opihi components
+
+if ($#argv != 2) then
+  echo "USAGE: tag-elixir (MODULE) (TAG)"
+  echo "  MODULE choices: base mana dvo dimm pantasks pcontrol pclient"
+  exit 2
+endif
+
+if ("$1" == "base") then
+  cvs diff -r $2 Makefile
+  cvs diff -r $2 Makefile.Common
+  cvs diff -r $2 include
+  cvs diff -r $2 test
+  cvs diff -r $2 lib.data
+  cvs diff -r $2 lib.shell
+  cvs diff -r $2 cmd.astro
+  cvs diff -r $2 cmd.basic
+  cvs diff -r $2 cmd.data
+  cvs diff -r $2 scripts
+  cvs diff -r $2 doc
+  exit 0;
+endif
+
+if ("$1" == "mana") goto valid;
+if ("$1" == "dvo") goto valid;
+if ("$1" == "dimm") goto valid;
+if ("$1" == "pantasks") goto valid;
+if ("$1" == "pclient") goto valid;
+if ("$1" == "pcontrol") goto valid;
+echo "invalid opihi module $1"
+exit 1;
+
+valid:
+  # diff the module ($1) with the specified tag ($2)
+  cvs diff -r $2 $1
+  exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/jobs.plot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/jobs.plot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/jobs.plot	(revision 16632)
@@ -0,0 +1,24 @@
+
+macro jobs.rates
+ clear -s
+
+ section a 0.0 0.0 1.0 0.5
+ data jobs.stop.dat
+ read t 6
+ set T = t*(t > 30) + (t+60)*(t<30)
+ create n 0 t[]
+ lim T n; box; plot T n
+ subset tf = T if (T > 70)
+ subset nf = n if (T > 70)
+ fit tf nf 1
+ 
+ section b 0.0 0.5 1.0 0.5
+ data jobs.run.dat
+ read t 6
+ set T = t*(t > 30) + (t+60)*(t<30)
+ create n 0 t[]
+ lim T n; box; plot T n
+ subset tf = T if (T > 70)
+ subset nf = n if (T > 70)
+ fit tf nf 1
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/manytasks.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/manytasks.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/manytasks.pro	(revision 16632)
@@ -0,0 +1,72 @@
+
+controller exit true
+controller host add kiawe
+
+$Ntest = 0
+pulse 1000
+controller pulse 1000
+
+macro load.machines
+  if ($0 != 2)
+    echo "load.machines (nmach)"
+    break
+  end
+
+  for i 0 $1
+    $n = $i + 1
+    sprintf host "po%02d" $n
+    controller host add $host
+  end
+end
+
+macro mktask
+  if ($0 != 2)
+    echo "USAGE: mktask (n)"
+    break
+  end
+
+  $N = $1
+
+  task test.$N
+    command partest
+    # polling period is no longer valid: we check for completed controller tasks
+    # correction: still valid for local tasks
+    periods -poll 0.2
+    periods -exec 0.01
+    periods -timeout 10.0
+    nmax 20
+    host anyhost
+
+    # stdout / stderr lines on named queues
+    task.exit 0
+      # echo "task exit 0"
+      queuedelete stdout
+      queuedelete stderr
+      date date
+      queuepush done "$date"
+      $Ntest ++
+    end
+
+    task.exit 1
+      # echo "task exit 1"
+      queuesize stdout
+      queuesize stderr
+    end
+
+    task.exit crash
+      echo "crashed job"
+    end
+
+    task.exit timeout
+      output timeout.log
+      echo $stdout
+      output stdout
+    end
+  end
+end
+
+macro mktasks
+ for i 0 $1
+  mktask $i
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/psched.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/psched.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/psched.pro	(revision 16632)
@@ -0,0 +1,99 @@
+
+controller exit true
+# controller host add kiawe
+$Ntest = 0
+# controller host add alala
+# verbose on
+pulse 1000
+controller pulse 1000
+
+macro load.machines
+  if ($0 != 2)
+    echo "load.machines (nmach)"
+    break
+  end
+
+  for i 0 $1
+    $n = $i + 1
+    sprintf host "po%02d" $n
+    controller host add $host
+  end
+end
+
+task test
+  command partest
+  # polling period is no longer valid: we check for completed controller tasks
+  # correction: still valid for local tasks
+  periods -poll 0.20
+  periods -exec 0.0001
+  periods -timeout 10.0
+  nmax 1024
+#  nmax 100
+  host anyhost
+
+  # stdout / stderr lines on named queues
+  task.exit 0
+    # echo "task exit 0"
+    queuedelete stdout
+    queuedelete stderr
+    date date
+    queuepush done "$date"
+    $Ntest ++
+#   memory leaks
+#   queuesize stdout -var Nstdout
+#    for i 0 $Nstdout
+#      queuepop stdout -var line
+#      queuepush results "$line"
+#    end
+  end
+
+  task.exit 1
+    # echo "task exit 1"
+    queuesize stdout
+    queuesize stderr
+  end
+
+  task.exit crash
+    echo "crashed job"
+  end
+
+  task.exit timeout
+    output timeout.log
+    echo $stdout
+    output stdout
+  end
+end
+
+# pulse == 100ms
+# poll/exit = 0.2  : 29 sec / 100 jobs
+# poll/exit = 0.1  : 20 sec / 100 jobs
+# poll/exit = 0.05 : 17 sec / 100 jobs
+# poll/exit = 0.01 : 18 sec / 100 jobs
+
+# pulse == 10ms
+# poll/exit = 0.2  : 20 sec / 100 jobs
+# poll/exit = 0.10 : 12 sec / 100 jobs
+# poll/exit = 0.05 : 12 sec / 100 jobs
+# poll/exit = 0.01 :  9 sec / 100 jobs
+
+# we are limited here by how quickly we can send data to the 
+# controller.  this is limited by the occasional 'CheckSystem'
+# loops, with ~40ms minimum.
+
+# seems to be faster on po01 from kiawe (less interference?)
+
+# pulse == 1ms, controller pulse == 1ms
+# poll/exit = 0.01 :  3 sec / 100 jobs
+# 2 mach, 3 sec
+# 4 mach, 3 sec
+# 8 mach, 3 sec
+
+# 16 machines, 500 jobs, 13 sec: 26ms / job
+# 32 machines, 1024 jobs, 26 sec: 26ms / job
+# job harvesting rate is still the limitation.  Each job harvest requires:
+#  - jobstack exit
+#  - stdout
+#  - stderr
+#  - delete
+#  - jobstack crash
+
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/queuetests
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/queuetests	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/queuetests	(revision 16632)
@@ -0,0 +1,19 @@
+
+macro test.unique
+  list line -x "cat new.list"
+  for i 0 $line:n
+    push t1 "$line:$i"
+  end
+
+  queuelist
+  queuesize t1
+
+  list line -x "cat copy.list"
+  for i 0 $line:n
+    push t1 "$line:$i" -uniq
+  end
+
+  queuelist
+  queuesize t1
+
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/rdiff-elixir
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/rdiff-elixir	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/rdiff-elixir	(revision 16632)
@@ -0,0 +1,31 @@
+#!/bin/csh -f
+
+# this just organizes the tagging of the elixir components
+
+if ($#argv != 1) then
+  echo "USAGE: rdiff-elixir (TAG)"
+  exit 2
+endif
+
+cvs rdiff -r $1 opihi/Makefile
+cvs rdiff -r $1 opihi/bin/
+cvs rdiff -r $1 opihi/cmd.astro/
+cvs rdiff -r $1 opihi/cmd.basic/
+cvs rdiff -r $1 opihi/cmd.data/
+cvs rdiff -r $1 opihi/doc/
+cvs rdiff -r $1 opihi/dvo/
+cvs rdiff -r $1 opihi/help/
+cvs rdiff -r $1 opihi/include/
+cvs rdiff -r $1 opihi/lib/
+cvs rdiff -r $1 opihi/lib.data/
+cvs rdiff -r $1 opihi/lib.shell/
+cvs rdiff -r $1 opihi/mana/
+cvs rdiff -r $1 opihi/scripts/
+
+# don't place tag on these implementations
+# cvs tag $1 dimm/
+# cvs tag $1 dvo2/
+# cvs tag $1 old/
+# cvs tag $1 pclient/
+# cvs tag $1 pcontrol/
+# cvs tag $1 sched/
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/run.pclient
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/run.pclient	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/run.pclient	(revision 16632)
@@ -0,0 +1,4 @@
+#!/bin/csh -f
+
+# pclient
+mana
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/sample.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/sample.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/sample.sh	(revision 16632)
@@ -0,0 +1,9 @@
+#!/usr/bin/env dvo
+
+echo "test"
+
+for i 0 $argv:n
+ echo $i $argv:$i
+end
+
+exit 0
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/sched.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/sched.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/sched.pro	(revision 16632)
@@ -0,0 +1,43 @@
+
+task test
+  command ls
+  periods -poll 1.0
+  periods -exec 2.0
+  periods -timeout 10.0
+  # trange 07:09 07:10
+  # trange -exclude 07:09:30 07:09:45
+  nmax 5
+  host local
+  # host localhost
+  # local is default 
+
+  task.exec
+    # echo "starting job sched.test"
+  end
+
+  # stdout / stderr lines on named queues
+  task.exit 0
+#    echo "task exit 0"
+#    queuesize stdout
+#    queuesize stderr
+    queuedelete stdout
+    queuedelete stderr
+    memory leaks
+  end
+
+  task.exit 1
+    echo "task exit 1"
+    queuesize stdout
+    queuesize stderr
+  end
+
+  task.exit crash
+    echo "crashed job"
+  end
+
+  task.exit timeout
+    output timeout.log
+    echo $stdout
+    output stdout
+  end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/tag-opihi
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/tag-opihi	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/tag-opihi	(revision 16632)
@@ -0,0 +1,38 @@
+#!/bin/csh -f
+
+# this just organizes the tagging of the opihi components
+
+if ($#argv != 2) then
+  echo "USAGE: tag-elixir (MODULE) (TAG)"
+  echo "  MODULE choices: base mana dvo dimm pantasks pcontrol pclient"
+  exit 2
+endif
+
+if ("$1" == "base") then
+  cvs tag $2 Makefile
+  cvs tag $2 Makefile.Common
+  cvs tag $2 include/
+  cvs tag $2 test/
+  cvs tag $2 lib.data/
+  cvs tag $2 lib.shell/
+  cvs tag $2 cmd.astro/
+  cvs tag $2 cmd.basic/
+  cvs tag $2 cmd.data/
+  cvs tag $2 scripts/
+  cvs tag $2 doc/
+  exit 0;
+endif
+
+if ("$1" == "mana") goto valid;
+if ("$1" == "dvo") goto valid;
+if ("$1" == "dimm") goto valid;
+if ("$1" == "pantasks") goto valid;
+if ("$1" == "pclient") goto valid;
+if ("$1" == "pcontrol") goto valid;
+echo "invalid opihi module $1"
+exit 1;
+
+valid:
+  # tag the module ($1) with the specified tag ($2)
+  cvs tag $2 $1
+  exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/test.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/test.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/test.pro	(revision 16632)
@@ -0,0 +1,144 @@
+
+macro testgauss
+ create x -20 20 0.1
+ set dy = zero(x) + 0.03
+ set X = x - $1
+ set y = $3*exp(-0.5*(X^2/$2^2)) + $4 + 0.1*(rnd(X) - 0.5)
+# set y = $3*exp(-0.5*(X^2/$2^2)) + $4
+ lim x y; clear; box; plot x y -dy dy -x 2 -pt 2
+
+ $C0 = $1+5
+ $C1 = $2-10
+ $C2 = $3
+ $C3 = $4
+
+ vgauss x y dy yf
+end
+
+macro testpoor
+ create x -20 20 0.1
+ set dy = zero(x) + 0.03
+ set X = x - $1
+ set y = 3 + zero(x) + 0.1*(rnd(X) - 0.5)
+# set y = (x + 20)/10 + $4 + 0.1*(rnd(X) - 0.5)
+# set y = $3*exp(-0.5*(X^2/$2^2)) + $4
+ lim x y; clear; box; plot x y -dy dy -x 2 -pt 2
+
+ $C0 = $1
+ $C1 = $2
+ $C2 = $3
+ $C3 = $4
+
+ vgauss x y dy yf
+end
+
+macro testfit
+ create x 0 1000
+ set y = 3 + 5*x
+ set dy = 10*(rnd(x) - 0.5)
+ set yr = y + dy
+ fit x yr 1
+ echo $Cn, $Cnv
+ echo $dC
+
+ yr[100] = yr[100] + 50
+ yr[200] = yr[200] - 50
+ yr[300] = yr[300] + 100
+ yr[400] = yr[400] - 500
+ yr[500] = yr[500] + 30
+
+ fit x yr 1
+ echo $Cn, $Cnv
+ echo $dC
+
+ fit x yr 1 -clip 3 3
+ echo $Cn, $Cnv
+ echo $dC
+end
+# expected output:
+# y = 3.013781 x^0 5.000005 x^1
+#     0.063198     0.000110
+# 1, 1000
+# 2.91071543189
+# y = 2.495040 x^0 5.000303 x^1
+#     0.063198     0.000110
+# 1, 1000
+# 16.5928919554
+# y = 3.021974 x^0 4.999991 x^1
+#     0.063419     0.000110
+# 1, 995
+# 2.90820510001
+
+macro testloops
+ for i 0 100
+  if ($i < 20)
+   continue
+  end
+  if ($i > 40)
+   break
+  end
+  echo $i
+ end
+end  
+
+# test math parsing
+macro testvars
+ echo testing variable assignment
+ $a = 1
+ echo $a is 1
+ $b = 5*3 + $a
+ echo $b is 16
+
+ $a = `ls`
+ echo $a
+ exec ls
+
+ echo testing in-line math
+ $a = 1
+ echo {1 + 1} is 2
+ echo {2^3} is 8
+ echo {$a + 2} is 3
+
+ echo testing vector assignment
+ create x 0 10
+ set y = x^2
+ echo x[2] is 2
+ echo y[2] is 4
+ lim x y; clear; box; plot x y
+ label -x "x axis" -y "&s y axis"
+end
+
+macro testspeed
+ exec date
+ create x 0 100000
+ for i 0 5000
+  set y = 3*x + $i
+ end
+ exec date
+end
+
+macro testmemory.buffers
+ mcreate a 2048 2048
+ exec date
+ for i 0 500
+  set b = 3*a + 6
+ end
+ exec date
+end
+
+macro testmemory.macros
+ exec date
+ for i 0 1000
+   for j 0 1000
+    $N = $N + 1
+   end
+ end
+ exec date
+end
+
+macro sample
+ $N = 0
+ for j 0 1000000
+  $N = 100
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/testloops.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/testloops.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/testloops.pro	(revision 16632)
@@ -0,0 +1,90 @@
+
+macro testloop1
+ local i
+ for i 0 10
+  echo "1: $i"
+    end
+end
+
+macro testloop2
+ local i
+ for i 0 5
+   echo "2: $i"
+   testloop1
+end
+end
+
+macro testlocal1
+ local -static foo
+ echo "1 - foo: $foo"
+ $foo = local.1
+ echo "1 - foo: $foo"
+end
+
+macro testlocal2
+ local foo
+ $foo = local.2
+ echo "2 - foo: $foo"
+ testlocal1
+ echo "2 - foo: $foo"
+ testlocal1
+ echo "2 - foo: $foo"
+end
+
+macro test1
+ # echo step $1
+ if ($1 == 1)
+  echo "break here"
+  break
+ end
+ if ($1 == 2)
+  continue
+ end
+end
+
+# continue
+
+macro test2
+ echo "input test"
+ break
+ echo "error, can't get here"
+end
+
+macro testm
+ break -auto off
+ test1 0
+ # echo $STATUS
+ test1 1
+ # echo $STATUS
+ test1 2
+ # echo $STATUS
+ if ($1 == 10) 
+  test1 1
+  if ($STATUS == 0)
+   echo "breaking it"
+   break
+  end
+ end
+ echo done
+end
+
+echo "done loading"
+
+macro test3
+ for i 0 12
+  echo $i
+  testm $i
+  echo "status: $STATUS"
+ end
+end
+
+macro testL
+ for i 0 10
+  for j 0 10
+   for k 0 10
+    echo $i $j $k
+    mcreate a 1024 1024   
+   end
+  end
+ end
+end
Index: /branches/eam_branch_20080223/Ohana/src/opihi/scripts/testscript
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/scripts/testscript	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/scripts/testscript	(revision 16632)
@@ -0,0 +1,16 @@
+#!/bin/csh -f
+
+date
+
+ls -d *
+# sleep 3
+ls foo
+
+foreach f (*)
+  echo $f
+  ls $f/*
+#  sleep 1
+end
+
+date
+#exit 3
Index: /branches/eam_branch_20080223/Ohana/src/opihi/test/basic.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/test/basic.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/test/basic.sh	(revision 16632)
@@ -0,0 +1,9 @@
+
+list testdir
+  cmd.data/test
+  cmd.basic/test
+end
+
+input test/tests.sh
+
+fulltests
Index: /branches/eam_branch_20080223/Ohana/src/opihi/test/pclient.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/test/pclient.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/test/pclient.sh	(revision 16632)
@@ -0,0 +1,8 @@
+
+list testdir
+  pclient/test
+end
+
+input test/tests.sh
+
+fulltests
Index: /branches/eam_branch_20080223/Ohana/src/opihi/test/tests.sh
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/opihi/test/tests.sh	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/opihi/test/tests.sh	(revision 16632)
@@ -0,0 +1,100 @@
+
+if ($?VERBOSE == 0)
+ $VERBOSE = 0
+end
+
+$failtest:n = 0
+$failfile:n = 0
+$faildirs:n = 0
+$currentdir = .
+
+macro fulltests
+  $Npass = 0
+  $Nfail = 0
+  $Ntest = 0
+  break -auto off
+
+  $failtest:n = 0
+  $failfile:n = 0
+  $faildirs:n = 0
+
+  for Ti 0 $testdir:n
+    if ($VERBOSE > 0)
+       echo "directory $testdir:$Ti"
+    end
+    runtestdir $testdir:$Ti
+  end
+
+  echo "completed $Ntest tests"
+  echo "$Npass tests passed"
+  echo "$Nfail tests failed"
+  echo "examined $testdir:n directories"
+
+  if ($Nfail > 0) 
+    echo " ** failed tests **"
+    for i 0 $Nfail
+      echo $faildirs:$i $failfile:$i $failtest:$i
+    end
+  end
+end
+
+macro runtestdir
+  if ($0 != 2)
+    echo "USAGE: runtestdir (testdir)"
+    break -auto on
+    break
+  end
+  
+  pwd -var startdir
+  cd -q $1
+  list testscripts -x "ls *.sh"
+
+  $currentdir = $1
+  for Tj 0 $testscripts:n
+    if ($VERBOSE > 1)
+      echo " running $testscripts:$Tj"
+    end
+    runtests $testscripts:$Tj      
+  end
+  
+  cd -q $startdir
+end
+
+macro runtests
+  if ($0 != 2)
+    echo "USAGE: runtests (script.sh)"
+    break -auto on
+    break
+  end
+  
+  local Tk
+
+  input $1
+  for Tk 0 $tests:n
+    if ($VERBOSE > 2)
+      echo "   running $tests:$Tk"
+    end
+    $PASS = 1
+    $tests:$Tk
+    if ($PASS == 0)
+      echo "   ** failed $tests:$Tk $1"
+      $Nfail ++
+      $n = $failtest:n
+      $failtest:$n = $tests:$Tk
+      $failfile:$n = $1
+      $faildirs:$n = $currentdir
+      $failtest:n ++
+      $failfile:n ++
+      $faildirs:n ++
+    else
+      $Npass ++
+    end
+    $Ntest ++
+    # echo "finished $tests:$Tk"
+  end
+end
+
+echo "USAGE:"
+echo "runtests (script.sh)"
+echo "runtestdir (testdir)"
+echo "set VERBOSE to 0 through 3"
Index: /branches/eam_branch_20080223/Ohana/src/perl/.status
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/.status	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/.status	(revision 16632)
@@ -0,0 +1,60 @@
+elixir status
+elixir flips
+elixir ptolemy
+nav
+nav
+!radec -hms
+region 168.148 6.9777 1.0
+catalog -g -m 14 20
+catalog -g -all -m 14 20
+style -pt 1
+region 168.148 6.9777 1.0
+catalog -g -all -m 14 20
+region 168.148 6.9777 0.3
+region 168.148 6.9777 1.0
+region 168.148 6.9777 0.3
+catalog -g -all -m 14 20
+catalog -g -all -m 10 15
+region 168.148 6.9777 0.3
+catalog -g -all -m 10 15
+nav
+pmeasure -all -m 16 22
+nav
+pmeasure -all -m 16 22
+style -pt 2
+c
+elixir flips
+elixir ptolemy
+elixir flips
+elixir complete
+elixir complete -time
+elixir complete -time
+na
+region
+region 30 0 90 ait
+style -c red; cgrid
+style -c black; images
+box
+region 30 0 90 ait
+style -c red; cgrid
+region 40 0 90 ait
+style -c red; cgrid
+style -c black; images
+clear
+style -c red; cgrid
+style -c black; images
+jpeg -g -name /h/eugene/spplots/allsky.png
+elixir complete
+elixir complete
+elixir complete -time
+elixir complete -time
+elixir complete -time
+elixir complete
+elixir complete
+echo {2500*60/11}
+echo {2500*60/11/3600}
+elixir complte
+elixir complete
+elixir complete -time
+elixir complete
+elixir complete -kill
Index: /branches/eam_branch_20080223/Ohana/src/perl/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/Makefile	(revision 16632)
@@ -0,0 +1,60 @@
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/perl
+
+perl: default
+
+default: install
+
+DADS = \
+dads.detrend dads.jpeg dads.keywords grab.keywords
+
+DETREND = \
+darktime.cfh12k darktime.linear \
+demodemap flatten.mana flatten.flips defringe getfringe defringe.ccd
+
+GENERAL = \
+cfht.names checkconfig mkrun megacenter megacoords \
+update.astrometry.iraf wfi.keywords mefheadunstrip cadc2qso \
+mkhtml mkidx
+
+IMSTATS = \
+imstatqso imstats \
+irstats seeingstats
+
+MKDETREND = \
+create.subset dt.select fixscat fixscat.mef mkscat \
+mkdetrend mosaic.merge mosaic.stats \
+normalize split.mef \
+detflips merge.lists
+
+MKFRINGE = \
+fr.mkmodes fr.modesave fr.modestats \
+fr.ckfile fr.detrend fr.frstats \
+fr.getfringe fr.imdata fr.jpegs \
+fr.medbin.spline fr.medbin.interp fr.mkhtml fr.mklists \
+fr.select mkfringe fr.defringe fr.smooth
+
+POSTRUN = \
+ckastrom ckdetrend ckphotom \
+ckrunid ckvalid elixir.photreport \
+elixir.postrun mktrans mktreport \
+validate rerun.complete elixir.rerun
+
+PTOLEMY = \
+cmp.header imclean.cfht imclean.subaru gastro.raw elixir.export
+
+REALTIME = \
+ckimregdb elixir.link elixir.reload
+
+CODE = $(DADS) $(DETREND) $(GENERAL) $(IMSTATS) $(MKDETREND) $(MKFRINGE) $(POSTRUN) $(PTOLEMY) $(REALTIME)
+
+install:
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	for file in $(CODE); do \
+	(chmod +x src/$$file && cd $(DESTBIN) && rm -f $$file && ln -s $(HOME)/src/$$file .); \
+	done
+
+# utilities #################################################
+clean:	
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
Index: /branches/eam_branch_20080223/Ohana/src/perl/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,13 @@
+
+perl-1-4: 
+  - dropped mkdist (moved to separate top-level module)
+
+perl-1-3:
+  - added mkdist, mkhtml, mkidx for ohana support
+
+perl-1-2:
+  - modified elixir.postrun to use unified addstar (not addref)
+
+perl-1-1:
+  - fixed /usr/bin/perl references everywhere *except* mkdetrend and
+    mkfringe, which must have the path explicitly defined.
Index: /branches/eam_branch_20080223/Ohana/src/perl/doc/keywords.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/doc/keywords.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/doc/keywords.txt	(revision 16632)
@@ -0,0 +1,130 @@
+
+Elixir data products are modified by several programs, each of which
+needs to make certain additions or changes to the headers.  this is a
+summary of those programs and the relevant keywords.  These programs
+may also add COMMENT and HISTORY fields, but these are ignored.
+
+* basic master bias, flat, dark frames are created by 'imcombred'
+  and adjusted by 'normalize'.
+
+- 'imcombred' adds the following keywords:
+
+IMCMB_DT= 'FLIPS ver 2.0 - Elixir by CFHT - Tue Aug 12 2003 -  9:09:32' / Date 
+IMCMB_AL= 'SIGMA   '           / CCD or SIGMA clipping, Scaled or Weighted Diff
+IMCMB_CA= 'MEAN    '           / Combining algorithm on final stack            
+IMCMB_LS=                  3.5 / Lower threshold for clipping rejection        
+IMCMB_HS=                  3.5 / Lower threshold for clipping rejection        
+IMCMB_FT= 'MASTER_DETREND_SKYFLAT' / Stacked frame type                        
+IMCMB_OP= '1DYMODEL_OVERSCAN + COMPUTED_MODE_RESCALING' / Input operations     
+IMCMB_NI=                   16 / Number of input files                         
+IMCMB_DA=                    T / Dual amplifier A,B (IMCMB_XX list format)     
+IMCMB_IF= 'NAME BIAS_A MODE_A BIAS_B MODE_B' / Input file parameters           
+IMCMB_nn= '712143f.fits[ccd00] 1287 3204 1232 3266' / Input file stats         
+
+- 'normalize' adds the following keywords:
+
+FLATSCAL=         1.0642668848 /                                               
+TVSTART = '2000/1/1          ' / data validity start time
+TVSTOP  = '2001/1/1          ' / data validity start time
+ELCONF  = '03Bm01.flat.g.0   ' / Original Elixir config
+EL_SYS  = '2.0               ' / Elixir System Version
+EL_NRM  = '1.4               ' / Elixir Normalize Version
+REL_DATE= '2003-09-30T15:59:33' / UTC Release Date
+
+* scatter-corrected flats are created by 'fixscat'
+- 'fixscat' adds the following keywords:
+
+EL_SFILE= '02Bm05.scatter.g.36.00.fits' / Scattered Light Image Used
+EL_SVER = 'B.0               ' / Scatter Correction Version
+
+* scatter frames are created by 'mkscat'
+- 'mkscat' adds the following keywords:
+
+TVSTART = '2000/1/1          ' / data validity start time
+TVSTOP  = '2001/1/1          ' / data validity start time
+FILTER  = 'g                 ' / filter uxed for model
+EL_SYS  = '2.0               ' / Elixir System Version
+EL_SVER = 'B.0               ' / Scatter Correction Version
+VERSION = 'B.0               ' / Scatter Correction Version
+
+* master fringe frames are created by 'imcombred' and adjusted by
+  'fr.smooth'
+
+- imcombred adds the following keywords:
+
+IMCMB_DT= 'FLIPS ver 2.1 - Elixir by CFHT - Tue Sep 16 2003 - 14:00:18' / Date 
+IMCMB_AL= 'SIGMA   '           / CCD or SIGMA clipping, Scaled or Weighted Diff
+IMCMB_CA= 'MEDIAN  '           / Combining algorithm on final stack            
+IMCMB_LS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_HS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_FT= 'MASTER_DETREND_FRINGE' / Stacked frame type                         
+IMCMB_OP= 'MODE_OFFSETING + FRINGE_RESCALING' / Input operations               
+IMCMB_NI=                   31 / Number of input files                         
+IMCMB_DA=                    F / Dual amplifier A,B (IMCMB_XX list format)     
+IMCMB_IF= 'NAME BIAS MODE SCALING' / Input file parameters                     
+IMCMB_00= '714505o00.fits 0 2582 0.441' / Input file stats                     
+
+- fr.smooth adds the following keywords:
+
+FRNG_C0 =         0.0000000000 / Fringe Cross Correlation linear fit term
+FRNG_C1 =         0.7197280000 / Fringe Cross Correlation linear fit term
+FRNG_SKY=      2882.0000000000 / Fringe Frame sky level
+FRNG_RNG=       -80.0000000000 / Fringe Frame fringe strength
+FRNG_REF= 'ccd13             ' / Fringe Cross Correlation reference chip
+FRNG_PTS= '2003A.frpts.i.36.00.fits' / Fringe Point File
+TVSTART = '2000/1/1          ' / data validity start time
+TVSTOP  = '2001/1/1          ' / data validity stop time
+EL_SYS  = '2.0               ' / Elixir System Version
+
+
+* processed science images are created by 'imred', defringed with
+  'imcombred', and keywords are updated with 'grab.keywords'
+
+- imred adds the following keywords:
+
+IMRED_DT= 'FLIPS ver 2.1 - Elixir by CFHT - Tue Sep 9 2003 - 12:29:37' / Date  
+IMRED_IF= '703406o.fits[ccd00]' / Input file to process by imred               
+IMRED_OF= '703406p00.fits'     / Output file resulting from the process by imre
+IMRED_OP= 'MASK_BP + OVERSCAN + BIAS + DARK_CURRENT + FLAT-FIELD' / Operation(s
+IMRED_MK= '2003A.mask.0.36.00.fits[ccd00]' / Mask of bad pixels (0/1) input fil
+IMRED_OV= '1DYMODEL_OVERSCAN'  / Type of overscan level correction             
+IMRED_BS= '03Am04n.bias.0.18.00.fits[ccd00]' / Bias frame input file           
+IMRED_DK= '03Am04n.dark.300.18.00.fits[ccd00]' / Dark frame input file         
+IMRED_DS=               1.0000 / Dark frame scaling factor                     
+IMRED_DB=                    T / Dark frame first corrected by bias frame      
+IMRED_FF= '03Am04n.flat.r.18.01.fits[ccd00]' / Flat-field frame input file     
+IMRED_NF=                    T / Normalized flat-field                         
+IMRED_SF=          1.009331465 / Output file dynamic stretching factor (BSCALe)
+
+- imcombred adds the following keywords:
+
+IMCMB_DT= 'FLIPS ver 2.1 - Elixir by CFHT - Tue Sep 9 2003 - 12:16:00' / Date  
+IMCMB_AL= 'SD      '           / CCD or SIGMA clipping, Scaled or Weighted Diff
+IMCMB_CA= 'SCALED_DIFFERENCE'  / Combining algorithm on final stack            
+IMCMB_LS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_HS=                  2.0 / Lower threshold for clipping rejection        
+IMCMB_FT= 'DEFRINGE_SCIENCE'   / Stacked frame type                            
+IMCMB_OP= 'MODE_OFFSETING + FRINGE_RESCALING' / Input operations               
+IMCMB_NI=                    2 / Number of input files                         
+IMCMB_DA=                    F / Dual amplifier A,B (IMCMB_XX list format)     
+IMCMB_IF= 'NAME BIAS MODE SCALING' / Input file parameters                     
+IMCMB_00= '703266p00.det 0 3808 1.000' / Input file stats                      
+IMCMB_01= '03Am04n.fringe.i.18.00.fits[ccd00] 0 4062 1.108' / Input file stats 
+
+- grab.keywords adds the following keywords:
+
+NASTRO  =                   49 / number of stars used for astrometry           
+CERROR  =         0.7334717934 / scatter in astrometry soln (arcsec)           
+PHOT_C  =               25.715 / Nightly zero point - actual                   
+PHOT_C0 =               25.743 / Nightly zero point - nominal                  
+PHOT_CS =                0.017 / Nightly zero point - scatter                  
+PHOT_NS =                    3 / Nightly zero point - N stars                  
+PHOT_NM =                    3 / Nightly zero point - N images                 
+PHOT_X  =                0.083 / Nightly zero point - color term               
+PHOT_K  =                -0.04 / Nightly zero point - airmass term             
+PHOT_C1 = 'r_SDSS            ' / Nightly zero point - color 1                  
+PHOT_C2 = 'i_SDSS            ' / Nightly zero point - color 2                  
+MAG_SAT =              13.8063 / approx saturation (mag)                       
+MAG_LIM =              23.2063 / approx completeness limit (mag)               
+DATEPROC= '2003-09-30T17:14:50' / Processing Date                                      
+EL_SYS  = '2.0                ' / Elixir System Version                               
Index: /branches/eam_branch_20080223/Ohana/src/perl/doc/mkdetrend-notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/doc/mkdetrend-notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/doc/mkdetrend-notes.txt	(revision 16632)
@@ -0,0 +1,46 @@
+
+files used by mkdetrend:
+
+flips/02Bk06.flat.I.00.0.fits     - master image, unnormalized
+flips/02Bk06.flat.I.00.0.imbin	  - binned master image
+flips/02Bk06.flat.I.00.0.log	  - log
+flips/02Bk06.flat.I.00.0.master	  - list of input images
+flips/02Bk06.flat.I.00.0.medbin	  - binned residual stack (50)
+flips/02Bk06.flat.I.00.0.mef	  - list of mef images
+flips/02Bk06.flat.I.00.0.msplit	  - list of split mef images
+flips/02Bk06.flat.I.00.0.norm	  - master image, normalized
+flips/02Bk06.flat.I.00.0.split	  - list of split images
+flips/02Bk06.flat.I.00.0.stats	  - residual stats per input image
+flips/02Bk06.flat.I.00.0.subset	  - list of images to be stacked
+flips/02Bk06.flat.I.00.0.tenbin	  - binned residual stack (10)
+
+changes:
+
+dt.select2: 
+mkdetrend2
+mode.mkdetrend2
+cfh12k.config.mef
+
+
+chip ID rules:
+
+there are two chip identifiers:  CCD ID & CCD N
+
+CCD ID is an arbitrary string
+CCD N  is a two digit code for the CCDs base on the camera config file
+
+CCD ID: cameraconfig -ccds
+CCD N:  cameraconfig -ccdn
+
+detsearch / imsearch use CCD ID for -ccd filter
+
+filenames of derivative products should use CCD N as a marker
+eg: 654321o.fits -> 654321o23.fits (for megacam ccd23 image)
+
+---
+
+dt.select2    : CCD ID fixed
+merge.lists   : CCD n/a
+create.subset : CCD n/a
+detflips      : CCD n/a - flips path needs to be set?
+normalize     : CCD ID Keyword used to id REF ccd (OK)
Index: /branches/eam_branch_20080223/Ohana/src/perl/doc/mkfringe.notes
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/doc/mkfringe.notes	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/doc/mkfringe.notes	(revision 16632)
@@ -0,0 +1,109 @@
+
+mkfringe file name examples
+
+CONFIG      = 01Ak01.fringe.I.0
+CONF-CCD    = 01Ak01.fringe.I.00.0
+RAWPATH     = /data/koa/cfh12k/01Ak04
+TMPPATH     = /data/elixir2/cfh12k/detrend/01Ak04/proc
+TMPDET-CCD  = /data/elixir2/cfh12k/detrend/01Ak04/proc/543210o/543210o00.fits
+TMPDEF-CCD  = /data/elixir2/cfh12k/detrend/01Ak04/proc/543210o.def/543210o00.fits
+
+ROOT = 543210o
+MODE = SPLIT / MEF
+status = 2 = new image, detrend it please, 1 = use to create master, 0 = don't use
+
+CONFIG.mef, CONFIG.split   [Nimage]
+ RAWPATH ROOT MODE
+ /data/koa/cfh12k/01Ak04 581688o SPLIT
+ /data/koa/cfh12k/01Ak04 581689o MEF
+
+CONFIG.master              [Nimage]
+ RAWPATH ROOT MODE status
+ /data/koa/cfh12k/01Ak04 581688o SPLIT 1
+ /data/koa/cfh12k/01Ak04 581689o MEF   1
+ 
+CONFIG.detrend             [Nimage] 
+ RAWPATH ROOT MODE
+ /data/koa/cfh12k/01Ak04 581688o SPLIT
+ /data/koa/cfh12k/01Ak04 581689o MEF
+
+CONFIG.defringe		   [Nimage]
+ TMPPATH/ROOT CONFIG
+ proc/581688o 01Ak01.fringe.I.0
+
+TMPPATH/ROOT.detlist       [Nccd]
+ TMPDET-CCD
+ proc/581688o/581688o00.fits
+
+TMPPATH/ROOT.deflist       [Nccd]
+ TMPDEF-CCD
+ proc/581688o.def/581688o00.fits
+
+CONF-CCD.ccdstats          [Nimage]
+ TMPDET-CCD (sky) (fringe) 0.0 0.0
+ proc/581688o/581688o00.fits (sky) (fringe) 0.0 0.0
+
+CONFIG.statlist: 
+ CONF-CCD.ccdstats 
+ fringe/01Ak01.fringe.I.00.0.ccdstats
+
+CONFIG.frlist               [Nccd]
+ CONF-CCD.fr.fits 
+ fringe/01Ak01.fringe.I.00.0.fr.fits
+
+CONFIG.smlist               [Nccd]
+ CONF-CCD.sm.fits 
+ fringe/01Ak01.fringe.I.00.0.sm.fits
+
+CONFIG.medbin:
+ HTML/CONFIG.medbin.NNN.jpg
+
+CONFIG.tenbin:
+ HTML/CONFIG.tenbin.NNN.jpg
+
+CONFIG.stats
+ (stats per mosaic)
+
+###### init: (takes CONFIG as input list) (mode.fringe1)
+fr.select I 2001/1/20 2001/2/5 split fringe/01Ak01.fringe.I.0.split
+fr.select I 2001/1/20 2001/2/5 mef   fringe/01Ak01.fringe.I.0.mef
+
+fr.mklists -initial  fringe/01Ak01.fringe.I.0.split fringe/01Ak01.fringe.I.0.mef fringe/01Ak01.fringe.I.0.master
+
+fr.mklists -imlist fringe/01Ak01.fringe.I.CCDNUM.0.ccdstats fringe/01Ak01.fringe.I.0.statlist
+fr.mklists -imlist fringe/01Ak01.fringe.I.CCDNUM.0.fr.fits  fringe/01Ak01.fringe.I.0.frlist
+fr.mklists -imlist fringe/01Ak01.fringe.I.CCDNUM.0.sm.fits  fringe/01Ak01.fringe.I.0.smlist
+
+fr.mklists -mosaic fringe/01Ak01.fringe.I.0.master proc det  (produces proc/ROOT.det/*NN.fits & proc/ROOT.detlist)
+fr.mklists -mosaic fringe/01Ak01.fringe.I.0.master proc def  (produces proc/ROOT.def/*NN.fits & proc/ROOT.deflist)
+fr.mklists -mosaic fringe/01Ak01.fringe.I.0.master proc med  (produces proc/ROOT.med/*NN.fits & proc/ROOT.medlist)
+
+fr.mklists -detrend  fringe/01Ak01.fringe.I.0.master fringe/01Ak01.fringe.I.0.detrend
+fr.mklists -defringe fringe/01Ak01.fringe.I.0.master fringe/01Ak01.fringe.I.0 proc fringe/01Ak01.fringe.I.0.defringe
+
+##### detrend: (takes CONFIG.detrend as input list)  (mode.fringe2)
+fr.detrend /data/koa/cfh12k/01Ak04 581688o SPLIT proc/581688o.det
+fr.medbin  proc/581688o.det 581688o 4 proc/581688o.med
+fr.gtstats proc/581688o.med 581688o 4 proc/581688o.imstats
+
+##### mkstats  (takes CONF-CCD as input list)  (mode.fringe4)
+fr.mklists -inlist  fringe/01Ak01.fringe.I.0.master 00 proc fringe/01Ak01.fringe.I.00.0.inlist
+fr.mklists -imstats fringe/01Ak01.fringe.I.0.master 00 proc fringe/01Ak01.fringe.I.0.imstats
+
+fr.mkstats fringe/01Ak01.fringe.I.00.0.inlist fringe/01Ak01.fringe.I.0.imstats 00 fringe/01Ak01.fringe.I.00.0.ccdstats fringe/01Ak01.fringe.I.0.frstats
+fr.mkrough fringe/01Ak01.fringe.I.00.0.ccdstats fringe/01Ak01.fringe.I.00.0.fr.fits comment
+
+[ fr.smooth fringe/01Ak01.fringe.I.00.0.fr.fits fringe/01Ak01.fringe.I.00.0.sm.fits ]
+
+##### defringe (takes CONFIG.defringe as input)  (mode.fringe3)
+fr.defringe proc/581688o.medlist proc/581688o.imstats fringe/01Ak01.fringe.I.00.0.frlist fringe/01Ak01.fringe.I.00.0.frstats proc/581688o.deflist 
+fr.stats proc/581688o.deflist proc/581688o.tenbin proc/581688o.medbin proc/581688o.stats
+
+# merge (not parallel)
+
+status: 2 = new image, detrend it please, 1 = use to create master, 0 = don't use
+
+fr.mklists -master fringe/01Ak01.fringe.I.0.master fringe/01Ak01.fringe.I.0.detrend
+
+[merge ccdstats > statlist]
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/doc/mkfringe.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/doc/mkfringe.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/doc/mkfringe.txt	(revision 16632)
@@ -0,0 +1,59 @@
+
+mkfringe states & programs [fringe only]
+
+running.init              : mode.fringe1 (config.mosaic)
+
+ - fr.select
+ - fr.mklists -initial
+ - fr.mklists -imlist
+ - fr.mklists -mosaic
+ - fr.mklists -detrend
+ - fr.mklists -maplist
+ - fr.mklists -mlist
+
+running.detrend           : mode.fringe2 (image)
+
+ - fr.ckfile
+ - fr.detrend
+ - fr.medbin.spline
+ - fr.getfringe
+ - fr.imdata
+ - fr.jpegs
+ - fr.mklists -master
+
+running.merge		  : mkfringe (config.mosaic)
+
+ - fr.mklists -subset
+ - fr.frstats -fitpars
+ - fr.frstats -plotstats
+ - fr.frstats -frstats
+ - fr.frstats -dfstats
+ - fr.mklists -imstats
+ - fr.jpegs
+ - fr.mkhtml -imstats
+ - fr.mkhtml -jpglist
+
+running.mkrough           : mkfringe / mode.fringe4 
+
+ - fr.mklists  -subset
+ - fr.frstats  -fitpars
+ - fr.frstats  -frstats
+ - fr.frstats  -dfstats
+ - fr.mklists  -imstats
+ - fr.mklists  -ccdstast
+ - fr.mkrough
+
+running.defringe          : mode.fringe3
+
+ - fr.defringe
+ - fr.getfringe
+ - fr.jpegs
+
+running.smooth            : mode.fringe4
+
+ - fr.smooth
+
+running.reg               : mkfringe
+
+ - detregister
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/archive
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/archive	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/archive	(revision 16632)
@@ -0,0 +1,353 @@
+#!/usr/bin/perl
+
+$dumpspace = "/pallas/d1/";
+$workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+$scriptdir = "/hebe/d27/logs/";
+$donelogfile = $scriptdir . "done.log";
+$scriptfile = $scriptdir . "maestro.dat";
+$flatdir = "/hebe/d27/references/config/";
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$alockfile = $database . "alock";
+$clockfile = $database . "clock";
+$killfile  = $database . "kill";
+$haltfile  = $database . "halt";
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    vsystem ("notify.pl $ARGV[0] none 0");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: archive.pl Noutfile\n"; }
+$Noutfile = $ARGV[0] + 1;
+$outfile = "archive" . $Noutfile . ".log";
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+# load in done date list
+open (DONELOG, $donelogfile);
+@donelist = ();
+while ($line = <DONELOG>) {
+  chop ($line);
+  @donelist = (@donelist,$line);
+}
+$Ndone = @donelist;
+close (DONELOG);
+
+# load in maestro list
+open (MAESTRO, $scriptfile);
+@todolist = ();
+while ($line = <MAESTRO>) {
+  chop ($line);
+  @todolist = (@todolist,$line);
+}
+$Ntodo = @todolist;
+close (MAESTRO);
+
+# find entries in MAESTRO that are NOT in DONELOG
+@leftlist = ();
+for ($i = 0; $i < $Ntodo; $i ++) {
+    $gotit = 0;
+    for ($j = 0; ($j < $Ndone) && ! $gotit; $j ++) {
+	@entries = split (" ",$todolist[$i]);
+	if ($entries[0] eq $donelist[$j]) {
+	    $gotit = 1;
+	}
+    }
+    if (!$gotit) {
+	@leftlist = (@leftlist, $todolist[$i]);  
+    }
+}
+$Nleft = @leftlist;
+
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+# run controller on unfinished entries
+# we are going to run this in the script directory
+if ($Nleft) {
+    chdir $scriptdir;
+    for ($i = 0; $i < $Nleft; $i++) {
+	print STDERR "unfinished: $leftlist[$i]\n";
+	@entries = split (" ",$leftlist[$i]);
+	$inlist = $entries[0] . ".inlist";
+	$outlist = $entries[0] . ".outlist";
+	$subdir = $entries[0];
+	$photcode = $entries[1];
+	print STDERR "$subdir: $inlist $outlist $photcode\n";
+	if (-e $outlist) {
+	    # partially successful run, restart controller in the middle
+	    $tmp_inlist = $entries[0] . ".tmp_inlist";
+	    $tmpoutlist = $entries[0] . ".tmpoutlist";
+	    if (-e $tmpoutlist) { if (vsystem ("cat $tmpoutlist >> $outlist")) { goodbye "trouble merging $tmpoutlist and $outlist\n"; }}
+	    # partially successful re-start: make sure $outlist is complete
+	    if (parse_outlist ($outlist,$tmp_inlist,1)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,2)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s dophot", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,3)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s fstat", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,4)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s gastro", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,5)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s addstar", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    # do inlist entries not in outlist
+	    if (parse_inlist ($inlist,$outlist,$tmp_inlist)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    unless (unlink ($tmpoutlist)) { goodbye "can't unlink $tmpoutlist, why not?"; }
+	    unless (unlink ($tmp_inlist)) { goodbye "can't unlink $tmp_inlist, why not?"; }
+	    vsystem ("cleaning.pl");
+	    if (-e $lockfile) { goodbye "lock file exists"; }
+
+	    print STDERR "done: $entries[0]\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$entries[0]\n";
+	    close (DONELOG);
+	} else {
+	    $controlflags = "";
+	    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+	    print STDERR "done: $subdir\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$subdir\n";
+	    close (DONELOG);
+	}
+    }
+    unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+    print STDERR "remember to delete images from complete directories\n";
+
+    unless (-e $haltfile) { 
+	print STDERR "re-did unfinished images\n";
+	print STDERR "starting a new archive.pl with output to $outfile\n";
+	vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+	vsystem ("archive.pl $Noutfile 1>$outfile 2>&1 &");
+	exit;
+    }
+    goodbye "re-did unfinished images";
+}
+    
+print STDERR "no unfinished nights, slurping a new set\n";
+if (-e $scriptfile) { if (vsystem ("rm $scriptfile")) { goodbye "couldn't delete old MAESTRO file"; }}
+
+if (vsystem ("rsh -n pallas slurp.pl")) { goodbye "couldn't start slurp on pallas"; }
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+if (!-e $scriptfile) {goodbye "slurp failed to download files"; }
+
+print STDERR "done slurping, starting controller runs\n";
+vsystem ("date");
+
+# run controller on the resulting images
+# controller wants to be run in the same directory as the inlists 
+chdir $scriptdir;
+open (MAESTRO, $scriptfile);
+while ($line = <MAESTRO>) {
+    @entries = split (" ",$line);
+    $inlist = $entries[0] . ".inlist";
+    $outlist = $entries[0] . ".outlist";
+    $subdir = $entries[0];
+    $photcode = $entries[1];
+    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+    print STDERR "done: $subdir\n";
+    open (DONELOG, ">>$donelogfile");
+    print DONELOG "$entries[0]\n";
+    close (DONELOG);
+}
+close (MAESTRO);
+
+unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+print STDERR "ending execution\n";
+vsystem ("date");
+print STDERR "finished new images";
+
+unless (-e $haltfile) { 
+    print STDERR "starting a new archive.pl with output to $outfile\n";
+    vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+    vsystem ("archive.pl $Noutfile 1>$outfile 2>&1 &");
+} else {
+    vsystem ("notify.pl $ARGV[0] none 0");
+}
+exit;
+
+# run nrphot on the altered cpt files and quit
+chdir $database;
+@files = `find . -name "*.cpt" -newer $reffile`;
+$Nfiles = @files;
+print STDERR "N: $Nfiles\n";
+foreach $f (@files) {
+    chop ($f);
+    vsystem ("nrphot -v $f");
+    if (-e $lockfile) { goodbye "lock file exists"; }
+}
+
+# delete inlist files
+
+# do controller (& cleaning if needed), taking care of flats and error conditions
+sub docontroller {
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    # break up entry line
+    $outsubdir = $_[0];
+    $in = $_[1];
+    $out = $_[2];
+    $phot = $_[3];
+    $flags = $_[4];
+    $clean = $_[5];
+    # create sub-directory in output dir
+    $outdir = $workspace . $outsubdir;
+    unless (-e $outdir) { unless (mkdir ($outdir,0777)) { goodbye "cannot create output directory $outdir"; } }
+    # make link to correct flat
+    $flatlink = $flatdir . "newflat.fits";
+    $realflat = $flatdir . "flatcode" . $phot . ".fits";
+    if (-l $flatlink) { unless (unlink ($flatlink)) { goodbye "cannot unlink $flatlink"; }}
+    if (-e $flatlink) { goodbye "$flatlink exists, but is not a link!"; }
+    unless (symlink ($realflat, $flatlink)) { goodbye "cannot symlink $realflat to $flatlink"; }
+    # run controller and cleanup
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    vsystem ("controller $flags -o $outsubdir $in $out $phot");
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if ($clean) {
+	vsystem ("cleaning.pl");
+	if (-e $lockfile) { goodbye "lock file exists"; }
+    }
+}
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $out = $_[1];
+    $mode = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    print STDERR ".";
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	open (OUTLIST, ">$out");
+	for ($k = 0; $k < $Nout; $k++) {
+	    print OUTLIST "$outarray[$k]\n";
+	}
+	close (OUTLIST);
+    }
+    $Nout;
+}
+
+sub parse_inlist {
+    $in = $_[0];
+    $out = $_[1];
+    $new = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+
+# load inlist
+    open (OUTLIST, $out);
+    @outarray = ();
+    while ($line = <OUTLIST>) {
+	chop ($line);
+	@outarray = (@outarray,$line);
+    }
+    $Nout = @outarray;
+    close (OUTLIST);
+
+# load outlist
+    @newarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	$gotit = 0;
+	for ($m = 0; ! $gotit && ($m < $Nout); $m++) {
+	    if ($outarray[$m] =~ /$inarray[$k]/) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @newarray = (@newarray,$inarray[$k]);
+	}
+    }
+    $Nnew = @newarray;
+    if ($Nnew) {
+	open (NEWLIST, ">$new");
+	for ($k = 0; $k < $Nnew; $k++) {
+	    print NEWLIST "$inarray[$k]\n";
+	}
+	close (NEWLIST);
+    }
+    $Nnew;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/checkoutfail.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/checkoutfail.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/checkoutfail.pl	(revision 16632)
@@ -0,0 +1,63 @@
+#!/usr/bin/perl
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $mode = $_[1];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$topdir//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	for ($k = 0; $k < $Nout; $k++) {
+	    print STDERR "$mode: $outarray[$k]\n";
+	}
+    }
+    $Nout;
+}
+
+$outlist = $ARGV[0];
+
+parse_outlist ($outlist,5);
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/checkoutlist.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/checkoutlist.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/checkoutlist.pl	(revision 16632)
@@ -0,0 +1,65 @@
+#!/usr/bin/perl
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $mode = $_[1];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$topdir//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	for ($k = 0; $k < $Nout; $k++) {
+	    print STDOUT "$mode: $outarray[$k]\n";
+	}
+    }
+    $Nout;
+}
+
+$outlist = $ARGV[0];
+
+for ($i = 1; $i < 6; $i++) {
+    parse_outlist ($outlist,$i);
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/cleaning.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/cleaning.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/cleaning.pl	(revision 16632)
@@ -0,0 +1,30 @@
+#!/usr/bin/perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$reffile = $database . "start.clean";
+
+chdir $database;
+
+@files = `find . -name "*.cpt" -newer $reffile`;
+$Nfiles = @files;
+print STDERR "N: $Nfiles\n";
+
+if (-e $lockfile) { die "lock file exists"; }
+
+foreach $f (@files) {
+    chop ($f);
+    vsystem ("markstar -v $f");
+    if (-e $lockfile) { die "lock file exists"; }
+    vsystem ("addusno -v $f");
+    if (-e $lockfile) { die "lock file exists"; }
+    vsystem ("markrock -v $f");
+    if (-e $lockfile) { die "lock file exists"; }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/locks.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/locks.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/locks.pl	(revision 16632)
@@ -0,0 +1,93 @@
+#!/usr/bin/perl
+
+$topdir  = "/pallas/";
+$scriptdir = "/hebe/d27/logs/";
+$donelogfile = $scriptdir . "done.log";
+$scriptfile = $scriptdir . "maestro.dat";
+$flatdir = "/hebe/d27/references/config/";
+
+$workspace = "/hebe/d27/workspace/";
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$alockfile = $database . "alock";
+$clockfile = $database . "clock";
+$killfile  = $database . "kill";
+$haltfile  = $database . "halt";
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    die "@_";
+}
+
+$Narg = @ARGV;
+if ($Narg > 1) {
+    goodbye "USAGE: locks.pl [-reset] [-halt] [-kill] [-dB] [-controller] [-archive]";
+}
+
+unless ($ARGV[0] cmp "-reset") {
+    unlink ($lockfile);
+    unlink ($alockfile);
+    unlink ($clockfile);
+    unlink ($killfile);
+    unlink ($haltfile);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-kill") {
+    open (TEMP, ">$killfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-halt") {
+    open (TEMP, ">$haltfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-dB") {
+    open (TEMP, ">$lockfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-controller") {
+    open (TEMP, ">$clockfile");
+    close (TEMP);
+    exit;
+}
+
+unless ($ARGV[0] cmp "-archive") {
+    open (TEMP, ">$alockfile");
+    close (TEMP);
+    exit;
+}
+
+@locks = ();
+if (-e $lockfile) { @locks = (@locks,$lockfile); }
+if (-e $alockfile) { @locks = (@locks,$alockfile); }
+if (-e $clockfile) { @locks = (@locks,$clockfile); }
+if (-e $killfile) { @locks = (@locks,$killfile); }
+if (-e $haltfile) { @locks = (@locks,$haltfile); }
+
+$Nlocks = @locks;
+
+if ($Nlocks > 0) {
+    print STDERR "locks set:\n";
+    for ($i = 0; $i < $Nlocks; $i++) {
+	print STDERR "$locks[$i]\n";
+    }
+} else {
+    print STDERR "no locks currently set\n";
+}
+
+print STDERR "\n";
+print STDERR "USAGE: locks.pl [-reset] [-kill] [-dB] [-controller] [-archive]\n";
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/notify.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/notify.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/notify.pl	(revision 16632)
@@ -0,0 +1,12 @@
+#!/usr/bin/perl
+
+$target= "gene\@astro.washington.edu";
+$targetmachine = "astro.washington.edu";
+
+$last = "archive." . $ARGV[0];
+$next = $ARGV[1];
+$N = $ARGV[2];
+
+# system ("echo \"done with $last, starting $next ($N)\" | mail $targetname\@$targetmachine");
+system ("echo \"done with $last, starting $next ($N)\" | mail $target");
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/rearchive.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/rearchive.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/rearchive.pl	(revision 16632)
@@ -0,0 +1,71 @@
+#!/usr/bin/perl
+
+# $dumpspace = "/pallas/d1/";
+# $workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";
+$alockfile = $database . "alock";
+$clockfile = $database . "clock";
+$killfile  = $database . "kill";
+$haltfile  = $database . "halt";
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: rearchive.pl dir\n"; }
+
+$target = $ARGV[0];
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+# untar directory 
+
+if (!-e $target.tgz) { goodbye "target $target.tgz not found"; }
+
+if (vsystem ("gunzip -c $target.tgz | tar xvf -")) { goodbye "untar failed for $target.tgz"; }
+if (vsystem ("ls $target/*.cmp > $target.lst")) { goodbye "failed to get directory listing for $target"; }
+
+open (TEMP, ">$target.log");
+close (TEMP);
+if (!-e $target.log) { goodbye "could not create $target.log"; }
+
+# load in done date list
+open (LISTFILE, $target.lst);
+@listfile = ();
+while ($line = <LISTFILE>) {
+  chop ($line);
+  @listfile = (@listfile,$line);
+}
+$Nlist = @listfile;
+close (LISTFILE);
+
+for ($i = 0; $i < Nlist; $i++) {
+    if (-e $lockfile) { goodbye "database lock $lockfile is set"; }
+    vsystem ("addstar -v $listfile[$i]");
+}
+
+if (-e $lockfile) { goodbye "lock file exists"; }
+vsystem ("cleaning.pl");
+if (-e $lockfile) { goodbye "lock file exists"; }
+
+# vsystem ("rm $target");
+exit;
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/slurp
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/slurp	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/slurp	(revision 16632)
@@ -0,0 +1,223 @@
+#!/usr/bin/env perl
+
+$Ngrab = 5;
+$scriptdir   = "/hebe/d27/logs/";
+$dumpspace   = "/pallas/d1/";
+$tapedrive   = "/dev/rmt/1cn";
+$tapelogfile = $scriptdir . "tape.log";
+$donelogfile = $scriptdir . "processed.log";
+$scriptfile  = $scriptdir . "extracted.log";
+
+# old directories:
+# $topdir  = "/pallas/";
+# $rootdir = "/pallas/d1/";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "@_\n";
+    vsystem ("unload $tape");
+    vsystem ("lunlock $tapedrive");
+    vsystem ("lunlock $dumpspace");
+    die;
+}
+
+# goodbye ("quit suddenly");
+
+# checkdone (line)
+# returns 1 if not in line (and sets $name), 
+# returns 0 otherwise
+sub checkdone {
+    local($inline) = @_;
+    @entries = split (" ",$inline);
+    $found = 0;
+    if ((@entries[0] > 1996) && (@entries[0] < 2097)) {
+	$found = 1;
+	$name = substr(@entries[0],2,2) . @entries[1] . @entries[2];
+	for ($j = 0; ($j < $Ndone) && ($found); $j++) {
+	    @done = split (" ", $donelist[$j]);
+	    if ($done[0] eq $name) {
+		$found = 0;
+	    }
+	}
+    }
+    $found;
+}
+
+# checktape (name)
+# find all entries which match name and add to dolist
+sub checktape {
+  local($inname) = @_;
+  $j = 0;
+  while ($j < $Ntape) {
+    @entries = split (" ",$tapelist[$j]);
+    if ((@entries[0] > 1996) && (@entries[0] < 2097)) {
+      $tmpname = substr(@entries[0],2,2) . @entries[1] . @entries[2];
+      if ($inname eq $tmpname) {
+	@dolist = (@dolist,$tapelist[$j]);
+	@doname = (@doname,$inname);
+      }
+    }
+    $j ++;
+  }
+}
+
+
+# load in done date list
+open (DONELOG, $donelogfile);
+@donelist = ();
+while ($line = <DONELOG>) {
+  chop ($line);
+  @donelist = (@donelist,$line);
+}
+$Ndone = @donelist;
+close (DONELOG);
+print "Ndone = $Ndone\n";
+
+# load in tape.log list
+open (TAPELOG, $tapelogfile);
+@tapelist = ();
+while ($line = <TAPELOG>) {
+  chop ($line);
+  @tapelist = (@tapelist,$line);
+}
+$Ntape = @tapelist;
+close (TAPELOG);
+# @tapelist = reverse(@tapelist);
+print "Ntape = $Ntape\n";
+
+# find 5 new nights not already in the "donelist"
+$N = 0;
+@tryname = ();
+for ($i = 0; ($i < $Ntape) && ($N < $Ngrab); $i++) {
+    if (&checkdone ($tapelist[$i])) {
+	$j = 0; 
+	$gotit = 0;
+	for ($j = 0; ($j < $N) && (! $gotit); $j++) {
+	    if ($name eq $tryname[$j]) {
+		$gotit = 1;
+	    }
+	}
+	if (! $gotit) {
+	    @tryname = (@tryname, $name);  
+	    $N ++;
+	}
+    }
+}
+$Ntryname = @tryname;
+# tryname has a list of the 980103 style names
+
+# now that we have a list of interesting nights, 
+# get a list of the actual lines from tape.log, 
+# along with a list of the matchine names
+$i = 0;
+@dolist = ();
+@doname = ();
+while ($i < $Ntryname) {
+  &checktape ($tryname[$i]);
+  $i ++;
+}
+
+$i = 0;
+$Ndolist = @dolist;
+@fileno = ();
+@tapeno = ();
+@gbytes = ();
+@photno = ();
+@entry = ();
+while ($i < $Ndolist) {
+    print STDERR "$doname[$i] == $dolist[$i]\n";
+    @words = split (" ",$dolist[$i]);
+    @entry = (@entry,$i);
+    @tapeno = (@tapeno,$words[3]);
+    @fileno = (@fileno,$words[4]);
+    @gbytes = (@gbytes,$words[5]);
+    @photno = (@photno,$words[8]);
+    $i ++;
+}
+
+# delete old downloaded data
+
+$dir = $dumpspace . "9";
+print STDERR "dir: $dir\n";
+@files = <$dir*>;
+$Nfiles = @files;
+print "files: @files\n";
+for ($i = 0; $i < $Nfiles; $i++) {
+    if ((-d $files[$i]) && (-O $files[$i])) {
+	if (vsystem ("rm -r $files[$i]")) { goodbye "error deleting directory $files[$i]"; }
+    }
+}
+
+# now sort the entries by tape and file number:
+
+sub by_tape_and_file { ($tapeno[$a] <=> $tapeno[$b]) || ($fileno[$a] <=> $fileno[$b]); }
+@entry = sort by_tape_and_file @entry;
+
+# lock tape and disk space. keep trying for up to 10 hours
+for ($i = 0; ($i < 30) && vsystem ("llock $dumpspace"); $i++) { system ("sleep 1200"); }
+ if ($i == 100) { goodbye "failed to grab disk space"; }
+for ($i = 0; ($i < 30) && vsystem ("llock $tapedrive"); $i++) { system ("sleep 1200"); }
+ if ($i == 100) { goodbye "failed to grab tape drive"; }
+
+$tape = -1;
+for ($i = 0; $i < $Ndolist; $i++) {
+    # do a df and compare to $gbytes[$entry[$i]]
+    @answer = `df -k $dumpspace`;
+    @tmp = split (" ", $answer[1]);
+    $space = $tmp[3] / (1024*1024);
+    print STDERR "compare $space and $gbytes[$entry[$i]]\n";
+    if (0.95*$space < $gbytes[$entry[$i]]) { last; }
+    # load tape if needed
+    if ($tapeno[$entry[$i]] != $tape) {
+	# unload old tape, load desired tape 
+	if ($tape != -1) { if (vsystem ("unload $tape")) { goodbye "trouble unloading tape $tape"; } }
+	if (vsystem ("load $tapeno[$entry[$i]]")) { goodbye "trouble loading tape $tapeno[$entry[$i]]"; }
+	$tape = $tapeno[$entry[$i]];
+	$j = 0;
+	$offline = 1;
+	# wait for tape to come online before starting anything
+	while (($j < 12) && $offline) {
+	    vsystem ("sleep 10");
+	    $offline = vsystem ("mt -f $tapedrive status");
+	    $j ++;
+	}
+	if ($j == 12) { goodbye "tape still not online!"; }
+	$file = 0;
+    }
+    # advance to first file of interest
+    $nskip = $fileno[$entry[$i]] - $file;
+    if ($nskip > 0) {
+	if (vsystem ("mt -f $tapedrive fsf $nskip")) { goodbye "error advancing tape"; }
+    }
+    # create output directory if it doesn't exist
+    $dir = $dumpspace . $doname[$entry[$i]];
+    unless (-e $dir) {
+	unless (mkdir ($dir,0777)) { goodbye "cannot create output directory $dir"; }
+    }
+    chdir $dir;
+    # extract the files
+    vsystem ("tar -xvfb $tapedrive 128");
+    $file = $fileno[$entry[$i]] + 1;
+}
+$Ndolist = $i;
+
+if (vsystem("unload $tape")) { goodbye "trouble unloading tape $tape"; }
+if (vsystem("lunlock $tapedrive")) { goodbye "trouble unlocking tape drive $tapedrive"; }
+if (vsystem ("lunlock $dumpspace")) { goodbye "trouble unlocking disk drive $dumpspace"; }
+
+open (MAESTRO, ">$scriptfile");
+chdir $dumpspace;
+$i = 0;
+while ($i < $Ndolist) {
+    vsystem ("ls $doname[$entry[$i]]/*b.fits > $scriptdir/$doname[$entry[$i]].inlist");
+    print MAESTRO "$doname[$entry[$i]] $photno[$entry[$i]] \n";
+    $i ++;
+}
+close (MAESTRO);
+
+1;
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/stage1
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/stage1	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/stage1	(revision 16632)
@@ -0,0 +1,342 @@
+#!/usr/bin/env perl
+
+# in this script, we run flatten, dophot, fstat, and gastro
+# these can be run totally in parallel, so this routine runs
+# independently of the series processing (addstar, markstar, etc)
+# in stage2
+
+# for now these directories are hard-wired.  eventually, they
+# should be looked up in the config file, so all scripts are
+# consistent
+$dumpspace = "/pallas/d1/";
+$workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+$scriptdir = "/hebe/d27/logs/";
+$donelogfile = $scriptdir . "processed.log";
+$scriptfile  = $scriptdir . "extracted.log";
+$flatdir = "/hebe/d27/references/config/";
+
+$database = "/hebe/d27/database/";
+$alockfile = $database . "alock1";     # lock on stage1 (only 1 running at a time)
+$clockfile = $database . "clock1";     # lock on controller
+$killfile  = $database . "kill";       # quickly stop the processing
+$haltfile  = $database . "halt";       # halt processing after this loop
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    vsystem ("notify.pl $ARGV[0] none 0");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: stage1 Noutfile\n"; }
+$Noutfile = $ARGV[0] + 1;
+$outfile = "stage1." . $Noutfile . ".log";
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+# load in done date list
+open (DONELOG, $donelogfile);
+@donelist = ();
+while ($line = <DONELOG>) {
+  chop ($line);
+  @donelist = (@donelist,$line);
+}
+$Ndone = @donelist;
+close (DONELOG);
+
+# load in maestro list
+open (MAESTRO, $scriptfile);
+@todolist = ();
+while ($line = <MAESTRO>) {
+  chop ($line);
+  @todolist = (@todolist,$line);
+}
+$Ntodo = @todolist;
+close (MAESTRO);
+
+# find entries in MAESTRO that are NOT in DONELOG
+@leftlist = ();
+for ($i = 0; $i < $Ntodo; $i ++) {
+    $gotit = 0;
+    for ($j = 0; ($j < $Ndone) && ! $gotit; $j ++) {
+	@todo = split (" ",$todolist[$i]);
+	@done = split (" ",$donelist[$j]);
+	if ($todo[0] eq $done[0]) {
+	    $gotit = 1;
+	}
+    }
+    if (!$gotit) {
+	@leftlist = (@leftlist, $todolist[$i]);  
+    }
+}
+$Nleft = @leftlist;
+
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+# run controller on unfinished entries
+# we are going to run this in the script directory
+if ($Nleft) {
+    chdir $scriptdir;
+    for ($i = 0; $i < $Nleft; $i++) {
+	print STDERR "unfinished: $leftlist[$i]\n";
+	@entries = split (" ",$leftlist[$i]);
+	$inlist = $entries[0] . ".inlist";
+	$outlist = $entries[0] . ".addlist";
+	$subdir = $entries[0];
+	$photcode = $entries[1];
+	print STDERR "$subdir: $inlist $outlist $photcode\n";
+	if (-e $outlist) {
+	    # partially successful run, restart controller in the middle
+	    $tmp_inlist = $entries[0] . ".tmp_inlist";
+	    $tmpoutlist = $entries[0] . ".tmpaddlist";
+	    if (-e $tmpoutlist) { if (vsystem ("cat $tmpoutlist >> $outlist")) { goodbye "trouble merging $tmpoutlist and $outlist\n"; }}
+	    # partially successful re-start: make sure $outlist is complete
+	    if (parse_outlist ($outlist,$tmp_inlist,1)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,2)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s dophot", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,3)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s fstat", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    if (parse_outlist ($outlist,$tmp_inlist,4)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s gastro", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    # do inlist entries not in outlist
+	    if (parse_inlist ($inlist,$outlist,$tmp_inlist)) {
+		docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s flatten", 0);
+		vsystem ("cat $tmpoutlist >> $outlist");
+	    }
+	    unless (unlink ($tmpoutlist)) { goodbye "can't unlink $tmpoutlist, why not?"; }
+	    unless (unlink ($tmp_inlist)) { goodbye "can't unlink $tmp_inlist, why not?"; }
+	    # done with this night, add to donelogfile
+	    print STDERR "done: $subdir $photcode\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$subdir $photcode\n";
+	    close (DONELOG);
+	} else {
+	    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+	    print STDERR "done: $subdir $photcode\n";
+	    open (DONELOG, ">>$donelogfile");
+	    print DONELOG "$subdir $photcode\n";
+	    close (DONELOG);
+	}
+    }
+    unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+    print STDERR "remember to delete images from complete directories\n";
+
+    unless (-e $haltfile) { 
+	print STDERR "re-did unfinished images\n";
+	print STDERR "starting a new stage1 with output to $outfile\n";
+	vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+	vsystem ("stage1 $Noutfile 1>$outfile 2>&1 &");
+	exit;
+    }
+    goodbye "re-did unfinished images";
+}
+    
+# get a new set of data
+print STDERR "no unfinished nights, slurping a new set\n";
+if (-e $scriptfile) { if (vsystem ("rm $scriptfile")) { goodbye "couldn't delete old MAESTRO file"; }}
+
+if (vsystem ("rsh -n pallas slurp")) { goodbye "couldn't start slurp on pallas"; }
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+if (!-e $scriptfile) {goodbye "slurp failed to download files"; }
+
+print STDERR "done slurping, starting controller runs\n";
+vsystem ("date");
+
+# run controller on the resulting images
+# controller wants to be run in the same directory as the inlists 
+$Nruns = 0;
+chdir $scriptdir;
+open (MAESTRO, $scriptfile);
+while ($line = <MAESTRO>) {
+    @entries = split (" ",$line);
+    $inlist = $entries[0] . ".inlist";
+    $outlist = $entries[0] . ".addlist";
+    $subdir = $entries[0];
+    $photcode = $entries[1];
+    docontroller ($subdir, $inlist, $outlist, $photcode, "-s flatten", 1);
+    print STDERR "done: $subdir $photcode\n";
+    open (DONELOG, ">>$donelogfile");
+    print DONELOG "$subdir $photcode\n";
+    close (DONELOG);
+    $Nruns ++;
+}
+close (MAESTRO);
+
+if (Nruns == 0) {
+    print STDERR "no data downloaded in slurp, waiting for a while\n";
+    vsystem ("sleep 3600");
+}
+unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+print STDERR "ending execution\n";
+vsystem ("date");
+print STDERR "finished new images";
+
+unless (-e $haltfile) { 
+    print STDERR "starting a new stage1 with output to $outfile\n";
+    vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+    vsystem ("stage1 $Noutfile 1>$outfile 2>&1 &");
+} else {
+    vsystem ("notify.pl $ARGV[0] none 0");
+}
+exit;
+
+# do controller (& cleaning if needed), taking care of flats and error conditions
+sub docontroller {
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    # break up entry line
+    $outsubdir = $_[0];
+    $in = $_[1];
+    $out = $_[2];
+    $phot = $_[3];
+    $flags = $_[4];
+    $clean = $_[5];
+    # create sub-directory in output dir
+    $outdir = $workspace . $outsubdir;
+    unless (-e $outdir) { unless (mkdir ($outdir,0777)) { goodbye "cannot create output directory $outdir"; } }
+    # make link to correct flat
+    $flatlink = $flatdir . "newflat.fits";
+    $realflat = $flatdir . "flatcode" . $phot . ".fits";
+    if (-l $flatlink) { unless (unlink ($flatlink)) { goodbye "cannot unlink $flatlink"; }}
+    if (-e $flatlink) { goodbye "$flatlink exists, but is not a link!"; }
+    unless (symlink ($realflat, $flatlink)) { goodbye "cannot symlink $realflat to $flatlink"; }
+    # run controller and cleanup
+    vsystem ("control1 $flags -o $outsubdir $in $out $phot");
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+}
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $out = $_[1];
+    $mode = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    print STDERR ".";
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# check the earlier status values: if failed earlier, skip
+	$skip = 0;
+	for ($m = 1; $m < $mode; $m++) { if (!$pvalues[$m]) { $skip = 1; } }
+	if (! $skip && !$pvalues[$mode]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	open (OUTLIST, ">$out");
+	for ($k = 0; $k < $Nout; $k++) {
+	    print OUTLIST "$outarray[$k]\n";
+	}
+	close (OUTLIST);
+    }
+    $Nout;
+}
+
+sub parse_inlist {
+    $in = $_[0];
+    $out = $_[1];
+    $new = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+
+# load inlist
+    open (OUTLIST, $out);
+    @outarray = ();
+    while ($line = <OUTLIST>) {
+	chop ($line);
+	@outarray = (@outarray,$line);
+    }
+    $Nout = @outarray;
+    close (OUTLIST);
+
+# load outlist
+    @newarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	$gotit = 0;
+	for ($m = 0; ! $gotit && ($m < $Nout); $m++) {
+	    if ($outarray[$m] =~ /$inarray[$k]/) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @newarray = (@newarray,$inarray[$k]);
+	}
+    }
+    $Nnew = @newarray;
+    if ($Nnew) {
+	open (NEWLIST, ">$new");
+	for ($k = 0; $k < $Nnew; $k++) {
+	    print NEWLIST "$newarray[$k]\n";
+	}
+	close (NEWLIST);
+    }
+    $Nnew;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/stage2
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/stage2	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/stage2	(revision 16632)
@@ -0,0 +1,307 @@
+#!/usr/bin/env perl
+
+# in this script, we run addstar and the cleaning routines
+# these must be run in series, so this routine runs
+# independently of the parallel processing in stage1
+
+# for now these directories are hard-wired.  eventually, they
+# should be looked up in the config file, so all scripts are
+# consistent
+$dumpspace = "/pallas/d1/";
+$workspace = "/metis/d27/workspace/";
+# $workspace = "/irene/d11/workspace/";
+
+#$scriptdir = "/hebe/d27/logs/";
+$scriptdir = "./";
+$addstarfile = $scriptdir . "addstared.log";
+$processfile = $scriptdir . "processed.log";
+$flatdir = "/hebe/d27/references/config/";
+
+$database = "/hebe/d27/database/";
+$lockfile = $database . "lock";      # lock on database files
+$alockfile = $database . "alock2";   # lock on stage2 (only 1 running at a time)
+$clockfile = $database . "clock2";   # lock on control2
+$killfile  = $database . "kill";     # quickly stop the processing
+$haltfile  = $database . "halt";     # halt processing after this loop
+$reffile = $database . "start.clean";
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    vsystem ("notify.pl $ARGV[0] none 0");
+    die "@_";
+}
+
+if (@ARGV < 1) {die "USAGE: stage2 Noutfile\n"; }
+$Noutfile = $ARGV[0] + 1;
+$outfile = "stage2." . $Noutfile . ".log";
+
+print STDERR "starting execution\n";
+vsystem ("date");
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+if (-e $alockfile) { goodbye "archive lock $alockfile is set"; }
+open (TEMP, ">$alockfile");
+close (TEMP);
+
+$Ntries = 0;
+$Nleft = 0;
+@leftlist = ();
+
+while (! $Nleft) {
+    compare_done_todo ();
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    vsystem ("sleep 60");
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    $Ntries ++;
+    if ($Ntries == 1440) { goodbye "timeout waiting for new data"; }
+}
+
+if (-e $killfile) { goodbye "process killed with $killfile"; }
+
+chdir $scriptdir;
+
+for ($i = 0; $i < $Nleft; $i++) {
+    print STDERR "adding: $leftlist[$i]\n";
+    @entries = split (" ",$leftlist[$i]);
+    $inlist = $entries[0] . ".addlist";
+    $outlist = $entries[0] . ".outlist";
+    $subdir = $entries[0];
+    $photcode = $entries[1];
+    print STDERR "$subdir: $inlist $outlist $photcode\n";
+    if (-e $outlist) {
+	# partially successful run, restart controller in the middle
+	$tmp_inlist = $entries[0] . ".tmpaddlist";
+	$tmpoutlist = $entries[0] . ".tmpoutlist";
+	if (-e $tmpoutlist) { if (vsystem ("cat $tmpoutlist >> $outlist")) { goodbye "trouble merging $tmpoutlist and $outlist\n"; }}
+	# partially successful re-start: make sure $outlist is complete
+	print STDERR "re-running unfinished entries in outlist\n";
+	if (parse_outlist ($outlist,$tmp_inlist, 4)) {
+	    docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s addstar", 0);
+	    vsystem ("cat $tmpoutlist >> $outlist");
+	}
+	# do inlist entries not in outlist
+	print STDERR "running undone entries in addlist\n";
+	parse_outlist ($inlist,"tmpinlist", 4);
+	parse_outlist ($outlist,"tmpoutlist", 5);
+	if (match_lists ("tmpinlist","tmpoutlist","$tmp_inlist")) {
+	    docontroller ($subdir, $tmp_inlist, $tmpoutlist, $photcode, "-s addstar", 0);
+	    vsystem ("cat $tmpoutlist >> $outlist");
+	}
+	# check ending success
+	unless (unlink ($tmpoutlist)) { goodbye "can't unlink $tmpoutlist, why not?"; }
+	unless (unlink ($tmp_inlist)) { goodbye "can't unlink $tmp_inlist, why not?"; }
+	vsystem ("cleaning.pl");
+	if (-e $lockfile) { goodbye "lock file exists"; }
+	
+	print STDERR "done: $subdir\n";
+	open (DONELOG, ">>$addstarfile");
+	print DONELOG "$subdir\n";
+	close (DONELOG);
+    } else {
+	$controlflags = "";
+	parse_outlist ($inlist,"tmpinlist", 4);
+	docontroller ($subdir, "tmpinlist", $outlist, $photcode, "-s addstar", 1);
+	print STDERR "done: $subdir\n";
+	open (DONELOG, ">>$addstarfile");
+	print DONELOG "$subdir\n";
+	close (DONELOG);
+    }
+}
+unless (unlink ($alockfile)) { goodbye "can't unlink $alockfile, why not?"; }
+print STDERR "remember to delete images from complete directories\n";
+
+unless (-e $haltfile) { 
+    print STDERR "re-did unfinished images\n";
+    print STDERR "starting a new stage2 with output to $outfile\n";
+    vsystem ("notify.pl $ARGV[0] $outfile $Noutfile");
+    vsystem ("stage2 $Noutfile 1>$outfile 2>&1 &");
+    exit;
+}
+goodbye "added images";
+exit;
+
+# do controller (& cleaning if needed), taking care of flats and error conditions
+sub docontroller {
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    # break up entry line
+    $outsubdir = $_[0];
+    $in = $_[1];
+    $out = $_[2];
+    $phot = $_[3];
+    $flags = $_[4];
+    $clean = $_[5];
+    # run controller and cleanup
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    vsystem ("control2 $flags -o $outsubdir $in $out $phot");
+    if (-e $clockfile) { goodbye "lock file $clockfile exists"; }
+    if (-e $lockfile) { goodbye "lock file exists"; }
+    if (-e $killfile) { goodbye "process killed with $killfile"; }
+    if ($clean) {
+	vsystem ("cleaning.pl");
+	if (-e $lockfile) { goodbye "lock file exists"; }
+    }
+}
+
+sub by_filename {
+    @value1 = split (" ", $a);
+    @value2 = split (" ", $b);
+    $value1[0] cmp $value2[0]; 
+}
+    
+# we read from in and write to out those files with 1st 0 in the mode column
+sub parse_outlist {
+    $in = $_[0];
+    $out = $_[1];
+    $mode = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+    @inarray = sort by_filename @inarray;
+
+    @outarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	@pvalues = split (" ", $inarray[$k]);
+	$more = 1;
+	while ($more) {
+	    print STDERR ".";
+	    @nvalues = split (" ", $inarray[$k+1]);
+	    if ($nvalues[0] cmp $pvalues[0]) {
+		$more = 0;
+	    } else {
+		$pvalues[1] |= $nvalues[1];
+		$pvalues[2] |= $nvalues[2];
+		$pvalues[3] |= $nvalues[3];
+		$pvalues[4] |= $nvalues[4];
+		$pvalues[5] |= $nvalues[5];
+		$k ++;
+	    }
+	}
+	# in this version, we only care about pvalues[4,5] (addstar) 
+	if (($mode == 4) && $pvalues[4] && !$pvalues[5]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	} 
+	if (($mode == 5) && $pvalues[5]) {
+	    $name = $pvalues[0];
+	    $name =~ s/$dumpspace//;
+	    $name =~ s/://;
+	    @outarray = (@outarray,$name);
+	}
+    }
+    $Nout = @outarray;
+    if ($Nout) {
+	open (OUTLIST, ">$out");
+	for ($k = 0; $k < $Nout; $k++) {
+	    print OUTLIST "$outarray[$k]\n";
+	}
+	close (OUTLIST);
+    }
+    $Nout;
+}
+
+# find lines in inlist which are not in outlist
+sub match_lists {
+    $in = $_[0];
+    $out = $_[1];
+    $new = $_[2];
+    
+# load inlist
+    open (INLIST, $in);
+    @inarray = ();
+    while ($line = <INLIST>) {
+	chop ($line);
+	@inarray = (@inarray,$line);
+    }
+    $Nin = @inarray;
+    close (INLIST);
+
+# load outlist
+    open (OUTLIST, $out);
+    @outarray = ();
+    while ($line = <OUTLIST>) {
+	chop ($line);
+	@outarray = (@outarray,$line);
+    }
+    $Nout = @outarray;
+    close (OUTLIST);
+
+# find matched lines 
+    @newarray = ();
+    for ($k = 0; $k < $Nin; $k++) {
+	$gotit = 0;
+	for ($m = 0; ! $gotit && ($m < $Nout); $m++) {
+	    if ($outarray[$m] =~ /$inarray[$k]/) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @newarray = (@newarray,$inarray[$k]);
+	}
+    }
+    $Nnew = @newarray;
+    if ($Nnew) {
+	open (NEWLIST, ">$new");
+	for ($k = 0; $k < $Nnew; $k++) {
+	    print NEWLIST "$newarray[$k]\n";
+	}
+	close (NEWLIST);
+    }
+    $Nnew;
+}
+
+sub compare_done_todo {
+    print STDERR "starting compare\n";
+# load in done date list
+    open (DONELOG, $addstarfile);
+    @donelist = ();
+    while ($line = <DONELOG>) {
+	chop ($line);
+	@donelist = (@donelist,$line);
+    }
+    $Ndone = @donelist;
+    close (DONELOG);
+
+# load in maestro list
+    open (TODOLOG, $processfile);
+    @todolist = ();
+    while ($line = <TODOLOG>) {
+	chop ($line);
+	@todolist = (@todolist,$line);
+    }
+    $Ntodo = @todolist;
+    close (TODOLOG);
+
+# find entries in MAESTRO that are NOT in DONELOG
+    for ($i = 0; $i < $Ntodo; $i ++) {
+	$gotit = 0;
+	for ($j = 0; ($j < $Ndone) && ! $gotit; $j ++) {
+	    @todo = split (" ",$todolist[$i]);
+	    @done = split (" ",$donelist[$j]);
+	    if ($todo[0] eq $done[0]) {
+		$gotit = 1;
+	    }
+	}
+	if (!$gotit) {
+	    @leftlist = (@leftlist, $todolist[$i]);  
+	}
+    }
+    $Nleft = @leftlist;
+    $Nleft;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/loneos/testlogs.pl
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/loneos/testlogs.pl	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/loneos/testlogs.pl	(revision 16632)
@@ -0,0 +1,86 @@
+#!/usr/bin/perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    vsystem ("date");
+    die "@_";
+}
+
+$Nline = -1;
+while ($line = <STDIN>) {
+    $Nline ++;
+    if ($Nline == 0) {	next; }
+    if ($Nline == 1) {
+	@parts = split (" ",$line);
+	$N1 = $parts[9];
+	next;
+    }
+    if ($Nline == 2) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+	if ($N1 != $N2) {
+	    print STDERR "problem in dophot\n";
+	    exit;
+	}
+	next;
+    }
+    if ($Nline == 3) {
+	@parts = split (" ",$line);
+	$N1 = $parts[10];
+	next;
+    }
+    if ($Nline == 4) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+        if ($N1 != $N2) {
+            print STDERR "problem in fstat\n";
+	    exit;
+        }
+	next;
+    }
+    if ($Nline == 5) {
+	@parts = split (" ",$line);
+	$N1 = $parts[8];
+	next;
+    }
+    if ($Nline == 6) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+        if ($N1 != $N2) {
+            print STDERR "problem in gastro\n";
+            exit;
+        }
+	next;
+    }
+    if ($Nline == 7) {
+	@parts = split (" ",$line);
+	$N1 = $parts[6];
+	next;
+    }
+    if ($Nline == 8) {
+	@parts = split (" ",$line);
+	$N2 = $parts[2];
+        if ($N1 != $N2) {
+            print STDERR "problem in addstar\n";
+            exit;
+        }
+	next;
+    }
+    if ($Nline > 8) {
+	print STDERR "$line\n";
+	print STDERR "too many lines?\n";
+	exit;
+    }
+
+}
+
+if ($Nline != 8) {
+    print STDERR "not enough lines\n";
+    exit;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/new/defringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/new/defringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/new/defringe	(revision 16632)
@@ -0,0 +1,65 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { &usage; }
+
+# command line arguments
+$inlist  = $ARGV[0];
+$outlist = $ARGV[1];
+
+# setup elixir references
+$coordpath = `gconfig FRINGE_COORD_PATH`;  chop $coordpath;
+$confdir   = `gconfig CONFDIR`;            chop $confdir;
+$script    = "$confdir/mana/fringe.pro";   
+
+$filtkwd   = `gconfig FILTER-KEYWORD`;     chop $filtkwd;
+$camerakwd = `gconfig CAMERA-KEYWORD`;     chop $camerakwd;
+$ccdkwd    = `gconfig CCDNUM-KEYWORD`;     chop $ccdkwd;
+
+$Nccd      = `cameraconfig -Nccd`;         chop $Nccd;
+$answer    = `cameraconfig -ccds`;
+@ccds      = split (" ", $answer);
+
+# temporary files needed:
+set imstats=`mktemp /tmp/defringe.XXXXXX`;
+set frstats=`mktemp /tmp/defringe.XXXXXX`;
+
+# calculate imstats for the input image, get stats from fringe image header
+set filtvalue = `head -1 $imlist | fields $filtkwd | awk '{print $2}'`;
+set filter = `filtnames $filtvalue`;
+
+set camera = `head -1 $imlist | fields $camerakwd | awk '{print $2}'`;
+if ("$camera" == "") set camera = "WFI";
+
+# load input / output lists:
+open (FILE, "$inlist");
+@inlist = <FILE>;
+close (FILE);
+
+open (FILE, "$outlist");
+@outlist = <FILE>;
+close (FILE);
+
+if (@inlist != @outlist) { die "ERROR: mismatched lists\n"; }
+ 
+# measure fringe amplitude
+
+
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print STDERR "USAGE: defringe (inlist) (outlist)\n";
+    exit 2;
+}
+
+sub uppercase {
+    return "\U$_[0]\E";
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/new/getfringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/new/getfringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/new/getfringe	(revision 16632)
@@ -0,0 +1,80 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 4) { die "USAGE: gtfringe (in.fits) (fringe.coords) (binning) (out.dat)\n"; }
+
+$input   = $ARGV[0];
+$coords  = $ARGV[1];
+$binning = $ARGV[2];
+$output  = $ARGV[3];
+
+# create temporary files:
+$PARFILE = `mktemp /tmp/gtfringe.XXXXXX`;
+$INFILE  = `mktemp /tmp/@gtfringe.XXXXXX`
+$OUTFILE = `mktemp /tmp/gtfringe.XXXXXX`
+
+# convert 
+
+open (FILE, "$inlist");
+@mef = <FILE>;
+close (FILE);
+
+@split = ();
+foreach $name (@mef) {
+    chop ($name);
+
+    # convert name /path/name.fits to /outdir/rootNN.fits
+    @words = split ("/", $name);
+    $root = $words[-1];
+    $root =~ s/.fits//;
+    
+    $new = sprintf "%s/%s%02d.fits", $outdir, $root, $ccd;
+    push @split, $new;
+}
+    
+open (MANA, "|mana --norc");
+
+# define the macro 'split'
+print MANA "macro split\n";
+print MANA " rd a \$1 -n $ccd\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+print MANA " if ((\$nx == 2080) && (\$ny == 4128))\n";
+print MANA "   wd a \$2 -bitpix 16 -bzero 32768 -bscale 1.0\n";
+print MANA "   exec echo \$2 >> $outlist\n";
+print MANA " end\n";
+print MANA "end\n";
+
+# create the macro 'go' with the commands 
+print MANA "macro go\n";
+for ($i = 0; $i < @mef; $i++) {
+    if (-e $split[$i]) { 
+	print STDERR "$split[$i] exists, skipping\n";
+	next; 
+    }
+    print MANA " split $mef[$i] $split[$i]\n";
+}
+# if the macro ends successfully, exit 0
+print MANA " exit 0\n";
+print MANA "end\n";
+
+# if the macro exits before the end, exit 1
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+
+$status = $?;
+print STDERR "mana exit status: $status\n";
+if ($status) {
+    print STDERR "ERROR: problem running split.mef\n";
+    exit 1;
+}
+
+print STDERR "SUCCESS\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/clear.rawdir
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/clear.rawdir	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/clear.rawdir	(revision 16632)
@@ -0,0 +1,258 @@
+#!/usr/bin/env perl
+
+# this script is very much specific to the CFHT data layout
+
+$archive = "/h/archive/current/instrument/cfh12k";
+$force = 0;
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    if ($ARGV[0] eq "-force") {
+	shift;
+	$force = 1;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 1) { die "USAGE: clean.rawdir (crunid)\n" ;}
+
+if ($ARGV[0] eq "-current") {
+    $runid = `gconfig -q RUNID`; chop ($runid);
+} else {
+    $runid = $ARGV[0];
+}
+print "runid: $runid\n";
+
+$rawdir = `gconfig -q -D RUNID $runid RAWDIR`; chop ($rawdir);
+if ($rawdir eq "") {
+    print STDERR "can't find config entry RAWDIR\n";
+    exit 1;
+}
+print "rawdir: $rawdir\n";
+
+@meflist = ();
+@splitlist = ();
+
+# load in the MEF files (must be of format 123456x.fits)
+@tlist = <$rawdir/*.fits>;
+foreach $tname (@tlist) { 
+    if ((-f $tname) && ($tname =~ /\d\d\d\d\d\d\w.fits$/)) { 
+	@meflist = (@meflist, $tname); 
+    } 
+}
+
+# load in the SPLIT directories (must be of format 123456x)
+@tlist = <$rawdir/???????>;
+foreach $tname (@tlist) { 
+    if ((-d $tname) && ($tname =~ /\d\d\d\d\d\d\w$/)) { 
+	@splitlist = (@splitlist, $tname); 
+    } 
+}
+$N1 = @meflist;
+$N2 = @splitlist;
+
+foreach $file (@meflist) {
+
+    # grab the root name:
+    $root = mefnames ($file, "root");
+    
+    $arname = "$archive/$root.fits";
+    $newname = $file;
+
+    # check that the file exists in the archive
+    if (-l $file) { next; }
+    if (! -e $arname) { next; }
+    if (! -f $arname) { next; }
+
+    unlink $file;
+    symlink $arname, $newname;
+}
+
+foreach $file (@splitlist) {
+
+    # grab the root name:
+    $root = splitnames ($file, "root");
+    
+    $arname = "$archive/$root.fits";
+    $newname = "$rawdir/$root.fits";
+
+    # check that the file exists in the archive
+    if (! -e $arname) { next; }
+    if (! -f $arname) { next; }
+
+    vsystem ("rm -rf $file\n");
+    symlink $arname, $newname;
+    vsystem ("imsearch -name $root -split2mef\n");
+}
+
+exit 0;
+
+# utilities ##############################################
+
+sub gt_names {
+    # in: filename mode type
+    # out: word
+
+    my ($value);
+
+    $value = "";
+    if ($_[2] eq "MEF")   { $value = mefnames ($_[0], $_[1]); }
+    if ($_[2] eq "SPLIT") { $value = splitnames ($_[0], $_[1]); }
+    
+    return $value;
+}
+
+sub mefnames {
+    # in: (/path/file.fits) (mode) 
+    # out: word
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer);
+
+    # split rootdir and filename:
+    my (@words) = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	$answer =~ s/.fits$//;
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	if (! -e $fullname) {
+	    return (0);
+	}
+	$answer = `echo $fullname | fields NEXTEND`;
+	@words = split (" ", $answer);
+	if ($words[1] eq "") {
+	    return (0);
+	}
+	return ($words[1]);
+    }
+    
+    return (0);
+}
+
+sub splitnames {
+    # in: (/path/file) (mode) 
+    # out: word
+    # /path/file is directory containing Nccd fits images
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer, $N, $tmpname, @imlist, @words);
+
+    # split rootdir and filename:
+    @words = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	
+	$tmpname = "$fullname/$words[$N-1]";
+	@imlist = <$tmpname??.fits>;
+
+	$Nccd = @imlist;
+	return $Nccd;
+    }
+    
+    return (0);
+}
+
+sub ckimtype {
+    # in: (/path/file)
+    # out: MEF | SPLIT | SINGLE | (NULL)
+    
+    my ($answer, $name, $value);
+    my ($file) = $_[0];
+
+    if (! -e $file) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+
+    # if /path/file is a directory, it is split:
+    if (-d $file) { return "SPLIT"; }
+
+    # check that the file is a FITS image
+    $answer = `file -L $file`;
+    if ($?) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+    ($name, $value) = split (" ", $answer);
+    if ($value ne "FITS") { 
+	print STDOUT "not a valid image\n";
+	return ""; 
+    }
+    
+    # check for NAXIS = 0 (MEF) 
+    $answer = `echo $file | fields NAXIS`;
+    # if ($?) { return ""; }
+    ($name, $value) = split (" ", $answer);
+    if ($value eq 0) { return "MEF"; }
+    
+    if ($value == 2) { return "SINGLE"; }
+
+    print STDOUT "not a valid image\n";
+    return "";
+}
+
+sub vsystem {
+    # print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+
+# This program calls several other perl scripts to get information 
+# about the image.  
+# ckrunid   - determine the appropriate Camera Run ID for this image
+# ckastrom  - check for the appropriate astrometry information
+# ckdetrend - check for the appropriate detrend images
+# ckphotom  - check for the appropriate photometry data
+
+# at the moment, there are different calling conventions for each of
+# these functions.  Some take a single name (MEF / SPLIT), some take a
+# reference to the specific CCD (filename CCD MODE).  
+
+# none of the called functions need to find the number of CCDs
+# ckvalid determines the number of CCDs from the header (MEF) or the
+# number of appropriately named FITS files in the directory (SPLIT).
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/create.imlists
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/create.imlists	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/create.imlists	(revision 16632)
@@ -0,0 +1,67 @@
+#!/usr/bin/env perl
+
+# take single list of images, create collection of lists in path, each with files for one image,
+# place list of lists in outlist
+
+if (@ARGV != 3) { die "ERROR: USAGE: create.subset (inlist) (path) (outlist)\n" }
+
+$inlist = $ARGV[0];
+$path = $ARGV[1];
+$outlist = $ARGV[2];
+
+open (FILE, $inlist);
+@inlist = <FILE>;
+close (FILE);
+foreach $name (@inlist) { chop ($name); }
+
+open (OUT, ">$outlist");
+
+while (@inlist) {
+    $name = pop (@inlist); 
+
+    @sublist = ($name);
+    ($subname, $ext) = $name =~ /(\S+)(\d\d\D+)/;
+    ($filename) = $subname =~ /(\d\d\d\d\d\d.)$/;
+    print STDERR "subname: $subname\n";
+    print STDERR "filename: $filename\n";
+    print STDERR "ext: $ext\n";
+    
+    @outlist = ();
+    while (@inlist) {
+	$name = pop (@inlist);
+	
+	if ($name =~ /$subname/) {
+	    push (@sublist, $name);
+	} else {
+	    push (@outlist, $name);
+	}
+    }
+    
+    @sublist = sort @sublist;
+
+    # file lists have names like /path/filename.imlist
+    open (FILE, ">$path/$filename.imlist");
+    foreach $name (@sublist) {
+	print FILE "$name\n";
+    }
+    close (FILE);
+
+    print OUT "$path/$filename.imlist\n";
+
+    @inlist = @outlist;
+}
+
+close (OUT);
+
+###########################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/elixir.grabd
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/elixir.grabd	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/elixir.grabd	(revision 16632)
@@ -0,0 +1,159 @@
+#!/usr/bin/env perl
+
+# this daemon creates links for new images in the elixir TMPDIR tree
+# and registers the images in the elixir database, and sends the image 
+# to imstats for processing.
+
+# the standard elixir config system is used to id the TMPDIR and the 
+# appropriate imstats.fifo, etc.
+
+# TMPDIR should be checked on each scan loop, in case the TMPDIR or
+# RUNID is switched
+
+# make sure the appropriate config file is used.
+
+use English;
+
+# check usage
+if (@ARGV != 0) { die "USAGE: elixir.grabd\n"; }
+
+# what do we do about config file?  demand account be set up correctly?
+$fifos = `gconfig FIFOS`; chop ($fifos);
+if ($?) { die "error in config system\n"; }
+
+# check for existing process and exit
+$pidfile = "$fifos/gradb.pid";
+if (-e $pidfile) {
+    $line = `head -1 $pidfile`;
+    ($ohost, $ouser, $opid) = split (" ", $line);
+
+    print STDERR "elixir.grabd is already being run:\n";
+    print STDERR " machine: $ohost\n";
+    print STDERR " user:    $ouser\n";
+    print STDERR " pid:     $opid\n";
+    print STDERR " pidfile: $pidfile\n";
+    exit 1;
+}
+
+# set process lock file:
+$host = `hostname`; chop ($host);
+$user = getlogin;
+open (FILE, ">$pidfile");
+print FILE "$host $user $PID\n";
+close (FILE);
+
+# place this in the config system?
+$srcdir = "/data/kapu/elixir/cfh12k";
+while (-e $pidfile) {
+    grabfiles ();
+    system ("sleep 60");
+}
+
+# clear process lock file:
+unlink ($pidfile);
+exit 0;
+
+
+##########################################################
+
+sub grabfiles () {
+    
+    $rawdir = `gconfig -q RAWDIR`;  chop $rawdir;
+
+    @files = glob ("$srcdir/*");
+    
+    if (! @files) {
+	system ("sleep 60");
+	return;
+    }
+
+    foreach $name (@files) {
+	if (! -l $name) { next; }
+	
+	# find real path
+	$path = convertlink ($name);
+	$file = filename ($path);
+
+	# set new path (skip if it exists)
+	$new = sprintf "%s/%s", $rawdir, $file;
+	if (-e $new) { 
+	    print STDERR "skipping file\n";
+	    next; 
+	}
+	
+	# print "$name -> $path ($file) -> $new\n";
+
+	# link file to rawdir:
+	symlink ($path, $new);
+	
+	# these files always come in as MEF
+	vsystem ("imsort $new");
+	if ($?) { next; }
+	
+	unlink $name
+    }
+}
+
+
+# utilities ##############################################
+sub vsystem {
+    print STDERR "@_\n";
+    my ($status) = system ("@_");
+    $status;
+}
+
+sub filename { 
+
+    my ($path) = $_[0];
+    my (@tmp);
+    
+    @tmp = split ("/", $path);
+    return $tmp[-1];
+}
+
+sub convertlink {
+    my ($link) = $_[0];
+    my ($file);
+
+    while (-l $link) {
+	$file  = readlink ($link);
+	$path1 = path ($link);
+	$path2 = path ($file);
+	
+	unless ($path2 =~ m|^/|) {
+	    $file = "$path1/$file";
+	}	
+	$link = $file;
+    }
+    return ($link);
+}    
+
+sub usage {
+    
+    if (@ARGV == 1) {
+	print STDERR "\n --- user modes ---\n";
+	print STDERR "create (run) (start) (stop)\n";
+	print STDERR "addqso (runid) (qsoid)\n";
+	print STDERR "delqso (qsoid)\n";
+	print STDERR "sched (runid)\n";
+	print STDERR "status\n";
+	&goodbye;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: prepare.run (help) [mode]\n"; &goodbye; }
+    
+    &goodbye;
+}
+
+sub path {
+
+    my ($file) = $_[0];
+
+    @words = split ("/", $file);
+
+    pop (@words);
+    
+    $path = join ("/", @words);
+
+    return ($path);
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/fixlists
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/fixlists	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/fixlists	(revision 16632)
@@ -0,0 +1,43 @@
+#!/usr/bin/env perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 3) { die "ERROR: USAGE: fixlists (in) (keep) (out)\n" }
+
+open (FILE, $ARGV[1]);
+@keep = ();
+while ($line = <FILE>) {
+    chop ($line);
+    @keep = (@keep, $line);
+}
+close (FILE);
+
+open (IN, $ARGV[0]);
+open (OUT, ">$ARGV[2]");
+
+for ($j = 0; $line = <IN>; $j++) {
+    chop ($line);
+    $found = 0;
+    for ($i = 0; !$found && ($i < @keep); $i++) {
+	if ($keep[$i] == $j) {
+	    $found = 1;
+	}
+    }
+    if ($found) {
+	print OUT "$line\n";
+    }
+}
+close (IN);
+close (OUT);
+
+print STDERR "SUCCESS\n";
+
+# put the logic for selecting images in this file
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/fl.split2mef
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/fl.split2mef	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/fl.split2mef	(revision 16632)
@@ -0,0 +1,98 @@
+#!/usr/bin/env perl
+
+# check the usage
+if (@ARGV != 2) { die "USAGE: fl.split2mef (file.master) (splitdir)\n" }
+
+# assign the command line arguments
+$master = $ARGV[0];
+$splitdir = $ARGV[1];
+
+open (FILE, "$master");
+@master = <FILE>;
+close (FILE);
+
+# master contains lines from both split and mef.  
+# convert all to split format, and write to root.mef
+# empty the split file, re-write the master file with new names.
+# when the new mef list is run through split.mef, only un-split entries 
+# will get split
+
+# /data/koa/cfh12k/01Ak05/587554f/587554f04.fits
+# /data/elixir2/cfh12k/detrend/01Ak04/split/582967f00.fits 1
+
+foreach $line (@master) {
+    
+    ($name, $mode) = split (" ", $line);
+
+    # test filename:
+    unless ($name =~ m|/\d\d\d\d\d\d\w\d\d.fits\Z|) {
+	print STDERR "Error with $name: not in split-name format\n";
+	next;
+    }
+
+    ($path, $root1, $root2, $ccd) = $name =~ m|(\S+)/(\d\d\d\d\d\d\w)/(\d\d\d\d\d\d\w)(\d\d).fits\Z|;
+    
+    # test for originally SPLIT image:
+    if ($root1 eq $root2) {
+	# check for existence of mef version file:
+	$new = sprintf "%s/%s.fits", $path, $root1;
+	if (! -e $new)  {
+	    print STDERR "Error, file $new is missing\n";
+	    exit 1;
+	}
+	@newmef = (@newmef, $new);
+
+	# create split version name:
+	$new = sprintf "%s/%s%02d.fits", $splitdir, $root1, $ccd;
+	@split = (@split, $new);
+	@splitmode = (@splitmode, $mode);
+	next;
+    }
+
+    # test for previously MEF -> SPLIT images: 
+    if ($root1 eq "split") {
+	@mef = (@mef, $name);
+	@mefmode = (@mefmode, $mode);
+	next; 
+    }
+    
+    print STDERR "Error with $name - neither split nor mef\n";
+}
+
+# empty *.split file
+$splitname = $master;
+$splitname =~ s/master\Z/split/;
+open (FILE, ">$splitname");
+close (FILE);
+
+# create *.mef file with new mefs (to be split)
+$mefname = $master;
+$mefname =~ s/master\Z/mef/;
+print STDERR "mefname: $mefname\n";
+open (FILE, ">$mefname");
+foreach $name (@newmef) {
+    print FILE "$name\n";
+}
+close (FILE);
+
+# save *.master file
+vsystem ("cp $master $master~");
+
+# re-create *.master file
+open (FILE, ">$master");
+@all = (@mef, @split);
+@allmode = (@mefmode, @splitmode);
+for ($i = 0; $i < @all; $i++) {
+    print FILE "$all[$i] $allmode[$i]\n";
+}
+close (FILE);
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/fr.detrend
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/fr.detrend	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/fr.detrend	(revision 16632)
@@ -0,0 +1,102 @@
+#!/usr/bin/env perl
+# calls flatten.flips, but no direct flips functions
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 4) { die "USAGE: fr.detrend (path) (root) (mode) (outdir)\n" }
+
+# assign the command line arguments
+$path = $ARGV[0];
+$root = $ARGV[1];
+$mode = "\U$ARGV[2]\E";
+if (($mode ne "MEF") && ($mode ne "SPLIT")) { die "ERROR: mode must be either -split or -mef\n";}
+$outdir = $ARGV[3];
+if (! -d $outdir) { vsystem ("mkdir -p $outdir"); }
+
+# get info on input image
+$basename = mk_basename ($path, $root, $mode);
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    
+    $infile  = mk_filename ($path, $root, $mode, $ccd);
+    $outfile = mk_filename2 ($outdir, $root, "SPLIT", $ccd);
+
+    $status = vsystem ("flatten.flips -quiet $infile $outfile $ccd $mode");
+    if ($status) { die "ERROR: problem running flatten on $infile\n"; }
+
+}
+
+print STDOUT "SUCCESS: finished with fr.detrend\n";
+exit 0;
+
+sub mk_basename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s", $path, $root;
+	return $name;
+    }
+    return "";
+}
+
+sub mk_filename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+    my ($ccd)  = $_[3];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s/%s%02d.fits", $path, $root, $root, $ccd;
+	return $name;
+    }
+    return "";
+}
+
+sub mk_filename2 {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+    my ($ccd)  = $_[3];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s%02d.fits", $path, $root, $ccd;
+	return $name;
+    }
+    return "";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.detrend (path) (root) (mode) (outdir)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/fr.gtstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/fr.gtstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/fr.gtstats	(revision 16632)
@@ -0,0 +1,75 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 3) { die "USAGE: fr.gtstats (inlist) (binning) (output)\n" }
+
+# define the path to include FLIPS:
+$flipsconf=`gconfig -q FLIPSCONF`; chop ($flipsconf);
+$flipspath=`gconfig -q FLIPSPATH`; chop ($flipspath);
+$ENV{'PATH'} = "$ENV{'PATH'}:$flipspath";
+$ENV{'FLIPSDIR'} = $flipsconf;
+
+# assign the command line arguments
+$inlist = $ARGV[0];
+$bin    = $ARGV[1];
+$output = $ARGV[2];
+
+# load input list:
+open (FILE, "$inlist");
+@inlist = <FILE>;
+close (FILE);
+
+# gtfringe is appending to the output file:
+unlink ($output);
+
+# we construct the Fringe Coord File from: FRINGE_COORD_PATH/CAMERA-FILTER-CCDNN-FringeCoord.reg
+$fkey      = `gconfig -q FILTER-KEYWORD`;    chop ($fkey);
+$ckey      = `gconfig -q CAMERA-KEYWORD`;    chop ($ckey);
+$coordpath = `gconfig -q FRINGE_COORD_PATH`; chop ($coordpath);
+$Nccd      = `cameraconfig -Nccd`;           chop ($Nccd);
+
+# double check lists size:
+if ($Nccd != @inlist) { die "ERROR: mis-matched image list sizes\n"; }
+
+# find filter and camera from image
+$answer = `echo $inlist[0] | fields $fkey $ckey`;
+($name, $filter, $camera) = split (" ", $answer);
+
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    
+    $infile    = $inlist[$ccd];
+    $coordfile = sprintf "%s/%s-%s-CCD%02d-FringeCoord.reg", $coordpath, $camera, $filter, $ccd;
+
+    # each call to gtfringe adds a line to $output 
+    vsystem ("gtfringe $infile $coordfile $bin $output");
+    if ($?) {
+	print STDERR "ERROR running gtfringe\n";
+	exit 1;
+    }
+}
+
+print STDOUT "SUCCESS: finished with fr.gtstats\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.gtstats (path) (root) (binning) (output)\n";
+    print " calculate fringe pattern strengths for images in (path)\n";
+    print " path:    path to MEF image or SPLIT dir\n";
+    print " root:    root name of image (MEF: root.fits, SPLIT: root/rootNN.fits)\n";
+    print " binning: binning factor of images\n";
+    print " outdir:  output file\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/fr.medbin
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/fr.medbin	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/fr.medbin	(revision 16632)
@@ -0,0 +1,71 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 4) { die "USAGE: fr.medbin (path) (root) (factor) (outpath)\n" }
+
+# assign the command line arguments
+$path = $ARGV[0];
+$root = $ARGV[1];
+$factor = $ARGV[2];
+$outpath = $ARGV[3];
+
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+
+# need some extra here: make the hierarchy needed, check exit status
+if (! -d $outpath) { vsystem ("mkdir -p $outpath"); }
+
+open (MANA, "|mana --norc");
+
+print MANA "macro mkmap\n";
+print MANA " rd a \$1\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+print MANA " medianmap a b {\$nx/$factor} {\$ny/$factor} -range 0.25 0.75\n";
+print MANA " wd b \$2\n";
+print MANA "end\n";
+
+print MANA "macro go\n";
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    $infile = sprintf "%s/%s%02d.fits", $path, $root, $ccd;
+    $outfile  = sprintf "%s/%s%02d.fits", $outpath, $root, $ccd;
+    print MANA " mkmap $infile $outfile\n";
+}
+print MANA " exit 0\n";
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR running mana\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.detrend\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.medbin (path) (root) (factor) (outpath)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/fr.stats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/fr.stats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/fr.stats	(revision 16632)
@@ -0,0 +1,69 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 5) { &usage (); }
+
+# assign the command line arguments
+$list   = $ARGV[0];
+$tenbin = $ARGV[1];
+$medbin = $ARGV[2];
+$stats  = $ARGV[3];
+$range  = $ARGV[4];
+
+# check for files to be processed
+@status = stat ($list);
+if ($status[7] == 0) {
+    print STDERR "no files in source list, skipping\n";
+    exit 1;
+}
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/fringe.pro";
+
+# test named Xserver, or start vnc on specified machine
+$xhost=`gconfig -q XHOST`; chop ($xhost);
+$xdisp=`gconfig -q XDISP`; chop ($xdisp);
+if (vsystem ("xdpyinfo -display $xdisp")) {
+    print STDERR "X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "\$RANGE = $range\n";
+print MANA "fringelist $list $tenbin $medbin $stats\n";
+print MANA "exit 1\n";
+close (MANA);
+
+if ($?) {
+    print STDERR "ERROR problem with fr.stats\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.stats\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fr.stats (list) (tenbin) (medbin) (stats) (range)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/fr.subset
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/fr.subset	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/fr.subset	(revision 16632)
@@ -0,0 +1,232 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 3) { die "ERROR: USAGE: fr.subset (master) (outdir) (subset)\n" }
+
+$inlist = $ARGV[0];
+$outdir = $ARGV[1];
+$outlist= $ARGV[2];
+
+print STDERR "ERROR: not fixed!!!\n";
+exit 1;
+
+# load in stats lines
+open (FILE,  "$ARGV[0]");
+@list = <FILE>;
+close (FILE);
+
+open (FILE, ">$outlist");
+
+foreach $line (@list) {
+    chop ($line);
+
+    # the infile contains (path) (root) (mode) (flag)
+    ($path, $root, $mode, $stat) = split (" ", $line);
+
+    if ($stat) {
+
+	$basename = mk_basename ($path, $root, $mode);
+	$Nccd = gt_names ($basename, "Nccd", $mode);
+
+	for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+
+	    $outfile = mk_filename ($outdir, $root, "SPLIT", $ccd);
+
+	    print FILE "$outfile\n";
+
+	}
+   }      
+}    
+close (FILE);
+
+print STDERR "SUCCESS\n";
+
+exit 0;
+
+######## cfht MEF/SPLIT name utilities ###########
+
+sub gt_names {
+    # in: filename mode type
+    # out: word
+
+    my ($value);
+
+    $value = "";
+    if ($_[2] eq "MEF")   { $value = mefnames ($_[0], $_[1]); }
+    if ($_[2] eq "SPLIT") { $value = splitnames ($_[0], $_[1]); }
+    
+    return $value;
+}
+
+sub mefnames {
+    # in: (/path/file.fits) (mode) 
+    # out: word
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer);
+
+    # split rootdir and filename:
+    my (@words) = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	$answer =~ s/.fits$//;
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	if (! -e $fullname) { return 0; }
+	$answer = `echo $fullname | fields NEXTEND`;
+	@words = split (" ", $answer);
+	if ($words[1] eq "") { return 0; }
+	return ($words[1]);
+    }
+    
+    return (0);
+}
+
+sub splitnames {
+    # in: (/path/file) (mode) 
+    # out: word
+    # /path/file is directory containing Nccd fits images
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer, $N, $tmpname, @imlist, @words);
+
+    # split rootdir and filename:
+    @words = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	
+	$tmpname = "$fullname/$words[$N-1]";
+	@imlist = <$tmpname??.fits>;
+
+	$Nccd = @imlist;
+	return $Nccd;
+    }
+    
+    return (0);
+}
+
+sub ckimtype {
+    # in: (/path/file)
+    # out: MEF | SPLIT | SINGLE | (NULL)
+    
+    my ($answer, $name, $value);
+    my ($file) = $_[0];
+
+    if (! -e $file) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+
+    # if /path/file is a directory, it is split:
+    if (-d $file) { return "SPLIT"; }
+
+    # check that the file is a FITS image
+    $answer = `file -L $file`;
+    if ($?) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+    ($name, $value) = split (" ", $answer);
+    if ($value ne "FITS") { 
+	print STDOUT "not a valid image\n";
+	return ""; 
+    }
+    
+    # check for NAXIS = 0 (MEF) 
+    $answer = `echo $file | fields NAXIS`;
+    # if ($?) { return ""; }
+    ($name, $value) = split (" ", $answer);
+    if ($value eq 0) { return "MEF"; }
+    
+    if ($value == 2) { return "SINGLE"; }
+
+    print STDOUT "not a valid image\n";
+    return "";
+}
+
+sub mk_basename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s", $path, $root;
+	return $name;
+    }
+    return "";
+}
+
+sub mk_filename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+    my ($ccd)  = $_[3];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s/%s%02d.fits", $path, $root, $root, $ccd;
+	return $name;
+    }
+    return "";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.detrend (path) (root) (mode) (outdir)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/get.standards
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/get.standards	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/get.standards	(revision 16632)
@@ -0,0 +1,103 @@
+#!/usr/bin/env perl
+
+# this script is very much specific to the CFHT data layout
+
+$VERBOSE = 1;
+$stdpath = "/h/archive/current/01aq97";
+
+$run = "all";
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    # by default, all OBJECT images are returned.  specify a run with -run
+    if ($ARGV[0] eq "-run") {
+	shift;
+	$run = $ARGV[0];
+	shift;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 0) { die "USAGE: ckrunid [-run RunID]\n" ;}
+
+# the archive is supposed to contain only MEF images.  
+# The standard star images might get a few focus or detrend images
+# mixed in, so restrict the glob to only *o.fits images:
+@imlist = <$stdpath/*o.fits>;
+
+# find date range in run list
+foreach $name (@imlist) {
+
+    if ($run eq "all") { 
+	@outlist = (@outlist, $name);
+	next; 
+    }
+
+    $runid = `ckrunid $name`;
+    if ($?) {
+	if ($VERBOSE) { print STDERR "no crunid for $name\n"; }
+	next;
+    }
+    chop ($runid);
+    
+    if ($runid ne $run) {
+	if ($VERBOSE) { print STDERR "wrong crunid for $name ($runid vs $run)\n"; }
+	next;
+    }
+
+    @outlist = (@outlist, $name);
+}
+
+foreach $name (@outlist) {
+    print STDOUT "$name\n";
+}
+
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub get_jd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5;
+    
+
+    return ($jd);
+
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/gtfringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/gtfringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/gtfringe	(revision 16632)
@@ -0,0 +1,80 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 4) { die "USAGE: gtfringe (in.fits) (fringe.coords) (binning) (out.dat)\n"; }
+
+$input   = $ARGV[0];
+$coords  = $ARGV[1];
+$binning = $ARGV[2];
+$output  = $ARGV[3];
+
+# create temporary files:
+$PARFILE = `mktemp /tmp/gtfringe.XXXXXX`;
+$INFILE  = `mktemp /tmp/@gtfringe.XXXXXX`
+$OUTFILE = `mktemp /tmp/gtfringe.XXXXXX`
+
+# convert 
+
+open (FILE, "$inlist");
+@mef = <FILE>;
+close (FILE);
+
+@split = ();
+foreach $name (@mef) {
+    chop ($name);
+
+    # convert name /path/name.fits to /outdir/rootNN.fits
+    @words = split ("/", $name);
+    $root = $words[-1];
+    $root =~ s/.fits//;
+    
+    $new = sprintf "%s/%s%02d.fits", $outdir, $root, $ccd;
+    push @split, $new;
+}
+    
+open (MANA, "|mana --norc");
+
+# define the macro 'split'
+print MANA "macro split\n";
+print MANA " rd a \$1 -n $ccd\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+print MANA " if ((\$nx == 2080) && (\$ny == 4128))\n";
+print MANA "   wd a \$2 -bitpix 16 -bzero 32768 -bscale 1.0\n";
+print MANA "   exec echo \$2 >> $outlist\n";
+print MANA " end\n";
+print MANA "end\n";
+
+# create the macro 'go' with the commands 
+print MANA "macro go\n";
+for ($i = 0; $i < @mef; $i++) {
+    if (-e $split[$i]) { 
+	print STDERR "$split[$i] exists, skipping\n";
+	next; 
+    }
+    print MANA " split $mef[$i] $split[$i]\n";
+}
+# if the macro ends successfully, exit 0
+print MANA " exit 0\n";
+print MANA "end\n";
+
+# if the macro exits before the end, exit 1
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+
+$status = $?;
+print STDERR "mana exit status: $status\n";
+if ($status) {
+    print STDERR "ERROR: problem running split.mef\n";
+    exit 1;
+}
+
+print STDERR "SUCCESS\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/images.names
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/images.names	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/images.names	(revision 16632)
@@ -0,0 +1,170 @@
+#!/usr/local/bin/perl
+
+$WANT = 0;
+
+# possible things to return:
+$FILE    = 1;
+$PATH    = 2;
+$ROOT    = 3;
+$EXT     = 4;
+$NCCD    = 5;
+$CCD     = 6;
+$BASEEXT = 7;
+$CCDLIST = 8;
+
+while (@ARGV) {
+    
+    $name = shift (@ARGV);
+
+    # provided component(s)
+    if ($name eq "-file") {
+	$file = shift (@ARGV);
+    }
+    if ($name eq "-path") {
+	$path = shift (@ARGV);
+    }
+    if ($name eq "-root") {
+	$root = shift (@ARGV);
+    }
+    if ($name eq "-base") {
+	$base = shift (@ARGV);
+    }
+    if ($name eq "-ext") {
+	$ext = shift (@ARGV);
+    }
+    if ($name eq "-baseext") {
+	$baseext = shift (@ARGV);
+    }
+    if ($name eq "-Nccd") {
+	$Nccd = shift (@ARGV);
+    }
+    if ($name eq "-ccd") {
+	$ccd = shift (@ARGV);
+    }
+    if ($name eq "-mode") {
+	$mode = "\U$ARGV[0]\E";
+	shift (@ARGV);
+    }
+
+    # desired component
+    if ($name eq "+file") {
+	if ($WANT) { &badchoice; }
+	$WANT = $FILE;
+    }
+    if ($name eq "+path") {
+	if ($WANT) { &badchoice; }
+	$WANT = $PATH;
+    }
+    if ($name eq "+root") {
+	if ($WANT) { &badchoice; }
+	$WANT = $ROOT;
+    }
+    if ($name eq "+ext") {
+	if ($WANT) { &badchoice; }
+	$WANT = $EXT;
+    }
+    if ($name eq "+baseext") {
+	if ($WANT) { &badchoice; }
+	$WANT = $BASEEXT;
+    }
+    if ($name eq "+Nccd") {
+	if ($WANT) { &badchoice; }
+	$WANT = $NCCD;
+    }
+    if ($name eq "+ccd") {
+	if ($WANT) { &badchoice; }
+	$WANT = $CCD;
+    }
+    if ($name eq "+mode") {
+	if ($WANT) { &badchoice; }
+	$WANT = $MODE;
+    }
+}
+
+if ($base eq "") { $base = $root; }
+if ($root eq "") { $root = $base; }
+if ($ext eq "") { $ext = "fits"; }
+if ($path eq "") { $path = "."; }
+if ($mode eq "") { $mode = "MEF"; }
+
+if (@ARGV != 0) { &usage; }
+if (!$WANT) { &usage; }
+
+if (0) {
+    print STDERR "want: $WANT\n";
+    print STDERR "file: $file\n";
+    print STDERR "path: $path\n";
+    print STDERR "root: $root\n";
+    print STDERR "base: $base\n";
+    print STDERR "ext: $ext\n";
+    print STDERR "baseext: $baseext\n";
+    print STDERR "Nccd: $Nccd\n";
+    print STDERR "ccd: $ccd\n";
+    print STDERR "mode: $mode\n";
+}
+
+if ($WANT == $FILE) {
+    if ($mode eq "SPLIT") {
+	$output = sprintf "%s/%s%s/%s%02d.%s", $path, $base, $baseext, $root, $ccd, $ext;
+    }
+    if ($mode eq "MEF") {
+	$output = sprintf "%s/%s%s.%s", $path, $base, $baseext, $ext;
+    }
+}
+
+if ($WANT == $PATH) {
+    # split path and filename:
+    @words = split ("/", $file);
+    $N = @words;
+
+    for ($i = 0; $i < $N - 1; $i++) {
+	$output = $output . $words[$i] . "/";
+    }
+    chop ($output);   # strip off last /
+}
+
+if ($WANT == $CCD) {
+    # split path and filename:
+    @words = split ("/", $file);
+    $N = @words;
+
+    for ($i = 0; $i < $N - 1; $i++) {
+	$output = $output . $words[$i] . "/";
+    }
+    chop ($output);   # strip off last /
+}
+
+print STDOUT "$output\n";
+exit 0;
+
+# definition of the path components:
+
+# MEF:
+# /path/root/base.ext
+
+# SPLIT:
+# /path/root/base.ext
+
+# file = 
+# 1: /data/koa/cfh12k/01Ak01/543210f.fits
+# 2: /data/koa/cfh12k/01Ak01/543210f/543210f00.fits
+# 3: /data/koa/cfh12k/01Ak01/543210f.alt/543210f00.fits
+
+# base = 543210f
+# path = /data/koa/cfh12k/01Ak01 
+# root = 543210f (1,2), 543210f.alt (3)
+# ext  = fits
+# ext = "" (1,2), ".alt" (3)
+# Nccd = 12 [for CFH12K]
+# ccd  = NN (1), 00 (2,3)
+
+sub badchoice {
+    print STDERR "only one choice allowed\n"; 
+    exit 1; 
+}
+
+sub usage {
+    print STDERR "USAGE: image.names [options]\n";
+    exit 2;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/imselect
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/imselect	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/imselect	(revision 16632)
@@ -0,0 +1,189 @@
+#!/usr/bin/env perl
+$SKIPDOME = 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    die "@_";
+}
+
+if (@ARGV != 7) { die "ERROR: USAGE: imselect (ccd) (type) (filter) (tstart) (tend) (output) (-split | -mef)\n" }
+
+$type = "\U$ARGV[1]\E";
+if ($type eq "DARK") { }
+
+if ($type eq "FLAT") {
+    # define some of the relevant parameters
+    $min = 2000;
+    $max = 60000;
+    $minrate = 100;
+    $ratescale = 70;
+    $filter = "\U$ARGV[2]\E";
+    if ($filter eq "B") { $minrate = 0.5  * $ratescale;  }
+    if ($filter eq "V") { $minrate = 1.0  * $ratescale;  }
+    if ($filter eq "R") { $minrate = 3.5  * $ratescale;  }
+    if ($filter eq "I") { $minrate = 14.2 * $ratescale; }
+    if ($filter eq "Z") { $minrate = 10.5 * $ratescale; }
+    if ($filter eq "HA")    { $min = 1000; }
+    if ($filter eq "HAOFF") { $min = 1000; }
+    # probably need to set these in a more intelligent fashion.
+}
+
+# $ccd is ccd number (see camera config), $ARGV[0] is ccd id
+$ccd = `cameraconfig -N $ARGV[0]`; chop ($ccd);
+if ($ccd eq "") { die "ERROR : can't find CCD $ARGV[0]\n"; } 
+
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+$line = `cameraconfig -axes`; chop ($line);
+($Naxis1, $Naxis2) = split (" ", $line);
+
+$mode = "none";
+if ($ARGV[6] eq "-split") { $mode = "split"; }
+if ($ARGV[6] eq "-mef")   { $mode = "mef";   }
+if ($mode eq "none") {
+    die "ERROR: mode must be either -split or -mef\n";
+}
+
+@good = ();
+@marginal = ();
+
+# define filter lines for imsearch.  for flats, there may be alternate filter names to test
+@filtline = ();
+if ($type eq "FLAT") {
+    # convert given filter name to list of possible names:
+    $answer = `filtnames $ARGV[2] -all`;
+    @filtlist = split (" ", $answer);
+
+    foreach $name (@filtlist) {
+	$line = "-type flat -filter $name -mode $mode -trange $ARGV[3] $ARGV[4]";
+	push @filtline, $line;
+    }
+} 
+if ($type eq "BIAS") {
+    push @filtline, "-type bias -mode $mode -trange $ARGV[3] $ARGV[4]";
+} 
+if ($type eq "DARK") {
+    push @filtline, "-type dark -etime $ARGV[2] -mode $mode -trange $ARGV[3] $ARGV[4]";
+} 
+
+# run selection on each possible $filtline
+@list = ();
+foreach $line (@filtline) {
+    @tlist = `imsearch -ccd $ccd $line`;
+    @list = (@list, @tlist);
+}
+$Nlist = @list;
+print STDERR "found $Nlist images\n";
+
+for ($i = 0; $i < $Nlist; $i++) {
+    @words = split (" ",$list[$i]);
+    
+    if ($SKIPDOME) {
+	# a fairly lame and non-robust way to detect dome flats
+	if ($type eq "FLAT") {
+	    @answer = `echo $words[4]/$words[5] | fields OBJECT | grep -i dome`;
+	    if ($answer[0] ne "") { print STDERR "$words[5] rejected: dome flat\n"; next; }
+	}
+    }
+
+    if ($mode eq "split") {
+	# all $Nccd images must exist on disk, split files are assumed to be 
+	# in a subdirectory of their own, .fits extension assumed
+	@answer = <$words[4]/*.fits>;
+	if (@answer != $Nccd) { print STDERR "$words[5] rejected: missing images\n"; next; }
+    }
+
+    # images have to have the correct dimensions
+    if ($mode eq "split") {
+	@answer = `echo $words[4]/$words[5] | fields NAXIS1 NAXIS2`;
+	@wds = split (" ",$answer[0]);
+	$Nx = $wds[1]; $Ny = $wds[2];
+    } else {
+	@answer = `ftable -X 1 $words[4]/$words[5] | grep "^NAXIS1"`;
+	@wds = split (" ",$answer[0]);
+	$Nx = $wds[2];
+	@answer = `ftable -X 1 $words[4]/$words[5] | grep "^NAXIS2"`;
+	@wds = split (" ",$answer[0]);
+	$Ny = $wds[2];
+    }
+    if (($Nx != $Naxis1) || ($Ny != $Naxis2)) { print STDERR "$words[5] rejected: wrong dimensions\n"; next; }
+    
+    # $match is a word unique to the full mosaic image (the rootdir for split, the image for mef) 
+    if ($mode eq "split") { 
+	@answer = split ("/", $words[4]); 
+	$match = $answer[-1]; 
+    } else { 
+	$match = $words[5]; 
+    }
+    @list2 = `imsearch -name $match`;
+    $Nlist2 = @list2;
+    print STDERR "$match: $Nlist2\n";
+    if (@list2 != $Nccd) {
+	print STDERR "$words[5] rejected: missing entries in image database\n";
+	next;
+    }
+
+    if ($type eq "FLAT") {
+
+	if ($SKIPDOME) {
+	    # test for acceptable time (or is probably a dome flat)
+	    @answer = `dusktime $words[8]`;
+	    @wds = split (" ",$answer[0]);
+	    if ($wds[2] < 0) { print STDERR "$words[5] rejected: not twilight\n"; next; }
+	}
+	
+	$range = 1;
+	$rate  = 1;
+
+	# check for counts or flux out of range or any chip
+	for ($j = 0; $rate && $range && ($j < @list2); $j++) {
+	    @words2 = split (" ", $list2[$j]);
+	    
+	    # test for acceptable flux range
+	    if ($words2[11] < $min) { $range = 0; print STDERR "$words[5] rejected: signal too low: $words2[11] vs $min\n"; next; }
+	    if ($words2[11] > $max) { $range = 0; print STDERR "$words[5] rejected: signal too high: $words2[11] vs $max\n"; next; }
+	    
+	    # test for acceptable rate
+	    if (($words2[11] / $words2[7]) < $minrate) { 
+	      $rate = 0; 
+	      $F = $words2[11] / $words2[7];
+	      print STDERR "$words[5] rejected: flux too low: $F vs $minrate\n"; next; }
+	}
+	if (!$range) { next; }
+
+	@marginal = (@marginal, "$words[4]/$words[5]");
+	if (!$rate) { next; }
+    } else {
+	@marginal = (@marginal, "$words[4]/$words[5]");
+    }
+
+    @good = (@good, "$words[4]/$words[5]");
+}
+
+open (LIST, ">$ARGV[5]");
+if (@good > 5) {
+    for ($i = 0; $i < @good; $i++) {
+	print LIST "$good[$i]\n";
+	if (($type eq "BIAS") && ($i > 30)) { last; }
+	if (($type eq "DARK") && ($i > 30)) { last; }
+    }
+} else {
+    print STDERR "warning: limited number of flat images, scraping the bottom\n";
+    for ($i = 0; $i < @marginal; $i++) {
+	print LIST "$marginal[$i]\n";
+    }
+}
+close (LIST);
+print STDERR "SUCCESS\n";
+exit 0;
+
+# we need to select the list of images which satisfy a few criteria:
+# 1) all 12 CCDs must exist
+# 2) stats must be measured for each
+# 3) stats for all 12 must be within range (2000 - 40000)
+# 4) NAXIS1 == 2080 && NAXIS2 == 4128
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/merge.lists
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/merge.lists	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/merge.lists	(revision 16632)
@@ -0,0 +1,92 @@
+#!/usr/bin/env perl
+
+$update = 0;
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    # new images get mode of 0, old image keep their mode
+    if ($ARGV[0] eq "-update") {
+	shift;
+	$update = 1;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 3) { die "USAGE: merge.lists (list.split) (list.msplit) (list.master) [-update]\n" ;}
+
+# load names from SPLIT and MEF
+open (FILE, "$ARGV[0]");
+@split = <FILE>;
+close (FILE);
+
+open (FILE, "$ARGV[1]");
+@mef = <FILE>;
+close (FILE);
+
+# load old names from MASTER
+open (FILE, "$ARGV[2]");
+@master = <FILE>;
+close (FILE);
+
+# merge new entries into a single list, compare with state in master
+@names = (@split, @mef);
+
+@newname = ();
+@newmode = ();
+
+for ($i = 0; $i < @names; $i++) {
+
+    $name = $names[$i]; chop ($name);
+
+    $mode = 1;
+    if ($update) {
+	$mode = 0;
+
+      INNER:
+	foreach $line (@master) {
+	    @words = split (" ", $line);
+	    if ($words[0] eq $name) {
+		$mode = $words[1];
+		last INNER;
+	    }
+	}
+    }
+    @newname = (@newname, $name);
+    @newmode = (@newmode, $mode);
+}
+
+if (! @newname) {
+    print STDERR "ERROR: no relevant ccd images\n";
+    exit 1;
+}
+    
+# check on list: if there are none selected, select all
+$Ngood = 0;
+foreach $mode (@newmode) {
+    if ($mode) {
+	$Ngood ++;
+    }
+}
+if ($Ngood == 0) {
+    foreach $mode (@newmode) {
+	$mode = 1;
+    }
+}
+
+open (FILE, ">$ARGV[2]");
+for ($i = 0; $i < @newname; $i++) {
+    print FILE "$newname[$i] $newmode[$i]\n";
+}
+close (FILE);
+
+# this file must be accessible by www user  
+chmod 0666, $ARGV[2];
+
+print STDOUT "SUCCESS\n";
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/mkptolemy.names
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/mkptolemy.names	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/mkptolemy.names	(revision 16632)
@@ -0,0 +1,71 @@
+#!/usr/bin/env perl
+
+$Nccd = 12;
+
+if (@ARGV != 3) { die "USAGE: mkptolemy.names (name) (mode) (dir)\n" ;}
+
+$name = $ARGV[0];
+$mode = "\U$ARGV[1]\E";
+$dir = $ARGV[2];
+
+unless ($name =~ /^\d\d\d\d\d\d\w$/) {
+    print STDERR "name does not match the expected format 555555o\n";
+    exit 1;
+}
+
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+
+    if ($mode eq "MEF") {
+	printf "%s/%s.fits %s/%s%02d %02d MEF\n", $dir, $name, $name, $name, $ccd, $ccd;
+    }
+
+    if ($mode eq "SPLIT") {
+	printf "%s/%s/%s%02d.fits %s/%s%02d %02d MEF\n", $dir, $name, $name, $ccd, $name, $name, $ccd, $ccd;
+    }
+
+}
+
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub get_jd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5;
+    
+
+    return ($jd);
+
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/prepare.run
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/prepare.run	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/prepare.run	(revision 16632)
@@ -0,0 +1,349 @@
+#!/usr/bin/env perl
+
+# global vars:
+$atmach  = "druid.cfht.hawaii.edu";
+$runlist = "";
+@runlist = ();
+
+# check usage
+if (@ARGV < 1) {
+    print STDOUT "USAGE: mkrun (mode) [arguments]\n";
+    print STDOUT " mkrun help gives a complete list\n";
+    &goodbye;
+}
+if ($ARGV[0] eq "help") { &usage; }
+
+&set_globals;
+
+# call appropriate command
+if ($ARGV[0] eq "create") { &create (@ARGV); }
+if ($ARGV[0] eq "addqso") { &addqso (@ARGV); }
+if ($ARGV[0] eq "delqso") { &delqso (@ARGV); }
+if ($ARGV[0] eq "status") { &status; }
+if ($ARGV[0] eq "sched")  { &sched  (@ARGV); }
+
+print STDOUT "invalid mkrun command\n";
+exit 1;
+
+sub status {
+
+    &load_runlist;
+    foreach $line (@runlist) {
+	print STDOUT "$line\n";
+    }
+    exit 0;
+}
+
+############
+sub create {
+
+    my (@argv) = @_;
+    
+    if (@argv != 4) {
+	print STDOUT "USAGE: mkrun create (run) (start) (stop)\n";
+	exit 2;
+    }
+
+    $runid = $argv[1];
+    $start = $argv[2];
+    $stop  = $argv[3];
+
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    ($Orunid, $Ostart, $Ostop, $qrunid) = split (" ", $line);
+    $line = mk_runline ($runid, $start, $stop, $qrunid);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub addqso {
+
+    my (@argv) = @_;
+    
+    if (@argv != 3) {
+	print STDOUT "USAGE: mkrun addqso (run) (qsorun)\n";
+	exit 2;
+    }
+
+    $runid = $argv[1];
+    $qrunid  = $argv[2];
+
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    if ($line eq "") { 
+	print STDERR "run id $runid not in run list\n";
+	exit 1;
+    }
+    ($runid, $start, $stop, $Oqrunid) = split (" ", $line, 4);
+    if ($Oqrunid) {
+	$qrunid = $Oqrunid . " " . $qrunid;
+    } 
+
+    $line = mk_runline ($runid, $start, $stop, $qrunid);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub delqso {
+    my (@argv) = @_;
+    if (@argv != 2) {
+	print STDOUT "USAGE: mkrun addqso (qsorun)\n";
+	exit 2;
+    }
+
+    $qrunid  = $argv[1];
+
+    &load_runlist;
+    
+    # find listed qrunid
+    $match = "";
+  SEARCH:
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($tmp, $tmp, $tmp, $qlist) = split (" ", $line, 4);
+	@qlist = split (" ", $qlist);
+	foreach $qid (@qlist) {
+	    if ($qrunid ne $qid) { next; }
+	    $match = $line;
+	    last SEARCH;
+	}
+    }
+    if ($match eq "") {
+	print STDERR "QSO run id $qrunid not found in run list\n";
+	exit 1;
+    }
+
+    # recreate $qlist without $qrunid
+    $qlist = "";
+    foreach $qid (@qlist) {
+	if ($qid eq $qrunid) { next; }
+	$qlist = $qlist . $qid . " ";
+    }
+
+    ($runid, $start, $stop) = split (" ", $match);
+
+    $line = mk_runline ($runid, $start, $stop, $qlist);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+##############
+
+sub sched {
+    my (@argv) = @_;
+    if (@argv != 2) {
+	print STDOUT "USAGE: mkrun sched (runid)\n";
+	exit 2;
+    }
+
+    $runid  = $argv[1];
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    ($runid, $start, $stop, $qlist) = split (" ", $line, 4);
+
+    at_loop ($runid, $start, $stop);
+    
+    exit 0;
+}
+
+##############
+sub at_loop {
+    my ($runid, $start, $stop);
+    $runid = $_[0];
+    $start = $_[1];
+    $stop  = $_[2];
+    
+    $mjd_start = date_to_mjd ($start);
+    $mjd_stop  = date_to_mjd ($stop);
+
+    $Nday = $mjd_stop - $mjd_start;
+
+    ($year, $month, $day) = $start =~ /(\d+)\/(\d+)\/(\d+)/;
+    for ($Day = -1; $Day < $Nday; $Day++) {
+	
+	# 'at' needs date in format MM/DD/YYYY or DD.MM.YYYY
+	$tday = $day + $Day;
+	$date = `date -d $year/$month/$tday +%m/%d/%Y`; chop ($date);
+
+	if ($Day == -1) {
+	    atcommand ("clear.rawdir -current >& /h/eugene/cfh12k/logs/clear.log &", "10:00", $date);
+	}
+
+	if ($Day == 0) {
+	    atcommand ("echo RUNID $runid > /h/cfh12k/elixir.run", "10:00", $date);
+	    atcommand ("mkdetrend create $runid $start $stop >& /h/eugene/cfh12k/logs/mkdetrend.log", "10:05", $date);
+	    atcommand ("mkfringe config $runid >& /h/eugene/cfh12k/logs/mkdetrend.log", "10:10", $date);
+	    atcommand ("mkfringe mkconfig $runid >& /h/eugene/cfh12k/logs/mkdetrend.log", "10:15", $date);
+	    
+	    atcommand ("elixir -D mode imstats >& /h/eugene/cfh12k/logs/imstats.log &", "15:00", $date);
+	    atcommand ("elixir -D mode sextract >& /h/eugene/cfh12k/logs/ptolemy.log &", "15:00", $date);
+	    atcommand ("gettemps &", "15:00", $date);
+	    atcommand ("elixir.report &", "15:00", $date);
+	}
+
+	if (($Day > 0) && ($Day < 4)) {
+	    atcommand ("mkdetrend init >& /h/eugene/cfh12k/logs/mkdetrend.log; mkdetrend run >& /h/eugene/cfh12k/logs/mkdetrend.log", "07:00", $date);
+	}
+	if ($Day >= 4) {
+	    atcommand ("mkdetrend update >& /h/eugene/cfh12k/logs/mkdetrend.log", "07:00", $date);
+	}
+	if ($Day > 0) {
+	    # atcommand ("clear /h/cfh12k/images/elixir", "12:00", $date);
+	}
+    }
+}
+
+####### runlist utilities ############################
+sub load_runlist {
+    open (FILE, "$runlist");
+    @runlist = <FILE>;
+    foreach $line (@runlist) {
+	chop ($line);
+    }
+    close (FILE);
+}    
+
+sub save_runlist {
+    open (FILE, ">$runlist");
+    foreach $line (@runlist) {
+	print FILE "$line\n";
+    }
+    close (FILE);
+}    
+
+sub grab_runline {
+    my ($id) = $_[0];
+    my ($line);
+    my ($runid);
+
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid) = split (" ", $line);
+	if ($runid ne $id) { next; }
+	return ($line);
+    }
+    return ("");
+}
+    
+sub insert_runline {
+    my ($runline) = $_[0];
+    my ($line);
+    my ($runid, $id);
+
+    # match the run id lines
+    ($id) = split (" ", $runline);
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid) = split (" ", $line);
+	if ($runid ne $id) { next; }
+	$line = $runline;
+	return 1;
+    }
+    @runlist = (@runlist, $runline);
+    return 0;
+}
+
+sub mk_runline {
+    my ($runid, $start, $stop, $qrunid, $line);
+    $runid  = $_[0];
+    $start  = $_[1];
+    $stop   = $_[2];
+    $qrunid = $_[3];
+
+    $start = date_format ($start);
+    $stop  = date_format ($stop);
+    $line = sprintf "%s %s %s  %s", $runid, $start, $stop, $qrunid;
+    return ($line);
+}
+
+# utilities ##############################################
+
+sub atcommand {
+    my ($cmd, $time, $date);
+    $cmd = $_[0];
+    $time = $_[1];
+    $date = $_[2];
+
+    $line = sprintf "echo %s | at %s %s", $cmd, $time, $date;
+    print STDOUT "$line\n";
+}
+
+
+sub vsystem {
+    # print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub date_format {
+    my ($date) = $_[0];
+    my ($year, $month, $day);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $date = sprintf "%4d/%02d/%02d", $year, $month, $day;
+    return ($date);
+}
+
+sub date_to_mjd {
+    my ($date) = $_[0];
+    my ($year, $month, $day, $mjd);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $mjd = get_mjd ($year, $month, $day);
+
+    return ($mjd);
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
+sub set_globals {
+
+    # this should come fron the config system
+#    $runlist = "/data/milo/eugene/elixir/refs/cfh12k.runs";
+    $runlist = "/h/eugene/test.runs";
+}
+
+sub usage {
+    
+    if (@ARGV == 1) {
+	print STDERR "\n --- user modes ---\n";
+	print STDERR "create (run) (start) (stop)\n";
+	print STDERR "addqso (runid) (qsoid)\n";
+	print STDERR "delqso (qsoid)\n";
+	print STDERR "sched (runid)\n";
+	print STDERR "status\n";
+	&goodbye;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: prepare.run (help) [mode]\n"; &goodbye; }
+    
+    &goodbye;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/pt.run
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/pt.run	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/pt.run	(revision 16632)
@@ -0,0 +1,66 @@
+#!/usr/bin/env perl
+
+# USAGE: pt.run (obsid)
+
+if (@ARGV != 1) { die "USAGE: ckvalid (obsid)\n" ;}
+
+$obsid = $ARGV[0];
+$archive = "/h/archive/current/instrument/cfh12k";
+
+# find the run id for this image
+$runid = `ckrunid $archive/$obsid.fits`;
+if ($?) {
+    print STDOUT "$obsid: no run ID\n";
+    exit 1;
+}
+chop ($runid);
+
+# try to use the flt files, if they exist, for headers
+$tmpdir = "/data/elixir2/cfh12k/tmpdata/$runid/$obsid";
+
+print "$tmpdir\n";
+
+@flt = <$tmpdir/*.flt>;
+$Nflt = @flt;
+if ($Nflt != 12) {
+    print STDOUT "not enough *.flt files ($Nflt)\n";
+    @smp = <$tmpdir/*.smp>;
+    if (@smp == 12) {
+	print STDOUT "using old *.smp files\n";
+	@flt = ();
+	foreach $smp (@smp) {
+	    $flt = $smp;
+	    $flt =~ s/smp/flt/;
+	    vsystem ("cp $smp $flt");
+	    @flt = (@flt, "$flt");
+	}
+    } else {
+	exit 1;
+    }
+}
+
+foreach $flt (@flt) {
+    $smp = $flt;
+    $smp =~ s/flt/smp/;
+
+    $sx = $flt;
+    $sx =~ s/flt/sx/;
+
+    vsystem ("imclean -sex $flt $sx $smp");
+    vsystem ("gastro -v $smp");
+
+    # imclean -sex *.flt *.sx *.smp
+    # gastro -v *.smp
+}
+
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/scheduler
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/scheduler	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/scheduler	(revision 16632)
@@ -0,0 +1,248 @@
+#!/usr/bin/env perl
+
+$ENV{'PATH'} = "$ENV{'PATH'}:/apps/elixir/bin";
+
+$schedule = `gconfig SCHEDULE`; chop $schedule;
+$logdir   = `gconfig LOGDIR`;   chop $logdir;
+$log      = "$logdir/scheduler.log";
+$window   = 0.02; # ~0.5 hours. 
+$machine  = "milo.cfht.hawaii.edu";
+
+$LIST = 0;
+$ALL  = 0;
+$RUN = 0;
+
+# execute any event which is within the time range: 
+# $last + $window < event < NOW + $window
+
+# check usage
+if ($ARGV[0] eq "help")  { &usage; }
+if ($ARGV[0] eq "all")   { &list_all; }
+if ($ARGV[0] eq "list")  { &list_active; }
+if ($ARGV[0] eq "run")   { &run_active; }
+if ($ARGV[0] eq "clear") { &clear_all; }
+print STDERR "scheduler command '$ARGV[0]' not found\n";
+&usage;
+
+sub list_active {
+
+    &set_current_time;  # set $NOWdate, $NOWtime $NOWmjd
+    &load_schedule;     # load into @list
+    &find_previous;     # set $last (last runtime)
+    &find_active;       # fill @execute & @cmdlogs for active commands
+
+    for ($i = 0; $i < @execute; $i++) {
+	print "$execute[$i] ($cmdlogs[$i])\n";
+    }
+    exit 0;
+}
+
+sub run_active {
+
+    &set_current_time;
+    &load_schedule;
+    &find_previous;
+    &find_active;
+
+    # re-create schedule with new PREVIOUS:
+    if (@list && (-e "$schedule")) { 
+	system ("cp $schedule $schedule~"); 
+	open (FILE, ">$schedule");
+	foreach $line (@list) {
+	    if ($line =~ /^\s*PREVIOUS/) { 
+		printf FILE "PREVIOUS %s %s\n", $NOWdate, $NOWtime;
+		next;
+	    }
+	    
+	    print FILE "$line";
+	}    
+	close (FILE);
+    } else {
+	# create a new schedule with PREVIOUS set to NEVER
+	print STDERR "creating $schedule\n";
+	open (FILE, ">$schedule");
+	print FILE "# schedule for scheduler system\n";
+	print FILE "# E. Magnier\n";
+	print FILE "\n";
+	print FILE "# last time scheduler was run:\n";
+	printf FILE "PREVIOUS %s %s\n", $NOWdate, $NOWtime;
+	print FILE "\n";
+	close (FILE);
+    }
+
+    # launch commands one-by-one in background
+    for ($i = 0; $i < @execute; $i++) {
+	docommand ($cmdlogs[$i], $execute[$i]);
+	system ("sleep 60");
+    }
+    exit 0;
+}
+
+# utilities ##############################################
+
+sub docommand {
+    my ($log, $cmd);
+    $log  = $_[0];
+    $cmd  = $_[1];
+
+    $line = sprintf "scheduler.exec $log \"$cmd\" ";
+    vsystem ($line);
+}
+
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub load_schedule {
+    open (FILE, "$schedule");
+    @list = <FILE>;
+    close (FILE);
+}
+
+sub clear_all {
+    if (-e $schedule) {
+	vsystem ("cp $schedule $schedule~");
+	vsystem ("rm $schedule");
+    }
+    exit 0;
+}
+
+sub find_previous {
+    $last = 0;
+    $date = "NEVER";
+    # find previous runtime:
+    foreach $line (@list) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	unless ($line =~ /^\s*PREVIOUS/) { next; }
+	
+	($tmp, $date, $time) = split (" ", $line);
+	if ($date eq "NEVER") {
+	    $last = 0;
+	    last; 
+	}
+	$last = timedate_to_mjd ($time, $date);
+	last;
+    }
+    print STDERR "run scheduler: $NOWdate $NOWtime (prev: $date $time)\n";
+}
+
+sub find_active {
+
+    @execute = ();
+    @cmdlogs = ();
+    # find relevant commands
+    foreach $line (@list) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	if ($line =~ /^\s*PREVIOUS/) { next; }
+	
+	($date, $time, $cmdlog, $command) = split (" ", $line, 4);
+	if ($command eq "") { next; }
+	chop ($command);
+	
+	$mjd = timedate_to_mjd ($time, $date);
+	
+	if ($last + $window > $mjd) { next; }
+	if ($NOWmjd + $window < $mjd) { next; }
+	
+	@cmdlogs = (@cmdlogs, $cmdlog);
+	@execute = (@execute, $command);
+    }
+    
+}
+
+sub set_current_time {
+
+    ($sec, $min, $hour, $day, $mon, $year) = localtime ();
+    $mon += 1;
+    $year += 1900;
+    $NOWdate = sprintf "%s/%02d/%02d", $year, $mon, $day;
+    $NOWtime = sprintf "%02d:%02d:%02d", $hour, $min, $sec;
+    $NOWmjd = timedate_to_mjd ($NOWtime, $NOWdate);
+}
+
+sub date_format {
+    my ($date) = $_[0];
+    my ($year, $month, $day);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $date = sprintf "%4d/%02d/%02d", $year, $month, $day;
+    return ($date);
+}
+
+sub timedate_to_mjd {
+    my ($time) = $_[0];
+    my ($date) = $_[1];
+    my ($mjd, $day);
+
+    $mjd  = date_to_mjd ($date);
+    $day += time_to_day ($time);
+
+    $mjd += $day;
+    return ($mjd);
+}
+    
+
+sub date_to_mjd {
+    my ($date) = $_[0];
+    my ($year, $month, $day, $mjd);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $mjd = get_mjd ($year, $month, $day);
+
+    return ($mjd);
+}
+
+sub time_to_day {
+    my ($time) = $_[0];
+    my ($hour, $min, $sec, $days);
+
+    ($hour, $min, $sec) = split (":", $time);
+    $day = $hour / 24.0 + $min / 1440.0 + $sec / 86400.0;
+
+    return ($day);
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
+sub list_all {
+
+    # load schedule:
+    open (FILE, "$schedule");
+    @list = <FILE>;
+    close (FILE);
+    
+    foreach $line (@list) {
+	print "$line";
+    }
+    exit 0;
+}
+
+sub usage {
+    
+    print STDERR "USAGE: scheduler [mode]\n";
+    print STDERR " list  : list all active commands\n";
+    print STDERR " all   : list all commands\n";
+    print STDERR " run   : execute active commands\n";
+    print STDERR " clear : delete schedule\n";
+    &goodbye;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/scheduler.exec
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/scheduler.exec	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/scheduler.exec	(revision 16632)
@@ -0,0 +1,21 @@
+#!/bin/csh -f
+
+set logdir = `gconfig LOGDIR`
+set log = "$logdir/scheduler.log"
+
+if ($#argv < 2) then
+ echo "USAGE: scheduler.exec (logfile) (cmd)"
+ exit 2;
+endif
+
+set cmdlog = $1
+shift
+
+set start=`date`
+echo "start: $start - $*" >> $log
+
+csh -c "$*" >>& $cmdlog
+set stat=$status
+
+set stop=`date`
+echo "stop:  $stop $stat $*" >> $log
Index: /branches/eam_branch_20080223/Ohana/src/perl/old/validate-1.0
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/old/validate-1.0	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/old/validate-1.0	(revision 16632)
@@ -0,0 +1,287 @@
+#!/usr/bin/env perl
+
+# validate 
+# -update sends the validation value to the QSO database
+#  1 - valid image
+#  2 - subvalid image (problem, but doesn't matter)
+#  3 - invalid image
+#  4 - data error (missing, corrupted image)
+
+# global constants:
+
+$TRUE  = 1;
+$FALSE = 0;
+$RETRY = $TRUE;
+
+$MODE_UNSET    = 0;
+$MODE_VALID    = 1;
+$MODE_SUBVALID = 2;
+$MODE_INVALID  = 3;
+$MODE_DATAERR  = 4;
+
+$infile = "";
+$update = $FALSE;
+# put this in the CONFIG file:
+$runlist = "/data/milo/eugene/elixir/refs/cfh12k.runs";
+
+# include the CFHT bin directory in the path so we have access to QSO functions:
+$ENV{'PATH'} = "$ENV{'PATH'}:/cfht/bin";
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    if ($ARGV[0] eq "-update") {
+	shift;
+	$update = $TRUE;
+	next;
+    }
+    if ($ARGV[0] eq "-skip") {
+	shift;
+	$RETRY = $FALSE;
+	next;
+    }
+    if ($ARGV[0] eq "-infile") {
+	shift;
+	$infile = $ARGV[0];
+	shift;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 1) { die "USAGE: validate (crunid) [-infile filename] [-update]\n" ;}
+
+$crunid = $ARGV[0];
+
+# find qso run id for this camera run id:
+open (FILE, "$runlist");
+@list = <FILE>;
+close (FILE);
+
+# find date range in run list
+foreach $line (@list) {
+    chop ($line);
+    if ($line =~ /^\#/) { next; }
+    ($Crunid, $start, $stop, $Qrunid) = split (" ", $line, 4);
+    if (($start eq "") || ($stop eq "")) { next; }
+    if ($Crunid eq $crunid) { $qrunid = $Qrunid; last; }
+}
+
+print STDERR "qso run ID(s): $qrunid\n";
+
+@valid    = ();
+@invalid  = ();
+@dataerr  = ();
+@subvalid = ();
+
+if ($infile) {
+    # load images from previous output run or source file:
+    open (FILE, $infile);
+    @rawlist = <FILE>;
+    close (FILE);
+    
+    $mode = $MODE_UNSET;
+    @imlist = ();
+    
+  RAWLIST:
+    foreach $name (@rawlist) {
+	chop ($name);
+	
+	if ($name eq "") { next RAWLIST; }
+	    
+	if ($name =~ /^valid images/) {
+	    $mode = $MODE_VALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^invalid images/) {
+	    $mode = $MODE_INVALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^subvalid images/) {
+	    $mode = $MODE_SUBVALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^dataerr images/) {
+	    $mode = $MODE_DATAERR;
+	    next RAWLIST;
+	}
+
+	# plain list of image names (/path/name.fits)
+	if ($mode == $MODE_UNSET) {
+	    # double check on name validity
+	    ($file, $junk) = split (" ", $name, 2);
+	    unless ($file =~ /\d\d\d\d\d\d\w/) { print STDERR "?"; next RAWLIST; }
+	    @imlist = (@imlist, $file);
+	    next RAWLIST;
+	    # if (! -e $file) { print STDERR "x"; next RAWLIST; }
+	}
+	# place image names in the appropriate list
+	if ($mode == $MODE_VALID) {
+	    ($file, $result) = split (":", $name, 2);
+	    @valid = (@valid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_INVALID) {
+	    ($file, $result) = split (":", $name, 2);
+	    @invalid = (@invalid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_SUBVALID) {
+	    ($file, $result) = split (":", $name, 2);
+	    @subvalid = (@subvalid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_DATAERR) {
+	    ($file, $result) = split (":", $name, 2);
+	    @dataerr = (@dataerr, $file);
+	    next RAWLIST;
+	}
+    }
+} else {
+    # load images directly from directory 
+    # this is not sufficient.  we need a better way to get a list of images for 
+    # a given run id (with the current MEF / SPLIT state correct).
+    # 
+    # probably we can just use imsearch -ccd 0
+    $rawdir = `gconfig -q -D RUNID $crunid RAWDIR`;
+    chop ($rawdir);
+    if ($rawdir eq "") {
+	print STDERR "can't find config entry TMPDIR\n";
+	exit 1;
+    }
+    @imlist = ();
+
+    # load in the MEF files (must be of format 123456x.fits)
+    @tlist = <$rawdir/*.fits>;
+    foreach $tname (@tlist) { 
+	if ((-f $tname) && ($tname =~ /\d\d\d\d\d\d\w.fits/)) { 
+	    @imlist = (@imlist, $tname); 
+	} 
+    }
+
+    # load in the SPLIT directories (must be of format 123456x)
+    @tlist = <$rawdir/???????>;
+    foreach $tname (@tlist) { 
+	if ((-d $tname) && ($tname =~ /\d\d\d\d\d\d\w/)) { 
+	    @imlist = (@imlist, $tname); 
+	} 
+    }
+}
+
+# load the QSO validated image list
+@qsovalid = ();
+if ($qrunid) { 
+    @qruns = split (" ", $qrunid);
+    @qsovalid = ();
+    foreach $id (@qruns) {
+	print STDERR "trying $id\n";
+	@answer = `select_val_xexp.sh -U qso_elixir -P op1eliw -qrunid $id`;
+	if ($?) {
+	    print STDERR "error in qso run ID\n";
+	    exit 1;
+	}
+	@qsovalid = (@qsovalid, @answer);
+    }
+}
+foreach $qname (@qsovalid) { chop ($qname); }
+
+if ($RETRY) {
+# evaluate the remaining entries in imlist & invalid:
+    @imlist = (@imlist, @invalid, @dataerr);
+    @invalid = ();
+    @dataerr = ();
+    
+  IMLIST:
+    foreach $name (@imlist) {
+	$answer = `ckvalid $name`;
+	if ($?) { print STDERR "error with $name\n"; }
+	chop ($answer);
+	
+	($file, $result) = split (" ", $answer, 2);
+	@words = split (" ", $answer);
+	
+	if ($words[1] eq "pass") {
+	    @valid = (@valid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "binned image") {
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "sub-rastered image") {
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "wrong image type") {
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "can't open file") {
+	    @dataerr = (@dataerr, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "no run ID") {
+	    @dataerr = (@dataerr, $answer);
+	    next IMLIST;
+	}
+	
+	if ($result eq "not a valid image") {
+	    @dataerr = (@dataerr, $answer);
+	    next IMLIST;
+	}
+	
+	if ($words[1] eq "fail") {
+	    foreach $line (@qsovalid) {
+		($qname, $qmode, $emode) = split (" ", $line);
+		if ($name =~ /$qname/) {
+		    @invalid = (@invalid, $answer);
+		    next IMLIST;
+		}
+	    }
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	
+	print STDERR "unknown result $answer\n";
+	
+    }
+}
+
+@mode = ('valid',     'subvalid',      'invalid',     'dataerr');
+@code = ($MODE_VALID, $MODE_SUBVALID,  $MODE_INVALID, $MODE_DATAERR);
+
+for ($i = 0; $i < @mode; $i++) {
+    $mode = $mode[$i];
+    $code = $code[$i];
+
+    print STDOUT "$mode images\n";
+    foreach $file (@$mode) {
+	print STDOUT "$file\n";
+	if ($update) { 
+	    @w = split ("/", $file);
+	    $n = substr ($w[-1], 0, 6);
+	    vsystem ("update_xexpe.sh -U qso_elixir -P op1eliw --obsid $n --eval $code >> test.list");
+	}
+    }
+    print STDOUT "\n";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/cadc2qso
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/cadc2qso	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/cadc2qso	(revision 16632)
@@ -0,0 +1,46 @@
+#!/usr/local/bin/perl
+# extract mosaic IQ values from table, send to QSO db
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 1) { die "USAGE: cadc2qso (table.fits)\n"; }
+
+# update the following entries to the QSO database (one per mosaic):
+
+# --iq_center (OBS_IQ_CENTER)
+# --iq_r_ratio (OBS_IQ_R_RATIO)
+# --iq_x_ratio (OBS_IQ_X_RATIO)
+# --iq_y_ratio (OBS_IQ_Y_RATIO)
+
+# add error checking on the ftable call...
+@obsid = `ftable -column OBSID $ARGV[0]`;
+@iqcen = `ftable -column OBS_IQ_CENTER $ARGV[0]`;
+@iqr   = `ftable -column OBS_IQ_R_RATIO $ARGV[0]`;
+@iqx   = `ftable -column OBS_IQ_X_RATIO $ARGV[0]`;
+@iqy   = `ftable -column OBS_IQ_Y_RATIO $ARGV[0]`;
+
+foreach $value (@obsid) { chop $value; }
+foreach $value (@iqcen) { chop $value; }
+foreach $value (@iqr)   { chop $value; }
+foreach $value (@iqx)   { chop $value; }
+foreach $value (@iqy)   { chop $value; }
+
+$Nrow = @obsid;
+if ($Nrow != @iqcen) { &goodbye ("error in OBS_IQ_CENTER"); }
+if ($Nrow != @iqr) { &goodbye ("error in OBS_IQ_R_RATIO"); }
+if ($Nrow != @iqx) { &goodbye ("error in OBS_IQ_X_RATIO"); }
+if ($Nrow != @iqy) { &goodbye ("error in OBS_IQ_Y_RATIO"); }
+
+for ($i = 0; $i < $Nrow; $i++) {
+    vsystem ("/cfht/bin/update_xexpe.sh -U qso_elixir -P op1eliw --obsid $obsid[$i] --iq_center $iqcen[$i] --iq_r_ratio $iqr[$i] --iq_x_ratio $iqx[$i] --iq_y_ratio $iqy[$i]");
+}
+print STDOUT "SUCCESS: done with $ARGV[0]\n";
+exit (0);
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/cfht.names
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/cfht.names	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/cfht.names	(revision 16632)
@@ -0,0 +1,49 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 1) {
+    print STDERR "USAGE: cfht.names (file)\n";
+    exit 2;
+}
+
+# given (filename) : return (path) (name) (mef)
+
+if (! -e $ARGV[0]) {
+    print STDERR "file $ARGV[0] not found\n";
+    exit 1;
+}
+
+$fullname = $ARGV[0];
+
+# if we get a relative path, add cwd:
+@words = split ("/", $ARGV[0]);
+if ($words[0] ne "") {
+    $cwd=`pwd`;
+    chop ($cwd);
+    $fullname = "$cwd/$ARGV[0]";
+}
+# we are now guaranteed to have a /complete/path/filename
+
+# if file is a directory, we assume it is split:
+if (-d $fullname) {
+    $mef = "off";
+} else {
+    $mef = "on";
+}
+
+# split path and filename:
+$path = "/";
+@words = split ("/", $fullname);
+$N = @words;
+for ($i = 1; $i < $N - 1; $i++) {
+    $path = $path . $words[$i] . "/";
+}
+chop ($path);   # strip off last /
+
+$file = $words[$N-1];
+
+if ($mef eq "on") {
+    $file =~ s/.fits$//;
+}
+
+print STDOUT "$path $file $mef\n";
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/checkconfig
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/checkconfig	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/checkconfig	(revision 16632)
@@ -0,0 +1,464 @@
+#!/usr/bin/env perl
+
+@ARGV = &elixir_config (@ARGV);
+if (@ARGV == 0) { &usage; }
+
+&pnotice;
+&pnotice ("current run ID: $run");
+&pnotice ("current camera: $camera");
+&pnotice;
+
+{ # check for valid camera
+    if ($camera eq "cfh12k")  { last; }
+    if ($camera eq "cfhtir")  { last; }
+    if ($camera eq "megacam") { last; }
+    if ($camera eq "meganorth") { last; }
+    &escape ("camera $camera not supported, skipping");
+}
+
+if ($ARGV[0] eq "init")   { 
+    &ck_dirs; 
+    &ck_flocks; 
+    &ck_fifos; 
+    
+    if ($camera eq "cfh12k") { &ck_detrend; }
+    if ($camera eq "megacam") { &ck_detrend; }
+    if ($camera eq "meganorth") { &ck_detrend; }
+    &goodbye; 
+}
+# if ($ARGV[0] eq "unlock") { &ck_dirs; &ck_flocks; &cl_locks; &goodbye; }
+
+&escape ("checkconfig command $ARGV[0] not valid");
+
+### main user functions
+
+# check state of directories
+sub ck_detrend {
+
+    $answer = `mkdetrend state -camera $camera -run $run`;
+    if ($VERBOSE) { 
+	&pnotice ("checking mkdetrend system");
+	push @notices, $answer; 
+    }
+    if ($?) {
+	&pnotice ("define mkdetrend $camera $run");
+	$answer = `mkdetrend create run $run`;
+	if ($?) {
+	    &pwarning ("can't define mkdetrend $camera $run");
+	    push @warnings, $answer;
+	}
+    }
+
+    $answer = `mkfringe state -camera $camera -run $run`;
+    if ($VERBOSE) { 
+	&pnotice ("checking mkfringe system");
+	push @notices, $answer; 
+    }
+    if ($?) {
+	&pnotice ("define mkfringe $camera $run");
+	$answer = `mkfringe create run $run`;
+	if ($?) {
+	    &pwarning ("can't define mkfringe $camera $run");
+	    push @warnings, $answer;
+	}
+    }
+}
+
+sub ck_dirs {
+    my ($i, @dirs, @need);
+
+    @dirs = ('RAWDIR', 'TMPDIR', 'HDXDIR', 'CATDIR', 'DATDIR', 'FIFOS');
+    @need = ( 20,       5,        1,        0.2,      2,        0);
+
+    if ($VERBOSE) { 
+	foreach $dir (@dirs) {
+	    $filename = `gconfig $dir`; chop ($filename);
+	    &pnotice ("check $dir : $filename");
+	}
+	&pnotice;
+    }
+
+    for ($i = 0; $i < @dirs; $i++) {
+	checkdir ($dirs[$i], 0777, $need[$i]);
+    }
+    if ($VERBOSE) { &pnotice; }
+    return 0;
+}
+
+# check state of files with locks
+sub ck_flocks { 
+
+    @files = ('REGISTRATION_DATABASE');
+    foreach $file (@files) {
+	&checklocks ($file, 0666);
+    }
+    if ($VERBOSE) { &pnotice; }
+}
+
+# check elixir fifo files
+sub ck_fifos {
+    @elixirs = ('imstats', 'ptolemy');
+    @fifos = ('global.source', 'global.msg', 'global.end');
+
+    foreach $elixir (@elixirs) {
+	if ($VERBOSE) { &pnotice ("check fifos for elixir $elixir"); }
+	foreach $fifo (@fifos) {
+	    $filename = `gconfig -D mode $elixir $fifo`; chop ($filename);
+	    setmode ($filename, 0666);
+	}
+    }
+    if ($VERBOSE) { &pnotice; }
+}
+
+sub cl_locks { 
+
+    @files = ('REGISTRATION_DATABASE');
+    foreach $file (@files) {
+
+	$filename = `gconfig $file`;  chop ($filename);
+	$lock = lockname ($filename);
+
+	if (!cklock ($lock) && $unlock) { setlock ($lock); }
+    }
+}
+
+sub ckelixir {
+    my($elixir) = $_[0];
+    
+    if ($VERBOSE) { &pnotice ("Checking on Elixir $elixir"); }
+    
+    $answer = `elixir -status -D mode $elixir`;
+    if ($?) { }
+    if ($VERBOSE) { push @notices, $answer; }
+
+    return (1);
+}
+
+# check that directory exists, create it if not, set permissions
+sub checkdir {
+    # in: dir-key, mode, bytes
+    # out: status
+
+    my ($dir) = $_[0];
+    my ($mode) = $_[1];
+    my ($bytes) = $_[2];
+    my ($status);
+
+    # set camera, runid from .current
+    $filename = `gconfig $dir`; chop ($filename);
+
+    # this will make a dir if the parent doesn't exist.
+    if (! -e $filename) {
+	$status = mkdirhier ($filename, $mode);
+	if (!$status) {
+	    &pwarning ("can't create directory $filename ($dir)");
+	    return 0;
+	}
+    }
+
+    # set mode to desired value
+    if (!ckmode ($filename, $mode)) { 
+	if (!chmod $mode, $filename) {
+	    &pwarning ("can't set permissions on $filename ($dir)");
+	    return 0;
+	}
+    }	    
+
+    # check available space
+    if ($bytes) {
+	$left = `sdf $filename`;
+	$left = sprintf "%5.1f", ($left / 1024 / 1024);
+	if ($VERBOSE) { &pnotice ("$dir : $left GB free : $filename"); }
+	if ($left < $bytes) {
+	    &pwarning ("$filename ($dir) is getting full");
+	    return 0;
+	}
+    }
+    return 1;
+}
+
+# check existence & permissions on file & corresponding lockfile
+sub checklocks { 
+
+    my ($file) = $_[0];
+    my ($mode) = $_[1];
+    
+    $filename = `gconfig $file`;  chop ($filename);
+    $lock = lockname ($filename);
+
+    if ($VERBOSE) { &pnotice ("check $file ($filename)"); }
+
+    # create file if it does not exist
+    setmode ($filename, $mode);
+
+    # create file if it does not exist
+    setmode ($lock, $mode);
+
+    return 1;
+}
+
+# basic utilities
+
+sub lockname {
+    # in: path/file
+    # out: path/.file.lck
+
+    my($lock, $N, $i);
+
+    @words = split ("/", $_[0]);
+    
+    $lock = "";
+    $N = @words - 1;
+    for ($i = 0; $i < $N; $i++) {
+	$lock = $lock . $words[$i] . "/";
+    }
+    $lock = $lock . "." . "$words[$N]" . ".lck";
+
+    return ($lock);
+}
+
+sub ckmode {
+    # in: file mode
+    # out: yes/no
+
+    $filename = $_[0];
+    $mode = $_[1];
+    $setmode = $mode;
+
+    unless (@fstat = stat ($filename)) {
+	if ($VERBOSE) { &pwarning ("$filename not found"); }
+	return 0;
+    }
+
+    $fmode = 07777 & $fstat[2];
+    $status = !($setmode ^ $fmode);
+
+    if (!$status && $VERBOSE) {
+	$line = sprintf "$filename has wrong mode: %o vs %o\n", $fmode, $setmode;
+	&pnotice ($line);
+    }
+
+    return ($status);
+}
+
+sub cklock {
+    # in: file
+    # out: yes/no
+
+    $filename = $_[0];
+
+    if (! -e $filename) { return (1); }
+
+    open (FILE, $filename);
+    $word = <FILE>;
+    close (FILE);
+
+    unless ($word =~ /^IDLE/) {
+	&pwarning ("$filename is locked");
+	return 0;
+    }
+
+    return 1;
+}
+
+# create file & set mode 
+sub setmode {
+    # in: file mode
+    # out: yes/no
+
+    $filename = $_[0];
+    $mode = $_[1];
+
+    if (! -e $filename) {
+	if (!open (FILE, ">$filename")) {
+	    &pwarning ("can't create file $filename");
+	    return 0;
+	}
+	close (FILE);
+    }
+    
+    if (!ckmode ($filename, $mode)) {
+	if (!chmod $mode, $filename) {
+	    &pwarning ("can't set mode on $filename");
+	    return 0;
+	}
+    }
+
+    return 1;
+}
+
+sub setlock {
+    # in: file
+    # out: yes/no
+
+    $filename = $_[0];
+
+    unless (open (FILE, ">$filename")) {
+	&pwarning ("can't set lock $filename");
+	return 0;
+    }
+    print FILE "IDLE";
+    close (FILE);
+    return 1;
+}
+
+sub mkdirhier {
+    # in: directory mode
+    # out: status
+
+    my ($dir) = $_[0];
+    my ($mode) = $_[1];
+    my (@words, $first, $last, $i, $part);
+
+    @words = split ("/", $dir);
+
+    foreach $level (@words) {
+	if ($level eq "") { $part = "/"; next; }
+	$part = $part . $level; 
+
+	if (-e $part && !-d $part) { return 0; }
+	if (! -e $part && !mkdir ($part, $mode)) { return 0; }
+	chmod $mode, $part;
+
+	$part = $part . "/";
+    }
+    return 1;
+}
+
+sub usage {
+    print STDERR "USAGE: checkconfig [command]\n";
+    print STDERR "  check elixir configuration & files\n";
+    exit 2;
+}
+
+sub escape { 
+    &dump_output;
+    if ($_[0]) { print "$_[0]\n"; }
+    unlink $tmpenv;
+    exit 1;
+}
+
+sub goodbye { 
+    &dump_output;
+    if ($_[0]) { print "$_[0]\n"; }
+    unlink $tmpenv;
+    exit 0;
+}
+
+sub pwarning {
+    push @warnings, $_[0];
+}
+
+sub pnotice {
+    push @notices, $_[0];
+}
+
+sub dump_output {
+    # output to screen
+    if (@warnings) {
+	print STDERR "\n--- problem with elixir system checkconfig --\n\n";
+	foreach $line (@warnings) { print STDERR "$line\n"; }
+	print STDERR "\n--- checkconfig output ---\n";
+    }
+    foreach $line (@notices) { print STDERR "$line\n"; }
+
+    if ($notify && @warnings) {
+	$answer = `mkrun sys notify`;
+	@list = split (",", $answer);
+	open (MAIL, "|mail -s 'elixir checkconfig error' @list");
+	print MAIL "problem with elixir system checkconfig:\n";
+	foreach $line (@warnings) { print MAIL "$line\n"; }
+	print MAIL "\n--- checkconfig output ---\n";
+	foreach $line (@notices) { print MAIL "$line\n"; }
+	close (MAIL);
+    }
+}
+
+# grab complete configuration info from the elixir config system, 
+# applying appropriate command-line arguments
+sub elixir_config {
+    my (@argv) = @_;
+    my ($opt, $config, @tmparg, $status);
+    $config = "";
+    if ($ENV{'PTOLEMY'}) { $config = "-c $ENV{'PTOLEMY'}"; }
+    umask (0);
+    $notify = 0;
+    $VERBOSE = 0;
+
+    # look for optional command-line arguments
+    @tmparg = @argv;
+    foreach (@tmparg) {
+	$value = shift @argv;
+
+	if ($value eq "-h")     { &usage; }
+	if ($value eq "--help") { &usage; }
+
+	if ($value eq "-c") {
+	    $value = shift @argv;
+	    $config = "-c $value";
+	    next;
+	}
+
+	if ($value eq "-C") {
+	    push @opt, $value;
+	    $value = shift @argv;
+	    push @opt, $value;
+	    $elconf = $value;
+	    next;
+	}
+	
+	if ($value eq "-C") {
+	    push @opt, $value;
+	    $value = shift @argv;
+	    push @opt, $value;
+	    $value = shift @argv;
+	    push @opt, $value;
+	    next;
+	}
+	
+	if ($value eq "-run") {
+	    $run = shift @argv;
+	    push @opt, "-D RUNID.CURRENT $run -D RUNID $run";
+	    next;
+	}
+	if ($value eq "-camera") {
+	    $camera = shift @argv;
+	    push @opt, "-D CAMERA.CURRENT $camera -D CAMERA $camera";
+	    next;
+	}
+	if ($value eq "-notify") {
+	    $notify = 1;
+	    next;
+	}
+	if ($value eq "-v") {
+	    $VERBOSE = 1;
+	    next;
+	}
+	push @argv, $value;
+    }
+
+    # load RUNID from state.data (unless set on command line)
+    if ($run eq "") {
+	$run = `gconfig RUNID.CURRENT`; chop $run;
+	if ($?) {  &escape ("run is not defined: use 'mkrun sys'\n"); }
+	if ($run eq "") {  &escape ("run is not defined: use 'mkrun sys'\n"); }
+	push @opt, "-D RUNID.CURRENT $run -D RUNID $run";
+    }
+
+    # load CAMERA from state.data (unless set on command line)
+    if ($camera eq "") {
+	$camera = `gconfig CAMERA.CURRENT`; chop $camera;
+	if ($?) {  &escape ("camera is not defined: use 'mkrun sys' to set\n"); }
+	if ($camera eq "") {  &escape ("camera is not defined: use 'mkrun sys'\n"); }
+	push @opt, "-D CAMERA.CURRENT $camera -D CAMERA $camera";
+    }
+
+    # set env PTOLEMY using values from command line
+    $config = join (" ", $config, @opt);
+    $tmpenv = `mktemp /tmp/elixir.XXXXXX`; chop ($tmpenv);
+    $status = system ("gconfig -raw $config > $tmpenv");
+    if ($status) { &escape ("error in elixir configuration: gconfig fails"); }
+    $ENV{'PTOLEMY'} = "$tmpenv";
+
+    return (@argv);
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/ckastrom
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/ckastrom	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/ckastrom	(revision 16632)
@@ -0,0 +1,58 @@
+#!/usr/bin/env perl
+
+# we need a mechanism to define the appropriate ext value 
+
+if (@ARGV != 3) { die "USAGE: ckastrom (run) (root) (Nccd)\n" ;}
+
+$runid = $ARGV[0];
+$root = $ARGV[1];
+$Nccd = $ARGV[2];
+
+$tmpdir = `gconfig -q -D RUNID $runid HDXDIR`; chop ($tmpdir);
+if ($?) {
+    print STDERR "can't find config entry HDXDIR\n";
+    exit 1;
+}
+chop ($runid);
+
+$Nbad = 0;
+$Nmiss = 0;
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+
+    $found = 0;
+
+    $name = sprintf "%s/%s/%s%02d.hdx", $tmpdir, $root, $root, $ccd;
+    if (-e $name) {
+	$found = 1;
+	$answer = `echo $name | fields NASTRO`;
+	@words = split (" ", $answer);
+	if ($words[1] > 0) { next; }
+    }
+
+    if (! $found) { $Nmiss ++; }
+    $Nbad ++;
+}
+
+if (!$Nbad) {
+    print STDOUT "pass\n";
+    exit 0;
+} 
+if ($Nbad < 0.4*$Nccd) {
+    print STDOUT "pass $Nbad bad\n";
+    exit 0;
+}
+print STDOUT "$Nbad bad\n";
+exit 1;
+
+# utilities ############################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/ckdetrend
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/ckdetrend	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/ckdetrend	(revision 16632)
@@ -0,0 +1,55 @@
+#!/usr/bin/env perl
+
+# the specific CCD is specified on the command line
+
+if ((@ARGV != 3) && (@ARGV != 4)) { die "USAGE: ckdetrend (name) (ccd) (mode) [-fringe]\n" ;}
+
+$fringe = 0;
+if (@ARGV == 4) { $fringe = 1; }
+
+$name = $ARGV[0];
+$ccd  = $ARGV[1];
+$mode = "\U$ARGV[2]\E";
+
+if (($mode ne "SPLIT") && ($mode ne "MEF")) {
+    print STDERR "mode must be SPLIT or MEF\n";
+    exit (2);
+}
+
+if ($fringe) {
+    @type = ("fringe");
+} else {
+    @type = ("mask", "bias", "dark", "flat");
+}
+
+@missing = ();
+
+foreach $type (@type) {
+    if (vsystem ("detsearch -image $name $ccd $mode -type $type")) {
+	print STDERR "can't find $type\n";
+	@missing = (@missing, $type);
+    }
+}
+
+if (@missing) {
+    print STDOUT "$name fails, missing: @missing\n";
+    exit 1;
+} else {
+    print STDOUT "$name: pass\n";
+    exit 0;
+}
+
+# utilities ############################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+### this is no needed anymore - superceeded by detsearch -mosaic filename.fits -recipe
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/ckimregdb
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/ckimregdb	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/ckimregdb	(revision 16632)
@@ -0,0 +1,116 @@
+#!/usr/bin/env perl
+
+# this script deals with:
+# - archived images which have not been reported to elixir,
+# - images which need to be reprocessed,
+# - images which can be send to CADC
+
+if (@ARGV != 2) { die "USAGE: ckimregdb (start) (range)\n" ;}
+
+# imsearch and ardrange12k have different default hr:mn:sc values
+# this script converts to the ardrange12k defaults: 12:00:00
+
+# WARNING: define a ref CCD for seeing
+
+# test for current camera?
+
+system ("gconfig CAMERA");
+exit; 
+
+$start = $ARGV[0];
+$range = $ARGV[1];
+
+# force explicit starting hours:
+@words = split (/\D/, $start);
+if (@words == 3) { $start = "$start,12:00:00"; }
+@words = split (/\D/, $range);
+if (@words == 3) { $range = "$range,12:00:00"; }
+
+# get list of images in the archive & imreg.db:
+if ($range =~ m|^-\d+[dhms]|) {
+    $answer = `/h/archive/sw/tools/ardrange12k $start$range`;
+} else {
+    $answer = `/h/archive/sw/tools/ardrange12k $start+$range`;
+}
+
+@ccds = split (" ", `cameraconfig -ccds`);
+if ($?) { &escape ("error with elixir camera configuration"); }
+
+@archive = split (" ", $answer);
+$N = @archive;
+print "archive: $N files\n";
+
+@imregdb = `imsearch -ccd $ccds[0] -trange $start $range -tz 10.0`;
+$N = @imregdb;
+print "imregdb: $N files\n";
+
+# search for missing images in archive
+ ARCH: foreach $arch (@archive) {
+     
+     # is $arch in @imregdb?
+     foreach $imreg (@imregdb) {
+	 @words = split (" ", $imreg);
+	 if ($arch eq $words[5]) { next ARCH; }
+     }
+     
+     push @missing, $arch;
+ }
+
+$Nmiss = @missing;
+print "$Nmiss files missing\n";
+
+# link each missing image in /data/kapu/elixir/cfh12k:
+$linkdir = `gconfig $opts ARCLINK_DIR`;  chop $linkdir;
+if ($?) { die "error in config system: missing ARCLINK_DIR\n"; }
+
+$archive = `gconfig $opts ARCHIVE_DIR`;  chop $archive;
+if ($?) { die "error in config system: missing ARCHIVE_DIR\n"; }
+
+# add missing links, elixir.link will add them to db
+foreach $file (@missing) {
+
+    print STDERR "link: $file\n";
+    $arcfile  = sprintf "%s/%s", $archive, $file;
+    $linkfile = sprintf "%s/%s", $linkdir, $file;
+    
+    if (-l $linkfile) { 
+	print STDERR "$linkfile exists, skipping\n";
+	next;
+    }
+    symlink ($linkfile, $arcfile);
+}    
+    
+# at this point, imstats from the last night is still running
+# the unprocessed images and the newly linked images will be 
+# added to the imstats fifo (not ptolemy, don't bother!)
+
+# find images which need to be re-processed (entire run)
+$runid = `gconfig RUNID.CURRENT`; chop $runid;
+$answer = `mkrun run $runid`;
+($tmp, $start, $stop) = split (" ", $answer);
+
+$fifo = `gconfig imstats`; chop $fifo;
+
+# the db lookup may take a long time or fail, the cat probably won't
+system ("imsearch -trange $start $stop -proc f > $fifo.tmp");
+if (! -s "$fifo.tmp") {
+    system ("glockfile $fifo.source xcld 5 &");
+    system ("cat $fifo.tmp >> $fifo.source");
+}
+
+# generate table of images which can be sent to CADC, mark as distributed:
+system ("imsearch -ccd $ccds[3] -trange $start $stop -proc t -dist f -cadctable cadc.fits");
+system ("imsearch -ccd $ccds[3] -trange $start $stop -proc t -dist f -modify dist t");
+
+# utilities ############################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/ckphotom
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/ckphotom	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/ckphotom	(revision 16632)
@@ -0,0 +1,35 @@
+#!/usr/bin/env perl
+
+# the specific ccd is passed in from outside
+
+if (@ARGV != 3) { die "USAGE: ckphotom (name) (ccd) (mode)\n" ;}
+
+$name = $ARGV[0];
+$ccd  = $ARGV[1];
+$mode = "\U$ARGV[2]\E";
+
+if (($mode ne "SPLIT") && ($mode ne "MEF")) {
+    print STDERR "mode must be SPLIT or MEF\n";
+    exit (2);
+}
+
+if (vsystem ("photsearch -trans -image $name $ccd $mode -equiv")) {
+    print STDOUT "$name fails, no photom data\n";
+    exit 1;
+} else {
+    print STDOUT "$name: pass\n";
+    exit 0;
+}
+
+# utilities ############################
+
+sub vsystem {
+#    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/ckrunid
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/ckrunid	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/ckrunid	(revision 16632)
@@ -0,0 +1,228 @@
+#!/usr/bin/env perl
+
+# USAGE: ckrunid (name) 
+# (name) may be a MEF or SINGLE CCD file or a SPLIT directory
+# does not depend on the number of CCDs in the image
+
+if (@ARGV != 1) { die "USAGE: ckrunid (name)\n" ;}
+
+$name = $ARGV[0];
+$imtype = ckimtype ($name);
+if (!$imtype) { exit 1; }
+
+if ($imtype eq SPLIT) {
+    $root = gt_names ($name, "root", $imtype);
+    $tmpname = "$name/$root" . "00.fits";
+} else {
+    $tmpname = $name;
+}
+
+# need to abstract MJD-OBS keywrod
+$answer = `echo $tmpname | fields MJD-OBS`; chop ($answer);
+($fullname, $mjd_obs) = split (" ", $answer);
+if ($mjd_obs eq "") {
+    print STDOUT "MJD-OBS not found in header for $tmpname\n";
+    exit 1;
+}
+
+$date = mjd_to_date ($mjd_obs);
+print STDERR "date: $date\n";
+
+$runinfo = `mkrun date $date`;
+if ($?) { die "no run defined $date $mjd\n"; }
+
+($crunid, $start, $stop, $camera, $qrunid) = split (" ", $runinfo);
+print STDOUT "$crunid\n";
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub get_jd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5;
+    
+
+    return ($jd);
+
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
+sub mjd_to_date {
+    my ($mjd) = $_[0];
+    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday);
+    my ($date, $time);
+    
+    $time = 86400 * ($mjd - 40587.0);
+    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime ($time);  
+    $year += 1900;
+    $mon ++;
+
+    $date = sprintf "%04d/%02d/%02d,%02d:%02d:%04.1f", $year, $mon, $mday, $hour, $min, $sec;
+    
+    return $date;
+}
+
+sub gt_names {
+    # in: filename mode type
+    # out: word
+
+    my ($value);
+
+    $value = "";
+    if ($_[2] eq "MEF")   { $value = mefnames ($_[0], $_[1]); }
+    if ($_[2] eq "SPLIT") { $value = splitnames ($_[0], $_[1]); }
+    
+    return $value;
+}
+
+sub mefnames {
+    # in: (/path/file.fits) (mode) 
+    # out: word
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer);
+
+    # split rootdir and filename:
+    my (@words) = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	$answer =~ s/.fits$//;
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	if (! -e $fullname) {
+	    return (0);
+	}
+	$answer = `echo $fullname | fields NEXTEND`;
+	@words = split (" ", $answer);
+	if ($words[1] eq "") {
+	    return (0);
+	}
+	return ($words[1]);
+    }
+    
+    return (0);
+}
+
+sub splitnames {
+    # in: (/path/file) (mode) 
+    # out: word
+    # /path/file is directory containing Nccd fits images
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer, $N, $tmpname, @imlist, @words);
+
+    # split rootdir and filename:
+    @words = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	
+	$tmpname = "$fullname/$words[$N-1]";
+	@imlist = <$tmpname??.fits>;
+
+	$Nccd = @imlist;
+	return $Nccd;
+    }
+    
+    return (0);
+}
+
+sub ckimtype {
+    # in: (/path/file)
+    # out: MEF | SPLIT | SINGLE | (NULL)
+    
+    my ($answer, $name, $value);
+    my ($file) = $_[0];
+
+    if (! -e $file) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+
+    # if /path/file is a directory, it is split:
+    if (-d $file) { return "SPLIT"; }
+
+    # check that the file is a FITS image
+    $answer = `file -L $file`;
+    if ($?) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+    ($name, $value) = split (" ", $answer);
+    if ($value ne "FITS") { 
+	print STDOUT "not a valid image\n";
+	return ""; 
+    }
+    
+    # check for NAXIS = 0 (MEF) 
+    $answer = `echo $file | fields NAXIS`;
+    # if ($?) { return ""; }
+    ($name, $value) = split (" ", $answer);
+    if ($value eq 0) { return "MEF"; }
+    
+    if ($value == 2) { return "SINGLE"; }
+
+    print STDOUT "not a valid image\n";
+    return "";
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/ckvalid
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/ckvalid	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/ckvalid	(revision 16632)
@@ -0,0 +1,302 @@
+#!/usr/bin/env perl
+
+$PASS = 0;
+$FAIL = 1;
+$SUBVALID = 2;
+$DATA_ERR = 3;
+$VERBOSE = 0;
+
+$eval{DATA}    = 0;  # image exists and is full-raster object MEF or SPLIT type
+$eval{DETREND} = 0;  # all needed detrend files exist for this image
+$eval{FRINGES} = 0;  # fringe frames exists if needed
+$eval{ASTROM}  = 0;  # astrometry measured for at least N / 12 chips
+$eval{PHOTOM}  = 0;  # photometry terms available for this image
+
+# USAGE: ckvalid (filename)
+# (filename) may be a MEF file or a SPLIT directory
+# [see end for notes]
+
+@tARGV = ();
+while (@ARGV) {
+    if ($ARGV[0] eq "-v") { 
+	$VERBOSE = 1;
+	shift @ARGV;
+	next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift @ARGV;
+}    
+@ARGV = @tARGV;
+
+if (@ARGV != 1) { die "USAGE: ckvalid (filename)\n" ;}
+$name = $ARGV[0];
+$mode = "unknown";
+$type = "unknown";
+$runid = "none";
+
+# load ccd config information
+@ccdn   = split (" ", `cameraconfig -ccdn`); if ($?) { &goodbye ("ERROR in cameraconfig"); }
+@ccds   = split (" ", `cameraconfig -ccds`); if ($?) { &goodbye ("ERROR in cameraconfig"); }
+
+# determine image mode (SPLIT / MEF / SINGLE)
+$mode = ckimmode ($name);
+if ($mode eq "unknown") { 
+    if ($VERBOSE) { print "can't identify image mode\n"; }
+    &print_status;
+    exit $DATA_ERR; 
+}
+if ($mode eq "SINGLE") { 
+    if ($VERBOSE) { print STDERR "mode = SINGLE, validation undefined\n"; }
+    &print_status;
+    exit $DATA_ERR;
+}
+
+# get filename components
+$path = gt_names ($name, "path", $mode);
+$root = gt_names ($name, "root", $mode);
+$Nccd = gt_names ($name, "Nccd", $mode);
+
+# create the name of a real file:
+if ($mode eq SPLIT) {
+    $tmpname = sprintf "%s/%s%s.fits", $name, $root, $ccdn[0];
+} else {
+    $tmpname = $name;
+}
+
+# find the run id for this image (needed to get astrometry)
+$runid = `ckrunid $tmpname`; chop ($runid);
+if ($?) {
+    if ($VERBOSE) { print STDOUT "$name: no run ID\n"; }
+    $runid = "none";
+}
+
+# check the IMAGETYP:
+$answer = `echo $tmpname | fields OBSTYPE`;
+($tmp, $type) = split (" ", $answer);
+if ($type ne "OBJECT") { 
+    if ($VERBOSE) { print STDOUT "$name: wrong image type $type\n"; }
+    &print_status;
+    exit $SUBVALID;
+}
+
+# check the GEOMETRY:
+$answer = `echo $tmpname | fields CCDBIN1 CCDBIN2 RASTER`;
+@words = split (" ", $answer);
+if (($words[1] != 1) || ($words[2] != 1)) { 
+    if ($VERBOSE) { print STDOUT "$name: binned image\n"; }
+    &print_status;
+    exit $SUBVALID;
+}
+if ($words[3] ne "FULL") { 
+    if ($VERBOSE) { print STDOUT "$name: sub-rastered image\n"; }
+    &print_status;
+    exit $SUBVALID;
+}
+
+# image is OK
+$eval{DATA} = 1;
+
+# check the ASTROMETRY:
+unless ($runid eq "none") {
+    $answer = `ckastrom $runid $root $Nccd`; chop ($answer);
+    if ($?) {
+	if ($VERBOSE) { print "astrometry: $answer\n"; }
+    } else {
+	$eval{ASTROM} = 1;
+    }
+}
+
+# check the DETREND data:
+if ($mode eq "SPLIT") {
+    # we only need the name of an single representative file on disk
+    $tmpname = sprintf "%s/%s%s.fits", $name, $root, $ccdn[0];
+} else {
+    $tmpname = $name;
+}
+$answer = `detsearch -quiet -mosaic $tmpname -recipe`;
+if ($?) { 
+    if ($VERBOSE) { print "missing detrend: $answer\n"; } 
+} else {
+    $eval{DETREND} = 1;
+}
+
+# check on PHOTOMETRY
+$answer = `ckphotom $tmpname $ccds[0] $mode`;
+if ($?) {
+    if ($VEROSE) { print STDERR "photom failed: $answer\n"; }
+} else {
+    $eval{PHOTOM} = 1;
+}
+
+&print_status;
+if ($eval{DATA} && $eval{DETREND} && $eval{PHOTOM} && $eval{ASTROM}) { exit $PASS; }
+exit $FAIL;
+
+# utilities ##############################################
+
+sub print_status {
+    printf STDOUT "%s %8s %8s %8s %d %d %d %d\n", $name, $mode, $type, 
+    $runid, $eval{DATA}, $eval{DETREND}, $eval{PHOTOM}, $eval{ASTROM};
+}
+
+sub gt_names {
+    # in: filename mode type
+    # out: word
+
+    my ($value);
+
+    $value = "";
+    if ($_[2] eq "MEF")   { $value = mefnames ($_[0], $_[1]); }
+    if ($_[2] eq "SPLIT") { $value = splitnames ($_[0], $_[1]); }
+    
+    return $value;
+}
+
+sub mefnames {
+    # in: (/path/file.fits) (mode) 
+    # out: word
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer);
+
+    # split rootdir and filename:
+    my (@words) = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	$answer =~ s/.fits$//;
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	if (! -e $fullname) {
+	    return (0);
+	}
+	$answer = `echo $fullname | fields NEXTEND`;
+	@words = split (" ", $answer);
+	if ($words[1] eq "") {
+	    return (0);
+	}
+	return ($words[1]);
+    }
+    
+    return (0);
+}
+
+sub splitnames {
+    # in: (/path/file) (mode) 
+    # out: word
+    # /path/file is directory containing Nccd fits images
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer, $N, $tmpname, @imlist, @words);
+
+    # split rootdir and filename:
+    @words = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	
+	$tmpname = "$fullname/$words[$N-1]";
+	@imlist = <$tmpname??.fits>;
+
+	$Nccd = @imlist;
+	return $Nccd;
+    }
+    
+    return (0);
+}
+
+sub ckimmode {
+    # in: (/path/file)
+    # out: MEF | SPLIT | SINGLE | (NULL)
+    
+    my ($answer, $name, $value);
+    my ($file) = $_[0];
+
+    if (! -e $file) { 
+	if ($VERBOSE) { print STDOUT "$file: can't open file\n"; }
+	return "unknown"; 
+    }
+
+    # if /path/file is a directory, it is split:
+    if (-d $file) { return "SPLIT"; }
+
+    # check that the file is a FITS image
+    $answer = `file -L $file`;
+    if ($?) { 
+	if ($VERBOSE) { print STDOUT "can't open file\n"; }
+	return "unknown"; 
+    }
+    ($name, $value) = split (" ", $answer);
+    if ($value ne "FITS") { 
+	if ($VERBOSE) { print STDOUT "not a valid image\n"; }
+	return "unknown"; 
+    }
+    
+    # check for NAXIS = 0 (MEF) 
+    $answer = `echo $file | fields NAXIS`;
+    # if ($?) { return ""; }
+    ($name, $value) = split (" ", $answer);
+    if ($value eq 0) { return "MEF"; }
+    
+    if ($value == 2) { return "SINGLE"; }
+
+    if ($VERBOSE) { print STDOUT "not a valid image\n"; }
+    return "unknown";
+}
+
+sub vsystem {
+    # print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+
+# This program calls several other perl scripts to get information 
+# about the image.  
+# ckrunid   - determine the appropriate Camera Run ID for this image
+# ckastrom  - check for the appropriate astrometry information
+# ckdetrend - check for the appropriate detrend images
+# ckphotom  - check for the appropriate photometry data
+
+# at the moment, there are different calling conventions for each of
+# these functions.  Some take a single name (MEF / SPLIT), some take a
+# reference to the specific CCD (filename CCD MODE).  
+
+# none of the called functions need to find the number of CCDs
+# ckvalid determines the number of CCDs from the header (MEF) or the
+# number of appropriately named FITS files in the directory (SPLIT).
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/cmp.header
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/cmp.header	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/cmp.header	(revision 16632)
@@ -0,0 +1,101 @@
+#!/usr/bin/env perl
+
+$version = 1.0;
+if (@ARGV != 2) { die "USAGE: cmp.header (cmpfile) (hdrfile)\n" ; }
+
+$cmpfile   = $ARGV[0];
+$hdrfile = $ARGV[1];
+
+&ckpathname ("$hdrfile");
+
+if (! -e $cmpfile) { die "ERROR: source cmpfile $cmpfile not found\n"; }
+
+# grab astrometry keywords from $cmpfile:
+@header = &load_header ($cmpfile);
+
+# convert stripped header to valid FITS file: NAXIS -> 0
+$found = 0;
+for ($i = 0; ($i < 16) && ($i < @header); $i++) {
+    if ($header[$i] =~ /^NAXIS   =/) { 
+	$header[$i] = sprintf "NAXIS   = %20d / %-47s", 0, "Header without Pixels";
+	$found = 1;
+	last;
+    }
+}
+if (!$found) { print STDERR "header is missing NAXIS\n"; }
+
+# write output to file
+open (FILE, ">$hdrfile");
+foreach $line (@header) {
+    print FILE "$line";
+}
+for ($i = 0; $i < $Nextra; $i++) {
+    for ($j = 0; $j < 80; $j++) {
+	print FILE " ";
+    }
+}
+close (FILE);
+
+print "SUCCESS: done with cmp.header\n";
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub load_header {
+
+    my ($file) = $_[0];
+    my ($ID, $buffer, $done, @buffer, $line);
+
+    open (FILE, "$file");
+    read FILE, $ID, 8;
+    if ($ID eq "SIMPLE  ") { goto valid; }
+    if ($ID eq "XTENSION") { goto valid; }
+    close (FILE);
+    die "SUCCESS: $file is not a valid header file\n";
+    
+valid:
+    seek FILE, 0, "SEEK_SET";
+    $done = 0;
+    @buffer = ();
+
+    while (! $done) {
+	read FILE, $buffer, 2880;
+	for ($i = 0; $i < 2880; $i+=80) {
+	    $line = substr ($buffer, $i, 80);
+	    @buffer = (@buffer, $line);
+	    if ($line =~ /^END     /) { $done = 1; }
+	}
+    }
+    close (FILE);
+    return (@buffer);
+}
+
+# given a filename, check that its path exists, create it if not
+sub ckpathname {
+    my ($file) = $_[0];
+    my (@words, $dir);
+
+    @words = split ("/", $file);
+    pop (@words);
+    $dir = join ("/", @words);
+
+    if ($dir eq "") { $dir = "."; }
+
+    if (! -d $dir) {
+	system ("mkdir -p $dir");
+	if ($?) {
+	    print STDERR "ERROR: can't make directory component for $file\n";
+	    exit 1;
+	}
+    }
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/complete.addstar
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/complete.addstar	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/complete.addstar	(revision 16632)
@@ -0,0 +1,31 @@
+#!/usr/bin/env perl
+
+# get list of *o/*.smp
+@smplist = <*o/*.smp>;
+
+$i = 0;
+foreach $file (@smplist) {
+
+    # is NASTRO > 0?
+    ($tmp, $nastro) = split (" ", `echo $file | fields NASTRO`);
+    if ($nastro == 0) { next; }
+
+    # is file already in db?
+    ($path, $root) = split ("/", $file);
+    $answer = `imphotsearch -D CATDIR $catdir -name $root`;
+    if ($answer == "") { next; }
+
+    # addstar file
+    vsystem ("addstar -D CATDIR $catdir $file");
+
+    $i ++;
+    if ($i > 30) {exit;}
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+#    my($status) = system ("@_");
+#    $status;
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/create.subset
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/create.subset	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/create.subset	(revision 16632)
@@ -0,0 +1,28 @@
+#!/usr/bin/env perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 2) { die "ERROR: USAGE: create.subset (master) (subset)\n" }
+
+# load in stats lines
+open (IN,  $ARGV[0]);
+open (OUT, ">$ARGV[1]");
+while ($line = <IN>) {
+    chop ($line);
+    @words = split (" ", $line);
+    if ($words[1]) {
+       print OUT "$words[0]\n";
+   }      
+}    
+close (IN);
+close (OUT);
+
+print STDERR "SUCCESS\n";
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/dads.detrend
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/dads.detrend	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/dads.detrend	(revision 16632)
@@ -0,0 +1,324 @@
+#!/usr/bin/env perl
+# calls flatten.flips & defringe, but no flips components directly
+
+$CLEANUP     = 1;
+$DO_DEFRINGE = 0;
+$DO_DEMODE   = 0;
+$config = "";
+if ($ENV{'PTOLEMY'}) { $config = "-c $ENV{'PTOLEMY'}"; }
+$tmpenv = `mktemp /tmp/elixir.XXXXXX`; chop ($tmpenv);
+
+@opt = ();
+@tARGV = ();
+$LIMITMODES = "";
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-c") {
+        $config = "-c $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-C") {
+        push @opt, "-C $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-D") {
+        push @opt, "-D $ARGV[1] $ARGV[2]";
+        shift; shift; shift; next;
+    }
+    if ($ARGV[0] eq "-cleanup") {
+	$CLEANUP = 0;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-limitmodes") {
+	$LIMITMODES = "-limitmodes $ARGV[1]";
+        shift; shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+$config = join (" ", $config, @opt);
+$status = system ("gconfig -raw $config > $tmpenv");
+if ($status) { &escape ("error in elixir configuration: gconfig fails"); }
+$ENV{'PTOLEMY'} = "$tmpenv";
+
+if (@ARGV != 3) { &escape ("USAGE: dads.detrend (input) (outbase) (level) [-cleanup] [elixir options]"); }
+
+$input  = $ARGV[0];   # input : /path/path/654321o.fits 
+$outdir = $ARGV[1];   # output: /path/path/654321p
+$level =  $ARGV[2];   # level : perfect, best, raw
+
+# validate level
+$level = "\U$level\E";
+if (($level ne "PERFECT") && ($level ne "BEST") && ($level ne "RAW")) {
+    &escape ("ERROR: invalid entry for (level)");
+}
+$close = "";
+if ($level eq "BEST") { $close = "-close"; }
+
+# check for input file (must be MEF)
+if (! -e $input) { &escape ("ERROR: input file not found"); }
+
+# for raw distribution, simply use fhtool to split the files:
+if ($level eq "RAW") {
+    system ("rmdir $outdir");
+    if ($?) { &escape ("ERROR: can't remove target directory for fhtool"); }
+    system ("fhtool $input $outdir");
+    if ($?) { &goodbye ("ERROR: failure in fhtool"); }
+    print STDOUT "SUCCESS: finished with dads.detrend\n";
+    &goodbye;
+}
+
+# force output directory to exist
+if (! -d $outdir) { 
+    system ("mkdir -p $outdir"); 
+    if ($?) { &goodbye ("ERROR: can't create output directory"); }
+}
+
+# load ccd config information
+@ccdn   = split (" ", `cameraconfig -ccdn`); if ($?) { &goodbye ("ERROR in cameraconfig"); }
+@ccds   = split (" ", `cameraconfig -ccds`); if ($?) { &goodbye ("ERROR in cameraconfig"); }
+
+# load abstracted keywords
+($typekwd, $filtkwd, $exptkwd) = split (" ", `gconfig IMAGETYPE-KEYWORD FILTER-KEYWORD EXPTIME-KEYWORD`);
+if ($?) { &goodbye ("ERROR: config system missing keyword abstractions"); }
+
+# extract keyword values:
+($junk, $type, $exptime, $filtvalue) = split (" ", `echo $input | fields $typekwd $exptkwd $filtkwd`);
+if ($?) { &goodbye ("ERROR: failure reading header keywords (1)"); }
+
+# check for valid imagetype & filter
+if ($type ne "OBJECT") { &goodbye ("ERROR: $input: wrong image type"); }
+$filter = `filtnames $filtvalue`; chop $filter;
+if ($?) { &goodbye ("ERROR: filter not found"); }
+
+# check recipe file for detrend types & cutoff exptime values
+$recipefile = `gconfig DETREND_RECIPES`; chop $recipefile;
+($detypes, $cutoffs) = split (" ", `gconfig -c $recipefile $filter`);
+if ($?) { &goodbye ("ERROR: failure to get detrend recipes"); }
+@detypes = split (",", $detypes);
+@cutoffs = split (",", $cutoffs);
+
+# check for DEFRINGE, DEMODE 
+$DO_DEFRINGE = 0;
+for ($i = 0; $i < @detypes; $i++) {
+    if ($detypes[$i] eq "fringe") {
+	if ($exptime >= $cutoffs[$i]) { $DO_DEFRINGE = 1; }
+	last;
+    }
+}
+$DO_DEMODE = 0;
+for ($i = 0; $i < @detypes; $i++) {
+    if ($detypes[$i] eq "modes") {
+	if ($exptime >= $cutoffs[$i]) { $DO_DEMODE = 1; }
+	last;
+    }
+}
+$camera = `gconfig CAMERA`; chop $camera;
+if ($camera eq "meganorth") { $DO_DEMODE = 0; }
+
+# check the GEOMETRY:
+($tmp, $bin1, $bin2, $raster) = split (" ", `echo $input | fields CCDBIN1 CCDBIN2 RASTER`);
+if ($?) { &goodbye ("ERROR: failure reading header keywords (2)"); }
+
+if ($bin1 != 1) { &goodbye ("ERROR: $input: binned image"); }
+if ($bin2 != 1) { &goodbye ("ERROR: $input: binned image"); }
+if ($raster ne "FULL") { &goodbye ("ERROR: $input: sub-rastered image"); } 
+
+# print a summary of the processing
+print STDOUT "\n";
+print STDOUT "image: $input, filter: $filter, exptime: $exptime\n";
+print STDOUT "detrend processing: defringe: $DO_DEFRINGE, demode: $DO_DEMODE, level: $level\n\n";
+
+# get image size:
+@words = stat ($input);
+$Nbyte = $words[7];
+
+# check space on /tmp:
+@answer = `df -k /tmp`;
+@words = split (" ", $answer[1]);
+$Nfree = $words[3]*1024;
+
+# need space in workdir for one image for each of DEMODE & DEFRINGE:
+$Need  = 0;
+if ($DO_DEMODE)   { $Need ++; }
+if ($DO_DEFRINGE) { $Need ++; }
+$Nneed = $Need*$Nbyte*1.01;
+
+# choose a work directory (/tmp vs $outdir):
+$workdir = $outdir;
+if ($Nfree > $Nneed) {
+    $workdir = "/tmp";
+}
+
+print STDERR "Need workspace for $Need images: $Nfree vs $Nneed\n";
+
+# extract image rootname from $outdir:
+$base = &basename ($outdir);
+
+# create output lists:
+@detlist = ();
+@deflist = ();
+@demlist = ();
+@fitlist = ();
+foreach $ccd (@ccdn) {
+    push @fitlist, "$outdir/$base$ccd.fits";
+    push @detlist, "$workdir/$base$ccd.det";
+    push @deflist, "$workdir/$base$ccd.def";
+}
+# phu file:
+$phufile = "$outdir/$base.phu";
+
+# detrend  $input[ccd] @detlist
+# defringe @detlist    @deflist
+# demode   @deflist    @demlist
+# output               @fitlist
+
+#* flatten.flips input fitlist
+
+#* flatten.flips input detlist
+#* demode detlist fitlist
+
+# flatten.flips input detlist
+# defringe detlist deflist
+
+#* flatten.flips input detlist
+#* defringe detlist deflist
+#* demode deflist fitlist
+
+#            @demlist = @fitlist
+# !demode:   @deflist = @demlist
+# !defringe: @detlist = @deflist
+
+if ($DO_DEMODE) {
+    @demlist = @fitlist;
+} else {
+    if ($DO_DEFRINGE) { 
+	@deflist = @fitlist; 
+    } else {
+	@detlist = @fitlist; 
+    }
+}
+
+# run the detrend system
+for ($i = 0; $i < @ccds; $i++) {
+    $status = &vsystem ("flatten.flips $close -quiet $input $detlist[$i] $ccds[$i] mef");
+    if ($status) { &escape ("ERROR: problem running flatten on $input, $ccds[$i]"); }
+}
+$status = &vsystem ("flatten.flips $close -quiet $input $phufile phu mef");
+if ($status) { &escape ("ERROR: problem running flatten on $input, phu"); }
+
+# we need files containing detlist, demlist, deflist:
+if ($DO_DEMODE || $DO_DEFRINGE) {
+    $detlist = "$outdir.detlist";
+    open (FILE, ">$detlist");
+    foreach $name (@detlist) {
+	print FILE "$name\n";
+    }
+    close (FILE);
+}
+if ($DO_DEMODE) {
+    $mapfile = "$outdir.map.fits";
+    $deflist = $detlist;
+    $demlist = "$outdir.demlist";
+    open (FILE, ">$demlist");
+    foreach $name (@demlist) {
+	print FILE "$name\n";
+    }
+    close (FILE);
+}
+if ($DO_DEFRINGE) {
+    $deflist = "$outdir.deflist";
+    open (FILE, ">$deflist");
+    foreach $name (@deflist) {
+	print FILE "$name\n";
+    }
+    close (FILE);
+}
+
+if ($DO_DEFRINGE) {
+    $status = &vsystem ("defringe $detlist $deflist $close");
+    if ($status) { &escape ("ERROR: problem running defringe on $outdir"); }
+}
+
+if ($DO_DEMODE) {
+    $status = &vsystem ("demodemap $deflist $demlist -mapfile $mapfile $LIMITMODES $close");
+    if ($status) { &escape ("ERROR: problem running demodemap on $outdir"); }
+}
+
+# update the phu header with the results from ccd # 0
+if ($DO_DEMODE || $DO_DEFRINGE) {
+    $temp = `mktemp /tmp/elixir.XXXXXX`; chop ($temp);
+    system ("fhead $detlist[0] > $temp.1.hdr");
+    system ("fhead $fitlist[0] > $temp.2.hdr");
+    
+    @answer = `diff $temp.1.hdr $temp.2.hdr`;
+    open (FILE, ">$temp.hdr");
+    foreach $line (@answer) {
+	if ($line =~ m|^>\s|) {
+	    ($head) = $line =~ m|^>\s(.*)$|;
+	    print FILE "$head\n";
+	}
+    }
+    close FILE;
+  
+    vsystem ("fits_insert $phufile $temp.hdr");
+    if ($?) { &escape ("ERROR: cannot update phu"); }
+    unlink ("$temp");
+    unlink ("$temp.1.hdr");
+    unlink ("$temp.2.hdr");
+    unlink ("$temp.hdr");
+}
+&goodbye ("SUCCESS: finished with dads.detrend");
+
+########################################################################
+
+sub cleanup {
+
+    if (!$CLEANUP) { return; }
+
+    unlink $tmpenv;
+    # detlist, demlist, deflist
+    foreach $name (@detlist) {
+	if (-e $name && ($name =~ m|^/tmp/|)) { unlink ($name); }
+    }
+    foreach $name (@demlist) {
+	if (-e $name && ($name =~ m|^/tmp/|)) { unlink ($name); }
+    }
+    foreach $name (@deflist) {
+	if (-e $name && ($name =~ m|^/tmp/|)) { unlink ($name); }
+    }
+    
+    if (-e $detlist) { unlink ($detlist); }
+    if (-e $demlist) { unlink ($demlist); }
+    if (-e $deflist) { unlink ($deflist); }
+    
+    return;
+}
+
+sub basename {
+
+    my ($file) = $_[0];
+    my ($base, @words);
+
+    @words = split ("/", $file);
+    $base = $words[-1];
+    return $base;
+}
+
+sub vsystem {
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    &cleanup; 
+    print STDERR "@_\n";
+    exit 0;
+}
+
+sub escape {
+    &cleanup;
+    print STDERR "@_\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/dads.jpeg
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/dads.jpeg	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/dads.jpeg	(revision 16632)
@@ -0,0 +1,59 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 3) { die "USAGE: dads.jpeg (inbase) (outbase) (level)\n" }
+
+# test named Xserver, or start vnc on specified machine
+$xhost = `gconfig XHOST`; chop $xhost;
+$xdisp = `gconfig XDISP`; chop $xdisp;
+if (vsystem ("xdpyinfo -display $xdisp")) {
+    print STDERR "X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# find mana script
+$confdir = `gconfig CONFDIR`;  chop $confdir;
+$script = "$confdir/mana/dads.pro";
+
+# get image list
+@ilist = <$ARGV[0]/*.fits>;
+
+# level may be: 'perfect', 'best', 'raw'
+$level = "\U$ARGV[2]\E";
+if (($level ne "PERFECT") && ($level ne "BEST") && ($level ne "RAW")) {
+    die "ERROR: invalid entry for (level)\n";
+}
+
+$out1 = "$ARGV[1].b10.jpg";
+$out2 = "$ARGV[1].b50.jpg";
+
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "init.mosaic\n";
+print MANA "macro go\n";
+foreach $in (@ilist) {
+    print MANA "load.image $in\n";
+}
+print MANA "do.jpeg $out1 $out2 $level\n";
+print MANA "exit 0\n";
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    die "ERROR: problem running dads.jpeg\n"; 
+} 
+
+print STDOUT "SUCCESS: finished running dads.jpeg\n"; 
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/dads.keywords
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/dads.keywords	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/dads.keywords	(revision 16632)
@@ -0,0 +1,96 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 1) { die "USAGE: dads.keywords (outdir)\n" ;}
+
+# get list of image files:
+@list = <$ARGV[0]/*.fits>;
+$name = $list[0];
+
+# get appropriate run ID
+$runid = `ckrunid $name`; chop ($runid);
+if ($?) {
+    print STDERR "ERROR: can't find run ID\n";
+    exit 1;
+}
+
+# get the appropriate reduced data directory
+$tmpdir=`gconfig -D RUNID $runid TMPDIR`; chop ($tmpdir);
+if ($?) {
+    print STDERR "ERROR: can't find tmpdir\n";
+    exit 1;
+}
+
+if (! -d $tmpdir) { 
+    print STDERR "ERROR: can't open $tmpdir\n";
+    exit 1;
+}
+
+foreach $name (@list) {
+
+    # files have names like /path/654321p/654321p00.fits
+
+    # split rootdir and filename:
+    @words = split ("/", $name);
+    $N = @words;
+
+    # extract root (654321p) convert to original form (654321o)
+    ($root, $ccd) = $words[$N-1] =~ /(\d\d\d\d\d\d)\S(\d\d)/;
+    $base = sprintf "%so/%so%02d", $root, $root, $ccd;
+
+    # generate name of output header file
+    $hdxfile = $name;
+    $hdxfile =~ s/.fits$/.hdx/;
+    if ($hdxfile eq $name) {
+	print STDERR "ERROR in format of filename $name\n";
+	exit 1;
+    }
+
+    # grab.keywords tests both smp & cmp
+    $cmproot = "$tmpdir/$base";
+    if (vsystem ("grab.keywords $name $cmproot $hdxfile")) {
+	print STDERR "ERROR: can't get keywords for $name\n";
+	exit 1;
+    }
+
+    if (vsystem ("fits_insert $name $hdxfile -comment 5 'Fully Characterized and Analysed by Elixir @ CFHT'" )) {
+	print STDERR "ERROR inserting keywords in $name\n";
+	exit 1;
+    }
+}
+
+# add data for phu file:
+@list = <$ARGV[0]/*.phu>;
+$phufile = $list[0];
+
+# generate name of output header file
+$hdxfile = $name;
+$hdxfile =~ s/.fits$/.phu/;
+if ($hdxfile eq $name) {
+    print STDERR "ERROR in format of filename $name\n";
+    exit 1;
+}
+
+if (vsystem ("grab.keywords $phufile phu $hdxfile")) {
+    print STDERR "ERROR: can't get keywords for $name\n";
+    exit 1;
+}
+
+if (vsystem ("fits_insert $phufile $hdxfile -comment 5 'Fully Characterized and Analysed by Elixir @ CFHT'" )) {
+    print STDERR "ERROR inserting keywords in $name\n";
+    exit 1;
+}
+
+print STDERR "SUCCESS: applied new keywords\n";
+exit 0;
+
+# utilities ##############################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/darktime.cfh12k
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/darktime.cfh12k	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/darktime.cfh12k	(revision 16632)
@@ -0,0 +1,33 @@
+#!/usr/bin/env perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 2) { die "USAGE: darktime.cfht (image.exptime) (dark.exptime)\n" }
+
+$t1 = $ARGV[0];
+$t2 = $ARGV[1];
+
+$a = 0.000781480;
+$b = 5.45879e-06;
+$c = -1.21674e-09;
+
+$d1 = $a*$t1 + $b*$t1**2 + $c*$t1**3;
+
+$d2 = $a*$t2 + $b*$t2**2 + $c*$t2**3;
+
+$f = $d1 / $d2;
+
+# no dark correction for exptime < 15 sec
+if ($t1 < 15) { $f = 0.001; }
+
+print STDOUT "$f\n";
+
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/darktime.linear
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/darktime.linear	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/darktime.linear	(revision 16632)
@@ -0,0 +1,26 @@
+#!/usr/bin/env perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 2) { die "USAGE: darktime.linear (image.exptime) (dark.exptime)\n" }
+
+
+$t1 = $ARGV[0];
+$t2 = $ARGV[1];
+
+$r = $t1 / $t2;
+
+# no dark correction for exptime < 60 sec
+if ($t1 < 60) { $r = 0.0; }
+
+print STDOUT "$r\n";
+
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/defringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/defringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/defringe	(revision 16632)
@@ -0,0 +1,177 @@
+#!/usr/bin/env perl
+
+# grab the command line options
+$close = "";
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-close") {
+	$close = "-close";
+        shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 2) { &escape ("USAGE: defringe (inlist) (outlist) [-close]"); }
+
+# load config info
+$confdir = `gconfig CONFDIR`; chop $confdir;
+if ($?) { &escape ("config failure"); }
+$script = "$confdir/mana/fringe.pro";
+
+# various lists
+@input  = split (" ", `cat $ARGV[0]`);
+@output = split (" ", `cat $ARGV[1]`);
+@ccds   = split (" ", `cameraconfig -ccds`);
+$Nccd   = @ccds;
+$dbmode = `gconfig DETREND-DB-MODE`; chop $dbmode;
+
+# find fringe-point file
+$frpts  = `detsearch -quiet -image $input[0] $ccds[0] split -type frpts`; chop $frpts;
+if ($?) { &escape ("can't get fringe points for image"); }
+
+# temporary files
+$frstats = mktemp ("defringe");
+$imstats = mktemp ("defringe");
+$fitpars = mktemp ("defringe");
+
+# prepare for defringing:
+# 1) measure input image fringe stats (imstats)
+# 2) extract master fringe frame stats (frstats)
+# 3) create output directory if needed
+# 4) delete output files if present
+
+open (FILE, ">$frstats");
+for ($i = 0; $i < $Nccd; $i++) {
+    # measure fringe amplitude of input image
+    vsystem ("getfringe $input[$i] $ccds[$i]  $frpts 1 >> $imstats");
+    if ($?) { die "failure to measure fringe amplitude\n"; }
+
+    print "imstats; $imstats\n";
+
+    # find fringe master frames
+    @file = `detsearch -quiet $close -image $input[$i] $ccds[$i] split -type fringe`; 
+    $file = $file[-1]; chop $file;
+    if ($?) { &escape ("can't find fringe master for $input[$i]"); }
+    $fringe[$i] = $file;
+    if ($dbmode eq "MEF") { $fringe[$i] = "$file\[$ccds[$i]\]"; }
+
+    print "file: $file\n";
+    print "fringe: $fringe[$i]\n";
+    print "dbmode; $dbmode\n";
+
+    # get fringe master stats
+    if ($dbmode eq "MEF") {
+	($name, $C0, $C1, $SKY, $RNG) = split (" ", `echo $file | fields -x $i FRNG_C0 FRNG_C1 FRNG_SKY FRNG_RNG`);
+    } else {
+	($name, $C0, $C1, $SKY, $RNG) = split (" ", `echo $file | fields FRNG_C0 FRNG_C1 FRNG_SKY FRNG_RNG`);
+    }
+    print FILE "$C0 $C1 $SKY $RNG\n";
+    print STDERR "$C0 $C1 $SKY $RNG\n";
+
+    # check on output directory
+    &ckdir ($output[$i]);
+
+    if (-e $output[$i]) { unlink $output[$i]; }
+}
+close (FILE);
+
+# convert image stats to optimal image parameters
+vsystem ("fr.frstats -applyfit $imstats $frstats $fitpars");
+if ($?) { &escape ("failure in fr.frstats"); }
+@fitpars = `cat $fitpars`;
+
+# load flips parameter file
+$paramfile = `gconfig FLIPS_PARAM_DEFRINGE`; chop $paramfile;
+open (FILE, "$paramfile");
+@rawpars = <FILE>;
+close (FILE);
+
+$infile  = mktemp ("\@defringe");
+$parfile = mktemp ("defringe");
+for ($i = 0; $i < $Nccd; $i++) {
+
+    # create input list file
+    ($s0, $s1, $RF, $ds) = split (" ", $fitpars[$i]);
+    open (FILE, ">$infile");
+    print FILE "$input[$i]  $s0 1.0 $ds\n";
+    print FILE "$fringe[$i] $s1 $RF $ds\n";
+    close (FILE);
+
+    # create input par file
+    @params = @rawpars;
+    foreach $line (@params) {
+	$line =~ s|LISTNAME|$infile|;
+	$line =~ s|FILENAME|$output[$i]|;
+	$line =~ s|COMMENT|Elixir Defringing|;
+    }
+    open (FILE, ">$parfile");
+    foreach $line (@params) { print FILE "$line"; }
+    close (FILE);
+
+    vsystem ("imcombred $parfile");
+    if ($?) { &escape ("failure running imcombred"); }
+}
+
+&goodbye;
+
+########
+
+sub ckdir {
+
+    my ($file) = $_[0];
+    my ($dir, @words);
+
+    @words = split ("/", $file);
+    pop (@words);
+    $dir = join ("/", @words);
+    if ($dir eq "") { $dir = "."; }
+    if (! -e $dir) {
+	system ("mkdir -p $dir");
+	if ($?) { die "can't create output directory $dir\n"; }
+    }
+}
+
+sub loadlist {
+
+    my($command) = $_[0];
+    my(@list, $line);
+
+    @list = `$command`;
+
+    foreach $line (@list) { chop ($line); }
+
+    return @list;
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+@temp = ();
+sub mktemp {
+
+    my ($base) = $_[0];
+    my ($name);
+    $name = `mktemp /tmp/$base.XXXXXX`;
+    chop $name;
+
+    push @temp, $name;
+    return $name;
+}
+
+sub escape {
+    $message = $_[0];
+    foreach $name (@temp) {
+	unlink ($name);
+    }
+    die "$message\n";
+}
+
+sub goodbye {
+    foreach $name (@temp) { unlink ($name); }
+    exit 0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/defringe.ccd
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/defringe.ccd	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/defringe.ccd	(revision 16632)
@@ -0,0 +1,141 @@
+#!/usr/bin/env perl
+
+# grab the command line options
+$close = "";
+$quiet = 0;
+$preserve = 0;
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-close") {
+	$close = "-close";
+        shift; next;
+    }
+    if ($ARGV[0] eq "-quiet") {
+	$quiet = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-preserve") {
+        $preserve = 1;
+        shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 4) { &escape ("USAGE: defringe.chip (input) (output) (ccd) (mode) [-close]"); }
+
+# various lists
+$input  = $ARGV[0];
+$output = $ARGV[1];
+$ccd    = $ARGV[2];
+$mode   = uppercase ($ARGV[3]);
+if ($mode ne "SPLIT") { &escape ("defringe.ccd requires SPLIT input data for now"); }
+
+# load config info
+$dbmode = `gconfig DETREND-DB-MODE`; chop $dbmode;
+$ccdn   = `cameraconfig -N $ccd`; chop $ccdn;
+
+# find fringe-point file (always MEF)
+$frpts  = `detsearch -quiet -image $input $ccd split -type frpts`; chop $frpts;
+if ($?) { &escape ("can't get fringe points for image"); }
+
+# measure fringe amplitude of input image
+($name, $sky, $rng, $drng) = split (" ", `getfringe $input $ccd $frpts 1`);
+if ($?) { &escape ("failure to measure fringe amplitude"); }
+
+# find fringe master frames
+$file = `detsearch -quiet $close -image $input $ccd split -type fringe`; chop $file;
+if ($?) { &escape ("can't find fringe master for $input"); }
+
+$frmaster = $file;
+if ($dbmode eq "MEF") { $frmaster = "$file\[$ccd\]"; }
+
+# get fringe master stats
+if ($dbmode eq "MEF") {
+    ($name, $C0, $C1, $SKY, $RNG) = split (" ", `echo $file | fields -x $ccdn FRNG_C0 FRNG_C1 FRNG_SKY FRNG_RNG`);
+} else {
+    ($name, $C0, $C1, $SKY, $RNG) = split (" ", `echo $file | fields FRNG_C0 FRNG_C1 FRNG_SKY FRNG_RNG`);
+}
+
+if (-e $output) { unlink $output; }
+
+# load flips parameter file
+$paramfile = `gconfig FLIPS_PARAM_DEFRINGE`; chop $paramfile;
+open (FILE, "$paramfile");
+@rawpars = <FILE>;
+close (FILE);
+
+$infile  = mktemp ("\@defringe");
+$parfile = mktemp ("defringe");
+
+# create input list file
+$s0 = $sky;
+$s1 = $SKY;
+$RF = $RNG / $rng;
+$ds = 0.0;
+open (FILE, ">$infile");
+print FILE "$input    $s0 1.0 $ds\n";
+print FILE "$frmaster $s1 $RF $ds\n";
+close (FILE);
+
+# create input par file
+@params = @rawpars;
+foreach $line (@params) {
+    $line =~ s|LISTNAME|$infile|;
+    $line =~ s|FILENAME|$output|;
+    $line =~ s|COMMENT|Elixir Defringing|;
+}
+open (FILE, ">$parfile");
+foreach $line (@params) { print FILE "$line"; }
+close (FILE);
+
+vsystem ("imcombred $parfile");
+if ($?) { &escape ("failure running imcombred"); }
+
+&goodbye;
+
+########
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+@temp = ();
+sub mktemp {
+
+    my ($base) = $_[0];
+    my ($name);
+    $name = `mktemp /tmp/$base.XXXXXX`;
+    chop $name;
+
+    push @temp, $name;
+    return $name;
+}
+
+sub uppercase {
+    return "\U$_[0]\E";
+}
+
+sub escape {
+    $message = $_[0];
+    foreach $name (@temp) {
+	unlink ($name);
+    }
+    if ($quiet) { 
+	die "$message\n";
+    } else {
+	die "ERROR: $message\n"; 
+    }
+}
+
+sub goodbye {
+    foreach $name (@temp) { 
+	if ($preserve) { print STDERR "tmp file: $name\n"; }
+	else { unlink ($name); }
+    }
+    if (!$quiet) { print STDERR "SUCCESS\n"; }
+    exit 0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/demodemap
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/demodemap	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/demodemap	(revision 16632)
@@ -0,0 +1,74 @@
+#!/usr/bin/env perl
+
+# grab the command line options
+$limitmodes = "";
+$mapfile = "";
+$close = "";
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-close") {
+	$close = "-close";
+        shift; next;
+    }
+    if ($ARGV[0] eq "-mapfile") {
+	$mapfile = $ARGV[1];
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-limitmodes") {
+	$limitmodes = $ARGV[1];
+        shift; shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 2) { die "USAGE: demodemap (inlist) (outlist) [-mapfile file] [-limitmodes N] [-close]\n" }
+
+$inlist  = $ARGV[0];
+$outlist = $ARGV[1];
+
+open (FILE, "$inlist");
+@list = <FILE>;
+$first = $list[$i]; chop ($first);
+close (FILE);
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/modes.pro";
+$answer  = `cameraconfig -ccds`;
+@ccds    = split (" ", $answer);
+
+$modefits = `detsearch $close -quiet -image $first $ccds[0] split -type modes`; chop ($modefits);
+if ($?) { die "can't get mode image\n"; }
+
+@words = split ("/", $modefits);
+$basename = $words[-1];
+
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+
+# override default values (set in modes.pro):
+if ($limitmodes) { print MANA "\$Nmodes = $limitmodes\n"; }
+if ($mapfile) { print MANA "\$savemap = $mapfile\n"; }
+print MANA "demodemap $inlist $outlist $modefits $basename\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "problem with demodemap\n";
+    exit 1;
+}
+
+print STDOUT "finished with demodemap\n";
+
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/detflips
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/detflips	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/detflips	(revision 16632)
@@ -0,0 +1,90 @@
+#!/usr/bin/env perl
+
+# grab the command line options [-C config] [-c configfile]
+$config = "";
+$preserve = 0;
+@tARGV = ();
+while (@ARGV) {
+    if ($ARGV[0] eq "-C") {
+	$config = "$config -C $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-c") {
+	$config = "$config -c $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-preserve") {
+        $preserve = 1;
+        shift; next;
+    }
+    push @tARGV, $ARGV[0];
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 3) { die "ERROR: USAGE: detflips (inlist) (output) (type)\n" }
+
+$inlist = $ARGV[0];
+$output = $ARGV[1];
+$type   = "\U$ARGV[2]\E";
+
+# count lines in $inlist, adjust statmode (FLAT only)
+($nlines) = split (" ", `wc -l $inlist`);
+$statmode = 0;
+if ($nlines < 6) { $statmode = 1; }
+if ($nlines == 0) { die "ERROR: no files in source list, skipping\n"; }
+
+# delete old output file 
+if (-e $output) { unlink "$output"; }
+
+$temp1 = `mktemp /tmp/detflips.XXXXXX`; chop $temp1;
+$temp2 = `mktemp /tmp/\@detflips.XXXXXX`; chop $temp2;
+
+if ($type eq "BIAS")    { $paramkey = "FLIPS_PARAM_DARK";   $detype = "bias";    }
+if ($type eq "DARK")    { $paramkey = "FLIPS_PARAM_DARK";   $detype = "dark";    }
+if ($type eq "FLAT")    { $paramkey = "FLIPS_PARAM_FLAT";   $detype = "skyflat"; }
+if ($type eq "FRINGE")  { $paramkey = "FLIPS_PARAM_FRINGE"; $detype = "fringe";  }
+if ($type eq "STACK")   { $paramkey = "FLIPS_PARAM_STACK";  $detype = "science";  }
+
+if ($paramkey eq "")  { 
+    print STDERR "ERROR: invalid detrend type $type\n";
+    exit 1;
+}
+
+$paramfile = `gconfig $config $paramkey`; chop $paramfile;
+if ($?) { die "ERROR: missing parameter file $paramkey from config\n"; }
+
+open (FILE, "$paramfile");
+@params = <FILE>;
+close (FILE);
+
+print STDERR "detflips parameter file: $paramfile\n";
+
+foreach $line (@params) {
+    $line =~ s|LISTNAME|$temp2|;
+    $line =~ s|FILENAME|$output|;
+    $line =~ s|COMMENT|$type|;
+    $line =~ s|DETRENDTYPE|$detype|;
+    if ($type eq "FLAT") { $line =~ s|STATMODE|$statmode|; }
+}
+
+open (FILE, ">$temp1");
+print FILE "@params\n";
+close $temp1;
+
+system ("cp $inlist $temp2");
+system ("imcombred $temp1");
+$stat = $?;
+
+if (! $preserve) {
+    unlink ($temp1);
+    unlink ($temp2);
+}
+
+if ($stat) {
+    print STDERR "ERROR: failure in detflips\n";
+} else {
+    print STDERR "SUCCESS\n";
+}
+
+exit $stat;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/dt.select
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/dt.select	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/dt.select	(revision 16632)
@@ -0,0 +1,219 @@
+#!/usr/bin/env perl
+$SKIPDOME = 0;
+
+if (@ARGV != 6) { die "ERROR: USAGE: imselect (type) (filter) (tstart) (tend) (output) (SPLIT | MEF)\n" }
+
+$type   = "\U$ARGV[0]\E";
+$filter = "\U$ARGV[1]\E";
+$start  = $ARGV[2];
+$stop   = $ARGV[3];
+$output = $ARGV[4];
+$mode   = $ARGV[5];
+
+unless ($output =~ /CCDNUM/) { die "ERROR: output file needs CCDNUM component\n"; }
+
+if (($mode ne "MEF") && ($mode ne "SPLIT")) { die "ERROR: mode must be either -split or -mef\n"; }
+
+if ($type eq "DARK") { }
+
+if ($type eq "FLAT") {
+    # define some of the relevant parameters
+    $max = 60000;
+
+    $tmp = `filtnames $filter`; chop $tmp;
+    if ($?) { die "ERROR: invalid filter $filter\n"; }
+    $filter = $tmp;
+
+    # recipe file defines detrend types & cutoff exptime values
+    $recipefile = `gconfig DETREND_RECIPES`; chop $recipefile;
+    if ($?) { die "ERROR: missing DETREND_RECIPES in configuration\n"; }
+
+    ($tmp, $tmp, $extras) = split (" ", `gconfig -c $recipefile $filter`);
+    if ($?) { die "ERROR: missing detrend recipe for $filter\n"; }
+
+    # all filters have 'flat', grab extras:
+    ($detype, $minflux, $min) = split (",", $extras);
+    if ("\U$detype\E" ne "FLAT") { die "ERROR: flat extras are missing\n"; }
+}
+
+$CCDWORD      = `gconfig CCDNUM-KEYWORD`; chop $CCDWORD;
+$CHIPSKIP     = `gconfig CHIP_SKIP_LIST`; chop $CHIPSKIP;
+@chipskip = ();
+if (-e $CHIPSKIP) { 
+    open (FILE, $CHIPSKIP);
+    @chipskip = <FILE>;
+    close (FILE);
+    foreach $chip (@chipskip) { chop $chip; }
+}
+
+# relevant camera parameters
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+if ($?) { die "error in config\n"; }
+
+($Naxis1, $Naxis2) = split (" ", `cameraconfig -axes`);
+if ($?) { die "error in config\n"; }
+
+@ccds = split (" ", `cameraconfig -ccds`);
+if ($?) { die "error in config\n"; }
+
+@ccdn = split (" ", `cameraconfig -ccdn`);
+if ($?) { die "error in config\n"; }
+
+@good = ();
+@marginal = ();
+
+# define filter lines for imsearch.  for flats, there may be alternate filter names to test
+@filtline = ();
+if ($type eq "FLAT") {
+    # convert given filter name to list of possible names:
+    @filtlist = split (" ", `filtnames $filter -all`);
+    foreach $filt (@filtlist) {
+	push @filtline, "-type flat -filter $filt -mode $mode -trange $start $stop";
+    }
+} 
+if ($type eq "BIAS") {
+    push @filtline, "-type bias -mode $mode -trange $start $stop";
+} 
+if ($type eq "DARK") {
+    push @filtline, "-type dark -etime $ARGV[1] -mode $mode -trange $start $stop";
+} 
+
+# run selection on each possible $filtline
+@list = ();
+foreach $line (@filtline) {
+    @tlist = `imsearch -ccd $ccds[0] $line`;
+    @list = (@list, @tlist);
+}
+$Nlist = @list;
+print STDERR "found $Nlist images\n";
+
+FRAME:
+foreach $frame (@list) {
+    @words = split (" ", $frame);
+
+    # skip domeflat images
+    if ($SKIPDOME && ($type eq "FLAT")) {
+	# a fairly lame and non-robust way to detect dome flats
+	@answer = `echo $words[4]/$words[5] | fields OBJECT | grep -i dome`;
+	if ($answer[0] ne "") { print STDERR "$words[5] rejected: dome flat\n"; next FRAME; }
+	
+	# test for acceptable time (or is probably a dome flat)
+	$answer = `dusktime $words[8]`;
+	($tmp, $tmp, $dt) = split (" ", $answer);
+	if ($dt < 0) { print STDERR "$words[5] rejected: not twilight\n"; next FRAME; }
+    }
+
+    # image(s) must exist on disk:
+    if ($mode eq "SPLIT") {
+	# all $Nccd images must exist on disk, split files are assumed to be 
+	# in a subdirectory of their own, .fits extension assumed
+	@answer = <$words[4]/*.fits>;
+	if (@answer != $Nccd) { print STDERR "$words[5] rejected: missing images\n"; next FRAME; }
+    } else {
+	# base file should exist:
+	if (! -e "$words[4]/$words[5]") { print STDERR "file $words[4]/$words[5] missing, skipping\n"; next FRAME; }
+    }
+
+    # images have to have the correct dimensions
+    if ($mode eq "SPLIT") {
+	($tmp, $Nx, $Ny) = split (" ", `echo $words[4]/$words[5] | fields NAXIS1 NAXIS2`);
+    } else {
+	($tmp, $Nx, $Ny) = split (" ", `echo $words[4]/$words[5] | fields -x 0 NAXIS1 NAXIS2`);
+    }
+    if ($?) { print STDERR "failure to find NAXIS1, NAXIS2 in file $words[4]/$words[5], skipping\n"; next FRAME; }
+    if ($Nx != $Naxis1) { print STDERR "$words[5] rejected: wrong dimensions\n"; next FRAME; }
+    if ($Ny != $Naxis2) { print STDERR "$words[5] rejected: wrong dimensions\n"; next FRAME; }
+    
+    # must have Nccd entries in db:
+    if ($mode eq "SPLIT") { 
+	@answer = split ("/", $words[4]); 
+	$match = $answer[-1]; 
+    } else { 
+	$match = $words[5]; 
+    }
+    @list2 = `imsearch -name $match`;
+    if (@list2 != $Nccd) { print STDERR "$words[5] rejected: missing entries in image database\n"; next FRAME; }
+
+    # test flux levels for FLATS
+    if ($type eq "FLAT") {
+       CHIP:  # check for counts or flux out of range or any chip
+	foreach $chip (@list2) {
+	    @words2 = split (" ", $chip);
+	    foreach $chipskip (@chipskip) { 
+		if ($words2[3] eq $chipskip) { next CHIP; }
+	    }
+	    
+	    # test for acceptable counts range
+	    if ($words2[11] < $min) { print STDERR "$words[5] rejected: signal too low: $words2[11] vs $min\n"; next FRAME; }
+	    if ($words2[11] > $max) { print STDERR "$words[5] rejected: signal too high: $words2[11] vs $max\n"; next FRAME; }
+	    
+	    # test for acceptable flux
+            if ($words2[7] > 0.0) {
+	       $Flux = $words2[11] / $words2[7];
+	    } else {
+	       $Flux = 0.0;
+	    }
+	    if ($Flux < $minflux) { print STDERR "$words[5] rejected: flux too low: $Flux vs $minflux\n"; next FRAME; }
+	}
+    }
+    # test bias levels for BIAS / DARK
+    if (($type eq "BIAS") || ($type eq "DARK")) {
+       CHIP:  # check for values in bias column
+	foreach $chip (@list2) {
+	    @words2 = split (" ", $chip);
+	    if ($words2[10] == 0.0) { print STDERR "$words[5] rejected: no imstats\n"; next FRAME; }
+	}
+    }
+
+    # add good images to the output lists (use CCD N for output filenames, CCD ID for [extname] in mef files)
+    # entries are not guaranteed to be in CCD N sequence
+
+    foreach $line (@list2) {
+	@words2 = split (" ", $line);
+	$ccdid  = $words2[3];
+	if ($mode eq "MEF") {
+	    @$ccdid = (@$ccdid, "$words2[4]/$words2[5]\[$ccdid]");
+	} else {
+	    @$ccdid = (@$ccdid, "$words2[4]/$words2[5]");
+	}
+    }
+    if (($type eq "BIAS") && (@$ccdid > 30)) { last FRAME; }
+    if (($type eq "DARK") && (@$ccdid > 30)) { last FRAME; }
+    if (($type eq "FLAT") && (@$ccdid > 50)) { last FRAME; }
+}
+
+# write output to Nccd list files 
+for ($i = 0; $i < $Nccd; $i++) {
+    $ccd   = $ccdn[$i];
+    $ccdid = $ccds[$i];
+
+    $name = $output;
+    $name =~ s/CCDNUM/$ccd/;
+
+    open (LIST, ">$name");
+    foreach $line (@$ccdid) {
+	print LIST "$line\n";
+    } 
+    close (LIST);
+}
+print STDERR "SUCCESS\n\n";
+exit 0;
+
+# we need to select the list of images which satisfy a few criteria:
+# 1) all 12 CCDs must exist
+# 2) stats must be measured for each
+# 3) stats for all 12 must be within range (2000 - 40000)
+# 4) NAXIS1 == 2080 && NAXIS2 == 4128
+
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    die "@_";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.export
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.export	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.export	(revision 16632)
@@ -0,0 +1,88 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 3) { die "ERROR: usage: elixir.export (rawfile) (datfile) (mode)\n"; }
+
+$datdir = `gconfig DATDIR`; chop $datdir;
+$logdir = `gconfig LOGDIR`; chop $logdir;
+$config = "$datdir/export.conf";
+
+$rawfile = $ARGV[0];
+$datfile = $ARGV[1];
+$MODE    = $ARGV[2];
+
+if (! -e $config) { die "ERROR: config file $config missing\n"; }
+
+open (FILE, $config);
+while ($line = <FILE>) {
+    if ($line =~ /^\s*$/) { next; } # skip empty lines
+    if ($line =~ /^\s*\#/) { next; } # skip commented lines
+    $Nlist = ($id, $runids, $filters, $modes, $outdir) = split (" ", $line);
+    if ($Nlist != 6) { print STDERR "WARNING: error in config file: $line\n"; }
+    push @id, $id;
+    $runids{$id}  = $runids;
+    $filters{$id} = $filters;
+    $modes{$id}   = $modes;
+    $outdir{$id}  = $outdir;
+}
+close (FILE);
+
+($tmp, $RUNID) = split (" ", `echo $rawfile | fields RUNID`);
+($tmp, $FILTER) = split (" ", `echo $rawfile | fields FILTER`);
+
+$FILTER = `filtnames $FILTER`; chop $FILTER;
+
+open (LOG, ">>$logdir/export.log");
+
+if ($MODE eq "any") { goto wanted; }
+
+foreach $id (@id) {
+
+    if (!findword ($MODE, $modes{$id})) { next; }
+    if (!findword ($RUNID, $runids{$id})) { next; }
+    if (!findword ($FILTER, $filters{$id})) { next; }
+
+    # success, copy datfile to outdir:
+
+    system ("cp $datfile $outdir{$id}\n");
+    if ($?) { print STDERR "WARNING: can't write $datfile to $outdir{$id}\n"; }
+
+    open (FILE, ">>$outdir/export.tbl");
+    print FILE "$datfile\n";
+    close (FILE);
+
+    print LOG "export $datfile to $outdir for $id\n";
+}
+close (LOG);
+
+print STDERR "SUCCESS: export $datfile to $outdir for $id\n";
+exit 0;
+
+wanted:
+foreach $id (@id) {
+
+    if (!findword ($RUNID, $runids{$id})) { next; }
+    if (!findword ($FILTER, $filters{$id})) { next; }
+
+    print LOG "export $datfile is wanted, process\n";
+    close (LOG);
+    print STDERR "SUCCESS: $datfile is wanted\n";
+    exit 0;
+}
+
+print LOG "export $datfile is not wanted, skip\n";
+close (LOG);
+print STDERR "ERROR: $datfile is not wanted\n";
+exit 1;
+
+sub findword {
+    # findword $WORD $list
+    $WORD = "\U$_[0]\E";
+    $list = $_[1];
+
+    @word = split (",", $list);
+    foreach $word (@word) {
+	$word = "\U$word\E";
+	if ($word eq $WORD) { return 1; }
+    }
+    return 0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.link
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.link	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.link	(revision 16632)
@@ -0,0 +1,150 @@
+#!/usr/bin/env perl
+
+# this script searches for new links in the archive elixir directory,
+# creates links for the new images in the elixir TMPDIR tree,
+# registers the images in the elixir database, and 
+# sends the images to imstats for processing.
+
+use English;
+
+# check usage
+if (@ARGV != 0) { die "USAGE: elixir.link\n"; }
+
+# what do we do about config file?  demand account be set up correctly?
+$camera = `gconfig CAMERA.CURRENT`; chop $camera;
+$runid  = `gconfig RUNID.CURRENT`; chop $runid;
+$opts = "-D CAMERA $camera -D RUNID $runid";
+
+{ # check camera validity
+    if ($camera eq "cfh12k")  { last; } 
+    if ($camera eq "megacam") { last; } 
+    if ($camera eq "meganorth") { last; } 
+    if ($camera eq "cfhtir")  { last; } 
+    die "invalid camera $camera";
+}
+
+$fifos = `gconfig $opts FIFOS`; chop $fifos;
+if ($?) { die "error in config system: missing FIFOS\n"; }
+
+$rawdir = `gconfig $opts RAWDIR`;  chop $rawdir;
+if ($?) { die "error in config system: missing RAWDIR\n"; }
+
+$linkdir = `gconfig $opts ARCLINK_DIR`;  chop $linkdir;
+if ($?) { die "error in config system: missing ARCLINK_DIR\n"; }
+
+$archive = `gconfig $opts ARCHIVE_DIR`;  chop $archive;
+if ($?) { die "error in config system: missing ARCHIVE_DIR\n"; }
+
+@links = glob ("$linkdir/*");
+
+if (! @links) { exit 0; }
+
+$Ngood = 0;
+$Nskip = 0;
+$Nfail = 0;
+
+foreach $name (@links) {
+    if (! -l $name) { $Nskip ++; next; }
+    
+    # find real path
+    $rootname     = filename ($name);
+    $arcfile = sprintf "%s/%s", $archive, $rootname;
+    
+    # set new path (skip if it exists)
+    $rawfile = sprintf "%s/%s", $rawdir, $rootname;
+    if ((-e $rawfile) || (-l $rawfile)) { 
+	$Nskip ++;
+	unlink ($name);
+	next; 
+    }
+    
+    # link file into rawdir:
+    $status = symlink ($arcfile, $rawfile);
+    if (! $status) {
+	$Nfail ++;
+	next;
+    }
+    
+    # these files always come in as MEF or CUBE 
+    # -needtype will skip focus frames
+    vsystem ("imsort -needtype $opts $rawfile");
+    if ($?) { 
+	# allow for retry on failure
+	$Nfail ++;
+
+	# save links for record.
+	if (! -d "$linkdir/failure") { mkdir "$linkdir/failure"; }
+	system ("mv $name $linkdir/failure/");
+	next; 
+    }
+
+    $Ngood ++;
+    unlink $name;
+}
+
+print STDERR "elixir.link: $Ngood good, $Nskip skip, $Nfail fail\n";
+exit 0;
+
+# utilities ##############################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    my ($status) = system ("@_");
+    $status;
+}
+
+sub filename { 
+
+    my ($path) = $_[0];
+    my (@tmp);
+    
+    @tmp = split ("/", $path);
+    return $tmp[-1];
+}
+
+sub convertlink {
+    my ($link) = $_[0];
+    my ($file);
+
+    while (-l $link) {
+	$file  = readlink ($link);
+	$path1 = path ($link);
+	$path2 = path ($file);
+	
+	unless ($path2 =~ m|^/|) {
+	    $file = "$path1/$file";
+	}	
+	$link = $file;
+    }
+    return ($link);
+}    
+
+sub usage {
+    
+    if (@ARGV == 1) {
+	print STDERR "\n --- user modes ---\n";
+	print STDERR "create (run) (start) (stop)\n";
+	print STDERR "addqso (runid) (qsoid)\n";
+	print STDERR "delqso (qsoid)\n";
+	print STDERR "sched (runid)\n";
+	print STDERR "status\n";
+	&goodbye;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: prepare.run (help) [mode]\n"; &goodbye; }
+    
+    &goodbye;
+}
+
+sub path {
+
+    my ($file) = $_[0];
+
+    @words = split ("/", $file);
+
+    pop (@words);
+    
+    $path = join ("/", @words);
+
+    return ($path);
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.photreport
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.photreport	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.photreport	(revision 16632)
@@ -0,0 +1,48 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { die "USAGE : elixir.photreport (name) (catdir)\n"; }
+
+$name   = $ARGV[0];
+$catdir = $ARGV[1];
+
+# test named Xserver, or start vnc on specified machine
+$xhost = `gconfig XHOST`; chop $xhost;
+$xdisp = `gconfig XDISP`; chop $xdisp;
+if (system ("/usr/bin/X11/xdpyinfo -display $xdisp")) {
+    print STDERR "X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# select filters 
+@filter = split (" ", `filtnames list`);
+
+$logdir   = `gconfig LOGDIR`;   chop $logdir;
+$confdir  = `gconfig CONFDIR`;  chop $confdir;
+$script   = "$confdir/mana/standards";
+
+# run mana, call script
+open (STAT, "|dvo -D CATDIR $catdir --norc");
+print STAT "input $script\n";
+
+# place commands in a macro
+print STAT "macro go\n";
+foreach $filter (@filter) {
+    @word = split (" ", `filtnames $filter -cal`);
+    if (@word[1] == 0) { next; }
+    $target = $word[2];
+    print STAT "echo $filter -> $target\n";
+    print STAT "photreport $target $name\n";
+}
+print STAT "exit 0\n";
+print STAT "end\n";
+
+print STAT "go\n";
+print STAT "exit 1\n";
+close (STAT);
+if ($?) {
+    print STDERR "ERROR problem with photreport\n";
+    exit 1;
+}
+print STDOUT "SUCCESS: finished with photreport\n";
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.postrun
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.postrun	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.postrun	(revision 16632)
@@ -0,0 +1,690 @@
+#!/usr/bin/env perl
+
+# check usage
+if (@ARGV == 0) { &usage; }
+if ($ARGV[0] eq "help") { &usage; }
+
+@ARGV = elixir_config (@ARGV);
+
+if ($ARGV[0] eq "config") { &set_config; }
+if ($ARGV[0] eq "set")    { &set_entry; }
+if ($ARGV[0] eq "state")  { &state; }
+if ($ARGV[0] eq "update") { &update; }
+
+&load_state;
+   
+if ($ARGV[0] eq "imstats")   { &imstats_state ("imstats");     &save_state; &goodbye; }
+if ($ARGV[0] eq "ptolemy")   { &ptolemy_state ("ptolemy");     &save_state; &goodbye; }
+if ($ARGV[0] eq "standards") { &standards_state ("standards"); &save_state; &goodbye; }
+if ($ARGV[0] eq "validate")  { &validate_state ("validate");   &save_state; &goodbye; }
+
+&escape ("unknown command $ARGV[0]");
+
+############# change current run ##############
+sub set_config {
+    if (@ARGV != 3) { &escape ("USAGE: elixir.postrun config (camera) (run)"); }
+    
+    $camera = $ARGV[1];
+    $run    = $ARGV[2];
+
+    # set current run id:
+    system ("mkrun sys camera.postrun $camera");
+    if ($?) { &escape ("can't define camera: error in mkrun"); }
+    
+    # set current run id:
+    system ("mkrun sys runid.postrun $run");
+    if ($?) { &escape ("can't define run: error in mkrun"); }
+    
+    &goodbye;
+}
+
+##############
+sub state {
+    print STDOUT "CAMERA: $camera\n";
+    print STDOUT "RUNID:  $runid\n";
+    print STDOUT "RUNDIR: $rundir\n";
+
+    &load_state;
+    foreach $entry (@entry) {
+	printf STDERR "%-15s %-10s\n", $entry,  $state{$entry};
+    }
+    &goodbye;
+}
+
+##############
+sub load_state {
+    # db contains: (entry) (state)
+    open (FILE, $dbfile);
+    @list = <FILE>;
+    close (FILE);
+
+    # there should be one line for each possible entry in @entry
+    # if a line is missing, set it to init
+    # if a line is extra, kill it.
+
+    # look for invalid entries
+    foreach $line (@list) {
+	($entry, $state) = split (" ", $line);
+	if (! $def_state{$entry}) { next; }
+	$state{$entry} = $state;
+    }
+
+    # look for missing entries
+    foreach $entry (@entry) {
+	if (! $state{$entry}) { $state{$entry} = $def_state{$entry}; }
+    }
+}
+
+##############
+sub save_state {
+    open (FILE, ">$dbfile");
+    foreach $entry (@entry) {
+	print FILE "$entry $state{$entry}\n";
+    }
+    close (FILE);
+}
+   
+##############
+sub set_entry {
+
+    if (@ARGV != 3) { &escape ("USAGE: elixir.postrun set (entry) (value)"); }
+
+    $reset = $ARGV[1];
+    $value = $ARGV[2];
+    
+    &load_state;
+
+    if (! $state{$reset}) { &escape ("invalid entry $reset"); }
+
+    $state{$reset} = $value;
+    &save_state;
+    &goodbye;
+}
+
+##############
+sub update {
+    
+    &load_state;
+	   
+    foreach $entry (@entry) {
+	update_state ($entry);
+	printf STDERR "%-15s %-10s\n", $entry,  $state{$entry};
+    }
+
+    &save_state;
+    &goodbye;
+}
+
+##############
+sub update_state {
+    
+    my ($entry) = $_[0];
+    
+    if ($entry eq "camera")    { &camera_state    ($entry); }
+    if ($entry eq "imstats")   { &imstats_state   ($entry); }
+    if ($entry eq "mkdetrend") { &detrend_state   ($entry); }
+    if ($entry eq "mkfringe")  { &detrend_state   ($entry); }
+    if ($entry eq "ptolemy")   { &ptolemy_state   ($entry); }
+    if ($entry eq "standards") { &standards_state ($entry); }
+    if ($entry eq "validate")  { &validate_state  ($entry); }
+}
+
+##############
+sub ptolemy_state {
+    
+    my ($entry) = "ptolemy";
+    $current = $state{$entry};
+    if (! $current) { &escape ("error: ptolemy state not set?"); }
+    
+    $fifos  = `gconfig FIFOS`; chop $fifos;
+    $ptlist = "$datdir/$runid/$runid.ptlist";
+    $ptlog  = "$datdir/$runid/$runid.log";
+    
+    # if we can, run 'elixir complete'
+    if (($current eq "init") && ($state{"mkdetrend"} eq "done")) {
+	$state{$entry} = "running";
+	&save_state;
+
+	if (-e "$fifos/complete.pid") { 
+	    print STDERR "elixir (sex)complete already running? check pid file $fifos/complete.pid"; 
+	    &save_escape ($entry, "failed to start ptolemy"); 
+	}
+
+	if (! -d "$datdir/$runid") { mkdir ("$datdir/$runid", 0777); }
+	($tmp, $start, $stop) = split (" ", `mkrun run $runid`);
+	if ($?) { &save_escape ($entry, "error in RUNID $runid"); }
+	vsystem ("imsearch -type object -trange $start $stop -pt > $ptlist");
+	if ($?) { &save_escape ($entry, "error extracting images from db"); }
+ 	vsystem ("elixir -D mode sexcomplete $ptlist >& $ptlog &");
+
+	# wait for up to 10 seconds for $fifos/complete.pid to exist 
+	for ($Nwait = 0; ($Nwait < 30) && (! -e "$fifos/complete.pid"); $Nwait ++) { sleep 2; }
+
+
+	if (! -e "$fifos/complete.pid") { &save_escape ($entry, "failed to start elixir (sex)complete"); }
+    }
+
+    # has 'elixir complete' finished? successfully?
+    if ($current eq "running") {
+	if (-e "$fifos/complete.end") {
+	    $answer = `wc -l $fifos/complete.success`;
+	    ($Nsuccess) = split (" ", $answer);
+	    $answer = `wc -l $fifos/complete.failure`;
+	    ($Nfailure) = split (" ", $answer);
+	    $answer = `wc -l $ptlist`;
+	    ($Ntotal) = split (" ", $answer);
+
+	    $state{$entry} = "fail";
+	    if ($Nsuccess > 0.8*$Ntotal) { 
+		$state{$entry} = "done"; 
+	    } else {
+		print STDERR "too many failures: $Nsuccess of $Ntotal\n";
+	    }
+	    if ($Nsuccess + $Nfailure > $Ntotal) { 
+		print STDERR "output list is inconsistent\n";
+		$state{$entry} = "fail"; 
+	    }
+	}
+	if ((! -e "$fifos/complete.end") && (! -e "$fifos/complete.pid")) {
+	    print STDERR "elixir complete killed?\n";
+	    $state{$entry} = "fail"; 
+	}
+    }
+}
+
+##############
+sub standards_state {
+
+    my ($entry) = "standards";
+    $current = $state{$entry};
+
+    print "entry: $entry\n";
+    print "current: $current\n";
+
+    if (! $current) { &escape ("error: standards state not set?"); }
+
+    # if elixir complete is done, add standards, run photometry routines
+    if (($current eq "init") && ($state{"ptolemy"} eq "done")) {
+	$state{$entry} = "running";
+	&save_state;
+
+	$refs = `gconfig REFSDIR`; chop $refs;
+	$stds = "$refs/standards";
+    
+	# insert standards in photometry database
+	foreach $filter (@filter) {
+	    @words = split (" ", `filtnames $filter -cal`);
+	    if ($words[1] == 0) { next; }
+	    $photref = $words[2];
+	    vsystem ("addstar -replace -v -ref $stds/$photref.dat -p $photref");
+	}
+
+	# cd to $rundir so photreport plots land there?
+	chdir $rundir;
+
+	# run elixir.photreport to generate plots (eg 02Ak03.B.time.png) and phot.reg files
+	vsystem ("elixir.photreport $runid $catdir");
+	if ($?) { goto standards_fail; }
+
+	# load lines from phot.reg files and execute:
+	@reglist = ();
+	foreach $filter (@filter) {
+	    $regfile = "$runid.$filter.phot.reg";
+	    open (FILE, $regfile);
+	    @list = <FILE>;
+	    close (FILE);
+	    @reglist = (@reglist, @list);
+	}
+	foreach $line (@reglist) {
+	    vsystem ($line);
+	}
+
+	# get date range for this run
+	$answer = `mkrun run $runid`;
+	($tmp, $start, $stop) = split (" ", $answer);
+	if ($start eq "") { &escape ("error with date range: $line"); }
+	if ($stop eq "") { &escape ("error with date range: $line"); }
+
+	# create transparency list, execute
+	vsystem ("mktrans $start $stop > $runid.trans.reg");
+	open (FILE, "$runid.trans.reg");
+	@list = <FILE>;
+	close (FILE);
+	foreach $line (@list) {
+	    vsystem ($line);
+	}
+
+	# create transparency report, execute
+	vsystem ("mktreport $start $stop > $runid.trans.txt");
+
+	$state{$entry} = "done";
+	&save_state;
+    }
+    return;
+
+  standards_fail:
+    $state{$entry} = "fail";
+    return;
+}
+
+##############
+sub camera_state {
+
+    # camera : 'pending' (date < start) 
+    # camera : 'on' (date in range start - stop) 
+    # camera : 'off' (date > stop) 
+
+    # transition on -> off : trigger message about mkdetrend 
+    
+    # get date range for this run
+    $answer = `mkrun run $runid`;
+    ($tmp, $start, $stop) = split (" ", $answer);
+    if ($start eq "") { &escape ("error with date range: $line"); }
+    if ($stop eq "") { &escape ("error with date range: $line"); }
+    $mjd_start = &date_to_mjd ($start);
+    $mjd_stop  = &date_to_mjd ($stop);
+    
+    # get current value of mjd
+    ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = gmtime ();
+    $year += 1900;
+    $mon += 1;
+    $mjd_now = &get_mjd ($year, $mon, $mday);
+
+    # check appropriate state
+    $state = "on";
+    if ($mjd_now < $mjd_start) { $state = "pending"; }
+    if ($mjd_now > $mjd_stop)  { $state = "off"; }
+
+    # if we are at end of run, check that mkdetrend has been started
+    if (($state{"camera"} eq "on") && ($state eq "off")) {
+	if ($state{"mkdetrend"} eq "init") {
+	    &notify ("start mkdetrend");
+	}
+    }
+    $state{"camera"} = $state;
+}
+	       
+##############
+sub notify {
+    print STDERR "$_[0]\n";
+}
+
+##############
+sub validate_state {
+
+    my ($entry) = "validate";
+    $current = $state{$entry};
+    if (! $current) { &escape ("error: validate state not set?"); }
+
+    chdir $rundir;
+
+    # if elixir complete is done, add standards, run photometry routines
+    if (($current eq "init") && ($state{"standards"} eq "done")) {
+	$state{$entry} = "running";
+	&save_state;
+	
+	# find the first unused val file (run.val.N)
+	$ver = 1;
+	$outfile = "$rundir/$runid.val.$ver";
+	while (-e $outfile) {
+	    $ver ++;
+	    $outfile = "$rundir/$runid.val.$ver";
+	}
+
+	# run first pass
+	vsystem ("validate $runid > $outfile");
+	if ($?) { goto validate_fail; }
+
+	# check output results
+	print STDERR "validate $runid -stats -infile $outfile\n";
+	@result = `validate $runid -stats -infile $outfile`;
+	if ($?) { goto validate_fail; }
+	
+	system ("validate $runid -infile $outfile -update");
+
+	# order should be: run, valid, invalid, subvalid, dataerr
+	($value, $Nvalid) = split (" ", $result[1]);
+	if ($value ne "valid") { goto validate_fail; }
+	($value, $Ninvalid) = split (" ", $result[2]);
+	if ($value ne "invalid") { goto validate_fail; }
+	($value, $Nsubvalid) = split (" ", $result[3]);
+	if ($value ne "subvalid") { goto validate_fail; }
+	($value, $Ndataerr) = split (" ", $result[4]);
+	if ($value ne "dataerr") { goto validate_fail; }
+	
+	if ($invalid > 0) { goto validate_fail; }
+	if ($dataerr > 0) { goto validate_fail; }
+
+	# if we pass validation, run validate -update:
+
+	$state{$entry} = "done";
+    }
+
+    if ($current eq "fail") {
+
+	# recheck the last validation file (run.val.N)
+	$outfile = "";
+	$ver = 1;
+	$try = "$rundir/$runid.val.$ver";
+	while (-e $try) {
+	    $outfile = $try;
+	    $ver ++;
+	    $try = "$rundir/$runid.val.$ver";
+	}
+	if ($outfile eq "") { goto validate_fail; }
+
+	# check output results
+	print STDERR "validate $runid -stats -infile $outfile\n";
+	@result = `validate $runid -stats -infile $outfile`;
+	if ($?) { goto validate_fail; }
+	
+	system ("validate $runid -infile $outfile -update");
+
+	# order should be: run, valid, invalid, subvalid, dataerr
+	$Nvalid = $Ninvalid = $Nsubvalid = $Ndataerr = -1;
+	foreach $line (@result) {
+	    ($value, $Nvalue) = split (" ", $line);
+	    if ($value eq "valid")    { $Nvalid    = $Nvalue; }
+	    if ($value eq "invalid")  { $Ninvalid  = $Nvalue; }
+	    if ($value eq "subvalid") { $Nsubvalid = $Nvalue; }
+	    if ($value eq "dataerr")  { $Ndataerr  = $Nvalue; }
+	}
+	if ($Nvalid == -1)                        { goto validate_fail; }
+	if ($Nsubvalid == -1)                     { goto validate_fail; }
+	if (($Ninvalid == -1) || ($Ninvalid > 0)) { goto validate_fail; }
+	if (($Ndataerr == -1) || ($Ndataerr > 0)) { goto validate_fail; }
+
+	# if we pass validation, run validate -update:
+	$state{$entry} = "done";
+    }
+    return ;
+
+  validate_fail:
+    $state{$entry} = "fail";
+    return;
+}
+
+##############
+sub imstats_state {
+
+    my ($entry) = "imstats";
+    $current = $state{$entry};
+    if (! $current) { &escape ("error: imstats state not set?"); }
+    
+    $fifos  = `gconfig FIFOS`; chop $fifos;
+    $pid    = "$fifos/imstats.pid";
+    $end    = "$fifos/imstats.pid";
+    $ptlist = "$datdir/$runid/$runid.redo.list";
+    $ptlog  = "$datdir/$runid/$runid.redo.log";
+
+    # if we can, run 'elixir complete'
+    if (($current eq "init") && ($state{"camera"} eq "off")) {
+	$state{$entry} = "running";
+	&save_state;
+	
+	# check for currently running imstats
+	if (-e $pid) { 
+	    print STDERR "elixir imstats still running?\n"; 
+	    print STDERR "run 'elixir -C $camera -D mode imstats -kill' to stop\n";
+	    &save_escape ($entry, "failure on imstats");
+	}
+
+	# extract redo list, run processing
+	($tmp, $start, $stop) = split (" ", `mkrun run $runid`);
+	if ($?) { &save_escape ($entry, "error in RUNID $runid"); }
+	vsystem ("imsearch -trange $start $stop -proc f -pt > $ptlist");
+	if ($?) { &save_escape ($entry, "error extracting unprocessed data"); }
+	vsystem ("elixir -D mode imstats $ptlist >& $ptlog &");
+	
+	# wait for up to 10 seconds for $pid to exist 
+	for ($Nwait = 0; ($Nwait < 30) && (! -e "$pid"); $Nwait ++) { sleep 2; }
+	if (! -e "$pid") { &save_escape ($entry, "failed to start elixir imstats"); }
+    }
+
+    # has 'elixir complete' finished? successfully?
+    if ($current eq "running") {
+	if (-e "$fifos/imstats.end") {
+	    $answer = `wc -l $fifos/imstats.success`;
+	    ($Nsuccess) = split (" ", $answer);
+	    $answer = `wc -l $fifos/imstats.failure`;
+	    ($Nfailure) = split (" ", $answer);
+	    $answer = `wc -l $ptlist`;
+	    ($Ntotal) = split (" ", $answer);
+
+	    print "Ntotal: $Ntotal\n";
+	    print "Nsuccess: $Nsuccess\n";
+	    print "Nfailure: $Nfailure\n";
+
+	    if ($Nsuccess < 0.5*$Ntotal) { &save_escape ($entry, "too many failures: $Nsuccess of $Ntotal"); }
+	    if ($Nsuccess + $Nfailure > $Ntotal) { &save_escape ($entry, "output list is inconsistent"); }
+	    $state{$entry} = "done"; 
+	    &save_state;
+	    return;
+	}
+	if ((! -e "$fifos/imstats.end") && (! -e "$fifos/imstats.pid")) { &save_escape ($entry, "elixir complete killed?"); }
+    }
+}
+
+##############
+sub detrend_state {
+
+    # force sequencing (mkdetrend -> mkfringe):
+    if (($entry eq "mkfringe") && ($state{"mkdetrend"} ne "done")) {
+	$state{$entry} = "init";
+	return;
+    }
+
+    # mkdetrend & mkfringe determine run from their own references, 
+    # which can be overridden with the '-run RUNID' flag
+
+    # determine state from mkdetrend / mkfringe response
+    $entry = $_[0];
+    print STDERR "$entry state\n";
+    @list = `$entry state`;
+    print STDERR "@list\n";
+
+    # skip first 4 lines
+    shift @list; shift @list; shift @list; shift @list; shift @list;
+
+    $Ninit = $Nfail = $Ndone = $Nrun = $Nmiss = 0;
+    foreach $line (@list) {
+	# interesting values for state: 
+	# init, not.available, running.xxx, done, fail.xxx
+	@words = split (" ", $line);
+	if ($words[7] eq "not.available") { $Nmiss ++; }
+	if ($words[7] eq "init")          { $Ninit ++; }
+	if ($words[7] eq "done")          { $Ndone ++; }
+	if ($words[7] eq "clean")         { $Ndone ++; }
+	if ($words[7] =~ /^fail./)        { $Nfail ++; }
+	if ($words[7] =~ /^running./)     { $Nrun ++; }
+    }
+
+    $state = "running";
+    if ($Ninit > 0) { $state = "init"; }
+    if ($Nfail > 0) { $state = "fail"; }
+    if ($Nrun  > 0) { $state = "running"; }
+    if ($Ndone + $Nmiss == @list) { $state = "done"; }
+
+    # check for mkdetrend transition -> "done"
+    if (($entry eq "mkdetrend") && ($state{$entry} ne "done") && ($state eq "done")) {
+	&notify ("start mkfringe");
+    }
+
+    $state{$entry} = $state;
+}
+
+#######################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    unlink $tmpenv;
+    if ($_[0]) {
+	print STDERR "@_\n";
+    }
+    exit 0;
+}
+
+sub escape { 
+    unlink $tmpenv;
+    print "$_[0]\n";
+    exit 1;
+}
+
+sub save_escape {
+    my ($entry) = $_[0];
+    my ($message) = $_[1];
+    $state{$entry} = "fail";
+    &save_state;
+    &escape ($message);
+}
+
+sub elixir_config {
+    my (@arg) = @_;
+    my ($opt, $config, @tmparg, $status);
+    $config = "";
+    if ($ENV{'PTOLEMY'}) { $config = "-c $ENV{'PTOLEMY'}"; }
+
+    # default values, override on command line
+    $runid  = `gconfig RUNID.POSTRUN`;  chop $runid;
+    $camera = `gconfig CAMERA.POSTRUN`; chop $camera;
+
+    # extract command line options
+    @tmparg = ();
+    while (@arg > 0) {
+	
+	# grab elixir/ptolemy config option -c 
+	if ($arg[0] eq "-c") {
+	    shift @arg;
+	    $config = "-c $arg[0]";
+	    shift @arg;
+	    next;
+	}
+	
+	# grab elixir/ptolemy config option -C 
+	if ($arg[0] eq "-C") {
+	    @opt = (@opt, $arg[0]);
+	    shift @arg;
+	    @opt = (@opt, $arg[0]);
+	    $elconf = $arg[0];
+	    shift @arg;
+	    next;
+	}
+	
+	# grab elixir/ptolemy config option -D
+	if ($arg[0] eq "-D") {
+	    @opt = (@opt, $arg[0]);
+	    shift @arg;
+	    @opt = (@opt, $arg[0]);
+	    shift @arg;
+	    @opt = (@opt, $arg[0]);
+	    shift @arg;
+	    next;
+	}
+	
+	# by default, $run is loaded from state.data file
+	if ($arg[0] eq "-run") {
+	    shift @arg;
+	    $runid = $arg[0];
+	    shift @arg;
+	    next;
+	}
+	
+	# by default, $camera is loaded from state.data file
+	if ($arg[0] eq "-camera") {
+	    shift @arg;
+	    $camera = $arg[0];
+	    shift @arg;
+	    next;
+	}
+	@tmparg = (@tmparg, $arg[0]);
+	shift @arg;
+    }
+
+    # create temporary ptolemy.rc file:
+    $catdir = `gconfig DB_STDS -D RUNID $runid -D CAMERA $camera`; chop $catdir;
+    @opt = (@opt, "-D CATDIR $catdir");
+    @opt = (@opt, "-D RUNID $runid");
+    @opt = (@opt, "-D CAMERA $camera");
+    @opt = (@opt, "-D RUNID.MKDETREND $runid");
+    @opt = (@opt, "-D CAMERA.MKDETREND $camera");
+    @opt = (@opt, "-D RUNID.MKFRINGE $runid");
+    @opt = (@opt, "-D CAMERA.MKFRINGE $camera");
+
+    $config = join (" ", $config, @opt);
+    $tmpenv = `mktemp /tmp/elixir.XXXXXX`; chop ($tmpenv);
+    $status = system ("gconfig -raw $config > $tmpenv");
+    if ($status) { &escape ("error in elixir configuration: gconfig fails"); }
+
+    $ENV{'PTOLEMY'} = "$tmpenv";
+
+    # global variables
+    # add this from the filter configuration system, eventually
+    @filter = split (" ", `filtnames list`);
+
+    @def_state = ("camera",    "off",
+		  "imstats",   "init",
+		  "mkdetrend", "init",
+		  "mkfringe",  "init", 
+		  "ptolemy",   "init", 
+		  "standards", "init", 
+		  "validate",  "init");
+    %def_state = @def_state;
+
+    # generate list of keys
+    @entry = ();
+    foreach $name (@def_state) {
+	push @entry, $name;
+	shift @def_state;
+    }
+
+    # global configuration variables
+    $datdir = `gconfig DATDIR`;  chop $datdir;
+    $rundir = "$datdir/$runid";
+    $dbfile = "$rundir/postrun.db";
+
+    if (! -d $rundir) { mkdir ($rundir, 0777); }
+
+    return (@tmparg);
+}
+
+sub set_globals {
+}    
+
+sub date_to_mjd {
+    my ($date) = $_[0];
+    my ($year, $month, $day, $mjd);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $mjd = get_mjd ($year, $month, $day);
+
+    return ($mjd);
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
+sub usage {
+    
+    print STDERR "elixir.postrun (mode)\n";
+    print STDERR "  state  - show current states\n";
+    print STDERR "  update - update system states\n";
+    print STDERR "  set (entry) (value) - manually set a state\n";
+    &goodbye;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.reload
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.reload	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.reload	(revision 16632)
@@ -0,0 +1,57 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 1) { die "USAGE: elixir.reload (elixir)\n"; }
+
+$elixir = $ARGV[0];
+
+# if an elixir is not running, start it, send output to $logdir/$elixir.log
+$logdir = `gconfig LOGDIR`; chop $logdir;
+if ($?) { die "error getting LOGDIR from configuration system\n"; }
+chdir $logdir;
+
+$pidfile = `gconfig -D mode $elixir global.pid`; chop ($pidfile);
+if ($?) { die "error getting PID from configuration system - is elixir $elixir defined?\n"; }
+
+# check that elixir is running
+if (! -f $pidfile) { &launch ($elixir, $logdir); }
+
+# load pid information
+open (FILE, "$pidfile");
+@list = <FILE>;
+close (FILE);
+
+($name, $pid)     = split (" ", $list[0]);
+($name, $user)    = split (" ", $list[1]);
+($name, $machine) = split (" ", $list[2]);
+
+# check that this process exists?
+@list = `rsh $machine /bin/ps -A -o pid,cmd`;
+$dead = 1;
+foreach $line (@list) {
+    ($rpid, $cmd) = split (" ", $line);
+    if (($rpid == $pid) && ($cmd =~ /elixir/)) {
+	$dead = 0;
+	print STDERR "elixir $elixir is running as $pid on $machine\n";
+	last;
+    }
+}
+if ($dead) { 
+    unlink ($pidfile);
+    &launch ($elixir, $logdir); 
+}
+
+# send USR1 signal to process:
+print STDERR "restarting process $pid\n";
+system ("rsh $machine kill -USR1 $pid");
+exit 0;
+
+sub launch {
+
+    my ($elixir) = $_[0];
+    my ($logdir) = $_[1];
+
+    # if elixir is not running, start it
+    print STDERR "starting elixir $elixir\n"; 
+    system ("elixir -D mode $elixir >& $logdir/$elixir.log &");
+    exit 0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.rerun
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.rerun	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/elixir.rerun	(revision 16632)
@@ -0,0 +1,152 @@
+#!/usr/bin/env perl
+
+# case 1: run on a list of MEF images:
+# case 2: run on a list from ptolemy.failure / ptolemy.success
+
+$complete = 0;
+$stds = 0;
+$demo = 0;
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-C") {
+        $config = "$config -C $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-c") {
+        $config = "$config -c $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-D") {
+        $config = "$config -D $ARGV[1] $ARGV[2]";
+        shift; shift; shift; next;
+    }
+    if ($ARGV[0] eq "-stds") {
+	$stds = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-demo") {
+	$demo = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-complete") {
+	$complete = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-h") {
+	print "USAGE: elixir.rerun (list) (mode) [elixir options]\n";
+	print "  options: \n";
+	print "  -C config (set value of CONFIG variable)\n";
+	print "  -c config.file (specify alternate to config file)\n";
+	print "  -D key value (set value of key)\n";
+	print "  -stds (send output to STDS directory)\n";
+	print "  -complete (use sexcomplete not sextract)\n";
+	print "  -demo (show input list and command)\n";
+	exit 1;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+if (@ARGV != 2) { die "USAGE: elixir.rerun (list) (mode) [elixir options]\n"; }
+
+if ($stds) {
+    $catdir = `gconfig $config DB_STDS`; chop $catdir;
+    if ($?) { die "config error with CATDIR\n" }
+} else {
+    $catdir = `gconfig $config CATDIR`; chop $catdir;
+    if ($?) { die "config error with CATDIR\n" }
+}
+
+$tmpdir = `gconfig $config TMPDIR`; chop $tmpdir;
+if ($?) { die "config error with TMPDIR\n" }
+
+$input  = $ARGV[0];
+$mode   = $ARGV[1];
+
+# check on mode:
+if ($mode eq "fifo") { &getfifo; }
+if ($mode eq "mef")  { &getmef;  }
+
+die "ERROR: unknown mode $mode\n";
+
+sub getfifo {
+
+    $temp = `mktemp elixir.XXXXXX`; chop $temp;
+    $templog = `mktemp elixir-log.XXXXXX`; chop $templog;
+
+    open (FILE, "$input");
+    @list = <FILE>;
+    close (FILE);
+
+    # write input list in correct format to $temp
+    open (FILE, ">$temp");
+    foreach $line (@list) {
+	($raw, $root, $ccd, $inmode) = split (" ", $line);
+	print FILE "$raw $root $ccd $inmode\n";
+    }
+    &runelixir;
+}
+
+sub getmef {
+
+    $temp = `mktemp elixir.XXXXXX`; chop $temp;
+    $templog = `mktemp elixir-log.XXXXXX`; chop $templog;
+
+    @ccds = split (" ", `cameraconfig -ccds`);
+    if ($?) { die "error in cameraconfig -ccds\n"; }
+
+    @ccdn = split (" ", `cameraconfig -ccdn`);
+    if ($?) { die "error in cameraconfig -ccdn\n"; }
+
+    $Nccd = `cameraconfig -Nccd`; chop $Nccd;
+    if ($?) { die "error in cameraconfig -Nccd\n"; }
+
+    open (FILE, "$input");
+    @list = <FILE>;
+    close (FILE);
+
+    # write input list in correct format to $temp
+    open (FILE, ">$temp");
+    foreach $line (@list) {
+	($file) = split (" ", $line);
+	if ($line =~ m|^\s*$|) { next; } # skip blank lines
+	if ($line =~ m|^\s*\#|) { next; } # skip commented lines
+	
+	# must be absolute path for elixir to work anyway
+	@words = split ("/", $file);
+	$root = $words[-1];
+	$root =~ s/.fits$//;
+	for ($i = 0; $i < $Nccd; $i++) {
+	    printf FILE "$file %s/%s%02d %s MEF\n", $root, $root, $ccdn[$i], $ccds[$i];
+	}
+    }
+    &runelixir; 
+}
+
+sub runelixir {
+    
+    if ($demo) {  
+	if ($complete) {
+	    print "elixir -D mode sexcomplete -D CATDIR $catdir -D TMPDIR $tmpdir $temp >& $templog\n";
+	} else {
+	    print "elixir -D mode sextract -D CATDIR $catdir -D TMPDIR $tmpdir $temp >& $templog\n";
+	}
+	printf "list is in $temp\n";
+	exit 0;
+    }
+
+    # launch elixir for input list
+    if ($complete) {
+	vsystem ("elixir -D mode sexcomplete -D CATDIR $catdir -D TMPDIR $tmpdir $temp >& $templog &");
+    } else {
+	vsystem ("elixir -D mode sextract -D CATDIR $catdir -D TMPDIR $tmpdir $temp >& $templog &");
+    }
+    exit 0;
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fixcoords2
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fixcoords2	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fixcoords2	(revision 16632)
@@ -0,0 +1,77 @@
+#!/usr/bin/env perl
+
+# USAGE: fixcoords (input) (output) (ref) (chip)
+use Math::Trig;
+# $DEG_RAD = 57.298688;
+# $RAD_DEG = 0.017452406;
+$DEG_RAD = 57.29577951;
+$RAD_DEG = 0.017453292;
+
+if (@ARGV != 4) { die "USAGE: fixcoords (input) (output) (ref) (chip)\n"; }
+
+$input  = $ARGV[0];
+$output = $ARGV[1];
+$ref    = $ARGV[2];
+$chip   = $ARGV[3];
+
+if (! -f $input) { die "file $input not found\n"; }
+
+# load astrometric terms from header of reference:
+
+$answer = `echo $ref | fields CRPIX1 CRPIX2 CRVAL1 CRVAL2 NASTRO`;
+($file, $crpix1, $crpix2, $crval1, $crval2, $Nastro) = split (" ", $answer);
+if ($Nastro == 0) { die "no astrometry solution in header\n"; }
+
+$answer = `echo $ref | fields PC001001 PC001002 PC002001 PC002002 CDELT1 CDELT2`;
+($file, $pc11, $pc12, $pc21, $pc22, $cd1, $cd2) = split (" ", $answer);
+
+open (FILE, "$input");
+open (OUT, ">$output");
+
+# copy header lines:
+for ($i = 0; $i < 16; $i++)  { $line = <FILE>; print OUT "$line"; }
+
+while ($line = <FILE>) {
+
+    @words = split (" ", $line);
+    xy2rd ($words[12], $words[13]);
+
+    if ($words[17] eq $chip) {
+	printf OUT "%4d %7.4f %7.4f %8.4f  %9.1f %6.3f %5.2f %2d  %9.1f %6.3f %5.2f %2d  %8.3f %8.3f  %15.11f %11.8f  %1s %2s\n",
+	    $words[0], $words[1], $words[2], $words[3], 
+	    $words[4], $words[5], $words[6], $words[7], 
+	    $words[8], $words[9], $words[10], $words[11], 
+	    $words[12], $words[13], $ra, $dec,
+	    $words[16], $words[17];
+    }
+}
+
+close (OUT);
+close (FILE);
+
+sub xy2rd {
+ $x = $_[0];
+ $y = $_[1];
+
+ $X = $cd1*($x - $crpix1);
+ $Y = $cd2*($y - $crpix2);
+
+ $L = $X*$pc11 + $Y*$pc12;
+ $M = $X*$pc21 + $Y*$pc22;
+
+ $chi = $RAD_DEG*$L;
+ $eta = $RAD_DEG*$M;
+
+ $sdp = sin ($RAD_DEG*$crval2);
+ $cdp = cos ($RAD_DEG*$crval2);
+
+ $talp = $chi / ($cdp - $eta*$sdp);
+ $alpha = atan ($talp);
+ $calp = cos ($alpha);
+ $tdel = $calp*($sdp + $eta*$cdp) / ($cdp - $eta*$sdp);
+ $delta = atan ($tdel);
+    
+ $ra  = $DEG_RAD*$alpha + $crval1;
+ $dec = $DEG_RAD*$delta;
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fixscat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fixscat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fixscat	(revision 16632)
@@ -0,0 +1,75 @@
+#!/usr/bin/env perl
+
+# warning: this function currently uses a fixed temporary name 'fix.NN.fits' 
+# for the intermediate product.  If we add this to elixir, convert to mktemp
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 3) { &usage (); }
+
+# assign the command line arguments
+$inlist   = $ARGV[0];
+$version  = $ARGV[1];
+$ID       = $ARGV[2];
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/scatter.pro";
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "applyscat $inlist $version $ID\n";
+print MANA "exit 1\n";
+close (MANA);
+print STDERR "exit statue: $?\n";
+if ($? == 2 * 256) { 
+    print STDERR "no scattered light term available\n"; 
+    exit 2;
+}
+if ($?) { die "ERROR problem with fixscat\n"; }
+
+print STDOUT "SUCCESS: finished with fixscat\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fixscat (inlist) (version) (ID)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
+
+# there are two possible flat-field photometric corrections: additive
+# and multiplicative:  
+# The correction images constructed by examining
+# the *difference* between dome-flats with and without the petals
+# covered is additive:  FLAT_new = (FLAT_old - SCAT) * A
+# (A is set to maintain the original normalization of chip 04)
+# 
+# The correction images constructed by examining stellar magnitude
+# difference is multiplicative: FLAT_new = (FLAT_old * SCAT) * A
+# (A is set to maintain the original normalization of chip 04)
+
+# there is a different scattered light image for each filter.
+# (these images are the same file for the additive version)
+
+# there should be no arbitrary normalization in the scattered frames
+# in the database. (we used to multiply the scattered light image by a
+# value of 10.0).  
+
+# images of the first class will be identified with the label scatter-A.0
+# images of the second class will be identified with the label scatter-B.0
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fixscat.mef
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fixscat.mef	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fixscat.mef	(revision 16632)
@@ -0,0 +1,75 @@
+#!/usr/bin/env perl
+
+# warning: this function currently uses a fixed temporary name 'fix.NN.fits' 
+# for the intermediate product.  If we add this to elixir, convert to mktemp
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 3) { &usage (); }
+
+# assign the command line arguments
+$inlist   = $ARGV[0];
+$version  = $ARGV[1];
+$ID       = $ARGV[2];
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/scatter.pro";
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "applyscat-mef $inlist $version $ID\n";
+print MANA "exit 1\n";
+close (MANA);
+print STDERR "exit statue: $?\n";
+if ($? == 2 * 256) { 
+    print STDERR "no scattered light term available\n"; 
+    exit 2;
+}
+if ($?) { die "ERROR problem with fixscat\n"; }
+
+print STDOUT "SUCCESS: finished with fixscat\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fixscat (inlist) (version) (ID)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
+
+# there are two possible flat-field photometric corrections: additive
+# and multiplicative:  
+# The correction images constructed by examining
+# the *difference* between dome-flats with and without the petals
+# covered is additive:  FLAT_new = (FLAT_old - SCAT) * A
+# (A is set to maintain the original normalization of chip 04)
+# 
+# The correction images constructed by examining stellar magnitude
+# difference is multiplicative: FLAT_new = (FLAT_old * SCAT) * A
+# (A is set to maintain the original normalization of chip 04)
+
+# there is a different scattered light image for each filter.
+# (these images are the same file for the additive version)
+
+# there should be no arbitrary normalization in the scattered frames
+# in the database. (we used to multiply the scattered light image by a
+# value of 10.0).  
+
+# images of the first class will be identified with the label scatter-A.0
+# images of the second class will be identified with the label scatter-B.0
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/flatten.flips
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/flatten.flips	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/flatten.flips	(revision 16632)
@@ -0,0 +1,276 @@
+#!/usr/bin/env perl
+
+### darks are currently disabled (look for dark detsearch and darkfactor)
+
+# grab the command line options
+$defringe = 0;
+$use_mask = 1;
+$fast = 0;
+$quiet = 0;
+$close = "";
+$config = "";
+$preserve = 0;
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-C") {
+        $config = "$config -C $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-c") {
+        $config = "$config -c $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-D") {
+        $config = "$config -D $ARGV[1] $ARGV[2]";
+        shift; shift; shift; next;
+    }
+    if ($ARGV[0] eq "-preserve") {
+        $preserve = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-fast") {
+        $fast = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-quiet") {
+	$quiet = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-close") {
+	$close = "-close";
+        shift; next;
+    }
+    if ($ARGV[0] eq "-defringe") {
+	$defringe = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-nomask") {
+	$use_mask = 0;
+        shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 4) { &usage; }
+
+# command line arguments
+$input  = $ARGV[0];
+$output = $ARGV[1];
+$ccd    = $ARGV[2];
+$mode   = uppercase ($ARGV[3]);
+
+$chipname = "-chipname";
+$infile = $input;
+if ($mode eq "MEF") { $infile = "$input\[$ccd]"; }
+if ($ccd eq "phu") {
+    $infile = "$input"; 
+    $ccd = "ccd00";
+    $chipname = "";
+}
+
+# remove old file if it exists
+if (-e $output) { unlink "$output"; }
+ckpathname ($output);
+
+# find the appropriate detrend images (need to fix output name for MEF - option?)
+$flat=`detsearch $config $chipname -quiet -image $input $ccd $mode -type flat $close`; chop ($flat);
+if ($?) { die "ERROR: can't get flat for image\n"; }
+
+if (!$fast) {
+    $bias=`detsearch $config $chipname -quiet -image $input $ccd $mode -type bias $close`; chop ($bias);
+    if ($?) { die "ERROR: can't get bias for image\n"; }
+
+#    $dark=`detsearch $config $chipname -quiet -image $input $ccd $mode -type dark $close`; chop ($dark);
+#    if ($?) { die "ERROR: can't get dark for image\n"; }
+}
+
+# find the appropriate mask image
+$mask = "none";
+if ($use_mask) {
+    $mask=`detsearch $config $chipname -quiet -image $input $ccd $mode -type mask $close`; chop ($mask);
+    if ($?) { die "ERROR: can't get mask for image\n"; }
+}
+
+# abstracted keywords
+$ccdkeyword  = `gconfig $config CCDNUM-KEYWORD`;    chop ($ccdkeyword);
+$darkword    = `gconfig $config DARKTIME-FUNCTION`; chop ($darkword);
+$exptimeword = `gconfig $config EXPTIME-KEYWORD`;   chop ($exptimeword);
+
+# find the appropriate fringe frame & coords file
+$fringe = "none";
+$frpts  = "none";
+if ($defringe) {
+
+    $filterword  = `gconfig $config FILTER-KEYWORD`;    chop ($filterword);
+
+    # check the FILTER and EXPTIME, include fringe correction?:
+    ($junk, $exptime, $filter) = `echo $input | fields $exptimeword $filterword`;
+    $filter = uppercase ($filter);
+
+    # recipe file defines detrend types & cutoff exptime values
+    $recipefile = `gconfig $config DETREND_RECIPES`; chop $recipefile;
+    ($detypes, $cutoffs) = split (" ", `gconfig -c $recipefile $filter`);
+    if ($?) { die "ERROR: failure to get detrend recipes\n"; }
+    @detypes = split (",", $detypes);
+    @cutoffs = split (",", $cutoffs);
+    
+    # check for DEFRINGE, DEMODE 
+    $defringe = 0;
+    for ($i = 0; $i < @detypes; $i++) {
+	if ($detypes[$i] eq "fringe") {
+	    if ($exptime >= $cutoffs[$i]) { $defringe = 1; }
+	    last;
+	}
+    }
+}
+
+if (! $fast && 0) {
+    # determine scale factor for dark image (use MEF rootname if EXTNAME is given)
+    $darkfile = $dark;
+    $darkfile =~ s|\[.*\]||;
+    ($junk, $t1) = split (" ", `echo $input    | fields $exptimeword`);
+    ($name, $t2) = split (" ", `echo $darkfile | fields $exptimeword`);
+    $darkfactor = `darktime.$darkword $t1 $t2`; chop ($darkfactor);
+    if ($?) { die "ERROR: failure to get darkfactor $t1 $t2\n"; }
+}
+
+# load FLIPS parameter file, fill in missing words:
+$paramfile = `gconfig $config FLIPS_PARAM_IMRED`; chop $paramfile;
+if ($?) { die "ERROR: missing FLIPS_PARAM_IMRED in config\n"; }
+open (FILE, "$paramfile");
+@params = <FILE>;
+close (FILE);
+
+foreach $line (@params) {
+    # input / output file names
+    $line =~ s|INFILE|$infile|;
+    $line =~ s|OUTFILE|$output|;
+    $line =~ s|COMMENT|Elixir / Flips2 flatten.flips|;
+
+    # overscan correction
+    $line =~ s|DOOVER|1|;
+
+    if ($fast) {
+	$line =~ s|DOBIAS|0|;
+	$line =~ s|DODARK|0|;
+    } else {
+	# bias corrections
+	$line =~ s|DOBIAS|1|;
+	$line =~ s|BIASNAME|$bias|;
+
+	# dark corrections - avoid for now
+	$line =~ s|DODARK|0|;
+#	$line =~ s|DODARK|1|;
+#	$line =~ s|DARK_FACT|$darkfactor|;
+#	$line =~ s|DARKNAME|$dark|;
+    }
+
+    # flat corrections
+    $line =~ s|DOFLAT|1|;
+    $line =~ s|FLATNAME|$flat|;
+
+    # mask corrections
+    if ($mask eq "none") {
+	$line =~ s|DOMASK|0|;
+    } else {
+	$line =~ s|DOMASK|1|;
+	$line =~ s|MASKNAME|$mask|;
+    }
+
+    # header blocks - we need an extra block for elixir keywords
+    $line =~ s|DOHEADER|1|;
+    $line =~ s|NBLOCKS|2|;
+}
+
+$temp = `mktemp /tmp/flatten.XXXXXX`; chop $temp;
+open (FILE, ">$temp");
+foreach $line (@params) {
+    print FILE "$line";
+}
+close (FILE);
+
+system ("imred $temp");
+$stat = $?;
+
+if ($preserve) { 
+    print STDERR "imred input file: $temp\n"; 
+} else {
+    unlink $temp; 
+}
+
+if ($stat) {
+    if (! $quiet) { print STDOUT "ERROR: failure running flatten.flips\n"; }
+    exit 1;
+}
+
+if ($defringe) {
+    system ("mv $output $output.det");
+    if ($?) { 
+	print STDERR "failure to save temporary output file\n";
+	exit 1;
+    }
+
+    system ("defringe.ccd -quiet $close $output.dat $output $ccd SPLIT");
+    if ($?) { 
+	print STDERR "failure in defringe\n";
+	$stat = 1;
+    }
+    unlink "$output.dat";
+}    
+
+if (! $quiet) {
+    if ($stat) { 
+	print STDOUT "ERROR: failure running flatten.flips\n"; 
+    } else {
+	print STDOUT "SUCCESS\n"; 
+    }
+}
+
+# always return 1, don't return just the exit status
+if ($stat) {
+    exit 1;
+} else {
+    exit 0;
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print STDERR "USAGE: flatten.flips (input) (output) CCD MODE [-fast] [-close] [-quiet]\n";
+    exit 2;
+}
+
+sub uppercase {
+    return "\U$_[0]\E";
+}
+
+# given a filename, check that its path exists, create it if not
+sub ckpathname {
+    my ($file) = $_[0];
+    my (@words, $dir);
+
+    @words = split ("/", $file);
+    pop (@words);
+    $dir = join ("/", @words);
+
+    if ($dir eq "") { $dir = "."; }
+
+    if (! -d $dir) {
+	system ("mkdir -p $dir");
+	if ($?) {
+	    print STDERR "ERROR: can't make directory component for $file\n";
+	    exit 1;
+	}
+    }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/flatten.mana
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/flatten.mana	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/flatten.mana	(revision 16632)
@@ -0,0 +1,269 @@
+#!/usr/bin/env perl
+
+# grab the command line options
+$use_fringe = 0;
+$use_mask = 1;
+$fast = 0;
+$quiet = 0;
+$close = "";
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-fast") {
+        $fast = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-quiet") {
+	$quiet = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-close") {
+	$close = "-close";
+        shift; next;
+    }
+    if ($ARGV[0] eq "-defringe") {
+	$use_fringe = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-nomask") {
+	$use_mask = 0;
+        shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 4) { &usage; }
+
+# command line arguments
+$input  = $ARGV[0];
+$output = $ARGV[1];
+$ccd    = $ARGV[2];
+$mode   = uppercase ($ARGV[3]);
+
+ckpathname ($output);
+
+if ($fast) { &fast; } else { &complete; }
+exit 1;
+
+sub complete {
+    # find the appropriate flat-field image
+    $flat=`detsearch -quiet -image $input $ccd $mode -type flat $close`; chop ($flat);
+    if ($?) {
+	print STDERR "ERROR: can't get flat for image\n";
+	exit 1;
+    }
+    # find the appropriate bias image
+    $bias=`detsearch -quiet -image $input $ccd $mode -type bias $close`; chop ($bias);
+    if ($?) {
+	print STDERR "ERROR: can't get bias for image\n";
+	exit 1;
+    }
+    # find the appropriate dark image
+    $dark=`detsearch -quiet -image $input $ccd $mode -type dark $close`; chop ($dark);
+    if ($?) {
+	print STDERR "ERROR: can't get dark for image\n";
+	exit 1;
+    }
+
+    # find the appropriate mask image
+    $mask = "none";
+    if ($use_mask) {
+	$mask=`detsearch -quiet -image $input $ccd $mode -type mask $close`; chop ($mask);
+	if ($?) {
+	    print STDERR "ERROR: can't get mask for image\n";
+	    exit 1;
+	}
+    }
+
+    # abstracted keywords
+    $ccdkeyword  = `gconfig -q CCDNUM-KEYWORD`; chop ($ccdkeyword);
+    $darkword    = `gconfig -q DARKTIME-FUNCTION`; chop ($darkword);
+
+    # find the appropriate fringe frame & coords file
+    $fringe = "none";
+    $coordfile = "none";
+    if ($use_fringe) {
+	$exptimeword = `gconfig -q EXPTIME-KEYWORD`; chop ($exptimeword);
+	$filterword  = `gconfig -q FILTER-KEYWORD`; chop ($filterword);
+	$cameraword  = `gconfig -q CAMERA-KEYWORD`; chop ($cameraword);
+	$coordpath   = `gconfig -q FRINGE_COORD_PATH`; chop ($coordpath);
+
+	$ccdnum = `cameraconfig -N $ccd`;
+
+	# check the FILTER and EXPTIME, include fringe correction?:
+	$answer = `echo $input | fields $exptimeword $filterword $cameraword`;
+	($junk, $exptime, $filter, $camera) = split (" ", $answer);
+	# i need to do a look-up on the valid filter filternames (filtname)
+	$filter = uppercase ($filter);
+
+	$use_fringe = 0; 
+	# abstract this a bit: recipe gives guidance
+        # set defringe based on filter & exptime
+	if (($filter eq "I")     && ($exptime > 60)) { $use_fringe = 1; }
+	if (($filter eq "Z")     && ($exptime > 60)) { $use_fringe = 1; }
+	if (($filter eq "NB920") && ($exptime > 60)) { $use_fringe = 1; }
+
+	if ($use_fringe) {
+	    $fringe = `detsearch -quiet -image $input $ccd $mode -type fringe $close`; chop ($fringe);
+	    if ($?) {
+		print STDERR "ERROR: can't get fringe for image\n";
+		exit 1;
+	    }
+	    $coordfile = sprintf "%s/%s-%s-CCD%02d-FringeCoord.reg", $coordpath, $camera, $filter, $ccd;
+	}
+    }
+
+    # determine scale factor for dark image
+    $answer = `echo $input | fields $exptimeword`;
+    ($name, $t1) = split (" ", $answer);
+    $answer = `echo $dark | fields $exptimeword`;
+    ($name, $t2) = split (" ", $answer);
+    $darkfactor = `darktime.$darkword $t1 $t2`; chop ($darkfactor);
+
+    # find the appropriate script file
+    $confdir = `gconfig -q CONFDIR`; chop ($confdir);
+    $script  = "$confdir/mana/flatten.pro";
+    
+    # run mana, call script
+    open (MANA, "|mana --norc");
+    print MANA "input $script\n";
+    print MANA "\$CCDKEYWORD = $ccdkeyword\n";
+    print MANA "\$bias       = $bias\n";
+    print MANA "\$dark       = $dark\n";
+    print MANA "\$flat       = $flat\n";
+    print MANA "\$mask       = $mask\n";
+    print MANA "\$fringe     = $fringe\n";
+    print MANA "\$use:mask   = $use_mask\n";
+    print MANA "\$use:fringe = $use_fringe\n";
+    print MANA "\$darkfactor = $darkfactor\n";
+    print MANA "\$coordfile  = $coordfile\n";
+    print MANA "flatten.complete $input $output $ccd $mode\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) {
+	print STDERR "ERROR problem with imstats\n";
+	exit 1;
+    }
+    print STDOUT "SUCCESS: finished with imstats\n";
+    exit 0;
+}
+    
+sub fast {
+    # find the appropriate flat-field image
+    $flat=`detsearch -quiet -image $input $ccd $mode -type flat -close`; chop ($flat);
+    if ($?) {
+	print STDERR "ERROR: can't get flat for image\n";
+	exit 1;
+    }
+
+    # find the appropriate mask image
+    $mask = "none";
+    if ($use_mask) {
+	$mask=`detsearch -quiet -image $input $ccd $mode -type mask -close`; chop ($mask);
+	if ($?) {
+	    print STDERR "ERROR: can't get mask for image\n";
+	    exit 1;
+	}
+    }
+
+    # abstracted keywords
+    $ccdkeyword  = `gconfig -q CCDNUM-KEYWORD`; chop ($ccdkeyword);
+
+    # find the appropriate fringe frame & coords file
+    $fringe = "none";
+    $coordfile = "none";
+    if ($use_fringe) {
+	$exptimeword = `gconfig -q EXPTIME-KEYWORD`; chop ($exptimeword);
+	$filterword  = `gconfig -q FILTER-KEYWORD`; chop ($filterword);
+	$cameraword  = `gconfig -q CAMERA-KEYWORD`; chop ($cameraword);
+	$coordpath   = `gconfig -q FRINGE_COORD_PATH`; chop ($coordpath);
+
+	$ccdnum = `cameraconfig -N $ccd`;
+
+	# check the FILTER and EXPTIME, include fringe correction?:
+	$answer = `echo $input | fields $exptimeword $filterword $cameraword`;
+	($junk, $exptime, $filter, $camera) = split (" ", $answer);
+	# i need to do a look-up on the valid filter filternames (filtname)
+	$filter = uppercase ($filter);
+
+	$use_fringe = 0; 
+        # set defringe based on filter & exptime
+	if (($filter eq "I")     && ($exptime > 60)) { $use_fringe = 1; }
+	if (($filter eq "Z")     && ($exptime > 60)) { $use_fringe = 1; }
+	if (($filter eq "NB920") && ($exptime > 60)) { $use_fringe = 1; }
+
+	if ($use_fringe) {
+	    $fringe = `detsearch -quiet -image $input $ccd $mode -type fringe -close`; chop ($fringe);
+	    if ($?) {
+		print STDERR "ERROR: can't get fringe for image\n";
+		exit 1;
+	    }
+	    $coordfile = sprintf "%s/%s-%s-CCD%02d-FringeCoord.reg", $coordpath, $camera, $filter, $ccd;
+	}
+    }
+
+    # find the appropriate script file
+    $confdir = `gconfig -q CONFDIR`; chop ($confdir);
+    $script  = "$confdir/mana/flatten.pro";
+    
+    # run mana, call script
+    open (MANA, "|mana --norc");
+    print MANA "input $script\n";
+    print MANA "\$CCDKEYWORD = $ccdkeyword\n";
+    print MANA "\$flat       = $flat\n";
+    print MANA "\$mask       = $mask\n";
+    print MANA "\$fringe     = $fringe\n";
+    print MANA "\$use:mask   = $use_mask\n";
+    print MANA "\$use:fringe = $use_fringe\n";
+    print MANA "\$coordfile  = $coordfile\n";
+    print MANA "flatten.fast $input $output $ccd $mode\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) {
+	print STDERR "ERROR problem with imstats\n";
+	exit 1;
+    }
+    print STDOUT "SUCCESS: finished with imstats\n";
+    exit 0;
+}
+    
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print STDERR "USAGE: flatten.mana (input) (output) CCD MODE [-fast] [-close] [-quiet]\n";
+    exit 2;
+}
+
+sub uppercase {
+    return "\U$_[0]\E";
+}
+
+# given a filename, check that its path exists, create it if not
+sub ckpathname {
+    my ($file) = $_[0];
+    my (@words, $dir);
+
+    @words = split ("/", $file);
+    pop (@words);
+    $dir = join ("/", @words);
+
+    if ($dir eq "") { $dir = "."; }
+
+    if (! -d $dir) {
+	system ("mkdir -p $dir");
+	if ($?) {
+	    print STDERR "ERROR: can't make directory component for $file\n";
+	    exit 1;
+	}
+    }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.ckfile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.ckfile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.ckfile	(revision 16632)
@@ -0,0 +1,30 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 1) { &usage (); }
+
+# assign the command line arguments
+$list   = $ARGV[0];
+
+# check for files to be processed
+open (FILE, "$list");
+@list = <FILE>;
+close (FILE);
+
+foreach $file (@list) {
+    chop ($file);
+    if (-e $file) { next; }
+    print STDERR "ERROR: missing file $file\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: found all files from $list\n";
+exit 0;
+
+sub usage {
+    print "USAGE: fr.ckfile (list)\n";
+    print " checks for the existence of each file in the list\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.defringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.defringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.defringe	(revision 16632)
@@ -0,0 +1,133 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 5) { &escape ("ERROR: USAGE: defringe (imlist) (imstats) (frlist) (frstats) (outlist)"); }
+
+$imlist  = $ARGV[0];
+$imstats = $ARGV[1];
+$frlist  = $ARGV[2];
+$frstats = $ARGV[3];
+$output  = $ARGV[4];
+
+# load config info
+$confdir = `gconfig CONFDIR`; chop $confdir;
+if ($?) { &escape ("ERROR: config failure"); }
+
+# various lists
+@input  = split (" ", `cat $imlist`);
+@output = split (" ", `cat $output`);
+@ccds   = split (" ", `cameraconfig -ccds`);
+@ccdn   = split (" ", `cameraconfig -ccdn`);
+$Nccd   = @ccds;
+
+# output directories must exist
+for ($i = 0; $i < $Nccd; $i++) { &ckdir ($output[$i]); }
+
+# convert image stats to optimal image parameters
+$fitpars = &mktemp ("defringe");
+vsystem ("fr.frstats -applyfit $imstats $frstats $fitpars");
+@fitpars = `cat $fitpars`; foreach $line (@fitpars) { chop $line; }
+@fringe  = `cat $frlist`; foreach $line (@fringe) { chop $line; }
+
+# load flips parameter file
+$paramfile = `gconfig FLIPS_PARAM_DEFRINGE`; chop $paramfile;
+if ($?) { die "ERROR: missing FLIPS_PARAM_DEFRINGE in config\n"; }
+
+open (FILE, "$paramfile");
+@rawpars = <FILE>;
+close (FILE);
+
+$infile  = &mktemp ("\@defringe");
+$parfile = &mktemp ("defringe");
+for ($i = 0; $i < $Nccd; $i++) {
+
+    # create input list file
+    ($s0, $s1, $RF, $ds) = split (" ", $fitpars[$i]);
+    open (FILE, ">$infile");
+    print FILE "$input[$i]  $s0 1.0 $ds\n";
+    print FILE "$fringe[$i] $s1 $RF $ds\n";
+    close (FILE);
+
+    print STDOUT "$fitpars[$i]\n";
+    print STDOUT "$input[$i]  $s0 1.0 $ds\n";
+    print STDOUT "$fringe[$i] $s1 $RF $ds\n";
+
+    # create input par file
+    @params = @rawpars;
+    foreach $line (@params) {
+	$line =~ s|LISTNAME|$infile|;
+	$line =~ s|FILENAME|$output[$i]|;
+	$line =~ s|COMMENT|Elixir Defringing|;
+    }
+    open (FILE, ">$parfile");
+    foreach $line (@params) { print FILE "$line"; }
+    close (FILE);
+
+    if (-e $output[$i]) { unlink $output[$i]; }
+    vsystem ("imcombred $parfile");
+    if ($?) { &escape ("ERROR: failure running imcombred"); }
+}
+
+&goodbye;
+
+########################################################
+
+sub ckdir {
+
+    my ($file) = $_[0];
+    my ($dir, @words);
+
+    @words = split ("/", $file);
+    pop (@words);
+    $dir = join ("/", @words);
+    if ($dir eq "") { $dir = "."; }
+    if (! -e $dir) {
+	system ("mkdir -p $dir");
+	if ($?) { die "ERROR: can't create output directory $dir\n"; }
+    }
+}
+
+sub loadlist {
+
+    my($command) = $_[0];
+    my(@list, $line);
+
+    @list = `$command`;
+
+    foreach $line (@list) { chop ($line); }
+
+    return @list;
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+@temp = ();
+sub mktemp {
+
+    my ($base) = $_[0];
+    my ($name);
+    $name = `mktemp /tmp/$base.XXXXXX`;
+    chop $name;
+
+    push @temp, $name;
+    return $name;
+}
+
+sub escape {
+    $message = $_[0];
+    foreach $name (@temp) {
+	unlink ($name);
+    }
+    die "$message\n";
+}
+
+sub goodbye {
+    foreach $name (@temp) { unlink ($name); }
+    print STDERR "SUCCESS\n";
+    exit 0;
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.detrend
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.detrend	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.detrend	(revision 16632)
@@ -0,0 +1,79 @@
+#!/usr/bin/env perl
+# calls flatten.flips, but no direct flips functions
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 4) { die "USAGE: fr.detrend (path) (root) (mode) (outlist)\n" }
+
+# assign the command line arguments
+$path = $ARGV[0];
+$root = $ARGV[1];
+$mode = "\U$ARGV[2]\E";
+if (($mode ne "MEF") && ($mode ne "SPLIT")) { die "ERROR: mode must be either -split or -mef\n";}
+
+# load output list (must be created in ccd order)
+$outlist = $ARGV[3];
+open (FILE, "$outlist");
+@outlist = <FILE>;
+close (FILE);
+foreach $line (@outlist) { chop ($line); }
+       
+# double checks: should be Nccd 
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+if ($Nccd != @outlist) { die "ERROR: mis-matched number of images\n"; }
+@ccds    = split (" ", `cameraconfig -ccds`);
+if ($?) { die "ERROR: cameraconfig error\n"; }
+@ccdn    = split (" ", `cameraconfig -ccdn`);
+if ($?) { die "ERROR: cameraconfig error\n"; }
+
+# run flatten.flips for each input and output image:
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    
+    $infile  = mk_filename ($path, $root, $mode, $ccdn[$ccd]);
+    $outfile = $outlist[$ccd];
+
+    $status = vsystem ("flatten.flips -quiet $infile $outfile $ccds[$ccd] $mode");
+    if ($status) { die "ERROR: problem running flatten on $infile\n"; }
+}
+print STDOUT "SUCCESS: finished with fr.detrend\n";
+exit 0;
+
+## utilities
+
+sub mk_filename {
+    my ($path) = $_[0];
+    my ($root) = $_[1];
+    my ($mode) = $_[2];
+    my ($ccd)  = $_[3];
+
+    if ($mode eq "MEF") {
+	$name = sprintf "%s/%s.fits", $path, $root;
+	return $name;
+    }
+    if ($mode eq "SPLIT") {
+	$name = sprintf "%s/%s/%s%s.fits", $path, $root, $root, $ccd;
+	return $name;
+    }
+    return "";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.detrend (path) (root) (mode) (outlist)\n";
+    print " path:    path to MEF image or SPLIT dir\n";
+    print " root:    root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:    MEF or SPLIT\n";
+    print " outlist: list of output files\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.frstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.frstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.frstats	(revision 16632)
@@ -0,0 +1,171 @@
+#!/usr/bin/env perl
+
+if (@ARGV < 1) { &escape ("USAGE: fr.frstats -mode [args]"); }
+if ($ARGV[0] eq "help") { &usage; }
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/fringe.pro";
+
+# test named Xserver, or start vnc on specified machine
+$xhost=`gconfig -q XHOST`; chop ($xhost);
+$xdisp=`gconfig -q XDISP`; chop ($xdisp);
+if (vsystem ("xdpyinfo -display $xdisp > /dev/null")) {
+    print STDERR "X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# determine fit parameters for list of raw fringe measurements
+if ($ARGV[0] eq "-fitpars") {
+    
+    $list = $ARGV[1];
+    $pars = $ARGV[2];
+
+    # run mana script:
+    open (MANA, "|mana --norc");
+    print MANA "input $script\n";
+    print MANA "getfitpars $list $pars\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) { &escape ("problem with fr.frstats -fitpars"); }
+
+    &goodbye;
+}
+
+# apply fit parameters for given chip
+if ($ARGV[0] eq "-applyfit") {
+    
+    if (@ARGV != 4) { die "USAGE: fr.frstats -applyfit (imlist) (fitpars) (output)\n"; }
+    $list = $ARGV[1];
+    $pars = $ARGV[2];
+    $output = $ARGV[3];
+
+    if (-e $output) { unlink $output; }
+
+    # run mana script:
+    open (MANA, "|mana --norc");
+    print MANA "input $script\n";
+    print MANA "applyfitstats $list $pars $output\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) { &escape ("problem with fr.frstats -applyfit"); }
+
+    &goodbye;
+}
+
+# determine fit parameters for list of raw fringe measurements
+if ($ARGV[0] eq "-plotstats") {
+    
+    $list = $ARGV[1];
+    $pars = $ARGV[2];
+    $output = $ARGV[3];
+
+    # run mana script:
+    open (MANA, "|mana --norc");
+    print MANA "input $script\n";
+    print MANA "showfits $list $pars $output\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) { &escape ("problem with fr.frstats -plotstats"); }
+
+    &goodbye;
+}
+
+# create frstats file for list of raw fringe measurements using measure fringe parameters
+if ($ARGV[0] eq "-frstats") {
+    
+    $list    = $ARGV[1];
+    $pars    = $ARGV[2];
+    $frstats = $ARGV[3];
+
+    # check if none of list exist, then skip
+    # otherwise, report error
+
+    open (FILE, "$list");
+    @list = <FILE>;
+    close (FILE);
+
+    $Nfound = 0;
+    foreach $line (@list) {
+	chop $line;
+	if (-e $line) { $Nfound ++; }
+    }
+    if ($Nfound < @list) { 
+	print STDERR "NOTE: missing some file from $list: assuming initial state\n";
+	&goodbye; 
+    }
+
+    # run mana script:
+    open (MANA, "|mana --norc");
+    print MANA "input $script\n";
+    print MANA "getfrstats $pars $list $frstats\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) { &escape ("problem with fr.frstats -frstats"); }
+
+    &goodbye;
+}
+
+# create dfstats file for list of fringe residual measurements
+if ($ARGV[0] eq "-dfstats") {
+    
+    $list    = $ARGV[1];
+    $pars    = $ARGV[2];
+    $frstats = $ARGV[3];
+
+    # check if none of list exist, then skip
+    # otherwise, report error
+
+    open (FILE, "$list");
+    @list = <FILE>;
+    close (FILE);
+
+    $Nfound = 0;
+    foreach $line (@list) {
+	chop $line;
+	if (-e $line) { $Nfound ++; }
+    }
+    if ($Nfound < @list) { 
+	print STDERR "NOTE: missing some files from $list: assuming initial state\n";
+	&goodbye; 
+    }
+
+    # run mana script:
+    open (MANA, "|mana --norc");
+    print MANA "input $script\n";
+    print MANA "getdfstats $pars $list $frstats\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) { &escape ("problem with fr.frstats -frstats"); }
+
+    &goodbye;
+}
+
+&escape ("unknown fr.frstats command $ARGV[0]");
+
+## utilities
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+  print STDOUT "finished with fr.stats\n";
+  exit 0;
+}
+
+sub escape {
+  print STDOUT "ERROR: $_[0]\n";
+  exit 1;
+}
+
+sub usage {
+
+    print STDOUT "fr.mklists -fitpars CONFIG.med.sublist  CONFIG.fitpars\n";
+    print STDOUT "fr.frstats -frstats CONFIG.med.statlist CONFIG.fitpars CONFIG.med.imstats\n";
+
+    exit 2;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.getfringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.getfringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.getfringe	(revision 16632)
@@ -0,0 +1,59 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 3) { die "USAGE: fr.getfringe (inlist) (binning) (output)\n" }
+
+# assign the command line arguments
+$inlist = $ARGV[0];
+$bin    = $ARGV[1];
+$output = $ARGV[2];
+
+# load input list:
+open (FILE, "$inlist");
+@inlist = <FILE>;
+close (FILE);
+foreach $line (@inlist) { chop $line; }
+
+# getfringe appends to the output file:
+unlink ($output);
+
+# basic camera data
+$Nccd      = `cameraconfig -Nccd`;  chop $Nccd;
+if ($Nccd != @inlist) { die "ERROR: mis-matched image list sizes\n"; }
+@ccds = split (" ", `cameraconfig -ccds`); 
+if ($?) { die "ERROR: cameraconfig error\n"; }
+
+# find fringe coordinate file
+$coordfile = `detsearch -quiet -image $inlist[0] $ccds[0] split -type frpts`; chop $coordfile;
+if ($?) { die "ERROR: can't find fringe point file for this image\n"; }
+
+# each call to getfringe adds a line to $output 
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    vsystem ("getfringe $inlist[$ccd] $ccds[$ccd] $coordfile $bin >> $output");
+    if ($?) { die "ERROR running getfringe\n"; }
+}
+
+print STDOUT "SUCCESS: finished with fr.getfringe\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.getfringe (inlist) (binning) (output)\n";
+    print " calculate fringe pattern strengths for images in (inlist)\n";
+    print " inlist  : list of input CCDs in CCD order\n";
+    print " binning : binning factor of images\n";
+    print " outdir  : output file\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.imdata
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.imdata	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.imdata	(revision 16632)
@@ -0,0 +1,55 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 2) { &usage (); }
+
+# assign the command line arguments
+$list   = $ARGV[0];
+$imdata = $ARGV[1];
+
+# load input list:
+open (FILE, "$list");
+@list = <FILE>;
+close (FILE);
+foreach $line (@list) {chop $line;}
+
+# check for file
+if (! -e $list[0]) { die "ERROR: image file $list[0] is missing\n"; }
+
+print STDOUT "$list[0]\n";
+
+# abstract header keywords
+($datekwd, $timekwd, $obsidkwd, $exptimekwd) = 
+    split (" ", `gconfig DATE-KEYWORD UT-KEYWORD ID-KEYWORD EXPTIME-KEYWORD`);
+if ($?) { die "ERROR problem with keywords\n"; }
+
+($file, $date, $utc, $obsid, $exptime) = 
+    split (" ", `echo $list[0] | fields $datekwd $timekwd $obsidkwd $exptimekwd`);
+if ($?) { die "ERROR missing header information\n"; }
+ 
+open (FILE, ">$imdata");
+print FILE "$obsid $date $utc $exptime\n";
+close (FILE);
+
+print STDOUT "SUCCESS: finished with fr.stats\n";
+exit 0;
+
+## utilities
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fr.imdata (list) (imdata)\n";
+    print "  extract basic image data from header for later reference\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.jpegs
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.jpegs	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.jpegs	(revision 16632)
@@ -0,0 +1,65 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 4) { &usage (); }
+
+# assign the command line arguments
+$list   = $ARGV[0];
+$tenbin = $ARGV[1];
+$medbin = $ARGV[2];
+$range  = $ARGV[3];
+
+# check for files to be processed
+@status = stat ($list);
+if ($status[7] == 0) {
+    print STDERR "no files in source list, skipping\n";
+    exit 1;
+}
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/fringe.pro";
+
+# test named Xserver, or start vnc on specified machine
+$xhost=`gconfig -q XHOST`; chop ($xhost);
+$xdisp=`gconfig -q XDISP`; chop ($xdisp);
+if (vsystem ("xdpyinfo -display $xdisp")) {
+    print STDERR "X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "\$RANGE = $range\n";
+print MANA "mkjpegs $list $tenbin $medbin $stats\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) { die "ERROR problem with fr.jpegs\n"; }
+
+print STDOUT "SUCCESS: finished with fr.jpegs\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fr.jpegs (list) (tenbin) (medbin) (range)\n";
+    print "  create big and small jpeg images from the input list\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.medbin.interp
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.medbin.interp	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.medbin.interp	(revision 16632)
@@ -0,0 +1,130 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 5) { die "USAGE: fr.medbin (path) (root) (factor) (meddir) (mapdir)\n" }
+
+# assign the command line arguments
+$path   = $ARGV[0];
+$root   = $ARGV[1];
+$factor = $ARGV[2];
+$meddir = $ARGV[3];
+$mapdir = $ARGV[4];
+
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+@ccds = split (" ", `cameraconfig -ccdn`);
+if ($?) { die "ERROR: cameraconfig error\n"; }
+
+($Xmap, $Ymap) = split (" ", `gconfig FRINGE_MAP_SCALE`);
+if ($?) { die "ERROR: missing FRINGE_MAP_SCALE in config system\n"; }
+
+if (! -d $meddir) { vsystem ("mkdir -p $meddir"); }
+if (! -d $mapdir) { vsystem ("mkdir -p $mapdir"); }
+
+open (MANA, "|mana --norc");
+
+# convert BIASSEC string to x1, x2, y1, y2 vars
+print MANA "macro parsesec\n";
+print MANA "  \$f = \$1\n";
+print MANA "  getchr \$f : n\n";
+print MANA "  substr \$f 1 {\$n-1} x1\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f , n\n";
+print MANA "  substr \$f 1 {\$n-1} x2\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f : n\n";
+print MANA "  substr \$f 1 {\$n-1} y1\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f ] n\n";
+print MANA "  substr \$f 1 {\$n-1} y2\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+print MANA "end\n";
+
+print MANA "macro mkmap\n";
+# load detrended image
+print MANA " rd a \$1\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+
+# generate binned image 
+print MANA " medianmap a b {\$nx/$factor} {\$ny/$factor} -range 0.25 0.75\n";
+print MANA " keyword a DATASEC line\n";
+print MANA " parsesec \$line\n";
+print MANA " sprint newline \"[%d:%d,%d:%d]\" {int(\$x1/2 + 1)} {int(\$x2/2 + 1)} {int(\$y1/2 + 1)} {int(\$y2/2 + 1)}\n";
+print MANA " keyword b DATASEC -w \$newline\n";
+print MANA " keyword b NAXIS1 nx\n";
+print MANA " keyword b NAXIS2 ny\n";
+
+# sky from first ccd saved for reference
+print MANA " if (\$setsky)\n";
+print MANA "  stats -q b - - - -\n";
+print MANA "  \$sky = \$MEDIAN\n";
+print MANA "  \$setsky = 0\n";
+print MANA " end\n";
+# we use the sky value of the first chip to remove the DC level for map, add it to med
+
+# create Xmap x Ymap sky map, interpolate to medbin scale
+print MANA " medianmap b m $Xmap $Ymap -ignore 0.0 -range 0.25 0.75\n";
+print MANA " set m = m - \$sky\n";
+print MANA " \$fm = \$nx / $Xmap\n";
+print MANA " \$fy = \$ny / $Ymap\n";
+print MANA " if (\$fy > \$fm)\n";
+print MANA "  \$fm = \$fy\n";
+print MANA " end\n";
+print MANA " minterp m M \$fm\n";
+print MANA " extract M sky 0 0 \$nx \$ny 0 0 \$nx \$ny\n";
+
+# multiplying by (abs(b) > 0.001) maintains the mask
+print MANA " set c = (b - sky) * (abs(b) > 0.001)\n";
+print MANA " wd c \$2\n";
+print MANA " wd m \$3 -bitpix -32 -bzero 0.0 -bscale 1.0\n";
+print MANA "end\n";
+
+print MANA "macro go\n";
+print MANA " \$setsky = 1\n";
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    $infile = sprintf "%s/%s%s.fits", $path,   $root, $ccds[$ccd];
+    $outmed = sprintf "%s/%s%s.fits", $meddir, $root, $ccds[$ccd];
+    $outmap = sprintf "%s/%s%s.fits", $mapdir, $root, $ccds[$ccd];
+    print MANA " mkmap $infile $outmed $outmap\n";
+}
+print MANA " exit 0\n";
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR running mana\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.medbin.spline\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.medbin.spline (path) (root) (factor) (outpath)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.medbin.spline
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.medbin.spline	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.medbin.spline	(revision 16632)
@@ -0,0 +1,125 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 5) { die "USAGE: fr.medbin (path) (root) (factor) (meddir) (mapdir)\n" }
+
+# assign the command line arguments
+$path   = $ARGV[0];
+$root   = $ARGV[1];
+$factor = $ARGV[2];
+$meddir = $ARGV[3];
+$mapdir = $ARGV[4];
+
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+@ccds = split (" ", `cameraconfig -ccdn`);
+if ($?) { die "ERROR: cameraconfig error\n"; }
+
+($Xmap, $Ymap) = split (" ", `gconfig FRINGE_MAP_SCALE`);
+if ($?) { die "ERROR: missing FRINGE_MAP_SCALE in config system\n"; }
+
+if (! -d $meddir) { vsystem ("mkdir -p $meddir"); }
+if (! -d $mapdir) { vsystem ("mkdir -p $mapdir"); }
+
+open (MANA, "|mana --norc");
+
+# convert BIASSEC string to x1, x2, y1, y2 vars
+print MANA "macro parsesec\n";
+print MANA "  \$f = \$1\n";
+print MANA "  getchr \$f : n\n";
+print MANA "  substr \$f 1 {\$n-1} x1\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f , n\n";
+print MANA "  substr \$f 1 {\$n-1} x2\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f : n\n";
+print MANA "  substr \$f 1 {\$n-1} y1\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f ] n\n";
+print MANA "  substr \$f 1 {\$n-1} y2\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+print MANA "end\n";
+
+print MANA "macro mkmap\n";
+# load detrended image
+print MANA " rd a \$1\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+
+# generate binned image 
+print MANA " medianmap a b {\$nx/$factor} {\$ny/$factor} -range 0.25 0.75\n";
+print MANA " keyword a DATASEC line\n";
+print MANA " parsesec \$line\n";
+print MANA " sprint newline \"[%d:%d,%d:%d]\" {int(\$x1/2 + 1)} {int(\$x2/2 + 1)} {int(\$y1/2 + 1)} {int(\$y2/2 + 1)}\n";
+print MANA " keyword b DATASEC -w \$newline\n";
+print MANA " keyword b NAXIS1 nx\n";
+print MANA " keyword b NAXIS2 ny\n";
+
+# sky from first ccd saved for reference
+print MANA " if (\$setsky)\n";
+print MANA "  stats -q b - - - -\n";
+print MANA "  \$sky = \$MEDIAN\n";
+print MANA "  \$setsky = 0\n";
+print MANA " end\n";
+# we use the sky value of the first chip to remove the DC level for map, add it to med
+
+# create Xmap x Ymap sky map, spline-fit to medbin scale
+print MANA " medianmap b m $Xmap $Ymap -ignore 0.0 -range 0.25 0.75\n";
+print MANA " set m = m - \$sky\n";
+print MANA " spline.construct m M x\n";
+print MANA " spline.apply m M sky x \$nx \$ny\n";
+
+# multiplying by (abs(b) > 0.001) maintains the mask
+print MANA " set c = (b - sky) * (abs(b) > 0.001)\n";
+print MANA " wd c \$2\n";
+print MANA " wd m \$3 -bitpix -32 -bzero 0.0 -bscale 1.0\n";
+print MANA "end\n";
+
+print MANA "macro go\n";
+print MANA " \$setsky = 1\n";
+for ($ccd = 0; $ccd < $Nccd; $ccd++) {
+    $infile = sprintf "%s/%s%s.fits", $path,   $root, $ccds[$ccd];
+    $outmed = sprintf "%s/%s%s.fits", $meddir, $root, $ccds[$ccd];
+    $outmap = sprintf "%s/%s%s.fits", $mapdir, $root, $ccds[$ccd];
+    print MANA " mkmap $infile $outmed $outmap\n";
+}
+print MANA " exit 0\n";
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR running mana\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.medbin.spline\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.medbin.spline (path) (root) (factor) (outpath)\n";
+    print " path:   path to MEF image or SPLIT dir\n";
+    print " root:   root name of image (MEF = root.fits, SPLIT = root/rootNN.fits)\n";
+    print " mode:   MEF or SPLIT\n";
+    print " outdir: directory for output results (all split)\n";
+    exit 1;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mkhtml
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mkhtml	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mkhtml	(revision 16632)
@@ -0,0 +1,96 @@
+#!/usr/bin/env perl
+
+if (@ARGV < 1) { &escape ("USAGE: fr.mkhtml -mode [args]"); }
+if ($ARGV[0] eq "help") { &usage; }
+
+# copy CONFIG.imstats to html dir
+if ($ARGV[0] eq "-imstats") {
+    
+    $input  = $ARGV[1];
+    $outdir = $ARGV[2];
+
+    if (! -d $outdir) {
+	vsystem ("mkdir -p $outdir");
+	if ($?) { &escape ("can't make directory component for output $outdir"); }
+    }
+
+    vsystem ("cp $input $outdir");
+    if ($?) { &escape ("problem copying $input to $outdir"); }
+
+    &goodbye;
+}
+
+# create frstats file for list of raw fringe measurements using measure fringe parameters
+if ($ARGV[0] eq "-jpglist") {
+    
+    $list    = $ARGV[1];
+    $outdir  = $ARGV[2];
+    $root    = $ARGV[3];
+    $outlist = sprintf "%s/%s.list", $outdir, $root;
+    print STDERR "outlist: $outlist\n";
+
+    if (! -d $outdir) {
+	vsystem ("mkdir -p $outdir");
+	if ($?) { &escape ("can't make directory component for output $outdir"); }
+    }
+
+    open (FILE, "$list");
+    @list = <FILE>;
+    close (FILE);
+    foreach $line (@list) { chop $line; }
+
+    # list contains MOSAIC.med.medbin.jpg
+    # copy to html/CONFIG.med.medbin.NNN.jpg
+
+    $Nfound = 0;
+    foreach $line (@list) {
+	if (-e $line) { $Nfound ++; }
+    }
+    if ($Nfound < @list) { 
+	print STDERR "NOTE: no files from $list: assuming initial state\n";
+	open (FILE, ">$outlist");
+	close (FILE);
+	&goodbye; 
+    }
+
+    open (FILE, ">$outlist");
+    for ($i = 0; $i < @list; $i++) {
+
+	$inname  = $list[$i];
+	$outname = sprintf "%s/%s.%03d.jpg", $outdir, $root, $i;
+	vsystem ("cp -f $inname $outname");
+	if ($?) { &escape ("problem copying $inname to $outname"); }
+	
+	print FILE "$outname\n";
+    }
+    close (FILE);
+    &goodbye;
+}
+
+&escape ("unknown fr.frstats command $ARGV[0]");
+
+## utilities
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+  print STDOUT "SUCCESS: finished with fr.stats\n";
+  exit 0;
+}
+
+sub escape {
+  print STDOUT "ERROR: $_[0]\n";
+  exit 1;
+}
+
+sub usage {
+
+    print STDOUT "fr.mklists -fitpars CONFIG.med.sublist  CONFIG.fitpars\n";
+    print STDOUT "fr.frstats -frstats CONFIG.med.statlist CONFIG.fitpars CONFIG.med.imstats\n";
+
+    exit 2;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mklists
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mklists	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mklists	(revision 16632)
@@ -0,0 +1,529 @@
+#!/usr/bin/env perl
+
+if (@ARGV < 1) {
+    print STDERR "USAGE: fr.mklists -mode [args]\n";
+    &escape;
+}
+
+if ($ARGV[0] eq "help") {
+
+    print STDERR "fr.mklists -initial  CONFIG.split CONFIG.mef CONFIG.master\n";
+    print STDERR "fr.mklists -detrend  CONFIG.master CONFIG.detrend\n";
+    print STDERR "fr.mklists -defringe CONFIG.master CONFIG.defringe\n";
+    print STDERR "fr.mklists -imlist   TEMPLATE CONFIG.statlist [Nccd?]\n";
+    print STDERR "fr.mklists -mosaic   CONFIG.master proc name\n";
+    print STDERR "fr.mklists -master   CONFIG.detrend CONFIG.master\n";
+    print STDERR "fr.mklists -inlist   CONFIG.master 00 proc CONF-CCD.inlist\n";
+    print STDERR "fr.mklists -imstats  CONFIG.master 00 proc CONF-CCD.imstats\n";
+    print STDERR "fr.mklists -frstats  CONFIG.master proc CONF-CCD.imstats\n";
+    &escape;
+}
+
+@ccds = split (" ", `cameraconfig -ccdn`);
+if ($?) { die "error in config\n"; }
+
+$STAT_XCLD = 0;
+$STAT_KEEP = 1;
+$STAT_XDET = 2;
+$STAT_DETR = 3;
+
+# merge CONFIG.mef & CONFIG.split to CONFIG.master [starting status = 3]
+if ($ARGV[0] eq "-initial") {
+
+    if (@ARGV != 4) {
+	print STDERR "fr.mklists -initial CONFIG.split CONFIG.mef CONFIG.master\n";
+	&escape;
+    }
+
+    open (FILE, "$ARGV[1]");
+    @list1 = <FILE>;
+    close (FILE);
+
+    open (FILE, "$ARGV[2]");
+    @list2 = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$ARGV[3]");
+    foreach $line (@list1) {
+	chop $line;
+	print FILE "$line $STAT_DETR\n";
+    }
+    foreach $line (@list2) {
+	chop $line;
+	print FILE "$line $STAT_DETR\n";
+    }
+    close (FILE);
+
+    if ((@list1 == 0) && (@list2 == 0)) {
+	print STDERR "no images available\n";
+	&escape;
+    }
+
+    &goodbye;
+}
+
+# convert CONFIG.master to CONFIG.detrend (status == XDET || DETR, strip status)
+if ($ARGV[0] eq "-detrend") {
+
+    if (@ARGV != 3) {
+	print STDERR "fr.mklists -detrend CONFIG.master CONFIG.detrend\n";
+	&escape;
+    }
+
+    open (FILE, "$ARGV[1]");
+    @list = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$ARGV[2]");
+    foreach $line (@list) {
+	@words = split (" ", $line);
+	if (($words[3] == $STAT_XDET) || ($words[3] == $STAT_DETR)) {
+	    print FILE "$words[0] $words[1] $words[2]\n";
+	}
+    }
+    close (FILE);
+    &goodbye;
+}
+
+# convert CONFIG.master to CONFIG.defringe, used to generate input list to mode.fringe3
+if ($ARGV[0] eq "-defringe") {
+
+    if (@ARGV != 5) {
+	print STDERR "@ARGV\n";
+	print STDERR "fr.mklists -detrend CONFIG.master CONFIG TMPPATH CONFIG.defringe\n";
+	&escape;
+    }
+
+    $infile   = $ARGV[1];
+    $confline = $ARGV[2];
+    $tmppath  = $ARGV[3];
+    $outfile  = $ARGV[4];
+
+    open (FILE, "$infile");
+    @list = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$outfile");
+    foreach $line (@list) {
+	($path, $root, $mode, $status) = split (" ", $line);
+	print FILE "$tmppath/$root $confline\n";
+    }
+    close (FILE);
+    &goodbye;
+}
+
+# use TEMPLATE to create a list with NCCD entries replacing CCDNUM
+if ($ARGV[0] eq "-imlist") {
+
+    if (@ARGV != 3) {
+	print STDERR "fr.mklists -detrend TEMPLATE CONFIG.defringe\n";
+	&escape;
+    }
+
+    open (FILE, ">$ARGV[2]");
+    foreach $ccd (@ccds) {
+	$name = $ARGV[1];
+	$name =~ s/CCDNUM/$ccd/;
+	print FILE "$name\n";
+    }
+    close (FILE);
+    &goodbye;
+}
+
+# use CONFIG.master to create Nimage lists, each called OUTDIR/root.WORDlist with
+# NCCD entries OUTDIR/root.WORD/rootNN.fits
+if ($ARGV[0] eq "-mosaic") {
+
+    if (@ARGV != 4) {
+	print STDERR "fr.mklists -mosaic CONFIG.master OUTDIR WORD\n";
+	&escape;
+    }
+
+    $infile = $ARGV[1];
+    $outpath = $ARGV[2];
+    $word = $ARGV[3];
+
+    open (FILE, $infile);
+    @inlist = <FILE>;
+    close (FILE);
+
+    foreach $name (@inlist) { 
+	($path, $root, $mode) = split (" ", $name);
+
+	$outfile = sprintf "%s/%s.%slist", $outpath, $root, $word;
+	
+	open (FILE, ">$outfile");
+	foreach $ccd (@ccds) {
+	    printf FILE "$outpath/$root.$word/$root$ccd.fits\n";
+	}
+	close (FILE);
+    }
+    &goodbye;
+}
+
+# use CONFIG.master to create OUTPUT list with Nimage lines: OUTDIR/root.WORD
+if ($ARGV[0] eq "-mlist") {
+
+    if (@ARGV != 5) { &escape ("USAGE: fr.mklists -mlist CONFIG.master OUTDIR WORD OUTPUT"); }
+
+    $infile   = $ARGV[1];
+    $outpath  = $ARGV[2];
+    $word     = $ARGV[3];
+    $outfile  = $ARGV[4];
+
+    open (FILE, $infile);
+    @inlist = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$outfile");
+    foreach $name (@inlist) { 
+	($path, $root, $mode) = split (" ", $name);
+	$file = sprintf "%s/%s.%s", $outpath, $root, $word;
+	printf FILE "$file\n";
+    }
+    close (FILE);
+
+    &goodbye;
+}
+
+# merge data from master, med.imstats, def.imstats, datlist into a single file for the html scripts
+if ($ARGV[0] eq "-imstats") {
+
+    if (@ARGV != 6) {
+	print STDERR "fr.mklists -imstats CONFIG.master CONFIG.med.imstats CONFIG.def.imstats CONFIG.datlist CONFIG.imstats\n";
+	&escape;
+    }
+
+    $master  = $ARGV[1];
+    $medstat = $ARGV[2];
+    $defstat = $ARGV[3];
+    $datlist = $ARGV[4];
+    $output  = $ARGV[5];
+
+    open (FILE, "$master");
+    @master = <FILE>;
+    close (FILE);
+
+    open (FILE, "$medstat");
+    @medstat = <FILE>;
+    close (FILE);
+    if (@master != @medstat) { &escape ("mismatch in master & medstat lists"); }
+
+    open (FILE, "$defstat");
+    @defstat = <FILE>;
+    close (FILE);
+    if (@master != @defstat) { print STDERR "NOTE: no data in $defstat\n"; }
+
+    open (FILE, "$datlist");
+    @datlist = <FILE>;
+    close (FILE);
+    if (@master != @datlist) { &escape ("mismatch in master & datlist lists"); }
+
+    open (FILE, ">$output");
+    for ($i = 0; $i < @master; $i++) {
+	($path, $root, $mode, $status) = split (" ", $master[$i]);
+	
+	open (LIST, "$datlist[$i]");
+	$line = <LIST>;
+	close (LIST);
+	($obsid, $date, $time, $exptime) = split (" ", $line);
+
+	($S1, $F1, $dF1) = split (" ", $medstat[$i]);
+	if (@defstat) {
+	    ($S2, $F2, $dF2) = split (" ", $defstat[$i]);
+	}
+	$flux = $S1 / $exptime;
+
+	if (@defstat) {
+	    printf FILE "%8s %11s %12s %7.1f %6.2f %6.1f %6.1f %6.1f %6.1f %2d %2d\n", $obsid, $date, $time, $S1, $flux, $F1, $dF1, $F2, $dF2, $status, $status;
+	} else {
+	    printf FILE "%8s %11s %12s %7.1f %6.2f %6.1f %6.1f   N/A    N/A  %2d %2d\n", $obsid, $date, $time, $S1, $flux, $F1, $dF1, $status, $status;
+	}
+    }
+    close (FILE);
+    &goodbye;
+}
+
+# use CONFIG.master to create a subset of INPUT in OUTPUT
+if ($ARGV[0] eq "-subset") {
+
+    if (@ARGV != 4) { &escape ("USAGE: fr.mklists -subset CONFIG.master INPUT OUTPUT"); }
+
+    $master = $ARGV[1];
+    $input  = $ARGV[2];
+    $output = $ARGV[3];
+
+    open (FILE, $master);
+    @master = <FILE>;
+    close (FILE);
+
+    open (FILE, $input);
+    @input = <FILE>;
+    close (FILE);
+
+    if (@master != @input) { &escape ("mismatch in input & master file lengths"); }
+
+    open (FILE, ">$output");
+
+    for ($i = 0; $i < @master; $i++) {
+	$line = $master[$i]; chop $line;
+	($path, $root, $mode, $status) = split (" ", $line);
+	if ($status != $STAT_KEEP) { next; }
+
+	$file = $input[$i]; chop $file;
+	printf FILE "$file\n";
+    }
+    close (FILE);
+
+    &goodbye;
+}
+
+# use master, med.imstats, and statlist to create input list for fr.mkrough (file sky fringe 0 0)
+if ($ARGV[0] eq "-ccdstats") {
+
+    if (@ARGV != 6) { &escape ("USAGE: fr.mklists -ccdstats CONFIG.master CONFIG.med.imstats CONFIG.med.statlist CCD CONFIG.CCD.ccdstats"); }
+
+    $master   = $ARGV[1];
+    $imstats  = $ARGV[2]; # list of basic image stats
+    $statlist = $ARGV[3]; # list of image stat files (1 line per frame)
+    $ccd      = $ARGV[4];
+    $output   = $ARGV[5];
+
+    # $ccd = `cameraconfig -N $ccdid`;
+    # if ($ccd eq "") { &escape ("error in CCD ID"); }
+
+    open (FILE, $master);
+    @master = <FILE>;
+    close (FILE);
+
+    open (FILE, $imstats);
+    @imstats = <FILE>;
+    close (FILE);
+    if (@master != @imstats) { &escape ("mismatch in master & imstats file lengths"); }
+
+    open (FILE, $statlist);
+    @statlist = <FILE>;
+    close (FILE);
+    if (@master != @statlist) { &escape ("mismatch in master & statlist file lengths"); }
+
+    # find image with strongest fringe amplitude
+    $fringemax = "";
+    for ($i = 0; $i < @imstats; $i++) {
+	$line = $master[$i]; chop $line;
+	($path, $root, $mode, $status) = split (" ", $line);
+	if ($status != $STAT_KEEP) { next; }
+	
+	$line = $imstats[$i]; chop $line;
+	($SKY, $fringe, $dfringe) = split (" ", $line);
+	if ($fringemax eq "") { $fringemax = $fringe; }
+	if ($fringemax < $fringe) { $fringemax = $fringe; }
+    }
+    print "fringemax: $fringemax\n";
+
+    open (FILE, ">$output");
+    for ($i = 0; $i < @master; $i++) {
+	$line = $master[$i]; chop $line;
+	($path, $root, $mode, $status) = split (" ", $line);
+	if ($status != $STAT_KEEP) { next; }
+
+	$line = $imstats[$i]; chop $line;
+	($SKY, $fringe, $dfringe) = split (" ", $line);
+	$frnorm = $fringe / $fringemax;
+	# imcombred is not renormalizing: this will force fringe amplitude to a useful level
+
+	# file is list of fringe stats (1 line per chip)
+	$file = $statlist[$i]; chop $file;
+	open (STAT, "$file");
+	@stats = <STAT>;
+	close (STAT);
+
+	$line = $stats[$ccd];
+	($name, $sky) = split (" ", $line);
+	
+	# compare $sky with average sky $SKY?
+	$dsky = $sky - $SKY;
+	print FILE "$name $sky $frnorm\n";
+    }
+    close (FILE);
+
+    &goodbye;
+}
+
+# re-create master list, applying changes from detrend list 
+if ($ARGV[0] eq "-master") {
+
+    if (@ARGV != 3) {
+	print STDERR "fr.mklists -master CONFIG.master CONFIG.detrend\n";
+	&escape;
+    }
+
+    $master = $ARGV[1];
+    $detrend = $ARGV[2];
+
+    open (FILE, $master);
+    @master = <FILE>;
+    close (FILE);
+    foreach $name (@master) { chop ($name); }
+
+    open (FILE, $detrend);
+    @detrend = <FILE>;
+    close (FILE);
+    foreach $name (@detrend) { chop ($name); }
+
+    @remaster = ();
+  MASTER:
+    foreach $name (@master) {
+	($path, $root, $mode, $status) = split (" ", $name);
+	
+	if (($status == $STAT_XDET) || ($status == $STAT_DETR)) {
+	    # find entry in detrend list.  if it exists, set status to status - 2
+	  DETREND:
+	    foreach $dname (@detrend) {
+		($dpath, $droot, $dmode) = split (" ", $name);
+		if ($droot eq $root) {
+		    if ($status == $STAT_XDET) { $status = $STAT_XCLD; }
+		    if ($status == $STAT_DETR) { $status = $STAT_KEEP; }
+		    last DETREND;
+		}
+	    }
+	}
+
+	$new = "$path $root $mode $status";
+	@remaster = (@remaster, $new);
+    }
+
+    open (FILE, ">$master");
+    foreach $name (@remaster) { 
+	print FILE "$name\n";
+    }
+    close (FILE);
+    &goodbye;
+}
+
+# create list of input (detrended) frames for a single CCD for mkstats (status == 1)
+if ($ARGV[0] eq "-inlist") {
+
+    if (@ARGV != 5) {
+	print STDERR "fr.mklists -inlist CONFIG.master CCD TMPPATH CONF-CCD.inlist\n";
+	&escape;
+    }
+
+    $infile  = $ARGV[1];
+    $ccd     = $ARGV[2];
+    $tmppath = $ARGV[3];
+    $outfile = $ARGV[4];
+
+    open (FILE, "$infile");
+    @inlist = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$outfile");
+    foreach $name (@inlist) { 
+	($path, $root, $mode, $status) = split (" ", $name);
+	if ($status != $STAT_KEEP) { next; }
+	
+	printf FILE "%s/%s.med/%s%s.fits\n", $tmppath, $root, $root, $ccd;
+    }
+    close (FILE);
+    &goodbye;
+}
+
+### this old -imstats will be replaced.
+# create list of input (detrended) frames for a single CCD for mkstats (status == 1)
+if ($ARGV[0] eq "-imstats") {
+
+    if (@ARGV != 5) {
+	print STDERR "fr.mklists -inlist CONFIG.master CCD TMPPATH CONF-CCD.imstats\n";
+	&escape;
+    }
+
+    $infile  = $ARGV[1];
+    $ccd     = $ARGV[2];
+    $tmppath = $ARGV[3];
+    $outfile = $ARGV[4];
+
+    open (FILE, "$infile");
+    @inlist = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$outfile");
+    foreach $name (@inlist) { 
+	($path, $root, $mode, $status) = split (" ", $name);
+	if ($status != $STAT_KEEP) { next; }
+	
+	printf FILE "%s/%s.imstats\n", $tmppath, $root;
+    }
+    close (FILE);
+    &goodbye;
+}
+
+# create list of input stats files 
+if ($ARGV[0] eq "-frstats") {
+
+    if (@ARGV != 4) {
+	print STDERR "fr.mklists -frstats CONFIG.master TMPPATH CONF-CCD.imstats\n";
+	&escape;
+    }
+
+    $infile  = $ARGV[1];
+    $tmppath = $ARGV[2];
+    $outfile = $ARGV[3];
+
+    open (FILE, "$infile");
+    @inlist = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$outfile");
+    foreach $name (@inlist) { 
+	($path, $root, $mode, $status) = split (" ", $name);
+	printf FILE "%s/%s.imstats\n", $tmppath, $root;
+    }
+    close (FILE);
+    &goodbye;
+}
+
+# create list of input stats files 
+if ($ARGV[0] eq "-maplist") {
+
+    if (@ARGV != 4) {
+	print STDERR "fr.mklists -maplist CONFIG.master TMPPATH CONFIG.maplists\n";
+	&escape;
+    }
+
+    $infile  = $ARGV[1];
+    $tmppath = $ARGV[2];
+    $outfile = $ARGV[3];
+
+    open (FILE, "$infile");
+    @inlist = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$outfile");
+    foreach $name (@inlist) { 
+	($path, $root, $mode, $status) = split (" ", $name);
+	printf FILE "%s/%s.maplist 1\n", $tmppath, $root;
+    }
+    close (FILE);
+    &goodbye;
+}
+
+&escape ("unknown mode $ARGV[0]");
+
+###########################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub escape {
+    print STDERR "ERROR: @_\n";
+    exit 1;
+}
+
+sub goodbye {
+    print STDERR "SUCCESS @_\n";
+    exit 0;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mkmodes
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mkmodes	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.mkmodes	(revision 16632)
@@ -0,0 +1,146 @@
+#!/usr/bin/env perl
+
+{ # grab the command line arguments:
+    $elconf = "";
+    $elixcf = "-c /h/eugene/.ptolemyrc";
+    @tARGV = ();
+    for (; @ARGV > 0; ) {
+	
+	# grab elixir/ptolemy config option -c 
+	if ($ARGV[0] eq "-c") {
+	    shift;
+	    $elixcf = "-c $ARGV[0]";
+	    shift;
+	    next;
+	}
+	
+	# grab elixir/ptolemy config option -C 
+	if ($ARGV[0] eq "-C") {
+	    @opt = (@opt, $ARGV[0]);
+	    shift;
+	    @opt = (@opt, $ARGV[0]);
+	    $elconf = $ARGV[0];
+	    shift;
+	    next;
+	}
+	
+	# grab elixir/ptolemy config option -D
+	if ($ARGV[0] eq "-D") {
+	    @opt = (@opt, $ARGV[0]);
+	    shift;
+	    @opt = (@opt, $ARGV[0]);
+	    shift;
+	    @opt = (@opt, $ARGV[0]);
+	    shift;
+	    next;
+	}
+	
+	@tARGV = (@tARGV, $ARGV[0]);
+	shift;
+    }
+    @ARGV = @tARGV;
+    $elixir = join (" ", $elixcf, @opt);
+}
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 3) { die "USAGE: fr.mkmodes (maplist) (mode.fits) (mode.list)\n" }
+
+# assign the command line arguments
+$list = $ARGV[0];
+$output = $ARGV[1];
+$modes = $ARGV[2];
+
+# find the appropriate script file
+$confdir = `gconfig $elixir -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/modes.pro";
+$Nccd = `cameraconfig $elixir -Nccd`; chop ($Nccd);
+
+# load in list of input image lists
+open (LIST, $list);
+@list = <LIST>;
+close (LIST);
+
+# if mode list exists, load it in and use the selected modes
+# to set the new default selection
+$GotModes = 0;
+if (-e $modes) {
+    open (LIST, $modes);
+    @modes = <LIST>;
+    close (LIST);
+    $GotModes = 1;
+}
+
+# send commands to mana:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+
+# create a mana list of input file names
+print MANA "list names\n";
+$Nimages = 0;
+foreach $line (@list) {
+    ($name, $status) = split (" ", $line);
+    if ($status) { print MANA " $name\n"; }
+    $Nimages ++;
+}
+print MANA "end\n";
+
+# create a mana list of input file names
+print MANA "macro go\n";
+print MANA "  mkimage $output\n";
+print MANA "  exit 0\n";
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR running mana\n";
+    exit 1;
+}
+
+# create new list of modes.  if modes existed, use selected modes, otherwisaudio/x-pn-realaudio-plugine first 8:
+$DefaultStatus = 1;
+open (LIST, ">$modes");
+for ($i = 0; $i < $Nimages; $i++) {
+    # this is just a little funny: there is not a 1-1 relationship 
+    # between the selected images and the modes in this selection.
+    # only the first few modes will be significant, so we are just
+    # cutting of the few end modes
+    if ($i >= 8) { $DefaultStatus = 0; }
+    if ($GotModes) {
+	($mode, $status) = split (" ", $modes[$i]);
+	print LIST "$mode $status\n";
+    } else {
+	print LIST "$i $DefaultStatus\n";
+    }
+}
+close (LIST);
+
+print STDOUT "SUCCESS: finished with fr.detrend\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "\n";
+    print "USAGE: fr.mkmodes (list) (output) (modes)\n";
+    print " list:   list of lists - each list contains names of the input images (*.map/*.fits)\n";
+    print " output: master image of orthonormal modes\n";
+    print " modes:  list of modes in output, with status\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.modesave
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.modesave	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.modesave	(revision 16632)
@@ -0,0 +1,78 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 6) { &usage (); }
+
+# assign the command line arguments
+$modefits  = $ARGV[0];
+$modelist  = $ARGV[1];
+$modesave  = $ARGV[2];
+$startime  = $ARGV[3];
+$stoptime  = $ARGV[4];
+$filter    = $ARGV[5];
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/modes.pro";
+
+# load in list of modes
+open (LIST, $modelist);
+@modelist = <LIST>;
+close (LIST);
+
+$Nmode = 8;
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+
+print MANA "macro go\n";
+print MANA "\$filter = $filter\n";
+print MANA "\$start = \"$startime\"\n";
+print MANA "\$stop = \"$stoptime\"\n";
+print MANA "\$Nmode = $Nmode\n";
+for ($i = 0; $i < $Nmode; $i++ ) {
+    ($mode, $status) = split (" ", $modelist[$i]);
+    if ($status) {
+	print MANA "\$mode$i = 1\n";
+    } else {
+	print MANA "\$mode$i = 0\n";
+    }
+}
+print MANA "rd U $modefits\n";
+print MANA "savemodes $modesave\n";
+print MANA "exit 0\n";
+
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR problem with fr.modesave\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.modesave\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fr.modesave (mode.fits) (mode.list) (mode.mef.fits) (start) (stop) (filter)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.modestats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.modestats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.modestats	(revision 16632)
@@ -0,0 +1,98 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 6) { &usage (); }
+
+# assign the command line arguments
+$imlist    = $ARGV[0];
+$modefits  = $ARGV[1];
+$modelist  = $ARGV[2];
+$modejpg   = $ARGV[3]; # root of jpg images
+$residjpg  = $ARGV[4]; # root of jpg images
+$inmapjpg  = $ARGV[5]; # root of jpg images
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/modes.pro";
+
+# test named Xserver, or start vnc on specified machine
+$xhost=`gconfig -q XHOST`; chop ($xhost);
+$xdisp=`gconfig -q XDISP`; chop ($xdisp);
+if (vsystem ("xdpyinfo -display $xdisp >& /dev/null")) {
+    print STDERR "X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# load in list of input image lists
+open (LIST, $imlist);
+@imlist = <LIST>;
+close (LIST);
+
+# load in list of input image lists
+open (LIST, $modelist);
+@modelist = <LIST>;
+close (LIST);
+$Nmode = 0;
+foreach $line (@modelist) {
+    ($mode, $status) = split (" ", $line);
+    if ($status) { $Nmode ++; }
+}
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "macro go\n";
+
+# we'll use the default 8 to generate the jpgs of the modes
+print MANA "jpgmodes $modefits $modejpg\n";
+
+system ("rm -f $residjpg");
+system ("rm -f $inmapjpg");
+
+# reset $Nmode for the actual number desired
+print MANA "\$Nmode = $Nmode\n";
+print MANA "getmodes\n";
+for ($i = 0; $i < @imlist; $i++) {
+    ($name, $status) = split (" ", $imlist[$i]);
+    $jpgname = sprintf "%s.%03d.jpg", $residjpg, $i;
+    system ("basename $jpgname >> $residjpg");
+    $srcname = sprintf "%s.%03d.jpg", $inmapjpg, $i;
+    system ("basename $srcname >> $inmapjpg");
+    print MANA "jpgresid $name $jpgname $srcname\n";
+}
+print MANA "exit 0\n";
+
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR problem with fr.modestats\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with fr.modestats\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: fr.modestats (map.list) (mode.fits) (mode.list) (modes[.NNN.jpg]) (resid[.NNN.jpg]) (source[.NNN.jpg])\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.select
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.select	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.select	(revision 16632)
@@ -0,0 +1,325 @@
+#!/usr/bin/env perl
+
+# check the usage
+if ($ARGV[0] eq "-h") { usage (); }
+if ($ARGV[0] eq "-help") { usage (); }
+if (@ARGV != 5) { die "ERROR: USAGE: fr.select (filter) (start) (stop) (mode) (output)\n"; }
+
+# assign the command line arguments
+$filter = $ARGV[0];
+$start  = $ARGV[1];
+$stop   = $ARGV[2];
+$mode = "\U$ARGV[3]\E";
+if (($mode ne "MEF") && ($mode ne "SPLIT")) { die "ERROR: mode must be either SPLIT or MEF\n";}
+$output = $ARGV[4];
+
+# global constants
+# these probably should go in the config files eventually.
+$MAX_CNTS = 60000;
+$MAX_FLUX = 40;
+
+# define some of the relevant parameters
+$tmp = `filtnames $filter`; chop $tmp;
+if ($?) { die "ERROR: invalid filter $filter\n"; }
+$filter = $tmp;
+
+# recipe file defines detrend types & cutoff exptime values
+$recipefile = `gconfig DETREND_RECIPES`; chop $recipefile;
+if ($?) { die "ERROR: missing DETREND_RECIPES in configuration\n"; }
+
+# extract filter extras list
+($tmp, $tmp, $tmp, $extras) = split (" ", `gconfig -c $recipefile $filter`);
+if ($?) { die "ERROR: missing detrend recipe for $filter\n"; }
+
+# grab extra values:
+($detype, $MIN_FLUX, $MIN_CNTS) = split (",", $extras);
+if ("\U$detype\E" ne "FRINGE") { die "ERROR: fringe extras are missing\n"; }
+
+# relevant camera parameters
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+if ($?) { die "error in config\n"; }
+
+($Naxis1, $Naxis2) = split (" ", `cameraconfig -axes`);
+if ($?) { die "error in config\n"; }
+
+@ccds = split (" ", `cameraconfig -ccds`);
+if ($?) { die "error in config\n"; }
+
+@good = ();
+@marginal = ();
+
+# special list to skip specific chips
+$CHIPSKIP     = `gconfig CHIP_SKIP_LIST`; chop $CHIPSKIP;
+@chipskip = ();
+if (-e $CHIPSKIP) { 
+    open (FILE, $CHIPSKIP);
+    @chipskip = <FILE>;
+    close (FILE);
+    foreach $chip (@chipskip) { chop $chip; }
+}
+
+$criteria = "-type object -mode $mode -trange $start $stop -filter $filter";
+
+# define filter lines.
+@filtline = ();
+# convert given filter name to list of possible names:
+$answer = `filtnames $ARGV[0] -all`;
+@filtlist = split (" ", $answer);
+
+foreach $name (@filtlist) {
+    $line = "-type object -mode $mode -trange $start $stop -filter $name";
+    push @filtline, $line;
+}
+
+# run selection on each possible $filtline
+@list = ();
+foreach $line (@filtline) {
+    @tlist = `imsearch -ccd $ccds[0] $line`;
+    @list = (@list, @tlist);
+}
+$Nlist = @list;
+print STDERR "found $Nlist images\n";
+
+FRAME:
+    foreach $image (@list) {
+    @words = split (" ",$image);
+    
+    # poor way to search for all images
+    if ($mode eq "SPLIT") {
+	# all $Nccd images must exist on disk, split files are assumed to be 
+	# in a subdirectory of their own, .fits extension assumed
+	@answer = <$words[4]/*.fits>;
+	if (@answer != $Nccd) { print STDERR "$words[5] rejected: missing images\n"; next FRAME; }
+    }
+
+    # images have to have the correct dimensions
+    if ($mode eq "SPLIT") {
+	$answer = `echo $words[4]/$words[5] | fields NAXIS1 NAXIS2`;
+    } else {
+	$answer = `echo $words[4]/$words[5] | fields -x 0 NAXIS1 NAXIS2`;
+    }
+    ($tmp, $Nx, $Ny) = split (" ", $answer);
+    if (($Nx != $Naxis1) || ($Ny != $Naxis2)) { print STDERR "$words[5] rejected: wrong dimensions\n"; next FRAME; }
+
+    # $match is a word unique to the full mosaic image (the rootdir for split, the image for mef) 
+    if ($mode eq "split") { 
+	@answer = split ("/", $words[4]); 
+	$match = $answer[-1]; 
+    } else { 
+	$match = $words[5]; 
+    }
+    @list2 = `imsearch -name $match`;
+    
+  CCD:
+    foreach $ccd (@list2) {
+	@words2 = split (" ", $ccd);
+	foreach $chipskip (@chipskip) { 
+	    if ($words2[3] eq $chipskip) { next CCD; }
+	}
+	
+	$cnts = $words2[11];
+	$flux = $words2[11] / $words2[7];
+	# test for acceptable flux range
+	if ($cnts < $MIN_CNTS) { print STDERR "$words[5] rejected: cnts too low:  $cnts vs $MIN_CNTS\n"; next FRAME; }
+	if ($cnts > $MAX_CNTS) { print STDERR "$words[5] rejected: cnts too high: $cnts vs $MAX_CNTS\n"; next FRAME; }
+	if ($flux < $MIN_FLUX) { print STDERR "$words[5] rejected: flux too low:  $flux vs $MIN_FLUX\n"; next FRAME; }
+	if ($flux > $MAX_FLUX) { print STDERR "$words[5] rejected: flux too high: $flux vs $MAX_FLUX\n"; next FRAME; }
+    }
+
+    $fullname = "$words[4]/$words[5]";
+    $root = gt_names ($fullname, "root", $mode);
+    $path = gt_names ($fullname, "path", $mode);
+    @good = (@good, "$path $root $mode");
+}
+
+open (LIST, ">$output");
+# write output to Nccd list files 
+# keep a random sample of roughly 60 images:
+$Nselect = @good;
+for ($i = 0; $i < $Nselect; $i++) {
+    if (rand ($Nselect) < 60) {
+	print LIST "$good[$i]\n";
+    }
+}
+close (LIST);
+print STDERR "SUCCESS\n\n";
+exit 0;
+
+# cfht MEF/SPLIT name utilities:
+
+sub gt_names {
+    # in: filename mode type
+    # out: word
+
+    my ($value);
+
+    $value = "";
+    if ($_[2] eq "MEF")   { $value = mefnames ($_[0], $_[1]); }
+    if ($_[2] eq "SPLIT") { $value = splitnames ($_[0], $_[1]); }
+    
+    return $value;
+}
+
+sub mefnames {
+    # in: (/path/file.fits) (mode) 
+    # out: word
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer);
+
+    # split rootdir and filename:
+    my (@words) = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 1; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-1]";
+	$answer =~ s/.fits$//;
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	if (! -e $fullname) {
+	    return (0);
+	}
+	$answer = `echo $fullname | fields NEXTEND`;
+	@words = split (" ", $answer);
+	if ($words[1] eq "") {
+	    return (0);
+	}
+	return ($words[1]);
+    }
+    
+    return (0);
+}
+
+sub splitnames {
+    # in: (/path/file) (mode) 
+    # out: word
+    # /path/file is directory containing Nccd fits images
+
+    my($fullname) = $_[0];
+    my($mode) = $_[1];
+    my($answer, $N, $tmpname, @imlist, @words);
+
+    # split rootdir and filename:
+    @words = split ("/", $fullname);
+    $N = @words;
+
+    if ($mode eq "path") {
+	$answer = "";
+	for ($i = 0; $i < $N - 2; $i++) {
+	    $answer = $answer . $words[$i] . "/";
+	}
+	chop ($answer); # strip off last /
+	if ($answer eq "") { $answer = "."; }
+	return ($answer);
+    }
+    
+    if ($mode eq "root") {
+	$answer = "$words[$N-2]";
+	return ($answer);
+    }
+    
+    if ($mode eq "Nccd") {
+	
+	$tmpname = "$fullname/$words[$N-1]";
+	@imlist = <$tmpname??.fits>;
+
+	$Nccd = @imlist;
+	return $Nccd;
+    }
+    
+    return (0);
+}
+
+sub ckimtype {
+    # in: (/path/file)
+    # out: MEF | SPLIT | SINGLE | (NULL)
+    
+    my ($answer, $name, $value);
+    my ($file) = $_[0];
+
+    if (! -e $file) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+
+    # if /path/file is a directory, it is split:
+    if (-d $file) { return "SPLIT"; }
+
+    # check that the file is a FITS image
+    $answer = `file -L $file`;
+    if ($?) { 
+	print STDOUT "can't open file\n";
+	return ""; 
+    }
+    ($name, $value) = split (" ", $answer);
+    if ($value ne "FITS") { 
+	print STDOUT "not a valid image\n";
+	return ""; 
+    }
+    
+    # check for NAXIS = 0 (MEF) 
+    $answer = `echo $file | fields NAXIS`;
+    # if ($?) { return ""; }
+    ($name, $value) = split (" ", $answer);
+    if ($value eq 0) { return "MEF"; }
+    
+    if ($value == 2) { return "SINGLE"; }
+
+    print STDOUT "not a valid image\n";
+    return "";
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    die "@_";
+}
+
+sub usage {
+    print "USAGE: fr.select (filter) (start) (stop) (mode) (output)\n";
+    print " filter: R I Z (etc)\n";
+    print " start:  start date (yyyy/mm/dd,hh:mm:ss)\n";
+    print " stop:   stop date\n";
+    print " mode:   MEF or SPLIT\n";
+    print " output: output file name\n";
+    exit 1;
+}
+
+# we need to select the list of images which satisfy a few criteria:
+# 1) all 12 CCDs must exist
+# 2) stats must be measured for each
+# 3) stats for all 12 must be within range (2000 - 40000)
+# 4) NAXIS1 == 2080 && NAXIS2 == 4128
+
+# fr.select: 
+# this program takes a list of criteria which define a fringe /
+# skyring frame, and an output filename, and fills the file with all
+# images that fit the given criteria.  It checks to make sure that the
+# images have flux and counts in the appropriate range, and that all
+# CCDs are available, and that they have the correct dimensions.
+
+# the output file consists of lines with the following entries:
+# (path) (root) (mode)
+# path: complete path to the image
+# root: base name for file - MEF: root.fits, SPLIT: root/rootNN.fits
+# mode: MEF / SPLIT
+
+ 
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/fr.smooth
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/fr.smooth	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/fr.smooth	(revision 16632)
@@ -0,0 +1,196 @@
+#!/usr/bin/env perl
+
+# this program converts the binned fringe image to an unbinned image,
+# adds necessary header information.  it could be used to smooth the 
+# image based on the filter and chip, if needed
+
+$version = 2.0;
+
+if (@ARGV != 8) { &escape ("ERROR: USAGE: fr.smooth (infile) (filter) (CCD) (unbin) (start) (stop) (frstats) (outfile)"); }
+
+$infile  = $ARGV[0];  # input image file
+$filter  = $ARGV[1];  # filter for image
+$ccd     = $ARGV[2];  # ccd number
+$binning = $ARGV[3];  # binning of input image
+$start   = $ARGV[4];  # valid time range start
+$stop    = $ARGV[5];  # valid time range stop
+$frstats = $ARGV[6];  # fringe statistics file
+$outfile = $ARGV[7];  # output image file
+
+@ccds   = split (" ", `cameraconfig -ccds`);
+@ccdn   = split (" ", `cameraconfig -ccdn`);
+$Nccd   = @ccds;
+
+$CCDKEYWORD = `gconfig CCDNUM-KEYWORD`; chop $CCDKEYWORD;
+$dbmode = `gconfig DETREND-DB-MODE`; chop $dbmode;
+
+@frstats = `cat $frstats`;
+for ($i = 0; $i < @frstats; $i++) {
+    if ($frstats[$i] =~ m|^\s*\#|) { 
+	($tmp, $entry, $value) = split (" ", $frstats[$i]);
+	if ($entry eq "REF_CHIP") { $RefChip = $ccds[$value]; }
+	splice @frstats, $i, 1; $i--; 
+    }
+}
+($C0, $C1, $Fs, $Fr) = split (" ", $frstats[$ccd]);
+
+# find fringe-point file
+$frpts  = `detsearch -quiet -image $infile $ccds[$ccd] split -type frpts`; chop $frpts;
+if ($?) { &escape ("can't get fringe points for image"); }
+($name, $Fs, $Fr) = split (" ", `getfringe $infile $ccds[$ccd] $frpts $binning`);
+
+$mask = `detsearch -ccd $ccds[$ccd] -type mask -time $start -select -quiet`; chop $mask;
+if ($?) { &escape ("ERROR: can't find mask for image $1"); }
+
+# unbin and insert header keywords
+open (MANA, "|mana --norc");
+
+# convert BIASSEC string to x1, x2, y1, y2 vars
+print MANA "macro parsesec\n";
+print MANA "  \$f = \$1\n";
+print MANA "  getchr \$f : n\n";
+print MANA "  substr \$f 1 {\$n-1} x1\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f , n\n";
+print MANA "  substr \$f 1 {\$n-1} x2\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f : n\n";
+print MANA "  substr \$f 1 {\$n-1} y1\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+  
+print MANA "  getchr \$f ] n\n";
+print MANA "  substr \$f 1 {\$n-1} y2\n";
+print MANA "  strlen \$f N\n";
+print MANA "  substr \$f \$n {\$N-\$n} f\n";
+print MANA "end\n";
+
+print MANA "list kernel\n";
+print MANA "  0.025\n";
+print MANA "  0.100\n";
+print MANA "  0.025\n";
+print MANA "  0.100\n";
+print MANA "  0.500\n";
+print MANA "  0.100\n";
+print MANA "  0.025\n";
+print MANA "  0.100\n";
+print MANA "  0.025\n";
+print MANA "end\n";
+print MANA "macro go\n";
+print MANA " \$CCDKEYWORD = $CCDKEYWORD\n";
+# read in mask, rebin
+if ($dbmode eq "MEF") {
+    print MANA " rd mask $mask -n $ccds[$ccd]\n";
+} else {
+    print MANA " rd mask $mask\n";
+}
+print MANA " keyword mask NAXIS1 nx2\n";
+print MANA " keyword mask NAXIS2 ny2\n";
+print MANA " rebin mask binmask $binning -norm\n";
+print MANA " clip binmask 0.9 0.0 1.1 0.0\n";
+
+print MANA " rd a $infile\n";
+print MANA " set a = a * binmask\n";
+# print MANA " set a = a * binmask + $Fs*not(binmask)\n";
+print MANA " rebin a A -$binning\n";
+print MANA " keyword A NAXIS1 nx1\n";
+print MANA " keyword A NAXIS2 ny1\n";
+print MANA " delete a\n";
+
+print MANA " extract A b 0 0 \$nx1 \$ny1 0 0 \$nx2 \$ny2\n";
+print MANA " keyword b DATASEC line\n";
+print MANA " parsesec \$line\n";
+print MANA " sprint newline \"[%d:%d,%d:%d]\" {\$x1*2} {\$x2*2} {\$y1*2} {\$y2*2}\n";
+print MANA " keyword b DATASEC -w \$newline\n";
+
+@time  = localtime;
+$now   = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1], $time[0];
+$elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+
+@word = split ("/", $frpts);
+$frpts = $word[-1];
+
+# add keywords for fringe amplitude, fit, etc
+print MANA " keyword b FRNG_C0  -wf $C0\n";
+print MANA " keyword b FRNG_C1  -wf $C1\n";
+print MANA " keyword b FRNG_SKY -wf $Fs\n";
+print MANA " keyword b FRNG_RNG -wf $Fr\n";
+print MANA " keyword b FRNG_REF -w  $RefChip\n";
+print MANA " keyword b FRNG_PTS -w  \"$frpts\"\n";
+print MANA " keyword b TVSTART  -w  $start\n";
+print MANA " keyword b TVSTOP   -w  $stop\n";
+print MANA " keyword b EL_SYS   -w  \"$elsys\"\n";
+print MANA " keyword b EL_SMTH  -w  \"$version\"\n";
+print MANA " keyword b REL_DATE -w  \"$now\"\n";
+
+# add comments for the new keywords
+print MANA " keyword b FRNG_C0  -wc \"Fringe Cross Correlation linear fit term\"\n";
+print MANA " keyword b FRNG_C1  -wc \"Fringe Cross Correlation linear fit term\"\n";
+print MANA " keyword b FRNG_SKY -wc \"Fringe Frame sky level\" \n";
+print MANA " keyword b FRNG_RNG -wc \"Fringe Frame fringe strength\"\n";
+print MANA " keyword b FRNG_REF -wc \"Fringe Cross Correlation reference chip\"\n";
+print MANA " keyword b FRNG_PTS -wc \"Fringe Point File\"\n";
+print MANA " keyword b TVSTART  -wc \"data validity start time\"\n";
+print MANA " keyword b TVSTOP   -wc \"data validity stop time\"\n";
+print MANA " keyword b OBSTYPE  -w  \"FRINGE\"\n";
+print MANA " keyword b EXPTYPE  -w  \"FRINGE\"\n";
+print MANA " keyword b EL_SYS   -wc \"Elixir System Version\"\n";
+print MANA " keyword b EL_SMTH  -wc \"Elixir Smooth Version\"\n";
+print MANA " keyword b REL_DATE -wc \"UTC Release Date\"\n";
+
+print MANA " keyword b COMMENT  -ws \"Fringe (NN) = C0 + C1 * Fringe (REF)\"\n";
+print MANA " keyword b COMMENT  -ws \"Elixir:fr.smooth version $version\"\n";
+print MANA " keyword b COMMENT  -ws \"Elixir Fringe Frame\"\n";
+print MANA " keyword b COMMENT  -ws \"Elixir smoothing: 3x3 kernel (1): 0.025, 0.100, 0.025\"\n";
+print MANA " keyword b COMMENT  -ws \"Elixir smoothing: 3x3 kernel (2): 0.100, 0.500, 0.100\"\n";
+print MANA " keyword b COMMENT  -ws \"Elixir smoothing: 3x3 kernel (3): 0.025, 0.100, 0.025\"\n";
+
+print MANA " stat b - - - -\n";
+print MANA " \$range = \$MAX - \$MIN + 4\n";
+print MANA " if (\$range < 100)\n";
+print MANA "  \$range = 100\n";
+print MANA " end\n";
+print MANA " sprintf bscale %9.4f {\$range / 2^16}\n";
+print MANA " \$bzero = \$bscale * int ((\$MIN + \$range / 2) / \$bscale)\n";
+
+print MANA " wd b $outfile -bzero \$bzero -bscale \$bscale \n";
+print MANA " exit 0\n";
+
+print MANA "end\n";
+print MANA "macro list go\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) { &escape ("ERROR: failure running mana"); }
+
+print STDERR "SUCCESS\n";
+exit 0;
+
+####################################################
+
+@temp = ();
+sub mktemp {
+
+    my ($base) = $_[0];
+    my ($name);
+    $name = `mktemp /tmp/$base.XXXXXX`;
+    chop $name;
+
+    push @temp, $name;
+    return $name;
+}
+
+sub escape {
+    $message = $_[0];
+    foreach $name (@temp) {
+	unlink ($name);
+    }
+    die "$message\n";
+}
+
+#print MANA " kern a kernel \n";
+#print MANA " set b = a*mask + $Fs*not(mask)\n";
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/gastro.raw
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/gastro.raw	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/gastro.raw	(revision 16632)
@@ -0,0 +1,79 @@
+#!/usr/bin/env perl
+
+$config = "";
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-C") {
+        $config = "-C $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-c") {
+        $config = "-c $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-D") {
+        $config = "-D $ARGV[1] $ARGV[2]";
+        shift; shift; shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 1) { die "USAGE: gastro.raw (filename)\n"; }
+
+if (! -e $ARGV[0]) { die "ERROR: file $ARGV[0] missing\n"; }
+
+($tmp, $RA, $DEC, $EXT) = split (" ", `echo $ARGV[0] | fields RA DEC EXTNAME`);
+
+if ($RA  eq "") { die "ERROR: missing RA in header\n"; }
+if ($DEC eq "") { die "ERROR: missing DEC in header\n"; }
+if ($EXT eq "") { die "ERROR: missing EXTNAME in header\n"; }
+
+while ($RA  =~ s|\:| |) { }
+while ($DEC =~ s|\:| |) { }
+
+($ra, $dec) = split (" ", `echo $RA $DEC | radec -hms`);
+
+@ccdx = split (" ", `cameraconfig $config -xoff`);
+@ccdy = split (" ", `cameraconfig $config -yoff`);
+@dx   = split (" ", `cameraconfig $config -xflip`);
+@dy   = split (" ", `cameraconfig $config -yflip`);
+
+$DX = `cameraconfig $config -axis0`; chop $DX;
+$DY = `cameraconfig $config -axis1`; chop $DY;
+$NX = `cameraconfig $config -mosaicx`; chop $NX;
+$NY = `cameraconfig $config -mosaicy`; chop $NY;
+
+$N = `cameraconfig $config -N $EXT`; chop $N;
+
+$Ro = $ra  - ($ccdx[$N] - $NX/2)*$DX*0.187/3600;
+$Do = $dec + ($ccdy[$N] - $NY/2)*$DY*0.187/3600;
+$Theta = 4;
+$P1 = -1;
+$P2 =  1;
+if ($dx[$N] == 1) {
+    $P1 =  1;
+    $Theta = $Theta * -1;
+}
+if ($dy[$N] == 1) {
+    $P2 =  -1;
+    $Theta = $Theta * -1;
+}
+
+vsystem ("gastro -v $config $ARGV[0] -coords $Ro $Do -D CCD_PC1_1 $P1 -D CCD_PC2_2 $P2 -D ROT_ZERO $Theta");
+exit 0;
+
+############
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    die "@_";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/getfringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/getfringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/getfringe	(revision 16632)
@@ -0,0 +1,118 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 4) { &escape ("USAGE: getfringe (input) (ccd) (frpts) (bin)"); }
+
+# assign the command line arguments
+$input   = $ARGV[0];
+$ccd     = $ARGV[1];
+$frpts   = $ARGV[2];
+$binning = $ARGV[3];
+
+# temporary files for flips input/output
+$temp1   = mktemp ("\@getfringe");
+$temp2   = mktemp ("getfringe");
+$temp3   = mktemp ("getfringe");
+
+# create input list file
+@coords = `gtfringetable $frpts $ccd $binning`;
+if ($?) { &escape ("failure to extract fringe point table"); }
+open (FILE, ">$temp1");
+foreach $line (@coords) {
+    chop ($line);
+    print FILE "$input $line\n";
+}
+close (FILE);
+
+# box size for stats:
+$dx = 1 + 2*int(0.5*25/$binning);
+
+# find input parameter file
+$paramfile = `gconfig FLIPS_PARAM_IMSTAT`; chop $paramfile;
+if ($?) { &escape ("paramfile FLIPS_PARAM_IMSTAT not in config system"); }
+
+# fill in missing keywords
+open (FILE, "$paramfile");
+@params = <FILE>;
+close (FILE);
+
+foreach $line (@params) {
+    chop ($line);
+    $line =~ s|INFILE|$temp1|;
+    $line =~ s|SIZEX|$dx|;
+    $line =~ s|SIZEY|$dx|;
+    $line =~ s|OUTFILE|$temp3|;
+}
+
+# save new parameter file
+open (FILE, ">$temp2");
+foreach $line (@params) {
+    print FILE "$line\n";
+}
+close $temp2;
+
+# run imstat (change to flips2 version)
+system ("imstat $temp2 > /dev/null");
+if ($?) { &escape ("failure in imstat"); }
+
+# accumulate sky, fringe
+open (FILE, "$temp3");
+@stats = <FILE>;
+@sky    = ();
+@fringe = ();
+for ($i = 0; $i < @stats; $i++) {
+    ($name, $max) = split (" ", $stats[$i]);
+    $i ++;
+    ($name, $min) = split (" ", $stats[$i]);
+
+    $fringe = $max - $min;
+    push @sky, $min;
+    push @fringe, $fringe;
+}
+
+# calculate fringe sigma:
+$F1 = $F2 = 0;
+foreach $fringe (@fringe) { 
+    $F1 += $fringe;
+    $F2 += $fringe*$fringe;
+}
+$N = @fringe;
+$F1 = $F1 / $N;
+$dfringe = sqrt ($F2/$N - $F1*$F1);
+
+# calculate fringe & sky medians
+@fringe = sort {$a <=> $b} @fringe;
+$fringe = $fringe[int(0.5*$N)];
+@sky = sort @sky;
+$sky = $sky[int(0.5*$N)];
+
+# write out results 
+print STDOUT "$input $sky $fringe $dfringe\n";
+
+&goodbye;
+
+########
+
+@temp = ();
+sub mktemp {
+
+    my ($base) = $_[0];
+    my ($name);
+    $name = `mktemp /tmp/$base.XXXXXX`;
+    chop $name;
+
+    push @temp, $name;
+    return $name;
+}
+
+sub escape {
+    $message = $_[0];
+    foreach $name (@temp) {
+	unlink ($name);
+    }
+    die "$message\n";
+}
+
+sub goodbye {
+    foreach $name (@temp) { unlink ($name); }
+    exit 0;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/grab.keywords
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/grab.keywords	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/grab.keywords	(revision 16632)
@@ -0,0 +1,243 @@
+#!/usr/bin/env perl
+
+$version = 2.0;
+
+if (@ARGV != 3) { die "USAGE: grab.keywords (infile) (cmproot) (outfile)\n" ; }
+
+$infile  = $ARGV[0];
+$cmproot = $ARGV[1];
+$outfile = $ARGV[2];
+
+# $infile  is the image.fits file
+# $cmproot is the rootname of the processed output for this file (contains astrom keywords)
+# $outfile is the output header data file
+
+if ($cmproot eq "phu") { goto photometry; }
+
+# grab astrometry keywords from $cmpfile:
+@header = ();
+
+ CMPTEST: {
+     # make this look for hdx files in hdxdir (fix dads.keywords as well)
+     # need to extract all header files first
+
+     # try *.smp:
+     $cmpfile = "$cmproot.smp";
+     if (-e $cmpfile) {
+	 $answer = `echo $cmpfile | fields NASTRO`;
+	 @words = split (" ", $answer);
+	 if ($words[1] > 0) { last CMPTEST; }
+     }
+    
+     # try *.cmp:
+     $cmpfile = "$cmproot.cmp";
+     if (-e $cmpfile) {
+	 $answer = `echo $cmpfile | fields NASTRO`;
+	 @words = split (" ", $answer);
+	 if ($words[1] > 0) { last CMPTEST; }
+     }
+
+     $cmpfile = "";
+ }
+
+if ($cmpfile) { @header = `fhead $cmpfile`; }
+
+# set some default values:
+@astrom = ();
+$fsatur = 0;
+$flimit = 0;
+$exptime = 0;
+$Nastro = 0;
+
+# search for the appropriate lines:
+foreach $line (@header) {
+    
+    # astrometry keywords which are copied directly
+    if ($line =~ /CTYPE1  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CTYPE2  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRPIX1  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRPIX2  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRVAL1  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRVAL2  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /NASTRO  =/) { @astrom = (@astrom, $line); $Nastro = substr ($line, 10, 21); }
+    if ($line =~ /CERROR  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /EQUINOX =/) { @astrom = (@astrom, $line);}
+
+    # convert the PC00i00j matrix & CDELTi to CDi_j
+    if ($line =~ /PC001001=/) { $pc11 = substr ($line, 10, 21); }
+    if ($line =~ /PC001002=/) { $pc12 = substr ($line, 10, 21); }
+    if ($line =~ /PC002001=/) { $pc21 = substr ($line, 10, 21); }
+    if ($line =~ /PC002002=/) { $pc22 = substr ($line, 10, 21); }
+    if ($line =~ /CDELT1  =/) { $cd1  = substr ($line, 10, 21); }
+    if ($line =~ /CDELT2  =/) { $cd2  = substr ($line, 10, 21); }
+
+    # save these values for the photometry section
+    if ($line =~ /FSATUR  =/) { $fsatur = substr ($line, 10, 21); }
+    if ($line =~ /FLIMIT  =/) { $flimit = substr ($line, 10, 21); }
+    if ($line =~ /EXPTIME =/) { $exptime = substr ($line, 10, 21); }
+
+    # we will not use the FWHM values until those are better defined...
+    if (0) {
+	if ($line =~ /FWHM_X  =/) { 
+	    $tmp = substr ($line, 10, 21); 
+	    $tmp = $tmp * 0.2;
+	    $line = sprintf "FWHM_A  = %20G / stellar profile major axis (arcsec)           \n", $tmp; 
+	    @astrom = (@astrom, $line);
+	}
+	if ($line =~ /FWHM_Y  =/) { 
+	    $tmp = substr ($line, 10, 21); 
+	    $tmp = $tmp * 0.2;
+	    $line = sprintf "FWHM_B  = %20G / stellar profile minor axis (arcsec)           \n", $tmp; 
+	    @astrom = (@astrom, $line);
+	}
+	if ($line =~ /ANGLE   =/) { @astrom = (@astrom, $line);}
+    }
+}
+
+# check for validity of astrometry data
+if ($Nastro == 0) {
+    print STDERR "can't find all astrometry keywords from $cmproot\n";
+    $line = sprintf "COMMENT  Elixir:  no astrometry solution for this image\n"; 
+    @astrom = ($line);
+} else {
+    # convert the pc, cdelt terms to cd terms
+    $cd11 = $cd1*$pc11;
+    $cd12 = $cd2*$pc12;
+    $cd21 = $cd1*$pc21;
+    $cd22 = $cd2*$pc22;
+    $line = sprintf "CD1_1   = %20.5E / WCS Coordinate scale matrix                   \n", $cd11; @astrom = (@astrom, $line);
+    $line = sprintf "CD1_2   = %20.5E / WCS Coordinate scale matrix                   \n", $cd12; @astrom = (@astrom, $line);
+    $line = sprintf "CD2_1   = %20.5E / WCS Coordinate scale matrix                   \n", $cd21; @astrom = (@astrom, $line);
+    $line = sprintf "CD2_2   = %20.5E / WCS Coordinate scale matrix                   \n", $cd22; @astrom = (@astrom, $line);
+}
+
+# define a reference chip to grab the photometry data
+ photometry: 
+     if ($cmproot eq "phu") {
+	 $ccd = "phu";
+     } else {
+	 $ccd = `cameraconfig -ID 0`; chop $ccd;
+	 if ($?) { die ("error in camera config\n"); }
+     }
+
+# grab the appropriate photometry data
+@photom = ();
+@photlist = `photsearch -trans -image $infile $ccd split -equiv`;
+if ($?) { @photlist = (); }
+
+# check validity of photometry data
+$Nphot = @photlist;
+if ($Nphot == 0) {
+    print STDERR "can't get photometry data for this image\n";
+    $line = sprintf "COMMENT  Elixir: No photometry calibrations for this night & filter\n"; 
+    @photom = ($line);
+} else {
+    # parse the photometry data line
+    @words = split (" ", $photlist[$Nphot-1]);
+#   we conclude that the nightly zero point contains insufficient information 
+    $line = sprintf "PHOT_C  = %20.4F / Elixir zero point - measured for camera run \n", $words[2];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_CS = %20.4F / Elixir zero point - scatter                \n", $words[4];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_NS = %20d / Elixir zero point - N stars                  \n", $words[5];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_NM = %20d / Elixir zero point - N images                 \n", $words[6];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_C0 = %20.4F / Elixir zero point - nominal                \n", $words[3];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_X  = %20.4F / Elixir zero point - color term             \n", $words[7];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_K  = %20.4F / Elixir zero point - airmass term           \n", $words[8];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_C1 = '%-18s' / Elixir zero point - color 1               \n", $words[10];  @photom = (@photom, $line);
+    $line = sprintf "PHOT_C2 = '%-18s' / Elixir zero point - color 2               \n", $words[11]; @photom = (@photom, $line);
+    
+    if ($cmproot ne "phu") {
+	# is there was no cmpfile, we should not set the SAT and LIM values.
+	if ($exptime == 0) { 
+	    $line = sprintf "COMMENT   Photometric Analysis is incomplete for this image.\n";
+	    @photom = (@photom, $line);
+	    $line = sprintf "COMMENT   MAG_SAT and MAG_LIM cannot be determined.\n";
+	    @photom = (@photom, $line);
+	} else {
+	    # adjust fsatur & flimit values by phot data
+	    $fsatur = $fsatur - 25.0 + $words[2] + 2.5*log($exptime) / log(10.0);
+	    $line = sprintf "MAG_SAT = %20G / approx saturation (mag)                       \n", $fsatur; 
+	    @photom = (@photom, $line);
+	    
+	    $flimit = $flimit - 25.0 + $words[2] + 2.5*log($exptime) / log(10.0);
+	    $line = sprintf "MAG_LIM = %20G / approx completeness limit (mag)               \n", $flimit; 
+	    @photom = (@photom, $line);
+	}
+    }
+
+    # add some comments 
+    $line = sprintf "COMMENT   Formula for Photometry, based on keywords given in this header:      \n"; @photom = (@photom, $line);
+    $line = sprintf "COMMENT   m = -2.5*log(DN) + 2.5*log(EXPTIME)                                  \n"; @photom = (@photom, $line);
+    $line = sprintf "COMMENT   M = m + PHOT_C + PHOT_K*(AIRMASS - 1) + PHOT_X*(PHOT_C1 - PHOT_C2)   \n"; @photom = (@photom, $line);
+}
+
+# add generic Elixir comments:
+
+@time = localtime;
+$now = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1], $time[0];
+$elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+# $frpts  = `detsearch -quiet -image $infile $ccds[$ccd] split -type frpts`; chop $frpts;
+
+@comment = ();
+$line = sprintf "COMMENT  --------------- Elixir Analysis ---------------                \n"; @comment = (@comment, $line);
+$line = sprintf "COMMENT  Elixir: processing performed \@ CFHT, version $elsys           \n"; @comment = (@comment, $line);
+$line = sprintf "COMMENT  Elixir: version: $elsys                                        \n"; @comment = (@comment, $line);
+$line = sprintf "COMMENT  Elixir: processing date: $now                                  \n"; @comment = (@comment, $line);
+$line = sprintf "COMMENT  Elixir: website: http://www.cfht.hawaii.edu/Instruments/Elixir \n"; @comment = (@comment, $line);
+$line = sprintf "COMMENT  Elixir: email: elixir\@cfht.hawaii.edu                         \n"; @comment = (@comment, $line);
+$line = sprintf "COMMENT  Elixir: team: Eugene Magnier & Jean-Charles Cuillandre         \n"; @comment = (@comment, $line);
+$line = sprintf "DATEPROC= '$now' / Processing Date                                      \n"; @comment = (@comment, $line);
+$line = sprintf "EL_SYS  = '%-18s' / Elixir System Version                               \n", "$elsys"; @comment = (@comment, $line);
+# (line < 80)    12345678901234567890123456789012345678901234567890123456789012345678901234567890
+
+@output = (@comment, @astrom, @photom);
+$line = sprintf "COMMENT  --------------- Elixir Analysis (end) ---------------         \n"; @output = (@output, $line);
+
+# write output to file
+open (FILE, ">$outfile");
+foreach $line (@output) {
+    print FILE "$line";
+}
+close (FILE);
+print STDERR "wrote $outfile\n";
+
+exit 0;
+
+# given an image directory with a name like /path/output (a SPLIT):
+
+# for each ccd:
+
+# 1) get astrometry
+# 2) 
+
+#ckrunid 570965o/570965o00.fits
+#set dir=`gconfig -q -D RUNID 01Ak01 TMPDIR`
+#$dir/570965o/570965o00.cmp
+
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+
+
+sub junk {
+
+    # create the basic entries for a header
+    $line = sprintf "SIMPLE  =                    T / Standard FITS \n"; @output = (@output, $line);
+    $line = sprintf "BITPIX  =                    8 / no actual data in this file\n"; @output = (@output, $line);
+    $line = sprintf "NAXIS   =                    0 / Number of axes \n"; @output = (@output, $line);                                
+
+
+
+    # fill in the bottom of the header
+    $line = sprintf "END"; @output = (@output, $line);                                
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/imclean.cfht
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/imclean.cfht	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/imclean.cfht	(revision 16632)
@@ -0,0 +1,64 @@
+#!/usr/bin/env perl
+
+$config = "";
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-C") {
+        $config = "-C $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-c") {
+        $config = "-c $ARGV[1]";
+        shift; shift; next;
+    }
+    if ($ARGV[0] eq "-D") {
+        $config = "-D $ARGV[1] $ARGV[2]";
+        shift; shift; shift; next;
+    }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV < 3) { 
+    print STDERR "ERROR: USAGE: USAGE: imclean.cfht (fits) (obj) (cmp) [option]\n";
+    print STDERR "  corrects for errors with CD1_1, CRPIX1 on 12k for 51400 < MJD < 51540\n";
+    print STDERR "  also determines and inserts the photcode for the image\n";
+    exit 2;
+}
+
+# input image must already be in SPLIT mode
+
+# determine the photcode of this image:
+$photcode=`photcode $config -quiet $ARGV[0] 0 split`; chop $photcode;
+if ($?) { die "ERROR: cannot find photcode\n"; }
+
+# check if we need to correct the WCS terms (only CFH12K)
+($name, $id, $mjd) = split (" ", `echo $ARGV[0] | fields IMAGEID MJD-OBS`);
+
+$fix="";
+if (($mjd > 51400) && ($mjd < 51540) && (($id == 2) || ($id == 6))) {
+    $line = `echo $ARGV[0] | fields CD1_1 CRPIX1 NAXIS1`;
+    ($name, $cd11, $crpix1, $nx) = split (" ", $line, 4);
+    $crpix1 = $nx - $crpix1;
+    $cd11 = -$cd11;
+    $fix = "-key CD1_1 %f $cd11  -key CRPIX1 %f $crpix1";
+}
+
+vsystem ("imclean $config @ARGV -p $photcode $fix");
+
+exit 0;
+
+############
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    die "@_";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/imclean.subaru
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/imclean.subaru	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/imclean.subaru	(revision 16632)
@@ -0,0 +1,52 @@
+#!/usr/bin/env perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    print STDERR "ending execution\n";
+    die "@_";
+}
+
+if (@ARGV < 3) { 
+    print STDERR "ERROR: USAGE: USAGE: imclean.cfht (fits) (obj) (cmp) [option]\n";
+    print STDERR "  corrects for errors with CD1_1, CRPIX1 on 12k for 51400 < MJD < 51540\n";
+    print STDERR "  also determines and inserts the photcode for the image\n";
+    exit 2;
+}
+
+# input image must already be in SPLIT mode
+# determine the photcode of this image:
+$photcode=`photcode -quiet $ARGV[0] 0 split`;
+if ($?) {
+    print STDERR "ERROR: cannot find photcode\n";
+    exit 1;
+}
+chop ($photcode);
+
+# check if we need to correct the WCS terms
+$line = `echo $ARGV[0] | fields DET-ID`;
+chop ($line);
+($name, $id) = split (" ", $line);
+
+$cfix = "";
+if ($id == 0) { $cfix = "-key CRPIX1 %f 4000.0 -key CRPIX2 %f  5000.0"; }
+if ($id == 1) { $cfix = "-key CRPIX1 %f 4000.0 -key CRPIX2 %f  3000.0"; }
+if ($id == 2) { $cfix = "-key CRPIX1 %f    0.0 -key CRPIX2 %f  1000.0"; }
+if ($id == 3) { $cfix = "-key CRPIX1 %f    0.0 -key CRPIX2 %f -1000.0"; }
+if ($id == 4) { $cfix = "-key CRPIX1 %f 4000.0 -key CRPIX2 %f -1000.0"; }
+if ($id == 5) { $cfix = "-key CRPIX1 %f 4000.0 -key CRPIX2 %f  1000.0"; }
+if ($id == 6) { $cfix = "-key CRPIX1 %f    0.0 -key CRPIX2 %f  5000.0"; }
+if ($id == 7) { $cfix = "-key CRPIX1 %f    0.0 -key CRPIX2 %f  3000.0"; }
+if ($id == 8) { $cfix = "-key CRPIX1 %f    0.0 -key CRPIX2 %f -3000.0"; }
+if ($id == 9) { $cfix = "-key CRPIX1 %f 4000.0 -key CRPIX2 %f -3000.0"; }
+
+$fix = "-key PC001001 %f 1.0 -key PC001002 %f 0.0 -key PC002001 %f 0.0 -key PC002002 %f 1.0";
+
+vsystem ("imclean @ARGV -p $photcode $fix $cfix");
+
+exit 0;
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/imstatqso
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/imstatqso	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/imstatqso	(revision 16632)
@@ -0,0 +1,87 @@
+#!/usr/bin/env perl
+
+# send sky & seeing to QSO db
+# probably need some error checking on the 
+#  system call functions (seeingstats & fields)
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 3) { die "USAGE: imstatqso (name) (stats) (sdat)\n"; }
+
+$ccdkeyword = `gconfig CCDNUM-KEYWORD`; chop ($ccdkeyword);
+if ($?) { die "ERROR: missing CCDNUM-KEYWORD in config system\n"; } 
+
+$refccd = `gconfig SEEING_REF_CCD`; chop ($refccd);
+if ($?) { die "ERROR: missing SEEING_REF_CCD in config system\n"; } 
+
+$pixscale = `gconfig ASEC_PIX`; chop ($pixscale);
+if ($?) { die "ERROR: missing ASEC_PIX in config system\n"; } 
+
+$line = `echo $ARGV[0] | fields $ccdkeyword`;
+($tmp, $ccd) = split (" ", $line);
+
+if ($ccd =~ m|amp|) { 
+    # convert to equivalent ccd
+    ($n) = $ccd =~ m|amp(\d*)|;
+    $ccd = sprintf "ccd%02d", $n/2;
+}
+
+if ($ccd ne $refccd) {
+    print STDOUT "SUCCESS: skipping ccd $ccd\n";
+    exit 0;
+}
+
+$line = `echo $ARGV[0] | fields OBSID`;
+($tmp, $obs) = split (" ", $line);
+$obs = substr ($obs, 0, 6);
+
+$line = `echo $ARGV[0] | fields OBSTYPE`;
+($tmp, $type) = split (" ", $line);
+$type = uc ($type);
+
+$line = `echo $ARGV[0] | fields EXPTIME`;
+($tmp, $etime) = split (" ", $line);
+
+open (FILE, "$ARGV[1]");
+@lines = <FILE>;
+close (FILE);
+@words = split (" ", $lines[0]);
+$skybg = $words[0];
+$bias = $words[1];
+
+if ($etime == 0) {
+    $flux = -1000;
+} else {
+    $flux = $skybg / $etime;
+}
+
+$fwhm = `seeingstats $ARGV[2]`; 
+chop ($fwhm);
+$fwhm = $fwhm * $pixscale;
+
+# if this is a BIAS, send just the bias for skybg
+if ($type eq "BIAS") {
+    vsystem ("/cfht/bin/update_xexpe.sh -U qso_elixir -P op1eliw --obsid $obs --skybg $bias");
+    print STDOUT "SUCCESS: done with $ARGV[0]\n";
+    exit (0);
+}
+
+# if this is an OBJECT, send both fwhm & flux
+if ($type eq "OBJECT") {
+    vsystem ("/cfht/bin/update_xexpe.sh -U qso_elixir -P op1eliw --obsid $obs --skybg $flux --iq $fwhm");
+    print STDOUT "SUCCESS: done with $ARGV[0]\n";
+    exit (0);
+}
+
+# otherwise, just send flux
+vsystem ("/cfht/bin/update_xexpe.sh -U qso_elixir -P op1eliw --obsid $obs --skybg $flux");
+print STDOUT "SUCCESS: done with $ARGV[0]\n";
+exit (0);
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/imstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/imstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/imstats	(revision 16632)
@@ -0,0 +1,63 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 5) { die "USAGE: imstats (file.fits) (file.stats) (file.split) CCD MODE\n" }
+
+$file = $ARGV[0];
+$stats = $ARGV[1];
+$split = $ARGV[2];
+$ccd = $ARGV[3];
+$mode = $ARGV[4];
+
+# check for outdir:
+@words = split ("/", $stats);
+pop (@words);
+$outdir = join ("/", @words);
+if ($outdir eq "") { $outdir = "."; }
+if (! -d $outdir) {
+    vsystem ("mkdir -p $outdir");
+    if ($?) {
+	print STDERR "ERROR: can't make directory component for output $outdir\n";
+	exit 1;
+    }
+}
+
+if (-e $stats) { unlink ($stats); }
+if (-e $split) { unlink ($split); }
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/imstats.pro";
+
+$ccdkeyword = `gconfig CCDNUM-KEYWORD`; chop ($ccdkeyword);
+
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+
+print MANA "\$CCDKEYWORD = $ccdkeyword\n";
+print MANA "macro go\n";
+print MANA " getstats $file $ccd $mode $stats $split\n";            # load images, create mosaic
+print MANA " exit 0\n";
+print MANA "end\n";
+
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR problem with imstats\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS: finished with imstats\n";
+
+exit 0;
+    
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/imstats.mana
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/imstats.mana	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/imstats.mana	(revision 16632)
@@ -0,0 +1,203 @@
+#!/usr/bin/env mana
+
+macro getstats 
+ # usage getstats (filename) (ccd) (mef) (stats) (split)
+
+ # load image into 'b'
+ if (($3 == mef) || ($3 == MEF))
+  rd b $1 -n $2
+ else
+  rd b $1
+ end
+
+ # raster goes in buffer 'a'
+ # $flux has sky + bias 
+ getraster
+
+ # result of this is $bias
+ getbiassec b $2
+
+ mkoutput $4 $5
+end
+
+# extract subraster from image center 0.1-0.9*NAXIS1 (max 800,800)
+macro getraster
+ keyword b NAXIS1 nx
+ keyword b NAXIS2 ny
+
+# $DX = $nx * 0.8 
+# if ($DX > $dx) 
+#   $DX = $dx
+# end
+# $DY = $ny * 0.8
+# if ($DY > $dy) 
+#   $DY = $dy
+# end
+#
+# $X0 = 0.5*($nx - $DX)
+# $Y0 = 0.5*($ny - $DX)
+#
+# extract b a $X0 $Y0 $DX $DY 0 0 $DX $DY
+
+ if ($nx < (2*$dx))
+   $dx = 0.5 * $nx
+ end
+ if ($ny < (2*$dy))
+   $dy = 0.5 * $ny
+ end
+ echo extract a b {0.5*$nx - $dx} {0.5*$ny - $dy} {2*$dx} {2*$dy} 0 0 {2*$dx} {2*$dy}
+ extract b a {0.5*$nx - $dx} {0.5*$ny - $dy} {2*$dx} {2*$dy} 0 0 {2*$dx} {2*$dy}
+
+ stats -q a - - - -
+ $flux = $MEDIAN
+end
+
+# usage: mkoutput (stats) (split)
+macro mkoutput 
+ $sky = $flux - $bias
+ output $1
+ echo $sky $bias
+ output stdout
+ wd a $2 
+end
+
+# get bias from BIASSEC (header or config)
+macro getbiassec 
+ if ($BIASSEC) 
+  echo "using header biassec"
+  keyword $1 BIASSEC biassec
+ else 
+  # this line converts 2 digit zero-padded number to single
+  echo "using config biassec"
+  $ccd = $2
+  $biassec = 0
+  for n 0 $biassec:n
+    if ($ccdlist:$n == $ccd) 
+      $biassec = $biassec:$n
+    end
+  end
+  if ($biassec == 0)
+    echo "biassec for chip $ccd not found"
+    exit 1
+  end
+ end
+ parsesec $biassec
+ stats -q $1 $x1 $y1 {$x2-$x1} {$y2-$y1}
+ $bias = $MEDIAN
+end
+
+# convert BIASSEC string to x1, x2, y1, y2 vars
+macro parsesec
+  $f = $1
+  getchr $f : n
+  substr $f 1 {$n-1} x1
+  strlen $f N
+  substr $f $n {$N-$n} f
+  
+  getchr $f , n
+  substr $f 1 {$n-1} x2
+  strlen $f N
+  substr $f $n {$N-$n} f
+  
+  getchr $f : n
+  substr $f 1 {$n-1} y1
+  strlen $f N
+  substr $f $n {$N-$n} f
+  
+  getchr $f ] n
+  substr $f 1 {$n-1} y2
+  strlen $f N
+  substr $f $n {$N-$n} f
+end
+
+macro vysub
+ if ($0 != 2)
+  echo "USAGE vysub (buffer)"
+  break
+ end
+
+ keyword $1 NAXIS1 nx
+ keyword $1 NAXIS2 ny
+
+ create dy 0 $ny
+ create dx 0 $ny
+ for ty 0 $ny
+  cut $1 x y x 0 $ty $nx 1
+  vstat -q y
+  dy[$ty] = $MEDIAN
+ end
+
+ # this subtraction is not at all obvious
+ set $1 = $1 - dy
+end
+
+macro vxsub
+ if ($0 != 2)
+  echo "USAGE vxsub (buffer)"
+  break
+ end
+
+ keyword $1 NAXIS1 nx
+ keyword $1 NAXIS2 ny
+
+ create dy 0 $nx
+ create dx 0 $nx
+ for tx 0 $nx
+  cut $1 x y y $tx 0 1 $ny
+  vstat -q y
+  dy[$tx] = $MEDIAN
+ end
+
+ # this subtraction is not at all obvious
+ set $1 = -(dy - $1)
+end
+
+macro irstats
+ $plane = $2 + 1
+ rd a $1 -plane $plane
+ vysub a
+ vstat -q dy
+ $sky = $MEDIAN
+ vxsub a
+ set a = a / $sky
+ wd a $3 -bitpix 16 -bzero 0 -bscale {1/$sky}
+ exec sexstats $3 $4
+ $fwhm = `seeingstats $4`
+ exec echo "$2 $sky $fwhm >> $5"
+ echo "$2 $sky $fwhm to $5"
+end
+
+unsign 0
+$dx = 800
+$dy = 800
+
+$CCDKEYWORD = `gconfig CCDNUM-KEYWORD`
+
+list biassec -x "cameraconfig -biassec"
+$BIASSEC = `cameraconfig -usebiassec`
+list ccdlist -x "cameraconfig -ccds"
+
+# if we can use BIASSEC, use it - BIASSEC changes with rastered, binned images
+# if not, use xbias, ybias lists to extract bias
+
+if ($argv:n != 5) 
+  echo "USAGE: imstats (file.fits) (file.stats) (file.split) CCD MODE"
+  exit 1
+end
+
+break -auto off
+$path = `dirname $argv:1`
+exec test -d $path
+if ($STATUS == 0)
+  exec mkdir -p $path
+  if ($STATUS == 0)
+    echo "ERROR: can't make directory"
+    exit 1
+  end
+end
+
+echo exec rm -f $argv:1
+echo exec rm -f $argv:2
+
+getstats $argv:0 $argv:3 $argv:4 $argv:1 $argv:2
+exit 0
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/irstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/irstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/irstats	(revision 16632)
@@ -0,0 +1,111 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { die "USAGE: imstats (file.fits) (file.stats)\n" }
+
+$file = $ARGV[0];
+$stats = $ARGV[1];
+@medlist = ();
+$cube = 1;
+
+# check for outdir:
+@words = split ("/", $stats);
+pop (@words);
+$outdir = join ("/", @words);
+if ($outdir eq "") { $outdir = "."; }
+if (! -d $outdir) {
+    system ("mkdir -p $outdir");
+    if ($?) { &escape ("ERROR: can't make directory component for output $outdir"); }
+}
+
+if (-e $stats) { unlink ($stats); }
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/imstats.pro";
+
+# check that image is not MEF?
+$answer = `echo $file | fields NAXIS3`;
+($tmp, $Nplane) = split (" ", $answer);
+if ($Nplane == 0) { 
+    $Nplane = 1; 
+    $cube = 0;
+}
+
+$temp = `mktemp /tmp/imstats.XXXXXX`; chop ($temp);
+
+# loop over cube planes:
+open (MANA, "|mana --norc > /dev/null");
+print MANA "input $script\n";
+
+print MANA "macro go\n";
+for ($plane = 0; $plane < $Nplane; $plane++) {
+    print MANA " irstats $file $plane $temp.$plane.fits $temp.stats $stats\n";  
+    @medlist = (@medlist, "$temp.$plane.fits");
+}
+print MANA " exit 0\n";
+print MANA "end\n";
+
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) { &escape ("ERROR problem with imstats"); }
+
+if (@medlist > 1) {
+    open (MED, "|medianfilter $temp.fits 0.25 0.75");
+    foreach $file (@medlist) {
+	print MED "$file\n";
+    }
+    close (MED);
+    if ($?) { &escape ("ERROR problem with medianfilter"); }
+
+    system ("sexstats $temp.fits $temp.stats > /dev/null");
+    if ($?) { &escape ("ERROR problem with sexstats"); }
+} else {
+    system ("sexstats $temp.0.fits $temp.stats > /dev/null");
+    if ($?) { &escape ("ERROR problem with sexstats"); }
+}    
+
+if ($cube) {
+    $fwhm = `seeingstats $temp.stats`; chop ($fwhm);
+    if ($?) { &escape ("ERROR problem with sexstats"); }
+    
+    open (MED, "$stats");
+    @list = <MED>;
+    close (MED);
+    
+    $sky = 0;
+    foreach $line (@list) {
+	($tmp, $isky, $tmp) = split (" ", $line);
+	$sky += $isky;
+    }
+    $sky = $sky / @list;
+    
+    open (MED, ">>$stats");
+    print MED "$Nplane $sky $fwhm\n";
+    close (MED);
+}
+
+&cleanup;
+print STDOUT "SUCCESS: finished with imstats\n";
+
+exit 0;
+    
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub escape {
+    &cleanup;
+    die "@_\n";
+}
+    
+sub cleanup { 
+    if (-e "$temp")       { unlink ("$temp"); }
+    if (-e "$temp.stats") { unlink ("$temp.stats"); }
+    if (-e "$temp.fits")  { unlink ("$temp.fits"); }
+    foreach $file (@medlist) {
+	if (-e $file) { unlink $file; }
+    }
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mefheadunstrip
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mefheadunstrip	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mefheadunstrip	(revision 16632)
@@ -0,0 +1,88 @@
+#!/usr/bin/env perl
+
+$xtline = "XTENSION= 'IMAGE   '           / Image extension ";
+$rwline = "SIMPLE  =                    T / Standard FITS   ";
+
+# input file is PHU: foo.fits.hdr
+# expect NEXTEND files: fooNN.fits.hdr
+
+if (@ARGV != 2) { die "ERROR: USAGE: mefheadunstrip (input) (output)\n" }
+$input  = $ARGV[0];
+$output = $ARGV[1];
+($root) = $input =~ m|(\S*).fits.hdr|;
+
+# blank line for padding:
+$blank = "";
+for ($i = 0; $i < 80; $i++) { $blank = $blank . " "; }
+
+if (-e $output) { die "remove existing target\n"; }
+
+open (OUT, ">$output");
+
+# load primary header
+@head = &loadheader ($input);
+foreach $line (@head) {
+    print OUT "$line";
+}
+
+# find N extensions
+$Nextend = 0;
+foreach $line (@head) {
+    if ($line =~ m|^NEXTEND =\s+\d+|) {
+	($Nextend) = $line =~ m|^NEXTEND =\s+(\d+)|;
+	last;
+    }
+}
+if (!$Nextend) { die "ERROR: no extensions\n"; }
+
+# load extension headers
+for ($i = 0; $i < $Nextend; $i++) {
+    $file = sprintf "%s%02d.fits.hdr", $root, $i;
+    print STDERR "$file\n";
+    
+    @head = &loadheader ($file);
+    foreach $line (@head) {
+	if ($line =~ s|^$rwline|$xtline|) {
+	    print STDERR "fixed SIMPLE\n";
+	}
+    }
+    foreach $line (@head) {
+	print OUT "$line";
+    }
+}
+
+close (OUT);
+exit 0;
+
+# load, strip, pad, fix NAXIS:
+sub loadheader {
+
+    my ($file) = $_[0];
+    my (@input, $i);
+
+    open (FILE, "$file");
+    @input = <FILE>;
+    close (FILE);
+    
+    # strip return chars
+    foreach $line (@input) { chop $line; }
+
+    # pad end of block
+    $N = @input;
+    if ($N % 36) {
+	$Nxtra = 36 - ($N % 36);
+	for ($i = 0; $i < $Nxtra; $i++) {
+	    @input = (@input, $blank);
+	}
+    }
+
+    # NAXIS = 2 -> NAXIS = 0
+    foreach $line (@input) {
+	if ($line =~ s|^NAXIS   =                    2|NAXIS   =                    0|) {
+	    print STDERR "fixed NAXIS\n";
+	}
+    }
+    
+    return (@input);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/megacenter
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/megacenter	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/megacenter	(revision 16632)
@@ -0,0 +1,91 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 1) { die "USAGE: megacenter (filename)\n"; }
+$ENV{'PATH'} = "/apps/elixir/bin:$ENV{'PATH'}";
+
+# currently we keep things hardwired:
+
+$input = $ARGV[0];
+$camera = `gconfig CAMERA`; chop $camera;
+if ($camera eq "megacam") {
+    $ccd   = "amp44";
+    $Xref  = 973;
+    $Yref  = 4560;
+}
+if ($camera eq "meganorth") {
+    $ccd   = "amp26";
+    $Xref  = 1140;
+    $Yref  = 4717;
+}
+if ($ccd eq "") { die "ERROR: camera $camera not found\n"; }
+
+$temp = `mktemp /tmp/center.XXXXXX`; chop ($temp);
+
+# loop over cube planes:
+open (MANA, "|mana --norc >& /dev/null");
+
+print MANA "\$CCDKEYWORD = EXTNAME\n";
+print MANA "macro go\n";
+print MANA " rd a $input -n $ccd\n";
+print MANA " wd a $temp.fits\n";
+print MANA " exec gosexphot $temp.fits $temp.sx >& /dev/null\n";
+print MANA " exec imclean -sex $temp.fits $temp.sx $temp.smp >& /dev/null\n";
+print MANA " exec gastro $temp.smp >& /dev/null\n";
+print MANA " header a -w $temp.smp\n";
+print MANA " coords a -p $Xref $Yref\n";
+print MANA " exec echo \$RA \$DEC > $temp.coords\n";
+print MANA " exit 0\n";
+print MANA "end\n";
+
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+
+($Robs, $Dobs) = split (" ", `cat $temp.coords`);
+($tmp, $Rreq, $Dreq) = split (" ", `echo $input | fields RA_DEG DEC_DEG`);
+
+($tmp, $Nastro, $Cerror) = split (" ", `echo $temp.smp | fields NASTRO CERROR`);
+
+if ($Robs < 0.0)   { $Robs += 360.0 }
+if ($Robs > 360.0) { $Robs -= 360.0 }
+
+if ($Rreq < 0.0)   { $Rreq += 360.0 }
+if ($Rreq > 360.0) { $Rreq -= 360.0 }
+
+$dR = sprintf "%.2f", 3600.0 * ($Rreq - $Robs) * cos ($Dobs*3.141592643589/180.0);
+$dD = sprintf "%.2f", 3600.0 * ($Dreq - $Dobs);
+
+$obscoords = `echo $Rreq $Dreq | radec -hh`; chop $obscoords;
+$reqcoords = `echo $Robs $Dobs | radec -hh`; chop $reqcoords;
+
+print "\n";
+printf STDOUT "$Nastro stars used in astrometry, astrometry error: %.2f\n", $Cerror;
+
+printf STDOUT "REQ COORDS: %10.6f %10.6f ($reqcoords )\n", $Rreq, $Dreq;
+printf STDOUT "OBS COORDS: %10.6f %10.6f ($obscoords )\n", $Robs, $Dobs;
+printf STDOUT "OFFSET IS: $dR $dD (arcsec)\n";
+
+if ($Nastro == 0) { 
+    print "No Astrometry solution was found! please try again\n";
+    goto escape;
+}
+
+if ($Cerror > 2.5) { print "WARNING: astrometry error is surprisingly high\n"; }
+if ($dR > 3600.0)  { print "WARNING: RA offset > 1 degree! is this correct?\n"; }
+if ($dD > 3600.0)  { print "WARNING: DEC offset > 1 degree! is this correct?\n"; }
+
+print STDOUT "apply this offset? y/[n] ";
+$answer = <STDIN>; chop $answer;
+$answer = "\U$answer\E";
+
+if ($answer ne "Y") { 
+    print STDOUT "offset not applied\n";
+    goto escape;
+}
+
+system ("clicmd ocoords rel t $dR $dD\n");
+system ("clicmd tcs.offset\n");
+
+escape:
+system ("rm -f $temp $temp.fits $temp.sx $temp.smp $temp.coords");
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/megacoords
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/megacoords	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/megacoords	(revision 16632)
@@ -0,0 +1,58 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { die "USAGE: megacoords (mode) (filename)\n"; }
+$ENV{'PATH'} = "$ENV{'PATH'}:/apps/elixir/bin";
+
+# currently we keep things hardwired:
+
+$mode = $ARGV[0];
+$input = $ARGV[1];
+
+if ($mode eq "chip") { $ccd   = "ccd22"; }
+if ($mode eq "amp")  { $ccd   = "amp44"; }
+$Xref  = 973;
+$Yref  = 4560;
+
+if ($ccd eq "") { die "ERROR: camera $camera not found\n"; }
+
+$temp = `mktemp /tmp/center.XXXXXX`; chop ($temp);
+
+# mana processing of image
+open (MANA, "|mana --norc >& /dev/null");
+
+print MANA "\$CCDKEYWORD = EXTNAME\n";
+print MANA "macro go\n";
+print MANA " rd a $input -n $ccd\n";
+print MANA " wd a $temp.fits\n";
+print MANA " exec gosexphot $temp.fits $temp.sx >& /dev/null\n";
+print MANA " exec imclean -sex $temp.fits $temp.sx $temp.smp >& /dev/null\n";
+print MANA " exec gastro $temp.smp >& /dev/null\n";
+print MANA " header a -w $temp.smp\n";
+print MANA " coords a -p $Xref $Yref\n";
+print MANA " exec echo \$RA \$DEC > $temp.coords\n";
+print MANA " exit 0\n";
+print MANA "end\n";
+
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+
+($Robs, $Dobs) = split (" ", `cat $temp.coords`);
+($tmp, $Rreq, $Dreq) = split (" ", `echo $input | fields RA_DEG DEC_DEG`);
+
+($tmp, $obsid, $Nastro, $Cerror) = split (" ", `echo $temp.smp | fields OBSID NASTRO CERROR`);
+
+if ($Robs < 0.0)   { $Robs += 360.0 }
+if ($Robs > 360.0) { $Robs -= 360.0 }
+
+if ($Rreq < 0.0)   { $Rreq += 360.0 }
+if ($Rreq > 360.0) { $Rreq -= 360.0 }
+
+$dR = 3600.0 * ($Rreq - $Robs) * cos ($Dobs*3.141592643589/180.0);
+$dD = 3600.0 * ($Dreq - $Dobs);
+
+printf "$obsid %10.6f %10.6f  %10.6f %10.6f  %6.1f %6.1f  %3d %4.2f\n", $Rreq, $Dreq, $Robs, $Dobs, $dR, $dD, $Nastro, $Cerror;
+
+escape:
+system ("rm -f $temp $temp.fits $temp.sx $temp.smp $temp.coords");
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/merge.lists
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/merge.lists	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/merge.lists	(revision 16632)
@@ -0,0 +1,101 @@
+#!/usr/bin/env perl
+
+$update = 0;
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    # new images get mode of 0, old image keep their mode
+    if ($ARGV[0] eq "-update") {
+	shift;
+	$update = 1;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 3) { die "USAGE: merge.lists (list.split) (list.msplit) (list.master) [-update]\n" ;}
+
+print STDERR "$ARGV[0], $ARGV[1], $ARGV[2]\n";
+
+# load names from SPLIT and MEF
+open (FILE, "$ARGV[0]");
+@split = <FILE>;
+close (FILE);
+
+open (FILE, "$ARGV[1]");
+@mef = <FILE>;
+close (FILE);
+
+# load old names from MASTER
+open (FILE, "$ARGV[2]");
+@master = <FILE>;
+close (FILE);
+
+$N = @split;
+print STDERR "N: $N\n";
+$N = @mef;
+print STDERR "N: $N\n";
+$N = @master;
+print STDERR "N: $N\n";
+
+# merge new entries into a single list, compare with state in master
+@names = (@split, @mef);
+
+@newname = ();
+@newmode = ();
+
+for ($i = 0; $i < @names; $i++) {
+
+    $name = $names[$i]; chop ($name);
+
+    $mode = 1;
+    if ($update) {
+	$mode = 0;
+
+      INNER:
+	foreach $line (@master) {
+	    @words = split (" ", $line);
+	    if ($words[0] eq $name) {
+		$mode = $words[1];
+		last INNER;
+	    }
+	}
+    }
+    @newname = (@newname, $name);
+    @newmode = (@newmode, $mode);
+}
+
+if (! @newname) {
+    print STDERR "ERROR: no relevant ccd images\n";
+    exit 1;
+}
+    
+# check on list: if there are none selected, select all
+$Ngood = 0;
+foreach $mode (@newmode) {
+    if ($mode) {
+	$Ngood ++;
+    }
+}
+if ($Ngood == 0) {
+    foreach $mode (@newmode) {
+	$mode = 1;
+    }
+}
+
+open (FILE, ">$ARGV[2]");
+for ($i = 0; $i < @newname; $i++) {
+    print FILE "$newname[$i] $newmode[$i]\n";
+}
+close (FILE);
+
+# this file must be accessible by www user  
+chmod 0666, $ARGV[2];
+
+print STDOUT "SUCCESS\n";
+exit 0;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mkdetrend
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mkdetrend	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mkdetrend	(revision 16632)
@@ -0,0 +1,2486 @@
+#!/usr/bin/perl
+# this function is called from the detrend apache user: 
+# it must be explicit about the location of perl
+
+$MKDETREND = "mkdetrend";
+
+# strip off args related to the elixir config system, set env PTOLEMY
+@ARGV = elixir_config (@ARGV);
+
+# interpret command-line arguments
+if (@ARGV < 1) {
+    print STDOUT "USAGE: $MKDETREND (mode) [arguments]\n";
+    print STDOUT "mode = help gives a complete list\n";
+    &escape;
+}
+if ($ARGV[0] eq "help") { &usage; }
+
+# main user level commands
+if ($ARGV[0] eq "create")       { &mk_create;     }
+if ($ARGV[0] eq "config")       { &mk_config;     }
+if ($ARGV[0] eq "run")          { &mk_run;        }
+if ($ARGV[0] eq "state")        { &mk_state;      }
+if ($ARGV[0] eq "list.runs")    { &mk_list_runs;  }
+if ($ARGV[0] eq "clean")        { &mk_clean;    }
+if ($ARGV[0] eq "reset")        { &mk_reset;      }
+if ($ARGV[0] eq "init")         { &mk_init;       }
+if ($ARGV[0] eq "update")       { &mk_update;     }
+if ($ARGV[0] eq "auto")         { &mk_auto;       }
+# lower level user comands
+if ($ARGV[0] eq "dup")          { &mk_dup;        }
+if ($ARGV[0] eq "del")          { &mk_del;        }
+if ($ARGV[0] eq "def")          { &mk_def;        }
+if ($ARGV[0] eq "set")          { &mk_set;        }
+if ($ARGV[0] eq "list.init")    { &mk_list_init;  }
+if ($ARGV[0] eq "split")        { &mk_split;      }
+if ($ARGV[0] eq "flips")        { &mk_flips;      }
+if ($ARGV[0] eq "norm")         { &mk_norm;       }
+if ($ARGV[0] eq "reg")          { &mk_reg;        }
+if ($ARGV[0] eq "scat")         { &mk_scat;       }
+if ($ARGV[0] eq "merge")        { &mk_merge;      }
+if ($ARGV[0] eq "update.list")  { &mk_update_list;     }
+if ($ARGV[0] eq "update.stats") { &mk_update_stats;     }
+# HTML cgibin commands
+if ($ARGV[0] eq "htmldup")      { &mk_htmldup;    }
+if ($ARGV[0] eq "htmldef")      { &mk_htmldef;    }
+if ($ARGV[0] eq "htmldel")      { &mk_htmldel;    }
+if ($ARGV[0] eq "htmlmod")      { &mk_htmlmod;    }
+if ($ARGV[0] eq "htmlkeep")     { &mk_htmlkeep;   }
+if ($ARGV[0] eq "htmlconfig")   { &mk_htmlconfig; }
+if ($ARGV[0] eq "html1")        { &mk_html1;      }
+if ($ARGV[0] eq "html2")        { &mk_html2;      }
+if ($ARGV[0] eq "html3")        { &mk_html3;      }
+# other support commands
+if ($ARGV[0] eq "dads")         { &mk_dads;       }
+if ($ARGV[0] eq "dads.top")     { &mk_dads_top;   }
+if ($ARGV[0] eq "meval")        { &mk_meval;      }
+if ($ARGV[0] eq "eval")         { &mk_eval;       }
+if ($ARGV[0] eq "fix.masters")  { &mk_fixmasters;  }
+if ($ARGV[0] eq "check.splits") { &mk_checksplits; }
+
+if ($ARGV[0] eq "test")         { &mk_test;       }
+
+&escape ("invalid $MKDETREND command $ARGV[0]");
+
+######## top level functions ######################
+
+sub mk_test {
+
+    print "Content-type: text/plain\n\n";
+
+    print "$MKDETREND\n";
+    exit 0;
+}
+
+############# define run ##############
+sub mk_create {
+    if ($ARGV[1] eq "run") { &mk_createrun; }
+    if (@ARGV != 5) { &escape ("USAGE: $MKDETREND create (camera) (run) (startdate) (stopdate)"); }
+    
+    $camera = $ARGV[1];
+    $run    = $ARGV[2];
+    $start  = $ARGV[3];
+    $stop   = $ARGV[4];
+
+    # create should NOT set the mkdetrend defaults 
+    if (0) {
+	# set current run id:
+	system ("mkrun sys camera.mkdetrend $camera");
+	if ($?) { &escape ("can't define camera: error in mkrun"); }
+	
+	# set current camera:
+	system ("mkrun sys runid.mkdetrend $run");
+	if ($?) { &escape ("can't define run: error in mkrun"); }
+    }
+
+    # reset values for the directories, etc.
+    $oldenv = $tmpenv;
+    &elixir_config (split (" ", "-run $run -camera $camera"));
+    unlink ($oldenv);
+
+    # create necessary directories, empty them if they exist
+    foreach $name ("detdir", "html", "stats", "flips") {
+	$file = mkfiles ($name);
+	if (! -d $file) {
+	    if (! mkdir ($file, 0777)) {
+		&escape ("can't create detdir $file\n");
+	    }
+	    chmod 0775, $file;
+	}
+    }
+    &save_dates ($start, $stop, "init");
+
+    # create run-specific config file
+    @list = ();
+    for ($i = 0; $i < @filt; $i++) {
+	$line = stconfig ("$run $type[$i] $filt[$i] 0 $start $stop init", "all");
+	@list = (@list, $line);
+    }
+    save_config (@list);
+    
+    # make the necessary directories?
+    &goodbye;
+}
+
+############# define run ##############
+sub mk_createrun {
+    if (@ARGV != 3) { &escape ("USAGE: $MKDETREND create run (run)"); }
+    if ($ARGV[1] ne "run") { &escape ("USAGE: $MKDETREND create run (run)"); }
+    
+    $run    = $ARGV[2];
+    $answer = `mkrun run $run`;
+    if ($?) { &escape ("run $run not defined, use 'mkrun'"); }
+    ($newrun, $start, $stop, $camera) = split (" ", $answer);
+    if ($run ne $newrun) { &escape ("inconsistent answer from mkrun run $run"); }
+
+    # reset values for the directories, etc.
+    $oldenv = $tmpenv;
+    &elixir_config (split (" ", "-run $run -camera $camera"));
+    unlink ($oldenv);
+
+    # create necessary directories, empty them if they exist
+    foreach $name ("detdir", "html", "stats", "flips") {
+	$file = mkfiles ($name);
+	if (! -d $file) {
+	    if (! mkdir ($file, 0777)) {
+		&escape ("can't create detdir $file\n");
+	    }
+	    chmod 0775, $file;
+	}
+    }
+    &save_dates ($start, $stop, "init");
+
+    # create run-specific config file
+    @list = ();
+    for ($i = 0; $i < @filt; $i++) {
+	$line = stconfig ("$run $type[$i] $filt[$i] 0 $start $stop init", "all");
+	@list = (@list, $line);
+    }
+    save_config (@list);
+    
+    # make the necessary directories?
+    &goodbye;
+}
+
+############# change current run ##############
+sub mk_config {
+    if (@ARGV != 3) { &escape ("USAGE: $MKDETREND config (camera) (run)"); }
+    
+    $camera = $ARGV[1];
+    $run    = $ARGV[2];
+
+    # set current run id:
+    system ("mkrun sys camera.mkdetrend $camera");
+    if ($?) { &escape ("can't define camera: error in mkrun"); }
+    
+    # set current run id:
+    system ("mkrun sys runid.mkdetrend $run");
+    if ($?) { &escape ("can't define run: error in mkrun"); }
+    
+    &goodbye;
+}
+
+############# auto run system ##############
+sub mk_auto {
+    my ($start, $stop, $mode);
+
+    if ((@ARGV != 2) && (@ARGV != 3)) { &escape ("USAGE: $MKDETREND auto [command]"); }
+    $command = $ARGV[1];
+
+    ($start, $stop, $mode) = load_dates ();
+    if ($command eq "set") {
+	if (@ARGV != 3) { &escape ("USAGE: $MKDETREND auto set (mode)"); }
+	&save_dates ($start, $stop, $ARGV[2]);
+	&goodbye;
+    }
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND auto [command]"); }
+    if ($command eq "show") {
+	print STDERR "MODE : $mode\n";
+	&goodbye;
+    }
+    
+    if ($command eq "run") {
+	if ($mode eq "init") {
+	    system ("$MKDETREND reset hard");
+	    system ("$MKDETREND init");
+	    system ("$MKDETREND run");
+	    &save_dates ($start, $stop, "init");
+	    &goodbye;
+	}
+	
+	if ($mode eq "update") {
+	    system ("$MKDETREND update");
+	    &save_dates ($start, $stop, "update");
+	    &goodbye;
+	}
+	
+	if ($mode eq "hold") {
+	    &goodbye;
+	}
+    }
+    &escape ("$MKDETREND auto $command : command not found\n");
+}
+
+############# main run ##############
+sub mk_run {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND run"); }
+    
+    system ("$MKDETREND flips");
+    system ("$MKDETREND norm");
+    system ("$MKDETREND merge");
+    
+    &goodbye;
+}
+
+############# main init ##############
+sub mk_init {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND init"); }
+    
+    system ("$MKDETREND list.init");
+    system ("$MKDETREND split");
+    
+    &goodbye;
+}
+
+############# main update ##############
+sub mk_update {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND update"); }
+    
+    system ("$MKDETREND reset update");
+    system ("$MKDETREND init");
+    system ("$MKDETREND update.list");
+    system ("$MKDETREND update.stats");
+    system ("$MKDETREND run");
+    
+    &goodbye;
+}
+
+############# show current state ##############
+sub mk_state {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND state"); }
+    
+    $file = mkfiles ("dates");
+    if (! -e $file) { 
+	print STDOUT "CAMERA    $camera\n";
+	print STDOUT "RUN       $run\n";
+	&escape ("setup not defined");
+    }
+    ($start, $stop, $mode) = load_dates ();
+
+    print STDOUT "CAMERA    $camera\n";
+    print STDOUT "RUN       $run\n";
+    print STDOUT "START     $start\n";
+    print STDOUT "STOP      $stop\n";
+    print STDOUT "MODE      $mode\n";
+    
+    @list = &load_config;
+    if (@list == 0) { &escape ("$MKDETREND not configured"); }
+
+    for ($i = 0; $i < @list; $i++) {
+	printf STDOUT "%3d %s\n", $i, $list[$i];
+    }
+    &goodbye;
+}
+
+############# show current state ##############
+sub mk_list_runs {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND list.runs"); }
+    
+    system ("ls $root");
+    &goodbye;
+}
+
+############## duplicate config ###############
+sub mk_dup {
+    if (@ARGV != 2) { &escape ("USAGE: detrend dup (config)"); }
+    
+    $key = $ARGV[1];
+    @list = load_config ();
+    
+    # look for entry that matches requested config
+    @match = ();
+    for ($i = 0; $i < @list; $i++) {
+	$config = gtconfig ($list[$i], "config");
+	if ($key eq $config) { @match = (@match, $i); }	
+    }
+    if (@match == 0) { &escape ("config $key not found\n"); }
+    
+    # create new config version based on version 0
+    $Nnew = @match;
+    $old = $list[$match[0]];
+    $new = stconfig ($old, "version", $Nnew);
+    @list = (@list, $new);
+    save_config (@list);
+    
+    # now we need to duplicate all of the reference files from the first config 
+    foreach $ccd (@ccds) {
+	$fold = mknames ("master", $old, $ccd);
+	$fnew = mknames ("master", $new, $ccd);
+	system ("cp $fold $fnew");
+    }
+    foreach $name ("stats", "medbin", "tenbin", "imbin") {
+	$fold = mknames ($name, $old);
+	$fnew = mknames ($name, $new);
+	system ("cp $fold $fnew");
+    }
+    
+    &goodbye;
+    
+}
+
+############## clean config ###############
+sub mk_clean {
+    if (@ARGV != 1) { &escape ("USAGE: detrend clean"); }
+    # only deletes temporary files for configs in state 'done'
+    
+    @list = load_config ();
+    
+    $detdir = mkfiles ("detdir");
+    open (CF, ">$detdir/clean.fail");
+
+    $Nmiss = 0;
+    $Nfail = 0;
+    $Ngood = 0;
+
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "done") { next; }
+
+	print STDERR "deleting files from $confline\n";
+	$confline = stconfig ($confline, "status", "running.clean");
+	save_config (@list);
+
+	foreach $ccd (@ccds) { 
+	    # delete these specific files:
+	    @dlist = ();
+	    push @dlist, &mknames ("fits", $confline, $ccd); 
+	    push @dlist, &mknames ("norm", $confline, $ccd); 
+	    push @dlist, &mknames ("proc.imbin", $confline, $ccd); 
+	    push @dlist, &mknames ("proc.medbin", $confline, $ccd); 
+	    push @dlist, &mknames ("proc.tenbin", $confline, $ccd); 
+
+	    # delete file, if it exists
+	    foreach $file (@dlist) { 
+		if (! -e $file) { $Nmiss ++; next; }
+		if (!unlink $file) { $Nfail ++; print CF "$file\n"; next; }
+		$Ngood ++;
+	    }
+	}
+	$confline = stconfig ($confline, "status", "clean");
+	save_config (@list);
+    }
+    close (CF);
+    
+    print STDERR "$Ngood files deleted\n";
+    print STDERR "$Nmiss files already removed\n";
+    print STDERR "$Nfail files not deleted, see '$detdir/clean.fail'\n";
+
+    &goodbye;
+}
+
+############## delete config ###############
+sub mk_del {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND del (config.ver)"); }
+    
+    $key = $ARGV[1];
+    @list = load_config ();
+    
+    # look for entry that matches requested config
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}	
+    }
+    if ($match == -1) {
+	print STDERR "config.ver $key not found\n";
+	&escape;
+    }
+    
+    # create new list without match:
+    @newlist = ();
+    for ($i = 0; $i < @list; $i++) {
+	if ($i == $match) { next; }
+	@newlist = (@newlist, $list[$i]);
+    }
+    
+    save_config (@newlist);
+    &goodbye;
+    
+}
+
+############## reset config ###############
+sub mk_reset {
+    if (@ARGV != 2) {
+	print STDERR "USAGE: $MKDETREND reset (level)\n";
+	print STDERR "       level = hard || update\n";
+	&escape; 
+    }
+
+    $level = $ARGV[1];
+    @list = load_config ();
+    
+    # find specific config:
+RESET:
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+
+	if ($level eq "hard" ) {
+	    $confline = stconfig ($confline, "status", "init");
+	}
+	if ($level eq "update") {
+	    if (($status eq "done.merge") || ($status eq "modified") || ($status eq "update")) {
+		$confline = stconfig ($confline, "status", "update");
+		next RESET;
+	    } 
+	    if (($status eq "freeze") || ($status eq "accepted")) {
+		next RESET;
+	    } 
+	    $confline = stconfig ($confline, "status", "init");
+	}
+    }
+    save_config (@list);
+    &goodbye;
+}
+
+############## define config ###############
+sub mk_def {
+    if (@ARGV != 4) { &escape ("USAGE: $MKDETREND def (config.ver) (start) (stop)"); }
+    
+    $key   = $ARGV[1];
+    $start = $ARGV[2];
+    $stop  = $ARGV[3];
+    
+    @list = load_config ();
+    
+    # find specific config:
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	}	
+    }
+    if (@match == -1) {
+	print STDERR "config.ver $key not found\n";
+	&escape;
+    }
+    
+    $new = $list[$match];
+    $new = stconfig ($new, "start", $start);
+    $new = stconfig ($new, "stop", $stop);
+    $list[$match] = $new;
+    
+    save_config (@list);
+    &goodbye;
+    
+}
+
+############## list init ###############
+sub mk_list_init {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND list.init"); }
+    
+    @list = load_config ();
+    
+    # create namelist
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "init") { next; }
+	$Nrun ++;
+	$line = gtconfig ($confline, "mosaic");
+	print FILE "$line\n";
+	$confline = stconfig ($confline, "status", "running.init");
+    }
+    close (FILE);
+    save_config (@list);
+
+    if ($Nrun == 0) { &goodbye; }
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode $MKDETREND -D global.pending imselect.split $file");
+    system ("$MKDETREND meval init");
+    
+    &goodbye;
+}
+
+############## split ###############
+sub mk_split {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND split"); }
+    
+    @list = load_config ();
+    
+    # create namelist
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.init") && ($status ne "split")) { next; }
+	$Nrun ++;
+	foreach $ccd (@ccds) {
+	    $line = gtconfig ($confline, "chiprun", $ccd);
+	    print FILE "$line\n";
+	}
+	$confline = stconfig ($confline, "status", "running.split");
+    }
+    close (FILE);
+    save_config (@list);
+
+    if ($Nrun == 0) { &goodbye; }
+    
+    system ("elixir -D DETREND_DIR $det -D mode $MKDETREND -D global.pending merge.lists $file");
+    system ("$MKDETREND eval split");
+    
+    &goodbye;
+}
+
+############## update lists ###############
+sub mk_update_list {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND update.list"); }
+    
+    @list = load_config ();
+    
+    # create namelist
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "update") { next; }
+	$Nrun ++;
+	$line = gtconfig ($confline, "mosaic");
+	print FILE "$line\n";
+	$confline = stconfig ($confline, "status", "running.update.list");
+    }
+    close (FILE);
+    save_config (@list);
+    
+    if ($Nrun == 0) { &goodbye; }
+    
+    system ("elixir -D DETREND_DIR $det -D mode $MKDETREND -D global.pending update.split $file");
+    system ("$MKDETREND meval update.list");
+    
+    &goodbye;
+}
+
+############## update stats ###############
+sub mk_update_stats {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND update.stats"); }
+    
+    @list = load_config ();
+    
+    # create namelist
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.update.list") && ($status ne "update.stats")) { next; }
+	$Nrun ++;
+	foreach $ccd (@ccds) {
+	    $line = gtconfig ($confline, "chiprun", $ccd);
+	    print FILE "$line\n";
+	}
+	$confline = stconfig ($confline, "status", "running.update.stats");
+
+    }
+    close (FILE);
+    save_config (@list);
+    
+    if ($Nrun == 0) { &goodbye; }
+    
+    system ("elixir -D DETREND_DIR $det -D mode $MKDETREND -D global.pending update.msplit $file");
+    system ("$MKDETREND eval update.stats");
+    
+    &goodbye;
+}
+
+############## set state ###############
+sub mk_set {
+    if (@ARGV != 3) { &escape ("USAGE: $MKDETREND set (config number) (state)"); }
+    
+    @list = load_config ();
+    
+    $key = $ARGV[1];
+    $state = $ARGV[2];
+    
+    $new = stconfig ($list[$key], "status", "$state");
+    $list[$key] = $new;
+    save_config (@list);
+    
+    &goodbye;
+}
+
+############## flips run ###############
+sub mk_flips {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND flips"); }
+    
+    @list = load_config ();
+    
+    # create namelist for those with appropriate status
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.split") && ($status ne "modified") && ($status ne "flips")) { next; }
+	$Nrun ++;
+	foreach $ccd (@ccds) {
+	    $line = gtconfig ($confline, "chiprun", $ccd);
+	    print FILE "$line\n";
+	}
+	$confline = stconfig ($confline, "status", "running.flips");
+    }
+    close (FILE);
+    save_config (@list);
+
+    if ($Nrun == 0) { &goodbye; }
+
+    system ("elixir -D DETREND_DIR $det -D mode $MKDETREND -D global.pending create.subset $file"); 
+    system ("$MKDETREND eval flips");
+
+    &goodbye;
+}
+
+############## norm run ###############
+sub mk_norm {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND norm"); }
+
+    @list = load_config ();
+
+    # create namelist for those with appropriate status
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.flips") && ($status ne "norm")) { next; }
+	$Nrun ++;
+	foreach $ccd (@ccds) {
+	    $line = gtconfig ($confline, "chiprun", $ccd);
+	    print FILE "$line\n";
+	}
+	$confline = stconfig ($confline, "status", "running.norm");
+    }
+    close (FILE);
+    save_config (@list);
+
+    if ($Nrun == 0) { &goodbye; }
+
+    vsystem ("elixir -D DETREND_DIR $det -D mode $MKDETREND -D global.pending normal $file");
+    vsystem ("$MKDETREND eval norm");
+
+    &goodbye;
+}
+
+############## merge run ###############
+sub mk_merge {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND merge"); }
+    
+    @list = load_config ();
+    
+    # create namelist for those with appropriate status
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.norm") && ($status ne "done.update.stats") && ($status ne "merge")) { next; }
+	$Nrun ++;
+	$line = gtconfig ($confline, "mosaic");
+	$confline = stconfig ($confline, "status", "running.merge");
+	print FILE "$line\n";
+    }
+    close (FILE);
+    save_config (@list);
+
+    if ($Nrun == 0) { &goodbye; }
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode $MKDETREND -D global.pending stats $file");
+    vsystem ("$MKDETREND meval merge");
+    
+    &goodbye;
+}
+
+############## reg run ###############
+sub mk_reg {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND reg"); }
+    
+    @list = load_config ();
+    
+    # create directory for fhtool to work in
+    $links = mkfiles ("links");
+    if (! -e $links) { mkdir ($links); }
+
+    # create namelist for those with appropriate status
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "accepted") && ($status ne "reg")) { next; }
+	$confline = stconfig ($confline, "status", "running.reg");
+	save_config (@list);
+
+	$success = 1;
+	$ID = gtconfig ($confline, "ID");
+
+	$DBmode = `gconfig DETREND-DB-MODE`; chop $DBmode;
+	$DBmode = "\U$DBmode\E";
+
+	if ($DBmode eq "SPLIT") {
+	    for ($j = 0; $j < $Nccd; $j++) {
+		$file = mknames ("norm", $confline, $ccds[$j]);
+		$line = "detregister $file -label elixir -ID $ID";
+		$status = system ($line);
+		if ($status) { 
+		    print STDERR "error registering $file\n";
+		    $success = 0;
+		}
+	    }
+	    goto registered;
+	}
+
+	if ($DBmode eq "MEF") {
+	    # empty link directory:
+	    system ("rm -f $links/*.fits");
+
+	    # make links 
+	    foreach $ccd (@ccds) {
+		$file = mknames ("norm", $confline, $ccd);
+		$link = mknames ("link", $confline, $ccd);
+		symlink $file, $link;
+	    }
+
+	    # mef, register
+	    $mef = mknames ("mef", $confline);
+	    if (-e $mef) { unlink $mef; }
+	    vsystem ("fhtool -P $links $mef");
+	    if ($status) { $success = 0; }
+	    vsystem ("detregister $mef -label elixir -ID $ID");
+	    if ($status) { $success = 0; }
+
+	    # remove links
+	    foreach $ccd (@ccds) {
+		$link = mknames ("link", $confline, $ccd);
+		unlink $link;
+	    }
+	    goto registered;
+	}
+	print STDERR "DB mode not defined?\n";
+	$success = 0;
+
+      registered:
+	if ($success) { 
+	    $confline = stconfig ($confline, "status", "done.reg");
+	} else {
+	    print STDERR "error registering $file\n"; 
+	    $confline = stconfig ($confline, "status", "fail.reg");
+	}
+	save_config (@list);
+
+    }
+
+    # use recipe file to decide if we apply 'scat' or not!
+    $file = mkfiles ("list");
+    # create list of images to apply scattered-light correction:
+    foreach $confline (@list) {
+	$type = gtconfig ($confline, "type");
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.reg") && ($status ne "scat")) { next; }
+
+	# only flats get scat correction
+	if ($type eq "flat") { 
+	    $ID = gtconfig ($confline, "ID");
+
+	    open (FILE, ">$file");
+	    foreach $ccd (@ccds) {
+		$line = mknames ("norm", $confline, $ccd);
+		print FILE "$line\n";
+	    }
+	    close (FILE);
+	    
+	    $confline = stconfig ($confline, "status", "running.scat");
+	    save_config (@list);
+
+	    $status = vsystem ("fixscat $file B.2 $ID");
+	    if (($status == 0) || ($status == 2 * 256)) { 
+		$confline = stconfig ($confline, "status", "done.scat");
+	    } else {
+		$confline = stconfig ($confline, "status", "fail.scat");
+	    }		
+	    save_config (@list);
+	}
+    }
+
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.reg") && ($status ne "done.scat")) { next; }
+	$confline = stconfig ($confline, "status", "done");
+    }
+    save_config (@list);
+    &goodbye;
+}
+
+############## html modify ###############
+sub mk_fixmasters {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND fix.masters"); }
+    
+    @list = load_config ();
+
+    foreach $name (@list) {
+
+	@mstate = ();
+	$master = mknames ("master", $name, $ccds[0]); 
+	print STDERR "$master: $name\n";
+	open (FILE, $master);
+	@master = <FILE>;
+	close FILE;
+	for ($j = 0; $j < @master; $j++) {
+	    ($tmp, $state) = split (" ", $master[$j]);
+	    @mstate = (@mstate, $state);
+	}
+
+	# re-create all masters to match master for chip 00
+	for ($i = 1; $i < $Nccd; $i++) {
+
+	    # load existing master file
+	    $master = mknames ("master", $name, $ccds[$i]); 
+	    open (FILE, $master);
+	    @master = <FILE>;
+	    close FILE;
+	    
+	    $Nm = @master;
+	    $Ns = @mstate;
+	    if (@mstate != @master) {
+		print STDOUT "error: mis-match in image lists ccd $i\n";
+		&escape;
+	    }
+	    
+	    # write results back to master file
+	    open (OUT, ">$master") or die "can't open $master";
+	    for ($j = 0; $j < @master; $j++) {
+		($fname, $state) = split (" ", $master[$j]);
+		if ($state != $mstate[$j]) { print STDERR "error on $j $name\n"; }
+		printf OUT "%s %d\n", $fname, $mstate[$j];
+	    }
+	    close (OUT);
+	}
+    }
+    &goodbye;
+}
+
+############## html modify ###############
+sub mk_checksplits {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND check.splits (config)"); }
+    
+    $Nconfig = $ARGV[1];
+    @list = load_config ();
+    $name = $list[$Nconfig];
+
+    # re-create all masters to match master for chip 00
+    foreach $ccd (@ccds) {
+	
+	# load existing master file
+	$master = mknames ("master", $name, $ccd); 
+	open (FILE, $master);
+	@master = <FILE>;
+	close FILE;
+	
+	for ($j = 0; $j < @master; $j++) {
+	    ($fname, $state) = split (" ", $master[$j]);
+	    if (! -e $fname) { 
+		print STDERR "missing file $fname\n";
+	    }
+	}
+    }
+    &goodbye;
+}
+
+####  HTML cgibin functions ################ 
+
+############## html duplicate ###############
+sub mk_htmldup {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND htmldup (config)"); }
+    
+    $config = $ARGV[1];
+    # we are just calling the "mkdetrend dup" function and then calling "$MKDETREND html1"
+    
+    system ("$MKDETREND dup $config");
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/dt.elixir1?&elconf=$elconf\">\n";
+    
+    &goodbye;
+    
+}
+
+############## html delete ###############
+sub mk_htmldel {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND htmldel (config.ver)"); }
+    
+    $config = $ARGV[1];
+    # we are just calling the "mkdetrend del" function and then calling "mkdetrend html1"
+    
+    system ("$MKDETREND del $config");
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/dt.elixir1?&elconf=$elconf\">\n";
+    
+    &goodbye;;
+    
+}
+
+############## html define ###############
+sub mk_htmldef {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND htmldef (config.ver)"); }
+    
+    $key = $ARGV[1];
+    
+    # find (config.ver) in list:
+    
+    @list = load_config ();
+    
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("error: can't find config entry"); }
+    
+    # show the complete list for reference
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0e0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    print STDOUT "<table border>\n";
+    for ($i = 0; $i < @list; $i++) {
+	$config  = gtconfig ($list[$i], "config");
+	$version = gtconfig ($list[$i], "version");
+	$status  = gtconfig ($list[$i], "status");
+	$from    = gtconfig ($list[$i], "from");
+	$to      = gtconfig ($list[$i], "to");
+	print STDOUT "<tr><td> $version </td>\n";
+	print STDOUT "<td> $from </td><td> $to </td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.elixir2?$version&elconf=$elconf> $status </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.split?$config&elconf=$elconf>      split </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.delete?$version&elconf=$elconf>   delete </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.redef?$version&elconf=$elconf>  redefine </a></td>\n";
+	print STDOUT "</tr>\n";
+    }
+    print STDOUT "</table></body><br><br>\n";
+    
+    $version = gtconfig ($list[$match], "version");
+    $status  = gtconfig ($list[$match], "status");
+    $from    = gtconfig ($list[$match], "from");
+    $to      = gtconfig ($list[$match], "to");
+    print STDOUT "redefining <b> $key: </b> <br>\n";    
+    print STDOUT "<table border>\n";
+    print STDOUT "<tr><td> $version </td>\n";
+    print STDOUT "<td> $from </td><td> $to </td><td> $status </a></td>\n";
+    print STDOUT "</tr></table>\n";
+    
+    
+    # create a simple form for redefine:
+    print STDOUT "<form method=post action=$CGI/dt.redefine&elconf=$elconf>\n";
+    print STDOUT "start: <input type=text value=$from name=start size=40 maxlength=40> <br>\n";
+    print STDOUT "stop: <input type=text value=$to name=stop size=40 maxlength=40> <br>\n";
+    print STDOUT "<input type=hidden name=config value=\"$key\">\n";
+    print STDOUT "<input type=\"submit\" value=\"submit\"><input type=\"reset\" value=\"reset\">\n";
+    print STDOUT "</form>\n";
+    print STDOUT "</body>\n";
+    
+    &goodbye;;
+    
+}
+
+############## html modify ###############
+sub mk_htmlmod {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND htmlmod"); }
+    
+    $key = $ENV{'WWW_config'};
+    $Nimage = $ENV{'WWW_Nimage'};
+    
+    @list = load_config ();
+    
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("error: can't find config entry"); }
+    
+    # re-create $master to match selections
+    # depends on the format of data in the 'master' file
+    foreach $ccd (@ccds) {
+
+	# load existing master file
+	$master = mknames ("master", $list[$match], $ccd); 
+	open (FILE, $master);
+	@master = <FILE>;
+	close FILE;
+
+	if ($Nimage != @master) {
+	    print STDOUT "error: mis-match in image lists ccd $ccd\n";
+	    &escape;
+	}
+
+	# write results back to master file
+	open (OUT, ">$master") or die "can't open $master";
+	for ($j = 0; $j < @master; $j++) {
+	    @tmpw = split (" ", $master[$j]);
+	    $name = "WWW_image_$j";
+
+	    $tmpw[1] = 0;
+	    if ($ENV{$name} ne "") { $tmpw[1] = 1; }
+	    printf OUT "%s %d\n", $tmpw[0], $tmpw[1];
+	}
+	close (OUT);
+    }
+    # adjust the config file: convert status to 'modified'
+    $list[$match] = stconfig ($list[$match], "status", "modified");
+    save_config (@list);
+
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/dt.elixir2?$key&elconf=$elconf\">\n";
+    &goodbye;
+}
+
+############## html accept ###############
+sub mk_htmlkeep {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND htmlkeep (config.ver)"); }
+    
+    $key = $ARGV[1];
+    @list = load_config ();
+    
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) {
+	print STDERR "error: can't find config entry\n";
+	&escape;
+    } 
+    
+    # adjust the config file: convert status to 'accepted'
+    $list[$match] = stconfig ($list[$match], "status", "accepted");
+    save_config (@list);
+    
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/dt.elixir1?&elconf=$elconf\">";
+    &goodbye;
+}
+
+############## html config ###############
+sub mk_htmlconfig {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND htmlconfig"); }
+    
+    ## html headers
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    
+    # create a simple form for redefine:
+    print STDOUT "<form method=post action=$CGI/dt.newconfig>\n";
+    if ($elconf) {
+	print STDOUT "enter new config: <input type=text value=$elconf name=config size=40 maxlength=40> <br>\n";
+    } else {
+	print STDOUT "enter new config: <input type=text name=config size=40 maxlength=40> <br>\n";
+    }
+    print STDOUT "<input type=\"submit\" value=\"submit\"><input type=\"reset\" value=\"reset\">\n";
+    print STDOUT "</form>\n";
+    print STDOUT "</body>\n";
+    
+    &goodbye;
+}
+
+############## html level 1 ###############
+sub mk_html1 {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND html1"); }
+    
+    @list = load_config ();
+    
+    ## html headers
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+
+    print STDOUT "<table border>\n";
+    for ($i = 0; $i < @list; $i++) {
+	$config  = gtconfig ($list[$i], "config");
+	$version = gtconfig ($list[$i], "version");
+	$from    = gtconfig ($list[$i], "from");
+	$to      = gtconfig ($list[$i], "to");
+	$status  = gtconfig ($list[$i], "status");
+	print STDOUT "<tr><td> $version </td>\n";
+	print STDOUT "<td> $from </td><td> $to </td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.elixir2?$version&elconf=$elconf> $status </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.split?$config&elconf=$elconf> split </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.delete?$version&elconf=$elconf> delete </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/dt.redef?$version&elconf=$elconf> redefine </a></td>\n";
+	print STDOUT "</tr>\n";
+    }
+    
+    print STDOUT "</table><br><br>\n";
+    if ($elconf eq "") {
+	print STDOUT "Current Config: <b>default</b><br>\n";
+    } else {
+	print STDOUT "Current Config: <b>$elconf</b><br>\n";
+    }
+    print STDOUT "<a href=$CGI/dt.config?&elconf=$elconf>Change Config</a></td>\n";
+    print STDOUT "</body>\n";
+    &goodbye;;
+}
+
+############## html level 2 ###############
+sub mk_html2 {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND html2 (config.ver)"); }
+    
+    @list = load_config ();
+    
+    # entry on line will be either config.ver (== key) or config.ver.col for sorting
+    # grab just the key portion
+    $status = "none";
+    ($key) = $ARGV[1] =~ /(\w+.\w+.\w+.\w+)/; # (config.ver)
+    $arg = $ARGV[1];
+    
+    # find appropriate config.ver entry:
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $confline = $list[$i];
+	    $status = gtconfig ($confline, "status");
+	    last;
+	}
+    }
+    
+    $from = gtconfig ($confline, "from");
+    $to   = gtconfig ($confline, "to");
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    print STDOUT "<center><table border>\n";
+    print STDOUT "<tr><th>config   </th><th> from  </th><th> to </th></tr>\n";
+    print STDOUT "<tr><td>$version </td><td> $from </td><td> $to</td></tr>\n";
+    print STDOUT "</table></center><hr>\n";
+    
+    $master = mknames ("master", $confline, $ccds[0]);
+    
+    if ($status eq "modified")   { flips_report ($arg, $confline,      "modified"); }
+    if ($status eq "accepted")   { flips_report ($arg, $confline,      "accepted"); }
+    if ($status eq "done.merge") { flips_report ($arg, $confline,      "merged"); }
+    if ($status eq "done.reg")   { flips_report_done ($key, $confline, "registered"); }
+    if ($status eq "done")       { flips_report_done ($key, $confline, "registered"); }
+    if ($status eq "clean")      { flips_report ($key, $confline,      "registered"); }
+    
+    if ($status eq "none")              { $message = "not found"; }
+    if ($status eq "init")              { $message = "initialized, not yet run."; }
+    if ($status eq "not.available")     { $message = "has no images available for detrend creation."; }
+    
+    foreach $step (init, flips, norm, merge) {
+	if ($status eq "running.$step") { $message = "running step $step"; }
+	if ($status eq "fail.$step")    { $message = "failed step $step"; }
+	if ($status eq "done.$step") { $message = "has finished $step"; }
+    }      
+
+    print STDOUT "config <b> $key </b> $message <br>\n";
+    
+    print STDOUT "<table border>\n";
+    open (FILE, "$master");
+    while ($line = <FILE>) {
+	chop ($line);
+	@entry = split ("/", $line);
+	$N = @entry - 1;
+	print STDOUT "<tr><td>$entry[$N]</td></tr>\n";
+    }
+    print STDOUT "</table>\n";
+    
+    print STDOUT "</body>\n";
+    &goodbye;
+}
+
+############## html level 3 ###############
+sub mk_html3 {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND html3 (entry.config.ver)"); }
+    
+    @list = load_config ();
+    
+    # extract the entry and key values from $ARGV[1]
+    ($entry, $key) = $ARGV[1] =~ /(\d+)\Q.\E(.*)/;
+    
+    $status = "none";
+    # find appropriate config.ver entry:
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $confline = $list[$i];
+	    $status = gtconfig ($confline, "status");
+	    last;
+	}
+    }
+    
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    
+    if ($status eq "none")              { print STDOUT "config <b> $key </b> not found\n </body>\n"; &goodbye; }
+    if ($status eq "init")              { print STDOUT "config <b> $key </b> initialized, not yet run\n </body>\n"; &goodbye; }
+    if ($status eq "not.available")     { print STDOUT "config <b> $key </b> has no images available for detrend creation\n </body>\n"; &goodbye; }
+    
+    # if ($status eq "done.update") { flips_entry ($key, $entry, $confline); }
+    if ($status eq "done.merge") { flips_entry ($key, $entry, $confline); }
+    if ($status eq "accepted")   { flips_entry ($key, $entry, $confline); }
+    if ($status eq "modified")   { flips_entry ($key, $entry, $confline); }
+    if ($status eq "done.reg")   { flips_entry ($key, $entry, $confline); }
+    
+    foreach $step (init, flips, norm, merge) {
+	# print "step: $step, $status: $status\n";
+	if ($status eq "running.$step") { print STDOUT "config <b> $key </b> running step $step \n </body>\n"; &goodbye; }
+	if ($status eq "fail.$step")    { print STDOUT "config <b> $key </b> failed step $step\n </body>\n"; &goodbye; }
+	
+	if ($status eq "done.$step") {
+	    print STDOUT "config <b> $key </b> has finished $step\n";
+	    
+	    # load image names from CCD 0 list:
+	    $master = mknames ("master", $confline, $ccds[0]);
+	    print STDOUT "<table border>\n";
+	    open (FILE, "$master");
+	    while ($line = <FILE>) {
+		chop ($line);
+		@entry = split ("/", $line);
+		$N = @entry - 1;
+		print STDOUT "<tr><td>$entry[$N]</td></tr>\n";
+	    }
+	    print STDOUT "</table>\n";
+	}
+    }
+    
+    # print STDOUT "</body>\n";
+    &goodbye;
+}
+
+###  other support commands ####################
+
+############## evaluate chip run ###############
+sub mk_eval {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND eval (step)"); }
+    
+    $step = $ARGV[1];
+    @list = load_config ();
+    
+    # load success fifo info:
+    $file = `gconfig -D mode $MKDETREND global.success`; chop $file;
+    open (FILE, "$file");
+    @success = <FILE>;
+    close (FILE);
+    
+    # load failure fifo info:
+    $file = `gconfig -D mode $MKDETREND global.failure`; chop $file;
+    open (FILE, "$file");
+    @failure = <FILE>;
+    close (FILE);
+    
+    # entry must be in state 'running.$step'
+    # possible states:
+    #   1 all 12 chips in success          == done.$step
+    #   2 any chips in failure             == fail.$step
+    #   3 any chips missing                == fail.$step
+    #   4 any chips in failure, merge.list == not.available (only for $step eq init)
+    # valid steps: init flips norm
+    
+  CONFIG:
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "running.$step") { next; }
+	$state = 1;
+
+      CCD:
+	foreach $ccd (@ccds) {
+	    $entry = gtconfig ($confline, "chiprun", $ccd);
+
+	    # search for entry in success fifo:
+	    foreach $value (@success) {
+		if ($value =~ /^$entry/) { next CCD; }
+	    }
+	    
+	    # search for entry in failure fifo: note the special ending state for 'init'
+	    foreach $value (@failure) {
+		if ($value =~ /^$entry/) {
+		    $state = 2;
+		    if ($step eq "split") {
+			($status) = $value =~ /$entry\s+\S+\s+(\S+)/;
+			if ($status eq "merge.lists") {
+			    $state = 4;
+			}
+		    }
+		    last CCD;
+		}
+	    }
+	    
+	    # if we make it here, it wasn't in either fifo.success or fifo.failure...
+	    $state = 3;
+	    last CCD;
+	}
+	
+	if ($state == 1) { $confline = stconfig ($confline, "status", "done.$step"); } 
+	if ($state == 2) { $confline = stconfig ($confline, "status", "fail.$step"); }
+	if ($state == 3) { $confline = stconfig ($confline, "status", "fail.$step"); } 
+	if ($state == 4) { $confline = stconfig ($confline, "status", "not.available"); }
+    }
+    save_config (@list);
+
+    system ("$MKDETREND state");
+    &goodbye;
+}
+
+############## evaluate mosaic run ###############
+sub mk_meval {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND meval (step)"); }
+    
+    $step = $ARGV[1];
+    @list = load_config ();
+    
+    # load success fifo info:
+    $file = `gconfig -D mode $MKDETREND global.success`; chop $file;
+    open (FILE, "$file");
+    @success = <FILE>;
+    close (FILE);
+    
+    # load failure fifo info:
+    $file = `gconfig -D mode $MKDETREND global.failure`; chop $file;
+    open (FILE, "$file");
+    @failure = <FILE>;
+    close (FILE);
+    
+    # entry must be in state 'running.$step'
+    # possible states:
+    #   1 entry in success          == done.$step
+    #   2 entry in failure          == fail.$step
+    #   3 entry missing             == fail.$step
+    # valid steps: merge
+    
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "running.$step") { next; }
+	$state = 3;
+	$entry = gtconfig ($confline, "mosaic");
+
+      MCHECK: 
+	{
+	    foreach $value (@success) {
+		if ($value =~ /^$entry/) { 
+		    $state = 1;
+		    last MCHECK;
+		}
+	    }
+	    
+	    foreach $value (@failure) {
+		if ($value =~ /^$entry/) { 
+		    $state = 2;
+		    next MCHECK;
+		}
+	    }
+	}
+	
+	if ($state == 1) { $confline = stconfig ($confline, "status", "done.$step"); } 
+	if ($state == 2) { $confline = stconfig ($confline, "status", "fail.$step"); }
+	if ($state == 3) { $confline = stconfig ($confline, "status", "fail.$step"); }
+    }
+    
+    save_config (@list);
+    system ("$MKDETREND state");
+    
+    &goodbye;
+}
+
+############## html for dads ###############
+sub mk_dads {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND dads (config.ver)"); }
+    
+    # options: mkdetrend dads (config.ver)
+    # return all relevant images (jpegs) for given config.ver
+
+    @list = load_config ();
+    
+    # entry on line will be either config.ver (== key) or config.ver.col for sorting
+    # grab just the key portion
+    $status = "none";
+    $arg = $ARGV[1];
+    ($key) = $arg =~ /(\w+.\w+.\w+.\w+)/; # (config.ver)
+    
+    # find appropriate config.ver entry:
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $confline = $list[$i];
+	    $status = gtconfig ($confline, "status");
+	    last;
+	}
+    }
+    if (!$confline) { &escape ("$key not found"); }
+    
+    # only print for config.ver entries which are ready (done, clean)
+    if (($status ne "done") && ($status ne "clean")) { 
+	&escape ("$version is not ready for release by Elixir"); 
+    }
+
+    # parse config entry and get data from appropriate files
+    $from = gtconfig ($confline, "from");
+    $to   = gtconfig ($confline, "to");
+    open (STAT,   mknames ("stats", $confline));            @statdata = <STAT>;        close (STAT);
+    open (MED,    mknames ("medbin", $confline));           @medndata = <MED>;         close (MED);
+    open (TEN,    mknames ("tenbin", $confline));           @tenndata = <TEN>;         close (TEN);
+    open (MASTER, mknames ("master", $confline, $ccds[0])); @mastdata = <MASTER>;      close (MASTER);
+    
+    $tmpname = mknames ("master", $confline, $ccds[0]);
+
+    # get stats from the stats & master files
+    $Nkeep = 0;
+    $Ncnt = 0;
+    $Sigma = 0;
+    $Nimage = @statdata;
+    for ($i = 0; $i < $Nimage; $i++) {
+	@tmpw = split (" ", $mastdata[$i]);
+	@tmps = split (" ", $statdata[$i]);
+	if ($tmpw[1]) { $Nkeep++; $Ncnt += $tmps[3]; $Sigma += $tmps[8]*$tmps[8]; }
+    }
+    $imbin = mknames ("dads.imbin", $confline);
+
+    ($start, $stop, $mode) = &load_dates;
+    print STDOUT "$imbin $Nimage $start $stop\n";
+
+    $dir = mkfiles ("html");
+    # create the image-by-image table lines
+    for ($i = 0; $i < $Nimage; $i++) {
+	@word = split (" ", $statdata[$i]);
+	$used = $word[12];
+	$dawn = $word[11];
+	
+	@tmpw = split (" ", $mastdata[$i]);
+	$keep = $tmpw[1];
+	
+	# data files contain the complete path, but this may have changed
+	# replace path with mkfiles ("html") -> $dir
+	@tmpw = split ('/', $tenndata[$i]);
+	$tenimg = "$dir/$tmpw[-1]"; chop $tenimg;
+	@tmpw = split ('/', $medndata[$i]);
+	$medimg = "$dir/$tmpw[-1]"; chop $medimg;
+
+	print STDOUT "$tenimg $medimg $word[0] $word[1] $dawn $word[2] $word[3] $word[5] $word[6] $word[8] $used\n";
+    }
+    &goodbye;
+}
+
+############## html for dads ###############
+sub mk_dads_html {
+    if (@ARGV != 2) { &escape ("USAGE: $MKDETREND dads (config.ver)"); }
+    
+    @list = load_config ();
+    
+    # entry on line will be either config.ver (== key) or config.ver.col for sorting
+    # grab just the key portion
+    $status = "none";
+    $arg = $ARGV[1];
+    ($key) = $arg =~ /(\w+.\w+.\w+.\w+)/; # (config.ver)
+    
+    # find appropriate config.ver entry:
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $confline = $list[$i];
+	    $status = gtconfig ($confline, "status");
+	    last;
+	}
+    }
+    
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+
+    # only print for config.ver entries which are ready
+    if ($status ne "done.reg") { &escape ("$version is not ready for release by Elixir"); }
+
+    # parse config entry and get data from appropriate files
+    $from = gtconfig ($confline, "from");
+    $to   = gtconfig ($confline, "to");
+    open (STAT,   mknames ("stats", $confline));     @statdata = <STAT>;        close (STAT);
+    open (MED,    mknames ("medbin", $confline));    @medndata = <MED>;         close (MED);
+    open (TEN,    mknames ("tenbin", $confline));    @tenndata = <TEN>;         close (TEN);
+    open (MASTER, mknames ("master", $confline, $ccds[0])); @mastdata = <MASTER>;      close (MASTER);
+    
+    $tmpname = mknames ("master", $confline, $ccds[0]);
+
+    # get stats from the stats & master files
+    $Nkeep = 0;
+    $Ncnt = 0;
+    $Sigma = 0;
+    $Nimage = @statdata;
+    for ($i = 0; $i < $Nimage; $i++) {
+	@tmpw = split (" ", $mastdata[$i]);
+	@tmps = split (" ", $statdata[$i]);
+	if ($tmpw[1]) { $Nkeep++; $Ncnt += $tmps[3]; $Sigma += $tmps[8]*$tmps[8]; }
+    }
+    $Sigma = sprintf "%5.3f", 100*sqrt ($Sigma/$Nkeep);
+
+    print STDOUT "<center><table border>\n";
+    print STDOUT "<tr><th>config   </th><th> from  </th><th> to </th></tr>\n";
+    print STDOUT "<tr><td>$version </td><td> $from </td><td> $to</td></tr>\n";
+    print STDOUT "</table></center><hr>\n";
+
+    $imbin = mknames ("dads.imbin", $confline);
+    print STDOUT "<table width=80%><tr><td valign=top>\n";
+    print STDOUT "this config has been created by Elixir. <br>\n";
+    print STDOUT "there are $Nimage images, $Nkeep used. <br>\n";
+    print STDOUT "Total Counts: $Ncnt<br> r.m.s. median sigma: $Sigma% <br><br>\n";
+    print STDOUT "</td><td align=right><img src=$imbin></td></tr></table>\n";
+    
+    print STDOUT "<center><b>Statistics on each available input image.</b></center>
+  Time is in UT, light background means dawn, grey means dusk.\n";
+
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    print STDOUT "<tr >\n";
+    print STDOUT "<th > image </th>\n";
+    print STDOUT "<th > Date  </th>\n";
+    print STDOUT "<th > Time  </th>\n";
+    print STDOUT "<th > Mean  </a></th>\n";
+    print STDOUT "<th > Sigma (raw) </a></th>\n";
+    print STDOUT "<th > Sigma (clipped) </a></th>\n";
+    print STDOUT "<th > Sigma (med) </a></th>\n";
+    print STDOUT "<th > image </th>\n";
+    print STDOUT "<th > used? </th></tr>\n";
+    
+    # sort the list by image seq number
+    @order = ();
+    for ($i = 0; $i < $Nimage; $i++) { @order = (@order, $i); }
+    $col = 0;
+    @entry = sort by_col @order;
+    
+    # create the image-by-image table lines
+    for ($i = 0; $i < $Nimage; $i++) {
+	$N = $entry[$i];
+	
+	@word = split (" ", $statdata[$N]);
+	$used = $word[12];
+	$dawn = $word[11];
+	
+	@tmpw = split (" ", $mastdata[$N]);
+	$keep = $tmpw[1];
+	
+	@tmpw = split ("/", $medndata[$N]);
+	$medname = $tmpw[-1];
+	
+	@tmpw = split ("/", $tenndata[$N]);
+	$tenname = $tmpw[-1];
+	
+	print STDOUT "<tr><td> $word[0] </td><td> $word[1] </td>\n";
+	if ($dawn) { print STDOUT "<td bgcolor=#cccccc> $word[2] </td>\n"; }
+	else       { print STDOUT "<td> $word[2] </td>\n"; }
+	print STDOUT "<td> $word[3] </td>\n";
+	print STDOUT "<td> $word[5] </td><td> $word[6] </td><td> $word[8] </td>\n";
+	print STDOUT "<td> <a border=0 href=$dadswww/$tenname> <img src=$dadswww/$medname></a></td>\n";
+	if ($used) { print STDOUT "<td bgcolor=#00c000>yes</td>\n"; }
+	else       { print STDOUT "<td bgcolor=#d00000>no</td>\n"; }
+	print STDOUT "</tr>\n\n"; 	
+    }
+    
+    print STDOUT "</table>\n";
+    &goodbye;
+}
+
+############## dads level 1 ###############
+sub mk_dads_top {
+    if (@ARGV != 1) { &escape ("USAGE: $MKDETREND dads.top"); }
+    
+    @list = load_config ();
+    
+    ## html headers
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+
+    print STDOUT "<table border>\n";
+    for ($i = 0; $i < @list; $i++) {
+	$config  = gtconfig ($list[$i], "config");
+	$version = gtconfig ($list[$i], "version");
+	$from    = gtconfig ($list[$i], "from");
+	$to      = gtconfig ($list[$i], "to");
+	$status  = gtconfig ($list[$i], "status");
+	print STDOUT "<tr><td> $version </td>\n";
+	print STDOUT "<td> $from </td><td> $to </td>\n";
+	print STDOUT "<td> <a href=$version.html> $status </a></td>\n";
+	print STDOUT "</tr>\n";
+    }
+    
+    print STDOUT "</table></body>\n";
+    &goodbye;;
+    
+}
+
+sub by_col { 
+    @word = split (" ", $statdata[$a]); $va = $word[$col]; 
+    @word = split (" ", $statdata[$b]); $vb = $word[$col]; 
+    $va <=> $vb;
+}
+
+sub flips_report {
+    
+    $col = 0;
+    ($type)   = $_[0] =~ /\w+.(\w+).\w+/;
+    ($config) = $_[0] =~ /(\w+.\w+.\w+)/;
+    ($key)    = $_[0] =~ /(\w+.\w+.\w+.\w+)/; # (config.ver)
+
+    # look for optional sort key (config.ver[.key])
+    if ($_[0] =~ /$key.(\d+)/) {
+	($col) = $_[0] =~ /$key.(\d+)/; 
+    } else {
+	$col = 0;
+    }
+
+    $line = $_[1];
+    $message = $_[2];
+    
+    open (FILE, mknames ("stats",  $line));            @statdata = <FILE>; close (FILE);
+    open (FILE, mknames ("medbin", $line));            @medndata = <FILE>; close (FILE);
+    open (FILE, mknames ("master", $line, $ccds[0]));  @mastdata = <FILE>; close (FILE);
+
+    $Nkeep = 0;
+    $Ncnt = 0;
+    $Sigma = 0;
+    $Nimage = @statdata;
+    for ($i = 0; $i < $Nimage; $i++) {
+	@tmpw = split (" ", $mastdata[$i]);
+	@tmps = split (" ", $statdata[$i]);
+	if ($tmpw[1]) { $Nkeep++; $Ncnt += $tmps[3]; $Sigma += $tmps[8]*$tmps[8]; }
+    }
+    if ($Nkeep > 0) {
+	if ($type eq "flat") { 
+	    $Sigma = sprintf "%5.3f", 100*sqrt ($Sigma/$Nkeep);
+	    $statline = "Total Counts: $Ncnt<br> r.m.s. median sigma: $Sigma% <br><br>\n";
+	} else {
+	    $Sigma = sprintf "%5.3f", sqrt ($Sigma/$Nkeep);
+	    $Ncnt  = sprintf "%5.3f", ($Ncnt / $Nkeep);
+	    $statline = "Mean Counts: $Ncnt<br> r.m.s. median sigma: $Sigma <br><br>\n";
+	}
+    } else {
+	$statline = "";
+    }
+
+    $imbin = mknames ("imbin",  $line);
+    print STDOUT "<table><tr><td width=300px valign=top>\n";
+    print STDOUT "<b>this config has been $message. </b><br>\n";
+    print STDOUT "there are $Nimage images, $Nkeep used. <br>\n";
+    print STDOUT "$statline\n";
+    print STDOUT "you have the following choices: <br>\n";
+    print STDOUT "<a href=$CGI/dt.elixir1?&elconf=$elconf> <b> return to top level </b><br></a>\n";
+    print STDOUT "<a href=$CGI/dt.split?$config&elconf=$elconf> <b> split config </b><br></a>\n";
+    print STDOUT "<a href=$CGI/dt.accept?$key&elconf=$elconf> <b> accept config </b><br></a>\n";
+    print STDOUT "</td><td width=640px align=right><img width=100% src=$imbin></td></tr></table>\n";
+    
+    print STDOUT "<form method=post action=$CGI/dt.modify?&elconf=$elconf>\n";
+
+    print STDOUT "<center><b>Statistics on each available input image.</b></center>
+  Time is in UT, light background means dawn, grey means dusk. Click
+  on the column heading to sort by that entry\n";
+
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    print STDOUT "<tr bgcolor=#00aaaa>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.0&elconf=$elconf> image </a></th>\n";
+    print STDOUT "<th > Date </th>\n";
+    print STDOUT "<th > Time </th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.3&elconf=$elconf> Mean </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.5&elconf=$elconf> Sigma (raw) </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.6&elconf=$elconf> Sigma (clipped) </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.8&elconf=$elconf> Sigma (med) </a></th>\n";
+    print STDOUT "<th > image </th>\n";
+    print STDOUT "<th > used? </th>\n";
+    print STDOUT "<th > keep? </th></tr>\n\n";
+    
+    @order = ();
+    for ($i = 0; $i < $Nimage; $i++) { @order = (@order, $i); }
+    
+    @entry = sort by_col @order;
+    
+    for ($i = 0; $i < $Nimage; $i++) {
+	$N = $entry[$i];
+	
+	@word = split (" ", $statdata[$N]);
+	$used = $word[12];
+	$dawn = $word[11];
+	
+	@tmpw = split (" ", $mastdata[$N]);
+	$keep = $tmpw[1];
+	
+	@tmpw = split ("/", $medndata[$N]);
+	$medname = $tmpw[-1];
+	
+	print STDOUT "<tr><td> <a href=$CGI/dt.elixir3?$N.$key&elconf=$elconf> $word[0] </a></td><td> $word[1] </td>\n";
+	if ($dawn) { print STDOUT "<td bgcolor=#cccccc> $word[2] </td>\n"; }
+	else       { print STDOUT "<td> $word[2] </td>\n"; }
+	print STDOUT "<td> $word[3] </td>\n"; # mean
+	print STDOUT "<td> $word[5] </td>\n"; # Sigma (raw)
+	print STDOUT "<td> $word[6] </td>\n"; # Sigma (clip)
+	print STDOUT "<td> $word[8] </td>\n"; # Sigma (med)
+	print STDOUT "<td> <a border=0 href=$CGI/dt.elixir3?$N.$key&elconf=$elconf>\n";
+	print STDOUT "<img src=$www/$medname></a></td>\n";
+	if ($used) { print STDOUT "<td>yes</td>\n"; }
+	else       { print STDOUT "<td>no</td>\n"; }
+	if ($keep) { print STDOUT "<td bgcolor=#00c000><input type=checkbox checked name=image.$N value=$N size=1></td></tr>\n\n"; }
+	else       { print STDOUT "<td bgcolor=#d00000><input type=checkbox         name=image.$N value=$N size=1></td></tr>\n\n"; }	
+	
+    }
+    
+    print STDOUT "</table>\n";
+    print STDOUT "<input type=hidden    name=Nimage value=\"$Nimage\">\n";
+    print STDOUT "<input type=hidden    name=config value=\"$key\">\n";
+    print STDOUT "<input type=submit    value=\"apply changes\">\n";
+    print STDOUT "<input type=reset     value=Reset>\n";
+    # print STDOUT "<select name=status   size=1> \n";
+    print STDOUT "</form></body>\n";
+    &goodbye;
+    
+}
+
+sub flips_report_done {
+    
+    $col = 0;
+    ($type)   = $_[0] =~ /\w+.(\w+).\w+/;
+    ($config) = $_[0] =~ /(\w+.\w+.\w+)/;
+    ($key)    = $_[0] =~ /(\w+.\w+.\w+.\w+)/; # (config.ver)
+
+    # look for optional sort key (config.ver[.key])
+    if ($_[0] =~ /$key.(\d+)/) {
+	($col) = $_[0] =~ /$key.(\d+)/; 
+    } else {
+	$col = 0;
+    }
+
+    $line = $_[1];
+    $message = $_[2];
+    
+    open (FILE, mknames ("stats",  $line));            @statdata = <FILE>; close (FILE);
+    open (FILE, mknames ("medbin", $line));            @medndata = <FILE>; close (FILE);
+    open (FILE, mknames ("master", $line, $ccds[0]));  @mastdata = <FILE>; close (FILE);
+
+    $Nkeep = 0;
+    $Ncnt = 0;
+    $Sigma = 0;
+    $Nimage = @statdata;
+    for ($i = 0; $i < $Nimage; $i++) {
+	@tmpw = split (" ", $mastdata[$i]);
+	@tmps = split (" ", $statdata[$i]);
+	if ($tmpw[1]) { $Nkeep++; $Ncnt += $tmps[3]; $Sigma += $tmps[8]*$tmps[8]; }
+    }
+    if ($Nkeep > 0) {
+	if ($type eq "flat") { 
+	    $Sigma = sprintf "%5.3f", 100*sqrt ($Sigma/$Nkeep);
+	    $statline = "Total Counts: $Ncnt<br> r.m.s. median sigma: $Sigma% <br><br>\n";
+	} else {
+	    $Sigma = sprintf "%5.3f", sqrt ($Sigma/$Nkeep);
+	    $Ncnt  = sprintf "%5.3f", ($Ncnt / $Nkeep);
+	    $statline = "Mean Counts: $Ncnt<br> r.m.s. median sigma: $Sigma <br><br>\n";
+	}
+    } else {
+	$statline = "";
+    }
+
+    $imbin = mknames ("imbin",  $line);
+    print STDOUT "<table><tr><td width=300px valign=top>\n";
+    print STDOUT "<b>this config has been $message. </b><br>\n";
+    print STDOUT "there are $Nimage images, $Nkeep used. <br>\n";
+    print STDOUT "$statline\n";
+    print STDOUT "you have the following choices: <br>\n";
+    print STDOUT "<a href=$CGI/dt.elixir1?&elconf=$elconf> <b> return to top level </b><br></a>\n";
+    print STDOUT "<a href=$CGI/dt.split?$config&elconf=$elconf> <b> split config </b><br></a>\n";
+    print STDOUT "<a href=$CGI/dt.accept?$key&elconf=$elconf> <b> accept config </b><br></a>\n";
+    print STDOUT "</td><td width=640px align=right><img width=100% src=$imbin></td></tr></table>\n";
+    
+    print STDOUT "<center><b>Statistics on each available input image.</b></center>
+  Time is in UT, light background means dawn, grey means dusk. Click
+  on the column heading to sort by that entry\n";
+
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    print STDOUT "<tr bgcolor=#00aaaa>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.0&elconf=$elconf> image </a></th>\n";
+    print STDOUT "<th > Date </th>\n";
+    print STDOUT "<th > Time </th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.3&elconf=$elconf> Mean </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.5&elconf=$elconf> Sigma (raw) </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.6&elconf=$elconf> Sigma (clipped) </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/dt.elixir2?$key.8&elconf=$elconf> Sigma (med) </a></th>\n";
+    print STDOUT "<th > image </th>\n";
+    print STDOUT "<th > used? </th></tr>\n\n";
+    
+    @order = ();
+    for ($i = 0; $i < $Nimage; $i++) { @order = (@order, $i); }
+    
+    @entry = sort by_col @order;
+    
+    for ($i = 0; $i < $Nimage; $i++) {
+	$N = $entry[$i];
+	
+	@word = split (" ", $statdata[$N]);
+	$used = $word[12];
+	$dawn = $word[11];
+	
+	@tmpw = split (" ", $mastdata[$N]);
+	$keep = $tmpw[1];
+	
+	@tmpw = split ("/", $medndata[$N]);
+	$medname = $tmpw[-1];
+	
+	print STDOUT "<tr><td> <a href=$CGI/dt.elixir3?$N.$key&elconf=$elconf> $word[0] </a></td><td> $word[1] </td>\n";
+	if ($dawn) { print STDOUT "<td bgcolor=#cccccc> $word[2] </td>\n"; }
+	else       { print STDOUT "<td> $word[2] </td>\n"; }
+	print STDOUT "<td> $word[3] </td>\n"; # mean
+	print STDOUT "<td> $word[5] </td>\n"; # Sigma (raw)
+	print STDOUT "<td> $word[6] </td>\n"; # Sigma (clip)
+	print STDOUT "<td> $word[8] </td>\n"; # Sigma (med)
+	print STDOUT "<td> <a border=0 href=$CGI/dt.elixir3?$N.$key&elconf=$elconf>\n";
+	print STDOUT "<img src=$www/$medname></a></td>\n";
+	if ($used) { print STDOUT "<td>yes</td>\n"; }
+	else       { print STDOUT "<td>no</td>\n"; }
+	print STDOUT "</tr>\n";
+    }
+    
+    print STDOUT "</table></body>\n";
+    &goodbye;
+    
+}
+
+#### process report for html2 ##########
+sub flips_report_done_old {
+    
+    ($config) = $_[0] =~ /(\w+.\w+.\w+)/;
+    ($key)    = $_[0] =~ /(\w+.\w+.\w+.\w+)/; # (config.ver)
+    $line = $_[1];
+    
+    open (STAT, mknames ("stats", $line));
+    open (MED,  mknames ("medbin", $line));
+    open (MASTER, mknames ("master", $line, $ccds[0]));
+    
+    print STDOUT "<table border>\n";
+    print STDOUT "<tr><th> image </th><th> Date </th><th> Time </th><th> Mean </th>\n";
+    print STDOUT "<th> Sigma (raw) </th><th> Sigma (clipped) </th><th> Sigma (med) </th><th> image </th><th> used? </th></tr>\n\n";
+    
+    for ($i = 0; $line = <STAT>; $i++) {
+	
+	chop ($line);
+	# print STDOUT "$line<br>\n";
+	@word = split (" ",$line);
+	$used = $word[12];
+	$dawn = $word[11];
+	
+	$line = <MASTER>;
+	chop ($line);
+	# print STDOUT "$line<br>\n";
+	@tmpw = split (" ",$line);
+	$keep = $tmpw[1];
+	
+	# mkdetrend works with files in the user's paths, but the web page needs 
+	# to work with files visible to the web server
+	$line = <MED>;
+	chop ($line);
+	@tmpw = split ("/", $line);
+	$N = @tmpw - 1;
+	$medname = $tmpw[$N];
+	
+	$sig1 = sprintf "%5.3f", $word[4];
+	$sig2 = sprintf "%5.3f", $word[5];
+	$sig3 = sprintf "%5.3f", $word[6];
+	$sig4 = sprintf "%5.3f", $word[7];
+	$mean = sprintf "%8.1f", $word[3];
+	
+	print STDOUT "<tr><td> <a href=$CGI/dt.elixir3?$i.$key&elconf=$elconf> $word[0] </a></td><td> $word[1] </td>\n";
+	if ($dawn) { print STDOUT "<td bgcolor=#cccccc> $word[2] </td>\n"; }
+	else       { print STDOUT "<td> $word[2] </td>\n"; } 
+	print STDOUT "<td> $word[3] </td>\n";
+	print STDOUT "<td> $word[5] </td><td> $word[6] </td><td> $word[8] </td><td><img src=$www/$medname></td>\n";
+	if ($used) { print STDOUT "<td bgcolor=#00c000>yes</td>\n"; }
+	else       { print STDOUT "<td bgcolor=#d00000>no</td>\n"; }
+    }
+    $Nimage = $i;
+    
+    print STDOUT "</table>\n";
+    print STDOUT "</body>\n";
+    
+    &goodbye;
+    
+}
+
+#### process report for html3 ##########
+sub flips_entry {
+    
+    my($version)= $_[0];		# version of desired entry
+    my($entry)  = $_[1];		# desired entry in list
+    my($line)   = $_[2];		# list of image stats
+    
+    open (STAT, mknames ("stats", $line));
+    open (TEN,  mknames ("tenbin", $line));
+    
+    for ($i = 0; ($i < $entry + 1) && ($line = <STAT>) && ($tenline = <TEN>); $i++) {}
+    if ($i != $entry + 1) { &escape ("</table> selected entry out of range"); }
+    
+    $first = ($entry == 0);
+    $tmp = <STAT>;
+    $last = ($tmp == "");
+    $next = $entry + 1;
+    $prev = $entry - 1;
+    
+    chop ($line);
+    @word = split (" ",$line);
+    $keep = $word[12];
+    
+    # mkdetrend works with files in the user's paths, but the web page needs 
+    # to work with files visible to the web server
+    chop ($tenline);
+    @tmpw = split ("/", $tenline);
+    $N = @tmpw - 1;
+    $name = $tmpw[$N];
+    
+    $sig1 = sprintf "%5.3f", $word[4];
+    $sig2 = sprintf "%5.3f", $word[5];
+    $sig3 = sprintf "%5.3f", $word[6];
+    $sig4 = sprintf "%5.3f", $word[7];
+    $mean = sprintf "%8.1f", $word[3];
+    
+    print STDOUT "<img width=100% src=$www/$name>\n";
+    
+    print STDOUT "<table><tr><td>\n";
+    print STDOUT "<table border>\n";
+    print STDOUT "<tr><th> image </th><th> Date </th><th> Time </th><th> Mean </th>\n";
+    print STDOUT "<th> Sigma (raw) </th><th> Sigma (clipped) </th><th> Sigma (med) </th><th> used? </th></tr>\n\n";
+    
+    print STDOUT "<tr><td> $word[0] </a></td><td> $word[1] </td><td> $word[2] </td><td> $word[3] </td>\n";
+    print STDOUT "<td> $word[5] </td><td> $word[6] </td><td> $word[8] </td>\n";
+    if ($keep) {
+	print STDOUT "<td>yes</td>\n";
+    } else {
+	print STDOUT "<td bgcolor=#ff0000>no</td>\n";
+    }	
+    print STDOUT "</tr>\n\n";
+    print STDOUT "</table>\n";
+    
+    print STDOUT "</td></tr>\n";
+
+    print STDOUT "<tr><td> return to <a href=$CGI/dt.elixir1&elconf=$elconf> config list </a></tr></td>\n"; 
+    print STDOUT "<tr><td> return to <a href=$CGI/dt.elixir2?$version&elconf=$elconf> $version </a></tr></td>\n"; 
+    if (!$first) { print STDOUT "<tr><td> goto <a href=$CGI/dt.elixir3?$prev.$version&elconf=$elconf> prev </a> image </td></tr>\n"; }
+    if (!$last)  { print STDOUT "<tr><td> goto <a href=$CGI/dt.elixir3?$next.$version&elconf=$elconf> next </a> image </td></tr>\n"; }
+    print STDOUT "</table>\n";
+    
+    print STDOUT "</body>\n";
+    &goodbye;
+}
+
+#################### functions to abstract file databases ###################
+
+# set config value
+# TYPE FILTER CRUNID VERSION START STOP STATE
+# CRUNID TYPE FILTER [CCD] VERSION START STOP STATE
+#**************************
+sub stconfig {
+    # in: (config line) (value) (type)
+    my (@words) = split (" ", $_[0]);
+    my ($type)  = $_[1];
+    my ($value) = $_[2];
+    my ($line);
+
+    $format = "%s %6s %5s %2d %s %s %s";
+
+    { 
+	if ($type eq "all") {
+	    $line = sprintf $format, $words[0], $words[1], $words[2], $words[3], $words[4], $words[5], $words[6];
+	    last;
+	}
+	if ($type eq "version") {
+	    $line = sprintf $format, $words[0], $words[1], $words[2], $value, $words[4], $words[5], $words[6];
+	    last;
+	}
+	if ($type eq "start") {
+	    $line = sprintf $format, $words[0], $words[1], $words[2], $words[3], $value, $words[5], $words[6];
+	    last;
+	}
+	if ($type eq "stop") {
+	    $line = sprintf $format, $words[0], $words[1], $words[2], $words[3], $words[4], $value, $words[6];
+	    last;
+	}
+	if ($type eq "status") {
+	    $line = sprintf $format, $words[0], $words[1], $words[2], $words[3], $words[4], $words[5], $value;
+	    last;
+	}
+	&escape ("unknown type $type for stconfig\n");
+    }
+
+    return $line;
+}
+
+# load config lines (returns @list)
+sub load_config {
+    my ($file, $line, @list);
+    
+    $file = mkfiles ("config");
+    @list = ();
+    open (FILE, "$file");
+    while ($line = <FILE>) {
+	chop ($line);
+	@list = (@list, $line);
+    }
+    close (FILE);
+    
+    @list;
+}
+
+# write to config file
+sub save_config {
+
+    my(@outlist) = sort @_;
+    
+    my($file) = mkfiles ("config");
+    open (FILE, ">$file");
+    for ($i = 0; $i < @outlist; $i++) {
+	print FILE "$outlist[$i]\n";
+    }
+    close (FILE);
+}    
+
+# load dates & mode (returns @list)
+sub load_dates {
+    my ($file, $line, @list);
+    my ($start, $stop, $mode);
+    
+    $file = mkfiles ("dates");
+    @list = ();
+    open (FILE, "$file");
+    @list = <FILE>;
+    close (FILE);
+
+    ($tmp, $start) = split (" ", $list[0]);
+    if ($tmp ne "START") { print STDERR "dates file is confused\n"; }
+
+    ($tmp, $stop) = split (" ", $list[1]);
+    if ($tmp ne "STOP") { print STDERR "dates file is confused\n"; }
+    
+    ($tmp, $mode) = split (" ", $list[2]);
+    if ($tmp ne "MODE") { print STDERR "dates file missing mode\n"; }
+    if ($mode eq "") { $mode = "hold"; }
+
+    ($start, $stop, $mode);
+}
+
+# write to dates file
+sub save_dates {
+    # save_dates start stop auto.mode
+    my (@outlist) = @_;
+
+    my ($file) = mkfiles ("dates");
+    open (FILE, ">$file");
+    print FILE "START $outlist[0]\n";
+    print FILE "STOP  $outlist[1]\n";
+    print FILE "MODE  $outlist[2]\n";
+    close (FILE);
+}    
+
+# $root/detrend.config    - current run
+# $det/config.dat         - config info for specific run, 1 line per setup
+# $det/dates.dat          - dates for specific run
+# $det/detrend.list       - temporary list to pass to elixirs
+# $det/flips              - directory to store temporary data
+# $det/split              - directory to store temporary images
+# $det/html               - directory to store results for www
+# $www/$run/html          - html directory as seen by Web server
+
+# construct specific file names
+sub mkfiles {
+    # in: (type)
+    my($type) = $_[0];
+    my($value);
+    
+    { 
+	if ($type eq "run") {
+	    $value = "$root/detrend.config";
+	    last;
+	}
+	if ($type eq "detdir") {
+	    $value = "$det";
+	    last;
+	}
+	if ($type eq "config") {
+	    $value = "$det/config.dat";
+	    last;
+	}
+	if ($type eq "dates") {
+	    $value = "$det/dates.dat";
+	    last;
+	}
+	if ($type eq "list") {
+	    $value = "$det/detrend.list";
+	    last;
+	}
+	if ($type eq "html") {
+	    $value = "$det/html";
+	    last;
+	}
+	if ($type eq "stats") {
+	    $value = "$det/stats";
+	    last;
+	}
+	if ($type eq "flips") {
+	    $value = "$det/flips";
+	    last;
+	}
+	if ($type eq "links") {
+	    $value = "$det/flips/links";
+	    last;
+	}
+	if ($type eq "split") {
+	    $value = "$det/split";
+	    last;
+	}
+	if ($type eq "www") {
+	    $value = "$www";
+	    last;
+	}
+	&escape ("unknown type $type for mkfiles");
+    }
+    $value;    
+}
+
+# construct files from config info:
+# CRUNID TYPE FILTER [CCD] VERSION START STOP STATE
+#**************************
+
+sub mknames {
+    # in: (type) (config.ver) [ccd]
+    my ($type, $version, @words, $dir, $value, $ccd);
+
+    $type = $_[0];
+    $version = $_[1];
+    @words = split (" ", $version);
+    
+    { 
+	# final versions in html dir:
+	if ($type eq "stats") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].stats";
+	    last;
+	}
+	if ($type eq "medbin") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].medbin";
+	    last;
+	}
+	if ($type eq "tenbin") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].tenbin";
+	    last;
+	}
+	if ($type eq "imbin") {
+	    $dir = mkfiles ("www");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].imbin.000.jpg";
+	    last;
+	}
+	if ($type eq "dads.imbin") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].imbin.000.jpg";
+	    last;
+	}
+	# files used for processing:
+	if ($type eq "master") {
+	    $dir = mkfiles ("flips");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames master"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].master";
+	    last;
+	}
+	if ($type eq "msplit") {
+	    $dir = mkfiles ("flips");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames master"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].msplit";
+	    last;
+	}
+	if ($type eq "norm") {
+	    $dir = mkfiles ("flips");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames norm"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].norm";
+	    last;
+	}
+	if ($type eq "fits") {
+	    $dir = mkfiles ("flips");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames fits"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].fits";
+	    last;
+	}
+	if ($type eq "link") {
+	    $dir = mkfiles ("links");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames fits"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].fits";
+	    last;
+	}
+	if ($type eq "mef") {
+	    $dir = mkfiles ("flips");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].fits";
+	    last;
+	}
+	if ($type eq "proc.medbin") {
+	    $dir = mkfiles ("flips");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames proc.medbin"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].medbin";
+	    last;
+	}
+	if ($type eq "proc.tenbin") {
+	    $dir = mkfiles ("flips");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames proc.tenbin"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].tenbin";
+	    last;
+	}
+	if ($type eq "proc.imbin") {
+	    $dir = mkfiles ("flips");
+	    $ccd = $_[2];
+	    if ($ccd eq "") { &escape ("missing CCD for mknames proc.imbin"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].imbin";
+	    last;
+	}
+	&escape ("unknown type $type for mknames");
+    }    
+    return ($value);
+}
+
+# parse config info
+# TYPE FILTER CRUNID VERSION START STOP STATE
+# CRUNID TYPE FILTER [CCD] VERSION START STOP STATE
+#**************************
+sub gtconfig {
+    my ($value, $type, @words);
+    # in: (config line) (type)
+    @words = split (" ", $_[0]);
+    $type = $_[1];
+
+    { 
+	if ($type eq "elixir") {
+	    $value = "$words[0] $words[1] $words[2] $words[3]";
+	    last;
+	}
+	if ($type eq "mosaic") {
+	    $ccd = "xx";
+	    $value = "$words[0] $words[1] $words[2] $ccd $words[3] $words[4] $words[5]";
+	    last;
+	}
+	if ($type eq "chiprun") {
+	    $ccd  = $_[2];
+	    $value = "$words[0] $words[1] $words[2] $ccd $words[3] $words[4] $words[5]";
+	    last;
+	}
+	if ($type eq "config") {
+	    $value = "$words[0].$words[1].$words[2]";
+	    last;
+	}
+	if ($type eq "version") {
+	    $value = "$words[0].$words[1].$words[2].$words[3]";
+	    last;
+	}
+	if ($type eq "ID") {
+	    $value = "$words[0]";
+	    last;
+	}
+	if ($type eq "type") {
+	    $value = "$words[1]";
+	    last;
+	}
+	if ($type eq "filter") {
+	    $value = "$words[2]";
+	    last;
+	}
+	if ($type eq "from") {
+	    $value = "$words[4]";
+	    last;
+	}
+	if ($type eq "to") {
+	    $value = "$words[5]";
+	    last;
+	}
+	if ($type eq "status") {
+	    $value = "$words[6]";
+	    last;
+	}
+	&escape ("unknown type for gtconfig: $type");
+    }
+    
+    return $value;
+}
+
+# grab complete configuration info from the elixir config system, 
+# applying appropriate command-line arguments
+sub elixir_config {
+    my (@argv) = @_;
+    my ($opt, $config, @tmparg, $status, $keyword, $value);
+    $config = "";
+    if ($ENV{'PTOLEMY'}) { $config = "-c $ENV{'PTOLEMY'}"; }
+    umask (0);
+
+    # look for optional command-line arguments
+    while (@argv) {
+	$value = shift @argv;
+
+	if ($value eq "-c") {
+	    $value = shift @argv;
+	    $config = "-c $value";
+	    next;
+	}
+
+	if ($value eq "-C") {
+	    $elconf = shift @argv;
+	    push @opt, "-C $elconf";
+	    next;
+	}
+	
+	if ($value eq "-D") {
+	    $keyword = shift @argv;
+	    $value = shift @argv;
+	    push @opt, "-D $keyword $value";
+	    next;
+	}
+	
+	if ($value eq "-run") {
+	    $run = shift @argv;
+	    push @opt, "-D RUNID.MKDETREND $run -D RUNID $run";
+	    next;
+	}
+	
+	if ($value eq "-camera") {
+	    $camera = shift @argv;
+	    push @opt, "-D CAMERA.MKDETREND $camera -D CAMERA $camera";
+	    next;
+	}
+	push @argt, $value;
+    }
+    @argv = @argt;
+
+    # load RUNID from state.data (unless set on command line)
+    if ($run eq "") {
+	$run = `gconfig RUNID.MKDETREND`; chop $run;
+	if ($?) {  &escape ("run is not defined: use '$MKDETREND config' or 'mkrun sys'\n"); }
+	if ($run eq "") {  &escape ("run is not defined: use '$MKDETREND config' or 'mkrun sys'\n"); }
+	push @opt, "-D RUNID.MKDETREND $run -D RUNID $run";
+    }
+
+    # load CAMERA from state.data (unless set on command line)
+    if ($camera eq "") {
+	$camera = `gconfig CAMERA.MKDETREND`; chop $camera;
+	if ($?) {  &escape ("camera is not defined: use 'mkrun sys' to set\n"); }
+	if ($camera eq "") {  &escape ("camera is not defined: use 'mkrun sys'\n"); }
+	push @opt, "-D CAMERA.MKDETREND $camera -D CAMERA $camera";
+    }
+
+    # set env PTOLEMY using values from command line
+    $config = join (" ", $config, @opt);
+    $tmpenv = `mktemp /tmp/elixir.XXXXXX`; chop ($tmpenv);
+    $status = system ("gconfig -raw $config > $tmpenv");
+    if ($status) { &escape ("error in elixir configuration: gconfig fails"); }
+    $ENV{'PTOLEMY'} = "$tmpenv";
+
+    # set global variables based on new config info
+    $root = `gconfig DETREND_ROOT`; chop $root;
+    if ($?) { &escape ("error with elixir configuration variable: DETREND_ROOT"); }
+
+    $wwwroot  = `gconfig DETREND_WWW`; chop $wwwroot;
+    if ($?) { &escape ("error with elixir configuration variable: DETREND_WWW"); }
+    
+    $Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+    if ($?) { &escape ("error with elixir camera configuration"); }
+
+    @ccds = split (" ", `cameraconfig -ccdn`);
+    if ($?) { &escape ("error with elixir camera configuration"); }
+
+    # get list of valid filters from lookup table
+    $answer = `filtnames list`;
+    if ($?) { &escape ("error with elixir filter configuration"); }
+
+    # these are the 'flat' types to create:
+    @filt = split (" ", $answer);
+    @type = ();
+    foreach $name (@filt) { push @type, "flat"; }
+    
+    # bias and dark use the exposure time as the 'filter'
+    @type = (@type, 'bias', 'dark', 'dark', 'dark', 'dark');
+    @filt = (@filt, '0',    '60',   '300',  '900',  '1800');
+    # determine dark times from existing data?
+
+    $CGI = `gconfig CGIBIN`; chop ($CGI);
+    if ($?) { &escape ("error with elixir configuration variable: CGIBIN"); }
+
+    $det  = "$root/$run";
+    $www  = "$wwwroot/$run/html";
+    $dadswww = "img";
+
+    return (@argv);
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye { 
+    unlink $tmpenv;
+    exit 0; 
+}
+
+sub escape { 
+    unlink $tmpenv;
+    print "$_[0]\n";
+    exit 1;
+}
+
+sub usage {
+    if (@ARGV == 1) {
+	print STDERR "\n --- user modes ---\n";
+	print STDERR "create (run) (startdate) (stopdate)\n";
+	print STDERR "config (run)\n";
+	print STDERR "init\n";
+	print STDERR "run\n";
+	print STDERR "list.runs\n";
+	print STDERR "set (config.ver) (state)\n";
+	print STDERR "reg\n";
+	print STDERR "state \n";
+	print STDERR "help \n";
+	print STDERR "\n --- internal modes --- \n";
+	print STDERR "flips\n";
+	print STDERR "norm\n";
+	print STDERR "update\n";
+	print STDERR "merge\n";
+	print STDERR "dup (config)\n";
+	print STDERR "del (config)\n";
+	print STDERR "def (config.ver) (start) (stop)\n";
+	print STDERR "eval (step)\n";
+	print STDERR "mevel (step)\n";
+	print STDERR "htmldup\n";
+	print STDERR "htmldel\n";
+	print STDERR "htmldef\n";
+	print STDERR "htmlmod\n";
+	print STDERR "htmlkeep\n";
+	print STDERR "html1\n";
+	print STDERR "html2 (config.ver)\n";
+	print STDERR "html3 (entry.config.ver)\n";
+	&escape;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: $MKDETREND (help) [mode]\n"; &escape; }
+    
+    if ($ARGV[1] eq "config") {
+	print STDERR "set up initial configuration\n";
+	&escape;
+    }
+    
+    if ($ARGV[1] eq "save") {
+	print STDERR "save results from current configuration\n";
+	&escape;
+    }
+    
+    print STDERR "help for $ARGV[1] no defined\n";
+    &escape;
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mkfringe
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mkfringe	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mkfringe	(revision 16632)
@@ -0,0 +1,2811 @@
+#!/usr/bin/perl
+$MKFRINGE = mkfringe;
+
+# strip off args related to the elixir config system, set env PTOLEMY
+@ARGV = elixir_config (@ARGV);
+
+# interpret command-line arguments
+if (@ARGV < 1) {
+    print STDOUT "USAGE: $MKFRINGE (mode) [arguments]\n";
+    print STDOUT "mode = help gives a complete list\n";
+    &escape;
+}
+if ($ARGV[0] eq "help") { &usage; }
+
+# user level commands
+if ($ARGV[0] eq "create")     { &mk_create;     }
+if ($ARGV[0] eq "config")     { &mk_config;     }
+if ($ARGV[0] eq "init")       { &mk_init;       }
+if ($ARGV[0] eq "run")        { &mk_run;        }
+if ($ARGV[0] eq "state")      { &mk_state;      }
+if ($ARGV[0] eq "mkconfig")   { &mk_mkconfig;   }
+if ($ARGV[0] eq "list.runs")  { &mk_list_runs;  }
+if ($ARGV[0] eq "clean")      { &mk_cleanup;    }
+if ($ARGV[0] eq "set")        { &mk_set;        }
+if ($ARGV[0] eq "reg")        { &mk_reg;        }
+
+if ($ARGV[0] eq "dup")        { &mk_dup;        }
+if ($ARGV[0] eq "del")        { &mk_del;        }
+if ($ARGV[0] eq "def")        { &mk_def;        }
+if ($ARGV[0] eq "list.init")  { &mk_list_init;  }
+if ($ARGV[0] eq "list.reinit")  { &mk_list_reinit;  }
+if ($ARGV[0] eq "detrend")    { &mk_detrend;    }
+if ($ARGV[0] eq "merge")      { &mk_merge;      }
+if ($ARGV[0] eq "mkrough")    { &mk_mkrough;    }
+if ($ARGV[0] eq "mksmooth")   { &mk_smooth;    }
+if ($ARGV[0] eq "regimage")   { &mk_regimage;    }
+if ($ARGV[0] eq "defringe")   { &mk_defringe;   }
+
+if ($ARGV[0] eq "map")        { &mk_map;        }
+if ($ARGV[0] eq "map.reg")    { &mk_map_reg;    }
+
+# HTML cgibin commands
+if ($ARGV[0] eq "htmldup")    { &mk_htmldup;    }
+if ($ARGV[0] eq "htmldel")    { &mk_htmldel;    }
+if ($ARGV[0] eq "htmldef")    { &mk_htmldef;    }
+if ($ARGV[0] eq "htmlmod")    { &mk_htmlmod;    }
+if ($ARGV[0] eq "htmlmodes")  { &mk_htmlmodes;  }
+if ($ARGV[0] eq "htmlmaps")   { &mk_htmlmaps;   }
+if ($ARGV[0] eq "htmlkeep")   { &mk_htmlkeep;   }
+if ($ARGV[0] eq "htmlmapkeep"){ &mk_htmlmapkeep;}
+if ($ARGV[0] eq "htmlconfig") { &mk_htmlconfig; }
+if ($ARGV[0] eq "html1")      { &mk_html1;      }
+if ($ARGV[0] eq "html2")      { &mk_html2;      }
+if ($ARGV[0] eq "html3")      { &mk_html3;      }
+# support commands
+if ($ARGV[0] eq "dads")       { &mk_dads;       }
+if ($ARGV[0] eq "dads.top")   { &mk_dads_top;   }
+if ($ARGV[0] eq "eval")       { &mk_eval;       }
+
+&escape ("invalid mkfring command $ARGV[0]");
+
+############# define/redefine config ##############
+sub mk_create {
+    
+    if ($ARGV[1] eq "run") { &mk_createrun; }
+    if (@ARGV != 5) { &escape ("USAGE: $MKFRINGE create (camera) (run) (startdate) (stopdate)"); }
+    
+    # setting $run & $start here overrides default values loaded by set_globals()
+    $camera = $ARGV[1];
+    $run    = $ARGV[2];
+    $start  = $ARGV[3];
+    $stop   = $ARGV[4];
+
+    if (0) {
+	# set current run id:
+	system ("mkrun sys camera.mkfringe $camera");
+	if ($?) { &escape ("can't define camera: error in mkrun"); }
+    
+	# set current camera:
+	system ("mkrun sys runid.mkfringe $run");
+	if ($?) { &escape ("can't define run: error in mkrun"); }
+    }
+
+    # reset values for the directories, etc.
+    $oldenv = $tmpenv;
+    &elixir_config (split (" ", "-run $run -camera $camera"));
+    unlink ($oldenv);
+
+    # create the new detdir (& subdirectories?)
+    $file = mkfiles ("detdir");
+    if (! -d $file) {
+	if (! mkdir ($file, 0777)) {
+	    &escape ("can't create detdir $file");
+	}
+    }
+    ($tmp, $tmp, $mode) = &load_dates;
+    &save_dates ($start, $stop, $mode);
+
+    # create run-specific config file
+    @list = ();
+    for ($i = 0; $i < @filt; $i++) {
+	$line = stconfig ("$run $type[$i] $filt[$i] 0 $start $stop init", "all");
+	@list = (@list, $line);
+    }
+    save_config (@list);
+    
+    &goodbye;
+}
+
+############# define/redefine config ##############
+sub mk_createrun {
+    
+    if (@ARGV != 3) { &escape ("USAGE: $MKFRINGE create run (run)"); }
+    if ($ARGV[1] ne "run") { &escape ("USAGE: mkdetrend create run (run)"); }
+    
+    # setting $run & $start here overrides default values loaded by set_globals()
+    $run    = $ARGV[2];
+    $answer = `mkrun run $run`;
+    if ($?) { &escape ("run $run not defined, use 'mkrun'"); }
+    ($newrun, $start, $stop, $camera) = split (" ", $answer);
+    if ($run ne $newrun) { &escape ("inconsistent answer from mkrun run $run"); }
+
+    # reset values for the directories, etc.
+    $oldenv = $tmpenv;
+    &elixir_config (split (" ", "-run $run -camera $camera"));
+    unlink ($oldenv);
+
+    # create the new detdir (& subdirectories?)
+    $file = mkfiles ("detdir");
+    if (! -d $file) {
+	if (! mkdir ($file, 0777)) {
+	    &escape ("can't create detdir $file");
+	}
+    }
+    ($tmp, $tmp, $mode) = &load_dates;
+    &save_dates ($start, $stop, $mode);
+
+    # create run-specific config file
+    @list = ();
+    for ($i = 0; $i < @filt; $i++) {
+	$line = stconfig ("$run $type[$i] $filt[$i] 0 $start $stop init", "all");
+	@list = (@list, $line);
+    }
+    save_config (@list);
+    
+    &goodbye;
+}
+
+############# change current run ##############
+sub mk_config {
+    
+    if (@ARGV != 3) { &escape ("USAGE: $MKFRINGE config (camera) (run)"); }    
+
+    $camera = $ARGV[1];
+    $run    = $ARGV[2];
+
+    # set current run id:
+    system ("mkrun sys camera.mkfringe $camera");
+    if ($?) { &escape ("can't define camera: error in mkrun"); }
+    
+    # set current run id:
+    system ("mkrun sys runid.mkfringe $run");
+    if ($?) { &escape ("can't define run: error in mkrun"); }
+    
+    &goodbye;
+}
+
+############# init ##############
+sub mk_init {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE run"); }
+
+    system "$MKFRINGE list.init\n";
+    system "$MKFRINGE detrend\n";
+    system "$MKFRINGE merge\n";
+    &goodbye;
+}
+
+############# main run ##############
+sub mk_run {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE run"); }
+    
+    system "$MKFRINGE mkrough";
+    system "$MKFRINGE defringe";
+    system "$MKFRINGE merge";
+    
+    &goodbye;
+}
+
+############# main run ##############
+sub mk_reg {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE reg"); }
+    
+    system "$MKFRINGE mksmooth";
+    system "$MKFRINGE regimage";
+    
+    &goodbye;
+}
+
+############# show current state ##############
+sub mk_state {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE state"); }
+    
+    ($start, $stop, $mode) = &load_dates;
+
+    print STDOUT "CAMERA    $camera\n";
+    print STDOUT "RUN       $run\n";
+    print STDOUT "START     $start\n";
+    print STDOUT "STOP      $stop\n";
+    print STDOUT "MODE      $mode\n";
+    
+    @list = &load_config;
+    if (@list == 0) { &escape ("$MKFRINGE not configured"); }
+
+    for ($i = 0; $i < @list; $i++) {
+	printf STDOUT "%3d %s\n", $i, $list[$i];
+    }
+    &goodbye;
+}
+
+############# show existing runs ##############
+sub mk_list_runs {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE list.runs"); }
+    
+    system ("ls $root");
+    &goodbye;
+}
+
+############# create config list ##############
+sub mk_mkconfig {
+    
+    # create mkfringe config file from existing date entries
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE mkconfig"); }
+    
+    # if new run, need to create the new detdir
+    $file = mkfiles ("detdir");
+    if (! -d $file) {
+	if (! mkdir ($file, 0777)) {
+	    &escape ("can't create detdir $file");
+	}
+    }
+
+    ($start, $stop, $mode) = &load_dates;
+    if (($start eq "") || ($stop eq "")) { &escape ("dates are not defined: use '$MKFRINGE config'"); }
+
+    # create run-specific config file
+    @list = ();
+    for ($i = 0; $i < @filt; $i++) {
+	$line = stconfig ("$run $type[$i] $filt[$i] 0 $start $stop init", "all");
+	@list = (@list, $line);
+    }
+    save_config (@list);
+    &goodbye;
+}
+
+############## duplicate config ###############
+sub mk_dup {
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKFRINGE dup (config)"); }
+    
+    $key = $ARGV[1];
+    @list = load_config ();
+    
+    # look for entry that matches requested config.ver
+    @match = ();
+    for ($i = 0; $i < @list; $i++) {
+	$config = gtconfig ($list[$i], "config");
+	if ($key eq $config) { @match = (@match, $i); }
+    }
+    if (@match == 0) { &escape ("config.ver $key not found"); }
+    
+    # create new config version based on config version # 0
+    $Nnew = @match;
+    $old = $list[$match[0]];
+    $new = stconfig ($old, "version", $Nnew);
+    @list = (@list, $new);
+    save_config (@list);
+    
+    # now we need to duplicate all of the reference files from the first config 
+    &goodbye;
+}
+
+############## cleanup config ###############
+sub mk_cleanup {
+    
+    if ((@ARGV != 1) && (@ARGV != 2)) { &escape ("USAGE: $MKFRINGE cleanup [mode]"); }
+
+    @list = load_config ();
+
+    $detdir = mkfiles ("detdir");
+    open (CF, ">$detdir/clean.fail");
+
+    $Nmiss = 0;
+    $Nfail = 0;
+    $Ngood = 0;
+
+    $mode = "partial"; 
+    if (@ARGV == 2) { $mode = $ARGV[1]; }
+
+    if (($mode ne "partial") && ($mode ne "total")) { &escape ("invalid cleanup mode $mode: use 'partial' or 'total'"); }
+
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "done") { next; }
+
+	print STDERR "deleting files from $confline\n";
+	$confline = stconfig ($confline, "status", "running.clean");
+	save_config (@list);
+
+	foreach $ccd (@ccds) { 
+	    @dlist = ();
+
+	    # delete these specific files:
+	    push @dlist, &mknames ("frfile", $confline, $ccd); 
+	    push @dlist, &mknames ("smfile", $confline, $ccd); 
+
+	    # delete file, if it exists
+	    foreach $file (@dlist) { 
+		if (! -e $file) { $Nmiss ++; next; }
+		if (!unlink $file) { $Nfail ++; print CF "$file\n"; next; }
+		$Ngood ++;
+	    }
+	}
+
+	# delete final MEF image
+	@dlist = ();
+	push @dlist, &mknames ("mef", $confline); 
+
+	# delete proc defringe, medbin images
+	$name = &mknames ("detrend", $confline);
+	open (FILE, $name);
+	@deflist = <FILE>;
+	close (FILE);
+
+	$proc = &mkfiles ("proc");
+	foreach $line (@deflist) {
+	    ($tmp, $root) = split (" ", $line);
+	    push @dlist, <$proc/$root.med/*.fits>;
+	    push @dlist, <$proc/$root.def/*.fits>;
+	}	    
+
+	# delete file, if it exists
+	foreach $file (@dlist) { 
+	    if (! -e $file) { $Nmiss ++; next; }
+	    if (!unlink $file) { $Nfail ++; print CF "$file\n"; next; }
+	    $Ngood ++;
+	}
+
+	$confline = stconfig ($confline, "status", "clean");
+	save_config (@list);
+    }
+    close (CF);
+
+    print STDERR "$Ngood files deleted\n";
+    print STDERR "$Nmiss files already removed\n";
+    print STDERR "$Nfail files not deleted, see '$detdir/clean.fail'\n";
+
+    &goodbye;
+}
+
+
+
+############## delete config ###############
+sub mk_del {
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKFRINGE del (config.ver)"); }
+    
+    $key = $ARGV[1];
+    @list = load_config ();
+    
+    # look for entry that matches requested config
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}	
+    }
+    if ($match == -1) { &escape ("config.ver $key not found"); }
+    
+    # create new list without match:
+    @newlist = ();
+    for ($i = 0; $i < @list; $i++) {
+	if ($i == $match) { next; }
+	@newlist = (@newlist, $list[$i]);
+    }
+    
+    save_config (@newlist);
+    &goodbye;
+    
+}
+
+
+
+############## define config ###############
+sub mk_def {
+    
+    if (@ARGV != 4) { &escape ("USAGE: $MKFRINGE def (config.ver) (start) (stop)"); }
+    
+    $key   = $ARGV[1];
+    $start = $ARGV[2];
+    $stop  = $ARGV[3];
+    
+    @list = load_config ();
+    
+    # find specific config:
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	}	
+    }
+    if (@match == -1) { &escape ("config.ver $key not found"); }
+    
+    $new = $list[$match];
+    $new = stconfig ($new, "start", $start);
+    $new = stconfig ($new, "stop", $stop);
+    $list[$match] = $new;
+    save_config (@list);
+
+    &goodbye;
+}
+
+
+
+############## set state ###############
+sub mk_set {
+    
+    if (@ARGV != 3) { &escape ("USAGE: $MKFRINGE set (config number) (state)"); }
+    
+    @list = load_config ();
+    
+    $key = $ARGV[1];
+    $state = $ARGV[2];
+    
+    $new = stconfig ($list[$key], "status", $state);
+    $list[$key] = $new;
+    
+    save_config (@list);
+    
+    &goodbye;
+}
+
+############## init run ###############
+
+
+# get valid images, create static lists
+sub mk_list_init {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE list.init"); }
+    
+    # create necessary directories
+    foreach $name ("html", "proc", "fringe") {
+	$dir = mkfiles ($name);
+	if (! -e $dir) {
+	    print STDERR "making $dir\n";
+	    $status = mkdir ("$dir", 0777);
+	    if (!$status) { die "can't create directory $dir\n"; }
+	}
+    }
+    @list = load_config ();
+    
+    # create elixir input list, set status to 'running.init'
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status eq "skip.init") { next; }
+
+	$line = gtconfig ($confline, "elixir");
+	print FILE "$line\n";
+	$confline = stconfig ($confline, "status", "running.init");
+    }
+    close (FILE);
+    save_config (@list);
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode fringe1 $file");
+    vsystem ("$MKFRINGE eval $file init");
+
+    open (FILE, "$file.eval");
+    @eval = <FILE>;
+    close (FILE);
+
+    # there is an entry in @eval for each @list with status of "running.init"
+    $N = 0;
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "running.init") { next; }
+	@words = split (" ", $eval[$N]);
+	if ($words[-1] == 0) { $status = "done.init"; }
+	if ($words[-1] == 1) { $status = "fail.init"; }
+	if ($words[-1] == 2) { $status = "fail.init"; }
+	if ($words[-1] == 3) { $status = "not.available"; }
+	$confline = stconfig ($confline, "status", $status);
+	$N++;
+    }
+    save_config (@list);
+    &goodbye;
+}
+
+# is this segment still used?
+# run mode.fringe1, skipping image selection
+sub mk_list_reinit {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE list.init"); }
+    
+    # create necessary directories
+    foreach $name ("html", "proc", "fringe") {
+	$dir = mkfiles ($name);
+	mkdir ("$dir", 0777);
+    }
+    
+    @list = load_config ();
+    
+    # create elixir input list, set status to 'running.init'
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status eq "skip.init") { next; }
+
+	$line = gtconfig ($confline, "elixir");
+	print FILE "$line\n";
+	$confline = stconfig ($confline, "status", "running.reinit");
+    }
+    close (FILE);
+    save_config (@list);
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode fringe1 -D global.pending master.lists $file");
+    vsystem ("$MKFRINGE eval $file init");
+
+    open (FILE, "$file.eval");
+    @eval = <FILE>;
+    close (FILE);
+
+    # there is an entry in @eval for each @list with status of "running.init"
+    $N = 0;
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "running.reinit") { next; }
+	@words = split (" ", $eval[$N]);
+	if ($words[-1] == 0) { $status = "done.init"; }
+	if ($words[-1] == 1) { $status = "fail.init"; }
+	if ($words[-1] == 2) { $status = "fail.init"; }
+	if ($words[-1] == 3) { $status = "not.available"; }
+	$confline = stconfig ($confline, "status", $status);
+	$N++;
+    }
+    save_config (@list);
+    &goodbye;
+}
+
+
+############## detrend ###############
+sub mk_detrend {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE detrend"); }
+
+    @list = load_config ();
+    
+    # create namelist for those with appropriate status
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    system ("rm -f $file");
+
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.init") && ($status ne "modified") && ($status ne "detrend")) { next; }
+
+	$Nrun ++;
+	$detrend = mknames ("detrend", $confline);
+
+	# merge lines from the "detrend" list to make elixir list
+	system ("cat $detrend >> $file");
+	
+	# set status for these config entries
+	$confline = stconfig ($confline, "status", "running.detrend");
+    }
+    save_config (@list);
+    
+    if ($Nrun == 0) { &goodbye; }
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode fringe2 $file"); 
+    vsystem ("$MKFRINGE eval $file detrend");
+
+    open (FILE, "$file.eval");
+    @eval = <FILE>;
+    close (FILE);
+
+    $N = 0;
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "running.detrend") { next; }
+
+	$detrend = mknames ("detrend", $confline);
+	open (FILE, "$detrend");
+	@testlist = <FILE>;
+	close (FILE);
+	
+	# each entry in $detrend must succeed for config to succeed
+	$status = "done.detrend";
+	for ($i = 0; $i < @testlist; $i++) {
+	    @words = split (" ", $eval[$N]);
+	    if ($words[-1] == 1) { $status = "fail.detrend"; }
+	    if ($words[-1] == 2) { $status = "fail.detrend"; }
+	    $N++;
+	}
+	$confline = stconfig ($confline, "status", $status);
+
+	$detrend = mknames ("detrend", $confline);
+	$master = mknames ("master", $confline);
+	# update master list (2 -> 0, 3 -> 1)
+	vsystem ("fr.mklists -master $master $detrend");
+    }
+    save_config (@list);
+
+    &goodbye;
+}
+
+############## map run ###############
+sub mk_map {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE map"); }
+
+    @list = load_config ();
+    
+    # this can be parallelized with elixir later...
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "map") && ($status ne "modified.map")) { next; }
+	$Nrun ++;
+	$confline = stconfig ($confline, "status", "running.map");
+	save_config (@list);
+
+	$maplist  = mknames ("maplist",  $confline);
+	$modelist = mknames ("modelist", $confline);
+	$modefits = mknames ("modefits", $confline);
+
+	$modesjpg = mknames ("modesjpg", $confline);
+	$residjpg = mknames ("residjpg", $confline);
+	$inmapjpg = mknames ("inmapjpg", $confline);
+
+	vsystem ("fr.mkmodes $maplist $modefits $modelist");
+	if ($status) { 
+	    $confline = stconfig ($confline, "status", "fail.map");
+	    save_config (@list);
+	    next;
+	}
+	vsystem ("fr.modestats $maplist $modefits $modelist $modesjpg $residjpg $inmapjpg");
+	if ($status) { 
+	    $confline = stconfig ($confline, "status", "fail.map");
+	    save_config (@list);
+	    next;
+	}
+	$confline = stconfig ($confline, "status", "done.map");
+	save_config (@list);
+    }
+    &goodbye;
+}
+
+############## map reg ###############
+sub mk_map_reg {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE map.reg"); }
+    
+    @list = load_config ();
+    
+    # this can be parallelized with elixir later...
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "accept.map") { next; }
+	$Nrun ++;
+	$confline = stconfig ($confline, "status", "register.map");
+	save_config (@list);
+
+	$modelist = mknames ("modelist", $confline);
+	$modefits = mknames ("modefits", $confline);
+	$modesave = mknames ("modesave", $confline);
+	$ID     = gtconfig ($confline, "ID");
+	$filter = gtconfig ($confline, "filter");
+	$from   = gtconfig ($confline, "from");
+	$to     = gtconfig ($confline, "to");
+
+	vsystem ("fr.modesave $modefits $modelist $modesave $from $to $filter");
+	vsystem ("detregister $modesave -label elixir -ID $ID");
+	$confline = stconfig ($confline, "status", "done.map.reg");
+	save_config (@list);
+    }
+    &goodbye;
+}
+
+############## mkrough run ###############
+sub mk_mkrough {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE mkrough"); }
+    
+    @list = load_config ();
+    
+    # create namelist for those with appropriate status
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.prep") && ($status ne "mkrough") && ($status ne "modified")) { next; }
+
+	$Nrun ++;
+
+	# one line for each config.ver.ccd:
+	for ($j = 0; $j < $Nccd; $j++) {
+	    $line = gtconfig ($confline, "chiprun", $ccds[$j]);
+	    print FILE "$line\n";
+	}
+	$confline = stconfig ($confline, "status", "running.mkrough");
+
+	$CONFIG  = mknames ("config", $confline);
+
+	# extract the selected subset of detrend images from master & statlist to sublist
+	vsystem ("fr.mklists -subset  $CONFIG.master $CONFIG.med.statlist $CONFIG.med.sublist");
+	if ($?) { &escape ("failure running fr.mklists -subset"); }
+
+	# extract the selected subset of defringed images from master & statlist to sublist
+	vsystem ("fr.mklists -subset  $CONFIG.master $CONFIG.def.statlist $CONFIG.def.sublist");
+	if ($?) { &escape ("failure running fr.mklists -subset"); }
+
+	# calculate fit parameters based on subset
+	vsystem ("fr.frstats -fitpars $CONFIG.med.sublist $CONFIG.fitpar");
+	if ($?) { &escape ("failure running fr.frstats -fitpars"); }
+
+	# calculate optimal per-image fringe statistics based on fit parameters
+	vsystem ("fr.frstats -frstats $CONFIG.med.statlist $CONFIG.fitpar $CONFIG.med.imstats");
+	if ($?) { &escape ("failure running fr.frstats -frstats"); }
+
+	# calculate per-image residual fringe stats 
+	vsystem ("fr.frstats -dfstats $CONFIG.def.statlist $CONFIG.fitpar $CONFIG.def.imstats");
+	if ($?) { &escape ("failure running fr.frstats -dfstats"); }
+
+	# assemble master fringe statistic file needed by web tools
+	vsystem ("fr.mklists -imstats $CONFIG.master $CONFIG.med.imstats $CONFIG.def.imstats $CONFIG.datlist $CONFIG.imstats");
+	if ($?) { &escape ("failure running fr.mklists -imstats"); }
+
+    }
+    close (FILE);
+    save_config (@list);
+
+    if ($Nrun == 0) { &goodbye; }
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode fringe4 $file");
+    vsystem ("$MKFRINGE eval $file mkrough");
+
+    open (FILE, "$file.eval");
+    @eval = <FILE>;
+    close (FILE);
+
+    # there is one entry in @eval for each ccd for each confline:
+    $N = 0;
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "running.mkrough") { next; }
+
+	# each chip must succeed for config to succeed
+	$status = "done.mkrough";
+	for ($j = 0; $j < $Nccd; $j++) {
+	    @words = split (" ", $eval[$N]);
+	    if ($words[-1] == 1) { $status = "fail.mkrough"; }
+	    if ($words[-1] == 2) { $status = "fail.mkrough"; }
+	    $N++;
+	}
+	$confline = stconfig ($confline, "status", $status);
+    }
+    save_config (@list);
+    
+    &goodbye;
+}
+
+############## defringe ###############
+sub mk_defringe {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE defringe"); }
+
+    @list = load_config ();
+    
+    # create namelist for those with appropriate status
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    system ("rm $file");
+
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.mkrough") && ($status ne "defringe")) { next; }
+
+	$Nrun ++;
+	$defringe = mknames ("defringe", $confline);
+	
+	# merge lines from the "defringe" list to make elixir list
+	system ("cat $defringe >> $file");
+	
+	$confline = stconfig ($confline, "status", "running.defringe");
+    }
+    save_config (@list);
+    
+    if ($Nrun == 0) { &goodbye; }
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode fringe3 $file"); 
+    vsystem ("$MKFRINGE eval $file defringe");
+
+    open (FILE, "$file.eval");
+    @eval = <FILE>;
+    close (FILE);
+
+    $N = 0;
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if ($status ne "running.defringe") { next; }
+
+	$defringe = mknames ("defringe", $confline);
+	open (FILE, "$defringe");
+	@testlist = <FILE>;
+	close (FILE);
+	
+	# each entry in $defringe must succeed for config to succeed
+	$status = "done.defringe";
+	for ($i = 0; $i < @testlist; $i++) {
+	    @words = split (" ", $eval[$N]);
+	    if ($words[-1] == 1) { $status = "fail.defringe"; }
+	    if ($words[-1] == 2) { $status = "fail.defringe"; }
+	    $N++;
+	}
+	$confline = stconfig ($confline, "status", $status);
+    }
+    save_config (@list);
+    &goodbye;
+}
+
+
+
+############## merge run ###############
+sub mk_merge {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE merge"); }
+
+    @list = load_config ();
+    
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.detrend") && ($status ne "done.defringe") && ($status ne "merge")) { next; }
+
+	$confline = stconfig ($confline, "status", "running.merge");
+	save_config (@list);
+
+	$CONFIG  = mknames ("config", $confline);
+	$VERSION = gtconfig ($confline, "version");
+	$HTML    = mkfiles ("html");
+
+	vsystem ("fr.mklists -subset  $CONFIG.master $CONFIG.med.statlist $CONFIG.med.sublist");
+	if ($?) { &escape ("failure running fr.mklists -subset"); }
+
+	vsystem ("fr.mklists -subset  $CONFIG.master $CONFIG.def.statlist $CONFIG.def.sublist");
+	if ($?) { &escape ("failure running fr.mklists -subset"); }
+
+	vsystem ("fr.frstats -fitpars $CONFIG.med.sublist $CONFIG.fitpar");
+	if ($?) { &escape ("failure running fr.frstats -fitpars"); }
+
+	vsystem ("fr.frstats -plotstats $CONFIG.med.statlist $CONFIG.fitpar $CONFIG.stats.png");
+	if ($?) { &escape ("failure running fr.frstats -plotstats"); }
+
+	vsystem ("fr.frstats -frstats $CONFIG.med.statlist $CONFIG.fitpar $CONFIG.med.imstats");
+	if ($?) { &escape ("failure running fr.frstats -frstats"); }
+
+	vsystem ("fr.frstats -dfstats $CONFIG.def.statlist $CONFIG.fitpar $CONFIG.def.imstats");
+	if ($?) { &escape ("failure running fr.frstats -dfstats"); }
+
+	vsystem ("fr.mklists -imstats $CONFIG.master $CONFIG.med.imstats $CONFIG.def.imstats $CONFIG.datlist $CONFIG.imstats");
+	if ($?) { &escape ("failure running fr.mklists -imstats"); }
+
+	$file = `head -1 $CONFIG.frlist`; chop ($file);
+	if (-e "$file") { 
+	    vsystem ("fr.jpegs $CONFIG.frlist $CONFIG.medbin.jpg $CONFIG.tenbin.jpg 0.02");
+	    if ($?) { &escape ("failure running fr.jpegs"); }
+	    vsystem ("fr.mkhtml -imstats $CONFIG.medbin.jpg $HTML");
+	    if ($?) { &escape ("failure running fr.mkhtml -jpgmain"); }
+	    vsystem ("fr.mkhtml -imstats $CONFIG.tenbin.jpg $HTML");
+	    if ($?) { &escape ("failure running fr.mkhtml -jpgmain"); }
+	} else {
+	    print STDOUT "no fits file $file\n";
+	}
+
+	vsystem ("fr.mkhtml -imstats $CONFIG.imstats $HTML");
+	if ($?) { &escape ("failure running fr.mkhtml -imstats"); }
+
+	vsystem ("fr.mkhtml -imstats $CONFIG.stats.png $HTML");
+	if ($?) { &escape ("failure running fr.mkhtml -imstats"); }
+
+	vsystem ("fr.mkhtml -jpglist $CONFIG.med.medbin.list $HTML $VERSION.med.medbin");
+	if ($?) { &escape ("failure running fr.mkhtml -jpglist"); }
+
+	vsystem ("fr.mkhtml -jpglist $CONFIG.med.tenbin.list $HTML $VERSION.med.tenbin");
+	if ($?) { &escape ("failure running fr.mkhtml -jpglist"); }
+
+	vsystem ("fr.mkhtml -jpglist $CONFIG.def.medbin.list $HTML $VERSION.def.medbin");
+	if ($?) { &escape ("failure running fr.mkhtml -jpglist"); }
+
+	vsystem ("fr.mkhtml -jpglist $CONFIG.def.tenbin.list $HTML $VERSION.def.tenbin");
+	if ($?) { &escape ("failure running fr.mkhtml -jpglist"); }
+
+	print STDOUT "CONFIG: $CONFIG.def.imstats\n";
+
+	if (-e "$CONFIG.def.imstats") { 
+	    $confline = stconfig ($confline, "status", "done.merge");
+	} else {
+	    $confline = stconfig ($confline, "status", "done.prep");
+	}
+	save_config (@list);
+    }
+
+    &goodbye;
+}
+
+############## reg run ###############
+sub mk_smooth {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE mksmooth"); }
+    
+    @list = load_config ();
+    
+    # create namelist for those with appropriate status
+    $Nrun = 0;
+    $file = mkfiles ("list");
+    open (FILE, ">$file");
+    foreach $confline (@list) {
+        $status = gtconfig ($confline, "status");
+        if (($status ne "accepted") && ($status ne "smooth")) { next; }
+
+        $Nrun ++;
+
+        # one line for each config.ver.ccd:
+        for ($j = 0; $j < $Nccd; $j++) {
+            $line = gtconfig ($confline, "chiprun", $ccds[$j]);
+            print FILE "$line\n";
+        }
+        $confline = stconfig ($confline, "status", "running.smooth");
+    }
+    close (FILE);
+    save_config (@list);
+
+    if ($Nrun == 0) { &goodbye; }
+    
+    vsystem ("elixir -D DETREND_DIR $det -D mode fringe4 -D global.pending mksmooth $file");
+    vsystem ("$MKFRINGE eval $file smooth");
+
+    open (FILE, "$file.eval");
+    @eval = <FILE>;
+    close (FILE);
+
+    # there is one entry in @eval for each ccd for each confline:
+    $N = 0;
+    foreach $confline (@list) {
+        $status = gtconfig ($confline, "status");
+        if ($status ne "running.smooth") { next; }
+
+        # each chip must succeed for config to succeed
+        $status = "done.smooth";
+        for ($j = 0; $j < $Nccd; $j++) {
+            @words = split (" ", $eval[$N]);
+            if ($words[-1] == 1) { $status = "fail.smooth"; }
+            if ($words[-1] == 2) { $status = "fail.smooth"; }
+            $N++;
+        }
+        $confline = stconfig ($confline, "status", $status);
+    }
+    save_config (@list);
+    
+    &goodbye;
+}
+
+############## reg run ###############
+sub mk_regimage {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE regimage"); }
+    
+    @list = load_config ();
+    
+    # create directory for fhtool to work in
+    $links = mkfiles ("links");
+    if (! -e $links) { system ("mkdir -p $links"); }
+
+    # create namelist for those with appropriate status
+    foreach $confline (@list) {
+	$status = gtconfig ($confline, "status");
+	if (($status ne "done.smooth") && ($status ne "reg")) { next; }
+	$confline = stconfig ($confline, "status", "running.reg");
+	save_config (@list);
+
+	$success = 1;
+	$ID = gtconfig ($confline, "ID");
+
+	$DBmode = `gconfig DETREND-DB-MODE`; chop $DBmode;
+	$DBmode = "\U$DBmode\E";
+
+	if ($DBmode eq "SPLIT") {
+	    for ($j = 0; $j < $Nccd; $j++) {
+		$file = mknames ("smfile", $confline, $ccds[$j]);
+		$line = "detregister $file -label fringe-2.1 -ID $ID";
+		$status = system ($line);
+		if ($status) { 
+		    print STDERR "error registering $file\n";
+		    $success = 0;
+		}
+	    }
+	    goto registered;
+	}
+
+	if ($DBmode eq "MEF") {
+	    # empty link directory:
+	    system ("rm -f $links/*.fits");
+
+	    # make links 
+	    foreach $ccd (@ccds) {
+		$file = mknames ("smfile", $confline, $ccd);
+		$link = mknames ("link", $confline, $ccd);
+		symlink $file, $link;
+	    }
+
+	    # mef, register
+	    $mef = mknames ("mef", $confline);
+	    system ("rm -f $mef");
+
+	    vsystem ("fhtool -P $links $mef");
+	    if ($status) { $success = 0; }
+	    vsystem ("detregister $mef -label fringe-2.1 -ID $ID");
+	    if ($status) { $success = 0; }
+
+	    # remove links
+	    foreach $ccd (@ccds) {
+		$link = mknames ("link", $confline, $ccd);
+		unlink $link;
+	    }
+	    goto registered;
+	}
+	print STDERR "DB mode not defined?\n";
+	$success = 0;
+
+      registered:
+	if ($success) {
+	    $confline = stconfig ($confline, "status", "done");
+	} else {
+	    print STDERR "error registering $file\n"; 
+	    $confline = stconfig ($confline, "status", "fail.reg");
+	}
+	save_config (@list);
+    }
+    &goodbye;
+}
+
+############## evaluate elixir run ###############
+sub mk_eval {
+    
+    if (@ARGV != 3) { &escape ("USAGE: $MKFRINGE meval (file) (step)"); }
+    
+    $infile = $ARGV[1];
+    $step = $ARGV[2];
+
+    open (FILE, "$infile");
+    @list = <FILE>;
+    close (file);
+    
+    # load success fifo info:
+    $file = `gconfig -D mode fringe1 global.success`; chop $file;
+    open (FILE, "$file");
+    @success = <FILE>;
+    close (FILE);
+    
+    # load failure fifo info:
+    $file = `gconfig -D mode fringe1 global.failure`; chop $file;
+    open (FILE, "$file");
+    @failure = <FILE>;
+    close (FILE);
+    
+    # possible states:
+    #   0 entry in success
+    #   1 entry in failure
+    #   2 entry missing   
+    #   3 special case    
+    
+    $outfile = "$infile.eval";
+    open (FILE, ">$outfile");
+    foreach $list (@list) {
+
+	# force lines to have only single spaces between words
+	@words = split (" ", $list);
+	$key = join (' ', @words);
+
+	$state = 2;
+      MCHECK: {
+	  foreach $entry (@success) {
+	      @words = split (" ", $entry);
+	      $value = join (' ', @words);
+	      if ($value =~ /$key/) { 
+		  $state = 0;
+		  last MCHECK;
+	      }
+	  }
+	  
+	  foreach $entry (@failure) {
+	      @words = split (" ", $entry);
+	      $value = join (' ', @words);
+	      if ($value =~ /$key/) { 
+		  $state = 1;
+		  $level = $words[-1];
+		  # SPECIAL CASES:
+		  if (($step eq "init") && ($level eq "master.lists")) {
+		      $state = 3;
+		  }
+		  last MCHECK;
+	      }
+	  }
+	  
+      }
+	print FILE "$key $state\n";
+    }
+    close (FILE);
+    &goodbye;
+}
+
+############## html duplicate ###############
+sub mk_htmldup {
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKFRINGE htmldup (config)"); }
+    
+    $config = $ARGV[1];
+    system ("$MKFRINGE dup $config");
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/fr.elixir1?&elconf=$elconf\">\n";
+    
+    &goodbye;
+}
+
+############## html delete ###############
+sub mk_htmldel {
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKFRINGE htmldel (config.ver)"); }
+    
+    $config = $ARGV[1];
+    system ("$MKFRINGE del $config");
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/fr.elixir1?&elconf=$elconf\">\n";
+    
+    &goodbye;
+}
+
+############## html define ###############
+sub mk_htmldef {
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKFRINGE htmldef (config.ver)"); }
+    
+    $key = $ARGV[1];
+    
+    # find (config.ver) in list:
+    
+    @list = load_config ();
+    
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("error: can't find config entry"); }
+    
+    # show the complete list for reference
+    print STDOUT "<HEADER> <TITLE>Elixir Mkfringe Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0e0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    print STDOUT "<table border>\n";
+    for ($i = 0; $i < @list; $i++) {
+	$config  = gtconfig ($list[$i], "config");
+	$version = gtconfig ($list[$i], "version");
+	$status  = gtconfig ($list[$i], "status");
+	$from    = gtconfig ($list[$i], "from");
+	$to      = gtconfig ($list[$i], "to");
+	print STDOUT "<tr><td> $version </td>\n";
+	print STDOUT "<td> $from </td><td> $to </td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.elixir2?$version&elconf=$elconf> $status </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.split?$config&elconf=$elconf>      split </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.delete?$version&elconf=$elconf>   delete </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.redef?$version&elconf=$elconf>  redefine </a></td>\n";
+	print STDOUT "</tr>\n";
+    }
+    print STDOUT "</table></body><br><br>\n";
+    
+    $version = gtconfig ($list[$match], "version");
+    $status  = gtconfig ($list[$match], "status");
+    $from    = gtconfig ($list[$match], "from");
+    $to      = gtconfig ($list[$match], "to");
+    print STDOUT "redefining <b> $key: </b> <br>\n";    
+    print STDOUT "<table border>\n";
+    print STDOUT "<tr><td> $version </td>\n";
+    print STDOUT "<td> $from </td><td> $to </td><td> $status </a></td>\n";
+    print STDOUT "</tr></table>\n";
+    
+    
+    # create a simple form for redefine:
+    print STDOUT "<form method=post action=$CGI/fr.redefine?&elconf=$elconf>\n";
+    print STDOUT "start: <input type=text value=$from name=start size=40 maxlength=40> <br>\n";
+    print STDOUT "stop: <input type=text value=$to name=stop size=40 maxlength=40> <br>\n";
+    print STDOUT "<input type=hidden name=config value=\"$key\">\n";
+    print STDOUT "<input type=\"submit\" value=\"submit\"><input type=\"reset\" value=\"reset\">\n";
+    print STDOUT "</form>\n";
+    print STDOUT "</body>\n";
+    
+    &goodbye;
+}
+
+############## html modify ###############
+sub mk_htmlmod {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE htmlmod"); }
+    
+    # images which are marked for exclusion are included in the 
+    # environment variable as $WWW_image_NN -- NN = sequence number
+    # in the master / defringe file
+
+    $key = $ENV{'WWW_config'};
+    $Nimage = $ENV{'WWW_Nimage'};
+    
+    @list = load_config ();
+
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("ERROR: can't find config entry"); }
+    
+    # change status entry in master list & $HTML.imstats
+    $HTML    = mkfiles ("html");
+    $imstat = "$HTML/$version.imstats";
+    $master = mknames ("master", $list[$match]); 
+
+    # load data from master list
+    open (FILE, "$master");
+    @master = <FILE>;
+    close (FILE);
+    if ($Nimage != @master) { &escape ("mis-match in image list lengths"); }
+
+    # load data from imstats list
+    open (FILE, "$imstat");
+    @imstat = <FILE>;
+    close (FILE);
+    if ($Nimage != @imstat) { &escape ("mis-match in image list lengths"); }
+
+    for ($i = 0; $i < @master; $i++) {
+	chop ($master[$i]);
+	chop ($imstat[$i]);
+	($path, $root, $mode, $status) = split (" ", $master[$i]);
+	$name = "WWW_image_$i";
+	$newstatus = $status;
+	if ($ENV{$name} eq "") { 
+	    $hstatus = 0;
+	    if (($status == 0) || ($status == 1)) { $newstatus = 0; }
+	    if (($status == 2) || ($status == 3)) { $newstatus = 2; }
+	} else {
+	    $hstatus = 1;
+	    if (($status == 0) || ($status == 1)) { $newstatus = 1; }
+	    if (($status == 2) || ($status == 3)) { $newstatus = 3; }
+	}	    
+	$master[$i] = "$path $root $mode $newstatus";
+	($line, $status) = $imstat[$i] =~ m|(\s*\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+\S+\s+)(\S)|;
+	$imstat[$i] = "$line $hstatus";
+    }
+
+    # save master list
+    open (FILE, ">$master");
+    foreach $line (@master) { print FILE "$line\n"; }
+    close (FILE);
+
+    # save imstats list
+    open (FILE, ">$imstat");
+    foreach $line (@imstat) { print FILE "$line\n"; }
+    close (FILE);
+
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/fr.elixir2?$key&elconf=$elconf\">\n";
+    
+    # adjust the config file: convert status to 'modified'
+    $list[$match] = stconfig ($list[$match], "status", "modified");
+    save_config (@list);
+    &goodbye;
+    
+}
+
+############## html changes modes ###############
+sub mk_htmlmodes {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE htmlmodes"); }
+    
+    # modes which are marked for exclusion are included in the 
+    # environment variable as $WWW_mode_NN -- NN = sequence number
+
+    $key = $ENV{'WWW_config'};
+    $Nmode = $ENV{'WWW_Nmode'};
+    
+    @list = load_config ();
+
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("ERROR: can't find config entry"); }
+    
+    $modelist = mknames ("modelist", $list[$match]);
+    open (FILE, "$modelist");
+    @inlist = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$modelist");
+    for ($i = 0; $i < @inlist; $i++) {
+	($N, $status) = split (" ", $inlist[$i]);
+	if ($i < $Nmode) {
+	    $name = "WWW_mode_$i";
+	    $newstatus = $status;
+	    if ($ENV{$name} eq "") { 
+		$newstatus = 0;
+	    } else {
+		$newstatus = 1;
+	    }	    
+	} else {
+	    $newstatus = 0;
+	}
+	print FILE "$i $newstatus\n";
+    }
+    close (FILE);
+
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/fr.elixir2?$key&elconf=$elconf\">\n";
+    
+    # adjust the config file: convert status to 'modified'
+    $list[$match] = stconfig ($list[$match], "status", "modified.map");
+    save_config (@list);
+    &goodbye;
+}
+
+############## html changes modes ###############
+sub mk_htmlmaps {
+    
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE htmlmaps"); }
+    
+    # maps which are marked for inclusion are given in the 
+    # environment variable as $WWW_mode_NN -- NN = sequence number
+
+    $key = $ENV{'WWW_config'};
+    $Nmaps = $ENV{'WWW_Nmaps'};
+    
+    @list = load_config ();
+
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("ERROR: can't find config entry"); }
+
+    $maplist = mknames ("maplist", $list[$match]);
+    open (FILE, "$maplist");
+    @inlist = <FILE>;
+    close (FILE);
+
+    open (FILE, ">$maplist");
+    for ($i = 0; $i < @inlist; $i++) {
+	($Name, $status) = split (" ", $inlist[$i]);
+	$name = "WWW_map_$i";
+	$newstatus = $status;
+	if ($ENV{$name} eq "") { 
+	    $newstatus = 0;
+	} else {
+	    $newstatus = 1;
+	}	    
+	print FILE "$Name $newstatus\n";
+    }
+    close (FILE);
+
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/fr.elixir2?$key&elconf=$elconf\">\n";
+
+    # adjust the config file: convert status to 'modified'
+    $list[$match] = stconfig ($list[$match], "status", "modified.map");
+    save_config (@list);
+    &goodbye;
+}
+
+############## html accept ###############
+sub mk_htmlkeep {
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKFRINGE htmlkeep (config.ver)"); }
+    
+    $key = $ARGV[1];
+    @list = load_config ();
+    
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("ERROR: can't find config entry"); }
+    
+    # adjust the config file: convert status to 'accepted'
+    $list[$match] = stconfig ($list[$match], "status", "accepted");
+    save_config (@list);
+    
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/fr.elixir1?&elconf=$elconf\">";
+    &goodbye;
+}
+
+############## html accept ###############
+sub mk_htmlmapkeep {
+    
+    if (@ARGV != 2) { &escape ("USAGE: $MKFRINGE htmlmapkeep (config.ver)"); }
+    
+    $key = $ARGV[1];
+    @list = load_config ();
+    
+    $match = -1;
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $match = $i;
+	    last;
+	}
+    }
+    if ($match == -1) { &escape ("ERROR: can't find config entry"); }
+    
+    # adjust the config file: convert status to 'accepted'
+    $list[$match] = stconfig ($list[$match], "status", "accept.map");
+    save_config (@list);
+    
+    print STDOUT "<meta http-equiv=refresh content=\"0; url=$CGI/fr.elixir1?&elconf=$elconf\">";
+    &goodbye;
+}
+
+############## html config ###############
+sub mk_htmlconfig {
+    
+    if (@ARGV != 1) { &escape ("USAGE: mkdetrend htmlconfig"); }
+    
+    ## html headers
+    print STDOUT "<HEADER> <TITLE>Elixir Mkdetrend Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    
+    # create a simple form for redefine:
+    print STDOUT "<form method=post action=$CGI/fr.newconfig?&elconf=$elconf>\n";
+    if ($elconf) {
+	print STDOUT "enter new config: <input type=text value=$elconf name=config size=40 maxlength=40> <br>\n";
+    } else {
+	print STDOUT "enter new config: <input type=text name=config size=40 maxlength=40> <br>\n";
+    }
+    print STDOUT "<input type=\"submit\" value=\"submit\"><input type=\"reset\" value=\"reset\">\n";
+    print STDOUT "</form>\n";
+    print STDOUT "</body>\n";
+    
+    &goodbye;
+}
+
+############## html level 1 ###############
+sub mk_html1 {
+    
+
+    if (@ARGV != 1) { &escape ("USAGE: $MKFRINGE html1"); }
+    
+    @list = load_config ();
+    
+    ## html headers
+    print STDOUT "<HEADER> <TITLE>Elixir Mkfringe Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+
+    print STDOUT "<table border>\n";
+    for ($i = 0; $i < @list; $i++) {
+	$config  = gtconfig ($list[$i], "config");
+	$version = gtconfig ($list[$i], "version");
+	$from    = gtconfig ($list[$i], "from");
+	$to      = gtconfig ($list[$i], "to");
+	$status  = gtconfig ($list[$i], "status");
+	print STDOUT "<tr><td> $version </td>\n";
+	print STDOUT "<td> $from </td><td> $to </td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.elixir2?$version&elconf=$elconf> $status </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.split?$config&elconf=$elconf> split </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.delete?$version&elconf=$elconf> delete </a></td>\n";
+	print STDOUT "<td> <a href=$CGI/fr.redef?$version&elconf=$elconf> redefine </a></td>\n";
+	print STDOUT "</tr>\n";
+    }
+    
+    print STDOUT "</table><br>\n";
+    if ($elconf eq "") {
+	print STDOUT "Current Config: <b>default</b><br>\n";
+    } else {
+	print STDOUT "Current Config: <b>$elconf</b><br>\n";
+    }
+    print STDOUT "<a href=$CGI/fr.config?&elconf=$elconf>Change Config</a></td>\n";
+    print STDOUT "</body>\n";
+    &goodbye;
+    
+}
+
+
+
+############## html level 2 ###############
+sub mk_html2 {
+    
+    if (@ARGV != 2) {
+	print STDERR "USAGE: $MKFRINGE html2 (config.ver)\n";
+	&goodbye; 
+    }
+    
+    @list = load_config ();
+    
+    # config:  run.type.filter
+    # key:     run.type.filter.ver
+    # key.col  run.type.filter.ver.column
+    # the words in config and key may consist of alphanumeric plus '_', '-'
+    # the words in col number be digits
+
+    # entry on line will be either config.ver (== key) or config.ver.col for sorting
+    # grab just the key portion
+    $status = "none";
+    ($key) = $ARGV[1] =~ /([-\w]+\.[-\w]+\.[-\w]+\.[-\w]+)/; # (config.ver)
+    $arg = $ARGV[1];
+    
+    # find appropriate config.ver entry:
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $confline = $list[$i];
+	    $status = gtconfig ($confline, "status");
+	    last;
+	}
+    }
+    
+    $from = gtconfig ($confline, "from");
+    $to   = gtconfig ($confline, "to");
+    print STDOUT "<HEADER> <TITLE>Elixir Mkfringe Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    print STDOUT "<center><table border>\n";
+    print STDOUT "<tr><th>config   </th><th> from  </th><th> to  </th><th> status  </th></tr>\n";
+    print STDOUT "<tr><td>$version </td><td> $from </td><td> $to </td><td> $status </th></tr>\n";
+    print STDOUT "</table></center><hr>\n";
+    
+    if ($status eq "modified")    { flips_report ($arg, $confline, "modified"); }
+    if ($status eq "accepted")    { flips_report ($arg, $confline, "accepted"); }
+    if ($status eq "done.merge")  { flips_report ($arg, $confline, "merged"); }
+    if ($status eq "done.prep")   { flips_report ($arg, $confline, "prepped"); }
+    if ($status eq "done.reg")    { flips_report ($key, $confline, "registered"); }
+    if ($status eq "done")        { flips_report ($key, $confline, "done"); }
+
+    if ($status eq "done.map")     { map_report ($arg, $confline, "mapped"); }
+    if ($status eq "modified.map") { map_report ($arg, $confline, "mapped"); }
+    
+    if ($status eq "none")              { $message = "not found"; }
+    if ($status eq "init")              { $message = "initialized, not yet run."; }
+    if ($status eq "not.available")     { $message = "has no images available for detrend creation."; }
+    
+    foreach $step (init, flips, norm, merge) {
+	if ($status eq "running.$step") { $message = "running step $step"; }
+	if ($status eq "fail.$step")    { $message = "failed step $step"; }
+	if ($status eq "done.$step")    { $message = "has finished $step"; }
+    }      
+
+    print STDOUT "config <b> $key </b> $message <br>\n";
+    
+    $master = mknames ("master", $confline);
+    print STDOUT "<table border>\n";
+    open (FILE, "$master");
+    while ($line = <FILE>) {
+	chop ($line);
+	@entry = split ("/", $line);
+	$N = @entry - 1;
+	print STDOUT "<tr><td>$entry[$N]</td></tr>\n";
+    }
+    print STDOUT "</table>\n";
+    
+    # print STDOUT "</body>\n";
+    &goodbye;
+    print STDOUT "<form method=get action=$CGI/fr.elixir1?&elconf=$elconf> <input type=submit value=\"back to config list\"></form>";
+}
+
+
+
+############## html level 3 ###############
+sub mk_html3 {
+    
+    if (@ARGV != 3) {
+	print STDERR "USAGE: $MKFRINGE html3 (entry.config.ver) (mode)\n";
+	&goodbye; 
+    }
+    
+    @list = load_config ();
+    
+    # extract the entry and key values from $ARGV[1]
+    ($entry, $key) = $ARGV[1] =~ /(\d+)\Q.\E(.*)/;
+    $mode = $ARGV[2];
+    
+    $status = "none";
+    # find appropriate config.ver entry:
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $confline = $list[$i];
+	    $status = gtconfig ($confline, "status");
+	    last;
+	}
+    }
+    
+    print STDOUT "<HEADER> <TITLE>Elixir Mkfringe Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+    
+    if ($status eq "none")              { print STDOUT "config <b> $key </b> not found\n </body>\n"; &goodbye; }
+    if ($status eq "init")              { print STDOUT "config <b> $key </b> initialized, not yet run\n </body>\n"; &goodbye; }
+    if ($status eq "not.available")     { print STDOUT "config <b> $key </b> has no images available for detrend creation\n </body>\n"; &goodbye; }
+
+    if ($status eq "done.prep")   { flips_entry ($key, $entry, $confline, $mode); }
+    if ($status eq "done.merge")  { flips_entry ($key, $entry, $confline, $mode); }
+    if ($status eq "accepted")    { flips_entry ($key, $entry, $confline, $mode); }
+    if ($status eq "modified")    { flips_entry ($key, $entry, $confline, $mode); }
+    if ($status eq "done.reg")    { flips_entry ($key, $entry, $confline, $mode); }
+    if ($status eq "done")        { flips_entry ($key, $entry, $confline, $mode); }
+    
+    foreach $step (init, flips, norm, merge) {
+	# print "step: $step, $status: $status\n";
+	if ($status eq "running.$step") { print STDOUT "config <b> $key </b> running step $step \n </body>\n"; &goodbye; }
+	if ($status eq "fail.$step")    { print STDOUT "config <b> $key </b> failed step $step\n </body>\n"; &goodbye; }
+	
+	if ($status eq "done.$step") {
+	    print STDOUT "config <b> $key </b> has finished $step\n";
+	    
+	    # load image names from CCD 0 list:
+	    $master = mknames ("master", $confline, "00");
+	    print STDOUT "<table border>\n";
+	    open (FILE, "$master");
+	    while ($line = <FILE>) {
+		chop ($line);
+		@entry = split ("/", $line);
+		$N = @entry - 1;
+		print STDOUT "<tr><td>$entry[$N]</td></tr>\n";
+	    }
+	    print STDOUT "</table>\n";
+	}
+    }
+    
+    # print STDOUT "</body>\n";
+    &goodbye;
+}
+
+$dadswww = "img";
+
+
+############## html for dads ###############
+sub mk_dads {
+    
+    if (@ARGV != 2) {
+	print STDERR "USAGE: $MKFRINGE dads (config.ver)\n";
+	&goodbye; 
+    }
+    
+    @list = load_config ();
+    
+    # entry on line will be either config.ver (== key) or config.ver.col for sorting
+    # grab just the key portion
+    $status = "none";
+    $arg = $ARGV[1];
+    ($key) = $arg =~ /([-\w]+\.[-\w]+\.[-\w]+\.[-\w]+)/; # (config.ver)
+    
+    # find appropriate config.ver entry:
+    for ($i = 0; $i < @list; $i++) {
+	$version = gtconfig ($list[$i], "version");
+	if ($key eq $version) {
+	    $confline = $list[$i];
+	    $status = gtconfig ($confline, "status");
+	    last;
+	}
+    }
+    
+    print STDOUT "<HEADER> <TITLE>Elixir Mkfringe Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#ffffff TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+
+    # only print for config.ver entries which are ready
+    if ($status ne "done") {
+	&escape ("$version is not ready for release by Elixir");
+    }
+
+    # parse config entry and get data from appropriate files
+    $from = gtconfig ($confline, "from");
+    $to   = gtconfig ($confline, "to");
+    open (STAT,   mknames ("stats", $confline));     @statdata = <STAT>;        close (STAT);
+    open (MED,    mknames ("medbin", $confline));    @medndata = <MED>;         close (MED);
+    open (TEN,    mknames ("tenbin", $confline));    @tenndata = <TEN>;         close (TEN);
+    open (MASTER, mknames ("master", $confline, 0)); @mastdata = <MASTER>;      close (MASTER);
+    
+    $tmpname = mknames ("master", $confline, 0);
+
+    # get stats from the stats & master files
+    $Nkeep = 0;
+    $Ncnt = 0;
+    $Sigma = 0;
+    $Nimage = @statdata;
+    for ($i = 0; $i < $Nimage; $i++) {
+	@tmpw = split (" ", $mastdata[$i]);
+	@tmps = split (" ", $statdata[$i]);
+	if ($tmpw[1]) { $Nkeep++; $Ncnt += $tmps[3]; $Sigma += $tmps[8]*$tmps[8]; }
+    }
+    $Sigma = sprintf "%5.3f", 100*sqrt ($Sigma/$Nkeep);
+
+    print STDOUT "<center><table border>\n";
+    print STDOUT "<tr><th>config   </th><th> from  </th><th> to </th></tr>\n";
+    print STDOUT "<tr><td>$version </td><td> $from </td><td> $to</td></tr>\n";
+    print STDOUT "</table></center><hr>\n";
+
+    $imbin = mknames ("dads.imbin", $confline);
+    print STDOUT "<table width=80%><tr><td valign=top>\n";
+    print STDOUT "this config has been created by Elixir. <br>\n";
+    print STDOUT "there are $Nimage images, $Nkeep used. <br>\n";
+    print STDOUT "Total Counts: $Ncnt<br> r.m.s. median sigma: $Sigma% <br><br>\n";
+    print STDOUT "</td><td align=right><img src=$imbin></td></tr></table>\n";
+    
+    print STDOUT "<center><b>Statistics on each available input image.</b></center>
+  Time is in UT, light background means dawn, grey means dusk.\n";
+
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    print STDOUT "<tr >\n";
+    print STDOUT "<th > image </th>\n";
+    print STDOUT "<th > Date  </th>\n";
+    print STDOUT "<th > Time  </th>\n";
+    print STDOUT "<th > Mean  </a></th>\n";
+    print STDOUT "<th > Sigma (raw) </a></th>\n";
+    print STDOUT "<th > Sigma (clipped) </a></th>\n";
+    print STDOUT "<th > Sigma (med) </a></th>\n";
+    print STDOUT "<th > image </th>\n";
+    print STDOUT "<th > used? </th></tr>\n";
+    
+    # sort the list by image seq number
+    @order = ();
+    for ($i = 0; $i < $Nimage; $i++) { @order = (@order, $i); }
+    $col = 0;
+    @entry = sort by_col @order;
+    
+    # create the image-by-image table lines
+    for ($i = 0; $i < $Nimage; $i++) {
+	$N = $entry[$i];
+	
+	@word = split (" ", $statdata[$N]);
+	$used = $word[12];
+	$dawn = $word[11];
+	
+	@tmpw = split (" ", $mastdata[$N]);
+	$keep = $tmpw[1];
+	
+	@tmpw = split ("/", $medndata[$N]);
+	$medname = $tmpw[-1];
+	
+	@tmpw = split ("/", $tenndata[$N]);
+	$tenname = $tmpw[-1];
+	
+	print STDOUT "<tr><td> $word[0] </td><td> $word[1] </td>\n";
+	if ($dawn) { print STDOUT "<td bgcolor=#cccccc> $word[2] </td>\n"; }
+	else       { print STDOUT "<td> $word[2] </td>\n"; }
+	print STDOUT "<td> $word[3] </td>\n";
+	print STDOUT "<td> $word[4] </td><td> $word[6] </td><td> $word[8] </td>\n";
+	print STDOUT "<td> <a border=0 href=$dadswww/$tenname> <img src=$dadswww/$medname></a></td>\n";
+	if ($used) { print STDOUT "<td bgcolor=#00c000>yes</td>\n"; }
+	else       { print STDOUT "<td bgcolor=#d00000>no</td>\n"; }
+	print STDOUT "</tr>\n\n"; 	
+    }
+    
+    print STDOUT "</table>\n";
+    &goodbye;
+}
+
+
+
+############## html level 1 ###############
+sub mk_dads_top {
+    
+    if (@ARGV != 1) {
+	print STDERR "USAGE: $MKFRINGE dads.top\n";
+	&goodbye; 
+    }
+    
+    @list = load_config ();
+    
+    ## html headers
+    print STDOUT "<HEADER> <TITLE>Elixir Mkfringe Report</TITLE> </HEADER>\n";
+    print STDOUT "<BODY BGCOLOR=#fff0f0 TEXT=#000000 LINK=#0000ff VLINK=#6600ff ALINK=#a0a0a0>\n";
+
+    print STDOUT "<table border>\n";
+    for ($i = 0; $i < @list; $i++) {
+	$config  = gtconfig ($list[$i], "config");
+	$version = gtconfig ($list[$i], "version");
+	$from    = gtconfig ($list[$i], "from");
+	$to      = gtconfig ($list[$i], "to");
+	$status  = gtconfig ($list[$i], "status");
+	print STDOUT "<tr><td> $version </td>\n";
+	print STDOUT "<td> $from </td><td> $to </td>\n";
+	print STDOUT "<td> <a href=$version.html> $status </a></td>\n";
+	print STDOUT "</tr>\n";
+    }
+    
+    print STDOUT "</table></body>\n";
+    &goodbye;
+    
+}
+
+sub by_col { 
+    @word = split (" ", $statdata[$a]); $va = $word[$col]; 
+    @word = split (" ", $statdata[$b]); $vb = $word[$col]; 
+    $va <=> $vb;
+}
+
+sub flips_report {
+    
+    $col = 0;
+    ($config) = $_[0] =~ /([-\w]+\.[-\w]+\.[-\w]+)/;
+    ($key)    = $_[0] =~ /([-\w]+\.[-\w]+\.[-\w]+\.[-\w]+)/; # (config.ver)
+
+    # look for optional sort key (config.ver[.key])
+    if ($_[0] =~ /$key.(\d+)/) {
+	($col) = $_[0] =~ /$key.(\d+)/; 
+    } else {
+	$col = 0;
+    }
+
+    $line = $_[1];
+    $message = $_[2];
+    
+    # list files: VERSION.imstats, VERSION.med.medbin.list, VERSION.med.tenbin.list, VERSION.def.medbin.list VERSION.def.tenbin.list
+
+    $root = mknames ("htmlroot", $line);
+    open (FILE, "$root.imstats");         @statdata = <FILE>; close (FILE);
+    open (FILE, "$root.med.medbin.list"); @meddata = <FILE>; close (FILE);
+    open (FILE, "$root.def.medbin.list"); @defdata = <FILE>; close (FILE);
+
+# format of statdata file:
+#  OBS     DATE        TIME        SKY      FLUX   FR1    dFR1    FR2   dFR2  stat keep
+#  606363  2001-10-09  10:21:15.62 12455.7  20.76  246.9   84.0   N/A    N/A   1   1
+
+    $Nkeep = 0;
+    $Ncnt = 0;
+    $Resid = 0;
+    $fResid = 0;
+    $Nimage = @statdata;
+    for ($i = 0; $i < $Nimage; $i++) {
+	@tmp = split (" ", $statdata[$i]);
+	if ($tmp[9]) { $Nkeep++; $Ncnt += $tmp[3]; }
+	$Resid  += $tmp[8];
+	$fResid += $tmp[8] / $tmp[3];
+    }
+    if ($Nimage > 0) { $Resid = $Resid / $Nimage; }
+    if ($Nimage > 0) { $fResid = $fResid / $Nimage; }
+    $Resid = sprintf "%7.3f", $Resid;
+    $fResid = sprintf "%7.3f", $fResid;
+
+    # $imbin = mknames ("dads.imbin", $line);
+    print STDOUT "<table width=100%><tr><td valign=top>\n";
+    print STDOUT "this config has been $message. <br>\n";
+    print STDOUT "there are $Nimage images, $Nkeep used. <br>\n";
+    print STDOUT "Total Counts: $Ncnt<br>\n";
+    print STDOUT "Median residual scatter: $Resid <br>\n";
+    print STDOUT "Median fractional residual: $fResid <br><br>\n";
+    print STDOUT "you have the following choices: <br>\n";
+    print STDOUT "<a href=$CGI/fr.elixir1?&elconf=$elconf> <b> return to top level </b><br></a>";
+    print STDOUT "<a href=$CGI/fr.split?$config&elconf=$elconf> <b> split config </b><br></a>";
+    print STDOUT "<a href=$CGI/fr.accept?$key&elconf=$elconf> <b> accept config </b><br></a></td>";
+    if (-e "$root.medbin.jpg") { 
+	@tmpw = split ("/", "$root.medbin.jpg");
+	$imname = "$www/$tmpw[-1]";
+	print STDOUT "<td align=right><img width=100% src=$imname></td>\n";
+    }
+    print STDOUT "</tr></table>\n";
+
+    print STDOUT "<form method=post action=$CGI/fr.modify?&elconf=$elconf>\n";
+    print STDOUT "<center><b>Statistics on each available input image.</b></center>\n";
+    print STDOUT "Time is in UT. Click on the column heading to sort by that entry\n";
+
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    print STDOUT "<tr bgcolor=#00aaaa>\n";
+    print STDOUT "<th > <a href=$CGI/fr.elixir2?$key.0&elconf=$elconf> image </a></th>\n";
+    print STDOUT "<th > Date </th>\n";
+    print STDOUT "<th > Time </th>\n";
+    print STDOUT "<th > <a href=$CGI/fr.elixir2?$key.3&elconf=$elconf> Sky </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/fr.elixir2?$key.4&elconf=$elconf> Flux </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/fr.elixir2?$key.5&elconf=$elconf> Fringe </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/fr.elixir2?$key.6&elconf=$elconf> dFringe </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/fr.elixir2?$key.7&elconf=$elconf> Resid </a></th>\n";
+    print STDOUT "<th > <a href=$CGI/fr.elixir2?$key.8&elconf=$elconf> dResid </a></th>\n";
+    print STDOUT "<th > F image </th>\n";
+    print STDOUT "<th > R image </th>\n";
+    print STDOUT "<th > used? </th>\n";
+    print STDOUT "<th > keep? </th></tr>\n\n";
+    
+    @order = ();
+    for ($i = 0; $i < $Nimage; $i++) { @order = (@order, $i); }
+    
+    @entry = sort by_col @order;
+    
+    for ($i = 0; $i < $Nimage; $i++) {
+	$N = $entry[$i];
+	
+	@word = split (" ", $statdata[$N]);
+	$used = $word[9];
+	$keep = $word[10];
+	
+	@tmpw = split ("/", $meddata[$N]);
+	$medname = $tmpw[-1];
+	@tmpw = split ("/", $defdata[$N]);
+	$defname = $tmpw[-1];
+	
+	print STDOUT "<tr><td> <a href=$CGI/fr.elixir3?$N.$key&med&elconf=$elconf> $word[0] </a></td><td> $word[1] </td>\n";
+	print STDOUT "<td> $word[2] </td>\n"; 
+	print STDOUT "<td> $word[3] </td>\n";
+	print STDOUT "<td> $word[4] </td>\n";
+	print STDOUT "<td> $word[5] </td>\n";
+	print STDOUT "<td> $word[6] </td>\n";
+	print STDOUT "<td> $word[7] </td>\n";
+	print STDOUT "<td> $word[8] </td>\n";
+	print STDOUT "<td> <a border=0 href=$CGI/fr.elixir3?$N.$key&med&elconf=$elconf> <img src=$www/$medname></a></td>\n";
+	if ("$defname" ne "") {
+	    print STDOUT "<td> <a border=0 href=$CGI/fr.elixir3?$N.$key&def&elconf=$elconf> <img src=$www/$defname></a></td>\n";
+	} else {
+	    print STDOUT "<td> N/A </td>\n";
+	}
+	if ($used) { print STDOUT "<td>yes</td>\n"; }
+	else       { print STDOUT "<td>no</td>\n"; }
+	if ($keep) { print STDOUT "<td bgcolor=#00c000><input type=checkbox checked name=image.$N value=$N size=1></td></tr>\n\n"; }
+	else       { print STDOUT "<td bgcolor=#d00000><input type=checkbox name=image.$N value=$N size=1></td></tr>\n\n"; }	
+	
+    }
+    
+    print STDOUT "</table>\n";
+    print STDOUT "<input type=hidden    name=Nimage value=\"$Nimage\">\n";
+    print STDOUT "<input type=hidden    name=config value=\"$key\">\n";
+    print STDOUT "<input type=submit    value=\"apply changes\">\n";
+    print STDOUT "<input type=reset     value=Reset>\n";
+    print STDOUT "</form>\n";
+
+    print STDOUT "<center>\n";
+    print STDOUT "<b>Fringe Correlation Plot</b><br>\n";
+    if (-e "$root.stats.png") { 
+	@tmpw = split ("/", "$root.stats.png");
+	$imname = "$www/$tmpw[-1]";
+	print STDOUT "<img src=$imname>\n";
+    }
+    print STDOUT "</center>\n";
+
+    print STDOUT "</body>\n";
+    &goodbye;
+    
+}
+
+sub flips_report_done {
+    
+    ($config) = $_[0] =~ /([-\w]+\.[-\w]+\.[-\w]+)/;
+    ($key)    = $_[0] =~ /([-\w]+\.[-\w]+\.[-\w]+\.[-\w]+)/; # (config.ver)
+
+    $line = $_[1];
+    
+    open (STAT, mknames ("stats", $line));
+    open (MED,  mknames ("medbin", $line));
+    open (MASTER, mknames ("master", $line, 0));
+    
+    print STDOUT "<table border>\n";
+    print STDOUT "<tr><th> image </th><th> Date </th><th> Time </th><th> Mean </th>\n";
+    print STDOUT "<th> Sigma (raw) </th><th> Sigma (clipped) </th><th> Sigma (med) </th><th> image </th><th> used? </th></tr>\n\n";
+    
+    for ($i = 0; $line = <STAT>; $i++) {
+	
+	chop ($line);
+	# print STDOUT "$line<br>\n";
+	@word = split (" ",$line);
+	$used = $word[12];
+	$dawn = $word[11];
+	
+	$line = <MASTER>;
+	chop ($line);
+	# print STDOUT "$line<br>\n";
+	@tmpw = split (" ",$line);
+	$keep = $tmpw[1];
+	
+	# mkfringe works with files in the user's paths, but the web page needs 
+	# to work with files visible to the web server
+	$line = <MED>;
+	chop ($line);
+	@tmpw = split ("/", $line);
+	$N = @tmpw - 1;
+	$medname = $tmpw[$N];
+	
+	$sig1 = sprintf "%5.3f", $word[4];
+	$sig2 = sprintf "%5.3f", $word[5];
+	$sig3 = sprintf "%5.3f", $word[6];
+	$sig4 = sprintf "%5.3f", $word[7];
+	$mean = sprintf "%8.1f", $word[3];
+	
+	print STDOUT "<tr><td> <a href=$CGI/fr.elixir3?$i.$key&med&elconf=$elconf> $word[0] </a></td><td> $word[1] </td>\n";
+	if ($dawn) { print STDOUT "<td bgcolor=#cccccc> $word[2] </td>\n"; }
+	else       { print STDOUT "<td> $word[2] </td>\n"; } 
+	print STDOUT "<td> $word[3] </td>\n";
+	print STDOUT "<td> $word[5] </td><td> $word[6] </td><td> $word[8] </td><td><img src=$www/$medname></td>\n";
+	if ($used) { print STDOUT "<td bgcolor=#00c000>yes</td>\n"; }
+	else       { print STDOUT "<td bgcolor=#d00000>no</td>\n"; }
+    }
+    $Nimage = $i;
+    
+    print STDOUT "</table>\n";
+    print STDOUT "</body>\n";
+    
+    &goodbye;
+    
+}
+
+sub flips_entry {
+    
+    my($version)= $_[0];		# version of desired entry
+    my($entry)  = $_[1];		# desired entry in list
+    my($line)   = $_[2];		# list of image stats
+    my($mode)   = $_[3];                # 'def' or 'med'
+    
+    if (($mode ne "def") && ($mode ne "med")) {
+	print STDOUT "error in $MKFRINGE mode\n";
+	&goodbye;
+    }
+
+    # load image & stat lists
+    $root = mknames ("htmlroot", $line);
+    open (FILE, "$root.imstats");         @statdata = <FILE>; close (FILE);
+    open (FILE, "$root.$mode.tenbin.list"); @meddata = <FILE>; close (FILE);
+
+    $Nimage = @statdata;
+    if ($entry >= $Nimage) {
+	print STDOUT "</table> selected entry out of range\n";
+	&goodbye;
+    }
+    
+    $first = ($entry == 0);
+    $last  = ($entry == $Nimage - 1);
+    $next  = $entry + 1;
+    $prev  = $entry - 1;
+    
+    $line = $statdata[$entry];
+    chop ($line);
+    @word = split (" ",$line);
+    $used = $word[9];
+    $keep = $word[10];
+    
+    # mkfringe works with files in the user's paths, but the web page needs 
+    # to work with files visible to the web server
+    $line = $meddata[$entry];
+    chop ($line);
+    @tmpw = split ("/", $line);
+    $name = "$www/$tmpw[-1]";
+    
+    print STDOUT "<img width=100% src=$name>\n";
+    print STDOUT "mode: $mode<br>\n";
+    
+    print STDOUT "<table><tr><td>\n";
+    print STDOUT "<table border>\n";
+    print STDOUT "<tr><th> image    </th><th> Date     </th><th> Time     </th><th> Sky      </th><th> Flux     </th><th> Fringe   </th><th> dFringe  </th><th> Resid    </th><th> dResid   </th><th> used? </th></tr>\n";
+    if ($mode eq "med") {
+	print STDOUT "<tr><td> <a href=$CGI/fr.elixir3?$entry.$version&def&elconf=$elconf> $word[0] </a></td>\n";
+    } else {
+	print STDOUT "<tr><td> <a href=$CGI/fr.elixir3?$entry.$version&med&elconf=$elconf> $word[0] </a></td>\n";
+    }
+    print STDOUT "<td> $word[1] </td><td> $word[2] </td><td> $word[3] </td><td> $word[4] </td><td> $word[5] </td><td> $word[6] </td><td> $word[7] </td><td> $word[8] </td>\n";
+    if ($used) {
+	print STDOUT "<td>yes</td>\n";
+    } else {
+	print STDOUT "<td bgcolor=#ff0000>no</td>\n";
+    }	
+    print STDOUT "</tr>\n\n";
+    print STDOUT "</table>\n";
+    
+    print STDOUT "</td></tr>\n";
+
+    print STDOUT "<tr><td> return to <a href=$CGI/fr.elixir1?&elconf=$elconf> config list </a></tr></td>\n"; 
+    print STDOUT "<tr><td> return to <a href=$CGI/fr.elixir2?$version&elconf=$elconf> $version </a></tr></td>\n"; 
+    if (!$first) { print STDOUT "<tr><td> goto <a href=$CGI/fr.elixir3?$prev.$version&$mode&elconf=$elconf> prev </a> image </td></tr>\n"; }
+    if (!$last)  { print STDOUT "<tr><td> goto <a href=$CGI/fr.elixir3?$next.$version&$mode&elconf=$elconf> next </a> image </td></tr>\n"; }
+    print STDOUT "</table>\n";
+    
+    print STDOUT "</body>\n";
+    &goodbye;
+}
+
+sub map_report {
+    
+    print STDOUT "A Simple Test <br>\n";
+
+    $col = 0;
+    ($config) = $_[0] =~ /([-\w]+\.[-\w]+\.[-\w]+)/;
+    ($key)    = $_[0] =~ /([-\w]+\.[-\w]+\.[-\w]+\.[-\w]+)/; # (config.ver)
+
+    # look for optional sort key (config.ver[.key])
+    if ($_[0] =~ /$key.(\d+)/) {
+	($col) = $_[0] =~ /$key.(\d+)/; 
+    } else {
+	$col = 0;
+    }
+
+    $line = $_[1];
+    $message = $_[2];
+    
+    open (LIST, mknames ("maplist",  $line)); @mapdata  = <LIST>; close (LIST);
+    open (LIST, mknames ("modelist", $line)); @modedata = <LIST>; close (LIST);
+    
+    open (LIST, mknames ("modesjpg", $line)); @modeslist = <LIST>; close (LIST);
+    open (LIST, mknames ("residjpg", $line)); @residlist = <LIST>; close (LIST);
+    open (LIST, mknames ("inmapjpg", $line)); @inmaplist = <LIST>; close (LIST);
+    foreach $name (@modeslist) { chop ($name); }
+    foreach $name (@residlist) { chop ($name); }
+    foreach $name (@inmaplist) { chop ($name); }
+
+    print STDOUT "You have the following choices: <br>\n";
+    print STDOUT "<a href=$CGI/fr.elixir1?&elconf=$elconf> <b> return to top level </b><br></a>";
+    print STDOUT "<a href=$CGI/fr.mapaccept?$key&elconf=$elconf> <b> accept config </b><br></a></td>";
+
+    print STDOUT "Modes avaliable for this config <br>\n";
+    print STDOUT "<form method=post action=$CGI/fr.modes?&elconf=$elconf>\n";
+    # 4 x N table of possible modes
+    $MaxModes = 8;
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    for ($i = 0; $i < $MaxModes; $i++) {
+	if ((($i - 0) % 4) == 0) { print STDOUT "<tr>\n"; }
+	($junk, $status) = split (" ", $modedata[$i]);
+	$name = sprintf "%s/%s", $www, $modeslist[$i];
+	print STDOUT "<td> <img height=64 src=$name> </td>\n";
+	if ($status) { print STDOUT "<td bgcolor=#00c000> <input type=checkbox checked name=mode.$i value=$i size=1> </td>\n"; }
+	else {         print STDOUT "<td bgcolor=#d00000> <input type=checkbox name=mode.$i value=$i size=1> </td>\n"; }
+	if ((($i - 3) % 4) == 0) { print STDOUT "</tr>\n"; }
+    }
+    print STDOUT "</table>\n";
+    print STDOUT "<input type=hidden    name=Nmode value=\"$MaxModes\">\n";
+    print STDOUT "<input type=hidden    name=config value=\"$key\">\n";
+    print STDOUT "<input type=submit    value=\"set mode selection\">\n";
+    print STDOUT "<input type=reset     value=Reset>\n";
+    print STDOUT "</form>\n";
+
+    # 2 x N table of image residuals
+    print STDOUT "Residual images <br>\n";
+    print STDOUT "<form method=post action=$CGI/fr.maps?&elconf=$elconf>\n";
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    for ($i = 0; $i < @mapdata; $i++) { 
+	if ((($i - 0) % 6) == 0) { print STDOUT "<tr>\n"; }
+
+	($name, $status) = split (" ", $mapdata[$i]);
+	@words = split ("/", $name);
+	$basename = $words[-1];
+	$basename =~ s/.maplist$//;
+
+	$imname = sprintf "%s/%s", $www, $residlist[$i];
+	print STDOUT "<td> $basename </td>\n";
+	print STDOUT "<td> <img height=64 src=$imname> </td>\n";
+	if ($status) { print STDOUT "<td bgcolor=#00c000> <input checked type=checkbox name=map.$i value=$i size=1> </td>\n"; }
+	else         { print STDOUT "<td bgcolor=#d00000> <input         type=checkbox name=map.$i value=$i size=1> </td>\n"; }
+
+	if ((($i - 5) % 6) == 0) { print STDOUT "</tr>\n"; } 
+	else { print STDOUT "<td width=10 bgcolor=#ffffff> &nbsp; </td>\n"; }
+	
+    }
+    print STDOUT "</table>\n";
+    $Nmaps = @mapdata;
+    print STDOUT "<input type=hidden    name=Nmaps value=\"$Nmaps\">\n";
+    print STDOUT "<input type=hidden    name=config value=\"$key\">\n";
+    print STDOUT "<input type=submit    value=\"set image selection\">\n";
+    print STDOUT "<input type=reset     value=Reset>\n";
+    print STDOUT "</form>\n";
+
+    # 2 x N table of source images 
+    print STDOUT "Source images <br>\n";
+    print STDOUT "<form method=post action=$CGI/fr.maps?&elconf=$elconf>\n";
+    print STDOUT "<table bgcolor=#fff0e0 border=1 cellspacing=0 cellpadding=3>\n";
+    for ($i = 0; $i < @mapdata; $i++) { 
+	if ((($i - 0) % 6) == 0) { print STDOUT "<tr>\n"; }
+
+	($name, $status) = split (" ", $mapdata[$i]);
+	@words = split ("/", $name);
+	$basename = $words[-1];
+	$basename =~ s/.maplist$//;
+
+	$imname = sprintf "%s/%s", $www, $inmaplist[$i];
+	print STDOUT "<td> $basename </td>\n";
+	print STDOUT "<td> <img height=64 src=$imname> </td>\n";
+	if ($status) { print STDOUT "<td bgcolor=#00c000> <input checked type=checkbox name=map.$i value=$i size=1> </td>\n"; }
+	else         { print STDOUT "<td bgcolor=#d00000> <input         type=checkbox name=map.$i value=$i size=1> </td>\n"; }
+
+	if ((($i - 5) % 6) == 0) { print STDOUT "</tr>\n"; } 
+	else { print STDOUT "<td width=10 bgcolor=#ffffff> &nbsp; </td>\n"; }
+    }
+    print STDOUT "</table>\n";
+    $Nmaps = @mapdata;
+    print STDOUT "<input type=hidden    name=Nmaps value=\"$Nmaps\">\n";
+    print STDOUT "<input type=hidden    name=config value=\"$key\">\n";
+    print STDOUT "<input type=submit    value=\"set image selection\">\n";
+    print STDOUT "<input type=reset     value=Reset>\n";
+    print STDOUT "</form>\n";
+    &goodbye;
+    
+}
+
+print STDOUT "error: invalid $MKFRINGE command\n";
+
+# run:    $root/detrend.config    - current run
+# detdir: $det                    - directory for current run
+# config: $det/fringe.config      - config info for specific run, 1 line per setup
+# dates:  $det/dates.dat          - dates for specific run
+# list:   $det/fringe.list        - temporary list to pass to elixirs
+# plist:  $det/fringe.plist       - list of files to process (detrend) for elixir
+# proc:   $det/proc               - directory to store temporary processed images
+# fringe: $det/fringe             - directory to store data files
+# html:   $det/html               - directory to store results for www
+# www:    $www/$run/html          - html directory as seen by Web server
+
+####  TOOLS TO ABSTRACT FILENAMES  ###################################################################
+
+# construct specific file names
+sub mkfiles {
+    # in: (type)
+    my($type) = $_[0];
+    my($value);
+    
+    { 
+	if ($type eq "run") {
+	    $value = "$root/fringe.config";
+	    last;
+	}
+	if ($type eq "detdir") {
+	    $value = "$det";
+	    last;
+	}
+	if ($type eq "config") {
+	    $value = "$det/fringe.config";
+	    last;
+	}
+	if ($type eq "dates") {
+	    $value = "$det/dates.dat";
+	    last;
+	}
+	if ($type eq "list") {
+	    $value = "$det/fringe.list";
+	    last;
+	}
+	if ($type eq "plist") {
+	    $value = "$det/fringe.plist";
+	    last;
+	}
+	if ($type eq "proc") {
+	    $value = "$det/proc";
+	    last;
+	}
+	if ($type eq "fringe") {
+	    $value = "$det/fringe";
+	    last;
+	}
+	if ($type eq "links") {
+	    $value = "$det/flips/links";
+	    last;
+	}
+	if ($type eq "html") {
+	    $value = "$det/html";
+	    last;
+	}
+	if ($type eq "www") {
+	    $value = "$www";
+	    last;
+	}
+	&escape ("unknown type for mkfiles");
+    }
+    $value;    
+}
+
+# construct files from config info:
+# CRUNID TYPE FILTER [CCD] VERSION START STOP STATE
+#**************************
+
+sub mknames {
+    # in: (type) (config.ver) [ccd]
+    my ($type, $version, @words, $dir, $value, $ccd);
+
+    $type = $_[0];
+    $version = $_[1];
+    @words = split (" ", $version);
+    $ccd = $_[2];
+    
+    { 
+	# list of fringe frames
+	if ($type eq "config") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3]";
+	    last;
+	}
+	# list of fringe frames
+	if ($type eq "frlist") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].frlist";
+	    last;
+	}
+	# smoothed (final) fringe image
+	if ($type eq "smfile") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].sm.fits";
+	    last;
+	}
+	# raw fringe image
+	if ($type eq "frfile") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].fr.fits";
+	    last;
+	}
+	# master list of input images
+	if ($type eq "master") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].master";
+	    last;
+	}
+	# output link file for fhtool
+	if ($type eq "link") {
+	    $dir = mkfiles ("links");
+	    if ($ccd eq "") { &escape ("missing CCD for mknames link"); }
+	    $value = "$dir/$words[0].$words[1].$words[2].$ccd.$words[3].fits";
+	    last;
+	}
+	# output mef file name
+	if ($type eq "mef") {
+	    $dir = mkfiles ("fringe");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].fits";
+	    last;
+	}
+	# list of image statistics files
+	if ($type eq "imstats") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].imstats";
+	    last;
+	}
+	# list of image map lists
+	if ($type eq "maplist") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].maplist";
+	    last;
+	}
+	# list of image map lists
+	if ($type eq "modelist") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].mode.list";
+	    last;
+	}
+	# list of image map lists
+	if ($type eq "modefits") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].mode.fits";
+	    last;
+	}
+	# list of image map lists
+	if ($type eq "modesave") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].mode.mef.fits";
+	    last;
+	}
+	# mosaic fringe statistics file
+	if ($type eq "frstats") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].frstats";
+	    last;
+	}
+	# images to be detrended
+	if ($type eq "detrend") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].detrend";
+	    last;
+	}
+	# list of input image lists to defringe
+	if ($type eq "defringe") {
+	    $dir = mkfiles ("fringe");
+	    $value = sprintf "$dir/$words[0].$words[1].$words[2].$words[3].defringe";
+	    last;
+	}
+	# file in HTML dir with all image stats
+	if ($type eq "htmlroot") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3]";
+	    last;
+	}
+	# file in HTML dir with all image stats
+	if ($type eq "stats") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].stats";
+	    last;
+	}
+	# file in HTML dir with all medbin jpg image names (also root for images)
+	if ($type eq "modesjpg") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].modes";
+	    last;
+	}
+	# file in HTML dir with all medbin jpg image names (also root for images)
+	if ($type eq "residjpg") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].resid";
+	    last;
+	}
+	# file in HTML dir with all medbin jpg image names (also root for images)
+	if ($type eq "inmapjpg") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].inmap";
+	    last;
+	}
+	# file in HTML dir with all medbin jpg image names (also root for images)
+	if ($type eq "medbin") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].medbin";
+	    last;
+	}
+	# file in HTML dir with all tenbin jpg image names (also root for images)
+	if ($type eq "tenbin") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].tenbin";
+	    last;
+	}
+	# file in HTML dir with jpg image of fringe framge
+	if ($type eq "imbin") {
+	    $dir = mkfiles ("html");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].imbin.jpg";
+	    last;
+	}
+	# file in WWW dir with jpg image of fringe framge
+	if ($type eq "dads.imbin") {
+	    $dir = mkfiles ("www");
+	    $value = "$dir/$words[0].$words[1].$words[2].$words[3].imbin.jpg";
+	    last;
+	}
+	&escape ("unknown type for mknames: $type");
+    }    
+    return ($value);
+}
+
+####  TOOLS TO INTERACT WITH FORMATED CONFIG FILE  #####################################################
+
+# parse config info
+# CRUNID TYPE FILTER [CCD] VERSION START STOP STATE
+#**************************
+sub gtconfig {
+    my ($value, $type, @words, $ccd);
+    # in: (config line) (type)
+    @words = split (" ", $_[0]);
+    $type = $_[1];
+
+    { 
+	if ($type eq "elixir") {
+	    $value = "$words[0] $words[1] $words[2] $words[3] $words[4] $words[5]";
+	    last;
+	}
+	if ($type eq "chiprun") {
+	    $ccd  = $_[2];
+	    $value = "$words[0] $words[1] $words[2] $ccd $words[3] $words[4] $words[5]";
+	    last;
+	}
+	if ($type eq "config") {
+	    $value = "$words[0].$words[1].$words[2]";
+	    last;
+	}
+	if ($type eq "filter") {
+	    $value = "$words[2]";
+	    last;
+	}
+	if ($type eq "ID") {
+	    $value = "$words[0]";
+	    last;
+	}
+	if ($type eq "version") {
+	    $value = "$words[0].$words[1].$words[2].$words[3]";
+	    last;
+	}
+	if ($type eq "from") {
+	    $value = "$words[4]";
+	    last;
+	}
+	if ($type eq "to") {
+	    $value = "$words[5]";
+	    last;
+	}
+	if ($type eq "status") {
+	    $value = "$words[6]";
+	    last;
+	}
+	&escape ("unknown type for gtconfig");
+    }
+
+    return $value;
+}
+
+# set config value
+# TYPE FILTER CRUNID VERSION START STOP STATE
+# CRUNID TYPE FILTER [CCD] VERSION START STOP STATE
+#**************************
+sub stconfig {
+    # in: (config line) (value) (type)
+    my (@words) = split (" ", $_[0]);
+    my ($type)  = $_[1];
+    my ($value) = $_[2];
+    my ($line);
+
+    { 
+	if ($type eq "all") {
+	    $line = sprintf "%s %6s %4s %2d %s %s %s", $words[0], $words[1], $words[2], $words[3], $words[4], $words[5], $words[6];
+	    last;
+	}
+	if ($type eq "version") {
+	    $line = sprintf "%s %6s %4s %2d %s %s %s", $words[0], $words[1], $words[2], $value, $words[4], $words[5], $words[6];
+	    last;
+	}
+	if ($type eq "start") {
+	    $line = sprintf "%s %6s %4s %2d %s %s %s", $words[0], $words[1], $words[2], $words[3], $value, $words[5], $words[6];
+	    last;
+	}
+	if ($type eq "stop") {
+	    $line = sprintf "%s %6s %4s %2d %s %s %s", $words[0], $words[1], $words[2], $words[3], $words[4], $value, $words[6];
+	    last;
+	}
+	if ($type eq "status") {
+	    $line = sprintf "%s %6s %4s %2d %s %s %s", $words[0], $words[1], $words[2], $words[3], $words[4], $words[5], $value;
+	    last;
+	}
+	&escape ("unknown type for stconfig");
+    }
+
+    return $line;
+}
+
+# load dates & mode (returns @list)
+sub load_dates {
+    my ($file, $line, @list);
+    my ($start, $stop);
+    
+    $file = mkfiles ("dates");
+    @list = ();
+    open (FILE, "$file");
+    @list = <FILE>;
+    close (FILE);
+
+    ($tmp, $start) = split (" ", $list[0]);
+    if ($tmp ne "START") { print STDERR "dates file is confused\n"; }
+
+    ($tmp, $stop) = split (" ", $list[1]);
+    if ($tmp ne "STOP") { print STDERR "dates file is confused\n"; }
+    
+    ($tmp, $mode) = split (" ", $list[2]);
+    if ($tmp ne "MODE") { print STDERR "dates file missing mode\n"; }
+    if ($mode eq "") { $mode = "hold"; }
+
+    ($start, $stop, $mode);
+}
+
+# write to dates file
+sub save_dates {
+    # save_dates start stop auto.mode
+    my (@outlist) = @_;
+
+    my ($file) = mkfiles ("dates");
+    open (FILE, ">$file");
+    print FILE "START $outlist[0]\n";
+    print FILE "STOP  $outlist[1]\n";
+    print FILE "MODE  $outlist[2]\n";
+    close (FILE);
+}    
+
+# load config lines (returns @list)
+sub load_config {
+    my ($file, $line, @list);
+    
+    $file = mkfiles ("config");
+    @list = ();
+    open (FILE, "$file");
+    while ($line = <FILE>) {
+	chop ($line);
+	@list = (@list, $line);
+    }
+    close (FILE);
+    
+    @list;
+}
+
+# write to config file
+sub save_config {
+
+    my(@outlist) = sort @_;
+    
+    my($file) = mkfiles ("config");
+    open (FILE, ">$file");
+    for ($i = 0; $i < @outlist; $i++) {
+	print FILE "$outlist[$i]\n";
+    }
+    close (FILE);
+    
+}    
+
+####  USEFUL TOOLS  #################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye { 
+    unlink $tmpenv;
+    exit 0; 
+}
+
+sub escape { 
+    unlink $tmpenv;
+    print STDERR "$_[0]\n";
+    exit 1;
+}
+
+# grab complete configuration info from the elixir config system, 
+# applying appropriate command-line arguments
+sub elixir_config {
+    my (@argv) = @_;
+    my ($opt, $config, @tmparg, $status);
+    $config = "";
+    if ($ENV{'PTOLEMY'}) { $config = "-c $ENV{'PTOLEMY'}"; }
+    umask (0);
+
+    # look for optional command-line arguments
+    @tmparg = @argv;
+    foreach (@tmparg) {
+	$value = shift @argv;
+
+	if ($value eq "-c") {
+	    $value = shift @argv;
+	    $config = "-c $value";
+	    next;
+	}
+
+	if ($value eq "-C") {
+	    push @opt, $value;
+	    $value = shift @argv;
+	    push @opt, $value;
+	    $elconf = $value;
+	    next;
+	}
+	
+	if ($value eq "-D") {
+	    push @opt, $value;
+	    $value = shift @argv;
+	    push @opt, $value;
+	    $value = shift @argv;
+	    push @opt, $value;
+	    next;
+	}
+	
+	if ($value eq "-run") {
+	    $run = shift @argv;
+	    push @opt, "-D RUNID.MKFRINGE $run -D RUNID $run";
+	    next;
+	}
+	
+	if ($value eq "-camera") {
+	    $camera = shift @argv;
+	    push @opt, "-D CAMERA.MKFRINGE $camera -D CAMERA $camera";
+	    next;
+	}
+	push @argv, $value;
+    }
+
+    # load RUNID from state.data (unless set on command line)
+    if ($run eq "") {
+	$run = `gconfig RUNID.MKFRINGE`; chop $run;
+	if ($?) {  &escape ("run is not defined: use 'mkdetrend config' or 'mkrun sys'\n"); }
+	if ($run eq "") {  &escape ("run is not defined: use 'mkdetrend config' or 'mkrun sys'\n"); }
+	push @opt, "-D RUNID.MKDETREND $run -D RUNID $run";
+    }
+
+    # load CAMERA from state.data (unless set on command line)
+    if ($camera eq "") {
+	$camera = `gconfig CAMERA.MKFRINGE`; chop $camera;
+	if ($?) {  &escape ("camera is not defined: use 'mkrun sys' to set\n"); }
+	if ($camera eq "") {  &escape ("camera is not defined: use 'mkrun sys'\n"); }
+	push @opt, "-D CAMERA.MKDETREND $camera -D CAMERA $camera";
+    }
+
+    # set env PTOLEMY using values from command line
+    $config = join (" ", $config, @opt);
+    $tmpenv = `mktemp /tmp/elixir.XXXXXX`; chop ($tmpenv);
+    $status = system ("gconfig -raw $config > $tmpenv");
+    if ($status) { &escape ("error in elixir configuration: gconfig fails"); }
+    $ENV{'PTOLEMY'} = "$tmpenv";
+
+    # set global variables based on new config info
+    $root = `gconfig DETREND_ROOT`;  chop $root;
+    if ($?) { &escape ("error with elixir configuration variable: DETREND_ROOT"); }
+
+    $wwwroot  = `gconfig DETREND_WWW`;  chop $wwwroot;
+    if ($?) { &escape ("error with elixir configuration variable: DETREND_WWW"); }
+    
+    $Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+    if ($?) { &escape ("error with elixir camera configuration"); }
+
+    @ccds = split (" ", `cameraconfig -ccdn`);
+    if ($?) { &escape ("error with elixir camera configuration"); }
+
+    # get list of valid filters from lookup table
+    @filters = split (" ", `filtnames list`);
+    if ($?) { &escape ("error with elixir filter configuration"); }
+
+    # recipe file defines detrend types & cutoff exptime values
+    $recipefile = `gconfig DETREND_RECIPES`; chop $recipefile;
+    if ($?) { &escape ("missing DETREND_RECIPES in configuration"); }
+
+    @filt = ();
+    foreach $filter (@filters) {
+	($detypes) = split (" ", `gconfig -c $recipefile $filter`);
+	if ($?) { die "ERROR: missing detrend recipe for $filter\n"; }
+
+	@detypes = split (",", $detypes);
+	for ($i = 0; $i < @detypes; $i++) {
+	    if ($detypes[$i] eq "fringe") {
+		push @filt, $filter;
+		push @type, "fringe";
+		last;
+	    }
+	}
+    }
+
+    $CGI = `gconfig CGIBIN`; chop ($CGI);
+    if ($?) { &escape ("error with elixir configuration variable: CGIBIN"); }
+
+    $det  = "$root/$run";
+    $www  = "$wwwroot/$run/html";
+    return (@argv);
+}
+
+sub usage {
+
+    if (@ARGV == 1) {
+	print STDERR "\n --- user modes ---\n";
+	print STDERR "create (run) (startdate) (stopdate)\n";
+	print STDERR "mkconfig\n";
+	print STDERR "config (run)\n";
+	print STDERR "init\n";
+	print STDERR "run\n";
+	print STDERR "list.runs\n";
+	print STDERR "set (config.ver) (state)\n";
+	print STDERR "reg\n";
+	print STDERR "state \n";
+	print STDERR "help \n";
+	print STDERR "\n --- internal modes --- \n";
+	print STDERR "flips\n";
+	print STDERR "norm\n";
+	print STDERR "update\n";
+	print STDERR "merge\n";
+	print STDERR "dup (config)\n";
+	print STDERR "del (config)\n";
+	print STDERR "def (config.ver) (start) (stop)\n";
+	print STDERR "eval (step)\n";
+	print STDERR "mevel (step)\n";
+	print STDERR "htmldup\n";
+	print STDERR "htmldel\n";
+	print STDERR "htmldef\n";
+	print STDERR "htmlmod\n";
+	print STDERR "htmlkeep\n";
+	print STDERR "html1\n";
+	print STDERR "html2 (config.ver)\n";
+	print STDERR "html3 (entry.config.ver)\n";
+	&goodbye;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: $MKFRINGE (help) [mode]\n"; &goodbye; }
+    
+    if ($ARGV[1] eq "config") {
+	print STDERR "set up initial configuration\n";
+	&goodbye;
+    }
+    
+    if ($ARGV[1] eq "save") {
+	print STDERR "save results from current configuration\n";
+	&goodbye;
+    }
+    
+    print STDERR "help for $ARGV[1] not defined\n";
+    &goodbye;
+}
+
+#### overview ########
+
+# init: create lists of possible images for each master type:
+#       01Ak01.fringe.I.0.master  (MOSAIC)
+
+# detrend: detrend the input images
+
+# files needed for html pages:
+
+# html/*
+# fringe/*.master
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mkhtml
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mkhtml	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mkhtml	(revision 16632)
@@ -0,0 +1,183 @@
+#!/usr/bin/env perl
+
+$template = "template.htm";
+if ($ARGV[0] eq "-template") { 
+    shift @ARGV;
+    $template = $ARGV[0]; 
+    shift @ARGV; 
+}
+
+if (@ARGV != 3) { die "USAGE: mkhtml [-template template] (root) (src) (html)\n"; }
+
+$root     = $ARGV[0];
+$root     =~ s|/*$||; # strip trailing /'s to clean path
+
+$input    = $ARGV[1];
+$output   = $ARGV[2];
+$config   = "Configure";
+
+# print STDERR "template: $template\n";
+
+# load variables from Configure (eg, ROOT, etc)
+# these are interpolated except in the content section
+open (FILE, $config);
+@input = <FILE>;
+close (FILE);
+foreach $line (@input) {
+    ($var, $eq, $value) = split (" ", $line);
+    $$var = $value;
+}
+
+# load data from template
+open (FILE, $template);
+@template = <FILE>;
+close (FILE);
+
+# load data from input file
+open (FILE, $input);
+@input = <FILE>;
+close (FILE);
+
+# default metadata values:
+$title = &rootname ($input);
+if ($title eq "index") { $title = &basename (&dirname ($input)); }
+
+$page  = &rootname ($input);
+if ($page  eq "index") { $page  = &basename (&dirname ($input)); }
+
+$path  = &dirname ($input);
+
+$ext   = &extname ($input);
+
+# file is the entry in the index listing
+$file  = $output;
+if ($file =~ m|index.html|) { $file = &dirname ($output); }
+$file  =~ s|^$root|ROOT|;
+
+# apply ROOT variable to content (this comes from Configure)
+# foreach $line (@input) { while ($line =~ m|\$ROOT|) { $line =~ s|\$ROOT|$ROOT|; } }
+
+# search for the metadata lines in input file
+while (@input) {
+    $line = shift @input;
+    if ($line =~ /^\s*$/) { next; }
+    if ($line =~ /<meta\s+name=title\s+content=/) {
+	($title) = $line =~ /<meta\s+name=title\s+content=(.*)>/;
+	next;
+    }
+    if ($line =~ /<meta\s+name=page\s+content=/) {
+	($page) = $line =~ /<meta\s+name=page\s+content=(.*)>/;
+	next;
+    }
+    unshift @input, $line;
+    last;
+}
+
+# create the output file
+open (OUT, ">$output");
+
+$found = $menu = 0;
+foreach $line (@template) {
+    
+    chop $line;
+    while ($line =~ m|ROOT|) { $line =~ s|ROOT|$ROOT|; }
+    
+    # interpolate over basic metadata entries
+    if ($line =~ m|<meta\s+name=page>|) {
+	print OUT "$page\n";
+	next;
+    }
+    if ($line =~ m|<meta\s+name=title>|) {
+	print OUT "$title\n";
+	next;
+    }
+    if ($line =~ m|<meta\s+name=body>|) {
+	# add in parsing of <p> tags, etc in here
+	&dumpinput;
+	next;
+    }
+
+    # parse the index file
+    if ($line =~ m|<meta\s+name=index\s+file=|) {
+	($index) = $line =~ m|<meta\s+name=index\s+file=(.*)>|;
+	$index = "$path/$index";
+	open (INDEX, $index);
+	@index = <INDEX>;
+	# need to find and tag this file 
+	foreach $index (@index) {
+	    if ($index =~ m|href=$file>|) {
+		$index =~ s|class=doc|class=sel|;
+		$index =~ s|class=dir|class=dsl|;
+		$index =~ s|class=dl|class=sl|;
+		$index =~ s|$file>\s+-\s+|$file> + |;
+	    }
+	    # interpolate ROOT
+	    while ($index =~ m|ROOT|) { $index =~ s|ROOT|$ROOT|; }
+	}
+
+	close (INDEX);
+	print OUT @index;
+	next;
+    }
+    print OUT "$line\n";
+}
+    
+close (OUT);
+exit 0;
+
+sub dumpinput {
+
+    if ($ext eq "txt") {
+	print OUT "<pre>\n";
+    }
+    print OUT "@input";
+    if ($ext eq "txt") {
+	print OUT "</pre>\n";
+    }
+}
+
+# behaves just like system basename function (returns last portion of path)
+sub basename {
+
+    my ($file) = $_[0];
+    my ($base, @words);
+
+    @words = split ("/", $file);
+    $base = $words[-1];
+    return $base;
+}
+
+
+# behaves just like system dirname function (strips last portion of path)
+sub dirname {
+
+    my ($file) = $_[0];
+    my ($base, @words);
+
+    @words = split ("/", $file);
+    if (@words == 1) { return "."; }
+
+    pop @words;
+    $file = join ('/', @words);
+    return $file;
+}
+
+# behaves just like system basename function (returns last portion of path)
+sub extname {
+    my ($file) = &basename ($_[0]);
+    my($ext) = $file =~ m|\S*\.(\S*)$|;
+    return $ext;
+}
+
+# behaves just like system basename function (returns last portion of path)
+sub rootname {
+    my ($file) = &basename ($_[0]);
+    my($ext) = $file =~ m|(\S*)\.\S*$|;
+    return $ext;
+}
+
+# input metadata lines:
+# <meta name="file"  content="test">
+# <meta name="title" content="a test title">
+# <meta name="page"  content="test">
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mkidx
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mkidx	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mkidx	(revision 16632)
@@ -0,0 +1,232 @@
+#!/usr/bin/env perl
+
+use strict;
+
+if (@ARGV != 1) { die "USAGE: mkidx (directory)\n"; }
+
+# input is the name of a directory and current level
+# outputs are: directory list, document list, index file for directory
+# menu for that directory
+
+# parse input info
+my($path);
+$path  = $ARGV[0];
+$path  =~ s|/*$||; # strip trailing /'s to clean path
+
+local($mkidx::root) = $path;
+
+&mksubidx ($path, 0, 0, "template.htm");
+exit 0;
+
+sub mksubidx {
+    # USAGE: mksubidx (path) (entry) (template) (index)
+    my($path)  	  = shift @_;
+    my($level) 	  = shift @_;
+    my($entry)    = shift @_;
+    my($template) = shift @_;
+    my(@updex)    = @_;
+
+    my($i, $j);
+    my($line, $value, $dir);
+    my(@list);
+    my($file, $root, $link, $ext);
+    my(@seq)    = ();
+    my(@dirs)   = ();
+    my(@mydirs) = ();
+    my(@docs)   = ();
+    my(@txts)   = ();
+    my(@index)  = ();
+    my(@mydex)  = ();
+    my($Nmydex);
+    my(@seqline);
+
+    # if this directory contains a template file, reset entry and level
+    # supply the template file to mkhtml here and below
+    if (-e "$path/template.htm") {
+	@updex = ();
+	$level = 0;
+	$entry = 0;
+	$template = "$path/template.htm";
+    }
+    # print STDERR "idx: $template\n";
+
+    # put leading portion of updex here
+    for ($i = 0; $i < $entry; $i++) {
+	push @index, $updex[$i];
+    }
+
+    # find all dirs in this directory
+    @list = <$path/*>;
+    foreach $file (@list) {
+	if (-e "$path/nochild.idx") { last; }
+	if (! -d $file) { next; }
+	$root = &basename ($file);
+	$link = $file;
+	$link =~ s|^$mkidx::root|ROOT|;
+
+	# list special directories here
+	if ($root eq "CVS") { next; }
+	if (-e "$file/noindex.idx") { next; }
+
+	push @mydirs, $file;
+
+	$line = sprintf "<tr><td class=dir%d> <a class=dl %-30s -%20s </a></td></tr>", $level, "href=$link>", $root;
+	push @mydex, $line;
+	push @seq, $root;
+    }
+
+    # find all docs (htm, txt) in this directory
+    @list = (<$path/*.htm>,<$path/*.hts>,<$path/*.txt>);
+    foreach $file (@list) {
+	if (! -f $file) { next; }
+
+	$ext = &extname ($file);
+	$root = &rootname ($file);
+
+	$link = $file;
+	$link =~ s|.$ext$|.html|;
+	$link =~ s|^$mkidx::root|ROOT|;
+
+	# list special files here
+	if ($root eq "index") { next; }
+	if ($root eq "template") { next; }
+	if ($root eq "sequence") { next; }
+
+	# print STDERR "ext: $ext, root: $root\n";
+
+	push @docs, $file;
+	push @mydirs, "0";
+	
+	if ($ext ne "hts") {
+	    # simple case: no extra information:
+	    $line = sprintf "<tr><td class=doc%d> <a class=dl %-30s &nbsp; %20s </a></td></tr>", $level, "href=$link>", $root;
+	    push @mydex, $line;
+	    push @seq, &basename ($file);
+	}
+    }
+
+    # look for directory sequencing information
+    if (-f "$path/sequence.idx") { 
+	open (FILE, "$path/sequence.idx");
+	@seqline = <FILE>;
+	close (FILE);
+      OUT:
+	for ($i = 0; $i < @seqline; $i++) {
+	    $Nmydex = @mydex;
+	    chop $seqline[$i];
+	  IN:
+	    for ($j = 0; $j < $Nmydex; $j++) {
+		$line  = shift @mydex;
+		$value = shift @seq;
+		$dir   = shift @mydirs;
+		if ($seqline[$i] eq $value) {
+		    push @index, $line;
+		    push @dirs, $dir;
+		    # print "ADD SEQ: $dir, $line\n";
+		    next OUT;
+		} else {
+		    push @mydex, $line;
+		    push @mydirs, $dir;
+		    push @seq, $value;
+		}
+	    }
+	}	
+    }
+    # add trailing portion of updex here
+    foreach $line (@mydex) {
+	$dir = shift @mydirs;
+	# print "ADD VAL: $dir, $line\n";
+	push @dirs, $dir;
+	push @index, $line;
+    }
+
+    # add trailing portion of updex here
+    for ($i = $entry; $i < @updex; $i++) {
+	push @index, $updex[$i];
+    }
+
+    for ($i = 0; $i < @dirs; $i++) {
+	if ($dirs[$i] eq 0) { next; }
+	&mksubidx ($dirs[$i], $level + 1, $i + $entry + 1, $template, @index);
+    }
+
+    # output index for this directory
+    open (FILE, ">$path/index.idx");
+    foreach $line (@index) {
+	print FILE "$line\n";
+    }
+    close (FILE);
+
+    # create html for docs in this directory
+    foreach $file (@docs, "$path/index.htm") {
+	$ext  = &extname ($file);
+	# print STDERR "ext: $ext\n";
+	# $root  = &rootname ($file);
+	# print STDERR "root: $root\n";
+	$link = $file;
+	$link =~ s|.$ext$|.html|;
+	system "mkhtml -template $template $mkidx::root $file $link";
+    }
+    return;
+}
+
+# behaves just like system basename function (returns last portion of path)
+sub basename {
+
+    my ($file) = $_[0];
+    my ($base, @words);
+
+    @words = split ("/", $file);
+    $base = $words[-1];
+    return $base;
+}
+
+# behaves just like system basename function (returns last portion of path)
+sub extname {
+    my ($file) = &basename ($_[0]);
+    my($ext) = $file =~ m|\S*\.(\S*)$|;
+    return $ext;
+}
+
+# behaves just like system basename function (returns last portion of path)
+sub rootname {
+    my ($file) = &basename ($_[0]);
+    my($ext) = $file =~ m|(\S*)\.\S*$|;
+    return $ext;
+}
+
+# behaves just like system dirname function (strips last portion of path)
+sub dirname {
+
+    my ($file) = $_[0];
+    my ($base, @words);
+
+    @words = split ("/", $file);
+    if (@words == 1) { return "."; }
+
+    pop @words;
+    $file = join ('/', @words);
+    return $file;
+}
+
+###
+#    # find all txt files in this directory
+#    @list = <$path/*.txt>;
+#    foreach $file (@list) {
+#	if (! -f $file) { next; }
+#
+#	$ext = &extname ($file);
+#
+#	$root = &basename ($file);
+#	$root =~ s|.txt$||;
+#	$link = $file;
+#	$link =~ s|.txt$|.html|;
+#	$link =~ s|^$mkidx::root|ROOT|;
+#
+#	push @txts, $file;
+#
+#	# simple case: no extra information:
+#	$line = sprintf "<tr><td class=doc%d> <a class=dl %-30s  %20s </a></td></tr>", $level, "href=$link>", $root;
+#	push @index, $line;
+#    }
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mkrun
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mkrun	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mkrun	(revision 16632)
@@ -0,0 +1,711 @@
+#!/usr/bin/env perl
+
+# check usage
+if (@ARGV < 1) {
+    print STDOUT "USAGE: mkrun (mode) [arguments]\n";
+    print STDOUT " mkrun help gives a complete list\n";
+    &goodbye;
+}
+if ($ARGV[0] eq "help") { &usage; }
+
+# this should come fron the config system
+$runlist  = `gconfig RUN_LIST`; chop $runlist;
+@runlist  = ();
+
+# call appropriate command
+if ($ARGV[0] eq "create")    { &create; }
+if ($ARGV[0] eq "delete")    { &delete; }
+if ($ARGV[0] eq "hstcreate") { &hstcreate; }
+if ($ARGV[0] eq "addqso")    { &addqso; }
+if ($ARGV[0] eq "delqso")    { &delqso; }
+if ($ARGV[0] eq "comment")   { &comment; }
+if ($ARGV[0] eq "status")    { &status; }
+if ($ARGV[0] eq "state")     { &status; }
+if ($ARGV[0] eq "sys")       { &sysfunc; }
+if ($ARGV[0] eq "run")       { &getrun; }
+if ($ARGV[0] eq "date")      { &getdate; }
+if ($ARGV[0] eq "update")    { &update; }
+if ($ARGV[0] eq "test")      { &test; }
+if ($ARGV[0] eq "today")     { &today; }
+
+print STDOUT "invalid mkrun command\n";
+exit 1;
+
+###########################################################
+
+######
+sub test {
+
+    $date = mjd_to_date ($ARGV[1]);
+    print "$ARGV[1] : $date\n";
+    exit 1;
+}
+
+######
+sub sysfunc {
+
+    $statedata = `gconfig STATE_DATA`; chop ($statedata);
+    if ($?) { die "can't find STATE_DATA\n"; }
+
+    # show current state
+    if (@ARGV == 1) {
+	system ("cat $statedata");
+	exit 0;
+    }
+
+    if (@ARGV == 2) {
+	$var  = "\U$ARGV[1]\E";
+	if ($var eq "INIT")          { goto initsys; }
+	if ($var eq "RUNID")         { goto getsys; }
+	if ($var eq "PROCESS")       { goto getsys; }
+	if ($var eq "NOTIFY")        { goto getsys; }
+	if ($var =~ m|CAMERA.(\S+)|) { goto getsys; }
+	if ($var =~ m|RUNID.(\S+)|)  { goto getsys; }
+	die "invalid sys parameter $var\n"; 
+
+      getsys:
+	open (FILE, "$statedata");
+	@list = <FILE>;
+	close (FILE);
+
+	foreach $line (@list) {
+	    ($key, $value) = split (" ", $line);
+	    $key  = "\U$key\E";
+	    if ($key ne $var) { next; }
+	    print STDOUT "$value\n";
+	    exit 0;
+	}
+	die "can't find entry $var\n"; 
+
+      initsys:
+	open (FILE, "$statedata");
+	print FILE "# elixir current state\n";
+	print FILE "\n";
+	print FILE "RUNID 02Bk03\n";
+	print FILE "PROCESS 02Bk03\n";
+	print FILE "\n";
+	print FILE "CAMERA.CURRENT       none\n";
+	print FILE "CAMERA.MKDETREND     none\n";
+	print FILE "CAMERA.MKFRINGE      none\n";
+	print FILE "CAMERA.POSTRUN       none\n";
+	print FILE "\n";
+	print FILE "RUNID.CURRENT        none\n";
+	print FILE "RUNID.MKDETREND      none\n";
+	print FILE "RUNID.MKFRINGE       none\n";
+	print FILE "RUNID.POSTRUN        none\n";
+	print FILE "\n";
+	print FILE "NOTIFY               \n";
+	close (FILE);
+	exit 0;
+    }
+
+    if (@ARGV == 3) {
+	$var  = "\U$ARGV[1]\E";
+	$nval = $ARGV[2];
+	if ($var eq "RUNID")         { goto setsys; }
+	if ($var eq "PROCESS")       { goto setsys; }
+	if ($var eq "NOTIFY")        { goto setsys; }
+	if ($var =~ m|CAMERA.(\S+)|) { goto setsys; }
+	if ($var =~ m|RUNID.(\S+)|)  { goto setsys; }
+	die "invalid sys parameter $var\n"; 
+
+      setsys:
+	open (FILE, "$statedata");
+	@list = <FILE>;
+	close (FILE);
+
+	$found = 0;
+	foreach $line (@list) {
+	    ($key, $value) = split (" ", $line);
+	    $key  = "\U$key\E";
+	    if ($key ne $var) { next; }
+	    $found = 1;
+	    $line = sprintf "%-20s %s\n", $var, $nval;
+	}
+
+	if (! $found) { die "can't find entry $var\n"; }
+	open (FILE, ">$statedata");
+	foreach $line (@list) {
+	    print FILE "$line";
+	}
+	close (FILE);
+	exit 0;
+    }
+
+    print "USAGE: mkrun sys\n";
+    print "USAGE: mkrun sys init\n";
+    print "USAGE: mkrun sys (key)\n";
+    print "USAGE: mkrun sys (key) (value)\n";
+    exit 1;
+}
+
+######
+sub update {
+
+    $now = time;
+    $mjd = &sec_to_mjd ($now);
+
+    &load_runlist;
+
+    $match = "";
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid, $start, $stop, $camera) = split (" ", $line);
+	if ($runid eq "") { next; } # skip empty lines
+	$mjd_start = date_to_mjd ($start);
+	$mjd_stop  = date_to_mjd ($stop);
+	if (($mjd >= $mjd_start) && ($mjd <= $mjd_stop)) { 
+	    $match = $line;
+	    last;
+	}
+    }
+    if ($match eq "") { 
+	$camera = "none";
+	$runid  = "none";
+    }
+    system ("mkrun sys camera.current $camera");
+    system ("mkrun sys runid.current $runid");
+    system ("ssPut /e/state/$camera/cameraRun $runid COMMENT=\"valid current camera run ID (CRUNID)\" LIFETIME=90000");
+    system ("ssPut /e/state/masterRun $runid COMMENT=\"master current camera run ID (CRUNID)\" LIFETIME=90000");
+    exit 0;
+}
+
+######
+sub today {
+
+    $now = time;
+    $mjd = &sec_to_mjd ($now);
+
+    &load_runlist;
+
+    $match = "";
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid, $start, $stop, $camera) = split (" ", $line);
+	if ($runid eq "") { next; } # skip empty lines
+	$mjd_start = date_to_mjd ($start);
+	$mjd_stop  = date_to_mjd ($stop);
+	if (($mjd >= $mjd_start) && ($mjd <= $mjd_stop)) { 
+	    $match = $line;
+	    last;
+	}
+    }
+    if ($match eq "") { 
+	$camera = "none";
+	$runid  = "none";
+    }
+    print STDOUT "CAMERA: $camera, RUNID: $runid\n";
+    exit 0;
+}
+
+######
+sub getrun {
+
+    if (@ARGV != 2) { die "USAGE: mkrun run (runid)\n"; }
+
+    &load_runlist;
+    $line = grab_runline ($ARGV[1]);
+    print STDOUT "$line\n";
+    if ($line eq "") { 
+	exit 1;
+    } else {
+	exit 0;
+    }
+}
+
+######
+sub getdate {
+
+    if (@ARGV != 2) { die "USAGE: mkrun date (yyyy/mm/dd)\n"; }
+
+    my ($mjd) = date_to_mjd ($ARGV[1]);
+
+    &load_runlist;
+
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid, $start, $stop) = split (" ", $line);
+	if ($runid eq "") { next; } # skip empty lines
+	$mjd_start = date_to_mjd ($start);
+	$mjd_stop  = date_to_mjd ($stop);
+	if (($mjd >= $mjd_start) && ($mjd < $mjd_stop)) { 
+	    print STDOUT "$line\n";
+	    exit 0;
+	}
+    }
+    print STDOUT "";
+    exit 1;
+}
+
+############
+sub status {
+
+    &load_runlist;
+    foreach $line (@runlist) {
+	print STDOUT "$line\n";
+    }
+    exit 0;
+}
+
+############
+sub comment {
+
+    my (@argv) = @_;
+    
+    if (@argv != 2) {
+	print STDOUT "USAGE: mkrun comment (comment line)\n";
+	exit 2;
+    }
+
+    $comment = $argv[1];
+
+    &load_runlist;
+    insert_comment ($argv[1]);
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub create {
+
+    if (@ARGV != 5) {
+	print STDOUT "USAGE: mkrun create (run) (start) (stop) (camera)\n";
+	exit 2;
+    }
+
+    $runid  = $ARGV[1];
+    $start  = $ARGV[2];
+    $stop   = $ARGV[3];
+    $camera = $ARGV[4];
+
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    ($Orunid, $Ostart, $Ostop, $Ocamera, $qrunid) = split (" ", $line);
+    $line = mk_runline ($runid, $start, $stop, $camera, $qrunid);
+    insert_runline ($line);
+
+    # does not check for overlaps, but probably should
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub delete {
+
+    if (@ARGV != 2) {
+	print STDOUT "USAGE: mkrun delete (run)\n";
+	exit 2;
+    }
+
+    $runid  = $ARGV[1];
+
+    &load_runlist;
+    
+    $Ns = @runlist;
+    delete_runline ($runid);
+    $Ne = @runlist;
+
+    if ($Ns == $Ne) {
+	print STDERR "runid $runid not found\n";
+	exit 1;
+    }
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub hstcreate {
+
+    if (@ARGV != 1) {
+	print STDOUT "USAGE: mkrun hstcreate\n";
+	exit 2;
+    }
+
+    print STDOUT "Enter HST date for start of first night (YYYY/MM/DD): ";
+    $start = <STDIN>; chop $start;
+    $mjd = date_to_mjd ($start);
+    $mjd += 1.0;
+    $start = date_format (&mjd_to_date ($mjd));
+
+    print STDOUT "Enter HST date for start of last night (YYYY/MM/DD): ";
+    $stop = <STDIN>; chop $stop;
+    $mjd = date_to_mjd ($stop);
+    $mjd += 2.0;
+    $stop = date_format (&mjd_to_date ($mjd));
+
+    print STDOUT "Enter camera: ";
+    $camera = <STDIN>; chop $camera;
+
+    print STDOUT "Enter run ID: ";
+    $runid = <STDIN>; chop $runid;
+
+    print STDOUT "Enter associated QSO run IDs (separated by commas): ";
+    $qrunid = <STDIN>; chop $qrunid;
+
+    &load_runlist;
+    
+#    $line = grab_runline ($runid);
+#    ($Orunid, $Ostart, $Ostop, $Ocamera, $Oqrunid) = split (" ", $line);
+    $line = mk_runline ($runid, $start, $stop, $camera, $qrunid);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub addqso {
+    if (@ARGV != 3) {
+	print STDOUT "USAGE: mkrun addqso (run) (qsorun)\n";
+	exit 2;
+    }
+
+    $runid = $ARGV[1];
+    $qrunid  = $ARGV[2];
+
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    if ($line eq "") { 
+	print STDERR "run id $runid not in run list\n";
+	exit 1;
+    }
+    ($runid, $start, $stop, $camera, $Oqrunid) = split (" ", $line);
+    if ($Oqrunid) {
+	$qrunid = $Oqrunid . "," . $qrunid;
+    } 
+
+    $line = mk_runline ($runid, $start, $stop, $camera, $qrunid);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+############
+sub delqso {
+    if (@ARGV != 2) {
+	print STDOUT "USAGE: mkrun delqso (qsorun)\n";
+	exit 2;
+    }
+
+    $qrunid  = $ARGV[1];
+
+    &load_runlist;
+    
+    # find listed qrunid
+    $match = "";
+  SEARCH:
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($tmp, $tmp, $tmp, $tmp, $qlist) = split (" ", $line);
+	@qlist = split (",", $qlist);
+	foreach $qid (@qlist) {
+	    if ($qrunid ne $qid) { next; }
+	    $match = $line;
+	    last SEARCH;
+	}
+    }
+    if ($match eq "") {
+	print STDERR "QSO run id $qrunid not found in run list\n";
+	exit 1;
+    }
+
+    # recreate $qlist without $qrunid
+    @qnew = ();
+    foreach $qid (@qlist) {
+	if ($qid eq $qrunid) { next; }
+	push @qnew, $qid;
+    }
+    $qlist = join (",", @qnew);
+
+    ($runid, $start, $stop, $camera) = split (" ", $match);
+
+    $line = mk_runline ($runid, $start, $stop, $camera, $qlist);
+    insert_runline ($line);
+
+    &save_runlist;
+    exit 0;
+}
+
+####### runlist utilities ############################
+sub load_runlist {
+    open (FILE, "$runlist");
+    @runlist = <FILE>;
+    foreach $line (@runlist) {
+	chop ($line);
+    }
+    close (FILE);
+}    
+
+sub save_runlist {
+    open (FILE, ">$runlist");
+    foreach $line (@runlist) {
+	print FILE "$line\n";
+    }
+    close (FILE);
+}    
+
+sub grab_runline {
+    my ($id) = $_[0];
+    my ($line);
+    my ($runid);
+
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid) = split (" ", $line);
+	if ($runid ne $id) { next; }
+	return ($line);
+    }
+    return ("");
+}
+    
+sub insert_comment {
+    my ($comment) = $_[0];
+
+    @runlist = (@runlist, $comment);
+    return 1;
+}
+
+sub insert_runline {
+    my ($runline) = $_[0];
+    my ($line);
+    my ($runid, $id);
+
+    # match the run id lines
+    ($id) = split (" ", $runline);
+    foreach $line (@runlist) {
+	if ($line =~ /^\#/) { next; } # skip commented lines
+	($runid) = split (" ", $line);
+	if ($runid ne $id) { next; }
+	$line = $runline;
+	return 1;
+    }
+    @runlist = (@runlist, $runline);
+    return 0;
+}
+
+sub delete_runline {
+    my ($id) = $_[0];
+    my ($line, $runid);
+
+    # match the run id lines
+    @newlist = ();
+    foreach $line (@runlist) {
+	($runid) = split (" ", $line);
+	if ($runid eq $id) { next; }
+	@newlist = (@newlist, $line); 
+    }
+    @runlist = @newlist;
+    return 0;
+}
+
+sub mk_runline {
+    my ($runid, $start, $stop, $camera, $qrunid, $line);
+    $runid  = $_[0];
+    $start  = $_[1];
+    $stop   = $_[2];
+    $camera = $_[3];
+    $qrunid = $_[4];
+
+    $start = date_format ($start);
+    $stop  = date_format ($stop);
+    $line = sprintf "%s %s %s %-9s  %s", $runid, $start, $stop, $camera, $qrunid;
+    return ($line);
+}
+
+# utilities ##############################################
+
+sub atcommand {
+    my ($cmd, $log, $time, $date);
+    $cmd  = $_[0];
+    $log  = $_[1];
+    $time = $_[2];
+    $date = $_[3];
+
+    if (($log eq "") || ($log eq "NONE")) { $log = "/dev/null"; } 
+
+    printf "%s %s: %s\n", $date, $time, $cmd;
+    $line = sprintf "%s %s %s %s", $date, $time, $log, $cmd;
+    print SCHED "$line\n";
+}
+
+
+sub vsystem {
+    # print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub date_format {
+    my ($date) = $_[0];
+    my ($year, $month, $day);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+    $date = sprintf "%4d/%02d/%02d", $year, $month, $day;
+    return ($date);
+}
+
+sub date_to_mjd {
+    my ($date) = $_[0];
+    my ($year, $month, $day, $mjd);
+
+    ($year, $month, $day) = $date =~ /(\d+)\/(\d+)\/(\d+)/;
+
+    $mjd = get_mjd ($year, $month, $day);
+
+    return ($mjd);
+}
+
+sub mjd_to_date {
+    my ($mjd) = $_[0];
+    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday);
+    my ($date, $time);
+    
+    $time = 86400 * ($mjd - 40587.0);
+    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime ($time);  
+    $year += 1900;
+    $mon ++;
+
+    $date = sprintf "%04d/%02d/%02d,%02d:%02d:%04.1f", $year, $mon, $mday, $hour, $min, $sec;
+    
+    return $date;
+}
+
+sub sec_to_mjd {
+    my ($sec) = $_[0];
+    my ($mjd);
+    
+    $mjd = $sec / 86400 + 40587.0;
+    return $mjd;
+}
+
+# gmtime
+# ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time);  
+# ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = localtime(time);  
+# $time = time
+# 0 sec (unix) = 2440587.5 jd = 40587.0 mjd
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+
+    return ($jd);
+}
+
+sub usage {
+    
+    if (@ARGV == 1) {
+	print STDERR "create (runid) (start) (stop) (camera) - create / change a camera run\n";
+	print STDERR "delete (runid)                         - delete a camera run\n";
+	print STDERR "hstcreate                              - interactive camera run creation\n";
+	print STDERR "addqso (runid) (qsoid)                 - add a qso run to camera run\n";
+	print STDERR "delqso (qsoid)                         - delete a qso run\n";
+	print STDERR "comment (line)                         - add a comment line to run list\n";
+	print STDERR "status                                 - check current run list\n";
+	print STDERR "date (date)                            - return run info for given date\n";
+	print STDERR "run (runid)                            - return run info for given camera run\n";
+	print STDERR "\n";
+	print STDERR "sys                                    - display current system variables\n";
+	print STDERR "sys init                               - set defaults for system variables\n";
+	print STDERR "sys (key)                              - fetch value of system variable\n";
+	print STDERR "sys (key) (value)                      - set value of system variable\n";
+	print STDERR "\n";
+	&goodbye;
+    }
+    
+    if (@ARGV > 2) { print STDERR "USAGE: prepare.run (help) [mode]\n"; &goodbye; }
+    
+    &goodbye;
+}
+
+
+
+##############
+sub mk_events {
+    my ($runid, $start, $stop);
+    $runid = $_[0];
+    $start = $_[1];
+    $stop  = $_[2];
+    
+    $mjd_start = date_to_mjd ($start);
+    $mjd_stop  = date_to_mjd ($stop);
+
+    $Nday = $mjd_stop - $mjd_start + 1;
+
+    if (! -e $schedule) {
+	# create a new schedule with PREVIOUS set to NEVER
+	open (SCHED, ">$schedule");
+	print SCHED "# schedule for scheduler system\n";
+	print SCHED "# E. Magnier\n";
+	print SCHED "\n";
+	print SCHED "# last time scheduler was run:\n";
+	print SCHED "PREVIOUS NEVER\n";
+	print SCHED "\n";
+	close (SCHED);
+    }
+	
+    open (SCHED, ">>$schedule");
+    print "\n";
+    $date = `date "+%Y/%m/%d %k:%M:%S"`; chop ($date);
+    print SCHED "# added $date\n";
+    
+
+    ($year, $month, $day) = $start =~ /(\d+)\/(\d+)\/(\d+)/;
+    for ($Day = -1; $Day < $Nday + 7; $Day++) {
+
+	$tday = $day + $Day - 1;
+	$date = `date -d $year/$month/$tday +%Y/%m/%d`; chop ($date);
+
+	if ($Day == 0) {
+	    atcommand ("mkrun sys RUNID $runid",                   "$logdir/config.log",    "10:00", $date);
+	    atcommand ("checkconfig -ckdirs",                      "$logdir/config.log",    "10:00", $date);
+	    atcommand ("mkdetrend create $runid $start $stop",     "$logdir/mkdetrend.log", "10:00", $date);
+	    atcommand ("mkfringe config $runid",                   "$logdir/mkdetrend.log", "10:00", $date);
+	    atcommand ("mkfringe mkconfig",                        "$logdir/mkdetrend.log", "10:00", $date);
+	}
+	if ($Day == 4) {
+	    atcommand ("mkdetrend auto set update",                "$logdir/mkdetrend.log", "10:00", $date);
+	}
+	if ($Day == $Nday) {
+	    atcommand ("mkdetrend auto set hold",                  "$logdir/mkdetrend.log", "10:00", $date);
+	}
+    }
+    close (SCHED);
+
+}
+
+
+##############
+
+sub sched {
+    if (@ARGV != 2) {
+	print STDOUT "USAGE: mkrun sched (runid)\n";
+	exit 2;
+    }
+
+    $runid  = $ARGV[1];
+    &load_runlist;
+    
+    $line = grab_runline ($runid);
+    ($runid, $start, $stop, $camera, $qlist) = split (" ", $line, 4);
+
+    mk_events ($runid, $start, $stop);
+    
+    exit 0;
+}
+
+if ($ARGV[0] eq "sched")   { &sched  (@ARGV); }
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mkscat
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mkscat	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mkscat	(revision 16632)
@@ -0,0 +1,72 @@
+#!/usr/bin/env perl
+
+# warning: this function currently uses a fixed temporary name 'fix.NN.fits' 
+# for the intermediate product.  If we add this to elixir, convert to mktemp
+
+# need to assimilate the -c -C -D cmd line options -> env
+
+# check the usage
+if ($ARGV[0] eq "-h") { &usage (); }
+if ($ARGV[0] eq "-help") { &usage (); }
+if (@ARGV != 5) { &usage (); }
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`; chop ($confdir);
+$script  = "$confdir/mana/scatter.pro";
+
+# run mana script:
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+print MANA "mkscat $ARGV[0] $ARGV[1] $ARGV[2] $ARGV[3] $ARGV[4]\n";
+print MANA "exit 1\n";
+close (MANA);
+print STDERR "exit statue: $?\n";
+if ($? == 2 * 256) { 
+    print STDERR "no scattered light term available\n"; 
+    exit 2;
+}
+if ($?) { die "ERROR problem with mkscat\n"; }
+
+print STDOUT "SUCCESS: finished with mkscat\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub usage {
+    print "USAGE: mkscat (mosiac) (start) (stop) (filter) (ID)\n";
+    exit 1;
+}
+
+# mana within perl:  we embed the mana functions within a macro to trap the 
+# exit status.  If mana has an error with one of the steps, it will exit the macros and 
+# the second exit will be called. Otherwise, the "go" macro will perform the exit 0
+# and mana will exit with status 0
+
+# there are two possible flat-field photometric corrections: additive
+# and multiplicative:  
+# The correction images constructed by examining
+# the *difference* between dome-flats with and without the petals
+# covered is additive:  FLAT_new = (FLAT_old - SCAT) * A
+# (A is set to maintain the original normalization of chip 04)
+# 
+# The correction images constructed by examining stellar magnitude
+# difference is multiplicative: FLAT_new = (FLAT_old * SCAT) * A
+# (A is set to maintain the original normalization of chip 04)
+
+# there is a different scattered light image for each filter.
+# (these images are the same file for the additive version)
+
+# there should be no arbitrary normalization in the scattered frames
+# in the database. (we used to multiply the scattered light image by a
+# value of 10.0).  
+
+# images of the first class will be identified with the label scatter-A.0
+# images of the second class will be identified with the label scatter-B.0
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mktrans
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mktrans	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mktrans	(revision 16632)
@@ -0,0 +1,141 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { die "USAGE: mktrans (start) (stop)\n" ;}
+
+$start = $ARGV[0];
+$stop  = $ARGV[1];
+
+@photcodes = split (" ", `filtnames list`);
+
+foreach $code (@photcodes) {
+
+    print STDERR "filter: $code\n";
+    @list = `photsearch -trange $start $stop -photcode $code`;
+    if (! @list) { next; }
+
+    # the lines from photsearch look like this:
+    # filter date            zp      dzp   N T label (N - Nmeas, T - Ntime)
+    # V 2001/02/03,15:38:53  26.249  0.017 3 1 elixir
+
+    if (1) {
+
+	# first pass, get list of zp, sort, find median 
+	@zp = ();
+	$sumN = $sumM = $sum1 = $sum2 = $n = 0;
+	foreach $line (@list) {
+	    @words = split (" ", $line);
+	    push @zp, $words[2];
+	    $sumN ++;
+	    $sumM += $words[5];
+	}
+	@zp = sort {$a <=> $b} @zp;
+
+	$N = @zp;
+	for ($i = 0.2*$N; $i < 0.8*$N; $i++) {
+	    $sum1 += $zp[$i];
+	    $sum2 += $zp[$i]*$zp[$i];
+	    $n ++;
+	}
+	
+	$zp = $sum1 / $n;
+	$dzp = sqrt (abs($sum2 / $n - $zp*$zp));
+
+	printf STDOUT "photreg -trans -photcode $code -zp %6.3f -dzp %6.4f -trange $start $stop -Nmeas $sumM -Ntime $sumN\n", $zp, $dzp;
+
+    } else {
+	# use date hashes to extract stats for each date:
+	@dates = ();
+	foreach $line (@list) {
+	    
+	    # parse the line for the date
+	    @words = split (" ", $line);
+	    ($date) = $words[1] =~ /(\d\d\d\d\/\d\d\/\d\d),/;
+	    
+	    # if this is a new date, save it in the list
+	    unless ($sum1{$date}) { @dates = (@dates, $date); }
+
+	    # add to the stats 
+	    $sumN{$date} ++;
+	    $sumM{$date} += $words[5];
+	    $sum1{$date} += $words[2];
+	    $sum2{$date} += $words[2]*$words[2];
+	}
+
+	@sdates = sort by_date @dates;
+
+	# calculate mean and stdev for each date
+	foreach $date (@sdates) {
+	    
+	    $Nm  = $sumM{$date};
+	    $Np  = $sumN{$date};
+	    $zp  = $sum1{$date} / $Np;
+	    $dzp = sqrt (abs($sum2{$date} / $Np - $zp*$zp));
+
+	    printf STDOUT "photreg -trans -photcode $code -zp %6.3f -dzp %6.4f -trange $start $stop -Nmeas $Nm -Ntime $Np\n", $zp, $dzp;
+	}
+
+	%sumM = ();
+	%sumN = ();
+	%sum1 = ();
+	%sum2 = ();
+	print STDOUT "\n";
+    }
+    
+}
+
+exit 0;
+
+sub by_date {
+    
+    ($year, $month, $day) = $a =~ /(\d\d\d\d).(\d\d).(\d\d)/;
+    $va = get_jd ($year, $month, $day);
+    ($year, $month, $day) = $b =~ /(\d\d\d\d).(\d\d).(\d\d)/;
+    $vb = get_jd ($year, $month, $day);
+    $va <=> $vb;
+}
+    
+
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+
+sub get_jd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5;
+    
+
+    return ($jd);
+
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mktreport
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mktreport	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mktreport	(revision 16632)
@@ -0,0 +1,135 @@
+#!/usr/bin/env perl
+
+if (@ARGV != 2) { die "USAGE: mktreport (start) (stop)\n" ;}
+
+$start = $ARGV[0];
+$stop  = $ARGV[1];
+
+@photcodes = split (" ", `filtnames list`);
+
+@list = `photsearch -trans -offset`;
+
+# the lines from transearch look like this:
+# R 2001/04/15,00:00:00  -0.032 26.259  0.004  0.040 -0.090 B_L92 V_L92 5 15 elixir
+#      (date)             (ZP)  (ZPo)   (sigma)
+
+@dates = ();
+
+# get the complete list of unique dates:
+
+LIST:
+foreach $line (@list) {
+	
+    # parse the line for the date
+    @words = split (" ", $line);
+    ($date) = $words[1] =~ /(\d\d\d\d\/\d\d\/\d\d),/;
+    
+    unless ($found{$date}) { @dates = (@dates, $date); $found{$date} = 1; }
+
+    for ($i = 0; $i < @photcodes; $i++) {
+	
+	if ($words[0] ne $photcodes[$i]) { next; }
+
+	$name1 = "ZPo$i";
+	$name2 = "dZP$i";
+	$$name1{$date} = $words[2] - $words[3];
+	$$name2{$date} = $words[4];
+	next LIST;
+    }
+
+    print STDERR "$words[0] not found in photcode list\n";
+}
+
+@sdates = sort by_date @dates;
+
+print STDOUT "           ";
+for ($i = 0; $i < @photcodes; $i++) {
+    printf STDOUT "%6s ", $photcodes[$i];
+}
+print STDOUT "  ";
+for ($i = 0; $i < @photcodes; $i++) {
+    printf STDOUT "%6s ", "d$photcodes[$i]";
+}
+print STDOUT "\n";
+
+foreach $date (@sdates) {
+    
+    print STDOUT "$date ";
+    
+    for ($i = 0; $i < @photcodes; $i++) {
+	$name = "ZPo$i";
+	if ($$name{$date}) {
+	    printf STDOUT "%6.3f ", $$name{$date};
+	} else {
+	    print STDOUT "     - ";
+	}
+    }
+    print STDOUT "  ";
+    for ($i = 0; $i < @photcodes; $i++) {
+	$name = "dZP$i";
+	if ($$name{$date}) {
+	    printf STDOUT "%6.3f ", $$name{$date};
+	} else {
+	    print STDOUT "     - ";
+	}
+    }
+	
+    print STDOUT "\n";
+}
+
+exit 0;
+
+sub by_date {
+    
+    ($year, $month, $day) = $a =~ /(\d\d\d\d).(\d\d).(\d\d)/;
+    $va = get_jd ($year, $month, $day);
+    ($year, $month, $day) = $b =~ /(\d\d\d\d).(\d\d).(\d\d)/;
+    $vb = get_jd ($year, $month, $day);
+    $va <=> $vb;
+}
+    
+
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+
+sub get_jd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5;
+    
+
+    return ($jd);
+
+}
+
+sub get_mjd {
+
+    my($year) = $_[0];
+    my($month) = $_[1];
+    my($day) = $_[2];
+
+    my($jd) = $day - 32075 + int (1461*($year + 4800 + int (($month - 14)/12))/4)
+	+ int(367*($month - 2 - int(($month - 14)/12)*12)/12)
+	    - int(3*int(($year + 4900 + int(($month - 14)/12))/100)/4) - 0.5 - 2400000.5;
+    
+
+    return ($jd);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mosaic.merge
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mosaic.merge	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mosaic.merge	(revision 16632)
@@ -0,0 +1,110 @@
+#!/usr/bin/env perl
+# this program takes a file template, with CCDNUM substituted for the 
+# CCD number.  each file contains the ccd frames as separate extents.  The program
+# loads the names, then for each frame, it goes through the CCDNUM entries
+# and mosaics together the appropriate image, writing them to an output filename 
+# formed from ARGV[1] (ARGV[1].n.jpg).  These names are written to ARGV[1]
+#
+# this program returns immediately if all CCDNUM entries are not found.
+# the previous function, detstats, must not create the *.stats file until the 
+# process is done.  similarly, this program deletes the *.stats files to avoid 
+# confusion on a second pass
+
+@ccds = split (" ", `cameraconfig -ccdn`);
+if ($?) { die "ERROR: configuration problem\n"; }
+
+if (@ARGV != 3) { die "ERROR: USAGE: mosaic.tenbin (name) (out) (type)\n" }
+$type = "\U$ARGV[2]\E";
+
+# find the appropriate script file
+$confdir = `gconfig -q CONFDIR`;  chop $confdir;
+$script = "$confdir/mana/flips.pro";
+
+# test named Xserver, or start vnc on specified machine
+$xhost = `gconfig -q XHOST`; chop $xhost;
+$xdisp = `gconfig -q XDISP`; chop $xdisp;
+if (vsystem ("xdpyinfo -display $xdisp")) {
+    print STDERR "ERROR: X server is not running. start it now on $xhost\n";
+    exit 1;
+}
+$ENV{'DISPLAY'} = $xdisp;
+
+# check for the existence of each input file, exit if non-existent
+foreach $ccd (@ccds) {
+    $name = $ARGV[0];
+    $name =~ s/CCDNUM/$ccd/;
+    unless (-r $name) {
+	print STDERR "ERROR: can't find all files\n";
+	exit 1;
+    }
+}
+
+# we are constructing the names of the input files.  there are NCCD
+# files with names of the form path/01Ak01.flat.I.CCDNUM.0.medbin we
+# need to loop over all NEXTEND entries in these files, creating
+# NEXTEND output images.  First check that each file has the same NEXTEND
+
+@filenames = ();
+foreach $ccd (@ccds) {
+    $name = $ARGV[0];
+    $name =~ s/CCDNUM/$ccd/;
+    push @filenames, $name;
+
+    ($junk, $N) = split (" ", `echo $name | fields NEXTEND`);
+    if ($ccd eq $ccds[0]) {
+	$Nline = $N;
+    } 
+    if ($N != $Nline) { die "ERROR: mis-matched number of images in $name\n"; }
+}    
+
+open (MANA, "|mana --norc");
+print MANA "input $script\n";
+
+# define list of names as mana list
+print MANA "list names\n";
+foreach $name (@filenames) {
+    print MANA "$name\n";
+}
+print MANA "end\n";
+
+# define macro for 1 image
+print MANA "macro mkimage\n";
+print MANA " mergemosaic \$1\n";
+if ($type eq "RAW")  { print MANA " jpgraw \$2\n";    } 
+if ($type eq "FLAT") { print MANA " jpgnorm \$2\n";   } 
+if ($type eq "BIAS") { print MANA " jpgmosaic \$2\n"; }
+if ($type eq "DARK") { print MANA " jpgmosaic \$2\n"; }
+print MANA "end\n";
+
+# define macro for image list 
+print MANA "macro go\n";
+open (LIST, ">$ARGV[1]");
+for ($i = 0; $i < $Nline; $i++) {
+    $outfile = sprintf "%s.%03d.jpg", $ARGV[1], $i;
+    print MANA " mkimage $i $outfile\n";
+    print LIST "$outfile\n";
+}
+close (LIST);
+print MANA " exit 0\n";
+print MANA "end\n";
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+if ($?) {
+    print STDERR "ERROR running mana\n";
+    exit 1;
+}
+
+print STDOUT "SUCCESS\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/mosaic.stats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/mosaic.stats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/mosaic.stats	(revision 16632)
@@ -0,0 +1,156 @@
+#!/usr/bin/env perl
+# this program takes a list template, with CCDNUM substituted for the 
+# CCD number.  each file contains a list of statistics for each image.  The program
+# loads the names, then for each frame, it goes through the CCDNUM entries
+# and loads the appropriate statistics, writing them to the output file
+#
+# this program returns immediately if all CCDNUM entries are not found.
+# the previous function, detstats, must not create the *.stats file until the 
+# process is done.  similarly, this program deletes the *.stats files to avoid 
+# confusion on a second pass
+
+@ccdn = split (" ", `cameraconfig -ccdn`);
+@ccds = split (" ", `cameraconfig -ccds`);
+if ($?) { die "ERROR: configuration problem\n"; }
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+if (@ARGV != 3) { die "ERROR: USAGE: mosaic.stats (name) (out) (type)\n" }
+
+$type = "\U$ARGV[2]\E";
+
+# load option list of ccds to skip (specific to run/camera)
+$CHIPSKIP     = `gconfig CHIP_SKIP_LIST`; chop $CHIPSKIP;
+@chipskip = ();
+if (-e $CHIPSKIP) { 
+    open (FILE, $CHIPSKIP);
+    @chipskip = <FILE>;
+    close (FILE);
+    foreach $chip (@chipskip) { chop $chip; }
+}
+
+# modify the list of ccds to exclude chipskip entries
+$N = @ccds;
+CCD: for ($i = 0; $i < $N; $i++) {
+    $ccds = shift @ccds;
+    $ccdn = shift @ccdn;
+
+    foreach $skip (@chipskip) { if ($skip eq $ccds) { next CCD; } }
+    push @ccds, $ccds;
+    push @ccdn, $ccdn;
+}
+
+# check for the existence of each input file, exit if non-existent
+foreach $ccd (@ccdn) {
+    $name = $ARGV[0];
+    $name =~ s/CCDNUM/$ccd/;
+    unless (-r $name) {
+	print STDERR "ERROR: can't find $name\n";
+	exit (0);
+    }
+}
+
+# load in stats from files (Nlist*Nccd entries)
+# each file contains stats for a single ccd, for all N files
+foreach $ccd (@ccdn) {
+    $name = $ARGV[0];
+    $name =~ s/CCDNUM/$ccd/;
+
+    open (FILE, $name);
+    @$ccd = <FILE>;
+    close (FILE);
+
+    if ($ccd eq $ccdn[0]) { $Nline = @$ccd; }
+    if (@$ccd != $Nline) { die "ERROR mis-matched file lengths\n"; }
+}    
+
+$dawn = 0;
+$dusk = 1;
+@pdate = ();
+@ptwil = ();
+$Nperiod = 0;
+@period = ();
+
+open (OUTPUT, ">$ARGV[1]");
+for ($i = 0; $i < $Nline; $i++) {
+
+    $mean  = 0;
+    $medn  = 0;
+    $sig12 = 0;
+    $sig22 = 0;
+    $mean2 = 0;
+    $mbin  = 0;
+    $sbin2 = 0;
+    $mbin2 = 0;
+
+    foreach $ccd (@ccdn) {
+	$line = $$ccd[$i];
+	chop ($line);
+	@words = split (" ", $line);
+	$file = $words[0];
+	$date = $words[1];
+	$time = $words[2];
+	$stat = $words[9];
+	$mean  += $words[3];
+	$medn  += $words[4];
+	$sig12 += $words[5]*$words[5];
+	$sig22 += $words[6]*$words[6];
+	$mean2 += $words[3]*$words[3];
+
+	$mbin  += $words[7];
+	$sbin2 += $words[8]*$words[8];
+	$mbin2 += $words[7]*$words[7];
+    }
+    $N = @ccdn;
+
+    # identify even or morn twilight
+    @words = split (':', $time);
+    if (($words[0] > 12) && ($words[0] < 24)) {
+	$twilite = $dawn;
+    } else {
+	$twilite = $dusk;
+    }
+    $ThisPeriod = -1;
+    for ($j = 0; $j < $Nperiod; $j++) {
+	if (($pdate[$j] eq $date) && ($ptwil[$j] == $twilite)) {
+	    $ThisPeriod = $j;
+	    last;
+	}
+    }
+    if ($ThisPeriod == -1) {
+	$ThisPeriod = $Nperiod;
+	@pdate = (@pdate, $date);
+	@ptwil = (@ptwil, $twilite);
+	$Nperiod ++;
+    }
+    @period = (@period, $ThisPeriod);
+
+    # determine global statistics
+    $Mean  = $mean / $N;
+    $Medn  = $medn / $N;
+    $Mbin  = $mbin / $N;
+
+    if ($type eq "FLAT") {
+      $Sig1  = sqrt ($sig12 / $N + $mean2 / $N - $Mean*$Mean) / abs ($Mean);
+      $Sig2  = sqrt ($sig22 / $N + $mean2 / $N - $Mean*$Mean) / abs ($Mean);
+      $Sbin  = sqrt ($sbin2 / $N + $mbin2 / $N - $Mbin*$Mbin) / abs ($Mbin);
+    } else {
+      $Sig1  = sqrt ($sig12 / $N + $mean2 / $N - $Mean*$Mean);
+      $Sig2  = sqrt ($sig22 / $N + $mean2 / $N - $Mean*$Mean);
+      $Sbin  = sqrt ($sbin2 / $N + $mbin2 / $N - $Mbin*$Mbin);
+    }      
+
+    printf OUTPUT "%6s %10s %11s %7.1f %7.1f %6.4f %6.4f %7.1f %6.4f %d %s %d %d\n", 
+    $file, $date, $time, $Mean, $Medn, $Sig1, $Sig2, $Mbin, $Sbin, $period[$i], $pdate[$period[$i]], $ptwil[$period[$i]], $stat;
+
+}    
+close (OUTPUT);
+print STDERR "SUCCESS\n";
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/normalize
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/normalize	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/normalize	(revision 16632)
@@ -0,0 +1,306 @@
+#!/usr/bin/env perl
+
+$revline = "\$Revision: 1.6 $?";
+($version) = $revline =~ m|\$Revision:\s*(\S*)|;
+
+# default variable values
+$start     = 0;
+$stop      = 0;
+$oldflips  = 0;
+$addtime   = 0;
+$addconfig = 0;
+
+# grab the command line options
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-oldflips") {
+        $oldflips = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-time") {
+	$addtime = 1;
+	$start = $ARGV[1];
+	$stop = $ARGV[2];
+	shift; shift; shift; next;
+    }
+    if ($ARGV[0] eq "-config") {
+	$addconfig = 1;
+	$elconf = $ARGV[1];
+	shift; shift; next;
+    }
+    if ($ARGV[0] eq "-h") { &usage; }
+    if ($ARGV[0] eq "--help") { &usage; }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 4) { &usage; }
+if ($addtime && ("$start" == "")) { &usage; }
+if ($addtime && ("$stop" == ""))  { &usage; }
+
+# command line arguments
+$input  = $ARGV[0];
+$output = $ARGV[1];
+$ref    = $ARGV[2];
+$type   = uppercase ($ARGV[3]);
+
+$ccdword = `gconfig -q CCDNUM-KEYWORD`; chop ($ccdword);
+$typeword = `gconfig -q IMAGETYPE-KEYWORD`; chop ($typeword);
+$dbmode = `gconfig -q DETREND-DB-MODE`; chop ($dbmode);
+
+# choose appropriate type
+if ($type eq "FLAT") { &mk_flat; }
+if ($type eq "DARK") { &mk_dark; }
+if ($type eq "BIAS") { &mk_dark; }
+print STDERR "unknown type $type";
+exit 1;
+
+sub mk_dark { 
+# create mana macro, run (allows exit status to be checked)
+    open (MANA, "|mana --norc");
+    print MANA "macro go\n";
+    print MANA "echo 'starting normalize'\n";
+    print MANA "rd a $input\n";
+    print MANA "keyword a $typeword -w $type\n";
+    
+    if ($addtime == 1) {
+	print MANA "keyword a TVSTART -w $start\n";
+	print MANA "keyword a TVSTART -wc \"data validity start time\"\n";
+	print MANA "keyword a TVSTOP  -w $stop\n";
+	print MANA "keyword a TVSTOP -wc \"data validity start time\"\n";
+    }
+    if ($addconfig == 1) {
+	print MANA "keyword a ELCONF -w $elconf\n";
+	print MANA "keyword a ELCONF -wc \"Original Elixir config\"\n";
+    }	
+    
+    $elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+    @time = localtime;
+    $now = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1], $time[0];
+    $elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+    print MANA "keyword a EL_SYS -w    \"$elsys\"\n";
+    print MANA "keyword a EL_SYS -wc   \"Elixir System Version\"\n";
+    print MANA "keyword a EL_NRM -w    \"$version\"\n";
+    print MANA "keyword a EL_NRM -wc   \"Elixir Normalize Version\"\n";
+    print MANA "keyword a REL_DATE -w  \"$now\"\n";
+    print MANA "keyword a REL_DATE -wc \"UTC Release Date\"\n";
+
+    print MANA "keyword a COMMENT -ws \"Elixir:normalize $version\"\n";
+    print MANA "keyword a COMMENT -ws \"no renormalization needed for $type\"\n";
+    print MANA "wd a $output -bitpix 16 -bzero 32668.0 -bscale 1.0\n";
+    print MANA "echo normlized done ($input to $output)\n";
+    print MANA "exit 0\n";
+    print MANA "end\n";  # end of macro 'go'
+
+    print MANA "go\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) {
+	print STDERR "ERROR problem running mana in normalize (bias, dark)\n";
+	exit 1;
+    }
+    print STDOUT "SUCCESS: finished with normalize\n";
+    exit 0;
+}
+   
+sub mk_flat {
+    # check on reference existence (not needed for BIAS, DARK)
+    if (! -f $ref) {
+	print STDERR "ERROR: ref file $args[3] is missing\n";
+	exit 1;
+    }
+    $chipref = `gconfig FLIPS_REF_CCD`; chop ($chipref);
+    $baseref = $chipref;
+    print STDERR "Normalizing reference: using file $ref\n";
+
+    # Check that FLIPS_REF_CCD is not in CHIPSKIP, otherwise find another CCD
+    $Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+    @ccdn = split (" ", `cameraconfig -ccdn`);
+    $CHIPSKIP = `gconfig CHIP_SKIP_LIST`; chop $CHIPSKIP;
+    @chipskip = ();
+    if (-e $CHIPSKIP) {
+
+       open (FILE, $CHIPSKIP);
+       @chipskip = <FILE>;
+       close (FILE);
+       foreach $chip (@chipskip) { chop $chip; }
+
+       foreach $chip (@chipskip) {
+          $chip =~ s/ccd//;
+	  if ($chip eq $chipref) {
+             print STDERR "Warning: found reference chip in skip list ($chipref)\n";
+	     
+	     # Find a new reference: increment by one
+             for ($i = 0; $i < $Nccd; $i++) {
+                $ccdindex = $ccdn[$i];
+	        if ( $ccdindex eq $chipref ) {
+                   $newref = $ccdn[$i + 1];
+                }
+	     }
+	     $chipref = $newref
+	  }
+       }
+       # Substitute the CCD reference number in the name of the ref FITS file
+       $ref =~ s/.$baseref./.$chipref./;
+       print STDERR "New SkipChip selection: using ref file $ref\n";
+    }
+    
+    # we need keywords defined by the process (flips) which creates the master frame
+    if ($oldflips) {
+        # these lines were used before flips was upgraded to add the DATAMODE keywords
+	$answer = `fhead $ref | grep "Output file mode"`;
+	@words = split (" ", $answer);
+	$refmode = $words[-1];
+
+	$answer = `fhead $input | grep "Output file mode"`;
+	@words = split (" ", $answer);
+	$mode = $words[-1];
+    } else {
+	# various options for datamode, refmode:
+	
+	# check for readout mode
+	($junk, $amplist)    = split (" ", `echo $input | fields AMPLIST`, 2);
+	if ($? == 0) {
+	    # multiamp mode, expect IMMODE$amp, create FLATSCL$amp
+	    @amps = split (" ", $amplist);
+	    foreach $amp (@amps) {
+		($junk, $mode)    = split (" ", `echo $input | fields IMMODE$amp`);
+		if ($?) { die "ERROR: missing IMMODE$amp\n"; }
+		@ampmode = (@ampmode, $mode);
+	    }
+	}
+	# try new IMMODE keyword:
+	$modeword = "IMMODE";
+	($junk, $mode)    = split (" ", `echo $input | fields $modeword`);
+	if ($?) {
+	    if (@amps) { die "ERROR: multiamp mode missing IMMODE\n"; }
+	    $modeword = "DATAMODE";
+	    ($junk, $mode)    = split (" ", `echo $input | fields $modeword`);
+	    if ($?) { die "ERROR: missing DATAMODE & IMMODE\n"; }
+	}
+	($junk, $refmode) = split (" ", `echo $ref   | fields $modeword`);
+	if ($?) { die "ERROR: ref file missing $modeword\n"; }
+    }
+    ($junk, $refccd) = split (" ", `echo $ref | fields $ccdword`);
+    if ($?) { die "ERROR: ref file missing $ccdword in ref\n"; }
+    
+    # grab mask file
+    $mask = `detsearch -quiet -image $input 0 split -type mask`; chop ($mask);
+    if ($? || ($mask eq "")) { 
+	print STDERR "can't find mask for this image, no mask applied\n";
+	$mask = "none"; 
+    }
+
+    # run MANA
+    open (MANA, "|mana --norc");
+    print MANA "macro go\n";
+    print MANA "echo 'starting normalize'\n";
+    print MANA "rd a $input\n";
+    print MANA "\$CCDKEYWORD = $ccdword\n";
+    print MANA "keyword a $ccdword ccd\n";
+    if ($mask eq "none") {
+	print MANA "set b = a / $refmode\n";
+    } else {
+	if ($dbmode eq "MEF") {
+	    print MANA "rd c $mask -n \$ccd\n";
+	} else {
+	    print MANA "rd c $mask\n";
+	}
+	print MANA "set b = (a / $refmode) * c\n";
+    }
+
+    $scale = $refmode / $mode;
+    $newmode = $mode / $refmode;
+    print MANA "keyword b $modeword -wf $newmode\n";
+    print MANA "keyword b FLATSCAL -wf $scale\n";
+
+    if (@amps) {
+	for ($i = 0; $i < @amps; $i++) {
+	    $amp = $amps[$i];
+	    $scale   = $refmode / $ampmode[$i];
+	    $newmode = $ampmode[$i] / $refmode;
+	    print MANA "keyword b IMMODE$amp -wf $newmode\n";
+	    print MANA "keyword b FLATSCL$amp -wf $scale\n";
+	}
+    }
+    print MANA "keyword b $typeword -w $type\n";
+    if ($addtime == 1) {
+	print MANA " keyword b TVSTART -w $start\n";
+	print MANA " keyword b TVSTART -wc \"data validity start time\"\n";
+	print MANA " keyword b TVSTOP  -w $stop\n";
+	print MANA " keyword b TVSTOP -wc \"data validity start time\"\n";
+    }
+    if ($addconfig == 1) {
+	print MANA "keyword b ELCONF -w $elconf\n";
+	print MANA "keyword b ELCONF -wc \"Original Elixir config\"\n";
+    }	
+
+    @time = localtime;
+    $now = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1], $time[0];
+    $elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+    print MANA "keyword b EL_SYS   -w  \"$elsys\"\n";
+    print MANA "keyword b EL_SYS   -wc \"Elixir System Version\"\n";
+    print MANA "keyword b EL_NRM   -w  \"$version\"\n";
+    print MANA "keyword b EL_NRM   -wc \"Elixir Normalize Version\"\n";
+    print MANA "keyword b REL_DATE -w \"$now\"\n";
+    print MANA "keyword b REL_DATE -wc \"UTC Release Date\"\n";
+
+    print MANA "keyword b COMMENT  -ws \"Elixir:normalize version $version\"\n";
+    print MANA "keyword b COMMENT  -ws \"FLAT image normalized wrt CCD $refccd\"\n";
+    print MANA "clip b 0.0 0.0 6.4 0.0\n";
+    print MANA "wd b $output -bitpix 16 -bzero 3.2 -bscale 0.0001\n";
+    print MANA "echo normlized done ($input to $output)\n";
+    print MANA "exit 0\n";
+    print MANA "end\n";  # end of macro 'go'
+
+    print MANA "go\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) {
+	print STDERR "ERROR problem running mana in normalize (flat)\n";
+	exit 1;
+    }
+    print STDOUT "SUCCESS: finished with normalize\n";
+    exit 0;
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub uppercase {
+    return "\U$_[0]\E";
+}
+
+# given a filename, check that its path exists, create it if not
+sub ckpathname {
+    my ($file) = $_[0];
+    my (@words, $dir);
+
+    @words = split ("/", $file);
+    pop (@words);
+    $dir = join ("/", @words);
+
+    if ($dir eq "") { $dir = "."; }
+
+    if (! -d $dir) {
+	system ("mkdir -p $dir");
+	if ($?) {
+	    print STDERR "ERROR: can't make directory component for $file\n";
+	    exit 1;
+	}
+    }
+}
+
+sub usage {
+    print STDERR "normalize (input) (output) (ref) (type) [-time start stop] [-oldflips]\n";
+    exit 2;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/normalize.pre12KfiltersHandling
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/normalize.pre12KfiltersHandling	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/normalize.pre12KfiltersHandling	(revision 16632)
@@ -0,0 +1,271 @@
+#!/usr/bin/env perl
+
+$revline = "\$Revision: 1.1 $?";
+($version) = $revline =~ m|\$Revision:\s*(\S*)|;
+
+# default variable values
+$start     = 0;
+$stop      = 0;
+$oldflips  = 0;
+$addtime   = 0;
+$addconfig = 0;
+
+# grab the command line options
+@tARGV = ();
+for (; @ARGV > 0; ) {
+    if ($ARGV[0] eq "-oldflips") {
+        $oldflips = 1;
+        shift; next;
+    }
+    if ($ARGV[0] eq "-time") {
+	$addtime = 1;
+	$start = $ARGV[1];
+	$stop = $ARGV[2];
+	shift; shift; shift; next;
+    }
+    if ($ARGV[0] eq "-config") {
+	$addconfig = 1;
+	$elconf = $ARGV[1];
+	shift; shift; next;
+    }
+    if ($ARGV[0] eq "-h") { &usage; }
+    if ($ARGV[0] eq "--help") { &usage; }
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 4) { &usage; }
+if ($addtime && ("$start" == "")) { &usage; }
+if ($addtime && ("$stop" == ""))  { &usage; }
+
+# command line arguments
+$input  = $ARGV[0];
+$output = $ARGV[1];
+$ref    = $ARGV[2];
+$type   = uppercase ($ARGV[3]);
+
+$ccdword = `gconfig -q CCDNUM-KEYWORD`; chop ($ccdword);
+$typeword = `gconfig -q IMAGETYPE-KEYWORD`; chop ($typeword);
+$dbmode = `gconfig -q DETREND-DB-MODE`; chop ($dbmode);
+
+# choose appropriate type
+if ($type eq "FLAT") { &mk_flat; }
+if ($type eq "DARK") { &mk_dark; }
+if ($type eq "BIAS") { &mk_dark; }
+print STDERR "unknown type $type";
+exit 1;
+
+sub mk_dark { 
+# create mana macro, run (allows exit status to be checked)
+    open (MANA, "|mana --norc");
+    print MANA "macro go\n";
+    print MANA "echo 'starting normalize'\n";
+    print MANA "rd a $input\n";
+    print MANA "keyword a $typeword -w $type\n";
+    
+    if ($addtime == 1) {
+	print MANA "keyword a TVSTART -w $start\n";
+	print MANA "keyword a TVSTART -wc \"data validity start time\"\n";
+	print MANA "keyword a TVSTOP  -w $stop\n";
+	print MANA "keyword a TVSTOP -wc \"data validity start time\"\n";
+    }
+    if ($addconfig == 1) {
+	print MANA "keyword a ELCONF -w $elconf\n";
+	print MANA "keyword a ELCONF -wc \"Original Elixir config\"\n";
+    }	
+    
+    $elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+    @time = localtime;
+    $now = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1], $time[0];
+    $elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+    print MANA "keyword a EL_SYS -w    \"$elsys\"\n";
+    print MANA "keyword a EL_SYS -wc   \"Elixir System Version\"\n";
+    print MANA "keyword a EL_NRM -w    \"$version\"\n";
+    print MANA "keyword a EL_NRM -wc   \"Elixir Normalize Version\"\n";
+    print MANA "keyword a REL_DATE -w  \"$now\"\n";
+    print MANA "keyword a REL_DATE -wc \"UTC Release Date\"\n";
+
+    print MANA "keyword a COMMENT -ws \"Elixir:normalize $version\"\n";
+    print MANA "keyword a COMMENT -ws \"no renormalization needed for $type\"\n";
+    print MANA "wd a $output -bitpix 16 -bzero 32668.0 -bscale 1.0\n";
+    print MANA "echo normlized done ($input to $output)\n";
+    print MANA "exit 0\n";
+    print MANA "end\n";  # end of macro 'go'
+
+    print MANA "go\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) {
+	print STDERR "ERROR problem running mana in normalize (bias, dark)\n";
+	exit 1;
+    }
+    print STDOUT "SUCCESS: finished with normalize\n";
+    exit 0;
+}
+   
+sub mk_flat {
+    # check on reference existence (not needed for BIAS, DARK)
+    if (! -f $ref) {
+	print STDERR "ERROR: ref file $args[3] is missing\n";
+	exit 1;
+    }
+    
+    # we need keywords defined by the process (flips) which creates the master frame
+    if ($oldflips) {
+        # these lines were used before flips was upgraded to add the DATAMODE keywords
+	$answer = `fhead $ref | grep "Output file mode"`;
+	@words = split (" ", $answer);
+	$refmode = $words[-1];
+
+	$answer = `fhead $input | grep "Output file mode"`;
+	@words = split (" ", $answer);
+	$mode = $words[-1];
+    } else {
+	# various options for datamode, refmode:
+	
+	# check for readout mode
+	($junk, $amplist)    = split (" ", `echo $input | fields AMPLIST`, 2);
+	if ($? == 0) {
+	    # multiamp mode, expect IMMODE$amp, create FLATSCL$amp
+	    @amps = split (" ", $amplist);
+	    foreach $amp (@amps) {
+		($junk, $mode)    = split (" ", `echo $input | fields IMMODE$amp`);
+		if ($?) { die "ERROR: missing IMMODE$amp\n"; }
+		@ampmode = (@ampmode, $mode);
+	    }
+	}
+	# try new IMMODE keyword:
+	$modeword = "IMMODE";
+	($junk, $mode)    = split (" ", `echo $input | fields $modeword`);
+	if ($?) {
+	    if (@amps) { die "ERROR: multiamp mode missing IMMODE\n"; }
+	    $modeword = "DATAMODE";
+	    ($junk, $mode)    = split (" ", `echo $input | fields $modeword`);
+	    if ($?) { die "ERROR: missing DATAMODE & IMMODE\n"; }
+	}
+	($junk, $refmode) = split (" ", `echo $ref   | fields $modeword`);
+	if ($?) { die "ERROR: ref file missing $modeword\n"; }
+    }
+    ($junk, $refccd) = split (" ", `echo $ref | fields $ccdword`);
+    if ($?) { die "ERROR: ref file missing $ccdword in ref\n"; }
+    
+    # grab mask file
+    $mask = `detsearch -quiet -image $input 0 split -type mask`; chop ($mask);
+    if ($? || ($mask eq "")) { 
+	print STDERR "can't find mask for this image, no mask applied\n";
+	$mask = "none"; 
+    }
+
+    # run MANA
+    open (MANA, "|mana --norc");
+    print MANA "macro go\n";
+    print MANA "echo 'starting normalize'\n";
+    print MANA "rd a $input\n";
+    print MANA "\$CCDKEYWORD = $ccdword\n";
+    print MANA "keyword a $ccdword ccd\n";
+    if ($mask eq "none") {
+	print MANA "set b = a / $refmode\n";
+    } else {
+	if ($dbmode eq "MEF") {
+	    print MANA "rd c $mask -n \$ccd\n";
+	} else {
+	    print MANA "rd c $mask\n";
+	}
+	print MANA "set b = (a / $refmode) * c\n";
+    }
+
+    $scale = $refmode / $mode;
+    $newmode = $mode / $refmode;
+    print MANA "keyword b $modeword -wf $newmode\n";
+    print MANA "keyword b FLATSCAL -wf $scale\n";
+
+    if (@amps) {
+	for ($i = 0; $i < @amps; $i++) {
+	    $amp = $amps[$i];
+	    $scale   = $refmode / $ampmode[$i];
+	    $newmode = $ampmode[$i] / $refmode;
+	    print MANA "keyword b IMMODE$amp -wf $newmode\n";
+	    print MANA "keyword b FLATSCL$amp -wf $scale\n";
+	}
+    }
+    print MANA "keyword b $typeword -w $type\n";
+    if ($addtime == 1) {
+	print MANA " keyword b TVSTART -w $start\n";
+	print MANA " keyword b TVSTART -wc \"data validity start time\"\n";
+	print MANA " keyword b TVSTOP  -w $stop\n";
+	print MANA " keyword b TVSTOP -wc \"data validity start time\"\n";
+    }
+    if ($addconfig == 1) {
+	print MANA "keyword b ELCONF -w $elconf\n";
+	print MANA "keyword b ELCONF -wc \"Original Elixir config\"\n";
+    }	
+
+    @time = localtime;
+    $now = sprintf "%04d-%02d-%02dT%02d:%02d:%02d", $time[5]+1900, $time[4]+1, $time[3], $time[2], $time[1], $time[0];
+    $elsys = `gconfig ELIXIR_VERSION`; chop ($elsys);
+    print MANA "keyword b EL_SYS   -w  \"$elsys\"\n";
+    print MANA "keyword b EL_SYS   -wc \"Elixir System Version\"\n";
+    print MANA "keyword b EL_NRM   -w  \"$version\"\n";
+    print MANA "keyword b EL_NRM   -wc \"Elixir Normalize Version\"\n";
+    print MANA "keyword b REL_DATE -w \"$now\"\n";
+    print MANA "keyword b REL_DATE -wc \"UTC Release Date\"\n";
+
+    print MANA "keyword b COMMENT  -ws \"Elixir:normalize version $version\"\n";
+    print MANA "keyword b COMMENT  -ws \"FLAT image normalized wrt CCD $refccd\"\n";
+    print MANA "clip b 0.0 0.0 6.4 0.0\n";
+    print MANA "wd b $output -bitpix 16 -bzero 3.2 -bscale 0.0001\n";
+    print MANA "echo normlized done ($input to $output)\n";
+    print MANA "exit 0\n";
+    print MANA "end\n";  # end of macro 'go'
+
+    print MANA "go\n";
+    print MANA "exit 1\n";
+    close (MANA);
+    if ($?) {
+	print STDERR "ERROR problem running mana in normalize (flat)\n";
+	exit 1;
+    }
+    print STDOUT "SUCCESS: finished with normalize\n";
+    exit 0;
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub uppercase {
+    return "\U$_[0]\E";
+}
+
+# given a filename, check that its path exists, create it if not
+sub ckpathname {
+    my ($file) = $_[0];
+    my (@words, $dir);
+
+    @words = split ("/", $file);
+    pop (@words);
+    $dir = join ("/", @words);
+
+    if ($dir eq "") { $dir = "."; }
+
+    if (! -d $dir) {
+	system ("mkdir -p $dir");
+	if ($?) {
+	    print STDERR "ERROR: can't make directory component for $file\n";
+	    exit 1;
+	}
+    }
+}
+
+sub usage {
+    print STDERR "normalize (input) (output) (ref) (type) [-time start stop] [-oldflips]\n";
+    exit 2;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/rerun.complete
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/rerun.complete	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/rerun.complete	(revision 16632)
@@ -0,0 +1,31 @@
+#!/usr/bin/env perl
+
+$fifo = `gconfig FIFOS`; chop $fifo;
+$failure = "$fifo/complete.failure"; 
+
+$Nflatten = `grep flatten $failure | wc -l`; chop $Nflatten;
+$Ngophot  = `grep gophot  $failure | wc -l`; chop $Ngophot;
+$Nimclean = `grep imclean $failure | wc -l`; chop $Nimclean;
+$Ngastro  = `grep gastro  $failure | wc -l`; chop $Ngastro;
+$Naddstar = `grep addstar $failure | wc -l`; chop $Naddstar;
+
+print "flatten: $Nflatten\n";
+print "gophot:  $Ngophot\n";
+print "imclean: $Nimclean\n";
+print "gastro:  $Ngastro\n";
+print "addstar: $Naddstar\n";
+
+# get the list of things to re-run:
+$runid  = `gconfig RUNID.POSTRUN`; chop $runid;
+$camera = `gconfig CAMERA.POSTRUN`; chop $camera;
+$catdir = `gconfig DB_STDS -D RUNID $runid -D CAMERA $camera`; chop $catdir;
+$datdir = `gconfig DATDIR`; chop $datdir;
+$ptlist = "$datdir/$runid/$runid.rerun.dat";
+$ptlist = "$datdir/$runid/$runid.rerun.log";
+
+#system ("grep addstar $failure | awk '{print \$1, \$2, \$3, \$4}' > $ptlist");
+#system ("elixir -D global.pending addstar -D RUNID $runid -D CAMERA $camera -D mode sexcomplete $ptlist >& $ptlog &");
+
+system ("cat $failure | awk '{print \$1, \$2, \$3, \$4}' > $ptlist");
+system ("elixir -D RUNID $runid -D CAMERA $camera -D mode sexcomplete $ptlist >& $ptlog &");
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/seeingstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/seeingstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/seeingstats	(revision 16632)
@@ -0,0 +1,113 @@
+#!/usr/bin/env perl
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+sub min {
+  if ($_[0] < $_[1]) {
+    return ($_[0]);
+  } else {
+    return ($_[1]);
+  }
+}
+
+sub max {
+  if ($_[0] > $_[1]) {
+    return ($_[0]);
+  } else {
+    return ($_[1]);
+  }
+}
+
+if (@ARGV != 1) { die "ERROR: USAGE: seeingstats (file)\n" }
+
+open (FILE, $ARGV[0]);
+@list = <FILE>;
+close (FILE);
+
+# the file contains results from sextractor. the lines
+# contain: FWHM FLAGS CLASS MAG 
+# reject bad objects, find mag min & number
+@mag = ();
+for ($i = 0; $i < @list; $i++) {
+  @words = split (" ", $list[$i]);
+  if ($words[1] > 0) { next; }
+  if ($words[3] > 0) { next; }
+  @mag = (@mag, $words[3]);
+}
+
+# find Mag threshold 
+@Mag = sort {$a <=> $b} @mag;
+$Nmag = @Mag;
+$Nwant = int(min(max(0.25*$Nmag, 10), $Nmag-1));
+$Mlim = $Mag[$Nwant];
+
+# fast way to zero a list of 1024 elements
+@Nfwhm = (0.0);
+for ($i = 0; $i < 10; $i++) {
+  @Nfwhm = (@Nfwhm, @Nfwhm);
+}
+$N = @Nfwhm;
+
+# reject bad objects, find mag min & number
+@fwhm = ();
+for ($i = 0; $i < @list; $i++) {
+  @words = split (" ", $list[$i]);
+  if ($words[1] > 0) { next; }
+  if ($words[3] > $Mlim) { next; }
+  @fwhm = (@fwhm, $words[0]);
+
+  # accumulate entry in histogram (@Nfwhm)
+  $bin = int ($words[0]*10.0);
+  if ($bin < 0)   { next; }
+  if ($bin > 999) { next; }
+  $Nfwhm[$bin] ++;
+}
+
+# find the mode (bin size = 0.1 pixels)
+$mode = 0;
+$Nmode = $Nfwhm[$mode];
+for ($i = 1; $i < @Nfwhm; $i++) {
+  if ($Nfwhm[$i] > $Nmode) {
+    $mode = $i;
+    $Nmode = $Nfwhm[$mode];
+  }
+}
+$Vmode = $mode * 0.1;
+$Fmin = $Vmode - 0.2;
+$Fmax = $Vmode + 0.2;
+
+# find the mean of values within 0.2 pix of the mode
+$F = 0;
+$N = 0;
+for ($i = 0; $i < @fwhm; $i++) {
+  if ($fwhm[$i] < $Fmin) { next; }
+  if ($fwhm[$i] > $Fmax) { next; }
+  $N++;
+  $F += $fwhm[$i];
+}
+if ($N > 3) {
+  $fwhm = $F / $N;
+  printf "%7.3f\n", $fwhm;
+  exit 0;
+}
+
+# I don't think the above can ever fail to get an answer, but...
+# if the mode search didn't work, resort to median
+$F = 0;
+$N = 0;
+@Fwhm = sort {$a <=> $b} @fwhm;
+$Nc = int(0.5*@Fwhm);
+for ($i = $Nc-1; $i < $Nc+2; $i++) {
+  $N++;
+  $F += $Fwhm[$i];
+}
+$fwhm = $F / $N;
+printf "%7.3f\n", $fwhm;
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/split.mef
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/split.mef	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/split.mef	(revision 16632)
@@ -0,0 +1,99 @@
+#!/usr/bin/env perl
+
+# we could test for each resulting file and re-construct the
+# output lists using only the successful ones.  This would work
+# best after we re-organize the flips elixirs to run imselect 1x
+# and the split parallel by image, not config
+
+if (@ARGV != 4) { die "USAGE: split.mef (list.mef) (outdir) (ccd) (list.msplit)\n"; }
+
+$inlist = $ARGV[0];
+$outdir = $ARGV[1];
+$ccd    = $ARGV[2];
+$outlist= $ARGV[3];
+
+$ccdkeyword = `gconfig CCDNUM-KEYWORD`; chop ($ccdkeyword);
+
+$line = `cameraconfig -axes`; chop ($line);
+($Naxis1, $Naxis2) = split (" ", $line);
+
+if (! -d $outdir) { vsystem ("mkdir -p $outdir"); }
+
+open (FILE, "$inlist");
+@mef = <FILE>;
+close (FILE);
+
+@split = ();
+foreach $name (@mef) {
+    chop ($name);
+
+    # convert name /path/name.fits to /outdir/rootccd.fits
+    @words = split ("/", $name);
+    $root = $words[-1];
+    $root =~ s/.fits//;
+    
+    # change to use ccd number, not id?
+    $new = sprintf "%s/%s%s.fits", $outdir, $root, $ccd;
+    push @split, $new;
+}
+ 
+# convert mef file to split files in outdir
+# write all valid entries to outlist
+   
+# start with empty file for msplit
+unlink ($outlist);
+
+open (MANA, "|mana --norc");
+
+# define the macro 'split'
+print MANA "macro split\n";
+print MANA " \$CCDKEYWORD = $ccdkeyword\n";
+print MANA " rd a \$1 -n $ccd\n";
+print MANA " keyword a NAXIS1 nx\n";
+print MANA " keyword a NAXIS2 ny\n";
+print MANA " if ((\$nx == $Naxis1) && (\$ny == $Naxis2))\n";
+print MANA "   wd a \$2 -bitpix 16 -bzero 32768 -bscale 1.0\n";
+print MANA "   exec echo \$2 >> $outlist\n";
+print MANA " end\n";
+print MANA "end\n";
+
+# create the macro 'go' with the commands 
+print MANA "macro go\n";
+for ($i = 0; $i < @mef; $i++) {
+    if (-e $split[$i]) { 
+	# if NAXIS1 & NAXIS2 are valid, add entry to outlist
+	$answer = `echo $split[$i] | fields NAXIS1 NAXIS2`;
+	($tmp, $nx, $ny) = split (" ", $answer);
+	if ($nx != $Naxis1) { next; }
+	if ($ny != $Naxis2) { next; }
+	print MANA "exec echo $split[$i] >> $outlist\n";
+	# print STDERR "$split[$i] exists, skipping\n";
+	next; 
+    }
+    print MANA " split $mef[$i] $split[$i]\n";
+}
+# if the macro ends successfully, exit 0
+print MANA " exit 0\n";
+print MANA "end\n";
+
+# if the macro exits before the end, exit 1
+print MANA "go\n";
+print MANA "exit 1\n";
+close (MANA);
+
+$status = $?;
+print STDERR "mana exit status: $status\n";
+if ($status) {
+    print STDERR "ERROR: problem running split.mef\n";
+    exit 1;
+}
+
+print STDERR "SUCCESS\n";
+exit 0;
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/update.astrometry.iraf
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/update.astrometry.iraf	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/update.astrometry.iraf	(revision 16632)
@@ -0,0 +1,116 @@
+#!/usr/bin/env perl
+
+$version = 1.0;
+if (@ARGV != 2) { die "USAGE: update.astrometry.iraf (efile) (cmpfile)\n" ; }
+
+$efile   = $ARGV[0];
+$cmpfile = $ARGV[1];
+
+if (! -e $efile) { die "output file $efile not found\n"; }
+if (! -e $cmpfile) { die "header source file $cmpfile not found\n"; }
+
+# grab astrometry keywords from $cmpfile:
+@header = &load_header ($cmpfile);
+
+# set some default values:
+@astrom = ();
+$Nastro = 0;
+
+# search for the appropriate lines:
+foreach $line (@header) {
+    
+    # astrometry keywords which are copied directly
+    if ($line =~ /NASTRO  =/) { $Nastro = substr ($line, 10, 21); }
+
+    if ($line =~ /CTYPE1  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CTYPE2  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRPIX1  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRPIX2  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRVAL1  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /CRVAL2  =/) { @astrom = (@astrom, $line);}
+#    if ($line =~ /NASTRO  =/) { @astrom = (@astrom, $line); $Nastro = substr ($line, 10, 21); }
+#    if ($line =~ /CERROR  =/) { @astrom = (@astrom, $line);}
+    if ($line =~ /EQUINOX =/) { @astrom = (@astrom, $line);}
+
+    # convert the PC00i00j matrix & CDELTi to CDi_j
+    if ($line =~ /PC001001=/) { $pc11 = substr ($line, 10, 21); }
+    if ($line =~ /PC001002=/) { $pc12 = substr ($line, 10, 21); }
+    if ($line =~ /PC002001=/) { $pc21 = substr ($line, 10, 21); }
+    if ($line =~ /PC002002=/) { $pc22 = substr ($line, 10, 21); }
+    if ($line =~ /CDELT1  =/) { $cd1  = substr ($line, 10, 21); }
+    if ($line =~ /CDELT2  =/) { $cd2  = substr ($line, 10, 21); }
+}
+
+# check for validity of astrometry data
+if ($Nastro == 0) {
+    print STDERR "can't find all astrometry keywords from $infile\n";
+    @astrom = ($line);
+} else {
+    # convert the pc, cdelt terms to cd terms
+    $cd11 = $cd1*$pc11;
+    $cd12 = $cd2*$pc12;
+    $cd21 = $cd1*$pc21;
+    $cd22 = $cd2*$pc22;
+    $line = sprintf "CD1_1   = %20G / WCS Coordinate scale matrix                   ", $cd11; @astrom = (@astrom, $line);
+    $line = sprintf "CD1_2   = %20G / WCS Coordinate scale matrix                   ", $cd12; @astrom = (@astrom, $line);
+    $line = sprintf "CD2_1   = %20G / WCS Coordinate scale matrix                   ", $cd21; @astrom = (@astrom, $line);
+    $line = sprintf "CD2_2   = %20G / WCS Coordinate scale matrix                   ", $cd22; @astrom = (@astrom, $line);
+}
+
+# write output to file
+foreach $line (@astrom) {
+    $hedit = convert_to_hedit ($line);
+    # print STDOUT "$line\n";
+    print STDOUT "$hedit\n";
+}
+
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
+# load FITS header lines (up to including END)
+sub load_header {
+
+    my ($file) = $_[0];
+    my ($buffer, $done, @buffer, $line);
+
+    open (FILE, "$file");
+    
+    $done = 0;
+    @buffer = ();
+
+    while (! $done) {
+	read FILE, $buffer, 2880;
+	for ($i = 0; $i < 2880; $i+=80) {
+	    $line = substr ($buffer, $i, 80);
+	    if (! $done) {
+		@buffer = (@buffer, $line);
+	    }
+	    if ($line =~ /^END     /) { $done = 1; }
+	}
+    }
+    close (FILE);
+    return (@buffer);
+}
+
+sub convert_to_hedit {
+
+    my ($line) = $_[0];
+    my ($hedit, $keyword, $value);
+
+    $keyword = substr ($line, 0, 8);
+    $value   = substr ($line, 10, 21);
+
+    $hedit = sprintf "hedit $efile $keyword $value ver- show-";
+    return ($hedit);
+}
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/validate
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/validate	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/validate	(revision 16632)
@@ -0,0 +1,309 @@
+#!/usr/bin/env perl
+
+# validate 
+# -update sends the validation value to the QSO database
+#  1 - valid image
+#  2 - subvalid image (problem, but doesn't matter)
+#  3 - invalid image
+#  4 - data error (missing, corrupted image)
+
+# global constants:
+
+$TRUE  = 1;
+$FALSE = 0;
+$RETRY = $TRUE;
+
+$PASS = (0 << 8);
+$FAIL = (1 << 8);
+$SUBVALID = (2 << 8);
+$DATA_ERR = (3 << 8);
+
+$MODE_UNSET    = 0;
+$MODE_VALID    = 1;
+$MODE_SUBVALID = 2;
+$MODE_INVALID  = 3;
+$MODE_DATAERR  = 4;
+
+$STATS = $FALSE;
+$update = $FALSE;
+
+$infile = "";
+
+# include the CFHT bin directory in the path so we have access to QSO functions:
+$ENV{'PATH'} = "$ENV{'PATH'}:/cfht/bin";
+
+# grab the command line arguments:
+@tARGV = ();
+for (; @ARGV > 0; ) {
+
+    if ($ARGV[0] eq "-stats") {
+	shift;
+	$STATS = $TRUE;
+	next;
+    }
+    if ($ARGV[0] eq "-update") {
+	shift;
+	$update = $TRUE;
+	next;
+    }
+    if ($ARGV[0] eq "-skip") {
+	shift;
+	$RETRY = $FALSE;
+	next;
+    }
+    if ($ARGV[0] eq "-infile") {
+	shift;
+	$infile = $ARGV[0];
+	shift;
+	next;
+    }
+    
+    @tARGV = (@tARGV, $ARGV[0]);
+    shift;
+}
+@ARGV = @tARGV;
+
+if (@ARGV != 1) { die "USAGE: validate (crunid) [-infile filename] [-update]\n" ;}
+
+$crunid = $ARGV[0];
+
+$answer = `mkrun run $crunid`; 
+if ($?) { die "ERROR finding run id: $crunid\n"; }
+($id, $start, $stop, $camera, $qrunid) = split (" ", $answer);
+# qrunid is space-separated (change?)
+if ($id ne $crunid) { die "ERROR with run id: $crunid\n"; }
+print STDERR "qso run ID(s): $qrunid\n";
+
+@valid    = ();
+@invalid  = ();
+@dataerr  = ();
+@subvalid = ();
+
+if ($infile) {
+    # load images from previous output run or source file:
+    open (FILE, $infile);
+    @rawlist = <FILE>;
+    close (FILE);
+    
+    $mode = $MODE_UNSET;
+    @imlist = ();
+    
+  RAWLIST:
+    foreach $name (@rawlist) {
+	chop ($name);
+	
+	if ($name eq "") { next RAWLIST; }
+	    
+	if ($name =~ /^valid images/) {
+	    $mode = $MODE_VALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^invalid images/) {
+	    $mode = $MODE_INVALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^subvalid images/) {
+	    $mode = $MODE_SUBVALID;
+	    next RAWLIST;
+	}
+	if ($name =~ /^dataerr images/) {
+	    $mode = $MODE_DATAERR;
+	    next RAWLIST;
+	}
+
+	# plain list of image names (/path/name.fits)
+	if ($mode == $MODE_UNSET) {
+	    # double check on name validity
+	    ($file, $junk) = split (" ", $name, 2);
+	    unless ($file =~ /\d\d\d\d\d\d\w/) { print STDERR "?"; next RAWLIST; }
+	    @imlist = (@imlist, $file);
+	    next RAWLIST;
+	}
+
+	# ($file) = split (" ", $name);
+	$file = $name;
+	# place image names in the appropriate list
+	if ($mode == $MODE_VALID) {
+	    @valid = (@valid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_INVALID) {
+	    @invalid = (@invalid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_SUBVALID) {
+	    @subvalid = (@subvalid, $file);
+	    next RAWLIST;
+	}
+	if ($mode == $MODE_DATAERR) {
+	    @dataerr = (@dataerr, $file);
+	    next RAWLIST;
+	}
+    }
+} else {
+    # load images directly from directory 
+    # this is not sufficient.  we need a better way to get a list of images for 
+    # a given run id (with the current MEF / SPLIT state correct).
+    # 
+    # probably we can just use imsearch -ccd 0
+    $rawdir = `gconfig -q -D RUNID $crunid RAWDIR`;
+    chop ($rawdir);
+    if ($rawdir eq "") {
+	print STDERR "can't find config entry RAWDIR\n";
+	exit 1;
+    }
+    @imlist = ();
+
+    # load in the MEF files (must be of format 123456x.fits)
+    @tlist = <$rawdir/*.fits>;
+    foreach $tname (@tlist) { 
+	if ((-f $tname) && ($tname =~ /\d\d\d\d\d\d\w.fits/)) { 
+	    @imlist = (@imlist, $tname); 
+	} 
+    }
+
+    # load in the SPLIT directories (must be of format 123456x)
+    @tlist = <$rawdir/???????>;
+    foreach $tname (@tlist) { 
+	if ((-d $tname) && ($tname =~ /\d\d\d\d\d\d\w/)) { 
+	    @imlist = (@imlist, $tname); 
+	} 
+    }
+}
+
+if ($STATS) {
+    $Nvalid = @valid;
+    $Ninvalid = @invalid;
+    $Nsubvalid = @subvalid;
+    $Ndataerr = @dataerr;
+
+    print STDOUT "valid    $Nvalid\n";
+    print STDOUT "invalid  $Ninvalid\n";
+    print STDOUT "subvalid $Nsubvalid\n";
+    print STDOUT "dataerr  $Ndataerr\n";
+    exit 0;
+}
+
+# load the QSO validated image list
+@qsovalid = ();
+if ($qrunid) { 
+    @qruns = split (",", $qrunid);
+    @qsovalid = ();
+    foreach $id (@qruns) {
+	print STDERR "$id:\n";
+	@answer = `select_val_xexp.sh -U qso_elixir -P op1eliw -qrunid $id`;
+	if ($?) {
+	    print STDERR "error in qso run ID\n";
+	    exit 1;
+	}
+	@qsovalid = (@qsovalid, @answer);
+    }
+}
+# create qsostate hash to quickly find valid qso images
+foreach $qline (@qsovalid) { 
+    chop ($qline); 
+    ($qname, $qeval, $eval, $seval) = split (" ", $qline);
+    $qsostate{$qname} = 1;
+}
+
+if ($RETRY) {
+# evaluate the remaining entries in imlist & invalid:
+    @imlist = (@imlist, @invalid, @dataerr);
+    @invalid = ();
+    @dataerr = ();
+    
+  IMLIST:
+    foreach $line (@imlist) {
+	($name) = split (" ", $line);
+	@words = split ("/", $name);
+	$tmp = $words[-1];
+	($obsid) = $tmp =~ /(\d\d\d\d\d\d\w)/;
+
+	$answer = `ckvalid $name`; chop ($answer);   
+	$status = $?;
+	if ($status) { 
+	    print STDERR "-";
+	} else {
+	    print STDERR "+";
+	}
+	
+	($file, $mode, $type, $runid, $state) = split (" ", $answer, 2);
+
+	if ($status == $PASS) { 
+	    @valid = (@valid, $answer);
+	    next IMLIST;
+	}
+	if ($status == $SUBVALID) {
+	    @subvalid = (@subvalid, $answer);
+	    next IMLIST;
+	}
+	if ($status == $DATA_ERR) {
+	    @dataerr = (@dataerr, $answer);
+	    next IMLIST;
+	}
+
+	# subvalid if not in qso list 
+	if ($status == $FAIL) {
+	    # are we in QSO list?
+	    if ($qsostate{$obsid}) {
+		@invalid = (@invalid, $answer);
+		next IMLIST;
+	    } else {
+		@subvalid = (@subvalid, $answer);
+		next IMLIST;
+	    }
+	}
+	print STDERR "unknown result $answer\n";
+    }
+}
+
+@mode = ('valid',     'subvalid',      'invalid',     'dataerr');
+@code = ($MODE_VALID, $MODE_SUBVALID,  $MODE_INVALID, $MODE_DATAERR);
+
+for ($i = 0; $i < @mode; $i++) {
+    $mode = $mode[$i];
+    $code = $code[$i];
+
+    print STDOUT "$mode images\n";
+    foreach $line (@$mode) {
+	print STDOUT "$line\n";
+	if ($update) { 
+	    ($file, $mode, $type, $runid, $state) = split (" ", $line, 5);
+	    $seval = get_seval ($state);
+
+	    @w = split ("/", $file);
+	    $n = substr ($w[-1], 0, 6);
+	    # print STDERR "update_xexpe.sh -U qso_elixir -P op1eliw --obsid $n --eval $code --Seval $seval >> test.list\n";
+	    vsystem ("update_xexpe.sh -U qso_elixir -P op1eliw --obsid $n --eval 0 --Seval $seval >> xexpe.list");
+	}
+    }
+    print STDOUT "\n";
+}
+
+sub get_seval {
+
+    my($state) = $_[0];
+    my (@evals, $seval);
+
+    @evals = split (" ", $state);
+    
+    $seval = "";
+    if ($evals[0]) { $seval = $seval . "t"; } else { $seval = $seval . "f"; }  # DATA
+    if ($evals[1]) { $seval = $seval . "t"; } else { $seval = $seval . "f"; }  # DETREND
+    $seval = $seval . "-";
+    if ($evals[2]) { $seval = $seval . "t"; } else { $seval = $seval . "f"; }  # PHOTOM
+    if ($evals[3]) { $seval = $seval . "t"; } else { $seval = $seval . "f"; }  # ASTROM
+
+    return ($seval);
+}
+
+sub vsystem {
+    print STDERR "@_\n";
+    my($status) = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/perl/src/wfi.keywords
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/perl/src/wfi.keywords	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/perl/src/wfi.keywords	(revision 16632)
@@ -0,0 +1,110 @@
+#!/usr/bin/env perl
+
+$version = 1.0;
+$Nccd = `cameraconfig -Nccd`; chop ($Nccd);
+
+if (@ARGV != 2) { die "USAGE: grab.keywords (fitsfile) (hdrfile)\n" ; }
+
+$fitsfile  = $ARGV[0];  # input image file
+$hdrfile   = $ARGV[1];  # hdr file for fits_insert
+
+@header = `fhead $fitsfile`;
+
+@newhead = ();
+# grab lines from primary header
+foreach $line (@header) {
+    # astrometry keywords which are copied directly
+    if ($line =~ /HIERARCH ESO INS FILT NAME  =/) { 
+	@word = split ("'", $line);
+	$newline = sprintf "FILTER  = '%-18s' / %-46s \n", $word[1], "Filter name";	
+	@newhead = (@newhead, $newline);
+    }
+    if ($line =~ /HIERARCH ESO DPR TYPE       =/) { 
+	@word = split ("'", $line);
+	$value = @word[1];
+	if ($value eq "SKY") { $value = "OBJECT"; }
+	if ($value eq "SKY,FLAT") { $value = "FLAT"; }
+	if ($value eq "DOME,FLAT") { $value = "FLAT"; }
+	$newline = sprintf "OBSTYPE = '%-18s' / %-46s \n", $value, "Obs Type";	
+	@newhead = (@newhead, $newline);
+    }
+    if ($line =~ /HIERARCH ESO TEL AIRM START =/) {
+	($value) = $line =~ /HIERARCH ESO TEL AIRM START = \s*(\S+)/;
+	$newline = sprintf "AIRMASS = %20.10f / %-46s \n", $value, "Airmass";	
+	@newhead = (@newhead, $newline);
+    }
+    if ($line =~ /HIERARCH ESO TEL FOCU VALUE =/) {
+	($value) = $line =~ /HIERARCH ESO TEL FOCU VALUE = \s*(\S+)/;
+	$newline = sprintf "FOCUS   = %20.10f / %-46s \n", $value, "Focus Value";	
+	@newhead = (@newhead, $newline);
+    }
+    if ($line =~ /HIERARCH ESO INS SIGNAL1 ST =/) {
+	($value) = $line =~ /HIERARCH ESO INS SIGNAL1 ST = \s*(\S+)/;
+	$newline = sprintf "SIGNAL1 = %20.10f / %-46s \n", $value, "Detector temp";	
+	@newhead = (@newhead, $newline);
+    }
+    if ($line =~ /HIERARCH ESO INS SIGNAL2 ST =/) {
+	($value) = $line =~ /HIERARCH ESO INS SIGNAL2 ST = \s*(\S+)/;
+	$newline = sprintf "SIGNAL2 = %20.10f / %-46s \n", $value, "Electronic temp";	
+	@newhead = (@newhead, $newline);
+    }
+    if ($line =~ /HIERARCH ESO INS SIGNAL3 ST =/) {
+	($value) = $line =~ /HIERARCH ESO INS SIGNAL3 ST = \s*(\S+)/;
+	$newline = sprintf "SIGNAL3 = %20.10f / %-46s \n", $value, "Barom press";	
+	@newhead = (@newhead, $newline);
+    }
+    $newline = sprintf "ROTATE  = %20.10f / %-46s \n", 0.0, "Barom press";	
+    @newhead = (@newhead, $newline);
+    $newline = sprintf "NEXTEND = %20d / %-46s \n", $Nccd, "Nextend";	
+    @newhead = (@newhead, $newline);
+}
+ 
+for ($i = 0; $i < $Nccd; $i++) {
+    @chiphead = ();
+    @header = `fhead -x $i $fitsfile`;
+    foreach $line (@header) {
+	if ($line =~ /HIERARCH ESO DET CHIP\d INDEX=/) {
+	    ($value) = $line =~ /HIERARCH ESO DET CHIP\d INDEX= \s*(\S+)/;
+#	    $newline = sprintf "CHIPID  = %20d / %-46s \n", $value, "Detector ID";	
+#	    @chiphead = (@chiphead, $newline);
+	    $newline = sprintf "IMAGEID = %20d / %-46s \n", $value, "Detector ID";	
+	    @chiphead = (@chiphead, $newline);
+	    last;
+	}
+    }
+
+    # write output to file
+    open (FILE, ">$hdrfile");
+    foreach $line (@newhead) {
+	print FILE "$line";
+    }
+    foreach $line (@chiphead) {
+	print FILE "$line";
+    }
+    close (FILE);
+
+    system ("fits_insert -X $i $fitsfile $hdrfile");
+    if ($?) { die "problem with extension $i\n"; }
+}
+
+# write output to file
+open (FILE, ">$hdrfile");
+foreach $line (@newhead) {
+    print FILE "$line";
+}
+system ("fits_insert $fitsfile $hdrfile");
+if ($?) { die "problem with phu\n"; }
+
+exit 0;
+
+###################################################################################
+
+sub vsystem {
+    print STDERR "@_\n";
+    $status = system ("@_");
+    $status;
+}
+
+sub goodbye {
+    die "@_\n";
+}
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/Makefile	(revision 16632)
@@ -0,0 +1,54 @@
+default: photdbc
+help:
+	@echo "make options: photdbc (default)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/photdbc
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+photdbc: $(BIN)/photdbc.$(ARCH)
+install: $(DESTBIN)/photdbc
+
+PHOTDBC = \
+$(SRC)/photdbc.$(ARCH).o	   \
+$(SRC)/initialize.$(ARCH).o	   \
+$(SRC)/ConfigInit.$(ARCH).o	   \
+$(SRC)/args.$(ARCH).o		   \
+$(SRC)/copy_images.$(ARCH).o	   \
+$(SRC)/Shutdown.$(ARCH).o          \
+$(SRC)/make_subcatalog.$(ARCH).o        
+
+OLD = \
+$(SRC)/liststats.$(ARCH).o	   \
+$(SRC)/name_region.$(ARCH).o	   \
+$(SRC)/find_images.$(ARCH).o	   \
+$(SRC)/find_regions.$(ARCH).o	   \
+$(SRC)/get_regions.$(ARCH).o	   \
+$(SRC)/load_catalogs.$(ARCH).o	   \
+$(SRC)/gcatalog.$(ARCH).o 	   \
+$(SRC)/join_stars.$(ARCH).o        \
+$(SRC)/unique_measures.$(ARCH).o   \
+$(SRC)/flag_measures.$(ARCH).o     \
+$(SRC)/get_mags.$(ARCH).o          \
+$(SRC)/check_directory.$(ARCH).o   \
+$(SRC)/overlap_funcs.$(ARCH).o     \
+$(SRC)/image-db.$(ARCH).o          \
+$(SRC)/check_permissions.$(ARCH).o \
+$(SRC)/misc.$(ARCH).o		   \
+$(SRC)/SetSignals.$(ARCH).o        \
+$(SRC)/Shutdown.$(ARCH).o          \
+$(SRC)/wcatalog.$(ARCH).o
+
+
+$(PHOTDBC): $(INC)/photdbc.h
+$(BIN)/photdbc.$(ARCH): $(PHOTDBC)
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,10 @@
+
+photdbc-1-1 : 
+  * converted to gfits APIs (forces libfits 1.6)
+  * updated to use sky regions
+  * general overhaul:
+    * performs a basic copy
+    * operations restricted by region
+    * output catalog may be filtered by
+      -maxminmag MAG
+      -instmag Mmin Mmax
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/doc/notes.txt	(revision 16632)
@@ -0,0 +1,28 @@
+
+- select a region
+
+- load average / measure / secfilt / missing
+
+- construct subset based on selection criteria:
+  - Minst
+  - dMinst
+  - X,Y
+  - R,D
+
+- merge neighbor stars (join within X.X arcsec)
+
+- mark bad measurements:
+
+  - outside area
+  - Minst < cutoff
+  - Mcal > 0.015 (lookup from table?)
+
+  - subset for given filter (match by string?):
+    - 2x 3sigma 
+    - softened chisq > 3.0
+
+- mark objects with fewer than N measurements
+
+
+-----
+
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/include/photdbc.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/include/photdbc.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/include/photdbc.h	(revision 16632)
@@ -0,0 +1,116 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+
+typedef struct {
+  int measure;          // pointer to measure entry
+  unsigned int averef;  // old measures come from multiple averages
+  float R, D;           // actual coordinates of this measure
+} Mpointer;
+
+typedef struct {
+  double median;
+  double mean;
+  double sigma;
+  double error;
+  double chisq;
+  double min;
+  double max;
+  double total;
+  int    Nmeas;
+} StatType;
+
+// need to get RADIUS from Config 
+
+/* global variables */
+int    SHOW_PARAMS;
+int    VERBOSE;
+double JOIN_RADIUS;
+double UNIQ_RADIUS;
+double DMCAL_MIN;;
+char   ImageCat[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char   PhotCodeFile[256];
+
+double RMIN;
+double RMAX;
+double DMIN;
+double DMAX;
+ 
+double XMIN;
+double XMAX;
+double YMIN;
+double YMAX;
+double MMIN;
+double MMAX;
+
+double DMSYS;
+double DMGAIN;
+double CHISQ_MAX;
+double SIGMA_MAX;
+int    NMEAS_MIN;
+double ZERO_POINT;
+
+int ExcludeByInstMag;
+double INST_MAG_MIN;
+double INST_MAG_MAX;
+
+int ExcludeByMaxMinMag;
+double MAX_MIN_MAG;
+
+SkyRegion REGION;
+PhotCodeData photcodes;
+
+# define FLAG_AREA            0X0001
+# define FLAG_MINST           0X0002
+# define FLAG_DMCAL           0x0004
+# define FLAG_SIGCLIP         0X0008
+# define FLAG_CHISQ           0x0010
+# define FLAG_TOOFEW          0x0020
+# define FLAG_DUPMEAS         0x0040
+
+Image        *find_images (FITS_DB *db, GSCRegion *region, int Nregion, int *Nimage, int **LineNum);
+GSCRegion    *find_regions (Image *image, int Nimage, int *Nregions, GSCRegion *fullregion); 
+GSCRegion    *get_regions (double minRa, double maxRa, double minDec, double maxDec, int *Nregions); 
+Catalog      *load_catalogs (GSCRegion *region, int Nregion); 
+GSCRegion    *load_images (FITS_DB *db, char *seed, int *nregion);
+GSCRegion    *name_region (char *name, int *Nregions); 
+void          ConfigInit (int *argc, char **argv); 
+int           args (int argc, char **argv); 
+int           corner_check (double *x1, double *y1, double *x2, double *y2); 
+int           edge_check (double *x1, double *y1, double *x2, double *y2); 
+void          flag_measures (FITS_DB *db, Catalog *catalog); 
+int           gcatalog (Catalog *catalog); 
+void          get_mags (Catalog *catalog); 
+void          getfullregion (Image *image, int Nimage, GSCRegion *fullregion); 
+void          initialize (int argc, char **argv); 
+void          initstats (char *mode); 
+void          join_stars (Catalog *catalog); 
+int           liststats (double *value, double *dvalue, int N, StatType *stats); 
+double        opening_angle (double x1, double y1, double x2, double y2, double x3, double y3); 
+void          set_ZP (double ZERO); 
+void          sortA (double *X, int N); 
+void          sortB (double *X, double *Y, int N); 
+void          sortC (double *X, double *Y, double *F1, double *F2, int N); 
+void          sortD (double *X, double *Y, double *Z, int N); 
+void          sort_lists (float *X, float *Y, int *index, int N); 
+void          sort_time (unsigned int *X, int *Y, int N); 
+void          unique_measures (Catalog *catalog);
+void          wcatalog (Catalog *catalog);
+int           make_subcatalog (Catalog *subcatalog, Catalog *catalog);
+void          check_directory (char *basefile);
+
+int Shutdown (char *format, ...);
+void set_db (FITS_DB *in);
+void lock_image_db (FITS_DB *db, char *filename);
+void unlock_image_db (FITS_DB *db);
+void check_permissions (char *basefile);
+void TrapSignal (int sig);
+void SetProtect (int mode);
+int SetSignals ();
+
+
+int copy_images (char *outdir);
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,75 @@
+# include "photdbc.h"
+
+int success = TRUE;
+
+void WarnConfig (char *config, char *key, char * mode, int N, void *var) {
+  if (!ScanConfig (config, key, mode, N, var)) {
+    fprintf (stderr, "missing config variable %s\n", key);
+    success = FALSE;
+  }
+}
+
+void ConfigInit (int *argc, char **argv) {
+
+  char *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  // WarnConfig (config, "JOIN_RADIUS",            "%lf", 0, &JOIN_RADIUS);
+  // WarnConfig (config, "UNIQ_RADIUS",            "%lf", 0, &UNIQ_RADIUS);
+
+  // WarnConfig (config, "XMIN",                   "%lf", 0, &XMIN);
+  // WarnConfig (config, "XMAX",                   "%lf", 0, &XMAX);
+  // WarnConfig (config, "YMIN",                   "%lf", 0, &YMIN);
+  // WarnConfig (config, "YMAX",                   "%lf", 0, &YMAX);
+  
+  // WarnConfig (config, "DMCAL_MIN",              "%lf", 0, &tmp);  DMCAL_MIN = 1000*tmp;
+  // WarnConfig (config, "MMIN",                   "%lf", 0, &tmp);  MMIN      = 1000*tmp;
+  // WarnConfig (config, "MMAX",                   "%lf", 0, &tmp);  MMAX      = 1000*tmp;
+  // WarnConfig (config, "DMSYS",                  "%lf", 0, &tmp);  DMSYS     = SQ(1000*tmp);
+  // WarnConfig (config, "DMGAIN",                 "%lf", 0, &DMGAIN); 
+  // WarnConfig (config, "CHISQ_MAX",              "%lf", 0, &CHISQ_MAX);
+
+  ScanConfig (config, "SIGMA_MAX",              "%lf", 0, &SIGMA_MAX);
+  ScanConfig (config, "NMEAS_MIN",              "%d",  0, &NMEAS_MIN);
+
+  WarnConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  WarnConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  WarnConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+
+  if (!success) { 
+    fprintf (stderr, "missing config parameter\n");
+    exit (1);
+  }
+
+  SetZeroPoint (ZERO_POINT);
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+  free (config);
+  free (file);
+}
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "photdbc.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,20 @@
+# include "photdbc.h"
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format));
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  fprintf (stderr, "ERROR: photdbc halted\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/args.c	(revision 16632)
@@ -0,0 +1,102 @@
+# include "photdbc.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  SHOW_PARAMS = FALSE;
+  if ((N = get_argument (argc, argv, "-params"))) {
+    remove_argument (N, &argc, argv);
+    SHOW_PARAMS = TRUE;
+  }
+
+  ExcludeByInstMag = FALSE;
+  if ((N = get_argument (argc, argv, "-instmag"))) {
+    remove_argument (N, &argc, argv);
+    ExcludeByInstMag = TRUE;
+    remove_argument (N, &argc, argv);
+    INST_MAG_MIN = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+    INST_MAG_MAX = atof(argv[N]);
+  }
+
+  ExcludeByMaxMinMag = FALSE;
+  if ((N = get_argument (argc, argv, "-maxminmag"))) {
+    remove_argument (N, &argc, argv);
+    ExcludeByMaxMinMag = TRUE;
+    remove_argument (N, &argc, argv);
+    MAX_MIN_MAG = atof(argv[N]);
+  }
+
+  /* specify portion of the sky */
+  REGION.Rmin = 0;
+  REGION.Rmax = 360;
+  REGION.Dmin = -90;
+  REGION.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    REGION.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    REGION.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    REGION.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    REGION.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+
+    if (REGION.Rmin == REGION.Rmax) {
+      fprintf (stderr, "ERROR: selected region is ill-defined: Rmin == Rmax\n");
+      exit (2);
+    }
+    if (REGION.Dmin == REGION.Dmax) {
+      fprintf (stderr, "ERROR: selected region is ill-defined: Dmin == Dmax\n");
+      exit (2);
+    }
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: photdbc (output)\n");
+    exit (2);
+  } 
+
+  if ((REGION.Rmin == 0) && (REGION.Rmax == 360) && (REGION.Dmin == -90) && (REGION.Dmax == +90)) {
+    int i;
+    fprintf (stderr, "you have requested a copy of the entire sky in one pass\n");
+    fprintf (stderr, "this could be a time consuming operation.  type Ctrl-C within 5 seconds to cancel\n");
+    for (i = 5; i > 0; i--) {
+      fprintf (stderr, "%d.. ", i);
+      usleep (1000000);
+    }
+    fprintf (stderr, "\n");
+  }
+
+  return (TRUE);
+}
+
+/**
+
+ this program takes an existing DVO database and makes a copy, applying a number of optional
+ filters in the process.  
+
+ photdbc (output)
+
+ allowed filters / restrictions include:
+
+ -region ra dec ra dec : limit operation to the specified region 
+ -join                 : join measurements between stars using JOIN_RADIUS
+ -ccdregion X Y X Y    : only keep detections within the specified detector region
+                         (can this be limited to specific photcodes? cameras? detectors?)
+ -photcode_limits code Mmin Mmax : allow multiples of these
+
+ SIGMA_MAX
+ NMEAS_MIN
+ INST_MAG_MAX
+ INST_MAG_MIN
+
+**/
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/copy_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/copy_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/copy_images.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "photdbc.h"
+
+int copy_images (char *outdir) {
+
+  int status, Nimage;
+  char *ImageOut;
+  FITS_DB in;
+  FITS_DB out;
+  Image *image;
+  struct stat filestat;
+  char *path;
+
+  path = pathname (ImageCat);
+  status = stat (path, &filestat);
+  if (status == -1) Shutdown ("ERROR: CATDIR %s does not exist, no data in database", path);
+
+  status = dvo_image_lock (&in, ImageCat, 60.0, LCK_SOFT);
+  if (!status) {
+    fprintf (stderr, "No images in catalog %s\n", ImageCat);
+    return (TRUE);
+  }
+  if (in.dbstate == LCK_EMPTY) {
+    fprintf (stderr, "No images in catalog %s\n", ImageCat);
+    dvo_image_unlock (&in);
+    return (TRUE);
+  }
+
+  // load the input image data
+  if (!dvo_image_load (&in, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", in.filename);
+  dvo_image_unlock (&in);
+
+  // define output filename (replace CATDIR)
+  ImageOut = strsubs (in.filename, CATDIR, outdir);
+  if (ImageOut == NULL) Shutdown ("error with input or output catalog name");
+
+  // lock the output catalog
+  status = dvo_image_lock (&out, ImageOut, 60.0, LCK_SOFT);
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", ImageOut);
+  if (out.dbstate != LCK_EMPTY) Shutdown ("ERROR: image table exists %s", ImageOut);
+
+  out.mode   = dvo_catalog_catmode (CATMODE);
+  out.format = dvo_catalog_catformat (CATFORMAT);
+  dvo_image_create (&out, ZERO_POINT);
+    
+  image = gfits_table_get_Image (&in.ftable, &Nimage, &in.swapped);
+  dvo_image_addrows (&out, image, Nimage);
+
+  dvo_image_save (&out, VERBOSE);
+  dvo_image_unlock (&out);
+  return (TRUE);
+}
+
+// globals: ImageCat, VERBOSE, CATMODE, CATFORMAT, ZeroPt
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/find_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/find_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/find_images.c	(revision 16632)
@@ -0,0 +1,129 @@
+# include "photdbc.h"
+
+/* this function returns a list of all images which overlap the given
+   set of region files.  All images in the image catalog are tested
+   once, so there is no check that an image already has been included.
+   LineNum stores the locations in the Image database of the list of
+   images */
+
+Image *find_images (FITS_DB *db, GSCRegion *region, int Nregion, int *Nimage, int **LineNum) {
+  
+  Image *timage, *image;
+  int i, j, k, m, found, nimage, Ntimage, NIMAGE;
+  int InRange;
+  double Xc[5], Yc[5], Xi[5], Yi[5], r, d, dx, dy;
+  int *line_number;
+  Coords tcoords;
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  /* we make positional comparisons in the projection of catalog */
+  tcoords.crval1 = 0.5*(region[0].RA[0]  + region[0].RA[1]);
+  tcoords.crval2 = 0.5*(region[0].DEC[0] + region[0].DEC[1]);
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  timage = gfits_table_get_Image (&db[0].ftable, &Ntimage, &db[0].swapped);
+
+  nimage = 0;
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  ALLOCATE (line_number, int, NIMAGE);
+  
+  for (i = 0; i < Ntimage; i++) {
+      
+# if (0)
+    /* select images by photcode */
+    ecode = GetPhotcodeEquivCodebyCode (timage[i].photcode);
+    if (ecode != photcode[0].code) continue;
+
+    /* select images by time */
+    if (TimeSelect) {
+      if (timage[i].tzero < TSTART) continue;
+      if (timage[i].tzero > TSTOP) continue;
+    }
+# endif
+
+    /* define image corners */
+    Xi[0] = 0;            Yi[0] = 0;
+    Xi[1] = timage[i].NX; Yi[1] = 0;
+    Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+    Xi[3] = 0;            Yi[3] = timage[i].NY;
+    Xi[4] = 0;            Yi[4] = 0;
+    found = FALSE;
+    /* transform to tcoords */
+    for (j = 0; j < 5; j++) {
+      XY_to_RD (&r, &d, Xi[j], Yi[j], &timage[i].coords);
+      InRange = RD_to_XY (&Xi[j], &Yi[j], r, d, &tcoords);
+      if (!InRange) goto imskip;
+    }
+    /* compare with each region file */
+    for (m = 0; (m < Nregion) && !found; m++) { 
+      /* define catalog corners */
+      Xc[0] = region[m].RA[0]; Yc[0] = region[m].DEC[0];
+      Xc[1] = region[m].RA[1]; Yc[1] = region[m].DEC[0];
+      Xc[2] = region[m].RA[1]; Yc[2] = region[m].DEC[1];
+      Xc[3] = region[m].RA[0]; Yc[3] = region[m].DEC[1];
+      Xc[4] = region[m].RA[0]; Yc[4] = region[m].DEC[0];
+      for (j = 0; j < 5; j++) {
+	r = Xc[j]; d = Yc[j];
+	RD_to_XY (&Xc[j], &Yc[j], r, d, &tcoords);
+      }
+      dx = 0.02*(Xc[2] - Xc[0]);
+      dy = 0.02*(Yc[2] - Yc[0]);
+      Xc[0] -= dx; Yc[0] -= dy;
+      Xc[1] += dx; Yc[1] -= dy;
+      Xc[2] += dx; Yc[2] += dy;
+      Xc[3] -= dx; Yc[3] += dy;
+      Xc[4] -= dx; Yc[4] -= dy;
+      
+      /* check if image corner inside catalog */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xi[j], &Yi[j], &Xc[0], &Yc[0]);
+      }
+      /* check if catalog corner inside image */
+      for (j = 0; (j < 4) && !found; j++) {
+	found |= corner_check (&Xc[j], &Yc[j], &Xi[0], &Yi[0]);
+      }
+      /* check if edges cross */
+      for (j = 0; (j < 4) && !found; j++) {
+	for (k = 0; (k < 4) && !found; k++) {
+	  found |= edge_check (&Xi[j], &Yi[j], &Xc[k], &Yc[k]);
+	}
+      }
+      if (found) {
+	image[nimage] = timage[i]; 
+	if (image[nimage].code == ID_IMAGE_NOCAL) {
+	  image[nimage].code &= ~ID_IMAGE_NOCAL;
+	}	    
+	line_number[nimage] = i;
+	nimage ++;
+	if (nimage == NIMAGE) {
+	  NIMAGE += 100;
+	  REALLOCATE (image, Image, NIMAGE);
+	  REALLOCATE (line_number, int, NIMAGE);
+	}
+      }
+    }
+  imskip:
+    continue;
+  }
+      
+  if (VERBOSE) fprintf (stderr, "found %d images\n", nimage);
+
+  /* we are going to use image[nimage] to represent images not in the database:
+     these are measurements from external sources, like USNO */
+
+  assignMcal (&image[nimage], (double *) NULL, -1);
+  image[nimage].code = ID_IMAGE_NEW;
+  
+  REALLOCATE (image, Image, MAX (nimage + 1, 1));
+  REALLOCATE (line_number, int, MAX (nimage + 1, 1));
+  *Nimage = nimage;
+  *LineNum = line_number;
+  return (image);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/flag_measures.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/flag_measures.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/flag_measures.c	(revision 16632)
@@ -0,0 +1,202 @@
+# include "photdbc.h"
+
+void flag_measures (FITS_DB *db, Catalog *catalog) {
+
+  int i, j, k, m, n, N, found;
+  int *imagelink, Nimage, Nlist, PhotNsec;
+  unsigned int Time;
+  int Ncode, Photcode, Minst, Mag, BAD_MEASURE;
+  double ra, dec, x, y, Nsigma;
+  double *list, *dlist;
+
+  Image *image;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "flagging bad measurements\n");
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  PhotNsec = GetPhotcodeNsecfilt ();
+  /* need to replace dMcal with values from external table? */
+
+  /* clear existing measure flags */
+  for (i = 0; i < catalog[0].Nmeasure; i++) catalog[0].measure[i].flags = 0;
+
+  /* generate image index */
+  ALLOCATE (imagelink, int, catalog[0].Nmeasure);
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    n = catalog[0].measure[i].averef;
+    Time = catalog[0].measure[i].t;
+    Photcode = catalog[0].measure[i].photcode;
+    found = FALSE;
+    for (k = 0; !found && (k < Nimage); k++) { 
+      if ((Time == image[k].tzero) && (Photcode == image[k].photcode)) {
+	imagelink[i] = k;
+	found = TRUE;
+      }
+    }
+    if (!found) {
+      /* some error? */
+    }
+  }
+
+  /* flag by area : find source image, get X,Y coords, set flag */
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    n = catalog[0].measure[i].averef;
+    ra  = catalog[0].average[n].R - catalog[0].measure[i].dR / 3600.0;
+    dec = catalog[0].average[n].D - catalog[0].measure[i].dD / 3600.0;
+    k = imagelink[i];
+    RD_to_XY (&x, &y, ra, dec, &image[k].coords);
+    if (x < XMIN) goto flagarea;
+    if (x > XMAX) goto flagarea;
+    if (y < YMIN) goto flagarea;
+    if (y > YMAX) goto flagarea;
+    continue;
+  flagarea:
+    catalog[0].measure[i].flags |= FLAG_AREA;
+  }
+
+  /* flag by Minst */
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    Minst = iPhotInst (&catalog[0].measure[i]);
+    if (Minst < MMIN) goto flagminst;
+    if (Minst > MMAX) goto flagminst;
+    continue;
+  flagminst:
+    catalog[0].measure[i].flags |= FLAG_MINST;
+  }
+
+  /* flag by image (dMcal? time from table?) */
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    k = imagelink[i];
+    if (image[k].dMcal > DMCAL_MIN) {
+      catalog[0].measure[i].flags |= FLAG_DMCAL;
+    }
+  }
+
+  /* allocate a list for temp storage of mag values */
+  Nlist = 0;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Nlist = MAX (Nlist, catalog[0].average[i].Nm);
+  }
+  ALLOCATE (list, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+  initstats ("MEAN");
+
+  /* the following sections apply only to PRI/SEC photcodes */
+  for (n = 0; n < photcodes.Ncode; n++) {
+    if (photcodes.code[n].type == PHOT_DEP) continue;
+    if (photcodes.code[n].type == PHOT_REF) continue;
+    Photcode = photcodes.code[n].code;
+    
+    BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_DMCAL;
+    /* 2x 3sigma clipping */
+    for (i = 0; i < catalog[0].Naverage; i++) {
+
+      /* extract good measures, calculate stats */
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	list[N] = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      if (N < 3) continue;
+      liststats (list, dlist, N, &stats);
+      Nsigma = 3.0;
+      if (N < 10) Nsigma = 0.9*N / sqrt (N - 1);
+
+      /* re-extract good measures, calculate stats */
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	Mag = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	if (fabs(Mag - stats.mean) > Nsigma*stats.sigma) continue;
+	list[N]  = Mag;
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      if (N > 2) liststats (list, dlist, N, &stats);
+
+      /* flag bad measures */
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	Mag = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	if (fabs(Mag - stats.mean) > Nsigma*stats.sigma) catalog[0].measure[m].flags |= FLAG_SIGCLIP;
+      }
+    }      
+  
+    BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_DMCAL | FLAG_SIGCLIP;
+    /* flag variables */
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      /* extract good measures, calculate chisq */
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	list[N] = iPhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*PhotNsec]);
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      liststats (list, dlist, N, &stats);
+      if (stats.chisq < CHISQ_MAX) continue;
+
+      /* flag bad measures */
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	catalog[0].measure[m].flags |= FLAG_CHISQ;
+      }
+    }	
+
+    /* flag too few valid measures */
+    BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_DMCAL | FLAG_SIGCLIP | FLAG_CHISQ;
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	N++;
+      }
+      if (N == 0) continue; // only flag objects with valid measurements, but too few
+      if (N >= NMEAS_MIN) continue;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	catalog[0].measure[m].flags |= FLAG_TOOFEW;
+      }
+    }	
+  }
+}
+
+
+/* notes
+   
+   flag by area: uses an inefficient search for the image.  
+   images should be sorted by time and we should use bisection
+   
+   number of loops over Nmeasure: 9
+
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/get_mags.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/get_mags.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/get_mags.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "photdbc.h"
+
+void get_mags (Catalog *catalog) {
+
+  int i, j, m, n, N;
+  int Nlist, Nsec, Nsecfilt, Ncode;
+  short int *Mval;
+  int Photcode, BAD_MEASURE;
+  double *list, *dlist;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "re-calculating photometry\n");
+
+  BAD_MEASURE = FLAG_AREA | FLAG_MINST | FLAG_SIGCLIP | FLAG_CHISQ | FLAG_TOOFEW;
+  Nsecfilt = catalog[0].Nsecfilt;
+
+  /* allocate a list for temp storage of mag values */
+  Nlist = 0;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Nlist = MAX (Nlist, catalog[0].average[i].Nm);
+    for (j = 0; j < Nsecfilt; j++) {
+      catalog[0].secfilt[i*Nsecfilt+j].M  = NAN;
+      catalog[0].secfilt[i*Nsecfilt+j].dM = NAN;
+      catalog[0].secfilt[i*Nsecfilt+j].Xm = NAN_S_SHORT;
+    }
+  }
+  ALLOCATE (list, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+  initstats ("WT_MEAN");
+
+  /* check on photcode */
+  for (n = 0; n < photcodes.Ncode; n++) {
+    if (photcodes.code[n].type == PHOT_DEP) continue;
+    if (photcodes.code[n].type == PHOT_REF) continue;
+    Photcode = photcodes.code[n].code;
+    Nsec = photcodes.hashNsec[Photcode];
+
+    /* find average magnitudes */
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      N = 0;
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	if ((Ncode = photcodes.hashcode[catalog[0].measure[m].photcode]) < 0) continue;
+	if (photcodes.code[Ncode].equiv != Photcode) continue;
+	if (photcodes.code[Ncode].type != PHOT_DEP) continue;
+	if (catalog[0].measure[m].flags & BAD_MEASURE) continue;
+	list[N] = PhotRel (&catalog[0].measure[m], &catalog[0].average[i],  &catalog[0].secfilt[i*Nsecfilt]);
+	dlist[N] = sqrt (SQ(DMGAIN*catalog[0].measure[m].dM) + DMSYS);
+	N++;
+      }
+      liststats (list, dlist, N, &stats);
+      if (N < 1) continue;
+    
+      Mval = (Nsec == -1) ? &catalog[0].average[i].M : &catalog[0].secfilt[i*Nsecfilt+Nsec].M;
+      *Mval = stats.mean;
+      Mval = (Nsec == -1) ? &catalog[0].average[i].dM : &catalog[0].secfilt[i*Nsecfilt+Nsec].dM;
+      *Mval = stats.sigma;
+      Mval = (Nsec == -1) ? &catalog[0].average[i].Xm : &catalog[0].secfilt[i*Nsecfilt+Nsec].Xm;
+      *Mval = 100.0*log10(stats.chisq);
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/initialize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/initialize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/initialize.c	(revision 16632)
@@ -0,0 +1,35 @@
+# include "photdbc.h"
+
+void initialize (int argc, char **argv) {
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  if (SHOW_PARAMS) {
+    fprintf (stderr, "current parameter settings:\n");
+    fprintf (stderr, "VERBOSE:                %d\n", VERBOSE);
+    fprintf (stderr, "JOIN_RADIUS:           %lf\n", JOIN_RADIUS);
+    fprintf (stderr, "UNIQ_RADIUS:           %lf\n", UNIQ_RADIUS);
+						     
+    fprintf (stderr, "XMIN:                  %lf\n", XMIN);
+    fprintf (stderr, "XMAX:                  %lf\n", XMAX);
+    fprintf (stderr, "YMIN:                  %lf\n", YMIN);
+    fprintf (stderr, "YMAX:                  %lf\n", YMAX);
+    fprintf (stderr, "MMIN:                  %lf\n", MMIN);
+    fprintf (stderr, "MMAX:                  %lf\n", MMAX);
+    fprintf (stderr, "DMCAL_MIN:             %lf\n", DMCAL_MIN);
+    fprintf (stderr, "DMSYS:                 %lf\n", DMSYS);
+						     
+    fprintf (stderr, "CHISQ_MAX:             %lf\n", CHISQ_MAX);
+    fprintf (stderr, "NMEAS_MIN:             %d\n",  NMEAS_MIN);
+
+    fprintf (stderr, "IMAGE_CATALOG          %s\n",  ImageCat);
+    fprintf (stderr, "GSCFILE                %s\n",  GSCFILE);
+    fprintf (stderr, "CATDIR                 %s\n",  CATDIR);
+    fprintf (stderr, "PHOTCODE_FILE          %s\n",  PhotCodeFile);
+
+    exit (0);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/join_stars.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/join_stars.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/join_stars.c	(revision 16632)
@@ -0,0 +1,187 @@
+# include "photdbc.h"
+
+void join_stars (Catalog *catalog) {
+
+  int i, j, k, m, M, Ni, Nj, first_j;
+  int Naves, Nmeas, Ncurr;
+  int Naverage, Nmeasure, *found, *index;
+  double *X, *Y, dX, dY, dR, RADIUS2;
+  double Sr, Sd, Rmid, Dmid;
+
+  Average *naverage, *average;
+  Measure *nmeasure, *measure;
+  SecFilt *nsecfilt, *secfilt;
+  Mpointer *mpointer;
+  Coords tcoords;
+
+  if (VERBOSE) fprintf (stderr, "joining overlapping stars\n");
+
+  average = catalog[0].average;
+  measure = catalog[0].measure;
+  secfilt = catalog[0].secfilt;
+
+  Naverage = catalog[0].Naverage;
+  Nmeasure = catalog[0].Nmeasure;
+  RADIUS2 = JOIN_RADIUS*JOIN_RADIUS;
+
+  /* reference for coords is this region */
+  Rmid = Dmid = 0;
+  for (i = 0; i < Naverage; i++) {
+    Rmid += average[i].R;
+    Dmid += average[i].D;
+  }
+  Rmid /= Naverage;
+  Dmid /= Naverage;
+
+  /* coordinate system for projection */
+  tcoords.crval1 = Rmid;
+  tcoords.crval2 = Dmid;
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  tcoords.Npolyterms = 0;
+  strcpy (tcoords.ctype, "RA---TAN");
+  
+  /* project & sort coordinates in local linear frame */
+  ALLOCATE (X, double, Naverage);
+  ALLOCATE (Y, double, Naverage);
+  ALLOCATE (index, int, Naverage);
+  for (i = 0; i < Naverage; i++) {
+    index[i] = i;
+    RD_to_XY (&X[i], &Y[i], average[i].R, average[i].D, &tcoords);
+  }
+  sort_coords_index (X, Y, index, Naverage);
+  
+  /* flags to mark if a star has been handled */
+  ALLOCATE (found, int, Naverage);
+  for (i = 0; i < Naverage; i++) found[i] = FALSE;
+
+  ALLOCATE (naverage, Average, Naverage);
+  ALLOCATE (mpointer, Mpointer, Nmeasure);
+  for (i = 0; i < Nmeasure; i++) mpointer[i].averef = -1;
+
+  Naves =  0; // counter for new averages
+  Nmeas =  0; // counter for new measures
+  for (i = j = 0; (i < Naverage) && (j < Naverage); ) {
+    
+    Ni = index[i];
+    Nj = index[j];
+
+    /* a new star, add it to naverage[] */
+    if (!found[i]) { 	
+      naverage[Naves]        = average[Ni];
+      naverage[Naves].offset = Nmeas;
+      for (k = 0; k < average[Ni].Nm; k++) {
+	m = average[Ni].offset + k;
+	mpointer[Nmeas].measure = m;
+	mpointer[Nmeas].averef  = Naves;
+	mpointer[Nmeas].R       = average[Ni].R - measure[m].dR / 3600.0;
+	mpointer[Nmeas].D       = average[Ni].D - measure[m].dD / 3600.0;
+	Nmeas ++;
+      }
+      Ncurr = Naves;
+      found[i] = TRUE;
+      Naves ++;
+    }
+
+    if (found[j]) { j++; continue; }  // don't duplicate
+    if (j == i) {   j++; continue; }  // don't auto-correlate
+
+    dX = X[i] - X[j];
+    if (dX <= -JOIN_RADIUS) { /* X[j] is too large */
+      while (found[i] && (i < Naverage)) i++;
+      continue;
+    }
+    if (dX >= +JOIN_RADIUS) { /* X[i] is too large */
+      j++;
+      continue;
+    }
+
+    first_j = j;
+    for (; (dX > -2*JOIN_RADIUS) && (j < Naverage); j++) {
+      Nj = index[j];
+      if (found[j]) continue;
+      dX = X[i] - X[j];
+      dY = Y[i] - Y[j];
+      dR = dX*dX + dY*dY;
+      if (dR < RADIUS2) {  /* matched star, join to first */
+
+	/* define pointers for new measures */
+	for (k = 0; k < average[Nj].Nm; k++) {
+	  m = average[Nj].offset + k;
+	  mpointer[Nmeas].measure = m;
+	  mpointer[Nmeas].averef  = Ncurr;
+	  mpointer[Nmeas].R       = average[Nj].R - measure[m].dR / 3600.0;
+	  mpointer[Nmeas].D       = average[Nj].D - measure[m].dD / 3600.0;
+	  Nmeas ++;
+	}
+	naverage[Ncurr].Nm += average[Nj].Nm;
+	found[j] = TRUE;
+	
+	/* recalculate naverage[Ncurr].RA,DEC */
+	/* this must be done here to keep the average position consistent
+	   for the next star found */
+	for (Sr = Sd = k = 0; k < naverage[Ncurr].Nm; k++) {
+	  m = naverage[Ncurr].offset + k;
+	  Sr += mpointer[m].R;
+	  Sd += mpointer[m].D;
+	}
+	Sr = Sr / naverage[Ncurr].Nm;
+	Sd = Sd / naverage[Ncurr].Nm;
+	naverage[Ncurr].R = Sr;
+	naverage[Ncurr].D = Sd;
+
+	/* update original measurement offsets */
+	for (k = 0; k < naverage[Ncurr].Nm; k++) {
+	  m = naverage[Ncurr].offset + k;
+	  M = mpointer[m].measure;
+	  measure[M].dR = 3600.0*(Sr - mpointer[m].R);
+	  measure[M].dD = 3600.0*(Sd - mpointer[m].D);
+	}
+
+	/* update current reference star position */
+	RD_to_XY (&X[i], &Y[i], Sr, Sd, &tcoords);
+      }
+    }
+    while (found[i] && (i < Naverage)) i++;
+    j = first_j;
+  }
+  if (Nmeas != Nmeasure) {
+    fprintf (stderr, "failure to match measures\n");
+  }
+  
+  /* create a new Measure table in the appropriate sequence */
+  ALLOCATE (nmeasure, Measure, Nmeasure);
+  for (i = 0; i < Nmeasure; i++) {
+    nmeasure[i]        = measure[mpointer[i].measure];
+    nmeasure[i].averef = mpointer[i].averef;
+  }
+
+  /* create an empty SecFilt table */
+  ALLOCATE (nsecfilt, SecFilt, Naves*catalog[0].Nsecfilt);
+  bzero (nsecfilt, Naves*catalog[0].Nsecfilt*sizeof(SecFilt));
+
+  free (catalog[0].average);
+  free (catalog[0].measure);
+  free (catalog[0].secfilt);
+
+  catalog[0].average = naverage;
+  catalog[0].measure = nmeasure;
+  catalog[0].secfilt = nsecfilt;
+  
+  catalog[0].Naverage = Naves;
+  catalog[0].Nsecf_mem = Naves*catalog[0].Nsecfilt;
+}
+
+/* notes:
+   merge averages of stars within RADIUS to single stars 
+   updates the average RA and DEC fields
+   creates a new Average table 'naverage' 
+   updates the Measure table to the new sequence
+   generates a new SecFilt table with empty values 
+   does NOT update magnitudes 
+   output measure table is the same size as the input measure table
+   (measures are just moved around).  thus, catalog[0].Nmeasure does not change.
+*/   
+   
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/liststats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/liststats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/liststats.c	(revision 16632)
@@ -0,0 +1,114 @@
+# include "photdbc.h"
+
+enum {M_MEAN, M_MEDIAN, M_WT_MEAN, M_INNER_MEAN, 
+      M_INNER_WTMEAN, M_CHI_INNER_MEAN, M_CHI_INNER_WTMEAN};
+
+static int statmode;
+
+void initstats (char *mode) {
+
+  statmode = -1;
+  if (!strcmp (mode, "MEAN")) statmode = M_MEAN;
+  if (!strcmp (mode, "MEDIAN")) statmode = M_MEDIAN;
+  if (!strcmp (mode, "WT_MEAN")) statmode = M_WT_MEAN;
+  if (!strcmp (mode, "INNER_MEAN")) statmode = M_INNER_MEAN;
+  if (!strcmp (mode, "INNER_WTMEAN")) statmode = M_INNER_WTMEAN;
+  if (!strcmp (mode, "CHI_INNER_MEAN")) statmode = M_CHI_INNER_MEAN;
+  if (!strcmp (mode, "CHI_INNER_WTMEAN")) statmode = M_CHI_INNER_WTMEAN;
+
+  if (statmode == -1) {
+    fprintf (stderr, "ERROR: invalid stats mode: %s\n", mode);
+    exit (1);
+  }
+}
+
+int liststats (double *value, double *dvalue, int N, StatType *stats) {
+  
+  int i, ks, ke, Nm;
+  double Mo, dMo, M, dM, X2, dS, *chi;
+
+  stats[0].Nmeas = N;
+  stats[0].mean  = 0;
+  if (N < 2) return (FALSE);
+
+  dsortpair (value, dvalue, N);
+  stats[0].median = value[(int)(0.5*N)];
+  stats[0].min    = value[0];
+  stats[0].max    = value[N-1];
+
+  switch (statmode) {
+  case M_MEDIAN:
+    ks = 0;
+    ke = N;
+    Mo = stats[0].median;
+    Nm = N;
+    goto chisq;
+    break;
+  case M_MEAN:
+  case M_WT_MEAN:
+    ks = 0;
+    ke = N;
+    break;
+  case M_INNER_MEAN:
+  case M_INNER_WTMEAN:
+  case M_CHI_INNER_MEAN:
+  case M_CHI_INNER_WTMEAN:
+    ks = 0.25*N + 0.50;
+    ke = 0.75*N + 0.25;
+    if (N <= 3) {
+      ks = 0;
+      ke = N;
+    }
+    break;
+  }    
+
+  if ((statmode == M_CHI_INNER_MEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    ALLOCATE (chi, double, N);
+    for (i = 0; i < N; i++) {
+      chi[i] = (value[i] - stats[0].median) / dvalue[i];
+    }
+    dsortthree (chi, value, dvalue, N);
+    free (chi);
+  }
+
+  /* calculating the per-star offset based on the weighted average */
+  M = dM = Nm = 0;
+  if ((statmode == M_WT_MEAN) || (statmode == M_INNER_WTMEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    for (i = ks; i < ke; i++) {
+      M   += value[i] / SQ (dvalue[i]);
+      dM  += 1.0 / SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / dM;
+    dMo = sqrt (1.0 / dM);
+  } else {
+    for (i = ks; i < ke; i++) {
+      M   += value[i];
+      dM  += SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / (double) Nm;
+    dMo = sqrt (dM / (double) Nm);
+  }
+
+ chisq:
+  /* find sigma and chisq */
+  X2 = dS = 0;
+  for (i = ks; i < ke; i++) {
+    M  = SQ (value[i] - Mo);
+    dM = SQ (dvalue[i]);
+    X2 += M / dM;
+    dS += M;
+  }
+  X2 = X2 / Nm;
+  dS = sqrt (dS / Nm);
+
+  stats[0].mean  = Mo;
+  stats[0].Nmeas = Nm;
+  stats[0].chisq = X2;
+  stats[0].sigma = dS;
+  stats[0].error = dMo;
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/make_subcatalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/make_subcatalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/make_subcatalog.c	(revision 16632)
@@ -0,0 +1,111 @@
+# include "photdbc.h"
+
+// copy a catalog to a new subcatalog, applying some filters
+// the supplied subcatalog must already be locked, opened, and created
+int make_subcatalog (Catalog *subcatalog, Catalog *catalog) {
+  
+  int i, j, offset;
+  int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm, Nsecfilt;
+  double mag, minMag;
+
+  Nsecfilt = GetPhotcodeNsecfilt ();
+  assert (catalog[0].Nsecfilt == Nsecfilt);
+
+  /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
+  NAVERAGE = 50;
+  NMEASURE = 1000;
+  Nmeasure = Naverage = 0;
+  REALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+  REALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*Nsecfilt);
+  REALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    // perform exclusions based on average properties
+
+    // exclude stars with too few measurements
+    if (NMEAS_MIN && (catalog[0].average[i].Nm < NMEAS_MIN)) continue; 
+
+    /* assign average and secfilt values */
+    subcatalog[0].average[Naverage] = catalog[0].average[i];
+    subcatalog[0].average[Naverage].offset = Nmeasure;
+    for (j = 0; j < Nsecfilt; j++) {
+      subcatalog[0].secfilt[Nsecfilt*Naverage+j] = catalog[0].secfilt[Nsecfilt*i+j];
+    }
+
+    minMag = 32;
+    Nm = 0;
+    for (j = 0; j < catalog[0].average[i].Nm; j++) {
+
+      offset = catalog[0].average[i].offset + j;
+
+      # if 0
+      if (DropPhotcode) {
+	ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[offset].photcode);
+	if (ecode == photcode[0].code) continue;
+      }
+      if (DropNonStellar && catalog[0].measure[offset].dophot != 1) continue;
+      # endif
+
+      /* exclude measurements by measurement error */
+      if (SIGMA_MAX && (catalog[0].measure[offset].dM > SIGMA_MAX)) continue;
+
+      /* select measurements by mag limit */
+      if (ExcludeByInstMag) {
+	mag = PhotInst (&catalog[0].measure[offset]);
+	if (mag < INST_MAG_MIN) continue;
+	if (mag > INST_MAG_MAX) continue;
+      }
+
+      if (ExcludeByMaxMinMag) {
+	mag = PhotSys (&catalog[0].measure[offset], &catalog[0].average[i], &catalog[0].secfilt[i*Nsecfilt]);
+	minMag = MIN (minMag, mag);
+      }
+
+      subcatalog[0].measure[Nmeasure]        = catalog[0].measure[offset];
+      subcatalog[0].measure[Nmeasure].averef = Naverage;
+      Nmeasure ++;
+      Nm ++;
+      if (Nmeasure == NMEASURE) {
+	NMEASURE += 1000;
+	REALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+      }
+    }
+
+    // exclude faint objects
+    if (ExcludeByMaxMinMag && (minMag > MAX_MIN_MAG)) {
+      Nmeasure -= Nm;
+      continue; 
+    }
+
+    // after measurement exclusion, exclude stars with too few measurements
+    if (Nm < NMEAS_MIN) {
+      Nmeasure -= Nm;
+      continue; 
+    }
+    subcatalog[0].average[Naverage].Nn = 0;
+    subcatalog[0].average[Naverage].Nm = Nm;
+    Naverage ++;
+    if (Naverage == NAVERAGE) {
+      NAVERAGE += 50;
+      REALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+      REALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*Nsecfilt);
+    }
+  }
+  REALLOCATE (subcatalog[0].average, Average, MAX (Naverage, 1));
+  REALLOCATE (subcatalog[0].measure, Measure, MAX (Nmeasure, 1));
+  REALLOCATE (subcatalog[0].secfilt, SecFilt, Nsecfilt*MAX (Naverage, 1));
+  subcatalog[0].Naverage = Naverage;
+  subcatalog[0].Nmeasure = Nmeasure;
+  subcatalog[0].Nsecfilt = Nsecfilt;
+  subcatalog[0].Nsecf_mem = Naverage * Nsecfilt;
+
+  // XXX for now, don't copy the missing entries (these should be re-computed)
+  ALLOCATE (subcatalog[0].missing, Missing, 1);
+  subcatalog[0].Nmissing = 0;
+
+  if (VERBOSE) {
+    fprintf (stderr, "%d: using %d stars (%d measures) for catalog\n", i, 
+	     subcatalog[0].Naverage, subcatalog[0].Nmeasure);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/misc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/misc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/misc.c	(revision 16632)
@@ -0,0 +1,16 @@
+# include "photdbc.h"
+
+void sort_time (unsigned int *X, int *Y, int N) {
+
+# define SWAPFUNC(A,B){ float tmp; \
+  unsigned int utmp = X[A]; X[A] = X[B]; X[B] = utmp; \
+  int          itmp = Y[A]; Y[A] = Y[B]; Y[B] = itmp; \
+}
+# define COMPARE(A,B)(X[A] < X[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/overlap_funcs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/overlap_funcs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/overlap_funcs.c	(revision 16632)
@@ -0,0 +1,78 @@
+# include "photdbc.h"
+
+/* check if line between points 0 and 1 of x1
+   crosses line between points 0 and 1 of x2 */
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/* check if point x1,y1 is in box formed by x2[0-4] */
+int corner_check (double *x1, double *y1, double *x2, double *y2) {
+
+  int i;
+  double theta;
+
+  theta = 0;
+
+  for (i = 0; i < 4; i++) {
+    theta += opening_angle (x2[i], y2[i], x1[0], y1[0], x2[i+1], y2[i+1]); 
+  }
+  if (fabs(theta) > 6) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+}
+
+/* returns the opening angle between the three points (2 is in middle) 
+   in range -pi to pi */
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/photdbc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/photdbc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/photdbc.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "photdbc.h"
+
+int main (int argc, char **argv) {
+
+  int i;
+  char *skyfile;
+  Catalog incatalog;
+  Catalog outcatalog;
+  SkyTable *sky;
+  SkyList *skylist;
+
+  /* get configuration info, args, lockfile */
+  initialize (argc, argv);
+
+  // load and copy the image table
+  copy_images (argv[1]);
+
+  // the output catalog needs to inherit the SKY_DEPTH of the input catalog
+  sky = SkyTableLoadOptimal (CATDIR, NULL, GSCFILE, SKY_DEPTH_HST, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  skylist = SkyListByPatch (sky, -1, &REGION);
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    if (i % 100 == 0) fprintf (stderr, "%s\n", skylist[0].regions[i][0].name);
+
+    // set the parameters which guide catalog open/load/create
+    incatalog.filename = skylist[0].filename[i];
+    incatalog.Nsecfilt = GetPhotcodeNsecfilt ();
+    incatalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_SECF;
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&incatalog, skylist[0].regions[i], VERBOSE, "r")) {
+      fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", incatalog.filename);
+      exit (2);
+    }
+    // skip empty input catalogs
+    if (!incatalog.Naves_disk) {
+      dvo_catalog_unlock (&incatalog);
+      dvo_catalog_free (&incatalog);
+      continue;
+    }
+
+    // create output catalog filename
+    outcatalog.filename = strsubs (incatalog.filename, CATDIR, argv[1]);
+    if (outcatalog.filename == NULL) Shutdown ("error with input catalog name");
+
+    // define outcatalog open parameters
+    outcatalog.catformat = dvo_catalog_catformat (CATFORMAT);  // set the default catformat from config data
+    outcatalog.catmode   = dvo_catalog_catmode (CATMODE);      // set the default catmode from config data
+    outcatalog.Nsecfilt  = incatalog.Nsecfilt;                 // inherit from the incatalog
+    outcatalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+    // output catalogs always represent the same skyregions as the input catalogs
+    if (!dvo_catalog_open (&outcatalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", outcatalog.filename);
+      exit (2);
+    }
+
+    /* limit number of measures based on selections */
+    make_subcatalog (&outcatalog, &incatalog);
+	
+    // XXX add other filters here:
+    // join_stars (catalog);
+    // unique_measures (catalog);
+    // flag_measures (&db, catalog);
+    // get_mags (catalog);
+
+    dvo_catalog_save (&outcatalog, VERBOSE);
+    dvo_catalog_unlock (&outcatalog);
+    dvo_catalog_free (&outcatalog);
+
+    dvo_catalog_unlock (&incatalog);
+    dvo_catalog_free (&incatalog);
+  }
+
+  ALLOCATE (skyfile, char, strlen(argv[1]) + strlen("/SkyTable.fits") + 1);
+  sprintf (skyfile, "%s/SkyTable.fits", argv[1]);
+  SkyTableSave (sky, skyfile);
+  exit (0);
+}
Index: /branches/eam_branch_20080223/Ohana/src/photdbc/src/unique_measures.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/photdbc/src/unique_measures.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/photdbc/src/unique_measures.c	(revision 16632)
@@ -0,0 +1,110 @@
+# include "photdbc.h"
+
+void unique_measures (Catalog *catalog) {
+
+  int i, j, k, m, N;
+  int No, Nm, Nvalid, Nlist;
+  int *ilist;
+  unsigned int *tlist;
+  Measure *mlist, *nmeasure;
+  double dR, dD, R, RADIUS2;
+  Average *p;
+
+  if (VERBOSE) fprintf (stderr, "removing duplicate measurements\n");
+
+  /* allocate a list for temp storage of measure values */
+  Nlist = 0;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Nlist = MAX (Nlist, catalog[0].average[i].Nm);
+  }
+  ALLOCATE (ilist, int, Nlist);
+  ALLOCATE (tlist, unsigned int, Nlist);
+  ALLOCATE (mlist, Measure, Nlist);
+
+  RADIUS2 = SQ(UNIQ_RADIUS);
+  
+  p = catalog[0].average;
+  for (i = 0; i < catalog[0].Naverage; i++) {
+
+    if (catalog[0].average != p) {
+      fprintf (stderr, "error\n");
+    }
+
+    /* extract list of measurements */
+    N = 0;
+    m = catalog[0].average[i].offset;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+      ilist[N] = m;
+      tlist[N] = catalog[0].measure[m].t;
+      N++;
+    }
+
+    /* sort the images by time */
+    sort_time (tlist, ilist, N);
+
+    /* look for duplicates */
+    for (j = k = 0; (j < N) && (k < N); j++) {
+      if (j == k) {
+	k++;
+	continue;
+      }
+      if (tlist[j] != tlist[k]) {
+	j++;
+	k = j + 1;
+	continue;
+      }
+      if (catalog[0].measure[ilist[j]].flags & FLAG_DUPMEAS) {
+	j++;
+	k = j + 1;
+	continue;
+      }
+      
+      dR = (catalog[0].measure[ilist[j]].dR - catalog[0].measure[ilist[k]].dR);
+      dD = (catalog[0].measure[ilist[j]].dD - catalog[0].measure[ilist[k]].dD);
+      R = SQ(dR) + SQ(dD);
+      
+      /* dR, dD in arcsec, RADIUS is 0.1 arcsec */
+      if (R < RADIUS2) {
+	/* matched pair */
+	catalog[0].measure[ilist[k]].flags |= FLAG_DUPMEAS;
+      }
+      k++;
+    }
+  }
+
+  Nvalid = 0;
+  for (i = 0; i < catalog[0].Nmeasure; i++) {
+    if (!(catalog[0].measure[i].flags & FLAG_DUPMEAS)) Nvalid ++;
+  }
+
+  No = 0;
+  ALLOCATE (nmeasure, Measure, MAX (Nvalid, 1));
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    /* copy valid measures to new table, update offset, Nm */
+    Nm = 0;
+    m = catalog[0].average[i].offset;
+    catalog[0].average[i].offset = No;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++, No++) {
+      if (catalog[0].measure[m].flags & FLAG_DUPMEAS) continue;
+      nmeasure[No] = catalog[0].measure[m];
+      if (catalog[0].measure[m].averef != i) { 
+	fprintf (stderr, "average reference mismatch!!\n");
+      }
+      Nm ++;
+    }
+    catalog[0].average[i].Nm = Nm;
+  }
+
+  free (catalog[0].measure);
+  catalog[0].measure = nmeasure;
+  catalog[0].Nmeasure = No;
+
+}
+
+/*** XXX 
+     this function does not quite do the right thing.  it should remove duplicate measurements 
+     for a single average object.  unique measurements have a unique combination of time and photcode
+     (IS this true?  only for DET, not for REF...)
+***/
+
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/Makefile	(revision 16632)
@@ -0,0 +1,57 @@
+default: relastro
+help:
+	@echo "make options: relastro (default)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/relastro
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+relastro: $(BIN)/relastro.$(ARCH)
+install: $(DESTBIN)/relastro
+
+RELASTRO = \
+$(SRC)/ConfigInit.$(ARCH).o	 \
+$(SRC)/FitChip.$(ARCH).o         \
+$(SRC)/FitMosaic.$(ARCH).o       \
+$(SRC)/FitPM.$(ARCH).o           \
+$(SRC)/FitPar.$(ARCH).o          \
+$(SRC)/FitPMandPar.$(ARCH).o     \
+$(SRC)/FitSimple.$(ARCH).o       \
+$(SRC)/ImageOps.$(ARCH).o	 \
+$(SRC)/MosaicOps.$(ARCH).o	 \
+$(SRC)/ParFactor.$(ARCH).o       \
+$(SRC)/SetSignals.$(ARCH).o 	 \
+$(SRC)/Shutdown.$(ARCH).o 	 \
+$(SRC)/UpdateChips.$(ARCH).o     \
+$(SRC)/UpdateMosaic.$(ARCH).o    \
+$(SRC)/UpdateObjects.$(ARCH).o   \
+$(SRC)/UpdateSimple.$(ARCH).o    \
+$(SRC)/args.$(ARCH).o		 \
+$(SRC)/bcatalog.$(ARCH).o	 \
+$(SRC)/dvo_astrom_ops.$(ARCH).o  \
+$(SRC)/fitpoly.$(ARCH).o         \
+$(SRC)/initialize.$(ARCH).o	 \
+$(SRC)/liststats.$(ARCH).o	 \
+$(SRC)/load_catalogs.$(ARCH).o	 \
+$(SRC)/load_images.$(ARCH).o	 \
+$(SRC)/mkpolyterm.$(ARCH).o      \
+$(SRC)/plot_scatter.$(ARCH).o	 \
+$(SRC)/plotstuff.$(ARCH).o	 \
+$(SRC)/select_images.$(ARCH).o	 \
+$(SRC)/relastro.$(ARCH).o	 \
+$(SRC)/save_catalogs.$(ARCH).o   \
+$(SRC)/setExclusions.$(ARCH).o 	 \
+$(SRC)/write_coords.$(ARCH).o
+
+$(RELASTRO): $(INC)/relastro.h $(KAPA_INCS)
+$(BIN)/relastro.$(ARCH): $(RELASTRO) $(KAPA_LIBS)
Index: /branches/eam_branch_20080223/Ohana/src/relastro/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/relastro/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/doc/notes.txt	(revision 16632)
@@ -0,0 +1,110 @@
+
+2007.11.12
+
+  relastro is working for the SIMPLE (single-chip) and CHIP
+  (mosaic-chip) modes.  it is not yet working for the MOSAIC mode.
+  The image table contains one mosaic entry and N chip entries for a
+  mosaic with N chips.  The mosaic entry has coord.ctype = DIS, while
+  the corresponding chips have coord.ctype = WRP (and matching
+  time/photcodes).
+
+  (this is fairly weak. we should just define the relationship when we
+  register the chips...)
+
+2007.10.06
+
+  relastro currently loads the set of detections, averages, and image,
+  and sets up arrays of pointers to define the relationships beteen
+  the detections, objects, and images.  This is probably an acceptable
+  scheme.  
+
+  However, the generation of those index arrays is probably very
+  inefficient.  Currently it is written for the old DVO tables in
+  which there was no real link between the detection and image.  We
+  are trying to move to a situation where each detection has a
+  reference to the image (imageID).  If this is unique, then we should
+  be able to make these links directly.
+
+  Outstanding issues:
+
+  * am I getting the correct set of matches for the mosaic images? 
+    ie, do getImageRaw & getImageRef return the correct list when the
+    image is a DIS mosaic image?
+
+  * is the operation in fit_apply_coords doing the correct thing?
+    compare this to psastro code.  This should not be a problem since
+    we are only fitting in the linear frames.  we are just fitting
+    simple polynomials.  We are not changing the reference coordinate
+    for the projection.
+
+  * measure the errors?
+
+  * apply the magnitude errors as weight?
+
+  * improve matching process with the index information available?
+
+  * add the ability to down-weight groups of detections by photcode?
+
+2007.02.11
+
+  relastro major modes:
+
+  - update the astrometry of objects in the images
+    - load objects within a region
+    - foreach object
+      - calculate average R,D
+      - update db tables (dR, dD)
+    - include external trends
+      - parallax factor
+      - atm trends
+
+  - update the astrometric parameters of images
+    - use the average R,D for objects, update image terms
+    * include external refs with adjustable weighting
+
+  - image parameter smoothing
+
+  - simultaneous fit of objects and images
+    - identify parameters to constrain
+    - limited number of internal objects?
+
+
+2006.04.08 : relastro contemplations
+
+relastro will perform the astrometry equivalent to relphot.  For
+region, it loads in the average objects, detections, and image
+parameters.  The goal is to determine improved astrometric positions
+of objects in the images and to determine improved astrometric
+parameters for the images.  Just like relphot, this is an iterative
+process in which the object postions are improved in one step, the
+image parameters are improved in the next, then back to the images.
+
+Relastro needs to deal with outlier objects in a robust way.  There
+are a few reasons why objects should have poor astrometric solutions,
+and these can be flagged up front: saturation and too many bad pixels.
+For detections which come from psphot, we can use the quality
+parameter to exclude objects which have excessively high bad pixel
+counts.  For detections from sextractor or other analysis tools,
+this information is missing.  In this case, we can use the distance
+from the image boundaries as a trigger.
+
+An open question to be addressed is the issue of external calibration
+sources.  Unlike photometry, external astrometric measurements do not
+need to have an unknown filter transformation applied.  They can thus
+be included as part of the solution automatically.  It is not clear,
+however, how to include *proper-motion* data in the analysis.  If I
+introduce, for example, USNO objects with proper motions, the
+information provided consists in practice of a velocity vector and
+errors.  How does this get folded into the fit?  One answer is to
+construct additional artificial datapoints for each entry with the
+proper errors and epochs.  Seems like something of a hack.  
+
+We may want to allow for different errors / weightings for the
+different external sources.
+
+After the initial iterations, we will can solve for proper-motion and
+parallax for (all?) objects
+
+- calculate the parallax normal vector for each image
+- calculate the atmospheric / orbital motion effects for each image
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/doc/parallax.pro
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/doc/parallax.pro	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/doc/parallax.pro	(revision 16632)
@@ -0,0 +1,348 @@
+
+macro sample
+  PMsim 15 30 20 10 $ANGLE
+  set dX = zero(X) + 10
+  set dY = zero(Y) + 10
+
+  style -c black
+  plot -x 2 -pt 2 -sz 2.0 X Y -dx dX -dy dY
+
+  # set x = (1000.0/$dS)*cos(t*$TP) + $vX*t
+  # set y = (1000.0/$dS)*sin(t*$TP)*dsin($ANGLE) + $vY*t
+  # plot -c grey60 -x 2 -sz 2.0 -pt 7 x y
+
+  create t 0 1.5 0.01
+  set x = (1000.0/$dS)*cos(t*$TP) + $vX*t
+  set y = (1000.0/$dS)*sin(t*$TP)*dsin($ANGLE) + $vY*t
+  plot -c grey60 -x 0 x y
+
+  # label -x "offset east (milliarcsec)"
+  # label -y "offset north (milliarcsec)"
+end
+
+macro PMsim
+  if ($0 != 6)
+    echo "USAGE: PMsim Do vX vY dP dT"
+    echo "Do : distance in parsec"
+    echo "vX, vY : velocity (milliarcsec/year)"
+    echo "dP : astrometric scatter (arcsec)"
+    echo "dT : ecliptic lattitude (degrees)"
+    break
+  end
+
+  $TP = 2*3.1416
+
+  $dS = $1
+  $vX = $2
+  $vY = $3
+  $dP = $4
+  $dT = $5
+
+  mkbase
+
+  set x = (1000.0/$dS)*cos(t*$TP) + $vX*t
+  set y = (1000.0/$dS)*sin(t*$TP)*dsin($dT) + $vY*t
+
+  gaussdev dx x[] 0.0 $dP
+  gaussdev dy y[] 0.0 $dP 
+
+  set X = x + dx
+  set Y = y + dy
+
+  if ($PLOT)
+    lim -200 200 -200 200; clear; box;
+    style -c black
+    plot -x 2 -pt 2 -sz 2.0 X Y
+    plot -x 0 X Y
+  end
+
+  PMfit X Y t $dT
+
+  if ($PLOT) 
+    label -x "offset east (milliarcsec)"
+    label -y "offset north (milliarcsec)"
+    section a 0 0 1 1
+    lim 0 1 0 1
+    sprintf line "input: D: %5.1f (pc), V: %5.1f, %5.1f (mas/yr), dS: %4.1f" $1 $2 $3 $4
+    textline -fn courier 14 0.15 0.95 "$line"
+    sprintf line "fit:    D: %5.1f (pc), V: %5.1f, %5.1f (mas/yr)" $dS $vX $vY
+    textline -fn courier 14 0.15 0.90 "$line"
+    section default
+  end
+end
+
+macro PMfit
+  if ($0 != 5)
+    echo "USAGE: PMfit X Y t (theta)"
+    echo "X,Y are offsets in milliarcsec"
+    echo "t is time in years"
+    break
+  end
+
+  $TP = 2*3.1416
+  set x = $1
+  set y = $2
+  set t = $3
+  set cs = cos(t*$TP)
+  set snx = sin(t*$TP)*dsin($4)
+
+  mcreate A 3 3
+  create B 0 3
+
+  # define A values:
+  set tmp = cs^2 + snx^2
+  vstat -q tmp
+  zap A 0 0 1 1 -v $TOTAL
+
+  set tmp = t*cs
+  vstat -q tmp
+  zap A 1 0 1 1 -v $TOTAL
+  zap A 0 1 1 1 -v $TOTAL
+
+  set tmp = t*snx
+  vstat -q tmp
+  zap A 2 0 1 1 -v $TOTAL
+  zap A 0 2 1 1 -v $TOTAL
+
+  set tmp = t^2
+  vstat -q tmp
+  zap A 1 1 1 1 -v $TOTAL
+  zap A 2 2 1 1 -v $TOTAL
+
+  zap A 2 1 1 1 -v 0
+  zap A 1 2 1 1 -v 0
+
+  # define B values:
+  set tmp = x*cs + y*snx
+  vstat -q tmp
+  B[0] = $TOTAL
+
+  set tmp = x*t
+  vstat -q tmp
+  B[1] = $TOTAL
+
+  set tmp = y*t
+  vstat -q tmp
+  B[2] = $TOTAL
+
+  gaussj A B
+
+  $dS = 1000/B[0]
+  $vX = B[1]
+  $vY = B[2]
+
+  if ($PLOT)
+    echo "Do: $dS"
+    echo "vX: $vX"
+    echo "vY: $vY"
+
+    set x = (1000.0/$dS)*cos(t*$TP) + $vX*t
+    set y = (1000.0/$dS)*sin(t*$TP)*dsin($4) + $vY*t
+    plot -c red -x 2 -sz 2.0 -pt 7 x y
+  end
+end
+
+macro PMstats
+  
+  if ($0 != 7)
+    echo "USAGE: PMsim Do vX vY dP dT (Niter)"
+    echo "Do : distance in parsec"
+    echo "vX, vY : velocity (milliarcsec/year)"
+    echo "dP : astrometric scatter (arcsec)"
+    echo "dT : ecliptic lattitude (degrees)"
+    break
+  end
+
+  delete -q vx vy ds
+  $PLOT = 0
+
+  for i 0 $6
+    PMsim $1 $2 $3 $4 $5
+    concat $dS ds
+    concat $vX vx
+    concat $vY vy
+  end
+
+  vstat ds
+  vstat vx
+  vstat vy
+
+  set gm = 1000/ds
+  vstat gm
+
+  clear -s -n 1
+  label -fn courier 14
+  # section a 0.0 0.0 0.5 1.0
+  lim {$2-30} {$2+30} {$3-30} {$3+30}; box
+  plot -x 2 -pt 2 -sz 0.5 vx vy
+  label -x "p.m. (east, mas/yr)"
+  label -y "p.m. (east, mas/yr)"
+
+  clear -s -n 2
+  # section b 0.5 0.0 0.5 1.0
+  histogram gm Ng {1000/$1 - 30.0} {1000/$1 + 30.0} 1.0
+  create dg {1000/$1 - 30.0} {1000/$1 + 30.0} 1.0
+  lim dg Ng; box
+  plot -x 1 dg Ng
+
+  label -x "parallax (mas)"
+  label -y "# of tests"
+
+end
+
+macro PMtrend
+
+  PMstats 10 5.0 5.0 10 90 100
+  echo 10
+  PMstats 10 5.0 5.0 {750/2.38/25} 90 100
+  echo {750/2.38/25} 
+  PMstats 10 5.0 5.0 {750/2.38/10} 90 100
+  echo {750/2.38/10} 
+  PMstats 10 5.0 5.0 {750/2.38/5} 90 100
+  echo {750/2.38/5} 
+end
+
+list dist
+  5
+  10
+  15
+  20
+  30
+  40
+  50
+  60
+  70
+  80
+end
+
+macro ParDetect
+
+  local i
+  delete -q xp yp dyp dym
+  
+  $ANGLE = 45
+
+  for i 0 $dist:n
+    PMstats $dist:$i 5.0 5.0 10 $ANGLE 100
+    concat $dist:$i xp
+    concat {1000/$MEAN} yp
+    concat {1000/($MEAN - $SIGMA) - 1000/$MEAN} dyp
+    concat {1000/$MEAN - 1000/($MEAN + $SIGMA)} dym
+  end
+
+  section a 0.0 0.0 0.5 1.0
+
+  lim xp -1.0 101; clear; box; 
+  plot -c black -x 2 xp yp -dy dym +dy dyp
+  
+  delete -q xp yp 
+  concat 0 xp
+  concat 100 xp
+  set yp = xp
+  plot -x 0 -c blue xp yp
+
+  set yp = zero(xp) + 62.5
+  plot -x 0 -c red -lt 1 xp yp
+  style -lt 0  
+  label -x "input dist (pc)" -y "output dist" -fn courier 14
+
+  $PLOT = 0
+  section b 0.5 0.0 0.5 1.0
+  lim -120 120 -120 120; box -labels 1001;
+
+  for i 0 5
+   sample
+  end
+
+  label -x "offset east (milliarcsec)"
+  label +y "offset north"
+  ps -name ParallaxDist.ps
+end
+
+macro fields
+
+  $Dx = 0.25*4800*8/3600
+  $Fo = 1.09
+
+  $dD = 2.65/1.09
+
+  $Nf = 0
+  for i {-30+$dD/2} 90 $dD
+    $Np = int(dcos($i)*1.09*360/2.65) + 1
+    $Nf = $Nf + $Np
+    fprintf "%5.1f %5.1f %4d %4d" $i {dcos($i)*1.09*360/2.65} $Np $Nf 
+  end
+end
+
+macro SNsim
+  $w  = 0.76
+  $m1 = 24.8
+  $mu = 20.4
+
+  lim 13.5 26.5 0.0 4.0; clear; box
+
+  $t = 1
+  SN
+
+  $t = 5
+  SN
+
+  $t = 30
+  SN
+
+  $t = 100
+  SN
+
+  set sn = 5 + zero (m)
+  set lsn = log(sn)
+  plot -lt 2 m lsn
+
+  set sn = 25 + zero (m)
+  set lsn = log(sn)
+  plot -lt 2 m lsn
+
+  set sn = 100 + zero (m)
+  set lsn = log(sn)
+  plot -lt 2 m lsn
+  style -lt 0
+end
+
+macro SN
+  create m 14 26 0.1
+  set sn = ten (-0.2*(2*m - $mu - $m1)) * sqrt($t/$w^2/3.1416)
+  set lsn = log(sn)
+  plot m lsn
+end
+
+# r: 30s @ 5sig = 22.65  (0.6")
+# i: 30s @ 5sig = 22.42  (0.6")
+# i: 30s @ 5sig = 22.27  (for 0.3 mag lower zp)
+
+macro mkbase
+  delete -q t
+  concat 0.0 t
+  concat {10.0/365.0} t
+  concat {20.0/365.0} t
+  concat { 6.0/52.0} t
+
+  concat { 3.0/12.0} t
+  concat { 6.0/12.0} t
+  concat {12.0/12.0} t
+  concat {18.0/12.0} t
+end
+
+
+macro parfactor
+
+  $RA = $1
+  $Dec = $2
+  $e = 23 + 27/60
+  
+  create s 0 360
+  set pR = dcos($e)*d
+
+  set pR =  +(dcos($e)*dsin(s)*dcos($RA) - dcos(s)*dsin($RA))
+  set pD =  -(dcos($e)*dsin(s)*dsin($RA) + dcos(s)*dcos($RA))*dsin($Dec) + dsin($e)*dsin(s)*dcos($Dec)
+
+  lim -1.1 1.1 -1.1 1.1; clear; box; plot pR pD
+end
Index: /branches/eam_branch_20080223/Ohana/src/relastro/include/relastro.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/include/relastro.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/include/relastro.h	(revision 16632)
@@ -0,0 +1,300 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <kapa.h>
+# include <signal.h>
+
+typedef enum {
+  MODE_SIMPLE,
+  MODE_CHIP,
+  MODE_MOSAIC,
+} CoordMode;
+
+typedef struct {
+  double R, D;  /* Sky Coords    - degrees */
+  double P, Q;  /* Tangent Plane - pixels  */
+  double L, M;  /* Focal Plane   - pixels  */
+  double X, Y;  /* Chip Coords   - pixels  */
+  double Mag, dMag;
+  int mask;
+} StarData;
+
+// structure to hold coordinate fitting terms
+typedef struct {
+    int Npts;
+    int Nterms;
+    int Norder;
+    int Nsums;
+    int Nelems;
+    double **sum;
+    double **xsum;
+    double **ysum;
+    double **xfit;
+    double **yfit;
+} CoordFit;
+
+typedef struct {
+  double Ro, dRo;
+  double Do, dDo;
+  
+  double uR, duR;
+  double uD, duD;
+
+  double p, dp;
+
+  double chisq;
+  int Nfit;
+} PMFit;
+
+typedef struct {
+  unsigned int start;
+  unsigned int stop;
+  float Mcal;
+  float dMcal;
+  short Xm;
+  float secz;
+  char code;
+  Coords coords;
+} Mosaic; 
+
+typedef struct {
+  double median;
+  double mean;
+  double sigma;
+  double error;
+  double chisq;
+  double min;
+  double max;
+  double total;
+  int    Nmeas;
+} StatType;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char   CameraConfig[256];
+char   SKY_TABLE[256];
+int    SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
+
+double MAG_LIM;
+double SIGMA_LIM;
+double IMAGE_SCATTER;
+double IMAGE_OFFSET;
+double STAR_SCATTER;
+double STAR_CHISQ;
+double MIN_ERROR;
+
+int    VERBOSE;
+
+int    NLOOP;
+int    RESET;
+int    UPDATE;
+int    PLOTSTUFF;
+int    SAVEPLOT;
+int    SHOW_PARAMS;
+char   MOSAICNAME[256];
+char   STATMODE[32];
+int    STAR_BAD;
+int    MEAS_BAD;
+int    POS_TOOFEW;
+int    PM_TOOFEW;
+double PM_DT_MIN;
+int    IMAGE_TOOFEW;
+double IMAGE_GOOD_FRACTION;
+int    IMAGE_BAD;
+int    FREEZE_IMAGES;
+int    USE_GRID;
+int    PLOTDELAY;
+
+int    RELPHOT_GRID_X;
+int    RELPHOT_GRID_Y;
+int    RELPHOT_GRID_BINNING;
+
+char          *PHOTCODE_LIST;
+int           Nphotcodes;
+PhotCode     **photcodes;
+int            PhotPrimary;
+int            PhotNsec;
+
+int AreaSelect;
+double AreaXmin, AreaXmax, AreaYmin, AreaYmax;
+
+int ImagSelect, ImagMin, ImagMax;
+
+double  PlotMmin, PlotMmax, PlotdMmin, PlotdMmax;
+enum {black, white, red, orange, yellow, green, blue, indigo, violet};
+
+int DophotSelect, DophotValue;
+
+int TimeSelect;
+time_t TSTART, TSTOP;
+
+int FIT_MODE;
+enum {FIT_NONE, FIT_AVERAGE, FIT_PM_ONLY, FIT_PAR_ONLY, FIT_PM_AND_PAR};
+
+int FIT_TARGET;
+enum {TARGET_NONE, TARGET_OBJECTS, TARGET_SIMPLE, TARGET_CHIPS, TARGET_MOSAICS};
+
+SkyRegion UserPatch;
+
+int DoUpdateObjects;
+int DoUpdateSimple;
+int DoUpdateChips;
+int DoUpdateMosaics;
+
+/*** relphot prototypes ***/
+void          ConfigInit          PROTO((int *argc, char **argv));
+void          GetConfig           PROTO((char *config, char *field, char *format, int N, void *ptr));
+char         *GetPhotnamebyCode   PROTO((PhotCodeData *photcodes, int code));
+void          InterpolateGrid     PROTO((float *buffer, int Nx, int Ny, Coords *ccd, Coords *gcoords));
+int          *SelectRefMosaic     PROTO((Mosaic **refmosaic, int *Nimage));
+int           args                PROTO((int argc, char **argv));
+int           bcatalog            PROTO((Catalog *subcatalog, Catalog *catalog));
+void          clean_images        PROTO(());
+void          clean_measures      PROTO((Catalog *catalog, int Ncatalog, int final));
+void          clean_mosaics       PROTO(());
+void          clean_stars         PROTO((Catalog *catalog, int Ncatalog));
+int           corner_check        PROTO((double *x1, double *y1, double *x2, double *y2));
+void          dumpGrid            PROTO(());
+void          dump_grid           PROTO(()); 
+int           edge_check          PROTO((double *x1, double *y1, double *x2, double *y2));
+void          findImages          PROTO((Catalog *catalog, int Ncatalog));
+int           findMosaics         PROTO((Catalog *catalog, int Ncatalog));
+Image        *find_images         PROTO((FITS_DB *db, GSCRegion *region, int Nregion, int *Nimage, int **LineNum));
+void set_db (FITS_DB *in);
+int Shutdown (char *format, ...);
+void TrapSignal (int sig);
+void SetProtect (int mode);
+int SetSignals ();
+
+GSCRegion    *find_regions        PROTO((Image *image, int Nimage, int *Nregions, GSCRegion *fullregion));
+void          freeGridBins        PROTO((int Ncatalog));
+void          freeImageBins       PROTO((int Ncatalog));
+void          freeMosaicBins      PROTO((int Ncatalog));
+void          free_catalogs       PROTO((Catalog *catalog, int Ncatalog));
+int           gcatalog            PROTO((Catalog *catalog, int FINAL));
+Coords       *getCoords           PROTO((int meas, int cat));
+float         getMcal             PROTO((int meas, int cat));
+float         getMgrid            PROTO((int meas, int cat));
+float         getMmos             PROTO((int meas, int cat));
+float         getMrel             PROTO((Catalog *catalog, int meas, int cat));
+GSCRegion    *get_regions         PROTO((double minRa, double maxRa, double minDec, double maxDec, int *Nregions));
+void          getfullregion       PROTO((Image *image, int Nimage, GSCRegion *fullregion));
+Image        *getimage            PROTO((int N));
+Image        *getimages           PROTO((int *N));
+void          global_stats        PROTO((Catalog *catalog, int Ncatalog));
+void          initGrid            PROTO((int dX, int dY));
+void          initGridBins        PROTO((Catalog *catalog, int Ncatalog));
+void          initImageBins       PROTO((Catalog *catalog, int Ncatalog));
+void          initImages          PROTO((Image *input, int N));
+void          initMosaicBins      PROTO((Catalog *catalog, int Ncatalog));
+void          initMosaicGrid      PROTO((Image *image, int Nimage));
+void          initMosaics         PROTO((Image *image, int Nimage));
+void          initMrel            PROTO((Catalog *catalog, int Ncatalog));
+void          initialize          PROTO((int argc, char **argv));
+void          initstats           PROTO((char *mode));
+int           liststats           PROTO((double *value, double *dvalue, int N, StatType *stats));
+Catalog      *load_catalogs       PROTO((SkyList *skylist, int *Ncatalog, int subselect));
+SkyList      *load_images         PROTO((FITS_DB *db, SkyRegion *region));
+Image        *select_images       PROTO((SkyList *skylist, Image *timage, int Ntimage, int **LineNumber, int *Nimage));
+
+void check_permissions (char *basefile);
+void lock_image_db (FITS_DB *db, char *filename);
+void unlock_image_db (FITS_DB *db);
+void create_image_db (FITS_DB *db);
+void save_catalogs (Catalog *catalog, int Ncatalog);
+
+int           main                PROTO((int argc, char **argv));
+void          mark_images         PROTO((Image *image, int Nimage, Image *timage, int Ntimage));
+void          matchImage          PROTO((Catalog *catalog, int meas, int cat));
+void          matchMosaics        PROTO((Catalog *catalog, int meas, int cat));
+GSCRegion    *name_region         PROTO((char *name, int *Nregions));
+double        opening_angle       PROTO((double x1, double y1, double x2, double y2, double x3, double y3));
+void          plot_chisq          PROTO((Catalog *catalog, int Ncatalog));
+void          plot_defaults       PROTO((Graphdata *graphdata));
+void          plot_grid           PROTO((Catalog *catalog));
+void          plot_images         PROTO(());
+void          plot_list           PROTO((Graphdata *graphdata, double *xlist, double *ylist, int N, char *label, char *file));
+void          plot_mosaic_fields  PROTO((Catalog *catalog));
+void          plot_mosaics        PROTO(());
+void          plot_scatter        PROTO((Catalog *catalog, int Ncatalog));
+void          plot_star_coords    PROTO((Catalog *catalog, int Ncatalog));
+void          plot_stars          PROTO((Catalog *catalog, int Ncatalog));
+void          reload_catalogs     PROTO((SkyList *skylist));
+int           setExclusions       PROTO((Catalog *catalog, int Ncatalog));
+void          setMcal             PROTO((Catalog *catalog, int Poor));
+void          setMcalFinal        PROTO(());
+int           setMcalOutput       PROTO((Catalog *catalog, int Ncatalog));
+void          setMgrid            PROTO((Catalog *catalog));
+int           setMmos             PROTO((Catalog *catalog, int Poor));
+int           setMrel             PROTO((Catalog *catalog, int Ncatalog));
+void          setMrelFinal        PROTO((Catalog *catalog));
+int           setMrelOutput       PROTO((Catalog *catalog, int Ncatalog, int mark));
+void          set_ZP              PROTO((double ZERO));
+int           setrefcode          PROTO((Image *image, int Nimage)); 
+void          skip_measurements   PROTO((Catalog *catalog, int pass));
+void          sortA               PROTO((double *X, int N));
+void          sortB               PROTO((double *X, double *Y, int N));
+void          sortC               PROTO((double *X, double *Y, double *F1, double *F2, int N));
+void          sortD               PROTO((double *X, double *Y, double *Z, int N));
+StatType      statsImageM         PROTO((Catalog *catalog));
+StatType      statsImageN         PROTO((Catalog *catalog));
+StatType      statsImageX         PROTO((Catalog *catalog));
+StatType      statsImagedM        PROTO((Catalog *catalog));
+StatType      statsMosaicM        PROTO((Catalog *catalog));
+StatType      statsMosaicN        PROTO((Catalog *catalog));
+StatType      statsMosaicX        PROTO((Catalog *catalog));
+StatType      statsMosaicdM       PROTO((Catalog *catalog));
+StatType      statsStarN          PROTO((Catalog *catalog, int Ncatalog));
+StatType      statsStarS          PROTO((Catalog *catalog, int Ncatalog));
+StatType      statsStarX          PROTO((Catalog *catalog, int Ncatalog));
+void          wcatalog            PROTO((Catalog *catalog));
+void          wimages             PROTO(());
+void          write_coords        PROTO((Header *header, Coords *coords));
+
+double **array_init (int Nx, int Ny);
+void array_free (double **array, int Nx);
+CoordFit *fit_init (int order);
+void fit_free (CoordFit *fit);
+void fit_add (CoordFit *fit, double x1, double y1, double x2, double y2, double wt);
+void fit_eval (CoordFit *fit);
+double **poly2d_dx (double **poly, int Nx, int Ny);
+double **poly2d_dy (double **poly, int Nx, int Ny);
+double **poly2d_copy (double **poly, int Nx, int Ny);
+double poly2d_eval (double **poly, int Nx, int Ny, double x, double y);
+void fit_apply_coords (CoordFit *fit, Coords *coords);
+int CoordsGetCenter (CoordFit *fit, double tol, double *xo, double *yo);
+CoordFit *CoordsSetCenter (CoordFit *input, double Xo, double Yo);
+void FitChip (StarData *raw, StarData *ref, int Nmatch, Coords *coords);
+void FitMosaic (StarData *raw, StarData *ref, int Nmatch, Coords *coords);
+void FitSimple (StarData *raw, StarData *ref, int Nmatch, Coords *coords);
+void initObjectData (Catalog *catalog, int Ncatalog);
+int UpdateObjects (Catalog *catalog, int Ncatalog);
+int UpdateSimple (Catalog *catalog, int Ncatalog);
+int UpdateChips (Catalog *catalog, int Ncatalog);
+int UpdateMosaic (Catalog *catalog, int Ncatalog);
+int sun_ecliptic (double jd, double *lambda, double *beta, double *epsilon);
+int ParFactor (double *pR, double *pD, double R, double D, time_t T);
+int FitPM (PMFit *fit, double *X, double *dX, double *Y, double *dY, double *T, int Npts);
+int FitPar (PMFit *fit, double *X, double *dX, double *Y, double *dY, double *pR, double *pD, int Npts);
+int FitPMandPar (PMFit *fit, double *X, double *dX, double *Y, double *dY, double *T, double *pR, double *pD, int Npts);
+
+Mosaic *getMosaicForImage (int N);
+
+StarData *getImageRef (Catalog *catalog, int Ncatalog, int im, int *Nstars, CoordMode mode);
+StarData *getImageRaw (Catalog *catalog, int Ncatalog, int im, int *Nstars, CoordMode mode);
+
+Mosaic *getmosaics (int *N);
+void initMosaics (Image *image, int Nimage);
+StarData *getMosaicRaw (Catalog *catalog, int Ncatalog, int mos, int *Nstars);
+StarData *getMosaicRef (Catalog *catalog, int Ncatalog, int mos, int *Nstars);
+Mosaic *getMosaicForImage (int im);
+
+double getMeanR (Measure *measure, Average *average, SecFilt *secfilt);
+double getMeanD (Measure *measure, Average *average, SecFilt *secfilt);
+int setMeanR (double ra_fit, Measure *measure, Average *average, SecFilt *secfilt);
+int setMeanD (double dec_fit, Measure *measure, Average *average, SecFilt *secfilt);
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "relastro.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  char  *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  GetConfig (config, "MAG_LIM",                "%lf", 0, &MAG_LIM);
+  GetConfig (config, "SIGMA_LIM",              "%lf", 0, &SIGMA_LIM);
+  GetConfig (config, "STAR_SCATTER",           "%lf", 0, &STAR_SCATTER);
+  GetConfig (config, "IMAGE_SCATTER",          "%lf", 0, &IMAGE_SCATTER);
+  GetConfig (config, "IMAGE_OFFSET",           "%lf", 0, &IMAGE_OFFSET);
+
+  GetConfig (config, "STAR_CHISQ",             "%lf", 0, &STAR_CHISQ);
+  GetConfig (config, "PM_DT_MIN",              "%lf",  0, &PM_DT_MIN);
+  GetConfig (config, "PM_TOOFEW",              "%d",  0, &PM_TOOFEW);
+  GetConfig (config, "POS_TOOFEW",             "%d",  0, &POS_TOOFEW);
+  GetConfig (config, "IMAGE_TOOFEW",           "%d",  0, &IMAGE_TOOFEW);
+  GetConfig (config, "IMAGE_GOOD_FRACTION",    "%lf", 0, &IMAGE_GOOD_FRACTION);
+
+  GetConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  GetConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig(config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig(config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig(config, "PHOTCODE_FILE",          "%s",  0, MasterPhotcodeFile);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = 2;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+
+  // GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  // GetConfig (config, "RELPHOT_GRID_X",         "%d",  0, &RELPHOT_GRID_X);
+  // GetConfig (config, "RELPHOT_GRID_Y",         "%d",  0, &RELPHOT_GRID_Y);
+  // GetConfig (config, "RELPHOT_GRID_BINNING",   "%d",  0, &RELPHOT_GRID_BINNING);
+  // GetConfig (config, "CAMERA_CONFIG",          "%s",  0, CameraConfig);
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+  SetZeroPoint (25.0);
+
+  free (config);
+  free (file);
+
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/FitChip.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/FitChip.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/FitChip.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "relastro.h"
+
+void FitChip (StarData *raw, StarData *ref, int Nmatch, Coords *coords) {
+
+  int i;
+  CoordFit *fit;
+
+  fit = fit_init (coords[0].Npolyterms);
+  for (i = 0; i < Nmatch; i++) {
+    if (raw[i].mask) continue;
+    fit_add (fit, raw[i].X, raw[i].Y, ref[i].L, ref[i].M, 1.0);
+  }
+  fit_eval (fit);
+  fit_apply_coords (fit, coords);
+  fit_free (fit);
+
+  // apply new coords to raw (X,Y -> L,M)
+  for (i = 0; i < Nmatch; i++) {
+    XY_to_LM (&raw[i].L, &raw[i].M, raw[i].X, raw[i].Y, coords);
+  }
+
+  fit_free (fit);
+}
+
+/* in the mosaic case, we have four coord systems of interest:
+   R,D : the sky
+   P,Q : the tangent plane
+   L,M : the focal plane
+   X,Y : the chip
+
+   R,D -> P,Q (projection)
+   P,Q -> L,M (polynomial transformation : DIS)
+   L,M -> X,Y (polynomial transformation : WRP)
+*/
+
+/* XXX I'm not using the errors at all : this could at least be done with the dMag values */
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/FitMosaic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/FitMosaic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/FitMosaic.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "relastro.h"
+
+void FitMosaic (StarData *raw, StarData *ref, int Nmatch, Coords *coords) {
+
+  int i;
+  CoordFit *fit;
+
+  fit = fit_init (coords[0].Npolyterms);
+  for (i = 0; i < Nmatch; i++) {
+    if (raw[i].mask) continue;
+    fit_add (fit, raw[i].L, raw[i].M, ref[i].P, ref[i].Q, 1.0);
+  }
+  fit_eval (fit);
+  fit_apply_coords (fit, coords);
+  fit_free (fit);
+
+  // apply new coords to raw (X,Y -> L,M)
+  for (i = 0; i < Nmatch; i++) {
+    XY_to_LM (&raw[i].P, &raw[i].Q, raw[i].L, raw[i].M, coords);
+  }
+}
+
+/* in the mosaic case, we have four coord systems of interest:
+   R,D : the sky
+   P,Q : the tangent plane
+   L,M : the focal plane
+   X,Y : the chip
+
+   R,D -> P,Q (projection)
+   P,Q -> L,M (polynomial transformation : DIS)
+   L,M -> X,Y (polynomial transformation : WRP)
+*/
+
+/* XXX I'm not using the errors at all : this could at least be done with the dMag values */
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPM.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPM.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPM.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "relastro.h"
+
+/* do we want an init function which does the alloc and a clear function to free? */
+int FitPM (PMFit *fit, double *X, double *dX, double *Y, double *dY, double *T, int Npts) {
+
+  int i;
+
+  double **A, **B;
+  double wx, wy, Wx, Wy, Tx, Ty, Tx2, Ty2, Xs, Ys, XT, YT;
+  double chisq, Xf, Yf;
+
+  /* do I need to do this as 2 2x2 matrix equations? */
+  A = array_init (4, 4);
+  B = array_init (4, 1);
+
+  Wx = Wy = Tx = Ty = Tx2 = Ty2 = Xs = Ys = XT = YT = 0.0;
+  for (i = 0; i < Npts; i++) {
+    /* handle case where dX or dY = 0.0 */
+    wx = 1.0 / SQ(dX[i]);
+    wy = 1.0 / SQ(dY[i]);
+
+    Wx += wx;
+    Wy += wy;
+
+    Tx += T[i]*wx;
+    Ty += T[i]*wy;
+    
+    Tx2 += SQ(T[i])*wx;
+    Ty2 += SQ(T[i])*wy;
+    
+    Xs += X[i]*wx;
+    Ys += Y[i]*wy;
+
+    XT += X[i]*T[i]*wx;
+    YT += Y[i]*T[i]*wy;
+  }
+
+  A[0][0] = Wx;
+  A[0][1] = Tx;
+
+  A[1][0] = Tx;
+  A[1][1] = Tx2;
+
+  A[2][2] = Wy;
+  A[2][3] = Ty;
+
+  A[3][2] = Ty;
+  A[3][3] = Ty2;
+
+  B[0][0] = Xs;
+  B[1][0] = XT;
+  B[2][0] = Ys;
+  B[3][0] = YT;
+
+  dgaussjordan (A, B, 4, 1);
+
+  fit[0].Ro = B[0][0];
+  fit[0].uR = B[1][0];
+  fit[0].Do = B[2][0];
+  fit[0].uD = B[3][0];
+  fit[0].p  = 0.0;
+  
+  fit[0].dRo = sqrt(A[0][0]);
+  fit[0].duR = sqrt(A[1][1]);
+  fit[0].dDo = sqrt(A[2][2]);
+  fit[0].duD = sqrt(A[3][3]);
+  fit[0].dp  = 0.0;
+  
+  array_free (A, 4);
+  array_free (B, 4);
+
+  // add up the chi square for the fit
+  chisq = 0.0;
+  for (i = 0; i < Npts; i++) {
+      Xf = fit[0].Ro + fit[0].uR*T[i];
+      Yf = fit[0].Do + fit[0].uD*T[i];
+      chisq += SQ(X[i] - Xf) / SQ(dX[i]);
+      chisq += SQ(Y[i] - Yf) / SQ(dY[i]);
+  }
+  fit[0].Nfit = Npts;
+
+  // the reduced chisq is divided by (Ndof = 2*Npts - 4)
+  fit[0].chisq = chisq / (2.0*Npts - 4.0);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPMandPar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPMandPar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPMandPar.c	(revision 16632)
@@ -0,0 +1,98 @@
+# include "relastro.h"
+
+/* do we want an init function which does the alloc and a clear function to free? */
+int FitPMandPar (PMFit *fit, double *X, double *dX, double *Y, double *dY, double *T, double *pR, double *pD, int Npts) {
+
+  int i;
+
+  double **A, **B;
+  double wx, wy, Wx, Wy, Tx, Ty, Tx2, Ty2, Xs, Ys, XT, YT;
+  double PR, PD, PRT, PDT, PRX, PDY, PR2, PD2;
+
+  A = array_init (5, 5);
+  B = array_init (5, 1);
+
+  PR = PD = PRT = PDT = PRX = PDY = PR2 = PD2 = 0.0;
+  Wx = Wy = Tx = Ty = Tx2 = Ty2 = Xs = Ys = XT = YT = 0.0;
+  for (i = 0; i < Npts; i++) {
+    /* handle case where dX or dY = 0.0 */
+    wx = 1.0 / SQ(dX[i]);
+    wy = 1.0 / SQ(dY[i]);
+
+    Wx += wx;
+    Wy += wy;
+
+    Tx += T[i]*wx;
+    Ty += T[i]*wy;
+    
+    Tx2 += SQ(T[i])*wx;
+    Ty2 += SQ(T[i])*wy;
+    
+    PR += pR[i]*wx;
+    PD += pD[i]*wy;
+    
+    PRT += pR[i]*T[i]*wx;
+    PDT += pD[i]*T[i]*wy;
+    
+    PRX += pR[i]*X[i]*wx;
+    PDY += pD[i]*Y[i]*wy;
+    
+    PR2 += SQ(pR[i])*wx;
+    PD2 += SQ(pD[i])*wy;
+
+    Xs += X[i]*wx;
+    Ys += Y[i]*wy;
+
+    XT += X[i]*T[i]*wx;
+    YT += Y[i]*T[i]*wy;
+  }
+
+  A[0][0] = Wx;
+  A[0][1] = Tx;
+  A[0][4] = PR;
+
+  A[1][0] = Tx;
+  A[1][1] = Tx2;
+  A[1][4] = PRT;
+
+  A[2][2] = Wy;
+  A[2][3] = Ty;
+  A[2][4] = PD;
+
+  A[3][2] = Ty;
+  A[3][3] = Ty2;
+  A[3][4] = PDT;
+
+  A[4][0] = PR;
+  A[4][1] = PRT;
+  A[4][2] = PD;
+  A[4][3] = PDT;
+  A[4][4] = PR2 + PD2;
+
+  B[0][0] = Xs;
+  B[1][0] = XT;
+  B[2][0] = Ys;
+  B[3][0] = YT;
+  B[4][0] = PRX + PDY;
+
+  dgaussjordan (A, B, 5, 1);
+
+  fit[0].Ro = B[0][0];
+  fit[0].uR = B[1][0];
+  fit[0].Do = B[2][0];
+  fit[0].uD = B[3][0];
+  fit[0].p  = B[4][0];
+  
+  fit[0].dRo = sqrt(A[0][0]);
+  fit[0].duR = sqrt(A[1][1]);
+  fit[0].dDo = sqrt(A[2][2]);
+  fit[0].duD = sqrt(A[3][3]);
+  fit[0].dp  = sqrt(A[4][4]);
+  
+  array_free (A, 5);
+  array_free (B, 5);
+
+  /* get the chisq from the matrix values */
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPar.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPar.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/FitPar.c	(revision 16632)
@@ -0,0 +1,74 @@
+# include "relastro.h"
+
+/* do we want an init function which does the alloc and a clear function to free? */
+int FitPar (PMFit *fit, double *X, double *dX, double *Y, double *dY, double *pR, double *pD, int Npts) {
+
+  int i;
+
+  double **A, **B;
+  double wx, wy, Wx, Wy, Xs, Ys;
+  double PR, PD, PRX, PDY, PR2, PD2;
+
+  A = array_init (3, 3);
+  B = array_init (3, 1);
+
+  Wx = Wy = Xs = Ys = 0.0;
+  PR = PD = PRX = PDY = PR2 = PD2 = 0.0;
+  for (i = 0; i < Npts; i++) {
+    /* handle case where dX or dY = 0.0 */
+    wx = 1.0 / SQ(dX[i]);
+    wy = 1.0 / SQ(dY[i]);
+
+    Wx += wx;
+    Wy += wy;
+
+    PR += pR[i]*wx;
+    PD += pD[i]*wy;
+    
+    PRX += pR[i]*X[i]*wx;
+    PDY += pD[i]*Y[i]*wy;
+    
+    PR2 += SQ(pR[i])*wx;
+    PD2 += SQ(pD[i])*wy;
+
+    Xs += X[i]*wx;
+    Ys += Y[i]*wy;
+  }
+
+  A[0][0] = Wx;
+  A[0][2] = PR;
+
+  A[1][1] = Wy;
+  A[1][2] = PD;
+
+  A[2][0] = PR;
+  A[2][1] = PD;
+  A[2][2] = PR2 + PD2;
+
+  B[0][0] = Xs;
+  B[1][0] = Ys;
+  B[2][0] = PRX + PDY;
+
+  dgaussjordan (A, B, 3, 1);
+
+  fit[0].Ro = B[0][0];
+  fit[0].Do = B[1][0];
+  fit[0].p  = B[2][0];
+
+  fit[0].uR = 0.0;
+  fit[0].uD = 0.0;
+  
+  fit[0].dRo = sqrt(A[0][0]);
+  fit[0].dDo = sqrt(A[2][2]);
+  fit[0].dp  = sqrt(A[4][4]);
+  
+  fit[0].duR = 0.0;
+  fit[0].duD = 0.0;
+
+  array_free (A, 3);
+  array_free (B, 3);
+
+  /* get the chisq from the matrix values */
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/FitSimple.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/FitSimple.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/FitSimple.c	(revision 16632)
@@ -0,0 +1,38 @@
+# include "relastro.h"
+
+void FitSimple (StarData *raw, StarData *ref, int Nmatch, Coords *coords) {
+
+  int i;
+  CoordFit *fit;
+
+  fit = fit_init (coords[0].Npolyterms);
+  for (i = 0; i < Nmatch; i++) {
+    if (raw[i].mask) continue;
+    fit_add (fit, raw[i].X, raw[i].Y, ref[i].P, ref[i].Q, 1.0);
+  }
+  fit_eval (fit);
+  fit_apply_coords (fit, coords);
+  fit_free (fit);
+
+  // apply new coords to raw (X,Y -> P,Q)
+  for (i = 0; i < Nmatch; i++) {
+    XY_to_LM (&raw[i].L, &raw[i].M, raw[i].X, raw[i].Y, coords);
+    raw[i].P = raw[i].L;
+    raw[i].Q = raw[i].M;
+  }
+
+  fit_free (fit);
+}
+
+/* in the simple case, we only have three coord systems of interest:
+   R,D : the sky
+   P,Q : the tangent plane
+   X,Y : the chip
+
+   R,D -> P,Q (projection)
+   P,Q -> X,Y (polynomial transformation)
+
+   L,M is maintained, but is identical to P,Q
+*/
+
+/* XXX I'm not using the errors at all : this could at least be done with the dMag values */
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/ImageOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/ImageOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/ImageOps.c	(revision 16632)
@@ -0,0 +1,299 @@
+# include "relastro.h"
+
+static unsigned int *start;
+static unsigned int *stop;
+static int         **bin;
+
+static int         **clist;
+static int         **mlist;
+static int          *Nlist;
+static int          *NLIST;
+
+static Image        *image;
+static int          Nimage;
+
+Image *getimages (int *N) {
+  *N = Nimage;
+  return (image);
+}
+
+Image *getimage (int N) {
+  return (&image[N]);
+}
+
+void initImages (Image *input, int N) {
+
+  int i;
+
+  image = input;
+  Nimage = N;
+
+  ALLOCATE (start,   unsigned, Nimage);
+  ALLOCATE (stop,    unsigned, Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+    start[i] = image[i].tzero - MAX(0.05*image[i].trate*image[i].NY, 1);
+    stop[i]  = image[i].tzero + MAX(1.05*image[i].trate*image[i].NY, 1);
+  }
+}
+
+void initImageBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  ALLOCATE (bin, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  ALLOCATE (Nlist, int, Nimage);
+  ALLOCATE (NLIST, int, Nimage);
+  ALLOCATE (clist, int *, Nimage);
+  ALLOCATE (mlist, int *, Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeImageBins (int Ncatalog) {
+
+  int i;
+
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+  }
+  free (bin);
+  for (i = 0; i < Nimage; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (clist);
+  free (mlist);
+}
+
+/* match measurements to images */
+void findImages (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Nmeasure; j++) {
+      matchImage (catalog, j, i);
+    }
+  }
+}
+
+/* modify this function to use the measure->imageID field */
+void matchImage (Catalog *catalog, int meas, int cat) {
+
+  int i;
+  Measure *measure;
+  
+  measure = &catalog[cat].measure[meas];
+
+  /* find the image that supplied this measurement */
+  for (i = 0; i < Nimage; i++) {
+    if (image[0].photcode == -1) continue;
+    if (measure[0].photcode != image[i].photcode) continue;
+    if (measure[0].t < start[i]) continue;
+    if (measure[0].t > stop[i]) continue;
+    
+    // index for (catalog, measure) -> image
+    bin[cat][meas] = i;
+
+    // index for image, Nentry -> catalog
+    clist[i][Nlist[i]] = cat;
+
+    // index for image, Nentry -> measure
+    mlist[i][Nlist[i]] = meas;
+    Nlist[i] ++;
+
+    if (Nlist[i] == NLIST[i]) {
+      NLIST[i] += 100;
+      REALLOCATE (clist[i], int, NLIST[i]);
+      REALLOCATE (mlist[i], int, NLIST[i]);
+    }	
+    return;
+  }
+}
+
+Coords *getCoords (int meas, int cat) {
+
+  int i;
+
+  i = bin[cat][meas];
+  if (i == -1) return (NULL);
+  return (&image[i].coords);
+}
+
+void plot_images () {
+
+  int i, bin;
+  double *xlist, *Mlist, *dlist;
+  Graphdata graphdata;
+
+  if (FREEZE_IMAGES) return;
+
+  ALLOCATE (xlist, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+  ALLOCATE (Mlist, double, Nimage);
+
+  /**** dMcal vs airmass ****/
+  for (i = 0; i < Nimage; i++) {
+    Mlist[i] = image[i].Mcal;
+    dlist[i] = image[i].dMcal;
+    xlist[i] = image[i].secz;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin; 
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, Nimage, "airmass vs Mcal", "airmass.png");
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, Mlist, dlist, Nimage, "Mcal vs dMcal", NULL);
+
+# define NBIN 200
+  REALLOCATE (xlist, double, NBIN);
+  REALLOCATE (Mlist, double, NBIN);
+
+  /**** dMcal histgram ****/
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.00025*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Nimage; i++) {
+    bin = image[i].dMcal / 0.00025;
+    bin = MAX (0, MIN (NBIN - 1, bin));
+    Mlist[bin] += 1.0;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMcal hist", "dMcalhist.png");
+
+  free (dlist);
+  free (xlist);
+  free (Mlist);
+}
+
+// return StarData values for detections in the specified image, converting coordinates from the
+// chip positions: X,Y -> L,M -> P,Q -> R,D
+StarData *getImageRaw (Catalog *catalog, int Ncatalog, int im, int *Nstars, CoordMode mode) {
+
+  int i, m, c;
+  
+  Mosaic *mosaic;
+  Coords *moscoords;
+  StarData *raw;
+  
+  ALLOCATE (raw, StarData, Nlist[im]);
+
+  mosaic = NULL;
+  moscoords = NULL;
+  if (mode == MODE_MOSAIC) {
+      mosaic = getMosaicForImage (im);
+      if (mosaic == NULL) {
+	fprintf (stderr, "mosaic not found for image %s\n", image[im].name);
+	exit (1);
+      }
+      moscoords = &mosaic[0].coords;
+  }
+
+  for (i = 0; i < Nlist[im]; i++) {
+    m = mlist[im][i];
+    c = clist[im][i];
+
+    /* apply the current image transformation or use the current value of R+dR, D+dD? */
+    raw[i].X = catalog[c].measure[m].Xccd;
+    raw[i].Y = catalog[c].measure[m].Yccd;
+    
+    raw[i].Mag  = catalog[c].measure[m].M;
+    raw[i].dMag = catalog[c].measure[m].dM;
+
+    raw[i].mask = FALSE;
+
+    switch (mode) {
+      case MODE_SIMPLE:
+	/* note that for a Simple image, L,M = P,Q */
+	XY_to_LM (&raw[i].L, &raw[i].M, raw[i].X, raw[i].Y, &image[im].coords);
+	raw[i].P = raw[i].L;
+	raw[i].Q = raw[i].M;
+	LM_to_RD (&raw[i].R, &raw[i].D, raw[i].P, raw[i].Q, &image[im].coords);
+	break;
+      case MODE_MOSAIC:
+	XY_to_LM (&raw[i].L, &raw[i].M, raw[i].X, raw[i].Y, &image[im].coords);
+	XY_to_LM (&raw[i].P, &raw[i].Q, raw[i].L, raw[i].M, moscoords);
+	LM_to_RD (&raw[i].R, &raw[i].D, raw[i].P, raw[i].Q, moscoords);
+	break;
+    default:
+      fprintf (stderr, "error: invalid mode in getImageRaw");
+      abort ();
+    }
+  }  
+
+  *Nstars = Nlist[im];
+  return (raw);
+}
+
+// return StarData values for averages positions in the specified image, converting coordinates from
+// the sky positions: R,D -> P,Q -> L,M -> X,Y
+StarData *getImageRef (Catalog *catalog, int Ncatalog, int im, int *Nstars, CoordMode mode) {
+
+  int i, m, c, n;
+
+  Mosaic *mosaic;
+  Coords *moscoords;
+  StarData *ref;
+  
+  ALLOCATE (ref, StarData, Nlist[im]);
+
+  mosaic = NULL;
+  moscoords = NULL;
+  if (mode == MODE_MOSAIC) {
+    mosaic = getMosaicForImage (im);
+    if (mosaic == NULL) {
+      fprintf (stderr, "mosaic not found for image %s\n", image[im].name);
+      exit (1);
+    }
+    moscoords = &mosaic[0].coords;
+  }
+
+  for (i = 0; i < Nlist[im]; i++) {
+    m = mlist[im][i];
+    c = clist[im][i];
+    n = catalog[c].measure[m].averef;
+
+    /* apply the current image transformation or use the current value of R+dR, D+dD? */
+    ref[i].R = catalog[c].average[n].R;
+    ref[i].D = catalog[c].average[n].D;
+    
+    ref[i].Mag  = catalog[c].measure[m].M;
+    ref[i].dMag = catalog[c].measure[m].dM;
+
+    ref[i].mask = FALSE;
+
+    /* note that for a Simple image, L,M = P,Q */
+    switch (mode) {
+      case MODE_SIMPLE:
+      RD_to_LM (&ref[i].P, &ref[i].Q, ref[i].R, ref[i].D, &image[im].coords);
+      ref[i].L = ref[i].P;
+      ref[i].M = ref[i].Q;
+      LM_to_XY (&ref[i].X, &ref[i].Y, ref[i].L, ref[i].M, &image[im].coords);
+      break;
+      case MODE_MOSAIC:
+      RD_to_LM (&ref[i].P, &ref[i].Q, ref[i].R, ref[i].D, moscoords);
+      LM_to_XY (&ref[i].M, &ref[i].L, ref[i].P, ref[i].Q, moscoords);
+      LM_to_XY (&ref[i].X, &ref[i].Y, ref[i].L, ref[i].M, &image[im].coords);
+      break;
+      default:
+	fprintf (stderr, "invalid case");
+	abort();
+    }
+  }
+  
+  *Nstars = Nlist[im];
+  return (ref);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/MosaicOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/MosaicOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/MosaicOps.c	(revision 16632)
@@ -0,0 +1,186 @@
+# include "relastro.h"
+
+// array of mosaic definition structures
+static int    Nmosaic;
+static Mosaic *mosaic;
+
+// list of all images associated with a mosaic
+static int   *Nmosaic_own_images; // number of images for this mosaic
+static int   *Amosaic_own_images; // size of allocated array
+static int   **mosaic_own_images; // array of arrays: mosaic -> images
+
+// list of mosaic associated with each image  
+static int    Nmosaic_for_images; // number of images (for internal checks)
+static int    *mosaic_for_images; // array of: image -> mosaic
+
+Mosaic *getmosaics (int *N) {
+  *N = Nmosaic;
+  return (mosaic);
+}
+
+// find mosaic frames (unique time periods & photcode name matches mosaic) 
+void initMosaics (Image *image, int Nimage) {
+
+  int i, j, found, NMOSAIC;
+  unsigned int start, stop;
+
+  Nmosaic = 0;
+  NMOSAIC = 10;
+  ALLOCATE (mosaic, Mosaic, NMOSAIC);
+
+  ALLOCATE (Nmosaic_own_images, int, NMOSAIC);
+  ALLOCATE (Amosaic_own_images, int, NMOSAIC);
+  ALLOCATE (mosaic_own_images, int *, NMOSAIC);
+
+  /* find the mosaic images (coords.ctype = DIS); generate list of unique mosaics */
+  for (i = 0; i < Nimage; i++) {
+    if (strcmp(&image[i].coords.ctype[4], "-DIS")) continue;
+
+    /* set image time range */
+    start = image[i].tzero - MAX(0.05*image[i].trate*image[i].NY, 1);
+    stop  = image[i].tzero + MAX(1.05*image[i].trate*image[i].NY, 1);
+
+    /* a new mosaic, define ranges */
+    mosaic[Nmosaic].start = start;
+    mosaic[Nmosaic].stop  = stop;
+    mosaic[Nmosaic].Mcal  = 0.0;
+    mosaic[Nmosaic].dMcal = 0.0;
+    mosaic[Nmosaic].Xm    = 0.0;
+    mosaic[Nmosaic].code  = image[i].code;
+    mosaic[Nmosaic].secz  = image[i].secz;
+    mosaic[Nmosaic].coords = image[i].coords;
+
+    // init the mosaic_own_images array data
+    Nmosaic_own_images[Nmosaic] = 0;
+    Amosaic_own_images[Nmosaic] = 10;
+    ALLOCATE (mosaic_own_images[Nmosaic], int, Amosaic_own_images[Nmosaic]);
+
+    Nmosaic ++;
+    if (Nmosaic == NMOSAIC) {
+      NMOSAIC += 10;
+      REALLOCATE (mosaic, Mosaic, NMOSAIC);
+      REALLOCATE (mosaic_own_images, int *, NMOSAIC);
+      REALLOCATE (Nmosaic_own_images, int, NMOSAIC);
+      REALLOCATE (Amosaic_own_images, int, NMOSAIC);
+    }
+  }
+
+  // array to store image->mosaic index
+  Nmosaic_for_images = Nimage;
+  ALLOCATE (mosaic_for_images, int, Nmosaic_for_images);
+
+  /* now assign the WRP images to these mosaics */
+  for (i = 0; i < Nimage; i++) {
+    mosaic_for_images[i] = -1; // default value for no mosaic found
+
+    if (strcmp(&image[i].coords.ctype[4], "-WRP")) continue;
+
+    /* set image time range */
+    start = image[i].tzero - MAX(0.05*image[i].trate*image[i].NY, 1);
+    stop  = image[i].tzero + MAX(1.05*image[i].trate*image[i].NY, 1);
+
+    /* find existing mosaic with this time range */
+    found = FALSE;
+    for (j = 0; !found && (j < Nmosaic); j++) { 
+      if (stop  < mosaic[j].start) continue;
+      if (start > mosaic[j].stop)  continue;
+      found = TRUE;
+      break;
+    }
+    /* if no matching mosaic exists, skip this image */
+    if (!found) continue;
+
+    // mosaic corresponding to this image
+    mosaic_for_images[i] = j;
+
+    // add image to mosaic_own_image list 
+    mosaic_own_images[j][Nmosaic_own_images[j]] = i;
+    Nmosaic_own_images[j] ++;
+    if (Nmosaic_own_images[j] == Amosaic_own_images[j]) {
+      Amosaic_own_images[j] += 10;
+      REALLOCATE (mosaic_own_images[j], int, Amosaic_own_images[j]);
+    }
+    assert (Nmosaic_own_images[j] < Amosaic_own_images[j]);
+  }
+
+  return;
+}
+
+// return StarData values for detections in the specified image, converting coordinates from the
+// chip positions: X,Y -> L,M -> P,Q -> R,D
+StarData *getMosaicRaw (Catalog *catalog, int Ncatalog, int mos, int *Nstars) {
+
+  int i, j, im, Nraw, Nnew;
+  StarData *raw, *new;
+
+  Nraw = 0;
+  ALLOCATE (raw, StarData, 1);
+
+  // loop over the images owned by this mosaic
+  for (i = 0; i < Nmosaic_own_images[mos]; i++) {
+
+    im = mosaic_own_images[mos][i];
+    
+    // retrieve stars for this chip, applying chip and mosaic astrometry
+    // this function does the reverse-lookup for the mosaic corresponding to this image
+    new = getImageRaw (catalog, Ncatalog, im, &Nnew, MODE_MOSAIC);
+    
+    // merge new and raw
+    REALLOCATE (raw, StarData, Nraw + Nnew);
+    for (j = 0; j < Nnew; j++) {
+      raw[Nraw+j] = new[j];
+    }
+    Nraw += Nnew;
+
+    free (new);
+  }
+
+  *Nstars = Nraw;
+  return (raw);
+}
+
+// return StarData values for averages positions in the specified image, converting coordinates from
+// the sky positions: R,D -> P,Q -> L,M -> X,Y
+StarData *getMosaicRef (Catalog *catalog, int Ncatalog, int mos, int *Nstars) {
+
+  int i, j, im, Nref, Nnew;
+  StarData *ref, *new;
+  
+  Nref = 0;
+  ALLOCATE (ref, StarData, 1);
+
+  for (i = 0; i < Nmosaic_own_images[mos]; i++) {
+
+    im = mosaic_own_images[mos][i];
+    
+    // retrieve stars for this chip, applying chip and mosaic astrometry
+    // this function does the reverse-lookup for the mosaic corresponding to this image
+    new = getImageRef (catalog, Ncatalog, im, &Nnew, MODE_MOSAIC);
+    
+    // merge new and ref
+    REALLOCATE (ref, StarData, Nref + Nnew);
+    for (j = 0; j < Nnew; j++) {
+      ref[Nref+j] = new[j];
+    }
+    Nref += Nnew;
+
+    free (new);
+  }
+
+  *Nstars = Nref;
+  return (ref);
+}
+
+Mosaic *getMosaicForImage (int im) {
+
+  int mos;
+
+  if (im < 0) abort();
+  if (im >= Nmosaic_for_images) abort();
+
+  // search for the mosaic that 
+  mos = mosaic_for_images[im];
+  if (mos < 0) return NULL;
+
+  return &mosaic[mos];
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/ParFactor.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/ParFactor.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/ParFactor.c	(revision 16632)
@@ -0,0 +1,62 @@
+# include "relastro.h"
+
+# if (0)
+/* Low precision formulae for the sun, from Almanac p. C24 (1990) */
+/* ra and dec are returned as decimal hours and decimal degrees. */
+void lpsun (double jd, double *ra, double *dec) {
+
+  double n, L, g, lambda,epsilon,alpha,delta,x,y,z;
+
+  n = jd - J2000;
+  L = 280.460 + 0.9856474 * n;
+  g = (357.528 + 0.9856003 * n)/DEG_IN_RADIAN;
+  lambda = (L + 1.915 * sin(g) + 0.020 * sin(2. * g))/DEG_IN_RADIAN;
+  epsilon = (23.439 - 0.0000004 * n)/DEG_IN_RADIAN;
+
+  // this is the conversion from ecliptic to celestial coords
+  x = cos(lambda);
+  y = cos(epsilon)*sin(lambda);
+  z = sin(epsilon)*sin(lambda);
+
+  *ra = (atan_circ(x,y))*HRS_IN_RADIAN;
+  *dec = (asin(z))*DEG_IN_RADIAN;
+}
+# endif
+
+/* code borrowed from Skycalc : fix this stuff XXX */
+/* Low precision formulae for the sun, from Almanac p. C24 (1990) */
+int sun_ecliptic (double jd, double *lambda, double *beta, double *epsilon) {
+
+  double n, L, g;
+
+# define J2000 2451545.       /* Julian date at standard epoch */
+
+  n = jd - J2000;
+  L = 280.460 + 0.9856474 * n;
+  g = (357.528 + 0.9856003 * n)*RAD_DEG;
+  *lambda = L + 1.915 * sin(g) + 0.020 * sin(2. * g); // longitude in degrees
+  *beta = 0.0;					  // approx latitude
+  *epsilon = (23.439 - 0.0000004 * n);		  // obliquity of ecliptic in degrees
+  return TRUE;
+}
+
+/* given RA, DEC, Time, calculate the parallax factor */
+int ParFactor (double *pR, double *pD, double R, double D, time_t T) {
+
+  double jd;
+  double L, B, E, e, s, r, d;
+
+  /* given a time T in UNIX seconds, determine the solar longitude S */
+
+  jd = ohana_sec_to_jd (T);
+  sun_ecliptic (jd, &L, &B, &E);
+
+  e = E * RAD_DEG;
+  s = L * RAD_DEG;
+  r = R * RAD_DEG;
+  d = D * RAD_DEG;
+  
+  *pR =  +(cos(e)*sin(s)*cos(r) - cos(s)*sin(r));
+  *pD =  -(cos(e)*sin(s)*sin(r) + cos(s)*cos(r))*sin(d) + sin(e)*sin(s)*cos(d);
+  return TRUE;
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "relastro.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,30 @@
+# include "relastro.h"
+
+static FITS_DB *db;
+
+void set_db (FITS_DB *in) {
+  db = in;
+}
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format));
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  SetProtect (TRUE);
+  gfits_db_close (db);
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
+
+/* XXX this is probably not needed anymore : just protect the write statements */
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/StarOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/StarOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/StarOps.c	(revision 16632)
@@ -0,0 +1,518 @@
+# include "relastro.h"
+
+static int Nmax;
+static double *list;
+static double *dlist;
+
+void initMrel (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+  
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+}  
+
+float getMrel (Catalog *catalog, int meas, int cat) {
+
+  int ave;
+  float value;
+
+  ave = catalog[cat].measure[meas].averef;
+  if (catalog[cat].average[ave].code & STAR_BAD) return (NO_MAG);  
+ 
+  value = catalog[cat].secfilt[PhotNsec*ave+PhotSec].M;
+  return (value);
+}
+
+int setMrel (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, N;
+  float Msys, Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < STAR_TOOFEW) { /* too few measurements */
+	catalog[i].average[j].code |= ID_STAR_FEW;
+      } else {
+	catalog[i].average[j].code &= ~ID_STAR_FEW;
+      }	
+
+      liststats (list, dlist, N, &stats);
+
+      catalog[i].secfilt[PhotNsec*j+PhotSec].M  = stats.mean;
+      catalog[i].secfilt[PhotNsec*j+PhotSec].dM = stats.sigma;
+      catalog[i].secfilt[PhotNsec*j+PhotSec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NO_MAG;
+    }
+  }
+  return (TRUE);
+}
+
+int setMrelOutput (Catalog *catalog, int Ncatalog, int mark) {
+
+  int i, j, k, m, N, Nmax;
+  float Msys, Mcal, Mmos, Mgrid;
+  double *list, *dlist;
+  StatType stats;
+
+  /* Nmeasure is now different, need to reallocate */
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* skip stars already calibrated */
+      if (catalog[i].found[j]) continue;  
+
+      N = 0;
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < 1) continue;
+
+      liststats (list, dlist, N, &stats);
+      if (mark) catalog[i].found[j] = TRUE;
+
+      /* use sigma or error in dM for output? */
+      catalog[i].secfilt[PhotNsec*j+PhotSec].M  = stats.mean;
+      catalog[i].secfilt[PhotNsec*j+PhotSec].dM = MAX (stats.error, stats.sigma);
+      catalog[i].secfilt[PhotNsec*j+PhotSec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NO_MAG;
+    }
+  }
+
+  free (list);
+  free (dlist);
+  return (TRUE);
+}
+
+/* set measure.Mcal for all measures except ID_MEAS_NOCAL and ID_IMAGE_NOCAL */
+int setMcalOutput (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m;
+  float Mcal, Mmos, Mgrid;
+
+  MEAS_BAD = ID_MEAS_NOCAL;
+  IMAGE_BAD = ID_IMAGE_NOCAL;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+	catalog[i].measure[m].Mcal = Mcal + Mmos + Mgrid;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void clean_stars (Catalog *catalog, int Ncatalog) {
+
+  int i, j, Ndel, Nave, Ntot, mark;
+  float dM, Xm;
+  double Chisq, MaxScatter, MaxChisq;
+  double *xlist, *slist, *dlist;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "marking poor stars\n");
+
+  /* find Xm median -> ChiSq lim must be > median */
+  for (i = Ntot = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+  ALLOCATE (xlist, double, Ntot);
+  ALLOCATE (slist, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+  for (i = Ntot = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;
+      Xm = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (Xm == -1) continue;
+      Chisq = pow (10.0, 0.01*Xm);
+      xlist[Ntot] = Chisq;
+      slist[Ntot] = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      dlist[Ntot] = 1;
+      Ntot ++;
+    }
+  }
+  
+  initstats ("MEAN");
+  liststats (xlist, dlist, Ntot, &stats);
+  MaxChisq = MAX (STAR_CHISQ, 2*stats.median);
+  liststats (slist, dlist, Ntot, &stats);
+  MaxScatter = MAX (STAR_SCATTER, 2*stats.median);
+  fprintf (stderr, "Max Scatter: %f, Max Chisq: %f\n", MaxScatter, MaxChisq);
+
+  Ndel = Nave = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      dM = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      Xm = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      Chisq = pow (10.0, 0.01*Xm);
+      mark = (dM > MaxScatter) || (Xm == NO_MAG) || (Chisq > MaxChisq);
+      if (mark) {
+	catalog[i].average[j].code |= ID_STAR_POOR;
+	Ndel ++;
+      } else {
+	catalog[i].average[j].code &= ~ID_STAR_POOR;
+      }
+      Nave ++;
+    }
+  }
+  fprintf (stderr, "%d stars marked variable, %d total\n", Ndel, Nave);
+  initstats (STATMODE);
+  free (xlist);
+  free (slist);
+  free (dlist);
+}
+
+void clean_measures (Catalog *catalog, int Ncatalog, int final) {
+
+  int i, j, k, m, N, Ndel, Nave, Nmax, image_bad, TOOFEW;
+  int *ilist;
+  double *tlist, *list, *dlist, Ns;
+  float Msys, Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "marking poor measures\n");
+  /* Nmeasure is now different, need to reallocate */
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+  ALLOCATE (ilist, int, Nmax);
+  ALLOCATE (tlist, double, Nmax);
+  
+  /* it makes no sense to mark 3-sigma outliers with <5 measurements */
+  TOOFEW = MAX (5, STAR_TOOFEW);
+
+  Ns = 3;
+  Ndel = Nave = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* skip bad stars to prevent them from becoming good (on inner sample) */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      /* on final processing, skip stars already measured */
+      if (final && catalog[i].found[j]) continue;  
+
+      /* accumulate list of valid measurements */
+      m = catalog[i].average[j].offset;
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	/* if (catalog[i].measure[m].flags & MEAS_BAD) continue; */
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < TOOFEW) continue;
+
+      /* 3-sigma clip based on stats of inner 50% */
+      initstats ("INNER_MEAN");
+      liststats (list, dlist, N, &stats);
+      stats.sigma = MAX (MIN_ERROR, stats.sigma); /* if measurements agree too well, sigma -> 0.0 */
+      for (k = m = 0; k < N; k++) {
+	if (fabs (list[k] - stats.median) < Ns*stats.sigma) {
+	  list[m] = list[k];
+	  m++;
+	}
+      }
+      initstats ("MEAN");
+      liststats (list, dlist, m, &stats);
+      stats.sigma = MAX (MIN_ERROR, stats.sigma);
+
+      /* apply to list of all relevant measurements, including IMAGE_POOR & IMAGE_FEW */
+      image_bad = IMAGE_BAD;
+      IMAGE_BAD = ID_IMAGE_NOCAL;
+      m = catalog[i].average[j].offset;
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	/* if (catalog[i].measure[m].flags & MEAS_BAD) continue; */
+	if ((Mcal  = getMcal  (m, i)) == NO_MAG) continue;
+	if ((Mmos  = getMmos  (m, i)) == NO_MAG) continue;
+	if ((Mgrid = getMgrid (m, i)) == NO_MAG) continue;
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	ilist[N] = m;
+	N++;
+	Nave ++;
+      }
+      if (N < TOOFEW) continue;
+
+      /* mark bad measures */
+      for (k = 0; k < N; k++) {
+	if (fabs (list[k] - stats.median) > Ns*stats.sigma) {
+	  catalog[i].measure[ilist[k]].flags |= ID_MEAS_POOR;
+	  Ndel ++;
+	}
+      }
+      IMAGE_BAD = image_bad;
+    }
+  }
+  initstats (STATMODE);
+  fprintf (stderr, "%d measures marked poor, %d total\n", Ndel, Nave);
+  free (ilist);
+  free (tlist);
+}
+
+StatType statsStarN (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, n, N, Ntot;
+  double *list, *dlist;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (getMcal  (m, i) == NO_MAG) continue;
+	if (getMmos  (m, i) == NO_MAG) continue;
+	if (getMgrid (m, i) == NO_MAG) continue;
+	N++;
+      }
+      
+      list[n] = N;
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsStarX (Catalog *catalog, int Ncatalog) {
+
+  int i, j, n, Ntot, Xm;
+  double *list, *dlist;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      Xm = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (Xm == NO_MAG) continue;
+      list[n] = pow (10.0, 0.01*Xm);
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsStarS (Catalog *catalog, int Ncatalog) {
+
+  int i, j, n, Ntot;
+  double *list, *dlist;
+  float dM;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      dM = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      list[n] = dM;
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+void plot_stars (Catalog *catalog, int Ncatalog) {
+
+  int i, j, bin;
+  float dMrel;
+  double *xlist, *Mlist;
+  Graphdata graphdata;
+
+# define NBIN 200
+  ALLOCATE (xlist, double, NBIN);
+  ALLOCATE (Mlist, double, NBIN);
+
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.00025*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      dMrel = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      bin = dMrel / 0.00025;
+      bin = MAX (0, MIN (NBIN-1, bin));
+      Mlist[bin] += 1.0;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMrel hist", "dMhist.png");
+
+  free (xlist);
+  free (Mlist);
+}
+
+void plot_chisq (Catalog *catalog, int Ncatalog) {
+
+  int i, j, N, Ntotal, value;
+  double *xlist, *ylist;
+  Graphdata graphdata;
+
+  Ntotal = 0;
+  for (i = 0; i < Ncatalog; i++) Ntotal += catalog[i].Naverage;
+
+  ALLOCATE (xlist, double, Ntotal);
+  ALLOCATE (ylist, double, Ntotal);
+
+  N = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;
+      xlist[N] = catalog[i].secfilt[PhotNsec*j+PhotSec].M;
+      value    = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (value == NO_MAG) continue;
+      ylist[N] = 0.01*value;
+      N++;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = -3.0;
+  plot_list (&graphdata, xlist, ylist, N, "chisq", NULL);
+  free (xlist);
+  free (ylist);
+}
+
+void plot_star_coords (Catalog *catalog, int Ncatalog) {
+
+  int i, j, N;
+  double *xlist, *ylist;
+  double Xmin, Ymin, Xmax, Ymax;
+  Graphdata graphdata;
+
+  N = 0; 
+  for (i = 0; i < Ncatalog; i++) {
+    N += catalog[i].Naverage;
+  }
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+
+  N = 0;
+  Xmin = Ymin = +360.0;
+  Xmax = Ymax = -360.0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      xlist[N] = catalog[i].average[j].R;
+      ylist[N] = catalog[i].average[j].D;
+      N++;
+    }
+  }
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, xlist, ylist, N, "coords", NULL);
+
+  free (xlist);
+  free (ylist);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateChips.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateChips.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateChips.c	(revision 16632)
@@ -0,0 +1,31 @@
+# include "relastro.h"
+
+int UpdateChips (Catalog *catalog, int Ncatalog) {
+
+  /* we can measure new image parameters for each non-mosaic chip independently */
+  int i, Nimage, Nstars;
+  Image *image;
+  StarData *raw, *ref;
+
+  image = getimages (&Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+
+    /* skip all except WRP images */
+    if (strcmp(&image[i].coords.ctype[4], "-WRP")) continue;
+
+    /* convert measure coordinates to raw entries */
+    raw = getImageRaw (catalog, Ncatalog, i, &Nstars, MODE_MOSAIC);
+
+    /* convert average coordinates to ref entries */
+    ref = getImageRef (catalog, Ncatalog, i, &Nstars, MODE_MOSAIC);
+
+    FitChip (raw, ref, Nstars, &image[i].coords);
+
+    free (raw);
+    free (ref);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateMosaic.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateMosaic.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateMosaic.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "relastro.h"
+
+int UpdateMosaic (Catalog *catalog, int Ncatalog) {
+
+  /* we can measure new image parameters for each mosaic independently */
+  int i, Nmosaic, Nstars;
+  Mosaic *mosaic;
+  StarData *raw, *ref;
+
+  mosaic = getmosaics (&Nmosaic);
+
+  for (i = 0; i < Nmosaic; i++) {
+
+    /* convert measure coordinates to raw entries */
+    raw = getMosaicRaw (catalog, Ncatalog, i, &Nstars);
+
+    /* convert average coordinates to ref entries */
+    ref = getMosaicRef (catalog, Ncatalog, i, &Nstars);
+
+    // XXX : I'll need to supply these back to the image[] entry
+    FitMosaic (raw, ref, Nstars, &mosaic[i].coords);
+
+    free (raw);
+    free (ref);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateObjects.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateObjects.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateObjects.c	(revision 16632)
@@ -0,0 +1,249 @@
+# include "relastro.h"
+
+static int Nmax;
+static double *X, *dX;
+static double *Y, *dY;
+static double *R, *dR;
+static double *D, *dD;
+static double *pX;
+static double *pY;
+static double *T;
+static double *dT;
+
+void initObjectData (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+  
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+
+  ALLOCATE (R, double, MAX (1, Nmax));
+  ALLOCATE (D, double, MAX (1, Nmax));
+  ALLOCATE (T, double, MAX (1, Nmax));
+  ALLOCATE (X, double, MAX (1, Nmax));
+  ALLOCATE (Y, double, MAX (1, Nmax));
+
+  ALLOCATE (dR, double, MAX (1, Nmax));
+  ALLOCATE (dD, double, MAX (1, Nmax));
+  ALLOCATE (dT, double, MAX (1, Nmax));
+  ALLOCATE (dX, double, MAX (1, Nmax));
+  ALLOCATE (dY, double, MAX (1, Nmax));
+
+  ALLOCATE (pX, double, MAX (1, Nmax));
+  ALLOCATE (pY, double, MAX (1, Nmax));
+}  
+
+int UpdateObjects (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, N;
+  StatType statsR, statsD;
+  Coords coords;
+  PMFit fit;
+  time_t To;
+  int mode, Nave, Npm, Npar, Nskip;
+  double Tmin, Tmax;
+  float errorScale;
+  PhotCode *code;
+
+  initObjectData (catalog, Ncatalog);
+
+  /* project coordinates to a plane centered on the object with units of arcsec */
+  coords.crval1 = 0;
+  coords.crval2 = 0;
+  coords.crpix1 = 0;
+  coords.crpix2 = 0;
+  coords.cdelt1 = coords.cdelt2 = 1.0 / 3600.0;
+  coords.pc1_1  = coords.pc2_2 = 1.0;
+  coords.pc1_2  = coords.pc2_1 = 0.0;
+  coords.Npolyterms = 1;
+  strcpy (coords.ctype, "RA---SIN");
+
+  // use J2000 as a reference time
+  To = ohana_date_to_sec ("2000/01/01");
+  Nave = Npar = Npm = 0;
+
+  for (i = 0; i < Ncatalog; i++) {
+
+    if (VERBOSE) fprintf (stderr, "astrometrize catalog %d : %d ave, %d meas\n", i, catalog[i].Naverage, catalog[i].Nmeasure);
+
+    Nskip = 0;
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value of R,D for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) {
+	Nskip ++;
+	continue;  
+      }
+
+      N = 0;
+      m = catalog[i].average[j].offset;
+
+      Tmin = Tmax = (catalog[i].measure[m].t - To) / (86400*365.25);
+      mode = FIT_MODE;
+
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue;
+	
+	R[N] = getMeanR (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	D[N] = getMeanD (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	T[N] = (catalog[i].measure[m].t - To) / (86400*365.25) ; // time relative to J2000 in years
+
+	Tmin = MIN(Tmin, T[N]);
+	Tmax = MAX(Tmax, T[N]);
+
+	/* the astrometric errors are not being carried yet (but should be!) */
+	/* we use the photometric mag error as a weighting term */
+
+	code = GetPhotcodebyCode (catalog[0].measure[m].photcode);
+	errorScale = code[0].astromScale;
+	dR[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR) * errorScale;
+	dD[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR) * errorScale;
+	dT[N] = catalog[i].measure[m].dt;
+
+	N++;
+      }
+
+      if ((Tmax - Tmin) < PM_DT_MIN) mode = FIT_AVERAGE;
+      if ((mode == FIT_PM_ONLY) && (N < PM_TOOFEW)) mode = FIT_AVERAGE;
+
+      // XXX This criterion needs to be better considered: adjust to match Ndof
+      if (N < POS_TOOFEW) { /* too few measurements */
+	catalog[i].average[j].code |= ID_STAR_FEW;
+	continue;
+      } else {
+	catalog[i].average[j].code &= ~ID_STAR_FEW;
+      }	
+
+      /* we need to do the fit in a locally linear space; choose a ref coordinate */
+      coords.crval1 = R[0];
+      coords.crval2 = D[0];
+      
+      /* project all of the R,D coordinates to a plane centered on this coordinate */
+      for (k = 0; k < N; k++) {
+	RD_to_XY (&X[k], &Y[k], R[k], D[k], &coords);
+	dX[k] =  dR[k];
+	dY[k] =  dD[k];
+	// fprintf (stderr, "%d %f %f %f  %f %f\n", k, T[k], R[k], D[k], X[k], Y[k]);
+      }	  
+
+      /* fit the model components as needed */
+      switch (mode) {
+	case FIT_AVERAGE:
+	  liststats (R, dR, N, &statsR);
+	  liststats (D, dD, N, &statsD);
+
+	  fit.Ro = statsR.mean;
+	  fit.dRo = 3600.0*statsR.sigma;
+
+	  fit.Do = statsD.mean;
+	  fit.dDo = 3600.0*statsD.sigma;
+
+	  fit.chisq = 0.5*(statsR.chisq + statsD.chisq);
+	  fit.Nfit = N;
+	  Nave ++;
+	  break;
+
+	case FIT_PM_ONLY:
+	  FitPM (&fit, X, dX, Y, dY, T, N);
+	  // fprintf (stderr, "fitted:  %f - %f : %f %f : %f %f : %f\n", Tmin, Tmax, fit.Ro, fit.Do, fit.uR, fit.uD, fit.p);
+	  // project Ro, Do back to RA,DEC
+	  XY_to_RD (&fit.Ro, &fit.Do, fit.Ro, fit.Do, &coords);
+	  // fprintf (stderr, "project: %f %f : %f %f : %f\n", fit.Ro, fit.Do, fit.uR, fit.uD, fit.p);
+	  // continue;
+	  Npm ++;
+	  break;
+
+	case FIT_PAR_ONLY:
+	  for (k = 0; k < N; k++) {
+	    ParFactor (&pX[k], &pY[k], R[k], D[k], T[k]);
+	  }
+	  FitPar (&fit, X, dX, Y, dY, pX, pY, N);
+
+	  // project Ro, Do back to RA,DEC
+	  XY_to_RD (&fit.Ro, &fit.Do, fit.Ro, fit.Do, &coords);
+	  Npar ++;
+	  break;
+
+	case FIT_PM_AND_PAR:
+	  for (k = 0; k < N; k++) {
+	    ParFactor (&pX[k], &pY[k], R[k], D[k], T[k]);
+	  }
+	  FitPMandPar (&fit, X, dX, Y, dY, T, pX, pY, N);
+	  XY_to_RD (&fit.Ro, &fit.Do, fit.Ro, fit.Do, &coords);
+	  Npar ++;
+	  break;
+
+	default:
+	  fprintf (stderr, "programming error at %s, %d", __FILE__, __LINE__);
+	  exit (2);
+      }	  
+
+      if (0 && (j < 100)) {
+	fprintf (stderr, "%f %f -> %f %f (%f,%f)\n",
+		 catalog[i].average[j].R, 
+		 catalog[i].average[j].D, 
+		 fit.Ro, fit.Do, 
+		 3600*(catalog[i].average[j].R - fit.Ro), 
+		 3600*(catalog[i].average[j].D - fit.Do));
+      }
+
+      // the measure fields must be updated before the average fields
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue;
+	setMeanR (fit.Ro, &catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	setMeanD (fit.Do, &catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+      }      
+
+      catalog[i].average[j].R  	= fit.Ro; // RA in degrees
+      catalog[i].average[j].D  	= fit.Do; // DEC in degrees
+      catalog[i].average[j].dR 	= fit.dRo; // RA scatter in arcsec
+      catalog[i].average[j].dD 	= fit.dDo; // DEC scatter in arcsec
+
+      catalog[i].average[j].uR  = fit.uR; // RA proper motion in arcsec/year
+      catalog[i].average[j].uD  = fit.uD; // DEC proper motion in arcsec/year
+      catalog[i].average[j].duR = fit.duR; // RA proper motion error in arcsec/year
+      catalog[i].average[j].duD = fit.duD; // DEC proper motion error in arcsec/year
+
+      catalog[i].average[j].P   = fit.p; // parallax in arcsec
+      catalog[i].average[j].dP  = fit.dp; // parallax error in arcsec
+
+      catalog[i].average[j].Xp  = (fit.Nfit > 1) ? 100.0*log10(fit.chisq) : NAN_S_SHORT;
+    }
+
+    if (VERBOSE) fprintf (stderr, "catalog %d : %d ave, %d pm, %d par : Nskip % d\n", i, Nave, Npm, Npar, Nskip);
+  }
+
+  if (VERBOSE) fprintf (stderr, "fitted %d objects (%d ave, %d pm, %d par)\n", Nave + Npm + Npar, Nave, Npm, Npar);
+  return (TRUE);
+}
+
+/* fitting proper-motion and parallax:
+
+given a source at position r,d, at a time t, we need to calculate a vector (pr,pd)
+
+let x,y be the coordinate in the linearized frame with y parallel to DEC lines
+
+L,B are the ecliptic longitude and latitude of the object, 
+dL and dB are the offsets in the L and B directions
+
+dL = sin(t - topp)
+dB = cos(t - topp)*sin(B)
+
+these need to be rotated to the R,D frame to yield pR,pD.  Then, the equation of motion
+for the source in the x,y frame is:
+
+x = Ro + uR * (t - to) + p * pR 
+y = Do + uD * (t - to) + p * pD
+
+the unknowns in these equations are Ro, uR, Do, uD, and p
+
+XXX think through the concepts for the pole a bit better.  all objects near the pole 
+move the same way with the same phase.  choose a projection center and define dL,dB relative 
+to that center point coordinate system?
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateSimple.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateSimple.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/UpdateSimple.c	(revision 16632)
@@ -0,0 +1,32 @@
+# include "relastro.h"
+
+int UpdateSimple (Catalog *catalog, int Ncatalog) {
+
+  /* we can measure new image parameters for each non-mosaic chip independently */
+  int i, Nimage, Nstars;
+  Image *image;
+  StarData *raw, *ref;
+
+  image = getimages (&Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+
+    /* skip WRP and DIS images */
+    if (!strcmp(&image[i].coords.ctype[4], "-WRP")) continue;
+    if (!strcmp(&image[i].coords.ctype[4], "-DIS")) continue;
+
+    /* convert measure coordinates to raw entries */
+    raw = getImageRaw (catalog, Ncatalog, i, &Nstars, MODE_SIMPLE);
+
+    /* convert average coordinates to ref entries */
+    ref = getImageRef (catalog, Ncatalog, i, &Nstars, MODE_SIMPLE);
+
+    FitSimple (raw, ref, Nstars, &image[i].coords);
+
+    free (raw);
+    free (ref);
+  }
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/args.c	(revision 16632)
@@ -0,0 +1,217 @@
+# include "relastro.h"
+void usage (void);
+
+int args (int argc, char **argv) {
+
+  int N;
+  double trange;
+
+  /* possible operations */
+  FIT_TARGET = TARGET_NONE;
+  FIT_MODE = FIT_AVERAGE;
+  if ((N = get_argument (argc, argv, "-update-objects"))) {
+    remove_argument (N, &argc, argv);
+    FIT_TARGET = TARGET_OBJECTS;
+
+    // check for object fitting modes (not valid for images)
+    if ((N = get_argument (argc, argv, "-pm"))) {
+	remove_argument (N, &argc, argv);
+	FIT_MODE = FIT_PM_ONLY;
+    }
+    if ((N = get_argument (argc, argv, "-par"))) {
+	remove_argument (N, &argc, argv);
+	FIT_MODE = FIT_PAR_ONLY;
+    }
+    if ((N = get_argument (argc, argv, "-pmpar"))) {
+	remove_argument (N, &argc, argv);
+	FIT_MODE = FIT_PM_AND_PAR;
+    }
+  }
+  if ((N = get_argument (argc, argv, "-update-simple"))) {
+    remove_argument (N, &argc, argv);
+    FIT_TARGET = TARGET_SIMPLE;
+  }
+  if ((N = get_argument (argc, argv, "-update-chips"))) {
+    remove_argument (N, &argc, argv);
+    FIT_TARGET = TARGET_CHIPS;
+  }
+  if ((N = get_argument (argc, argv, "-update-mosaics"))) {
+    remove_argument (N, &argc, argv);
+    FIT_TARGET = TARGET_MOSAICS;
+  }
+  if (FIT_TARGET == TARGET_NONE) usage();
+
+  /* specify portion of the sky : allow default of all sky? */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  } else {
+    usage ();
+  }
+
+  /* define time */
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &TSTART)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      if (!ohana_str_to_time (argv[N], &TSTOP)) { 
+	fprintf (stderr, "ERROR: syntax error\n");
+	return (FALSE);
+      }
+    } else {
+      if (trange < 0) {
+	trange = fabs (trange);
+	TSTOP = TSTART;
+	TSTART -= trange;
+      } else {
+	TSTOP = TSTART + trange;
+      }
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+
+  PHOTCODE_LIST = NULL;
+  if ((N = get_argument (argc, argv, "-photcode"))) {
+    remove_argument (N, &argc, argv);
+    PHOTCODE_LIST = strcreate(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PLOTSTUFF = FALSE;
+  if ((N = get_argument (argc, argv, "-plot"))) {
+    PLOTSTUFF = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PLOTDELAY = 500000;
+  if ((N = get_argument (argc, argv, "-plotdelay"))) {
+    remove_argument (N, &argc, argv);
+    PLOTDELAY = 1e6*atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (STATMODE, "CHI_INNER_WTMEAN");
+  if ((N = get_argument (argc, argv, "-statmode"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (STATMODE, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  RESET = FALSE;
+  if ((N = get_argument (argc, argv, "-reset"))) {
+    remove_argument (N, &argc, argv);
+    RESET = TRUE;
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  SHOW_PARAMS = FALSE;
+  if ((N = get_argument (argc, argv, "-params"))) {
+    remove_argument (N, &argc, argv);
+    SHOW_PARAMS = TRUE;
+  }
+
+  /* XXX update these for relevant plots */
+  PlotMmin = 10.0; PlotMmax = 20.0; PlotdMmin = -1.0; PlotdMmax = 1.0;
+  if ((N = get_argument (argc, argv, "-plrange"))) {
+    remove_argument (N, &argc, argv);
+    PlotMmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotMmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotdMmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotdMmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* XXX update this */
+  MIN_ERROR = 0.001;
+  if ((N = get_argument (argc, argv, "-minerror"))) {
+    remove_argument (N, &argc, argv);
+    MIN_ERROR = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    /* require MIN_ERROR > 0 */
+  }  
+
+  AreaSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-area"))) {
+    remove_argument (N, &argc, argv);
+    AreaXmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaXmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaYmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaYmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaSelect = TRUE;
+  }
+
+  ImagSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-instmag"))) {
+    remove_argument (N, &argc, argv);
+    ImagMin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImagMax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImagSelect = TRUE;
+  }
+  
+  /* XXX drop this? */
+  DophotSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-dophot"))) {
+    remove_argument (N, &argc, argv);
+    DophotValue = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    DophotSelect = TRUE;
+  }
+
+  if (argc != 1) usage ();
+  return TRUE;
+}
+
+void usage () {
+  fprintf (stderr, "ERROR: USAGE: relastro -region RA RA DEC DEC\n");
+  fprintf (stderr, "  working options: \n");
+  fprintf (stderr, "  -time (start) (stop)\n");
+  fprintf (stderr, "  -v\n");
+  fprintf (stderr, "  -plot\n");
+  fprintf (stderr, "  -plotdelay (seconds)\n");
+  fprintf (stderr, "  -update\n");
+  fprintf (stderr, "  -params\n");
+  fprintf (stderr, "  -reset\n");
+  fprintf (stderr, "  -area Xmin Xmax Ymin Ymax\n");
+  fprintf (stderr, "  -instmag min max\n\n");
+  fprintf (stderr, "  planned options: \n");
+  fprintf (stderr, "  -photcode code[,code,code,..]\n");
+  fprintf (stderr, "  \n");
+  exit (2);
+} 
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/bcatalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/bcatalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/bcatalog.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include "relastro.h"
+
+int bcatalog (Catalog *subcatalog, Catalog *catalog) {
+  
+  int i, j, k, offset, found;
+  int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm;
+  float mag;
+
+  // XXX PhotNsec as a global is a bad idea; either get it from catalog
+  // or get it from:
+  // Nsecfilt = GetPhotcodeNsecfilt ();
+  // assert (catalog[0].Nsecfilt == Nsecfilt);
+
+  /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
+  NAVERAGE = 50;
+  NMEASURE = 1000;
+  ALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+  ALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*PhotNsec);
+  ALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+  Nmeasure = Naverage = 0;
+
+  /* exclude stars not in range or with too few measurements */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    if (catalog[0].average[i].Nm < 2) continue; 
+
+    /* start with all stars good */
+    subcatalog[0].average[Naverage] = catalog[0].average[i];
+    subcatalog[0].average[Naverage].offset = Nmeasure;
+    for (j = 0; j < PhotNsec; j++) {
+      subcatalog[0].secfilt[PhotNsec*Naverage+j] = catalog[0].secfilt[PhotNsec*i+j];
+    }
+
+    if (RESET) {
+      // XXX reset the ra,dec coords?
+      subcatalog[0].average[Naverage].code &= ~ID_STAR_FEW;
+      subcatalog[0].average[Naverage].code &= ~ID_STAR_POOR;
+    }
+
+    Nm = 0;
+    for (j = 0; j < catalog[0].average[i].Nm; j++) {
+
+      offset = catalog[0].average[i].offset + j;
+
+      /* select measurements by photcode, if specified */
+      if (Nphotcodes > 0) {
+	found = FALSE;
+	for (k = 0; (k < Nphotcodes) && !found; k++) {
+	  if (photcodes[k][0].code == catalog[0].measure[offset].photcode) found = TRUE;
+	}
+	if (!found) continue;
+      }
+
+      /* select measurements by time */
+      if (TimeSelect) {
+	if (catalog[0].measure[offset].t < TSTART) continue;
+	if (catalog[0].measure[offset].t > TSTOP) continue;
+      }
+
+      /* select measurements by quality */
+      if (DophotSelect && (catalog[0].measure[offset].dophot != DophotValue)) continue;
+
+      /* select measurements by mag limit */
+      mag = PhotCat (&catalog[0].measure[offset]);
+      if (mag > MAG_LIM) continue;
+
+      /* select measurements by measurement error */
+      if ((SIGMA_LIM > 0) && (catalog[0].measure[offset].dM > SIGMA_LIM)) continue;
+
+      /* select measurements by mag limit */
+      if (ImagSelect) {
+	mag = PhotInst (&catalog[0].measure[offset]);
+	if (mag < ImagMin) continue;
+	if (mag > ImagMax) continue;
+      }
+
+      subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_SKIP;
+      subcatalog[0].measure[Nmeasure]        = catalog[0].measure[offset];
+      subcatalog[0].measure[Nmeasure].averef = Naverage;
+      if (RESET) { 
+	subcatalog[0].measure[Nmeasure].Mcal = 0;
+	subcatalog[0].measure[Nmeasure].dbFlags &= 0xff00;
+	subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_POOR;
+	subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_AREA;
+	subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_NOCAL;
+      }
+      Nmeasure ++;
+      Nm ++;
+      if (Nmeasure == NMEASURE) {
+	NMEASURE += 1000;
+	REALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+      }
+    }
+    if (Nm < 2) { /* enough measurements in band? */
+      Nmeasure -= Nm;
+      continue; 
+    }
+    subcatalog[0].average[Naverage].Nm = Nm;
+    Naverage ++;
+    if (Naverage == NAVERAGE) {
+      NAVERAGE += 50;
+      REALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+      REALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*PhotNsec);
+    }
+  }
+  REALLOCATE (subcatalog[0].average, Average, MAX (Naverage, 1));
+  REALLOCATE (subcatalog[0].measure, Measure, MAX (Nmeasure, 1));
+  REALLOCATE (subcatalog[0].secfilt, SecFilt, PhotNsec*MAX (Naverage, 1));
+  subcatalog[0].Naverage = Naverage;
+  subcatalog[0].Nmeasure = Nmeasure;
+  subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
+  subcatalog[0].Nsecf_mem = Naverage * PhotNsec;
+  assert (PhotNsec == catalog[0].Nsecfilt);
+
+  if (VERBOSE) {
+    fprintf (stderr, "%d: using %d stars (%d measures) for catalog\n", i, 
+	     subcatalog[0].Naverage, subcatalog[0].Nmeasure);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/dvo_astrom_ops.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/dvo_astrom_ops.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/dvo_astrom_ops.c	(revision 16632)
@@ -0,0 +1,91 @@
+# include "relastro.h"
+
+double getMeanR (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  double ra;
+
+  /* the measure carries the instantaneous mean position at the epoch t */ 
+  ra = average[0].R - measure[0].dR / 3600.0;
+
+  /* possible corrections to mean ra:
+
+  - proper-motion and parallax
+  - abberation
+  - precession and nutation, etc
+  - refraction
+  - DCR
+
+  */
+
+  return (ra);
+}
+
+double getMeanD (Measure *measure, Average *average, SecFilt *secfilt) {
+
+  double dec;
+
+  /* the measure carries the instantaneous mean position at the epoch t */ 
+  dec = average[0].D - measure[0].dD / 3600.0;
+
+  /* possible corrections to mean ra:
+
+  - proper-motion and parallax
+  - abberation
+  - precession and nutation, etc
+  - refraction
+  - DCR
+
+  */
+
+  return (dec);
+}
+
+int setMeanR (double ra_fit, Measure *measure, Average *average, SecFilt *secfilt) {
+
+  /* math to get from new fitted position to new measure offset
+     ra_obs = average[0].R - measure[0].dR / 3600.0;
+     measure[0].dR = (ra_fit - ra_obs) * 3600.0;
+     measure[0].dR = (ra_fit - average[0].R + measure[0].dR/3600) * 3600.0
+     measure[0].dR = (ra_fit - average[0].R) * 3600.0 + measure[0].dR;
+  */
+
+  /* the measure carries the instantaneous mean position at the epoch t */ 
+  measure[0].dR += (ra_fit - average[0].R) * 3600.0;
+
+  /* possible corrections to mean ra:
+
+  - proper-motion and parallax
+  - abberation
+  - precession and nutation, etc
+  - refraction
+  - DCR
+
+  */
+
+  return (TRUE);
+}
+
+int setMeanD (double dec_fit, Measure *measure, Average *average, SecFilt *secfilt) {
+
+  /* math to get from new fitted position to new measure offset
+     dec_obs = average[0].D - measure[0].dD / 3600.0;
+     measure[0].dD = (dec_fit - dec_obs) * 3600.0;
+     measure[0].dD = (dec_fit - average[0].D + measure[0].dD/3600) * 3600.0
+     measure[0].dD = (dec_fit - average[0].D) * 3600.0 + measure[0].dD;
+  */
+
+  /* the measure carries the instantaneous mean position at the epoch t */ 
+  measure[0].dD += (dec_fit - average[0].D) * 3600.0;
+
+  /* possible corrections to mean ra:
+
+  - proper-motion and parallax
+  - abberation
+  - precession and nutation, etc
+  - refraction
+  - DCR
+
+  */
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/fitpoly.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/fitpoly.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/fitpoly.c	(revision 16632)
@@ -0,0 +1,306 @@
+# include "relastro.h"
+
+/* these functions support simultaneous 2D fits to
+   x2 = \sum a_i,j x1^i y1^j 
+   y2 = \sum b_i,j x1^i y1^j 
+
+   the order of the fit (largest coefficient) is fixed to a single
+   value for both x1,y1 terms and for x2,y2 fits
+
+   the code is currently confusing because we limit to i+j <= order.
+   this could be cleaner if we used masks and allowed i <= order, j <= order
+*/
+
+double **array_init (int Nx, int Ny) {
+
+  int i;
+  double **array;
+
+  ALLOCATE (array, double *, Nx);
+  for (i = 0; i < Nx; i++) {
+    ALLOCATE (array[i], double, Ny);
+    memset (array[i], 0, Ny*sizeof(double));
+  }    
+  return (array);
+}
+
+void array_free (double **array, int Nx) {
+
+  int i;
+
+  for (i = 0; i < Nx; i++) {
+    free (array[i]);
+  }    
+  free (array);
+}
+
+// XXX define a fit structure and drop the file static variables?
+CoordFit *fit_init (int order) {
+
+  CoordFit *fit;
+
+  ALLOCATE (fit, CoordFit, 1);
+
+  fit[0].Npts   = 0;
+  fit[0].Norder = order;
+  fit[0].Nterms = order + 1;
+  fit[0].Nsums  = 2*order + 1;
+  fit[0].Nelems = SQ(order + 1);
+
+  /* summing arrays for fit solution */
+
+  // xsum[i][j] holds \sum (x2 wt x1^i y1^j)
+  // ysum[i][j] holds \sum (y2 wt x1^i y1^j)
+  fit[0].xsum = array_init (fit[0].Nterms, fit[0].Nterms);
+  fit[0].ysum = array_init (fit[0].Nterms, fit[0].Nterms);
+
+  // xfit[i][j] holds x2 coeff for x1^i y1^j
+  // yfit[i][j] holds y2 coeff for x1^i y1^j
+  fit[0].xfit = array_init (fit[0].Nterms, fit[0].Nterms);
+  fit[0].yfit = array_init (fit[0].Nterms, fit[0].Nterms);
+
+  // sum[i][j] holds \sum (wt x1^i y1^j)
+  fit[0].sum = array_init (fit[0].Nsums, fit[0].Nsums);
+
+  return (fit);
+}
+
+void fit_free (CoordFit *fit) {
+
+  array_free (fit[0].xfit, fit[0].Nterms);
+  array_free (fit[0].yfit, fit[0].Nterms);
+
+  array_free (fit[0].sum, fit[0].Nsums);
+  array_free (fit[0].xsum, fit[0].Nterms);
+  array_free (fit[0].ysum, fit[0].Nterms);
+  
+  free (fit);
+}
+  
+// XXX use implicit masks as below or explicit masks (with function to set?)
+// XXX eg, add a global mask to this file and 
+void fit_add (CoordFit *fit, double x1, double y1, double x2, double y2, double wt) {
+
+  int ix, iy;
+  double xterm, yterm, term;
+
+  xterm = 1;
+  for (ix = 0; ix < fit[0].Nsums; ix++) {
+    yterm = 1;
+    for (iy = 0; iy < fit[0].Nsums; iy++) {
+      term = xterm*yterm*wt;
+      fit[0].sum[ix][iy] += term;
+      if ((iy < fit[0].Nterms) && (ix < fit[0].Nterms)) {
+	fit[0].xsum[ix][iy] += x2*term;
+	fit[0].ysum[ix][iy] += y2*term;
+      }
+      yterm *= y1;
+    }
+    xterm *= x1;
+  }
+  fit[0].Npts ++;
+}
+
+/* convert the xsum,ysum,sum terms into vector,matrix and solve */
+void fit_eval (CoordFit *fit) {
+
+  int i, j, ix, iy, jx, jy;
+  double **matrix, **vector;
+
+  if (fit[0].Npts == 0) {
+    fprintf (stderr, "warning: no valid pts\n");
+  }
+
+  // matrix, vector hold the final linear system
+  matrix = array_init (fit[0].Nelems, fit[0].Nelems);
+  vector = array_init (fit[0].Nelems, 2);
+
+  /* remap the xsum,ysum terms into the vector */
+  for (i = 0; i < fit[0].Nelems; i++) {
+    ix = i % fit[0].Nterms;
+    iy = i / fit[0].Nterms;
+    vector[i][0] = fit[0].xsum[ix][iy];
+    vector[i][1] = fit[0].ysum[ix][iy];
+
+    for (j = 0; j < fit[0].Nelems; j++) {
+      jx = j % fit[0].Nterms;
+      jy = j / fit[0].Nterms;
+      matrix[i][j] = fit[0].sum[ix+jx][iy+jy];
+    }
+  }
+
+  for (i = 0; i < fit[0].Nelems; i++) {
+    ix = i % fit[0].Nterms;
+    iy = i / fit[0].Nterms;
+    fprintf (stderr, "x2 : x^%dy^%d: %10.4g    y2 : x^%dy^%d: %10.4g \n", 
+	     ix, iy, vector[i][0], ix, iy, vector[i][1]);
+  }	
+
+  dgaussjordan (matrix, vector, fit[0].Nelems, 2); 
+
+  for (i = 0; i < fit[0].Nelems; i++) {
+    ix = i % fit[0].Nterms;
+    iy = i / fit[0].Nterms;
+    fprintf (stderr, "x2 : x^%dy^%d: %10.4g    y2 : x^%dy^%d: %10.4g \n", 
+	     ix, iy, vector[i][0], ix, iy, vector[i][1]);
+  }	
+
+  /* remap the vector terms into xfit,yfit */
+  for (i = 0; i < fit[0].Nelems; i++) {
+    ix = i % fit[0].Nterms;
+    iy = i / fit[0].Nterms;
+    fit[0].xfit[ix][iy] = vector[i][0];
+    fit[0].yfit[ix][iy] = vector[i][1];
+  }
+
+  array_free (matrix, fit[0].Nelems);
+  array_free (vector, fit[0].Nelems);
+}
+
+// Nx, Ny is the number of terms in x and in y
+double **poly2d_dx (double **poly, int Nx, int Ny) {
+
+  int i, j, Nxout, Nyout;
+  double **dpoly;
+
+  Nxout = Nx - 1;
+  Nyout = Ny;
+
+  // poly[i][j] holds coeff for x1^i y1^j
+  dpoly = array_init (Nxout, Nyout);
+
+  for (i = 0; i < Nxout; i++) {
+    for (j = 0; j < Nyout; j++) {
+      dpoly[i][j] = poly[i+1][j] * (i+1);
+    }
+  }
+  return dpoly;
+}
+
+// Nx, Ny is the number of terms in x and in y
+double **poly2d_dy (double **poly, int Nx, int Ny) {
+
+  int i, j, Nxout, Nyout;
+  double **dpoly;
+
+  Nxout = Nx;
+  Nyout = Ny - 1;
+
+  // poly[i][j] holds coeff for x1^i y1^j
+  dpoly = array_init (Nxout, Nyout);
+
+  for (i = 0; i < Nxout; i++) {
+    for (j = 0; j < Nyout; j++) {
+      dpoly[i][j] = poly[i][j+1] * (j+1);
+    }
+  }
+  return dpoly;
+}
+
+// Nx, Ny is the number of terms in x and in y
+double **poly2d_copy (double **poly, int Nx, int Ny) {
+
+  int i, j;
+  double **out;
+
+  // poly[i][j] holds coeff for x1^i y1^j
+  out = array_init (Nx, Ny);
+
+  for (i = 0; i < Nx; i++) {
+    for (j = 0; j < Ny; j++) {
+      out[i][j] = poly[i][j+1];
+    }
+  }
+  return out;
+}
+
+double poly2d_eval (double **poly, int Nx, int Ny, double x, double y) {
+
+  int i, j;
+  double xsum, ysum, sum;
+
+  sum = 0;
+  xsum = ysum = 1.0;
+
+  for (i = 0; i < Nx; i++) {
+    ysum = xsum;
+    for (j = 0; j < Ny; j++) {
+      sum += poly[i][j] * ysum;
+      ysum *= y;
+    }
+    xsum *= x;
+  }
+  return (sum);
+}
+
+/* linear portion of fit : NORDER is 1 */
+/* this should only apply to the polynomial, not the projection terms */
+/* compare with psastro supporting code */
+void fit_apply_coords (CoordFit *fit, Coords *coords) {
+
+  double c11, c12;
+  double c21, c22;
+  double Xo, Yo, R;
+  CoordFit *modfit;
+
+  /* I have L,M = fit(X,Y). set corresponding terms for coords */
+
+  // L = a[0][0] + a[1][0]x^1 y^0 + a[0][1] x^0 y^1 + ...
+  // L = pc1_1*cd1*(x - cp1) + pc1_2*cd2*(y - cp2) + ...
+
+  CoordsGetCenter (fit, 0.001, &Xo, &Yo);
+  coords[0].crpix1 = Xo;
+  coords[0].crpix2 = Yo;
+  
+  // resulting fit should have zero constant terms
+  modfit = CoordsSetCenter (fit, Xo, Yo);
+
+  // set pc1_1, pc1_2, pc2_1, pc2_2 (cd1,cd2 = 1.0)
+  coords[0].pc1_1 = modfit[0].xfit[1][0];
+  coords[0].pc1_2 = modfit[0].xfit[0][1];
+  coords[0].pc2_1 = modfit[0].yfit[1][0];
+  coords[0].pc2_2 = modfit[0].yfit[0][1];
+
+  // set the polyterm elements 
+  if (coords->Npolyterms > 1) {
+    coords[0].polyterms[0][0] = modfit[0].xfit[2][0];
+    coords[0].polyterms[1][0] = modfit[0].xfit[1][1];
+    coords[0].polyterms[2][0] = modfit[0].xfit[0][2];
+
+    coords[0].polyterms[0][1] = modfit[0].yfit[2][0];
+    coords[0].polyterms[1][1] = modfit[0].yfit[1][1];
+    coords[0].polyterms[2][1] = modfit[0].yfit[0][2];
+  }
+
+  // I need to validate Norder
+  if (coords->Npolyterms > 2) {
+    coords[0].polyterms[3][0] = modfit[0].xfit[3][0];
+    coords[0].polyterms[4][0] = modfit[0].xfit[2][1];
+    coords[0].polyterms[5][0] = modfit[0].xfit[1][2];
+    coords[0].polyterms[6][0] = modfit[0].xfit[0][3];
+
+    coords[0].polyterms[3][1] = modfit[0].yfit[3][0];
+    coords[0].polyterms[4][1] = modfit[0].yfit[2][1];
+    coords[0].polyterms[5][1] = modfit[0].yfit[1][2];
+    coords[0].polyterms[6][1] = modfit[0].yfit[0][3];
+  }
+
+  /* we do not modify crval1,2: these are kept at the default values */
+
+  /* normalize pc11,etc */
+  c11 = coords[0].pc1_1;
+  c21 = coords[0].pc1_1;
+  c12 = coords[0].pc1_1;
+  c22 = coords[0].pc1_1;
+  coords[0].cdelt1 = coords[0].cdelt2 = sqrt(fabs(c11*c22 - c12*c21));
+  R = 1 / coords[0].cdelt1;
+
+  coords[0].pc1_1  = c11*R;
+  coords[0].pc2_1  = c21*R;
+  coords[0].pc1_2  = c12*R;
+  coords[0].pc2_2  = c22*R;
+
+  fit_free (modfit);
+  /* keep the order and type from initial values */
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/global_stats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/global_stats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/global_stats.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "relastro.h"
+
+void global_stats (Catalog *catalog, int Ncatalog) {
+
+  StatType stN, stX, stS, imN, imX, imM, imD, msM, msX, msN, msD;
+
+  initstats ("MEAN");
+
+  stN = statsStarN (catalog, Ncatalog);
+  stX = statsStarX (catalog, Ncatalog);
+  stS = statsStarS (catalog, Ncatalog);
+
+  imN = statsImageN (catalog);
+  imX = statsImageX (catalog);
+  imM = statsImageM (catalog);
+  imD = statsImagedM (catalog);
+
+  msN = statsMosaicN (catalog);
+  msM = statsMosaicM (catalog);
+  msD = statsMosaicdM (catalog);
+  msX = statsMosaicX (catalog);
+
+  fprintf (stderr, "STATS            median     mean    sigma      min      max   Nmeas\n");
+  fprintf (stderr, "meas / image:   %7.0f  %7.0f  %7.0f  %7.0f  %7.0f  %6d\n",   imN.median, imN.mean, imN.sigma, imN.min, imN.max, imN.Nmeas);
+  fprintf (stderr, "meas / mosaic:  %7.0f  %7.0f  %7.0f  %7.0f  %7.0f  %6d\n",   msN.median, msN.mean, msN.sigma, msN.min, msN.max, msN.Nmeas);
+  fprintf (stderr, "meas / star:    %7.0f  %7.1f  %7.1f  %7.0f  %7.0f  %6d\n",   stN.median, stN.mean, stN.sigma, stN.min, stN.max, stN.Nmeas);
+
+  fprintf (stderr, "chisq image:    %7.1f  %7.1f  %7.1f  %7.1f  %7.1f  %6d\n",   imX.median, imX.mean, imX.sigma, imX.min, imX.max, imX.Nmeas);
+  fprintf (stderr, "chisq mosaic:   %7.1f  %7.1f  %7.1f  %7.1f  %7.1f  %6d\n",   msX.median, msX.mean, msX.sigma, msX.min, msX.max, msX.Nmeas);
+  fprintf (stderr, "chisq star:     %7.1f  %7.1f  %7.1f  %7.1f  %7.1f  %6d\n",   stX.median, stX.mean, stX.sigma, stX.min, stX.max, stX.Nmeas);
+
+  fprintf (stderr, "Mcal image:     %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   imM.median, imM.mean, imM.sigma, imM.min, imM.max, imM.Nmeas);
+  fprintf (stderr, "dMcal image:    %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   imD.median, imD.mean, imD.sigma, imD.min, imD.max, imD.Nmeas);
+
+  fprintf (stderr, "Mcal mosaic:    %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   msM.median, msM.mean, msM.sigma, msM.min, msM.max, msM.Nmeas);
+  fprintf (stderr, "dMcal mosaic:   %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   msD.median, msD.mean, msD.sigma, msD.min, msD.max, msD.Nmeas);
+
+  fprintf (stderr, "dMrel star:     %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n\n", stS.median, stS.mean, stS.sigma, stS.min, stS.max, stS.Nmeas);
+
+  initstats (STATMODE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/initialize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/initialize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/initialize.c	(revision 16632)
@@ -0,0 +1,61 @@
+# include "relastro.h"
+
+void initialize (int argc, char **argv) {
+
+  int NPHOTCODES;
+  char *codename, *ptr;
+
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  /* XXX we need to build a list of accepted photcodes. these will be used by bcatalog to accept or
+     reject loaded data */
+
+  Nphotcodes = 0;
+  photcodes = NULL;
+  if (PHOTCODE_LIST != NULL) {
+    NPHOTCODES = 10;
+    ALLOCATE (photcodes, PhotCode *, NPHOTCODES);
+
+    /* parse the comma-separated list of photcodes */
+    strtok_r (PHOTCODE_LIST, ",", &ptr);
+    while ((codename = strtok_r (NULL, ",", &ptr)) != NULL) {
+      fprintf (stderr, "PHOTCODE_LIST: %s\n", PHOTCODE_LIST);
+      fprintf (stderr, "codename: %s\n", codename);
+      if ((photcodes[Nphotcodes] = GetPhotcodebyName (codename)) == NULL) {
+	fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", codename);
+	exit (1);
+      }
+      Nphotcodes ++;
+      CHECK_REALLOCATE (photcodes, PhotCode *, NPHOTCODES, Nphotcodes, 10);
+    }
+  }
+  PhotNsec = GetPhotcodeNsecfilt ();
+
+  initstats (STATMODE);
+
+  IMAGE_BAD = ID_IMAGE_POOR | ID_IMAGE_FEW | ID_IMAGE_SKIP;
+  STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
+  MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR | ID_MEAS_SKIP | ID_MEAS_AREA;
+
+  /* XXX drop irrelevant entries */
+  if (SHOW_PARAMS) {
+    fprintf (stderr, "current parameter settings:\n");
+    if (TimeSelect) {
+      fprintf (stderr, "TimeSelect: TRUE (%s - %s)\n", ohana_sec_to_date (TSTART), ohana_sec_to_date (TSTOP));
+    } else {
+      fprintf (stderr, "TimeSelect: FALSE\n");
+    }
+    fprintf (stderr, "VERBOSE: %d, PLOTSTUFF: %d\n", VERBOSE, PLOTSTUFF);
+
+    fprintf (stderr, "MAG_LIM                %lf\n", MAG_LIM);
+    fprintf (stderr, "STAR_SCATTER           %lf\n", STAR_SCATTER);
+    fprintf (stderr, "IMAGE_SCATTER          %lf\n", IMAGE_SCATTER);
+    fprintf (stderr, "IMAGE_OFFSET           %lf\n", IMAGE_OFFSET);
+    fprintf (stderr, "IMAGE_CATALOG          %s\n",  ImageCat);
+    fprintf (stderr, "GSCFILE                %s\n",  GSCFILE);
+    fprintf (stderr, "CATDIR                 %s\n",  CATDIR);
+    exit (0);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/liststats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/liststats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/liststats.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include "relastro.h"
+
+enum {M_MEAN, M_MEDIAN, M_WT_MEAN, M_INNER_MEAN, 
+      M_INNER_WTMEAN, M_CHI_INNER_MEAN, M_CHI_INNER_WTMEAN};
+
+static int statmode;
+
+void initstats (char *mode) {
+
+  statmode = -1;
+  if (!strcmp (mode, "MEAN")) statmode = M_MEAN;
+  if (!strcmp (mode, "MEDIAN")) statmode = M_MEDIAN;
+  if (!strcmp (mode, "WT_MEAN")) statmode = M_WT_MEAN;
+  if (!strcmp (mode, "INNER_MEAN")) statmode = M_INNER_MEAN;
+  if (!strcmp (mode, "INNER_WTMEAN")) statmode = M_INNER_WTMEAN;
+  if (!strcmp (mode, "CHI_INNER_MEAN")) statmode = M_CHI_INNER_MEAN;
+  if (!strcmp (mode, "CHI_INNER_WTMEAN")) statmode = M_CHI_INNER_WTMEAN;
+
+  if (statmode == -1) {
+    fprintf (stderr, "ERROR: invalid stats mode: %s\n", mode);
+    exit (1);
+  }
+}
+
+int liststats (double *value, double *dvalue, int N, StatType *stats) {
+  
+  int i, ks, ke, Nm;
+  double Mo, dMo, M, dM, X2, dS, *chi;
+
+  ke = ks = dMo = 0;
+
+  stats[0].Nmeas = N;
+  stats[0].mean  = 0;
+  stats[0].sigma = 0;
+  stats[0].error = 0;
+  stats[0].chisq = 0;
+  if (N < 1) return (FALSE);
+
+  dsortpair (value, dvalue, N);
+  stats[0].median = value[(int)(0.5*N)];
+  stats[0].min    = value[0];
+  stats[0].max    = value[N-1];
+
+  switch (statmode) {
+  case M_MEDIAN:
+    ks = 0;
+    ke = N;
+    Mo = stats[0].median;
+    Nm = N;
+    goto chisq;
+    break;
+  case M_MEAN:
+  case M_WT_MEAN:
+    ks = 0;
+    ke = N;
+    break;
+  case M_INNER_MEAN:
+  case M_INNER_WTMEAN:
+  case M_CHI_INNER_MEAN:
+  case M_CHI_INNER_WTMEAN:
+    ks = 0.25*N + 0.50;
+    ke = 0.75*N + 0.25;
+    if (N <= 3) {
+      ks = 0;
+      ke = N;
+    }
+    break;
+  }    
+
+  if ((statmode == M_CHI_INNER_MEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    ALLOCATE (chi, double, N);
+    for (i = 0; i < N; i++) {
+      chi[i] = (value[i] - stats[0].median) / dvalue[i];
+    }
+    dsortthree (chi, value, dvalue, N);
+    free (chi);
+  }
+
+  /* calculating the per-star offset based on the weighted average */
+  M = dM = Nm = 0;
+  if ((statmode == M_WT_MEAN) || (statmode == M_INNER_WTMEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    for (i = ks; i < ke; i++) {
+      M   += value[i] / SQ (dvalue[i]);
+      dM  += 1.0 / SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / dM;
+    dMo = sqrt (1.0 / dM);
+  } else {
+    for (i = ks; i < ke; i++) {
+      M   += value[i];
+      dM  += SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / (double) Nm;
+    dMo = sqrt (dM / (double) Nm);
+  }
+
+ chisq:
+  /* find sigma and chisq */
+  X2 = dS = 0;
+  for (i = ks; i < ke; i++) {
+    M  = SQ (value[i] - Mo);
+    dM = SQ (dvalue[i]);
+    X2 += M / dM;
+    dS += M;
+  }
+  X2 = X2 / Nm;
+  dS = sqrt (dS / Nm);
+
+  stats[0].mean  = Mo;
+  stats[0].Nmeas = Nm;
+  stats[0].chisq = X2;
+  stats[0].sigma = dS;
+  stats[0].error = dMo;
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/load_catalogs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/load_catalogs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/load_catalogs.c	(revision 16632)
@@ -0,0 +1,68 @@
+# include "relastro.h"
+
+Catalog *load_catalogs (SkyList *skylist, int *Ncatalog, int subselect) {
+
+  int i, j, k, m, Nstar;
+  Catalog *catalog, *pcatalog, tcatalog;
+
+  if (VERBOSE) fprintf (stderr, "loading catalog data\n");
+
+  ALLOCATE (catalog, Catalog, skylist[0].Nregions);
+
+  // load data from each region file, only use bright stars
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // we only allow output if we do not use a subset.  in this case,
+    // the output parameters are correctly set for catalog[i] via pcatalog
+    pcatalog = subselect ? &tcatalog : &catalog[i];
+
+    // set up the basic catalog info
+    pcatalog[0].filename  = skylist[0].filename[i];
+    pcatalog[0].catformat = dvo_catalog_catformat (CATFORMAT);    // set the default catformat from config data
+    pcatalog[0].catmode   = dvo_catalog_catmode (CATMODE);        // set the default catmode from config data
+    pcatalog[0].catflags  = LOAD_AVES | LOAD_MEAS | LOAD_SECF; // don't need to load all data at this point
+    pcatalog[0].Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    if (!dvo_catalog_open (pcatalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", pcatalog[0].filename);
+      exit (1);
+    }
+    if (VERBOSE && !pcatalog[0].Naves_disk) fprintf (stderr, "no data in %s, skipping\n", pcatalog[0].filename);
+
+    // select only the brighter stars
+    if (subselect) {
+      bcatalog (&catalog[i], &tcatalog);
+      dvo_catalog_unlock (&tcatalog);
+      dvo_catalog_free (&tcatalog);
+    } else {
+      if (RESET) {
+	for (j = 0; j < catalog[i].Naverage; j++) {
+	  catalog[i].average[j].code = 0;
+	  m = catalog[i].average[j].offset;
+	  for (k = 0; k < catalog[i].average[j].Nm; k++) {
+	    catalog[i].measure[m+k].dbFlags = 0;
+	  }
+	}
+      }
+    }
+  }
+
+  // XXX keep this test?
+  Nstar = 0;
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    Nstar += catalog[i].Naverage;
+  }
+  if (Nstar < 2) { 
+    fprintf (stderr, "warning: insufficient stars %d\n", Nstar);
+  }
+
+  // XXX consider only returning the populated catalogs
+  *Ncatalog = skylist[0].Nregions;
+  return (catalog);
+}
+
+/* this function loads all relevant catalog files for the first pass.  it currently loads the data
+   read only (SOFT lock) since it assumes the image table has been locked. if we go to the new
+   addstar locking paradigm, in which the images and catalogs are updated independently, then we may
+   need to use an XCLD lock here.  
+*/
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/load_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/load_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/load_images.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "relastro.h"
+
+SkyList *load_images (FITS_DB *db, SkyRegion *region) {
+
+  Image     *image, *subset;
+  int        Nimage, Nsubset;
+  int       *LineNumber;
+
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+
+  // load the current sky table (layout of all SkyRegions) 
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  // determine the populated SkyRegions overlapping the requested area
+  skylist = SkyListByPatch (sky, -1, region);
+
+  // convert database table to internal structure
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  // select the images which overlap the selected sky regions
+  subset = select_images (skylist, image, Nimage, &LineNumber, &Nsubset);
+
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, LineNumber, Nsubset);
+
+  initImages (subset, Nsubset);
+  initMosaics (subset, Nsubset);
+  
+  /* unlock, if we can (else, unlocked below) */
+  if (!UPDATE) dvo_image_unlock (db); 
+
+  return (skylist);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/mkpolyterm.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/mkpolyterm.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/mkpolyterm.c	(revision 16632)
@@ -0,0 +1,159 @@
+# include "relastro.h"
+
+double factorial (int N) {
+
+  int i;
+  double F;
+
+  F = 1;
+  for (i = N; i > 1; i--) {
+    F *= i;
+  }
+  return F;
+}
+
+// XXX use a separate structure for the map (x2,y2 = f,g(x1,y1)) ?
+
+// given a 2D transformation -- L(x,y),M(x,y) -- find the coordinates x,y
+// for which L,M = 0,0. tol is the allowed error on x,y.
+int CoordsGetCenter (CoordFit *fit, double tol, double *xo, double *yo) {
+
+  int i, Nx, Ny;
+  double R, Xo, Yo, dPos;
+  double **XdX, **XdY, **YdX, **YdY, **alpha, **beta;
+  double **xfit, **yfit;
+
+  xfit = fit[0].xfit;
+  yfit = fit[0].yfit;
+
+  // solve for Xo,Yo where L,M(Xo,Yo) = 0,0
+  // start with linear solution for Xo,Yo:
+  R  = (xfit[1][0]*yfit[0][1] - xfit[0][1]*yfit[1][0]);
+  Xo = (yfit[0][0]*xfit[0][1] - xfit[0][0]*yfit[0][1])/R;
+  Yo = (xfit[0][0]*yfit[1][0] - yfit[0][0]*xfit[1][0])/R;
+
+  Nx = fit[0].Nterms;
+  Ny = fit[0].Nterms;
+
+  // iterate to actual solution: requires small non-linear terms
+  if (fit[0].Norder > 1) {
+    XdX = poly2d_dx (xfit, Nx, Ny);
+    XdY = poly2d_dy (xfit, Nx, Ny);
+    YdX = poly2d_dx (yfit, Nx, Ny);
+    YdY = poly2d_dy (yfit, Nx, Ny);
+
+    alpha = array_init (2, 2);
+    beta  = array_init (2, 1);
+
+    /* this loop uses the Newton-Raphson method to solve for Xo,Yo
+     * it needs the high order terms to be small 
+     * Xo,Yo are in pixels;
+     */
+    dPos = tol + 1;
+    for (i = 0; (dPos > tol) && (i < 20); i++) {
+      // NOTE: order for alpha is: [y][x]
+      alpha[0][0] = poly2d_eval (XdX, Nx-1, Ny,   Xo, Yo);
+      alpha[1][0] = poly2d_eval (XdY, Nx,   Ny-1, Xo, Yo);
+      alpha[0][1] = poly2d_eval (YdX, Nx-1, Ny,   Xo, Yo);
+      alpha[1][1] = poly2d_eval (YdY, Nx,   Ny-1, Xo, Yo);
+
+      beta[0][0] = poly2d_eval (xfit, Nx, Ny, Xo, Yo);
+      beta[1][0] = poly2d_eval (yfit, Nx, Ny, Xo, Yo);
+
+      dgaussjordan (alpha, beta, 2, 1);
+
+      Xo -= beta[0][0];
+      Yo -= beta[1][0];
+      dPos = hypot(beta[0][0], beta[1][0]);
+    }
+    array_free (alpha, 2);
+    array_free (beta, 2);
+    array_free (XdX, Nx - 1);
+    array_free (XdY, Nx);
+    array_free (YdX, Nx - 1);
+    array_free (YdY, Nx);
+  }
+  *xo = Xo;
+  *yo = Yo;
+  return TRUE;
+}
+
+// convert a transformation L(x,y) to L'(x-xo,y-yo)
+CoordFit *CoordsSetCenter (CoordFit *input, double Xo, double Yo) {
+
+  int i, j, Nx, Ny;
+  double **xPx, **yPx, **xPy, **yPy, **tmp;
+
+  CoordFit *output;
+  output = fit_init (input->Norder);
+
+  /* given two equivalent polynomial representations L(x,y) = \sum_i \sum_j A_{i,j} x^i y^j
+   * we can transform L(x,y) into L'(x-xo,y-yo) by taking the derivatives of both sides and 
+   * noting that the constant term in each is the coefficient in the case of L(x,y) and is the 
+   * value of L'(-xo,-yo) in the second case.
+   */
+
+  Nx = input->Nterms;
+  Ny = input->Nterms;
+
+  xPx = poly2d_copy (input->xfit, Nx, Ny);
+  yPx = poly2d_copy (input->yfit, Nx, Ny);
+
+  for (i = 0; i < input->Nterms; i++) {
+    xPy = poly2d_copy (xPx, Nx, Ny);
+    yPy = poly2d_copy (yPx, Nx, Ny);
+    for (j = 0; j < input->Nterms; j++) {
+      output->xfit[i][j] = poly2d_eval (xPy, Nx, Ny, Xo, Yo) / factorial(i) / factorial(j);
+      output->yfit[i][j] = poly2d_eval (yPy, Nx, Ny, Xo, Yo) / factorial(i) / factorial(j);
+
+      // take the next derivative wrt y, catch output (is NULL on last pass)
+      if (Ny > 0) {
+	tmp = poly2d_dy(xPy, Nx, Ny);
+	array_free (xPy, Nx);
+	xPy = tmp;
+
+	tmp = poly2d_dy(yPy, Nx, Ny);
+	array_free (yPy, Nx);
+	yPy = tmp;
+      } else {
+	array_free (xPy, Nx);
+	array_free (yPy, Nx);
+      }
+
+      Ny --;
+    }
+    Ny = input->Nterms;
+    // take the next derivative wrt x, catch output (is NULL on last pass)
+    if (Nx > 0) {
+      tmp = poly2d_dx(xPx, Nx, Ny);
+      array_free (xPx, Nx);
+      xPx = tmp;
+      tmp = poly2d_dx(yPx, Nx, Ny);
+      array_free (yPx, Nx);
+      yPx = tmp;
+      Nx --;
+    } else {
+      array_free (xPx, Nx);
+      array_free (yPx, Nx);
+    }
+  }
+  return output;
+}
+
+/*
+  Coords uses a rigid sequence for the coefficients:
+
+  x^0 y^0 : crpix1,2 (but note this is applied before higher order terms)
+
+  x^1 y^0 : pc1_1, pc2_1
+  x^0 y^1 : pc1_2, pc2_2
+
+  x^2 y^0 : polyterm[0][0,1]
+  x^1 y^1 : polyterm[1][0,1]
+  x^0 y^2 : polyterm[2][0,1]
+
+  x^3 y^0 : polyterm[3][0,1]
+  x^2 y^1 : polyterm[4][0,1]
+  x^1 y^2 : polyterm[5][0,1]
+  x^0 y^3 : polyterm[6][0,1]
+*/
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/plot_scatter.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/plot_scatter.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/plot_scatter.c	(revision 16632)
@@ -0,0 +1,59 @@
+# include "relastro.h"
+   
+void plot_scatter (Catalog *catalog, int Ncatalog) {
+
+# if (0)   
+  int i, j, k, m, N, Ntot;
+  float Mrel, Mcal, Mmos, Mgrid;
+  double *xlist, *ylist, *ilist;
+  Graphdata graphdata;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Ntot += catalog[i].average[j].Nm;
+    }
+  }
+  ALLOCATE (xlist, double, Ntot);
+  ALLOCATE (ylist, double, Ntot);
+  ALLOCATE (ilist, double, Ntot);
+
+  N = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].flags & MEAS_BAD) continue;
+
+	Mrel = catalog[i].secfilt[PhotNsec*j+PhotSec].M;
+	xlist[N] = Mrel;
+	ylist[N] = PhotSys  (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]) - Mcal - Mmos - Mgrid - Mrel;
+	ilist[N] = PhotInst (&catalog[i].measure[m]);
+	N++;
+      }
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.xmin = PlotMmin;
+  graphdata.xmax = PlotMmax;
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, ylist, N, "mag vs dmag", "Mag.png");
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, ilist, ylist, N, "imag vs dmag", "iMag.png");
+  free (xlist);
+  free (ylist);
+  free (ilist);
+
+# endif
+}
+
+/* XXX this should become astrometrically relevant */
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/plotstuff.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/plotstuff.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/plotstuff.c	(revision 16632)
@@ -0,0 +1,146 @@
+# include "relastro.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+/*
+static union { unsigned char c[4]; float f; } f_undef = { {0xff, 0xff, 0xff, 0xfe} };
+# define fUNDEF (f_undef.f)
+*/
+
+static union { unsigned char c[8]; float d; } d_undef = { {0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00} };
+# define dUNDEF (d_undef.d)
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+  char name[100];
+
+  sprintf (name, "gastro [%d]", N);
+  Xgraph[N] = KapaOpen ("kapa", name);
+
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+
+  if (Xgraph[N] == 0) return;
+
+  KapaBox (Xgraph[N], graphmode);
+  return;
+}
+
+void JpegPlot (Graphdata *graphmode, int N, char *filename) {
+
+  if (Xgraph[N] == 0) return;
+
+  KapaPNG (Xgraph[N], filename);
+  return;
+}
+
+void PSPlot (Graphdata *graphmode, int N, char *filename) {
+
+  if (Xgraph[N] == 0) return;
+
+  KiiPS (Xgraph[N], filename, TRUE, KAPA_PS_NEWPLOT, "default");
+  return;
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  if (Npts < 1) return;
+
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+
+  KapaClearSections (Xgraph[N]);
+
+  KapaPrepPlot (Xgraph[N], Npts, graphmode);
+  return;
+}
+
+void PlotLabel (char *string, int N) {
+
+  if (Xgraph[N] == 0) return;
+
+  KapaSendLabel (Xgraph[N], string, 2);
+}
+
+void PlotVector (int Npts, double *vect, int mode, int N, char *type) {
+
+  float *values;
+  int i;
+
+  if (Npts < 1) return;
+
+  ALLOCATE (values, float, Npts);
+  for (i = 0; i < Npts; i++) {
+    values[i] = vect[i];
+  }
+
+  KapaPlotVector (Xgraph[N], Npts, values, type);
+  free (values);
+  return;
+}
+
+void plot_list (Graphdata *graphdata, double *xlist, double *ylist, int N, char *label, char *file) {
+
+  int i;
+  StatType stats;
+  
+  stats.min = stats.max = xlist[0];
+  for (i = 0; i < N; i++) {
+    stats.min = MIN (stats.min, xlist[i]);
+    stats.max = MAX (stats.max, xlist[i]);
+  }
+  if (graphdata[0].xmin == dUNDEF) graphdata[0].xmin = 1.05*stats.min - 0.05*stats.max;
+  if (graphdata[0].xmax == dUNDEF) graphdata[0].xmax = 1.05*stats.max - 0.05*stats.min;
+
+  stats.min = stats.max = ylist[0];
+  for (i = 0; i < N; i++) {
+    stats.min = MIN (stats.min, ylist[i]);
+    stats.max = MAX (stats.max, ylist[i]);
+  }
+  if (graphdata[0].ymin == dUNDEF) graphdata[0].ymin = 1.05*stats.min - 0.05*stats.max;
+  if (graphdata[0].ymax == dUNDEF) graphdata[0].ymax = 1.05*stats.max - 0.05*stats.min;
+
+  PrepPlotting (N, graphdata, 0);
+  PlotVector (N, xlist, 0, 0, "x");
+  PlotVector (N, ylist, 1, 0, "y");
+  if (label != NULL) PlotLabel (label, 0);
+  DonePlotting (graphdata, 0);
+
+  if ((file != NULL) && SAVEPLOT) JpegPlot (graphdata, 0, file);
+  if (PLOTDELAY > 500000) {
+    fprintf (stdout, "press return\n"); 
+    fscanf (stdin, "%*c");
+  } else {
+    usleep (PLOTDELAY);
+  }
+}
+
+void plot_defaults (Graphdata *graphdata) {
+
+  graphdata[0].style = 2;
+  graphdata[0].ptype = 2;
+  graphdata[0].ltype = 0;
+  graphdata[0].etype = 0;
+  graphdata[0].color = black;
+  graphdata[0].lweight = 0;
+  graphdata[0].size = 0.5;
+
+  graphdata[0].xmin = dUNDEF;
+  graphdata[0].xmax = dUNDEF;
+  graphdata[0].ymin = dUNDEF;
+  graphdata[0].ymax = dUNDEF;
+   
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/relastro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/relastro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/relastro.c	(revision 16632)
@@ -0,0 +1,72 @@
+# include "relastro.h"
+
+int main (int argc, char **argv) {
+
+  int status, Ncatalog;
+  Catalog *catalog;
+  FITS_DB db;
+
+  SkyList *skylist = NULL;
+
+  /* get configuration info, args */
+  initialize (argc, argv);
+
+  /* register database handle with shutdown procedure */
+  set_db (&db);
+
+  /* lock and load the image db table */
+  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+  if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+  if (!dvo_image_load (&db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db.filename);
+
+  /* load regions and images based on specified sky patch */
+  skylist = load_images (&db, &UserPatch);
+
+  /* load catalog data from region files : subselect only if we are not doing the objects */
+  catalog = load_catalogs (skylist, &Ncatalog, (FIT_TARGET != TARGET_OBJECTS));
+
+  /* match measurements with images */
+  initImageBins (catalog, Ncatalog);
+  findImages (catalog, Ncatalog);
+
+  if (PLOTSTUFF) {
+    // plot_star_coords (catalog, Ncatalog);
+    // plot_mosaic_fields (catalog);
+  }
+
+  /* major modes */
+  switch (FIT_TARGET) {
+    case TARGET_OBJECTS:
+      UpdateObjects (catalog, Ncatalog);
+      break;
+
+    case TARGET_SIMPLE:
+      UpdateSimple (catalog, Ncatalog);
+      break;
+
+    case TARGET_CHIPS:
+      UpdateChips (catalog, Ncatalog);
+      break;
+
+    case TARGET_MOSAICS:
+      UpdateMosaic (catalog, Ncatalog);
+      break;
+
+    default:
+      fprintf (stderr, "programming error at %s:%d", __FILE__, __LINE__);
+      exit (2);
+  }
+
+  if (!UPDATE) exit (0);
+
+  if (FIT_TARGET == TARGET_OBJECTS) {
+    save_catalogs (catalog, Ncatalog);
+  } else {
+    dvo_image_update (&db, VERBOSE);
+    dvo_image_unlock (&db); 
+  }
+
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/reload_catalogs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/reload_catalogs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/reload_catalogs.c	(revision 16632)
@@ -0,0 +1,51 @@
+# include "relastro.h"
+
+void reload_catalogs (SkyList *skylist) {
+
+  int i;
+  int status;
+  struct stat filestat;
+  Catalog catalog;
+
+  if (VERBOSE) fprintf (stderr, "re-loading catalog data\n");
+
+  /* load data from each region file */
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    catalog.filename = skylist[0].filename[i];
+
+    // only update existing db tables
+    status = stat (catalog.filename, &filestat);
+    if ((status == -1) && (errno == ENOENT)) {
+      if (VERBOSE) fprintf (stderr, "no file %s, skipping\n", catalog.filename);
+      continue;
+    }
+
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);    // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);        // set the default catmode from config data
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (VERBOSE && (catalog.Naves_disk == 0)) {
+	fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+	dvo_catalog_unlock (&catalog);
+	dvo_catalog_free (&catalog);
+	continue;
+    }
+
+    initImageBins  (&catalog, 1);
+    initMosaicBins (&catalog, 1);
+
+    findImages (&catalog, 1);
+    findMosaics (&catalog, 1);
+
+    dvo_catalog_save (&catalog, VERBOSE); 
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+
+    freeImageBins (1);
+    freeMosaicBins (1);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/save_catalogs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/save_catalogs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/save_catalogs.c	(revision 16632)
@@ -0,0 +1,15 @@
+# include "relastro.h"
+
+void save_catalogs (Catalog *catalog, int Ncatalog) {
+
+  int i;
+
+  /* load data from each region file */
+  for (i = 0; i < Ncatalog; i++) {
+
+    if (VERBOSE) fprintf (stderr, "saving catalog %s\n", catalog[i].filename);
+    dvo_catalog_save (&catalog[i], VERBOSE); 
+    dvo_catalog_unlock (&catalog[i]);
+    dvo_catalog_free (&catalog[i]);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/select_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/select_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/select_images.c	(revision 16632)
@@ -0,0 +1,245 @@
+# include "relastro.h"
+
+/* this function returns a list of all images which overlap the given SkyList (set of
+   SkyRegions).  All images in the image catalog are tested once, so there is no check that an
+   image already has been included.  LineNum stores the locations in the Image database of the
+   list of images */
+
+typedef struct {
+  double Xc[5];
+  double Yc[5];
+  double Rc;
+  double Dc;
+} SkyRegionCoords;
+
+Image *select_images (SkyList *skylist, Image *timage, int Ntimage, int **LineNumber, int *Nimage) {
+  
+  Image *image;
+  int i, j, k, m, found, nimage, NIMAGE;
+  int InRange;
+  double Ri[5], Di[5], Xi[5], Yi[5], dx, dy;
+  int *line_number;
+  Coords tcoords;
+  SkyRegionCoords *skycoords;
+  
+  if (skylist[0].Nregions < 1) {
+    *Nimage = 0;
+    *LineNumber = NULL;
+    if (VERBOSE) fprintf (stderr, "no matching sky regions\n");
+    return NULL;
+  }
+
+  // the comparison is made in the catalog local projection. below we set crval1,2
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  ALLOCATE (skycoords, SkyRegionCoords, skylist[0].Nregions);
+
+  /* compare with each region file */
+  for (i = 0; i < skylist[0].Nregions; i++) { 
+
+    /* we make positional comparisons in the projection of catalog */
+    skycoords[i].Rc = 0.5*(skylist[0].regions[i][0].Rmax + skylist[0].regions[i][0].Rmin);
+    skycoords[i].Dc = 0.5*(skylist[0].regions[i][0].Dmax + skylist[0].regions[i][0].Dmin);
+    tcoords.crval1 = skycoords[i].Rc;
+    tcoords.crval2 = skycoords[i].Dc;
+
+    /* define catalog corners */
+    RD_to_XY (&skycoords[i].Xc[0], &skycoords[i].Yc[0], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmin, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[1], &skycoords[i].Yc[1], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmin, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[2], &skycoords[i].Yc[2], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmax, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[3], &skycoords[i].Yc[3], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmax, &tcoords);
+    skycoords[i].Xc[4] = skycoords[i].Xc[0];    
+    skycoords[i].Yc[4] = skycoords[i].Yc[0];    
+
+    dx = 0.02*(skycoords[i].Xc[2] - skycoords[i].Xc[0]);
+    dy = 0.02*(skycoords[i].Yc[2] - skycoords[i].Yc[0]);
+    skycoords[i].Xc[0] -= dx; skycoords[i].Yc[0] -= dy;
+    skycoords[i].Xc[1] += dx; skycoords[i].Yc[1] -= dy;
+    skycoords[i].Xc[2] += dx; skycoords[i].Yc[2] += dy;
+    skycoords[i].Xc[3] -= dx; skycoords[i].Yc[3] += dy;
+    skycoords[i].Xc[4] -= dx; skycoords[i].Yc[4] -= dy;
+  }
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+  BuildChipMatch (timage, Ntimage);
+
+  nimage = 0;
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  ALLOCATE (line_number, int, NIMAGE);
+  
+  // go through the complete list of images, selecting ones which overlap any region
+  for (i = 0; i < Ntimage; i++) {
+      
+    /* exclude images by photcode, if selected */
+    if (Nphotcodes > 0) {
+      found = FALSE;
+      for (j = 0; (j < Nphotcodes) && !found; j++) {
+	if (photcodes[j][0].code == timage[i].photcode) found = TRUE;
+      }
+      if (!found) continue;
+    }
+
+    /* exclude images by time */
+    if (TimeSelect) {
+      if (timage[i].tzero < TSTART) continue;
+      if (timage[i].tzero > TSTOP) continue;
+    }
+    
+    if (!FindMosaicForImage (timage, Ntimage, i)) continue;
+
+    /* define image corners */
+    Xi[0] = 0;            Yi[0] = 0;
+    Xi[1] = timage[i].NX; Yi[1] = 0;
+    Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+    Xi[3] = 0;            Yi[3] = timage[i].NY;
+    Xi[4] = 0;            Yi[4] = 0;
+    found = FALSE;
+
+    /* transform to ra,dec */
+    for (j = 0; j < 5; j++) {
+      XY_to_RD (&Ri[j], &Di[j], Xi[j], Yi[j], &timage[i].coords);
+    }
+
+    /* compare with each region file */
+    for (m = 0; (m < skylist[0].Nregions) && !found; m++) { 
+
+      /* we make positional comparisons in the projection of catalog */
+      tcoords.crval1 = skycoords[m].Rc;
+      tcoords.crval2 = skycoords[m].Dc;
+
+      /* transform to ra,dec */
+      InRange = TRUE;
+      for (j = 0; (j < 5) && InRange; j++) {
+	InRange = RD_to_XY (&Xi[j], &Yi[j], Ri[j], Di[j], &tcoords);
+      }
+      if (!InRange) continue;
+
+      /* check if image corner inside catalog */
+      for (j = 0; (j < 4) && !found; j++) {
+	found = corner_check (&Xi[j], &Yi[j], &skycoords[m].Xc[0], &skycoords[m].Yc[0]);
+      }
+      /* check if catalog corner inside image */
+      for (j = 0; (j < 4) && !found; j++) {
+	found = corner_check (&skycoords[m].Xc[j], &skycoords[m].Yc[j], &Xi[0], &Yi[0]);
+      }
+      /* check if edges cross */
+      for (j = 0; (j < 4) && !found; j++) {
+	for (k = 0; (k < 4) && !found; k++) {
+	  found = edge_check (&Xi[j], &Yi[j], &skycoords[m].Xc[k], &skycoords[m].Yc[k]);
+	}
+      }
+      if (!found) continue;
+
+      image[nimage] = timage[i]; 
+      /* always allow 'few' images to succeed, if possible */
+      if (image[nimage].code & ID_IMAGE_FEW) { 
+	image[nimage].code &= ~(ID_IMAGE_FEW | ID_IMAGE_POOR);
+      }
+      if (RESET) {
+	// XXX do we need this in relastro?
+	assignMcal (&image[nimage], (double *) NULL, -1);
+	image[nimage].dMcal = NAN;
+	image[nimage].code &= ~ID_IMAGE_POOR;
+      }
+      line_number[nimage] = i;
+      nimage ++;
+      if (nimage == NIMAGE) {
+	NIMAGE += 100;
+	REALLOCATE (image, Image, NIMAGE);
+	REALLOCATE (line_number, int, NIMAGE);
+      }
+    }
+  }
+      
+  if (VERBOSE) fprintf (stderr, "found %d images\n", nimage);
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  REALLOCATE (line_number, int, MAX (nimage, 1));
+  free (skycoords);
+
+  *Nimage  = nimage;
+  *LineNumber = line_number;
+  return (image);
+}
+
+/* check if line between points 0 and 1 of x1
+   crosses line between points 0 and 1 of x2 */
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/* check if point x1,y1 is in box formed by x2[0-4] */
+int corner_check (double *x1, double *y1, double *x2, double *y2) {
+
+  int i;
+  double theta;
+
+  theta = 0;
+
+  for (i = 0; i < 4; i++) {
+    theta += opening_angle (x2[i], y2[i], x1[0], y1[0], x2[i+1], y2[i+1]); 
+  }
+  if (fabs(theta) > 6) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+}
+
+/* returns the opening angle between the three points (2 is in middle) 
+   in range -pi to pi */
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/setExclusions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/setExclusions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/setExclusions.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "relastro.h"
+
+/* XXX I think all of these, except for X,Y selection, are done / can be done in bcatalog */
+int setExclusions (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, Narea, Nnocal;
+  Coords *coords;
+  double r, d, x, y;
+
+  Nnocal = Narea = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+
+	/* select measurements by photcode */
+	// XXXX is this done when loaded, or is it needed for reload?
+	// ecode = GetPhotcodeEquivCodebyCode (catalog[i].measure[m].photcode);
+	// if (ecode != photcode[0].code) goto mark_nocal;
+	
+	/* select measurements by time */
+	if (TimeSelect) {
+	  if (catalog[i].measure[m].t < TSTART) goto mark_nocal;
+	  if (catalog[i].measure[m].t > TSTOP) goto mark_nocal;
+	}
+
+	/* select measurements by mag limit */
+	if (AreaSelect) {
+	  r = catalog[i].average[j].R + catalog[i].measure[m].dR / 3600.0;
+	  d = catalog[i].average[j].D + catalog[i].measure[m].dD / 3600.0;
+	  if ((coords = getCoords (m, i)) == NULL) goto markbad;
+	  RD_to_XY (&x, &y, r, d, coords);
+	  if (x < AreaXmin) goto markbad;
+	  if (x > AreaXmax) goto markbad;
+	  if (y < AreaYmin) goto markbad;
+	  if (y > AreaYmax) goto markbad;
+	}
+	continue;
+
+      markbad:
+	catalog[i].measure[m].dbFlags |= ID_MEAS_AREA;
+	Narea ++;
+	continue;
+	
+      mark_nocal:
+	catalog[i].measure[m].dbFlags |= ID_MEAS_NOCAL;
+	Nnocal ++;
+	continue;
+      }
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "%d measurements marked by area\n", Narea);
+  if (VERBOSE) fprintf (stderr, "%d measurements marked nocal\n", Nnocal);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/setMrelFinal.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/setMrelFinal.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/setMrelFinal.c	(revision 16632)
@@ -0,0 +1,154 @@
+# include "relastro.h"
+
+void setMrelFinal (Catalog *catalog) {
+
+  int i, j, m, ecode;
+  float *p;
+  short *q;
+
+  /* if we reset the catalog, reset all the current measurements */
+  if (RESET) {
+
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      p = (PhotPrimary) ? &catalog[0].average[i].M  : &catalog[0].secfilt[PhotNsec*i+PhotSec].M;
+      *p = NO_MAG;
+      p = (PhotPrimary) ? &catalog[0].average[i].dM : &catalog[0].secfilt[PhotNsec*i+PhotSec].dM;
+      *p = NO_MAG;
+      q = (PhotPrimary) ? &catalog[0].average[i].Xm : &catalog[0].secfilt[PhotNsec*i+PhotSec].Xm;
+      *q = NO_MAG;
+
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	
+	/* select measurements by photcode */
+	ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[m].photcode);
+	if (ecode != photcode[0].code) continue;
+	
+	/* select measurements by time */
+	if (TimeSelect) {
+	  if (catalog[0].measure[m].t < TSTART) continue;
+	  if (catalog[0].measure[m].t > TSTOP) continue;
+	}
+	
+	catalog[0].measure[m].Mcal = 0;
+	catalog[0].measure[m].flags &= 0xff00;
+	catalog[0].measure[m].flags &= ~ID_MEAS_POOR;
+	catalog[0].measure[m].flags &= ~ID_MEAS_SKIP;
+	catalog[0].measure[m].flags &= ~ID_MEAS_AREA;
+	catalog[0].measure[m].flags &= ~ID_MEAS_NOCAL;
+      }
+    }
+  }
+
+  setExclusions (catalog, 1);  /* mark by area */
+
+  /* set catalog[0].found[i] = FALSE */
+  ALLOCATE (catalog[0].found, int, MAX (1, catalog[0].Naverage));
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    catalog[0].found[i] = FALSE;
+  }
+
+  for (i = 0; i < 5; i++) {
+    skip_measurements (catalog, i);       /* set ID_MEAS_SKIP for measures to be skipped */
+    setMrelOutput  (catalog, 1, FALSE);   /* set Mrel using all measures not skipped */
+    clean_measures (catalog, 1, TRUE);    /* mark outliers ID_MEAS_POOR */
+    setMrelOutput  (catalog, 1, TRUE);    /* set Mrel using remaining measures */
+  }
+  setMcalOutput (catalog, 1);
+
+  /* clear ID_STAR_POOR, ID_STAR_FEW, ID_MEAS_NOCAL values before writing ??? */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    catalog[0].average[i].code &= ~ID_STAR_FEW;
+    catalog[0].average[i].code &= ~ID_STAR_POOR;
+    m = catalog[0].average[i].offset;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+      catalog[0].measure[m].flags &= ~ID_MEAS_NOCAL;
+    }
+  }
+}
+
+/* ID_MEAS_SKIP marks measurements which were not used to calculate Mrel */
+void skip_measurements (Catalog *catalog, int pass) {
+
+  int i, k, m, ecode, d1, d2;
+  int Ntot, Ntry, Nkeep, Nskip;
+  float mag;
+
+  Ntot = Ntry = Nskip = Nkeep = 0;
+
+  /* allow measures from images marked POOR and FEW */
+  if (pass >= 3) IMAGE_BAD = ID_IMAGE_NOCAL;
+  
+  /* allow measures marked as outliers (POOR) and off image region (AREA) */
+  if (pass >= 3) MEAS_BAD = ID_MEAS_NOCAL | ID_MEAS_SKIP;
+
+  /* mark measures which should be ignored on second pass */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Ntot += catalog[0].average[i].Nm;
+    if (catalog[0].found[i]) continue;
+
+    m = catalog[0].average[i].offset;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, m++) {
+      Ntry++;
+
+      /* clear SKIP for all measures at first */
+      catalog[0].measure[m].flags &= ~ID_MEAS_SKIP;
+
+      /** never use these measurements (wrong photcode, bad time range) */
+      /* skipped via NOCAL, don't mark as skipped */
+      ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[m].photcode);
+      if (ecode != photcode[0].code) continue;
+
+      /* skip measurements by time range */
+      if (TimeSelect) {
+	if (catalog[0].measure[m].t < TSTART) goto skip;
+	if (catalog[0].measure[m].t > TSTOP) goto skip;
+      }
+
+      /* skip measurements with sat. dophot values */
+      if ((pass < 4) && (catalog[0].measure[m].dophot == 10)) goto skip;
+
+      /* skip measurements from BAD images and mosaics */
+      if ((getMcal  (m, 0)) == NO_MAG) goto skip;
+      if ((getMmos  (m, 0)) == NO_MAG) goto skip;
+
+      /* skip measurements by inst mag limit */
+      if ((pass < 4) && ImagSelect) {
+	mag = PhotInst (&catalog[0].measure[m]);
+	if (mag < ImagMin) goto skip;
+	if (mag > ImagMax) goto skip;
+      }
+
+      d1 = (catalog[0].measure[m].dophot == 1);
+      d2 = (catalog[0].measure[m].dophot == 2);
+
+      /* skip measurements by measurement error */
+      if ((pass < 2) && !(d1 || d2)) goto skip;
+
+      /* if ((pass < 1) && (catalog[0].measure[m].dM > SIGMA_LIM)) goto skip; */
+      if ((pass < 1) && !d1) goto skip;
+      Nkeep ++;
+
+      continue;
+
+    skip:
+      catalog[0].measure[m].flags |= ID_MEAS_SKIP;
+      Nskip ++;
+    }
+  }
+  fprintf (stderr, "pass %d, Ntot: %d, Ntry: %d, Nskip: %d, Nkeep: %d\n",
+	   pass, Ntot, Ntry, Nskip, Nkeep);
+}
+
+/* dophot types:
+
+1 - star
+2 - galaxy
+3 - star
+4 - weak
+5 - edge
+7 - weak
+9 - weak
+10 - sat
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/sort.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/sort.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/sort.c	(revision 16632)
@@ -0,0 +1,182 @@
+# include "relastro.h"
+
+void sortA (double *X, int N) {
+
+  int l,j,ir,i;
+  double tX;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+void sortB (double *X, double *Y, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+void sortC (double *X, double *Y, double *F1, double *F2, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  double t1, t2;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      t1 = F1[l];
+      t2 = F2[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      t1 = F1[ir];
+      F1[ir] = F1[0];
+      t2 = F2[ir];
+      F2[ir] = F2[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	F1[0] = t1;
+	F2[0] = t2;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	F1[i] = F1[j];
+	F2[i] = F2[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    F1[i] = t1;
+    F2[i] = t2;
+  }
+}
+
+void sortD (double *X, double *Y, double *Z, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tZ;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tZ = Z[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tZ = Z[ir];
+      Z[ir] = Z[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	Z[0] = tZ;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	Z[i] = Z[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    Z[i] = tZ;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/relastro/src/write_coords.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relastro/src/write_coords.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relastro/src/write_coords.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "relastro.h"
+
+# define CD_COORDS 1
+
+void write_coords (Header *header, Coords *coords) {
+
+  gfits_modify (header, "CTYPE1",   "%s",  1, "RA---TAN");
+  gfits_modify (header, "CTYPE2",   "%s",  1, "DEC--TAN");
+
+  gfits_modify (header, "CRVAL1",   "%lf", 1, coords[0].crval1);
+  gfits_modify (header, "CRVAL2",   "%lf", 1, coords[0].crval2);  
+
+  gfits_modify (header, "CRPIX1",   "%lf", 1, coords[0].crpix1);
+  gfits_modify (header, "CRPIX2",   "%lf", 1, coords[0].crpix2);
+
+# if (CD_COORDS)  
+  gfits_modify (header, "CD1_1",    "%le", 1, coords[0].pc1_1 * coords[0].cdelt1);
+  gfits_modify (header, "CD2_1",    "%le", 1, coords[0].pc2_1 * coords[0].cdelt1);
+  gfits_modify (header, "CD1_2",    "%le", 1, coords[0].pc1_2 * coords[0].cdelt2);
+  gfits_modify (header, "CD2_2",    "%le", 1, coords[0].pc2_2 * coords[0].cdelt2);
+# else
+  gfits_modify (header, "CDELT1",   "%le", 1, coords[0].cdelt1); 
+  gfits_modify (header, "CDELT2",   "%le", 1, coords[0].cdelt2);
+  gfits_modify (header, "PC001001", "%le", 1, coords[0].pc1_1);
+  gfits_modify (header, "PC001002", "%le", 1, coords[0].pc1_2);
+  gfits_modify (header, "PC002001", "%le", 1, coords[0].pc2_1);
+  gfits_modify (header, "PC002002", "%le", 1, coords[0].pc2_2);
+# endif
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/Makefile	(revision 16632)
@@ -0,0 +1,47 @@
+default: relphot
+help:
+	@echo "make options: relphot (default)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/relphot
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -lkapa -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+relphot: $(BIN)/relphot.$(ARCH)
+install: $(DESTBIN)/relphot
+
+RELPHOT = \
+$(SRC)/ConfigInit.$(ARCH).o	 \
+$(SRC)/GridOps.$(ARCH).o	 \
+$(SRC)/ImageOps.$(ARCH).o	 \
+$(SRC)/MosaicOps.$(ARCH).o	 \
+$(SRC)/SetSignals.$(ARCH).o 	 \
+$(SRC)/Shutdown.$(ARCH).o 	 \
+$(SRC)/StarOps.$(ARCH).o	 \
+$(SRC)/args.$(ARCH).o		 \
+$(SRC)/bcatalog.$(ARCH).o	 \
+$(SRC)/global_stats.$(ARCH).o	 \
+$(SRC)/initialize.$(ARCH).o	 \
+$(SRC)/liststats.$(ARCH).o	 \
+$(SRC)/load_catalogs.$(ARCH).o	 \
+$(SRC)/load_images.$(ARCH).o	 \
+$(SRC)/plot_scatter.$(ARCH).o	 \
+$(SRC)/plotstuff.$(ARCH).o	 \
+$(SRC)/reload_catalogs.$(ARCH).o \
+$(SRC)/relphot.$(ARCH).o	 \
+$(SRC)/select_images.$(ARCH).o	 \
+$(SRC)/setExclusions.$(ARCH).o 	 \
+$(SRC)/setMrelFinal.$(ARCH).o 	 \
+$(SRC)/write_coords.$(ARCH).o
+
+$(RELPHOT): $(INC)/relphot.h
+$(BIN)/relphot.$(ARCH): $(RELPHOT)
Index: /branches/eam_branch_20080223/Ohana/src/relphot/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/relphot/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,22 @@
+
+- relphot-1-4:
+  * converted to gfits APIs (forces libfits 1.6)
+  * converted to new DVO APIs (forces libdvo 1.3)
+  * allow seletion by RA/DEC limits
+  * removed old, unused code
+  * added time range to time selections
+
+- relphot-1-3:
+  * dropped IMAGE_CATALOG from config
+  * convert to use libkapa
+  * dropped _PS from average.R,D,M,dM
+  * convert to dvo_image_lock,unlock
+
+- relphot-1-2: released 2005.10.20
+  * substantial changes to sync with addstar v1.3
+    (added mode/format support, new dvo load functions, etc).
+  * various cleanups (functions moved to libohana)
+  * changes to use new libohana (v1.5) / libfits (v1.4)
+
+- relphot-1-1
+  * minor cleanup, loneos.h -> dvo.h
Index: /branches/eam_branch_20080223/Ohana/src/relphot/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/doc/notes.txt	(revision 16632)
@@ -0,0 +1,135 @@
+
+2006.10.17
+
+  I am working on a partial upgrade of relphot to handle more general
+  problems than I have treated in the past.  In particular, I would
+  like to be able to have it assign the average magnitudes, regardless
+  of whether any or all images and/or objects are well-treated for
+  relative photometry.  In fact, I would like it to be able to
+  determine average magnitudes even for sources which have only
+  externally supplied data, and thus have no matching images.  I would
+  eventually like to have more flexibility about the filtering which
+  is performed on the measurements to determine the average
+  magnitudes.  Some of this work will require a bit of a more careful
+  treatment of the process.  
+
+  At the moment, we can consider the relphot process to consist of the
+  following steps:
+
+  1) load the complete catalog data
+  2) select a subset of the sources:
+     - appropriate photcode (equiv == selected photcode)
+     - in time range, if specified
+     - appropriate dophot type, if specified
+     - bright enough:
+       - mag < MAG_LIM	
+       - dMag > SIGMA_LIM
+       - ImagMin < iMag < ImagMax
+     - other restrictions
+       - within valid image region for chip
+  3) iterate to a solution for Mcal (image offsets)
+     - mark specific images as bad
+     - mark specific sources as bad
+     - mark specific measurements as bad
+     - include desired restrictions on Mcal (eg, all chips of mosaic
+       matched)
+     - only keep the image offsets
+
+  4) if the results are to be kept, recalculate the average magnitudes
+     using the image exclusions and Mcal values determined above 
+
+2006.05.03
+
+  I am upgrading relphot to accept as input an arbitrary region (using
+  the standard ohana SkyRegion concept of a RA & DEC bounded patch on
+  the sky).  This modification has a few implications.  First, the
+  analysis is in fact performed on the populated SkyRegions which
+  overlap the requested area on the sky.
+
+- select different calibration options
+- plot various terms
+
+- rationalize Mmos & Mcal (sum(Mcal) -> Mmos)
+
+- options:
+
+  -update:  update phot database 
+  -mosaic:  apply per-mosaic corrections
+  -grid:    apply X,Y-based offset
+  -chips:   apply per-chip corrections
+  -trange:  select images in time range
+  
+
+find_images: selects images in region, filtered by photcode, time range
+
+bcatalog:    selects stars & measurments, filtered by mag limit, photcode, time range
+
+image:  a single ccd
+mosaic: a collection of associate ccds (mosaiclink[image])
+grid:   x,y magnitude correction grid across mosaic 
+fit:    2-d fit of mag offsets across field
+
+
+
+m = Mrel + Mcal + Mmos + Mxy + Mgrid
+
+Mrel  (average)
+Mcal  (image)
+Mmos  (mosaic)
+Mxy   (Xi, Yi) (Xi,Yi per image ??)
+Mgrid (Xm, Ym)
+
+
+ measure -> average           catalog[i].measure[j].averef 
+ average -> measure           catalog[i].average[j].offset, catalog[i].average[j].Nm
+
+ measure -> image             image:  image[cat, meas]
+ image   -> measure           image:  catlist[image], measlist[image]
+
+ measure -> mosaic            mosaic: mosaic[cat, meas]
+ mosaic  -> measure	      mosaic: catlist[mosaic], measlist[mosaic]
+
+ measure -> gridbin           grid:   bin[cat, meas]
+ gridbin -> measure           grid:   catlist[bin], measlist[bin]
+
+ measure -> Xi, Yi -> Mxy     
+
+
+getMmos:
+
+ for (i = 0; i < Nmosaic; i++) {
+
+   for (j = 0; j < Nmeasure[i]; j++) {
+      cat  = catlist[i][j]
+      meas = measlist[i][j]
+
+      M = catalog[cat].measure[meas].M
+      Mcal  = applyMcal  (cat, meas)
+      Mrel  = applyMrel  (cat, meas)
+      Mxy   = applyMxy   (cat, meas)
+      Mgrid = applyMgrid (cat, meas)
+
+      list[n] = M - Mcal - Mrel - Mxy - Mgrid
+    }
+  }
+
+
+
+excluding data points:
+
+star:   N < 2
+image:  
+
+
+--
+
+MAG_LIM      : keep stars brighter than MAG_LIM (Mcat)
+SIGMA_LIM    : keep stars with error < SIGMA_LIM
+STAR_SCATTER : exclude stars with dM > STAR_SCATTER
+IMAGE_SCATTER, NIMAGE_SCATTER : define image scatter limits
+
+
+
+load_images - exclude images 
+
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/include/relphot.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/include/relphot.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/include/relphot.h	(revision 16632)
@@ -0,0 +1,213 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <kapa.h>
+# include <signal.h>
+
+/* # define GRID_V1 */
+# define GRID_V2
+# define NO_IMAGE -100
+
+# if (0)
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, color;
+  double lweight, size;
+} Graphdata;
+# endif
+
+typedef struct {
+  unsigned int start;
+  unsigned int stop;
+  float Mcal;
+  float dMcal;
+  short Xm;
+  float secz;
+  char code;
+  Coords coords;
+} Mosaic; 
+
+typedef struct {
+  double median;
+  double mean;
+  double sigma;
+  double error;
+  double chisq;
+  double min;
+  double max;
+  double total;
+  int    Nmeas;
+} StatType;
+
+/* global variables set in parameter file */
+char   ImageCat[256];
+char   ImageTemplate[256];
+char   CatTemplate[256];
+char   GSCFILE[256];
+char   CATDIR[256];
+char   CATMODE[16];    /* raw, mef, split, mysql */
+char   CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char   CameraConfig[256];
+char   SKY_TABLE[256];
+int    SKY_DEPTH;  /** XXX EAM : depth of catalog tables, fix usage */
+
+double MAG_LIM;
+double SIGMA_LIM;
+double IMAGE_SCATTER;
+double IMAGE_OFFSET;
+double STAR_SCATTER;
+double STAR_CHISQ;
+double MIN_ERROR;
+
+int    VERBOSE;
+
+int    NLOOP;
+int    RESET;
+int    UPDATE;
+int    PLOTSTUFF;
+int    SAVEPLOT;
+int    SHOW_PARAMS;
+char   MOSAICNAME[256];
+char   STATMODE[32];
+int    STAR_BAD;
+int    MEAS_BAD;
+int    STAR_TOOFEW;
+int    IMAGE_TOOFEW;
+double IMAGE_GOOD_FRACTION;
+int    IMAGE_BAD;
+int    FREEZE_IMAGES;
+int    USE_GRID;
+int    PLOTDELAY;
+
+int    RELPHOT_GRID_X;
+int    RELPHOT_GRID_Y;
+int    RELPHOT_GRID_BINNING;
+
+PhotCode      *photcode;
+int            PhotNsec;
+int            PhotSec;
+
+int AreaSelect;
+double AreaXmin, AreaXmax, AreaYmin, AreaYmax;
+
+int ImagSelect, ImagMin, ImagMax;
+
+int DophotSelect, DophotValue;
+
+double  PlotMmin, PlotMmax, PlotdMmin, PlotdMmax;
+enum {black, white, red, orange, yellow, green, blue, indigo, violet};
+
+int TimeSelect;
+time_t TSTART, TSTOP;
+
+SkyRegion UserPatch;
+int UserPatchSelect;
+
+# ifdef GRID_V1
+int setGridMeasure (int meas, int cat, double X, double Y);
+# endif
+
+# ifdef GRID_V2
+int setGridMeasure (int meas, int cat, double X, double Y, int ccdnum);
+# endif
+
+/*** relphot prototypes ***/
+void          ConfigInit          PROTO((int *argc, char **argv));
+void          GetConfig           PROTO((char *config, char *field, char *format, int N, void *ptr));
+char         *GetPhotnamebyCode   PROTO((PhotCodeData *photcodes, int code));
+void          InterpolateGrid     PROTO((float *buffer, int Nx, int Ny, Coords *ccd, Coords *gcoords));
+int          *SelectRefMosaic     PROTO((Mosaic **refmosaic, int *Nimage));
+int           args                PROTO((int argc, char **argv));
+int           bcatalog            PROTO((Catalog *subcatalog, Catalog *catalog));
+void          clean_images        PROTO(());
+void          clean_measures      PROTO((Catalog *catalog, int Ncatalog, int final));
+void          clean_mosaics       PROTO(());
+void          clean_stars         PROTO((Catalog *catalog, int Ncatalog));
+int           corner_check        PROTO((double *x1, double *y1, double *x2, double *y2));
+void          dumpGrid            PROTO(());
+void          dump_grid           PROTO(()); 
+int           edge_check          PROTO((double *x1, double *y1, double *x2, double *y2));
+void          findImages          PROTO((Catalog *catalog, int Ncatalog));
+int           findMosaics         PROTO((Catalog *catalog, int Ncatalog));
+
+void set_db (FITS_DB *in);
+int Shutdown (char *format, ...);
+void TrapSignal (int sig);
+void SetProtect (int mode);
+int SetSignals ();
+
+void          freeGridBins        PROTO((int Ncatalog));
+void          freeImageBins       PROTO((int Ncatalog));
+void          freeMosaicBins      PROTO((int Ncatalog));
+void          free_catalogs       PROTO((Catalog *catalog, int Ncatalog));
+int           gcatalog            PROTO((Catalog *catalog, int FINAL));
+Coords       *getCoords           PROTO((int meas, int cat));
+int           getImageEntry       PROTO((int meas, int cat));
+float         getMcal             PROTO((int meas, int cat));
+float         getMgrid            PROTO((int meas, int cat));
+float         getMmos             PROTO((int meas, int cat));
+float         getMrel             PROTO((Catalog *catalog, int meas, int cat));
+Image        *getimage            PROTO((int N));
+Image        *getimages           PROTO((int *N));
+void          global_stats        PROTO((Catalog *catalog, int Ncatalog));
+void          initGrid            PROTO((int dX, int dY));
+void          initGridBins        PROTO((Catalog *catalog, int Ncatalog));
+void          initImageBins       PROTO((Catalog *catalog, int Ncatalog));
+void          initImages          PROTO((Image *input, int N));
+void          initMosaicBins      PROTO((Catalog *catalog, int Ncatalog));
+void          initMosaicGrid      PROTO((Image *image, int Nimage));
+void          initMosaics         PROTO((Image *image, int Nimage));
+void          initMrel            PROTO((Catalog *catalog, int Ncatalog));
+void          initialize          PROTO((int argc, char **argv));
+void          initstats           PROTO((char *mode));
+int           liststats           PROTO((double *value, double *dvalue, int N, StatType *stats));
+Catalog       *load_catalogs      PROTO((SkyList *skylist, int *Ncatalog));
+SkyList      *load_images         PROTO((FITS_DB *db, char *regionName, SkyRegion *region, int RegionSelect));
+Image         *select_images      PROTO((SkyList *skylist, Image *timage, int Ntimage, int **LineNumber, int *Nimage));
+
+int           main                PROTO((int argc, char **argv));
+void          mark_images         PROTO((Image *image, int Nimage, Image *timage, int Ntimage));
+void          matchImage          PROTO((Catalog *catalog, int meas, int cat));
+void          matchMosaics        PROTO((Catalog *catalog, int meas, int cat));
+double        opening_angle       PROTO((double x1, double y1, double x2, double y2, double x3, double y3));
+void          plot_chisq          PROTO((Catalog *catalog, int Ncatalog));
+void          plot_defaults       PROTO((Graphdata *graphdata));
+void          plot_grid           PROTO((Catalog *catalog));
+void          plot_images         PROTO(());
+void          plot_list           PROTO((Graphdata *graphdata, double *xlist, double *ylist, int N, char *label, char *file));
+void          plot_mosaic_fields  PROTO((Catalog *catalog));
+void          plot_mosaics        PROTO(());
+void          plot_scatter        PROTO((Catalog *catalog, int Ncatalog));
+void          plot_star_coords    PROTO((Catalog *catalog, int Ncatalog));
+void          plot_stars          PROTO((Catalog *catalog, int Ncatalog));
+void          reload_catalogs     PROTO((SkyList *skylist));
+int           reload_images       PROTO((FITS_DB *db));
+int           setExclusions       PROTO((Catalog *catalog, int Ncatalog));
+void          setMcal             PROTO((Catalog *catalog, int Poor));
+void          setMcalFinal        PROTO(());
+int           setMcalOutput       PROTO((Catalog *catalog, int Ncatalog));
+void          setMgrid            PROTO((Catalog *catalog));
+int           setMmos             PROTO((Catalog *catalog, int Poor));
+int           setMrel             PROTO((Catalog *catalog, int Ncatalog));
+void          setMrelFinal        PROTO((Catalog *catalog));
+int           setMrelOutput       PROTO((Catalog *catalog, int Ncatalog, int mark));
+void          set_ZP              PROTO((double ZERO));
+int           setrefcode          PROTO((Image *image, int Nimage)); 
+void          skip_measurements   PROTO((Catalog *catalog, int pass));
+void          sortA               PROTO((double *X, int N));
+void          sortB               PROTO((double *X, double *Y, int N));
+void          sortC               PROTO((double *X, double *Y, double *F1, double *F2, int N));
+void          sortD               PROTO((double *X, double *Y, double *Z, int N));
+StatType      statsImageM         PROTO((Catalog *catalog));
+StatType      statsImageN         PROTO((Catalog *catalog));
+StatType      statsImageX         PROTO((Catalog *catalog));
+StatType      statsImagedM        PROTO((Catalog *catalog));
+StatType      statsMosaicM        PROTO((Catalog *catalog));
+StatType      statsMosaicN        PROTO((Catalog *catalog));
+StatType      statsMosaicX        PROTO((Catalog *catalog));
+StatType      statsMosaicdM       PROTO((Catalog *catalog));
+StatType      statsStarN          PROTO((Catalog *catalog, int Ncatalog));
+StatType      statsStarS          PROTO((Catalog *catalog, int Ncatalog));
+StatType      statsStarX          PROTO((Catalog *catalog, int Ncatalog));
+void          wcatalog            PROTO((Catalog *catalog));
+void          wimages             PROTO(());
+void          write_coords        PROTO((Header *header, Coords *coords));
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,79 @@
+# include "relphot.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char  *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  GetConfig (config, "MAG_LIM",                "%lf", 0, &MAG_LIM);
+  GetConfig (config, "SIGMA_LIM",              "%lf", 0, &SIGMA_LIM);
+  GetConfig (config, "STAR_SCATTER",           "%lf", 0, &STAR_SCATTER);
+  GetConfig (config, "IMAGE_SCATTER",          "%lf", 0, &IMAGE_SCATTER);
+  GetConfig (config, "IMAGE_OFFSET",           "%lf", 0, &IMAGE_OFFSET);
+
+  GetConfig (config, "STAR_CHISQ",             "%lf", 0, &STAR_CHISQ);
+  GetConfig (config, "STAR_TOOFEW",            "%d",  0, &STAR_TOOFEW);
+  GetConfig (config, "IMAGE_TOOFEW",           "%d",  0, &IMAGE_TOOFEW);
+  GetConfig (config, "IMAGE_GOOD_FRACTION",    "%lf", 0, &IMAGE_GOOD_FRACTION);
+
+  GetConfig (config, "GSCFILE",                "%s",  0, GSCFILE);
+  GetConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  if (!ScanConfig (config, "SKY_DEPTH",         "%d",  0, &SKY_DEPTH)) {
+    SKY_DEPTH = 2;
+  }
+  if (!ScanConfig (config, "SKY_TABLE",         "%s",  0, SKY_TABLE)) {
+    SKY_TABLE[0] = 0;
+  }
+
+  GetConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+
+  GetConfig (config, "RELPHOT_GRID_X",         "%d",  0, &RELPHOT_GRID_X);
+  GetConfig (config, "RELPHOT_GRID_Y",         "%d",  0, &RELPHOT_GRID_Y);
+  GetConfig (config, "RELPHOT_GRID_BINNING",   "%d",  0, &RELPHOT_GRID_BINNING);
+  GetConfig (config, "CAMERA_CONFIG",          "%s",  0, CameraConfig);
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+  SetZeroPoint (ZERO_POINT);
+
+  free (config);
+  free (file);
+
+}
+
+void GetConfig (char *config, char *field, char *format, int N, void *ptr) {
+
+  char *status;
+
+  status = ScanConfig (config, field, format, N, ptr);
+  if (status == NULL) {
+    fprintf (stderr, "error in config, cannot find %s\n", field);
+    exit (1);
+  }
+  return;
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/GridOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/GridOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/GridOps.c	(revision 16632)
@@ -0,0 +1,583 @@
+# include "relphot.h"
+
+static int     Ngrid;
+static float   *gridM;
+static float   *gridS;
+static int     *gridN;
+static int      gridX;
+static int      gridY;
+
+static int    **bin;
+static int    **Xmeas;
+static int    **Ymeas;
+
+static int    **clist;
+static int    **mlist;
+static int     *Nlist;
+static int     *NLIST;
+
+static struct {
+  int Nchip;
+  int Mx, My;  /* mosaic size in chips */
+  int Nx, Ny;  /* chip size in pixels */
+  int *Fx, *Fy;  /* chip flip */
+  int *Ox, *Oy;  /* chip offset */
+  char **ccdname;
+} camera;    
+
+# ifdef GRID_V1
+void initGrid (int dX, int dY) {
+
+  int i;
+
+  /* define mosaic 2d correction grid */
+  gridX = dX / RELPHOT_GRID_BINNING + 1;
+  gridY = dY / RELPHOT_GRID_BINNING + 1;
+  Ngrid = gridX * gridY;
+
+  ALLOCATE (gridM, float, Ngrid);
+  ALLOCATE (gridS, float, Ngrid);
+  ALLOCATE (gridN, int,   Ngrid);
+  bzero (gridM, Ngrid*sizeof(float));
+  bzero (gridS, Ngrid*sizeof(float));
+  bzero (gridN, Ngrid*sizeof(int));
+
+}
+# endif
+
+# ifdef GRID_V2
+void initGrid (int dX, int dY) {
+
+  int i;
+  char field[64], *config, line[256];
+
+  /* load camera config file */
+  config = LoadConfigFile (CameraConfig);
+  if (config == (char *) NULL) {
+    fprintf (stderr, "ERROR: can't find camera config file %s\n", CameraConfig);
+    exit (1);
+  }
+
+  /* load basic mosaic parameters */
+  ScanConfig (config, "NCCD", "%d", 1, &camera.Nchip);
+  ScanConfig (config, "MOSAIC_X", "%d", 1, &camera.Mx);
+  ScanConfig (config, "MOSAIC_Y", "%d", 1, &camera.My);
+  ScanConfig (config, "NAXIS1", "%d", 1, &camera.Nx);
+  ScanConfig (config, "NAXIS2", "%d", 1, &camera.Ny);
+
+  ALLOCATE (camera.Fx, int, camera.Nchip);
+  ALLOCATE (camera.Fy, int, camera.Nchip);
+  ALLOCATE (camera.Ox, int, camera.Nchip);
+  ALLOCATE (camera.Oy, int, camera.Nchip);
+  ALLOCATE (camera.ccdname, char *, camera.Nchip);
+
+  /* load per-chip parameters */
+  for (i = 0; i < camera.Nchip; i++) {
+    ALLOCATE (camera.ccdname[i], char, 256);
+    sprintf (field, "CCD.%d", i);
+    ScanConfig (config, field, "%s", 1, line);
+    sscanf (line, "%s %d %d %d %d", camera.ccdname[i], &camera.Ox[i], &camera.Oy[i], &camera.Fx[i], &camera.Fy[i]);
+  }
+  free (config);
+
+  /* define mosaic 2d correction grid: 
+   * GRID_X is the number of grid pixels per chip in the X direction */
+  gridX = RELPHOT_GRID_X * camera.Mx;
+  gridY = RELPHOT_GRID_Y * camera.My;
+  Ngrid = gridX * gridY;
+
+  ALLOCATE (gridM, float, Ngrid);
+  ALLOCATE (gridS, float, Ngrid);
+  ALLOCATE (gridN, int,   Ngrid);
+  bzero (gridM, Ngrid*sizeof(float));
+  bzero (gridS, Ngrid*sizeof(float));
+  bzero (gridN, Ngrid*sizeof(int));
+
+}
+# endif
+
+void initGridBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  if (!USE_GRID) return;
+
+  /* define cat,meas -> grid pointers */
+  ALLOCATE (bin, int *, Ncatalog);
+  ALLOCATE (Xmeas, int *, Ncatalog);
+  ALLOCATE (Ymeas, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    ALLOCATE (Xmeas[i], int, MAX (catalog[i].Nmeasure, 1));
+    ALLOCATE (Ymeas[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  /* define grid -> cat,meas pointers */
+  ALLOCATE (Nlist, int, Ngrid);
+  ALLOCATE (NLIST, int, Ngrid);
+  ALLOCATE (clist, int *, Ngrid);
+  ALLOCATE (mlist, int *, Ngrid);
+
+  for (i = 0; i < Ngrid; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeGridBins (int Ncatalog) {
+
+  int i;
+
+  if (!USE_GRID) return;
+
+  /* define cat,meas -> grid pointers */
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+    free (Xmeas[i]);
+    free (Ymeas[i]);
+  }
+  free (bin);
+  free (Xmeas);
+  free (Ymeas);
+
+  /* define grid -> cat,meas pointers */
+  for (i = 0; i < Ngrid; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (Nlist);
+  free (NLIST);
+  free (clist);
+  free (mlist);
+}
+
+# ifdef GRID_V1
+int setGridMeasure (int meas, int cat, double X, double Y) {
+
+  int ix, iy, i;
+
+  ix = X / RELPHOT_GRID_BINNING;
+  iy = Y / RELPHOT_GRID_BINNING;
+  if (ix < 0) goto escape;
+  if (iy < 0) goto escape;
+  if (ix >= gridX) goto escape;
+  if (iy >= gridY) goto escape;
+
+  i = ix + iy*gridX;
+
+  bin[cat][meas] = i;
+  Xmeas[cat][meas] = X;
+  Ymeas[cat][meas] = Y;
+  clist[i][Nlist[i]] = cat;
+  mlist[i][Nlist[i]] = meas;
+
+  Nlist[i] ++;
+  if (Nlist[i] == NLIST[i]) {
+    NLIST[i] += 100;
+    REALLOCATE (clist[i], int, NLIST[i]);
+    REALLOCATE (mlist[i], int, NLIST[i]);
+  }	
+  return (TRUE);
+
+escape:
+  fprintf (stderr, "error: star out of grid\n");
+  exit (1);
+}
+# endif
+
+# ifdef GRID_V2
+int setGridMeasure (int meas, int cat, double X, double Y, int ccdnum) {
+
+  int ix, iy, Cx, Cy, i;
+  double x, y;
+
+  /* X, Y are chip coords on chip ccdnum */
+
+  /* normalize X & Y */
+  x = X;
+  if (camera.Fx[ccdnum]) x = camera.Nx - X;
+  y = Y;
+  if (camera.Fy[ccdnum]) y = camera.Ny - Y;
+
+  /* grid coords on the chip */
+  Cx = MIN (MAX ((x / camera.Nx) * RELPHOT_GRID_X, 0), RELPHOT_GRID_X - 1);
+  Cy = MIN (MAX ((y / camera.Ny) * RELPHOT_GRID_Y, 0), RELPHOT_GRID_Y - 1);
+  
+  /* coordinates in the grid */
+  ix = Cx + camera.Ox[ccdnum]*RELPHOT_GRID_X;
+  iy = Cy + camera.Oy[ccdnum]*RELPHOT_GRID_Y;
+
+  i = ix + iy*gridX;
+
+  bin[cat][meas] = i;
+  Xmeas[cat][meas] = x + camera.Ox[ccdnum]*camera.Nx;
+  Ymeas[cat][meas] = Y + camera.Oy[ccdnum]*camera.Ny;
+  clist[i][Nlist[i]] = cat;
+  mlist[i][Nlist[i]] = meas;
+
+  Nlist[i] ++;
+  if (Nlist[i] == NLIST[i]) {
+    NLIST[i] += 100;
+    REALLOCATE (clist[i], int, NLIST[i]);
+    REALLOCATE (mlist[i], int, NLIST[i]);
+  }	
+  return (TRUE);
+
+  fprintf (stderr, "error: star out of grid\n");
+  exit (1);
+}
+# endif
+
+float getMgrid (int meas, int cat) {
+
+  int i;
+  float value;
+
+  if (!USE_GRID) return (0);
+  i = bin[cat][meas];
+  if (i == -1) return (NAN);
+
+  value = gridM[i];
+  return (value);
+}
+
+/* determine Mgrid values for all grid bins */
+void setMgrid (Catalog *catalog) {
+
+  int i, j, m, c, n, N, Nmax;
+  double *list, *dlist;
+  float Msys, Mrel, Mcal, Mmos;
+  StatType stats;
+  
+  if (!USE_GRID) return;
+
+  Nmax = Nlist[0];
+  for (i = 0; i < Ngrid; i++) {
+    Nmax = MAX (Nmax, Nlist[i]);
+  }
+  ALLOCATE (list, double, Nmax);
+  ALLOCATE (dlist, double, Nmax);
+
+  for (i = 0; i < Ngrid; i++) {
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].dbFlags & MEAS_BAD) continue;
+      Mcal = getMcal  (m, c);
+      if (isnan(Mcal)) continue;
+      Mmos = getMmos  (m, c);
+      if (isnan(Mmos)) continue;
+      Mrel  = getMrel  (catalog, m, c);
+      if (isnan(Mrel)) continue;
+      
+      n = catalog[c].measure[m].averef;
+      Msys = PhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      list[N] = Msys - Mrel - Mcal - Mmos;
+      dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
+      N++;
+    }
+
+    liststats (list, dlist, N, &stats);
+    gridM[i] = stats.mean;
+    gridS[i] = stats.sigma;
+    gridN[i] = N;
+  }
+  free (list);
+  free (dlist);
+}
+
+void plot_grid (Catalog *catalog) {
+
+  int i, j, m, c, n, N, Narea;
+  float Msys, Mrel, Mcal, Mmos;
+  double *xlist, *Mlist, *dlist, *ylist;
+  Graphdata graphdata;
+
+  if (!USE_GRID) return;
+
+  N = 0;
+  for (i = 0; i < Ngrid; i++) 
+    N += Nlist[i];
+
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+  ALLOCATE (Mlist, double, N);
+  ALLOCATE (dlist, double, N);
+
+  Narea = 0;
+  N = 0;
+  for (i = 0; i < Ngrid; i++) {
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].dbFlags & MEAS_BAD) {
+	Narea ++;
+	continue;
+      }
+      Mcal  = getMcal  (m, c);
+      if (isnan(Mcal)) continue;
+      Mmos  = getMmos  (m, c);
+      if (isnan(Mmos)) continue;
+      Mrel  = getMrel  (catalog, m, c);
+      if (isnan(Mrel)) continue;
+
+      n = catalog[c].measure[m].averef;
+      Msys = PhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+
+      xlist[N] = Xmeas[c][m];
+      ylist[N] = Ymeas[c][m];
+      Mlist[N] = Msys - Mrel - Mcal - Mmos;
+      dlist[N] = Msys - Mrel - Mcal - Mmos - gridM[i];
+      N++;
+    }
+  }
+
+  fprintf (stderr, "skipped %d meas for area\n", Narea);
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, N, "X vs dM raw", "XdM.png");
+  plot_list (&graphdata, xlist, dlist, N, "X vs dM corrected", "XdMf.png");
+  plot_list (&graphdata, ylist, dlist, N, "Y vs dM corrected", "YdMf.png");
+
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, xlist, ylist, N, "X vs Y", "XY.png");
+
+  free (ylist);
+  free (xlist);
+  free (Mlist);
+  free (dlist);
+
+}
+
+void dump_grid () { 
+
+  int i, j, Nimage;
+  int *imlist;
+  FILE *f;
+  Header header, theader;
+  Matrix matrix;
+  Mosaic *refmosaic;
+    
+  /* select reference mosaic image */
+  imlist = SelectRefMosaic (&refmosaic, &Nimage);
+
+  /* we are writing to this file */
+  f = fopen ("mosaic.fits", "w");
+  if (f == (FILE *) NULL) { 
+    fprintf (stderr, "cannot open %s for output\n", "mosaic.fits");
+    return;
+  }
+
+  /* create empty phu */
+  gfits_init_header (&header);
+  header.extend = TRUE;
+  gfits_create_header (&header);
+  gfits_create_matrix (&header, &matrix);
+  gfits_modify (&header, "NEXTEND", "%d", 1, Nimage + 3);
+  gfits_modify (&header, "FILTER", "%s", 1, photcode[0].name);
+  gfits_modify (&header, "COMMENT", "%S", 1, "Mosaic Photometry Grid Analysis");
+  gfits_fwrite_header (f, &header);
+  gfits_fwrite_matrix (f, &matrix);
+  gfits_free_matrix (&matrix);
+
+  /* save grid mag values */
+  gfits_init_header (&theader);
+  theader.Naxes = 2;
+  theader.Naxis[0] = gridX;
+  theader.Naxis[1] = gridY;
+  theader.bitpix   = -32;
+  gfits_create_Theader (&theader, "IMAGE");
+  gfits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  gfits_modify (&theader, "EXTNAME", "%s", 1, "MAG_OFFSET");
+  gfits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      gfits_set_matrix_value (&matrix, i, j, (double) gridM[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  gfits_fwrite_header (f, &theader);
+  gfits_fwrite_matrix (f, &matrix);
+  gfits_free_matrix (&matrix);
+
+  /* save grid Nmeas values */
+  gfits_modify (&theader, "EXTNAME", "%s", 1, "NMEAS");
+  gfits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  gfits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      gfits_set_matrix_value (&matrix, i, j, (double) gridN[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  gfits_fwrite_header (f, &theader);
+  gfits_fwrite_matrix (f, &matrix);
+  gfits_free_matrix (&matrix);
+
+  /* save grid sigma values */
+  gfits_modify (&theader, "EXTNAME", "%s", 1, "SIGMA");
+  gfits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+  gfits_create_matrix  (&theader, &matrix);
+  for (i = 0; i < gridX; i++) {
+    for (j = 0; j < gridY; j++) {
+      gfits_set_matrix_value (&matrix, i, j, (double) gridS[i + j*gridX]);
+    }
+  }
+  write_coords (&theader, &refmosaic[0].coords);
+  gfits_fwrite_header (f, &theader);
+  gfits_fwrite_matrix (f, &matrix);
+  gfits_free_matrix (&matrix);
+
+# ifdef GRID_V1
+  /* calculate pixel values for each CCD pixel, write out CCD images */
+  /* grid pixels are in RA,DEC coords, transform to image and interpolate */
+  for (i = 0; i < Nimage; i++) {
+    image = getimage (imlist[i]);
+    pname = GetPhotcodeNamebyCode (image[0].photcode);
+
+    /* this is kind of bogus... */
+    /* pname is CAMERA.FILTER.CCD, grab the CCD */
+    p = strrchr (pname, '.');
+    if (p == (char *) NULL) {
+      fprintf (stderr, "error parsing photcode %s\n", pname);
+      exit (2);
+    }
+    p++;
+    sprintf (ccdname, "ccd%s", p);
+
+    gfits_modify (&theader, "EXTNAME", "%s", 1, ccdname);
+    gfits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+    gfits_modify (&theader, "PHOTCODE", "%s", 1, pname);
+    gfits_modify (&theader, "NX", "%d", 1, image[i].NX);
+    gfits_modify (&theader, "NY", "%d", 1, image[i].NY);
+    write_coords (&theader, &image[0].coords);
+
+    Nx = 2 * image[i].NX / RELPHOT_GRID_BINNING;
+    Ny = 2 * image[i].NY / RELPHOT_GRID_BINNING;
+    theader.Naxis[0] = Nx;
+    theader.Naxis[1] = Ny;
+    gfits_modify (&theader, "NAXIS1", "%d", 1, Nx);
+    gfits_modify (&theader, "NAXIS2", "%d", 1, Ny);
+    gfits_create_matrix  (&theader, &matrix);
+
+    InterpolateGrid ((float *)matrix.buffer, Nx, Ny, &image[0].coords, &refmosaic[0].coords);
+    gfits_fwrite_header (f, &theader);
+    gfits_fwrite_matrix (f, &matrix);
+    gfits_free_matrix (&matrix);
+  }
+# endif
+
+# ifdef GRID_V2
+  /* calculate value for each CCD pixel, write out CCD images */
+  /* grid pixels are tied to detector pixels, but are flipped to match focal plane */
+  for (i = 0; i < camera.Nchip; i++) {
+    int ix, iy, x, y, X, Y, bin;
+
+    gfits_modify (&theader, "EXTNAME", "%s", 1, camera.ccdname[i]);
+    gfits_modify (&theader, "FILTER", "%s", 1, photcode[0].name);
+    gfits_modify (&theader, "NX", "%d", 1, camera.Nx);
+    gfits_modify (&theader, "NY", "%d", 1, camera.Ny);
+      
+    theader.Naxis[0] = RELPHOT_GRID_X;
+    theader.Naxis[1] = RELPHOT_GRID_Y;
+    gfits_modify (&theader, "NAXIS1", "%d", 1, RELPHOT_GRID_X);
+    gfits_modify (&theader, "NAXIS2", "%d", 1, RELPHOT_GRID_Y);
+    gfits_create_matrix  (&theader, &matrix);
+
+    for (Y = 0; Y < RELPHOT_GRID_Y; Y++) {
+      for (X = 0; X < RELPHOT_GRID_X; X++) {
+	      
+	/* normalize X & Y */
+	x = X;
+	if (camera.Fx[i]) x = RELPHOT_GRID_X - X - 1;
+	y = Y;
+	if (camera.Fy[i]) y = RELPHOT_GRID_Y - Y - 1;
+	      
+	/* coordinates in the grid */
+	ix = x + camera.Ox[i]*RELPHOT_GRID_X;
+	iy = y + camera.Oy[i]*RELPHOT_GRID_Y;
+	      
+	bin = ix + iy*gridX;
+	gfits_set_matrix_value (&matrix, X, Y, (double) gridM[bin]);
+      }
+    }
+    gfits_fwrite_header (f, &theader);
+    gfits_fwrite_matrix (f, &matrix);
+    gfits_free_matrix (&matrix);
+  }
+# endif
+
+}
+
+void InterpolateGrid (float *buffer, int Nx, int Ny, Coords *ccd, Coords *gcoords) {
+
+  int i, j;
+  double x, y, r, d, X, Y, dx, dy;
+  double V00, V01, V10, V11;
+  double wV00, wV01, wV10, wV11;
+  double dV00, dV01, dV10, dV11;
+  double v1, v2, value;
+  int ix, iy, N;
+
+  for (i = 0; i < Nx; i++) {
+    for (j = 0; j < Ny; j++) {
+      x = i * RELPHOT_GRID_BINNING / 2;
+      y = j * RELPHOT_GRID_BINNING / 2;
+      XY_to_RD (&r, &d, x, y, ccd);
+      RD_to_XY (&X, &Y, r, d, gcoords);
+
+      X = X / RELPHOT_GRID_BINNING;
+      Y = Y / RELPHOT_GRID_BINNING;
+
+      ix = (int) X;
+      dx = X - ix;
+      iy = (int) Y;
+      dy = Y - iy;
+
+      if (ix < 0) continue;
+      if (iy < 0) continue;
+      if (ix >= gridX) continue;
+      if (iy >= gridY) continue;
+
+      N = ix + iy*gridX;
+      V00 = gridM[N];
+      V10 = gridM[N + 1];
+      V01 = gridM[N + gridX];
+      V11 = gridM[N + gridX + 1];
+
+      dV00 = gridS[N];
+      dV10 = gridS[N + 1];
+      dV01 = gridS[N + gridX];
+      dV11 = gridS[N + gridX + 1];
+
+      wV00 = (dV00 == 0) ? 0.0 : 1 / SQ(dV00);
+      wV01 = (dV01 == 0) ? 0.0 : 1 / SQ(dV01);
+      wV10 = (dV10 == 0) ? 0.0 : 1 / SQ(dV10);
+      wV11 = (dV11 == 0) ? 0.0 : 1 / SQ(dV11);
+
+      v1 = wV00*V00*(1 + dx*dy - dx - dy) +
+	wV10*V10*(dx - dx*dy) +
+	wV01*V01*(dy - dx*dy) +
+	wV11*V11*(dx*dy);
+
+      v2 = wV00*(1 + dx*dy - dx - dy) +
+	wV10*(dx - dx*dy) +
+	wV01*(dy - dx*dy) +
+	wV11*(dx*dy);
+
+      value = v1 / v2;
+      buffer[j*Nx + i] = value;
+    }
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/ImageOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/ImageOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/ImageOps.c	(revision 16632)
@@ -0,0 +1,480 @@
+# include "relphot.h"
+
+static unsigned int *start;
+static unsigned int *stop;
+static int         **bin;
+
+static int         **clist;
+static int         **mlist;
+static int          *Nlist;
+static int          *NLIST;
+
+static Image        *image;
+static int          Nimage;
+
+void initImages (Image *input, int N) {
+
+  int i;
+
+  image = input;
+  Nimage = N;
+
+  ALLOCATE (start,   unsigned, Nimage);
+  ALLOCATE (stop,    unsigned, Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+    start[i] = image[i].tzero - MAX(0.05*image[i].trate*image[i].NY, 1);
+    stop[i]  = image[i].tzero + MAX(1.05*image[i].trate*image[i].NY, 1);
+  }
+}
+
+void initImageBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  ALLOCATE (bin, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  ALLOCATE (Nlist, int, Nimage);
+  ALLOCATE (NLIST, int, Nimage);
+  ALLOCATE (clist, int *, Nimage);
+  ALLOCATE (mlist, int *, Nimage);
+
+  for (i = 0; i < Nimage; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeImageBins (int Ncatalog) {
+
+  int i;
+
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+  }
+  free (bin);
+  for (i = 0; i < Nimage; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (clist);
+  free (mlist);
+}
+
+/* select all image equivalent to the current photcode */
+void findImages (Catalog *catalog, int Ncatalog) {
+
+  int i, j, ecode;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Nmeasure; j++) {
+      ecode = GetPhotcodeEquivCodebyCode (catalog[i].measure[j].photcode);
+      if (photcode[0].code != ecode) continue;
+      matchImage (catalog, j, i);
+    }
+  }
+}
+
+/* XXX convert this to use the values of measure->Xccd,Yccd */
+/* XXX need to apply the conversion for ELIXIR and LONEOS formats */
+void matchImage (Catalog *catalog, int meas, int cat) {
+
+  int i, ave, ccdnum;
+  double ra, dec, X, Y;
+  char *pname, *filter, *p, base[256];
+  Measure *measure;
+  
+  measure = &catalog[cat].measure[meas];
+  for (i = 0; i < Nimage; i++) {
+    if (image[0].photcode == -1) continue;
+    if (measure[0].photcode != image[i].photcode) continue;
+    if (measure[0].t < start[i]) continue;
+    if (measure[0].t > stop[i]) continue;
+    
+# ifdef GRID_V2 /* this section is added to support GridOps.v2.c */
+    if (USE_GRID) {
+
+      /* identify the ccd on the basis of the photcode name */
+      pname = GetPhotcodeNamebyCode (image[i].photcode);
+      filter = photcode[0].name;
+      sprintf (base, "%s.%s.", MOSAICNAME, filter);
+      if (strncmp (pname, base, strlen (base))) continue;
+      p = pname + strlen(base);
+      if (*p == 0) continue;
+      ccdnum = atoi (p);
+      /* some ambiguity here between seq number and id number */
+
+      /* add this measurement to the grid cell for this chip */
+      ave = measure[0].averef;
+      ra  = catalog[cat].average[ave].R - measure[0].dR / 3600.0;
+      dec = catalog[cat].average[ave].D - measure[0].dD / 3600.0;
+       
+      /* X,Y always positive-definite in range 0,0 - dX, dY */
+      RD_to_XY (&X, &Y, ra, dec, &image[i].coords);
+      setGridMeasure (meas, cat, X, Y, ccdnum);
+    }
+# endif
+
+    bin[cat][meas] = i;
+
+    clist[i][Nlist[i]] = cat;
+    mlist[i][Nlist[i]] = meas;
+    Nlist[i] ++;
+
+    if (Nlist[i] == NLIST[i]) {
+      NLIST[i] += 100;
+      REALLOCATE (clist[i], int, NLIST[i]);
+      REALLOCATE (mlist[i], int, NLIST[i]);
+    }	
+    return;
+  }
+  /*  fprintf (stderr, "can't find source image for this measurement: %d (%d)\n", measure[0].t, measure[0].photcode); */
+}
+
+int getImageEntry (int meas, int cat) {
+
+  int i;
+
+  i = bin[cat][meas];
+  return (i);
+}
+
+float getMcal (int meas, int cat) {
+
+  int i;
+  float value;
+
+  i = bin[cat][meas];
+  if (i == -1) return (NAN);
+
+  if (image[i].code & IMAGE_BAD) return (NAN);  
+  value = image[i].Mcal;
+  return (value);
+}
+
+Coords *getCoords (int meas, int cat) {
+
+  int i;
+
+  i = bin[cat][meas];
+  if (i == -1) return (NULL);
+  return (&image[i].coords);
+}
+
+/* determine Mcal values for all images */
+void setMcal (Catalog *catalog, int PoorImages) {
+
+  int i, j, m, c, n, N, Nmax, mark, bad;
+  float Msys, Mrel, Mmos, Mgrid;
+  double *list, *dlist;
+  StatType stats;
+
+  if (FREEZE_IMAGES) return;
+
+  if (PoorImages) {
+    IMAGE_BAD = STAR_BAD = MEAS_BAD = 0;
+  }
+
+  Nmax = 0;
+  for (i = 0; i < Nimage; i++) {
+    Nmax = MAX (Nmax, Nlist[i]);
+  }
+  ALLOCATE (list, double, Nmax);
+  ALLOCATE (dlist, double, Nmax);
+
+  for (i = 0; i < Nimage; i++) {
+    
+    /* on PoorImages run, skip good images */
+    if (PoorImages) {
+      bad = image[i].code & (ID_IMAGE_FEW | ID_IMAGE_POOR | ID_IMAGE_SKIP);
+      if (!bad) continue;
+    }      
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].dbFlags & MEAS_BAD) continue;
+      Mmos  = getMmos  (m, c);
+      if (isnan(Mmos)) continue;
+      Mgrid = getMgrid (m, c);
+      if (isnan(Mgrid)) continue;
+      Mrel  = getMrel  (catalog, m, c);
+      if (isnan(Mrel)) continue;
+      
+      n = catalog[c].measure[m].averef;
+      Msys = PhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      list[N] = Msys - Mrel - Mmos - Mgrid;
+      dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
+      N++;
+    }
+    /* Nlist[i] is all measurements, N is good measurements */
+
+    /* too few good measurements or too many bad measurements */
+    if (!PoorImages) {
+      mark = (N < IMAGE_TOOFEW) || (N < IMAGE_GOOD_FRACTION*Nlist[i]);
+      if (mark) {
+	image[i].code |= ID_IMAGE_FEW;
+      } else {
+	image[i].code &= ~ID_IMAGE_FEW;
+      }      
+    }
+    
+    liststats (list, dlist, N, &stats);
+    image[i].Mcal  = stats.mean;
+    image[i].dMcal = stats.sigma;
+    image[i].Xm    = 100.0*log10(stats.chisq);
+  }
+  free (list);
+  free (dlist);
+  if (PoorImages) {
+    IMAGE_BAD = ID_IMAGE_POOR | ID_IMAGE_FEW | ID_IMAGE_SKIP;
+    STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
+    MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR | ID_MEAS_SKIP | ID_MEAS_AREA;
+  }
+  return;
+}
+
+/* mark image if: abs(Mcal) too large, dMcal too large */
+void clean_images () {
+
+  int i, N, mark, Nmark;
+  double *mlist, *slist, *dlist;
+  double MaxOffset, MaxScatter, MedOffset;
+  StatType stats;
+
+  if (FREEZE_IMAGES) return;
+
+  if (VERBOSE) fprintf (stderr, "marking poor images\n");
+
+  ALLOCATE (mlist, double, Nimage);
+  ALLOCATE (slist, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  for (i = N = 0; i < Nimage; i++) {
+    if (image[i].code & IMAGE_BAD) continue;
+    mlist[N] = fabs (image[i].Mcal);
+    slist[N] = image[i].dMcal;
+    dlist[N] = 1;
+    N++;
+  }
+  initstats ("MEAN");
+  liststats (mlist, dlist, N, &stats);
+  MaxOffset = MAX (IMAGE_OFFSET, 3*stats.sigma);
+  MedOffset = stats.median;
+  liststats (slist, dlist, N, &stats);
+  MaxScatter = MAX (IMAGE_SCATTER, 2*stats.median);
+  fprintf (stderr, "Mrel: %f, dMrel: %f, Max Scatter: %f, Max Offset: %f\n", MedOffset, stats.median, MaxScatter, MaxOffset);
+  
+  Nmark = 0;
+  for (i = 0; i < Nimage; i++) {
+    mark = FALSE;
+    image[i].code &= ~ID_IMAGE_POOR;
+    mark = (image[i].dMcal > MaxScatter) || (fabs(image[i].Mcal - MedOffset) > MaxOffset);
+    if (mark) { 
+      Nmark ++;
+      image[i].code |= ID_IMAGE_POOR;
+    } else {
+      image[i].code &= ~ID_IMAGE_POOR;
+    }
+  }
+
+  fprintf (stderr, "%d images marked poor\n", Nmark);
+  initstats (STATMODE);
+  free (mlist);
+  free (slist);
+  free (dlist);
+}
+
+void plot_images () {
+
+  int i, bin;
+  double *xlist, *Mlist, *dlist;
+  Graphdata graphdata;
+
+  if (FREEZE_IMAGES) return;
+
+  ALLOCATE (xlist, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+  ALLOCATE (Mlist, double, Nimage);
+
+  /**** dMcal vs airmass ****/
+  for (i = 0; i < Nimage; i++) {
+    Mlist[i] = image[i].Mcal;
+    dlist[i] = image[i].dMcal;
+    xlist[i] = image[i].secz;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin; 
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, Nimage, "airmass vs Mcal", "airmass.png");
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, Mlist, dlist, Nimage, "Mcal vs dMcal", NULL);
+
+# define NBIN 200
+  REALLOCATE (xlist, double, NBIN);
+  REALLOCATE (Mlist, double, NBIN);
+
+  /**** dMcal histgram ****/
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.00025*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Nimage; i++) {
+    bin = image[i].dMcal / 0.00025;
+    bin = MAX (0, MIN (NBIN - 1, bin));
+    Mlist[bin] += 1.0;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMcal hist", "dMcalhist.png");
+
+  free (dlist);
+  free (xlist);
+  free (Mlist);
+}
+
+StatType statsImageN (Catalog *catalog) {
+
+  int i, j, m, c, n, N;
+  double *list, *dlist;
+  float Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+
+      m = mlist[i][j];
+      c = clist[i][j];
+
+      Mcal  = getMcal  (m, c);
+      if (isnan(Mcal)) continue;
+      Mmos  = getMmos  (m, c);
+      if (isnan(Mmos)) continue;
+      Mgrid = getMgrid (m, c);
+      if (isnan(Mgrid)) continue;
+      N++;
+    }
+    list[n] = N;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsImageX (Catalog *catalog) {
+
+  int i, n;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    list[n] = pow (10.0, 0.01*image[i].Xm);
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsImageM (Catalog *catalog) {
+
+  int i, n;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    list[n] = image[i].Mcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsImagedM (Catalog *catalog) {
+
+  int i, n;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (FREEZE_IMAGES) return (stats);
+
+  ALLOCATE (list, double, Nimage);
+  ALLOCATE (dlist, double, Nimage);
+
+  n = 0;
+  for (i = 0; i < Nimage; i++) {
+
+    if (image[i].code & IMAGE_BAD)  continue;
+
+    list[n] = image[i].dMcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+Image *getimages (int *N) {
+
+  *N = Nimage;
+  return (image);
+}
+
+Image *getimage (int N) {
+  return (&image[N]);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/MosaicOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/MosaicOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/MosaicOps.c	(revision 16632)
@@ -0,0 +1,681 @@
+# include "relphot.h"
+
+Image *getimages (int *N);
+
+static int    Nmosaic;
+static Mosaic *mosaic;
+
+static int    *Nimlist;
+static int   **imlist; /* mosaic -> image[] */
+static int   **bin;    /* catalog, measure -> mosaic */
+
+static int   **clist;  /* mosaic -> catalog[] */
+static int   **mlist;  /* mosiac -> measure[] */
+static int    *Nlist;
+static int    *NLIST;
+
+/* find mosaic frames (unique time periods & photcode name matches mosaic) */
+void initMosaics (Image *image, int Nimage) {
+
+  int i, j, status, found, NMOSAIC, *NIMLIST;
+  unsigned int start, stop;
+  char *pname;
+
+  if (!MOSAICNAME[0]) return;
+
+  Nmosaic = 0;
+  NMOSAIC = 10;
+  ALLOCATE (mosaic, Mosaic, NMOSAIC);
+
+  ALLOCATE (imlist, int *, NMOSAIC);
+  ALLOCATE (Nimlist, int, NMOSAIC);
+  ALLOCATE (NIMLIST, int, NMOSAIC);
+
+  /* generate list of unique mosaics */
+  for (i = 0; i < Nimage; i++) {
+
+    /* select valid mosaic images by photcode */
+    pname = GetPhotcodeNamebyCode (image[i].photcode);
+    status = strncmp (pname, MOSAICNAME, strlen (MOSAICNAME));
+    if (status) continue;
+
+    /* set image time range */
+    start = image[i].tzero - MAX(0.05*image[i].trate*image[i].NY, 1);
+    stop  = image[i].tzero + MAX(1.05*image[i].trate*image[i].NY, 1);
+
+    /* find existing mosaic with this time range */
+    found = FALSE;
+    for (j = 0; !found && (j < Nmosaic); j++) { 
+      if (stop  < mosaic[j].start) continue;
+      if (start > mosaic[j].stop)  continue;
+      found = TRUE;
+
+      /* add image to mosaic image list */
+      imlist[j][Nimlist[j]] = i;
+      Nimlist[j] ++;
+      if (Nimlist[j] == NIMLIST[j]) {
+	NIMLIST[j] += 10;
+	REALLOCATE (imlist[j], int, NIMLIST[j]);
+      }
+
+    }
+    if (found) continue;
+    
+    /* a new mosaic, define ranges */
+    mosaic[Nmosaic].start = start;
+    mosaic[Nmosaic].stop  = stop;
+    mosaic[Nmosaic].Mcal  = 0.0;
+    mosaic[Nmosaic].dMcal = 0.0;
+    mosaic[Nmosaic].Xm    = 0.0;
+    mosaic[Nmosaic].code  = image[i].code;
+    mosaic[Nmosaic].secz  = image[i].secz;
+
+    /* add image to mosaic image list */
+    NIMLIST[Nmosaic] = 10;
+    Nimlist[Nmosaic] = 1;
+    ALLOCATE (imlist[Nmosaic], int, NIMLIST[Nmosaic]);
+    imlist[Nmosaic][0] = i;
+
+    Nmosaic ++;
+    if (Nmosaic == NMOSAIC) {
+      NMOSAIC += 10;
+      REALLOCATE (mosaic, Mosaic, NMOSAIC);
+      REALLOCATE (imlist, int *, NMOSAIC);
+      REALLOCATE (Nimlist, int, NMOSAIC);
+      REALLOCATE (NIMLIST, int, NMOSAIC);
+    }
+  }
+
+  initMosaicGrid (image, Nimage);
+  return;
+}
+
+void initMosaicGrid (Image *image, int Nimage) {
+
+  /* find max dR, dD range for all mosaics */
+  /* define mosaic.coords to cover dR, dD */
+  /* send results to initGridBins */
+
+  int i, j, m, NX, NY;
+  int dXmax, dYmax;
+  double dS, dX, dY;
+  double R, D, Rmin, Rmax, Dmin, Dmax;
+  double Mcal, dMcal, Xm;
+
+  dXmax = dYmax = 0.0;
+  for (i = 0; i < Nmosaic; i++) {
+    Dmin = Rmin =  360.0;
+    Dmax = Rmax = -360.0;
+    dS = 0.0;
+    Mcal = dMcal = Xm = 0;
+    for (j = 0; j < Nimlist[i]; j++) {
+      m = imlist[i][j];
+      NX = image[m].NX;
+      NY = image[m].NY;
+      dS += hypot (image[m].coords.cdelt1*image[m].coords.pc1_1, image[m].coords.cdelt1*image[m].coords.pc2_1);
+      XY_to_RD (&R, &D, 0.0, 0.0, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      XY_to_RD (&R, &D, (double) NX, 0.0, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      XY_to_RD (&R, &D, (double) NX, (double) NY, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      XY_to_RD (&R, &D, 0.0, (double) NY, &image[m].coords);
+      Rmin = MIN (Rmin, R);
+      Rmax = MAX (Rmax, R);
+      Dmin = MIN (Dmin, D);
+      Dmax = MAX (Dmax, D);
+      Mcal  += image[m].Mcal;
+      dMcal += image[m].dMcal;
+      Xm    += image[m].Xm;
+      /* we are using mosaic.Mcal, not image.Mcal. reset image.Mcal */
+      image[m].Mcal  = 0.0;
+      image[m].dMcal = NAN;
+      image[m].Xm    = NAN_S_SHORT;
+    }
+    dS /= Nimlist[i];
+    strcpy (mosaic[i].coords.ctype, "RA---TAN");
+    mosaic[i].coords.crval1 = Rmin;
+    mosaic[i].coords.crval2 = Dmin;
+    mosaic[i].coords.crpix1 = 0.0;
+    mosaic[i].coords.crpix2 = 0.0;
+    mosaic[i].coords.cdelt1 = dS;
+    mosaic[i].coords.cdelt2 = dS;
+    mosaic[i].coords.pc1_1  = 1.0;
+    mosaic[i].coords.pc2_2  = 1.0;
+    mosaic[i].coords.pc1_2  = 0.0;
+    mosaic[i].coords.pc2_1  = 0.0;
+    RD_to_XY (&dX, &dY, Rmax, Dmax, &mosaic[i].coords);
+
+    mosaic[i].Mcal  = Mcal / Nimlist[i];
+    mosaic[i].dMcal = dMcal / Nimlist[i];
+    mosaic[i].Xm    = Xm / Nimlist[i];
+  }
+  if (!USE_GRID) return;
+
+  dXmax = MAX (dXmax, dX);
+  dYmax = MAX (dYmax, dY);
+  initGrid (dXmax, dYmax);
+  return;
+}
+
+void setMcalFinal () {
+
+  int i, j, im, Nimage;
+  Image *image;
+
+  if (!MOSAICNAME[0]) return;
+
+  image = getimages (&Nimage);
+
+  for (i = 0; i < Nmosaic; i++) {
+    for (j = 0; j < Nimlist[i]; j++) {
+      im = imlist[i][j];
+      image[im].Mcal = mosaic[i].Mcal;
+      image[im].dMcal = mosaic[i].dMcal;
+      image[im].Xm = mosaic[i].Xm;
+      image[im].code |= (mosaic[i].code & ID_IMAGE_FEW);
+      image[im].code |= (mosaic[i].code & ID_IMAGE_POOR);
+    }
+  }      
+}
+
+void initMosaicBins (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+
+  /* measure -> mosaic */
+  if (!MOSAICNAME[0]) return;
+  ALLOCATE (bin, int *, Ncatalog);
+  for (i = 0; i < Ncatalog; i++) {
+    ALLOCATE (bin[i], int, MAX (catalog[i].Nmeasure, 1));
+    for (j = 0; j < catalog[i].Nmeasure; j++) bin[i][j] = -1;
+  }
+
+  /* mosaic -> measure */
+  ALLOCATE (Nlist, int, Nmosaic);
+  ALLOCATE (NLIST, int, Nmosaic);
+  ALLOCATE (clist, int *, Nmosaic);
+  ALLOCATE (mlist, int *, Nmosaic);
+
+  for (i = 0; i < Nmosaic; i++) {
+    Nlist[i] = 0;
+    NLIST[i] = 100;
+    ALLOCATE (clist[i], int, NLIST[i]);
+    ALLOCATE (mlist[i], int, NLIST[i]);
+  }
+}
+
+void freeMosaicBins (int Ncatalog) {
+
+  int i;
+
+  /* measure -> mosaic */
+  if (!MOSAICNAME[0]) return;
+  for (i = 0; i < Ncatalog; i++) {
+    free (bin[i]);
+  }
+  free (bin);
+
+  /* mosaic -> measure */
+  for (i = 0; i < Nmosaic; i++) {
+    free (clist[i]);
+    free (mlist[i]);
+  }
+  free (Nlist);
+  free (NLIST);
+  free (clist);
+  free (mlist);
+}
+
+int findMosaics (Catalog *catalog, int Ncatalog) {
+  
+  int i, j, ecode;
+
+  if (!MOSAICNAME[0]) return (FALSE);
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Nmeasure; j++) {
+      if (TimeSelect) {
+	if (catalog[i].measure[j].t < TSTART) continue;
+	if (catalog[i].measure[j].t > TSTOP) continue;
+      }
+      ecode = GetPhotcodeEquivCodebyCode (catalog[i].measure[j].photcode);
+      if (photcode[0].code != ecode) continue;
+      matchMosaics (catalog, j, i);
+    }
+  }
+  return (TRUE);
+}
+
+void matchMosaics (Catalog *catalog, int meas, int cat) {
+
+  int i;
+
+  for (i = 0; i < Nmosaic; i++) {
+    if (catalog[cat].measure[meas].t < mosaic[i].start) continue;
+    if (catalog[cat].measure[meas].t > mosaic[i].stop) continue;
+    
+# ifdef GRID_V1
+    if (USE_GRID) {
+      ave = catalog[cat].measure[meas].averef;
+      ra  = catalog[cat].average[ave].R - catalog[cat].measure[meas].dR / 3600.0;
+      dec = catalog[cat].average[ave].D - catalog[cat].measure[meas].dD / 3600.0;
+
+      /* X,Y always positive-definite in range 0,0 - dX, dY */
+      RD_to_XY (&X, &Y, ra, dec, &mosaic[i].coords);
+      setGridMeasure (meas, cat, X, Y);
+    }
+# endif
+
+    bin[cat][meas] = i;
+
+    clist[i][Nlist[i]] = cat;
+    mlist[i][Nlist[i]] = meas;
+    Nlist[i] ++;
+    
+    if (Nlist[i] == NLIST[i]) {
+      NLIST[i] += 100;
+      REALLOCATE (clist[i], int, NLIST[i]);
+      REALLOCATE (mlist[i], int, NLIST[i]);
+    }	
+    return;
+  }
+  fprintf (stderr, "missed measurement\n");
+  return;
+}
+
+float getMmos (int meas, int cat) {
+
+  int i;
+  float value;
+
+  if (!MOSAICNAME[0]) return (0);
+  i = bin[cat][meas];
+  if (i == -1) return (NAN);
+
+  if (mosaic[i].code & IMAGE_BAD) return (NAN);  
+  value = mosaic[i].Mcal;
+  return (value);
+}
+
+int setMmos (Catalog *catalog, int PoorImages) {
+
+  int i, j, m, c, n, N, Nmax, mark, bad;
+  float Msys, Mrel, Mcal, Mgrid;
+  double *list, *dlist, *Mlist, *dMlist;
+  StatType stats;
+  Image *image;
+
+  if (!MOSAICNAME[0]) return (FALSE);
+
+  image = getimages (&N);
+
+  if (PoorImages) {
+    IMAGE_BAD = 0;
+  }
+
+  Nmax = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    Nmax = MAX (Nmax, Nlist[i]);
+  }
+  ALLOCATE (list, double, Nmax);
+  ALLOCATE (dlist, double, Nmax);
+  ALLOCATE (Mlist, double, Nmax);
+  ALLOCATE (dMlist, double, Nmax);
+
+  for (i = 0; i < Nmosaic; i++) {
+    
+    /* on PoorImages run, skip good images */
+    if (PoorImages) {
+      bad = mosaic[i].code & (ID_IMAGE_FEW | ID_IMAGE_POOR | ID_IMAGE_SKIP);
+      if (!bad) continue;
+    }      
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].dbFlags & MEAS_BAD) continue;
+      Mcal  = getMcal  (m, c);
+      if (isnan(Mcal)) continue;
+      Mgrid = getMgrid (m, c);
+      if (isnan(Mgrid)) continue;
+      Mrel  = getMrel  (catalog, m, c);
+      if (isnan(Mrel)) continue;
+      
+      n = catalog[c].measure[m].averef;
+      Msys = PhotSys (&catalog[c].measure[m], &catalog[c].average[n], &catalog[c].secfilt[n*PhotNsec]);
+      list[N]  = Msys - Mrel - Mcal - Mgrid;
+      dlist[N] = MAX (catalog[c].measure[m].dM, MIN_ERROR);
+      Mlist[N] = Msys;
+      dMlist[N] = list[N];
+      N++;
+    }
+    /* Nlist[i] is all measurements, N is good measurements */
+
+    /* too few good measurements or too many bad measurements (skip in PoorImages run) */
+
+    if (!PoorImages) {
+      mark = (N < IMAGE_TOOFEW) || (N < IMAGE_GOOD_FRACTION*Nlist[i]);
+      if (mark) {
+	fprintf (stderr, "marked image %s (%d), (%d < %d) || (%d < %f*%d)\n", image[imlist[i][0]].name, i, N, IMAGE_TOOFEW, N, IMAGE_GOOD_FRACTION, Nlist[i]);
+	mosaic[i].code |= ID_IMAGE_FEW;
+      } else {
+	mosaic[i].code &= ~ID_IMAGE_FEW;
+      }
+    }
+    liststats (list, dlist, N, &stats);
+    if (PoorImages) fprintf (stderr, "Mmos: %f %f %d %d\n", stats.mean, stats.sigma, stats.Nmeas, N);
+    mosaic[i].Mcal  = stats.mean;
+    mosaic[i].dMcal = stats.sigma;
+    mosaic[i].Xm    = 100.0*log10(stats.chisq);
+  }
+  free (list);
+  free (dlist);
+  free (Mlist);
+  free (dMlist);
+
+  if (PoorImages) {
+    IMAGE_BAD = ID_IMAGE_POOR | ID_IMAGE_FEW | ID_IMAGE_SKIP;
+    STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
+    MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR | ID_MEAS_SKIP | ID_MEAS_AREA;
+  }
+  return (TRUE);
+}
+  
+StatType statsMosaicM (Catalog *catalog) {
+
+  int i, n;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    list[n] = mosaic[i].Mcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsMosaicdM (Catalog *catalog) {
+
+  int i, n;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    list[n] = mosaic[i].dMcal;
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsMosaicN (Catalog *catalog) {
+
+  int i, j, m, c, n, N;
+  double *list, *dlist;
+  float Mcal, Mgrid, Mrel;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    if (mosaic[i].code & IMAGE_BAD)  continue;
+
+    N = 0;
+    for (j = 0; j < Nlist[i]; j++) {
+
+      m = mlist[i][j];
+      c = clist[i][j];
+
+      Mcal = getMcal  (m, c);
+      if (isnan(Mcal)) continue;
+      Mgrid = getMgrid (m, c);
+      if (isnan(Mgrid)) continue;
+      Mrel = getMrel  (catalog, m, c);
+      if (isnan(Mrel)) continue;
+      N++;
+    }
+    list[n] = N;
+    dlist[n] = 1;
+    n++;
+  }
+  fprintf (stderr, "Nmosaic: %d, n: %d\n", Nmosaic, n);
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsMosaicX (Catalog *catalog) {
+
+  int i, n;
+  double *list, *dlist;
+  StatType stats;
+
+  bzero (&stats, sizeof (StatType));
+  if (!MOSAICNAME[0]) return (stats);
+
+  ALLOCATE (list, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  n = 0;
+  for (i = 0; i < Nmosaic; i++) {
+
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    list[n] = pow(10.0, 0.01*mosaic[i].Xm);
+    dlist[n] = 1;
+    n++;
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+/* mark mosaic if: abs(Mcal - <Mcal>) too large, dMcal too large */
+void clean_mosaics () {
+
+  int i, N, mark, Nmark;
+  double *mlist, *slist, *dlist;
+  double MaxOffset, MedOffset, MaxScatter;
+  StatType stats;
+
+  if (!MOSAICNAME[0]) return;
+
+  if (VERBOSE) fprintf (stderr, "marking poor mosaics\n");
+
+  ALLOCATE (mlist, double, Nmosaic);
+  ALLOCATE (slist, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+
+  for (i = N = 0; i < Nmosaic; i++) {
+    if (mosaic[i].code & IMAGE_BAD) continue;
+    mlist[N] = mosaic[i].Mcal;
+    slist[N] = mosaic[i].dMcal;
+    dlist[N] = 1;
+    N++;
+  }
+  initstats ("MEAN");
+  liststats (mlist, dlist, N, &stats);
+  MaxOffset = MAX (IMAGE_OFFSET, 2*stats.sigma);
+  MedOffset = stats.median;
+  liststats (slist, dlist, N, &stats);
+  MaxScatter = MAX (IMAGE_SCATTER, 2*stats.median);
+  fprintf (stderr, "Mrel: %f, dMrel: %f, Max Scatter: %f, Max Offset: %f\n", MedOffset, stats.median, MaxScatter, MaxOffset);
+  
+  Nmark = 0;
+  for (i = 0; i < Nmosaic; i++) {
+    mark = FALSE;
+    mark = (mosaic[i].dMcal > MaxScatter) || (fabs(mosaic[i].Mcal - MedOffset) > MaxOffset);
+    if (mark) { 
+      Nmark ++;
+      mosaic[i].code |= ID_IMAGE_POOR;
+    } else {
+      mosaic[i].code &= ~ID_IMAGE_POOR;
+    }
+  }
+
+  fprintf (stderr, "%d mosaics marked poor\n", Nmark);
+  initstats (STATMODE);
+  free (mlist);
+  free (slist);
+  free (dlist);
+}
+
+void plot_mosaic_fields (Catalog *catalog) {
+
+  int i, j, m, c, N, ave, Nimage;
+  double *xlist, *ylist;
+  double Xmin, Xmax, Ymin, Ymax;
+  char string[64];
+  Image *image;
+  Graphdata graphdata;
+
+  if (!MOSAICNAME[0]) return;
+
+  image = getimages (&Nimage);
+
+  N = 0;
+  for (i = 0; i < Nmosaic; i++) 
+    N = MAX (N, Nlist[i]);
+
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+
+  for (i = 0; i < Nmosaic; i++) {
+    N = 0;
+    Xmin = Ymin = +360.0;
+    Xmax = Ymax = -360.0;
+    for (j = 0; j < Nlist[i]; j++) {
+      
+      m = mlist[i][j];
+      c = clist[i][j];
+      
+      if (catalog[c].measure[m].dbFlags & (ID_MEAS_AREA | ID_MEAS_NOCAL)) continue;
+
+      ave = catalog[c].measure[m].averef;
+      xlist[N] = catalog[c].average[ave].R - catalog[c].measure[m].dR / 3600.0;
+      ylist[N] = catalog[c].average[ave].D - catalog[c].measure[m].dD / 3600.0;
+      N++;
+    }
+  
+    sprintf (string, "Mosaic %d", i);
+    plot_defaults (&graphdata);
+    plot_list (&graphdata, xlist, ylist, N, string, NULL);
+  }
+
+  free (ylist);
+  free (xlist);
+}
+
+void plot_mosaics () {
+
+  int i, bin;
+  double *xlist, *Mlist, *dlist;
+  Graphdata graphdata;
+
+  if (!MOSAICNAME[0]) return;
+
+  ALLOCATE (xlist, double, Nmosaic);
+  ALLOCATE (dlist, double, Nmosaic);
+  ALLOCATE (Mlist, double, Nmosaic);
+
+  for (i = 0; i < Nmosaic; i++) {
+    Mlist[i] = mosaic[i].Mcal;
+    dlist[i] = mosaic[i].dMcal;
+    xlist[i] = mosaic[i].secz;
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.xmin = 0.95;
+  graphdata.xmax = 2.50;
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, Mlist, Nmosaic, "airmass vs Mcal", "airmass.png");
+  plot_defaults (&graphdata);
+  graphdata.size = 1.5;
+  graphdata.ptype = 7;
+  plot_list (&graphdata, Mlist, dlist, Nmosaic, "Mcal vs dMcal", "MdM.png");
+
+# define NBIN 200
+  REALLOCATE (xlist, double, NBIN);
+  REALLOCATE (Mlist, double, NBIN);
+
+  /**** dMcal histgram ****/
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.00005*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Nmosaic; i++) {
+    bin = mosaic[i].dMcal / 0.00005;
+    bin = MAX (0, MIN (NBIN - 1, bin));
+    Mlist[bin] += 1.0;
+  }
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMcal hist", "dMcalhist.png");
+
+  free (dlist);
+  free (xlist);
+  free (Mlist);
+}
+
+int *SelectRefMosaic (Mosaic **refmosaic, int *Nimage) {
+
+  int i, Imax, Nmax;
+
+  Imax = 0;
+  Nmax = Nimlist[0];
+  for (i = 0; i < Nmosaic; i++) {
+    if (Nimlist[i] > Nmax) {
+      Imax = i;
+      Nmax = Nimlist[i];
+    }
+  }
+
+  *refmosaic = &mosaic[Imax];
+  *Nimage = Nmax;
+  return (imlist[Imax]);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "relphot.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "relphot.h"
+
+static FITS_DB *db;
+
+void set_db (FITS_DB *in) {
+  db = in;
+}
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format));
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  SetProtect (TRUE);
+  gfits_db_close (db);
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/StarOps.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/StarOps.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/StarOps.c	(revision 16632)
@@ -0,0 +1,551 @@
+# include "relphot.h"
+
+static int Nmax;
+static double *list;
+static double *dlist;
+
+void initMrel (Catalog *catalog, int Ncatalog) {
+
+  int i, j;
+  
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+}  
+
+float getMrel (Catalog *catalog, int meas, int cat) {
+
+  int ave;
+  float value;
+
+  ave = catalog[cat].measure[meas].averef;
+  if (catalog[cat].average[ave].code & STAR_BAD) return (NAN);  
+ 
+  value = catalog[cat].secfilt[PhotNsec*ave+PhotSec].M;
+  return (value);
+}
+
+int setMrel (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, N;
+  float Msys, Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue;
+	// XXX allow REF stars (no Image Entry) to be included in the calculation this
+	// should be optionally set, and should allow for REF stars to be downweighted by
+	// more than their reported errors.  how such info is carried is unclear...
+	if (getImageEntry (m, i) < 0) {
+	  Mcal = Mmos = Mgrid = 0;
+	} else {
+	  Mcal  = getMcal  (m, i);
+	  if (isnan(Mcal)) continue;
+	  Mmos  = getMmos  (m, i);
+	  if (isnan(Mmos)) continue;
+	  Mgrid = getMgrid (m, i);
+	  if (isnan(Mgrid)) continue;
+	}
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < STAR_TOOFEW) { /* too few measurements */
+	catalog[i].average[j].code |= ID_STAR_FEW;
+      } else {
+	catalog[i].average[j].code &= ~ID_STAR_FEW;
+      }	
+
+      liststats (list, dlist, N, &stats);
+
+      catalog[i].secfilt[PhotNsec*j+PhotSec].M  = stats.mean;
+      catalog[i].secfilt[PhotNsec*j+PhotSec].dM = stats.sigma;
+      catalog[i].secfilt[PhotNsec*j+PhotSec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NAN_S_SHORT;
+    }
+  }
+  return (TRUE);
+}
+
+int setMrelOutput (Catalog *catalog, int Ncatalog, int mark) {
+
+  int i, j, k, m, N, Nmax;
+  float Msys, Mcal, Mmos, Mgrid;
+  double *list, *dlist;
+  StatType stats;
+
+  /* Nmeasure is now different, need to reallocate */
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* skip stars already calibrated */
+      if (catalog[i].found[j]) continue;  
+
+      N = 0;
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue;
+	// XXX allow REF stars (no Image Entry) to be included in the calculation this
+	// should be optionally set, and should allow for REF stars to be downweighted by
+	// more than their reported errors.  how such info is carried is unclear...
+	if (getImageEntry (m, i) < 0) {
+	  Mcal = Mmos = Mgrid = 0;
+	} else {
+	  Mcal  = getMcal  (m, i);
+	  if (isnan(Mcal)) continue;
+	  Mmos  = getMmos  (m, i);
+	  if (isnan(Mmos)) continue;
+	  Mgrid = getMgrid (m, i);
+	  if (isnan(Mgrid)) continue;
+	}
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < 1) continue;
+
+      liststats (list, dlist, N, &stats);
+      if (mark) catalog[i].found[j] = TRUE;
+
+      /* use sigma or error in dM for output? */
+      catalog[i].secfilt[PhotNsec*j+PhotSec].M  = stats.mean;
+      catalog[i].secfilt[PhotNsec*j+PhotSec].dM = MAX (stats.error, stats.sigma);
+      catalog[i].secfilt[PhotNsec*j+PhotSec].Xm = (stats.Nmeas > 1) ? 100.0*log10(stats.chisq) : NAN_S_SHORT;
+    }
+  }
+
+  free (list);
+  free (dlist);
+  return (TRUE);
+}
+
+/* set measure.Mcal for all measures except ID_MEAS_NOCAL and ID_IMAGE_NOCAL */
+int setMcalOutput (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m;
+  float Mcal, Mmos, Mgrid;
+
+  MEAS_BAD = ID_MEAS_NOCAL;
+  IMAGE_BAD = ID_IMAGE_NOCAL;
+
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue;
+	Mcal  = getMcal  (m, i);
+	if (isnan(Mcal)) continue;
+	Mmos  = getMmos  (m, i);
+	if (isnan(Mmos)) continue;
+	Mgrid = getMgrid (m, i);
+	if (isnan(Mgrid)) continue;
+	catalog[i].measure[m].Mcal = Mcal + Mmos + Mgrid;
+      }
+    }
+  }
+  return (TRUE);
+}
+
+void clean_stars (Catalog *catalog, int Ncatalog) {
+
+  int i, j, Ndel, Nave, Ntot, mark;
+  float dM, Xm;
+  double Chisq, MaxScatter, MaxChisq;
+  double *xlist, *slist, *dlist;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "marking poor stars\n");
+
+  /* find Xm median -> ChiSq lim must be > median */
+  for (i = Ntot = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+  ALLOCATE (xlist, double, Ntot);
+  ALLOCATE (slist, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+  for (i = Ntot = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;
+      Xm = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (Xm == -1) continue;
+      Chisq = pow (10.0, 0.01*Xm);
+      xlist[Ntot] = Chisq;
+      slist[Ntot] = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      dlist[Ntot] = 1;
+      Ntot ++;
+    }
+  }
+  
+  initstats ("MEAN");
+  liststats (xlist, dlist, Ntot, &stats);
+  MaxChisq = MAX (STAR_CHISQ, 2*stats.median);
+  liststats (slist, dlist, Ntot, &stats);
+  MaxScatter = MAX (STAR_SCATTER, 2*stats.median);
+  fprintf (stderr, "Max Scatter: %f, Max Chisq: %f\n", MaxScatter, MaxChisq);
+
+  Ndel = Nave = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      dM = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      Xm = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      Chisq = pow (10.0, 0.01*Xm);
+      mark = (dM > MaxScatter) || (Xm == NAN_S_SHORT) || (Chisq > MaxChisq);
+      if (mark) {
+	catalog[i].average[j].code |= ID_STAR_POOR;
+	Ndel ++;
+      } else {
+	catalog[i].average[j].code &= ~ID_STAR_POOR;
+      }
+      Nave ++;
+    }
+  }
+  fprintf (stderr, "%d stars marked variable, %d total\n", Ndel, Nave);
+  initstats (STATMODE);
+  free (xlist);
+  free (slist);
+  free (dlist);
+}
+
+void clean_measures (Catalog *catalog, int Ncatalog, int final) {
+
+  int i, j, k, m, N, Ndel, Nave, Nmax, image_bad, TOOFEW;
+  int *ilist;
+  double *tlist, *list, *dlist, Ns;
+  float Msys, Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  if (VERBOSE) fprintf (stderr, "marking poor measures\n");
+  /* Nmeasure is now different, need to reallocate */
+  Nmax = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Nmax = MAX (Nmax, catalog[i].average[j].Nm);
+    }
+  }
+  ALLOCATE (list, double, MAX (1, Nmax));
+  ALLOCATE (dlist, double, MAX (1, Nmax));
+  ALLOCATE (ilist, int, Nmax);
+  ALLOCATE (tlist, double, Nmax);
+  
+  /* it makes no sense to mark 3-sigma outliers with <5 measurements */
+  TOOFEW = MAX (5, STAR_TOOFEW);
+
+  Ns = 3;
+  Ndel = Nave = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* skip bad stars to prevent them from becoming good (on inner sample) */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      /* on final processing, skip stars already measured */
+      if (final && catalog[i].found[j]) continue;  
+
+      /* accumulate list of valid measurements */
+      m = catalog[i].average[j].offset;
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	/* if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue; */
+	Mcal  = getMcal  (m, i);
+	if (isnan(Mcal)) continue;
+	Mmos  = getMmos  (m, i);
+	if (isnan(Mmos)) continue;
+	Mgrid = getMgrid (m, i);
+	if (isnan(Mgrid)) continue;
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	N++;
+      }
+      if (N < TOOFEW) continue;
+
+      /* 3-sigma clip based on stats of inner 50% */
+      initstats ("INNER_MEAN");
+      liststats (list, dlist, N, &stats);
+      stats.sigma = MAX (MIN_ERROR, stats.sigma); /* if measurements agree too well, sigma -> 0.0 */
+      for (k = m = 0; k < N; k++) {
+	if (fabs (list[k] - stats.median) < Ns*stats.sigma) {
+	  list[m] = list[k];
+	  m++;
+	}
+      }
+      initstats ("MEAN");
+      liststats (list, dlist, m, &stats);
+      stats.sigma = MAX (MIN_ERROR, stats.sigma);
+
+      /* apply to list of all relevant measurements, including IMAGE_POOR & IMAGE_FEW */
+      image_bad = IMAGE_BAD;
+      IMAGE_BAD = ID_IMAGE_NOCAL;
+      m = catalog[i].average[j].offset;
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	/* if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue; */
+	Mcal  = getMcal  (m, i);
+	if (isnan(Mcal)) continue;
+	Mmos  = getMmos  (m, i);
+	if (isnan(Mmos)) continue;
+	Mgrid = getMgrid (m, i);
+	if (isnan(Mgrid)) continue;
+
+	Msys = PhotSys (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]);
+	list[N] = Msys - Mcal - Mmos - Mgrid;
+	dlist[N] = MAX (catalog[i].measure[m].dM, MIN_ERROR);
+	ilist[N] = m;
+	N++;
+	Nave ++;
+      }
+      if (N < TOOFEW) continue;
+
+      /* mark bad measures */
+      for (k = 0; k < N; k++) {
+	if (fabs (list[k] - stats.median) > Ns*stats.sigma) {
+	  catalog[i].measure[ilist[k]].dbFlags |= ID_MEAS_POOR;
+	  Ndel ++;
+	}
+      }
+      IMAGE_BAD = image_bad;
+    }
+  }
+  initstats (STATMODE);
+  if (VERBOSE) fprintf (stderr, "%d measures marked poor, %d total\n", Ndel, Nave);
+  free (ilist);
+  free (tlist);
+}
+
+StatType statsStarN (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, n, N, Ntot;
+  double *list, *dlist;
+  float Mcal, Mmos, Mgrid;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      N = 0;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	Mcal = getMcal  (m, i);
+	if (isnan(Mcal)) continue;
+	Mmos = getMmos  (m, i);
+	if (isnan(Mmos)) continue;
+	Mgrid = getMgrid (m, i);
+	if (isnan(Mgrid)) continue;
+	N++;
+      }
+      
+      list[n] = N;
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsStarX (Catalog *catalog, int Ncatalog) {
+
+  int i, j, n, Ntot, Xm;
+  double *list, *dlist;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      Xm = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (Xm == NAN_S_SHORT) continue;
+      list[n] = pow (10.0, 0.01*Xm);
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+StatType statsStarS (Catalog *catalog, int Ncatalog) {
+
+  int i, j, n, Ntot;
+  double *list, *dlist;
+  float dM;
+  StatType stats;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    Ntot += catalog[i].Naverage; 
+  }
+
+  ALLOCATE (list, double, Ntot);
+  ALLOCATE (dlist, double, Ntot);
+
+  n = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+
+      dM = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      list[n] = dM;
+      dlist[n] = 1;
+      n++;
+    }
+  }
+
+  liststats (list, dlist, n, &stats);
+  free (list);
+  free (dlist);
+  return (stats);
+}
+
+void plot_stars (Catalog *catalog, int Ncatalog) {
+
+  int i, j, bin;
+  float dMrel;
+  double *xlist, *Mlist;
+  Graphdata graphdata;
+
+# define NBIN 200
+  ALLOCATE (xlist, double, NBIN);
+  ALLOCATE (Mlist, double, NBIN);
+
+  for (i = 0; i < NBIN; i++) xlist[i] = 0.00025*i;
+  bzero (Mlist, NBIN*sizeof(double));
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      dMrel = catalog[i].secfilt[PhotNsec*j+PhotSec].dM;
+      bin = dMrel / 0.00025;
+      bin = MAX (0, MIN (NBIN-1, bin));
+      Mlist[bin] += 1.0;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.style = 1;
+  plot_list (&graphdata, xlist, Mlist, NBIN, "dMrel hist", "dMhist.png");
+
+  free (xlist);
+  free (Mlist);
+}
+
+void plot_chisq (Catalog *catalog, int Ncatalog) {
+
+  int i, j, N, Ntotal, value;
+  double *xlist, *ylist;
+  Graphdata graphdata;
+
+  Ntotal = 0;
+  for (i = 0; i < Ncatalog; i++) Ntotal += catalog[i].Naverage;
+
+  ALLOCATE (xlist, double, Ntotal);
+  ALLOCATE (ylist, double, Ntotal);
+
+  N = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      if (catalog[i].average[j].code & STAR_BAD) continue;
+      xlist[N] = catalog[i].secfilt[PhotNsec*j+PhotSec].M;
+      value    = catalog[i].secfilt[PhotNsec*j+PhotSec].Xm;
+      if (value == NAN_S_SHORT) continue;
+      ylist[N] = 0.01*value;
+      N++;
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = -3.0;
+  plot_list (&graphdata, xlist, ylist, N, "chisq", NULL);
+  free (xlist);
+  free (ylist);
+}
+
+void plot_star_coords (Catalog *catalog, int Ncatalog) {
+
+  int i, j, N;
+  double *xlist, *ylist;
+  double Xmin, Ymin, Xmax, Ymax;
+  Graphdata graphdata;
+
+  N = 0; 
+  for (i = 0; i < Ncatalog; i++) {
+    N += catalog[i].Naverage;
+  }
+  ALLOCATE (xlist, double, N);
+  ALLOCATE (ylist, double, N);
+
+  N = 0;
+  Xmin = Ymin = +360.0;
+  Xmax = Ymax = -360.0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      xlist[N] = catalog[i].average[j].R;
+      ylist[N] = catalog[i].average[j].D;
+      N++;
+    }
+  }
+  plot_defaults (&graphdata);
+  plot_list (&graphdata, xlist, ylist, N, "coords", NULL);
+
+  free (xlist);
+  free (ylist);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/args.c	(revision 16632)
@@ -0,0 +1,209 @@
+# include "relphot.h"
+void usage (void);
+
+int args (int argc, char **argv) {
+
+  int N;
+  double trange;
+
+  /* define time */
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &TSTART)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      return (FALSE);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_dtime (argv[N], &trange)) { 
+      if (!ohana_str_to_time (argv[N], &TSTOP)) { 
+	fprintf (stderr, "ERROR: syntax error\n");
+	return (FALSE);
+      }
+    } else {
+      if (trange < 0) {
+	trange = fabs (trange);
+	TSTOP = TSTART;
+	TSTART -= trange;
+      } else {
+	TSTOP = TSTART + trange;
+      }
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+
+  /* specify portion of the sky */
+  UserPatch.Rmin = 0;
+  UserPatch.Rmax = 360;
+  UserPatch.Dmin = -90;
+  UserPatch.Dmax = +90;
+  UserPatchSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-region"))) {
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Rmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatch.Dmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    UserPatchSelect = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PLOTSTUFF = FALSE;
+  if ((N = get_argument (argc, argv, "-plot"))) {
+    PLOTSTUFF = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  PLOTDELAY = 500000;
+  if ((N = get_argument (argc, argv, "-plotdelay"))) {
+    remove_argument (N, &argc, argv);
+    PLOTDELAY = 1e6*atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (STATMODE, "CHI_INNER_WTMEAN");
+  if ((N = get_argument (argc, argv, "-statmode"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (STATMODE, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  NLOOP = 8;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    NLOOP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  RESET = FALSE;
+  if ((N = get_argument (argc, argv, "-reset"))) {
+    remove_argument (N, &argc, argv);
+    RESET = TRUE;
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  SHOW_PARAMS = FALSE;
+  if ((N = get_argument (argc, argv, "-params"))) {
+    remove_argument (N, &argc, argv);
+    SHOW_PARAMS = TRUE;
+  }
+
+  PlotMmin = 10.0; PlotMmax = 20.0; PlotdMmin = -1.0; PlotdMmax = 1.0;
+  if ((N = get_argument (argc, argv, "-plrange"))) {
+    remove_argument (N, &argc, argv);
+    PlotMmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotMmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotdMmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    PlotdMmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* group images by mosaic, find Mmos */
+  MOSAICNAME[0] = 0;
+  if ((N = get_argument (argc, argv, "-mosaic"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (MOSAICNAME, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  FREEZE_IMAGES = FALSE;
+  if ((N = get_argument (argc, argv, "-imfreeze"))) {
+    remove_argument (N, &argc, argv);
+    FREEZE_IMAGES = TRUE;
+  }
+
+  USE_GRID = FALSE;
+  if ((N = get_argument (argc, argv, "-grid"))) {
+    remove_argument (N, &argc, argv);
+    USE_GRID = TRUE;
+    if (!MOSAICNAME[0]) {
+      fprintf (stderr, "-grid is only valid with -mosaic\n");
+      exit (2);
+    }
+  }
+
+  MIN_ERROR = 0.001;
+  if ((N = get_argument (argc, argv, "-minerror"))) {
+    remove_argument (N, &argc, argv);
+    MIN_ERROR = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    /* require MIN_ERROR > 0 */
+  }  
+
+  AreaSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-area"))) {
+    remove_argument (N, &argc, argv);
+    AreaXmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaXmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaYmin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaYmax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    AreaSelect = TRUE;
+  }
+
+  ImagSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-instmag"))) {
+    remove_argument (N, &argc, argv);
+    ImagMin = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImagMax = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    ImagSelect = TRUE;
+  }
+
+  DophotSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-dophot"))) {
+    remove_argument (N, &argc, argv);
+    DophotValue = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+    DophotSelect = TRUE;
+  }
+
+  if ( UserPatchSelect && (argc != 2)) usage ();
+  if (!UserPatchSelect && (argc != 3)) usage ();
+
+  return TRUE;
+}
+
+void usage () {
+  fprintf (stderr, "ERROR: USAGE: relphot (region) (photcode)\n");
+  fprintf (stderr, "       or:    relphot (photcode) -region RA RA DEC DEC\n");
+  fprintf (stderr, "  options: \n");
+  fprintf (stderr, "  -time (start) (stop)\n");
+  fprintf (stderr, "  -v\n");
+  fprintf (stderr, "  -plot\n");
+  fprintf (stderr, "  -plotdelay (seconds)\n");
+  fprintf (stderr, "  -statmode (mode)\n");
+  fprintf (stderr, "  -n (nloop)\n");
+  fprintf (stderr, "  -reset\n");
+  fprintf (stderr, "  -update\n");
+  fprintf (stderr, "  -params\n");
+  fprintf (stderr, "  -mosaic (mosaic)\n");
+  fprintf (stderr, "  -imfreeze\n");
+  fprintf (stderr, "  -grid\n");
+  fprintf (stderr, "  -area Xmin Xmax Ymin Ymax\n");
+  fprintf (stderr, "  -instmag min max\n");
+  fprintf (stderr, "  \n");
+  exit (2);
+} 
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/bcatalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/bcatalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/bcatalog.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "relphot.h"
+
+int bcatalog (Catalog *subcatalog, Catalog *catalog) {
+  
+  int i, j, offset, ecode;
+  int NAVERAGE, NMEASURE, Naverage, Nmeasure, Nm;
+  float mag;
+
+  // XXX PhotNsec as a global is a bad idea; either get it from catalog
+  // or get it from:
+  // Nsecfilt = GetPhotcodeNsecfilt ();
+  // assert (catalog[0].Nsecfilt == Nsecfilt);
+
+  /* we are moving only the subset of measurements from catalog[0] to subcatalog[0] */
+  NAVERAGE = 50;
+  NMEASURE = 1000;
+  ALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+  ALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*PhotNsec);
+  ALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+  Nmeasure = Naverage = 0;
+
+  /* exclude stars not in range or with too few measurements */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    // if (catalog[0].average[i].Nm < 2) continue; 
+
+    /* start with all stars good */
+    subcatalog[0].average[Naverage] = catalog[0].average[i];
+    subcatalog[0].average[Naverage].offset = Nmeasure;
+    for (j = 0; j < PhotNsec; j++) {
+      subcatalog[0].secfilt[PhotNsec*Naverage+j] = catalog[0].secfilt[PhotNsec*i+j];
+    }
+
+    if (RESET) {
+      subcatalog[0].secfilt[PhotNsec*Naverage+PhotSec].M  = NAN;
+      subcatalog[0].secfilt[PhotNsec*Naverage+PhotSec].dM = NAN;
+      subcatalog[0].average[Naverage].code &= ~ID_STAR_FEW;
+      subcatalog[0].average[Naverage].code &= ~ID_STAR_POOR;
+    }
+
+    Nm = 0;
+    for (j = 0; j < catalog[0].average[i].Nm; j++) {
+
+      offset = catalog[0].average[i].offset + j;
+
+      /* select measurements by photcode */
+      ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[offset].photcode);
+      if (ecode != photcode[0].code) continue;
+
+      /* select measurements by time */
+      if (TimeSelect) {
+	if (catalog[0].measure[offset].t < TSTART) continue;
+	if (catalog[0].measure[offset].t > TSTOP) continue;
+      }
+
+      /* select measurements by quality */
+      // XXX ignore this criterion for REF measurements?
+      if (DophotSelect && (catalog[0].measure[offset].dophot != DophotValue)) continue;
+
+      /* select measurements by mag limit */
+      mag = PhotCat (&catalog[0].measure[offset]);
+      if (mag > MAG_LIM) continue;
+
+      /* select measurements by measurement error */
+      if ((SIGMA_LIM > 0) && (catalog[0].measure[offset].dM > SIGMA_LIM)) continue;
+
+      /* select measurements by mag limit */
+      if (ImagSelect) {
+	mag = PhotInst (&catalog[0].measure[offset]);
+	if (mag < ImagMin) continue;
+	if (mag > ImagMax) continue;
+      }
+
+      subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_SKIP;
+      subcatalog[0].measure[Nmeasure]        = catalog[0].measure[offset];
+      subcatalog[0].measure[Nmeasure].averef = Naverage;
+      if (RESET) { 
+	subcatalog[0].measure[Nmeasure].Mcal = 0;
+	subcatalog[0].measure[Nmeasure].dbFlags &= 0xff00;
+	subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_POOR;
+	subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_AREA;
+	subcatalog[0].measure[Nmeasure].dbFlags &= ~ID_MEAS_NOCAL;
+      }
+      Nmeasure ++;
+      Nm ++;
+      if (Nmeasure == NMEASURE) {
+	NMEASURE += 1000;
+	REALLOCATE (subcatalog[0].measure, Measure, NMEASURE);
+      }
+    }
+
+    // XXXX test : what checks do I need to make elsewhere to avoid problems here?
+    # if 0
+    if (Nm < 2) { /* enough measurements in band? */
+      Nmeasure -= Nm;
+      continue; 
+    }
+    # endif
+    subcatalog[0].average[Naverage].Nm = Nm;
+    Naverage ++;
+    if (Naverage == NAVERAGE) {
+      NAVERAGE += 50;
+      REALLOCATE (subcatalog[0].average, Average, NAVERAGE);
+      REALLOCATE (subcatalog[0].secfilt, SecFilt, NAVERAGE*PhotNsec);
+    }
+  }
+  REALLOCATE (subcatalog[0].average, Average, MAX (Naverage, 1));
+  REALLOCATE (subcatalog[0].measure, Measure, MAX (Nmeasure, 1));
+  REALLOCATE (subcatalog[0].secfilt, SecFilt, PhotNsec*MAX (Naverage, 1));
+  subcatalog[0].Naverage = Naverage;
+  subcatalog[0].Nmeasure = Nmeasure;
+  subcatalog[0].Nsecfilt = catalog[0].Nsecfilt;
+  subcatalog[0].Nsecf_mem = Naverage * catalog[0].Nsecfilt;
+  assert (PhotNsec == catalog[0].Nsecfilt);
+
+  if (VERBOSE) {
+    fprintf (stderr, "%d: using %d stars (%d measures) for catalog\n", i, 
+	     subcatalog[0].Naverage, subcatalog[0].Nmeasure);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/global_stats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/global_stats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/global_stats.c	(revision 16632)
@@ -0,0 +1,44 @@
+# include "relphot.h"
+
+void global_stats (Catalog *catalog, int Ncatalog) {
+
+  StatType stN, stX, stS, imN, imX, imM, imD, msM, msX, msN, msD;
+
+  initstats ("MEAN");
+
+  stN = statsStarN (catalog, Ncatalog);
+  stX = statsStarX (catalog, Ncatalog);
+  stS = statsStarS (catalog, Ncatalog);
+
+  imN = statsImageN (catalog);
+  imX = statsImageX (catalog);
+  imM = statsImageM (catalog);
+  imD = statsImagedM (catalog);
+
+  msN = statsMosaicN (catalog);
+  msM = statsMosaicM (catalog);
+  msD = statsMosaicdM (catalog);
+  msX = statsMosaicX (catalog);
+
+  fprintf (stderr, "STATS            median     mean    sigma      min      max   Nmeas\n");
+  fprintf (stderr, "meas / image:   %7.0f  %7.0f  %7.0f  %7.0f  %7.0f  %6d\n",   imN.median, imN.mean, imN.sigma, imN.min, imN.max, imN.Nmeas);
+  fprintf (stderr, "meas / mosaic:  %7.0f  %7.0f  %7.0f  %7.0f  %7.0f  %6d\n",   msN.median, msN.mean, msN.sigma, msN.min, msN.max, msN.Nmeas);
+  fprintf (stderr, "meas / star:    %7.0f  %7.1f  %7.1f  %7.0f  %7.0f  %6d\n",   stN.median, stN.mean, stN.sigma, stN.min, stN.max, stN.Nmeas);
+
+  fprintf (stderr, "chisq image:    %7.1f  %7.1f  %7.1f  %7.1f  %7.1f  %6d\n",   imX.median, imX.mean, imX.sigma, imX.min, imX.max, imX.Nmeas);
+  fprintf (stderr, "chisq mosaic:   %7.1f  %7.1f  %7.1f  %7.1f  %7.1f  %6d\n",   msX.median, msX.mean, msX.sigma, msX.min, msX.max, msX.Nmeas);
+  fprintf (stderr, "chisq star:     %7.1f  %7.1f  %7.1f  %7.1f  %7.1f  %6d\n",   stX.median, stX.mean, stX.sigma, stX.min, stX.max, stX.Nmeas);
+
+  fprintf (stderr, "Mcal image:     %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   imM.median, imM.mean, imM.sigma, imM.min, imM.max, imM.Nmeas);
+  fprintf (stderr, "dMcal image:    %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   imD.median, imD.mean, imD.sigma, imD.min, imD.max, imD.Nmeas);
+
+  fprintf (stderr, "Mcal mosaic:    %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   msM.median, msM.mean, msM.sigma, msM.min, msM.max, msM.Nmeas);
+  fprintf (stderr, "dMcal mosaic:   %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n",   msD.median, msD.mean, msD.sigma, msD.min, msD.max, msD.Nmeas);
+
+  fprintf (stderr, "dMrel star:     %7.4f  %7.4f  %7.4f  %7.4f  %7.4f  %6d\n\n", stS.median, stS.mean, stS.sigma, stS.min, stS.max, stS.Nmeas);
+
+  initstats (STATMODE);
+
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/initialize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/initialize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/initialize.c	(revision 16632)
@@ -0,0 +1,53 @@
+# include "relphot.h"
+
+void initialize (int argc, char **argv) {
+
+  int N;
+
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  N = UserPatchSelect ? 1 : 2;
+  if ((photcode = GetPhotcodebyName (argv[N])) == NULL) {
+    fprintf (stderr, "ERROR: photcode %s not found in photcode table\n", argv[N]);
+    exit (1);
+  }
+  if (photcode[0].type != PHOT_SEC) {
+    fprintf (stderr, "photcode %s is not a primary or secondary filter\n", argv[N]);
+    exit (1);
+  }
+
+  PhotNsec = GetPhotcodeNsecfilt ();
+  PhotSec = GetPhotcodeNsec (photcode[0].code);
+
+  initstats (STATMODE);
+
+  IMAGE_BAD = ID_IMAGE_POOR | ID_IMAGE_FEW | ID_IMAGE_SKIP;
+  STAR_BAD  = ID_STAR_POOR | ID_STAR_FEW;
+  MEAS_BAD  = ID_MEAS_NOCAL | ID_MEAS_POOR | ID_MEAS_SKIP | ID_MEAS_AREA;
+
+  if (SHOW_PARAMS) {
+    fprintf (stderr, "current parameter settings:\n");
+    if (TimeSelect) {
+      fprintf (stderr, "TimeSelect: TRUE (%s - %s)\n", ohana_sec_to_date (TSTART), ohana_sec_to_date (TSTOP));
+    } else {
+      fprintf (stderr, "TimeSelect: FALSE\n");
+    }
+    fprintf (stderr, "VERBOSE: %d, PLOTSTUFF: %d\n", VERBOSE, PLOTSTUFF);
+    fprintf (stderr, "GRID_X: %d, GRID_Y: %d, BINNING: %d == Nmx: %d, Nmy: %d\n", 
+	     RELPHOT_GRID_X, 
+	     RELPHOT_GRID_Y, 
+	     RELPHOT_GRID_BINNING, 
+	     (int)(RELPHOT_GRID_X/RELPHOT_GRID_BINNING), (int)(RELPHOT_GRID_Y/RELPHOT_GRID_BINNING));
+
+    fprintf (stderr, "MAG_LIM                %lf\n", MAG_LIM);
+    fprintf (stderr, "STAR_SCATTER           %lf\n", STAR_SCATTER);
+    fprintf (stderr, "IMAGE_SCATTER          %lf\n", IMAGE_SCATTER);
+    fprintf (stderr, "IMAGE_OFFSET           %lf\n", IMAGE_OFFSET);
+    fprintf (stderr, "IMAGE_CATALOG          %s\n",  ImageCat);
+    fprintf (stderr, "GSCFILE                %s\n",  GSCFILE);
+    fprintf (stderr, "CATDIR                 %s\n",  CATDIR);
+    exit (0);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/liststats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/liststats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/liststats.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include "relphot.h"
+
+enum {M_MEAN, M_MEDIAN, M_WT_MEAN, M_INNER_MEAN, 
+      M_INNER_WTMEAN, M_CHI_INNER_MEAN, M_CHI_INNER_WTMEAN};
+
+static int statmode;
+
+void initstats (char *mode) {
+
+  statmode = -1;
+  if (!strcmp (mode, "MEAN")) statmode = M_MEAN;
+  if (!strcmp (mode, "MEDIAN")) statmode = M_MEDIAN;
+  if (!strcmp (mode, "WT_MEAN")) statmode = M_WT_MEAN;
+  if (!strcmp (mode, "INNER_MEAN")) statmode = M_INNER_MEAN;
+  if (!strcmp (mode, "INNER_WTMEAN")) statmode = M_INNER_WTMEAN;
+  if (!strcmp (mode, "CHI_INNER_MEAN")) statmode = M_CHI_INNER_MEAN;
+  if (!strcmp (mode, "CHI_INNER_WTMEAN")) statmode = M_CHI_INNER_WTMEAN;
+
+  if (statmode == -1) {
+    fprintf (stderr, "ERROR: invalid stats mode: %s\n", mode);
+    exit (1);
+  }
+}
+
+int liststats (double *value, double *dvalue, int N, StatType *stats) {
+  
+  int i, ks, ke, Nm;
+  double Mo, dMo, M, dM, X2, dS, *chi;
+
+  ke = ks = dMo = 0;
+
+  stats[0].Nmeas = N;
+  stats[0].mean  = 0;
+  stats[0].sigma = 0;
+  stats[0].error = 0;
+  stats[0].chisq = 0;
+  if (N < 1) return (FALSE);
+
+  dsortpair (value, dvalue, N);
+  stats[0].median = value[(int)(0.5*N)];
+  stats[0].min    = value[0];
+  stats[0].max    = value[N-1];
+
+  switch (statmode) {
+  case M_MEDIAN:
+    ks = 0;
+    ke = N;
+    Mo = stats[0].median;
+    Nm = N;
+    goto chisq;
+    break;
+  case M_MEAN:
+  case M_WT_MEAN:
+    ks = 0;
+    ke = N;
+    break;
+  case M_INNER_MEAN:
+  case M_INNER_WTMEAN:
+  case M_CHI_INNER_MEAN:
+  case M_CHI_INNER_WTMEAN:
+    ks = 0.25*N + 0.50;
+    ke = 0.75*N + 0.25;
+    if (N <= 3) {
+      ks = 0;
+      ke = N;
+    }
+    break;
+  }    
+
+  if ((statmode == M_CHI_INNER_MEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    ALLOCATE (chi, double, N);
+    for (i = 0; i < N; i++) {
+      chi[i] = (value[i] - stats[0].median) / dvalue[i];
+    }
+    dsortthree (chi, value, dvalue, N);
+    free (chi);
+  }
+
+  /* calculating the per-star offset based on the weighted average */
+  M = dM = Nm = 0;
+  if ((statmode == M_WT_MEAN) || (statmode == M_INNER_WTMEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    for (i = ks; i < ke; i++) {
+      M   += value[i] / SQ (dvalue[i]);
+      dM  += 1.0 / SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / dM;
+    dMo = sqrt (1.0 / dM);
+  } else {
+    for (i = ks; i < ke; i++) {
+      M   += value[i];
+      dM  += SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / (double) Nm;
+    dMo = sqrt (dM / (double) Nm);
+  }
+
+ chisq:
+  /* find sigma and chisq */
+  X2 = dS = 0;
+  for (i = ks; i < ke; i++) {
+    M  = SQ (value[i] - Mo);
+    dM = SQ (dvalue[i]);
+    X2 += M / dM;
+    dS += M;
+  }
+  X2 = X2 / Nm;
+  dS = sqrt (dS / Nm);
+
+  stats[0].mean  = Mo;
+  stats[0].Nmeas = Nm;
+  stats[0].chisq = X2;
+  stats[0].sigma = dS;
+  stats[0].error = dMo;
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/load_catalogs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/load_catalogs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/load_catalogs.c	(revision 16632)
@@ -0,0 +1,52 @@
+# include "relphot.h"
+
+Catalog *load_catalogs (SkyList *skylist, int *Ncatalog) {
+
+  int i, Nstar;
+  Catalog *catalog, tcatalog;
+
+  if (VERBOSE) fprintf (stderr, "loading catalog data\n");
+
+  ALLOCATE (catalog, Catalog, skylist[0].Nregions);
+
+  // load data from each region file, only use bright stars
+  for (i = 0; i < skylist[0].Nregions; i++) {
+
+    // set up the basic catalog info
+    tcatalog.filename = skylist[0].filename[i];
+    tcatalog.catformat = dvo_catalog_catformat (CATFORMAT);    // set the default catformat from config data
+    tcatalog.catmode   = dvo_catalog_catmode (CATMODE);        // set the default catmode from config data
+    tcatalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_SECF;    // don't need to load all data at this point
+    tcatalog.Nsecfilt  = GetPhotcodeNsecfilt ();               // set the desired number in case we need to create the catalog
+
+    if (!dvo_catalog_open (&tcatalog, skylist[0].regions[i], VERBOSE, "r")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", tcatalog.filename);
+      exit (1);
+    }
+    if (VERBOSE && !tcatalog.Naves_disk) fprintf (stderr, "no data in %s, skipping\n", tcatalog.filename);
+
+    // select only the brighter stars
+    bcatalog (&catalog[i], &tcatalog);
+    dvo_catalog_unlock (&tcatalog);
+    dvo_catalog_free (&tcatalog);
+  }
+
+  // XXX keep this test?
+  Nstar = 0;
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    Nstar += catalog[i].Naverage;
+  }
+  if (Nstar < 2) { 
+    fprintf (stderr, "warning: insufficient stars %d\n", Nstar);
+  }
+
+  // XXX consider only returning the populated catalogs
+  *Ncatalog = skylist[0].Nregions;
+  return (catalog);
+}
+
+/* this function loads all relevant catalog files for the first pass.  it currently loads the data
+   read only (SOFT lock) since it assumes the image table has been locked. if we go to the new
+   addstar locking paradigm, in which the images and catalogs are updated independently, then we may
+   need to use an XCLD lock here.  
+*/
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/load_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/load_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/load_images.c	(revision 16632)
@@ -0,0 +1,54 @@
+# include "relphot.h"
+
+SkyList *load_images (FITS_DB *db, char *regionName, SkyRegion *region, int RegionSelect) {
+
+  Image     *image, *subset;
+  int        Nimage, Nsubset, Nchar;
+  int       *LineNumber;
+
+  SkyTable *sky = NULL;
+  SkyList *skylist = NULL;
+
+  // load the current sky table (layout of all SkyRegions) 
+  sky = SkyTableLoadOptimal (CATDIR, SKY_TABLE, GSCFILE, SKY_DEPTH, VERBOSE);
+  SkyTableSetFilenames (sky, CATDIR, "cpt");
+  
+  // determine the populated SkyRegions overlapping the requested area
+  if (RegionSelect) {
+    skylist = SkyListByPatch (sky, -1, region);
+  } else {
+    Nchar = strlen(regionName);
+    if (!strcmp (&regionName[Nchar-4], ".cpt")) regionName[Nchar-4] = 0;
+    skylist = SkyListByName (sky, regionName);
+  }
+
+  // convert database table to internal structure
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  // select the images which overlap the selected sky regions
+  subset = select_images (skylist, image, Nimage, &LineNumber, &Nsubset);
+
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, LineNumber, Nsubset);
+
+  initImages (subset, Nsubset);
+  initMosaics (subset, Nsubset);
+  
+  return (skylist);
+}
+
+int reload_images (FITS_DB *db) {
+
+  Image     *image;
+  int        Nimage, Nx, i;
+  VTable    *vtable;
+
+  image = getimages (&Nimage);
+
+  vtable = &db[0].vtable;
+
+  gfits_scan (vtable[0].header, "NAXIS1", "%d", 1, &Nx);
+  for (i = 0; i < Nimage; i++) {
+    memcpy (vtable[0].buffer[i], &image[i], Nx);
+  }
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/plot_scatter.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/plot_scatter.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/plot_scatter.c	(revision 16632)
@@ -0,0 +1,60 @@
+# include "relphot.h"
+   
+void plot_scatter (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, N, Ntot;
+  float Mrel, Mcal, Mmos, Mgrid;
+  double *xlist, *ylist, *ilist;
+  Graphdata graphdata;
+
+  Ntot = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      Ntot += catalog[i].average[j].Nm;
+    }
+  }
+  ALLOCATE (xlist, double, Ntot);
+  ALLOCATE (ylist, double, Ntot);
+  ALLOCATE (ilist, double, Ntot);
+
+  N = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+
+      /* calculate the average value for a single star */
+      if (catalog[i].average[j].code & STAR_BAD) continue;  
+      m = catalog[i].average[j].offset;
+
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+	if (catalog[i].measure[m].dbFlags & MEAS_BAD) continue;
+	Mcal = getMcal  (m, i);
+	if (isnan(Mcal)) continue;
+	Mmos = getMmos  (m, i);
+	if (isnan(Mmos)) continue;
+	Mgrid = getMgrid (m, i);
+	if (isnan(Mgrid)) continue;
+
+	Mrel = catalog[i].secfilt[PhotNsec*j+PhotSec].M;
+	xlist[N] = Mrel;
+	ylist[N] = PhotSys  (&catalog[i].measure[m], &catalog[i].average[j], &catalog[i].secfilt[j*PhotNsec]) - Mcal - Mmos - Mgrid - Mrel;
+	ilist[N] = PhotInst (&catalog[i].measure[m]);
+	N++;
+      }
+    }
+  }
+
+  plot_defaults (&graphdata);
+  graphdata.xmin = PlotMmin;
+  graphdata.xmax = PlotMmax;
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, xlist, ylist, N, "mag vs dmag", "Mag.png");
+
+  plot_defaults (&graphdata);
+  graphdata.ymin = PlotdMmin;
+  graphdata.ymax = PlotdMmax;
+  plot_list (&graphdata, ilist, ylist, N, "imag vs dmag", "iMag.png");
+  free (xlist);
+  free (ylist);
+  free (ilist);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/plotstuff.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/plotstuff.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/plotstuff.c	(revision 16632)
@@ -0,0 +1,149 @@
+# include "relphot.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+/*
+static union { unsigned char c[4]; float f; } f_undef = { {0xff, 0xff, 0xff, 0xfe} };
+# define fUNDEF (f_undef.f)
+*/
+
+static union { unsigned char c[8]; float d; } d_undef = { {0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00, 0x00} };
+# define dUNDEF (d_undef.d)
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+  char name[100];
+
+  sprintf (name, "gastro [%d]", N);
+
+  // XXX need to allow for KapaOpenNamed socket instead
+  Xgraph[N] = KapaOpen ("kapa", name);
+
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+
+  if (Xgraph[N] == 0) return;
+
+  KapaBox (Xgraph[N], graphmode);
+  return;
+}
+
+void JpegPlot (Graphdata *graphmode, int N, char *filename) {
+
+  if (Xgraph[N] == 0) return;
+
+  KapaPNG (Xgraph[N], filename);
+  return;
+}
+
+void PSPlot (Graphdata *graphmode, int N, char *filename) {
+
+  if (Xgraph[N] == 0) return;
+
+  KiiPS (Xgraph[N], filename, TRUE, KAPA_PS_NEWPLOT, "default");
+  return;
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  if (Npts < 1) return;
+
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+
+  KapaClearSections (Xgraph[N]);
+
+  KapaPrepPlot (Xgraph[N], Npts, graphmode);
+  return;
+}
+
+void PlotLabel (char *string, int N) {
+
+  if (Xgraph[N] == 0) return;
+
+  KapaSendLabel (Xgraph[N], string, 2);
+}
+
+void PlotVector (int Npts, double *vect, int mode, int N, char *type) {
+
+  float *values;
+  int i;
+
+  if (Npts < 1) return;
+
+  ALLOCATE (values, float, Npts);
+  for (i = 0; i < Npts; i++) {
+    values[i] = vect[i];
+  }
+
+  KapaPlotVector (Xgraph[N], Npts, values, type);
+  free (values);
+  return;
+}
+
+void plot_list (Graphdata *graphdata, double *xlist, double *ylist, int N, char *label, char *file) {
+
+  int i;
+  StatType stats;
+  
+  stats.min = stats.max = xlist[0];
+  for (i = 0; i < N; i++) {
+    stats.min = MIN (stats.min, xlist[i]);
+    stats.max = MAX (stats.max, xlist[i]);
+  }
+  if (graphdata[0].xmin == dUNDEF) graphdata[0].xmin = 1.05*stats.min - 0.05*stats.max;
+  if (graphdata[0].xmax == dUNDEF) graphdata[0].xmax = 1.05*stats.max - 0.05*stats.min;
+
+  stats.min = stats.max = ylist[0];
+  for (i = 0; i < N; i++) {
+    stats.min = MIN (stats.min, ylist[i]);
+    stats.max = MAX (stats.max, ylist[i]);
+  }
+  if (graphdata[0].ymin == dUNDEF) graphdata[0].ymin = 1.05*stats.min - 0.05*stats.max;
+  if (graphdata[0].ymax == dUNDEF) graphdata[0].ymax = 1.05*stats.max - 0.05*stats.min;
+
+  PrepPlotting (N, graphdata, 0);
+  PlotVector (N, xlist, 0, 0, "x");
+  PlotVector (N, ylist, 1, 0, "y");
+  if (label != NULL) PlotLabel (label, 0);
+  DonePlotting (graphdata, 0);
+
+  if ((file != NULL) && SAVEPLOT) JpegPlot (graphdata, 0, file);
+  if (PLOTDELAY > 500000) {
+    fprintf (stdout, "press return\n"); 
+    fscanf (stdin, "%*c");
+  } else {
+    usleep (PLOTDELAY);
+  }
+}
+
+void plot_defaults (Graphdata *graphdata) {
+
+  KapaInitGraph (graphdata);
+  graphdata[0].style = 2;
+  graphdata[0].ptype = 2;
+  graphdata[0].ltype = 0;
+  graphdata[0].etype = 0;
+  graphdata[0].color = black;
+  graphdata[0].lweight = 0;
+  graphdata[0].size = 0.5;
+
+  graphdata[0].xmin = dUNDEF;
+  graphdata[0].xmax = dUNDEF;
+  graphdata[0].ymin = dUNDEF;
+  graphdata[0].ymax = dUNDEF;
+   
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/reload_catalogs.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/reload_catalogs.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/reload_catalogs.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "relphot.h"
+
+void reload_catalogs (SkyList *skylist) {
+
+  int i;
+  int status;
+  struct stat filestat;
+  Catalog catalog;
+
+  if (VERBOSE) fprintf (stderr, "re-loading catalog data\n");
+
+  /* load data from each region file */
+  for (i = 0; i < skylist[0].Nregions; i++) {
+    catalog.filename = skylist[0].filename[i];
+
+    // only update existing db tables
+    status = stat (catalog.filename, &filestat);
+    if ((status == -1) && (errno == ENOENT)) {
+      if (VERBOSE) fprintf (stderr, "no file %s, skipping\n", catalog.filename);
+      continue;
+    }
+
+    catalog.catformat = dvo_catalog_catformat (CATFORMAT);    // set the default catformat from config data
+    catalog.catmode   = dvo_catalog_catmode (CATMODE);        // set the default catmode from config data
+    catalog.catflags  = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();               // set the desired number in case we need to create the catalog
+
+    if (!dvo_catalog_open (&catalog, skylist[0].regions[i], VERBOSE, "w")) {
+      fprintf (stderr, "ERROR: failure reading catalog %s\n", catalog.filename);
+      exit (1);
+    }
+    if (VERBOSE && (catalog.Naves_disk == 0)) {
+	fprintf (stderr, "no data in %s, skipping\n", catalog.filename);
+	dvo_catalog_unlock (&catalog);
+	dvo_catalog_free (&catalog);
+	continue;
+    }
+
+    initImageBins  (&catalog, 1);
+    initMosaicBins (&catalog, 1);
+    initGridBins   (&catalog, 1);
+
+    findImages (&catalog, 1);
+    findMosaics (&catalog, 1);
+
+    setMrelFinal (&catalog);
+    dvo_catalog_save (&catalog, VERBOSE); 
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+
+    freeImageBins (1);
+    freeMosaicBins (1);
+    freeGridBins (1);
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/relphot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/relphot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/relphot.c	(revision 16632)
@@ -0,0 +1,120 @@
+# include "relphot.h"
+
+int main (int argc, char **argv) {
+
+  int i, status, Ncatalog;
+  Catalog *catalog;
+  FITS_DB db;
+
+  SkyList *skylist = NULL;
+
+  /* get configuration info, args */
+  initialize (argc, argv);
+
+  /* register database handle with shutdown procedure */
+  set_db (&db);
+  db.mode   = dvo_catalog_catmode (CATMODE);
+  db.format = dvo_catalog_catformat (CATFORMAT);
+
+  /* lock and load the image db table */
+  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
+  if (!status && UPDATE) {
+    fprintf (stderr, "error\n");
+    Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+  }
+  // if the file is missing, db.dbstate will have a value of either:
+  // LCK_EMPTY (if UPDATE) or LCK_MISSING (if !UPDATE)
+  if ((db.dbstate == LCK_EMPTY) || (db.dbstate == LCK_MISSING)) {
+    // XXX get ZERO_POINT from config
+    dvo_image_create (&db, 25.0);
+    // Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+  } else {
+    if (!dvo_image_load (&db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db.filename);
+  }
+
+  /* load regions and images based on specified sky patch */
+  // XXX need to mimic old-style load by passing patch name
+  // XXX need to reduce number of global variables in use.
+  // XXX this is fairly lame: argv[1] is photcode if UserPatchSelect is true
+  skylist = load_images (&db, argv[1], &UserPatch, UserPatchSelect);
+
+  /* unlock, if we can (else, unlocked below) */
+  if (!UPDATE) dvo_image_unlock (&db); 
+
+  /* load catalog data from region files */
+  catalog = load_catalogs (skylist, &Ncatalog);
+  
+  /* add in a loop over the catalogs calling dvo_catalog_chipcoords */
+
+  /* match measurements with images, mosaics */
+  initImageBins  (catalog, Ncatalog);
+  initMosaicBins (catalog, Ncatalog);
+  initGridBins   (catalog, Ncatalog);
+  initMrel (catalog, Ncatalog);
+
+  findImages (catalog, Ncatalog);
+  findMosaics (catalog, Ncatalog);  /* also sets Grid values */
+  SAVEPLOT = FALSE;
+
+  setExclusions (catalog, Ncatalog);
+
+  if (PLOTSTUFF) {
+    plot_star_coords (catalog, Ncatalog);
+    plot_mosaic_fields (catalog);
+  }
+
+  /* determine fit values */
+  for (i = 0; i < NLOOP; i++) {
+    setMrel  (catalog, Ncatalog);
+    setMcal  (catalog, FALSE);
+    setMmos  (catalog, FALSE);
+    setMgrid (catalog);
+    
+    if (PLOTSTUFF) {
+      plot_scatter (catalog, Ncatalog); 
+      plot_grid (catalog); 
+      plot_mosaics ();
+      plot_images ();
+      plot_stars (catalog, Ncatalog);
+      plot_chisq (catalog, Ncatalog);
+    }
+    if ((i == 1) || (i == 5) || (i ==  9) || (i == 13)) clean_measures (catalog, Ncatalog, FALSE); 
+    if ((i == 2) || (i == 6) || (i == 10) || (i == 14)) clean_stars (catalog, Ncatalog);
+    if ((i == 4) || (i == 8) || (i == 12) || (i == 16)) clean_mosaics (catalog, Ncatalog);
+    if ((i == 4) || (i == 8) || (i == 12) || (i == 16)) clean_images ();
+    global_stats (catalog, Ncatalog);
+  }
+
+  SAVEPLOT = TRUE;
+  plot_scatter (catalog, Ncatalog); 
+  plot_grid (catalog); 
+  plot_mosaics ();
+  plot_images ();
+  plot_stars (catalog, Ncatalog);
+  plot_chisq (catalog, Ncatalog);
+
+  if (USE_GRID) dump_grid ();
+  if (!UPDATE) exit (0);
+
+  /* set Mcal & Mmos for bad images */
+  setMcal  (catalog, TRUE);
+  setMmos  (catalog, TRUE);
+
+  /* at this point, we have correct cal coeffs in the image/mosaic structures */
+  for (i = 0; i < Ncatalog; i++) dvo_catalog_free (&catalog[i]);
+  freeImageBins (Ncatalog);
+  freeMosaicBins (Ncatalog);
+  freeGridBins (Ncatalog);
+
+  /* load catalog data from region files, update Mrel include all data */
+  reload_catalogs (skylist);
+  setMcalFinal ();
+
+  reload_images (&db);
+  
+  dvo_image_update (&db, VERBOSE);
+  dvo_image_unlock (&db); 
+
+  exit (0);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/select_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/select_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/select_images.c	(revision 16632)
@@ -0,0 +1,239 @@
+# include "relphot.h"
+
+/* this function returns a list of all images which overlap the given SkyList (set of
+   SkyRegions).  All images in the image catalog are tested once, so there is no check that an
+   image already has been included.  LineNum stores the locations in the Image database of the
+   list of images */
+
+typedef struct {
+  double Xc[5];
+  double Yc[5];
+  double Rc;
+  double Dc;
+} SkyRegionCoords;
+
+Image *select_images (SkyList *skylist, Image *timage, int Ntimage, int **LineNumber, int *Nimage) {
+  
+  Image *image;
+  int i, j, k, m, found, nimage, NIMAGE;
+  int InRange, ecode;
+  double Ri[5], Di[5], Xi[5], Yi[5], dx, dy;
+  int *line_number;
+  Coords tcoords;
+  SkyRegionCoords *skycoords;
+  
+  if (skylist[0].Nregions < 1) {
+    *Nimage = 0;
+    *LineNumber = NULL;
+    if (VERBOSE) fprintf (stderr, "no matching sky regions\n");
+    return NULL;
+  }
+
+  // the comparison is made in the catalog local projection. below we set crval1,2
+  tcoords.crpix1 = tcoords.crpix2 = 0.0;
+  tcoords.cdelt1 = tcoords.cdelt2 = 1.0 / 3600.0;
+  tcoords.pc1_1  = tcoords.pc2_2 = 1.0;
+  tcoords.pc1_2  = tcoords.pc2_1 = 0.0;
+  strcpy (tcoords.ctype, "RA---TAN");
+
+  ALLOCATE (skycoords, SkyRegionCoords, skylist[0].Nregions);
+
+  /* compare with each region file */
+  for (i = 0; i < skylist[0].Nregions; i++) { 
+
+    /* we make positional comparisons in the projection of catalog */
+    skycoords[i].Rc = 0.5*(skylist[0].regions[i][0].Rmax + skylist[0].regions[i][0].Rmin);
+    skycoords[i].Dc = 0.5*(skylist[0].regions[i][0].Dmax + skylist[0].regions[i][0].Dmin);
+    tcoords.crval1 = skycoords[i].Rc;
+    tcoords.crval2 = skycoords[i].Dc;
+
+    /* define catalog corners */
+    RD_to_XY (&skycoords[i].Xc[0], &skycoords[i].Yc[0], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmin, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[1], &skycoords[i].Yc[1], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmin, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[2], &skycoords[i].Yc[2], skylist[0].regions[i][0].Rmax, skylist[0].regions[i][0].Dmax, &tcoords);
+    RD_to_XY (&skycoords[i].Xc[3], &skycoords[i].Yc[3], skylist[0].regions[i][0].Rmin, skylist[0].regions[i][0].Dmax, &tcoords);
+    skycoords[i].Xc[4] = skycoords[i].Xc[0];    
+    skycoords[i].Yc[4] = skycoords[i].Yc[0];    
+
+    dx = 0.02*(skycoords[i].Xc[2] - skycoords[i].Xc[0]);
+    dy = 0.02*(skycoords[i].Yc[2] - skycoords[i].Yc[0]);
+    skycoords[i].Xc[0] -= dx; skycoords[i].Yc[0] -= dy;
+    skycoords[i].Xc[1] += dx; skycoords[i].Yc[1] -= dy;
+    skycoords[i].Xc[2] += dx; skycoords[i].Yc[2] += dy;
+    skycoords[i].Xc[3] -= dx; skycoords[i].Yc[3] += dy;
+    skycoords[i].Xc[4] -= dx; skycoords[i].Yc[4] -= dy;
+  }
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+  BuildChipMatch (timage, Ntimage);
+
+  nimage = 0;
+  NIMAGE = 100;
+  ALLOCATE (image, Image, NIMAGE);
+  ALLOCATE (line_number, int, NIMAGE);
+  
+  // go through the complete list of images, selecting ones which overlap any region
+  for (i = 0; i < Ntimage; i++) {
+      
+    /* exclude images by photcode */
+    ecode = GetPhotcodeEquivCodebyCode (timage[i].photcode);
+    if (ecode != photcode[0].code) continue;
+
+    /* exclude images by time */
+    if (TimeSelect) {
+      if (timage[i].tzero < TSTART) continue;
+      if (timage[i].tzero > TSTOP) continue;
+    }
+    
+    if (!FindMosaicForImage (timage, Ntimage, i)) continue;
+
+    /* define image corners */
+    Xi[0] = 0;            Yi[0] = 0;
+    Xi[1] = timage[i].NX; Yi[1] = 0;
+    Xi[2] = timage[i].NX; Yi[2] = timage[i].NY;
+    Xi[3] = 0;            Yi[3] = timage[i].NY;
+    Xi[4] = 0;            Yi[4] = 0;
+    found = FALSE;
+
+    /* transform to ra,dec */
+    for (j = 0; j < 5; j++) {
+      XY_to_RD (&Ri[j], &Di[j], Xi[j], Yi[j], &timage[i].coords);
+    }
+
+    /* compare with each region file */
+    for (m = 0; (m < skylist[0].Nregions) && !found; m++) { 
+
+      /* we make positional comparisons in the projection of catalog */
+      tcoords.crval1 = skycoords[m].Rc;
+      tcoords.crval2 = skycoords[m].Dc;
+
+      /* transform to ra,dec */
+      InRange = TRUE;
+      for (j = 0; (j < 5) && InRange; j++) {
+	InRange = RD_to_XY (&Xi[j], &Yi[j], Ri[j], Di[j], &tcoords);
+      }
+      if (!InRange) continue;
+
+      /* check if image corner inside catalog */
+      for (j = 0; (j < 4) && !found; j++) {
+	found = corner_check (&Xi[j], &Yi[j], &skycoords[m].Xc[0], &skycoords[m].Yc[0]);
+      }
+      /* check if catalog corner inside image */
+      for (j = 0; (j < 4) && !found; j++) {
+	found = corner_check (&skycoords[m].Xc[j], &skycoords[m].Yc[j], &Xi[0], &Yi[0]);
+      }
+      /* check if edges cross */
+      for (j = 0; (j < 4) && !found; j++) {
+	for (k = 0; (k < 4) && !found; k++) {
+	  found = edge_check (&Xi[j], &Yi[j], &skycoords[m].Xc[k], &skycoords[m].Yc[k]);
+	}
+      }
+      if (!found) continue;
+
+      image[nimage] = timage[i]; 
+      /* always allow 'few' images to succeed, if possible */
+      if (image[nimage].code & ID_IMAGE_FEW) { 
+	image[nimage].code &= ~(ID_IMAGE_FEW | ID_IMAGE_POOR);
+      }
+      if (RESET) {
+	assignMcal (&image[nimage], (double *) NULL, -1);
+	image[nimage].dMcal = NAN;
+	image[nimage].code &= ~ID_IMAGE_POOR;
+      }
+      line_number[nimage] = i;
+      nimage ++;
+      if (nimage == NIMAGE) {
+	NIMAGE += 100;
+	REALLOCATE (image, Image, NIMAGE);
+	REALLOCATE (line_number, int, NIMAGE);
+      }
+    }
+  }
+      
+  if (VERBOSE) fprintf (stderr, "found %d images\n", nimage);
+
+  REALLOCATE (image, Image, MAX (nimage, 1));
+  REALLOCATE (line_number, int, MAX (nimage, 1));
+  free (skycoords);
+
+  *Nimage  = nimage;
+  *LineNumber = line_number;
+  return (image);
+}
+
+/* check if line between points 0 and 1 of x1
+   crosses line between points 0 and 1 of x2 */
+int edge_check (double *x1, double *y1, double *x2, double *y2) {
+
+  double theta1, theta2;
+  double Theta1, Theta2;
+
+  theta1 = opening_angle (x1[0], y1[0], x2[0], y2[0], x1[1], y1[1]); 
+  theta2 = opening_angle (x1[0], y1[0], x2[0], y2[0], x2[1], y2[1]); 
+
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  Theta1 = theta1;
+  Theta2 = theta2;
+  theta1 = opening_angle (x2[0], y2[0], x1[1], y1[1], x2[1], y2[1]); 
+  theta2 = opening_angle (x2[0], y2[0], x1[1], y1[1], x1[0], y1[0]); 
+  
+ 
+  if (theta1*theta2 < 0.0) {
+    return (FALSE);
+  }
+
+  if (fabs(theta1) < fabs(theta2)) {
+    return (FALSE);
+  }
+
+  return (TRUE);
+
+}
+
+/* check if point x1,y1 is in box formed by x2[0-4] */
+int corner_check (double *x1, double *y1, double *x2, double *y2) {
+
+  int i;
+  double theta;
+
+  theta = 0;
+
+  for (i = 0; i < 4; i++) {
+    theta += opening_angle (x2[i], y2[i], x1[0], y1[0], x2[i+1], y2[i+1]); 
+  }
+  if (fabs(theta) > 6) {
+    return (TRUE);
+  } else {
+    return (FALSE);
+  }
+}
+
+/* returns the opening angle between the three points (2 is in middle) 
+   in range -pi to pi */
+
+double opening_angle (double x1, double y1, double x2, double y2, double x3, double y3) {
+
+  double dx1, dy1, dx2, dy2, ct, st, theta;
+
+  dx1 = x1 - x2;
+  dy1 = y1 - y2;
+  
+  dx2 = x3 - x2;
+  dy2 = y3 - y2;
+  
+  ct = (dx1*dx2 + dy1*dy2);
+  st = (dx1*dy2 - dx2*dy1);
+
+  theta = atan2 (st, ct);
+
+  return (theta);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/setExclusions.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/setExclusions.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/setExclusions.c	(revision 16632)
@@ -0,0 +1,55 @@
+# include "relphot.h"
+
+int setExclusions (Catalog *catalog, int Ncatalog) {
+
+  int i, j, k, m, Narea, Nnocal, Ngood, ecode;
+  Coords *coords;
+  double r, d, x, y;
+
+  Ngood = Nnocal = Narea = 0;
+  for (i = 0; i < Ncatalog; i++) {
+    for (j = 0; j < catalog[i].Naverage; j++) {
+      m = catalog[i].average[j].offset;
+      for (k = 0; k < catalog[i].average[j].Nm; k++, m++) {
+
+	/* select measurements by photcode */
+	ecode = GetPhotcodeEquivCodebyCode (catalog[i].measure[m].photcode);
+	if (ecode != photcode[0].code) goto mark_nocal;
+	
+	/* select measurements by time */
+	if (TimeSelect) {
+	  if (catalog[i].measure[m].t < TSTART) goto mark_nocal;
+	  if (catalog[i].measure[m].t > TSTOP) goto mark_nocal;
+	}
+
+	/* select measurements by mag limit */
+	if (AreaSelect) {
+	  r = catalog[i].average[j].R + catalog[i].measure[m].dR / 3600.0;
+	  d = catalog[i].average[j].D + catalog[i].measure[m].dD / 3600.0;
+	  if ((coords = getCoords (m, i)) == NULL) goto markbad;
+	  RD_to_XY (&x, &y, r, d, coords);
+	  if (x < AreaXmin) goto markbad;
+	  if (x > AreaXmax) goto markbad;
+	  if (y < AreaYmin) goto markbad;
+	  if (y > AreaYmax) goto markbad;
+	}
+	Ngood ++;
+	continue;
+
+      markbad:
+	catalog[i].measure[m].dbFlags |= ID_MEAS_AREA;
+	Narea ++;
+	continue;
+	
+      mark_nocal:
+	catalog[i].measure[m].dbFlags |= ID_MEAS_NOCAL;
+	Nnocal ++;
+	continue;
+      }
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "%d measurements marked by area\n", Narea);
+  if (VERBOSE) fprintf (stderr, "%d measurements marked nocal\n", Nnocal);
+  if (VERBOSE) fprintf (stderr, "%d measurements kept for analysis\n", Ngood);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/setMrelFinal.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/setMrelFinal.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/setMrelFinal.c	(revision 16632)
@@ -0,0 +1,150 @@
+# include "relphot.h"
+
+void setMrelFinal (Catalog *catalog) {
+
+  int i, j, m, ecode;
+
+  /* if we reset the catalog, reset all the current measurements */
+  if (RESET) {
+
+    for (i = 0; i < catalog[0].Naverage; i++) {
+      catalog[0].secfilt[PhotNsec*i+PhotSec].M  = NAN;
+      catalog[0].secfilt[PhotNsec*i+PhotSec].dM = NAN;
+      catalog[0].secfilt[PhotNsec*i+PhotSec].Xm = NAN_S_SHORT;
+
+      m = catalog[0].average[i].offset;
+      for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+	
+	/* select measurements by photcode */
+	ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[m].photcode);
+	if (ecode != photcode[0].code) continue;
+	
+	/* select measurements by time */
+	if (TimeSelect) {
+	  if (catalog[0].measure[m].t < TSTART) continue;
+	  if (catalog[0].measure[m].t > TSTOP) continue;
+	}
+	
+	catalog[0].measure[m].Mcal = 0;
+	catalog[0].measure[m].dbFlags &= 0xff00;
+	catalog[0].measure[m].dbFlags &= ~ID_MEAS_POOR;
+	catalog[0].measure[m].dbFlags &= ~ID_MEAS_SKIP;
+	catalog[0].measure[m].dbFlags &= ~ID_MEAS_AREA;
+	catalog[0].measure[m].dbFlags &= ~ID_MEAS_NOCAL;
+      }
+    }
+  }
+
+  setExclusions (catalog, 1);  /* mark by area */
+
+  /* set catalog[0].found[i] = FALSE */
+  ALLOCATE (catalog[0].found, int, MAX (1, catalog[0].Naverage));
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    catalog[0].found[i] = FALSE;
+  }
+
+  for (i = 0; i < 5; i++) {
+    skip_measurements (catalog, i);       /* set ID_MEAS_SKIP for measures to be skipped */
+    setMrelOutput  (catalog, 1, FALSE);   /* set Mrel using all measures not skipped */
+    clean_measures (catalog, 1, TRUE);    /* mark outliers ID_MEAS_POOR */
+    setMrelOutput  (catalog, 1, TRUE);    /* set Mrel using remaining measures */
+  }
+  setMcalOutput (catalog, 1);
+
+  /* clear ID_STAR_POOR, ID_STAR_FEW, ID_MEAS_NOCAL values before writing ??? */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    catalog[0].average[i].code &= ~ID_STAR_FEW;
+    catalog[0].average[i].code &= ~ID_STAR_POOR;
+    m = catalog[0].average[i].offset;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+      catalog[0].measure[m].dbFlags &= ~ID_MEAS_NOCAL;
+    }
+  }
+}
+
+/* ID_MEAS_SKIP marks measurements which were not used to calculate Mrel */
+void skip_measurements (Catalog *catalog, int pass) {
+
+  int i, k, m, ecode, d1, d2;
+  int Ntot, Ntry, Nkeep, Nskip;
+  float mag;
+
+  Ntot = Ntry = Nskip = Nkeep = 0;
+
+  /* allow measures from images marked POOR and FEW */
+  if (pass >= 3) IMAGE_BAD = ID_IMAGE_NOCAL;
+  
+  /* allow measures marked as outliers (POOR) and off image region (AREA) */
+  if (pass >= 3) MEAS_BAD = ID_MEAS_NOCAL | ID_MEAS_SKIP;
+
+  /* mark measures which should be ignored on second pass */
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    Ntot += catalog[0].average[i].Nm;
+    if (catalog[0].found[i]) continue;
+
+    m = catalog[0].average[i].offset;
+    for (k = 0; k < catalog[0].average[i].Nm; k++, m++) {
+      Ntry++;
+
+      /* clear SKIP for all measures at first */
+      catalog[0].measure[m].dbFlags &= ~ID_MEAS_SKIP;
+
+      /** never use these measurements (wrong photcode, bad time range) */
+      /* skipped via NOCAL, don't mark as skipped */
+      ecode = GetPhotcodeEquivCodebyCode (catalog[0].measure[m].photcode);
+      if (ecode != photcode[0].code) continue;
+
+      /* skip measurements by time range */
+      if (TimeSelect) {
+	if (catalog[0].measure[m].t < TSTART) goto skip;
+	if (catalog[0].measure[m].t > TSTOP) goto skip;
+      }
+
+      /* skip measurements with sat. dophot values */
+      if ((pass < 4) && (catalog[0].measure[m].dophot == 10)) goto skip;
+
+      /* skip measurements from BAD images and mosaics */
+      /* do NOT skip measurements without a matching image */
+      if (isnan(getMcal (m, 0))) goto skip;
+      if (isnan(getMmos (m, 0))) goto skip;
+
+      /* skip measurements by inst mag limit */
+      if ((pass < 4) && ImagSelect) {
+	mag = PhotInst (&catalog[0].measure[m]);
+	if (mag < ImagMin) goto skip;
+	if (mag > ImagMax) goto skip;
+      }
+
+      d1 = (catalog[0].measure[m].dophot == 1);
+      d2 = (catalog[0].measure[m].dophot == 2);
+
+      /* skip measurements by measurement error */
+      if ((pass < 2) && !(d1 || d2)) goto skip;
+
+      /* if ((pass < 1) && (catalog[0].measure[m].dM > SIGMA_LIM)) goto skip; */
+      if ((pass < 1) && !d1) goto skip;
+      Nkeep ++;
+
+      continue;
+
+    skip:
+      catalog[0].measure[m].dbFlags |= ID_MEAS_SKIP;
+      Nskip ++;
+    }
+  }
+  if (VERBOSE) fprintf (stderr, "pass %d, Ntot: %d, Ntry: %d, Nskip: %d, Nkeep: %d\n",
+			pass, Ntot, Ntry, Nskip, Nkeep);
+}
+
+/* dophot types:
+
+1 - star
+2 - galaxy
+3 - star
+4 - weak
+5 - edge
+7 - weak
+9 - weak
+10 - sat
+*/
+
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/sort.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/sort.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/sort.c	(revision 16632)
@@ -0,0 +1,182 @@
+# include "relphot.h"
+
+void sortA (double *X, int N) {
+
+  int l,j,ir,i;
+  double tX;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+  }
+}
+
+void sortB (double *X, double *Y, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+  }
+}
+
+void sortC (double *X, double *Y, double *F1, double *F2, int N) {
+
+  int l,j,ir,i;
+  double tX, tY;
+  double t1, t2;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      t1 = F1[l];
+      t2 = F2[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      t1 = F1[ir];
+      F1[ir] = F1[0];
+      t2 = F2[ir];
+      F2[ir] = F2[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	F1[0] = t1;
+	F2[0] = t2;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	F1[i] = F1[j];
+	F2[i] = F2[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    F1[i] = t1;
+    F2[i] = t2;
+  }
+}
+
+void sortD (double *X, double *Y, double *Z, int N) {
+
+  int l,j,ir,i;
+  double tX, tY, tZ;
+  
+  if (N < 2) return;
+
+  l = N >> 1;
+  ir = N - 1;
+  for (;;) {
+    if (l > 0) {
+      l--;
+      tX = X[l];
+      tY = Y[l];
+      tZ = Z[l];
+    }
+    else {
+      tX = X[ir];
+      X[ir] = X[0];
+      tY = Y[ir];
+      Y[ir] = Y[0];
+      tZ = Z[ir];
+      Z[ir] = Z[0];
+      if (--ir == 0) {
+	X[0] = tX;
+	Y[0] = tY;
+	Z[0] = tZ;
+	return;
+      }
+    }
+    i = l;
+    j = (l << 1) + 1;
+    while (j <= ir) {
+      if (j < ir && X[j] < X[j+1]) j++;
+      if (tX < X[j]) {
+	X[i] = X[j];
+	Y[i] = Y[j];
+	Z[i] = Z[j];
+	j += (i=j) + 1;
+      }
+      else j = ir + 1;
+    }
+    X[i] = tX;
+    Y[i] = tY;
+    Z[i] = tZ;
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/src/relphot/src/write_coords.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/relphot/src/write_coords.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/relphot/src/write_coords.c	(revision 16632)
@@ -0,0 +1,29 @@
+# include "relphot.h"
+
+# define CD_COORDS 1
+
+void write_coords (Header *header, Coords *coords) {
+
+  gfits_modify (header, "CTYPE1",   "%s",  1, "RA---TAN");
+  gfits_modify (header, "CTYPE2",   "%s",  1, "DEC--TAN");
+
+  gfits_modify (header, "CRVAL1",   "%lf", 1, coords[0].crval1);
+  gfits_modify (header, "CRVAL2",   "%lf", 1, coords[0].crval2);  
+
+  gfits_modify (header, "CRPIX1",   "%lf", 1, coords[0].crpix1);
+  gfits_modify (header, "CRPIX2",   "%lf", 1, coords[0].crpix2);
+
+# if (CD_COORDS)  
+  gfits_modify (header, "CD1_1",    "%le", 1, coords[0].pc1_1 * coords[0].cdelt1);
+  gfits_modify (header, "CD2_1",    "%le", 1, coords[0].pc2_1 * coords[0].cdelt1);
+  gfits_modify (header, "CD1_2",    "%le", 1, coords[0].pc1_2 * coords[0].cdelt2);
+  gfits_modify (header, "CD2_2",    "%le", 1, coords[0].pc2_2 * coords[0].cdelt2);
+# else
+  gfits_modify (header, "CDELT1",   "%le", 1, coords[0].cdelt1); 
+  gfits_modify (header, "CDELT2",   "%le", 1, coords[0].cdelt2);
+  gfits_modify (header, "PC001001", "%le", 1, coords[0].pc1_1);
+  gfits_modify (header, "PC001002", "%le", 1, coords[0].pc1_2);
+  gfits_modify (header, "PC002001", "%le", 1, coords[0].pc2_1);
+  gfits_modify (header, "PC002002", "%le", 1, coords[0].pc2_2);
+# endif
+}
Index: /branches/eam_branch_20080223/Ohana/src/shell/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/Makefile	(revision 16632)
@@ -0,0 +1,42 @@
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/shell
+
+shell:
+
+default: install
+
+DADS = \
+dads.cleanup
+
+GENERAL = \
+block checkdisks dumptape \
+fits2jpeg gopsfphot gosexphot \
+setpath scattercorrection \
+vncstart vnccheck gpc.cell.zoom
+
+IMSTATS = \
+irsex sexstats
+
+MKDETREND = \
+detstats rm.elixir
+
+REALTIME = \
+el_plots elixir.fork elixir.launch \
+getfocus getseeing gettemps mkjpeg
+
+SKYPROBE = \
+sp_command sp_phot \
+sp_plots sp_sexphot
+
+CODE = $(DADS) $(GENERAL) $(IMSTATS) $(MKDETREND) $(POSTRUN) $(PTOLEMY) $(REALTIME) $(SKYPROBE)
+
+install:
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	for file in $(CODE); do \
+	(chmod +x src/$$file && cd $(DESTBIN) && rm -f $$file && ln -s $(HOME)/src/$$file .); \
+	done
+
+# utilities #################################################
+clean:	
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
Index: /branches/eam_branch_20080223/Ohana/src/shell/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,10 @@
+
+- shell 1.2
+  * fixed to work with mana 1.0 changes (only one cmd line input file)
+  * replace addspphot with addstar -skyprobe
+
+shell-1-1:
+  - changed sp_phot to use unified addstar, not addspphot
+
+shell-1-0:
+  - initial release
Index: /branches/eam_branch_20080223/Ohana/src/shell/doc/flips.notes
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/doc/flips.notes	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/doc/flips.notes	(revision 16632)
@@ -0,0 +1,51 @@
+
+Some of the Elixir scripts call Flips programs.  Here is a list of the
+programs in Flips being used by Elixir:
+
+fr.defringe   : flipsrun (imcombred)
+fr.gtfringe   : flipsrun (imstat)
+defringe      : flipsrun (imcombred)
+doflips       : flatccd
+doflips       : darkccd
+flatten.flips : redccd 
+fr.mkrough    : flipsrun (imcombred)
+fr.smooth     : flipsrun (imfilter)
+gtfringe      : flipsrun (imstat)
+
+noni: file *
+RCS:            directory
+block:          C shell script text
+checkdisks:     C shell script text
+dads.cleanup:   C shell script text
+dads.remef:     C shell script text  - to be deprecated?
+dads.split:     C shell script text  - to be deprecated
+defringe:       C shell script text  - perl
+detstats:       C shell script text  - (mkdetrend)
+doflips:        C shell script text  - perl/detflips
+dumptape:       C shell script text
+el_plots:       C shell script text
+elixir.fork:    C shell script text
+elixir.launch:  C shell script text
+fits2jpeg:      C shell script text
+flatten.flips:  C shell script text  - perl
+flatten.subaru: C shell script text  - old
+fr.defringe:    C shell script text  - perl
+fr.mkrough:     C shell script text  - perl/detflips
+fr.smooth:      C shell script text  - perl TBD
+getfocus:       C shell script text
+getfringe:      bash shell script    - perl
+getseeing:      C shell script text
+gettemps:       C shell script text
+gopsfphot:      C shell script text
+gosexphot:      C shell script text
+irsex:          C shell script text
+mk.ptlist:      C shell script text
+mkjpeg:         C shell script text
+pt.export:      C shell script text
+rm.elixir:      C shell script text
+setpath:        C shell script text
+sexstats:       C shell script text
+sp_command:     C shell script text
+sp_phot:        C shell script text
+sp_plots:       C shell script text
+sp_sexphot:     C shell script text
Index: /branches/eam_branch_20080223/Ohana/src/shell/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/doc/notes.txt	(revision 16632)
@@ -0,0 +1,113 @@
+block			general
+checkdisks		CFHT specific
+dads.cleanup		
+dads.remef		
+dads.split		
+defringe		N CCDs, CFH12K Coord file
+detrend			Not Used?
+detstats		OK (check mana scripts)
+doflips			OK
+dumptape		
+elixir.fork		
+elixir.grab		
+elixir.report		
+fits2jpeg		
+fixdetrend		
+flatten.flips		OK
+flatten.mana		OK	
+focusstats		
+fr.ckfile		Not Used
+fr.defringe		N CCDs (check mana scripts)
+fr.mkimage		OK
+fr.mkrough		OK
+fr.mkstats		(check scripts)
+fr.smooth		Scale is CCD dependent
+fr.stats		OK
+getfocus		
+getseeing		
+gettemps		
+gopsfphot		
+gosexphot		
+gtfringe		(sh) OK
+imstats			CCD size specific -- should use DETSEC
+merge.lists		OK
+mk2d			Not Used
+mkjpeg			(realtime) N CCD specific
+normalize		OK
+normalize.invert	-
+phot.by.night		
+pt.export		(ptolemy export process)
+rm.elixir		(drop & convert to the exit status method)
+setpath			unused?
+sexstats		OK
+skyprobephot		
+split.mef		OK
+spphot			
+
+-
+
+cfht.names		a
+checkconfig		CFHT specific
+ckastrom		
+ckdetrend		
+ckphotom		
+ckrunid			
+ckvalid			
+clear.rawdir		
+create.imlists		nut used
+create.subset		OK
+dads.detrend		
+dads.jpeg		
+dads.keywords		
+darktime.cfht		CFH12K specific -- these curves must be measured for a new device!
+fixlists		
+fl.split2mef		not used?
+fr.detrend		Nccds from gt_names -- more general encapsulation
+fr.gtstats		Nccds
+fr.medbin		Nccds
+fr.medbin.spline	Nccds
+fr.mklists		OK
+fr.select		
+fr.subset		
+get.standards		
+grab.keywords		
+images.names		
+imclean.cfht		
+imselect		
+imstatqso		
+merge.lists		
+mkdetrend		
+mkfringe		
+mkptolemy.names		
+mktrans			
+mktreport		
+mosaic.merge		
+mosaic.stats		
+pt.run			
+seeingstats		
+validate		
+
+shell scripts that use awk -v (convert to perl):
+defringe
+fr.defringe
+fr.smooth
+gtfringe   (convert from sh anyway)
+
+shell scripts which use CFH12K dependent things:
+
+defringe		N CCDs, CFH12K Coord file
+detstats		(check mana scripts)
+fr.ckfile		Nccds
+fr.defringe		N CCDs (check mana scripts)
+fr.mkimage		(check scripts)
+fr.mkstats		(check scripts)
+fr.smooth		Scale is CCD dependent
+fr.stats		(check scripts)
+imstats			CCD size specific -- should use DETSEC
+normalize		OK
+split.mef		CCD size specific
+
+(watch out for header keywords -- make a complete dictionary)
+
+shell -> perl
+split.mef
Index: /branches/eam_branch_20080223/Ohana/src/shell/doc/programs.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/doc/programs.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/doc/programs.txt	(revision 16632)
@@ -0,0 +1,61 @@
+block			: x
+checkdisks		: x
+ckastro			: x
+dads.cleanup		: x
+dads.remef		: x
+dads.split		: +
+doflips			: x
+dumptape		: x
+elixir.fork		: x
+fits2jpeg		: x
+flatten.flips		: +
+flatten.subaru		: x (fake)
+gettemps		: x
+gopsfphot		: x
+gosexphot		: +
+imstats			: +
+merge.lists		: x
+mk2d			: x
+normalize		: x
+normalize.invert	: x
+phot.by.night		: x
+pt.export		: x
+rm.elixir		: x
+setpath			: x
+sexstats		: x
+detstats		: x
+
+getfocus		: [which chips should be camera-dependent]
+getseeing		: [which chip should be camera-dependent]
+mkjpeg			: [scale and ccd list should be camera-dependend]
+
+mk.ptlist		: - [ccds in list need to be ID, not N - add option to imsearch?]
+el_plots		: - (in script mana/elixir)
+
+skyprobe should have its own minimal config file
+
+skyprobephot		: [cleanup up config reference]
+sp_expose		: x
+split.mef		: x
+spphot			: [abstract RAWDIR, etc?]
+sp_plots		: [abstract plot directory?]
+
+mkfringe stuff:
+
+fr.fitstats		: +
+fr.imstats		: +
+fr.mkimage		: 
+fr.mkrough		: 
+fr.mkstats		: 
+fr.smooth		: 
+fr.stats		: 
+getfringe		: 
+defringe		: - (not very clean; might work)
+fr.defringe		: - (some major issues..)
+
+
+already checked:
+
+mode.imstats
+mode.sextract
+mode.flips
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/block
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/block	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/block	(revision 16632)
@@ -0,0 +1,40 @@
+#!/bin/csh -f
+# wait for the file to exist
+
+set file=""
+set timeout=10;
+while ("$1" != "") 
+ switch ($1)
+  case -t: 
+   shift;
+   if ("$1" == "") goto escape
+   set timeout=$1;
+   breaksw;
+  case -*: 
+   goto escape
+   breaksw;
+  default:
+   if ("$file" != "") goto escape
+   set file=$1;
+   breaksw;
+ endsw
+ shift
+end
+
+if ("$file" == "") goto escape
+
+set i=0
+while ($i < $timeout)
+ if (-r $file) then
+  echo "block success: $i seconds $file"
+  exit 0;
+ endif
+ sleep 1
+ @ i++
+end
+echo "block failure: $i seconds $file";
+exit 1;
+
+escape:
+ echo "USAGE: block file [-t timeout]";
+ exit 2;
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/checkdisks
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/checkdisks	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/checkdisks	(revision 16632)
@@ -0,0 +1,9 @@
+#!/bin/csh -f
+
+set disks="/data/elixir /data/elixir1 /data/elixir2 /data/elixir3 /h/skyprobe /data/ulu /data/hau /data/naupaka /data/mamane /data/naio /data/koa /data/kiawe /data/noni"
+
+foreach f ($disks)
+    set uspace = `sdf -a $f -M`
+    set aspace = `sdf -c $f -M`
+    echo $f $uspace $aspace | awk '{printf "%-20s %8.3f of %8.3f GB\n", $1, $2/1000, $3/1000}'
+end
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/dads.cleanup
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/dads.cleanup	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/dads.cleanup	(revision 16632)
@@ -0,0 +1,17 @@
+#!/bin/csh -f
+
+if ($#argv != 1) then
+ echo "USAGE: dads.remef (outbase)"
+ exit;
+endif
+
+set outdir=$1
+
+rm -f $outdir/*.raw
+rm -f $outdir/*.det
+rm -f $outdir/*.def
+
+# generate binned-by-12 image
+mosmc $outdir/*.fits $outdir.B12.fits 12
+
+echo "SUCCESS"
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/detstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/detstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/detstats	(revision 16632)
@@ -0,0 +1,86 @@
+#!/bin/csh
+
+if ($#argv != 7) then
+ echo "USAGE: detstats (list) (detimage) (type) (medbin) (tenbin) (stats) (imbin)"
+ exit;
+endif
+
+set nline = `wc -l $1 | awk '{print $1}'`
+
+if ($nline == 0) then
+ echo "no files in source list, skipping"
+ echo "ERROR"
+ exit;
+endif
+
+# find the appropriate script file
+set confdir=`gconfig -q CONFDIR`
+set script="$confdir/mana/flips.pro"
+
+# set up temp files
+set temp=`mktemp /tmp/detstats.XXXXXX`
+rm -f $temp
+rm -f $4
+rm -f $5
+rm -f $6
+rm -f $7
+
+# choose appropriate operation
+switch ($3) 
+  case flat:
+  case FLAT:
+    goto doflat;
+    breaksw;
+  case dark:
+  case DARK:
+  case bias:
+  case BIAS:
+    goto dodark;
+    breaksw;
+  default:
+    echo "unknown type $3";
+    echo ERROR;
+    exit;
+endsw
+
+doflat:
+    
+# flatstats (list) (detimage) (medlist) (tenlist) (statlist) 
+cat > $temp << END
+input $script
+flatstats $1 $2 $4 $5 $6 $7
+END
+
+mana --only $temp
+
+rm -f $temp
+
+echo "SUCCESS"
+exit; 
+
+dodark:
+    
+# darkstats (list) (detimage) (medlist) (tenlist) (statlist) 
+cat > $temp << END
+input $script
+darkstats $1 $2 $4 $5 $6 $7
+END
+
+mana --only $temp
+
+rm -f $temp
+
+echo "SUCCESS"
+exit; 
+
+
+# we are performing statistics on the detrended images:
+# input is a list of images for a given ccd, along with the
+# appropriate detrend image
+# 
+# for each image in the list, detrend the image, measure statistics,
+# create a binned-by-10 image, create a median-binned image, write
+# them out.  to be used by the mosaicing step
+#
+# need to create many output files: 1 medbin & 1 jpeg for each entry in list.
+# these need to be merged by a later program...       
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/dumptape
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/dumptape	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/dumptape	(revision 16632)
@@ -0,0 +1,81 @@
+#!/bin/csh
+
+# possible machines:
+# druid /dev/dlt
+
+# set dumpdir=/data/elixir2/eugene/archive/raw
+set dumpdir=.
+set host=`hostname | awk -F. '{print $1}'`
+set tape=""
+
+if ("$host" == "druid") then
+ set tape=/dev/dlt
+endif
+if ("$host" == "hoku") then
+ set tape=/dev/rmt/0mn
+endif
+if ("$host" == "kapu") then
+ set tape=/dev/rmt/0mn
+endif
+
+if ("$tape" == "") then
+ echo "ERROR: must use dumptape on druid, hoku, or kapu"
+ exit 1
+endif
+
+mt -f $tape stat
+
+echo "type 'y' to continue"
+
+set n=$<
+
+if ("$n" == "y") then
+ echo "continuing"
+else
+ echo "stopping"
+ exit 
+endif
+
+cd $dumpdir
+set dname=`date +%m%d%H`
+echo $dname
+
+set temp1=/tmp/dumptape.1.$$
+set temp2=extracted.$host.$dname.list
+set temp3=deleted.$host.$dname.list
+
+rm -f temp1
+
+set i=1
+
+while ($i < 32)
+ echo $i
+ tar xvf $tape >>& $temp1
+ if ($status) goto finish
+ mt -f $tape fsf
+ if ($status) goto finish
+ @ i++
+end
+
+finish:
+
+mt -f $tape rewind
+mt -f $tape offline
+
+mail eugene << END
+ done with tape on $host
+END
+ 
+grep fits $temp1 | awk '{s=index($0,"fits")}{n=substr($0,s-8,7)}{printf "%s.fits\n", n}' | fields INSTRUME | awk '($2=="CFH12K"){print $0}' > $temp2
+grep fits $temp1 | awk '{s=index($0,"fits")}{n=substr($0,s-8,7)}{printf "%s.fits\n", n}' | fields INSTRUME | awk '($2!="CFH12K"){print $0}' > $temp3
+
+foreach f (`awk '{print $1}' $temp3`) 
+ rm -f $f
+end
+
+# foreach f (`awk '{print $1}' $temp2`) 
+#  imsort $f -C config info here on this line
+# end
+
+rm -f $temp1
+
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/el_plots
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/el_plots	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/el_plots	(revision 16632)
@@ -0,0 +1,63 @@
+#!/bin/csh -f
+
+if (($#argv != 1) && ($#argv != 2)) goto usage
+
+setenv PATH /bin:/usr/bin:/usr/bin/X11:/apps/elixir/bin:/usr/local/bin
+
+# check that camera is ok:
+set camera=`gconfig CAMERA.CURRENT`
+set datdir=`gconfig DATDIR`
+if ($camera == "cfh12k") goto valid;
+if ($camera == "cfhtir") goto valid;
+if ($camera == "megacam") goto valid;
+if ($camera == "meganorth") goto valid;
+
+if ("$1" == "init") then
+  echo "current camera $camera, not supported by el_plots"
+endif
+exit 0;
+
+valid:
+# find the appropriate script file
+set confdir=`gconfig CONFDIR`
+set script="$confdir/mana/$camera.plots"
+set xhost=`gconfig XHOST`
+set xdisp=`gconfig XDISP`
+setenv DISPLAY $xdisp
+
+if ("$1" == "init") goto init;
+if ("$1" == "plot") goto plot;
+if ("$1" == "done") goto done;
+goto usage;
+
+init:
+ # test named Xserver, or start vnc on specified machine
+ xdpyinfo -display $xdisp >& /dev/null
+ if ($status) then
+   # X server is not running. start it now
+   echo "X server is not running. start it now"
+   exit 1;
+ endif
+ echo "X server $xdisp is running"
+ exit 0;
+
+plot: 
+ echo $script
+ echo "doplots; exit 0" | dvo -D CAMERA $camera --norc $script
+ exit 0;
+
+
+done:
+ if ("$2" == "") then
+  echo "USAGE: el_plots done (date)"
+  exit 2;
+ endif 
+
+ cp $datdir/plot/seeing_night.png /apps/www/www.cfht.hawaii.edu/Instruments/Elixir/seeing/archive/seeing_$2.png
+ exit 0;
+
+usage:
+ echo "USAGE: el_plots init"
+ echo "USAGE: el_plots plot"
+ echo "USAGE: el_plots done (date)"
+ exit 2;
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/elixir.fork
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/elixir.fork	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/elixir.fork	(revision 16632)
@@ -0,0 +1,112 @@
+#!/bin/csh -f
+
+# this script is called by the CFH12K 'go' command and is run on the
+# acquisition machine.  It is run as user cfh12k, or who ever else
+# might be running the camera.  It assumes the user does not have any
+# the elixir path (/apps/elixir/bin at CFHT) define.
+
+# all needed elixir functions should be in the path of cfh12k (and megacam)
+setenv PATH /bin:/usr/bin:/apps/elixir/bin
+umask 0
+
+# file must exist when elixir.fork is called
+if ($#argv != 1) then
+ echo "USAGE: elixir.fork (filename)"
+ echo "(filename) must be the file for MEF, the top directory for SPLIT"
+ exit;
+endif
+
+# convert filename to (dir) (base) (mode):
+set answer=`/apps/elixir/bin/cfht.names $1`
+if ($status) exit 1
+
+set list=($answer)
+set fdir=$list[1]
+set name=$list[2]
+set mode=$list[3]
+
+# set logdir for various logging
+# set logdir=`gconfig LOGDIR`
+# if ($status) then 
+#  echo "error with elixir configurations: missing LOGDIR, using /tmp" 
+# endif
+
+set logdir = "$HOME/elixir"
+if (! -e $logdir) then 
+  mkdir $logdir
+  if ($status) then 
+    echo "error with elixir configurations: missing LOGDIR, using /tmp" 
+    set logdir = "/tmp"
+  endif
+endif
+
+# get name for a specific image, get image type
+# the definition of the name is system dependent
+if ("$mode" == "on") then
+ set file=$fdir/$name.fits
+else 
+ set file=$fdir/$name/$name\00.fits
+endif
+
+# abstract the OBSTYPE keyword? 
+set type=`echo $file | fields OBSTYPE | awk '{print $2}' | tr '[:lower:]' '[:upper:]'`
+
+# name for summit processing machine
+set remote=wekiu
+
+# realtime functions to perform
+set focus=0
+set seeing=0
+set jpeg=0
+switch ($type)
+    case FOCUS:
+	set focus=1
+	breaksw;
+    case DARK:
+    case BIAS:
+    case FLAT:
+	breaksw;
+    case OBJECT:
+	set jpeg=1
+	set seeing=1
+	# send to the seeing stats
+	breaksw;
+    default:
+	breaksw;
+endsw
+
+if (-r ~/.elixir.override) then
+ echo "NOTE: using values from .elixir.override" >> $logdir/fork.log
+ source ~/.elixir.override
+endif
+
+set comp = ""
+if ($focus) set comp = "getfocus $comp"
+if ($seeing) set comp = "getseeing $comp"
+if ($jpeg) set comp = "mkjpeg $comp"
+if ("$comp" == "") set comp = "nothing" 
+
+echo "$fdir $name $mode : type $type : running $comp" >> $logdir/fork.log
+# echo "$fdir $name $mode : type $type : running $comp"
+
+if ($seeing) then 
+    # getseeing - measure seeing stats for image
+    rsh -n $remote /apps/elixir/bin/getseeing $fdir $name $mode >>& $logdir/getseeing.log &
+endif
+
+if ($focus) then 
+    # getfocus - measure focus frame
+    rsh -n $remote /apps/elixir/bin/getfocus $fdir $name $mode >>& $logdir/getfocus.log &
+endif
+
+if ($jpeg) then 
+    # mkjpeg - create binned images
+    rsh -n $remote /apps/elixir/bin/mkjpeg $fdir $name $mode >>& $logdir/mkjpeg.log &
+endif
+
+exit 0;
+
+# note on script launches:
+# script >>& logfile.log &
+# launches the script immediately, ignores the exit status,
+# saves all output into logfile.log
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/elixir.launch
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/elixir.launch	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/elixir.launch	(revision 16632)
@@ -0,0 +1,124 @@
+#!/bin/csh -f
+
+if ($#argv != 1) then
+ echo "USAGE: elixir.launch (system)"
+ exit 2
+endif
+
+set run    = `gconfig RUNID.CURRENT`;
+set camera = `gconfig CAMERA.CURRENT`;
+set logdir = `gconfig LOGDIR`;
+set datdir = `gconfig DATDIR`;
+
+if ($1 == "mkdetrend") then
+    switch ($camera)
+     case cfh12k:
+     case megacam:
+     case meganorth:
+      echo "starting mkdetrend"
+      mkdetrend auto run -run $run -camera $camera >>& $logdir/mkdetrend.log &
+      breaksw;
+
+     default:
+      breaksw;
+    endsw
+
+    exit 0;
+endif
+
+if ($1 == "imstats") then
+    switch ($camera)
+     case cfh12k:
+     case megacam:
+     case meganorth:
+      echo "starting elixir imstats"
+      elixir -restart -D mode imstats -D CAMERA $camera -D RUNID $run >>& $logdir/imstats.log &
+      breaksw;
+
+     case cfhtir:
+      echo "starting elixir irstats"
+      elixir -restart -D mode irstats -D CAMERA $camera -D RUNID $run >>& $logdir/imstats.log &
+      breaksw;
+
+     default:
+      echo "stopping elixir imstats"
+      elixir -stop -D mode imstats
+      breaksw;
+    endsw
+    exit 0;
+endif
+
+if ($1 == "imstatreg") then
+    switch ($camera)
+     case cfhtir:
+     case cfh12k:
+     case megacam:
+     case meganorth:
+      echo "checking for existing imstatreg -daemon"
+      imstatreg -D CAMERA $camera -D RUNID $run -daemon -status
+      if ($status) then
+	echo "no imstatreg -daemon, starting..."
+	imstatreg -D CAMERA $camera -D RUNID $run -daemon -v
+	if ($status) then
+	    echo "error starting imstatreg -daemon"
+	endif
+      endif
+      breaksw;
+
+     default:
+      echo "no imstatreg -daemon needed for $camera"
+      breaksw;
+    endsw
+    exit 0;
+endif
+
+if ($1 == "cadc") then
+    switch ($camera)
+     case cfh12k:
+     case megacam:
+     case meganorth:
+      set date = `date -u +%Y%m%d+%H:%M:%S`
+
+      # extract CADC table, using all undistributed, object images from the past few days
+      imsearch -D CAMERA $camera -D RUNID $run -type object -dist f -trange now -4d -cadctable $datdir/cadc/mcmd.raw.$date.fits
+      if ($status) then
+	echo "error extracting cadc table"
+	exit 1;
+      endif
+      # mark the images above distributed
+      imsearch -D CAMERA $camera -D RUNID $run -type object -dist f -trange now -4d -modify dist t
+
+      # send the file to the CADC ftp location
+      cp $datdir/cadc/mcmd.raw.$date.fits /h/ftp/pub/fits_hdrs/
+
+      # update the values to the QSO database
+      cadc2qso $datdir/cadc/mcmd.raw.$date.fits
+
+      breaksw;
+
+     default:
+      echo "no CADC table needed for $camera"
+      breaksw;
+    endsw
+    exit 0;
+endif
+
+if ($1 == "sextract") then
+    switch ($camera)
+     case cfh12k:
+     case megacam:
+     case meganorth:
+      echo "starting elixir sextract"
+      elixir -restart -D mode sextract -D CAMERA $camera -D RUNID $run >>& $logdir/sextract.log &
+      breaksw;
+
+     default:
+      echo "stopping elixir sextract"
+      elixir -stop -D mode sextract
+      breaksw;
+    endsw
+    exit 0;
+endif
+
+echo "command $1 not found"
+exit 1
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/fits2jpeg
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/fits2jpeg	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/fits2jpeg	(revision 16632)
@@ -0,0 +1,68 @@
+#!/bin/csh -f
+# convert a FITS image to jpeg, scaling based on data
+
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ case HP-UX:
+    setenv ARCH hp;
+    breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+
+setenv PATH /bin:/usr/bin:/usr/bin/X11:/data/milo/eugene/elixir/ohana/bin/{$ARCH}
+
+if ($#argv != 2) then
+ echo "USAGE: fits2jpeg (fits) (jpeg)"
+ exit;
+endif
+
+set temp=`mktemp /tmp/fitsjpg.XXXXXX`
+rm -f $temp
+
+xset q >& /dev/null
+if ($status) then
+ echo "can't access X server"
+ exit 1
+endif
+
+cat > $temp << END
+ \$KII = kii -nomap -private
+ rd a $1
+ keyword a NAXIS1 nx
+ keyword a NAXIS2 ny
+ rotate a flipy
+ stats a - - - -
+ tv a {\$MEDIAN-0.5*\$SIGMA} {2.5*\$SIGMA} 
+ resize \$nx \$ny
+ center {0.5*\$nx} {0.5*\$ny} 
+ jpeg -name $2
+ exit 0
+END
+
+(mana --only $temp) >& /dev/null
+if ($status) then
+ echo "problem running mana
+ rm -f $temp
+ exit 1
+endif
+
+rm -f $temp
+exit 0
+
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/flatten.subaru
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/flatten.subaru	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/flatten.subaru	(revision 16632)
@@ -0,0 +1,43 @@
+#!/bin/csh -f
+
+# this script performs the detrending operation using mana
+# for image arithmetic.  detrending images are stored in the
+# detrend database.  flats are defined so that the science image
+# is divided by the flatfield image, and the normalization is such 
+# that the entire mosaic is normalized by this process
+
+if ($#argv < 2) then
+ echo "USAGE: flatten (in) (out)"
+ exit 2
+endif
+
+set temp=`mktemp /tmp/flatten.XXXXXX`
+
+# create mana script
+echo "fixing the astrometry keywords"
+
+echo "macro go"                    > $temp
+echo "rd a $1"                    >> $temp
+echo "keyword a PC001001 -wf 1.0" >> $temp
+echo "keyword a PC001002 -wf 0.0" >> $temp
+echo "keyword a PC002001 -wf 0.0" >> $temp
+echo "keyword a PC002002 -wf 1.0" >> $temp
+echo "wd a $2"                    >> $temp
+echo "exit 0"                     >> $temp
+echo "end"                        >> $temp
+
+echo "go"                         >> $temp
+echo "exit 1"                     >> $temp
+
+mana --only $temp
+set mana=$status
+rm -f $temp
+
+if ($mana) then
+ echo "ERROR: flatten failed"
+else
+ echo "SUCCESS: flatten succeeded"
+endif
+
+exit $mana
+
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/getfocus
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/getfocus	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/getfocus	(revision 16632)
@@ -0,0 +1,195 @@
+#!/bin/csh -f
+# load the file, determine bias and sky, then extract a subraster
+# write out the subraster 
+
+setenv PATH /bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/apps/elixir/bin
+
+set tmpout=""
+set args=""
+while ("$1" != "") 
+ switch ($1)
+  case -output: 
+   shift
+   set tmpout=$1
+   breaksw;
+  case -*: 
+   goto usage
+   breaksw;
+  default:
+   set args=($args $1);
+   breaksw;
+ endsw
+ shift
+end
+
+if ($#args != 3) goto usage
+
+# kill off other processes with this name, and their children
+set procname=getfocus
+set list=`/bin/ps -eo pid,user,comm | awk -v n=$procname -v m=$$ '($3==n)&&($1!=m){print $1}'`
+foreach pid ($list)
+ echo "kill $pid"
+ set children=`/bin/ps -eo pid,ppid | awk -v p=$pid '($2==p){print $1}'`
+ kill $pid
+ foreach child ($children)
+   echo "kill $child"
+   kill $child
+ end
+end
+
+set fdir=$args[1]
+set name=$args[2]
+set mode=$args[3]
+
+# set script=/apps/elixir/config/mana/focus.pro
+set datdir  = `gconfig DATDIR`
+set confdir = `gconfig CONFDIR`
+set ccds    = `gconfig FOCUS-CCDS-LIST`
+set ccdn    = `gconfig FOCUS-CCDN-LIST`
+
+# sextractor needs full paths to:
+set sexconf = "$confdir/sextract/focus.sex"
+set sexpars = "$confdir/sextract/focus.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+set script  = "$confdir/mana/focus.pro"
+set output1 = "$datdir/plots/focus.unit.gif"
+set output2 = "$datdir/plots/$name.focus.gif"
+if ("$tmpout" != "") then 
+ set output1=$tmpout.ppm
+ set output2=$tmpout.gif
+endif
+
+# test named Xserver, or start vnc on specified machine
+set xhost = `gconfig XHOST.SUMMIT`
+set xdisp = `gconfig XDISP.SUMMIT`
+xdpyinfo -display $xdisp >& /dev/null
+if ($status) then
+  # X server is not running. start it now
+  echo "X server is not running. start it now"
+  exit 1;
+endif
+setenv DISPLAY $xdisp
+
+set temp=`mktemp /tmp/focus.XXXXXX`
+rm -f $temp
+
+if ("$mode" == "on") goto mef
+if ("$mode" == "off") goto split
+goto usage
+
+### SPLIT mode
+split:
+
+# make sure all four files exist
+foreach ccd ($ccdn)
+ block $fdir/$name/$name$ccd.fits -t 60 || goto failure;
+end
+
+# run sextractor on each chip
+foreach ccd ($ccdn)
+ sex $fdir/$name/$name$ccd.fits \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $temp.$ccd; \
+    mv $temp.$ccd $temp.sdat.$ccd &
+end
+
+# wait for results, extract stellar objects
+foreach ccd ($ccdn)
+ block $temp.sdat.$ccd -t 60 || goto failure;
+ awk '($6 > -14) && ($6 < -8) && ($4== 0){print $0}' $temp.sdat.$ccd | sort -k 6n | head -500 | sort -k 2n > $temp.$ccd.sdat
+ rm -f $temp.sdat.$ccd
+end
+# result i in $temp.$ccd.sdat ($ccd from $ccdn)
+
+# create mana script & run it
+rm -f $temp.pro
+set ccd = $ccdn[1]
+echo "input $script" >> $temp.pro
+echo "plotfocus $temp $temp.ppm $name $fdir/$name/$name$ccd.fits" >> $temp.pro
+mana --norc --only $temp.pro
+if ($status) goto failure
+
+# save resulting image for posterity
+ppmtogif < $temp.ppm > $output1
+cp $output1 $output2
+
+# cleanup temp files
+rm -f $temp $temp.sdat $temp.pro $temp.ppm
+foreach ccd ($ccdn)
+ rm -f $temp.$ccd.sdat $temp.$ccd.fits
+end
+exit 0;
+
+### MEF mode
+mef:
+ 
+# wait for file to appear
+block $fdir/$name.fits -t 60 || goto failure;
+
+# extract section of each image to $temp.$ccd.fits ($ccd in $ccdn)
+rm -f $temp.pro
+set i = 1
+while ($i <= $#ccds)
+ echo $i $ccds
+ set ccdnum = $ccdn[$i]
+ set ccdnam = $ccds[$i]
+ echo "input $script" >> $temp.pro
+ echo "split $fdir/$name.fits $ccdnam $temp.$ccdnum.fits" >> $temp.pro
+ @ i++
+end
+mana --norc --only $temp.pro
+
+# run sextractor on each chip
+foreach ccd ($ccdn)
+ sex $temp.$ccd.fits \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $temp.$ccd; \
+    mv $temp.$ccd $temp.sdat.$ccd &
+end
+
+# wait for results, extract stellar objects
+foreach ccd ($ccdn)
+ block $temp.sdat.$ccd -t 60 || goto failure;
+ awk '($6 > -14) && ($6 < -8) && ($4 == 0){print $0}' $temp.sdat.$ccd | sort -k 6n | head -500 | sort -k 2n > $temp.$ccd.sdat
+ rm -f $temp.sdat.$ccd
+end
+
+# create mana script & run it
+rm -f $temp.pro
+set ccd = $ccdn[1]
+echo "input $script" >> $temp.pro
+echo "plotfocus $temp $temp.ppm $name $temp.$ccd.fits" >> $temp.pro
+mana --norc --only $temp.pro
+if ($status) goto failure
+
+# save resulting image for posterity
+ppmtogif < $temp.ppm > $output1
+cp $output1 $output2
+
+# cleanup temp files
+rm -f $temp $temp.sdat $temp.pro $temp.ppm
+foreach ccd ($ccdn)
+ rm -f $temp.$ccd.sdat $temp.$ccd.fits
+end
+exit 0;
+
+failure: 
+ echo "****** error with focus ******"
+ rm -f $temp $temp.sdat $temp.pro
+ foreach ccd ($ccdn)
+  rm -f $temp.$ccd.sdat $temp.$ccd.fits
+ end
+ exit 1;
+
+usage:
+ echo "USAGE: getfocus (fdir) (file) (mode)"
+ echo "(mode) may be 'on' for mef, 'off' for split"
+ exit 2;
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/getfocus.org
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/getfocus.org	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/getfocus.org	(revision 16632)
@@ -0,0 +1,192 @@
+#!/bin/csh -f
+# load the file, determine bias and sky, then extract a subraster
+# write out the subraster 
+
+setenv PATH /bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/apps/elixir/bin
+
+set tmpout=""
+set args=""
+while ("$1" != "") 
+ switch ($1)
+  case -output: 
+   shift
+   set tmpout=$1
+   breaksw;
+  case -*: 
+   goto usage
+   breaksw;
+  default:
+   set args=($args $1);
+   breaksw;
+ endsw
+ shift
+end
+
+if ($#args != 3) goto usage
+
+# kill off other processes with this name, and their children
+set procname=getfocus
+set list=`/bin/ps -eo pid,user,comm | awk -v n=$procname -v m=$$ '($3==n)&&($1!=m){print $1}'`
+foreach pid ($list)
+ echo "kill $pid"
+ set children=`/bin/ps -eo pid,ppid | awk -v p=$pid '($2==p){print $1}'`
+ kill $pid
+ foreach child ($children)
+   echo "kill $child"
+   kill $child
+ end
+end
+
+set fdir=$args[1]
+set name=$args[2]
+set mode=$args[3]
+
+# set script=/apps/elixir/config/mana/focus.pro
+set datdir  = `gconfig DATDIR`
+set confdir = `gconfig CONFDIR`
+set ccds    = `gconfig FOCUS-CCDS-LIST`
+set ccdn    = `gconfig FOCUS-CCDN-LIST`
+
+# sextractor needs full paths to:
+set sexconf = "$confdir/sextract/focus.sex"
+set sexpars = "$confdir/sextract/focus.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+set script  = "$confdir/mana/focus.pro"
+set output1 = "$datdir/plots/focus.unit.gif"
+set output2 = "$datdir/plots/$name.focus.gif"
+if ("$tmpout" != "") then 
+ set output1=$tmpout.ppm
+ set output2=$tmpout.gif
+endif
+
+# test named Xserver, or start vnc on specified machine
+set xhost = `gconfig XHOST.SUMMIT`
+set xdisp = `gconfig XDISP.SUMMIT`
+xdpyinfo -display $xdisp >& /dev/null
+if ($status) then
+  # X server is not running. start it now
+  echo "X server is not running. start it now"
+  exit 1;
+endif
+setenv DISPLAY $xdisp
+
+set temp=`mktemp /tmp/focus.XXXXXX`
+rm -f $temp
+
+if ("$mode" == "on") goto mef
+if ("$mode" == "off") goto split
+goto usage
+
+### SPLIT mode
+split:
+
+# make sure all four files exist
+foreach ccd ($ccdn)
+ block $fdir/$name/$name$ccd.fits -t 60 || goto failure;
+end
+
+# run sextractor on each chip
+foreach ccd ($ccdn)
+ sex $fdir/$name/$name$ccd.fits \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $temp.$ccd; \
+    mv $temp.$ccd $temp.sdat.$ccd &
+end
+
+# wait for results, extract stellar objects
+foreach ccd ($ccdn)
+ block $temp.sdat.$ccd -t 60 || goto failure;
+ awk '($6 > -14) && ($6 < -8){print $0}' $temp.sdat.$ccd | sort -k 6n | head -300 | sort -k 2n > $temp.$ccd.sdat
+ rm -f $temp.sdat.$ccd
+end
+# result i in $temp.$ccd.sdat ($ccd from $ccdn)
+
+# create mana script & run it
+rm -f $temp.pro
+set ccd = $ccdn[1]
+echo "plotfocus $temp $temp.ppm $name $fdir/$name/$name$ccd.fits" >> $temp.pro
+mana --norc --only $script $temp.pro
+if ($status) goto failure
+
+# save resulting image for posterity
+ppmtogif < $temp.ppm > $output1
+cp $output1 $output2
+
+# cleanup temp files
+rm -f $temp $temp.sdat $temp.pro $temp.ppm
+foreach ccd ($ccdn)
+ rm -f $temp.$ccd.sdat $temp.$ccd.fits
+end
+exit 0;
+
+### MEF mode
+mef:
+ 
+# wait for file to appear
+block $fdir/$name.fits -t 60 || goto failure;
+
+# extract section of each image to $temp.$ccd.fits ($ccd in $ccdn)
+rm -f $temp.pro
+set i = 1
+while ($i <= $#ccds)
+ echo $i $ccds
+ set ccdnum = $ccdn[$i]
+ set ccdnam = $ccds[$i]
+ echo "split $fdir/$name.fits $ccdnam $temp.$ccdnum.fits" >> $temp.pro
+ @ i++
+end
+mana --norc --only $script $temp.pro
+
+# run sextractor on each chip
+foreach ccd ($ccdn)
+ sex $temp.$ccd.fits \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $temp.$ccd; \
+    mv $temp.$ccd $temp.sdat.$ccd &
+end
+
+# wait for results, extract stellar objects
+foreach ccd ($ccdn)
+ block $temp.sdat.$ccd -t 60 || goto failure;
+ awk '($6 > -14) && ($6 < -8){print $0}' $temp.sdat.$ccd | sort -k 6n | head -300 | sort -k 2n > $temp.$ccd.sdat
+ rm -f $temp.sdat.$ccd
+end
+
+# create mana script & run it
+rm -f $temp.pro
+set ccd = $ccdn[1]
+echo "plotfocus $temp $temp.ppm $name $temp.$ccd.fits" >> $temp.pro
+mana --norc --only $script $temp.pro
+if ($status) goto failure
+
+# save resulting image for posterity
+ppmtogif < $temp.ppm > $output1
+cp $output1 $output2
+
+# cleanup temp files
+rm -f $temp $temp.sdat $temp.pro $temp.ppm
+foreach ccd ($ccdn)
+ rm -f $temp.$ccd.sdat $temp.$ccd.fits
+end
+exit 0;
+
+failure: 
+ echo "****** error with focus ******"
+ rm -f $temp $temp.sdat $temp.pro
+ foreach ccd ($ccdn)
+  rm -f $temp.$ccd.sdat $temp.$ccd.fits
+ end
+ exit 1;
+
+usage:
+ echo "USAGE: getfocus (fdir) (file) (mode)"
+ echo "(mode) may be 'on' for mef, 'off' for split"
+ exit 2;
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/getseeing
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/getseeing	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/getseeing	(revision 16632)
@@ -0,0 +1,119 @@
+#!/bin/csh -f
+# measure the seeing on a subraster of a specific CCD
+# write the results to a file for the TCL display
+
+setenv PATH /bin:/usr/bin:/usr/local/bin:/usr/bin/X11:/apps/elixir/bin
+
+set screen=0
+if (($#argv == 4) && ("$4" == "-screen")) then
+ set screen=1
+ set argv=($1 $2 $3)
+endif
+
+if ($#argv != 3) then
+ echo "USAGE: getseeing (fdir) (file) (mode) [-screen]"
+ echo "(mode) may be 'on' for mef, 'off' for split"
+ exit;
+endif
+
+# kill off other processes with this name, and their children
+set procname=getseeing
+set list=`/bin/ps -eo pid,user,comm | awk -v n=$procname -v m=$$ '($3==n)&&($1!=m){print $1}'`
+foreach pid ($list)
+ echo "kill $pid"
+ set children=`/bin/ps -eo pid,ppid | awk -v p=$pid '($2==p){print $1}'`
+ kill $pid
+ foreach child ($children)
+   echo "kill $child"
+   kill $child
+ end
+end
+
+# set up references & defaults
+set fdir=$1
+set name=$2
+set mode=$3
+
+set pixscale = `gconfig ASEC_PIX`
+set ccd      = `gconfig SEEING_REF_CCD`
+set amp      = `gconfig SEEING_REF_AMP`
+set datdir   = `gconfig DATDIR`
+set confdir  = `gconfig CONFDIR`
+
+# sextractor needs full paths to:
+set sexconf = "$confdir/sextract/seeing.sex"
+set sexpars = "$confdir/sextract/seeing.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+set script  = "$confdir/mana/seeing.pro"
+set output  = "$datdir/plots/seeing.dat"
+
+# MEF / SPLIT mode
+if ("$mode" == "on") then
+ set mef=1
+ set file=$fdir/$name.fits
+else
+ set mef=0
+ set file=$fdir/$name/$name$ccd.fits
+endif
+
+# wait for file to exist
+block $file -t 60 || exit 1;
+
+# create mana script 
+set temp=`mktemp /tmp/seeing.XXXXXX`
+rm -f $temp $temp.fits $temp.stats $temp.pro $temp.cat
+if ($mef) then
+ set Nextend = `echo $file | fields NEXTEND | awk '{print $2}'` 
+ set Nccds   = `echo $file | fields NCCDS | awk '{print $2}'` 
+ set tccd = $ccd
+ if ($Nextend != $Nccds) set tccd = $amp
+ # use amp for un-spliced data, ccd for spliced
+ echo "input $script" > $temp.pro
+ echo "subraster.mef   $file $tccd $temp.fits $temp.stats" >> $temp.pro
+else
+ echo "input $script" > $temp.pro
+ echo "subraster.split $file $ccd $temp.fits $temp.stats" >> $temp.pro
+endif
+
+# run mana
+mana --only $temp.pro || goto failure;
+
+# run sextractor
+sex $temp.fits \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $temp.cat
+
+set fwhm   = `seeingstats $temp.cat | awk -v scale=$pixscale '{print $1*scale}'`
+set filter = `echo $temp.fits | fields FILTER`
+
+# send output (screen || $output & QSO)
+if ($screen) then
+ echo $name $fwhm $filter
+else
+ echo $name $fwhm $filter > $output
+ imstatqso $temp.fits $temp.stats $temp.cat
+endif 
+
+# cleanup 
+rm -f $temp $temp.fits $temp.stats $temp.pro $temp.cat
+exit 0;
+
+# failure:
+failure:
+ rm -f $temp $temp.fits $temp.stats $temp.pro $temp.cat
+ echo $name died X.XX 0.0 0.0 X > $output
+ exit 1;
+ 
+
+
+# old method of sending data to QSO db:
+#set obs=`echo $name | awk '{n=substr($1,1,6)}{print n}'`
+#/cfht/bin/update_xexpe.sh -U qso_elixir -P op1eliw --obsid $obs --iq $fwhm
+
+
+
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/gettemps
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/gettemps	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/gettemps	(revision 16632)
@@ -0,0 +1,45 @@
+#!/bin/csh -f
+
+# check command-line arguments
+while ("$1" != "") 
+ switch ($1)
+  case -h:
+  case -help:
+  default:  
+   echo "USAGE: gettemps"
+   exit 1
+   breaksw;
+ endsw
+ shift
+end
+
+# find the appropriate script file
+set file=`gconfig TEMPERATURE_LOG`
+if ($status) then 
+ echo "configuration error: TEMPERATURE_LOG"
+ exit 1;
+endif
+
+set temp=`mktemp /tmp/teltemps.XXXXXX`
+set date=`date +%Y/%m/%d`
+cfhtlog -f $date -t "$date 23:59" -p 2,36,43,45 > $temp
+
+# mv is atomic - other processes won't miss the file
+mv -f $temp $file
+chmod 666 $file
+
+exit 0;
+
+# using dl_query gives a consistent output format regardless of 
+# whether it is recent or old DataLogger data
+
+# dl_now -p 4  | awk '(NR==2){print $0}' >  /tmp/teltemps.$$
+
+# data logger probe choices:
+#  2 surface temp, primary mirror west (silver)           deg celsius
+# 36 air temp, dome top ws side                           deg celsius
+# 43 air temp, 6' above 5th floor                         deg celsius
+# 45 air temp, 2" above 5th floor                         deg celsius
+
+# the complete list of data logger probes is found in:
+# /data/logger/www/probe.list
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/gopsfphot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/gopsfphot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/gopsfphot	(revision 16632)
@@ -0,0 +1,46 @@
+#!/bin/csh -f
+# load the file, determine bias and sky, then extract a subraster
+# write out the subraster 
+
+set sexconf=/data/milo/eugene/elixir/config/sextract
+
+if ($#argv != 4) then
+ echo "USAGE: gopsfphot file.fits file.px file.st file.psf"
+ exit;
+endif
+
+set infile = $1
+set pxfile = $2
+set stfile = $3
+set psfile = $4
+
+# find the appropriate script file
+set confdir=`gconfig -q CONFDIR`
+
+# sextractor needs full paths to:
+set sexconf = "$confdir/sextract/gosexphot.sex"
+set sexpars = "$confdir/sextract/gosexphot.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+set psfconf = "$confdir/sextract/gopsfphot.psf"
+set psfpars = "$confdir/sextract/psf.param"
+
+set pexconf = "$confdir/sextract/gopsfphot.psfex"
+
+sex $infile \
+    -c $psfconf \
+    -PARAMETERS_NAME $psfpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $stfile
+
+psfex $stfile -c $pexconf -PSF_NAME $psfile
+
+sex $infile \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -PSF_NAME        $psfile \
+    -CATALOG_NAME    $pxfile
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/gosexphot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/gosexphot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/gosexphot	(revision 16632)
@@ -0,0 +1,49 @@
+#!/bin/csh -f
+# load the file, determine bias and sky, then extract a subraster
+# write out the subraster 
+
+if (($#argv != 2) && ($#argv != 3)) then
+ echo "USAGE: gosexphot file.fits file.sx [-shallow]"
+ exit;
+endif
+
+set infile = $1
+set outfile = $2
+
+# find the appropriate script file
+set confdir=`gconfig CONFDIR`
+
+set name = "gosexphot.sex"
+set param = "gosexphot.param"
+
+if ($#argv == 3) then
+    if ("$3" == "-shallow") then
+        set name  = "gosexshallow.sex"
+    endif
+    if ("$3" == "-stds") then
+        set name  = "gosexstds.sex"
+	set param = "gosexstds.param"
+    endif
+    if ("$3" == "-deep") then
+        set name  = "gosexdeep.sex"
+    endif
+endif
+
+# sextractor needs full paths to:
+set sexconf = "$confdir/sextract/$name"
+set sexpars = "$confdir/sextract/gosexphot.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+sex $infile \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $outfile
+
+if ($status) then 
+  echo "ERROR: problem with sextractor"
+else
+  echo "SUCCESS"
+endif
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/gpc.cell.zoom
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/gpc.cell.zoom	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/gpc.cell.zoom	(revision 16632)
@@ -0,0 +1,124 @@
+#!/usr/bin/env mana
+
+if (($argv:n != 1) && ($argv:n != 2)) 
+  echo "USAGE: gpc.cell.zoom (gpcdir) [output]"
+  exit 2
+end
+
+macro cell-zoom 
+  $CCDKEYWORD = EXTNAME
+  $gpcdir = $argv:0
+  $basename = `basename $gpcdir`
+
+  $output = $basename.grid.fits
+  if ($argv:n == 2)
+    $output = $argv:1
+  end
+
+  # we assume the files have names of the form gpcdir/gpcdirXY.fits
+  list name -x "ls $gpcdir/$basename??.fits"
+
+  if ($name:n == 0)
+    echo "No fits files found in $gpcdir"
+    exit 1
+  end
+
+  # judge the full mosaic size by a single sample cell
+  rd cell $name:0 -x 0
+  keyword cell NAXIS1 Nx
+  keyword cell NAXIS2 Ny
+
+  mcreate mosaic {8*$Nx} {8*$Ny}
+
+  for ix 0 8
+    for iy 0 8
+      sprintf filename "%s/%s%d%d.fits" $gpcdir $basename $ix $iy
+      file $filename found
+      if (not($found)) continue
+
+      # try to read the center cell:
+      #  3,3 if (x < 4) && (y < 4)
+      #  3,4 if (x < 4) && (y > 3)
+      #  3,4 if (x > 3) && (y < 4)
+      #  3,3 if (x > 3) && (y > 3)
+      if (($ix < 4) && ($iy < 4))
+        $xo = 3; $yo = 3
+      end
+      if (($ix < 4) && ($iy > 3))
+        $xo = 3; $yo = 4
+      end
+      if (($ix > 3) && ($iy < 4))
+        $xo = 3; $yo = 4
+      end
+      if (($ix > 3) && ($iy > 3))
+        $xo = 3; $yo = 3
+      end
+
+      # avoid the calcite cells & another poor cell
+      if (($ix == 7) && ($iy == 6))
+        $xo = 2; $yo = 2
+      end
+      if (($ix == 1) && ($iy == 7))
+        $xo = 2; $yo = 5
+      end
+      if (($ix == 4) && ($iy == 4))
+        $xo = 3; $yo = 4
+      end
+
+      break -auto off
+      sprintf cell "xy%d%d" $xo $yo
+      rd cell $filename -n $cell
+      if (not($STATUS))
+        echo "failed to find desired cell, just using first in file"
+        rd cell $filename -x 0
+      end
+      break -auto on
+
+      stats -q cell
+
+      set cell = cell - $MEDIAN
+
+      keyword cell LTM1_1 dx
+      keyword cell LTM2_2 dy
+      if ($ix < 4)
+        $dx = $dx * -1
+        $dy = $dy * -1
+      end
+
+      if (($dx == -1) && ($dy == -1)) 
+        rotate cell upsize
+      end
+      if (($dx == -1) && ($dy == +1)) 
+        rotate cell flipx
+      end
+      if (($dx == +1) && ($dy == -1)) 
+        rotate cell flipy
+      end
+
+      keyword cell NAXIS1 nx
+      keyword cell NAXIS2 ny
+      if (($nx != $Nx) || ($ny != $Ny))
+        echo "cell has different size"
+        $nx = $nx << $Nx
+        $ny = $ny << $Ny
+      end
+      extract cell mosaic 0 0 $nx $ny {$ix*$Nx} {$iy*$Ny} {8*$Nx} {8*$Ny}
+    end
+  end
+
+  # apply the header from the 00 chip:
+  sprintf filename "%s/%s11.fits" $gpcdir $basename
+  header mosaic -w $filename
+
+  keyword mosaic NAXIS  -wd 2
+  keyword mosaic NAXIS1 -wd {8*$Nx}
+  keyword mosaic NAXIS2 -wd {8*$Ny}
+
+  wd mosaic $output -bitpix -32 -bzero 0.0 -bscale 1.0
+  exit 0
+end
+
+cell-zoom 
+
+echo "error in gpc.cell.zoom"
+exit 2
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/irsex
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/irsex	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/irsex	(revision 16632)
@@ -0,0 +1,55 @@
+#!/bin/csh -f
+# measure stars (fluxes, fwhm, etc) 
+
+if ($#argv != 2) then
+ echo "USAGE: irsex infile file.sdat"
+ exit;
+endif
+
+set infile = $1
+set outfile = $2
+
+if (! -e $infile) then
+ echo "ERROR: file $infile is missing"
+ exit 1
+endif
+
+# determine image type
+set imageword = `gconfig IMAGETYPE-KEYWORD`
+set type = `echo $1 | fields $imageword | awk '{print $2}'`
+
+# find the sextractor param files (can tune for cfhtir if needed)
+set confdir = `gconfig CONFDIR`
+set sexconf = "$confdir/sextract/cfhtir.sex"
+set sexpars = "$confdir/sextract/cfhtir.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+switch ($type)
+  case object:
+  case Object:
+  case OBJECT:
+     sex $infile \
+	-c $sexconf \
+	-PARAMETERS_NAME $sexpars \
+	-FILTER_NAME     $sexfilt \
+	-STARNNW_NAME    $sexnnw \
+	-CATALOG_NAME    $outfile
+     set stat=$status
+     breaksw;
+
+   default:
+      echo '0' > $2;
+      echo "image type $type, skipping FWHM";
+      set stat = 0
+      breaksw;
+endsw
+
+if ($stat) then
+  echo "ERROR ($stat): problem with sextractor"
+else
+  echo SUCCESS;
+endif
+
+exit $stat
+
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/mkjpeg
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/mkjpeg	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/mkjpeg	(revision 16632)
@@ -0,0 +1,90 @@
+#!/bin/csh -f
+# create a binned-by-10 mosaic in jpeg format
+# write the results to a file for the TCL display
+
+setenv PATH /bin:/usr/bin:/usr/bin/X11:/apps/elixir/bin:/usr/local/bin
+
+if ($#argv != 3) then
+ echo "USAGE: mkjpeg (fdir) (file) (mode)"
+ echo "(mode) may be 'on' for mef, 'off' for split"
+ exit;
+endif
+
+# this is stupid, but simple: wait a few seconds to let 'getseeing' win
+sleep 5
+
+# kill off other processes with this name, and their children
+set procname=mkjpeg
+set list=`/bin/ps -eo pid,user,comm | awk -v n=$procname -v m=$$ '($3==n)&&($1!=m){print $1}'`
+foreach pid ($list)
+ echo "kill $pid"
+ set children=`/bin/ps -eo pid,ppid | awk -v p=$pid '($2==p){print $1}'`
+ kill $pid
+ foreach child ($children)
+   echo "kill $child"
+   kill $child
+ end
+end
+
+set fdir=$1
+set name=$2
+set mode=$3
+
+# find the appropriate script file
+set confdir = `gconfig CONFDIR`
+set datdir  = `gconfig DATDIR`
+
+set confdir  = "/data/elixir2/elixir/config"
+set script   = "$confdir/mana/mkjpeg.pro"
+set output   = "$datdir/plots/current.b10.gif"
+set outzoom  = "$datdir/plots/current.zoom.gif"
+set outshort = "$datdir/plots/lastshort.zoom.gif"
+
+# test named Xserver, or start vnc on specified machine
+set xhost   = `gconfig XHOST.SUMMIT`
+set xdisp   = `gconfig XDISP.SUMMIT`
+xdpyinfo -display $xdisp >& /dev/null
+if ($status) then
+  # X server is not running. start it now
+  echo "X server is not running. start it now on $xhost"
+  exit 1;
+endif
+setenv DISPLAY $xdisp
+
+set temp=`mktemp /tmp/mkjpeg.XXXXXX`
+rm -f $temp $temp.jpg
+
+if ("$mode" == "on") then
+ set mef=1
+else 
+ set mef=0
+endif
+
+echo "input $script" > $temp
+echo "init.mosaic" >> $temp
+foreach ccd (00 01 02 03 04 05 06 07 08 09 10 11)
+ if ($mef) then
+  set file=$fdir/$name.fits
+  block $file -t 60 || exit 1;
+  echo "load.mosaic $file $ccd MEF" >> $temp
+ else
+  set file=$fdir/$name/$name$ccd.fits
+  block $file -t 60 || exit 1;
+  echo "load.mosaic $fdir/$name/$name$ccd.fits $ccd SPLIT" >> $temp
+ endif
+end
+echo "jpeg.mosaic $temp.jpg $temp.zoom.jpg" >> $temp
+
+mana --norc --only $temp
+# ppmquant 256 $temp.jpg | ppmtogif > $output
+djpeg -gif < $temp.jpg > $output
+djpeg -gif < $temp.zoom.jpg > $outzoom
+
+set short = `echo $file | fields EXPTIME | awk '{s = 0}($2 < 30){s = 1}{print s}'`
+echo "short: $short"
+if ($short) then
+ cp -f $outzoom $outshort
+endif
+
+rm -f $temp $temp.jpg $temp.zoom.jpg
+exit 0
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/rm.elixir
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/rm.elixir	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/rm.elixir	(revision 16632)
@@ -0,0 +1,12 @@
+#!/bin/csh -f 
+
+# USAGE: rm.elixir *
+# deletes files in arg list
+# echo "SUCCESS" at end (or ERROR if failure)
+
+while ("$1" != "") 
+ /bin/rm $1
+ shift
+end
+
+echo SUCCESS
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/scattercorrection
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/scattercorrection	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/scattercorrection	(revision 16632)
@@ -0,0 +1,53 @@
+#!/bin/csh -f
+
+# USAGE: scattercorrection (input) (output) (ccd) (xcol) (ycol) (mcol) (nhead)
+if ($#argv != 6) then
+  echo "USAGE: scattercorrection (input) (output) (ccd) (xcol) (ycol) (mcol)"
+  exit 2
+endif
+
+set INPUT  = $1
+set OUTPUT = $2
+set CCD    = `echo $3 | awk '{printf "%02d", $1}'`
+set XCOL   = $4
+set YCOL   = $5
+set MCOL   = $6
+
+rm -f $OUTPUT
+rm -f tmp.cat
+
+mana << END
+
+macro fixcat
+ data $INPUT
+ read x $XCOL y $YCOL m $MCOL
+ set x = x * (x > 5)       + 5 * (x <= 5)
+ set x = x * (x < 2050) + 2050 * (x >= 2050)
+ set y = y * (y > 20)     + 20 * (y <= 20)
+ set y = y * (y < 4096) + 4096 * (y >= 4096)
+ rd a 2002B.scatter.Z.$CCD.00.fits 
+ for i 0 x[]
+  stats -q a {x[\$i]-5} {y[\$i]-5} 11 11
+  \$dmag = -2.5*log(\$MEDIAN)
+  m[\$i] = m[\$i] - \$dmag
+  sprintf line "%7.4f" m[\$i]
+  output tmp.cat
+  echo "\$line" 
+  output stdout
+ end
+ exit 0
+end
+
+fixcat
+exit 1
+
+END
+
+if ($status) then
+ echo "problem running mana on $INPUT"
+ exit 1
+endif
+
+grep '#' $INPUT > tmp.head
+grep -v '#' $INPUT | paste - tmp.cat > tmp.body
+cat tmp.head tmp.body > $OUTPUT
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/setpath
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/setpath	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/setpath	(revision 16632)
@@ -0,0 +1,30 @@
+#!/bin/csh -f
+
+set sys=`uname -s` 
+switch ($sys)
+ case IRIX64:
+   setenv ARCH irix;
+   breaksw;
+ case SunOS:
+   set ver=`uname -r | awk '{print substr($1,1,1)}'`;
+   if ($ver == 5) then
+     setenv ARCH sol
+   else 
+     setenv ARCH sun4
+   endif
+   breaksw;
+ case Linux:
+   setenv ARCH linux;
+   breaksw;
+ case HP-UX:
+    setenv ARCH hp;
+    breaksw;
+ default:
+   echo "unknown architecture";
+   setenv ARCH unknown;
+   breaksw;
+endsw
+
+setenv PATH /bin:/usr/bin:/data/milo/eugene/elixir/ohana/bin/{$ARCH}
+
+echo $PATH
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/sexstats
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/sexstats	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/sexstats	(revision 16632)
@@ -0,0 +1,55 @@
+#!/bin/csh -f
+# measure stars (fluxes, fwhm, etc) 
+
+if ($#argv != 2) then
+ echo "USAGE: sexstats infile file.sdat"
+ exit;
+endif
+
+set infile = $1
+set outfile = $2
+
+if (! -e $infile) then
+ echo "ERROR: file $infile is missing"
+ exit 1
+endif
+
+# determine image type
+set imageword = `gconfig IMAGETYPE-KEYWORD`
+set type = `echo $1 | fields $imageword | awk '{print $2}'`
+
+# find the sextractor param files (can tune for cfhtir if needed)
+set confdir = `gconfig CONFDIR`
+set sexconf = "$confdir/sextract/shallow.sex"
+set sexpars = "$confdir/sextract/shallow.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+switch ($type)
+  case object:
+  case Object:
+  case OBJECT:
+     sex $infile \
+	-c $sexconf \
+	-PARAMETERS_NAME $sexpars \
+	-FILTER_NAME     $sexfilt \
+	-STARNNW_NAME    $sexnnw \
+	-CATALOG_NAME    $outfile
+     set stat=$status
+     breaksw;
+
+   default:
+      echo '0' > $2;
+      echo "image type $type, skipping FWHM";
+      set stat = 0
+      breaksw;
+endsw
+
+if ($stat) then
+  echo "ERROR ($stat): problem with sextractor"
+else
+  echo SUCCESS;
+endif
+
+exit $stat
+
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/sp_command
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/sp_command	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/sp_command	(revision 16632)
@@ -0,0 +1,274 @@
+#!/bin/csh -f
+
+set IOPENER   = "root@128.171.83.9"
+set template  = "/h/skyprobe/data/Refs/template.fits"
+set dummyfits = "/h/skyprobe/data/Refs/dummy.fits"
+set dlogfile  = "/h/skyprobe/log/sp_expose.log"
+set photlog   = "/h/skyprobe/log/sp_phot.log"
+set process   = 1
+
+set args=""
+while ($#argv) 
+ switch ($1)
+  case -iopener: 
+   shift
+   set IOPENER=$1
+   breaksw;
+  case -noprocess: 
+   set process = 0
+   breaksw;
+  case -h: 
+  case --help: 
+   goto usage;
+   breaksw;
+  default:
+   set args=($args $1);
+   breaksw;
+ endsw
+ shift
+end
+
+if ($args[1] == "") goto usage;
+if ($args[1] == "init")   goto init;
+if ($args[1] == "cool")   goto cool;
+if ($args[1] == "warm")   goto warm;
+if ($args[1] == "dark")   goto dark;
+if ($args[1] == "test")   goto test;
+if ($args[1] == "expose") goto expose;
+goto usage;
+
+######
+
+init:
+ if ($#args != 2) goto usage
+ if (! -d $args[2]) then
+  mkdir -p $args[2]
+ endif
+ echo "" > $dlogfile
+ echo "" > $photlog
+ exit 0;
+
+cool: 
+ if ($#args != 2) goto usage
+ ssh -n $IOPENER sp_ccdcontrol cool 1 $args[2]
+ exit 0;
+
+warm: 
+ if ($#args != 1) goto usage
+ ssh -n $IOPENER sp_ccdcontrol cool 2 0
+ exit 0;
+
+dark:
+ if ($#args != 3) goto usage
+ set exptime = $args[2]
+ set output  = $args[3]
+ ssh -n $IOPENER sp_ccdcontrol expose -etime $exptime -shuttermode 2 > $output
+ exit 0;
+
+test:
+
+ echo ""
+ echo "starting skyprobe test suite"
+ echo "this will take about 2 minutes"
+ echo ""
+
+ # is computer user & name valid?
+ set machine = `echo $IOPENER | tr '@' ' '`
+ if ($#machine != 2) then
+   echo "invalid name for iopener $IOPENER"
+   exit 1;
+ endif
+
+ # is computer alive?
+ ping -c 2 -w 4 $machine[2] >& /dev/null
+ if ($status) then    
+   echo "can't contact iopener $machine[2]"
+   exit 1;
+ endif
+ echo "iopener is OK"
+ echo ""
+
+ # cool camera & wait for 60 seconds
+ echo "cooling camera & waiting for 1 minute"
+ ssh -n $IOPENER sp_ccdcontrol cool 1 -20
+ sleep 60
+ echo ""
+
+ # take a dark frame
+ echo "taking 1 sec dark frame sample.dark.fits"
+ set exptime = 1.0
+ set output  = sample.dark.fits
+ ssh -n $IOPENER sp_ccdcontrol expose -etime $exptime -shuttermode 2 > $output
+ echo ""
+
+ # is DETTEMP in range?
+ set temps = `echo sample.dark.fits | fields DETTEM CAMTEM`
+ if ($status) then
+   echo "header information incorrect for sample.dark.fits"
+   exit 1
+ endif
+ echo "temperatures: camera: $temps[2], outside: $temps[3]"
+ set t = `echo $temps[2] | awk '($1 > 10){print 1}'`
+ if ($t) then
+  echo "WARNING: camera temperature is high!"
+ else
+  echo "camera temperature OK"
+ endif
+ echo ""
+
+ # measure dark frame stats
+ mana --norc << EOF >& /dev/null
+  macro go
+   rd a sample.dark.fits
+   stats a - - - -
+   exec echo \$MEAN \$MEDIAN \$SIGMA > sample.dark.dat
+   exit 0
+  end
+  go
+  exit 1
+EOF
+ if ($status) then 
+  echo "error measuring dark flux"
+  exit 1
+ endif
+
+ # check dark frame stats
+ set flux = `cat sample.dark.dat`
+ echo "dark flux: $flux[2]"
+ set t = `echo $flux[2] | awk '($1 > 10000){print 1}'`
+ if ($t) then
+  echo "WARNING: dark frame is bright!"
+ endif
+ echo ""
+ 
+ # take a light frame
+ echo "taking 0.1 sec light frame sample.light.fits"
+ set exptime = 0.1
+ set output  = sample.light.fits
+ ssh -n $IOPENER sp_ccdcontrol expose -etime $exptime -shuttermode 1 > $output
+ echo ""
+
+printout:
+
+ # test named Xserver, or start vnc on specified machine
+ set xhost = `gconfig XHOST.SUMMIT`
+ set xdisp = `gconfig XDISP.SUMMIT`
+ xdpyinfo -display $xdisp >& /dev/null
+ if ($status) then
+   # X server is not running. start it now
+   echo "X server is not running on $xdisp. start it now"
+   exit 1;
+ endif
+ setenv DISPLAY $xdisp
+ echo $xdisp
+
+ # delete old PS file
+ date +%Y.%m.%d | awk '{printf "TEXT 10 20 date:%s\n", $1}' > date.reg
+
+ mana --norc << EOF >& /dev/null
+  macro go
+   rd a sample.light.fits
+   stats a - - - -
+   exec echo \$MEAN \$MEDIAN \$SIGMA > sample.light.dat
+   keyword a NAXIS1 nx
+   keyword a NAXIS2 ny
+   tv a {\$MEDIAN*1.1} {-0.2*\$MEDIAN}
+   resize \$nx \$ny
+   load red date.reg
+   exec sleep 2
+   ps -name sample.light.ps
+   exit 0
+  end
+  go
+  exit 1
+EOF
+ if ($status) then 
+  echo "error measuring light flux"
+  exit 1
+ endif
+
+ # check light frame stats
+ set flux = `cat sample.light.dat`
+ echo "light flux: $flux[2]"
+ echo "approx. expected counts: "
+ echo "     100 for dark dome"
+ echo "   15000 for dome lights on"
+ echo "   30000 for dome open daytime"
+ echo ""
+
+ if (! -e sample.light.ps) then 
+   echo "sample.light.ps not created, cannot print out image"
+ else
+   lpr -Psps sample.light.ps
+   echo "image is being printed on SPS"
+ endif
+
+ rm -f date.reg
+ rm -r sample.dark.dat
+ rm -r sample.light.dat
+
+ # test tcsh & loggerh
+ # cp -f $template $dummyfits
+ # setenv FFTEMPLATE $dummyfits
+ # /cfht/bin/tcsh -B >>& $logfile
+ # /cfht/bin/loggerh -E >>& $logfile
+
+ exit 0; 
+
+expose:
+ if ($#args != 3) goto usage
+ set exptime  = $args[2]
+ set output = $args[3]
+
+ # setup logfile (default or /dev/null)
+ if ((-e $dlogfile) && (! -w $dlogfile)) then
+  set logfile = /dev/null
+ else
+  set logfile = $dlogfile
+ endif
+
+ # pre-exposure:
+ # get current RA & DEC, etc
+ # cp -f $template $dummyfits
+ # setenv FFTEMPLATE $dummyfits
+ # /cfht/bin/tcsh -B >>& $logfile
+ # at this point, we could check the TCS status and wait until dome & tel
+ # are not moving.  a future addition
+    
+ # take exposure:
+ if ($process) then
+  (ssh -n $IOPENER sp_ccdcontrol expose -etime $exptime -shuttermode 1 > $output) >>& $logfile
+ else
+   ssh -n $IOPENER sp_ccdcontrol expose -etime $exptime -shuttermode 1 > $output
+ endif
+
+ # post-exposure 
+ if ($process) then 
+  # set target for tcsh & loggerh
+  setenv FFTEMPLATE $output
+
+  # update RA & DEC in image header
+  /cfht/bin/tcsh -B >>& $logfile
+  /cfht/bin/loggerh -E >>& $logfile
+
+  # todo:
+  # read RA & DEC from $dummyfits, check for offset, set flag
+  # check exit status for functions above. if they fail, exit 1
+
+  # currently skipping the animation jpegs
+  # makejpegs $output &
+  sp_phot $output >>& $photlog & 
+ endif
+  
+ exit 0;
+
+######
+
+usage:
+  echo "USAGE: sp_command init (path)"
+  echo "USAGE: sp_command cool (temp)"
+  echo "USAGE: sp_command warm"
+  echo "USAGE: sp_command test"
+  echo "USAGE: sp_command dark (exptime) (filename)"
+  echo "USAGE: sp_command expose (exptime) (filename)"
+exit 2;
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/sp_phot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/sp_phot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/sp_phot	(revision 16632)
@@ -0,0 +1,148 @@
+#!/bin/csh -f
+
+# USAGE: sp_phot (filename.fits) 
+
+# this script has a few goals:
+# 1) make a copy of the unreduced image in RAWDIR
+# 2) run skyproberedccd, produce a reduced image
+# 3) run skyprobephot (sextractor) on image
+# 4) run imclean on result, place smp file in SMPDIR
+# 5) run gastro on smp file 
+# 6) run addstar on smp to add to CATDIR
+
+# run this process on 'druid' instead of 'ohia'?
+
+set DBMACHINE = `gconfig DBMACHINE`
+set PROCNAME  = sp_phot
+set MAXTIME   = 300
+
+set args=""
+set setdate=1
+set testrun=0
+while ($#argv)
+ switch ($1)
+  case -date: 
+   set setdate=0;
+   shift;
+   set DATE=$1;
+   breaksw;
+  default:
+   set args=($args $1);
+   breaksw;
+ endsw
+ shift
+end
+
+if ("$args[1]" == "") then
+  echo "USAGE: sp_phot (filename.fits) [-date YYYYMMDD]";
+  echo "USAGE: sp_phot (test)";
+  exit 2;
+endif
+
+if ($args[1] == "test") set testrun = 1
+
+# kill off other processes with this name, and their children
+# but only if they've run for more than $MAXTIME
+set list=`/bin/ps -eo pid,user,comm | awk -v n=$PROCNAME -v m=$$ '($3==n)&&($1!=m){print $1}'`
+foreach pid ($list)
+  set etime=`/bin/ps -eo pid,etime | awk -v n=$pid '($1==n){{m=substr($2,1,2)}{s=substr($2,4,2)}{print m*60+s}}'`
+  if ($etime < $MAXTIME) continue
+  echo "kill $pid ($etime)"
+  set children=`/bin/ps -eo pid,ppid | awk -v p=$pid '($2==p){print $1}'`
+  kill $pid
+  foreach child ($children)
+    echo "kill $child (child)"
+    kill $child
+  end
+end
+
+if ($setdate) then
+  set DATE=`date -u +%Y%m%d`
+endif
+
+set spdir = `gconfig SKYPROBE_DIR`
+if ($?) then 
+  echo "problem with config system: missing SKYPROBE_DIR"
+  exit 1;
+endif
+set RAWDIR = "$spdir/rawdir/$DATE"
+set SMPDIR = "$spdir/smpdir/$DATE"
+set TYCHO  = "$spdir/tycho" 
+
+# check that directories exist
+if (! -d $RAWDIR) then
+  mkdir -p $RAWDIR
+  if ($status) then
+    echo "can't create save directory $RAWDIR";
+    exit 1;
+  endif
+endif
+if (! -d $SMPDIR) then
+  mkdir -p $SMPDIR
+  if ($status) then
+    echo "can't create save directory $SMPDIR";
+    exit 1;
+  endif
+endif
+
+set raw=$args[1]
+if ($testrun) then
+ set raw = /h/skyprobe/data/Refs/sample.fits
+endif
+
+set root=`echo $raw | awk -F/ '{print $NF}' | sed s/.fits//`
+
+cp $raw $RAWDIR/
+if ($status) then
+  echo "warning: can't make copy of image $raw"
+endif
+
+skyproberedccd $raw $SMPDIR/$root.flt
+if ($status) goto cleanup;
+
+# skyprobephot $SMPDIR/$root.flt $SMPDIR/$root.sx
+sp_sexphot $SMPDIR/$root.flt $SMPDIR/$root.sx
+if ($status) goto cleanup;
+
+# need to have a generic method of introducing the correct photcode
+# based on both camera and filter
+imclean -sex -p SKYPROBE.V $SMPDIR/$root.flt $SMPDIR/$root.sx $SMPDIR/$root.smp 
+if ($status) goto cleanup;
+
+# use the tycho data only to do astrometry
+# rsh -n $DBMACHINE gastro -D CATDIR $TYCHO $SMPDIR/$root.smp
+echo gastro -D CATDIR $TYCHO $SMPDIR/$root.smp
+gastro -D CATDIR $TYCHO $SMPDIR/$root.smp
+# if ($status) goto cleanup;
+
+# rsh -n $DBMACHINE addstar -skyprobe -image -cal TYCHO_V TYCHO_B $SMPDIR/$root.smp 
+addstar -skyprobe -image -cal $SMPDIR/$root.smp 
+# if ($status) goto cleanup;
+
+if ($testrun) then
+ set N = `imphotsearch -name sample | wc -l`
+ imphotsearch -name sample
+ if ($status) then
+   echo "failure to find image in db"
+   exit 2;
+ endif
+ if ($N == 0) then
+   echo "failure to write image to db"
+   exit 1;
+ endif
+ echo delstar $SMPDIR/$root.smp 
+ delstar $SMPDIR/$root.smp 
+ if ($status) then
+   echo "failure to remove test image from db"
+   exit 2;
+ endif
+endif
+
+rm -f $SMPDIR/$root.flt 
+rm -f $SMPDIR/$root.sx
+exit 0;
+
+cleanup:
+rm -f $SMPDIR/$root.flt 
+rm -f $SMPDIR/$root.sx
+exit 1;
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/sp_plots
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/sp_plots	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/sp_plots	(revision 16632)
@@ -0,0 +1,57 @@
+#!/bin/csh -f
+
+if (($#argv != 1) && ($#argv != 2)) goto usage
+
+setenv PATH /bin:/usr/bin:/usr/bin/X11:/apps/elixir/bin:/usr/local/bin
+
+# find the appropriate script file
+set confdir=`gconfig CONFDIR`
+set datdir=`gconfig DATDIR`
+set script="$confdir/mana/skyprobe"
+set xhost=`gconfig XHOST.SUMMIT`
+set xdisp=`gconfig XDISP.SUMMIT`
+setenv DISPLAY $xdisp
+
+if ("$1" == "init")   goto init;
+if ("$1" == "plot")   goto plot;
+if ("$1" == "mkplot") goto mkplot;
+if ("$1" == "done")   goto done;
+goto usage;
+
+init:
+ # test named Xserver, or start vnc on specified machine
+ xdpyinfo -display $xdisp >& /dev/null
+ if ($status) then
+   # X server is not running. start it now
+   echo "X server is not running. start it now"
+   exit 1;
+ endif
+ echo "X server $xdisp is running"
+ exit 0;
+
+plot: 
+ echo "init; doplots; exit 0" | dvo -C skyprobe --norc $script
+ exit 0;
+
+
+mkplot: 
+ if ($#argv != 2) goto usage
+ echo "init; ntplot $2; exit 0" | status -C skyprobe --norc $script
+ exit 0;
+
+
+done:
+ if ("$2" == "") then
+  echo "USAGE: sp_plots done (date)"
+  exit 2;
+ endif 
+
+ cp $datdir/plots/skyprobe_night.png /apps/www/www.cfht.hawaii.edu/Instruments/Skyprobe/archive/mcal_$2.png
+ exit 0;
+
+usage:
+ echo "USAGE: sp_plots init"
+ echo "USAGE: sp_plots plot"
+ echo "USAGE: sp_plots mkplot (yyyy/mm/dd)"
+ echo "USAGE: sp_plots done (yyyymmdd))"
+ exit 2;
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/sp_sexphot
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/sp_sexphot	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/sp_sexphot	(revision 16632)
@@ -0,0 +1,32 @@
+#!/bin/csh -f
+# load the file, determine bias and sky, then extract a subraster
+# write out the subraster 
+
+if ($#argv != 2) then
+ echo "USAGE: skyprobephot file.fits file.sx"
+ exit 2;
+endif
+
+set infile = $1
+set outfile = $2
+
+# sex $1 -c $script -CATALOG_NAME $2
+# exit $status
+
+# find the appropriate script file
+set confdir=`gconfig CONFDIR`
+
+# sextractor needs full paths to:
+set sexconf = "$confdir/sextract/skyprobe.sex"
+set sexpars = "$confdir/sextract/skyprobe.param"
+set sexfilt = "$confdir/sextract/default.conv"
+set sexnnw  = "$confdir/sextract/default.nnw"
+
+sex $infile \
+    -c $sexconf \
+    -PARAMETERS_NAME $sexpars \
+    -FILTER_NAME     $sexfilt \
+    -STARNNW_NAME    $sexnnw \
+    -CATALOG_NAME    $outfile
+
+exit $status
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/vnccheck
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/vnccheck	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/vnccheck	(revision 16632)
@@ -0,0 +1,15 @@
+#!/bin/csh -f 
+
+# test if the vnc is alive.  if not, restart it.
+
+if ($#argv != 0) then
+ echo "USAGE: vnccheck" 
+ exit 2
+endif
+
+set disp = `hostname`:1
+
+xdpyinfo -display $disp >& /dev/null
+if ($status) then
+  vncstart
+endif
Index: /branches/eam_branch_20080223/Ohana/src/shell/src/vncstart
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/shell/src/vncstart	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/shell/src/vncstart	(revision 16632)
@@ -0,0 +1,12 @@
+#!/bin/csh -f
+
+setenv PATH {$PATH}:/apps/elixir/bin
+
+vncserver -kill :1
+
+# remove lock files from Xvnc 
+rm -f /tmp/.X1-lock
+rm -f /tmp/.X11-unix/X1
+
+# start Xvnc as user 'cfh12k' (so users can restart as needed)
+vncserver -depth 16 :1
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/Makefile	(revision 16632)
@@ -0,0 +1,77 @@
+default: skycalc
+help:
+	@echo "make options: (default)"
+
+include ../../Makefile.System
+HOME	=	$(ROOT)/src/skycalc
+BIN	= 	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	= 	$(HOME)/doc
+INC	=	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = $(BASE_LDFLAGS)
+
+skycalc: $(DESTLIB)/libskycalc.a
+install: $(DESTINC)/skycalc.h $(DESTLIB)/libskycalc.a
+
+all: moondata dusktime sundata
+
+OBJ = 	$(SRC)/time.$(ARCH).o		$(SRC)/geometry.$(ARCH).o \
+	$(SRC)/astro.$(ARCH).o		$(SRC)/sun.$(ARCH).o \
+	$(SRC)/moon.$(ARCH).o
+
+$(OBJ): $(INC)/skycalc.h $(INC)/skycalc_internal.h
+
+$(LIB)/libskycalc.$(ARCH).a: $(OBJ)
+	@if [ ! -d $(LIB) ]; then mkdir -p $(LIB); fi
+	rm -f $(LIB)/libskycalc.$(ARCH).a
+	ar rcv $(LIB)/libskycalc.$(ARCH).a $(OBJ)
+	$(RANLIB) $(LIB)/libskycalc.$(ARCH).a
+
+$(DESTLIB)/libskycalc.a: $(LIB)/libskycalc.$(ARCH).a 
+	@if [ ! -d $(DESTLIB) ]; then mkdir -p $(DESTLIB); fi
+	rm -f  $(DESTLIB)/libskycalc.a
+	cp $(LIB)/libskycalc.$(ARCH).a $(DESTLIB)/libskycalc.a
+
+$(DESTINC)/skycalc.h: $(INC)/skycalc.h
+	@if [ ! -d $(DESTINC) ]; then mkdir -p $(DESTINC); fi
+	rm -f $(DESTINC)/skycalc.h
+	cp $(INC)/skycalc.h $(DESTINC)/
+
+test:
+	$(CC) $(CCFLAGS) -g -o skylib $(SRC)/skylib.c -lskycalc -lm
+
+dusktime: skycalc
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	$(CC) $(CCFLAGS) -g -o $(BIN)/dusktime.$(ARCH) $(SRC)/dusktime.c -lskycalc -lm -lohana
+	cp $(BIN)/dusktime.$(ARCH) $(DESTBIN)/dusktime
+
+moondata: skycalc
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	$(CC) $(CCFLAGS) -g -o $(BIN)/moondata.$(ARCH) $(SRC)/moondata.c -lskycalc -lm -lohana
+	cp $(BIN)/moondata.$(ARCH) $(DESTBIN)/moondata
+
+sundata: skycalc
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	$(CC) $(CCFLAGS) -g -o $(BIN)/sundata.$(ARCH) $(SRC)/sundata.c -lskycalc -lm -lohana
+	cp $(BIN)/sundata.$(ARCH) $(DESTBIN)/sundata
+
+clean:	
+	rm -f `find . -name "*.o"`
+	rm -f `find . -name "*.a"`
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
+.SUFFIXES: .$(ARCH).o
+
+.c.$(ARCH).o:
+	$(CC) $(CFLAGS) -c $<
+
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/doc/skycalc.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/doc/skycalc.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/doc/skycalc.txt	(revision 16632)
@@ -0,0 +1,92 @@
+
+functions in time.c:
+
+int    get_sys_date (struct SC_date_time *date)
+       set SC date & time from system clock
+
+double date_to_jd (struct SC_date_time date)
+       convert JD to SC date & time
+
+void   jd_to_date (double jdin, struct SC_date_time *date)
+       convert SC date & time to JD
+
+double lst (double jd, double longit)
+       convert JD & longitude to LST
+
+double adj_time (double x)
+       force time domain to be -12h and 12h 
+
+
+functions in geometry.c:
+
+void   xyz_cel (double x, double y, double z, double *r, double *d)
+       converts a coordinate triplet back to a standard ra and dec
+
+double atan_circ (double x, double y)
+       returns radian angle 0 to 2pi for coords x, y -- get that quadrant right !! */
+
+double altit (double dec, double ha, double lat, double *az)
+       returns altitude (degrees) for dec, ha, lat (degree)
+       also computes and returns azimuth through pointer argument.
+
+double ha_alt (double dec, double lat, double alt)
+       returns hour angle at which object at dec is at altitude alt.
+       If object is never at this altitude, signals with special
+       return values 1000 (always higher) and -1000 (always lower).
+
+void   min_max_alt (double lat, double dec, double *min, double *max)
+       computes minimum and maximum altitude for a given dec and latitude.
+
+double circulo (double x)
+       force domain to be 0 - 360 degrees
+
+
+functions in astro.c:
+
+void   precrot (double rorig, double dorig, double orig_epoch, double final_epoch, double *rf, double *df) {
+       accurate precession method from rorig, dorig, orig_epoch 
+
+void   geocent (double geolong, double geolat, double height, double x_geo, double y_geo, double z_geo)
+       return geocentric coordinate from geodetic data
+
+void   eclrot(double jd, double x, double y, double z)
+       rotates ecliptic rectangular coords x, y, z to equatorial
+
+double etcorr (double jd)
+       return correction to jd for shifts in ET or TDT
+
+void   set_zenith (struct SC_date_time date, double lat, double longit, double epoch, double *ra, double *dec)
+       return zenith coords for given date, time, epoch, position 
+
+
+functions is sun.c:
+
+void   lpsun (double jd, double ra, double dec)
+       return ra & dec for sun on given JD (low precision)
+
+double jd_sun_alt (double alt, double jdguess, double lat, double longit)
+       return JD for sun at given altitude, start with jdguess
+
+double sunset_tonight (struct SC_date_time date, double lat, double longit, double elev)
+       return JD for sunset before closest midnight to date & time
+
+double sunrise_tonight (struct SC_date_time date, double lat, double longit, double elev)
+       return JD for sunrise after closest midnight to date & time
+
+
+functions in moon.c:
+
+void   accumoon (double jd, double geolat, double lst, double elevsea, 
+       double *geora, double *geodec, double *geodist, 
+       double *topora, double *topodec, double *topodist)
+       calculate position of moon given jd, lat, etc.
+
+double jd_moon_alt (double alt, double jdguess, double lat, double longit, double elevsea)
+       return JD for moon at given altitude, start with jdguess
+
+double moonset_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+       Given site position, return Moonset for closest midnight
+
+double moonrise_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+       Given site position, return Moonrise for closest midnight
+
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/include/skycalc.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/include/skycalc.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/include/skycalc.h	(revision 16632)
@@ -0,0 +1,23 @@
+
+/* header for skycalc library function calls */
+
+struct SC_coord {
+     short sign;  /* carry sign explicitly since -0 not neg. */
+     double hh;
+     double mm;
+     double ss;
+}; 
+
+struct SC_date_time {
+  short y;
+  short mo;
+  short d;
+  short h;
+  short mn;
+  float s;
+};
+
+double sunset_tonight (struct SC_date_time date, double lat, double longit, double elev);
+double sunrise_tonight (struct SC_date_time date, double lat, double longit, double elev);
+double moonset_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev);
+double moonrise_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev);
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/include/skycalc_internal.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/include/skycalc_internal.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/include/skycalc_internal.h	(revision 16632)
@@ -0,0 +1,104 @@
+
+/* header for use by the skycalc library files, not needed for external calls */
+
+# include <skycalc.h>
+# include <stdio.h>
+# include <math.h>
+# include <ctype.h>
+# include <stdarg.h>
+# include <string.h>
+# include <time.h>
+
+/* a couple of the system-dependent magic numbers are defined here */
+
+#define SYS_CLOCK_OK 1    /* 1 means ANSI-standard time libraries do work,
+   2 means they don't.  This is used by compiler switches in file 5 and
+   the main program.  */
+
+#define LOG_FILES_OK 1  /* 1 means that log files are enabled.
+			Any other value means they're not.  */
+
+#define MAX_OBJECTS 500
+#define MINSHORT -32767   /* min, max short integers and double precision */
+#define MAXSHORT 32767
+#define MAXDOUBLE 1.0e38
+#define MINDOUBLE -1.0e38
+#define BUFSIZE 150
+
+/* some (not all) physical, mathematical, and astronomical constants
+   used are defined here. */
+
+#define  PI                3.14159265358979
+#define  ARCSEC_IN_RADIAN  206264.8062471
+#define  DEG_IN_RADIAN     57.2957795130823
+#define  HRS_IN_RADIAN     3.819718634205
+#define  KMS_AUDAY         1731.45683633   /* km per sec in 1 AU/day */
+#define  SS_MASS           1.00134198      /* solar system mass in solar units */
+#define  J2000             2451545.        /* Julian date at standard epoch */
+#define  SEC_IN_DAY        86400.
+#define  FLATTEN           0.003352813   /* flattening of earth, 1/298.257 */
+#define  EQUAT_RAD         6378137.    /* equatorial radius of earth, meters */
+#define  ASTRO_UNIT        1.4959787066e11 /* 1 AU in meters */
+#define  RSUN              6.96000e8  /* IAU 1976 recom. solar radius, meters */
+#define  RMOON             1.738e6    /* IAU 1976 recom. lunar radius, meters */
+#define  PLANET_TOL        3.          /* flag if nearer than 3 degrees
+						to a major planet ... */
+#define  KZEN              0.172       /* zenith extinction, mag, for use
+				     in lunar sky brightness calculations. */
+#define FIRSTJD            2415387.  /* 1901 Jan 1 -- calendrical limit */
+#define LASTJD             2488070.  /* 2099 Dec 31 */
+
+/* MAGIC NUMBERS which might depend on how accurately double-
+   precision floating point is handled on your machine ... */
+
+#define  EARTH_DIFF        0.05            /* used in numerical
+   differentiation to find earth velocity -- this value gives
+   about 8 digits of numerical accuracy on the VAX, but is
+   about 3 orders of magnitude larger than the value where roundoff
+   errors become apparent. */
+
+#define  MIDN_TOL          0.00001         /* this is no longer
+   used -- it was formerly
+   how close (in days) a julian date has to be to midnight
+   before a warning flag is printed for the reader.  VAX
+   double precision renders a Julian date considerably
+   more accurately than this.  The day and date are now based
+   on the same rounding of the julian date, so they should
+   always agree. */
+
+/** prototypes **/
+int    get_sys_date (struct SC_date_time *date);
+double date_to_jd (struct SC_date_time date);
+void   jd_to_date (double jdin, struct SC_date_time *date);
+double lst (double jd, double longit);
+double adj_time (double x);
+void   xyz_cel (double x, double y, double z, double *r, double *d);
+double atan_circ (double x, double y);
+double altit (double dec, double ha, double lat, double *az);
+double ha_alt (double dec, double lat, double alt);
+void   min_max_alt (double lat, double dec, double *min, double *max);
+double circulo (double x);
+void   precrot (double rorig, double dorig, double orig_epoch, double final_epoch, double *rf, double *df);
+void   geocent (double geolong, double geolat, double height, double *x_geo, double *y_geo, double *z_geo);
+void   eclrot(double jd, double *x, double *y, double *z);
+double etcorr (double jd);
+void   set_zenith (struct SC_date_time date, double lat, double longit, double epoch, double *ra, double *dec);
+void   lpsun (double jd, double *ra, double *dec);
+double jd_sun_alt (double alt, double jdguess, double lat, double longit);
+void   accumoon (double jd, double geolat, double lst, double elevsea, 
+       double *geora, double *geodec, double *geodist, 
+       double *topora, double *topodec, double *topodist);
+double jd_moon_alt (double alt, double jdguess, double lat, double longit, double elevsea);
+
+double sunset_tonight (struct SC_date_time date, double lat, double longit, double elev);
+double sunrise_tonight (struct SC_date_time date, double lat, double longit, double elev);
+
+int dms_to_ddd (double *Value, char *string);
+int str_to_radec (double *ra, double *dec, char *str1, char *str2);
+int chk_time (char *line);
+double sec_to_jd (time_t second);
+time_t jd_to_sec (double jd);
+char *sec_to_date (time_t second);
+time_t date_to_sec (char *date);
+int str_to_time (char *line, time_t *second);
+int str_to_dtime (char *line, double *second);
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/astro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/astro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/astro.c	(revision 16632)
@@ -0,0 +1,192 @@
+# include <skycalc_internal.h>
+
+/* Takes a coordinate pair and precesses it using matrix procedures
+   as outlined in Taff's Computational Spherical Astronomy book.
+   This is the so-called 'rigorous' method which should give very
+   accurate answers all over the sky over an interval of several
+   centuries.  Naked eye accuracy holds to ancient times, too.
+   Precession constants used are the new IAU1976 -- the 'J2000'
+   system. Angles in degrees, epochs in years */
+
+void precrot (double rorig, double dorig, double orig_epoch, double final_epoch, double *rf, double *df) {
+  
+  double ti, tf, zeta, z, theta;  /* all as per  Taff */
+  double cosz, coszeta, costheta, sinz, sinzeta, sintheta;  /* ftns */
+  double p11, p12, p13, p21, p22, p23, p31, p32, p33;
+  /* elements of the rotation matrix */
+  double radian_ra, radian_dec;
+  double orig_x, orig_y, orig_z;
+  double fin_x, fin_y, fin_z;   /* original and final unit ectors */
+
+  ti = (orig_epoch - 2000.) / 100.;
+  tf = (final_epoch - 2000. - 100. * ti) / 100.;
+
+  zeta = (2306.2181 + 1.39656 * ti + 0.000139 * ti * ti) * tf +
+    (0.30188 - 0.000344 * ti) * tf * tf + 0.017998 * tf * tf * tf;
+  z = zeta + (0.79280 + 0.000410 * ti) * tf * tf + 0.000205 * tf * tf * tf;
+  theta = (2004.3109 - 0.8533 * ti - 0.000217 * ti * ti) * tf
+    - (0.42665 + 0.000217 * ti) * tf * tf - 0.041833 * tf * tf * tf;
+
+  /* convert to radians */
+
+  zeta = zeta / ARCSEC_IN_RADIAN;
+  z = z / ARCSEC_IN_RADIAN;
+  theta = theta / ARCSEC_IN_RADIAN;
+
+  /* compute the necessary trig functions for speed and simplicity */
+
+  cosz = cos(z);
+  coszeta = cos(zeta);
+  costheta = cos(theta);
+  sinz = sin(z);
+  sinzeta = sin(zeta);
+  sintheta = sin(theta);
+
+  /* compute the elements of the precession matrix */
+
+  p11 = coszeta * cosz * costheta - sinzeta * sinz;
+  p12 = -1. * sinzeta * cosz * costheta - coszeta * sinz;
+  p13 = -1. * cosz * sintheta;
+
+  p21 = coszeta * sinz * costheta + sinzeta * cosz;
+  p22 = -1. * sinzeta * sinz * costheta + coszeta * cosz;
+  p23 = -1. * sinz * sintheta;
+
+  p31 = coszeta * sintheta;
+  p32 = -1. * sinzeta * sintheta;
+  p33 = costheta;
+
+  /* transform original coordinates */
+
+  radian_ra = rorig / HRS_IN_RADIAN;
+  radian_dec = dorig / DEG_IN_RADIAN;
+
+  orig_x = cos(radian_dec) * cos(radian_ra);
+  orig_y = cos(radian_dec) *sin(radian_ra);
+  orig_z = sin(radian_dec);
+  /* (hard coded matrix multiplication ...) */
+  fin_x = p11 * orig_x + p12 * orig_y + p13 * orig_z;
+  fin_y = p21 * orig_x + p22 * orig_y + p23 * orig_z;
+  fin_z = p31 * orig_x + p32 * orig_y + p33 * orig_z;
+
+  /* convert back to spherical polar coords */
+
+  xyz_cel(fin_x, fin_y, fin_z, rf, df);
+
+}
+
+
+/* computes the geocentric coordinates from the geodetic
+   (standard map-type) longitude, latitude, and height.
+   These are assumed to be in decimal hours, decimal degrees, and
+   meters respectively.  Notation generally follows 1992 Astr Almanac,
+   p. K11 */
+
+void geocent (double geolong, double geolat, double height, double *x_geo, double *y_geo, double *z_geo) {
+
+  double denom, C_geo, S_geo;
+
+  geolat = geolat / DEG_IN_RADIAN;
+  geolong = geolong / HRS_IN_RADIAN;
+  denom = (1. - FLATTEN) * sin(geolat);
+  denom = cos(geolat) * cos(geolat) + denom*denom;
+  C_geo = 1. / sqrt(denom);
+  S_geo = (1. - FLATTEN) * (1. - FLATTEN) * C_geo;
+  C_geo = C_geo + height / EQUAT_RAD;  /* deviation from almanac
+					  notation -- include height here. */
+  S_geo = S_geo + height / EQUAT_RAD;
+  *x_geo = C_geo * cos(geolat) * cos(geolong);
+  *y_geo = C_geo * cos(geolat) * sin(geolong);
+  *z_geo = S_geo * sin(geolat);
+}
+
+/* rotates ecliptic rectangular coords x, y, z to
+   equatorial (all assumed of date.) */
+void eclrot(double jd, double *x, double *y, double *z) {
+
+  double incl;
+  double xpr,ypr,zpr;
+  double T;
+
+  T = (jd - J2000) / 36525;  /* centuries since J2000 */
+
+  incl = (23.439291 + T * (-0.0130042 - 0.00000016 * T))/DEG_IN_RADIAN;
+  /* 1992 Astron Almanac, p. B18, dropping the
+     cubic term, which is 2 milli-arcsec! */
+  ypr = cos(incl) * *y - sin(incl) * *z;
+  zpr = sin(incl) * *y + cos(incl) * *z;
+  *y = ypr;
+  *z = zpr;
+  /* x remains the same. */
+}
+
+/* Given a julian date in 1900-2100, returns the correction
+     delta t which is:
+     TDT - UT (after 1983 and before 1993)
+     ET - UT (before 1983)
+     an extrapolated guess  (after 1993).
+
+     For dates in the past (<= 1993) the value is linearly
+     interpolated on 5-year intervals; for dates after the present,
+     an extrapolation is used, because the true value of delta t
+     cannot be predicted precisely.  Note that TDT is essentially the
+     modern version of ephemeris time with a slightly cleaner
+     definition.
+
+     Where the algorithm shifts there is an approximately 0.1 second
+     discontinuity.  Also, the 5-year linear interpolation scheme can
+     lead to errors as large as 0.5 seconds in some cases, though
+     usually rather smaller. */
+
+double etcorr (double jd) {
+
+  double jd1900 = 2415019.5;
+  double dates[20] = {1900,1905,1910,1915,1920,1925,1930,1935,1940,1945,
+		      1950,1955,1960,1965,1970,1975,1980,1985,1990,1993};
+  double delts[20]={-2.72,3.86,10.46,17.20,21.16,23.62,24.02,23.93,24.33,26.77,
+		    29.15,31.07,33.15,35.73,40.18,45.48,50.54,54.34,56.86,59.12};
+  double year, delt;
+  short i;
+
+  year = 1900. + (jd - 2415019.5) / 365.25;
+
+  if(year < 1993.0 && year >= 1900.) {
+    i = (year - 1900) / 5;
+    delt = delts[i] +
+      ((delts[i+1] - delts[i])/(dates[i+1] - dates[i])) * (year - dates[i]);
+  }
+
+  else if (year > 1993. && year < 2100.)
+    delt = 33.15 + (2.164e-3) * (jd - 2436935.4);  /* rough extrapolation */
+
+  else if (year < 1900) {
+    delt = 0.;
+  }
+
+  else if (year >= 2100.) {
+    delt = 180.; /* who knows? */
+  }
+
+  return (delt);
+
+}
+
+/* sets RA and DEC at zenith as defined by given time and date  */
+void set_zenith (struct SC_date_time date, double lat, double longit, double epoch, double *ra, double *dec)
+{
+  double jd, current_epoch;
+
+  jd = date_to_jd (date);
+
+  if (jd < 0.) return;  /* nonexistent time. */
+
+  *ra = lst (jd, longit);
+
+  *dec = lat;
+
+  current_epoch = 2000. + (jd - J2000) / 365.25;
+
+  precrot (*ra,*dec,current_epoch,epoch,ra,dec);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/dusktime.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/dusktime.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/dusktime.c	(revision 16632)
@@ -0,0 +1,67 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc_internal.h>
+# define VERBOSE 0
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main (int argc, char **argv) {
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jdnow, jdset, jdrise, d1, d2;
+  time_t tzero;
+  struct tm *stm;
+
+  if (argc != 2) {
+    fprintf (stderr, "USAGE: dusktime (date)\n");
+    exit (1);
+  }
+
+  if (!str_to_time (argv[1], &tzero)) { 
+    fprintf (stderr, "syntax error\n");
+    exit (1);
+  }
+  stm = gmtime (&tzero);
+  date.y  = (short) (stm->tm_year + 1900);
+  date.mo = (short) (stm->tm_mon + 1);
+  date.d  = (short) (stm->tm_mday);
+  date.h  = (short) (stm->tm_hour);
+  date.mn = (short) (stm->tm_min);
+  date.s  = (float) (stm->tm_sec);
+
+  if (VERBOSE) fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", date.y, date.mo, date.d, date.h, date.mn, date.s);
+
+  set_site (&longit, &lat, &elevsea, &elev);
+
+  jdnow  = date_to_jd (date);
+  jdset  = sunset_tonight (date, lat, longit, elev);
+  jdrise = sunrise_tonight (date, lat, longit, elev);
+
+
+  d1 = fabs (jdnow - jdset);
+  d2 = fabs (jdnow - jdrise);
+
+  if (d1 < d2) {
+    fprintf (stdout, "set %f  %f\n", jdset, 24*60*(jdnow - jdset));
+    jdnow = jdset;
+  } else {
+    fprintf (stdout, "rise %f  %f\n", jdrise, 24*60*(jdrise - jdnow));
+    jdnow = jdrise;
+  }    
+
+  if (VERBOSE) {
+    jd_to_date (jdnow, &tmpdate);
+    fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+  }
+  exit (0);
+}
+
+  /* set_zenith (date, lat, longit, objepoch, &objra, &objdec); */
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/geometry.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/geometry.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/geometry.c	(revision 16632)
@@ -0,0 +1,135 @@
+# include <skycalc_internal.h>
+
+/* converts a coordinate triplet back to a standard ra and dec */
+void xyz_cel (double x, double y, double z, double *r, double *d) {
+
+   /* converts a coordinate triplet back to a standard ra and dec */
+
+   double mod;    /* modulus */
+   double xy;     /* component in xy plane */
+   short sign;    /* for determining quadrant */
+   double radian_ra, radian_dec;
+
+   /* this taken directly from pl1 routine - no acos or asin available there,
+       as it is in c. Easier just to copy, though */
+
+   mod = sqrt(x*x + y*y + z*z);
+   x = x / mod;
+   y = y / mod;
+   z = z / mod;   /* normalize 'em explicitly first. */
+
+   xy = sqrt(x*x + y*y);
+
+   if(xy < 1.0e-10) {
+      radian_ra = 0.;  /* too close to pole */
+      radian_dec = PI / 2.;
+      if(z < 0.) radian_dec = radian_dec * -1.;
+   }
+   else {
+      if(fabs(z/xy) < 3.) radian_dec = atan(z / xy);
+	 else if (z >= 0.) radian_dec = PI / 2. - atan(xy / z);
+	 else radian_dec = -1. * PI / 2. - atan(xy / z);
+      if(fabs(x) > 1.0e-10) {
+	 if(fabs(y / x) < 3.) radian_ra = atan(y / x);
+	 else if ((x * y ) >= 0.) radian_ra = PI / 2. - atan(x/y);
+	 else radian_ra = -1. *  PI / 2. - atan(x / y);
+      }
+      else {
+	 radian_ra = PI / 2.;
+	 if((x * y)<= 0.) radian_ra = radian_ra * -1.;
+      }
+      if(x <0.) radian_ra = radian_ra + PI ;
+      if(radian_ra < 0.) radian_ra = radian_ra + 2. * PI ;
+   }
+
+   *r = radian_ra * HRS_IN_RADIAN;
+   *d = radian_dec * DEG_IN_RADIAN;
+
+}
+
+/* returns radian angle 0 to 2pi for coords x, y -- get that quadrant right !! */
+double atan_circ (double x, double y) {
+  
+  double theta;
+  
+  if(x == 0.) {
+    if(y > 0.) theta = PI / 2.;
+    else if(y < 0.) theta = 3.* PI / 2.;
+    else theta = 0.;   /* x and y zero */
+  }
+  else theta = atan(y/x);
+  if(x < 0.) theta = theta + PI;
+  if(theta < 0.) theta = theta + 2.* PI;
+  return(theta);
+}
+
+/* returns altitude(degr) for dec, ha, lat (decimal degr, hr, degr);
+    also computes and returns azimuth through pointer argument. */
+double altit (double dec, double ha, double lat, double *az) {
+
+  double x,y,z;
+
+  dec = dec / DEG_IN_RADIAN;
+  ha = ha / HRS_IN_RADIAN;
+  lat = lat / DEG_IN_RADIAN;
+  x = DEG_IN_RADIAN * asin(cos(dec)*cos(ha)*cos(lat) + sin(dec)*sin(lat));
+  y =  sin(dec)*cos(lat) - cos(dec)*cos(ha)*sin(lat); /* due N comp. */
+  z =  -1. * cos(dec)*sin(ha); /* due east comp. */
+  *az = atan_circ(y,z) * DEG_IN_RADIAN;
+  return(x);
+}
+
+/* returns hour angle at which object at dec is at altitude alt.
+   If object is never at this altitude, signals with special
+   return values 1000 (always higher) and -1000 (always lower). */
+double ha_alt (double dec, double lat, double alt) {
+
+  double x,coalt,min,max;
+  
+  min_max_alt(lat,dec,&min,&max);
+  if(alt < min)
+    return(1000.);  /* flag value - always higher than asked */
+  if(alt > max)
+    return(-1000.); /* flag for object always lower than asked */
+  dec = (0.5*PI) - dec / DEG_IN_RADIAN;
+  lat = (0.5*PI) - lat / DEG_IN_RADIAN;
+  coalt = (0.5*PI) - alt / DEG_IN_RADIAN;
+  x = (cos(coalt) - cos(dec)*cos(lat)) / (sin(dec)*sin(lat));
+  if (fabs(x) <= 1.) return(acos(x) * HRS_IN_RADIAN);
+  else {
+    printf  ("Error in ha_alt ... acos(>1).\n");
+    return (1000.);
+  }
+}
+
+/* computes minimum and maximum altitude for a given dec and latitude. */
+void min_max_alt (double lat, double dec, double *min, double *max) {
+
+  double x;
+
+  lat = lat / DEG_IN_RADIAN; /* pass by value! */
+  dec = dec / DEG_IN_RADIAN;
+  x = cos(dec)*cos(lat) + sin(dec)*sin(lat);
+  if (fabs(x) <= 1.) {
+    *max = asin(x) * DEG_IN_RADIAN;
+  }
+  else printf ("Error in min_max_alt -- arcsin(>1)\n");
+
+  x = sin(dec)*sin(lat) - cos(dec)*cos(lat);
+  if(fabs(x) <= 1.) {
+    *min = asin(x) * DEG_IN_RADIAN;
+  }
+  else printf ("Error in min_max_alt -- arcsin(>1)\n");
+}
+
+/* force domain to be 0 - 360 degrees */
+double circulo (double x) {
+  
+  /* fails for negative angles! */
+
+  int n;
+  
+  n = (int)(x / 360.);
+  return(x - 360. * n);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/misc.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/misc.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/misc.c	(revision 16632)
@@ -0,0 +1,314 @@
+# include <ohana.h>
+# include <skycalc_internal.h>
+
+/***** convert [-]00:00:00 to 0.0000 ****/
+int dms_to_ddd (double *Value, char *string) {
+  
+  int valid, neg, status;
+  double tmp, value;
+  char *p1, *p2, *px;
+
+  valid = FALSE; 
+  neg = FALSE;
+  stripwhite (string);
+  p1 = string;
+  px = string + strlen(string);
+
+  if (string[0] == '-') { 
+    valid = TRUE; 
+    neg = TRUE;
+    p1 = &string[1];
+  }
+  if (string[0] == '+') { 
+    valid = TRUE; 
+    neg = FALSE;
+    p1 = &string[1];
+  }
+  if (isdigit(string[0])) { 
+    valid = TRUE;
+    p1 = &string[0];
+  }
+  if (!valid) { return (FALSE); }
+
+  status = 1;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) return (FALSE); /* entry not a number: +fred */
+  value = tmp;
+  if (p2 == px) goto escape;    /* entry only number: +1.0 */ 
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:fred */
+  status = 2;
+  value += tmp / 60.0;
+  if (p2 == px) goto escape;    /* entry only number: +1:1 */
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;    /* entry not a number: +1:1:fred */
+  value += tmp / 3600.0;
+
+ escape:
+  if (neg) {
+    value *= -1;
+  }
+  *Value = value;
+
+  return (status);
+}
+
+/**********/
+int str_to_radec (double *ra, double *dec, char *str1, char *str2) {
+
+  double Ra, Dec;
+
+  *ra = *dec = 0;
+  switch (dms_to_ddd (&Ra, str1)) {
+  case 0:
+    fprintf (stderr, "syntax error in RA\n");
+    return (FALSE);
+  case 1:
+    break;
+  case 2:
+    Ra = Ra * 15;
+    break;
+  }
+  switch (dms_to_ddd (&Dec, str2)) {
+  case 0:
+    fprintf (stderr, "syntax error in DEC\n");
+    return (FALSE);
+  case 1:
+  case 2:
+    break;
+  }
+  *ra = Ra;
+  *dec = Dec;
+  return (TRUE);
+}
+
+# define FORMAT_DAYS    1
+# define FORMAT_HOURS   2
+# define FORMAT_MINUTES 3
+# define FORMAT_SECONDS 4
+# define FORMAT_JD      5
+# define FORMAT_DATE    6
+
+/**********/
+int chk_time (char *line) {
+
+  char *p1, *p2;
+  double tmp;
+  int mode;
+
+  p1 = line;
+  tmp = strtod (p1, &p2);
+  if (p2 == p1 + strlen (p1) - 1) {
+    if (*p2 == 'd') {
+      mode = FORMAT_DAYS;
+    }
+    if (*p2 == 'h') {
+      mode = FORMAT_HOURS;
+    }
+    if (*p2 == 'm') {
+      mode = FORMAT_MINUTES;
+    }
+    if (*p2 == 's') {
+      mode = FORMAT_SECONDS;
+    }
+    if (*p2 == 'j') {
+      mode = FORMAT_JD;
+    }
+  } else { 
+    mode = FORMAT_DATE;
+  }
+  return (mode);
+}
+
+/**********/
+int str_to_time (char *line, time_t *second) {
+  
+  struct timeval now;
+  double jd;
+
+  if (!strcasecmp (line, "NOW")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = now.tv_sec;
+    return (TRUE);
+  }
+    
+  if (!strcasecmp (line, "TODAY")) {
+    gettimeofday (&now, (struct timezone *) NULL);
+    *second = 86400 * ((int)(now.tv_sec / 86400));
+    return (TRUE);
+  }
+    
+  switch (chk_time (line)) {
+  case 0:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  case FORMAT_JD:
+    jd = strtod (line, 0);
+    *second = jd_to_sec (jd);
+    return (TRUE);
+  case FORMAT_DATE:
+    *second = date_to_sec (line);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+int str_to_dtime (char *line, double *second) {
+  
+  switch (chk_time (line)) {
+  case 0:
+  case FORMAT_JD:
+  case FORMAT_DATE:
+    return (FALSE);
+  case FORMAT_DAYS:
+    *second = strtod (line, 0) * 86400.0;
+    return (TRUE);
+  case FORMAT_HOURS:
+    *second = strtod (line, 0) * 3600.0;
+    return (TRUE);
+  case FORMAT_MINUTES:
+    *second = strtod (line, 0) * 60.0;
+    return (TRUE);
+  case FORMAT_SECONDS:
+    *second = strtod (line, 0);
+    return (TRUE);
+  }
+  return (FALSE);
+}
+
+/**********/
+double sec_to_jd (time_t second) {
+
+  double jd;
+  
+  jd = second/86400.0 + 2440587.5;
+  return (jd);
+}
+
+/**********/
+time_t jd_to_sec (double jd) {
+
+  time_t second;
+
+  second = (jd - 2440587.5)*86400;
+  return (second);
+}
+
+/**********/
+char *sec_to_date (time_t second) {
+  
+  struct tm *gmt;
+  char *line;
+  
+  ALLOCATE (line, char, 64);
+  gmt   = gmtime (&second);
+  sprintf (line, "%4d/%02d/%02d,%02d:%02d:%02d", 1900+gmt[0].tm_year, gmt[0].tm_mon+1, gmt[0].tm_mday, gmt[0].tm_hour, gmt[0].tm_min, gmt[0].tm_sec); 
+  return (line);
+
+}
+
+/***** date in format yyyy/mm/dd,hh:mm:ss *****/
+time_t date_to_sec (char *date) {
+  
+  time_t second;
+  double tmp, jd;
+  struct tm now;
+  char *p1, *p2, *px;
+  
+  p1 = date;
+  px = date + strlen(date);
+  bzero (&now, sizeof(now));
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_year = tmp;
+  if (now.tm_year > 1000) now.tm_year -= 1900;
+  if (now.tm_year <   50) now.tm_year += 100;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mon = tmp - 1; /* mon runs from 0 - 11 */
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_mday = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  p1 = p2 + 1;
+  now.tm_hour = tmp;
+  if (p2 == px) goto escape;  
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_min = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+  tmp = strtod (p1, &p2);
+  if (p2 == p1) goto escape;
+  now.tm_sec = tmp;
+  if (p2 == px) goto escape;  
+  p1 = p2 + 1;
+
+ escape:
+  jd = now.tm_mday - 32075 + (int)(1461*(1900 + now.tm_year + 4800 + (int)(((now.tm_mon+1)-14)/12))/4)
+    + (int)(367*((now.tm_mon+1) - 2 - (int)(((now.tm_mon+1) - 14)/12)*12)/12)
+    - (int)(3*(int)((1900 + now.tm_year + 4900 + (int)(((now.tm_mon+1) - 14)/12))/100)/4) - 0.5;
+  
+  second = (jd - 2440587.5)*86400 + 3600.0*now.tm_hour + now.tm_min*60.0 + now.tm_sec;
+
+  return (second);
+}
+
+
+/* times may be in forms as:
+   20040200450s (N seconds since 1970.0)
+   2440900.232j (julian date)
+   99/02/23,03:22:18 (date string)
+   (separators may be anything except space, +, -)
+   99:02:15:12:23:30
+   99:02:15:12h23m30s
+   */
+
+
+/* fseek with timeout - 0.5 sec */
+int Fseek (FILE *f, long offset, int whence) {
+
+  int status, k;
+
+  status = fseek (f, offset, whence);
+  if (status == -1) {
+    int k;
+    /* fprintf (stderr, "problem seeking position: %d\n", errno); */
+    for (k = 0; (k < 10) && ((status = fseek (f, 0, SEEK_SET)) == -1); k++) usleep (50000);
+    if (status == -1) {
+      /* fprintf (stderr, "ERROR: serious problem seeking position: %d\n", errno); */
+      /* clear lock at this point? */
+      return (0);
+    }
+  }
+  return (1);
+}
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/moon.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/moon.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/moon.c	(revision 16632)
@@ -0,0 +1,465 @@
+# include <skycalc_internal.h>
+
+void lpmoon(double jd, double lat, double sid,
+       double* ra, double* dec, double* dist) {
+
+
+/* implements "low precision" moon algorithms from
+   Astronomical Almanac (p. D46 in 1992 version).  Does
+   apply the topocentric correction. 
+   Units are as follows
+   jd,lat, sid;   decimal hours 
+   *ra, *dec,   decimal hours, degrees 
+   *dist;      earth radii */
+
+
+    double T, lambda, beta, pie, l, m, n, x, y, z, alpha, delta,
+        rad_lat, rad_lst, distance, topo_dist;
+    char dummy[40];  /* to fix compiler bug on IBM system */
+
+    T = (jd - J2000) / 36525.;  /* jul cent. since J2000.0 */
+
+    lambda = 218.32 + 481267.883 * T 
+        + 6.29 * sin((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        - 1.27 * sin((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.66 * sin((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.21 * sin((269.9 + 954397.70 * T) / DEG_IN_RADIAN)
+        - 0.19 * sin((357.5 + 35999.05 * T) / DEG_IN_RADIAN)
+        - 0.11 * sin((186.6 + 966404.05 * T) / DEG_IN_RADIAN);
+    lambda = lambda / DEG_IN_RADIAN;
+    beta = 5.13 * sin((93.3 + 483202.03 * T) / DEG_IN_RADIAN)
+        + 0.28 * sin((228.2 + 960400.87 * T) / DEG_IN_RADIAN)
+        - 0.28 * sin((318.3 + 6003.18 * T) / DEG_IN_RADIAN)
+        - 0.17 * sin((217.6 - 407332.20 * T) / DEG_IN_RADIAN);
+    beta = beta / DEG_IN_RADIAN;
+    pie = 0.9508 
+        + 0.0518 * cos((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        + 0.0095 * cos((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.0078 * cos((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.0028 * cos((269.9 + 954397.70 * T) / DEG_IN_RADIAN);
+    pie = pie / DEG_IN_RADIAN;
+    distance = 1 / sin(pie);
+
+    l = cos(beta) * cos(lambda);
+    m = 0.9175 * cos(beta) * sin(lambda) - 0.3978 * sin(beta);
+    n = 0.3978 * cos(beta) * sin(lambda) + 0.9175 * sin(beta);
+
+    x = l * distance; 
+    y = m * distance; 
+    z = n * distance;  /* for topocentric correction */
+
+
+    /* lat isn't passed right on some IBM systems unless you do this
+       or something like it! */
+    sprintf(dummy,"%f",lat);
+
+    rad_lat = lat / DEG_IN_RADIAN;
+    rad_lst = sid / HRS_IN_RADIAN;
+
+    x = x - cos(rad_lat) * cos(rad_lst);
+    y = y - cos(rad_lat) * sin(rad_lst);
+    z = z - sin(rad_lat);
+
+
+    topo_dist = sqrt(x * x + y * y + z * z);
+
+    l = x / topo_dist; 
+    m = y / topo_dist; 
+    n = z / topo_dist;
+
+    alpha = atan_circ(l,m);
+    delta = asin(n);
+
+    *ra = alpha * HRS_IN_RADIAN;
+
+    *dec = delta * DEG_IN_RADIAN;
+    
+    *dist = topo_dist;
+
+}
+
+/* More accurate (but more elaborate and slower) lunar
+   ephemeris, from Jean Meeus' *Astronomical Formulae For Calculators*,
+   pub. Willman-Bell.  Includes all the terms given there. */
+
+void accumoon (jd,geolat,lst,elevsea,geora,geodec,geodist,topora,topodec,topodist)
+     double jd,geolat,lst,elevsea;
+     double *geora,*geodec,*geodist,*topora,*topodec,*topodist;
+{
+  double pie, dist;  /* horiz parallax */
+  double Lpr,M,Mpr,D,F,Om,T,Tsq,Tcb;
+  double e,lambda,B,beta,om1,om2;
+  double sinx, x, y, z, l, m, n;
+  double x_geo, y_geo, z_geo;  /* geocentric position of *observer* */
+
+  jd = jd + etcorr(jd)/SEC_IN_DAY;   /* approximate correction to ephemeris time */
+  T = (jd - 2415020.) / 36525.;   /* this based around 1900 ... */
+  Tsq = T * T;
+  Tcb = Tsq * T;
+
+  Lpr = 270.434164 + 481267.8831 * T - 0.001133 * Tsq
+    + 0.0000019 * Tcb;
+  M = 358.475833 + 35999.0498*T - 0.000150*Tsq
+    - 0.0000033*Tcb;
+  Mpr = 296.104608 + 477198.8491*T + 0.009192*Tsq
+    + 0.0000144*Tcb;
+  D = 350.737486 + 445267.1142*T - 0.001436 * Tsq
+    + 0.0000019*Tcb;
+  F = 11.250889 + 483202.0251*T -0.003211 * Tsq
+    - 0.0000003*Tcb;
+  Om = 259.183275 - 1934.1420*T + 0.002078*Tsq
+    + 0.0000022*Tcb;
+
+  Lpr = circulo(Lpr);
+  Mpr = circulo(Mpr);
+  M = circulo(M);
+  D = circulo(D);
+  F = circulo(F);
+  Om = circulo(Om);
+
+
+  sinx =  sin((51.2 + 20.2 * T)/DEG_IN_RADIAN);
+  Lpr = Lpr + 0.000233 * sinx;
+  M = M - 0.001778 * sinx;
+  Mpr = Mpr + 0.000817 * sinx;
+  D = D + 0.002011 * sinx;
+
+  sinx = 0.003964 * sin((346.560+132.870*T -0.0091731*Tsq)/DEG_IN_RADIAN);
+
+  Lpr = Lpr + sinx;
+  Mpr = Mpr + sinx;
+  D = D + sinx;
+  F = F + sinx;
+
+  sinx = sin(Om/DEG_IN_RADIAN);
+  Lpr = Lpr + 0.001964 * sinx;
+  Mpr = Mpr + 0.002541 * sinx;
+  D = D + 0.001964 * sinx;
+  F = F - 0.024691 * sinx;
+  F = F - 0.004328 * sin((Om + 275.05 -2.30*T)/DEG_IN_RADIAN);
+
+  e = 1 - 0.002495 * T - 0.00000752 * Tsq;
+
+  M = M / DEG_IN_RADIAN;   /* these will all be arguments ... */
+  Mpr = Mpr / DEG_IN_RADIAN;
+  D = D / DEG_IN_RADIAN;
+  F = F / DEG_IN_RADIAN;
+
+  lambda = Lpr + 6.288750 * sin(Mpr)
+    + 1.274018 * sin(2*D - Mpr)
+    + 0.658309 * sin(2*D)
+    + 0.213616 * sin(2*Mpr)
+    - e * 0.185596 * sin(M)
+    - 0.114336 * sin(2*F)
+    + 0.058793 * sin(2*D - 2*Mpr)
+    + e * 0.057212 * sin(2*D - M - Mpr)
+    + 0.053320 * sin(2*D + Mpr)
+    + e * 0.045874 * sin(2*D - M)
+    + e * 0.041024 * sin(Mpr - M)
+    - 0.034718 * sin(D)
+    - e * 0.030465 * sin(M+Mpr)
+    + 0.015326 * sin(2*D - 2*F)
+    - 0.012528 * sin(2*F + Mpr)
+    - 0.010980 * sin(2*F - Mpr)
+    + 0.010674 * sin(4*D - Mpr)
+    + 0.010034 * sin(3*Mpr)
+    + 0.008548 * sin(4*D - 2*Mpr)
+    - e * 0.007910 * sin(M - Mpr + 2*D)
+    - e * 0.006783 * sin(2*D + M)
+    + 0.005162 * sin(Mpr - D);
+
+		/* And furthermore.....*/
+
+  lambda = lambda + e * 0.005000 * sin(M + D)
+    + e * 0.004049 * sin(Mpr - M + 2*D)
+    + 0.003996 * sin(2*Mpr + 2*D)
+    + 0.003862 * sin(4*D)
+    + 0.003665 * sin(2*D - 3*Mpr)
+    + e * 0.002695 * sin(2*Mpr - M)
+    + 0.002602 * sin(Mpr - 2*F - 2*D)
+    + e * 0.002396 * sin(2*D - M - 2*Mpr)
+    - 0.002349 * sin(Mpr + D)
+    + e * e * 0.002249 * sin(2*D - 2*M)
+    - e * 0.002125 * sin(2*Mpr + M)
+    - e * e * 0.002079 * sin(2*M)
+    + e * e * 0.002059 * sin(2*D - Mpr - 2*M)
+    - 0.001773 * sin(Mpr + 2*D - 2*F)
+    - 0.001595 * sin(2*F + 2*D)
+    + e * 0.001220 * sin(4*D - M - Mpr)
+    - 0.001110 * sin(2*Mpr + 2*F)
+    + 0.000892 * sin(Mpr - 3*D)
+    - e * 0.000811 * sin(M + Mpr + 2*D)
+    + e * 0.000761 * sin(4*D - M - 2*Mpr)
+    + e * e * 0.000717 * sin(Mpr - 2*M)
+    + e * e * 0.000704 * sin(Mpr - 2 * M - 2*D)
+    + e * 0.000693 * sin(M - 2*Mpr + 2*D)
+    + e * 0.000598 * sin(2*D - M - 2*F)
+    + 0.000550 * sin(Mpr + 4*D)
+    + 0.000538 * sin(4*Mpr)
+    + e * 0.000521 * sin(4*D - M)
+    + 0.000486 * sin(2*Mpr - D);
+
+/*              *eclongit = lambda;  */
+
+  B = 5.128189 * sin(F)
+    + 0.280606 * sin(Mpr + F)
+    + 0.277693 * sin(Mpr - F)
+    + 0.173238 * sin(2*D - F)
+    + 0.055413 * sin(2*D + F - Mpr)
+    + 0.046272 * sin(2*D - F - Mpr)
+    + 0.032573 * sin(2*D + F)
+    + 0.017198 * sin(2*Mpr + F)
+    + 0.009267 * sin(2*D + Mpr - F)
+    + 0.008823 * sin(2*Mpr - F)
+    + e * 0.008247 * sin(2*D - M - F)
+    + 0.004323 * sin(2*D - F - 2*Mpr)
+    + 0.004200 * sin(2*D + F + Mpr)
+    + e * 0.003372 * sin(F - M - 2*D)
+    + 0.002472 * sin(2*D + F - M - Mpr)
+    + e * 0.002222 * sin(2*D + F - M)
+    + e * 0.002072 * sin(2*D - F - M - Mpr)
+    + e * 0.001877 * sin(F - M + Mpr)
+    + 0.001828 * sin(4*D - F - Mpr)
+    - e * 0.001803 * sin(F + M)
+    - 0.001750 * sin(3*F)
+    + e * 0.001570 * sin(Mpr - M - F)
+    - 0.001487 * sin(F + D)
+    - e * 0.001481 * sin(F + M + Mpr)
+    + e * 0.001417 * sin(F - M - Mpr)
+    + e * 0.001350 * sin(F - M)
+    + 0.001330 * sin(F - D)
+    + 0.001106 * sin(F + 3*Mpr)
+    + 0.001020 * sin(4*D - F)
+    + 0.000833 * sin(F + 4*D - Mpr);
+  /* not only that, but */
+  B = B + 0.000781 * sin(Mpr - 3*F)
+    + 0.000670 * sin(F + 4*D - 2*Mpr)
+    + 0.000606 * sin(2*D - 3*F)
+    + 0.000597 * sin(2*D + 2*Mpr - F)
+    + e * 0.000492 * sin(2*D + Mpr - M - F)
+    + 0.000450 * sin(2*Mpr - F - 2*D)
+    + 0.000439 * sin(3*Mpr - F)
+    + 0.000423 * sin(F + 2*D + 2*Mpr)
+    + 0.000422 * sin(2*D - F - 3*Mpr)
+    - e * 0.000367 * sin(M + F + 2*D - Mpr)
+    - e * 0.000353 * sin(M + F + 2*D)
+    + 0.000331 * sin(F + 4*D)
+    + e * 0.000317 * sin(2*D + F - M + Mpr)
+    + e * e * 0.000306 * sin(2*D - 2*M - F)
+    - 0.000283 * sin(Mpr + 3*F);
+
+  om1 = 0.0004664 * cos(Om/DEG_IN_RADIAN);
+  om2 = 0.0000754 * cos((Om + 275.05 - 2.30*T)/DEG_IN_RADIAN);
+
+  beta = B * (1. - om1 - om2);
+  /*      *eclatit = beta; */
+
+  pie = 0.950724
+    + 0.051818 * cos(Mpr)
+    + 0.009531 * cos(2*D - Mpr)
+    + 0.007843 * cos(2*D)
+    + 0.002824 * cos(2*Mpr)
+    + 0.000857 * cos(2*D + Mpr)
+    + e * 0.000533 * cos(2*D - M)
+    + e * 0.000401 * cos(2*D - M - Mpr)
+    + e * 0.000320 * cos(Mpr - M)
+    - 0.000271 * cos(D)
+    - e * 0.000264 * cos(M + Mpr)
+    - 0.000198 * cos(2*F - Mpr)
+    + 0.000173 * cos(3*Mpr)
+    + 0.000167 * cos(4*D - Mpr)
+    - e * 0.000111 * cos(M)
+    + 0.000103 * cos(4*D - 2*Mpr)
+    - 0.000084 * cos(2*Mpr - 2*D)
+    - e * 0.000083 * cos(2*D + M)
+    + 0.000079 * cos(2*D + 2*Mpr)
+    + 0.000072 * cos(4*D)
+    + e * 0.000064 * cos(2*D - M + Mpr)
+    - e * 0.000063 * cos(2*D + M - Mpr)
+    + e * 0.000041 * cos(M + D)
+    + e * 0.000035 * cos(2*Mpr - M)
+    - 0.000033 * cos(3*Mpr - 2*D)
+    - 0.000030 * cos(Mpr + D)
+    - 0.000029 * cos(2*F - 2*D)
+    - e * 0.000029 * cos(2*Mpr + M)
+    + e * e * 0.000026 * cos(2*D - 2*M)
+    - 0.000023 * cos(2*F - 2*D + Mpr)
+    + e * 0.000019 * cos(4*D - M - Mpr);
+
+  beta = beta/DEG_IN_RADIAN;
+  lambda = lambda/DEG_IN_RADIAN;
+  l = cos(lambda) * cos(beta);
+  m = sin(lambda) * cos(beta);
+  n = sin(beta);
+  eclrot(jd,&l,&m,&n);
+
+  dist = 1/sin((pie)/DEG_IN_RADIAN);
+  x = l * dist;
+  y = m * dist;
+  z = n * dist;
+
+  *geora = atan_circ(l,m) * HRS_IN_RADIAN;
+  *geodec = asin(n) * DEG_IN_RADIAN;
+  *geodist = dist;
+
+  geocent (lst, geolat, elevsea, &x_geo, &y_geo, &z_geo);
+
+  x = x - x_geo;  /* topocentric correction using elliptical earth fig. */
+  y = y - y_geo;
+  z = z - z_geo;
+
+  *topodist = sqrt(x*x + y*y + z*z);
+
+  l = x / (*topodist);
+  m = y / (*topodist);
+  n = z / (*topodist);
+
+  *topora = atan_circ(l,m) * HRS_IN_RADIAN;
+  *topodec = asin(n) * DEG_IN_RADIAN;
+
+}
+
+/* returns jd at which moon is at a given
+   altitude, given jdguess as a starting point. In current version
+   uses high-precision moon -- execution time does not seem to be
+   excessive on modern hardware.  If it's a problem on your machine,
+   you can replace calls to 'accumoon' with 'lpmoon' and remove
+   the 'elevsea' argument. */
+double jd_moon_alt (double alt, double jdguess, double lat, double longit, double elevsea) {
+
+  double jdout;
+  double deriv, err, del = 0.002;
+  double ra,dec,dist,geora,geodec,geodist,sid,ha,alt2,alt3,az;
+  short i = 0;
+
+  /* first guess */
+
+  sid=lst(jdguess,longit);
+  accumoon(jdguess,lat,sid,elevsea,&geora,&geodec,&geodist,
+	   &ra,&dec,&dist);
+  ha = lst(jdguess,longit) - ra;
+  alt2 = altit(dec,ha,lat,&az);
+  jdguess = jdguess + del;
+  sid = lst(jdguess,longit);
+  accumoon(jdguess,lat,sid,elevsea,&geora,&geodec,&geodist,
+	   &ra,&dec,&dist);
+  alt3 = altit(dec,(sid - ra),lat,&az);
+  err = alt3 - alt;
+  deriv = (alt3 - alt2) / del;
+  while((fabs(err) > 0.1) && (i < 10)) {
+    jdguess = jdguess - err/deriv;
+    sid=lst(jdguess,longit);
+    accumoon(jdguess,lat,sid,elevsea,&geora,&geodec,&geodist,
+	     &ra,&dec,&dist);
+    alt3 = altit(dec,(sid - ra),lat,&az);
+    err = alt3 - alt;
+    i++;
+  }
+  if(i >= 9) jdguess = -1000.;
+  jdout = jdguess;
+  return(jdout);
+}
+
+/* Given site position, return Moonset for closest midnight */
+double moonset_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+
+  double jd, jdmid, stmid;
+  double min_alt, max_alt;
+  double geora, geodec, geodist;  /* geocent for moon, not used here.*/
+  double ramoon, decmoon, distmoon;
+  double hamoonrise, hamoonset, tmoonrise, tmoonset, jdmoonrise, jdmoonset;
+  short dow; /* day of week */
+  struct SC_date_time date_midnight, tmpdate;
+  double dt, lst0, lst1, djd, horiz;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid = date_to_jd (date_midnight) - dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  accumoon (jdmid,lat,stmid,elevsea,&geora,&geodec,&geodist,&ramoon,&decmoon,&distmoon);
+
+  min_max_alt (lat,decmoon,&min_alt,&max_alt);  /* rough check -- occurs? */
+  if (max_alt < -(0.83+horiz)) return (-1);
+  if (min_alt > -(0.83+horiz)) return (-1);
+
+  /* compute moonrise and set if they're likely to occur */
+
+  hamoonset = ha_alt(decmoon,lat,-(0.83+horiz)); /* rough approx. */
+
+  tmoonset = adj_time(ramoon+hamoonset-stmid);
+  jdmoonset = jdmid + tmoonset / 24.;
+  jdmoonset = jd_moon_alt(-(0.83+horiz),jdmoonset,lat,longit,elevsea);
+
+  return (jdmoonset);
+
+}
+
+/* Given site position, return Moonrise for closest midnight */
+double moonrise_tonight (struct SC_date_time date, double lat, double longit, double elevsea, double elev) {
+
+  double jd, jdmid, stmid;
+  double min_alt, max_alt;
+  double geora, geodec, geodist;  /* geocent for moon, not used here.*/
+  double ramoon, decmoon, distmoon;
+  double hamoonrise, hamoonset, tmoonrise, tmoonset, jdmoonrise, jdmoonset;
+  short dow; /* day of week */
+  struct SC_date_time date_midnight, tmpdate;
+  double dt, lst0, lst1, djd, horiz;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid = date_to_jd (date_midnight) - dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  accumoon (jdmid,lat,stmid,elevsea,&geora,&geodec,&geodist,&ramoon,&decmoon,&distmoon);
+
+  min_max_alt (lat,decmoon,&min_alt,&max_alt);  /* rough check -- occurs? */
+  if (max_alt < -(0.83+horiz)) return (-1);
+  if (min_alt > -(0.83+horiz)) return (-1);
+
+  /* compute moonrise and set if they're likely to occur */
+
+  hamoonset = ha_alt(decmoon,lat,-(0.83+horiz)); /* rough approx. */
+
+  tmoonrise = adj_time(ramoon-hamoonset-stmid);
+  jdmoonrise = jdmid + tmoonrise / 24.;
+  jdmoonrise = jd_moon_alt(-(0.83+horiz),jdmoonrise,lat,longit,elevsea);
+
+  return (jdmoonrise);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/moon_interference.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/moon_interference.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/moon_interference.c	(revision 16632)
@@ -0,0 +1,875 @@
+/*
+   This program segment is extracted from the skycalc program written
+   by John Thorstensen from Dartmouth College.  For question please
+   contact: John.Thorstensen@Dartmouth.edu
+   This is one long and ugly, but accurate program.  Ideally I should
+   have split this into separate modules, but this may be replaced by
+   Bernt's algorithm anyway... so "let's wait and see what happens"   
+   -Rosemary Alles 04/18/2001
+   */
+
+#include <stdio.h>
+#include <math.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+
+/* some (not all) physical, mathematical, and astronomical constants
+   used are defined here. */
+#define  DEG_IN_RADIAN     57.2957795130823
+#define  HRS_IN_RADIAN     3.819718634205
+#define  EQUAT_RAD         6378137.    /* equatorial radius of earth, meters */
+#define  TWOPI             6.28318530717959
+#define  J2000             2451545.    /* Julian date at standard epoch */
+#define  SEC_IN_DAY        86400.
+
+struct coord {
+    short sign;  /* carry sign explicitly since -0 not neg. */
+    double hh;
+    double mm;
+    double ss;
+};
+
+struct date_time {
+    short y;
+    short mo;
+    short d;
+    short h;
+    short mn;
+    float s;
+};
+
+/* Gloabals */
+int update_on = 0; 
+double update_delta = 0.;
+
+/* Prototypes */
+void load_site(double* longit, double* lat, double* stdz,
+               short* use_dst, char* zone_name, char* zabr,
+               double* elevsea, double* elev, double* horiz,
+               char* site_name);
+double zone(short use_dst, double stdz,
+            double jd, double jdb, double jde);
+void caldat(double jdin, struct date_time* date, short *dow);
+short day_of_week(double jd);
+double day_of_year(double jd);
+void find_dst_bounds(short yr, double stdz, short use_dst,
+                     double *jdb, double* jde);
+int get_sys_date(struct date_time *date, short use_dst, short enter_ut,
+                 short night_date, double stdz, double toffset, double* jd);
+double lst(double jd, double longit);
+double date_to_jd(struct date_time date);
+void lpmoon(double jd, double lat, double sid,
+            double* ra, double* dec, double* dist);
+void put_coords(double deci, int precision, int showsign);
+double get_coord(void);
+void dec_to_bab (double deci, struct coord* bab);
+double atan_circ(double x, double y);
+double adj_time(double x);
+
+    
+void
+load_site(double* longit, double* lat, double* stdz,
+          short* use_dst, char* zone_name, char* zabr,
+          double* elevsea, double* elev, double* horiz,
+          char* site_name) {
+              
+/* sets the site-specific quantities; these are
+   longit     = W longitude in decimal hours
+   lat        = N latitude in decimal degrees
+   stdz       = standard time zone offset, hours
+   elevsea    = elevation above sea level (for absolute location)
+   elev       = observatory elevation above horizon, meters
+   horiz      = (derived) added zenith distance for rise/set due
+                to elevation
+   use_dst    = 0 don't use it
+                1 use USA convention
+                2 use Spanish convention
+                < 0 Southern hemisphere (reserved, unimplimented)
+   zone_name  = name of time zone, e. g. Eastern
+   zabr       = single-character abbreviation of time zone
+   site_name  = name of site.  */
+    
+    strcpy(site_name, "Mauna Kea, Hawaii");
+    strcpy(zone_name, "Hawaiian");
+    *zabr = 'H';
+    *use_dst = 0;
+    *longit = 10.36478;
+    *lat = 19.8267;
+    *elevsea = 4215.;
+    *elev = 4215.;  /* yow! */
+    *stdz = 10.;
+
+    /* now compute derived quantity "horiz" = depression of horizon.*/
+    *horiz = sqrt(2. * *elev / EQUAT_RAD) * DEG_IN_RADIAN;   
+}
+
+double
+zone(short use_dst, double stdz,
+     double jd, double jdb, double jde) {
+    
+    /* Returns zone time offset when standard time zone is stdz,
+       when daylight time begins (for the year) on jdb, and ends
+       (for the year) on jde.  This is parochial to the northern
+       hemisphere.  */
+    /* Extension -- specifying a negative value of use_dst reverses
+       the logic for the Southern hemisphere; then DST is assumed for
+       the Southern hemisphere summer (which is the end and beginning
+       of the year. */
+    
+    if(use_dst == 0) return(stdz);
+    else if((jd > jdb) && (jd < jde) && (use_dst > 0)) return(stdz-1.);
+    /* next line .. use_dst < 0 .. for Southern Hemisphere sites. */
+    else if(((jd < jdb) || (jd > jde)) && (use_dst < 0)) return(stdz-1.);
+    else return(stdz);
+}
+
+void
+caldat(double jdin, struct date_time* date, short *dow) {
+
+    /* from Jean Meeus, Astronomical Formulae for Calculators,
+       published by Willman-Bell Inc.
+       Avoids a copyrighted routine from Numerical Recipes.
+       Tested and works properly from the beginning of the 
+       Gregorian calendar era (1583) to beyond 3000 AD. */
+
+    double jdtmp;
+    long alpha;
+    long Z;
+    long A, B, C, D, E;
+    double F; 
+    double x;   /* for day-of-week calculation */
+
+    jdtmp = jdin + 0.5;
+
+    Z = (long) jdtmp;
+
+    x = Z/7.+0.01;
+    *dow = 7.*(x - (long) x);   /* truncate for day of week */
+
+    F = jdtmp - Z;
+
+    if(Z < 2299161) A = Z;
+    else {
+        alpha = (long) ((Z - 1867216.25) / 36524.25);
+        A = Z + 1 + alpha - (long) (alpha / 4);
+    }
+
+    B = A + 1524;
+    C = ((B - 122.1) / 365.25);
+    D =  (365.25 * C);\
+    E =  ((B - D) / 30.6001);
+
+    date->d = B - D - (long)(30.6001 * E);
+    if(E < 13.5) date->mo = E - 1;
+    else date->mo = E - 13;
+    if(date->mo  > 2.5)  date->y = C - 4716;
+    else date->y = C - 4715;
+	
+    date->h = F * 24.;  /* truncate */
+    date->mn = (F - ((float) date->h)/24.) * 1440.;
+    date->s = (F - ((float) date->h)/24. -
+               ((float) date->mn)/1440.) * 86400;
+	
+}
+
+short
+day_of_week(double jd) { 
+
+    /* returns day of week for a jd, 0 = Mon, 6 = Sun. */
+    
+    double x;
+    long i;
+    short d;
+    
+    jd = jd+0.5;
+    i = jd; /* truncate */
+    x = i/7.+0.01; 
+    d = 7.*(x - (long) x);   /* truncate */
+    return(d);
+}
+
+double
+day_of_year(double jd) {
+    
+    double jdjan0;
+    struct date_time date;
+    short dow;
+    
+    caldat(jd,&date,&dow);
+    /* find jd of "jan 0" = Dec 31 of previous year */
+    date.y = date.y - 1;
+    date.mo = 12;
+    date.d = 31;
+    date.h = 0;
+    date.mn = 0;
+    date.s = 0.;
+    jdjan0 = date_to_jd(date);
+    return(jd - jdjan0);
+}
+
+void
+find_dst_bounds(short yr, double stdz, short use_dst,
+                double *jdb, double* jde) {
+    
+	/* finds jd's at which daylight savings time begins 
+	    and ends.  The parameter use_dst allows for a number
+	    of conventions, namely:
+		0 = don't use it at all (standard time all the time)
+		1 = use USA convention (1st Sun in April to
+		     last Sun in Oct after 1986; last Sun in April before)
+		2 = use Spanish convention (for Canary Islands)
+		-1 = use Chilean convention (CTIO).
+		-2 = Australian convention (for AAT).
+	    Negative numbers denote sites in the southern hemisphere,
+	    where jdb and jde are beginning and end of STANDARD time for
+	    the year. 
+	    It's assumed that the time changes at 2AM local time; so
+	    when clock is set ahead, time jumps suddenly from 2 to 3,
+	    and when time is set back, the hour from 1 to 2 AM local 
+	    time is repeated.  This could be changed in code if need be. */
+
+	struct date_time trial;
+
+	if((use_dst == 1) || (use_dst == 0)) { 
+	    /* USA Convention, and including no DST to be defensive */
+	    /* Note that this ignores various wrinkles such as the
+		brief Nixon administration flirtation with year-round DST,
+		the extended DST of WW II, and so on. */
+		trial.y = yr;
+		trial.mo = 4;
+		if(yr >= 1986) trial.d = 1;
+		else trial.d = 30; 
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		/* Find first Sunday in April for 1986 on ... */
+		if(yr >= 1986) 
+			while(day_of_week(date_to_jd(trial)) != 6) 
+				trial.d++;
+			
+		/* Find last Sunday in April for pre-1986 .... */
+		else while(day_of_week(date_to_jd(trial)) != 6) 
+				trial.d--;
+
+		*jdb = date_to_jd(trial) + stdz/24.;    
+
+		/* Find last Sunday in October ... */
+		trial.mo = 10;
+		trial.d = 31;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jde = date_to_jd(trial) + (stdz - 1.)/24.;             
+	}
+	else if (use_dst == 2) {  /* Spanish, for Canaries */
+		trial.y = yr;
+		trial.mo = 3;
+		trial.d = 31; 
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jdb = date_to_jd(trial) + stdz/24.;    
+		trial.mo = 9;
+		trial.d = 30;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jde = date_to_jd(trial) + (stdz - 1.)/24.;             
+	}               
+	else if (use_dst == -1) {  /* Chilean, for CTIO, etc.  */
+	   /* off daylight 2nd Sun in March, onto daylight 2nd Sun in October */
+		trial.y = yr;
+		trial.mo = 3;
+		trial.d = 8;  /* earliest possible 2nd Sunday */
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d++;
+		}
+		*jdb = date_to_jd(trial) + (stdz - 1.)/24.;
+			/* note jdb is beginning of STANDARD time in south,
+				hence use stdz - 1. */  
+		trial.mo = 10;
+		trial.d = 8;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d++;
+		}
+		*jde = date_to_jd(trial) + stdz /24.;           
+	}                       
+	else if (use_dst == -2) {  /* For Anglo-Australian Telescope  */
+	   /* off daylight 1st Sun in March, onto daylight last Sun in October */
+		trial.y = yr;
+		trial.mo = 3;
+		trial.d = 1;  /* earliest possible 1st Sunday */
+		trial.h = 2;
+		trial.mn = 0;
+		trial.s = 0;
+
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d++;
+		}
+		*jdb = date_to_jd(trial) + (stdz - 1.)/24.;
+			/* note jdb is beginning of STANDARD time in south,
+				hence use stdz - 1. */  
+		trial.mo = 10;
+		trial.d = 31;
+		while(day_of_week(date_to_jd(trial)) != 6) {
+			trial.d--;
+		}
+		*jde = date_to_jd(trial) + stdz /24.;           
+	}               
+}
+
+int
+get_sys_date(struct date_time *date, short use_dst, short enter_ut,
+             short night_date, double stdz, double toffset, double* jd) {
+
+    /* Reads the system clock; loads up the date structure
+       to conform to the prevailing conventions for the interpretation
+       of times.  Optionally adds "toffset" minutes to the system
+       clock, as in x minutes in the future. */
+
+    time_t t, *tp;
+    struct tm *stm;
+    double jdb, jde;
+    short dow;
+
+    tp = &t;  /* have to initialize pointer variable for it to
+                 serve as an argument. */
+
+    t = time(tp);
+    if(t == -1) {
+        printf("error: system time unavailable during calculation of moon interference\n");
+        return(-1);
+    }
+    stm = localtime(&t);
+    date->y = (short) (stm->tm_year + 1900);
+    date->mo = (short) (stm->tm_mon + 1);
+    date->d = (short) (stm->tm_mday);
+    date->h = (short) (stm->tm_hour);
+    date->mn = (short) (stm->tm_min);
+    date->s = (float) (stm->tm_sec);
+
+    if(toffset != 0.) {
+        *jd = date_to_jd(*date);
+        *jd = *jd + toffset / 1440.;
+        caldat(*jd,date,&dow);
+    }
+
+    if(enter_ut == 1)  { /* adjust if needed */
+        find_dst_bounds(date->y,stdz,use_dst,&jdb,&jde);
+        *jd = date_to_jd(*date);
+        *jd = *jd + zone(use_dst,stdz,*jd,jdb,jde)/24.;
+        caldat(*jd,date,&dow);
+    }
+    if((night_date == 1) && (date->h < 12)) {
+        date->d = date->d - 1;
+    }
+
+    return(0); /* success */
+}
+
+double
+lst(double jd, double longit) {
+
+    /* returns the local MEAN sidereal time (dec hrs) at julian date jd
+       at west longitude long (decimal hours).  Follows
+       definitions in 1992 Astronomical Almanac, pp. B7 and L2. 
+       Expression for GMST at 0h ut referenced to Aoki et al, A&A 105,
+       p.359, 1982.  On workstations, accuracy (numerical only!)
+       is about a millisecond in the 1990s. */
+
+    double t, ut, jdmid, jdint, jdfrac, sid_g;
+    long jdin, sid_int;
+
+    jdin = jd;         /* fossil code from earlier package which 
+                          split jd into integer and fractional parts ... */
+    jdint = jdin;
+    jdfrac = jd - jdint;
+    if(jdfrac < 0.5) {
+        jdmid = jdint - 0.5;
+        ut = jdfrac + 0.5;
+    }
+    else {
+        jdmid = jdint + 0.5;
+        ut = jdfrac - 0.5;
+    }
+    t = (jdmid - J2000)/36525;
+    sid_g = (24110.54841+8640184.812866*t+0.093104*t*t-6.2e-6*t*t*t)/SEC_IN_DAY;
+    sid_int = sid_g;
+    sid_g = sid_g - (double) sid_int;
+    sid_g = sid_g + 1.0027379093 * ut - longit/24.;
+    sid_int = sid_g;
+    sid_g = (sid_g - (double) sid_int) * 24.;
+    if(sid_g < 0.) sid_g = sid_g + 24.;
+    return(sid_g);
+}
+
+
+double
+date_to_jd(struct date_time date) {
+    
+/* From Meeus' Astronomical Formulae for Calculators.  The two JD
+   conversion routines routines were replaced 1998 November 29 to
+   avoid inclusion of copyrighted "Numerical Recipes" code.  A test
+   of 1 million random JDs between 1585 and 3200 AD gave the same
+   conversions as the NR routines. */
+
+
+    double jd;
+    int y, m;
+    long A, B;
+
+    if(date.mo <= 2) {
+        y = date.y - 1;
+        m = date.mo + 12;
+    }
+    else {
+        y = date.y;
+        m = date.mo;
+    }
+
+    A = (long) (y / 100.);
+    B = 2 - A + (long) (A / 4.);
+
+    jd = (long) (365.25 * y) + (long) (30.6001 * (m + 1)) + date.d + 
+        1720994.5;
+
+    jd += date.h / 24. + date.mn / 1440. + date.s / 86400.;
+
+    if(date.y > 1583) return(jd + B);  
+    else return(jd);
+    /* Not quite right, since Gregorian calendar first
+       adopted around Oct 1582.  But fine for modern. */
+}
+
+void
+lpmoon(double jd, double lat, double sid,
+       double* ra, double* dec, double* dist) {
+
+
+/* implements "low precision" moon algorithms from
+   Astronomical Almanac (p. D46 in 1992 version).  Does
+   apply the topocentric correction. 
+   Units are as follows
+   jd,lat, sid;   decimal hours 
+   *ra, *dec,   decimal hours, degrees 
+   *dist;      earth radii */
+
+
+    double T, lambda, beta, pie, l, m, n, x, y, z, alpha, delta,
+        rad_lat, rad_lst, distance, topo_dist;
+    char dummy[40];  /* to fix compiler bug on IBM system */
+
+    T = (jd - J2000) / 36525.;  /* jul cent. since J2000.0 */
+
+    lambda = 218.32 + 481267.883 * T 
+        + 6.29 * sin((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        - 1.27 * sin((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.66 * sin((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.21 * sin((269.9 + 954397.70 * T) / DEG_IN_RADIAN)
+        - 0.19 * sin((357.5 + 35999.05 * T) / DEG_IN_RADIAN)
+        - 0.11 * sin((186.6 + 966404.05 * T) / DEG_IN_RADIAN);
+    lambda = lambda / DEG_IN_RADIAN;
+    beta = 5.13 * sin((93.3 + 483202.03 * T) / DEG_IN_RADIAN)
+        + 0.28 * sin((228.2 + 960400.87 * T) / DEG_IN_RADIAN)
+        - 0.28 * sin((318.3 + 6003.18 * T) / DEG_IN_RADIAN)
+        - 0.17 * sin((217.6 - 407332.20 * T) / DEG_IN_RADIAN);
+    beta = beta / DEG_IN_RADIAN;
+    pie = 0.9508 
+        + 0.0518 * cos((134.9 + 477198.85 * T) / DEG_IN_RADIAN)
+        + 0.0095 * cos((259.2 - 413335.38 * T) / DEG_IN_RADIAN)
+        + 0.0078 * cos((235.7 + 890534.23 * T) / DEG_IN_RADIAN)
+        + 0.0028 * cos((269.9 + 954397.70 * T) / DEG_IN_RADIAN);
+    pie = pie / DEG_IN_RADIAN;
+    distance = 1 / sin(pie);
+
+    l = cos(beta) * cos(lambda);
+    m = 0.9175 * cos(beta) * sin(lambda) - 0.3978 * sin(beta);
+    n = 0.3978 * cos(beta) * sin(lambda) + 0.9175 * sin(beta);
+
+    x = l * distance; 
+    y = m * distance; 
+    z = n * distance;  /* for topocentric correction */
+
+
+    /* lat isn't passed right on some IBM systems unless you do this
+       or something like it! */
+    sprintf(dummy,"%f",lat);
+
+    rad_lat = lat / DEG_IN_RADIAN;
+    rad_lst = sid / HRS_IN_RADIAN;
+
+    x = x - cos(rad_lat) * cos(rad_lst);
+    y = y - cos(rad_lat) * sin(rad_lst);
+    z = z - sin(rad_lat);
+
+
+    topo_dist = sqrt(x * x + y * y + z * z);
+
+    l = x / topo_dist; 
+    m = y / topo_dist; 
+    n = z / topo_dist;
+
+    alpha = atan_circ(l,m);
+    delta = asin(n);
+
+    *ra = alpha * HRS_IN_RADIAN;
+
+    *dec = delta * DEG_IN_RADIAN;
+    
+    *dist = topo_dist;
+
+}
+
+
+void
+put_coords(double deci, int precision, int showsign) {
+
+
+/* prints out a struct coord in a nice format; precision
+   is a code for how accurate you want it.  The options are:
+     precision = 0;   minutes rounded to the nearest minute
+     precision = 1;   minutes rounded to the nearest tenth.
+     precision = 2;   seconds rounded to the nearest second
+     precision = 3;   seconds given to the tenth
+     precision = 4;   seconds given to the hundredth
+   The program assumes that the line is ready for the coord
+   to be printed and does NOT deliver a new line at the end
+   of the output. */
+
+   
+   double minutes;  /* for rounding off if necess. */
+   struct coord out_coord, coords;
+   char out_string[20];  /* for checking for nasty 60's */
+
+   dec_to_bab(deci,&coords);  /* internally convert to coords*/
+
+   if(coords.sign == -1) printf("-");
+	else printf(" "); /* to preserve alignment */
+
+   if(precision == 0) {   /* round to nearest minute */
+      minutes = coords.mm + coords.ss / 60.;
+           /* check to be sure minutes aren't 60 */
+      sprintf(out_string,"%.0f %02.0f",coords.hh,minutes);
+      sscanf(out_string,"%lf %lf",&out_coord.hh,&out_coord.mm);
+      if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+         out_coord.mm = 0.;
+         out_coord.hh = out_coord.hh + 1.;
+      }
+      printf("%2.0f:%02.0f",out_coord.hh,out_coord.mm);
+   }
+
+   else if(precision == 1) {    /* keep nearest tenth of a minute */
+      minutes = coords.mm + coords.ss / 60.;
+           /* check to be sure minutes are not 60 */
+      sprintf(out_string,"%.0f %04.1f",coords.hh,minutes);
+      sscanf(out_string,"%lf %lf",&out_coord.hh, &out_coord.mm);
+      if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+         out_coord.mm = 0.;
+         out_coord.hh = out_coord.hh + 1.;
+      }
+      printf("%2.0f:%04.1f", out_coord.hh, out_coord.mm);
+   }
+   else if(precision == 2) {
+          /* check to be sure seconds are not 60 */
+      sprintf(out_string,"%.0f %02.0f %02.0f",coords.hh,coords.mm,coords.ss);
+      sscanf(out_string,"%lf %lf %lf",&out_coord.hh,&out_coord.mm,
+           &out_coord.ss);
+      if(fabs(out_coord.ss - 60.) < 1.0e-7) {
+          out_coord.mm = out_coord.mm + 1.;
+          out_coord.ss = 0.;
+          if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+              out_coord.hh = out_coord.hh + 1.;
+              out_coord.mm = 0.;
+          }
+      }
+      printf("%2.0f:%02.0f:%02.0f",out_coord.hh,out_coord.mm,out_coord.ss);
+   }
+   else if(precision == 3) {
+          /* the usual shuffle to check for 60's */
+      sprintf(out_string,"%.0f %02.0f %04.1f",coords.hh, coords.mm, coords.ss);
+      sscanf(out_string,"%lf %lf %lf",&out_coord.hh,&out_coord.mm,
+           &out_coord.ss);
+      if(fabs(out_coord.ss - 60.) < 1.0e-7) {
+          out_coord.mm = out_coord.mm + 1.;
+          out_coord.ss = 0.;
+          if(fabs(out_coord.mm - 60.) < 1.0e-7) {
+             out_coord.hh = out_coord.hh + 1.;
+             out_coord.mm = 0.;
+          }
+      }
+      printf("%2.0f:%02.0f:%04.1f",out_coord.hh,out_coord.mm,out_coord.ss);
+   }
+   else {
+      sprintf(out_string,"%.0f %02.0f %05.2f",coords.hh,coords.mm,coords.ss);
+      sscanf(out_string,"%lf %lf %lf",&out_coord.hh,&out_coord.mm,
+           &out_coord.ss);
+      if(fabs(out_coord.ss - 60.) < 1.0e-6) {
+         out_coord.mm = out_coord.mm + 1.;
+         out_coord.ss = 0.;
+         if(fabs(out_coord.mm - 60.) < 1.0e-6) {
+            out_coord.hh = out_coord.hh + 1.;
+            out_coord.mm = 0.;
+         }
+      }
+      printf("%2.0f:%02.0f:%05.2f",out_coord.hh, out_coord.mm, out_coord.ss);
+   }
+}
+
+
+double
+get_coord(void) {
+
+/* Reads a string from the terminal and converts it into
+   a double-precision coordinate.  This is trickier than 
+   it appeared at first, since a -00 tests as non-negative; 
+   the sign has to be picked out and handled explicitly. */
+/* Prompt for input in the calling routine.*/
+
+   short sign;
+   double hrs, mins, secs;
+   char hh_string[6];  /* string with the first coord (hh) */
+   char hh1[1];
+   short i = 0;
+
+   /* read and handle the hour (or degree) part with sign */
+
+   scanf("%s",hh_string);
+   hh1[0] = hh_string[i];
+
+   while(hh1[0] == ' ') {
+       /* discard leading blanks */
+       i++;
+       hh1[0] = hh_string[i];
+   }
+
+   if(hh1[0] == '-') sign = -1;
+
+     else sign = 1;
+
+   sscanf(hh_string,"%lf", &hrs);
+   if(sign == -1) hrs = -1. * hrs;
+
+   /* read in the minutes and seconds normally */
+   scanf("%lf %lf",&mins,&secs);
+
+   return(sign * (hrs + mins / 60. + secs / 3600.));
+}
+
+void
+dec_to_bab (double deci, struct coord* bab) {
+
+    /* function for converting decimal to babylonian hh mm ss.ss */
+    int hr_int, min_int;
+    
+    if (deci >= 0.) bab->sign = 1; 
+    else {
+        bab->sign = -1;
+        deci = -1. * deci;
+    }
+    hr_int = deci;   /* use conversion conventions to truncate */
+    bab->hh = hr_int;
+    min_int = 60. * (deci - bab->hh);
+    bab->mm = min_int;
+    bab->ss = 3600. * (deci - bab->hh - bab->mm / 60.);
+}
+
+double
+atan_circ(double x, double y) {
+    
+    /* returns radian angle 0 to 2pi for coords x, y --
+       get that quadrant right !! */
+    
+    double theta;
+    
+    if((x == 0.) && (y == 0.)) return(0.);  /* guard ... */
+    
+    theta = atan2(y,x);  /* turns out there is such a thing in math.h */
+    while(theta < 0.) theta += TWOPI;
+    return(theta);
+}
+
+
+double
+adj_time(double x) {
+
+    /* adjusts a time (decimal hours) to be between -12 and 12, 
+       generally used for hour angles.  */
+    
+    if(fabs(x) < 100000.) {  /* too inefficient for this! */
+        while(x > 12.) {
+            x = x - 24.;
+        }
+        while(x < -12.) {
+            x = x + 24.;
+        }
+    }
+
+    else printf("warning: Out of bounds in adj_time in moon interference routine!\n");
+
+    return(x);
+}
+
+double
+altit(double dec, double ha, double lat,
+      double* az, double *parang) {
+            
+/*
+  returns altitude(degr) for dec, ha, lat (decimal degr, hr, degr); 
+  also computes and returns azimuth through pointer argument,
+  and as an extra added bonus returns parallactic angle (decimal degr)
+  through another pointer argument.
+  */
+
+    double x,y,z;
+    double sinp, cosp;  /* sin and cos of parallactic angle */
+    double cosdec, sindec, cosha, sinha, coslat, sinlat;
+    /* time-savers ... */
+    
+    dec = dec / DEG_IN_RADIAN;
+    ha = ha / HRS_IN_RADIAN;
+    lat = lat / DEG_IN_RADIAN;  /* thank heavens for pass-by-value */
+    cosdec = cos(dec); sindec = sin(dec);
+    cosha = cos(ha); sinha = sin(ha);
+    coslat = cos(lat); sinlat = sin(lat);
+    x = DEG_IN_RADIAN * asin(cosdec*cosha*coslat + sindec*sinlat);
+    y =  sindec*coslat - cosdec*cosha*sinlat; /* due N comp. */
+    z =  -1. * cosdec*sinha; /* due east comp. */
+    *az = atan2(z,y);   
+    
+    /* as it turns out, having knowledge of the altitude and 
+       azimuth makes the spherical trig of the parallactic angle
+       less ambiguous ... so do it here!  Method uses the 
+       "astronomical triangle" connecting celestial pole, object,
+       and zenith ... now know all the other sides and angles,
+       so we can crush it ... */
+    
+    if(cosdec != 0.) { /* protect divide by zero ... */ 
+        sinp = -1. * sin(*az) * coslat / cosdec;
+        /* spherical law of sines .. note cosdec = sin of codec,
+           coslat = sin of colat .... */
+        cosp = -1. * cos(*az) * cosha - sin(*az) * sinha * sinlat;
+        /* spherical law of cosines ... also transformed to local
+           available variables. */
+	   *parang = atan2(sinp,cosp) * DEG_IN_RADIAN;
+           /* let the library function find the quadrant ... */
+    }
+    else { /* you're on the pole */
+        if(lat >= 0.) *parang = 180.;
+        else *parang = 0.;
+    }
+    
+    *az *= DEG_IN_RADIAN;  /* done with taking trig functions of it ... */ 
+    while(*az < 0.) *az += 360.;  /* force 0 -> 360 */
+    while(*az >= 360.) *az -= 360.;
+    
+    return(x);
+}
+
+
+int
+main(void) {
+
+    /* Site specific parameters */
+    double longit, lat;
+    double stdz;
+    short use_dst;
+    char zabr;
+    double elevsea;
+    double elev, horiz;
+
+    char site_name[45];  /* initialized later with
+                            strcpy for portability */
+    char zone_name[25];  /* this too */
+
+    struct date_time date;
+    double jd, sid;    
+
+    /* Position of moon */    
+    double ra, dec, dist;    
+    double ha, az, par, alt;    
+    
+    /* Misc stuff */
+    short enter_ut = 1;
+    short night_date = 0;
+    
+    /* Load site specific information */
+    load_site(&longit,&lat,&stdz,&use_dst,zone_name,&zabr,
+          &elevsea,&elev,&horiz,site_name);
+
+    /* Get system date and calculate julian date */
+    if (get_sys_date(&date, use_dst, enter_ut, night_date, stdz,
+                     update_delta, &jd) != 0) { 
+        printf("error: Can't get system date! \n");
+        return(-1);
+    }
+
+    /* Calcualte local sidereal time */
+    sid = lst(jd, longit);
+
+    /* Calculate position of moon */
+    lpmoon(jd, lat, sid, &ra, &dec, &dist);
+
+    ha = adj_time(sid - ra);
+    
+    alt=altit(dec, ha, lat, &az, &par);
+
+    /* Debug section
+      printf("moon ra = ");    
+      put_coords(ra, 2, 1);    
+      printf("\n"); 
+      printf("moon dec = ");  
+      put_coords(dec, 2, 1); 
+      printf("\n");
+      printf("moon ha = "); 
+      put_coords(ha, 2, 1); 
+      printf("\n");
+      printf("moon altitude = %.2f\n", alt); 
+      printf("moon zenith-distance = %.2f\n", 90 - alt);    
+      */
+      
+    /* Calculation of where to move */
+    /* If zenith distance is within 40 degrees then we move.
+       In order to do so the following logic will be applied:
+
+       1) Is zenith distance within 40 degrees (inclusive)
+       2) If so:
+             if dec > 20 then
+                move dec by -40
+             else
+                move dec by +40        
+          
+    */                      
+
+    if (fabs(90.0 - alt) <= 40) {
+        double adj_dec;        
+        /* Zenith distance within 40 degress */        
+        if (dec > lat) {
+            adj_dec = dec - 40.0;                              
+        }
+        else {
+            adj_dec = dec + 40.0;                     
+        }
+        printf("TRUE ");
+        put_coords(adj_dec, 2, 1);
+        printf("\n");    
+    }
+    else {
+        printf("FALSE\n");        
+    }
+    
+    return(0);    
+    
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/moondata.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/moondata.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/moondata.c	(revision 16632)
@@ -0,0 +1,81 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc_internal.h>
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+
+double atof();
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main (int argc, char **argv) {
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jdnow, ra, dec, sid;
+  double geora, geodec, geodist, dist;
+  double RAo, DECo, abx, aby, abz, cs, theta;
+  double Rsun, Dsun, days;
+  time_t tzero;
+  struct tm *stm;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: moondata (date) (ra) (dec) [ra & dec in dec. deg.]\n");
+    exit (1);
+  }
+
+  RAo = atof (argv[2]);
+  DECo = atof (argv[3]);
+
+  if (!str_to_time (argv[1], &tzero)) { 
+    fprintf (stderr, "syntax error\n");
+    exit (1);
+  }
+  stm = gmtime (&tzero);
+  date.y  = (short) (stm->tm_year + 1900);
+  date.mo = (short) (stm->tm_mon + 1);
+  date.d  = (short) (stm->tm_mday);
+  date.h  = (short) (stm->tm_hour);
+  date.mn = (short) (stm->tm_min);
+  date.s  = (float) (stm->tm_sec);
+
+  /*
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", date.y, date.mo, date.d, date.h, date.mn, date.s);
+  */
+
+  set_site (&longit, &lat, &elevsea, &elev);
+  jdnow  = date_to_jd (date);
+  /* Calcualte local sidereal time */
+  sid = lst(jdnow, longit);
+  lpsun (jdnow, &Rsun, &Dsun);
+
+  accumoon(jdnow,lat,sid,elevsea,&geora,&geodec,&geodist,&ra,&dec,&dist);
+
+  /*  fprintf (stdout, "moon @ %f %f\n", 15*ra, dec); */
+
+  abx = cos(RAo*RAD_DEG)*cos(DECo*RAD_DEG)*cos(15*ra*RAD_DEG)*cos(dec*RAD_DEG);
+  aby = sin(RAo*RAD_DEG)*cos(DECo*RAD_DEG)*sin(15*ra*RAD_DEG)*cos(dec*RAD_DEG);
+  abz = sin(DECo*RAD_DEG)*sin(dec*RAD_DEG);
+
+  cs = abx + aby + abz;
+  
+  theta = DEG_RAD * acos (cs);
+
+  days = (Rsun - ra - 12)/24.0;
+  while (days < -0.5) days += 1.0;
+  while (days >  0.5) days -= 1.0;
+  days *= 29.5;
+
+  fprintf (stdout, "moon @ %f %f dist %f %f days from full\n", 15*ra, dec, theta, days);
+  exit (0);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/skylib.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/skylib.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/skylib.c	(revision 16632)
@@ -0,0 +1,48 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc.h>
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main()
+
+{
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jd;
+
+  set_site (&longit, &lat, &elevsea, &elev);
+  get_sys_date (&date);
+
+  jd = sunset_tonight (date, lat, longit, elev);
+  fprintf (stderr, "Sunset (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+
+  jd = sunrise_tonight (date, lat, longit, elev);
+  fprintf (stderr, "Sunrise (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+  
+
+  jd = moonset_tonight (date, lat, longit, elevsea, elev);
+  fprintf (stderr, "Moonset (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+
+  jd = moonrise_tonight (date, lat, longit, elevsea, elev);
+  fprintf (stderr, "Moonrise (%5.0f m horizon): %f\n", elev, jd);
+  jd_to_date (jd, &tmpdate);
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", tmpdate.y, tmpdate.mo, tmpdate.d, tmpdate.h, tmpdate.mn, tmpdate.s);
+
+}
+
+  /* set_zenith (date, lat, longit, objepoch, &objra, &objdec); */
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/sun.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/sun.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/sun.c	(revision 16632)
@@ -0,0 +1,157 @@
+# include <skycalc_internal.h>
+
+/* Low precision formulae for the sun, from Almanac p. C24 (1990) */
+/* ra and dec are returned as decimal hours and decimal degrees. */
+void lpsun (double jd, double *ra, double *dec) {
+
+  double n, L, g, lambda,epsilon,alpha,delta,x,y,z;
+
+  n = jd - J2000;
+  L = 280.460 + 0.9856474 * n;
+  g = (357.528 + 0.9856003 * n)/DEG_IN_RADIAN;
+  lambda = (L + 1.915 * sin(g) + 0.020 * sin(2. * g))/DEG_IN_RADIAN;
+  epsilon = (23.439 - 0.0000004 * n)/DEG_IN_RADIAN;
+
+  x = cos(lambda);
+  y = cos(epsilon) * sin(lambda);
+  z = sin(epsilon)*sin(lambda);
+
+  *ra = (atan_circ(x,y))*HRS_IN_RADIAN;
+  *dec = (asin(z))*DEG_IN_RADIAN;
+}
+
+/* returns jd at which sun is at a given
+   altitude, given jdguess as a starting point. Uses
+   low-precision sun, which is plenty good enough. */
+double jd_sun_alt (double alt, double jdguess, double lat, double longit) {
+
+  double jdout;
+  double deriv, err, del = 0.002;
+  double ra,dec,ha,alt2,alt3,az;
+  short i = 0;
+  
+  /* first guess */
+  
+  lpsun (jdguess, &ra, &dec);
+  ha = lst (jdguess,longit) - ra;
+  alt2 = altit (dec,ha,lat,&az);
+  jdguess = jdguess + del;
+  lpsun (jdguess,&ra,&dec);
+  alt3 = altit(dec,(lst(jdguess,longit) - ra),lat,&az);
+  err = alt3 - alt;
+  deriv = (alt3 - alt2) / del;
+  while((fabs(err) > 0.1) && (i < 10)) {
+    jdguess = jdguess - err/deriv;
+    lpsun(jdguess,&ra,&dec);
+    alt3 = altit(dec,(lst(jdguess,longit) - ra),lat,&az);
+    err = alt3 - alt;
+    i++;
+    if(i == 9) printf ("Sunrise, set, or twilight calculation not converging!\n");
+  }
+  if(i >= 9) jdguess = -1000.;
+  jdout = jdguess;
+  return(jdout);
+}
+
+/* Given site position, prints Sun info for the given night.
+/* dates are all in UT now */
+double sunset_tonight (struct SC_date_time date, double lat, double longit, double elev) {
+
+  double jd, jdmid0, jdmid, stmid;
+  double rasun, decsun, min_alt, max_alt, horiz;
+  double hasunset, jdsunset, jdsunrise, sid;
+  double dt, lst0, lst1, djd;
+  struct SC_date_time date_midnight, tmpdate;
+  short dow;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid0 = date_to_jd (date_midnight);
+  jdmid = jdmid0 + dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  /* sunset / sunrise hour angle */
+  lpsun (jdmid, &rasun, &decsun);
+  hasunset = ha_alt (decsun, lat, -(0.83+horiz));
+  if(hasunset > 900.) {  /* flag for never sets */
+    return (-1);
+  }
+  if(hasunset < -900.) {
+    return (-1);
+  }
+
+  /* find sunset time */
+  jdsunset = jdmid + adj_time(rasun+hasunset-stmid)/24.;
+  jdsunset = jd_sun_alt (-(0.83+horiz),jdsunset,lat,longit);
+
+  return (jdsunset);
+
+}
+
+/* Given site position, prints Sun info for the given night.
+/* dates are all in UT now */
+double sunrise_tonight (struct SC_date_time date, double lat, double longit, double elev) {
+
+  double jd, jdmid, stmid;
+  double rasun, decsun, min_alt, max_alt, horiz;
+  double hasunset, jdsunset, jdsunrise, sid;
+  double dt, lst0, lst1, djd;
+  struct SC_date_time date_midnight, tmpdate;
+  short dow;
+
+  horiz = sqrt (2. * elev / 6378140.) * DEG_IN_RADIAN;
+
+  /* find offset in hours from longit to greenwich */
+  jd = date_to_jd (date);  /* true jd now */
+  lst0 = lst (jd, 0.0);    /* lst at long = 0 */
+  lst1 = lst (jd, longit); /* local lst now */
+  dt = lst0 - lst1;
+  if (dt < 0) dt += 24;
+	
+  /* midnight at greenwich */
+  date_midnight = date;
+  date_midnight.h = 0;
+  date_midnight.mn = 0;
+  date_midnight.s = 0;
+	
+  /* find jd for local midnight, select the *closest* midnight */
+  jdmid = date_to_jd (date_midnight) - dt / 24.0;
+  djd = jd - jdmid;
+  if (djd < -0.5) jdmid -= 1.0;
+  if (djd >  0.5) jdmid += 1.0;
+  stmid = lst (jdmid,longit); 
+
+  /* sunset / sunrise hour angle */
+  lpsun (jdmid, &rasun, &decsun);
+  hasunset = ha_alt (decsun, lat, -(0.83+horiz));
+  if(hasunset > 900.) {  /* flag for never sets */
+    return (-1);
+  }
+  if(hasunset < -900.) {
+    fprintf (stderr, "Sun down all day!\n");
+    return (-1);
+  }
+
+  /* find sunrise time */
+  jdsunrise = jdmid + adj_time(rasun-hasunset-stmid)/24.;
+  jdsunrise = jd_sun_alt(-(0.83+horiz),jdsunrise,lat,longit);
+
+  return (jdsunrise);
+}
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/sundata.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/sundata.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/sundata.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include <stdio.h>
+# include <math.h>
+# include <skycalc_internal.h>
+
+# define DEG_RAD 57.295779513082322
+# define RAD_DEG  0.017453292519943
+# define dCOS(A)   ((double) cos ((double)RAD_DEG*A))
+# define dSIN(A)   ((double) sin ((double)RAD_DEG*A))
+
+double atof();
+
+void set_site (double *longit, double *lat, double *elevsea, double *elev) {
+
+  *longit = 10.36478; /*  W longitude in decimal hours */                     
+  *lat = 19.8267;     /*  N latitude in decimal degrees */                    
+  *elevsea = 4215.;   /* elevation above sea level (for absolute location) */ 
+  *elev = 4215.;      /* observatory elevation above horizon, meters */       
+
+}
+
+main (int argc, char **argv) {
+
+  struct SC_date_time date, tmpdate;
+  double longit, lat, elevsea, elev;
+  double jdnow, ra, dec, sid, alt, az, sind, sinh, cosh;
+  double geora, geodec, geodist, dist;
+  double RAo, DECo, abx, aby, abz, cs, theta;
+  double Rsun, Dsun, days, Hsun;
+  time_t tzero;
+  struct tm *stm;
+
+  if (argc != 4) {
+    fprintf (stderr, "USAGE: sundata (date) (ra) (dec) [ra & dec in dec. deg.]\n");
+    exit (1);
+  }
+
+  RAo = atof (argv[2]);
+  DECo = atof (argv[3]);
+
+  if (!str_to_time (argv[1], &tzero)) { 
+    fprintf (stderr, "syntax error\n");
+    exit (1);
+  }
+  stm = gmtime (&tzero);
+  date.y  = (short) (stm->tm_year + 1900);
+  date.mo = (short) (stm->tm_mon + 1);
+  date.d  = (short) (stm->tm_mday);
+  date.h  = (short) (stm->tm_hour);
+  date.mn = (short) (stm->tm_min);
+  date.s  = (float) (stm->tm_sec);
+
+  /*
+  fprintf (stderr, "%4d/%02d/%02d %02d:%02d:%02f\n", date.y, date.mo, date.d, date.h, date.mn, date.s);
+  */
+
+  set_site (&longit, &lat, &elevsea, &elev);
+  jdnow  = date_to_jd (date);
+
+  /* Calcualte local sidereal time */
+  sid = lst(jdnow, longit);
+  lpsun (jdnow, &Rsun, &Dsun);
+
+  /* dot product of unit vectors of (RAo,DECo) & (Rsun,Dsun) */
+  abx = dCOS(RAo)*dCOS(DECo)*dCOS(15*Rsun)*dCOS(Dsun);
+  aby = dSIN(RAo)*dCOS(DECo)*dSIN(15*Rsun)*dCOS(Dsun);
+  abz = dSIN(DECo)*dSIN(Dsun);
+  cs = abx + aby + abz;
+  theta = DEG_RAD * acos (cs);
+
+  /***** get sun altitude *****/
+  Hsun = 15.0*(sid - Rsun);
+ 
+  sind = dSIN (Dsun) * dSIN (lat) + dCOS (Dsun) * dCOS (Hsun) * dCOS (lat);
+  alt  = DEG_RAD * asin (sind);
+
+  sinh = - dCOS (Dsun) * dSIN (Hsun);
+  cosh =   dSIN (Dsun) * dCOS (lat) - dCOS (Dsun) * dCOS (Hsun) * dSIN (lat);
+  az = DEG_RAD * atan2 (sinh, cosh);
+
+  fprintf (stdout, "sun @ %f %f dist %f altaz: %f %f\n", 15*Rsun, Dsun, theta, alt, az);
+  exit (0);
+
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/skycalc/src/time.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skycalc/src/time.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skycalc/src/time.c	(revision 16632)
@@ -0,0 +1,148 @@
+# include <skycalc_internal.h>
+
+/* fill date structure with current date & time (UT) */
+int get_sys_date (struct SC_date_time *date) {
+
+  time_t t;
+  struct tm *stm;
+  double jd, jdb, jde;
+  short dow;
+  
+  t = time (0);
+  if (t == -1) return (-1);
+
+  stm = gmtime (&t);
+  date->y = (short) (stm->tm_year + 1900);
+  date->mo = (short) (stm->tm_mon + 1);
+  date->d = (short) (stm->tm_mday);
+  date->h = (short) (stm->tm_hour);
+  date->mn = (short) (stm->tm_min);
+  date->s = (float) (stm->tm_sec);
+
+  return (0); /* success */
+
+}
+
+/* convert a UT date to JD ( 1900 -- 2100?) */
+double date_to_jd (struct SC_date_time date) {
+  
+  short yr1=0, mo1=1;
+  long jdzpt = 1720982, jdint, inter;
+  double jd,jdfrac;
+  
+  if ((date.y <= 1900) | (date.y >= 2100)) return (0.0);
+  
+  if (date.mo <= 2) {
+    yr1 = -1;
+    mo1 = 13;
+  }
+  
+  jdint = 365.25*(date.y+yr1);  /* truncates */
+  inter = 30.6001*(date.mo+mo1);
+  jdint = jdint+inter+date.d+jdzpt;
+  jd = jdint;
+  jdfrac=date.h/24.+date.mn/1440.+date.s/SEC_IN_DAY;
+  if (jdfrac < 0.5) {
+    jdint--;
+    jdfrac=jdfrac+0.5;
+  }
+  else jdfrac=jdfrac-0.5;
+  jd = jdint+jdfrac;
+  return (jd);
+}
+
+/* convert JD to a UT date & time */
+void jd_to_date (double jdin, struct SC_date_time *date) {
+  
+#define IGREG 2299161
+
+  /* Adapted from Press, Flannery, Teukolsky, &
+     Vetterling, Numerical Recipes in C, (Cambridge
+     University Press), 1st edn, p. 12. */
+  
+  int mm, id, iyyy;  /* their notation */
+  long ja, jdint, jalpha, jb, jc, jd, je;
+  float jdfrac;
+  double x;
+
+  jdin = jdin + 0.5;  /* adjust for 1/2 day */
+  jdint = jdin;
+  x = jdint/7.+0.01;
+  jdfrac = jdin - jdint;
+  date->h = jdfrac * 24; /* truncate */
+  date->mn = (jdfrac - ((float) date->h)/24.) * 1440.;
+  date->s = (jdfrac - ((float) date->h)/24. -
+	     ((float) date->mn)/1440.) * SEC_IN_DAY;
+
+  if(jdint > IGREG) {
+    jalpha=((float) (jdint-1867216)-0.25)/36524.25;
+    ja=jdint+1+jalpha-(long)(0.25*jalpha);
+  }
+  else
+    ja=jdint;
+  jb=ja+1524;
+  jc=6680.0+((float) (jb-2439870)-122.1)/365.25;
+  jd=365*jc+(0.25*jc);
+  je=(jb-jd)/30.6001;
+  id=jb-jd-(int) (30.6001*je);
+  mm=je-1;
+  if(mm > 12) mm -= 12;
+  iyyy=jc-4715;
+  if(mm > 2) --iyyy;
+  if (iyyy <= 0) --iyyy;
+  date->y = iyyy;
+  date->mo = mm;
+  date->d = id;
+
+}
+
+
+/* returns the local MEAN sidereal time (dec hrs) at julian date jd
+   at west longitude long (decimal hours).  Follows
+   definitions in 1992 Astronomical Almanac, pp. B7 and L2.
+   Expression for GMST at 0h ut referenced to Aoki et al, A&A 105,
+   p.359, 1982.  On workstations, accuracy (numerical only!)
+   is about a millisecond in the 1990s. */
+double lst (double jd, double longit) {
+  
+  double t, ut, jdmid, jdint, jdfrac, sid_g, sid;
+  long sid_int;
+  
+  jdint = (int) jd;
+  jdfrac = jd - jdint;
+
+  if (jdfrac < 0.5) {
+    jdmid = jdint - 0.5;
+    ut = jdfrac + 0.5;
+  }
+  else {
+    jdmid = jdint + 0.5;
+    ut = jdfrac - 0.5;
+  }
+  t = (jdmid - J2000)/36525;
+  sid_g = (24110.54841+8640184.812866*t+0.093104*t*t-6.2e-6*t*t*t)/SEC_IN_DAY;
+  sid_int = sid_g;
+  sid_g = sid_g - (double) sid_int;
+  sid_g = sid_g + 1.0027379093 * ut - longit/24.;
+  sid_int = sid_g;
+  sid_g = (sid_g - (double) sid_int) * 24.;
+  if (sid_g < 0.) sid_g = sid_g + 24.;
+  return (sid_g);
+}
+
+/* force time domain to be -12h and 12h  */
+double adj_time (double x) {
+  
+  /* ridiculously inefficient - use modulo and fractions.. */
+  if(fabs(x) < 100000.) {  
+    while(x > 12.) {
+      x = x - 24.;
+    }
+    while(x < -12.) {
+      x = x + 24.;
+    }
+  }
+  else printf ("Out of bounds in adj_time!\n");
+  return(x);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/skyprobe/skyproberedccd
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/skyprobe/skyproberedccd	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/skyprobe/skyproberedccd	(revision 16632)
@@ -0,0 +1,44 @@
+#!/bin/sh
+
+echo " FLIPS - skyproberedccd (imred)"
+if [ $# -ne 2 ] ; then
+  echo " Process: single SkyProbe CCD image reduction with Dark & Flat-Field"
+  echo " Syntax:  skyproberedccd FILE_IN FILE_OUT"
+  exit 1
+fi
+
+# Check if INPUT FITS file exists
+if [ ! -f $1 ]; then
+   echo "FITS file '$1' (FILE_IN = 1st argument) does not exist"
+   exit 1
+fi
+
+# Create temporary parameter file name
+TEMP="/tmp/redccd$$"
+
+# Prepare parameter file
+cat ~skyprobe/.skyprobeimred.param.CCD | sed "s|INFILE|$1|"   | sed "s|OUTFILE|$2|" > $TEMP
+
+# Set a default size for the buffer height
+echo "BUFFER"                       >> $TEMP
+echo "        height          240"  >> $TEMP
+echo "        end"                  >> $TEMP
+# CPU type: for swap or not
+echo "CPU"                          >> $TEMP
+echo "        swap            1"    >> $TEMP
+echo "        end"                  >> $TEMP
+# Timing info flag
+echo "TIMING"                       >> $TEMP
+echo "        timing          1"    >> $TEMP
+echo "        end"                  >> $TEMP
+# End of the parfile
+echo "END"                          >> $TEMP
+
+# Combine files
+imred_lx $TEMP
+
+# Remove temporary file
+rm -f $TEMP
+rm -f imred-stat.dat
+
+exit 0
Index: /branches/eam_branch_20080223/Ohana/src/tcl/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tcl/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tcl/Makefile	(revision 16632)
@@ -0,0 +1,20 @@
+include ../../Makefile.System
+HOME 	=	$(ROOT)/src/tcl
+
+tcl:
+
+default: install
+
+CODE =  edisp
+
+install:
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	for file in $(CODE); do \
+	(cd $(DESTBIN); rm -f $$file; ln -s $(HOME)/src/$$file .); \
+	done
+
+# utilities #################################################
+clean:	
+	rm -f `find . -name "*~"`
+	rm -f `find . -name "#*"`
+
Index: /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp	(revision 16632)
@@ -0,0 +1,217 @@
+#!/usr/bin/env wish
+
+# define three components to the window:
+
+# text line with data value
+# image region with image
+# quit button
+
+if [catch {exec /apps/elixir/bin/gconfig DATDIR} datdir] { 
+    set picpath "ERROR" 
+} else {
+    set picpath "$datdir/plots"
+}
+
+set imname "(empty)"
+set name "(empty)"
+set pid [pid]
+set index 0
+
+proc mk_layout { } {
+
+    global file lasttime picpath
+
+    set lasttime 0
+    if {$picpath == "ERROR"} {
+	set file "ERROR"
+    } else {
+	set file "$picpath/empty.gif"
+    }
+    wm withdraw .
+
+    set w [toplevel .t]
+    wm title .t "user display"
+    
+    # top level containers
+    frame $w.menubar -relief raised -borderwidth 2
+    frame $w.picture -relief raised -borderwidth 2
+    frame $w.dataline -relief raised -borderwidth 2
+
+    pack $w.menubar -fill x
+    pack $w.picture -fill x
+    pack $w.dataline -fill x
+
+    mk_menubar $w.menubar
+    mk_picture $w.picture
+    mk_dataline $w.dataline
+
+    update
+}
+
+proc do_quit {} {
+    
+    exit 
+
+}
+
+proc mk_picture {w} {
+
+    global file
+
+    if {$file == "ERROR"} {
+	label $w.name -text "Config Error: missing DATDIR"
+	pack  $w.name -side top -fill both
+    } else {
+	image create photo picture -file $file
+	label $w.name -image picture
+	pack  $w.name -side top -fill both
+    }
+}
+
+proc mk_menubar {w} {
+
+    global file picpath cycle
+
+    menubutton $w.file -text "File" -menu $w.file.menu
+    pack $w.file -side left
+
+    menu $w.file.menu -tearoff 0
+    $w.file.menu add command -label "Quit" -command { do_quit }
+    bind all <Alt-q> { do_quit }
+    bind all <Control-q> { do_quit }
+    
+    menubutton $w.plot -text "Plots" -menu $w.plot.menu
+    pack $w.plot -side left
+
+    label $w.label -text "$file"
+    pack $w.label -side right
+
+    menu $w.plot.menu -tearoff 0
+    $w.plot.menu add command -label "Cycle"           -command { set cycle 1 ; cycleImages }
+    $w.plot.menu add command -label "biases"          -command { set cycle 0 ; set file "$picpath/biases.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe recent" -command { set cycle 0 ; set file "$picpath/skyprobe_recent.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe night"  -command { set cycle 0 ; set file "$picpath/skyprobe_night.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs time"     -command { set cycle 0 ; set file "$picpath/sky.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs airmass"  -command { set cycle 0 ; set file "$picpath/sky.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "Recent Seeing"    -command { set cycle 0 ; set file "$picpath/seeing_recent.gif"; refresh_now;  }
+    $w.plot.menu add command -label "Night Seeing"    -command { set cycle 0 ; set file "$picpath/seeing_night.gif"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs airmass" -command { set cycle 0 ; set file "$picpath/fwhm.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (small)"   -command { set cycle 0 ; set file "$picpath/field.small.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (large)"   -command { set cycle 0 ; set file "$picpath/field.large.gif"; refresh_now;  }
+    $w.plot.menu add command -label "temperatures"    -command { set cycle 0 ; set file "$picpath/temps.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (10x10)"   -command { set cycle 0 ; set file "$picpath/current.b10.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (zoom)"     -command { set cycle 0 ; set file "$picpath/current.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last short image" -command { set cycle 0 ; set file "$picpath/lastshort.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "focus (unit)"     -command { set cycle 0 ; set file "$picpath/focus.unit.gif"; refresh_now;  }
+
+}
+
+proc mk_dataline {w} {
+
+    global fwhm imname name file
+    set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+    label $w.label -text "name: $name  |  FHWM: 0.0  |  FILTER: X  |  time: $time            | image: $imname"
+    pack $w.label -fill x
+
+}
+
+proc cycleImages { } {
+
+    global file cycle picpath index
+
+    set images { skyprobe_recent.gif sky.time.gif seeing_recent.gif biases.gif temps.time.gif current.b10.gif current.zoom.gif lastshort.zoom.gif }
+
+
+    if { $cycle == 0 } { return }
+
+    set file "$picpath/[lindex $images $index]"
+    refresh_now
+
+    incr index
+    if { $index == [llength $images] } {
+	set index 0
+    }
+
+    after 30000 {
+	cycleImages
+    }
+}
+
+proc do_refresh { } {
+
+    global picpath imname name file
+
+    after 1000 {
+	
+	set time [clock format [clock seconds] -format "%H:%M:%S"]
+	set name "(empty)"
+	set fwhm 0.0
+	set filter "X"
+
+	if {! [catch {open $picpath/seeing.dat r} data] } {
+	    gets $data line
+	    close $data
+	    set list [split $line]
+	    if {[llength $list] == 4} {
+		set name [lindex $list 0]
+		catch { set fwhm [format "%5.2f" [lindex $list 1]] } status
+		set filter [lindex $list 3]
+            }
+	}
+	
+	.t.dataline.label configure -text "name: $name  |  FHWM: $fwhm  |  FILTER: $filter  |  time: $time           | image: $imname"
+	.t.menubar.label configure -text "file: $file"
+	update
+	do_refresh 
+    }
+}
+
+proc do_refresh_pic { } {
+
+    global file lasttime imname name pid
+
+    after 2000 {
+	
+	# get file status & time
+	if {! [catch {file stat $file stats}] } {
+	    set newtime $stats(mtime)
+	    if {$newtime > $lasttime} {
+		set tmpfile "$file.$pid"
+		catch { exec ln -f $file $tmpfile }
+		catch { picture read $tmpfile -shrink } 
+		catch { exec rm -f $tmpfile }
+		set imname $name
+		set lasttime $newtime
+		update
+	    }
+	}
+	do_refresh_pic
+    }
+}
+
+proc bgerror {result} {
+	puts "edisp error: $result"
+}
+
+proc refresh_now { } {
+
+    global file lasttime imname name pid
+
+    if {[file exists $file]} {
+	set tmpfile "$file.$pid"
+	catch { exec ln -f $file $tmpfile }
+	catch { picture read $tmpfile -shrink }
+	catch { exec rm -f $tmpfile }
+
+	file stat $file stats
+	set imname $name
+	set lasttime $stats(mtime)
+	update
+	
+    }
+}
+
+mk_layout
+do_refresh
+do_refresh_pic
Index: /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp-1.0
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp-1.0	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp-1.0	(revision 16632)
@@ -0,0 +1,175 @@
+#!/usr/bin/env wish
+
+# define three components to the window:
+
+# text line with data value
+# image region with image
+# quit button
+
+set picpath "/data/milo/elixir/plots"
+set imname "(empty)"
+set name "(empty)"
+set pid [pid]
+
+proc mk_layout { } {
+
+    global file lasttime picpath
+
+    set lasttime 0
+    set file "$picpath/empty.gif"
+    wm withdraw .
+
+    set w [toplevel .t]
+    wm title .t "user display"
+    
+    # top level containers
+    frame $w.menubar -relief raised -borderwidth 2
+    frame $w.picture -relief raised -borderwidth 2
+    frame $w.dataline -relief raised -borderwidth 2
+
+    pack $w.menubar -fill x
+    pack $w.picture -fill x
+    pack $w.dataline -fill x
+
+    mk_menubar $w.menubar
+    mk_picture $w.picture
+    mk_dataline $w.dataline
+
+    update
+}
+
+proc do_quit {} {
+    
+    exit 
+
+}
+
+proc mk_picture {w} {
+
+    global file
+
+    image create photo picture -file $file
+
+    label $w.name -image picture
+    pack  $w.name -side top -fill both
+}
+
+proc mk_menubar {w} {
+
+    global file picpath
+
+    menubutton $w.file -text "File" -menu $w.file.menu
+    pack $w.file -side left
+
+    menu $w.file.menu -tearoff 0
+    $w.file.menu add command -label "Quit" -command { do_quit }
+    bind all <Alt-q> { do_quit }
+    bind all <Control-q> { do_quit }
+    
+    menubutton $w.plot -text "Plots" -menu $w.plot.menu
+    pack $w.plot -side left
+
+    menu $w.plot.menu -tearoff 0
+    $w.plot.menu add command -label "biases"          -command { set file "$picpath/biases.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe recent" -command { set file "$picpath/skyprobe_recent.gif"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe night"  -command { set file "$picpath/skyprobe_night.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs time"     -command { set file "$picpath/sky.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs airmass"  -command { set file "$picpath/sky.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs time"    -command { set file "$picpath/fwhm.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs airmass" -command { set file "$picpath/fwhm.airmass.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (small)"   -command { set file "$picpath/field.small.gif"; refresh_now;  }
+    $w.plot.menu add command -label "field (large)"   -command { set file "$picpath/field.large.gif"; refresh_now;  }
+    $w.plot.menu add command -label "temperatures"    -command { set file "$picpath/temps.time.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (10x10)"   -command { set file "$picpath/current.b10.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last image (zoom)"     -command { set file "$picpath/current.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "last short image" -command { set file "$picpath/lastshort.zoom.gif"; refresh_now;  }
+    $w.plot.menu add command -label "focus (unit)"     -command { set file "$picpath/focus.unit.gif"; refresh_now;  }
+
+}
+
+proc mk_dataline {w} {
+
+    global fwhm imname name
+    set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+    label $w.label -text "name: $name  |  FHWM: 0.0  |  FILTER: X  |  time: $time            | image: $imname"
+    pack $w.label -side left
+    
+}
+
+proc do_refresh { } {
+
+    global picpath imname name
+
+    after 1000 {
+	
+	set time [clock format [clock seconds] -format "%H:%M:%S"]
+	set name "(empty)"
+	set fwhm 0.0
+	set filter "X"
+
+	if {! [catch {open $picpath/seeing.dat r} data] } {
+	    gets $data line
+	    close $data
+	    set list [split $line]
+	    if {[llength $list] == 4} {
+		set name [lindex $list 0]
+		catch { set fwhm [format "%5.2f" [lindex $list 1]] } status
+		set filter [lindex $list 3]
+            }
+	}
+	
+	.t.dataline.label configure -text "name: $name  |  FHWM: $fwhm  |  FILTER: $filter  |  time: $time           | image: $imname"
+	update
+	do_refresh 
+    }
+}
+
+proc do_refresh_pic { } {
+
+    global file lasttime imname name pid
+
+    after 2000 {
+	
+	# get file status & time
+	if {! [catch {file stat $file stats}] } {
+	    set newtime $stats(mtime)
+	    if {$newtime > $lasttime} {
+		set tmpfile "$file.$pid"
+		catch { exec ln -f $file $tmpfile }
+		catch { picture read $tmpfile -shrink } 
+		catch { exec rm -f $tmpfile }
+		set imname $name
+		set lasttime $newtime
+		update
+	    }
+	}
+	do_refresh_pic
+    }
+}
+
+proc bgerror {result} {
+	puts "edisp error: $result"
+}
+
+proc refresh_now { } {
+
+    global file lasttime imname name pid
+
+    if {[file exists $file]} {
+	set tmpfile "$file.$pid"
+	catch { exec ln -f $file $tmpfile }
+	catch { picture read $tmpfile -shrink }
+	catch { exec rm -f $tmpfile }
+
+	file stat $file stats
+	set imname $name
+	set lasttime $stats(mtime)
+	update
+	
+    }
+}
+
+mk_layout
+do_refresh
+do_refresh_pic
Index: /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp.ppm
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp.ppm	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tcl/src/edisp.ppm	(revision 16632)
@@ -0,0 +1,169 @@
+#!/usr/bin/env wish
+
+# define three components to the window:
+
+# text line with data value
+# image region with image
+# quit button
+
+set picpath "/data/milo/cfh12k/plots"
+set imname "(empty)"
+set name "(empty)"
+
+proc mk_layout { } {
+
+    global file lasttime picpath
+
+    set lasttime 0
+    set file "$picpath/empty.gif"
+    wm withdraw .
+
+    set w [toplevel .t]
+    wm title .t "user display"
+    
+    # top level containers
+    frame $w.menubar -relief raised -borderwidth 2
+    frame $w.picture -relief raised -borderwidth 2
+    frame $w.dataline -relief raised -borderwidth 2
+
+    pack $w.menubar -fill x
+    pack $w.picture -fill x
+    pack $w.dataline -fill x
+
+    mk_menubar $w.menubar
+    mk_picture $w.picture
+    mk_dataline $w.dataline
+
+    update
+}
+
+proc do_quit {} {
+    
+    exit 
+
+}
+
+proc mk_picture {w} {
+
+    global file
+
+    image create photo picture -file $file
+
+    label $w.name -image picture
+    pack  $w.name -side top -fill both
+}
+
+proc mk_menubar {w} {
+
+    global file picpath
+
+    menubutton $w.file -text "File" -menu $w.file.menu
+    pack $w.file -side left
+
+    menu $w.file.menu -tearoff 0
+    $w.file.menu add command -label "Quit" -command { do_quit }
+    bind all <Alt-q> { do_quit }
+    
+    menubutton $w.plot -text "Plots" -menu $w.plot.menu
+    pack $w.plot -side left
+
+    menu $w.plot.menu -tearoff 0
+    $w.plot.menu add command -label "biases"          -command { set file "$picpath/biases.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe recent" -command { set file "$picpath/skyprobe_recent.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "skyprobe night"  -command { set file "$picpath/skyprobe_night.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs time"     -command { set file "$picpath/sky.time.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "sky vs airmass"  -command { set file "$picpath/sky.airmass.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs time"    -command { set file "$picpath/fwhm.time.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "FWHM vs airmass" -command { set file "$picpath/fwhm.airmass.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "field (small)"   -command { set file "$picpath/field.small.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "field (large)"   -command { set file "$picpath/field.large.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "temperatures"    -command { set file "$picpath/temps.time.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "image (10x10)"   -command { set file "$picpath/current.b10.ppm"; refresh_now;  }
+    $w.plot.menu add command -label "focus (unit)"    -command { set file "$picpath/focus.unit.ppm"; refresh_now;  }
+
+}
+
+proc mk_dataline {w} {
+
+    global fwhm imname name
+    set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+    label $w.label -text "name: $name  |  FHWM: 0.0  |  FILTER: X  |  time: $time            | image: $imname"
+    pack $w.label -side left
+    
+}
+
+proc do_refresh { } {
+
+    global picpath imname name
+
+    after 1000 {
+	
+	set time [clock format [clock seconds] -format "%H:%M:%S"]
+
+	set name "empty"
+	set fwhm 0.0
+	set filter "X"
+
+	if {! [catch "open $picpath/seeing.dat r" data] } {
+	    gets $data line
+	    close $data
+	    set list [split $line]
+	    set name [lindex $list 0]
+	    set fwhm [format "%5.2f" [lindex $list 1]]
+	    set filter [lindex $list 3]
+	}
+
+	.t.dataline.label configure -text "name: $name  |  FHWM: $fwhm  |  FILTER: $filter  |  time: $time           | image: $imname"
+	update
+	
+	do_refresh 
+    }
+}
+
+proc do_refresh_pic { } {
+
+    global file lasttime imname name
+
+    after 2000 {
+	
+	if {! [catch "file stat $file stats"] } {
+	    set newtime $stats(mtime)
+	    if {$newtime > $lasttime} {
+		set tmpfile "$file.tmp"
+		catch "exec ln -f $file $tmpfile"
+		catch "picture read $tmpfile -shrink"
+		catch "exec rm $tmpfile"
+		set imname $name
+		set lasttime $newtime
+		update
+	    }
+	}
+	do_refresh_pic
+    }
+}
+
+proc refresh_now { } {
+
+    global file lasttime imname name
+
+    picture read $file -shrink;
+
+    if {[file exists $file]} {
+	set tmpfile "$file.tmp"
+	catch "exec ln -f $file $tmpfile"
+	catch "picture read $tmpfile -shrink"
+	catch "exec rm -f $tmpfile"
+
+	file stat $file stats
+	set lasttime $stats(mtime)
+	set imname $name
+	
+	update
+	
+    }
+}
+
+mk_layout
+do_refresh
+do_refresh_pic
Index: /branches/eam_branch_20080223/Ohana/src/tools/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/Makefile	(revision 16632)
@@ -0,0 +1,82 @@
+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
+# include ../../Makefile.Common
+
+DVO_LIBS  = $(DESTLIB)/libdvo.a $(DESTLIB)/libFITS.a $(DESTLIB)/libohana.a
+DVO_INCS  = $(DESTINC)/dvo.h $(DESTINC)/gfitsio.h $(DESTINC)/ohana.h $(DESTINC)/autocode.h 
+
+PROGRAMS = gconfig fhead ftable fields list_astro glockfile \
+radec mktemp precess csystem fits_insert \
+medianfilter mefhead ckfits
+
+all tools: $(PROGRAMS)
+
+BASE_CFLAGS   =	$(CFLAGS)
+BASE_CPPFLAGS =	$(CPPFLAGS) -I$(INC) -I$(DESTINC) $(INCDIRS) -D$(ARCH)
+BASE_LDFLAGS  = $(LDFLAGS) -L$(LIB) -L$(DESTLIB) $(LIBDIRS) $(LIBFLAGS)
+
+FULL_CFLAGS   =	$(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+# 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
+
+%.$(ARCH).o : %.c $(DVO_INCS)
+	$(CC) $(FULL_CFLAGS) $(FULL_CPPFLAGS) -c $< -o $@
+	@echo "compiled $<"
+	@echo ""
+
+$(BIN)/%.$(ARCH) : $(SRC)/%.$(ARCH).o $(DVO_LIBS)
+	@if [ ! -d $(BIN) ]; then mkdir -p $(BIN); fi
+	$(CC) $(FULL_CFLAGS) -o $@ $^ $(FULL_LDFLAGS)
+	@echo "compiled $*"
+	@echo ""
+
+$(DESTBIN)/%: $(BIN)/%.$(ARCH)  $(DVO_LIBS)
+	@if [ ! -d $(DESTBIN) ]; then mkdir -p $(DESTBIN); fi
+	rm -f $(DESTBIN)/$*
+	cp $(BIN)/$*.$(ARCH) $(DESTBIN)/$*
+	@echo "installed $*"
+	@echo ""
+
+$(PROGRAMS) : % : $(BIN)/%.$(ARCH)
+
+%.clean:
+	rm -f $(SRC)/$*.$(ARCH).o
+	rm -f $(BIN)/$*.$(ARCH)
+
+%.install:
+	make $(DESTBIN)/$*
+
+install:
+	for i in $(PROGRAMS); do make $$i.install || exit; done
+
+
+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)
+
+# $@ : target filename
+# $* : matched word (%)
+# $< : first prereq
+# $^ : all prereqs
+
+.PRECIOUS: %.$(ARCH).o
+.PRECIOUS: $(BIN)/%.$(ARCH)
+
Index: /branches/eam_branch_20080223/Ohana/src/tools/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/tools/src/ckfits.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/ckfits.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/ckfits.c	(revision 16632)
@@ -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_data_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/eam_branch_20080223/Ohana/src/tools/src/csystem.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/csystem.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/csystem.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/fhead.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/fhead.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/fhead.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/fields.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/fields.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/fields.c	(revision 16632)
@@ -0,0 +1,139 @@
+# 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) {
+
+  FILE *f;
+  Header header;
+  char filename[1000], *CCDKeyword, *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();
+
+  CCDKeyword = NULL;
+  if ((N = get_argument (argc, argv, "-keyword"))) {
+    remove_argument (N, &argc, argv);
+    CCDKeyword = strcreate (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+  if (CCDKeyword == NULL) {
+    CCDKeyword = strcreate ("EXTNAME");
+  }
+
+  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 (or other CCDKeyword) for this component (set to PHU for 0th component) */
+	status = gfits_scan (&header, CCDKeyword, "%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_data_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, 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/eam_branch_20080223/Ohana/src/tools/src/findexec.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/findexec.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/findexec.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/fits_insert.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/fits_insert.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/fits_insert.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/ftable.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/ftable.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/ftable.c	(revision 16632)
@@ -0,0 +1,406 @@
+# 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_data_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_data_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_data_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_data_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_data_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;
+
+  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*Nv*Nb], 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/eam_branch_20080223/Ohana/src/tools/src/gconfig.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/gconfig.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/gconfig.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/glockfile.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/glockfile.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/glockfile.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/list_astro.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/list_astro.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/list_astro.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/medianfilter.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/medianfilter.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/medianfilter.c	(revision 16632)
@@ -0,0 +1,133 @@
+# include <ohana.h>
+# include <gfitsio.h>
+
+# define D_NFILES 100
+
+int main (int argc, char **argv) {
+
+  int i, j, k, n, Npixels, Npixin, Npixrd, Npixlast, N;
+  int Npass, NFILES, Nfiles, Nvalid;
+
+  char **filename;
+  Header head, *tmphead;
+  Matrix out,  *tmpmatr;
+  float *list, *v, *O;
+  float fmin, fmax, Nval, sum, MinValid;
+
+  if ((N = get_argument (argc, argv, "-unsign"))) {
+    remove_argument (N, &argc, argv);
+    gfits_set_unsign_mode (TRUE);
+  }
+
+  MinValid = 1.0;
+  if ((N = get_argument (argc, argv, "-bad"))) {
+    remove_argument (N, &argc, argv);
+    MinValid = atof(argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  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++) {
+      Nvalid = 0;
+      for (k = 0; k < Nfiles; k++) {
+	v = (float *)tmpmatr[k].buffer;
+	if (v[j] < MinValid) continue;
+	if (isnan(v[j])) continue;
+	if (isinf(v[j])) continue;
+	list[k] = v[j];
+	Nvalid ++;
+      }
+      if (Nvalid == 0) {
+	*O = 0.0;
+	continue;
+      }
+      fsort (list, Nvalid);
+      sum = 0;
+      Nval = 0;
+      for (k = fmin*Nvalid; k < fmax*Nvalid; k++) {
+	sum += list[k];
+	Nval ++;
+      }
+      *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);
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/tools/src/mefhead.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/mefhead.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/mefhead.c	(revision 16632)
@@ -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_data_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_data_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/eam_branch_20080223/Ohana/src/tools/src/mktemp.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/mktemp.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/mktemp.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/precess.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/precess.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/precess.c	(revision 16632)
@@ -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/eam_branch_20080223/Ohana/src/tools/src/radec.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/tools/src/radec.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/tools/src/radec.c	(revision 16632)
@@ -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);
+}
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/Makefile	(revision 16632)
@@ -0,0 +1,40 @@
+default: uniphot
+help:
+	@echo "make options: uniphot (default)"
+
+include ../../Makefile.System
+HOME    =       $(ROOT)/src/uniphot
+BIN	=	$(HOME)/bin
+LIB	=	$(HOME)/lib
+SRC	=	$(HOME)/src
+MAN	=	$(HOME)/doc
+INC	= 	$(HOME)/include
+include ../../Makefile.Common
+
+# programs may add their own internal requirements here
+FULL_CFLAGS   = $(BASE_CFLAGS)
+FULL_CPPFLAGS = $(BASE_CPPFLAGS)
+FULL_LDFLAGS  = -ldvo -lFITS -lohana $(BASE_LDFLAGS)
+
+uniphot: $(BIN)/uniphot.$(ARCH)
+install: $(DESTBIN)/uniphot
+
+UNIPHOT = \
+$(SRC)/uniphot.$(ARCH).o	    \
+$(SRC)/initialize.$(ARCH).o	    \
+$(SRC)/ConfigInit.$(ARCH).o	    \
+$(SRC)/args.$(ARCH).o		    \
+$(SRC)/liststats.$(ARCH).o	    \
+$(SRC)/load_images.$(ARCH).o	    \
+$(SRC)/subset_images.$(ARCH).o	    \
+$(SRC)/find_image_tgroups.$(ARCH).o \
+$(SRC)/find_image_sgroups.$(ARCH).o \
+$(SRC)/fit_groups.$(ARCH).o	    \
+$(SRC)/update.$(ARCH).o		    \
+$(SRC)/update_catalog.$(ARCH).o	    \
+$(SRC)/SetSignals.$(ARCH).o	    \
+$(SRC)/Shutdown.$(ARCH).o	    \
+$(SRC)/sort.$(ARCH).o
+
+$(UNIPHOT): $(INC)/uniphot.h
+$(BIN)/uniphot.$(ARCH): $(UNIPHOT)
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/bin/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/bin/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/bin/.cvsignore	(revision 16632)
@@ -0,0 +1,4 @@
+*.linux *.lin64 *.sol *.sun *.sid *.hp *.irix
+*.linrh
+*.darwin
+*.darwin_x86
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/doc/ChangeLog.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/doc/ChangeLog.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/doc/ChangeLog.txt	(revision 16632)
@@ -0,0 +1,24 @@
+
+- uniphot-1-4:
+  * converted to gfits APIs (forces libfits 1.6)
+  * converted to new DVO APIs (forces libdvo 1.3)
+  * removed old, unused code
+
+- uniphot-1-3:
+  * dropped IMAGE_CATALOG from config
+  * convert to dvo_image_lock,unlock
+  * dropped _PS from average.R,D,M,dM
+
+- uniphot-1-2:
+
+  * various changes to use mode/format concepts
+  * mods to use new dvo load functions / libdvo
+  * minor changes to use new libohana (v1.5) / libfits (v1.4)
+
+- uniphot-1-1:
+
+  * changes from loneos.h to dvo.h (libohana)
+
+- uniphot-1-0:
+
+  * initial release
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/doc/notes.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/doc/notes.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/doc/notes.txt	(revision 16632)
@@ -0,0 +1,14 @@
+
+<h2> uniphot </h2>
+
+<ul>
+<li> load images (select on photcode, time range)
+<li> create time groups
+<li> create space groups
+<li> solve for:
+     tgroup[i].M = ave(image[tgroup].Mcal - image[tgroup].sgroup.Mcal)
+     sgroup[i].M = ave(image[sgroup].Mcal - image[tgroup].tgroup.Mcal)
+
+     image.tgroup -> tgroup
+     group.Nimage, image
+     
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/include/uniphot.h
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/include/uniphot.h	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/include/uniphot.h	(revision 16632)
@@ -0,0 +1,106 @@
+# include <ohana.h>
+# include <dvo.h>
+# include <signal.h>
+
+# ifdef ANSI
+#   define F_SETFL      4   
+#   define O_NONBLOCK   0200000  
+#   define AF_UNIX      1          
+#   define SOCK_STREAM  1          
+#   define ENOENT       2       /* No such file or directory    */
+# endif /* ANSI */
+
+typedef struct {
+  double median;
+  double mean;
+  double sigma;
+  double error;
+  double chisq;
+  double min;
+  double max;
+  double total;
+  int    Nmeas;
+} StatType;
+
+typedef struct {
+  void *tgroup;
+  void *sgroup;
+} ImageLink;
+
+typedef struct {
+  char label[64];
+  float M;
+  float dM;
+  float dMsub;
+  double v1, v2;
+  Image **image;
+  ImageLink **imlink;
+  int Nimage, Ngood;
+} Group;
+
+/* global variables set in parameter file */
+char         ImageCat[256];
+char         CATDIR[256];
+char         CATMODE[16];    /* raw, mef, split, mysql */
+char         CATFORMAT[16];  /* internal, elixir, loneos, panstarrs */
+char         STATMODE[64];
+int          VERBOSE;
+int          NLOOP;
+int          TimeSelect;
+int          VERBOSE;
+int          UPDATE;
+int          IMAGE_BAD;
+double       RADIUS;
+double       TRANGE;
+time_t 	     TSTART;
+time_t 	     TSTOP;
+PhotCode    *photcode;
+
+enum {black, white, red, orange, yellow, green, blue, indigo, violet};
+
+typedef struct {
+  double xmin, xmax, ymin, ymax;
+  int style, ptype, ltype, etype, color;
+  double lweight, size;
+} Graphdata;
+
+/***** prototypes ****/
+void          ConfigInit         PROTO((int *argc, char **argv));
+void          DonePlotting       PROTO((Graphdata *graphmode, int N));
+void          JpegPlot           PROTO((Graphdata *graphmode, int N, char *filename));
+void          PSPlot             PROTO((Graphdata *graphmode, int N, char *filename));
+void          PlotLabel          PROTO((char *string, int N));
+void          PlotVector         PROTO((int Npts, double *vect, int mode, int N));
+void          PrepPlotting       PROTO((int Npts, Graphdata *graphmode, int N));
+void          XDead              PROTO(());
+int           args               PROTO((int argc, char **argv));
+void          dumpresult         PROTO(());
+Group        *find_image_sgroups PROTO((FITS_DB *db, ImageLink **imlink, int *Nsgroup));
+Group        *find_image_tgroups PROTO((FITS_DB *db, ImageLink **imlink, int *Ntgroup));
+void          fit_sgroup         PROTO((Group *sgroup, int Nsgroup));
+void          fit_tgroup         PROTO((Group *tgroup, int Ntgroup));
+int           gcatalog           PROTO((Catalog *catalog));
+void          initialize         PROTO((int argc, char **argv));
+void          initstats          PROTO((char *mode));
+int           liststats          PROTO((double *value, double *dvalue, int N, StatType *stats));
+int           load_images        PROTO((FITS_DB *db));
+int           main               PROTO((int argc, char **argv));
+int           open_graph         PROTO((int N));
+void          sort               PROTO((unsigned int *X, int N));
+void          sortB              PROTO((double *X, double *Y, int N));
+void          sortD              PROTO((double *X, double *Y, double *Z, int N));
+void          update_dvo_catalog PROTO((Catalog *catalog, Group *sgroup, int warn));
+void          wcatalog           PROTO((Catalog *catalog));
+void          wimages            PROTO((Image *image, int Nimage));
+void check_permissions (char *basefile);
+void lock_image_db (FITS_DB *db, char *filename);
+void unlock_image_db (FITS_DB *db);
+void create_image_db (FITS_DB *db);
+void set_db (FITS_DB *in);
+int Shutdown (char *format, ...);
+void TrapSignal (int sig);
+void SetProtect (int mode);
+int SetSignals ();
+int subset_images (FITS_DB *db);
+void update (FITS_DB *db, Group *sgroup, int Nsgroup);
+void sort_time (unsigned int *value, int N);
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/ConfigInit.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/ConfigInit.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/ConfigInit.c	(revision 16632)
@@ -0,0 +1,43 @@
+# include "uniphot.h"
+
+void ConfigInit (int *argc, char **argv) {
+
+  double ZERO_POINT;
+  char  *config, *file;
+  char CatdirPhotcodeFile[256];
+  char MasterPhotcodeFile[256];
+
+  /*** load configuration info ***/
+  file = SelectConfigFile (argc, argv, "ptolemy");
+  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 (0);
+  }
+  if (VERBOSE) fprintf (stderr, "loaded config file: %s\n", file);
+
+  ScanConfig (config, "CATDIR",                 "%s",  0, CATDIR);
+  ScanConfig (config, "CATMODE",                "%s",  0, CATMODE);
+  ScanConfig (config, "CATFORMAT",              "%s",  0, CATFORMAT);
+  ScanConfig (config, "PHOTCODE_FILE",         	"%s",  0, MasterPhotcodeFile);
+
+  sprintf (ImageCat, "%s/Images.dat", CATDIR);
+
+  ScanConfig (config, "ZERO_PT",                "%lf", 0, &ZERO_POINT);
+  SetZeroPoint (ZERO_POINT);
+
+  free (config);
+  free (file);
+
+  if (*CATMODE == 0) strcpy (CATMODE, "RAW");
+  if (*CATFORMAT == 0) strcpy (CATFORMAT, "ELIXIR");
+
+  /* XXX this does not yet write out the master photcode table */
+  sprintf (CatdirPhotcodeFile, "%s/Photcodes.dat", CATDIR);
+  if (!LoadPhotcodes (CatdirPhotcodeFile, MasterPhotcodeFile)) {
+    fprintf (stderr, "error loading photcode table %s or master file %s\n", CatdirPhotcodeFile, MasterPhotcodeFile);
+    exit (1);
+  }
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/SetSignals.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/SetSignals.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/SetSignals.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "uniphot.h"
+
+static int Protect = FALSE;
+static int Trapped = FALSE;
+
+void TrapSignal (int sig) {
+    fprintf (stderr, "trapped signal %d\n", sig);
+    if (sig == 11) {
+      fprintf (stderr, "seg fault\n");
+      exit (1);
+    }
+    if (Protect) {
+      Trapped = TRUE;
+      fprintf (stderr, "blocking until protected sections are clear\n");
+      return;
+    }
+    Shutdown ("halted by signal (trapped)");
+}    
+
+void SetProtect (int mode) {
+  Protect = mode;
+  if (Trapped && !Protect) Shutdown ("halted by signal (protect)");
+}
+
+int SetSignals () {
+
+  int i;
+
+  /* disable almost all signal interrupts */
+  for (i = 0; i < 36; i++) {
+    switch (i) {
+      /* can't redirect this signals */
+    case SIGKILL:    /* kill -9: cannot be caught or ignored */
+    case SIGSTOP:    /* SIGSTOP: cannot be caught or ignored */
+      /* ignore these signals */
+    case SIGCHLD:    /* child halted: ignore */
+    case SIGCONT:    /* continue - maintain this action */
+    case SIGTSTP:    /* stop signal sent from tty - why ignore? */
+    case SIGURG:     /* socket signal, ignore this */
+# ifdef SIGPWR
+    case SIGPWR:     /* power failure - why ignore this? (Sys V) */
+# endif
+# ifdef SIGWINCH
+    case SIGWINCH:   /* window resized (4.3BSD) */
+# endif
+      break;
+      
+    default:
+      signal (i, TrapSignal);
+    }
+  }
+  return (TRUE);
+}
+/*
+
+       Signal     Value     Action   Comment
+       -------------------------------------------------------------------------
+       SIGHUP        1        A      Hangup detected on controlling terminal
+                                     or death of controlling process
+       SIGINT        2        A      Interrupt from keyboard
+       SIGQUIT       3        A      Quit from keyboard
+       SIGILL        4        A      Illegal Instruction
+       SIGABRT       6        C      Abort signal from abort(3)
+       SIGFPE        8        C      Floating point exception
+       SIGKILL       9       AEF     Kill signal
+       SIGSEGV      11        C      Invalid memory reference
+       SIGPIPE      13        A      Broken pipe: write to pipe with no readers
+       SIGALRM      14        A      Timer signal from alarm(2)
+       SIGTERM      15        A      Termination signal
+       SIGUSR1   30,10,16     A      User-defined signal 1
+       SIGUSR2   31,12,17     A      User-defined signal 2
+       SIGCHLD   20,17,18     B      Child stopped or terminated
+       SIGCONT   19,18,25            Continue if stopped
+       SIGSTOP   17,19,23    DEF     Stop process
+       SIGTSTP   18,20,24     D      Stop typed at tty
+       SIGTTIN   21,21,26     D      tty input for background process
+       SIGTTOU   22,22,27     D      tty output for background process
+
+       Next various other signals.
+
+       Signal       Value     Action   Comment
+       ---------------------------------------------------------------------
+       SIGTRAP        5         CG     Trace/breakpoint trap
+       SIGIOT         6         CG     IOT trap. A synonym for SIGABRT
+       SIGEMT       7,-,7       G
+       SIGBUS      10,7,10      AG     Bus error
+       SIGSYS      12,-,12      G      Bad argument to routine (SVID)
+       SIGSTKFLT    -,16,-      AG     Stack fault on coprocessor
+       SIGURG      16,23,21     BG     Urgent condition on socket (4.2 BSD)
+       SIGIO       23,29,22     AG     I/O now possible (4.2 BSD)
+       SIGPOLL                  AG     A synonym for SIGIO (System V)
+       SIGCLD       -,-,18      G      A synonym for SIGCHLD
+       SIGXCPU     24,24,30     AG     CPU time limit exceeded (4.2 BSD)
+       SIGXFSZ     25,25,31     AG     File size limit exceeded (4.2 BSD)
+       SIGVTALRM   26,26,28     AG     Virtual alarm clock (4.2 BSD)
+       SIGPROF     27,27,29     AG     Profile alarm clock
+       SIGPWR      29,30,19     AG     Power failure (System V)
+       SIGINFO      29,-,-      G      A synonym for SIGPWR
+       SIGLOST      -,-,-       AG     File lock lost
+       SIGWINCH    28,28,20     BG     Window resize signal (4.3 BSD, Sun)
+       SIGUNUSED    -,31,-      AG     Unused signal
+       (Here - denotes that a signal is absent; there where three values are given, the first one is usually  valid  for  alpha  and
+       sparc,  the  middle  one  for i386 and ppc, the last one for mips. Signal 29 is SIGINFO / SIGPWR on an alpha but SIGLOST on a
+       sparc.)
+
+       The letters in the "Action" column have the following meanings:
+
+       A      Default action is to terminate the process.
+
+       B      Default action is to ignore the signal.
+
+       C      Default action is to dump core.
+
+       D      Default action is to stop the process.
+
+       E      Signal cannot be caught.
+
+       F      Signal cannot be ignored.
+
+       G      Not a POSIX.1 conformant signal.
+
+*/
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/Shutdown.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/Shutdown.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/Shutdown.c	(revision 16632)
@@ -0,0 +1,28 @@
+# include "uniphot.h"
+
+static FITS_DB *db;
+
+void set_db (FITS_DB *in) {
+  db = in;
+}
+
+/* clean up open / locked ImageCat before shutting down */
+int Shutdown (char *format, ...) {  
+  va_list argp;
+  char *formatplus;
+  
+  ALLOCATE (formatplus, char, strlen(format));
+  strcpy (formatplus, format);
+  strcat (formatplus, "\n");
+
+  va_start (argp, format);
+  vfprintf (stderr, formatplus, argp);
+  free (formatplus);
+  va_end (argp);
+
+  SetProtect (TRUE);
+  gfits_db_close (db);
+  fprintf (stderr, "ERROR: addstar halted\n");
+  exit (1);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/args.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/args.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/args.c	(revision 16632)
@@ -0,0 +1,73 @@
+# include "uniphot.h"
+
+int args (int argc, char **argv) {
+
+  int N;
+
+  /* define time */
+  TimeSelect = FALSE;
+  if ((N = get_argument (argc, argv, "-time"))) {
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &TSTART)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    if (!ohana_str_to_time (argv[N], &TSTOP)) { 
+      fprintf (stderr, "ERROR: syntax error\n");
+      exit (1);
+    }
+    remove_argument (N, &argc, argv);
+    TimeSelect = TRUE;
+  }
+
+  VERBOSE = FALSE;
+  if ((N = get_argument (argc, argv, "-v"))) {
+    VERBOSE = TRUE;
+    remove_argument (N, &argc, argv);
+  }
+
+  NLOOP = 8;
+  if ((N = get_argument (argc, argv, "-n"))) {
+    remove_argument (N, &argc, argv);
+    NLOOP = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  strcpy (STATMODE, "MEAN");
+  if ((N = get_argument (argc, argv, "-statmode"))) {
+    remove_argument (N, &argc, argv);
+    strcpy (STATMODE, argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  UPDATE = FALSE;
+  if ((N = get_argument (argc, argv, "-update"))) {
+    remove_argument (N, &argc, argv);
+    UPDATE = TRUE;
+  }
+
+  /* max separation for unique space group, in degrees */
+  RADIUS = 2.0;
+  if ((N = get_argument (argc, argv, "-radius"))) {
+    remove_argument (N, &argc, argv);
+    RADIUS = atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  /* max separation for unique time group, in days -> seconds */
+  TRANGE = 86400*7.0;
+  if ((N = get_argument (argc, argv, "-trange"))) {
+    remove_argument (N, &argc, argv);
+    TRANGE = 86400*atof (argv[N]);
+    remove_argument (N, &argc, argv);
+  }
+
+  if (argc != 2) {
+    fprintf (stderr, "ERROR: USAGE: uniphot (photcode) [options]\n");
+    exit (2);
+  } 
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/dumpresult.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/dumpresult.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/dumpresult.c	(revision 16632)
@@ -0,0 +1,25 @@
+# include "uniphot.h"
+
+void dumpresult () {
+  short Mcal, Mgrp, Mset;
+  FILE *f;
+  char outfile[64];
+  Group *tgrp;
+
+  for (i = 0; i < Nsgroup; i++) {
+    sprintf (outfile, "test.%02d.dat", i);
+    f = fopen (outfile, "w");
+    for (j = 0; j < sgroup[i].Nimage; j++) {
+      if (sgroup[i].image[j][0].code & IMAGE_BAD) continue;
+      tgrp = (Group *) sgroup[i].imlink[j][0].tgroup;
+      Mcal = sgroup[i].image[j][0].Mcal;
+      Mset = sgroup[i].M;
+      Mgrp = tgrp[0].M;
+      fprintf (f, "%7.4f %7.4f %7.4f %7.4f   %10.6f %10.6f  %f %s\n", 
+	       0.001*Mcal, 0.001*Mgrp, 0.001*Mset, 0.001*sgroup[i].image[j][0].dMcal, 
+	       sgroup[i].image[j][0].coords.crval1, sgroup[i].image[j][0].coords.crval2, (sgroup[i].image[j][0].tzero-915148800)/86400.0, tgrp[0].label);
+    }
+    fclose (f);
+  }
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/find_image_sgroups.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/find_image_sgroups.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/find_image_sgroups.c	(revision 16632)
@@ -0,0 +1,85 @@
+# include "uniphot.h"
+
+Group *find_image_sgroups (FITS_DB *db, ImageLink **Imlink, int *Nsgroup) {
+
+  int i, j, Nimage, Ngroup, Nentry, NENTRY;
+  double r, d, x, y, radius;
+  Group *group;
+  Coords coords;
+  Image *image;
+  ImageLink *imlink;
+
+  imlink = *Imlink;
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  coords.crpix1 = coords.crpix2 = 0.0;
+  coords.cdelt1 = coords.cdelt2 = 1.0; /* scale is degrees, radius in degrees */
+  coords.pc1_1 = coords.pc2_2 = 1.0;
+  coords.pc1_2 = coords.pc2_1 = 0.0;
+  strcpy (coords.ctype, "RA---TAN");
+  
+  Ngroup = 0;
+  ALLOCATE (group, Group, Nimage);
+
+  /* set imlink.sgroups = NULL as a marker */
+  for (i = 0; i < Nimage; i++) imlink[i].sgroup = NULL;
+
+  for (i = 0; i < Nimage; i++) {
+    if (imlink[i].sgroup != NULL) continue;
+    if (image[i].code & ID_IMAGE_NOCAL) continue;
+
+    /* new sgroup, set ref coords */
+    XY_to_RD (&r, &d, 0.5*image[i].NX, 0.5*image[i].NX, &image[i].coords);
+    coords.crval1 = r;
+    coords.crval2 = d;
+
+    /* init sgroup structure */
+    Nentry = 0;
+    NENTRY = 100;
+    ALLOCATE (group[Ngroup].image, Image *, NENTRY);
+    ALLOCATE (group[Ngroup].imlink, ImageLink *, NENTRY);
+    group[Ngroup].M = 0;
+    group[Ngroup].dM = 0;
+    snprintf (group[Ngroup].label, 64, "%10.6f - %10.6f", r, d);
+    group[Ngroup].v1 = r;
+    group[Ngroup].v2 = d;
+
+    /* link this image to sgroup */
+    group[Ngroup].image[Nentry] = &image[i];
+    group[Ngroup].imlink[Nentry] = &imlink[i];
+    imlink[i].sgroup = &group[Ngroup];
+    Nentry ++;
+
+    for (j = 0; j < Nimage; j++) {
+      if (image[j].code & ID_IMAGE_NOCAL) continue;
+      if (imlink[j].sgroup != NULL) continue;
+
+      /* project image center to local coords, check radius */
+      XY_to_RD (&r, &d, 0.5*image[j].NX, 0.5*image[j].NX, &image[j].coords);
+      if (!RD_to_XY (&x, &y, r, d, &coords)) continue; 
+      /* RD_to_XY returns FALSE if opposite hemispheres */
+      radius = hypot (x, y);
+
+      if (radius > RADIUS) continue;
+
+      /* image in sgroup, add to entry */
+      group[Ngroup].image[Nentry] = &image[j];
+      group[Ngroup].imlink[Nentry] = &imlink[j];
+      imlink[j].sgroup = &group[Ngroup];
+      Nentry ++;
+      if (Nentry == NENTRY) {
+	NENTRY += 100;
+	REALLOCATE (group[Ngroup].image, Image *, NENTRY);
+	REALLOCATE (group[Ngroup].imlink, ImageLink *, NENTRY);
+      }
+    }
+    group[Ngroup].Nimage = Nentry;
+    Ngroup ++;
+  }
+  *Nsgroup = Ngroup;
+  return (group);
+}
+
+  /* this is a bit weak: since we use pointers, we can't
+     reallocate group after the pointers are assigned.
+     therefore, we allocate the max possible groups */
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/find_image_tgroups.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/find_image_tgroups.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/find_image_tgroups.c	(revision 16632)
@@ -0,0 +1,84 @@
+# include "uniphot.h"
+
+Group *find_image_tgroups (FITS_DB *db, ImageLink **Imlink, int *Ntgroup) {
+
+  char *start, *stop;
+  int i, j, Nimage, Ngroup, NGROUP, Nentry, NENTRY;
+  unsigned int *time, *tmin, *tmax;
+  Group *group;
+  Image *image;
+  ImageLink *imlink;
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+  ALLOCATE (imlink, ImageLink, Nimage);
+
+  /* sort time list (use only valid images?) */
+  ALLOCATE (time, unsigned int, Nimage);
+  for (i = 0; i < Nimage; i++) {
+    time[i] = image[i].tzero;
+  }
+  sort_time (time, Nimage);
+
+  /* find groups with dt < TRANGE */
+  Ngroup = 0;
+  NGROUP = 100;
+  ALLOCATE (tmin, unsigned int, NGROUP);
+  ALLOCATE (tmax, unsigned int, NGROUP);
+  tmin[Ngroup] = time[0];
+
+  /* generate tgroups */
+  for (i = 0; i < Nimage - 1; i++) {
+    if (time[i+1] - time[i] < TRANGE) continue;
+    
+    tmax[Ngroup] = time[i];
+    
+    Ngroup ++;
+    if (Ngroup == NGROUP) {
+      NGROUP += 100;
+      REALLOCATE (tmin, unsigned int, NGROUP);
+      REALLOCATE (tmax, unsigned int, NGROUP);
+    }
+    tmin[Ngroup] = time[i + 1];
+  }
+  tmax[Ngroup] = time[Nimage - 1];
+  Ngroup ++;
+  ALLOCATE (group, Group, Ngroup);
+
+  /* assign images to groups */
+  for (i = 0; i < Ngroup; i++) {
+    Nentry = 0;
+    NENTRY = 100;
+    ALLOCATE (group[i].image, Image *, NENTRY);
+    ALLOCATE (group[i].imlink, ImageLink *, NENTRY);
+    group[i].M = 0;
+    group[i].dM = 0;
+
+    start = ohana_sec_to_date (tmin[i]);
+    stop = ohana_sec_to_date (tmax[i]);
+    snprintf (group[i].label, 64, "%s - %s", start, stop);
+    free (start);
+    free (stop);
+
+    for (j = 0; j < Nimage; j++) {
+      if (image[j].tzero < tmin[i]) continue;
+      if (image[j].tzero > tmax[i]) continue;
+      if (image[j].code & ID_IMAGE_NOCAL) continue;
+      
+      group[i].image[Nentry] = &image[j];
+      group[i].imlink[Nentry] = &imlink[j];
+      imlink[j].tgroup = &group[i];
+      Nentry ++;
+      if (Nentry == NENTRY) {
+	NENTRY += 100;
+	REALLOCATE (group[i].image, Image *, NENTRY);
+	REALLOCATE (group[i].imlink, ImageLink *, NENTRY);
+      }
+    }
+    group[i].Nimage = Nentry;
+  }
+  *Imlink = imlink;
+  *Ntgroup = Ngroup;
+  return (group);
+}
+
+
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/fit_groups.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/fit_groups.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/fit_groups.c	(revision 16632)
@@ -0,0 +1,76 @@
+# include "uniphot.h"
+
+void fit_tgroup (Group *tgroup, int Ntgroup) {
+
+  int i, j, Nlist;
+  float Mcal, Mgrp;
+  double *mlist, *dlist;
+  StatType stats;
+  Group *sgroup;
+
+  Nlist = tgroup[0].Nimage;
+  for (i = 0; i < Ntgroup; i++) { Nlist = MAX (Nlist, tgroup[i].Nimage); }
+  ALLOCATE (mlist, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+
+  for (i = 0; i < Ntgroup; i++) {
+    for (j = Nlist = 0; j < tgroup[i].Nimage; j++) {
+      if (tgroup[i].image[j][0].code & IMAGE_BAD) continue;
+      sgroup = (Group *) tgroup[i].imlink[j][0].sgroup;
+      Mcal = tgroup[i].image[j][0].Mcal;
+      Mgrp = sgroup[0].M;
+      mlist[Nlist] = (Mcal - Mgrp);
+      dlist[Nlist] = tgroup[i].image[j][0].dMcal;
+      Nlist ++;
+    }
+    liststats (mlist, dlist, Nlist, &stats);
+    tgroup[i].M  = stats.mean;
+    tgroup[i].dMsub = stats.sigma;
+    tgroup[i].Ngood = stats.Nmeas;
+    
+    initstats ("MEAN");
+    liststats (mlist, dlist, Nlist, &stats);
+    tgroup[i].dM = stats.sigma;
+    initstats (STATMODE);
+  }
+  free (mlist);
+  free (dlist);
+}
+
+void fit_sgroup (Group *sgroup, int Nsgroup) {
+
+  int i, j, Nlist;
+  float Mcal, Mgrp;
+  double *mlist, *dlist;
+  StatType stats;
+  Group *tgroup;
+  
+  Nlist = sgroup[0].Nimage;
+  for (i = 0; i < Nsgroup; i++) { Nlist = MAX (Nlist, sgroup[i].Nimage); }
+  ALLOCATE (mlist, double, Nlist);
+  ALLOCATE (dlist, double, Nlist);
+  Nlist = 0;
+
+  for (i = 0; i < Nsgroup; i++) {
+    for (j = Nlist = 0; j < sgroup[i].Nimage; j++) {
+      if (sgroup[i].image[j][0].code & IMAGE_BAD) continue;
+      tgroup = (Group *) sgroup[i].imlink[j][0].tgroup;
+      Mcal = sgroup[i].image[j][0].Mcal;
+      Mgrp = tgroup[0].M;
+      mlist[Nlist] = (Mcal - Mgrp);
+      dlist[Nlist] = sgroup[i].image[j][0].dMcal;
+      Nlist ++;
+    }
+    liststats (mlist, dlist, Nlist, &stats);
+    sgroup[i].M  = stats.mean;
+    sgroup[i].dMsub = stats.sigma;
+    sgroup[i].Ngood = stats.Nmeas;
+
+    initstats ("MEAN");
+    liststats (mlist, dlist, Nlist, &stats);
+    sgroup[i].dM = stats.sigma;
+    initstats (STATMODE);
+  }
+  free (mlist);
+  free (dlist);
+}
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/initialize.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/initialize.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/initialize.c	(revision 16632)
@@ -0,0 +1,22 @@
+# include "uniphot.h"
+
+void initialize (int argc, char **argv) {
+
+  /* are these set correctly? */
+  ConfigInit (&argc, argv);
+  args (argc, argv);
+
+  if ((photcode = GetPhotcodebyName (argv[1])) == NULL) {
+    fprintf (stderr, "ERROR: photcode not found in photcode table\n");
+    exit (1);
+  }
+  if ((photcode[0].type == PHOT_DEP) && (photcode[0].type == PHOT_REF)) {
+    fprintf (stderr, "photcode must be primary or secondary type\n");
+    exit (1);
+  }
+
+  IMAGE_BAD = ID_IMAGE_NOCAL | ID_IMAGE_POOR | ID_IMAGE_SKIP | ID_IMAGE_FEW;
+
+  initstats (STATMODE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/liststats.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/liststats.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/liststats.c	(revision 16632)
@@ -0,0 +1,117 @@
+# include "uniphot.h"
+
+enum {M_MEAN, M_MEDIAN, M_WT_MEAN, M_INNER_MEAN, 
+      M_INNER_WTMEAN, M_CHI_INNER_MEAN, M_CHI_INNER_WTMEAN};
+
+static int statmode;
+
+void initstats (char *mode) {
+
+  statmode = -1;
+  if (!strcmp (mode, "MEAN")) statmode = M_MEAN;
+  if (!strcmp (mode, "MEDIAN")) statmode = M_MEDIAN;
+  if (!strcmp (mode, "WT_MEAN")) statmode = M_WT_MEAN;
+  if (!strcmp (mode, "INNER_MEAN")) statmode = M_INNER_MEAN;
+  if (!strcmp (mode, "INNER_WTMEAN")) statmode = M_INNER_WTMEAN;
+  if (!strcmp (mode, "CHI_INNER_MEAN")) statmode = M_CHI_INNER_MEAN;
+  if (!strcmp (mode, "CHI_INNER_WTMEAN")) statmode = M_CHI_INNER_WTMEAN;
+
+  if (statmode == -1) {
+    fprintf (stderr, "ERROR: invalid stats mode: %s\n", mode);
+    exit (1);
+  }
+}
+
+int liststats (double *value, double *dvalue, int N, StatType *stats) {
+  
+  int i, ks, ke, Nm;
+  double Mo, dMo, M, dM, X2, dS, *chi;
+
+  ke = ks = dMo = 0;
+
+  stats[0].Nmeas = N;
+  stats[0].mean  = 0;
+  stats[0].sigma = 0;
+  if (N < 2) return (FALSE);
+
+  dsortpair (value, dvalue, N);
+  stats[0].median = value[(int)(0.5*N)];
+  stats[0].min    = value[0];
+  stats[0].max    = value[N-1];
+
+  switch (statmode) {
+  case M_MEDIAN:
+    ks = 0;
+    ke = N;
+    Mo = stats[0].median;
+    Nm = N;
+    goto chisq;
+    break;
+  case M_MEAN:
+  case M_WT_MEAN:
+    ks = 0;
+    ke = N;
+    break;
+  case M_INNER_MEAN:
+  case M_INNER_WTMEAN:
+  case M_CHI_INNER_MEAN:
+  case M_CHI_INNER_WTMEAN:
+    ks = 0.25*N + 0.50;
+    ke = 0.75*N + 0.25;
+    if (N <= 3) {
+      ks = 0;
+      ke = N;
+    }
+    break;
+  }    
+
+  if ((statmode == M_CHI_INNER_MEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    ALLOCATE (chi, double, N);
+    for (i = 0; i < N; i++) {
+      chi[i] = (value[i] - stats[0].median) / dvalue[i];
+    }
+    dsortthree (chi, value, dvalue, N);
+    free (chi);
+  }
+
+  /* calculating the per-star offset based on the weighted average */
+  M = dM = Nm = 0;
+  if ((statmode == M_WT_MEAN) || (statmode == M_INNER_WTMEAN) || (statmode == M_CHI_INNER_WTMEAN)) {
+    for (i = ks; i < ke; i++) {
+      M   += value[i] / SQ (dvalue[i]);
+      dM  += 1.0 / SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / dM;
+    dMo = sqrt (1.0 / dM);
+  } else {
+    for (i = ks; i < ke; i++) {
+      M   += value[i];
+      dM  += SQ (dvalue[i]);
+      Nm  ++;  
+    }	
+    Mo = M / (double) Nm;
+    dMo = sqrt (dM / (double) Nm);
+  }
+
+ chisq:
+  /* find sigma and chisq */
+  X2 = dS = 0;
+  for (i = ks; i < ke; i++) {
+    M  = SQ (value[i] - Mo);
+    dM = SQ (dvalue[i]);
+    X2 += M / dM;
+    dS += M;
+  }
+  X2 = X2 / Nm;
+  dS = sqrt (dS / Nm);
+
+  stats[0].mean  = Mo;
+  stats[0].Nmeas = Nm;
+  stats[0].chisq = X2;
+  stats[0].sigma = dS;
+  stats[0].error = dMo;
+
+  return (TRUE);
+}
+
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/load_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/load_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/load_images.c	(revision 16632)
@@ -0,0 +1,11 @@
+# include "uniphot.h"
+
+int load_images (FITS_DB *db) {
+
+  if (VERBOSE) fprintf (stderr, "finding images\n");
+
+  /* read entire db table */
+  if (!dvo_image_load (db, VERBOSE, FALSE)) Shutdown ("can't read image catalog %s", db[0].filename);
+
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/plotstuff.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/plotstuff.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/plotstuff.c	(revision 16632)
@@ -0,0 +1,119 @@
+# include "uniphot.h"
+# include <signal.h>
+
+static int Xgraph[5] = {0,0,0,0,0};
+static int active;
+
+void XDead () {
+  signal (SIGPIPE, XDead);
+  fprintf (stderr, "kapa is dead, must restart\n");
+  Xgraph[active] = -1;
+}
+
+int open_graph (int N) {
+
+  char name[100];
+  
+  active = N;
+
+  sprintf (name, "gastro [%d]", N);
+  Xgraph[N] = KapaOpen ("kapa", name);
+
+  if (Xgraph[N] < 0) {
+    fprintf (stderr, "error starting kapa\n");
+    return (FALSE);
+  }
+  return (TRUE);
+}
+
+void DonePlotting (Graphdata *graphmode, int N) {
+
+  if (Xgraph[N] == 0) return;
+  KapaBox (Xgraph[N], graphmode);
+  return;
+}
+
+void PrepPlotting (int Npts, Graphdata *graphmode, int N) {
+
+  active = N;
+  if (Npts < 1) return;
+
+  KapaPrepPlot (Xgraph[N], Npts, graphmode);
+}
+
+void PlotVector (int Npts, float *vect, int mode, int N) {
+
+  int Nbytes;
+
+  if (Npts < 1) return;
+  active = N;
+  KapaPlotVector (Xgraph[N], Npts, vect);
+}
+
+void PlotLabel (char *string, int N) {
+
+  char buffer[32];
+
+  if (Xgraph[N] == 0) return;
+
+  KapaSendLabel (Xgraph[N[, string, 4);
+}
+
+void PlotReset (int N) {
+
+  char buffer[128];
+  int i;
+
+  /* test Xgraph[N], flush junk from pipe */
+  signal (SIGPIPE, XDead);
+  fcntl (Xgraph[N], F_SETFL,  O_NONBLOCK); 
+  for (i = 0; (read (Xgraph[N], buffer, 64) > 0) && (i < 20); i++);
+  fcntl (Xgraph[N], F_SETFL, !O_NONBLOCK); 
+  
+  if (Xgraph[N] < 1) if (!open_graph(N)) return;
+  KapaClearSections (Xgraph[N]);
+}
+
+void JpegPlot (Graphdata *graphmode, int N, char *filename) {
+
+  if (Xgraph[N] == 0) return;
+
+  KapaPNG (Xgraph[N], filename);
+  return;
+}
+
+void PSPlot (Graphdata *graphmode, int N, char *filename) {
+
+  if (Xgraph[N] == 0) return;
+
+  KiiPS (Xgraph[N], filename, TRUE, KAPA_PS_NEWPLOT, "default");
+  return;
+}
+
+/* include these lines to plot a pair of vectors: 
+
+   typedef struct {
+   double xmin, xmax, ymin, ymax;
+   int style, ptype, ltype, etype, color;
+   double lweight, size;
+   } Graphdata;
+   Graphdata graphdata;
+   
+   graphdata.xmin = -200;
+   graphdata.xmax = 4200;
+   graphdata.ymin = -500;
+   graphdata.ymax = 500;
+   graphdata.style = 2;
+   graphdata.ptype = 2;
+   graphdata.ltype = 0;
+   graphdata.etype = 0;
+   graphdata.color = 0;
+   graphdata.lweight = 0;
+   graphdata.size = 0.5;
+   
+   PrepPlotting (N, &graphdata, n);
+   PlotVector (N, Y, 0, n);
+   PlotVector (N, dM, 1, n);
+   DonePlotting (&graphdata, n);
+   
+ */
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/sort.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/sort.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/sort.c	(revision 16632)
@@ -0,0 +1,13 @@
+# include "uniphot.h"
+
+void sort_time (unsigned int *value, int N) {
+
+# define SWAPFUNC(A,B){ unsigned int tmp = value[A]; value[A] = value[B]; value[B] = tmp; }
+# define COMPARE(A,B)(value[A] < value[B])
+
+  OHANA_SORT (N, COMPARE, SWAPFUNC);
+
+# undef SWAPFUNC
+# undef COMPARE
+
+}
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/subset_images.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/subset_images.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/subset_images.c	(revision 16632)
@@ -0,0 +1,36 @@
+# include "uniphot.h"
+
+int subset_images (FITS_DB *db) {
+
+  int    i, Nimage, equiv;
+  int    Nkeep, *keep;
+  Image *image;
+
+  /* use a vtable to keep the images to be calibrated */
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  Nkeep = 0;
+  ALLOCATE (keep, int, Nimage);
+
+  /* mark images to be calibrated */
+  for (i = 0; i < Nimage; i++) {
+      
+    image[i].code |= ID_IMAGE_NOCAL;
+
+    /* select images by photcode */
+    equiv = GetPhotcodeEquivCodebyCode (image[i].photcode);
+    if (equiv != photcode[0].code) continue;
+
+    /* select images by time */
+    if (TimeSelect) {
+      if (image[i].tzero < TSTART) continue;
+      if (image[i].tzero > TSTOP) continue;
+    }
+    image[i].code &= ~ID_IMAGE_NOCAL;
+    keep[Nkeep] = i;
+    Nkeep ++;
+  }
+
+  gfits_vtable_from_ftable (&db[0].ftable, &db[0].vtable, keep, Nkeep);
+  return (TRUE);
+}
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/uniphot.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/uniphot.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/uniphot.c	(revision 16632)
@@ -0,0 +1,63 @@
+# include "uniphot.h"
+
+int main (int argc, char **argv) {
+
+  int i, Ntgroup, Nsgroup, status;
+  Group *tgroup, *sgroup;
+  ImageLink *imlinks;
+  FITS_DB db;
+
+  /* get configuration info, args, lockfile */
+  initialize (argc, argv);
+
+  set_db (&db);
+  status = dvo_image_lock (&db, ImageCat, 60.0, (UPDATE ? LCK_XCLD : LCK_SOFT));
+  if (!status) Shutdown ("ERROR: failure to lock image catalog %s", db.filename);
+  if (db.dbstate == LCK_EMPTY) Shutdown ("ERROR: No images in catalog %s (1)", db.filename);
+  if (!UPDATE) dvo_image_unlock (&db); 
+
+  /* load images */
+  load_images (&db);
+  
+  /* filter image list by selection */
+  subset_images (&db);
+
+  tgroup = find_image_tgroups (&db, &imlinks, &Ntgroup);
+  sgroup = find_image_sgroups (&db, &imlinks, &Nsgroup);
+
+  /* determine fit values */
+  for (i = 0; i < NLOOP; i++) {
+
+    fit_tgroup (tgroup, Ntgroup);
+    fit_sgroup (sgroup, Nsgroup); 
+
+  }    
+
+  fprintf (stdout, "# uniphot results for filter %s\n", photcode[0].name);
+  fprintf (stdout, "# STATMODE: %s\n", STATMODE);
+  fprintf (stdout, "# NLOOP: %d\n", NLOOP);
+  fprintf (stdout, "# time groups : %d\n", Ntgroup);
+  for (i = 0; i < Ntgroup; i++) {
+    fprintf (stdout, "%s %5d %5d %7.4f  %7.4f %7.4f\n", tgroup[i].label, 
+	     tgroup[i].Nimage, tgroup[i].Ngood, 0.001*tgroup[i].M, 0.001*tgroup[i].dM, 0.001*tgroup[i].dMsub);
+  }
+  fprintf (stdout, "\n");
+
+  fprintf (stdout, "# space groups : %d\n", Nsgroup);
+  for (i = 0; i < Nsgroup; i++) {
+    fprintf (stdout, "%s %5d %5d %7.4f  %7.4f %7.4f\n", sgroup[i].label, 
+	     sgroup[i].Nimage, sgroup[i].Ngood, 0.001*sgroup[i].M, 0.001*sgroup[i].dM, 0.001*sgroup[i].dMsub);
+  }
+  if (!UPDATE) exit (0);
+
+  update (&db, sgroup, Nsgroup);
+  dvo_image_unlock (&db); 
+
+  exit (0);
+}
+
+/* add a mode to check / force consistency between image.Mcal and
+   measure.Mcal.
+
+   use the method in delstar to match image with measure (gregions (image), etc)
+*/
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/update.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/update.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/update.c	(revision 16632)
@@ -0,0 +1,122 @@
+# include "uniphot.h"
+# include <glob.h>
+
+void update (FITS_DB *db, Group *sgroup, int Nsgroup) {
+
+  int i, j, status, Nmin, Nimage;
+  char line[256];
+  glob_t pglob;
+  double Rmin, Rmax, Dmin, Dmax, x, y, radius;
+  Image *image;
+  Catalog catalog;
+  Coords coords;
+
+  image = gfits_table_get_Image (&db[0].ftable, &Nimage, &db[0].swapped);
+
+  /* clear the NOCAL flags */
+  for (i = 0; i < Nimage; i++) {
+    image[i].code &= ~ID_IMAGE_NOCAL;
+  }
+
+  /* apply calculated space-group offset to image Mcal values */
+  for (i = 0; i < Nsgroup; i++) {
+    for (j = 0; j < sgroup[i].Nimage; j++) {
+      sgroup[i].image[j][0].Mcal -= sgroup[i].M;
+    }
+  }
+
+  /** write image table **/
+  dvo_image_update (db, VERBOSE);
+
+  // XXX this process uses the existence of the file to perform the update
+  // XXX convert this to an examination of the SkyTable
+  /** update catalog tables **/
+  pglob.gl_offs = 0;
+  sprintf (line, "%s/*/*.cpt", CATDIR);
+  status = glob (line, 0, NULL, &pglob);
+
+  coords.crpix1 = coords.crpix2 = 0.0;
+  coords.cdelt1 = coords.cdelt2 = 1.0; /* scale is degrees, radius in degrees */
+  coords.pc1_1 = coords.pc2_2 = 1.0;
+  coords.pc1_2 = coords.pc2_1 = 0.0;
+  strcpy (coords.ctype, "RA---TAN");
+  
+  for (i = 0; i < pglob.gl_pathc; i++) {
+    catalog.filename = pglob.gl_pathv[i];
+    catalog.catflags = LOAD_AVES | LOAD_MEAS | LOAD_MISS | LOAD_SECF;
+    catalog.Nsecfilt  = GetPhotcodeNsecfilt ();
+
+    // an error exit status here is a significant error
+    if (!dvo_catalog_open (&catalog, NULL, VERBOSE, "a")) {
+      fprintf (stderr, "ERROR: failure to open/create catalog file %s\n", catalog.filename);
+      exit (2);
+    }
+    if (!catalog.Naves_disk) {
+      dvo_catalog_unlock (&catalog);
+      dvo_catalog_free (&catalog);
+      continue;
+    }
+
+    gfits_scan (&catalog.header, "RA0", "%lf",  1, &Rmin);
+    gfits_scan (&catalog.header, "RA1", "%lf",  1, &Rmax);
+    gfits_scan (&catalog.header, "DEC0", "%lf", 1, &Dmin);
+    gfits_scan (&catalog.header, "DEC1", "%lf", 1, &Dmax);
+    while (Rmin <   0.0) { Rmin += 360.0; }
+    while (Rmin > 360.0) { Rmin -= 360.0; }
+    while (Rmax <   0.0) { Rmax += 360.0; }
+    while (Rmax > 360.0) { Rmax -= 360.0; }
+
+    coords.crval1 = 0.5*(Rmin + Rmax);
+    coords.crval2 = 0.5*(Dmin + Dmax);
+
+    Nmin = 0;
+    Rmin = 1000;
+    /* primitive version: match catalog with closest sgroup */
+    for (j = 0; j < Nsgroup; j++) {
+      if (!RD_to_XY (&x, &y, sgroup[j].v1, sgroup[j].v2, &coords)) continue;
+      radius = hypot (x, y);
+      if ((j == 0) || (radius < Rmin)) {
+	Rmin = radius;
+	Nmin = j;
+      }
+    }
+
+    fprintf (stderr, "catalog: %s sgroup: %d %s %f\n", catalog.filename, Nmin, sgroup[Nmin].label, Rmin);
+    update_dvo_catalog (&catalog, &sgroup[Nmin], (Rmin > 2*RADIUS)); 
+    dvo_catalog_save (&catalog, VERBOSE);
+    dvo_catalog_unlock (&catalog);
+    dvo_catalog_free (&catalog);
+  }
+}      
+
+/* loop over all average 
+
+   if (source equiv photcode)
+
+   loop over sgroups
+
+   if (radius < RADIUS) 
+      
+   average.M (+/-) source.M
+*/
+
+/* loop over all measure 
+
+   if (source equiv photcode)
+
+   loop over sgroups
+
+   if (radius < RADIUS) 
+      
+   measure.Mcal (+/-) source.M
+*/
+
+/* alternative (slower, more robust)
+
+   loop over all average
+   loop over all average.Nm
+   select measure with source equiv photcode
+   match measure to image, get Mcal & offset
+   if any offset for average[i] is different, give error
+   apply offset to average.M
+*/
Index: /branches/eam_branch_20080223/Ohana/src/uniphot/src/update_catalog.c
===================================================================
--- /branches/eam_branch_20080223/Ohana/src/uniphot/src/update_catalog.c	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/src/uniphot/src/update_catalog.c	(revision 16632)
@@ -0,0 +1,34 @@
+# include "uniphot.h"
+
+void update_dvo_catalog (Catalog *catalog, Group *sgroup, int warn) {
+
+  int i, j, m, found;
+  int Nsec, Nsecfilt;
+  PhotCode *code;
+
+  Nsec = GetPhotcodeNsec (photcode[0].code);
+  Nsecfilt = GetPhotcodeNsecfilt ();
+
+  found = 0;    
+  for (i = 0; i < catalog[0].Naverage; i++) {
+    
+    if (!isnan(catalog[0].secfilt[i*Nsecfilt+Nsec].M)) {
+      catalog[0].secfilt[i*Nsecfilt+Nsec].M += sgroup[0].M;
+    }
+
+    m = catalog[0].average[i].offset;
+    for (j = 0; j < catalog[0].average[i].Nm; j++, m++) {
+      code = GetPhotcodebyCode (catalog[0].measure[m].photcode);
+      if (code == NULL) continue;
+      if (code[0].type != PHOT_DEP) continue;
+      if (code[0].equiv != photcode[0].code) continue;
+      catalog[0].measure[m].Mcal -= sgroup[0].M;
+      found ++;
+    }
+  }
+
+  if (found) {
+    fprintf (stderr, "found %d matches\n", found);
+    if (warn) fprintf (stderr, "warning: updated values, perhaps out of range?\n");
+  }
+}
Index: /branches/eam_branch_20080223/Ohana/test/addstar/README
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/README	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/README	(revision 16632)
@@ -0,0 +1,13 @@
+
+This directory contains DVO/addstar tests.  DVO/addstar has a large
+number of modes and options which must be tested.  Each directory
+defines tests for a major addstar mode.  The tests are also divided
+into those using the stand-alone version of addstar (TEST.sa) and
+those using the client/server version (TEST.cs).  There are also a set
+of tests using the unthreaded client/server setup (TEST.cu).  
+
+refcat:  add stars to a database from the reference catalog
+reflist: add stars to a database from an ascii list
+image: addstar to a database from an image
+fakeimage: add simulated images to the database
+
Index: /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+catdir.*
Index: /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/Makefile	(revision 16632)
@@ -0,0 +1,245 @@
+
+DVOCHECK = ./dvocheck
+
+all: megacam asca
+
+asca: asca.raw asca.mef asca.split
+
+asca.raw: asca.loneos.raw asca.elixir.raw asca.pmtest.raw asca.panstarrs.raw
+asca.mef: asca.loneos.mef asca.elixir.mef asca.pmtest.mef asca.panstarrs.mef
+asca.split: asca.loneos.split asca.elixir.split asca.pmtest.split asca.panstarrs.split
+
+######
+asca.L1:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	$(DVOCHECK) catdir.asca.L1.raw asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	$(DVOCHECK) catdir.asca.L1.mef asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	$(DVOCHECK) catdir.asca.L1.split asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L1.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar -resort -D CATDIR catdir.asca.L1.update
+	$(DVOCHECK) catdir.asca.L1.update asca
+
+######
+asca.L2:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	$(DVOCHECK) catdir.asca.L2.raw asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	$(DVOCHECK) catdir.asca.L2.mef asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	$(DVOCHECK) catdir.asca.L2.split asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 2 -D CATDIR catdir.asca.L2.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar -resort -D CATDIR catdir.asca.L2.update
+	$(DVOCHECK) catdir.asca.L2.update asca
+
+######
+asca.L3:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	$(DVOCHECK) catdir.asca.L3.raw asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	$(DVOCHECK) catdir.asca.L3.mef asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	$(DVOCHECK) catdir.asca.L3.split asca
+#
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D SKY_DEPTH 3 -D CATDIR catdir.asca.L3.update -D CATFORMAT ELIXIR -D CATMODE SPLIT -update -missed -closest
+	addstar -resort -D CATDIR catdir.asca.L3.update
+	$(DVOCHECK) catdir.asca.L3.update asca
+
+######
+asca.loneos.raw:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.raw -D CATFORMAT LONEOS -D CATMODE RAW
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.raw -D CATFORMAT LONEOS -D CATMODE RAW
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.raw -D CATFORMAT LONEOS -D CATMODE RAW
+	$(DVOCHECK) catdir.asca.loneos.raw asca
+
+asca.elixir.raw:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	$(DVOCHECK) catdir.asca.elixir.raw asca
+
+asca.pmtest.raw:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.raw -D CATFORMAT PMTEST -D CATMODE RAW
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.raw -D CATFORMAT PMTEST -D CATMODE RAW
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.raw -D CATFORMAT PMTEST -D CATMODE RAW
+	$(DVOCHECK) catdir.asca.pmtest.raw asca
+
+asca.panstarrs.raw:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.raw -D CATFORMAT PANSTARRS -D CATMODE RAW
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.raw -D CATFORMAT PANSTARRS -D CATMODE RAW
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.raw -D CATFORMAT PANSTARRS -D CATMODE RAW
+	$(DVOCHECK) catdir.asca.panstarrs.raw asca
+
+#######
+asca.loneos.mef:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.mef -D CATFORMAT LONEOS -D CATMODE MEF
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.mef -D CATFORMAT LONEOS -D CATMODE MEF
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.mef -D CATFORMAT LONEOS -D CATMODE MEF
+	$(DVOCHECK) catdir.asca.loneos.mef asca
+
+asca.elixir.mef:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	$(DVOCHECK) catdir.asca.elixir.mef asca
+
+asca.pmtest.mef:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.mef -D CATFORMAT PMTEST -D CATMODE MEF
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.mef -D CATFORMAT PMTEST -D CATMODE MEF
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.mef -D CATFORMAT PMTEST -D CATMODE MEF
+	$(DVOCHECK) catdir.asca.pmtest.mef asca
+
+asca.panstarrs.mef:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.mef -D CATFORMAT PANSTARRS -D CATMODE MEF
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.mef -D CATFORMAT PANSTARRS -D CATMODE MEF
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.mef -D CATFORMAT PANSTARRS -D CATMODE MEF
+	$(DVOCHECK) catdir.asca.panstarrs.mef asca
+
+#######
+asca.loneos.split:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.split -D CATFORMAT LONEOS -D CATMODE SPLIT
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.split -D CATFORMAT LONEOS -D CATMODE SPLIT
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.loneos.split -D CATFORMAT LONEOS -D CATMODE SPLIT
+	$(DVOCHECK) catdir.asca.loneos.split asca
+
+asca.elixir.split:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.elixir.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	$(DVOCHECK) catdir.asca.elixir.split asca
+
+asca.pmtest.split:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.split -D CATFORMAT PMTEST -D CATMODE SPLIT
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.split -D CATFORMAT PMTEST -D CATMODE SPLIT
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.pmtest.split -D CATFORMAT PMTEST -D CATMODE SPLIT
+	$(DVOCHECK) catdir.asca.pmtest.split asca
+
+asca.panstarrs.split:
+	addstar asca/to_r20060121ut005757s32340.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.split -D CATFORMAT PANSTARRS -D CATMODE SPLIT
+	addstar asca/to_r20060121ut015747s35940.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.split -D CATFORMAT PANSTARRS -D CATMODE SPLIT
+	addstar asca/to_r20060121ut025738s39540.smp -p ASCA_RED -D CATDIR catdir.asca.panstarrs.split -D CATFORMAT PANSTARRS -D CATMODE SPLIT
+	$(DVOCHECK) catdir.asca.panstarrs.split asca
+
+# megacam images:
+# add in both FITS and RAW versions of output data
+# 'best' and 'ap25' are from Sextractor / imclean
+# 'ps10' is from psphot direct
+
+megacam: megacam.raw megacam.mef megacam.split
+
+megacam.raw: megacam.loneos.raw megacam.elixir.raw megacam.pmtest.raw megacam.panstarrs.raw
+megacam.mef: megacam.loneos.mef megacam.elixir.mef megacam.pmtest.mef megacam.panstarrs.mef
+megacam.split: megacam.loneos.split megacam.elixir.split megacam.pmtest.split megacam.panstarrs.split
+
+#######
+megacam.loneos.raw:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.loneos.raw -D CATFORMAT LONEOS -D CATMODE RAW
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.loneos.raw -D CATFORMAT LONEOS -D CATMODE RAW
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.loneos.raw -D CATFORMAT LONEOS -D CATMODE RAW
+	$(DVOCHECK) catdir.megacam.loneos.raw megacam
+
+megacam.elixir.raw:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.elixir.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.elixir.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.elixir.raw -D CATFORMAT ELIXIR -D CATMODE RAW
+	$(DVOCHECK) catdir.megacam.elixir.raw megacam
+
+megacam.pmtest.raw:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.pmtest.raw -D CATFORMAT PMTEST -D CATMODE RAW
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.pmtest.raw -D CATFORMAT PMTEST -D CATMODE RAW
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.pmtest.raw -D CATFORMAT PMTEST -D CATMODE RAW
+	$(DVOCHECK) catdir.megacam.pmtest.raw megacam
+
+megacam.panstarrs.raw:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.panstarrs.raw -D CATFORMAT PANSTARRS -D CATMODE RAW
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.panstarrs.raw -D CATFORMAT PANSTARRS -D CATMODE RAW
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.panstarrs.raw -D CATFORMAT PANSTARRS -D CATMODE RAW
+	$(DVOCHECK) catdir.megacam.panstarrs.raw megacam
+
+#######
+megacam.loneos.mef:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.loneos.mef -D CATFORMAT LONEOS -D CATMODE MEF
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.loneos.mef -D CATFORMAT LONEOS -D CATMODE MEF
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.loneos.mef -D CATFORMAT LONEOS -D CATMODE MEF
+	$(DVOCHECK) catdir.megacam.loneos.mef megacam
+
+megacam.elixir.mef:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.elixir.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.elixir.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.elixir.mef -D CATFORMAT ELIXIR -D CATMODE MEF
+	$(DVOCHECK) catdir.megacam.elixir.mef megacam
+
+megacam.pmtest.mef:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.pmtest.mef -D CATFORMAT PMTEST -D CATMODE MEF
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.pmtest.mef -D CATFORMAT PMTEST -D CATMODE MEF
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.pmtest.mef -D CATFORMAT PMTEST -D CATMODE MEF
+	$(DVOCHECK) catdir.megacam.pmtest.mef megacam
+
+megacam.panstarrs.mef:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.panstarrs.mef -D CATFORMAT PANSTARRS -D CATMODE MEF
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.panstarrs.mef -D CATFORMAT PANSTARRS -D CATMODE MEF
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.panstarrs.mef -D CATFORMAT PANSTARRS -D CATMODE MEF
+	$(DVOCHECK) catdir.megacam.panstarrs.mef megacam
+
+#######
+megacam.loneos.split:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.loneos.split -D CATFORMAT LONEOS -D CATMODE SPLIT
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.loneos.split -D CATFORMAT LONEOS -D CATMODE SPLIT
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.loneos.split -D CATFORMAT LONEOS -D CATMODE SPLIT
+	$(DVOCHECK) catdir.megacam.loneos.split megacam
+
+megacam.elixir.split:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.elixir.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.elixir.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.elixir.split -D CATFORMAT ELIXIR -D CATMODE SPLIT
+	$(DVOCHECK) catdir.megacam.elixir.split megacam
+
+megacam.pmtest.split:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.pmtest.split -D CATFORMAT PMTEST -D CATMODE SPLIT
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.pmtest.split -D CATFORMAT PMTEST -D CATMODE SPLIT
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.pmtest.split -D CATFORMAT PMTEST -D CATMODE SPLIT
+	$(DVOCHECK) catdir.megacam.pmtest.split megacam
+
+megacam.panstarrs.split:
+	addstar megacam/720357o13.best.smp -D CATDIR catdir.megacam.panstarrs.split -D CATFORMAT PANSTARRS -D CATMODE SPLIT
+	addstar megacam/720357o13.ap25.smp -D CATDIR catdir.megacam.panstarrs.split -D CATFORMAT PANSTARRS -D CATMODE SPLIT
+	addstar megacam/720357o13.ps10.cmp -D CATDIR catdir.megacam.panstarrs.split -D CATFORMAT PANSTARRS -D CATMODE SPLIT
+	$(DVOCHECK) catdir.megacam.panstarrs.split megacam
+
+#######
+
+clean:
+	rm -rf catdir.*
Index: /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/dvocheck
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/dvocheck	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/dvocheck	(revision 16632)
@@ -0,0 +1,29 @@
+#!/usr/bin/env dvo
+
+if ($argv:n != 2) 
+  echo "USAGE: validate (catdir) (mode)"
+  echo $argv:n
+  exit 2
+end
+
+catdir $argv:0
+$KAPA = kapa -nomap
+
+if ("$argv:1" == "megacam") 
+  region 300.0 10.18 0.3
+end
+
+if ("$argv:1" == "asca")
+  resize -g 800 420
+  usleep 200000
+  region 60 0 90 ait
+end
+
+mextract ra
+if (ra[] == 0)
+  echo "no stars found for $1"
+  exit 1
+end
+
+echo "found ra[] stars"
+exit 0
Index: /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/photcode.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/photcode.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/photcode.txt	(revision 16632)
@@ -0,0 +1,75 @@
+# this file contains the list of valid photometry codes.
+# there should be one code for each combination of CCD, filter, and
+# telescope (and possibly additional ones if filter transmission
+# reduces with time).  The code on each line is a unique number, while
+# the name is a representative name.  The type defines how the
+# photometry is treated.  There can only be one primary photcode.  There
+# should only be a few secondary photcodes: these are the calibrated
+# values for stars.  The dependent photcodes are those which are
+# equivalent to a primary or secondary photcode, and are equated after
+# photometric solutions.  Reference photcodes are for anything without
+# a dynamic solution: the reference values are provided externally.
+
+# a bogosity in scatfit: it assumes primary photcodes are those which
+# N % 50 == 0
+
+# I discovered that the standards star analysis and the photreg
+# process are inconsistent.  the standard star analysis was using the
+# per-chip zero-points while photreg was using the per-filter
+# zero-points.  these should have been the same, but were not.  See
+# cfh12.photcode.original for the version with this error.  This file
+# now contains consistent entries
+
+# code name		type  zero    airmass  offset   c1   c2   slope  <color> equivalence
+#  1    B		pri   26.017  -0.15     -       1023 1024 0.016     -      1
+#  2    V		sec   26.220  -0.12     -       1023 1024 0.008     -      2
+#  3    R		sec   26.190  -0.09     -       1024 1025 0.028     -      3
+#  4    I		sec   26.185  -0.04     -       1025 1027 0.107     -      4
+
+#  1    B		pri   26.017  -0.15     -       1003 1004 0.016     -      1
+#  2    V		sec   26.220  -0.12     -       1003 1004 0.008     -      2
+#  3    R		sec   26.190  -0.09     -       1004 1005 0.028     -      3
+#  4    I		sec   26.185  -0.04     -       1005 1007 0.107     -      4
+
+  1    B		pri   26.000  -0.15     -       1003 1004 0.016     -      1
+  2    V		sec   26.150  -0.12     -       1003 1004 0.008     -      2
+  3    R		sec   26.190  -0.09     -       1003 1004 0.028     -      3
+  4    I		sec   26.135  -0.04     -       1003 1004 0.107     -      4
+  5    Z		sec   25.830  -0.03     -       -    -    -         -      5
+
+  1000 USNO_BLUE	ref   -     -        -       -  -   -      -        -
+  1001 USNO_RED		ref   -     -        -       -  -   -      -        -
+
+    50 ASCA_RED    	dep  10.000 0.0      -       -  -   -      -        3
+    51 ASCA_BLUE    	dep  10.000 0.0      -       -  -   -      -        3
+
+  1002 U_L92		ref   -     -        -       -  -   -      -        -
+  1003 B_L92		ref   -     -        -       -  -   -      -        -
+  1004 V_L92		ref   -     -        -       -  -   -      -        -
+  1005 R_L92		ref   -     -        -       -  -   -      -        -
+  1007 I_L92		ref   -     -        -       -  -   -      -        -
+
+  1022 U_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1023 B_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1024 V_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1025 R_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1027 I_L92_HQ		ref   -     -        -       -  -   -      -        -
+
+  1012 U_STET		ref   -     -        -       -  -   -      -        -
+  1013 B_STET		ref   -     -        -       -  -   -      -        -
+  1014 V_STET		ref   -     -        -       -  -   -      -        -
+  1015 R_STET		ref   -     -        -       -  -   -      -        -
+  1017 I_STET		ref   -     -        -       -  -   -      -        -
+
+  1100 GSC_M    	ref   -     -        -       -  -   -      -        -
+  1101 SAO		ref   -     -        -       -  -   -      -        -
+
+  1200 TYCHO_B		ref   -     -        -       -  -   -      -        -
+  1201 TYCHO_V		ref   -     -        -       -  -   -      -        -
+
+  2011 2MASS_J          ref   -     -        -       -  -   -      -        -
+  2012 2MASS_H          ref   -     -        -       -  -   -      -        -
+  2013 2MASS_K          ref   -     -        -       -  -   -      -        -
+
+  100  CFH12K.B.00	dep   26.000 -0.15     -       -  -   -      -        1
+  101  MEGACAM.r.13	dep   26.000 -0.15     -       -  -   -      -        1
Index: /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/ptolemy.rc
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/ptolemy.rc	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/image.sa/ptolemy.rc	(revision 16632)
@@ -0,0 +1,23 @@
+# .ptolemyrc
+ 
+REFSDIR                 ../../refs
+
+# asca camera settings
+UT-KEYWORD              UTSHUT
+DATE-KEYWORD            DATE
+DATE-MODE               yyyy-mm-dd
+
+# matching radius (arcseconds)
+# RADIUS  1.0  (old name, deprecated)
+ADDSTAR_RADIUS  1.0
+
+GSCFILE $REFSDIR/GSCregions.tbl
+CATDIR catdir
+PHOTCODE_FILE photcode.txt
+
+USNO_A_DIR /data/elixir/srcdir/refs/usno
+USNO_B_DIR /data/elixir/srcdir/refs/usnob
+
+ZERO_PT 25.0
+
+GSCDIR /data/elixir/srcdir/refs/gsc
Index: /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/.cvsignore
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/.cvsignore	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/.cvsignore	(revision 16632)
@@ -0,0 +1,1 @@
+catdir.*
Index: /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/Makefile	(revision 16632)
@@ -0,0 +1,91 @@
+
+REG = -region 0 1 0 1
+
+usno: usno.photcodes usno.formats usno.depths
+usno.depths:  usno.depths.raw  usno.depths.mef  usno.depths.split
+usno.formats: usno.formats.raw usno.formats.mef usno.formats.split
+
+gsc:
+	addstar -v -cat GSC $(REG) -D CATDIR catdir.gsc
+	dvocheck catdir.gsc gsc
+
+2mass:
+	addstar -cat 2MASS $(REG) -D CATDIR catdir.2mass -photcode 2MASS_J
+	addstar -cat 2MASS $(REG) -D CATDIR catdir.2mass -photcode 2MASS_H
+	addstar -cat 2MASS $(REG) -D CATDIR catdir.2mass -photcode 2MASS_K
+	dvocheck catdir.2mass 2mass
+
+tycho:
+	addstar -cat TYCHO $(REG) -D CATDIR catdir.tycho -photcode TYCHO_B
+	addstar -cat TYCHO $(REG) -D CATDIR catdir.tycho -photcode TYCHO_V
+	dvocheck catdir.tycho tycho
+
+usnob:
+	addstar -cat USNOB $(REG) -D CATDIR catdir.usnob -photcode USNO_RED
+	addstar -cat USNOB $(REG) -D CATDIR catdir.usnob -photcode USNO_BLUE
+	dvocheck catdir.usnob usnob
+
+usno.photcodes:
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno -photcode USNO_RED
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno -photcode USNO_BLUE
+	dvocheck catdir.usno usno
+
+usno.formats.raw:
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.raw.loneos    -photcode USNO_BLUE -D CATFORMAT LONEOS
+	dvocheck catdir.usno.raw.loneos usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.raw.elixir    -photcode USNO_BLUE -D CATFORMAT ELIXIR
+	dvocheck catdir.usno.raw.elixir usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.raw.pmtest    -photcode USNO_BLUE -D CATFORMAT PMTEST
+	dvocheck catdir.usno.raw.pmtest usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.raw.panstarrs -photcode USNO_BLUE -D CATFORMAT PANSTARRS
+	dvocheck catdir.usno.raw.panstarrs usno
+
+usno.formats.mef:
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.mef.loneos    -photcode USNO_BLUE -D CATMODE MEF -D CATFORMAT LONEOS 
+	dvocheck catdir.usno.mef.loneos usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.mef.elixir    -photcode USNO_BLUE -D CATMODE MEF -D CATFORMAT ELIXIR
+	dvocheck catdir.usno.mef.elixir usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.mef.pmtest    -photcode USNO_BLUE -D CATMODE MEF -D CATFORMAT PMTEST
+	dvocheck catdir.usno.mef.pmtest usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.mef.panstarrs -photcode USNO_BLUE -D CATMODE MEF -D CATFORMAT PANSTARRS
+	dvocheck catdir.usno.mef.panstarrs usno
+
+usno.formats.split:
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.split.loneos    -photcode USNO_BLUE -D CATMODE SPLIT -D CATFORMAT LONEOS
+	dvocheck catdir.usno.split.loneos usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.split.elixir    -photcode USNO_BLUE -D CATMODE SPLIT -D CATFORMAT ELIXIR
+	dvocheck catdir.usno.split.elixir usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.split.pmtest    -photcode USNO_BLUE -D CATMODE SPLIT -D CATFORMAT PMTEST
+	dvocheck catdir.usno.split.pmtest usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.split.panstarrs -photcode USNO_BLUE -D CATMODE SPLIT -D CATFORMAT PANSTARRS
+	dvocheck catdir.usno.split.panstarrs usno
+
+usno.depths.raw:
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.raw.L2 -photcode USNO_BLUE -D SKY_DEPTH 2 -D CATMODE RAW
+	dvocheck catdir.usno.raw.L2 usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.raw.L3 -photcode USNO_BLUE -D SKY_DEPTH 3 -D CATMODE RAW
+	dvocheck catdir.usno.raw.L3 usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.raw.L4 -photcode USNO_BLUE -D SKY_DEPTH 4 -D CATMODE RAW
+	dvocheck catdir.usno.raw.L4 usno
+
+usno.depths.mef:
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.mef.L2 -photcode USNO_BLUE -D SKY_DEPTH 2 -D CATMODE MEF
+	dvocheck catdir.usno.mef.L2 usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.mef.L3 -photcode USNO_BLUE -D SKY_DEPTH 3 -D CATMODE MEF
+	dvocheck catdir.usno.mef.L3 usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.mef.L4 -photcode USNO_BLUE -D SKY_DEPTH 4 -D CATMODE MEF
+	dvocheck catdir.usno.mef.L4 usno
+
+usno.depths.split:
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.split.L2 -photcode USNO_BLUE -D SKY_DEPTH 2 -D CATMODE SPLIT
+	dvocheck catdir.usno.split.L2 usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.split.L3 -photcode USNO_BLUE -D SKY_DEPTH 3 -D CATMODE SPLIT
+	dvocheck catdir.usno.split.L3 usno
+	addstar -cat USNO $(REG) -D CATDIR catdir.usno.split.L4 -photcode USNO_BLUE -D SKY_DEPTH 4 -D CATMODE SPLIT
+	dvocheck catdir.usno.split.L4 usno
+
+
+#####
+
+clean:
+	rm -rf catdir.*
Index: /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/dvocheck
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/dvocheck	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/dvocheck	(revision 16632)
@@ -0,0 +1,29 @@
+#!/usr/bin/env dvo
+
+if ($argv:n != 2) 
+  echo "USAGE: validate (catdir) (mode)"
+  echo $argv:n
+  exit 2
+end
+
+catdir $argv:0
+$KAPA = kapa -nomap
+
+if ("$argv:1" == "gsc") 
+  region 0.5 0.5 0.5
+end
+
+if ("$argv:1" == "asca")
+  resize -g 800 420
+  usleep 200000
+  region 60 0 90 ait
+end
+
+mextract ra
+if (ra[] == 0)
+  echo "no stars found for $1"
+  exit 1
+end
+
+echo "found ra[] stars"
+exit 0
Index: /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/photcode.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/photcode.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/photcode.txt	(revision 16632)
@@ -0,0 +1,225 @@
+# this file contains the list of valid photometry codes.
+# there should be one code for each combination of CCD, filter, and
+# telescope (and possibly additional ones if filter transmission
+# reduces with time).  The code on each line is a unique number, while
+# the name is a representative name.  The type defines how the
+# photometry is treated.  There can only be one primary photcode.  There
+# should only be a few secondary photcodes: these are the calibrated
+# values for stars.  The dependent photcodes are those which are
+# equivalent to a primary or secondary photcode, and are equated after
+# photometric solutions.  Reference photcodes are for anything without
+# a dynamic solution: the reference values are provided externally.
+
+# a bogosity in scatfit: it assumes primary photcodes are those which
+# N % 50 == 0
+
+# I discovered that the standards star analysis and the photreg
+# process are inconsistent.  the standard star analysis was using the
+# per-chip zero-points while photreg was using the per-filter
+# zero-points.  these should have been the same, but were not.  See
+# cfh12.photcode.original for the version with this error.  This file
+# now contains consistent entries
+
+# code name		type  zero    airmass  offset   c1   c2   slope  <color> equivalence
+#  1    B		pri   26.017  -0.15     -       1023 1024 0.016     -      1
+#  2    V		sec   26.220  -0.12     -       1023 1024 0.008     -      2
+#  3    R		sec   26.190  -0.09     -       1024 1025 0.028     -      3
+#  4    I		sec   26.185  -0.04     -       1025 1027 0.107     -      4
+
+#  1    B		pri   26.017  -0.15     -       1003 1004 0.016     -      1
+#  2    V		sec   26.220  -0.12     -       1003 1004 0.008     -      2
+#  3    R		sec   26.190  -0.09     -       1004 1005 0.028     -      3
+#  4    I		sec   26.185  -0.04     -       1005 1007 0.107     -      4
+
+  1    B		pri   26.000  -0.15     -       1003 1004 0.016     -      1
+  2    V		sec   26.150  -0.12     -       1003 1004 0.008     -      2
+  3    R		sec   26.190  -0.09     -       1003 1004 0.028     -      3
+  4    I		sec   26.135  -0.04     -       1003 1004 0.107     -      4
+  5    Z		sec   25.830  -0.03     -       -    -    -         -      5
+
+  1000 USNO_BLUE	ref   -     -        -       -  -   -      -        -
+  1001 USNO_RED		ref   -     -        -       -  -   -      -        -
+
+    50 ASCA_RED    	dep  10.000 0.0      -       -  -   -      -        3
+
+  1002 U_L92		ref   -     -        -       -  -   -      -        -
+  1003 B_L92		ref   -     -        -       -  -   -      -        -
+  1004 V_L92		ref   -     -        -       -  -   -      -        -
+  1005 R_L92		ref   -     -        -       -  -   -      -        -
+  1007 I_L92		ref   -     -        -       -  -   -      -        -
+
+  1022 U_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1023 B_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1024 V_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1025 R_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1027 I_L92_HQ		ref   -     -        -       -  -   -      -        -
+
+  1012 U_STET		ref   -     -        -       -  -   -      -        -
+  1013 B_STET		ref   -     -        -       -  -   -      -        -
+  1014 V_STET		ref   -     -        -       -  -   -      -        -
+  1015 R_STET		ref   -     -        -       -  -   -      -        -
+  1017 I_STET		ref   -     -        -       -  -   -      -        -
+
+  1100 GSC_M    	ref   -     -        -       -  -   -      -        -
+  1101 SAO		ref   -     -        -       -  -   -      -        -
+
+  1200 TYCHO_B		ref   -     -        -       -  -   -      -        -
+  1201 TYCHO_V		ref   -     -        -       -  -   -      -        -
+
+  2011 2MASS_J          ref   -     -        -       -  -   -      -        -
+  2012 2MASS_H          ref   -     -        -       -  -   -      -        -
+  2013 2MASS_K          ref   -     -        -       -  -   -      -        -
+
+  100  CFH12K.B.00	dep   26.000 -0.15     -       -  -   -      -        1
+  101  CFH12K.B.01	dep   26.000 -0.15     -       -  -   -      -        1
+  102  CFH12K.B.02	dep   26.000 -0.15     -       -  -   -      -        1
+  103  CFH12K.B.03	dep   26.000 -0.15     -       -  -   -      -        1
+  104  CFH12K.B.04	dep   26.000 -0.15     -       -  -   -      -        1
+  105  CFH12K.B.05	dep   26.000 -0.15     -       -  -   -      -        1
+  106  CFH12K.B.06	dep   26.000 -0.15     -       -  -   -      -        1
+  107  CFH12K.B.07	dep   26.000 -0.15     -       -  -   -      -        1
+  108  CFH12K.B.08	dep   26.000 -0.15     -       -  -   -      -        1
+  109  CFH12K.B.09	dep   26.000 -0.15     -       -  -   -      -        1
+  110  CFH12K.B.10	dep   26.000 -0.15     -       -  -   -      -        1
+  111  CFH12K.B.11	dep   26.000 -0.15     -       -  -   -      -        1
+
+  200  CFH12K.V.00	dep   26.150 -0.12     -       -  -   -      -        2
+  201  CFH12K.V.01	dep   26.150 -0.12     -       -  -   -      -        2
+  202  CFH12K.V.02	dep   26.150 -0.12     -       -  -   -      -        2
+  203  CFH12K.V.03	dep   26.150 -0.12     -       -  -   -      -        2
+  204  CFH12K.V.04	dep   26.150 -0.12     -       -  -   -      -        2
+  205  CFH12K.V.05	dep   26.150 -0.12     -       -  -   -      -        2
+  206  CFH12K.V.06	dep   26.150 -0.12     -       -  -   -      -        2
+  207  CFH12K.V.07	dep   26.150 -0.12     -       -  -   -      -        2
+  208  CFH12K.V.08	dep   26.150 -0.12     -       -  -   -      -        2
+  209  CFH12K.V.09	dep   26.150 -0.12     -       -  -   -      -        2
+  210  CFH12K.V.10	dep   26.150 -0.12     -       -  -   -      -        2
+  211  CFH12K.V.11	dep   26.150 -0.12     -       -  -   -      -        2
+
+# was 26.190
+  300  CFH12K.R.00	dep   26.190 -0.09     -       -  -   -      -        3
+  301  CFH12K.R.01	dep   26.190 -0.09     -       -  -   -      -        3
+  302  CFH12K.R.02	dep   26.190 -0.09     -       -  -   -      -        3
+  303  CFH12K.R.03	dep   26.190 -0.09     -       -  -   -      -        3
+  304  CFH12K.R.04	dep   26.190 -0.09     -       -  -   -      -        3
+  305  CFH12K.R.05	dep   26.190 -0.09     -       -  -   -      -        3
+  306  CFH12K.R.06	dep   26.190 -0.09     -       -  -   -      -        3
+  307  CFH12K.R.07	dep   26.190 -0.09     -       -  -   -      -        3
+  308  CFH12K.R.08	dep   26.190 -0.09     -       -  -   -      -        3
+  309  CFH12K.R.09	dep   26.190 -0.09     -       -  -   -      -        3
+  310  CFH12K.R.10	dep   26.190 -0.09     -       -  -   -      -        3
+  311  CFH12K.R.11	dep   26.190 -0.09     -       -  -   -      -        3
+
+  400  CFH12K.I.00	dep   26.135 -0.04     -       -  -   -      -        4
+  401  CFH12K.I.01	dep   26.135 -0.04     -       -  -   -      -        4
+  402  CFH12K.I.02	dep   26.135 -0.04     -       -  -   -      -        4
+  403  CFH12K.I.03	dep   26.135 -0.04     -       -  -   -      -        4
+  404  CFH12K.I.04	dep   26.135 -0.04     -       -  -   -      -        4
+  405  CFH12K.I.05	dep   26.135 -0.04     -       -  -   -      -        4
+  406  CFH12K.I.06	dep   26.135 -0.04     -       -  -   -      -        4
+  407  CFH12K.I.07	dep   26.135 -0.04     -       -  -   -      -        4
+  408  CFH12K.I.08	dep   26.135 -0.04     -       -  -   -      -        4
+  409  CFH12K.I.09	dep   26.135 -0.04     -       -  -   -      -        4
+  410  CFH12K.I.10	dep   26.135 -0.04     -       -  -   -      -        4
+  411  CFH12K.I.11	dep   26.135 -0.04     -       -  -   -      -        4
+
+### This needs to be fixed: I am setting all filters which are not
+###   BVRI to point at photcode 5 (= Z) as a reference.  This is
+###   needed because the 
+
+  500  CFH12K.Z.00	dep   25.83 -0.03     -       -  -   -      -        5
+  501  CFH12K.Z.01	dep   25.83 -0.03     -       -  -   -      -        5
+  502  CFH12K.Z.02	dep   25.83 -0.03     -       -  -   -      -        5
+  503  CFH12K.Z.03	dep   25.83 -0.03     -       -  -   -      -        5
+  504  CFH12K.Z.04	dep   25.83 -0.03     -       -  -   -      -        5
+  505  CFH12K.Z.05	dep   25.83 -0.03     -       -  -   -      -        5
+  506  CFH12K.Z.06	dep   25.83 -0.03     -       -  -   -      -        5
+  507  CFH12K.Z.07	dep   25.83 -0.03     -       -  -   -      -        5
+  508  CFH12K.Z.08	dep   25.83 -0.03     -       -  -   -      -        5
+  509  CFH12K.Z.09	dep   25.83 -0.03     -       -  -   -      -        5
+  510  CFH12K.Z.10	dep   25.83 -0.03     -       -  -   -      -        5
+  511  CFH12K.Z.11	dep   25.83 -0.03     -       -  -   -      -        5
+
+  600  CFH12K.Ha.00	dep   25.000 0.04     -       -  -   -      -       5
+  601  CFH12K.Ha.01	dep   25.000 0.04     -       -  -   -      -       5 
+  602  CFH12K.Ha.02	dep   25.000 0.04     -       -  -   -      -       5 
+  603  CFH12K.Ha.03	dep   25.000 0.04     -       -  -   -      -       5 
+  604  CFH12K.Ha.04	dep   25.000 0.04     -       -  -   -      -       5 
+  605  CFH12K.Ha.05	dep   25.000 0.04     -       -  -   -      -       5 
+  606  CFH12K.Ha.06	dep   25.000 0.04     -       -  -   -      -       5 
+  607  CFH12K.Ha.07	dep   25.000 0.04     -       -  -   -      -       5 
+  608  CFH12K.Ha.08	dep   25.000 0.04     -       -  -   -      -       5 
+  609  CFH12K.Ha.09	dep   25.000 0.04     -       -  -   -      -       5 
+  610  CFH12K.Ha.10	dep   25.000 0.04     -       -  -   -      -       5 
+  611  CFH12K.Ha.11	dep   25.000 0.04     -       -  -   -      -       5 
+									     
+  700  CFH12K.HaOff.00	dep   25.000 0.04     -       -  -   -      -       5
+  701  CFH12K.HaOff.01	dep   25.000 0.04     -       -  -   -      -       5 
+  702  CFH12K.HaOff.02	dep   25.000 0.04     -       -  -   -      -       5 
+  703  CFH12K.HaOff.03	dep   25.000 0.04     -       -  -   -      -       5 
+  704  CFH12K.HaOff.04	dep   25.000 0.04     -       -  -   -      -       5 
+  705  CFH12K.HaOff.05	dep   25.000 0.04     -       -  -   -      -       5 
+  706  CFH12K.HaOff.06	dep   25.000 0.04     -       -  -   -      -       5 
+  707  CFH12K.HaOff.07	dep   25.000 0.04     -       -  -   -      -       5 
+  708  CFH12K.HaOff.08	dep   25.000 0.04     -       -  -   -      -       5 
+  709  CFH12K.HaOff.09	dep   25.000 0.04     -       -  -   -      -       5 
+  710  CFH12K.HaOff.10	dep   25.000 0.04     -       -  -   -      -       5 
+  711  CFH12K.HaOff.11	dep   25.000 0.04     -       -  -   -      -       5 
+
+  800  CFH12K.CN.00	dep   25.000 0.04     -       -  -   -      -       5
+  801  CFH12K.CN.01	dep   25.000 0.04     -       -  -   -      -       5 
+  802  CFH12K.CN.02	dep   25.000 0.04     -       -  -   -      -       5 
+  803  CFH12K.CN.03	dep   25.000 0.04     -       -  -   -      -       5 
+  804  CFH12K.CN.04	dep   25.000 0.04     -       -  -   -      -       5 
+  805  CFH12K.CN.05	dep   25.000 0.04     -       -  -   -      -       5 
+  806  CFH12K.CN.06	dep   25.000 0.04     -       -  -   -      -       5 
+  807  CFH12K.CN.07	dep   25.000 0.04     -       -  -   -      -       5 
+  808  CFH12K.CN.08	dep   25.000 0.04     -       -  -   -      -       5 
+  809  CFH12K.CN.09	dep   25.000 0.04     -       -  -   -      -       5 
+  810  CFH12K.CN.10	dep   25.000 0.04     -       -  -   -      -       5 
+  811  CFH12K.CN.11	dep   25.000 0.04     -       -  -   -      -       5 
+
+  900  CFH12K.TiO.00	dep   25.000 0.04     -       -  -   -      -       5
+  901  CFH12K.TiO.01	dep   25.000 0.04     -       -  -   -      -       5 
+  902  CFH12K.TiO.02	dep   25.000 0.04     -       -  -   -      -       5 
+  903  CFH12K.TiO.03	dep   25.000 0.04     -       -  -   -      -       5 
+  904  CFH12K.TiO.04	dep   25.000 0.04     -       -  -   -      -       5 
+  905  CFH12K.TiO.05	dep   25.000 0.04     -       -  -   -      -       5 
+  906  CFH12K.TiO.06	dep   25.000 0.04     -       -  -   -      -       5 
+  907  CFH12K.TiO.07	dep   25.000 0.04     -       -  -   -      -       5 
+  908  CFH12K.TiO.08	dep   25.000 0.04     -       -  -   -      -       5 
+  909  CFH12K.TiO.09	dep   25.000 0.04     -       -  -   -      -       5 
+  910  CFH12K.TiO.10	dep   25.000 0.04     -       -  -   -      -       5 
+  911  CFH12K.TiO.11	dep   25.000 0.04     -       -  -   -      -       5 
+
+  950  CFH12K.NB920.00	dep   25.000 0.04     -       -  -   -      -       5
+  951  CFH12K.NB920.01	dep   25.000 0.04     -       -  -   -      -       5 
+  952  CFH12K.NB920.02	dep   25.000 0.04     -       -  -   -      -       5 
+  953  CFH12K.NB920.03	dep   25.000 0.04     -       -  -   -      -       5 
+  954  CFH12K.NB920.04	dep   25.000 0.04     -       -  -   -      -       5 
+  955  CFH12K.NB920.05	dep   25.000 0.04     -       -  -   -      -       5 
+  956  CFH12K.NB920.06	dep   25.000 0.04     -       -  -   -      -       5 
+  957  CFH12K.NB920.07	dep   25.000 0.04     -       -  -   -      -       5 
+  958  CFH12K.NB920.08	dep   25.000 0.04     -       -  -   -      -       5 
+  959  CFH12K.NB920.09	dep   25.000 0.04     -       -  -   -      -       5 
+  960  CFH12K.NB920.10	dep   25.000 0.04     -       -  -   -      -       5 
+  961  CFH12K.NB920.11	dep   25.000 0.04     -       -  -   -      -       5 
+
+  970  CFH12K.B2F.00	dep   25.000 0.04     -       -  -   -      -       5
+  971  CFH12K.B2F.01	dep   25.000 0.04     -       -  -   -      -       5 
+  972  CFH12K.B2F.02	dep   25.000 0.04     -       -  -   -      -       5 
+  973  CFH12K.B2F.03	dep   25.000 0.04     -       -  -   -      -       5 
+  974  CFH12K.B2F.04	dep   25.000 0.04     -       -  -   -      -       5 
+  975  CFH12K.B2F.05	dep   25.000 0.04     -       -  -   -      -       5 
+  976  CFH12K.B2F.06	dep   25.000 0.04     -       -  -   -      -       5 
+  977  CFH12K.B2F.07	dep   25.000 0.04     -       -  -   -      -       5 
+  978  CFH12K.B2F.08	dep   25.000 0.04     -       -  -   -      -       5 
+  979  CFH12K.B2F.09	dep   25.000 0.04     -       -  -   -      -       5 
+  980  CFH12K.B2F.10	dep   25.000 0.04     -       -  -   -      -       5 
+  981  CFH12K.B2F.11	dep   25.000 0.04     -       -  -   -      -       5 
+
+  2000 U_BESS		dep   25.0  0.10     -       -  -   -      -        5
+  2001 B_BESS		dep   25.0  0.10     -       -  -   -      -        1
+  2002 V_BESS		dep   25.0  0.10     -       -  -   -      -        2
+  2003 R_BESS		dep   25.0  0.10     -       -  -   -      -        3
+  2004 I_BESS		dep   25.0  0.10     -       -  -   -      -        4
Index: /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/ptolemy.rc
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/ptolemy.rc	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/addstar/refcat.sa/ptolemy.rc	(revision 16632)
@@ -0,0 +1,25 @@
+# .ptolemyrc
+ 
+REFDIR ../../refs
+
+# asca camera settings
+UT-KEYWORD              UTSHUT
+DATE-KEYWORD            DATE
+DATE-MODE               yyyy-mm-dd
+
+# matching radius (arcseconds)
+# RADIUS  1.0  (old name, deprecated)
+ADDSTAR_RADIUS  1.0
+
+GSCFILE $REFDIR/GSCregions.tbl
+CATDIR catdir
+PHOTCODE_FILE photcode.txt
+
+USNO_A_DIR /data/elixir/srcdir/refs/usno
+USNO_B_DIR /data/elixir/srcdir/refs/usnob
+
+ZERO_PT 25.0
+
+GSCDIR         /data/elixir/srcdir/refs/gsc
+2MASS_DIR_AS   /data/elixir/srcdir/refs/2mass.allsky
+2MASS_DIR_DR2  /data/elixir/srcdir/refs/2mass.dr2
Index: /branches/eam_branch_20080223/Ohana/test/photdbc/Makefile
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/photdbc/Makefile	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/photdbc/Makefile	(revision 16632)
@@ -0,0 +1,24 @@
+
+clean:
+	rm -rf catdir.output.copy
+	rm -rf catdir.output.clip
+	rm -rf catdir.output.clip2
+
+empty: clean
+	rm -rf catdir.input
+	rm -rf catdir.in2
+
+init:
+	rm -rf catdir.input
+	addstar -D CATDIR catdir.input -cat usno -p USNO_RED -region 0 1 0 1
+	addstar -D CATDIR catdir.in2 -cat usno -p USNO_RED -region 0 1 0 1
+	addstar -D CATDIR catdir.in2 -cat usno -p USNO_BLUE -region 0 1 0 1
+
+copy:
+	photdbc -D CATDIR catdir.input catdir.output.copy -region 0 1 0 1
+
+clip:
+	photdbc -D CATDIR catdir.input catdir.output.clip -region 0 1 0 1 -maxminmag 14.0
+
+clip2:
+	photdbc -D CATDIR catdir.in2 catdir.output.clip2 -region 0 1 0 1 -maxminmag 14.0
Index: /branches/eam_branch_20080223/Ohana/test/photdbc/photcode.txt
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/photdbc/photcode.txt	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/photdbc/photcode.txt	(revision 16632)
@@ -0,0 +1,75 @@
+# this file contains the list of valid photometry codes.
+# there should be one code for each combination of CCD, filter, and
+# telescope (and possibly additional ones if filter transmission
+# reduces with time).  The code on each line is a unique number, while
+# the name is a representative name.  The type defines how the
+# photometry is treated.  There can only be one primary photcode.  There
+# should only be a few secondary photcodes: these are the calibrated
+# values for stars.  The dependent photcodes are those which are
+# equivalent to a primary or secondary photcode, and are equated after
+# photometric solutions.  Reference photcodes are for anything without
+# a dynamic solution: the reference values are provided externally.
+
+# a bogosity in scatfit: it assumes primary photcodes are those which
+# N % 50 == 0
+
+# I discovered that the standards star analysis and the photreg
+# process are inconsistent.  the standard star analysis was using the
+# per-chip zero-points while photreg was using the per-filter
+# zero-points.  these should have been the same, but were not.  See
+# cfh12.photcode.original for the version with this error.  This file
+# now contains consistent entries
+
+# code name		type  zero    airmass  offset   c1   c2   slope  <color> equivalence
+#  1    B		pri   26.017  -0.15     -       1023 1024 0.016     -      1
+#  2    V		sec   26.220  -0.12     -       1023 1024 0.008     -      2
+#  3    R		sec   26.190  -0.09     -       1024 1025 0.028     -      3
+#  4    I		sec   26.185  -0.04     -       1025 1027 0.107     -      4
+
+#  1    B		pri   26.017  -0.15     -       1003 1004 0.016     -      1
+#  2    V		sec   26.220  -0.12     -       1003 1004 0.008     -      2
+#  3    R		sec   26.190  -0.09     -       1004 1005 0.028     -      3
+#  4    I		sec   26.185  -0.04     -       1005 1007 0.107     -      4
+
+  1    B		pri   26.000  -0.15     -       1003 1004 0.016     -      1
+  2    V		sec   26.150  -0.12     -       1003 1004 0.008     -      2
+  3    R		sec   26.190  -0.09     -       1003 1004 0.028     -      3
+  4    I		sec   26.135  -0.04     -       1003 1004 0.107     -      4
+  5    Z		sec   25.830  -0.03     -       -    -    -         -      5
+
+  1000 USNO_BLUE	ref   -     -        -       -  -   -      -        -
+  1001 USNO_RED		ref   -     -        -       -  -   -      -        -
+
+    50 ASCA_RED    	dep  10.000 0.0      -       -  -   -      -        3
+    51 ASCA_BLUE    	dep  10.000 0.0      -       -  -   -      -        3
+
+  1002 U_L92		ref   -     -        -       -  -   -      -        -
+  1003 B_L92		ref   -     -        -       -  -   -      -        -
+  1004 V_L92		ref   -     -        -       -  -   -      -        -
+  1005 R_L92		ref   -     -        -       -  -   -      -        -
+  1007 I_L92		ref   -     -        -       -  -   -      -        -
+
+  1022 U_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1023 B_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1024 V_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1025 R_L92_HQ		ref   -     -        -       -  -   -      -        -
+  1027 I_L92_HQ		ref   -     -        -       -  -   -      -        -
+
+  1012 U_STET		ref   -     -        -       -  -   -      -        -
+  1013 B_STET		ref   -     -        -       -  -   -      -        -
+  1014 V_STET		ref   -     -        -       -  -   -      -        -
+  1015 R_STET		ref   -     -        -       -  -   -      -        -
+  1017 I_STET		ref   -     -        -       -  -   -      -        -
+
+  1100 GSC_M    	ref   -     -        -       -  -   -      -        -
+  1101 SAO		ref   -     -        -       -  -   -      -        -
+
+  1200 TYCHO_B		ref   -     -        -       -  -   -      -        -
+  1201 TYCHO_V		ref   -     -        -       -  -   -      -        -
+
+  2011 2MASS_J          ref   -     -        -       -  -   -      -        -
+  2012 2MASS_H          ref   -     -        -       -  -   -      -        -
+  2013 2MASS_K          ref   -     -        -       -  -   -      -        -
+
+  100  CFH12K.B.00	dep   26.000 -0.15     -       -  -   -      -        1
+  101  MEGACAM.r.13	dep   26.000 -0.15     -       -  -   -      -        1
Index: /branches/eam_branch_20080223/Ohana/test/photdbc/ptolemy.rc
===================================================================
--- /branches/eam_branch_20080223/Ohana/test/photdbc/ptolemy.rc	(revision 16632)
+++ /branches/eam_branch_20080223/Ohana/test/photdbc/ptolemy.rc	(revision 16632)
@@ -0,0 +1,23 @@
+# .ptolemyrc
+ 
+REFSDIR                 ../../refs
+
+# asca camera settings
+UT-KEYWORD              UTSHUT
+DATE-KEYWORD            DATE
+DATE-MODE               yyyy-mm-dd
+
+# matching radius (arcseconds)
+# RADIUS  1.0  (old name, deprecated)
+ADDSTAR_RADIUS  1.0
+
+GSCFILE ../refs/GSCregions.tbl
+CATDIR catdir
+PHOTCODE_FILE photcode.txt
+
+USNO_A_DIR /data/elixir/srcdir/refs/usno
+USNO_B_DIR /data/elixir/srcdir/refs/usnob
+
+ZERO_PT 25.0
+
+GSCDIR /data/elixir/srcdir/refs/gsc
